diff --git a/src/babel/transformation/file.js b/src/babel/transformation/file.js index 900ffc3106..785f4ab4a4 100644 --- a/src/babel/transformation/file.js +++ b/src/babel/transformation/file.js @@ -1,6 +1,7 @@ import convertSourceMap from "convert-source-map"; import shebangRegex from "shebang-regex"; import isFunction from "lodash/lang/isFunction"; +import TraversalPath from "../traversal/path"; import sourceMap from "source-map"; import transform from "./index"; import generate from "../generation"; @@ -375,7 +376,7 @@ export default class File { this.usedHelpers[name] = true; var generator = this.get("helperGenerator"); - var runtime = this.get("helpersNamespace"); + var runtime = this.get("helpersNamespace"); if (generator) { return generator(name); } else if (runtime) { @@ -425,9 +426,11 @@ export default class File { transform(ast) { this.log.debug(); - this.ast = ast; + this.path = TraversalPath.get(null, null, ast, ast, "program", this); + this.scope = this.path.scope; + this.ast = ast; + this.lastStatements = t.getLastStatements(ast.program); - this.scope = new Scope(ast.program, ast, null, this); var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules); if (modFormatter.init && this.transformers["es6.modules"].canRun()) { @@ -481,14 +484,14 @@ export default class File { if (inputMap) { map.sources[0] = inputMap.file; - var inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap); - var outputMapConsumer = new sourceMap.SourceMapConsumer(map); + var inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap); + var outputMapConsumer = new sourceMap.SourceMapConsumer(map); var outputMapGenerator = sourceMap.SourceMapGenerator.fromSourceMap(outputMapConsumer); outputMapGenerator.applySourceMap(inputMapConsumer); var mergedMap = outputMapGenerator.toJSON(); mergedMap.sources = inputMap.sources - mergedMap.file = inputMap.file; + mergedMap.file = inputMap.file; return mergedMap; } diff --git a/src/babel/transformation/transformers/es6/for-of.js b/src/babel/transformation/transformers/es6/for-of.js index 28f7d98df0..9f7b1d9b04 100644 --- a/src/babel/transformation/transformers/es6/for-of.js +++ b/src/babel/transformation/transformers/es6/for-of.js @@ -29,9 +29,6 @@ export function ForOfStatement(node, parent, scope, file) { t.inherits(loop, node); - // todo: find out why this is necessary? #538 - loop._scopeInfo = node._scopeInfo; - if (build.replaceParent) { this.parentPath.node = build.node; } else { diff --git a/src/babel/traversal/path.js b/src/babel/traversal/path.js index fb5c204050..88bed83108 100644 --- a/src/babel/traversal/path.js +++ b/src/babel/traversal/path.js @@ -10,7 +10,7 @@ export default class TraversalPath { this.data = {}; } - static get(parentPath, context, parent, container, key) { + static get(parentPath: TraversalPath, context?: TraversalContext, parent, container, key, file?: File) { var targetNode = container[key]; var paths = container._paths ||= []; var path; @@ -28,17 +28,17 @@ export default class TraversalPath { paths.push(path); } - path.setContext(parentPath, context, key); + path.setContext(parentPath, context, key, file); return path; } - static getScope(node, parent, scope) { + static getScope(path: TraversalPath, scope: Scope, file?: File) { var ourScope = scope; // we're entering a new scope so let's construct it! - if (t.isScope(node, parent)) { - ourScope = new Scope(node, parent, scope); + if (path.isScope()) { + ourScope = new Scope(path, scope, file); } return ourScope; @@ -60,21 +60,24 @@ export default class TraversalPath { return this.data[key]; } - setScope() { - this.scope = TraversalPath.getScope(this.node, this.parent, this.context.scope); + setScope(file?) { + this.scope = TraversalPath.getScope(this, this.context && this.context.scope, file); } - setContext(parentPath, context, key) { + setContext(parentPath, context, key, file?) { this.shouldSkip = false; this.shouldStop = false; this.parentPath = parentPath || this.parentPath; - this.context = context; - this.state = context.state; - this.opts = context.opts; this.key = key; - this.setScope(); + if (context) { + this.context = context; + this.state = context.state; + this.opts = context.opts; + } + + this.setScope(file); } remove() { @@ -200,6 +203,10 @@ export default class TraversalPath { return TraversalPath.get(this, this.context, this.node, this.node, key); } + isScope() { + return t.isScope(this.node, this.parent); + } + isReferencedIdentifier(opts) { return t.isReferencedIdentifier(this.node, this.parent, opts); } diff --git a/src/babel/traversal/scope.js b/src/babel/traversal/scope.js index 5c006703b8..8aafda19ff 100644 --- a/src/babel/traversal/scope.js +++ b/src/babel/traversal/scope.js @@ -65,12 +65,20 @@ export default class Scope { * within. */ - constructor(block: Object, parentBlock: Object, parent?: Scope, file?: File) { + constructor(path: TraversalPath, parent?: Scope, file?: File) { + var cached = path.getData("scope"); + if (cached) { + return cached; + } else { + path.setData("scope", this); + } + this.parent = parent; this.file = parent ? parent.file : file; - this.parentBlock = parentBlock; - this.block = block; + this.parentBlock = path.parent; + this.block = path.node; + this.path = path; this.crawl(); } @@ -472,7 +480,7 @@ export default class Scope { */ recrawl() { - this.block._scopeInfo = null; + this.path.setData("scopeInfo", null); this.crawl(); } @@ -481,21 +489,21 @@ export default class Scope { */ crawl() { - var block = this.block; + var block = this.block; var i; // - var info = block._scopeInfo; + var info = this.path.getData("scopeInfo"); if (info) { extend(this, info); return; } - info = block._scopeInfo = { + info = this.path.setData("scopeInfo", { bindings: object(), globals: object() - }; + }); extend(this, info);