UNPKG

44.5 kBJavaScriptView Raw
1/***********************************************************************
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 var node = from_moz(M.expression);
560 node.terminal = true;
561 return node;
562 },
563 };
564
565 MOZ_TO_ME.UpdateExpression =
566 MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
567 var prefix = "prefix" in M ? M.prefix
568 : M.type == "UnaryExpression" ? true : false;
569 return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
570 start : my_start_token(M),
571 end : my_end_token(M),
572 operator : M.operator,
573 expression : from_moz(M.argument)
574 });
575 };
576
577 map("EmptyStatement", AST_EmptyStatement);
578 map("ExpressionStatement", AST_SimpleStatement, "expression>body");
579 map("BlockStatement", AST_BlockStatement, "body@body");
580 map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
581 map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
582 map("BreakStatement", AST_Break, "label>label");
583 map("ContinueStatement", AST_Continue, "label>label");
584 map("WithStatement", AST_With, "object>expression, body>body");
585 map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
586 map("ReturnStatement", AST_Return, "argument>value");
587 map("ThrowStatement", AST_Throw, "argument>value");
588 map("WhileStatement", AST_While, "test>condition, body>body");
589 map("DoWhileStatement", AST_Do, "test>condition, body>body");
590 map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
591 map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
592 map("DebuggerStatement", AST_Debugger);
593 map("VariableDeclarator", AST_VarDef, "id>name, init>value");
594 map("CatchClause", AST_Catch, "param>argname, body%body");
595
596 map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
597 map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
598 map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
599 map("AssignmentPattern", AST_DefaultValue, "left>name, right>value");
600 map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
601 map("NewExpression", AST_New, "callee>expression, arguments@args, pure=pure");
602 map("CallExpression", AST_Call, "callee>expression, arguments@args, optional=optional, pure=pure");
603 map("SequenceExpression", AST_Sequence, "expressions@expressions");
604 map("SpreadElement", AST_Spread, "argument>expression");
605 map("ObjectExpression", AST_Object, "properties@properties");
606 map("AwaitExpression", AST_Await, "argument>expression");
607 map("YieldExpression", AST_Yield, "argument>expression, delegate=nested");
608
609 def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
610 return to_moz_scope("Program", M);
611 });
612
613 def_to_moz(AST_LambdaDefinition, function To_Moz_FunctionDeclaration(M) {
614 var params = M.argnames.map(to_moz);
615 if (M.rest) params.push({
616 type: "RestElement",
617 argument: to_moz(M.rest),
618 });
619 return {
620 type: "FunctionDeclaration",
621 id: to_moz(M.name),
622 async: is_async(M),
623 generator: is_generator(M),
624 params: params,
625 body: to_moz_scope("BlockStatement", M),
626 };
627 });
628
629 def_to_moz(AST_Lambda, function To_Moz_FunctionExpression(M) {
630 var params = M.argnames.map(to_moz);
631 if (M.rest) params.push({
632 type: "RestElement",
633 argument: to_moz(M.rest),
634 });
635 if (is_arrow(M)) return {
636 type: "ArrowFunctionExpression",
637 async: is_async(M),
638 params: params,
639 body: M.value ? to_moz(M.value) : to_moz_scope("BlockStatement", M),
640 };
641 return {
642 type: "FunctionExpression",
643 id: to_moz(M.name),
644 async: is_async(M),
645 generator: is_generator(M),
646 params: params,
647 body: to_moz_scope("BlockStatement", M),
648 };
649 });
650
651 def_to_moz(AST_DefClass, function To_Moz_ClassDeclaration(M) {
652 return {
653 type: "ClassDeclaration",
654 id: to_moz(M.name),
655 superClass: to_moz(M.extends),
656 body: {
657 type: "ClassBody",
658 body: M.properties.map(to_moz),
659 },
660 };
661 });
662
663 def_to_moz(AST_ClassExpression, function To_Moz_ClassExpression(M) {
664 return {
665 type: "ClassExpression",
666 id: to_moz(M.name),
667 superClass: to_moz(M.extends),
668 body: {
669 type: "ClassBody",
670 body: M.properties.map(to_moz),
671 },
672 };
673 });
674
675 function To_Moz_MethodDefinition(kind) {
676 return function(M) {
677 var computed = M.key instanceof AST_Node;
678 var key = computed ? to_moz(M.key) : M.private ? {
679 type: "PrivateIdentifier",
680 name: M.key.slice(1),
681 } : {
682 type: "Literal",
683 value: M.key,
684 };
685 return {
686 type: "MethodDefinition",
687 kind: kind,
688 computed: computed,
689 key: key,
690 static: M.static,
691 value: to_moz(M.value),
692 };
693 };
694 }
695 def_to_moz(AST_ClassGetter, To_Moz_MethodDefinition("get"));
696 def_to_moz(AST_ClassSetter, To_Moz_MethodDefinition("set"));
697 def_to_moz(AST_ClassMethod, To_Moz_MethodDefinition("method"));
698
699 def_to_moz(AST_ClassField, function To_Moz_PropertyDefinition(M) {
700 var computed = M.key instanceof AST_Node;
701 var key = computed ? to_moz(M.key) : M.private ? {
702 type: "PrivateIdentifier",
703 name: M.key.slice(1),
704 } : {
705 type: "Literal",
706 value: M.key,
707 };
708 return {
709 type: "PropertyDefinition",
710 computed: computed,
711 key: key,
712 static: M.static,
713 value: to_moz(M.value),
714 };
715 });
716
717 function To_Moz_ForOfStatement(is_await) {
718 return function(M) {
719 return {
720 type: "ForOfStatement",
721 await: is_await,
722 left: to_moz(M.init),
723 right: to_moz(M.object),
724 body: to_moz(M.body),
725 };
726 };
727 }
728 def_to_moz(AST_ForAwaitOf, To_Moz_ForOfStatement(true));
729 def_to_moz(AST_ForOf, To_Moz_ForOfStatement(false));
730
731 def_to_moz(AST_Directive, function To_Moz_Directive(M) {
732 return {
733 type: "ExpressionStatement",
734 expression: set_moz_loc(M, {
735 type: "Literal",
736 value: M.value,
737 }),
738 };
739 });
740
741 def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
742 return {
743 type: "SwitchCase",
744 test: to_moz(M.expression),
745 consequent: M.body.map(to_moz),
746 };
747 });
748
749 def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
750 return {
751 type: "TryStatement",
752 block: to_moz_block(M),
753 handler: to_moz(M.bcatch),
754 guardedHandlers: [],
755 finalizer: to_moz(M.bfinally),
756 };
757 });
758
759 def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
760 return {
761 type: "CatchClause",
762 param: to_moz(M.argname),
763 guard: null,
764 body: to_moz_block(M),
765 };
766 });
767
768 def_to_moz(AST_ExportDeclaration, function To_Moz_ExportNamedDeclaration_declaration(M) {
769 return {
770 type: "ExportNamedDeclaration",
771 declaration: to_moz(M.body),
772 };
773 });
774
775 def_to_moz(AST_ExportDefault, function To_Moz_ExportDefaultDeclaration(M) {
776 return {
777 type: "ExportDefaultDeclaration",
778 declaration: to_moz(M.body),
779 };
780 });
781
782 def_to_moz(AST_ExportForeign, function To_Moz_ExportAllDeclaration_ExportNamedDeclaration(M) {
783 if (M.keys[0] == "*") return {
784 type: "ExportAllDeclaration",
785 exported: M.aliases[0] == "*" ? null : {
786 type: "Identifier",
787 name: M.aliases[0],
788 },
789 source: {
790 type: "Literal",
791 value: M.path,
792 },
793 };
794 var specifiers = [];
795 for (var i = 0; i < M.aliases.length; i++) {
796 specifiers.push({
797 type: "ExportSpecifier",
798 exported: {
799 type: "Identifier",
800 name: M.aliases[i],
801 },
802 local: {
803 type: "Identifier",
804 name: M.keys[i],
805 },
806 });
807 }
808 return {
809 type: "ExportNamedDeclaration",
810 specifiers: specifiers,
811 source: {
812 type: "Literal",
813 value: M.path,
814 },
815 };
816 });
817
818 def_to_moz(AST_ExportReferences, function To_Moz_ExportNamedDeclaration_specifiers(M) {
819 return {
820 type: "ExportNamedDeclaration",
821 specifiers: M.properties.map(function(prop) {
822 return {
823 type: "ExportSpecifier",
824 local: to_moz(prop),
825 exported: {
826 type: "Identifier",
827 name: prop.alias,
828 },
829 };
830 }),
831 };
832 });
833
834 def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
835 var specifiers = M.properties ? M.properties.map(function(prop) {
836 return {
837 type: "ImportSpecifier",
838 local: to_moz(prop),
839 imported: {
840 type: "Identifier",
841 name: prop.key,
842 },
843 };
844 }) : [];
845 if (M.all) specifiers.unshift({
846 type: "ImportNamespaceSpecifier",
847 local: to_moz(M.all),
848 });
849 if (M.default) specifiers.unshift({
850 type: "ImportDefaultSpecifier",
851 local: to_moz(M.default),
852 });
853 return {
854 type: "ImportDeclaration",
855 specifiers: specifiers,
856 source: {
857 type: "Literal",
858 value: M.path,
859 },
860 };
861 });
862
863 def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
864 return {
865 type: "VariableDeclaration",
866 kind: M.TYPE.toLowerCase(),
867 declarations: M.definitions.map(to_moz),
868 };
869 });
870
871 def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
872 var computed = M instanceof AST_Sub;
873 var expr = {
874 type: "MemberExpression",
875 object: to_moz(M.expression),
876 computed: computed,
877 optional: M.optional,
878 property: computed ? to_moz(M.property) : {
879 type: "Identifier",
880 name: M.property,
881 },
882 };
883 return M.terminal ? {
884 type: "ChainExpression",
885 expression: expr,
886 } : expr;
887 });
888
889 def_to_moz(AST_Unary, function To_Moz_Unary(M) {
890 return {
891 type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
892 operator: M.operator,
893 prefix: M instanceof AST_UnaryPrefix,
894 argument: to_moz(M.expression)
895 };
896 });
897
898 def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
899 return {
900 type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
901 left: to_moz(M.left),
902 operator: M.operator,
903 right: to_moz(M.right)
904 };
905 });
906
907 def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
908 return {
909 type: "ArrayExpression",
910 elements: M.elements.map(to_moz),
911 };
912 });
913
914 def_to_moz(AST_DestructuredArray, function To_Moz_ArrayPattern(M) {
915 var elements = M.elements.map(to_moz);
916 if (M.rest) elements.push({
917 type: "RestElement",
918 argument: to_moz(M.rest),
919 });
920 return {
921 type: "ArrayPattern",
922 elements: elements,
923 };
924 });
925
926 def_to_moz(AST_DestructuredKeyVal, function To_Moz_Property(M) {
927 var computed = M.key instanceof AST_Node;
928 var key = computed ? to_moz(M.key) : {
929 type: "Literal",
930 value: M.key,
931 };
932 return {
933 type: "Property",
934 kind: "init",
935 computed: computed,
936 key: key,
937 value: to_moz(M.value),
938 };
939 });
940
941 def_to_moz(AST_DestructuredObject, function To_Moz_ObjectPattern(M) {
942 var props = M.properties.map(to_moz);
943 if (M.rest) props.push({
944 type: "RestElement",
945 argument: to_moz(M.rest),
946 });
947 return {
948 type: "ObjectPattern",
949 properties: props,
950 };
951 });
952
953 def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
954 var computed = M.key instanceof AST_Node;
955 var key = computed ? to_moz(M.key) : {
956 type: "Literal",
957 value: M.key,
958 };
959 var kind;
960 if (M instanceof AST_ObjectKeyVal) {
961 kind = "init";
962 } else if (M instanceof AST_ObjectGetter) {
963 kind = "get";
964 } else if (M instanceof AST_ObjectSetter) {
965 kind = "set";
966 }
967 return {
968 type: "Property",
969 kind: kind,
970 computed: computed,
971 method: M instanceof AST_ObjectMethod,
972 key: key,
973 value: to_moz(M.value),
974 };
975 });
976
977 def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
978 var def = M.definition();
979 return {
980 type: "Identifier",
981 name: def && def.mangled_name || M.name,
982 };
983 });
984
985 def_to_moz(AST_Super, function To_Moz_Super() {
986 return { type: "Super" };
987 });
988
989 def_to_moz(AST_This, function To_Moz_ThisExpression() {
990 return { type: "ThisExpression" };
991 });
992
993 def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
994 return {
995 type: "MetaProperty",
996 meta: {
997 type: "Identifier",
998 name: "new",
999 },
1000 property: {
1001 type: "Identifier",
1002 name: "target",
1003 },
1004 };
1005 });
1006
1007 def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
1008 var flags = M.value.toString().match(/[gimuy]*$/)[0];
1009 var value = "/" + M.value.raw_source + "/" + flags;
1010 return {
1011 type: "Literal",
1012 value: value,
1013 raw: value,
1014 regex: {
1015 pattern: M.value.raw_source,
1016 flags: flags
1017 }
1018 };
1019 });
1020
1021 def_to_moz(AST_BigInt, function To_Moz_BigInt(M) {
1022 var value = M.value;
1023 return {
1024 type: "Literal",
1025 bigint: value.slice(0, -1),
1026 raw: value,
1027 };
1028 });
1029
1030 function To_Moz_Literal(M) {
1031 var value = M.value;
1032 if (typeof value === "number" && (value < 0 || (value === 0 && 1 / value < 0))) {
1033 return {
1034 type: "UnaryExpression",
1035 operator: "-",
1036 prefix: true,
1037 argument: {
1038 type: "Literal",
1039 value: -value,
1040 raw: M.start.raw,
1041 },
1042 };
1043 }
1044 return {
1045 type: "Literal",
1046 value: value,
1047 raw: M.start.raw,
1048 };
1049 }
1050 def_to_moz(AST_Boolean, To_Moz_Literal);
1051 def_to_moz(AST_Constant, To_Moz_Literal);
1052 def_to_moz(AST_Null, To_Moz_Literal);
1053
1054 def_to_moz(AST_Atom, function To_Moz_Atom(M) {
1055 return {
1056 type: "Identifier",
1057 name: String(M.value),
1058 };
1059 });
1060
1061 def_to_moz(AST_Template, function To_Moz_TemplateLiteral_TaggedTemplateExpression(M) {
1062 var last = M.strings.length - 1;
1063 var tmpl = {
1064 type: "TemplateLiteral",
1065 expressions: M.expressions.map(to_moz),
1066 quasis: M.strings.map(function(str, index) {
1067 return {
1068 type: "TemplateElement",
1069 tail: index == last,
1070 value: { raw: str },
1071 };
1072 }),
1073 };
1074 if (!M.tag) return tmpl;
1075 return {
1076 type: "TaggedTemplateExpression",
1077 tag: to_moz(M.tag),
1078 quasi: tmpl,
1079 };
1080 });
1081
1082 AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
1083 AST_Hole.DEFMETHOD("to_mozilla_ast", return_null);
1084 AST_Node.DEFMETHOD("to_mozilla_ast", function() {
1085 throw new Error("Cannot convert AST_" + this.TYPE);
1086 });
1087
1088 /* -----[ tools ]----- */
1089
1090 function normalize_directives(body) {
1091 for (var i = 0; i < body.length; i++) {
1092 var stat = body[i];
1093 if (!(stat instanceof AST_SimpleStatement)) break;
1094 var node = stat.body;
1095 if (!(node instanceof AST_String)) break;
1096 if (stat.start.pos !== node.start.pos) break;
1097 body[i] = new AST_Directive(node);
1098 }
1099 return body;
1100 }
1101
1102 function raw_token(moznode) {
1103 if (moznode.type == "Literal") {
1104 return moznode.raw != null ? moznode.raw : moznode.value + "";
1105 }
1106 }
1107
1108 function my_start_token(moznode) {
1109 var loc = moznode.loc, start = loc && loc.start;
1110 var range = moznode.range;
1111 return new AST_Token({
1112 file : loc && loc.source,
1113 line : start && start.line,
1114 col : start && start.column,
1115 pos : range ? range[0] : moznode.start,
1116 endline : start && start.line,
1117 endcol : start && start.column,
1118 endpos : range ? range[0] : moznode.start,
1119 raw : raw_token(moznode),
1120 });
1121 }
1122
1123 function my_end_token(moznode) {
1124 var loc = moznode.loc, end = loc && loc.end;
1125 var range = moznode.range;
1126 return new AST_Token({
1127 file : loc && loc.source,
1128 line : end && end.line,
1129 col : end && end.column,
1130 pos : range ? range[1] : moznode.end,
1131 endline : end && end.line,
1132 endcol : end && end.column,
1133 endpos : range ? range[1] : moznode.end,
1134 raw : raw_token(moznode),
1135 });
1136 }
1137
1138 function read_name(M) {
1139 return "" + M[M.type == "Identifier" ? "name" : "value"];
1140 }
1141
1142 function map(moztype, mytype, propmap) {
1143 var moz_to_me = [
1144 "start: my_start_token(M)",
1145 "end: my_end_token(M)",
1146 ];
1147 var me_to_moz = [
1148 "type: " + JSON.stringify(moztype),
1149 ];
1150
1151 if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
1152 var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
1153 if (!m) throw new Error("Can't understand property map: " + prop);
1154 var moz = m[1], how = m[2], my = m[3];
1155 switch (how) {
1156 case "@":
1157 moz_to_me.push(my + ": M." + moz + ".map(from_moz)");
1158 me_to_moz.push(moz + ": M." + my + ".map(to_moz)");
1159 break;
1160 case ">":
1161 moz_to_me.push(my + ": from_moz(M." + moz + ")");
1162 me_to_moz.push(moz + ": to_moz(M." + my + ")");
1163 break;
1164 case "=":
1165 moz_to_me.push(my + ": M." + moz);
1166 me_to_moz.push(moz + ": M." + my);
1167 break;
1168 case "%":
1169 moz_to_me.push(my + ": from_moz(M." + moz + ").body");
1170 me_to_moz.push(moz + ": to_moz_block(M)");
1171 break;
1172 default:
1173 throw new Error("Can't understand operator in propmap: " + prop);
1174 }
1175 });
1176
1177 MOZ_TO_ME[moztype] = new Function("U2", "my_start_token", "my_end_token", "from_moz", [
1178 "return function From_Moz_" + moztype + "(M) {",
1179 " return new U2.AST_" + mytype.TYPE + "({",
1180 moz_to_me.join(",\n"),
1181 " });",
1182 "};",
1183 ].join("\n"))(exports, my_start_token, my_end_token, from_moz);
1184 def_to_moz(mytype, new Function("to_moz", "to_moz_block", "to_moz_scope", [
1185 "return function To_Moz_" + moztype + "(M) {",
1186 " return {",
1187 me_to_moz.join(",\n"),
1188 " };",
1189 "};",
1190 ].join("\n"))(to_moz, to_moz_block, to_moz_scope));
1191 }
1192
1193 var FROM_MOZ_STACK = null;
1194
1195 function from_moz(moz) {
1196 FROM_MOZ_STACK.push(moz);
1197 var node = null;
1198 if (moz) {
1199 if (!HOP(MOZ_TO_ME, moz.type)) throw new Error("Unsupported type: " + moz.type);
1200 node = MOZ_TO_ME[moz.type](moz);
1201 }
1202 FROM_MOZ_STACK.pop();
1203 return node;
1204 }
1205
1206 AST_Node.from_mozilla_ast = function(node) {
1207 var save_stack = FROM_MOZ_STACK;
1208 FROM_MOZ_STACK = [];
1209 var ast = from_moz(node);
1210 FROM_MOZ_STACK = save_stack;
1211 ast.walk(new TreeWalker(function(node) {
1212 if (node instanceof AST_LabelRef) {
1213 for (var level = 0, parent; parent = this.parent(level); level++) {
1214 if (parent instanceof AST_Scope) break;
1215 if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
1216 node.thedef = parent.label;
1217 break;
1218 }
1219 }
1220 if (!node.thedef) {
1221 var s = node.start;
1222 js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
1223 }
1224 }
1225 }));
1226 return ast;
1227 };
1228
1229 function set_moz_loc(mynode, moznode) {
1230 var start = mynode.start;
1231 var end = mynode.end;
1232 if (start.pos != null && end.endpos != null) {
1233 moznode.range = [start.pos, end.endpos];
1234 }
1235 if (start.line) {
1236 moznode.loc = {
1237 start: {line: start.line, column: start.col},
1238 end: end.endline ? {line: end.endline, column: end.endcol} : null,
1239 };
1240 if (start.file) {
1241 moznode.loc.source = start.file;
1242 }
1243 }
1244 return moznode;
1245 }
1246
1247 function def_to_moz(mytype, handler) {
1248 mytype.DEFMETHOD("to_mozilla_ast", function() {
1249 return set_moz_loc(this, handler(this));
1250 });
1251 }
1252
1253 function to_moz(node) {
1254 return node != null ? node.to_mozilla_ast() : null;
1255 }
1256
1257 function to_moz_block(node) {
1258 return {
1259 type: "BlockStatement",
1260 body: node.body.map(to_moz),
1261 };
1262 }
1263
1264 function to_moz_scope(type, node) {
1265 var body = node.body.map(to_moz);
1266 if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
1267 body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
1268 }
1269 return {
1270 type: type,
1271 body: body,
1272 };
1273 }
1274})();