From 75808a2d14a5872472eb12ee5135faca4950d57a Mon Sep 17 00:00:00 2001 From: Sarup Banskota Date: Thu, 3 Aug 2017 04:30:33 +0700 Subject: [PATCH] Prevent getFunctionParent from returning Program (#5923) --- lib/types.js | 2 +- .../src/index.js | 4 ++-- packages/babel-traverse/src/path/ancestry.js | 5 +++-- .../babel-traverse/src/path/introspection.js | 6 ++++-- packages/babel-traverse/src/scope/index.js | 17 ++++++++++------- packages/babel-types/src/definitions/core.js | 2 +- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/lib/types.js b/lib/types.js index be6adefb71..fccd1a8405 100644 --- a/lib/types.js +++ b/lib/types.js @@ -1242,7 +1242,7 @@ type BabelNodeExpressionWrapper = BabelNodeExpressionStatement | BabelNodeTypeCa type BabelNodeFor = BabelNodeForInStatement | BabelNodeForStatement | BabelNodeForOfStatement; type BabelNodeForXStatement = BabelNodeForInStatement | BabelNodeForOfStatement; type BabelNodeFunction = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeObjectMethod | BabelNodeArrowFunctionExpression | BabelNodeClassMethod; -type BabelNodeFunctionParent = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeProgram | BabelNodeObjectMethod | BabelNodeArrowFunctionExpression | BabelNodeClassMethod; +type BabelNodeFunctionParent = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeObjectMethod | BabelNodeArrowFunctionExpression | BabelNodeClassMethod; type BabelNodePureish = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeStringLiteral | BabelNodeNumericLiteral | BabelNodeNullLiteral | BabelNodeBooleanLiteral | BabelNodeArrowFunctionExpression | BabelNodeClassDeclaration | BabelNodeClassExpression; type BabelNodeDeclaration = BabelNodeFunctionDeclaration | BabelNodeVariableDeclaration | BabelNodeClassDeclaration | BabelNodeExportAllDeclaration | BabelNodeExportDefaultDeclaration | BabelNodeExportNamedDeclaration | BabelNodeImportDeclaration | BabelNodeDeclareClass | BabelNodeDeclareFunction | BabelNodeDeclareInterface | BabelNodeDeclareModule | BabelNodeDeclareModuleExports | BabelNodeDeclareTypeAlias | BabelNodeDeclareOpaqueType | BabelNodeDeclareVariable | BabelNodeDeclareExportDeclaration | BabelNodeDeclareExportAllDeclaration | BabelNodeInterfaceDeclaration | BabelNodeTypeAlias | BabelNodeOpaqueType | BabelNodeTSDeclareFunction | BabelNodeTSInterfaceDeclaration | BabelNodeTSTypeAliasDeclaration | BabelNodeTSEnumDeclaration | BabelNodeTSModuleDeclaration; type BabelNodePatternLike = BabelNodeIdentifier | BabelNodeRestElement | BabelNodeAssignmentPattern | BabelNodeArrayPattern | BabelNodeObjectPattern; diff --git a/packages/babel-plugin-transform-es2015-block-scoping/src/index.js b/packages/babel-plugin-transform-es2015-block-scoping/src/index.js index a5a1d45cd4..f9e27de7b6 100644 --- a/packages/babel-plugin-transform-es2015-block-scoping/src/index.js +++ b/packages/babel-plugin-transform-es2015-block-scoping/src/index.js @@ -123,7 +123,7 @@ function convertBlockScopedToVar( // Move bindings from current block scope to function scope. if (moveBindingsToParent) { - const parentScope = scope.getFunctionParent(); + const parentScope = scope.getFunctionParent() || scope.getProgramParent(); const ids = path.getBindingIdentifiers(); for (const name in ids) { const binding = scope.getOwnBinding(name); @@ -371,7 +371,7 @@ class BlockScoping { updateScopeInfo(wrappedInClosure) { const scope = this.scope; - const parentScope = scope.getFunctionParent(); + const parentScope = scope.getFunctionParent() || scope.getProgramParent(); const letRefs = this.letReferences; for (const key in letRefs) { diff --git a/packages/babel-traverse/src/path/ancestry.js b/packages/babel-traverse/src/path/ancestry.js index 7968fb645b..360a4d1f4b 100644 --- a/packages/babel-traverse/src/path/ancestry.js +++ b/packages/babel-traverse/src/path/ancestry.js @@ -17,7 +17,8 @@ export function findParent(callback): ?NodePath { } /** - * Description + * Starting at current `NodePath` and going up the tree, return the first + * `NodePath` that causes the provided `callback` to return a truthy value. */ export function find(callback): ?NodePath { @@ -33,7 +34,7 @@ export function find(callback): ?NodePath { */ export function getFunctionParent(): ?NodePath { - return this.findParent(path => path.isFunction() || path.isProgram()); + return this.findParent(p => p.isFunction()); } /** diff --git a/packages/babel-traverse/src/path/introspection.js b/packages/babel-traverse/src/path/introspection.js index 586d039b8c..1888a6e2af 100644 --- a/packages/babel-traverse/src/path/introspection.js +++ b/packages/babel-traverse/src/path/introspection.js @@ -215,8 +215,10 @@ export function willIMaybeExecuteBefore(target) { export function _guessExecutionStatusRelativeTo(target) { // check if the two paths are in different functions, we can't track execution of these - const targetFuncParent = target.scope.getFunctionParent(); - const selfFuncParent = this.scope.getFunctionParent(); + const targetFuncParent = + target.scope.getFunctionParent() || target.scope.getProgramParent(); + const selfFuncParent = + this.scope.getFunctionParent() || target.scope.getProgramParent(); // here we check the `node` equality as sometimes we may have different paths for the // same node due to path thrashing diff --git a/packages/babel-traverse/src/scope/index.js b/packages/babel-traverse/src/scope/index.js index fd5089caef..356b063980 100644 --- a/packages/babel-traverse/src/scope/index.js +++ b/packages/babel-traverse/src/scope/index.js @@ -72,7 +72,9 @@ const collectorVisitor = { for (const key of (t.FOR_INIT_KEYS: Array)) { const declar = path.get(key); if (declar.isVar()) { - path.scope.getFunctionParent().registerBinding("var", declar); + const parentScope = + path.scope.getFunctionParent() || path.scope.getProgramParent(); + parentScope.registerBinding("var", declar); } } }, @@ -90,7 +92,9 @@ const collectorVisitor = { //if (path.isFlow()) return; // we've ran into a declaration! - path.scope.getFunctionParent().registerDeclaration(path); + const parent = + path.scope.getFunctionParent() || path.scope.getProgramParent(); + parent.registerDeclaration(path); }, ReferencedIdentifier(path, state) { @@ -786,7 +790,7 @@ export default class Scope { } if (path.isSwitchStatement()) { - path = this.getFunctionParent().path; + path = (this.getFunctionParent() || this.getProgramParent()).path; } if (path.isLoop() || path.isCatchClause() || path.isFunction()) { @@ -825,12 +829,11 @@ export default class Scope { return scope; } } while ((scope = scope.parent)); - throw new Error("We couldn't find a Function or Program..."); + throw new Error("Couldn't find a Program"); } /** - * Walk up the scope tree until we hit either a Function or reach the - * very top and hit Program. + * Walk up the scope tree until we hit either a Function or return null. */ getFunctionParent() { @@ -840,7 +843,7 @@ export default class Scope { return scope; } } while ((scope = scope.parent)); - throw new Error("We couldn't find a Function or Program..."); + return null; } /** diff --git a/packages/babel-types/src/definitions/core.js b/packages/babel-types/src/definitions/core.js index 531eb3af6f..93157cc7ed 100644 --- a/packages/babel-types/src/definitions/core.js +++ b/packages/babel-types/src/definitions/core.js @@ -532,7 +532,7 @@ defineType("Program", { ), }, }, - aliases: ["Scopable", "BlockParent", "Block", "FunctionParent"], + aliases: ["Scopable", "BlockParent", "Block"], }); defineType("ObjectExpression", {