Skip to content

Commit

Permalink
fix: Props are lost when the template replaces the node (#15286)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu authored Jul 25, 2024
1 parent dcfa42b commit b540ab3
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 3 deletions.
22 changes: 19 additions & 3 deletions packages/babel-template/src/populate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,26 @@ function applyReplacement(
}
}

function set(parent: any, key: any, value: any) {
const node = parent[key] as t.Node;
parent[key] = value;
if (node.type === "Identifier") {
if (node.typeAnnotation) {
value.typeAnnotation = node.typeAnnotation;
}
if (node.optional) {
value.optional = node.optional;
}
if (node.decorators) {
value.decorators = node.decorators;
}
}
}

if (index === undefined) {
validate(parent, key, replacement);

(parent as any)[key] = replacement;
set(parent, key, replacement);
} else {
const items: Array<t.Node> = (parent as any)[key].slice();

Expand All @@ -134,10 +150,10 @@ function applyReplacement(
} else if (Array.isArray(replacement)) {
items.splice(index, 1, ...replacement);
} else {
items[index] = replacement;
set(items, index, replacement);
}
} else {
items[index] = replacement;
set(items, index, replacement);
}

validate(parent, key, items);
Expand Down
48 changes: 48 additions & 0 deletions packages/babel-template/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,5 +473,53 @@ describe("@babel/template", function () {
});
expect(generator(output).code).toMatchInlineSnapshot(`"let x = 7;"`);
});

it("should keep node props", () => {
const outputs = [
template({ plugins: ["typescript"] }).ast`
const ${t.identifier("greeting")}: string = 'Hello';
`,
template({ plugins: ["typescript"] }).ast`
var ${t.objectPattern([])}: string = x;
`,
template({ plugins: ["decorators-legacy"] }).ast`
class X {
f(@dec ${t.identifier("x")}) {}
}
`,
template({ plugins: ["typescript"] }).ast`
function f(${t.identifier("x")}?) {}
`,
template({ plugins: ["typescript"] }).ast`
function f(${Object.assign(t.identifier("x"), { optional: true })}: string) {}
`,
template({ plugins: ["decorators-legacy"] }).ast`
class X {
f(@dec ${Object.assign(t.identifier("x"), { optional: true })}) {}
}
`,
template({ plugins: ["typescript"] }).ast`
function f(${Object.assign(t.identifier("x"), { typeAnnotation: t.tsTypeAnnotation(t.tsStringKeyword()) })}: number) {}
`,
];

expect(outputs.map(ast => generator(ast).code)).toMatchInlineSnapshot(`
Array [
"const greeting: string = 'Hello';",
"var {}: string = x;",
"class X {
f(@dec
x) {}
}",
"function f(x?) {}",
"function f(x?: string) {}",
"class X {
f(@dec
x?) {}
}",
"function f(x: number) {}",
]
`);
});
});
});
6 changes: 6 additions & 0 deletions packages/babel-types/src/clone/cloneNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ function cloneNodeInternal<T extends t.Node>(
)
: node.typeAnnotation;
}

if (hasOwn(node, "decorators")) {
newNode.decorators = deep
? cloneIfNodeOrArray(node.decorators, true, withoutLoc, commentsCache)
: node.decorators;
}
} else if (!hasOwn(NODE_FIELDS, type)) {
throw new Error(`Unknown node type: "${type}"`);
} else {
Expand Down

0 comments on commit b540ab3

Please sign in to comment.