From 740064ced79a69ae74523e36e1e6a8956b274dca Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Mon, 20 Jan 2020 03:32:05 +0100 Subject: [PATCH] Fix missing ClassDeclaration references after scope#crawl (#11011) * Bug replication test * Simplify test * Fixes #10896 * Merge path.crawl `ClassDeclaration` and `Declaration` visitors Merged to avoid subtle assumption that `Declaration` is called before `ClassDeclaration` * Move registartion of class id in crawl to BlockScoped * Add some assertions to crawl test --- packages/babel-traverse/src/scope/index.js | 16 +++++++++------- packages/babel-traverse/test/scope.js | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/babel-traverse/src/scope/index.js b/packages/babel-traverse/src/scope/index.js index 9f9d786673..7ba6793be3 100644 --- a/packages/babel-traverse/src/scope/index.js +++ b/packages/babel-traverse/src/scope/index.js @@ -128,15 +128,17 @@ const collectorVisitor = { BlockScoped(path) { let scope = path.scope; if (scope.path === path) scope = scope.parent; - scope.getBlockParent().registerDeclaration(path); - }, - ClassDeclaration(path) { - const id = path.node.id; - if (!id) return; + const parent = scope.getBlockParent(); + parent.registerDeclaration(path); - const name = id.name; - path.scope.bindings[name] = path.scope.getBinding(name); + // Register class identifier in class' scope if this is a class declaration. + if (path.isClassDeclaration() && path.node.id) { + const id = path.node.id; + const name = id.name; + + path.scope.bindings[name] = path.scope.parent.getBinding(name); + } }, Block(path) { diff --git a/packages/babel-traverse/test/scope.js b/packages/babel-traverse/test/scope.js index b796dbf682..d4115b1c9e 100644 --- a/packages/babel-traverse/test/scope.js +++ b/packages/babel-traverse/test/scope.js @@ -289,6 +289,20 @@ describe("scope", () => { column: 32, }); }); + + it("class identifier available in class scope after crawl", function() { + const path = getPath("class a { build() { return new a(); } }"); + + path.scope.crawl(); + + let referencePaths = path.scope.bindings.a.referencePaths; + expect(referencePaths).toHaveLength(1); + + referencePaths = path.get("body[0]").scope.bindings.a.referencePaths; + expect(referencePaths).toHaveLength(1); + + expect(path.scope.bindings.a).toBe(path.get("body[0]").scope.bindings.a); + }); }); describe("duplicate bindings", () => {