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