diff --git a/lib/6to5/file.js b/lib/6to5/file.js index d4a0e6ef50..968796b731 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -262,7 +262,7 @@ File.prototype.transform = function (ast) { var self = this; this.ast = ast; - this.scope = new Scope(ast.program); + this.scope = new Scope(ast.program, null, this); this.moduleFormatter = this.getModuleFormatter(this.opts.modules); var astRun = function (key) { diff --git a/lib/6to5/transformation/helpers/remap-async-to-generator.js b/lib/6to5/transformation/helpers/remap-async-to-generator.js index 447ac18b76..d8473a6697 100644 --- a/lib/6to5/transformation/helpers/remap-async-to-generator.js +++ b/lib/6to5/transformation/helpers/remap-async-to-generator.js @@ -13,11 +13,11 @@ var traverser = { } }; -module.exports = function (node, callId) { +module.exports = function (node, callId, scope) { node.async = false; node.generator = true; - traverse(node, traverser); + traverse(node, traverser, scope); var call = t.callExpression(callId, [node]); diff --git a/lib/6to5/transformation/helpers/replace-supers.js b/lib/6to5/transformation/helpers/replace-supers.js index 738cb6346a..addeb1261c 100644 --- a/lib/6to5/transformation/helpers/replace-supers.js +++ b/lib/6to5/transformation/helpers/replace-supers.js @@ -12,15 +12,17 @@ var t = require("../../types"); * @param {Object} className * @param {Object} superName * @param {Boolean} isLoose + * @param {Scope} scope * @param {File} file */ -function ReplaceSupers(methodNode, className, superName, isLoose, file) { +function ReplaceSupers(methodNode, className, superName, isLoose, scope, file) { this.topLevelThisReference = null; this.methodNode = methodNode; this.className = className; this.superName = superName; this.isLoose = isLoose; + this.scope = scope; this.file = file; } @@ -140,7 +142,7 @@ var traverser = { ReplaceSupers.prototype.traverseLevel = function (node, topLevel) { var state = { self: this, topLevel: topLevel }; - traverse(node, traverser, null, state); + traverse(node, traverser, this.scope, state); }; /** diff --git a/lib/6to5/transformation/modules/_default.js b/lib/6to5/transformation/modules/_default.js index 52ecda7cf8..079c020798 100644 --- a/lib/6to5/transformation/modules/_default.js +++ b/lib/6to5/transformation/modules/_default.js @@ -29,7 +29,7 @@ var exportsTraverser = { DefaultFormatter.prototype.getLocalExports = function () { var localExports = {}; - traverse(this.file.ast, exportsTraverser, null, localExports); + traverse(this.file.ast, exportsTraverser, this.file.scope, localExports); return localExports; }; @@ -43,7 +43,7 @@ var importsTraverser = { DefaultFormatter.prototype.getLocalImports = function () { var localImports = {}; - traverse(this.file.ast, importsTraverser, null, localImports); + traverse(this.file.ast, importsTraverser, this.file.scope, localImports); return localImports; }; @@ -140,7 +140,7 @@ var remapTraverser = { DefaultFormatter.prototype.remapAssignments = function () { var state = { self: this }; - traverse(this.file.ast, remapTraverser, null, state); + traverse(this.file.ast, remapTraverser, this.file.scope, state); }; DefaultFormatter.prototype.getModuleName = function () { diff --git a/lib/6to5/transformation/modules/common.js b/lib/6to5/transformation/modules/common.js index 00c4c84567..e1ee82fb84 100644 --- a/lib/6to5/transformation/modules/common.js +++ b/lib/6to5/transformation/modules/common.js @@ -18,7 +18,7 @@ function CommonJSFormatter(file) { DefaultFormatter.apply(this, arguments); var state = { hasNonDefaultExports: false }; - traverse(file.ast, traverser, null, state); + traverse(file.ast, traverser, file.scope, state); this.hasNonDefaultExports = state.hasNonDefaultExports; } diff --git a/lib/6to5/transformation/modules/system.js b/lib/6to5/transformation/modules/system.js index 2f373a7d80..73be1a9444 100644 --- a/lib/6to5/transformation/modules/system.js +++ b/lib/6to5/transformation/modules/system.js @@ -83,6 +83,8 @@ var runnerSettersTraverser = { }; SystemFormatter.prototype.buildRunnerSetters = function (block, hoistDeclarators) { + var scope = this.file.scope; + return t.arrayExpression(_.map(this.ids, function (uid, source) { var state = { source: source, @@ -90,7 +92,7 @@ SystemFormatter.prototype.buildRunnerSetters = function (block, hoistDeclarators hoistDeclarators: hoistDeclarators }; - traverse(block, runnerSettersTraverser, null, state); + traverse(block, runnerSettersTraverser, scope, state); return t.functionExpression(null, [uid], t.blockStatement(state.nodes)); })); @@ -171,7 +173,7 @@ SystemFormatter.prototype.transform = function (ast) { var returnStatement = handlerBody.pop(); // hoist up all variable declarations - traverse(block, hoistVariablesTraverser, null, hoistDeclarators); + traverse(block, hoistVariablesTraverser, this.file.scope, hoistDeclarators); if (hoistDeclarators.length) { var hoistDeclar = t.variableDeclaration("var", hoistDeclarators); @@ -180,7 +182,7 @@ SystemFormatter.prototype.transform = function (ast) { } // hoist up function declarations for circular references - traverse(block, hoistFunctionsTraverser, null, handlerBody); + traverse(block, hoistFunctionsTraverser, this.file.scope, handlerBody); handlerBody.push(returnStatement); diff --git a/lib/6to5/transformation/transformer.js b/lib/6to5/transformation/transformer.js index 63c6288dfd..65ba4792a3 100644 --- a/lib/6to5/transformation/transformer.js +++ b/lib/6to5/transformation/transformer.js @@ -76,7 +76,7 @@ Transformer.prototype.transform = function (file) { this.astRun(file, "before"); var state = { file: file, transformer: this.transformer }; - traverse(file.ast, transformTraverser, null, state); + traverse(file.ast, transformTraverser, file.scope, state); this.astRun(file, "after"); }; diff --git a/lib/6to5/transformation/transformers/_alias-functions.js b/lib/6to5/transformation/transformers/_alias-functions.js index 836bf8f362..74cdd54637 100644 --- a/lib/6to5/transformation/transformers/_alias-functions.js +++ b/lib/6to5/transformation/transformers/_alias-functions.js @@ -37,7 +37,7 @@ var functionTraverser = { } // traverse all child nodes of this function and find `arguments` and `this` - traverse(node, functionChildrenTraverser, null, state); + traverse(node, functionChildrenTraverser, scope, state); return context.skip(); } @@ -58,7 +58,7 @@ var go = function (getBody, node, file, scope) { // traverse the function and find all alias functions so we can alias // `arguments` and `this` if necessary - traverse(node, functionTraverser, null, state); + traverse(node, functionTraverser, scope, state); var body; diff --git a/lib/6to5/transformation/transformers/es6/block-scoping.js b/lib/6to5/transformation/transformers/es6/block-scoping.js index ef0e2c0c7f..694920f7bf 100644 --- a/lib/6to5/transformation/transformers/es6/block-scoping.js +++ b/lib/6to5/transformation/transformers/es6/block-scoping.js @@ -212,7 +212,7 @@ LetScoping.prototype.needsClosure = function () { var call = t.callExpression(fn, params); var ret = this.file.generateUidIdentifier("ret", this.scope); - var hasYield = traverse.hasType(fn.body, "YieldExpression", t.FUNCTION_TYPES); + var hasYield = traverse.hasType(fn.body, this.scope, "YieldExpression", t.FUNCTION_TYPES); if (hasYield) { fn.generator = true; call = t.yieldExpression(call, true); diff --git a/lib/6to5/transformation/transformers/es6/classes.js b/lib/6to5/transformation/transformers/es6/classes.js index 807be19474..dd842f774a 100644 --- a/lib/6to5/transformation/transformers/es6/classes.js +++ b/lib/6to5/transformation/transformers/es6/classes.js @@ -137,7 +137,7 @@ Class.prototype.buildBody = function () { for (var i = 0; i < classBody.length; i++) { var node = classBody[i]; if (t.isMethodDefinition(node)) { - var replaceSupers = new ReplaceSupers(node, this.className, this.superName, this.isLoose, this.file); + var replaceSupers = new ReplaceSupers(node, this.className, this.superName, this.isLoose, this.scope, this.file); replaceSupers.replace(); if (node.key.name === "constructor") { diff --git a/lib/6to5/transformation/transformers/es6/constants.js b/lib/6to5/transformation/transformers/es6/constants.js index 701339c3d4..835f4bb4f0 100644 --- a/lib/6to5/transformation/transformers/es6/constants.js +++ b/lib/6to5/transformation/transformers/es6/constants.js @@ -83,5 +83,5 @@ exports.ForStatement = function (node, parent, scope, context, file) { if (!hasConstants) return; var state = { check: check, getIds: getIds }; - traverse(node, traverser, null, state); + traverse(node, traverser, scope, state); }; diff --git a/lib/6to5/transformation/transformers/es7/comprehensions.js b/lib/6to5/transformation/transformers/es7/comprehensions.js index e57dce69b5..9b9a4d2b9c 100644 --- a/lib/6to5/transformation/transformers/es7/comprehensions.js +++ b/lib/6to5/transformation/transformers/es7/comprehensions.js @@ -36,7 +36,7 @@ var array = function (node, parent, scope, file) { var block = container.callee.body; var body = block.body; - if (traverse.hasType(node, "YieldExpression", t.FUNCTION_TYPES)) { + if (traverse.hasType(node, scope, "YieldExpression", t.FUNCTION_TYPES)) { container.callee.generator = true; container = t.yieldExpression(container, true); } diff --git a/lib/6to5/transformation/transformers/optional/async-to-generator.js b/lib/6to5/transformation/transformers/optional/async-to-generator.js index 017e7b3dd8..790078275a 100644 --- a/lib/6to5/transformation/transformers/optional/async-to-generator.js +++ b/lib/6to5/transformation/transformers/optional/async-to-generator.js @@ -10,5 +10,5 @@ exports.manipulateOptions = bluebirdCoroutines.manipulateOptions; exports.Function = function (node, parent, scope, context, file) { if (!node.async || node.generator) return; - return remapAsyncToGenerator(node, file.addHelper("async-to-generator")); + return remapAsyncToGenerator(node, file.addHelper("async-to-generator"), scope); }; diff --git a/lib/6to5/transformation/transformers/optional/bluebird-coroutines.js b/lib/6to5/transformation/transformers/optional/bluebird-coroutines.js index 2057ce0b7d..3be41cdff6 100644 --- a/lib/6to5/transformation/transformers/optional/bluebird-coroutines.js +++ b/lib/6to5/transformation/transformers/optional/bluebird-coroutines.js @@ -16,6 +16,7 @@ exports.Function = function (node, parent, scope, context, file) { return remapAsyncToGenerator( node, - t.memberExpression(file.addImport("bluebird"), t.identifier("coroutine")) + t.memberExpression(file.addImport("bluebird"), t.identifier("coroutine")), + scope ); }; diff --git a/lib/6to5/transformation/transformers/playground/object-getter-memoization.js b/lib/6to5/transformation/transformers/playground/object-getter-memoization.js index 0287e12795..fa80f94d7a 100644 --- a/lib/6to5/transformation/transformers/playground/object-getter-memoization.js +++ b/lib/6to5/transformation/transformers/playground/object-getter-memoization.js @@ -36,5 +36,5 @@ exports.MethodDefinition = function (node, parent, scope, context, file) { file: file }; - traverse(value, traverser, null, state); + traverse(value, traverser, scope, state); }; diff --git a/lib/6to5/traverse/index.js b/lib/6to5/traverse/index.js index ee412284be..eddc67c249 100644 --- a/lib/6to5/traverse/index.js +++ b/lib/6to5/traverse/index.js @@ -164,6 +164,12 @@ function traverse(parent, opts, scope, state) { // falsy node if (!parent) return; + if (!scope) { + if (parent.type !== "Program" && parent.type !== "File") { + throw new Error("Must pass a scope unless traversing a Program/File got a " + parent.type + " node"); + } + } + if (!opts) opts = {}; if (!opts.enter) opts.enter = _.noop; if (!opts.exit) opts.exit = _.noop; @@ -217,7 +223,7 @@ function hasBlacklistedType(node, parent, scope, context, state) { } } -traverse.hasType = function (tree, type, blacklistTypes) { +traverse.hasType = function (tree, scope, type, blacklistTypes) { // the node we're searching in is blacklisted if (_.contains(blacklistTypes, tree.type)) return false; @@ -232,7 +238,7 @@ traverse.hasType = function (tree, type, blacklistTypes) { traverse(tree, { blacklist: blacklistTypes, enter: hasBlacklistedType - }, null, state); + }, scope, state); return state.has; }; diff --git a/lib/6to5/traverse/scope.js b/lib/6to5/traverse/scope.js index 434f387690..ddf685e412 100644 --- a/lib/6to5/traverse/scope.js +++ b/lib/6to5/traverse/scope.js @@ -14,11 +14,13 @@ var FOR_KEYS = ["left", "init"]; * * @param {Node} block * @param {Scope} [parent] + * @param {File} [file] */ -function Scope(block, parent) { +function Scope(block, parent, file) { this.parent = parent; this.block = block; + this.file = parent ? parent.file : file; var info = this.getInfo(); this.references = info.references; @@ -34,7 +36,7 @@ Scope.defaultDeclarations = _.flatten([ vars.reservedVars ].map(_.keys)); -Scope.add = function (node, references) { +Scope.add = function (node, references, throwOnDuplicate) { if (!node) return; _.defaults(references, t.getIds(node, true)); };