diff --git a/packages/babel-traverse/src/path/family.js b/packages/babel-traverse/src/path/family.js index 533b52722720..19479009e986 100644 --- a/packages/babel-traverse/src/path/family.js +++ b/packages/babel-traverse/src/path/family.js @@ -127,7 +127,7 @@ export function getSibling(key: string): NodePath { container: this.container, listKey: this.listKey, key: key, - }); + }).setContext(this.context); } export function getPrevSibling(): NodePath { diff --git a/packages/babel-traverse/test/family.js b/packages/babel-traverse/test/family.js index 80d2d8955687..ef5fa0fac4d8 100644 --- a/packages/babel-traverse/test/family.js +++ b/packages/babel-traverse/test/family.js @@ -1,5 +1,6 @@ import traverse from "../lib"; import { parse } from "@babel/parser"; +import * as t from "@babel/types"; describe("path/family", function () { describe("getBindingIdentifiers", function () { @@ -81,6 +82,32 @@ describe("path/family", function () { expect(sibling.getAllNextSiblings()).toHaveLength(2); expect(lastSibling.getAllPrevSiblings()).toHaveLength(2); }); + + it("should initialize path.scope when needed", function () { + const ast = parse("if (0) {}"); + + let testHasScope = false; + let consequentHasScope = false; + + traverse(ast, { + IfStatement(path) { + // @babel/traverse pre-traverses the whole tree to populate the initial + // scope. Thus, it pre-caches paths for all the original nodes. + // We need to introduce two new nodes to avoid using the cached paths + // that already have the path.scope property. + path.set("test", t.identifier("a")); + path.set("consequent", t.expressionStatement(t.identifier("b"))); + + const testPath = path.get("test"); + + testHasScope = !!testPath.scope; + consequentHasScope = !!testPath.getSibling("consequent").scope; + }, + }); + + expect(testHasScope).toBe(true); + expect(consequentHasScope).toBe(true); + }); }); });