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