UNPKG

44.6 kBJavaScriptView Raw
1/***********************************************************************
2
3 A JavaScript tokenizer / parser / beautifier / compressor.
4 https://github.com/mishoo/UglifyJS2
5
6 -------------------------------- (C) ---------------------------------
7
8 Author: Mihai Bazon
9 <mihai.bazon@gmail.com>
10 http://mihai.bazon.net/blog
11
12 Distributed under the BSD license:
13
14 Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
15
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
19
20 * Redistributions of source code must retain the above
21 copyright notice, this list of conditions and the following
22 disclaimer.
23
24 * Redistributions in binary form must reproduce the above
25 copyright notice, this list of conditions and the following
26 disclaimer in the documentation and/or other materials
27 provided with the distribution.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
30 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
33 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 SUCH DAMAGE.
41
42 ***********************************************************************/
43
44import * as ast from "./ast.js";
45import { make_node } from "./utils/index.js";
46import {
47 AST_Accessor,
48 AST_Array,
49 AST_Arrow,
50 AST_Assign,
51 AST_Atom,
52 AST_Await,
53 AST_BigInt,
54 AST_Binary,
55 AST_Block,
56 AST_BlockStatement,
57 AST_Boolean,
58 AST_Break,
59 AST_Call,
60 AST_Case,
61 AST_Catch,
62 AST_Chain,
63 AST_Class,
64 AST_ClassExpression,
65 AST_ClassProperty,
66 AST_ConciseMethod,
67 AST_Conditional,
68 AST_Const,
69 AST_Constant,
70 AST_Continue,
71 AST_Debugger,
72 AST_Default,
73 AST_DefaultAssign,
74 AST_DefClass,
75 AST_Definitions,
76 AST_Defun,
77 AST_Destructuring,
78 AST_Directive,
79 AST_Do,
80 AST_Dot,
81 AST_EmptyStatement,
82 AST_Expansion,
83 AST_Export,
84 AST_False,
85 AST_Finally,
86 AST_For,
87 AST_ForIn,
88 AST_ForOf,
89 AST_Function,
90 AST_Hole,
91 AST_If,
92 AST_Import,
93 AST_ImportMeta,
94 AST_Label,
95 AST_LabeledStatement,
96 AST_LabelRef,
97 AST_Lambda,
98 AST_Let,
99 AST_NameMapping,
100 AST_New,
101 AST_NewTarget,
102 AST_Node,
103 AST_Null,
104 AST_Number,
105 AST_Object,
106 AST_ObjectGetter,
107 AST_ObjectKeyVal,
108 AST_ObjectProperty,
109 AST_ObjectSetter,
110 AST_PrefixedTemplateString,
111 AST_PropAccess,
112 AST_RegExp,
113 AST_Return,
114 AST_Sequence,
115 AST_SimpleStatement,
116 AST_Statement,
117 AST_String,
118 AST_Sub,
119 AST_Super,
120 AST_Switch,
121 AST_SwitchBranch,
122 AST_Symbol,
123 AST_SymbolCatch,
124 AST_SymbolClass,
125 AST_SymbolClassProperty,
126 AST_SymbolConst,
127 AST_SymbolDefClass,
128 AST_SymbolDefun,
129 AST_SymbolExport,
130 AST_SymbolExportForeign,
131 AST_SymbolFunarg,
132 AST_SymbolImport,
133 AST_SymbolImportForeign,
134 AST_SymbolLambda,
135 AST_SymbolLet,
136 AST_SymbolMethod,
137 AST_SymbolRef,
138 AST_SymbolVar,
139 AST_TemplateSegment,
140 AST_TemplateString,
141 AST_This,
142 AST_Throw,
143 AST_Token,
144 AST_Toplevel,
145 AST_True,
146 AST_Try,
147 AST_Unary,
148 AST_UnaryPostfix,
149 AST_UnaryPrefix,
150 AST_Var,
151 AST_VarDef,
152 AST_While,
153 AST_With,
154 AST_Yield,
155} from "./ast.js";
156
157(function() {
158
159 var normalize_directives = function(body) {
160 var in_directive = true;
161
162 for (var i = 0; i < body.length; i++) {
163 if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
164 body[i] = new AST_Directive({
165 start: body[i].start,
166 end: body[i].end,
167 value: body[i].body.value
168 });
169 } else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) {
170 in_directive = false;
171 }
172 }
173
174 return body;
175 };
176
177 var MOZ_TO_ME = {
178 Program: function(M) {
179 return new AST_Toplevel({
180 start: my_start_token(M),
181 end: my_end_token(M),
182 body: normalize_directives(M.body.map(from_moz))
183 });
184 },
185 ArrayPattern: function(M) {
186 return new AST_Destructuring({
187 start: my_start_token(M),
188 end: my_end_token(M),
189 names: M.elements.map(function(elm) {
190 if (elm === null) {
191 return new AST_Hole();
192 }
193 return from_moz(elm);
194 }),
195 is_array: true
196 });
197 },
198 ObjectPattern: function(M) {
199 return new AST_Destructuring({
200 start: my_start_token(M),
201 end: my_end_token(M),
202 names: M.properties.map(from_moz),
203 is_array: false
204 });
205 },
206 AssignmentPattern: function(M) {
207 return new AST_DefaultAssign({
208 start: my_start_token(M),
209 end: my_end_token(M),
210 left: from_moz(M.left),
211 operator: "=",
212 right: from_moz(M.right)
213 });
214 },
215 SpreadElement: function(M) {
216 return new AST_Expansion({
217 start: my_start_token(M),
218 end: my_end_token(M),
219 expression: from_moz(M.argument)
220 });
221 },
222 RestElement: function(M) {
223 return new AST_Expansion({
224 start: my_start_token(M),
225 end: my_end_token(M),
226 expression: from_moz(M.argument)
227 });
228 },
229 TemplateElement: function(M) {
230 return new AST_TemplateSegment({
231 start: my_start_token(M),
232 end: my_end_token(M),
233 value: M.value.cooked,
234 raw: M.value.raw
235 });
236 },
237 TemplateLiteral: function(M) {
238 var segments = [];
239 for (var i = 0; i < M.quasis.length; i++) {
240 segments.push(from_moz(M.quasis[i]));
241 if (M.expressions[i]) {
242 segments.push(from_moz(M.expressions[i]));
243 }
244 }
245 return new AST_TemplateString({
246 start: my_start_token(M),
247 end: my_end_token(M),
248 segments: segments
249 });
250 },
251 TaggedTemplateExpression: function(M) {
252 return new AST_PrefixedTemplateString({
253 start: my_start_token(M),
254 end: my_end_token(M),
255 template_string: from_moz(M.quasi),
256 prefix: from_moz(M.tag)
257 });
258 },
259 FunctionDeclaration: function(M) {
260 return new AST_Defun({
261 start: my_start_token(M),
262 end: my_end_token(M),
263 name: from_moz(M.id),
264 argnames: M.params.map(from_moz),
265 is_generator: M.generator,
266 async: M.async,
267 body: normalize_directives(from_moz(M.body).body)
268 });
269 },
270 FunctionExpression: function(M) {
271 return new AST_Function({
272 start: my_start_token(M),
273 end: my_end_token(M),
274 name: from_moz(M.id),
275 argnames: M.params.map(from_moz),
276 is_generator: M.generator,
277 async: M.async,
278 body: normalize_directives(from_moz(M.body).body)
279 });
280 },
281 ArrowFunctionExpression: function(M) {
282 const body = M.body.type === "BlockStatement"
283 ? from_moz(M.body).body
284 : [make_node(AST_Return, {}, { value: from_moz(M.body) })];
285 return new AST_Arrow({
286 start: my_start_token(M),
287 end: my_end_token(M),
288 argnames: M.params.map(from_moz),
289 body,
290 async: M.async,
291 });
292 },
293 ExpressionStatement: function(M) {
294 return new AST_SimpleStatement({
295 start: my_start_token(M),
296 end: my_end_token(M),
297 body: from_moz(M.expression)
298 });
299 },
300 TryStatement: function(M) {
301 var handlers = M.handlers || [M.handler];
302 if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
303 throw new Error("Multiple catch clauses are not supported.");
304 }
305 return new AST_Try({
306 start : my_start_token(M),
307 end : my_end_token(M),
308 body : from_moz(M.block).body,
309 bcatch : from_moz(handlers[0]),
310 bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
311 });
312 },
313 Property: function(M) {
314 var key = M.key;
315 var args = {
316 start : my_start_token(key || M.value),
317 end : my_end_token(M.value),
318 key : key.type == "Identifier" ? key.name : key.value,
319 value : from_moz(M.value)
320 };
321 if (M.computed) {
322 args.key = from_moz(M.key);
323 }
324 if (M.method) {
325 args.is_generator = M.value.generator;
326 args.async = M.value.async;
327 if (!M.computed) {
328 args.key = new AST_SymbolMethod({ name: args.key });
329 } else {
330 args.key = from_moz(M.key);
331 }
332 return new AST_ConciseMethod(args);
333 }
334 if (M.kind == "init") {
335 if (key.type != "Identifier" && key.type != "Literal") {
336 args.key = from_moz(key);
337 }
338 return new AST_ObjectKeyVal(args);
339 }
340 if (typeof args.key === "string" || typeof args.key === "number") {
341 args.key = new AST_SymbolMethod({
342 name: args.key
343 });
344 }
345 args.value = new AST_Accessor(args.value);
346 if (M.kind == "get") return new AST_ObjectGetter(args);
347 if (M.kind == "set") return new AST_ObjectSetter(args);
348 if (M.kind == "method") {
349 args.async = M.value.async;
350 args.is_generator = M.value.generator;
351 args.quote = M.computed ? "\"" : null;
352 return new AST_ConciseMethod(args);
353 }
354 },
355 MethodDefinition: function(M) {
356 var args = {
357 start : my_start_token(M),
358 end : my_end_token(M),
359 key : M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value }),
360 value : from_moz(M.value),
361 static : M.static,
362 };
363 if (M.kind == "get") {
364 return new AST_ObjectGetter(args);
365 }
366 if (M.kind == "set") {
367 return new AST_ObjectSetter(args);
368 }
369 args.is_generator = M.value.generator;
370 args.async = M.value.async;
371 return new AST_ConciseMethod(args);
372 },
373 FieldDefinition: function(M) {
374 let key;
375 if (M.computed) {
376 key = from_moz(M.key);
377 } else {
378 if (M.key.type !== "Identifier") throw new Error("Non-Identifier key in FieldDefinition");
379 key = from_moz(M.key);
380 }
381 return new AST_ClassProperty({
382 start : my_start_token(M),
383 end : my_end_token(M),
384 key,
385 value : from_moz(M.value),
386 static : M.static,
387 });
388 },
389 ArrayExpression: function(M) {
390 return new AST_Array({
391 start : my_start_token(M),
392 end : my_end_token(M),
393 elements : M.elements.map(function(elem) {
394 return elem === null ? new AST_Hole() : from_moz(elem);
395 })
396 });
397 },
398 ObjectExpression: function(M) {
399 return new AST_Object({
400 start : my_start_token(M),
401 end : my_end_token(M),
402 properties : M.properties.map(function(prop) {
403 if (prop.type === "SpreadElement") {
404 return from_moz(prop);
405 }
406 prop.type = "Property";
407 return from_moz(prop);
408 })
409 });
410 },
411 SequenceExpression: function(M) {
412 return new AST_Sequence({
413 start : my_start_token(M),
414 end : my_end_token(M),
415 expressions: M.expressions.map(from_moz)
416 });
417 },
418 MemberExpression: function(M) {
419 return new (M.computed ? AST_Sub : AST_Dot)({
420 start : my_start_token(M),
421 end : my_end_token(M),
422 property : M.computed ? from_moz(M.property) : M.property.name,
423 expression : from_moz(M.object),
424 optional : M.optional || false
425 });
426 },
427 ChainExpression: function(M) {
428 return new AST_Chain({
429 start : my_start_token(M),
430 end : my_end_token(M),
431 expression : from_moz(M.expression)
432 });
433 },
434 SwitchCase: function(M) {
435 return new (M.test ? AST_Case : AST_Default)({
436 start : my_start_token(M),
437 end : my_end_token(M),
438 expression : from_moz(M.test),
439 body : M.consequent.map(from_moz)
440 });
441 },
442 VariableDeclaration: function(M) {
443 return new (M.kind === "const" ? AST_Const :
444 M.kind === "let" ? AST_Let : AST_Var)({
445 start : my_start_token(M),
446 end : my_end_token(M),
447 definitions : M.declarations.map(from_moz)
448 });
449 },
450
451 ImportDeclaration: function(M) {
452 var imported_name = null;
453 var imported_names = null;
454 M.specifiers.forEach(function (specifier) {
455 if (specifier.type === "ImportSpecifier") {
456 if (!imported_names) { imported_names = []; }
457 imported_names.push(new AST_NameMapping({
458 start: my_start_token(specifier),
459 end: my_end_token(specifier),
460 foreign_name: from_moz(specifier.imported),
461 name: from_moz(specifier.local)
462 }));
463 } else if (specifier.type === "ImportDefaultSpecifier") {
464 imported_name = from_moz(specifier.local);
465 } else if (specifier.type === "ImportNamespaceSpecifier") {
466 if (!imported_names) { imported_names = []; }
467 imported_names.push(new AST_NameMapping({
468 start: my_start_token(specifier),
469 end: my_end_token(specifier),
470 foreign_name: new AST_SymbolImportForeign({ name: "*" }),
471 name: from_moz(specifier.local)
472 }));
473 }
474 });
475 return new AST_Import({
476 start : my_start_token(M),
477 end : my_end_token(M),
478 imported_name: imported_name,
479 imported_names : imported_names,
480 module_name : from_moz(M.source)
481 });
482 },
483 ExportAllDeclaration: function(M) {
484 return new AST_Export({
485 start: my_start_token(M),
486 end: my_end_token(M),
487 exported_names: [
488 new AST_NameMapping({
489 name: new AST_SymbolExportForeign({ name: "*" }),
490 foreign_name: new AST_SymbolExportForeign({ name: "*" })
491 })
492 ],
493 module_name: from_moz(M.source)
494 });
495 },
496 ExportNamedDeclaration: function(M) {
497 return new AST_Export({
498 start: my_start_token(M),
499 end: my_end_token(M),
500 exported_definition: from_moz(M.declaration),
501 exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
502 return new AST_NameMapping({
503 foreign_name: from_moz(specifier.exported),
504 name: from_moz(specifier.local)
505 });
506 }) : null,
507 module_name: from_moz(M.source)
508 });
509 },
510 ExportDefaultDeclaration: function(M) {
511 return new AST_Export({
512 start: my_start_token(M),
513 end: my_end_token(M),
514 exported_value: from_moz(M.declaration),
515 is_default: true
516 });
517 },
518 Literal: function(M) {
519 var val = M.value, args = {
520 start : my_start_token(M),
521 end : my_end_token(M)
522 };
523 var rx = M.regex;
524 if (rx && rx.pattern) {
525 // RegExpLiteral as per ESTree AST spec
526 args.value = {
527 source: rx.pattern,
528 flags: rx.flags
529 };
530 return new AST_RegExp(args);
531 } else if (rx) {
532 // support legacy RegExp
533 const rx_source = M.raw || val;
534 const match = rx_source.match(/^\/(.*)\/(\w*)$/);
535 if (!match) throw new Error("Invalid regex source " + rx_source);
536 const [_, source, flags] = match;
537 args.value = { source, flags };
538 return new AST_RegExp(args);
539 }
540 if (val === null) return new AST_Null(args);
541 switch (typeof val) {
542 case "string":
543 args.value = val;
544 return new AST_String(args);
545 case "number":
546 args.value = val;
547 return new AST_Number(args);
548 case "boolean":
549 return new (val ? AST_True : AST_False)(args);
550 }
551 },
552 MetaProperty: function(M) {
553 if (M.meta.name === "new" && M.property.name === "target") {
554 return new AST_NewTarget({
555 start: my_start_token(M),
556 end: my_end_token(M)
557 });
558 } else if (M.meta.name === "import" && M.property.name === "meta") {
559 return new AST_ImportMeta({
560 start: my_start_token(M),
561 end: my_end_token(M)
562 });
563 }
564 },
565 Identifier: function(M) {
566 var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
567 return new ( p.type == "LabeledStatement" ? AST_Label
568 : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : p.kind == "let" ? AST_SymbolLet : AST_SymbolVar)
569 : /Import.*Specifier/.test(p.type) ? (p.local === M ? AST_SymbolImport : AST_SymbolImportForeign)
570 : p.type == "ExportSpecifier" ? (p.local === M ? AST_SymbolExport : AST_SymbolExportForeign)
571 : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
572 : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
573 : p.type == "ArrowFunctionExpression" ? (p.params.includes(M)) ? AST_SymbolFunarg : AST_SymbolRef
574 : p.type == "ClassExpression" ? (p.id === M ? AST_SymbolClass : AST_SymbolRef)
575 : p.type == "Property" ? (p.key === M && p.computed || p.value === M ? AST_SymbolRef : AST_SymbolMethod)
576 : p.type == "FieldDefinition" ? (p.key === M && p.computed || p.value === M ? AST_SymbolRef : AST_SymbolClassProperty)
577 : p.type == "ClassDeclaration" ? (p.id === M ? AST_SymbolDefClass : AST_SymbolRef)
578 : p.type == "MethodDefinition" ? (p.computed ? AST_SymbolRef : AST_SymbolMethod)
579 : p.type == "CatchClause" ? AST_SymbolCatch
580 : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
581 : AST_SymbolRef)({
582 start : my_start_token(M),
583 end : my_end_token(M),
584 name : M.name
585 });
586 },
587 BigIntLiteral(M) {
588 return new AST_BigInt({
589 start : my_start_token(M),
590 end : my_end_token(M),
591 value : M.value
592 });
593 }
594 };
595
596 MOZ_TO_ME.UpdateExpression =
597 MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
598 var prefix = "prefix" in M ? M.prefix
599 : M.type == "UnaryExpression" ? true : false;
600 return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
601 start : my_start_token(M),
602 end : my_end_token(M),
603 operator : M.operator,
604 expression : from_moz(M.argument)
605 });
606 };
607
608 MOZ_TO_ME.ClassDeclaration =
609 MOZ_TO_ME.ClassExpression = function From_Moz_Class(M) {
610 return new (M.type === "ClassDeclaration" ? AST_DefClass : AST_ClassExpression)({
611 start : my_start_token(M),
612 end : my_end_token(M),
613 name : from_moz(M.id),
614 extends : from_moz(M.superClass),
615 properties: M.body.body.map(from_moz)
616 });
617 };
618
619 map("EmptyStatement", AST_EmptyStatement);
620 map("BlockStatement", AST_BlockStatement, "body@body");
621 map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
622 map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
623 map("BreakStatement", AST_Break, "label>label");
624 map("ContinueStatement", AST_Continue, "label>label");
625 map("WithStatement", AST_With, "object>expression, body>body");
626 map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
627 map("ReturnStatement", AST_Return, "argument>value");
628 map("ThrowStatement", AST_Throw, "argument>value");
629 map("WhileStatement", AST_While, "test>condition, body>body");
630 map("DoWhileStatement", AST_Do, "test>condition, body>body");
631 map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
632 map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
633 map("ForOfStatement", AST_ForOf, "left>init, right>object, body>body, await=await");
634 map("AwaitExpression", AST_Await, "argument>expression");
635 map("YieldExpression", AST_Yield, "argument>expression, delegate=is_star");
636 map("DebuggerStatement", AST_Debugger);
637 map("VariableDeclarator", AST_VarDef, "id>name, init>value");
638 map("CatchClause", AST_Catch, "param>argname, body%body");
639
640 map("ThisExpression", AST_This);
641 map("Super", AST_Super);
642 map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
643 map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
644 map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
645 map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
646 map("NewExpression", AST_New, "callee>expression, arguments@args");
647 map("CallExpression", AST_Call, "callee>expression, optional=optional, arguments@args");
648
649 def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
650 return to_moz_scope("Program", M);
651 });
652
653 def_to_moz(AST_Expansion, function To_Moz_Spread(M) {
654 return {
655 type: to_moz_in_destructuring() ? "RestElement" : "SpreadElement",
656 argument: to_moz(M.expression)
657 };
658 });
659
660 def_to_moz(AST_PrefixedTemplateString, function To_Moz_TaggedTemplateExpression(M) {
661 return {
662 type: "TaggedTemplateExpression",
663 tag: to_moz(M.prefix),
664 quasi: to_moz(M.template_string)
665 };
666 });
667
668 def_to_moz(AST_TemplateString, function To_Moz_TemplateLiteral(M) {
669 var quasis = [];
670 var expressions = [];
671 for (var i = 0; i < M.segments.length; i++) {
672 if (i % 2 !== 0) {
673 expressions.push(to_moz(M.segments[i]));
674 } else {
675 quasis.push({
676 type: "TemplateElement",
677 value: {
678 raw: M.segments[i].raw,
679 cooked: M.segments[i].value
680 },
681 tail: i === M.segments.length - 1
682 });
683 }
684 }
685 return {
686 type: "TemplateLiteral",
687 quasis: quasis,
688 expressions: expressions
689 };
690 });
691
692 def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
693 return {
694 type: "FunctionDeclaration",
695 id: to_moz(M.name),
696 params: M.argnames.map(to_moz),
697 generator: M.is_generator,
698 async: M.async,
699 body: to_moz_scope("BlockStatement", M)
700 };
701 });
702
703 def_to_moz(AST_Function, function To_Moz_FunctionExpression(M, parent) {
704 var is_generator = parent.is_generator !== undefined ?
705 parent.is_generator : M.is_generator;
706 return {
707 type: "FunctionExpression",
708 id: to_moz(M.name),
709 params: M.argnames.map(to_moz),
710 generator: is_generator,
711 async: M.async,
712 body: to_moz_scope("BlockStatement", M)
713 };
714 });
715
716 def_to_moz(AST_Arrow, function To_Moz_ArrowFunctionExpression(M) {
717 var body = {
718 type: "BlockStatement",
719 body: M.body.map(to_moz)
720 };
721 return {
722 type: "ArrowFunctionExpression",
723 params: M.argnames.map(to_moz),
724 async: M.async,
725 body: body
726 };
727 });
728
729 def_to_moz(AST_Destructuring, function To_Moz_ObjectPattern(M) {
730 if (M.is_array) {
731 return {
732 type: "ArrayPattern",
733 elements: M.names.map(to_moz)
734 };
735 }
736 return {
737 type: "ObjectPattern",
738 properties: M.names.map(to_moz)
739 };
740 });
741
742 def_to_moz(AST_Directive, function To_Moz_Directive(M) {
743 return {
744 type: "ExpressionStatement",
745 expression: {
746 type: "Literal",
747 value: M.value,
748 raw: M.print_to_string()
749 },
750 directive: M.value
751 };
752 });
753
754 def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
755 return {
756 type: "ExpressionStatement",
757 expression: to_moz(M.body)
758 };
759 });
760
761 def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
762 return {
763 type: "SwitchCase",
764 test: to_moz(M.expression),
765 consequent: M.body.map(to_moz)
766 };
767 });
768
769 def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
770 return {
771 type: "TryStatement",
772 block: to_moz_block(M),
773 handler: to_moz(M.bcatch),
774 guardedHandlers: [],
775 finalizer: to_moz(M.bfinally)
776 };
777 });
778
779 def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
780 return {
781 type: "CatchClause",
782 param: to_moz(M.argname),
783 guard: null,
784 body: to_moz_block(M)
785 };
786 });
787
788 def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
789 return {
790 type: "VariableDeclaration",
791 kind:
792 M instanceof AST_Const ? "const" :
793 M instanceof AST_Let ? "let" : "var",
794 declarations: M.definitions.map(to_moz)
795 };
796 });
797
798 def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
799 if (M.exported_names) {
800 if (M.exported_names[0].name.name === "*") {
801 return {
802 type: "ExportAllDeclaration",
803 source: to_moz(M.module_name)
804 };
805 }
806 return {
807 type: "ExportNamedDeclaration",
808 specifiers: M.exported_names.map(function (name_mapping) {
809 return {
810 type: "ExportSpecifier",
811 exported: to_moz(name_mapping.foreign_name),
812 local: to_moz(name_mapping.name)
813 };
814 }),
815 declaration: to_moz(M.exported_definition),
816 source: to_moz(M.module_name)
817 };
818 }
819 return {
820 type: M.is_default ? "ExportDefaultDeclaration" : "ExportNamedDeclaration",
821 declaration: to_moz(M.exported_value || M.exported_definition)
822 };
823 });
824
825 def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
826 var specifiers = [];
827 if (M.imported_name) {
828 specifiers.push({
829 type: "ImportDefaultSpecifier",
830 local: to_moz(M.imported_name)
831 });
832 }
833 if (M.imported_names && M.imported_names[0].foreign_name.name === "*") {
834 specifiers.push({
835 type: "ImportNamespaceSpecifier",
836 local: to_moz(M.imported_names[0].name)
837 });
838 } else if (M.imported_names) {
839 M.imported_names.forEach(function(name_mapping) {
840 specifiers.push({
841 type: "ImportSpecifier",
842 local: to_moz(name_mapping.name),
843 imported: to_moz(name_mapping.foreign_name)
844 });
845 });
846 }
847 return {
848 type: "ImportDeclaration",
849 specifiers: specifiers,
850 source: to_moz(M.module_name)
851 };
852 });
853
854 def_to_moz(AST_ImportMeta, function To_Moz_MetaProperty() {
855 return {
856 type: "MetaProperty",
857 meta: {
858 type: "Identifier",
859 name: "import"
860 },
861 property: {
862 type: "Identifier",
863 name: "meta"
864 }
865 };
866 });
867
868 def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
869 return {
870 type: "SequenceExpression",
871 expressions: M.expressions.map(to_moz)
872 };
873 });
874
875 def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
876 var isComputed = M instanceof AST_Sub;
877 return {
878 type: "MemberExpression",
879 object: to_moz(M.expression),
880 computed: isComputed,
881 property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property},
882 optional: M.optional
883 };
884 });
885
886 def_to_moz(AST_Chain, function To_Moz_ChainExpression(M) {
887 return {
888 type: "ChainExpression",
889 expression: to_moz(M.expression)
890 };
891 });
892
893 def_to_moz(AST_Unary, function To_Moz_Unary(M) {
894 return {
895 type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
896 operator: M.operator,
897 prefix: M instanceof AST_UnaryPrefix,
898 argument: to_moz(M.expression)
899 };
900 });
901
902 def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
903 if (M.operator == "=" && to_moz_in_destructuring()) {
904 return {
905 type: "AssignmentPattern",
906 left: to_moz(M.left),
907 right: to_moz(M.right)
908 };
909 }
910
911 const type = M.operator == "&&" || M.operator == "||" || M.operator === "??"
912 ? "LogicalExpression"
913 : "BinaryExpression";
914
915 return {
916 type,
917 left: to_moz(M.left),
918 operator: M.operator,
919 right: to_moz(M.right)
920 };
921 });
922
923 def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
924 return {
925 type: "ArrayExpression",
926 elements: M.elements.map(to_moz)
927 };
928 });
929
930 def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
931 return {
932 type: "ObjectExpression",
933 properties: M.properties.map(to_moz)
934 };
935 });
936
937 def_to_moz(AST_ObjectProperty, function To_Moz_Property(M, parent) {
938 var key = M.key instanceof AST_Node ? to_moz(M.key) : {
939 type: "Identifier",
940 value: M.key
941 };
942 if (typeof M.key === "number") {
943 key = {
944 type: "Literal",
945 value: Number(M.key)
946 };
947 }
948 if (typeof M.key === "string") {
949 key = {
950 type: "Identifier",
951 name: M.key
952 };
953 }
954 var kind;
955 var string_or_num = typeof M.key === "string" || typeof M.key === "number";
956 var computed = string_or_num ? false : !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef;
957 if (M instanceof AST_ObjectKeyVal) {
958 kind = "init";
959 computed = !string_or_num;
960 } else
961 if (M instanceof AST_ObjectGetter) {
962 kind = "get";
963 } else
964 if (M instanceof AST_ObjectSetter) {
965 kind = "set";
966 }
967 if (M instanceof AST_ClassProperty) {
968 return {
969 type: "FieldDefinition",
970 computed,
971 key,
972 value: to_moz(M.value),
973 static: M.static
974 };
975 }
976 if (parent instanceof AST_Class) {
977 return {
978 type: "MethodDefinition",
979 computed: computed,
980 kind: kind,
981 static: M.static,
982 key: to_moz(M.key),
983 value: to_moz(M.value)
984 };
985 }
986 return {
987 type: "Property",
988 computed: computed,
989 kind: kind,
990 key: key,
991 value: to_moz(M.value)
992 };
993 });
994
995 def_to_moz(AST_ConciseMethod, function To_Moz_MethodDefinition(M, parent) {
996 if (parent instanceof AST_Object) {
997 return {
998 type: "Property",
999 computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
1000 kind: "init",
1001 method: true,
1002 shorthand: false,
1003 key: to_moz(M.key),
1004 value: to_moz(M.value)
1005 };
1006 }
1007 return {
1008 type: "MethodDefinition",
1009 computed: !(M.key instanceof AST_Symbol) || M.key instanceof AST_SymbolRef,
1010 kind: M.key === "constructor" ? "constructor" : "method",
1011 static: M.static,
1012 key: to_moz(M.key),
1013 value: to_moz(M.value)
1014 };
1015 });
1016
1017 def_to_moz(AST_Class, function To_Moz_Class(M) {
1018 var type = M instanceof AST_ClassExpression ? "ClassExpression" : "ClassDeclaration";
1019 return {
1020 type: type,
1021 superClass: to_moz(M.extends),
1022 id: M.name ? to_moz(M.name) : null,
1023 body: {
1024 type: "ClassBody",
1025 body: M.properties.map(to_moz)
1026 }
1027 };
1028 });
1029
1030 def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
1031 return {
1032 type: "MetaProperty",
1033 meta: {
1034 type: "Identifier",
1035 name: "new"
1036 },
1037 property: {
1038 type: "Identifier",
1039 name: "target"
1040 }
1041 };
1042 });
1043
1044 def_to_moz(AST_Symbol, function To_Moz_Identifier(M, parent) {
1045 if (M instanceof AST_SymbolMethod && parent.quote) {
1046 return {
1047 type: "Literal",
1048 value: M.name
1049 };
1050 }
1051 var def = M.definition();
1052 return {
1053 type: "Identifier",
1054 name: def ? def.mangled_name || def.name : M.name
1055 };
1056 });
1057
1058 def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
1059 const pattern = M.value.source;
1060 const flags = M.value.flags;
1061 return {
1062 type: "Literal",
1063 value: null,
1064 raw: M.print_to_string(),
1065 regex: { pattern, flags }
1066 };
1067 });
1068
1069 def_to_moz(AST_Constant, function To_Moz_Literal(M) {
1070 var value = M.value;
1071 if (typeof value === "number" && (value < 0 || (value === 0 && 1 / value < 0))) {
1072 return {
1073 type: "UnaryExpression",
1074 operator: "-",
1075 prefix: true,
1076 argument: {
1077 type: "Literal",
1078 value: -value,
1079 raw: M.start.raw
1080 }
1081 };
1082 }
1083 return {
1084 type: "Literal",
1085 value: value,
1086 raw: M.start.raw
1087 };
1088 });
1089
1090 def_to_moz(AST_Atom, function To_Moz_Atom(M) {
1091 return {
1092 type: "Identifier",
1093 name: String(M.value)
1094 };
1095 });
1096
1097 def_to_moz(AST_BigInt, M => ({
1098 type: "BigIntLiteral",
1099 value: M.value
1100 }));
1101
1102 AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
1103 AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
1104 AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null; });
1105
1106 AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
1107 AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
1108
1109 /* -----[ tools ]----- */
1110
1111 function raw_token(moznode) {
1112 if (moznode.type == "Literal") {
1113 return moznode.raw != null ? moznode.raw : moznode.value + "";
1114 }
1115 }
1116
1117 function my_start_token(moznode) {
1118 var loc = moznode.loc, start = loc && loc.start;
1119 var range = moznode.range;
1120 return new AST_Token({
1121 file : loc && loc.source,
1122 line : start && start.line,
1123 col : start && start.column,
1124 pos : range ? range[0] : moznode.start,
1125 endline : start && start.line,
1126 endcol : start && start.column,
1127 endpos : range ? range[0] : moznode.start,
1128 raw : raw_token(moznode),
1129 });
1130 }
1131
1132 function my_end_token(moznode) {
1133 var loc = moznode.loc, end = loc && loc.end;
1134 var range = moznode.range;
1135 return new AST_Token({
1136 file : loc && loc.source,
1137 line : end && end.line,
1138 col : end && end.column,
1139 pos : range ? range[1] : moznode.end,
1140 endline : end && end.line,
1141 endcol : end && end.column,
1142 endpos : range ? range[1] : moznode.end,
1143 raw : raw_token(moznode),
1144 });
1145 }
1146
1147 function map(moztype, mytype, propmap) {
1148 var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
1149 moz_to_me += "return new U2." + mytype.name + "({\n" +
1150 "start: my_start_token(M),\n" +
1151 "end: my_end_token(M)";
1152
1153 var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
1154 me_to_moz += "return {\n" +
1155 "type: " + JSON.stringify(moztype);
1156
1157 if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
1158 var m = /([a-z0-9$_]+)([=@>%])([a-z0-9$_]+)/i.exec(prop);
1159 if (!m) throw new Error("Can't understand property map: " + prop);
1160 var moz = m[1], how = m[2], my = m[3];
1161 moz_to_me += ",\n" + my + ": ";
1162 me_to_moz += ",\n" + moz + ": ";
1163 switch (how) {
1164 case "@":
1165 moz_to_me += "M." + moz + ".map(from_moz)";
1166 me_to_moz += "M." + my + ".map(to_moz)";
1167 break;
1168 case ">":
1169 moz_to_me += "from_moz(M." + moz + ")";
1170 me_to_moz += "to_moz(M." + my + ")";
1171 break;
1172 case "=":
1173 moz_to_me += "M." + moz;
1174 me_to_moz += "M." + my;
1175 break;
1176 case "%":
1177 moz_to_me += "from_moz(M." + moz + ").body";
1178 me_to_moz += "to_moz_block(M)";
1179 break;
1180 default:
1181 throw new Error("Can't understand operator in propmap: " + prop);
1182 }
1183 });
1184
1185 moz_to_me += "\n})\n}";
1186 me_to_moz += "\n}\n}";
1187
1188 moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
1189 ast, my_start_token, my_end_token, from_moz
1190 );
1191 me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
1192 to_moz, to_moz_block, to_moz_scope
1193 );
1194 MOZ_TO_ME[moztype] = moz_to_me;
1195 def_to_moz(mytype, me_to_moz);
1196 }
1197
1198 var FROM_MOZ_STACK = null;
1199
1200 function from_moz(node) {
1201 FROM_MOZ_STACK.push(node);
1202 var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
1203 FROM_MOZ_STACK.pop();
1204 return ret;
1205 }
1206
1207 AST_Node.from_mozilla_ast = function(node) {
1208 var save_stack = FROM_MOZ_STACK;
1209 FROM_MOZ_STACK = [];
1210 var ast = from_moz(node);
1211 FROM_MOZ_STACK = save_stack;
1212 return ast;
1213 };
1214
1215 function set_moz_loc(mynode, moznode) {
1216 var start = mynode.start;
1217 var end = mynode.end;
1218 if (!(start && end)) {
1219 return moznode;
1220 }
1221 if (start.pos != null && end.endpos != null) {
1222 moznode.range = [start.pos, end.endpos];
1223 }
1224 if (start.line) {
1225 moznode.loc = {
1226 start: {line: start.line, column: start.col},
1227 end: end.endline ? {line: end.endline, column: end.endcol} : null
1228 };
1229 if (start.file) {
1230 moznode.loc.source = start.file;
1231 }
1232 }
1233 return moznode;
1234 }
1235
1236 function def_to_moz(mytype, handler) {
1237 mytype.DEFMETHOD("to_mozilla_ast", function(parent) {
1238 return set_moz_loc(this, handler(this, parent));
1239 });
1240 }
1241
1242 var TO_MOZ_STACK = null;
1243
1244 function to_moz(node) {
1245 if (TO_MOZ_STACK === null) { TO_MOZ_STACK = []; }
1246 TO_MOZ_STACK.push(node);
1247 var ast = node != null ? node.to_mozilla_ast(TO_MOZ_STACK[TO_MOZ_STACK.length - 2]) : null;
1248 TO_MOZ_STACK.pop();
1249 if (TO_MOZ_STACK.length === 0) { TO_MOZ_STACK = null; }
1250 return ast;
1251 }
1252
1253 function to_moz_in_destructuring() {
1254 var i = TO_MOZ_STACK.length;
1255 while (i--) {
1256 if (TO_MOZ_STACK[i] instanceof AST_Destructuring) {
1257 return true;
1258 }
1259 }
1260 return false;
1261 }
1262
1263 function to_moz_block(node) {
1264 return {
1265 type: "BlockStatement",
1266 body: node.body.map(to_moz)
1267 };
1268 }
1269
1270 function to_moz_scope(type, node) {
1271 var body = node.body.map(to_moz);
1272 if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
1273 body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
1274 }
1275 return {
1276 type: type,
1277 body: body
1278 };
1279 }
1280})();