diff --git a/src/babel/transformation/templates/for-of-array.js b/src/babel/transformation/templates/for-of-array.js new file mode 100644 index 0000000000..7f27900c15 --- /dev/null +++ b/src/babel/transformation/templates/for-of-array.js @@ -0,0 +1 @@ +for (var KEY = 0; KEY < ARR.length; KEY++) BODY; diff --git a/src/babel/transformation/transformers/es6/destructuring.js b/src/babel/transformation/transformers/es6/destructuring.js index ea9e3bdaf3..7fecf07eef 100644 --- a/src/babel/transformation/transformers/es6/destructuring.js +++ b/src/babel/transformation/transformers/es6/destructuring.js @@ -432,7 +432,7 @@ class DestructuringTransformer { } else { arrayRef = this.scope.generateUidBasedOnNode(arrayRef); this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray)); - this.scope.assignTypeGeneric(arrayRef.name, "Array"); + this.getBinding(arrayRef.name).assignTypeGeneric("Array"); } // diff --git a/src/babel/transformation/transformers/es6/for-of.js b/src/babel/transformation/transformers/es6/for-of.js index 9f7b1d9b04..addd609af5 100644 --- a/src/babel/transformation/transformers/es6/for-of.js +++ b/src/babel/transformation/transformers/es6/for-of.js @@ -5,6 +5,12 @@ import * as t from "../../../types"; export var check = t.isForOfStatement; export function ForOfStatement(node, parent, scope, file) { + if (this.get("right").isTypeGeneric("Array")) { + return array(node, scope, file); + } + + // + var callback = spec; if (file.isLoose("es6.forOf")) callback = loose; @@ -36,6 +42,44 @@ export function ForOfStatement(node, parent, scope, file) { } } +var array = function (node, scope, file) { + var nodes = []; + var right = node.right; + + if (!t.isIdentifier(right) || !scope.hasBinding(right.name)) { + var uid = scope.generateUidIdentifier("arr"); + nodes.push(t.variableDeclaration("var", [ + t.variableDeclarator(uid, right) + ])); + right = uid; + } + + var iterationKey = scope.generateUidIdentifier("i"); + + var loop = util.template("for-of-array", { + BODY: node.body, + KEY: iterationKey, + ARR: right + }); + + t.inherits(loop, node); + t.ensureBlock(loop); + + var iterationValue = t.memberExpression(right, iterationKey, true); + + var left = node.left; + if (t.isVariableDeclaration(left)) { + left.declarations[0].init = iterationValue; + loop.body.body.unshift(left); + } else { + loop.body.body.unshift(t.expressionStatement(t.assignmentExpression("=", left, iterationValue))); + } + + nodes.push(loop); + + return nodes; +}; + var loose = function (node, parent, scope, file) { var left = node.left; var declar, id; diff --git a/src/babel/transformation/transformers/es6/parameters.rest.js b/src/babel/transformation/transformers/es6/parameters.rest.js index 14098fa0e3..e79af4418d 100644 --- a/src/babel/transformation/transformers/es6/parameters.rest.js +++ b/src/babel/transformation/transformers/es6/parameters.rest.js @@ -127,16 +127,14 @@ exports.Function = function (node, parent, scope, file) { ); } - scope.assignTypeGeneric(rest.name, "Array"); - var loop = util.template("rest", { ARGUMENTS: argsId, ARRAY_KEY: arrKey, ARRAY_LEN: arrLen, - START: start, - ARRAY: rest, - KEY: key, - LEN: len, + START: start, + ARRAY: rest, + KEY: key, + LEN: len }); loop._blockHoist = node.params.length + 1; node.body.body.unshift(loop); diff --git a/src/babel/transformation/transformers/es6/tail-call.js b/src/babel/transformation/transformers/es6/tail-call.js index e7439cdf5a..563ad8bd00 100644 --- a/src/babel/transformation/transformers/es6/tail-call.js +++ b/src/babel/transformation/transformers/es6/tail-call.js @@ -142,7 +142,7 @@ class TailCallTransformer { hasDeopt() { // check if the ownerId has been reassigned, if it has then it's not safe to // perform optimisations - var ownerIdInfo = this.scope.getBindingInfo(this.ownerId.name); + var ownerIdInfo = this.scope.getBinding(this.ownerId.name); return ownerIdInfo && ownerIdInfo.reassigned; } diff --git a/src/babel/transformation/transformers/index.js b/src/babel/transformation/transformers/index.js index e318ff6902..c1098afeb7 100644 --- a/src/babel/transformation/transformers/index.js +++ b/src/babel/transformation/transformers/index.js @@ -20,7 +20,6 @@ export default { "playground.objectGetterMemoization": require("./playground/object-getter-memoization"), reactCompat: require("./other/react-compat"), - flow: require("./other/flow"), react: require("./other/react"), _modules: require("./internal/modules"), @@ -110,5 +109,6 @@ export default { "utility.inlineExpressions": require("./utility/inline-expressions"), "utility.deadCodeElimination": require("./utility/dead-code-elimination"), + flow: require("./other/flow"), _cleanUp: require("./internal/cleanup") }; diff --git a/src/babel/traversal/binding.js b/src/babel/traversal/binding.js new file mode 100644 index 0000000000..95f45dace7 --- /dev/null +++ b/src/babel/traversal/binding.js @@ -0,0 +1,92 @@ +import * as t from "../types"; + +export default class Binding { + constructor({ identifier, scope, path, kind }) { + this.identifier = identifier; + this.reassigned = false; + this.scope = scope; + this.path = path; + this.kind = kind; + } + + /** + * Description + */ + + setTypeAnnotation() { + var typeInfo = this.path.getTypeAnnotation(); + this.typeAnnotationInferred = typeInfo.inferred; + this.typeAnnotation = typeInfo.annotation; + } + + /** + * Description + */ + + isTypeGeneric(): boolean { + return this.path.isTypeGeneric(...arguments); + } + + /** + * Description + */ + + assignTypeGeneric(type: Object, params?) { + var typeParams = null; + if (params) params = t.typeParameterInstantiation(params); + this.assignType(t.genericTypeAnnotation(t.identifier(type), typeParams)); + } + + /** + * Description + */ + + assignType(type: Object) { + this.typeAnnotation = type; + } + + /** + * Description + */ + + reassign() { + this.reassigned = true; + + if (this.typeAnnotationInferred) { + // destroy the inferred typeAnnotation + this.typeAnnotation = null; + } + } + + /** + * Description + */ + + getValueIfImmutable() { + // can't guarantee this value is the same + if (this.reassigned) return; + + var node = this.path.node; + if (t.isVariableDeclarator(node)) { + if (t.isIdentifier(node.id)) { + node = node.init; + } else { + // otherwise it's probably a destructuring like: + // var { foo } = "foo"; + return; + } + } + + if (t.isImmutable(node)) { + return node; + } + } + + /** + * Description + */ + + isCompatibleWithType(newType): boolean { + return false; + } +} diff --git a/src/babel/traversal/index.js b/src/babel/traversal/index.js index 86c94d9fbe..b2befe1823 100644 --- a/src/babel/traversal/index.js +++ b/src/babel/traversal/index.js @@ -42,7 +42,6 @@ traverse.node = function (node, opts, scope, state, parentPath) { function clearNode(node) { node._declarations = null; node.extendedRange = null; - node._scopeInfo = null; node._paths = null; node.tokens = null; node.range = null; diff --git a/src/babel/traversal/path.js b/src/babel/traversal/path.js index 88bed83108..67f527871b 100644 --- a/src/babel/traversal/path.js +++ b/src/babel/traversal/path.js @@ -1,3 +1,7 @@ +import isBoolean from "lodash/lang/isBoolean"; +import isNumber from "lodash/lang/isNumber"; +import isRegExp from "lodash/lang/isRegExp"; +import isString from "lodash/lang/isString"; import traverse from "./index"; import includes from "lodash/collection/includes"; import Scope from "./scope"; @@ -200,7 +204,104 @@ export default class TraversalPath { } get(key) { - return TraversalPath.get(this, this.context, this.node, this.node, key); + var node = this.node; + var container = node[key]; + if (Array.isArray(container)) { + return container.map((_, i) => { + return TraversalPath.get(this, this.context, node, container, i); + }); + } else { + return TraversalPath.get(this, this.context, node, node, key); + } + } + + has(key) { + return !!this.node[key]; + } + + getTypeAnnotation(): Object { + if (this.typeInfo) { + return this.typeInfo; + } + + var info = this.typeInfo = { + inferred: false, + annotation: null + }; + + var type = this.node.typeAnnotation; + + if (!type) { + info.inferred = true; + type = this.inferType(this); + } + + if (type) { + if (t.isTypeAnnotation(type)) type = type.typeAnnotation; + info.annotation = type; + } + + return info; + } + + resolve(): ?TraversalPath { + if (this.isVariableDeclarator()) { + return this.get("init").resolve(); + } else if (this.isIdentifier()) { + var binding = this.scope.getBinding(this.node.name); + if (!binding) return; + + if (binding.path === this) { + return this; + } else { + return binding.path.resolve();; + } + } else if (this.isMemberExpression()) { + var targetKey = t.toComputedKey(this.node); + if (!t.isLiteral(targetKey)) return; + var targetName = targetKey.value; + + var target = this.get("object").resolve(); + if (!target || !target.isObjectExpression()) return; + + var props = target.get("properties"); + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + if (!prop.isProperty()) continue; + + var key = prop.get("key"); + if (key.isIdentifier({ name: targetName }) || key.isLiteral({ value: targetName })) { + return prop.get("value"); + } + } + } else { + return this; + } + } + + inferType(path: TraversalPath) { + path = path.resolve(); + if (!path) return; + + if (path.isRestElement() || path.isArrayExpression()) { + return t.genericTypeAnnotation(t.identifier("Array")); + } + + if (path.isObjectExpression()) { + return t.genericTypeAnnotation(t.identifier("Object")); + } + + if (path.isLiteral()) { + var value = path.node.value; + if (isString(value)) return t.stringTypeAnnotation(); + if (isNumber(value)) return t.numberTypeAnnotation(); + if (isBoolean(value)) return t.booleanTypeAnnotation(); + } + + if (path.isCallExpression()) { + var callee = path.get("callee").resolve(); + if (callee && callee.isFunction()) return callee.node.returnType; + } } isScope() { @@ -215,13 +316,40 @@ export default class TraversalPath { return t.isReferenced(this.node, this.parent); } + isBlockScoped() { + return t.isBlockScoped(this.node); + } + + isVar() { + return t.isVar(this.node); + } + isScope() { return t.isScope(this.node, this.parent); } + isTypeGeneric(genericName: string, hasTypeParameters?): boolean { + var type = this.getTypeAnnotation().annotation; + if (!type) return false; + + if (!t.isGenericTypeAnnotation(type) || !t.isIdentifier(type.id, { name: genericName })) { + return false; + } + + if (hasTypeParameters && !type.typeParameters) { + return false; + } + + return true; + } + getBindingIdentifiers() { return t.getBindingIdentifiers(this.node); } + + traverse(opts, state) { + traverse(this.node, opts, this.scope, state); + } } for (var i = 0; i < t.TYPES.length; i++) { diff --git a/src/babel/traversal/scope.js b/src/babel/traversal/scope.js index 8aafda19ff..e58da1aabe 100644 --- a/src/babel/traversal/scope.js +++ b/src/babel/traversal/scope.js @@ -2,6 +2,7 @@ import includes from "lodash/collection/includes"; import traverse from "./index"; import defaults from "lodash/object/defaults"; import * as messages from "../messages"; +import Binding from "./binding"; import globals from "globals"; import flatten from "lodash/array/flatten"; import extend from "lodash/object/extend"; @@ -12,27 +13,27 @@ import * as t from "../types"; var functionVariableVisitor = { enter(node, parent, scope, state) { if (t.isFor(node)) { - each(t.FOR_INIT_KEYS, function (key) { - var declar = node[key]; - if (t.isVar(declar)) state.scope.registerBinding("var", declar); + each(t.FOR_INIT_KEYS, (key) => { + var declar = this.get(key); + if (declar.isVar()) state.scope.registerBinding("var", declar); }); } // this block is a function so we'll stop since none of the variables // declared within are accessible - if (t.isFunction(node)) return this.skip(); + if (this.isFunction()) return this.skip(); // function identifier doesn't belong to this scope if (state.blockId && node === state.blockId) return; // delegate block scope handling to the `blockVariableVisitor` - if (t.isBlockScoped(node)) return; + if (this.isBlockScoped()) return; // this will be hit again once we traverse into it after this iteration - if (t.isExportDeclaration(node) && t.isDeclaration(node.declaration)) return; + if (this.isExportDeclaration() && t.isDeclaration(node.declaration)) return; // we've ran into a declaration! - if (t.isDeclaration(node)) state.scope.registerDeclaration(node); + if (this.isDeclaration()) state.scope.registerDeclaration(this); } }; @@ -42,16 +43,20 @@ var programReferenceVisitor = { state.addGlobal(node); } else if (t.isLabeledStatement(node)) { state.addGlobal(node); - } else if (t.isAssignmentExpression(node) || t.isUpdateExpression(node) || (t.isUnaryExpression(node) && node.operator === "delete")) { - scope.registerBindingReassignment(node); + } else if (t.isAssignmentExpression(node)) { + scope.registerBindingReassignment(this.get("left"), this.get("right")); + } else if (t.isUpdateExpression(node)) { + // TODO + } else if (t.isUnaryExpression(node) && node.operator === "delete") { + scope.registerBindingReassignment(this.get("left"), null); } } }; var blockVariableVisitor = { enter(node, parent, scope, state) { - if (t.isFunctionDeclaration(node) || t.isBlockScoped(node)) { - state.registerDeclaration(node); + if (this.isFunctionDeclaration() || this.isBlockScoped()) { + state.registerDeclaration(this); } else if (t.isScope(node, parent)) { this.skip(); } @@ -112,9 +117,7 @@ export default class Scope { */ generateUidIdentifier(name: string) { - var id = t.identifier(this.generateUid(name)); - this.getFunctionParent().registerBinding("uid", id); - return id; + return t.identifier(this.generateUid(name)); } /** @@ -129,7 +132,8 @@ export default class Scope { do { uid = this._generateUid(name, i); i++; - } while (this.hasBinding(uid) || this.hasGlobal(uid)); + } while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasUid(uid)); + this.uids[uid] = true; return uid; } @@ -139,6 +143,19 @@ export default class Scope { return `_${id}`; } + /** + * Description + */ + + hasUid(name): boolean { + var scope = this; + do { + if (scope.uids[name]) return true; + scope = scope.parent; + } while (scope); + return false; + } + /* * Description */ @@ -217,7 +234,7 @@ export default class Scope { rename(oldName: string, newName: string) { newName ||= this.generateUidIdentifier(oldName).name; - var info = this.getBindingInfo(oldName); + var info = this.getBinding(oldName); if (!info) return; var binding = info.identifier; @@ -246,102 +263,6 @@ export default class Scope { binding.name = newName; } - /** - * Description - */ - - inferType(node: Object) { - var target; - - if (t.isVariableDeclarator(node)) { - target = node.init; - } - - if (t.isArrayExpression(target)) { - return t.genericTypeAnnotation(t.identifier("Array")); - } - - if (t.isObjectExpression(target)) { - return; - } - - if (t.isLiteral(target)) { - return; - } - - if (t.isCallExpression(target) && t.isIdentifier(target.callee)) { - var funcInfo = this.getBindingInfo(target.callee.name); - if (funcInfo) { - var funcNode = funcInfo.node; - return !funcInfo.reassigned && t.isFunction(funcNode) && node.returnType; - } - } - - if (t.isIdentifier(target)) { - return; - } - } - - /** - * Description - */ - - isTypeGeneric(name: string, genericName: string) { - var info = this.getBindingInfo(name); - if (!info) return false; - - var type = info.typeAnnotation; - return t.isGenericTypeAnnotation(type) && t.isIdentifier(type.id, { name: genericName }); - } - - /** - * Description - */ - - assignTypeGeneric(name: string, type: Object) { - this.assignType(name, t.genericTypeAnnotation(t.identifier(type))); - } - - /** - * Description - */ - - assignType(name: string, type: Object) { - var info = this.getBindingInfo(name); - if (!info) return; - - info.typeAnnotation = type; - } - - /** - * Description - */ - - getTypeAnnotation(id: Object, node: Object): Object { - var info = { - annotation: null, - inferred: false - }; - - var type; - - if (id.typeAnnotation) { - type = id.typeAnnotation; - } - - if (!type) { - info.inferred = true; - type = this.inferType(node); - } - - if (type) { - if (t.isTypeAnnotation(type)) type = type.typeAnnotation; - info.annotation = type; - } - - return info; - } - /** * Description */ @@ -349,8 +270,9 @@ export default class Scope { toArray(node: Object, i?: number) { var file = this.file; - if (t.isIdentifier(node) && this.isTypeGeneric(node.name, "Array")) { - return node; + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (binding && binding.isTypeGeneric("Array")) return node; } if (t.isArrayExpression(node)) { @@ -376,33 +298,21 @@ export default class Scope { * Description */ - refreshDeclaration(node: Object) { - if (t.isBlockScoped(node)) { - this.getBlockParent().registerDeclaration(node); - } else if (t.isVariableDeclaration(node, { kind: "var" })) { - this.getFunctionParent().registerDeclaration(node); - } else if (node === this.block) { - this.recrawl(); - } - } - - /** - * Description - */ - - registerDeclaration(node: Object) { + registerDeclaration(path: TraversalPath) { + var node = path.node; if (t.isFunctionDeclaration(node)) { - this.registerBinding("hoisted", node); + this.registerBinding("hoisted", path); } else if (t.isVariableDeclaration(node)) { - for (var i = 0; i < node.declarations.length; i++) { - this.registerBinding(node.kind, node.declarations[i]); + var declarations = path.get("declarations"); + for (var i = 0; i < declarations.length; i++) { + this.registerBinding(node.kind, declarations[i]); } } else if (t.isClassDeclaration(node)) { - this.registerBinding("let", node); + this.registerBinding("let", path); } else if (t.isImportDeclaration(node) || t.isExportDeclaration(node)) { - this.registerBinding("module", node); + this.registerBinding("module", path); } else { - this.registerBinding("unknown", node); + this.registerBinding("unknown", path); } } @@ -410,18 +320,16 @@ export default class Scope { * Description */ - registerBindingReassignment(node: Object) { - var ids = t.getBindingIdentifiers(node); + registerBindingReassignment(left: TraversalPath, right: TraversalPath) { + var ids = left.getBindingIdentifiers(); for (var name in ids) { - var info = this.getBindingInfo(name); - if (info) { - info.reassigned = true; - - if (info.typeAnnotationInferred) { - // destroy the inferred typeAnnotation - info.typeAnnotation = null; - } + var binding = this.getBinding(name); + if (!binding) continue; + if (right) { + var rightType = right.typeAnnotation; + if (rightType && binding.isCompatibleWithType(rightType)) continue; } + binding.reassign(); } } @@ -429,27 +337,22 @@ export default class Scope { * Description */ - registerBinding(kind: string, node: Object) { + registerBinding(kind: string, path: TraversalPath) { if (!kind) throw new ReferenceError("no `kind`"); - var ids = t.getBindingIdentifiers(node); + var ids = path.getBindingIdentifiers(); for (var name in ids) { var id = ids[name]; this.checkBlockScopedCollisions(kind, name, id); - var typeInfo = this.getTypeAnnotation(id, node); - - this.bindings[name] = { - typeAnnotationInferred: typeInfo.inferred, - typeAnnotation: typeInfo.annotation, - reassigned: false, - identifier: id, - scope: this, - node: node, - kind: kind - }; + this.bindings[name] = new Binding({ + identifier: id, + scope: this, + path: path, + kind: kind + }); } } @@ -489,91 +392,92 @@ export default class Scope { */ crawl() { - var block = this.block; + var path = this.path; var i; // - var info = this.path.getData("scopeInfo"); + var info = path.getData("scopeInfo"); if (info) { extend(this, info); return; } - info = this.path.setData("scopeInfo", { + info = path.setData("scopeInfo", { bindings: object(), - globals: object() + globals: object(), + uids: object() }); extend(this, info); // ForStatement - left, init - if (t.isLoop(block)) { + if (path.isLoop()) { for (i = 0; i < t.FOR_INIT_KEYS.length; i++) { - var node = block[t.FOR_INIT_KEYS[i]]; - if (t.isBlockScoped(node)) this.registerBinding("let", node); + var node = path.get(t.FOR_INIT_KEYS[i]); + if (node.isBlockScoped()) this.registerBinding("let", node); } - if (t.isBlockStatement(block.body)) { - block = block.body; - } + var body = path.get("body"); + if (body.isBlockStatement()) path = path.get("body"); } // FunctionExpression - id - if (t.isFunctionExpression(block) && block.id) { - if (!t.isProperty(this.parentBlock, { method: true })) { - this.registerBinding("var", block.id); + if (path.isFunctionExpression() && path.has("id")) { + if (!t.isProperty(path.parent, { method: true })) { + this.registerBinding("var", path.get("id")); } } // Class - if (t.isClass(block) && block.id) { - this.registerBinding("var", block.id); + if (path.isClass() && path.has("id")) { + this.registerBinding("var", path.get("id")); } // Function - params, rest - if (t.isFunction(block)) { - for (i = 0; i < block.params.length; i++) { - this.registerBinding("param", block.params[i]); + if (path.isFunction()) { + var params = path.get("params"); + for (i = 0; i < params.length; i++) { + this.registerBinding("param", params[i]); } - this.traverse(block.body, blockVariableVisitor, this); + this.traverse(path.get("body"), blockVariableVisitor, this); } // Program, BlockStatement, Function - let variables - if (t.isBlockStatement(block) || t.isProgram(block)) { - this.traverse(block, blockVariableVisitor, this); + if (path.isBlockStatement() || path.isProgram()) { + this.traverse(path.node, blockVariableVisitor, this); } // CatchClause - param - if (t.isCatchClause(block)) { - this.registerBinding("let", block.param); + if (path.isCatchClause()) { + this.registerBinding("let", path.get("param")); } // ComprehensionExpression - blocks - if (t.isComprehensionExpression(block)) { - this.registerBinding("let", block); + if (path.isComprehensionExpression()) { + this.registerBinding("let", path); } // Program, Function - var variables - if (t.isProgram(block) || t.isFunction(block)) { - this.traverse(block, functionVariableVisitor, { - blockId: block.id, + if (path.isProgram() || path.isFunction()) { + this.traverse(path.node, functionVariableVisitor, { + blockId: path.get("id").node, scope: this }); } // Program - if (t.isProgram(block)) { - this.traverse(block, programReferenceVisitor, this); + if (path.isProgram()) { + this.traverse(path.node, programReferenceVisitor, this); } } @@ -674,7 +578,7 @@ export default class Scope { * Description */ - getBindingInfo(name: string) { + getBinding(name: string) { var scope = this; do { @@ -696,7 +600,7 @@ export default class Scope { */ getBindingIdentifier(name: string) { - var info = this.getBindingInfo(name); + var info = this.getBinding(name); return info && info.identifier; } @@ -722,29 +626,11 @@ export default class Scope { */ getImmutableBindingValue(name: string) { - return this._immutableBindingInfoToValue(this.getBindingInfo(name)); + return this._immutableBindingInfoToValue(this.getBinding(name)); } - _immutableBindingInfoToValue(info) { - if (!info) return; - - // can't guarantee this value is the same - if (info.reassigned) return; - - var node = info.node; - if (t.isVariableDeclarator(node)) { - if (t.isIdentifier(node.id)) { - node = node.init; - } else { - // otherwise it's probably a destructuring like: - // var { foo } = "foo"; - return; - } - } - - if (t.isImmutable(node)) { - return node; - } + _immutableBindingInfoToValue(binding) { + if (binding) return binding.getValueIfImmutable(); } /** @@ -789,7 +675,7 @@ export default class Scope { */ removeBinding(name: string) { - var info = this.getBindingInfo(name); + var info = this.getBinding(name); if (info) info.scope.removeOwnBinding(name); } } diff --git a/src/babel/types/converters.js b/src/babel/types/converters.js index ea3a240ff3..429e9c45dd 100644 --- a/src/babel/types/converters.js +++ b/src/babel/types/converters.js @@ -10,7 +10,7 @@ import * as t from "./index"; * Description */ -export function toComputedKey(node: Object, key: Object = node.key): Object { +export function toComputedKey(node: Object, key: Object = node.key || node.property): Object { if (!node.computed) { if (t.isIdentifier(key)) key = t.literal(key.name); } diff --git a/src/babel/types/index.js b/src/babel/types/index.js index dfbdf9b07e..79293f0694 100644 --- a/src/babel/types/index.js +++ b/src/babel/types/index.js @@ -281,7 +281,6 @@ export function inheritsComments(child: Object, parent: Object): Object { export function inherits(child: Object, parent: Object): Object { child._declarations = parent._declarations; - child._scopeInfo = parent._scopeInfo; child.range = parent.range; child.start = parent.start; child.loc = parent.loc;