Skip to content

Commit

Permalink
Update pathCache in NodePath#_replaceWith (#12391)
Browse files Browse the repository at this point in the history
* add tests on regression 12386

* fix: update cache on _replaceWith

* fix: pathCache in replaceWithMultiple could be nullish

* Update packages/babel-traverse/src/path/replacement.js

Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>

* test: add replaceWith test to traverse

Co-authored-by: Brian Ng <bng412@gmail.com>
Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
3 people committed Nov 24, 2020
1 parent 8ab668b commit eea3065
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 1 deletion.
@@ -0,0 +1,2 @@
const a = 1;
const b = () => a?.b?.c!.d;
@@ -0,0 +1,3 @@
{
"plugins": ["transform-typescript", "proposal-optional-chaining"]
}
@@ -0,0 +1,7 @@
const a = 1;

const b = () => {
var _a$b;

return a === null || a === void 0 ? void 0 : (_a$b = a.b) === null || _a$b === void 0 ? void 0 : _a$b.c.d;
};
3 changes: 2 additions & 1 deletion packages/babel-traverse/src/path/replacement.js
Expand Up @@ -50,7 +50,7 @@ export function replaceWithMultiple(nodes: Array<Object>) {
nodes = this._verifyNodeList(nodes);
t.inheritLeadingComments(nodes[0], this.node);
t.inheritTrailingComments(nodes[nodes.length - 1], this.node);
pathCache.get(this.parent).delete(this.node);
pathCache.get(this.parent)?.delete(this.node);
this.node = this.container[this.key] = null;
const paths = this.insertAfter(nodes);

Expand Down Expand Up @@ -199,6 +199,7 @@ export function _replaceWith(node) {
}

this.debug(`Replace with ${node?.type}`);
pathCache.get(this.parent)?.set(node, this).delete(this.node);

this.node = this.container[this.key] = node;
}
Expand Down
8 changes: 8 additions & 0 deletions packages/babel-traverse/test/conversion.js
Expand Up @@ -51,6 +51,14 @@ describe("conversion", function () {
expect(generateCode(rootPath)).toBe("() => {\n return false;\n};");
});

it("preserves arrow function body's context", function () {
const rootPath = getPath("() => true").get("expression");
const body = rootPath.get("body");
rootPath.ensureBlock();
body.replaceWithMultiple([t.booleanLiteral(false), t.emptyStatement()]);
expect(generateCode(rootPath)).toBe("() => {\n return false;\n};");
});

it("converts for loop with statement body to block", function () {
const rootPath = getPath("for (;;) true;");
rootPath.ensureBlock();
Expand Down
27 changes: 27 additions & 0 deletions packages/babel-traverse/test/replacement.js
Expand Up @@ -112,6 +112,33 @@ describe("path/replacement", function () {
});
expect(visitCounter).toBe(1);
});

// https://github.com/babel/babel/issues/12386
it("updates pathCache with the replaced node", () => {
const ast = parse(`() => (a?.b)?.c`, {
createParenthesizedExpressions: true,
});
traverse(ast, {
OptionalMemberExpression(path) {
path.node.type = "MemberExpression";
// force `replaceWith` to replace `path.node`
path.replaceWith(path.node.__clone());
path.parentPath.ensureBlock();

const aQuestionDotBNode = path.node.object.expression;
// avoid traversing to a?.b
aQuestionDotBNode.type = "MemberExpression";
},
ParenthesizedExpression(path) {
path.replaceWith(path.node.expression);
},
});
expect(generate(ast).code).toMatchInlineSnapshot(`
"() => {
return a.b.c;
};"
`);
});
});
describe("replaceWithMultiple", () => {
it("does not add extra parentheses for a JSXElement with a JSXElement parent", () => {
Expand Down

0 comments on commit eea3065

Please sign in to comment.