OLD | NEW |
1 // This script rewrites AST to be compatible with JavaScript 1.5 and decompiles | 1 // This script rewrites AST to be compatible with JavaScript 1.5 and decompiles |
2 // the modified tree then | 2 // the modified tree then |
3 | 3 |
4 include("../scripts/astDecompile.js"); | 4 include("../scripts/astDecompile.js"); |
5 include("../utils/beautify.js"); | 5 include("../utils/beautify.js"); |
6 | 6 |
7 let headerPrinted = false; | 7 let headerPrinted = false; |
8 | 8 |
9 // See https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API for | 9 // See https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API for |
10 // AST structure. | 10 // AST structure. |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 return modifyForStatement(ast.body); | 389 return modifyForStatement(ast.body); |
390 } | 390 } |
391 | 391 |
392 return ast; | 392 return ast; |
393 } | 393 } |
394 | 394 |
395 function modifyFunctionExpression(ast) | 395 function modifyFunctionExpression(ast) |
396 { | 396 { |
397 if (ast.expression) | 397 if (ast.expression) |
398 { | 398 { |
399 // Convert expression closures: | 399 print("Use arrow functions instead of function expressions!\n"); |
400 // function() foo; | 400 throw new Error("Use arrow functions instead of function expressions!"); |
401 // | |
402 // Change into: | |
403 // function() | |
404 // { | |
405 // return foo; | |
406 // } | |
407 ast.expression = false; | |
408 ast.body = { | |
409 type: "BlockStatement", | |
410 body: [ | |
411 { | |
412 type: "ReturnStatement", | |
413 argument: ast.body | |
414 } | |
415 ] | |
416 }; | |
417 } | 401 } |
418 | 402 |
419 if (ast.generator) | 403 if (ast.generator) |
420 { | 404 { |
421 // Convert generators: | 405 // Convert generators: |
422 // function() | 406 // function() |
423 // { | 407 // { |
424 // ... | 408 // ... |
425 // yield "foo"; | 409 // yield "foo"; |
426 // ... | 410 // ... |
(...skipping 25 matching lines...) Expand all Loading... |
452 } | 436 } |
453 | 437 |
454 return ast; | 438 return ast; |
455 } | 439 } |
456 | 440 |
457 function modifyFunctionDeclaration(ast) | 441 function modifyFunctionDeclaration(ast) |
458 { | 442 { |
459 return modifyFunctionExpression(ast); | 443 return modifyFunctionExpression(ast); |
460 } | 444 } |
461 | 445 |
| 446 function modifyArrowExpression(ast) |
| 447 { |
| 448 if (ast.body.type != "BlockStatement") { |
| 449 // Convert expressions to block statements. |
| 450 // (a) => a + 1 |
| 451 // |
| 452 // Change into: |
| 453 // (a) => { return a + 1; } |
| 454 ast.body = { |
| 455 type: "BlockStatement", |
| 456 body: [ |
| 457 { |
| 458 type: "ReturnStatement", |
| 459 argument: ast.body |
| 460 } |
| 461 ] |
| 462 }; |
| 463 } |
| 464 |
| 465 // Now convert the arrow expression into a normal |
| 466 // function expression. |
| 467 ast.type = "FunctionExpression"; |
| 468 ast.expression = false; |
| 469 |
| 470 // We want to avoid the .bind call if |this| isn't actually used. |
| 471 // This is not necessarily always correct, but should be good enough. |
| 472 var body = decompileAST(ast.body); |
| 473 if (["this", "Function", "eval", "=>"].some(search => body.contains(search)))
{ |
| 474 return { |
| 475 type: "CallExpression", |
| 476 callee: Member(ast, "bind"), |
| 477 arguments: [ |
| 478 { |
| 479 type: "ThisExpression" |
| 480 } |
| 481 ] |
| 482 }; |
| 483 } |
| 484 return ast; |
| 485 } |
| 486 |
462 function modifyYieldExpression(ast) | 487 function modifyYieldExpression(ast) |
463 { | 488 { |
464 // Convert generators into functions returning arrays: | 489 // Convert generators into functions returning arrays: |
465 // yield "foo"; | 490 // yield "foo"; |
466 // | 491 // |
467 // Change into: | 492 // Change into: |
468 // _generatorResult44.push("foo"); | 493 // _generatorResult44.push("foo"); |
469 | 494 |
470 if (ast.argument) | 495 if (ast.argument) |
471 { | 496 { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 let code = 'require.scopes["' + options.filename + '"] = (function() {\n' + | 568 let code = 'require.scopes["' + options.filename + '"] = (function() {\n' + |
544 'var exports = {};\n' + | 569 'var exports = {};\n' + |
545 decompileAST(ast) + | 570 decompileAST(ast) + |
546 'return exports;\n' + | 571 'return exports;\n' + |
547 '})();\n'; | 572 '})();\n'; |
548 _print(js_beautify(code, options)); | 573 _print(js_beautify(code, options)); |
549 } | 574 } |
550 else | 575 else |
551 _print(js_beautify(decompileAST(ast), options)); | 576 _print(js_beautify(decompileAST(ast), options)); |
552 } | 577 } |
OLD | NEW |