Skip to content

Commit

Permalink
fix cloneNode with comments
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed May 14, 2022
1 parent 1d2e7e9 commit ea5bdbf
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
22 changes: 19 additions & 3 deletions packages/babel-types/src/clone/cloneNode.ts
Expand Up @@ -3,6 +3,7 @@ import type * as t from "..";
import { isFile, isIdentifier } from "../validators/generated";

const has = Function.call.bind(Object.prototype.hasOwnProperty);
const commentsCache: Map<any, any> = new Map();

// This function will never be called for comments, only for real nodes.
function cloneIfNode(obj, deep, withoutLoc) {
Expand Down Expand Up @@ -32,6 +33,9 @@ export default function cloneNode<T extends t.Node>(
): T {
if (!node) return node;

const isTop = !commentsCache.get("inCloning");
if (isTop) commentsCache.set("inCloning", true);

const { type } = node;
const newNode: any = { type: node.type };

Expand All @@ -49,6 +53,7 @@ export default function cloneNode<T extends t.Node>(
: node.typeAnnotation;
}
} else if (!has(NODE_FIELDS, type)) {
if (isTop) commentsCache.clear();
throw new Error(`Unknown node type: "${type}"`);
} else {
for (const field of Object.keys(NODE_FIELDS[type])) {
Expand Down Expand Up @@ -99,6 +104,8 @@ export default function cloneNode<T extends t.Node>(
};
}

if (isTop) commentsCache.clear();

return newNode;
}

Expand All @@ -110,10 +117,19 @@ function maybeCloneComments<T extends t.Comment>(
if (!comments || !deep) {
return comments;
}
return comments.map(({ type, value, loc }) => {
return comments.map(comment => {
const cache = commentsCache.get(comment);
if (cache) return cache;

const { type, value, loc } = comment;

const ret = { type, value, loc } as T;
if (withoutLoc) {
return { type, value, loc: null } as T;
ret.loc = null;
}
return { type, value, loc } as T;

commentsCache.set(comment, ret);

return ret;
});
}
21 changes: 21 additions & 0 deletions packages/babel-types/test/cloning.js
@@ -1,5 +1,6 @@
import * as t from "../lib/index.js";
import { parse } from "@babel/parser";
import { CodeGenerator } from "@babel/generator";

describe("cloneNode", function () {
it("should handle undefined", function () {
Expand Down Expand Up @@ -151,4 +152,24 @@ describe("cloneNode", function () {
expect(cloned.declarations[0].id.innerComments[0].loc).toBe(null);
expect(cloned.declarations[0].id.trailingComments[0].loc).toBe(null);
});

it("should same code after deep cloning", function () {
let code = `//test1
/*test2*/var/*test3*/ a = 1/*test4*/;//test5
//test6
var b;
`;
code = new CodeGenerator(parse(code), { retainLines: true }).generate()
.code;

const ast = t.cloneNode(
parse(code),
/* deep */ true,
/* withoutLoc */ false,
);
const newCode = new CodeGenerator(ast, { retainLines: true }).generate()
.code;

expect(code).toBe(newCode);
});
});

0 comments on commit ea5bdbf

Please sign in to comment.