diff --git a/src/babel/transformation/file/index.js b/src/babel/transformation/file/index.js index 70ea6726e9..d3ec64c601 100644 --- a/src/babel/transformation/file/index.js +++ b/src/babel/transformation/file/index.js @@ -38,7 +38,6 @@ export default class File { this.usedHelpers = {}; this.dynamicData = {}; this.data = {}; - this.uids = {}; this.pipeline = pipeline; this.log = new Logger(this, opts.filename || "unknown"); diff --git a/src/babel/traversal/scope.js b/src/babel/traversal/scope.js index 0facdf60ea..fe91f03e5d 100644 --- a/src/babel/traversal/scope.js +++ b/src/babel/traversal/scope.js @@ -48,6 +48,12 @@ var programReferenceVisitor = explode({ } }, + Scopable(node, parent, scope, state) { + for (var name in scope.bindings) { + state.references[name] = true; + } + }, + ExportDeclaration(node, parent, scope, state) { var declar = node.declaration; if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) { @@ -182,8 +188,13 @@ export default class Scope { do { uid = this._generateUid(name, i); i++; - } while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasUid(uid)); - this.file.uids[uid] = true; + } while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid)); + + + var program = this.getProgramParent(); + program.references[uid] = true; + program.uids[uid] = true; + return uid; } @@ -193,19 +204,6 @@ export default class Scope { return `_${id}`; } - /** - * Description - */ - - hasUid(name): boolean { - var scope = this; - do { - if (scope.file.uids[name]) return true; - scope = scope.parent; - } while (scope); - return false; - } - /* * Description */ @@ -453,6 +451,20 @@ export default class Scope { this.globals[node.name] = node; } + /** + * Description + */ + + hasUid(name): boolean { + var scope = this; + + do { + if (scope.uids[name]) return true; + } while (scope = scope.parent); + + return false; + } + /** * Description */ @@ -467,6 +479,20 @@ export default class Scope { return false; } + /** + * Description + */ + + hasReference(name: string): boolean { + var scope = this; + + do { + if (scope.references[name]) return true; + } while (scope = scope.parent); + + return false; + } + /** * Description */ @@ -502,8 +528,10 @@ export default class Scope { if (info) return extend(this, info); info = this.block._scopeInfo = { - bindings: object(), - globals: object() + references: object(), + bindings: object(), + globals: object(), + uids: object(), }; extend(this, info); @@ -611,6 +639,18 @@ export default class Scope { declar.declarations.push(t.variableDeclarator(opts.id, opts.init)); } + /** + * Walk up to the top of the scope tree and get the `Program`. + */ + + getProgramParent() { + var scope = this; + while (scope.parent) { + scope = scope.parent; + } + return scope; + } + /** * Walk up the scope tree until we hit either a Function or reach the * very top and hit Program. @@ -737,7 +777,7 @@ export default class Scope { if (!name) return false; if (this.hasOwnBinding(name)) return true; if (this.parentHasBinding(name)) return true; - if (this.file.uids[name]) return true; + if (this.hasUid(name)) return true; if (includes(Scope.globals, name)) return true; if (includes(Scope.contextVariables, name)) return true; return false;