jass 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +47 -0
- data/README.md +45 -0
- data/lib/jass.rb +55 -0
- data/lib/jass/base.rb +141 -0
- data/lib/jass/bundle_processor.rb +28 -0
- data/lib/jass/compiler.rb +112 -0
- data/lib/jass/dependency.rb +14 -0
- data/lib/jass/errors.rb +29 -0
- data/lib/jass/es6_processor.rb +17 -0
- data/lib/jass/function.rb +13 -0
- data/lib/jass/global_directive_processor.rb +12 -0
- data/lib/jass/plugin.rb +13 -0
- data/lib/jass/railtie.rb +12 -0
- data/lib/jass/version.rb +3 -0
- data/vendor/node_modules/@types/acorn/index.d.ts +256 -0
- data/vendor/node_modules/@types/acorn/package.json +29 -0
- data/vendor/node_modules/@types/estree/index.d.ts +546 -0
- data/vendor/node_modules/@types/estree/package.json +22 -0
- data/vendor/node_modules/acorn-dynamic-import/lib/index.js +17 -0
- data/vendor/node_modules/acorn-dynamic-import/lib/inject.js +72 -0
- data/vendor/node_modules/acorn-dynamic-import/lib/walk.js +22 -0
- data/vendor/node_modules/acorn-dynamic-import/package.json +45 -0
- data/vendor/node_modules/acorn-dynamic-import/src/index.js +4 -0
- data/vendor/node_modules/acorn-dynamic-import/src/inject.js +52 -0
- data/vendor/node_modules/acorn-dynamic-import/src/walk.js +12 -0
- data/vendor/node_modules/acorn-es7-plugin/acorn-es7-plugin.js +17 -0
- data/vendor/node_modules/acorn-es7-plugin/acorn-v3.js +333 -0
- data/vendor/node_modules/acorn-es7-plugin/acorn-v4.js +194 -0
- data/vendor/node_modules/acorn-es7-plugin/package.json +29 -0
- data/vendor/node_modules/acorn-jsx/index.js +3 -0
- data/vendor/node_modules/acorn-jsx/inject.js +449 -0
- data/vendor/node_modules/acorn-jsx/package.json +28 -0
- data/vendor/node_modules/acorn-jsx/xhtml.js +255 -0
- data/vendor/node_modules/acorn/bin/_acorn.js +69 -0
- data/vendor/node_modules/acorn/bin/acorn +4 -0
- data/vendor/node_modules/acorn/bin/run_test262.js +22 -0
- data/vendor/node_modules/acorn/bin/test262.whitelist +409 -0
- data/vendor/node_modules/acorn/dist/acorn.es.js +5305 -0
- data/vendor/node_modules/acorn/dist/acorn.js +5336 -0
- data/vendor/node_modules/acorn/dist/acorn_loose.es.js +1412 -0
- data/vendor/node_modules/acorn/dist/acorn_loose.js +1422 -0
- data/vendor/node_modules/acorn/dist/walk.es.js +419 -0
- data/vendor/node_modules/acorn/dist/walk.js +439 -0
- data/vendor/node_modules/acorn/package.json +56 -0
- data/vendor/node_modules/ansi-styles/index.js +165 -0
- data/vendor/node_modules/ansi-styles/package.json +56 -0
- data/vendor/node_modules/arr-diff/index.js +58 -0
- data/vendor/node_modules/arr-diff/package.json +49 -0
- data/vendor/node_modules/arr-flatten/index.js +22 -0
- data/vendor/node_modules/arr-flatten/package.json +76 -0
- data/vendor/node_modules/array-unique/index.js +28 -0
- data/vendor/node_modules/array-unique/package.json +37 -0
- data/vendor/node_modules/braces/index.js +399 -0
- data/vendor/node_modules/braces/package.json +83 -0
- data/vendor/node_modules/buble/bin/buble +24 -0
- data/vendor/node_modules/buble/bin/handleError.js +58 -0
- data/vendor/node_modules/buble/bin/runBuble.js +150 -0
- data/vendor/node_modules/buble/bin/showHelp.js +16 -0
- data/vendor/node_modules/buble/dist/buble-browser-deps.umd.js +14857 -0
- data/vendor/node_modules/buble/dist/buble-browser.cjs.js +9941 -0
- data/vendor/node_modules/buble/dist/buble-browser.es.js +9933 -0
- data/vendor/node_modules/buble/dist/buble.cjs.js +9433 -0
- data/vendor/node_modules/buble/dist/buble.es.js +9425 -0
- data/vendor/node_modules/buble/package.json +74 -0
- data/vendor/node_modules/buble/register.js +90 -0
- data/vendor/node_modules/buble/src/index.js +98 -0
- data/vendor/node_modules/buble/src/program/BlockStatement.js +373 -0
- data/vendor/node_modules/buble/src/program/Node.js +112 -0
- data/vendor/node_modules/buble/src/program/Program.js +74 -0
- data/vendor/node_modules/buble/src/program/Scope.js +116 -0
- data/vendor/node_modules/buble/src/program/extractNames.js +35 -0
- data/vendor/node_modules/buble/src/program/keys.js +4 -0
- data/vendor/node_modules/buble/src/program/types/ArrayExpression.js +70 -0
- data/vendor/node_modules/buble/src/program/types/ArrowFunctionExpression.js +52 -0
- data/vendor/node_modules/buble/src/program/types/AssignmentExpression.js +185 -0
- data/vendor/node_modules/buble/src/program/types/BinaryExpression.js +12 -0
- data/vendor/node_modules/buble/src/program/types/BreakStatement.js +26 -0
- data/vendor/node_modules/buble/src/program/types/CallExpression.js +104 -0
- data/vendor/node_modules/buble/src/program/types/ClassBody.js +237 -0
- data/vendor/node_modules/buble/src/program/types/ClassDeclaration.js +79 -0
- data/vendor/node_modules/buble/src/program/types/ClassExpression.js +51 -0
- data/vendor/node_modules/buble/src/program/types/ContinueStatement.js +17 -0
- data/vendor/node_modules/buble/src/program/types/ExportDefaultDeclaration.js +10 -0
- data/vendor/node_modules/buble/src/program/types/ExportNamedDeclaration.js +10 -0
- data/vendor/node_modules/buble/src/program/types/ForInStatement.js +76 -0
- data/vendor/node_modules/buble/src/program/types/ForOfStatement.js +89 -0
- data/vendor/node_modules/buble/src/program/types/ForStatement.js +54 -0
- data/vendor/node_modules/buble/src/program/types/FunctionDeclaration.js +25 -0
- data/vendor/node_modules/buble/src/program/types/FunctionExpression.js +74 -0
- data/vendor/node_modules/buble/src/program/types/Identifier.js +54 -0
- data/vendor/node_modules/buble/src/program/types/IfStatement.js +29 -0
- data/vendor/node_modules/buble/src/program/types/ImportDeclaration.js +10 -0
- data/vendor/node_modules/buble/src/program/types/ImportDefaultSpecifier.js +8 -0
- data/vendor/node_modules/buble/src/program/types/ImportSpecifier.js +8 -0
- data/vendor/node_modules/buble/src/program/types/JSXAttribute.js +20 -0
- data/vendor/node_modules/buble/src/program/types/JSXClosingElement.js +27 -0
- data/vendor/node_modules/buble/src/program/types/JSXClosingFragment.js +22 -0
- data/vendor/node_modules/buble/src/program/types/JSXElement.js +57 -0
- data/vendor/node_modules/buble/src/program/types/JSXExpressionContainer.js +10 -0
- data/vendor/node_modules/buble/src/program/types/JSXFragment.js +4 -0
- data/vendor/node_modules/buble/src/program/types/JSXOpeningElement.js +93 -0
- data/vendor/node_modules/buble/src/program/types/JSXOpeningFragment.js +7 -0
- data/vendor/node_modules/buble/src/program/types/JSXSpreadAttribute.js +10 -0
- data/vendor/node_modules/buble/src/program/types/Literal.js +43 -0
- data/vendor/node_modules/buble/src/program/types/MemberExpression.js +13 -0
- data/vendor/node_modules/buble/src/program/types/NewExpression.js +55 -0
- data/vendor/node_modules/buble/src/program/types/ObjectExpression.js +250 -0
- data/vendor/node_modules/buble/src/program/types/Property.js +52 -0
- data/vendor/node_modules/buble/src/program/types/ReturnStatement.js +32 -0
- data/vendor/node_modules/buble/src/program/types/SpreadElement.js +12 -0
- data/vendor/node_modules/buble/src/program/types/Super.js +88 -0
- data/vendor/node_modules/buble/src/program/types/TaggedTemplateExpression.js +63 -0
- data/vendor/node_modules/buble/src/program/types/TemplateElement.js +7 -0
- data/vendor/node_modules/buble/src/program/types/TemplateLiteral.js +80 -0
- data/vendor/node_modules/buble/src/program/types/ThisExpression.js +31 -0
- data/vendor/node_modules/buble/src/program/types/UpdateExpression.js +32 -0
- data/vendor/node_modules/buble/src/program/types/VariableDeclaration.js +101 -0
- data/vendor/node_modules/buble/src/program/types/VariableDeclarator.js +43 -0
- data/vendor/node_modules/buble/src/program/types/index.js +98 -0
- data/vendor/node_modules/buble/src/program/types/shared/LoopStatement.js +105 -0
- data/vendor/node_modules/buble/src/program/types/shared/ModuleDeclaration.js +10 -0
- data/vendor/node_modules/buble/src/program/wrap.js +68 -0
- data/vendor/node_modules/buble/src/support.js +97 -0
- data/vendor/node_modules/buble/src/utils/CompileError.js +30 -0
- data/vendor/node_modules/buble/src/utils/array.js +11 -0
- data/vendor/node_modules/buble/src/utils/checkConst.js +8 -0
- data/vendor/node_modules/buble/src/utils/deindent.js +30 -0
- data/vendor/node_modules/buble/src/utils/destructure.js +377 -0
- data/vendor/node_modules/buble/src/utils/getSnippet.js +30 -0
- data/vendor/node_modules/buble/src/utils/isReference.js +41 -0
- data/vendor/node_modules/buble/src/utils/locate.js +20 -0
- data/vendor/node_modules/buble/src/utils/patterns.js +1 -0
- data/vendor/node_modules/buble/src/utils/removeTrailingComma.js +13 -0
- data/vendor/node_modules/buble/src/utils/reserved.js +6 -0
- data/vendor/node_modules/buble/src/utils/spread.js +70 -0
- data/vendor/node_modules/builtin-modules/builtin-modules.json +39 -0
- data/vendor/node_modules/builtin-modules/index.js +10 -0
- data/vendor/node_modules/builtin-modules/package.json +40 -0
- data/vendor/node_modules/builtin-modules/static.js +2 -0
- data/vendor/node_modules/chalk/index.js +228 -0
- data/vendor/node_modules/chalk/package.json +66 -0
- data/vendor/node_modules/chalk/templates.js +128 -0
- data/vendor/node_modules/chalk/types/index.d.ts +97 -0
- data/vendor/node_modules/color-convert/conversions.js +861 -0
- data/vendor/node_modules/color-convert/index.js +78 -0
- data/vendor/node_modules/color-convert/package.json +46 -0
- data/vendor/node_modules/color-convert/route.js +97 -0
- data/vendor/node_modules/color-name/index.js +152 -0
- data/vendor/node_modules/color-name/package.json +25 -0
- data/vendor/node_modules/color-name/test.js +7 -0
- data/vendor/node_modules/date-time/index.js +33 -0
- data/vendor/node_modules/date-time/package.json +39 -0
- data/vendor/node_modules/escape-string-regexp/index.js +11 -0
- data/vendor/node_modules/escape-string-regexp/package.json +41 -0
- data/vendor/node_modules/estree-walker/dist/estree-walker.es.js +57 -0
- data/vendor/node_modules/estree-walker/dist/estree-walker.umd.js +68 -0
- data/vendor/node_modules/estree-walker/package.json +34 -0
- data/vendor/node_modules/estree-walker/src/estree-walker.js +51 -0
- data/vendor/node_modules/expand-brackets/index.js +163 -0
- data/vendor/node_modules/expand-brackets/package.json +62 -0
- data/vendor/node_modules/expand-range/index.js +43 -0
- data/vendor/node_modules/expand-range/package.json +73 -0
- data/vendor/node_modules/extglob/index.js +178 -0
- data/vendor/node_modules/extglob/package.json +60 -0
- data/vendor/node_modules/filename-regex/index.js +10 -0
- data/vendor/node_modules/filename-regex/package.json +50 -0
- data/vendor/node_modules/fill-range/index.js +408 -0
- data/vendor/node_modules/fill-range/package.json +61 -0
- data/vendor/node_modules/for-in/index.js +16 -0
- data/vendor/node_modules/for-in/package.json +68 -0
- data/vendor/node_modules/for-own/index.js +19 -0
- data/vendor/node_modules/for-own/package.json +70 -0
- data/vendor/node_modules/glob-base/index.js +51 -0
- data/vendor/node_modules/glob-base/package.json +52 -0
- data/vendor/node_modules/glob-parent/index.js +10 -0
- data/vendor/node_modules/glob-parent/package.json +35 -0
- data/vendor/node_modules/glob-parent/test.js +28 -0
- data/vendor/node_modules/has-flag/index.js +8 -0
- data/vendor/node_modules/has-flag/package.json +44 -0
- data/vendor/node_modules/irregular-plurals/irregular-plurals.json +146 -0
- data/vendor/node_modules/irregular-plurals/package.json +39 -0
- data/vendor/node_modules/is-buffer/index.js +21 -0
- data/vendor/node_modules/is-buffer/package.json +51 -0
- data/vendor/node_modules/is-dotfile/index.js +14 -0
- data/vendor/node_modules/is-dotfile/package.json +69 -0
- data/vendor/node_modules/is-equal-shallow/index.js +27 -0
- data/vendor/node_modules/is-equal-shallow/package.json +54 -0
- data/vendor/node_modules/is-extendable/index.js +13 -0
- data/vendor/node_modules/is-extendable/package.json +51 -0
- data/vendor/node_modules/is-extglob/index.js +11 -0
- data/vendor/node_modules/is-extglob/package.json +48 -0
- data/vendor/node_modules/is-glob/index.js +14 -0
- data/vendor/node_modules/is-glob/package.json +60 -0
- data/vendor/node_modules/is-module/index.js +11 -0
- data/vendor/node_modules/is-module/package.json +20 -0
- data/vendor/node_modules/is-number/index.js +19 -0
- data/vendor/node_modules/is-number/package.json +59 -0
- data/vendor/node_modules/is-posix-bracket/index.js +10 -0
- data/vendor/node_modules/is-posix-bracket/package.json +64 -0
- data/vendor/node_modules/is-primitive/index.js +13 -0
- data/vendor/node_modules/is-primitive/package.json +46 -0
- data/vendor/node_modules/is-reference/dist/is-reference.es.js +26 -0
- data/vendor/node_modules/is-reference/dist/is-reference.js +34 -0
- data/vendor/node_modules/is-reference/dist/types/index.d.ts +2 -0
- data/vendor/node_modules/is-reference/package.json +47 -0
- data/vendor/node_modules/isarray/index.js +5 -0
- data/vendor/node_modules/isarray/package.json +45 -0
- data/vendor/node_modules/isarray/test.js +20 -0
- data/vendor/node_modules/isobject/index.js +14 -0
- data/vendor/node_modules/isobject/package.json +67 -0
- data/vendor/node_modules/kind-of/index.js +116 -0
- data/vendor/node_modules/kind-of/package.json +90 -0
- data/vendor/node_modules/locate-character/dist/locate-character.es.js +43 -0
- data/vendor/node_modules/locate-character/dist/locate-character.umd.js +54 -0
- data/vendor/node_modules/locate-character/dist/types/index.d.ts +17 -0
- data/vendor/node_modules/locate-character/package.json +41 -0
- data/vendor/node_modules/magic-string/dist/magic-string.cjs.js +1300 -0
- data/vendor/node_modules/magic-string/dist/magic-string.es.js +1296 -0
- data/vendor/node_modules/magic-string/dist/magic-string.umd.js +1352 -0
- data/vendor/node_modules/magic-string/index.d.ts +83 -0
- data/vendor/node_modules/magic-string/node_modules/vlq/dist/vlq.js +91 -0
- data/vendor/node_modules/magic-string/node_modules/vlq/package.json +27 -0
- data/vendor/node_modules/magic-string/node_modules/vlq/src/vlq.js +78 -0
- data/vendor/node_modules/magic-string/package.json +55 -0
- data/vendor/node_modules/micromatch/index.js +431 -0
- data/vendor/node_modules/micromatch/lib/chars.js +67 -0
- data/vendor/node_modules/micromatch/lib/expand.js +304 -0
- data/vendor/node_modules/micromatch/lib/glob.js +193 -0
- data/vendor/node_modules/micromatch/lib/utils.js +149 -0
- data/vendor/node_modules/micromatch/package.json +114 -0
- data/vendor/node_modules/minimist/index.js +236 -0
- data/vendor/node_modules/minimist/package.json +45 -0
- data/vendor/node_modules/nodent-compiler/compiler.js +171 -0
- data/vendor/node_modules/nodent-compiler/lib/arboriculture.js +2694 -0
- data/vendor/node_modules/nodent-compiler/lib/output.js +934 -0
- data/vendor/node_modules/nodent-compiler/lib/parser.js +291 -0
- data/vendor/node_modules/nodent-compiler/package.json +37 -0
- data/vendor/node_modules/normalize-path/index.js +19 -0
- data/vendor/node_modules/normalize-path/package.json +78 -0
- data/vendor/node_modules/object.omit/index.js +40 -0
- data/vendor/node_modules/object.omit/package.json +67 -0
- data/vendor/node_modules/os-homedir/index.js +24 -0
- data/vendor/node_modules/os-homedir/package.json +41 -0
- data/vendor/node_modules/parse-glob/index.js +156 -0
- data/vendor/node_modules/parse-glob/package.json +62 -0
- data/vendor/node_modules/parse-ms/index.js +16 -0
- data/vendor/node_modules/parse-ms/package.json +34 -0
- data/vendor/node_modules/path-parse/index.js +93 -0
- data/vendor/node_modules/path-parse/index.min.js +1 -0
- data/vendor/node_modules/path-parse/package.json +33 -0
- data/vendor/node_modules/path-parse/test.js +77 -0
- data/vendor/node_modules/path-parse/test.min.js +1 -0
- data/vendor/node_modules/plur/index.js +20 -0
- data/vendor/node_modules/plur/package.json +42 -0
- data/vendor/node_modules/preserve/index.js +54 -0
- data/vendor/node_modules/preserve/package.json +48 -0
- data/vendor/node_modules/preserve/test.js +48 -0
- data/vendor/node_modules/pretty-ms/index.js +48 -0
- data/vendor/node_modules/pretty-ms/package.json +48 -0
- data/vendor/node_modules/randomatic/index.js +82 -0
- data/vendor/node_modules/randomatic/node_modules/is-number/index.js +22 -0
- data/vendor/node_modules/randomatic/node_modules/is-number/node_modules/kind-of/index.js +116 -0
- data/vendor/node_modules/randomatic/node_modules/is-number/node_modules/kind-of/package.json +90 -0
- data/vendor/node_modules/randomatic/node_modules/is-number/package.json +83 -0
- data/vendor/node_modules/randomatic/node_modules/kind-of/index.js +119 -0
- data/vendor/node_modules/randomatic/node_modules/kind-of/package.json +90 -0
- data/vendor/node_modules/randomatic/package.json +78 -0
- data/vendor/node_modules/regex-cache/index.js +68 -0
- data/vendor/node_modules/regex-cache/package.json +64 -0
- data/vendor/node_modules/remove-trailing-separator/index.js +17 -0
- data/vendor/node_modules/remove-trailing-separator/package.json +37 -0
- data/vendor/node_modules/repeat-element/index.js +18 -0
- data/vendor/node_modules/repeat-element/package.json +44 -0
- data/vendor/node_modules/repeat-string/index.js +70 -0
- data/vendor/node_modules/repeat-string/package.json +77 -0
- data/vendor/node_modules/require-relative/index.js +33 -0
- data/vendor/node_modules/require-relative/package.json +22 -0
- data/vendor/node_modules/resolve/index.js +8 -0
- data/vendor/node_modules/resolve/lib/async.js +203 -0
- data/vendor/node_modules/resolve/lib/caller.js +8 -0
- data/vendor/node_modules/resolve/lib/core.js +53 -0
- data/vendor/node_modules/resolve/lib/core.json +69 -0
- data/vendor/node_modules/resolve/lib/node-modules-paths.js +45 -0
- data/vendor/node_modules/resolve/lib/sync.js +93 -0
- data/vendor/node_modules/resolve/package.json +40 -0
- data/vendor/node_modules/rollup-plugin-commonjs/dist/rollup-plugin-commonjs.cjs.js +804 -0
- data/vendor/node_modules/rollup-plugin-commonjs/dist/rollup-plugin-commonjs.es.js +800 -0
- data/vendor/node_modules/rollup-plugin-commonjs/package.json +52 -0
- data/vendor/node_modules/rollup-plugin-commonjs/src/ast-utils.js +104 -0
- data/vendor/node_modules/rollup-plugin-commonjs/src/defaultResolver.js +39 -0
- data/vendor/node_modules/rollup-plugin-commonjs/src/helpers.js +19 -0
- data/vendor/node_modules/rollup-plugin-commonjs/src/index.js +198 -0
- data/vendor/node_modules/rollup-plugin-commonjs/src/transform.js +431 -0
- data/vendor/node_modules/rollup-plugin-commonjs/src/utils.js +13 -0
- data/vendor/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.cjs.js +218 -0
- data/vendor/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.es.js +214 -0
- data/vendor/node_modules/rollup-plugin-node-resolve/package.json +51 -0
- data/vendor/node_modules/rollup-plugin-node-resolve/src/empty.js +1 -0
- data/vendor/node_modules/rollup-plugin-node-resolve/src/index.js +205 -0
- data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.cjs.js +223 -0
- data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.es.js +214 -0
- data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.es6.js +217 -0
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.es.js +55 -0
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.es6.js +59 -0
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.umd.js +65 -0
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/package.json +33 -0
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/src/estree-walker.js +49 -0
- data/vendor/node_modules/rollup-pluginutils/package.json +40 -0
- data/vendor/node_modules/rollup-pluginutils/src/addExtension.js +6 -0
- data/vendor/node_modules/rollup-pluginutils/src/attachScopes.js +147 -0
- data/vendor/node_modules/rollup-pluginutils/src/createFilter.js +33 -0
- data/vendor/node_modules/rollup-pluginutils/src/index.js +4 -0
- data/vendor/node_modules/rollup-pluginutils/src/makeLegalIdentifier.js +15 -0
- data/vendor/node_modules/rollup-pluginutils/src/utils/ensureArray.js +5 -0
- data/vendor/node_modules/rollup/bin/rollup +4085 -0
- data/vendor/node_modules/rollup/dist/rollup.browser.js +19829 -0
- data/vendor/node_modules/rollup/dist/rollup.es.js +23586 -0
- data/vendor/node_modules/rollup/dist/rollup.js +23597 -0
- data/vendor/node_modules/rollup/dist/typings/Chunk.d.ts +85 -0
- data/vendor/node_modules/rollup/dist/typings/ExternalModule.d.ts +30 -0
- data/vendor/node_modules/rollup/dist/typings/Graph.d.ts +47 -0
- data/vendor/node_modules/rollup/dist/typings/Module.d.ts +130 -0
- data/vendor/node_modules/rollup/dist/typings/ast/CallOptions.d.ts +20 -0
- data/vendor/node_modules/rollup/dist/typings/ast/Entity.d.ts +16 -0
- data/vendor/node_modules/rollup/dist/typings/ast/ExecutionPathOptions.d.ts +57 -0
- data/vendor/node_modules/rollup/dist/typings/ast/clone.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/ast/enhance.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/ast/keys.d.ts +4 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ArrayExpression.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ArrayPattern.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ArrowFunctionExpression.d.ts +25 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/AssignmentExpression.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/AssignmentPattern.d.ts +16 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/AssignmentProperty.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/AwaitExpression.d.ts +8 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/BinaryExpression.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/BlockStatement.d.ts +19 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/BreakStatement.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/CallExpression.d.ts +22 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/CatchClause.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ClassBody.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ClassDeclaration.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ClassExpression.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ConditionalExpression.d.ts +28 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/DoWhileStatement.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/EmptyStatement.d.ts +8 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ExportAllDeclaration.d.ts +12 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ExportDefaultDeclaration.d.ts +21 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ExportNamedDeclaration.d.ts +21 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ExportSpecifier.d.ts +8 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ExpressionStatement.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ForInStatement.d.ts +20 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ForOfStatement.d.ts +21 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ForStatement.d.ts +19 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/FunctionDeclaration.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/FunctionExpression.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/Identifier.d.ts +29 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/IfStatement.d.ts +17 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/Import.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ImportDeclaration.d.ts +17 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ImportDefaultSpecifier.d.ts +7 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ImportNamespaceSpecifier.d.ts +7 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ImportSpecifier.d.ts +8 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/LabeledStatement.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/Literal.d.ts +22 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/LogicalExpression.d.ts +23 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/MemberExpression.d.ts +34 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/MethodDefinition.d.ts +16 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/NewExpression.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/NodeType.d.ts +64 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ObjectExpression.d.ts +22 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ObjectPattern.d.ts +15 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/Program.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/Property.d.ts +30 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/RestElement.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ReturnStatement.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/SequenceExpression.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/SpreadElement.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/SwitchCase.d.ts +11 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/SwitchStatement.d.ts +12 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/TaggedTemplateExpression.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/TemplateElement.d.ts +12 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/TemplateLiteral.d.ts +12 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ThisExpression.d.ts +17 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/ThrowStatement.d.ts +8 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/UnaryExpression.d.ts +16 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/UnknownNode.d.ts +5 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/UpdateExpression.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/VariableDeclaration.d.ts +21 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/VariableDeclarator.d.ts +13 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/WhileStatement.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/YieldExpression.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/index.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/shared/ClassNode.d.ts +17 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/shared/Expression.d.ts +21 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/shared/FunctionNode.d.ts +25 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/shared/Node.d.ts +133 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/shared/Pattern.d.ts +4 -0
- data/vendor/node_modules/rollup/dist/typings/ast/nodes/shared/pureFunctions.d.ts +4 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/BlockScope.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/CatchScope.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/FunctionScope.d.ts +20 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/GlobalScope.d.ts +7 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/ModuleScope.d.ts +11 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/ParameterScope.d.ts +16 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/ReturnValueScope.d.ts +11 -0
- data/vendor/node_modules/rollup/dist/typings/ast/scopes/Scope.d.ts +42 -0
- data/vendor/node_modules/rollup/dist/typings/ast/utils/extractNames.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/ast/values.d.ts +31 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/ArgumentsVariable.d.ts +15 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/ExportDefaultVariable.d.ts +16 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/ExternalVariable.d.ts +12 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/GlobalVariable.d.ts +11 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/LocalVariable.d.ts +21 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/NamespaceVariable.d.ts +20 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/ParameterVariable.d.ts +5 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/ReplaceableInitializationVariable.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/ThisVariable.d.ts +4 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/Variable.d.ts +43 -0
- data/vendor/node_modules/rollup/dist/typings/ast/variables/VariableReassignmentTracker.d.ts +11 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/amd.d.ts +11 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/cjs.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/es.d.ts +9 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/iife.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/index.d.ts +15 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/esModuleExport.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/getExportBlock.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/getGlobalNameMaker.d.ts +4 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/getInteropBlock.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/sanitize.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/setupNamespace.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/trimEmptyImports.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/shared/warnOnBuiltins.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/system.d.ts +8 -0
- data/vendor/node_modules/rollup/dist/typings/finalisers/umd.d.ts +10 -0
- data/vendor/node_modules/rollup/dist/typings/node-entry.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/rollup/index.d.ts +167 -0
- data/vendor/node_modules/rollup/dist/typings/utils/callIfFunction.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/utils/collapseSourcemaps.d.ts +5 -0
- data/vendor/node_modules/rollup/dist/typings/utils/commondir.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/utils/defaults.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/utils/deprecateOptions.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/utils/ensureArray.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/utils/entryHashing.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/utils/error.d.ts +18 -0
- data/vendor/node_modules/rollup/dist/typings/utils/first-sync.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/utils/first.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/utils/flushTime.d.ts +5 -0
- data/vendor/node_modules/rollup/dist/typings/utils/fs.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/utils/getCodeFrame.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/utils/getExportMode.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/utils/getIndentString.d.ts +4 -0
- data/vendor/node_modules/rollup/dist/typings/utils/identifierHelpers.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/utils/mergeOptions.d.ts +19 -0
- data/vendor/node_modules/rollup/dist/typings/utils/object.d.ts +7 -0
- data/vendor/node_modules/rollup/dist/typings/utils/path.d.ts +6 -0
- data/vendor/node_modules/rollup/dist/typings/utils/promise.d.ts +2 -0
- data/vendor/node_modules/rollup/dist/typings/utils/relativeId.d.ts +1 -0
- data/vendor/node_modules/rollup/dist/typings/utils/renderHelpers.d.ts +26 -0
- data/vendor/node_modules/rollup/dist/typings/utils/sourceMappingURL.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/utils/timers.d.ts +7 -0
- data/vendor/node_modules/rollup/dist/typings/utils/transform.d.ts +25 -0
- data/vendor/node_modules/rollup/dist/typings/utils/transformBundle.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/watch/chokidar.d.ts +3 -0
- data/vendor/node_modules/rollup/dist/typings/watch/fileWatchers.d.ts +14 -0
- data/vendor/node_modules/rollup/dist/typings/watch/index.d.ts +47 -0
- data/vendor/node_modules/rollup/package.json +122 -0
- data/vendor/node_modules/rollup/typings/package.json.d.ts +3 -0
- data/vendor/node_modules/signal-exit/index.js +157 -0
- data/vendor/node_modules/signal-exit/package.json +38 -0
- data/vendor/node_modules/signal-exit/signals.js +53 -0
- data/vendor/node_modules/source-map/dist/source-map.debug.js +3091 -0
- data/vendor/node_modules/source-map/dist/source-map.js +3090 -0
- data/vendor/node_modules/source-map/dist/source-map.min.js +2 -0
- data/vendor/node_modules/source-map/lib/array-set.js +121 -0
- data/vendor/node_modules/source-map/lib/base64-vlq.js +140 -0
- data/vendor/node_modules/source-map/lib/base64.js +67 -0
- data/vendor/node_modules/source-map/lib/binary-search.js +111 -0
- data/vendor/node_modules/source-map/lib/mapping-list.js +79 -0
- data/vendor/node_modules/source-map/lib/quick-sort.js +114 -0
- data/vendor/node_modules/source-map/lib/source-map-consumer.js +1082 -0
- data/vendor/node_modules/source-map/lib/source-map-generator.js +416 -0
- data/vendor/node_modules/source-map/lib/source-node.js +413 -0
- data/vendor/node_modules/source-map/lib/util.js +417 -0
- data/vendor/node_modules/source-map/package.json +72 -0
- data/vendor/node_modules/source-map/source-map.js +8 -0
- data/vendor/node_modules/sourcemap-codec/dist/sourcemap-codec.es.js +129 -0
- data/vendor/node_modules/sourcemap-codec/dist/sourcemap-codec.umd.js +140 -0
- data/vendor/node_modules/sourcemap-codec/dist/types/sourcemap-codec.d.ts +5 -0
- data/vendor/node_modules/sourcemap-codec/package.json +52 -0
- data/vendor/node_modules/supports-color/browser.js +5 -0
- data/vendor/node_modules/supports-color/index.js +135 -0
- data/vendor/node_modules/supports-color/package.json +53 -0
- data/vendor/node_modules/time-zone/index.js +10 -0
- data/vendor/node_modules/time-zone/package.json +35 -0
- data/vendor/node_modules/vlq/dist/types/vlq.d.ts +2 -0
- data/vendor/node_modules/vlq/dist/vlq.es.js +64 -0
- data/vendor/node_modules/vlq/dist/vlq.js +75 -0
- data/vendor/node_modules/vlq/package.json +30 -0
- data/vendor/package.json +15 -0
- data/vendor/yarn.lock +453 -0
- metadata +641 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "minimist",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "parse argument options",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"covert": "^1.0.0",
|
|
8
|
+
"tap": "~0.4.0",
|
|
9
|
+
"tape": "^3.5.0"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"test": "tap test/*.js",
|
|
13
|
+
"coverage": "covert test/*.js"
|
|
14
|
+
},
|
|
15
|
+
"testling": {
|
|
16
|
+
"files": "test/*.js",
|
|
17
|
+
"browsers": [
|
|
18
|
+
"ie/6..latest",
|
|
19
|
+
"ff/5",
|
|
20
|
+
"firefox/latest",
|
|
21
|
+
"chrome/10",
|
|
22
|
+
"chrome/latest",
|
|
23
|
+
"safari/5.1",
|
|
24
|
+
"safari/latest",
|
|
25
|
+
"opera/12"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git://github.com/substack/minimist.git"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/substack/minimist",
|
|
33
|
+
"keywords": [
|
|
34
|
+
"argv",
|
|
35
|
+
"getopt",
|
|
36
|
+
"parser",
|
|
37
|
+
"optimist"
|
|
38
|
+
],
|
|
39
|
+
"author": {
|
|
40
|
+
"name": "James Halliday",
|
|
41
|
+
"email": "mail@substack.net",
|
|
42
|
+
"url": "http://substack.net"
|
|
43
|
+
},
|
|
44
|
+
"license": "MIT"
|
|
45
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
var parser = require('./lib/parser') ;
|
|
2
|
+
var treeSurgeon = require('./lib/arboriculture') ;
|
|
3
|
+
var outputCode = require('./lib/output') ;
|
|
4
|
+
|
|
5
|
+
/* Utils */
|
|
6
|
+
function copyObj(a){
|
|
7
|
+
var o = {} ;
|
|
8
|
+
a.forEach(function(b){
|
|
9
|
+
if (b && typeof b==='object')
|
|
10
|
+
for (var k in b)
|
|
11
|
+
o[k] = b[k] ;
|
|
12
|
+
}) ;
|
|
13
|
+
return o ;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function btoa(str) {
|
|
17
|
+
var buffer ;
|
|
18
|
+
if (str instanceof Buffer) {
|
|
19
|
+
buffer = str;
|
|
20
|
+
} else {
|
|
21
|
+
buffer = new Buffer(str.toString(), 'binary');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return buffer.toString('base64');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function noLogger(){}
|
|
28
|
+
|
|
29
|
+
/* NodentCompiler prototypes, that refer to 'this' */
|
|
30
|
+
function compile(code,origFilename,__sourceMapping,opts) {
|
|
31
|
+
if (typeof __sourceMapping==="object" && opts===undefined)
|
|
32
|
+
opts = __sourceMapping ;
|
|
33
|
+
|
|
34
|
+
opts = opts || {} ;
|
|
35
|
+
|
|
36
|
+
// Fill in any default codeGen options
|
|
37
|
+
for (var k in NodentCompiler.initialCodeGenOpts) {
|
|
38
|
+
if (!(k in opts))
|
|
39
|
+
opts[k] = NodentCompiler.initialCodeGenOpts[k] ;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var pr = this.parse(code,origFilename,null,opts);
|
|
43
|
+
this.asynchronize(pr,null,opts,this.log || noLogger) ;
|
|
44
|
+
this.prettyPrint(pr,opts) ;
|
|
45
|
+
return pr ;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function prettyPrint(pr,opts) {
|
|
49
|
+
var map ;
|
|
50
|
+
var filepath = pr.filename ? pr.filename.split("/") :["anonymous"] ;
|
|
51
|
+
var filename = filepath.pop() ;
|
|
52
|
+
|
|
53
|
+
var out = outputCode(pr.ast,(opts && opts.sourcemap)?{map:{
|
|
54
|
+
startLine: opts.mapStartLine || 0,
|
|
55
|
+
file: filename+"(original)",
|
|
56
|
+
sourceMapRoot: filepath.join("/"),
|
|
57
|
+
sourceContent: pr.origCode
|
|
58
|
+
}}:null, pr.origCode) ;
|
|
59
|
+
|
|
60
|
+
if (opts && opts.sourcemap){
|
|
61
|
+
try {
|
|
62
|
+
var mapUrl = "" ;
|
|
63
|
+
var jsmap = out.map.toJSON();
|
|
64
|
+
if (jsmap) {
|
|
65
|
+
// require an expression to defeat browserify
|
|
66
|
+
var SourceMapConsumer = require('source-map').SourceMapConsumer;
|
|
67
|
+
pr.sourcemap = jsmap ;
|
|
68
|
+
this.smCache[pr.filename] = {map:jsmap,smc:new SourceMapConsumer(jsmap)} ;
|
|
69
|
+
mapUrl = "\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,"
|
|
70
|
+
+btoa(JSON.stringify(jsmap))+"\n" ;
|
|
71
|
+
}
|
|
72
|
+
pr.code = out.code+mapUrl ;
|
|
73
|
+
} catch (ex) {
|
|
74
|
+
pr.code = out ;
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
pr.code = out ;
|
|
78
|
+
}
|
|
79
|
+
return pr ;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function NodentCompiler(members) {
|
|
83
|
+
this.covers = {} ;
|
|
84
|
+
this._ident = NodentCompiler.prototype.version+"_"+Math.random() ;
|
|
85
|
+
this.setOptions(members || {}) ;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
NodentCompiler.prototype.smCache = {} ;
|
|
89
|
+
|
|
90
|
+
NodentCompiler.prototype.setOptions = function(members){
|
|
91
|
+
this.log = members.log===false?noLogger:members.log||this.log;
|
|
92
|
+
this.options = copyObj([this.options,members]) ;
|
|
93
|
+
delete this.options.log ;
|
|
94
|
+
return this ;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
function parseCode(code,origFilename,__sourceMapping,opts) {
|
|
98
|
+
if (typeof __sourceMapping==="object" && opts===undefined)
|
|
99
|
+
opts = __sourceMapping ;
|
|
100
|
+
|
|
101
|
+
var r = { origCode:code.toString(), filename:origFilename } ;
|
|
102
|
+
try {
|
|
103
|
+
r.ast = parser.parse(r.origCode, opts && opts.parser) ;
|
|
104
|
+
if (opts.babelTree) {
|
|
105
|
+
parser.treeWalker(r.ast,function(node,descend,path){
|
|
106
|
+
if (node.type==='Literal')
|
|
107
|
+
path[0].replace(treeSurgeon.babelLiteralNode(node.value)) ;
|
|
108
|
+
else if (node.type==='Property') {
|
|
109
|
+
// Class/ObjectProperty in babel6
|
|
110
|
+
if (path[0].parent.type==='ClassBody'){
|
|
111
|
+
// There's no easy mapping here as it appears to be borderline in the specification?
|
|
112
|
+
// It's definitely a kind of ClassProperty tho....
|
|
113
|
+
node.type = 'ClassProperty' ;
|
|
114
|
+
} else {
|
|
115
|
+
node.type = 'ObjectProperty' ;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
descend() ;
|
|
119
|
+
}) ;
|
|
120
|
+
}
|
|
121
|
+
return r ;
|
|
122
|
+
} catch (ex) {
|
|
123
|
+
if (ex instanceof SyntaxError) {
|
|
124
|
+
var l = r.origCode.substr(ex.pos-ex.loc.column) ;
|
|
125
|
+
l = l.split("\n")[0] ;
|
|
126
|
+
ex.message += " "+origFilename+" (nodent)\n"+l+"\n"+l.replace(/[\S ]/g,"-").substring(0,ex.loc.column)+"^" ;
|
|
127
|
+
ex.stack = "" ;
|
|
128
|
+
}
|
|
129
|
+
throw ex ;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
NodentCompiler.prototype.version = require("./package.json").version ;
|
|
134
|
+
NodentCompiler.prototype.isThenable = function(x) { return x && x instanceof Object && typeof x.then==="function"} ;
|
|
135
|
+
NodentCompiler.prototype.compile = compile ;
|
|
136
|
+
// Exported ; but not to be used lightly!
|
|
137
|
+
NodentCompiler.prototype.parse = parseCode ;
|
|
138
|
+
NodentCompiler.prototype.asynchronize = treeSurgeon.asynchronize ;
|
|
139
|
+
NodentCompiler.prototype.printNode = treeSurgeon.printNode ;
|
|
140
|
+
NodentCompiler.prototype.prettyPrint = prettyPrint ;
|
|
141
|
+
NodentCompiler.prototype.getDefaultCompileOptions = undefined ;
|
|
142
|
+
|
|
143
|
+
Object.defineProperty(NodentCompiler.prototype,"Promise",{
|
|
144
|
+
get:function (){
|
|
145
|
+
initOpts.log("Warning: nodent.Promise is deprecated. Use nodent.Thenable instead");
|
|
146
|
+
return Thenable;
|
|
147
|
+
},
|
|
148
|
+
enumerable:false,
|
|
149
|
+
configurable:false
|
|
150
|
+
}) ;
|
|
151
|
+
|
|
152
|
+
NodentCompiler.initialCodeGenOpts = {
|
|
153
|
+
noRuntime:false,
|
|
154
|
+
lazyThenables:false,
|
|
155
|
+
es6target:false,
|
|
156
|
+
noUseDirective:false,
|
|
157
|
+
wrapAwait:null,
|
|
158
|
+
mapStartLine:0,
|
|
159
|
+
sourcemap:true,
|
|
160
|
+
engine:false,
|
|
161
|
+
parser:{sourceType:'script'},
|
|
162
|
+
$return:"$return",
|
|
163
|
+
$error:"$error",
|
|
164
|
+
$arguments:"$args",
|
|
165
|
+
$asyncspawn:"$asyncspawn",
|
|
166
|
+
$asyncbind:"$asyncbind",
|
|
167
|
+
generatedSymbolPrefix:"$",
|
|
168
|
+
$makeThenable:'$makeThenable'
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
module.exports = NodentCompiler ;
|
|
@@ -0,0 +1,2694 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/* We manipulate (abstract syntax) trees */
|
|
4
|
+
var parser = require('./parser');
|
|
5
|
+
var outputCode = require('./output');
|
|
6
|
+
/** Helpers **/
|
|
7
|
+
/*global.printNode = */function printNode(n) {
|
|
8
|
+
if (!n) return '' ;
|
|
9
|
+
if (Array.isArray(n))
|
|
10
|
+
return n.map(printNode).join("|\n");
|
|
11
|
+
try {
|
|
12
|
+
return outputCode(n) ; //+"\t//@"+Object.keys(n).filter(function(k){ return k[0]==='$'}).map(function(k){ return k+":"+n[k] });
|
|
13
|
+
} catch (ex) {
|
|
14
|
+
return ex.message + ": " + (n && n.type);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function cloneNode(n) {
|
|
19
|
+
if (Array.isArray(n))
|
|
20
|
+
return n.map(function (n) {
|
|
21
|
+
return cloneNode(n);
|
|
22
|
+
});
|
|
23
|
+
var o = {};
|
|
24
|
+
Object.keys(n).forEach(function (k) {
|
|
25
|
+
o[k] = n[k];
|
|
26
|
+
});
|
|
27
|
+
return o;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Bit of a hack: without having to search for references to this
|
|
31
|
+
* node, force it to be some replacement node */
|
|
32
|
+
var locationInfo = { start:true, end: true, loc: true, range: true } ;
|
|
33
|
+
function coerce(node, replace) {
|
|
34
|
+
if (node===replace) return ;
|
|
35
|
+
node.__proto__ = Object.getPrototypeOf(replace);
|
|
36
|
+
Object.keys(node).forEach(function (k) {
|
|
37
|
+
if (!(k in locationInfo))
|
|
38
|
+
delete node[k];
|
|
39
|
+
});
|
|
40
|
+
Object.keys(replace).forEach(function (k) {
|
|
41
|
+
if (!(k in node))
|
|
42
|
+
node[k] = replace[k];
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function Nothing(){}
|
|
47
|
+
|
|
48
|
+
var examinations = {
|
|
49
|
+
getScope: function(){ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || (this.node.type === 'ArrowFunctionExpression' && this.node.body.type === 'BlockStatement') ? this.node.body.body : this.node.type === 'Program' ? this.node.body : null},
|
|
50
|
+
isScope: function(){ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'Program' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || (this.node.type === 'ArrowFunctionExpression' && this.node.body.type === 'BlockStatement')},
|
|
51
|
+
isFunction: function(){ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || this.node.type === 'ArrowFunctionExpression'},
|
|
52
|
+
isClass: function(){ return this.node.type === 'ClassDeclaration' || this.node.type === 'ClassExpression'},
|
|
53
|
+
isBlockStatement: function(){ return this.node.type==='ClassBody' || this.node.type === 'Program' || this.node.type === 'BlockStatement' ? this.node.body : this.node.type === 'SwitchCase' ? this.node.consequent : false},
|
|
54
|
+
isExpressionStatement: function(){ return this.node.type === 'ExpressionStatement'},
|
|
55
|
+
isLiteral: function(){ return this.node.type === 'Literal' || this.node.type === 'BooleanLiteral' || this.node.type === 'RegExpLiteral' || this.node.type === 'NumericLiteral' || this.node.type === 'StringLiteral' || this.node.type === 'NullLiteral'},
|
|
56
|
+
isDirective: function(){ return this.node.type === 'ExpressionStatement' && (this.node.expression.type === 'StringLiteral' || this.node.expression.type === 'Literal' && typeof this.node.expression.value === 'string')},
|
|
57
|
+
isUnaryExpression: function(){ return this.node.type === 'UnaryExpression'},
|
|
58
|
+
isAwait: function(){ return this.node.type === 'AwaitExpression' && !this.node.$hidden},
|
|
59
|
+
isAsync: function(){ return this.node.async },
|
|
60
|
+
isStatement: function(){ return this.node.type.match(/[a-zA-Z]+Declaration/) !== null || this.node.type.match(/[a-zA-Z]+Statement/) !== null},
|
|
61
|
+
isExpression: function(){ return this.node.type.match(/[a-zA-Z]+Expression/) !== null},
|
|
62
|
+
isLoop: function(){ return this.node.type === 'ForStatement' || this.node.type === 'WhileStatement' || this.node.type === 'DoWhileStatement'}, // Other loops?
|
|
63
|
+
isJump: function(){ return this.node.type === 'ReturnStatement' || this.node.type === 'ThrowStatement' || this.node.type === 'BreakStatement' || this.node.type === 'ContinueStatement'},
|
|
64
|
+
isES6: function(){
|
|
65
|
+
switch (this.node.type) {
|
|
66
|
+
case 'ExportNamedDeclaration':
|
|
67
|
+
case 'ExportSpecifier':
|
|
68
|
+
case 'ExportDefaultDeclaration':
|
|
69
|
+
case 'ExportAllDeclaration':
|
|
70
|
+
case 'ImportDeclaration':
|
|
71
|
+
case 'ImportSpecifier':
|
|
72
|
+
case 'ImportDefaultSpecifier':
|
|
73
|
+
case 'ImportNamespaceSpecifier':
|
|
74
|
+
case 'ArrowFunctionExpression':
|
|
75
|
+
case 'ForOfStatement':
|
|
76
|
+
case 'YieldExpression':
|
|
77
|
+
case 'Super':
|
|
78
|
+
case 'RestElement':
|
|
79
|
+
case 'RestProperty':
|
|
80
|
+
case 'SpreadElement':
|
|
81
|
+
case 'TemplateLiteral':
|
|
82
|
+
case 'ClassDeclaration':
|
|
83
|
+
case 'ClassExpression':
|
|
84
|
+
return true ;
|
|
85
|
+
|
|
86
|
+
case 'VariableDeclaration':
|
|
87
|
+
return this.node.kind && this.node.kind !== 'var' ;
|
|
88
|
+
|
|
89
|
+
case 'FunctionDeclaration':
|
|
90
|
+
case 'FunctionExpression':
|
|
91
|
+
return !!this.node.generator;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
var NodeExaminer = {} ;
|
|
97
|
+
Object.keys(examinations).forEach(function(k){
|
|
98
|
+
Object.defineProperty(NodeExaminer,k,{
|
|
99
|
+
get:examinations[k]
|
|
100
|
+
}) ;
|
|
101
|
+
}) ;
|
|
102
|
+
|
|
103
|
+
function examine(node) {
|
|
104
|
+
if (!node)
|
|
105
|
+
return {};
|
|
106
|
+
NodeExaminer.node = node ;
|
|
107
|
+
return NodeExaminer ;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* descendOn = true Enter scopes within scopes
|
|
112
|
+
* descendOn = false/undefined/null Do not enter scopes within scopes
|
|
113
|
+
* descendOn = function Descend when function(node) is true
|
|
114
|
+
*/
|
|
115
|
+
function contains(ast, fn, descendOn) {
|
|
116
|
+
if (!ast)
|
|
117
|
+
return null;
|
|
118
|
+
if (fn && typeof fn === 'object') {
|
|
119
|
+
var keys = Object.keys(fn);
|
|
120
|
+
return contains(ast, function (node) {
|
|
121
|
+
return keys.every(function (k) {
|
|
122
|
+
return node[k] == fn[k];
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
var n, found = {};
|
|
127
|
+
if (Array.isArray(ast)) {
|
|
128
|
+
for (var i = 0;i < ast.length; i++)
|
|
129
|
+
if (n = contains(ast[i], fn))
|
|
130
|
+
return n;
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
var subScopes = descendOn ;
|
|
135
|
+
if (typeof descendOn !== "function") {
|
|
136
|
+
if (descendOn) {
|
|
137
|
+
subScopes = function(n) { return true } ;
|
|
138
|
+
} else {
|
|
139
|
+
subScopes = function(n) { return !examine(n).isScope } ;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
145
|
+
if (fn(node)) {
|
|
146
|
+
found.path = path;
|
|
147
|
+
throw found;
|
|
148
|
+
}
|
|
149
|
+
if (node === ast || subScopes(node))
|
|
150
|
+
descend();
|
|
151
|
+
});
|
|
152
|
+
} catch (ex) {
|
|
153
|
+
if (ex === found)
|
|
154
|
+
return found.path;
|
|
155
|
+
throw ex;
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function containsAwait(ast) {
|
|
161
|
+
return contains(ast, function(n){
|
|
162
|
+
return n.type==='AwaitExpression' && !n.$hidden
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function containsAwaitInBlock(ast) {
|
|
167
|
+
return contains(ast, function(n){
|
|
168
|
+
return n.type==='AwaitExpression' && !n.$hidden
|
|
169
|
+
}, function (n) {
|
|
170
|
+
var x = examine(n) ;
|
|
171
|
+
return !x.isBlockStatement && !x.isScope
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function containsThis(ast) {
|
|
176
|
+
return contains(ast, {
|
|
177
|
+
type: 'ThisExpression'
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function babelLiteralNode(value) {
|
|
182
|
+
if (value === null)
|
|
183
|
+
return {
|
|
184
|
+
type: 'NullLiteral',
|
|
185
|
+
value: null,
|
|
186
|
+
raw: 'null'
|
|
187
|
+
};
|
|
188
|
+
if (value === true || value === false)
|
|
189
|
+
return {
|
|
190
|
+
type: 'BooleanLiteral',
|
|
191
|
+
value: value,
|
|
192
|
+
raw: JSON.stringify(value)
|
|
193
|
+
};
|
|
194
|
+
if (value instanceof RegExp) {
|
|
195
|
+
var str = value.toString();
|
|
196
|
+
var parts = str.split('/');
|
|
197
|
+
return {
|
|
198
|
+
type: 'RegExpLiteral',
|
|
199
|
+
value: value,
|
|
200
|
+
raw: str,
|
|
201
|
+
pattern: parts[1],
|
|
202
|
+
flags: parts[2]
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (typeof value === 'number')
|
|
206
|
+
return {
|
|
207
|
+
type: 'NumericLiteral',
|
|
208
|
+
value: value,
|
|
209
|
+
raw: JSON.stringify(value)
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
type: 'StringLiteral',
|
|
213
|
+
value: value,
|
|
214
|
+
raw: JSON.stringify(value)
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function ident(name, loc) {
|
|
219
|
+
return {
|
|
220
|
+
type: 'Identifier',
|
|
221
|
+
name: name,
|
|
222
|
+
loc: loc
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function idents(s) {
|
|
227
|
+
var r = {};
|
|
228
|
+
for (var k in s)
|
|
229
|
+
r[k] = typeof s[k] === "string" ? ident(s[k]) : s[k];
|
|
230
|
+
return r;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function asynchronize(pr, __sourceMapping, opts, logger) {
|
|
234
|
+
var continuations = {};
|
|
235
|
+
var generatedSymbol = 1;
|
|
236
|
+
var genIdent = {};
|
|
237
|
+
Object.keys(opts).filter(function (k) {
|
|
238
|
+
return k[0] === '$';
|
|
239
|
+
}).forEach(function (k) {
|
|
240
|
+
genIdent[k.slice(1)] = ident(opts[k]);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
/* Generate a prototypical call of the form:
|
|
244
|
+
* (left).$asyncbind(this,...args)
|
|
245
|
+
*/
|
|
246
|
+
function bindAsync(left,arg) {
|
|
247
|
+
if (opts.es6target && !left.id && !arg && left.type.indexOf("Function")===0) {
|
|
248
|
+
left.type = 'ArrowFunctionExpression' ;
|
|
249
|
+
return left ;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (opts.noRuntime) {
|
|
253
|
+
if (arg) {
|
|
254
|
+
if (examine(arg).isLiteral) {
|
|
255
|
+
throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes") ;
|
|
256
|
+
}
|
|
257
|
+
// Add a global synchronous exception handler to (left)
|
|
258
|
+
left.body.body = parser.part("try {$:0} catch($2) {return $1($2)}",[cloneNode(left.body),arg,ident('$boundEx')]).body ;
|
|
259
|
+
} else if (opts.es6target && !left.id && left.type.indexOf("Function")===0) {
|
|
260
|
+
left.type = 'ArrowFunctionExpression' ;
|
|
261
|
+
return left ;
|
|
262
|
+
}
|
|
263
|
+
if (opts.es6target && !left.id) {
|
|
264
|
+
left.type = 'ArrowFunctionExpression' ;
|
|
265
|
+
return left;
|
|
266
|
+
}
|
|
267
|
+
return parser.part("$0.bind(this)",[left]).expr;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
var params = [{ "type": "ThisExpression" }] ;
|
|
271
|
+
if (arg) {
|
|
272
|
+
return parser.part("$0.$1(this,$2)",[left,genIdent.asyncbind,arg]).expr;
|
|
273
|
+
}
|
|
274
|
+
return parser.part("$0.$1(this)",[left,genIdent.asyncbind]).expr;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function makeBoundFn(name, body, argnames, binding) {
|
|
278
|
+
return parser.part("var $0 = $1",[ident(name),bindAsync({
|
|
279
|
+
"type": "FunctionExpression",
|
|
280
|
+
"id": null,
|
|
281
|
+
"generator": false,
|
|
282
|
+
"expression": false,
|
|
283
|
+
"params": argnames || [],
|
|
284
|
+
"body": Array.isArray(body)?{type:'BlockStatement',body:body}:body
|
|
285
|
+
}, binding)]).body[0] ;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function where(node) {
|
|
289
|
+
return pr.filename + (node && node.loc && node.loc.start ? "(" + node.loc.start.line + ":" + node.loc.start.column + ")\t" : "\t");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function literal(value) {
|
|
293
|
+
if (opts.babelTree) {
|
|
294
|
+
return babelLiteralNode(value);
|
|
295
|
+
} else {
|
|
296
|
+
return {
|
|
297
|
+
type: 'Literal',
|
|
298
|
+
value: value,
|
|
299
|
+
raw: JSON.stringify(value)
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function getMemberFunction(node) {
|
|
305
|
+
if (!node)
|
|
306
|
+
return null ;
|
|
307
|
+
if (opts.babelTree && (node.type === 'ClassMethod' || node.type === 'ObjectMethod')) {
|
|
308
|
+
return node;
|
|
309
|
+
} else if ((!opts.babelTree && node.type === 'MethodDefinition' || node.type === 'Property' && (node.method || node.kind == 'get' || node.kind == 'set')) && examine(node.value).isFunction) {
|
|
310
|
+
return node.value;
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
var assign$Args = parser.part("var $0 = arguments",[genIdent.arguments]).body[0] ;
|
|
316
|
+
|
|
317
|
+
/* Replace 'arguments' identifiers in a function. Return true if a
|
|
318
|
+
* replacement has been made and so the symbol opts.$arguments needs
|
|
319
|
+
* initializing.
|
|
320
|
+
*/
|
|
321
|
+
function replaceArguments(ast,nested) {
|
|
322
|
+
if (!examine(ast).isFunction)
|
|
323
|
+
throw new Error("Can only replace 'arguments' in functions") ;
|
|
324
|
+
|
|
325
|
+
if (!('$usesArguments' in ast)) {
|
|
326
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
327
|
+
if (node.type === 'Identifier' && node.name === 'arguments') {
|
|
328
|
+
// Fix up shorthand properties
|
|
329
|
+
if (path[0].parent.shorthand) {
|
|
330
|
+
path[0].parent.shorthand = false ;
|
|
331
|
+
path[0].parent.key = ident('arguments') ;
|
|
332
|
+
ast.$usesArguments = true ;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Replace identifiers that are not keys
|
|
336
|
+
if (path[0].field !== 'key') {
|
|
337
|
+
node.name = opts.$arguments;
|
|
338
|
+
ast.$usesArguments = true ;
|
|
339
|
+
}
|
|
340
|
+
} else if (node === ast || !examine(node).isFunction) {
|
|
341
|
+
descend();
|
|
342
|
+
} else if (node.type==='ArrowFunctionExpression') {
|
|
343
|
+
replaceArguments(node) ;
|
|
344
|
+
ast.$usesArguments = ast.$usesArguments || node.$usesArguments ;
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
ast.$usesArguments = ast.$usesArguments || false ;
|
|
348
|
+
}
|
|
349
|
+
return ast.$usesArguments && ast.type !== 'ArrowFunctionExpression';
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function generateSymbol(node) {
|
|
353
|
+
if (typeof node != 'string')
|
|
354
|
+
node = node.type.replace(/Statement|Expression/g,"");
|
|
355
|
+
return opts.generatedSymbolPrefix + node + "_" + generatedSymbol++;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function setExit(n, sym) {
|
|
359
|
+
if (n) {
|
|
360
|
+
n.$exit = idents({
|
|
361
|
+
$error: sym.$error,
|
|
362
|
+
$return: sym.$return
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
return n;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function getExitNode(path) {
|
|
369
|
+
for (var n = 0;n < path.length; n++) {
|
|
370
|
+
if (path[n].self.$exit) {
|
|
371
|
+
return path[n].self;
|
|
372
|
+
}
|
|
373
|
+
if (path[n].parent && path[n].parent.$exit) {
|
|
374
|
+
return path[n].parent;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function getExit(path, parents) {
|
|
381
|
+
var n = getExitNode(path);
|
|
382
|
+
if (n)
|
|
383
|
+
return n.$exit;
|
|
384
|
+
if (parents) {
|
|
385
|
+
for (var i = 0;i < parents.length; i++)
|
|
386
|
+
if (parents[i])
|
|
387
|
+
return idents(parents[i]);
|
|
388
|
+
}
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// actually do the transforms
|
|
393
|
+
if (opts.engine) {
|
|
394
|
+
// Only Transform extensions:
|
|
395
|
+
// - await outside of async
|
|
396
|
+
// - async return <optional-expression>
|
|
397
|
+
// - async throw <expression>
|
|
398
|
+
// - get async id(){} / async get id(){}
|
|
399
|
+
// - super references (in case they are used by async exits - in general they aren't)
|
|
400
|
+
// Everything else is passed through unmolested to be run by a JS engine such as V8 v5.4
|
|
401
|
+
pr.ast = fixSuperReferences(pr.ast,true);
|
|
402
|
+
pr.ast = asyncSpawn(pr.ast, opts.engine);
|
|
403
|
+
pr.ast = exposeCompilerOpts(pr.ast);
|
|
404
|
+
cleanCode(pr.ast)
|
|
405
|
+
} else if (opts.generators) {
|
|
406
|
+
// Transform to generators
|
|
407
|
+
pr.ast = fixSuperReferences(pr.ast);
|
|
408
|
+
pr.ast = asyncSpawn(pr.ast);
|
|
409
|
+
pr.ast = exposeCompilerOpts(pr.ast);
|
|
410
|
+
cleanCode(pr.ast)
|
|
411
|
+
} else {
|
|
412
|
+
// Transform to callbacks, optionally with Promises
|
|
413
|
+
pr.ast = fixSuperReferences(pr.ast);
|
|
414
|
+
asyncTransforms(pr.ast);
|
|
415
|
+
}
|
|
416
|
+
if (opts.babelTree) {
|
|
417
|
+
parser.treeWalker(pr.ast, function (node, descend, path) {
|
|
418
|
+
descend();
|
|
419
|
+
if (node.type === 'Literal') {
|
|
420
|
+
coerce(node, literal(node.value));
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
return pr;
|
|
425
|
+
|
|
426
|
+
function asyncTransforms(ast, awaitFlag) {
|
|
427
|
+
var useLazyLoops = !(opts.promises || opts.generators || opts.engine) && opts.lazyThenables ;
|
|
428
|
+
// Because we create functions (and scopes), we need all declarations before use
|
|
429
|
+
blockifyArrows(ast);
|
|
430
|
+
hoistDeclarations(ast);
|
|
431
|
+
// All TryCatch blocks need a name so we can (if necessary) find out what the enclosing catch routine is called
|
|
432
|
+
labelTryCatch(ast);
|
|
433
|
+
// Convert async functions and their contained returns & throws
|
|
434
|
+
asyncDefine(ast);
|
|
435
|
+
asyncDefineMethod(ast);
|
|
436
|
+
// Loops are asynchronized in an odd way - the loop is turned into a function that is
|
|
437
|
+
// invoked through tail recursion OR callback. They are like the inner functions of
|
|
438
|
+
// async functions to allow for completion and throwing
|
|
439
|
+
(useLazyLoops?asyncLoops_1:Nothing)(ast);
|
|
440
|
+
// Handle the various JS control flow keywords by splitting into continuations that could
|
|
441
|
+
// be invoked asynchronously
|
|
442
|
+
mapLogicalOp(ast);
|
|
443
|
+
mapCondOp(ast);
|
|
444
|
+
walkDown(ast, [mapTryCatch,(useLazyLoops?Nothing:mapLoops),mapIfStmt,mapSwitch,mapBlock]);
|
|
445
|
+
// Map awaits by creating continuations and passing them into the async resolver
|
|
446
|
+
asyncAwait(ast, awaitFlag);
|
|
447
|
+
exposeCompilerOpts(ast);
|
|
448
|
+
// Remove guff generated by transpiling
|
|
449
|
+
cleanCode(ast);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* Create a 'continuation' - a block of statements that have been hoisted
|
|
453
|
+
* into a named function so they can be invoked conditionally or asynchronously */
|
|
454
|
+
function makeContinuation(name, body) {
|
|
455
|
+
var ctn = {
|
|
456
|
+
$continuation: true,
|
|
457
|
+
type: name?'FunctionDeclaration':'FunctionExpression',
|
|
458
|
+
id: name?typeof name==="string"?ident(name):name:undefined,
|
|
459
|
+
params: [],
|
|
460
|
+
body: {
|
|
461
|
+
type: 'BlockStatement',
|
|
462
|
+
body: cloneNode(body)
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
if (name) {
|
|
466
|
+
continuations[name] = {
|
|
467
|
+
def: ctn
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
return ctn;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/* Generate an expression AST the immediate invokes the specified async function, e.g.
|
|
474
|
+
* (await ((async function(){ ...body... })()))
|
|
475
|
+
*/
|
|
476
|
+
function internalIIAFE(body) {
|
|
477
|
+
return {
|
|
478
|
+
type: 'AwaitExpression',
|
|
479
|
+
argument: asyncDefine({
|
|
480
|
+
"type": "FunctionExpression",
|
|
481
|
+
"generator": false,
|
|
482
|
+
"expression": false,
|
|
483
|
+
"async": true,
|
|
484
|
+
"params": [],
|
|
485
|
+
"body": {
|
|
486
|
+
"type": "BlockStatement",
|
|
487
|
+
"body": body
|
|
488
|
+
}
|
|
489
|
+
}).body.body[0].argument
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/* Used to invoke a 'continuation' - a function that represents
|
|
494
|
+
* a block of statements lifted out so they can be labelled (as
|
|
495
|
+
* a function definition) to be invoked via multiple execution
|
|
496
|
+
* paths - either conditional or asynchronous. Since 'this' existed
|
|
497
|
+
* in the original scope of the statements, the continuation function
|
|
498
|
+
* must also have the correct 'this'.*/
|
|
499
|
+
function thisCall(name, args) {
|
|
500
|
+
if (typeof name === 'string')
|
|
501
|
+
name = ident(name);
|
|
502
|
+
var n = parser.part("$0.call($1)",[name,[{"type": "ThisExpression"}].concat(args || [])]).expr ;
|
|
503
|
+
name.$thisCall = n;
|
|
504
|
+
n.$thisCallName = name.name;
|
|
505
|
+
return n;
|
|
506
|
+
}
|
|
507
|
+
function returnThisCall(name,args) {
|
|
508
|
+
return {
|
|
509
|
+
type:'ReturnStatement',
|
|
510
|
+
argument: thisCall(name,args)
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function deferredFinally(node, expr) {
|
|
515
|
+
return {
|
|
516
|
+
"type": "CallExpression",
|
|
517
|
+
"callee": ident(node.$seh + "Finally"),
|
|
518
|
+
"arguments": expr ? [expr] : []
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* returnMapper is an Uglify2 transformer that is used to change statements such as:
|
|
524
|
+
* return some-expression ;
|
|
525
|
+
* into
|
|
526
|
+
* return $return(some-expression) ;
|
|
527
|
+
* for the current scope only -i.e. returns nested in inner functions are NOT modified.
|
|
528
|
+
*
|
|
529
|
+
* This allows us to capture a normal "return" statement and actually implement it
|
|
530
|
+
* by calling the locally-scoped function $return()
|
|
531
|
+
*/
|
|
532
|
+
function mapReturns(n, path) {
|
|
533
|
+
if (Array.isArray(n)) {
|
|
534
|
+
return n.map(function (m) {
|
|
535
|
+
return mapReturns(m, path);
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
var lambdaNesting = 0;
|
|
539
|
+
var tryNesting = 0 ;
|
|
540
|
+
return parser.treeWalker(n, function (node, descend, path) {
|
|
541
|
+
if (node.type === 'ReturnStatement' && !node.$mapped) {
|
|
542
|
+
if (lambdaNesting > 0) {
|
|
543
|
+
if (!examine(node).isAsync) {
|
|
544
|
+
return descend(node);
|
|
545
|
+
}
|
|
546
|
+
delete node.async;
|
|
547
|
+
}
|
|
548
|
+
/* NB: There is a special case where we do a REAL return to allow for chained async-calls and synchronous returns
|
|
549
|
+
*
|
|
550
|
+
* The selected syntax for this is:
|
|
551
|
+
* return void (expr) ;
|
|
552
|
+
* which is mapped to:
|
|
553
|
+
* return (expr) ;
|
|
554
|
+
*
|
|
555
|
+
* Note that the parenthesis are necessary in the case of anything except a single symbol as "void" binds to
|
|
556
|
+
* values before operator. In the case where we REALLY want to return undefined to the callback, a simple
|
|
557
|
+
* "return" or "return undefined" works.
|
|
558
|
+
*
|
|
559
|
+
* There is an argument for only allowing this exception in es7 mode, as Promises and generators might (one day)
|
|
560
|
+
* get their own cancellation method.
|
|
561
|
+
* */
|
|
562
|
+
node.$mapped = true;
|
|
563
|
+
if (examine(node.argument).isUnaryExpression && node.argument.operator === "void") {
|
|
564
|
+
node.argument = node.argument.argument;
|
|
565
|
+
} else {
|
|
566
|
+
node.argument = {
|
|
567
|
+
"type": "CallExpression",
|
|
568
|
+
callee: getExit(path, [opts]).$return,
|
|
569
|
+
"arguments": node.argument ? [node.argument] : []
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
return;
|
|
573
|
+
} else if (node.type === 'ThrowStatement') {
|
|
574
|
+
var isAsync = examine(node).isAsync ;
|
|
575
|
+
if (lambdaNesting > 0) {
|
|
576
|
+
if (!isAsync) {
|
|
577
|
+
return descend(node);
|
|
578
|
+
}
|
|
579
|
+
delete node.async;
|
|
580
|
+
}
|
|
581
|
+
if (!isAsync && tryNesting) {
|
|
582
|
+
descend() ;
|
|
583
|
+
} else {
|
|
584
|
+
node.type = 'ReturnStatement';
|
|
585
|
+
node.$mapped = true;
|
|
586
|
+
node.argument = {
|
|
587
|
+
type: 'CallExpression',
|
|
588
|
+
callee: getExit(path, [opts]).$error,
|
|
589
|
+
arguments: [node.argument]
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
return;
|
|
593
|
+
} else if (node.type === 'TryStatement') {
|
|
594
|
+
tryNesting++;
|
|
595
|
+
descend(node);
|
|
596
|
+
tryNesting--;
|
|
597
|
+
return;
|
|
598
|
+
} else if (examine(node).isFunction) {
|
|
599
|
+
lambdaNesting++;
|
|
600
|
+
descend(node);
|
|
601
|
+
lambdaNesting--;
|
|
602
|
+
return;
|
|
603
|
+
} else {
|
|
604
|
+
descend(node);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
}, path);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/*
|
|
611
|
+
To implement conditional execution, a?b:c is mapped to
|
|
612
|
+
|
|
613
|
+
await (async function(){ if (a) return b ; return c })
|
|
614
|
+
|
|
615
|
+
Note that 'await (async function(){})()' can be optimized to a Thenable since no args are passed
|
|
616
|
+
*/
|
|
617
|
+
function mapCondOp(ast, state) {
|
|
618
|
+
if (Array.isArray(ast))
|
|
619
|
+
return ast.map(function (n) {
|
|
620
|
+
return mapCondOp(n, state);
|
|
621
|
+
});
|
|
622
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
623
|
+
descend();
|
|
624
|
+
if (node.type === 'ConditionalExpression' && (containsAwait(node.alternate) || containsAwait(node.consequent))) {
|
|
625
|
+
var z = ident(generateSymbol("condOp"));
|
|
626
|
+
var xform = internalIIAFE(parser.part("if ($0) return $1 ; return $2",[node.test,node.consequent,node.alternate]).body);
|
|
627
|
+
coerce(node, xform);
|
|
628
|
+
}
|
|
629
|
+
}, state);
|
|
630
|
+
return ast;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/*
|
|
634
|
+
To implement conditional execution, logical operators with an awaited RHS are mapped thus:
|
|
635
|
+
|
|
636
|
+
Translate a || b into await (async function Or(){ var z ; if (!(z=a)) z=b ; return z })
|
|
637
|
+
Translate a && b into await (async function And(){ var z ; if (z=a) z=b ; return z })
|
|
638
|
+
|
|
639
|
+
Note that 'await (async function(){})()' can be optimized to a Thenable since no args are passed
|
|
640
|
+
*/
|
|
641
|
+
function mapLogicalOp(ast, state) {
|
|
642
|
+
if (Array.isArray(ast))
|
|
643
|
+
return ast.map(function (n) {
|
|
644
|
+
return mapLogicalOp(n, state);
|
|
645
|
+
});
|
|
646
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
647
|
+
descend();
|
|
648
|
+
if (node.type === 'LogicalExpression' && containsAwait(node.right)) {
|
|
649
|
+
var codeFrag;
|
|
650
|
+
var z = ident(generateSymbol("logical" + (node.operator === '&&' ? "And" : "Or")));
|
|
651
|
+
|
|
652
|
+
if (node.operator === '||') {
|
|
653
|
+
codeFrag = "var $0; if (!($0 = $1)) {$0 = $2} return $0" ;
|
|
654
|
+
} else if (node.operator === '&&') {
|
|
655
|
+
codeFrag = "var $0; if ($0 = $1) {$0 = $2} return $0" ;
|
|
656
|
+
} else
|
|
657
|
+
throw new Error(where(node) + "Illegal logical operator: "+node.operator);
|
|
658
|
+
|
|
659
|
+
coerce(node, internalIIAFE(parser.part(codeFrag,[z,node.left, node.right]).body));
|
|
660
|
+
}
|
|
661
|
+
}, state);
|
|
662
|
+
return ast;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function mapBlock(block, path, down) {
|
|
666
|
+
if (block.type !== "SwitchCase" && examine(block).isBlockStatement) {
|
|
667
|
+
var idx = 0 ;
|
|
668
|
+
while (idx < block.body.length) {
|
|
669
|
+
var node = block.body[idx] ;
|
|
670
|
+
if (node.type !== "SwitchCase" && examine(node).isBlockStatement) {
|
|
671
|
+
var blockScoped = containsBlockScopedDeclarations(node.body) ;
|
|
672
|
+
if (!blockScoped) {
|
|
673
|
+
block.body.splice.apply(block.body,[idx,1].concat(node.body));
|
|
674
|
+
} else {
|
|
675
|
+
if (containsAwaitInBlock(node)) {
|
|
676
|
+
var symName = generateSymbol(node);
|
|
677
|
+
var deferredCode = block.body.splice(idx + 1, block.body.length - (idx + 1));
|
|
678
|
+
if (deferredCode.length) {
|
|
679
|
+
var ctn = makeContinuation(symName, deferredCode);
|
|
680
|
+
delete continuations[symName] ;
|
|
681
|
+
node.body.push(returnThisCall(symName));
|
|
682
|
+
block.body.push(ctn) ;
|
|
683
|
+
idx++ ;
|
|
684
|
+
} else idx++ ;
|
|
685
|
+
} else idx++ ;
|
|
686
|
+
}
|
|
687
|
+
} else idx++ ;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/*
|
|
693
|
+
* Translate:
|
|
694
|
+
if (x) { y; } more... ;
|
|
695
|
+
* into
|
|
696
|
+
if (x) { y; return $more(); } function $more() { more... } $more() ;
|
|
697
|
+
*
|
|
698
|
+
* ...in case 'y' uses await, in which case we need to invoke $more() at the end of the
|
|
699
|
+
* callback to continue execution after the case.
|
|
700
|
+
*/
|
|
701
|
+
function mapIfStmt(ifStmt, path, down) {
|
|
702
|
+
if (ifStmt.type === 'IfStatement' && containsAwait([ifStmt.consequent,ifStmt.alternate])) {
|
|
703
|
+
var symName = generateSymbol(ifStmt);
|
|
704
|
+
var ref = path[0];
|
|
705
|
+
var synthBlock = {
|
|
706
|
+
type: 'BlockStatement',
|
|
707
|
+
body: [ifStmt]
|
|
708
|
+
};
|
|
709
|
+
if ('index' in ref) {
|
|
710
|
+
var idx = ref.index;
|
|
711
|
+
var deferredCode = ref.parent[ref.field].splice(idx + 1, ref.parent[ref.field].length - (idx + 1));
|
|
712
|
+
ref.replace(synthBlock);
|
|
713
|
+
if (deferredCode.length) {
|
|
714
|
+
var call = returnThisCall(symName);
|
|
715
|
+
synthBlock.body.push(down(makeContinuation(symName, deferredCode)));
|
|
716
|
+
[ifStmt.consequent,ifStmt.alternate].forEach(function (cond) {
|
|
717
|
+
if (!cond)
|
|
718
|
+
return;
|
|
719
|
+
var blockEnd;
|
|
720
|
+
if (!examine(cond).isBlockStatement)
|
|
721
|
+
blockEnd = cond;
|
|
722
|
+
else
|
|
723
|
+
blockEnd = cond.body[cond.body.length - 1];
|
|
724
|
+
if (!(blockEnd && blockEnd.type === 'ReturnStatement')) {
|
|
725
|
+
if (!(cond.type === 'BlockStatement')) {
|
|
726
|
+
coerce(cond, {
|
|
727
|
+
type: 'BlockStatement',
|
|
728
|
+
body: [cloneNode(cond)]
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
cond.$deferred = true;
|
|
732
|
+
cond.body.push(cloneNode(call));
|
|
733
|
+
}
|
|
734
|
+
down(cond);
|
|
735
|
+
});
|
|
736
|
+
// If both blocks are transformed, the trailing call to $post_if()
|
|
737
|
+
// can be omitted as it'll be unreachable via a synchronous path
|
|
738
|
+
if (!(ifStmt.consequent && ifStmt.alternate && ifStmt.consequent.$deferred && ifStmt.alternate.$deferred))
|
|
739
|
+
synthBlock.body.push(cloneNode(call));
|
|
740
|
+
}
|
|
741
|
+
} else {
|
|
742
|
+
ref.parent[ref.field] = synthBlock;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function mapSwitch(switchStmt, path, down) {
|
|
748
|
+
if (!switchStmt.$switched && switchStmt.type === 'SwitchStatement' && containsAwait(switchStmt.cases)) {
|
|
749
|
+
switchStmt.$switched = true;
|
|
750
|
+
var symName, deferred, deferredCode, ref = path[0];
|
|
751
|
+
if ('index' in ref) {
|
|
752
|
+
var j = ref.index + 1;
|
|
753
|
+
deferredCode = ref.parent[ref.field].splice(j, ref.parent[ref.field].length - j);
|
|
754
|
+
if (deferredCode.length && deferredCode[deferredCode.length - 1].type === 'BreakStatement')
|
|
755
|
+
ref.parent[ref.field].push(deferredCode.pop());
|
|
756
|
+
symName = generateSymbol(switchStmt);
|
|
757
|
+
deferred = returnThisCall(symName);
|
|
758
|
+
ref.parent[ref.field].unshift(makeContinuation(symName, deferredCode));
|
|
759
|
+
ref.parent[ref.field].push(cloneNode(deferred));
|
|
760
|
+
}
|
|
761
|
+
// Now transform each case so that 'break' looks like return <deferred>
|
|
762
|
+
switchStmt.cases.forEach(function (caseStmt, idx) {
|
|
763
|
+
if (!(caseStmt.type === 'SwitchCase')) {
|
|
764
|
+
throw new Error("switch contains non-case/default statement: " + caseStmt.type);
|
|
765
|
+
}
|
|
766
|
+
if (containsAwait(caseStmt.consequent)) {
|
|
767
|
+
var end = caseStmt.consequent[caseStmt.consequent.length - 1];
|
|
768
|
+
if (end.type === 'BreakStatement') {
|
|
769
|
+
caseStmt.consequent[caseStmt.consequent.length - 1] = cloneNode(deferred) ;
|
|
770
|
+
} else if (end.type === 'ReturnStatement' || end.type === 'ThrowStatement') {} else {
|
|
771
|
+
// Do nothing - block ends in return or throw
|
|
772
|
+
logger(where(caseStmt) + "switch-case fall-through not supported - added break. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
|
|
773
|
+
caseStmt.consequent.push(cloneNode(deferred));
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function isExitStatement(n) {
|
|
782
|
+
return n.type==='ReturnStatement' || n.type==='ThrowStatement'
|
|
783
|
+
}
|
|
784
|
+
/* Give unique names to TryCatch blocks */
|
|
785
|
+
function labelTryCatch(ast,engineMode) {
|
|
786
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
787
|
+
if (node.type === 'TryStatement' && !node.$seh) {
|
|
788
|
+
if (!examine(path[0].parent).isBlockStatement) {
|
|
789
|
+
path[0].parent[path[0].field] = {
|
|
790
|
+
type:'BlockStatement',
|
|
791
|
+
body:[node]
|
|
792
|
+
} ;
|
|
793
|
+
}
|
|
794
|
+
// Every try-catch needs a name, so asyncDefine/asyncAwait knows who's handling errors
|
|
795
|
+
node.$seh = generateSymbol("Try") + "_";
|
|
796
|
+
node.$containedAwait = !!containsAwait(node);
|
|
797
|
+
node.$finallyExit = node.finalizer && inAsync(path) && !!contains(node.finalizer.body,isExitStatement) ;
|
|
798
|
+
|
|
799
|
+
if (node.$containedAwait || node.$finallyExit) {
|
|
800
|
+
node.$needsMapping = engineMode? !node.$finallyExit : true ;
|
|
801
|
+
var parent = getExit(path, [opts]);
|
|
802
|
+
if (node.finalizer && !node.handler) {
|
|
803
|
+
// We have a finally, but no 'catch'. Create the default catch clause 'catch(_ex) { throw _ex }'
|
|
804
|
+
var exSym = ident(generateSymbol("exception"));
|
|
805
|
+
node.handler = {
|
|
806
|
+
"type": "CatchClause",
|
|
807
|
+
"param": exSym,
|
|
808
|
+
"body": {
|
|
809
|
+
"type": "BlockStatement",
|
|
810
|
+
"body": [{
|
|
811
|
+
"type": "ThrowStatement",
|
|
812
|
+
"argument": exSym
|
|
813
|
+
}]
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
if (!node.handler && !node.finalizer) {
|
|
818
|
+
var ex = new SyntaxError(where(node.value) + "try requires catch and/or finally clause", pr.filename, node.start);
|
|
819
|
+
ex.pos = node.start;
|
|
820
|
+
ex.loc = node.loc.start;
|
|
821
|
+
throw ex;
|
|
822
|
+
}
|
|
823
|
+
if (node.finalizer) {
|
|
824
|
+
setExit(node.block, {
|
|
825
|
+
$error: node.$seh + "Catch",
|
|
826
|
+
$return: deferredFinally(node, parent.$return)
|
|
827
|
+
});
|
|
828
|
+
setExit(node.handler, {
|
|
829
|
+
$error: deferredFinally(node, parent.$error),
|
|
830
|
+
$return: deferredFinally(node, parent.$return)
|
|
831
|
+
});
|
|
832
|
+
} else {
|
|
833
|
+
setExit(node.block, {
|
|
834
|
+
$error: node.$seh + "Catch",
|
|
835
|
+
$return: parent.$return
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
descend();
|
|
841
|
+
});
|
|
842
|
+
return ast;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function afterDirectives(body,nodes) {
|
|
846
|
+
for (var i=0; i<body.length; i++) {
|
|
847
|
+
if (examine(body[i]).isDirective)
|
|
848
|
+
continue ;
|
|
849
|
+
body.splice.apply(body,[i,0].concat(nodes)) ;
|
|
850
|
+
return ;
|
|
851
|
+
}
|
|
852
|
+
body.splice.apply(body,[body.length,0].concat(nodes)) ;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
function inAsync(path) {
|
|
856
|
+
for (var i=0; i<path.length; i++)
|
|
857
|
+
if (examine(path[i].self).isFunction)
|
|
858
|
+
return path[i].self.async || path[i].self.$wasAsync ;
|
|
859
|
+
return false ;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
function mapTryCatch(node, path, down) {
|
|
863
|
+
if (node.$needsMapping) {
|
|
864
|
+
var continuation, ctnName, catchBody;
|
|
865
|
+
var ref = path[0];
|
|
866
|
+
if ('index' in ref) {
|
|
867
|
+
var i = ref.index + 1;
|
|
868
|
+
var afterTry = ref.parent[ref.field].splice(i, ref.parent[ref.field].length - i);
|
|
869
|
+
if (afterTry.length) {
|
|
870
|
+
ctnName = node.$seh + "Post";
|
|
871
|
+
var afterContinuation = down(makeBoundFn(ctnName, afterTry, [], getExit(path, [opts]).$error));
|
|
872
|
+
ref.parent[ref.field].splice(ref.index,0,afterContinuation);
|
|
873
|
+
continuation = parser.part("return $0()",
|
|
874
|
+
[node.finalizer ? deferredFinally(node, ident(ctnName)) : ident(ctnName)]).body[0] ;
|
|
875
|
+
} else if (node.finalizer) {
|
|
876
|
+
continuation = returnThisCall(deferredFinally(node));
|
|
877
|
+
}
|
|
878
|
+
} else {
|
|
879
|
+
throw new Error(pr.filename + " - malformed try/catch blocks");
|
|
880
|
+
}
|
|
881
|
+
node.$mapped = true;
|
|
882
|
+
if (continuation) {
|
|
883
|
+
node.block.body.push(cloneNode(continuation));
|
|
884
|
+
node.handler.body.body.push(cloneNode(continuation));
|
|
885
|
+
}
|
|
886
|
+
var binding = getExit(path, [opts]);
|
|
887
|
+
if (node.handler) {
|
|
888
|
+
var symCatch = ident(node.$seh + "Catch");
|
|
889
|
+
catchBody = cloneNode(node.handler.body);
|
|
890
|
+
var catcher = makeBoundFn(symCatch.name, catchBody, [cloneNode(node.handler.param)], node.finalizer ? deferredFinally(node, binding.$error) : binding.$error);
|
|
891
|
+
node.handler.body.body = [{
|
|
892
|
+
type: 'CallExpression',
|
|
893
|
+
callee: symCatch,
|
|
894
|
+
arguments: [cloneNode(node.handler.param)]
|
|
895
|
+
}];
|
|
896
|
+
ref.parent[ref.field].splice(ref.index,0,catcher) ;
|
|
897
|
+
}
|
|
898
|
+
if (node.finalizer) {
|
|
899
|
+
down(node.finalizer) ;
|
|
900
|
+
var finalParams = {
|
|
901
|
+
exit:ident(node.$seh + "Exit"),
|
|
902
|
+
value:ident(node.$seh + "Value"),
|
|
903
|
+
body:cloneNode(node.finalizer.body),
|
|
904
|
+
} ;
|
|
905
|
+
|
|
906
|
+
var chainFinalize = parser.part(
|
|
907
|
+
"(function ($value) { "+
|
|
908
|
+
" $:body; "+
|
|
909
|
+
" return $exit && ($exit.call(this, $value)); "+
|
|
910
|
+
" })",finalParams).expr ;
|
|
911
|
+
|
|
912
|
+
var finalizer = {
|
|
913
|
+
type: 'VariableDeclaration',
|
|
914
|
+
kind: 'var',
|
|
915
|
+
declarations: [{
|
|
916
|
+
type: "VariableDeclarator",
|
|
917
|
+
id: ident(node.$seh + "Finally"),
|
|
918
|
+
init: bindAsync({
|
|
919
|
+
type:'FunctionExpression',
|
|
920
|
+
params:[finalParams.exit],
|
|
921
|
+
id:null,
|
|
922
|
+
body:{
|
|
923
|
+
type:'BlockStatement',
|
|
924
|
+
body:[{
|
|
925
|
+
type: 'ReturnStatement',
|
|
926
|
+
argument: bindAsync(chainFinalize,binding.$error)
|
|
927
|
+
}]
|
|
928
|
+
}
|
|
929
|
+
})
|
|
930
|
+
}]
|
|
931
|
+
} ;
|
|
932
|
+
|
|
933
|
+
afterDirectives(ref.parent[ref.field],[finalizer]);
|
|
934
|
+
var callFinally = parser.part("return $0()",
|
|
935
|
+
[node.finalizer ? deferredFinally(node, ident(ctnName)) : ident(ctnName)]).body[0] ;
|
|
936
|
+
catchBody.body[catchBody.length - 1] = callFinally;
|
|
937
|
+
node.block.body[node.block.body.length - 1] = callFinally;
|
|
938
|
+
delete node.finalizer;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
function walkDown(ast, mappers, state) {
|
|
944
|
+
var walked = [];
|
|
945
|
+
|
|
946
|
+
function closedWalk(ast,state) {
|
|
947
|
+
return parser.treeWalker(ast, function (node, descend, path) {
|
|
948
|
+
function walkDownSubtree(node) {
|
|
949
|
+
return closedWalk(node, path);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
if (walked.indexOf(node) < 0) {
|
|
953
|
+
walked.push(node) ;
|
|
954
|
+
mappers.forEach(function (m) {
|
|
955
|
+
m(node, path, walkDownSubtree);
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
descend();
|
|
959
|
+
return;
|
|
960
|
+
}, state);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
closedWalk(ast,state)
|
|
964
|
+
return ast ;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
function asyncAwait(ast, inAsync, parentCatcher) {
|
|
968
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
969
|
+
if (node.type == 'IfStatement') {
|
|
970
|
+
if (node.consequent.type != 'BlockStatement' && containsAwait(node.consequent))
|
|
971
|
+
node.consequent = {
|
|
972
|
+
type: 'BlockStatement',
|
|
973
|
+
body: [node.consequent]
|
|
974
|
+
};
|
|
975
|
+
if (node.alternate && node.alternate.type != 'BlockStatement' && containsAwait(node.alternate))
|
|
976
|
+
node.alternate = {
|
|
977
|
+
type: 'BlockStatement',
|
|
978
|
+
body: [node.alternate]
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
descend();
|
|
982
|
+
if (examine(node).isAwait) {
|
|
983
|
+
var loc = node.loc;
|
|
984
|
+
/* Warn if this await expression is not inside an async function, as the return
|
|
985
|
+
* will depend on the Thenable implementation, and references to $return might
|
|
986
|
+
* not resolve to anything */
|
|
987
|
+
inAsync = inAsync || path.some(function (ancestor) {
|
|
988
|
+
return ancestor.self && ancestor.self.$wasAsync;
|
|
989
|
+
});
|
|
990
|
+
if (!inAsync || inAsync === "warn") {
|
|
991
|
+
var errMsg = where(node) + "'await' used inside non-async function. ";
|
|
992
|
+
if (opts.promises)
|
|
993
|
+
errMsg += "'return' value Promise runtime-specific";
|
|
994
|
+
else
|
|
995
|
+
errMsg += "'return' value from await is synchronous";
|
|
996
|
+
logger(errMsg + ". See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
|
|
997
|
+
}
|
|
998
|
+
var parent = path[0].parent;
|
|
999
|
+
if (parent.type === 'LogicalExpression' && parent.right === node) {
|
|
1000
|
+
logger(where(node.argument) + "'" + printNode(parent) + "' on right of " + parent.operator + " will always evaluate '" + printNode(node.argument) + "'");
|
|
1001
|
+
}
|
|
1002
|
+
if (parent.type === 'ConditionalExpression' && parent.test !== node) {
|
|
1003
|
+
logger(where(node.argument) + "'" + printNode(parent) + "' will always evaluate '" + printNode(node.argument) + "'");
|
|
1004
|
+
}
|
|
1005
|
+
var result = ident(generateSymbol("await"));
|
|
1006
|
+
var expr = cloneNode(node.argument);
|
|
1007
|
+
coerce(node, result);
|
|
1008
|
+
// Find the statement containing this await expression (and it's parent)
|
|
1009
|
+
var stmt, body;
|
|
1010
|
+
for (var n = 1;n < path.length; n++) {
|
|
1011
|
+
if (body = examine(path[n].self).isBlockStatement) {
|
|
1012
|
+
stmt = path[n - 1];
|
|
1013
|
+
break;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
if (!stmt)
|
|
1017
|
+
throw new Error(where(node) + "Illegal await not contained in a statement");
|
|
1018
|
+
var containingExits = getExit(path, [parentCatcher,opts]);
|
|
1019
|
+
var i = stmt.index;
|
|
1020
|
+
var callback, callBack = body.splice(i, body.length - i).slice(1);
|
|
1021
|
+
var returner;
|
|
1022
|
+
// If stmt is of the form 'return fn(result.name)', just replace it a
|
|
1023
|
+
// reference to 'fn'.
|
|
1024
|
+
if (stmt.self.type === 'ReturnStatement' && stmt.self.argument.type === 'CallExpression' && stmt.self.argument.arguments.length === 1 && stmt.self.argument.arguments[0].name === result.name) {
|
|
1025
|
+
returner = (callback = stmt.self.argument.callee);
|
|
1026
|
+
// If stmt is only a reference to the result, suppress the result
|
|
1027
|
+
// reference as it does nothing
|
|
1028
|
+
} else if (!(stmt.self.type === 'Identifier' || stmt.self.name === result.name || stmt.self.type === 'ExpressionStatement' && stmt.self.expression.type === 'Identifier' && stmt.self.expression.name === result.name)) {
|
|
1029
|
+
callBack.unshift(stmt.self);
|
|
1030
|
+
callback = {
|
|
1031
|
+
type: 'FunctionExpression',
|
|
1032
|
+
params: [cloneNode(result)],
|
|
1033
|
+
body: asyncAwait({
|
|
1034
|
+
type: 'BlockStatement',
|
|
1035
|
+
body: cloneNode(callBack)
|
|
1036
|
+
}, inAsync, containingExits)
|
|
1037
|
+
};
|
|
1038
|
+
} else {
|
|
1039
|
+
if (callBack.length)
|
|
1040
|
+
callback = {
|
|
1041
|
+
type: 'FunctionExpression',
|
|
1042
|
+
params: [cloneNode(result)],
|
|
1043
|
+
body: asyncAwait({
|
|
1044
|
+
type: 'BlockStatement',
|
|
1045
|
+
body: cloneNode(callBack)
|
|
1046
|
+
}, inAsync, containingExits)
|
|
1047
|
+
};
|
|
1048
|
+
else {
|
|
1049
|
+
callback = {
|
|
1050
|
+
type: 'FunctionExpression',
|
|
1051
|
+
params: [],
|
|
1052
|
+
body: {
|
|
1053
|
+
type: 'BlockStatement',
|
|
1054
|
+
body: []
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
// Wrap the callback statement(s) in a Block and transform them
|
|
1060
|
+
if (!returner) {
|
|
1061
|
+
if (callback) {
|
|
1062
|
+
returner = bindAsync(callback,containingExits.$error) ;
|
|
1063
|
+
} else {
|
|
1064
|
+
returner = {
|
|
1065
|
+
type: 'FunctionExpression',
|
|
1066
|
+
params: [],
|
|
1067
|
+
body: {
|
|
1068
|
+
type: 'BlockStatement',
|
|
1069
|
+
body: []
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
if (opts.wrapAwait) {
|
|
1075
|
+
expr = {
|
|
1076
|
+
type: 'CallExpression',
|
|
1077
|
+
arguments: [expr],
|
|
1078
|
+
callee: (opts.promises || opts.generators)?{
|
|
1079
|
+
type: 'MemberExpression',
|
|
1080
|
+
object: ident('Promise'),
|
|
1081
|
+
property: ident('resolve')
|
|
1082
|
+
}:{
|
|
1083
|
+
// ES7 makeThenable
|
|
1084
|
+
type: 'MemberExpression',
|
|
1085
|
+
object: ident('Object'),
|
|
1086
|
+
property: ident('$makeThenable')
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
var exitCall = {
|
|
1091
|
+
type: 'CallExpression',
|
|
1092
|
+
callee: {
|
|
1093
|
+
type: 'MemberExpression',
|
|
1094
|
+
object: expr,
|
|
1095
|
+
property: ident('then', loc),
|
|
1096
|
+
computed: false
|
|
1097
|
+
},
|
|
1098
|
+
arguments: [returner,containingExits.$error]
|
|
1099
|
+
};
|
|
1100
|
+
body.push({
|
|
1101
|
+
loc: loc,
|
|
1102
|
+
type: 'ReturnStatement',
|
|
1103
|
+
argument: exitCall
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
return true;
|
|
1107
|
+
});
|
|
1108
|
+
return ast;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// Transform a for..in into it's iterative equivalent
|
|
1112
|
+
function transformForIn(node, path) {
|
|
1113
|
+
var label = node.$label ;
|
|
1114
|
+
delete node.$label ;
|
|
1115
|
+
|
|
1116
|
+
var idx = ident(generateSymbol("idx"))
|
|
1117
|
+
var inArray = ident(generateSymbol("in"));
|
|
1118
|
+
var declVars = parser.part("var $0,$1 = [];for ($0 in $2) $1.push($0)",[idx,inArray,node.right]).body ;
|
|
1119
|
+
var loop = parser.part("for ($0; $1.length;){ $2 = $1.shift(); $:3 ; }",[
|
|
1120
|
+
node.left,
|
|
1121
|
+
inArray,
|
|
1122
|
+
node.left.type === 'VariableDeclaration' ? node.left.declarations[0].id : node.left,
|
|
1123
|
+
node.body]).body[0] ;
|
|
1124
|
+
loop.$label = label ;
|
|
1125
|
+
for (var b=0; b<path.length; b++) {
|
|
1126
|
+
if (examine(path[b].parent).isBlockStatement) {
|
|
1127
|
+
path[b].parent[path[b].field].splice(path[b].index,0,declVars[0],declVars[1]) ;
|
|
1128
|
+
break ;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
coerce(node,loop) ;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// Transform a for..of into it's iterative equivalent
|
|
1135
|
+
function iterizeForOf(node, path) {
|
|
1136
|
+
if (node.body.type !== 'BlockStatement') {
|
|
1137
|
+
node.body = {
|
|
1138
|
+
type: 'BlockStatement',
|
|
1139
|
+
body: [node.body]
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
var index, iterator, initIterator = parser.part("[$0[Symbol.iterator]()]",[node.right]).expr;
|
|
1143
|
+
|
|
1144
|
+
if (node.left.type === 'VariableDeclaration') {
|
|
1145
|
+
if (node.left.kind==='const')
|
|
1146
|
+
node.left.kind = 'let' ;
|
|
1147
|
+
|
|
1148
|
+
index = node.left.declarations[0].id ;
|
|
1149
|
+
var decls = getDeclNames(node.left.declarations[0].id) ;
|
|
1150
|
+
iterator = ident(generateSymbol("iterator_" + decls.join('_')));
|
|
1151
|
+
|
|
1152
|
+
node.left.declarations = decls.map(function(name){
|
|
1153
|
+
return {
|
|
1154
|
+
type: "VariableDeclarator",
|
|
1155
|
+
id: ident(name)
|
|
1156
|
+
} ;
|
|
1157
|
+
}) ;
|
|
1158
|
+
node.left.declarations.push({
|
|
1159
|
+
type: "VariableDeclarator",
|
|
1160
|
+
id: iterator,
|
|
1161
|
+
init: initIterator
|
|
1162
|
+
});
|
|
1163
|
+
node.init = node.left;
|
|
1164
|
+
} else {
|
|
1165
|
+
index = node.left;
|
|
1166
|
+
iterator = ident(generateSymbol("iterator_" + index.name));
|
|
1167
|
+
var declaration = {
|
|
1168
|
+
type: 'VariableDeclaration',
|
|
1169
|
+
kind: 'var',
|
|
1170
|
+
declarations: [{
|
|
1171
|
+
type: "VariableDeclarator",
|
|
1172
|
+
id: iterator,
|
|
1173
|
+
init: initIterator
|
|
1174
|
+
}]
|
|
1175
|
+
};
|
|
1176
|
+
node.init = declaration;
|
|
1177
|
+
}
|
|
1178
|
+
node.type = 'ForStatement';
|
|
1179
|
+
node.test = parser.part("!($0[1] = $0[0].next()).done && (($1 = $0[1].value) || true)",[iterator,index]).expr ;
|
|
1180
|
+
delete node.left;
|
|
1181
|
+
delete node.right;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
/* Map loops */
|
|
1185
|
+
/* As of v3.0.0 loops are asynchronized via a trampoline to prevent stack overflow in big loops with no actionable awaits. */
|
|
1186
|
+
function mapLoops(node, path, down) {
|
|
1187
|
+
var depth = node.$depth ;
|
|
1188
|
+
if (node.type === 'ForInStatement' && containsAwait(node)) {
|
|
1189
|
+
transformForIn(node, path) ;
|
|
1190
|
+
} else if (node.type === 'ForOfStatement' && containsAwait(node)) {
|
|
1191
|
+
iterizeForOf(node, path);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
// Are we inside a loop that has already been asynchronized and is labelled?
|
|
1195
|
+
var inAsyncLoop = path.some(function(p){
|
|
1196
|
+
return ('$label' in p.self && p.self.type==='ForStatement' && p.self.$mapped) ;
|
|
1197
|
+
}) ;
|
|
1198
|
+
|
|
1199
|
+
// Check if the loop contains an await, or a labelled exit if we're inside an async loop
|
|
1200
|
+
function mappableLoop(n){
|
|
1201
|
+
return (n.type==='AwaitExpression' && !n.$hidden)
|
|
1202
|
+
|| (inAsyncLoop && (n.type==='BreakStatement'|| n.type==='ContinueStatement') && n.label)
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
if (!node.$mapped && examine(node).isLoop && contains(node,mappableLoop)) {
|
|
1206
|
+
path[0].self.$mapped = true ;
|
|
1207
|
+
var p ;
|
|
1208
|
+
var mapped = [] ;
|
|
1209
|
+
var init = node.init;
|
|
1210
|
+
var test = node.test || literal(true);
|
|
1211
|
+
var step = node.update;
|
|
1212
|
+
var body = node.body;
|
|
1213
|
+
|
|
1214
|
+
if (step) {
|
|
1215
|
+
step = {
|
|
1216
|
+
type:'ExpressionStatement',
|
|
1217
|
+
expression: step
|
|
1218
|
+
} ;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
if (init) {
|
|
1222
|
+
if (!examine(init).isStatement) {
|
|
1223
|
+
init = {
|
|
1224
|
+
type: 'ExpressionStatement',
|
|
1225
|
+
expression: init
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
mapped.push(init) ;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
var ref, label ;
|
|
1232
|
+
if (node.$label) {
|
|
1233
|
+
label = node.$label.name ;
|
|
1234
|
+
ref = path[1] ;
|
|
1235
|
+
} else {
|
|
1236
|
+
label = generatedSymbol++ ;
|
|
1237
|
+
ref = path[0] ;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
label = opts.generatedSymbolPrefix + "Loop_" + label;
|
|
1241
|
+
var idTrampoline = ident(label + "_trampoline") ;
|
|
1242
|
+
var idIter = ident(label) ;
|
|
1243
|
+
var idStep = step ? ident(label + "_step") : idIter ;
|
|
1244
|
+
var idContinuation = ident(label + "_exit") ;
|
|
1245
|
+
var idBounce = ident("q") ;
|
|
1246
|
+
var idCatchParam = ident("$exception") ;
|
|
1247
|
+
var continuation, deferredCode ;
|
|
1248
|
+
|
|
1249
|
+
if ('index' in ref) {
|
|
1250
|
+
var idx = ref.index;
|
|
1251
|
+
deferredCode = ref.parent[ref.field].splice(idx + 1, ref.parent[ref.field].length - (idx + 1));
|
|
1252
|
+
} else {
|
|
1253
|
+
deferredCode = [] ;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
continuation = makeContinuation(idContinuation, deferredCode) ;
|
|
1257
|
+
var returnIter = {
|
|
1258
|
+
"type": "ReturnStatement",
|
|
1259
|
+
"argument": idIter
|
|
1260
|
+
} ;
|
|
1261
|
+
|
|
1262
|
+
var returnStep = {
|
|
1263
|
+
"type": "ReturnStatement",
|
|
1264
|
+
"argument": idStep
|
|
1265
|
+
} ;
|
|
1266
|
+
|
|
1267
|
+
var returnBreak = {
|
|
1268
|
+
type: 'ReturnStatement',
|
|
1269
|
+
argument: {
|
|
1270
|
+
"type": "ArrayExpression",
|
|
1271
|
+
"elements":[literal(1)]
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
parser.treeWalker(body, function mapExits(n, descend, subpath) {
|
|
1276
|
+
if (examine(n).isFunction || examine(n).isLoop) {
|
|
1277
|
+
return true;
|
|
1278
|
+
} else if (n.type === 'BreakStatement' || n.type === 'ContinueStatement') {
|
|
1279
|
+
if (n.label) {
|
|
1280
|
+
var labelStack = subpath.filter(function(p){
|
|
1281
|
+
return '$label' in p.self
|
|
1282
|
+
}).map(function(p,idx){
|
|
1283
|
+
return p.self.$label && p.self.$label.name
|
|
1284
|
+
}) ;
|
|
1285
|
+
|
|
1286
|
+
// Work out how many loops to exit by examining subpath.
|
|
1287
|
+
var loops = [] ;
|
|
1288
|
+
for (var l=0; l<labelStack.length; l++) {
|
|
1289
|
+
if (labelStack[l] === n.label.name) {
|
|
1290
|
+
if (n.type === 'BreakStatement')
|
|
1291
|
+
loops.push(literal(1)) ;
|
|
1292
|
+
subpath[0].replace({
|
|
1293
|
+
type: 'ReturnStatement',
|
|
1294
|
+
argument: {
|
|
1295
|
+
"type": "ArrayExpression",
|
|
1296
|
+
"elements":loops.reverse()
|
|
1297
|
+
}
|
|
1298
|
+
}) ;
|
|
1299
|
+
break ;
|
|
1300
|
+
}
|
|
1301
|
+
loops.push(literal(0)) ;
|
|
1302
|
+
}
|
|
1303
|
+
} else {
|
|
1304
|
+
if (n.type === 'BreakStatement')
|
|
1305
|
+
subpath[0].replace(returnBreak) ;
|
|
1306
|
+
else // continue;
|
|
1307
|
+
subpath[0].replace(returnStep) ;
|
|
1308
|
+
}
|
|
1309
|
+
} else {
|
|
1310
|
+
descend();
|
|
1311
|
+
}
|
|
1312
|
+
},path) ;
|
|
1313
|
+
|
|
1314
|
+
if (body.type === 'BlockStatement')
|
|
1315
|
+
body = body.body.slice(0) ;
|
|
1316
|
+
else
|
|
1317
|
+
body = [body] ;
|
|
1318
|
+
|
|
1319
|
+
if (node.type==='DoWhileStatement') {
|
|
1320
|
+
body = body.concat({
|
|
1321
|
+
"type": "IfStatement",
|
|
1322
|
+
"test": {
|
|
1323
|
+
type:'UnaryExpression',
|
|
1324
|
+
argument:test,
|
|
1325
|
+
prefix:true,
|
|
1326
|
+
operator:'!'
|
|
1327
|
+
},
|
|
1328
|
+
"consequent": returnBreak,
|
|
1329
|
+
alternate:returnStep
|
|
1330
|
+
}) ;
|
|
1331
|
+
} else {
|
|
1332
|
+
body = [{
|
|
1333
|
+
"type": "IfStatement",
|
|
1334
|
+
"test": test,
|
|
1335
|
+
"consequent": {
|
|
1336
|
+
"type": "BlockStatement",
|
|
1337
|
+
"body": body.concat(returnStep)
|
|
1338
|
+
},
|
|
1339
|
+
alternate:returnBreak
|
|
1340
|
+
}] ;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
if (opts.noRuntime) {
|
|
1344
|
+
mapped.push({
|
|
1345
|
+
"type": "VariableDeclaration",
|
|
1346
|
+
"declarations": [{
|
|
1347
|
+
"type": "VariableDeclarator",
|
|
1348
|
+
"id": idTrampoline
|
|
1349
|
+
}],
|
|
1350
|
+
"kind": "var"
|
|
1351
|
+
}) ;
|
|
1352
|
+
}
|
|
1353
|
+
var invokeIterate ;
|
|
1354
|
+
var exit = getExit(path, [opts]).$error ;
|
|
1355
|
+
if (opts.noRuntime) {
|
|
1356
|
+
invokeIterate = parser.part(
|
|
1357
|
+
opts.es6target?
|
|
1358
|
+
"($idTrampoline = ((q) => { "+
|
|
1359
|
+
" $$setMapped: while (q) { "+
|
|
1360
|
+
" if (q.then) "+
|
|
1361
|
+
(depth===1?
|
|
1362
|
+
" return void q.then($idTrampoline, $exit); ":
|
|
1363
|
+
" return q.then($idTrampoline, $exit); ")+
|
|
1364
|
+
" try { "+
|
|
1365
|
+
" if (q.pop) "+
|
|
1366
|
+
" if (q.length) "+
|
|
1367
|
+
" return q.pop() ? $idContinuation.call(this) : q; "+
|
|
1368
|
+
" else "+
|
|
1369
|
+
" q = $idStep; "+
|
|
1370
|
+
" else "+
|
|
1371
|
+
" q = q.call(this) "+
|
|
1372
|
+
" } catch (_exception) { "+
|
|
1373
|
+
" return $exit(_exception); "+
|
|
1374
|
+
" } "+
|
|
1375
|
+
" } "+
|
|
1376
|
+
"}))($idIter)":
|
|
1377
|
+
"($idTrampoline = (function (q) { "+
|
|
1378
|
+
" $$setMapped: while (q) { "+
|
|
1379
|
+
" if (q.then) "+
|
|
1380
|
+
(depth===1?
|
|
1381
|
+
" return void q.then($idTrampoline, $exit); ":
|
|
1382
|
+
" return q.then($idTrampoline, $exit); ")+
|
|
1383
|
+
" try { "+
|
|
1384
|
+
" if (q.pop) "+
|
|
1385
|
+
" if (q.length) "+
|
|
1386
|
+
" return q.pop() ? $idContinuation.call(this) : q; "+
|
|
1387
|
+
" else "+
|
|
1388
|
+
" q = $idStep; "+
|
|
1389
|
+
" else "+
|
|
1390
|
+
" q = q.call(this) "+
|
|
1391
|
+
" } catch (_exception) { "+
|
|
1392
|
+
" return $exit(_exception); "+
|
|
1393
|
+
" } "+
|
|
1394
|
+
" } "+
|
|
1395
|
+
"}).bind(this))($idIter)",
|
|
1396
|
+
{
|
|
1397
|
+
setMapped:function(n){ n.$mapped = true ; return n },
|
|
1398
|
+
idTrampoline:idTrampoline,
|
|
1399
|
+
exit:exit,
|
|
1400
|
+
idIter:idIter,
|
|
1401
|
+
idContinuation:idContinuation,
|
|
1402
|
+
idStep:idStep
|
|
1403
|
+
}).expr ;
|
|
1404
|
+
} else {
|
|
1405
|
+
invokeIterate = parser.part("(Function.$0.trampoline(this,$1,$2,$3,$5)($4))",[
|
|
1406
|
+
genIdent.asyncbind,
|
|
1407
|
+
idContinuation,idStep,exit,
|
|
1408
|
+
idIter,
|
|
1409
|
+
literal(depth===1)
|
|
1410
|
+
]).expr;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
mapped.push({type:'ReturnStatement',argument:invokeIterate}) ;
|
|
1414
|
+
mapped.push({
|
|
1415
|
+
$label:node.$label,
|
|
1416
|
+
"type": "FunctionDeclaration",
|
|
1417
|
+
"id": idIter,
|
|
1418
|
+
"params": [],
|
|
1419
|
+
"body": {
|
|
1420
|
+
"type": "BlockStatement",
|
|
1421
|
+
"body": body
|
|
1422
|
+
}
|
|
1423
|
+
}) ;
|
|
1424
|
+
|
|
1425
|
+
if (step) {
|
|
1426
|
+
mapped.push({
|
|
1427
|
+
"type": "FunctionDeclaration",
|
|
1428
|
+
id: idStep,
|
|
1429
|
+
"params": [],
|
|
1430
|
+
"body": {
|
|
1431
|
+
"type": "BlockStatement",
|
|
1432
|
+
"body": [ step,returnIter ]
|
|
1433
|
+
}
|
|
1434
|
+
}) ;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
if (init && init.type==='VariableDeclaration' && (init.kind==='let' || init.kind==='const')) {
|
|
1438
|
+
if (init.kind==='const')
|
|
1439
|
+
init.kind = 'let' ;
|
|
1440
|
+
|
|
1441
|
+
path[0].replace([{
|
|
1442
|
+
type:'BlockStatement',
|
|
1443
|
+
body:mapped.map(down)
|
|
1444
|
+
},down(continuation)]) ;
|
|
1445
|
+
} else {
|
|
1446
|
+
mapped.push(continuation) ;
|
|
1447
|
+
path[0].replace(mapped.map(down)) ;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
/* Previous, recursive implementation for backwards compatibility */
|
|
1453
|
+
function asyncLoops_1(ast,state) {
|
|
1454
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
1455
|
+
function mapContinue(label) {
|
|
1456
|
+
return {
|
|
1457
|
+
type: 'ReturnStatement',
|
|
1458
|
+
argument: {
|
|
1459
|
+
type: 'UnaryExpression',
|
|
1460
|
+
operator: 'void',
|
|
1461
|
+
prefix: true,
|
|
1462
|
+
argument: thisCall(label || symContinue)
|
|
1463
|
+
}
|
|
1464
|
+
};
|
|
1465
|
+
};
|
|
1466
|
+
function mapExits(n, descend) {
|
|
1467
|
+
if (n.type === 'BreakStatement') {
|
|
1468
|
+
coerce(n, cloneNode(mapBreak(n.label && opts.generatedSymbolPrefix + "Loop_" + n.label.name + "_exit")));
|
|
1469
|
+
} else if (n.type === 'ContinueStatement') {
|
|
1470
|
+
coerce(n, cloneNode(mapContinue(n.label && opts.generatedSymbolPrefix + "Loop_" + n.label.name + "_next")));
|
|
1471
|
+
} else if (examine(n).isFunction) {
|
|
1472
|
+
return true;
|
|
1473
|
+
}
|
|
1474
|
+
descend();
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
if (node.type === 'ForInStatement' && containsAwait(node)) {
|
|
1478
|
+
transformForIn(node, path) ;
|
|
1479
|
+
} else if (node.type === 'ForOfStatement' && containsAwait(node)) {
|
|
1480
|
+
iterizeForOf(node, path);
|
|
1481
|
+
}
|
|
1482
|
+
descend();
|
|
1483
|
+
var p;
|
|
1484
|
+
if (examine(node).isLoop && containsAwait(node)) {
|
|
1485
|
+
var init = node.init;
|
|
1486
|
+
var condition = node.test || literal(true);
|
|
1487
|
+
var step = node.update;
|
|
1488
|
+
var body = node.body;
|
|
1489
|
+
var loopUsesThis = containsThis(body) ;
|
|
1490
|
+
if (init) {
|
|
1491
|
+
if (!examine(init).isStatement) {
|
|
1492
|
+
init = {
|
|
1493
|
+
type: 'ExpressionStatement',
|
|
1494
|
+
expression: init
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
step = step && {
|
|
1499
|
+
type: 'ExpressionStatement',
|
|
1500
|
+
expression: step
|
|
1501
|
+
} ;
|
|
1502
|
+
body = examine(body).isBlockStatement ? cloneNode(body).body : [cloneNode(body)];
|
|
1503
|
+
var label = node.$label && node.$label.name ;
|
|
1504
|
+
label = "Loop_" + (label || generatedSymbol++);
|
|
1505
|
+
var symExit = opts.generatedSymbolPrefix + (label + "_exit");
|
|
1506
|
+
var symContinue = opts.generatedSymbolPrefix + (label + "_next");
|
|
1507
|
+
var loop = ident(opts.generatedSymbolPrefix + (label));
|
|
1508
|
+
// How to exit the loop
|
|
1509
|
+
var mapBreak = function (label) {
|
|
1510
|
+
return {
|
|
1511
|
+
type: 'ReturnStatement',
|
|
1512
|
+
argument: {
|
|
1513
|
+
type: 'UnaryExpression',
|
|
1514
|
+
operator: 'void',
|
|
1515
|
+
prefix: true,
|
|
1516
|
+
argument: {
|
|
1517
|
+
type: 'CallExpression',
|
|
1518
|
+
callee: ident(label || symExit),
|
|
1519
|
+
arguments: []
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
// How to continue the loop
|
|
1526
|
+
var defContinue = makeContinuation(symContinue, [{
|
|
1527
|
+
type: 'ReturnStatement',
|
|
1528
|
+
argument: {
|
|
1529
|
+
type: 'CallExpression',
|
|
1530
|
+
callee: loopUsesThis? bindAsync(loop):loop,
|
|
1531
|
+
arguments: [ident(symExit),genIdent.error]
|
|
1532
|
+
}
|
|
1533
|
+
}]);
|
|
1534
|
+
if (step)
|
|
1535
|
+
defContinue.body.body.unshift(step);
|
|
1536
|
+
for (var i = 0;i < body.length; i++) {
|
|
1537
|
+
parser.treeWalker(body[i], mapExits);
|
|
1538
|
+
}
|
|
1539
|
+
body.push(cloneNode(mapContinue()));
|
|
1540
|
+
var subCall = {
|
|
1541
|
+
type: 'FunctionExpression',
|
|
1542
|
+
id: loop,
|
|
1543
|
+
params: [ident(symExit),genIdent.error],
|
|
1544
|
+
body: {
|
|
1545
|
+
type: 'BlockStatement',
|
|
1546
|
+
body: [defContinue]
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
if (node.type === 'DoWhileStatement') {
|
|
1550
|
+
defContinue.body.body = [{
|
|
1551
|
+
type: 'IfStatement',
|
|
1552
|
+
test: cloneNode(condition),
|
|
1553
|
+
consequent: {
|
|
1554
|
+
type: 'BlockStatement',
|
|
1555
|
+
body: cloneNode(defContinue.body.body)
|
|
1556
|
+
},
|
|
1557
|
+
alternate: {
|
|
1558
|
+
type: 'ReturnStatement',
|
|
1559
|
+
argument: {
|
|
1560
|
+
type: 'CallExpression',
|
|
1561
|
+
callee: ident(symExit),
|
|
1562
|
+
arguments: []
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
}];
|
|
1566
|
+
subCall.body.body = [defContinue].concat(body);
|
|
1567
|
+
} else {
|
|
1568
|
+
var nextTest = {
|
|
1569
|
+
type: 'IfStatement',
|
|
1570
|
+
test: cloneNode(condition),
|
|
1571
|
+
consequent: {
|
|
1572
|
+
type: 'BlockStatement',
|
|
1573
|
+
body: body
|
|
1574
|
+
},
|
|
1575
|
+
alternate: cloneNode(mapBreak())
|
|
1576
|
+
};
|
|
1577
|
+
subCall.body.body.push(nextTest);
|
|
1578
|
+
}
|
|
1579
|
+
var replace = {
|
|
1580
|
+
type: 'ExpressionStatement',
|
|
1581
|
+
expression: {
|
|
1582
|
+
type: 'AwaitExpression',
|
|
1583
|
+
argument: bindAsync(subCall, literal(0))
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1587
|
+
if (init && init.type==='VariableDeclaration' && (init.kind==='let' || init.kind==='const')) {
|
|
1588
|
+
if (init.kind==='const')
|
|
1589
|
+
init.kind = 'let' ;
|
|
1590
|
+
replace = {
|
|
1591
|
+
type:'BlockStatement',
|
|
1592
|
+
body:[cloneNode(init),replace]
|
|
1593
|
+
};
|
|
1594
|
+
init = null ;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
for (p = 0; p < path.length; p++) {
|
|
1598
|
+
var ref = path[p];
|
|
1599
|
+
if ('index' in ref) {
|
|
1600
|
+
if (init) {
|
|
1601
|
+
ref.parent[ref.field].splice(ref.index, 1, cloneNode(init), replace);
|
|
1602
|
+
} else {
|
|
1603
|
+
ref.parent[ref.field][ref.index] = replace;
|
|
1604
|
+
}
|
|
1605
|
+
return true;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
return true;
|
|
1610
|
+
},state);
|
|
1611
|
+
return ast;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
function containsAsyncExit(fn) {
|
|
1615
|
+
if (!examine(fn).isFunction) {
|
|
1616
|
+
throw new Error("Cannot examine non-Function node types for async exits") ;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
return contains(fn.body,function(node){
|
|
1620
|
+
return ((node.type === 'Identifier' && (node.name === opts.$return || node.name === opts.$error))
|
|
1621
|
+
|| (isExitStatement(node) && examine(node).isAsync)) ;
|
|
1622
|
+
},function(node){
|
|
1623
|
+
return !(examine(node).isFunction && (node.$wasAsync || examine(node).isAsync)) ;
|
|
1624
|
+
}) ;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// TODO: Hoist directives (as in asyncDefine)
|
|
1628
|
+
function asyncDefineMethod(ast) {
|
|
1629
|
+
return parser.treeWalker(ast, function (node, descend, path) {
|
|
1630
|
+
var transform = getMemberFunction(node);
|
|
1631
|
+
descend();
|
|
1632
|
+
if (!transform || !examine(transform).isAsync)
|
|
1633
|
+
return;
|
|
1634
|
+
if (node.kind == 'set') {
|
|
1635
|
+
var ex = new SyntaxError(where(transform) + "method 'async set' cannot be invoked", pr.filename, node.start);
|
|
1636
|
+
ex.pos = node.start;
|
|
1637
|
+
ex.loc = node.loc.start;
|
|
1638
|
+
throw ex;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
transform.async = false;
|
|
1642
|
+
var usesArgs = replaceArguments(transform);
|
|
1643
|
+
if (!containsAsyncExit(transform) && (transform.body.body.length === 0 || transform.body.body[transform.body.body.length - 1].type !== 'ReturnStatement')) {
|
|
1644
|
+
transform.body.body.push({
|
|
1645
|
+
type: 'ReturnStatement'
|
|
1646
|
+
});
|
|
1647
|
+
}
|
|
1648
|
+
var funcback = bindAsync(setExit({
|
|
1649
|
+
type: 'FunctionExpression',
|
|
1650
|
+
params: [genIdent.return,genIdent.error],
|
|
1651
|
+
body: asyncDefineMethod(mapReturns(transform.body, path)),
|
|
1652
|
+
$wasAsync: true
|
|
1653
|
+
}, opts),(opts.promises || opts.generators || opts.engine) ? null : literal(opts.lazyThenables?0:true) ) ;
|
|
1654
|
+
|
|
1655
|
+
if (opts.promises) {
|
|
1656
|
+
transform.body = {
|
|
1657
|
+
type: 'BlockStatement',
|
|
1658
|
+
body: [{
|
|
1659
|
+
type: 'ReturnStatement',
|
|
1660
|
+
argument: {
|
|
1661
|
+
type: 'NewExpression',
|
|
1662
|
+
callee: ident('Promise'),
|
|
1663
|
+
arguments: [funcback]
|
|
1664
|
+
}
|
|
1665
|
+
}]
|
|
1666
|
+
};
|
|
1667
|
+
} else {
|
|
1668
|
+
transform.body = {
|
|
1669
|
+
type: 'BlockStatement',
|
|
1670
|
+
body: [{
|
|
1671
|
+
type: 'ReturnStatement',
|
|
1672
|
+
argument: funcback
|
|
1673
|
+
}]
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
if (usesArgs) {
|
|
1677
|
+
afterDirectives(transform.body.body,[assign$Args]);
|
|
1678
|
+
}
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
function asyncDefine(ast) {
|
|
1683
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
1684
|
+
descend();
|
|
1685
|
+
if (examine(node).isAsync && examine(node).isFunction) {
|
|
1686
|
+
var member ;
|
|
1687
|
+
if ((member = getMemberFunction(path[0].parent))
|
|
1688
|
+
&& examine(member).isAsync && path[0].parent.kind === 'get') {
|
|
1689
|
+
warnAsyncGetter(path[0].parent.key) ;
|
|
1690
|
+
}
|
|
1691
|
+
delete node.async;
|
|
1692
|
+
|
|
1693
|
+
var usesArgs = replaceArguments(node);
|
|
1694
|
+
var fnBody = setExit({
|
|
1695
|
+
type: 'FunctionExpression',
|
|
1696
|
+
params: [genIdent.return,genIdent.error],
|
|
1697
|
+
$wasAsync: true
|
|
1698
|
+
}, opts) ;
|
|
1699
|
+
var thisPath = [{self:fnBody}].concat(path) ;
|
|
1700
|
+
|
|
1701
|
+
if (examine(node.body).isBlockStatement) {
|
|
1702
|
+
if (!containsAsyncExit(node) && (node.body.body.length === 0 || node.body.body[node.body.body.length - 1].type !== 'ReturnStatement')) {
|
|
1703
|
+
node.body.body.push({
|
|
1704
|
+
type: 'ReturnStatement'
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
fnBody.body = {
|
|
1708
|
+
type: 'BlockStatement',
|
|
1709
|
+
body: node.body.body.map(function (sub) {
|
|
1710
|
+
return mapReturns(sub, thisPath);
|
|
1711
|
+
})
|
|
1712
|
+
};
|
|
1713
|
+
} else {
|
|
1714
|
+
fnBody.body = {
|
|
1715
|
+
type: 'BlockStatement',
|
|
1716
|
+
body: [mapReturns({
|
|
1717
|
+
type: 'ReturnStatement',
|
|
1718
|
+
argument: node.body
|
|
1719
|
+
}, thisPath)]
|
|
1720
|
+
};
|
|
1721
|
+
node.expression = false;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
fnBody = bindAsync(fnBody,(opts.promises || opts.generators || opts.engine) ? null : literal(opts.lazyThenables?0:true)) ;
|
|
1725
|
+
|
|
1726
|
+
if (opts.promises) {
|
|
1727
|
+
fnBody = {
|
|
1728
|
+
type: 'NewExpression',
|
|
1729
|
+
callee: ident('Promise'),
|
|
1730
|
+
arguments: [fnBody]
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
fnBody = {
|
|
1734
|
+
type: 'BlockStatement',
|
|
1735
|
+
body: [{
|
|
1736
|
+
type: 'ReturnStatement',
|
|
1737
|
+
loc: node.loc,
|
|
1738
|
+
argument: fnBody
|
|
1739
|
+
}]
|
|
1740
|
+
};
|
|
1741
|
+
if (usesArgs)
|
|
1742
|
+
afterDirectives(fnBody.body,[assign$Args]);
|
|
1743
|
+
node.body = fnBody;
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
});
|
|
1747
|
+
return ast;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
/*
|
|
1751
|
+
* Rewrite
|
|
1752
|
+
async function <name>?<argumentlist><body>
|
|
1753
|
+
to
|
|
1754
|
+
function <name>?<argumentlist>{ return function*() {<body>}.$asyncspawn(); }
|
|
1755
|
+
*/
|
|
1756
|
+
// Like mapReturns, but ONLY for return/throw async
|
|
1757
|
+
function mapAsyncReturns(ast) {
|
|
1758
|
+
if (Array.isArray(ast)) {
|
|
1759
|
+
return ast.map(mapAsyncReturns);
|
|
1760
|
+
}
|
|
1761
|
+
var lambdaNesting = 0;
|
|
1762
|
+
return parser.treeWalker(ast, function (node, descend, path) {
|
|
1763
|
+
if ((node.type === 'ThrowStatement' || node.type === 'ReturnStatement') && !node.$mapped) {
|
|
1764
|
+
if (lambdaNesting > 0) {
|
|
1765
|
+
if (examine(node).isAsync) {
|
|
1766
|
+
delete node.async;
|
|
1767
|
+
node.argument = {
|
|
1768
|
+
"type": "CallExpression",
|
|
1769
|
+
"callee": node.type === 'ThrowStatement' ? genIdent.error : genIdent.return,
|
|
1770
|
+
"arguments": node.argument ? [node.argument] : []
|
|
1771
|
+
};
|
|
1772
|
+
node.type = 'ReturnStatement';
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
} else if (examine(node).isFunction) {
|
|
1777
|
+
lambdaNesting++;
|
|
1778
|
+
descend(node);
|
|
1779
|
+
lambdaNesting--;
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
descend(node);
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
function spawnBody(body, deferExit) {
|
|
1787
|
+
if (opts.noRuntime)
|
|
1788
|
+
throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes") ;
|
|
1789
|
+
|
|
1790
|
+
return parser.part("{ return (function*($return,$error){ $:body }).$asyncspawn(Promise,this) }",{
|
|
1791
|
+
'return':genIdent.return,
|
|
1792
|
+
error:genIdent.error,
|
|
1793
|
+
asyncspawn:genIdent.asyncspawn,
|
|
1794
|
+
body: mapAsyncReturns(body).concat(deferExit ? [{
|
|
1795
|
+
type: 'ReturnStatement',
|
|
1796
|
+
argument: genIdent.return
|
|
1797
|
+
}] : [])
|
|
1798
|
+
}).body[0] ;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
function warnAsyncGetter(id) {
|
|
1802
|
+
if (!id.$asyncgetwarninig) {
|
|
1803
|
+
id.$asyncgetwarninig = true;
|
|
1804
|
+
logger(where(id) + "'async get "+printNode(id)+"(){...}' is non-standard. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
function asyncSpawn(ast,engine) {
|
|
1809
|
+
function mapAwaits(ast,hide) {
|
|
1810
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
1811
|
+
if (node !== ast && examine(node).isFunction)
|
|
1812
|
+
return;
|
|
1813
|
+
if (examine(node).isAwait) {
|
|
1814
|
+
if (hide) {
|
|
1815
|
+
node.$hidden = true;
|
|
1816
|
+
descend();
|
|
1817
|
+
} else {
|
|
1818
|
+
delete node.operator;
|
|
1819
|
+
node.delegate = false;
|
|
1820
|
+
node.type = 'YieldExpression';
|
|
1821
|
+
descend();
|
|
1822
|
+
}
|
|
1823
|
+
} else
|
|
1824
|
+
descend();
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
function promiseTransform(ast) {
|
|
1829
|
+
var promises = opts.promises;
|
|
1830
|
+
opts.promises = true;
|
|
1831
|
+
asyncTransforms(ast, true);
|
|
1832
|
+
opts.promises = promises;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
function expandArrows(fn) {
|
|
1836
|
+
if (fn.body.type !== 'BlockStatement') {
|
|
1837
|
+
fn.body = {
|
|
1838
|
+
type: 'BlockStatement',
|
|
1839
|
+
body: [{
|
|
1840
|
+
type: 'ReturnStatement',
|
|
1841
|
+
argument: fn.body
|
|
1842
|
+
}]
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
return fn;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
function warnAsyncExit(exit, fn) {
|
|
1849
|
+
if (!fn.$asyncexitwarninig) {
|
|
1850
|
+
fn.$asyncexitwarninig = true;
|
|
1851
|
+
logger(where(exit) + "'async " + ({
|
|
1852
|
+
ReturnStatement: 'return',
|
|
1853
|
+
ThrowStatement: 'throw'
|
|
1854
|
+
})[exit.type] + "' not possible in "+(engine?'engine':'generator')+" mode. Using Promises for function at " + where(fn));
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
1859
|
+
descend();
|
|
1860
|
+
var fn, exit, usesArgs;
|
|
1861
|
+
if (examine(node).isAsync && examine(node).isFunction) {
|
|
1862
|
+
var member ;
|
|
1863
|
+
if ((member = getMemberFunction(path[0].parent))
|
|
1864
|
+
&& examine(member).isAsync && path[0].parent.kind === 'get') {
|
|
1865
|
+
warnAsyncGetter(path[0].parent.key) ;
|
|
1866
|
+
}
|
|
1867
|
+
if (exit = containsAsyncExit(node)) {
|
|
1868
|
+
// Do the Promise transform
|
|
1869
|
+
warnAsyncExit(exit, node.body);
|
|
1870
|
+
promiseTransform(node);
|
|
1871
|
+
} else if (!engine) {
|
|
1872
|
+
fn = node;
|
|
1873
|
+
delete fn.async;
|
|
1874
|
+
usesArgs = replaceArguments(fn);
|
|
1875
|
+
mapAwaits(fn,false);
|
|
1876
|
+
fn = expandArrows(fn);
|
|
1877
|
+
fn.body = spawnBody(fn.body.body, exit);
|
|
1878
|
+
if (usesArgs)
|
|
1879
|
+
afterDirectives(fn.body.body,[assign$Args]);
|
|
1880
|
+
if (fn.id && path[0].parent.type === 'ExpressionStatement') {
|
|
1881
|
+
fn.type = 'FunctionDeclaration';
|
|
1882
|
+
path[1].replace(fn);
|
|
1883
|
+
} else {
|
|
1884
|
+
path[0].replace(fn);
|
|
1885
|
+
}
|
|
1886
|
+
} else if (path[0].parent.kind !== 'get')
|
|
1887
|
+
mapAwaits(node,true) ;
|
|
1888
|
+
} else if ((fn = getMemberFunction(node)) && examine(fn).isAsync) {
|
|
1889
|
+
if (exit = containsAsyncExit(fn)) {
|
|
1890
|
+
// Do the Promise transform
|
|
1891
|
+
warnAsyncExit(exit, fn);
|
|
1892
|
+
promiseTransform(node);
|
|
1893
|
+
} else if (!engine || node.kind==='get') {
|
|
1894
|
+
if (engine) {
|
|
1895
|
+
promiseTransform(node) ;
|
|
1896
|
+
} else {
|
|
1897
|
+
node.async = false;
|
|
1898
|
+
usesArgs = replaceArguments(fn);
|
|
1899
|
+
mapAwaits(fn,false);
|
|
1900
|
+
coerce(fn, expandArrows(fn));
|
|
1901
|
+
fn.body = spawnBody(fn.body.body, exit);
|
|
1902
|
+
}
|
|
1903
|
+
if (usesArgs)
|
|
1904
|
+
afterDirectives(fn.body.body,[assign$Args]);
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
});
|
|
1908
|
+
|
|
1909
|
+
// Map (and warn) about any out-of-scope awaits that are being
|
|
1910
|
+
// mapped using Promises.
|
|
1911
|
+
var st = cloneNode(opts);
|
|
1912
|
+
opts.engine = false;
|
|
1913
|
+
opts.generators = false;
|
|
1914
|
+
blockifyArrows(ast);
|
|
1915
|
+
hoistDeclarations(ast);
|
|
1916
|
+
labelTryCatch(ast,st.engine);
|
|
1917
|
+
mapLogicalOp(ast);
|
|
1918
|
+
mapCondOp(ast);
|
|
1919
|
+
walkDown(ast, [mapTryCatch,mapLoops,mapIfStmt,mapSwitch,mapBlock]);
|
|
1920
|
+
asyncAwait(ast, "warn");
|
|
1921
|
+
opts.engine = st.engine;
|
|
1922
|
+
opts.generators = st.generators;
|
|
1923
|
+
return ast;
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
/* Find all nodes within this scope matching the specified function */
|
|
1927
|
+
function scopedNodes(ast, matching, flat) {
|
|
1928
|
+
var matches = [];
|
|
1929
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
1930
|
+
if (node === ast)
|
|
1931
|
+
return descend();
|
|
1932
|
+
if (matching(node, path)) {
|
|
1933
|
+
matches.push([].concat(path));
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
if (flat || examine(node).isScope) {
|
|
1937
|
+
return;
|
|
1938
|
+
}
|
|
1939
|
+
descend();
|
|
1940
|
+
});
|
|
1941
|
+
return matches;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
function extractVars(vars,kind) {
|
|
1945
|
+
var varDecls = [];
|
|
1946
|
+
var duplicates = {} ;
|
|
1947
|
+
vars = vars.filter(function(v){ return v[0].parent.type !== 'ExportNamedDeclaration'}) ;
|
|
1948
|
+
if (vars.length) {
|
|
1949
|
+
var definitions = {};
|
|
1950
|
+
vars.forEach(function (path) {
|
|
1951
|
+
function addName(name) {
|
|
1952
|
+
if (name in definitions) {
|
|
1953
|
+
duplicates[name] = self.declarations[i] ;
|
|
1954
|
+
} else {
|
|
1955
|
+
definitions[name] = self.declarations[i] ;
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
var ref = path[0];
|
|
1960
|
+
var self = ref.self;
|
|
1961
|
+
var kind = self.kind ;
|
|
1962
|
+
var values = [];
|
|
1963
|
+
for (var i = 0;i < self.declarations.length; i++) {
|
|
1964
|
+
var decl = self.declarations[i] ;
|
|
1965
|
+
getDeclNames(decl.id).forEach(addName) ;
|
|
1966
|
+
if (decl.init) {
|
|
1967
|
+
var value = {
|
|
1968
|
+
type: 'AssignmentExpression',
|
|
1969
|
+
left: cloneNode(decl.id),
|
|
1970
|
+
operator: '=',
|
|
1971
|
+
right: cloneNode(decl.init)
|
|
1972
|
+
};
|
|
1973
|
+
values.push(value);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
if (values.length == 0)
|
|
1977
|
+
ref.remove();
|
|
1978
|
+
else {
|
|
1979
|
+
var repl = (values.length > 1)?{type:'SequenceExpression',expressions:values} : values[0] ;
|
|
1980
|
+
if (ref.parent.type.slice(0,3)!=='For')
|
|
1981
|
+
repl = {type:'ExpressionStatement',expression:repl} ;
|
|
1982
|
+
ref.replace(repl);
|
|
1983
|
+
}
|
|
1984
|
+
});
|
|
1985
|
+
|
|
1986
|
+
var defs = Object.keys(definitions) ;
|
|
1987
|
+
if (defs.length) {
|
|
1988
|
+
defs = defs.map(function (name) {
|
|
1989
|
+
return {
|
|
1990
|
+
type: 'VariableDeclarator',
|
|
1991
|
+
id: ident(name),
|
|
1992
|
+
loc: definitions[name].loc,
|
|
1993
|
+
start: definitions[name].start,
|
|
1994
|
+
end: definitions[name].end
|
|
1995
|
+
};
|
|
1996
|
+
});
|
|
1997
|
+
if (!varDecls[0] || varDecls[0].type !== 'VariableDeclaration') {
|
|
1998
|
+
varDecls.unshift({
|
|
1999
|
+
type: 'VariableDeclaration',
|
|
2000
|
+
kind: kind,
|
|
2001
|
+
declarations: defs
|
|
2002
|
+
});
|
|
2003
|
+
} else {
|
|
2004
|
+
varDecls[0].declarations = varDecls[0].declarations.concat(defs);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
return { decls: varDecls, duplicates: duplicates } ;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
function getDeclNames(id) {
|
|
2012
|
+
if (!id) return [] ;
|
|
2013
|
+
if (Array.isArray(id)) {
|
|
2014
|
+
return id.reduce(function(z,j){ return z.concat(getDeclNames(j.id))},[]) ;
|
|
2015
|
+
}
|
|
2016
|
+
switch (id.type) {
|
|
2017
|
+
case 'Identifier':
|
|
2018
|
+
return [id.name] ;
|
|
2019
|
+
case 'AssignmentPattern':
|
|
2020
|
+
return getDeclNames(id.left);
|
|
2021
|
+
case 'ArrayPattern':
|
|
2022
|
+
return id.elements.reduce(function(z,e){ return z.concat(getDeclNames(e)) },[]) ;
|
|
2023
|
+
case 'ObjectPattern':
|
|
2024
|
+
return id.properties.reduce(function(z,e){ return z.concat(getDeclNames(e)) },[]) ;
|
|
2025
|
+
case 'ObjectProperty':
|
|
2026
|
+
case 'Property':
|
|
2027
|
+
return getDeclNames(id.value) ;
|
|
2028
|
+
case 'RestElement':
|
|
2029
|
+
case 'RestProperty':
|
|
2030
|
+
return getDeclNames(id.argument) ;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
function checkConstsNotAssigned(ast) {
|
|
2035
|
+
/* Ensure no consts are on the LHS of an AssignmentExpression */
|
|
2036
|
+
var names = {} ;
|
|
2037
|
+
|
|
2038
|
+
function fail(node){
|
|
2039
|
+
logger(where(node) + "Possible assignment to 'const " + printNode(node)+"'");
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
function checkAssignable(target) {
|
|
2043
|
+
switch (target.type) {
|
|
2044
|
+
case 'Identifier':
|
|
2045
|
+
// Find the declaration of any names on the left
|
|
2046
|
+
if (names[target.name] === 'const') fail(target) ;
|
|
2047
|
+
break ;
|
|
2048
|
+
case 'ArrayPattern':
|
|
2049
|
+
target.elements.forEach(function(e){
|
|
2050
|
+
if (names[e.name] === 'const') fail(e) ;
|
|
2051
|
+
}) ;
|
|
2052
|
+
break ;
|
|
2053
|
+
case 'ObjectPattern':
|
|
2054
|
+
target.properties.forEach(function(p){
|
|
2055
|
+
if (names[p.key.name] === 'const') fail(p) ;
|
|
2056
|
+
}) ;
|
|
2057
|
+
break ;
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2062
|
+
var body = examine(node).isBlockStatement ;
|
|
2063
|
+
if (body) {
|
|
2064
|
+
names = Object.create(names) ;
|
|
2065
|
+
|
|
2066
|
+
for (var h=0; h<body.length; h++) {
|
|
2067
|
+
if (body[h].type === 'VariableDeclaration') {
|
|
2068
|
+
for (var i=0; i<body[h].declarations.length; i++) {
|
|
2069
|
+
getDeclNames(body[h].declarations[i].id).forEach(function(name){
|
|
2070
|
+
names[name] = body[h].kind ;
|
|
2071
|
+
}) ;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
descend() ;
|
|
2077
|
+
|
|
2078
|
+
if (node.type === 'AssignmentExpression')
|
|
2079
|
+
checkAssignable(node.left) ;
|
|
2080
|
+
else if (node.type === 'UpdateExpression')
|
|
2081
|
+
checkAssignable(node.argument) ;
|
|
2082
|
+
if (body)
|
|
2083
|
+
names = Object.getPrototypeOf(names) ;
|
|
2084
|
+
});
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
/* Move directives, vars and named functions to the top of their scope iff. the scope contains an 'await' */
|
|
2088
|
+
function hoistDeclarations(ast) {
|
|
2089
|
+
var sequences = {
|
|
2090
|
+
TemplateLiteral:function(x) { return x.expressions },
|
|
2091
|
+
NewExpression:function(x) { return x.arguments },
|
|
2092
|
+
CallExpression:function(x) { return x.arguments },
|
|
2093
|
+
SequenceExpression:function(x) { return x.expressions },
|
|
2094
|
+
ArrayExpression:function(x) { return x.elements },
|
|
2095
|
+
ObjectExpression:function(oe){ return oe.properties.map(function(p){ return p.value })}
|
|
2096
|
+
};
|
|
2097
|
+
/* Identify SequenceExpressions, Parameter lists and VariableDeclarators that contain assigments and split them up
|
|
2098
|
+
to ensure the correct evaluation order */
|
|
2099
|
+
|
|
2100
|
+
function containsAssign(ast){
|
|
2101
|
+
return contains(ast, function(n){
|
|
2102
|
+
return n.type==='AssignmentExpression'
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2107
|
+
var i ;
|
|
2108
|
+
descend() ;
|
|
2109
|
+
// Ensure assigments are evaluated before any await expressions, eg:
|
|
2110
|
+
// f(a=1, b = await a) --> a=1; f(a,b=await a)
|
|
2111
|
+
|
|
2112
|
+
function moveAssignments(dest){
|
|
2113
|
+
if (assignments.length) {
|
|
2114
|
+
dest.argument = {
|
|
2115
|
+
type:'SequenceExpression',
|
|
2116
|
+
expressions:assignments.map(function(a){
|
|
2117
|
+
var b = cloneNode(a)
|
|
2118
|
+
coerce(a,a.left);
|
|
2119
|
+
return b ;
|
|
2120
|
+
}).concat(dest.argument)
|
|
2121
|
+
} ;
|
|
2122
|
+
assignments = [] ;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
if (node.type in sequences && !node.$hoisted) {
|
|
2128
|
+
var expr = sequences[node.type](node) ;
|
|
2129
|
+
var assignments = [] ;
|
|
2130
|
+
var path ;
|
|
2131
|
+
for (i=0; i<expr.length;i++) {
|
|
2132
|
+
if (examine(expr[i]).isScope)
|
|
2133
|
+
continue ;
|
|
2134
|
+
|
|
2135
|
+
if (path = containsAwait(expr[i]))
|
|
2136
|
+
moveAssignments(path[0].self) ;
|
|
2137
|
+
|
|
2138
|
+
if (!containsAwait(expr.slice(i+1)))
|
|
2139
|
+
break ;
|
|
2140
|
+
|
|
2141
|
+
if (path = containsAssign(expr[i]))
|
|
2142
|
+
assignments.push(path[0].self) ;
|
|
2143
|
+
}
|
|
2144
|
+
} else if (node.type === 'VariableDeclaration') {
|
|
2145
|
+
// If any of the VariableDeclarators contain an initial value and are followed by a VariableDeclarator
|
|
2146
|
+
// containing an await, split them up into multiple statements
|
|
2147
|
+
for (i=node.declarations.length-1; i>0; i--) {
|
|
2148
|
+
if (node.declarations[i] && node.declarations[i].init && containsAwait(node.declarations[i].init)) {
|
|
2149
|
+
var insert = {
|
|
2150
|
+
type:'VariableDeclaration',
|
|
2151
|
+
kind: node.kind,
|
|
2152
|
+
declarations: node.declarations.splice(i)
|
|
2153
|
+
} ;
|
|
2154
|
+
var ref = path[0] ;
|
|
2155
|
+
if ('index' in ref) {
|
|
2156
|
+
ref.parent[ref.field].splice(ref.index+1,0,insert) ;
|
|
2157
|
+
} else throw new Error("VariableDeclaration not in a block") ;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}) ;
|
|
2162
|
+
|
|
2163
|
+
/* Hoist declarations */
|
|
2164
|
+
function isFreeVariable(kinds) {
|
|
2165
|
+
return function(n, path) {
|
|
2166
|
+
if (n.type === 'VariableDeclaration' && (n.kind = n.kind || 'var') && kinds.indexOf(n.kind)>=0) {
|
|
2167
|
+
var p = path[0] ;
|
|
2168
|
+
// Don't hoist the LHS of for (var/let/const _ of/in ... ; ;){}
|
|
2169
|
+
if (p.field == "left" && (p.parent.type === 'ForInStatement' || p.parent.type === 'ForOfStatement'))
|
|
2170
|
+
return false;
|
|
2171
|
+
|
|
2172
|
+
// Don't hoist the LHS of for (let/const _ = ... ; ;){}
|
|
2173
|
+
if (p.field == "init" && p.parent.type === 'ForStatement' && (n.kind==="const" || n.kind==="let"))
|
|
2174
|
+
return false;
|
|
2175
|
+
|
|
2176
|
+
return true;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
function isHoistableFunction(n, path) {
|
|
2182
|
+
// YES: We're a named function, but not a continuation
|
|
2183
|
+
if (n.type==='FunctionDeclaration' && n.id) {
|
|
2184
|
+
return examine(n).isAsync || !n.$continuation;
|
|
2185
|
+
}
|
|
2186
|
+
// No, we're not a hoistable function
|
|
2187
|
+
return false;
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
checkConstsNotAssigned(ast) ;
|
|
2191
|
+
|
|
2192
|
+
var inStrictBody = false ;
|
|
2193
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2194
|
+
var prevScope = inStrictBody ;
|
|
2195
|
+
inStrictBody = inStrictBody || isStrict(node) ;
|
|
2196
|
+
|
|
2197
|
+
if (examine(node).isBlockStatement) {
|
|
2198
|
+
if (containsAwait(node)) {
|
|
2199
|
+
// For this scope/block, find all the hoistable functions, vars and directives
|
|
2200
|
+
var isScope = !path[0].parent || examine(path[0].parent).isScope ;
|
|
2201
|
+
|
|
2202
|
+
/* 'const' is highly problematic. In early version of Chrome (Node 0.10, 4.x, 5.x) non-standard behaviour:
|
|
2203
|
+
*
|
|
2204
|
+
* Node scope multiple-decls
|
|
2205
|
+
* v0.1x function SyntaxError
|
|
2206
|
+
* v0.1x strict SyntaxError SyntaxError
|
|
2207
|
+
* 4/5.x function SyntaxError
|
|
2208
|
+
* 4/5.x strict block ok (SyntaxError on duplicate in block)
|
|
2209
|
+
* 6.x (as 4/5.x strict)
|
|
2210
|
+
*
|
|
2211
|
+
* To make these non-standard behaviours work, we treat a single declaration of a const identifier as requiring function scope (which works everywhere),
|
|
2212
|
+
* declare as a 'var' and initialize inline.
|
|
2213
|
+
* We treat multiple declarations as block-scoped, and let the engine work it out. To make consts blocked-scope, we use 'const' where possible (i.e. before
|
|
2214
|
+
* any await expressions), or declare as 'let' after an await. This breaks in non-strict mode in Node 4/5, as 'let' requires strict mode.
|
|
2215
|
+
*
|
|
2216
|
+
* In summary, what this means is:
|
|
2217
|
+
* - const's with a single declaration in the current scope (NOT block) should be hoisted to function level, and defined as 'var'
|
|
2218
|
+
* - const's with duplicate declarations in the current scope (NOT block) should be hoisted to block level, and defined as 'let'
|
|
2219
|
+
*/
|
|
2220
|
+
|
|
2221
|
+
var directives, consts, vars, lets, functions ;
|
|
2222
|
+
if (isScope) {
|
|
2223
|
+
consts = scopedNodes(node, isFreeVariable(['const']),false);
|
|
2224
|
+
var names = {}, duplicates = {} ;
|
|
2225
|
+
|
|
2226
|
+
// Work out which const identifiers are duplicates
|
|
2227
|
+
// Ones that are only declared once can simply be treated as vars, whereas
|
|
2228
|
+
// identifiers that are declared multiple times have block-scope and are
|
|
2229
|
+
// only valid in node 6 or in strict mode on node 4/5
|
|
2230
|
+
consts.forEach(function(d){
|
|
2231
|
+
d[0].self.declarations.forEach(function(e){
|
|
2232
|
+
getDeclNames(e.id).forEach(function(n){
|
|
2233
|
+
if (names[n] || duplicates[n]) {
|
|
2234
|
+
delete names[n] ;
|
|
2235
|
+
duplicates[n] = e ;
|
|
2236
|
+
} else {
|
|
2237
|
+
names[n] = e ;
|
|
2238
|
+
}
|
|
2239
|
+
}) ;
|
|
2240
|
+
}) ;
|
|
2241
|
+
}) ;
|
|
2242
|
+
|
|
2243
|
+
// Change all the declarations into assignments, since consts are always initialized
|
|
2244
|
+
consts.forEach(function(d){
|
|
2245
|
+
for (var depth=0; depth<d.length; depth++)
|
|
2246
|
+
if (examine(d[depth].parent).isBlockStatement)
|
|
2247
|
+
break ;
|
|
2248
|
+
|
|
2249
|
+
var ref = d[depth] ;
|
|
2250
|
+
ref.append({
|
|
2251
|
+
type: 'ExpressionStatement',
|
|
2252
|
+
expression: {
|
|
2253
|
+
type: 'SequenceExpression',
|
|
2254
|
+
expressions: d[0].self.declarations.map(function (d) {
|
|
2255
|
+
var a = {
|
|
2256
|
+
type: 'AssignmentExpression',
|
|
2257
|
+
operator: '=',
|
|
2258
|
+
left: d.id,
|
|
2259
|
+
right: d.init
|
|
2260
|
+
};
|
|
2261
|
+
d.init = null ;
|
|
2262
|
+
return a ;
|
|
2263
|
+
})
|
|
2264
|
+
}
|
|
2265
|
+
});
|
|
2266
|
+
var ids = getDeclNames(d[0].self.declarations) ;
|
|
2267
|
+
var decls = ids.filter(function(name){ return name in duplicates }) ;
|
|
2268
|
+
if (decls.length) {
|
|
2269
|
+
d[0].append({
|
|
2270
|
+
type:'VariableDeclaration',
|
|
2271
|
+
kind:'let',
|
|
2272
|
+
declarations: decls.map(function(name){
|
|
2273
|
+
return {
|
|
2274
|
+
type:'VariableDeclarator',
|
|
2275
|
+
id:ident(name)
|
|
2276
|
+
}
|
|
2277
|
+
})
|
|
2278
|
+
}) ;
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
d[0].self.kind = 'var' ;
|
|
2282
|
+
decls = ids.filter(function(name){ return name in names }) ;
|
|
2283
|
+
if (decls.length) {
|
|
2284
|
+
d[0].self.declarations = decls.map(function(name){
|
|
2285
|
+
return {
|
|
2286
|
+
type:'VariableDeclarator',
|
|
2287
|
+
id:ident(name)
|
|
2288
|
+
}
|
|
2289
|
+
});
|
|
2290
|
+
} else {
|
|
2291
|
+
ref.remove() ;
|
|
2292
|
+
}
|
|
2293
|
+
}) ;
|
|
2294
|
+
vars = scopedNodes(node, isFreeVariable(['var']),false);
|
|
2295
|
+
lets = [] ;
|
|
2296
|
+
} else {
|
|
2297
|
+
lets = scopedNodes(node, isFreeVariable(['const']),true);
|
|
2298
|
+
}
|
|
2299
|
+
lets = lets.concat(scopedNodes(node, isFreeVariable(['let']),true));
|
|
2300
|
+
directives = scopedNodes(node, function (n) { return examine(n).isDirective },true);
|
|
2301
|
+
functions = scopedNodes(node, isHoistableFunction, inStrictBody);
|
|
2302
|
+
|
|
2303
|
+
vars = vars?extractVars(vars,'var'):{duplicates:{},decls:[]} ;
|
|
2304
|
+
lets = lets?extractVars(lets,'let'):{duplicates:{},decls:[]} ;
|
|
2305
|
+
|
|
2306
|
+
Object.keys(vars.duplicates).forEach(function(id){
|
|
2307
|
+
logger(where(vars.duplicates[id]) + "Duplicate declaration '" + printNode(vars.duplicates[id]) + "'");
|
|
2308
|
+
}) ;
|
|
2309
|
+
Object.keys(lets.duplicates).forEach(function(id){
|
|
2310
|
+
logger(where(lets.duplicates[id]) + "Duplicate declaration '" + printNode(lets.duplicates[id]) + "'");
|
|
2311
|
+
}) ;
|
|
2312
|
+
|
|
2313
|
+
functions = functions.map(function (path) {
|
|
2314
|
+
var ref = path[0], symName;
|
|
2315
|
+
// What is the name of this function (could be async, so check the expression if necessary),
|
|
2316
|
+
// and should we remove and hoist, or reference and hoist?
|
|
2317
|
+
if (examine(ref.self).isAsync) {
|
|
2318
|
+
symName = ref.self.id.name;
|
|
2319
|
+
// If we're actually a top-level async FunctionExpression, redeclare as a FunctionDeclaration
|
|
2320
|
+
if (examine(ref.parent).isBlockStatement) {
|
|
2321
|
+
ref.self.type = 'FunctionDeclaration';
|
|
2322
|
+
ref.remove();
|
|
2323
|
+
return ref.self;
|
|
2324
|
+
}
|
|
2325
|
+
// We're an async FunctionExpression
|
|
2326
|
+
return ref.replace(ident(symName));
|
|
2327
|
+
}
|
|
2328
|
+
// We're just a vanilla FunctionDeclaration or FunctionExpression
|
|
2329
|
+
symName = ref.self.id.name;
|
|
2330
|
+
var movedFn = ref.self.type === 'FunctionDeclaration' ? ref.remove() : ref.replace(ident(symName));
|
|
2331
|
+
return movedFn;
|
|
2332
|
+
});
|
|
2333
|
+
|
|
2334
|
+
directives = directives.map(function (path) {
|
|
2335
|
+
var ref = path[0];
|
|
2336
|
+
return ref.remove();
|
|
2337
|
+
});
|
|
2338
|
+
if (directives.length || vars.decls.length || lets.decls.length || functions.length) {
|
|
2339
|
+
node.body = directives.concat(vars.decls).concat(lets.decls).concat(functions).concat(node.body);
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
inStrictBody = prevScope ;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
// Labeled blocks need to be treated as loops that exit on the first iteration if they contain awaits and labelled breaks
|
|
2346
|
+
if (node.type==='LabeledStatement' && node.body.type==='BlockStatement' && containsAwait(node.body) && contains(node.body,function(m){
|
|
2347
|
+
return m.type === 'BreakStatement' && m.label
|
|
2348
|
+
})) {
|
|
2349
|
+
node.body.body.push({ type: 'BreakStatement' }) ;
|
|
2350
|
+
node.body = {
|
|
2351
|
+
type: 'DoWhileStatement',
|
|
2352
|
+
test: literal(0),
|
|
2353
|
+
body: node.body
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
descend();
|
|
2358
|
+
|
|
2359
|
+
// It makes life easier if labeled loops have the label to hand, so we simply reference them here with a hidden $label
|
|
2360
|
+
// and keep a record of how nested the for loop is (since it's transformed top to bottom and counting during
|
|
2361
|
+
// transformation is therefore not possible
|
|
2362
|
+
if (node.type==='ForOfStatement' || node.type==='ForInStatement' || examine(node).isLoop) {
|
|
2363
|
+
var depth = 0 ;
|
|
2364
|
+
for (var n=0; n<path.length;n++)
|
|
2365
|
+
if (path[n].self.type==='ForOfStatement' || path[n].self.type==='ForInStatement' || examine(path[n].self).isLoop)
|
|
2366
|
+
depth += 1 ;
|
|
2367
|
+
else if (examine(path[n].self).isFunction)
|
|
2368
|
+
break ;
|
|
2369
|
+
|
|
2370
|
+
node.$depth = depth ;
|
|
2371
|
+
if (path[0].parent.type==='LabeledStatement') {
|
|
2372
|
+
node.$label = path[0].parent.label ;
|
|
2373
|
+
} else {
|
|
2374
|
+
node.$label = null ;
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
return true;
|
|
2378
|
+
});
|
|
2379
|
+
return ast;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
function mapSupers(classNode, engine) {
|
|
2383
|
+
function superID() {
|
|
2384
|
+
return classNode.$superID = classNode.$superID || ident("$super$" + generatedSymbol++);
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
return function (method) {
|
|
2388
|
+
method = getMemberFunction(method);
|
|
2389
|
+
if (method && examine(method).isAsync && (!engine || method.kind === 'get' || contains(method,function(n){
|
|
2390
|
+
return (examine(n).isFunction && contains(n,function(n){
|
|
2391
|
+
return n.type==='Super'
|
|
2392
|
+
}) && contains(n,function(n){
|
|
2393
|
+
return n.async && (n.type==='ReturnStatement' || n.type==='ThrowStatement') ;
|
|
2394
|
+
}))
|
|
2395
|
+
},true))) {
|
|
2396
|
+
parser.treeWalker(method.body, function (node, descend, path) {
|
|
2397
|
+
var r;
|
|
2398
|
+
if (!examine(node).isClass) {
|
|
2399
|
+
descend();
|
|
2400
|
+
if (node.type === 'Super') {
|
|
2401
|
+
if (path[0].parent.type === 'MemberExpression') {
|
|
2402
|
+
if (path[1].parent.type === 'CallExpression' && path[1].field === 'callee') {
|
|
2403
|
+
// super[m](...) maps to: this.$superid(m).call(this,...)
|
|
2404
|
+
r = parser.part("this.$super($field).call(this,$args)",{
|
|
2405
|
+
'super':superID(),
|
|
2406
|
+
field:path[0].parent.computed ? path[0].parent.property:literal(path[0].parent.property.name),
|
|
2407
|
+
args:path[1].parent.arguments
|
|
2408
|
+
}).expr ;
|
|
2409
|
+
path[2].replace(r);
|
|
2410
|
+
} else {
|
|
2411
|
+
// super[f], maps to: this.$superid(f)
|
|
2412
|
+
r = parser.part("this.$super($field)",{
|
|
2413
|
+
'super':superID(),
|
|
2414
|
+
field:path[0].parent.computed ?path[0].parent.property : literal(path[0].parent.property.name)
|
|
2415
|
+
}).expr ;
|
|
2416
|
+
path[1].replace(r);
|
|
2417
|
+
}
|
|
2418
|
+
} else {
|
|
2419
|
+
logger(where(node) + "'super' in async methods must be deferenced. 'async constructor()'/'await super()' not valid.");
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
};
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
function fixSuperReferences(ast,engine) {
|
|
2429
|
+
return parser.treeWalker(ast, function (node, descend, path) {
|
|
2430
|
+
descend();
|
|
2431
|
+
if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
2432
|
+
node.body.body.forEach(mapSupers(node,engine));
|
|
2433
|
+
if (node.$superID) {
|
|
2434
|
+
var method = parser.part("(function($field) { return super[$field] })",{ field:ident("$field") }).expr ;
|
|
2435
|
+
if (opts.babelTree) {
|
|
2436
|
+
method.type = 'ClassMethod';
|
|
2437
|
+
method.key = node.$superID;
|
|
2438
|
+
method.kind = 'method';
|
|
2439
|
+
node.body.body.push(method);
|
|
2440
|
+
} else {
|
|
2441
|
+
node.body.body.push({
|
|
2442
|
+
type: 'MethodDefinition',
|
|
2443
|
+
key: node.$superID,
|
|
2444
|
+
kind: 'method',
|
|
2445
|
+
value: method
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
});
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
function blockifyArrows(ast) {
|
|
2454
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2455
|
+
var awaiting = containsAwait(node);
|
|
2456
|
+
if (awaiting) {
|
|
2457
|
+
if (node.type === 'ArrowFunctionExpression' && node.body.type !== 'BlockStatement') {
|
|
2458
|
+
node.body = {
|
|
2459
|
+
type: "BlockStatement",
|
|
2460
|
+
body: [{
|
|
2461
|
+
type: "ReturnStatement",
|
|
2462
|
+
argument: node.body
|
|
2463
|
+
}]
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
descend();
|
|
2468
|
+
return true;
|
|
2469
|
+
});
|
|
2470
|
+
return ast;
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
function exposeCompilerOpts(ast) {
|
|
2474
|
+
// Expose compiler
|
|
2475
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2476
|
+
descend();
|
|
2477
|
+
if (node.type === 'Identifier' && node.name === '__nodent') {
|
|
2478
|
+
coerce(node, literal(opts));
|
|
2479
|
+
}
|
|
2480
|
+
});
|
|
2481
|
+
return ast;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
/* Called with a Program or FunctionDeclaration.body */
|
|
2485
|
+
function isStrict(node) {
|
|
2486
|
+
if (node.type === 'Program' && node.sourceType === 'module')
|
|
2487
|
+
return true ;
|
|
2488
|
+
|
|
2489
|
+
var nodes ;
|
|
2490
|
+
if (node.type === 'Program')
|
|
2491
|
+
nodes = node.body ;
|
|
2492
|
+
else if (examine(node).isFunction)
|
|
2493
|
+
nodes = node.body.body ;
|
|
2494
|
+
else return false ;
|
|
2495
|
+
|
|
2496
|
+
if (nodes) for (var i=0; i<nodes.length; i++)
|
|
2497
|
+
if (examine(nodes[i]).isDirective && nodes[i].expression.value.match(/^\s*use\s+strict\s*$/))
|
|
2498
|
+
return true ;
|
|
2499
|
+
return false ;
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
function containsBlockScopedDeclarations(nodes) {
|
|
2503
|
+
for (var i = 0;i < nodes.length; i++) {
|
|
2504
|
+
var node = nodes[i];
|
|
2505
|
+
if (node.type === 'ClassDeclaration' ||
|
|
2506
|
+
(node.type === 'VariableDeclaration' && (node.kind === 'let' || node.kind === 'const')) ||
|
|
2507
|
+
(node.type === 'FunctionDeclaration' && node.id && node.id.name && !node.$continuation)) {
|
|
2508
|
+
return true;
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
return false;
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
/* Remove un-necessary nested blocks and crunch down empty function implementations */
|
|
2515
|
+
function cleanCode(ast) {
|
|
2516
|
+
// Coalese BlockStatements
|
|
2517
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2518
|
+
descend();
|
|
2519
|
+
if (node.type==='ArrowFunctionExpression'
|
|
2520
|
+
&& node.body.type === 'BlockStatement'
|
|
2521
|
+
&& node.body.body.length===1
|
|
2522
|
+
&& node.body.body[0].type==='ReturnStatement') {
|
|
2523
|
+
node.body = node.body.body[0].argument
|
|
2524
|
+
} else {
|
|
2525
|
+
var block, child;
|
|
2526
|
+
// If this node is a block with vanilla BlockStatements (no controlling entity), merge them
|
|
2527
|
+
if (block = examine(node).isBlockStatement) {
|
|
2528
|
+
// Remove any empty statements from within the block
|
|
2529
|
+
// For ES6, this needs more care, as blocks containing 'let/const/class' have a scope of their own
|
|
2530
|
+
for (var i = 0;i < block.length; i++) {
|
|
2531
|
+
if ((child = examine(block[i]).isBlockStatement) && !containsBlockScopedDeclarations(child)) {
|
|
2532
|
+
if (!containsBlockScopedDeclarations(block[i]))
|
|
2533
|
+
[].splice.apply(block, [i,1].concat(child));
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
});
|
|
2539
|
+
// Truncate BlockStatements with a Jump (break;continue;return;throw) inside
|
|
2540
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2541
|
+
descend();
|
|
2542
|
+
if (examine(node).isJump) {
|
|
2543
|
+
var ref = path[0];
|
|
2544
|
+
if ('index' in ref) {
|
|
2545
|
+
var i = ref.index + 1;
|
|
2546
|
+
var ctn = ref.parent[ref.field];
|
|
2547
|
+
while (i < ctn.length) {
|
|
2548
|
+
// Remove any statements EXCEPT for function/var definitions
|
|
2549
|
+
if (ctn[i].type === 'VariableDeclaration' || examine(ctn[i]).isFunction && ctn[i].id)
|
|
2550
|
+
i += 1;
|
|
2551
|
+
else
|
|
2552
|
+
ctn.splice(i, 1);
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
});
|
|
2557
|
+
/* Inline continuations that are only referenced once */
|
|
2558
|
+
// Find any continuations that have a single reference
|
|
2559
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2560
|
+
descend();
|
|
2561
|
+
if (node.$thisCall && continuations[node.name]) {
|
|
2562
|
+
if (continuations[node.name].ref) {
|
|
2563
|
+
delete continuations[node.name]; // Multiple ref
|
|
2564
|
+
} else {
|
|
2565
|
+
continuations[node.name].ref = node.$thisCall;
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
});
|
|
2569
|
+
var calls = Object.keys(continuations).map(function (c) {
|
|
2570
|
+
return continuations[c].ref;
|
|
2571
|
+
});
|
|
2572
|
+
if (calls.length) {
|
|
2573
|
+
// Replace all the calls to the continuation with the body from the continuation followed by 'return;'
|
|
2574
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2575
|
+
descend();
|
|
2576
|
+
if (calls.indexOf(node) >= 0) {
|
|
2577
|
+
if (path[1].self.type === 'ReturnStatement') {
|
|
2578
|
+
var sym = node.$thisCallName;
|
|
2579
|
+
var repl = cloneNode(continuations[sym].def.body.body);
|
|
2580
|
+
continuations[sym].$inlined = true;
|
|
2581
|
+
if (!examine(path[1].self).isJump)
|
|
2582
|
+
repl.push({
|
|
2583
|
+
type: 'ReturnStatement'
|
|
2584
|
+
});
|
|
2585
|
+
path[1].replace(repl);
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
});
|
|
2589
|
+
var defs = Object.keys(continuations).map(function (c) {
|
|
2590
|
+
return continuations[c].$inlined && continuations[c].def;
|
|
2591
|
+
});
|
|
2592
|
+
// Remove all the (now inline) declarations of the continuations
|
|
2593
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2594
|
+
descend();
|
|
2595
|
+
if (defs.indexOf(node) >= 0) {
|
|
2596
|
+
path[0].remove();
|
|
2597
|
+
}
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
// Hoist generated FunctionDeclarations within ES5 Strict functions (actually put them at the
|
|
2602
|
+
// end of the scope-block, don't hoist them, it's just an expensive operation)
|
|
2603
|
+
var looksLikeES6 = (ast.type==='Program' && ast.sourceType==='module') || contains(ast,function(n){
|
|
2604
|
+
return examine(n).isES6 ;
|
|
2605
|
+
},true) ;
|
|
2606
|
+
|
|
2607
|
+
if (!looksLikeES6) {
|
|
2608
|
+
var useStrict = isStrict(ast) ;
|
|
2609
|
+
(function(ast){
|
|
2610
|
+
parser.treeWalker(ast, function (node, descend, path) {
|
|
2611
|
+
if (node.type==='Program' || node.type==='FunctionDeclaration' || node.type==='FunctionExpression') {
|
|
2612
|
+
var wasStrict = useStrict ;
|
|
2613
|
+
useStrict = useStrict || isStrict(node) ;
|
|
2614
|
+
if (useStrict) {
|
|
2615
|
+
descend();
|
|
2616
|
+
|
|
2617
|
+
var functionScope = node.type === 'Program' ? node : node.body ;
|
|
2618
|
+
var functions = scopedNodes(functionScope,function(n,path){
|
|
2619
|
+
if (n.type==='FunctionDeclaration') {
|
|
2620
|
+
return path[0].parent !== functionScope ;
|
|
2621
|
+
}
|
|
2622
|
+
}) ;
|
|
2623
|
+
|
|
2624
|
+
functions = functions.map(function (path) {
|
|
2625
|
+
return path[0].remove() ;
|
|
2626
|
+
});
|
|
2627
|
+
[].push.apply(functionScope.body,functions) ;
|
|
2628
|
+
} else {
|
|
2629
|
+
descend();
|
|
2630
|
+
}
|
|
2631
|
+
useStrict = wasStrict ;
|
|
2632
|
+
} else {
|
|
2633
|
+
descend();
|
|
2634
|
+
}
|
|
2635
|
+
}) ;
|
|
2636
|
+
})(ast);
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
/*
|
|
2640
|
+
function replaceSymbols(ast,from,to) {
|
|
2641
|
+
parser.treeWalker(ast,function(node,descend,path){
|
|
2642
|
+
descend() ;
|
|
2643
|
+
if (node.type=='Identifier' && node.name==from) {
|
|
2644
|
+
node.name = to ;
|
|
2645
|
+
}
|
|
2646
|
+
}) ;
|
|
2647
|
+
return ast ;
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
// Find declarations of functions of the form:
|
|
2651
|
+
// function [sym]() { return _call_.call(this) }
|
|
2652
|
+
// or
|
|
2653
|
+
// function [sym]() { return _call_() }
|
|
2654
|
+
// and replace with:
|
|
2655
|
+
// _call_
|
|
2656
|
+
// If the [sym] exists and is referenced elsewhere, replace those too. This
|
|
2657
|
+
// needs to be done recursively from the bottom of the tree upwards.
|
|
2658
|
+
// NB: If _call_ is in the parameter list for the function, this is NOT a correct optimization
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
// The symbol folding above might generate lines like:
|
|
2662
|
+
// $return.$asyncbind(this,$error)
|
|
2663
|
+
// these can be simplified to:
|
|
2664
|
+
// $return
|
|
2665
|
+
*/
|
|
2666
|
+
|
|
2667
|
+
// Remove all the 'hiiden' node info generated during transformation
|
|
2668
|
+
parser.treeWalker(ast,function(node,descend,path){
|
|
2669
|
+
descend() ;
|
|
2670
|
+
Object.keys(node).filter(function(k){ return k[0]==='$'}).forEach(function(k){
|
|
2671
|
+
delete node[k] ;
|
|
2672
|
+
}) ;
|
|
2673
|
+
}) ;
|
|
2674
|
+
return ast;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
module.exports = {
|
|
2679
|
+
printNode:printNode,
|
|
2680
|
+
babelLiteralNode: babelLiteralNode,
|
|
2681
|
+
asynchronize: function (pr, __sourceMapping, opts, logger) {
|
|
2682
|
+
try {
|
|
2683
|
+
return asynchronize(pr, __sourceMapping, opts, logger);
|
|
2684
|
+
} catch (ex) {
|
|
2685
|
+
if (ex instanceof SyntaxError) {
|
|
2686
|
+
var l = pr.origCode.substr(ex.pos - ex.loc.column);
|
|
2687
|
+
l = l.split("\n")[0];
|
|
2688
|
+
ex.message += " (nodent)\n" + l + "\n" + l.replace(/[\S ]/g, "-").substring(0, ex.loc.column) + "^";
|
|
2689
|
+
ex.stack = "";
|
|
2690
|
+
}
|
|
2691
|
+
throw ex;
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
};
|