From 7d2a14b8561ba115c635478af4f088c7c0bda1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 23 Nov 2020 16:03:11 +0100 Subject: [PATCH] Initialize NodePath context when using `getSibling` (#12387) --- packages/babel-traverse/src/path/family.js | 2 +- packages/babel-traverse/test/family.js | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) 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); + }); }); });