Disallow duplicated AST nodes (#11807)
This commit is contained in:
parent
ffb42488ba
commit
5dd64ecc4a
1
.gitignore
vendored
1
.gitignore
vendored
@ -72,3 +72,4 @@ packages/babel-standalone/babel.min.js
|
||||
/eslint/*/node_modules
|
||||
/eslint/*/LICENSE
|
||||
!/packages/babel-eslint-plugin/LICENSE
|
||||
/.vscode
|
||||
|
||||
@ -457,7 +457,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
|
||||
}
|
||||
|
||||
return makeTrace(
|
||||
state.fileNameIdentifier,
|
||||
t.cloneNode(state.fileNameIdentifier),
|
||||
location.start.line,
|
||||
location.start.column,
|
||||
);
|
||||
|
||||
@ -137,7 +137,7 @@ export function buildDecoratedClass(ref, path, elements, file) {
|
||||
let replacement = template.expression.ast`
|
||||
${addDecorateHelper(file)}(
|
||||
${classDecorators || t.nullLiteral()},
|
||||
function (${initializeId}, ${superClass ? superId : null}) {
|
||||
function (${initializeId}, ${superClass ? t.cloneNode(superId) : null}) {
|
||||
${node}
|
||||
return { F: ${t.cloneNode(node.id)}, d: ${definitions} };
|
||||
},
|
||||
@ -158,7 +158,7 @@ export function buildDecoratedClass(ref, path, elements, file) {
|
||||
}
|
||||
|
||||
return {
|
||||
instanceNodes: [template.statement.ast`${initializeId}(this)`],
|
||||
instanceNodes: [template.statement.ast`${t.cloneNode(initializeId)}(this)`],
|
||||
wrapClass(path) {
|
||||
path.replaceWith(replacement);
|
||||
return path.get(classPathDesc);
|
||||
|
||||
@ -45,8 +45,9 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
|
||||
// In spec mode, only instance fields need a "private name" initializer
|
||||
// because static fields are directly assigned to a variable in the
|
||||
// buildPrivateStaticFieldInitSpec function.
|
||||
const { id, static: isStatic, method: isMethod, getId, setId } = value;
|
||||
const { static: isStatic, method: isMethod, getId, setId } = value;
|
||||
const isAccessor = getId || setId;
|
||||
const id = t.cloneNode(value.id);
|
||||
if (loose) {
|
||||
initNodes.push(
|
||||
template.statement.ast`
|
||||
@ -157,7 +158,7 @@ const privateInVisitor = privateNameVisitorFactory({
|
||||
if (loose) {
|
||||
const { id } = privateNamesMap.get(name);
|
||||
path.replaceWith(template.expression.ast`
|
||||
Object.prototype.hasOwnProperty.call(${right}, ${id})
|
||||
Object.prototype.hasOwnProperty.call(${right}, ${t.cloneNode(id)})
|
||||
`);
|
||||
return;
|
||||
}
|
||||
@ -169,7 +170,7 @@ const privateInVisitor = privateNameVisitorFactory({
|
||||
return;
|
||||
}
|
||||
|
||||
path.replaceWith(template.expression.ast`${id}.has(${right})`);
|
||||
path.replaceWith(template.expression.ast`${t.cloneNode(id)}.has(${right})`);
|
||||
},
|
||||
});
|
||||
|
||||
@ -327,8 +328,8 @@ const privateNameHandlerLoose = {
|
||||
|
||||
return template.expression`BASE(REF, PROP)[PROP]`({
|
||||
BASE: file.addHelper("classPrivateFieldLooseBase"),
|
||||
REF: object,
|
||||
PROP: privateNamesMap.get(name).id,
|
||||
REF: t.cloneNode(object),
|
||||
PROP: t.cloneNode(privateNamesMap.get(name).id),
|
||||
});
|
||||
},
|
||||
|
||||
@ -387,7 +388,7 @@ function buildPrivateFieldInitLoose(ref, prop, privateNamesMap) {
|
||||
const value = prop.node.value || prop.scope.buildUndefinedNode();
|
||||
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
Object.defineProperty(${ref}, ${t.cloneNode(id)}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
writable: true,
|
||||
@ -400,7 +401,7 @@ function buildPrivateInstanceFieldInitSpec(ref, prop, privateNamesMap) {
|
||||
const { id } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const value = prop.node.value || prop.scope.buildUndefinedNode();
|
||||
|
||||
return template.statement.ast`${id}.set(${ref}, {
|
||||
return template.statement.ast`${t.cloneNode(id)}.set(${ref}, {
|
||||
// configurable is always false for private elements
|
||||
// enumerable is always false for private elements
|
||||
writable: true,
|
||||
@ -422,7 +423,7 @@ function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
|
||||
});
|
||||
|
||||
return template.statement.ast`
|
||||
var ${id.name} = {
|
||||
var ${t.cloneNode(id)} = {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
@ -434,7 +435,7 @@ function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
|
||||
|
||||
const value = prop.node.value || prop.scope.buildUndefinedNode();
|
||||
return template.statement.ast`
|
||||
var ${id} = {
|
||||
var ${t.cloneNode(id)} = {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
writable: true,
|
||||
@ -603,14 +604,14 @@ function buildPrivateMethodDeclaration(prop, privateNamesMap, loose = false) {
|
||||
if (isStatic && !loose) {
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
id,
|
||||
t.cloneNode(id),
|
||||
t.functionExpression(id, params, body, generator, async),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(methodId, methodValue),
|
||||
t.variableDeclarator(t.cloneNode(methodId), methodValue),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { types as t } from "@babel/core";
|
||||
import nameFunction from "@babel/helper-function-name";
|
||||
import splitExportDeclaration from "@babel/helper-split-export-declaration";
|
||||
import {
|
||||
@ -129,7 +130,7 @@ export function createClassFeaturePlugin({
|
||||
nameFunction(path);
|
||||
ref = path.scope.generateUidIdentifier("class");
|
||||
} else {
|
||||
ref = path.node.id;
|
||||
ref = t.cloneNode(path.node.id);
|
||||
}
|
||||
|
||||
// NODE: These three functions don't support decorators yet,
|
||||
|
||||
@ -72,8 +72,14 @@ export function injectInitialization(path, constructor, nodes, renamer) {
|
||||
if (isDerived) {
|
||||
const bareSupers = [];
|
||||
constructor.traverse(findBareSupers, bareSupers);
|
||||
let isFirst = true;
|
||||
for (const bareSuper of bareSupers) {
|
||||
bareSuper.insertAfter(nodes);
|
||||
if (isFirst) {
|
||||
bareSuper.insertAfter(nodes);
|
||||
isFirst = false;
|
||||
} else {
|
||||
bareSuper.insertAfter(nodes.map(n => t.cloneNode(n)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
constructor.get("body").unshiftContainer("body", nodes);
|
||||
|
||||
@ -235,8 +235,12 @@ const handle = {
|
||||
t.binaryExpression(
|
||||
"===",
|
||||
baseNeedsMemoised
|
||||
? t.assignmentExpression("=", baseRef, startingNode)
|
||||
: baseRef,
|
||||
? t.assignmentExpression(
|
||||
"=",
|
||||
t.cloneNode(baseRef),
|
||||
t.cloneNode(startingNode),
|
||||
)
|
||||
: t.cloneNode(baseRef),
|
||||
t.nullLiteral(),
|
||||
),
|
||||
t.binaryExpression(
|
||||
@ -263,7 +267,7 @@ const handle = {
|
||||
false,
|
||||
true,
|
||||
),
|
||||
[context, ...endParent.arguments],
|
||||
[t.cloneNode(context), ...endParent.arguments],
|
||||
false,
|
||||
),
|
||||
);
|
||||
|
||||
@ -337,7 +337,9 @@ const rewriteReferencesVisitor = {
|
||||
path
|
||||
.get("left")
|
||||
.replaceWith(
|
||||
t.variableDeclaration("let", [t.variableDeclarator(newLoopId)]),
|
||||
t.variableDeclaration("let", [
|
||||
t.variableDeclarator(t.cloneNode(newLoopId)),
|
||||
]),
|
||||
);
|
||||
scope.registerDeclaration(path.get("left"));
|
||||
}
|
||||
|
||||
@ -146,6 +146,7 @@ function run(task) {
|
||||
function getOpts(self) {
|
||||
const newOpts = merge(
|
||||
{
|
||||
ast: true,
|
||||
cwd: path.dirname(self.loc),
|
||||
filename: self.loc,
|
||||
filenameRelative: self.filename,
|
||||
|
||||
@ -61,7 +61,7 @@ export default function (path, { getAsyncIterator }) {
|
||||
ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
|
||||
GET_ITERATOR: getAsyncIterator,
|
||||
OBJECT: node.right,
|
||||
STEP_VALUE: stepValue,
|
||||
STEP_VALUE: t.cloneNode(stepValue),
|
||||
STEP_KEY: stepKey,
|
||||
});
|
||||
|
||||
|
||||
@ -160,7 +160,7 @@ function applyTargetDecorators(path, state, decoratedProps) {
|
||||
acc = acc.concat([
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
descriptor,
|
||||
t.cloneNode(descriptor),
|
||||
t.callExpression(state.addHelper("applyDecoratedDescriptor"), [
|
||||
t.cloneNode(target),
|
||||
t.cloneNode(property),
|
||||
|
||||
@ -7,7 +7,7 @@ export default declare(api => {
|
||||
|
||||
function getTempId(scope) {
|
||||
let id = scope.path.getData("functionBind");
|
||||
if (id) return id;
|
||||
if (id) return t.cloneNode(id);
|
||||
|
||||
id = scope.generateDeclaredUidIdentifier("context");
|
||||
return scope.path.setData("functionBind", id);
|
||||
@ -35,7 +35,7 @@ export default declare(api => {
|
||||
bind.callee.object,
|
||||
);
|
||||
}
|
||||
return tempId;
|
||||
return t.cloneNode(tempId);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -97,7 +97,7 @@ export default declare(api => {
|
||||
"=",
|
||||
t.cloneNode(functionLVal),
|
||||
t.memberExpression(
|
||||
receiverLVal,
|
||||
t.cloneNode(receiverLVal),
|
||||
node.callee.property,
|
||||
false,
|
||||
false,
|
||||
@ -105,19 +105,19 @@ export default declare(api => {
|
||||
),
|
||||
...argsInitializers,
|
||||
t.functionExpression(
|
||||
node.callee.property,
|
||||
t.cloneNode(node.callee.property),
|
||||
placeholdersParams,
|
||||
t.blockStatement(
|
||||
[
|
||||
t.returnStatement(
|
||||
t.callExpression(
|
||||
t.memberExpression(
|
||||
functionLVal,
|
||||
t.cloneNode(functionLVal),
|
||||
t.identifier("call"),
|
||||
false,
|
||||
false,
|
||||
),
|
||||
[receiverLVal, ...args],
|
||||
[t.cloneNode(receiverLVal), ...args],
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -132,10 +132,14 @@ export default declare(api => {
|
||||
t.assignmentExpression("=", t.cloneNode(functionLVal), node.callee),
|
||||
...argsInitializers,
|
||||
t.functionExpression(
|
||||
node.callee,
|
||||
t.cloneNode(node.callee),
|
||||
placeholdersParams,
|
||||
t.blockStatement(
|
||||
[t.returnStatement(t.callExpression(functionLVal, args))],
|
||||
[
|
||||
t.returnStatement(
|
||||
t.callExpression(t.cloneNode(functionLVal), args),
|
||||
),
|
||||
],
|
||||
[],
|
||||
),
|
||||
false,
|
||||
|
||||
@ -30,7 +30,7 @@ const buildOptimizedSequenceExpression = ({ assign, call, path }) => {
|
||||
|
||||
call.callee = evalSequence;
|
||||
|
||||
path.scope.push({ id: placeholderNode });
|
||||
path.scope.push({ id: t.cloneNode(placeholderNode) });
|
||||
|
||||
return t.sequenceExpression([assign, call]);
|
||||
}
|
||||
@ -40,7 +40,7 @@ const buildOptimizedSequenceExpression = ({ assign, call, path }) => {
|
||||
return t.sequenceExpression([pipelineLeft, calledExpression.body]);
|
||||
}
|
||||
|
||||
path.scope.push({ id: placeholderNode });
|
||||
path.scope.push({ id: t.cloneNode(placeholderNode) });
|
||||
|
||||
if (param) {
|
||||
path.get("right").scope.rename(param.name, placeholderNode.name);
|
||||
|
||||
@ -2,7 +2,7 @@ import { types as t } from "@babel/core";
|
||||
|
||||
const updateTopicReferenceVisitor = {
|
||||
PipelinePrimaryTopicReference(path) {
|
||||
path.replaceWith(this.topicId);
|
||||
path.replaceWith(t.cloneNode(this.topicId));
|
||||
},
|
||||
PipelineTopicExpression(path) {
|
||||
path.skip();
|
||||
|
||||
@ -33,7 +33,7 @@ export default declare((api, opts) => {
|
||||
const decl = node.declarations[i];
|
||||
const assign = t.assignmentExpression(
|
||||
"=",
|
||||
decl.id,
|
||||
t.cloneNode(decl.id),
|
||||
decl.init || scope.buildUndefinedNode(),
|
||||
);
|
||||
assign._ignoreBlockScopingTDZ = true;
|
||||
|
||||
@ -71,8 +71,8 @@ export default declare((api, options) => {
|
||||
new Promise((${resolveId}, ${rejectId}) =>
|
||||
${requireId}(
|
||||
[${getImportSource(t, path.node)}],
|
||||
imported => ${resolveId}(${result}),
|
||||
${rejectId}
|
||||
imported => ${t.cloneNode(resolveId)}(${result}),
|
||||
${t.cloneNode(rejectId)}
|
||||
)
|
||||
)`,
|
||||
);
|
||||
@ -84,7 +84,7 @@ export default declare((api, options) => {
|
||||
if (requireId) {
|
||||
injectWrapper(
|
||||
path,
|
||||
buildAnonymousWrapper({ REQUIRE: requireId }),
|
||||
buildAnonymousWrapper({ REQUIRE: t.cloneNode(requireId) }),
|
||||
);
|
||||
}
|
||||
return;
|
||||
@ -94,7 +94,7 @@ export default declare((api, options) => {
|
||||
const importNames = [];
|
||||
if (requireId) {
|
||||
amdArgs.push(t.stringLiteral("require"));
|
||||
importNames.push(requireId);
|
||||
importNames.push(t.cloneNode(requireId));
|
||||
}
|
||||
|
||||
let moduleName = getModuleName(this.file.opts, options);
|
||||
|
||||
@ -233,8 +233,8 @@ export default declare((api, options) => {
|
||||
}
|
||||
},
|
||||
exit(path, state) {
|
||||
const undefinedIdent = path.scope.buildUndefinedNode();
|
||||
const exportIdent = path.scope.generateUid("export");
|
||||
const scope = path.scope;
|
||||
const exportIdent = scope.generateUid("export");
|
||||
const contextIdent = state.contextIdent;
|
||||
|
||||
const exportMap = Object.create(null);
|
||||
@ -285,7 +285,7 @@ export default declare((api, options) => {
|
||||
beforeBody.push(path.node);
|
||||
removedPaths.push(path);
|
||||
} else if (path.isClassDeclaration()) {
|
||||
variableIds.push(path.node.id);
|
||||
variableIds.push(t.cloneNode(path.node.id));
|
||||
path.replaceWith(
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
@ -299,7 +299,7 @@ export default declare((api, options) => {
|
||||
const source = path.node.source.value;
|
||||
pushModule(source, "imports", path.node.specifiers);
|
||||
for (const name of Object.keys(path.getBindingIdentifiers())) {
|
||||
path.scope.removeBinding(name);
|
||||
scope.removeBinding(name);
|
||||
variableIds.push(t.identifier(name));
|
||||
}
|
||||
path.remove();
|
||||
@ -312,8 +312,8 @@ export default declare((api, options) => {
|
||||
if (declar.isClassDeclaration()) {
|
||||
if (id) {
|
||||
exportNames.push("default");
|
||||
exportValues.push(undefinedIdent);
|
||||
variableIds.push(id);
|
||||
exportValues.push(scope.buildUndefinedNode());
|
||||
variableIds.push(t.cloneNode(id));
|
||||
addExportName(id.name, "default");
|
||||
path.replaceWith(
|
||||
t.expressionStatement(
|
||||
@ -360,8 +360,8 @@ export default declare((api, options) => {
|
||||
} else if (path.isClass()) {
|
||||
const name = declar.node.id.name;
|
||||
exportNames.push(name);
|
||||
exportValues.push(undefinedIdent);
|
||||
variableIds.push(declar.node.id);
|
||||
exportValues.push(scope.buildUndefinedNode());
|
||||
variableIds.push(t.cloneNode(declar.node.id));
|
||||
path.replaceWith(
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
@ -389,9 +389,7 @@ export default declare((api, options) => {
|
||||
const nodes = [];
|
||||
|
||||
for (const specifier of specifiers) {
|
||||
const binding = path.scope.getBinding(
|
||||
specifier.local.name,
|
||||
);
|
||||
const binding = scope.getBinding(specifier.local.name);
|
||||
// hoisted function export
|
||||
if (
|
||||
binding &&
|
||||
@ -426,7 +424,7 @@ export default declare((api, options) => {
|
||||
|
||||
modules.forEach(function (specifiers) {
|
||||
let setterBody = [];
|
||||
const target = path.scope.generateUid(specifiers.key);
|
||||
const target = scope.generateUid(specifiers.key);
|
||||
|
||||
for (let specifier of specifiers.imports) {
|
||||
if (t.isImportNamespaceSpecifier(specifier)) {
|
||||
@ -510,7 +508,7 @@ export default declare((api, options) => {
|
||||
variableIds.push(id);
|
||||
if (!hasInit) {
|
||||
exportNames.push(name);
|
||||
exportValues.push(undefinedIdent);
|
||||
exportValues.push(scope.buildUndefinedNode());
|
||||
}
|
||||
},
|
||||
null,
|
||||
@ -540,7 +538,7 @@ export default declare((api, options) => {
|
||||
path.traverse(reassignmentVisitor, {
|
||||
exports: exportMap,
|
||||
buildCall: buildExportCall,
|
||||
scope: path.scope,
|
||||
scope,
|
||||
});
|
||||
|
||||
for (const path of removedPaths) {
|
||||
|
||||
@ -229,6 +229,6 @@ function buildScopeIIFE(shadowedParams, body) {
|
||||
}
|
||||
|
||||
return t.returnStatement(
|
||||
t.callExpression(t.arrowFunctionExpression(params, body), params),
|
||||
t.callExpression(t.arrowFunctionExpression(params, body), args),
|
||||
);
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ export default declare(api => {
|
||||
}
|
||||
|
||||
const trace = makeTrace(
|
||||
state.fileNameIdentifier,
|
||||
t.cloneNode(state.fileNameIdentifier),
|
||||
location.start.line,
|
||||
location.start.column,
|
||||
);
|
||||
|
||||
@ -301,7 +301,11 @@ export default declare((api, options, dirname) => {
|
||||
context2 = t.cloneNode(object);
|
||||
} else {
|
||||
context1 = path.scope.generateDeclaredUidIdentifier("context");
|
||||
context2 = t.assignmentExpression("=", context1, object);
|
||||
context2 = t.assignmentExpression(
|
||||
"=",
|
||||
t.cloneNode(context1),
|
||||
object,
|
||||
);
|
||||
}
|
||||
node.callee = t.memberExpression(
|
||||
t.callExpression(
|
||||
|
||||
@ -87,7 +87,7 @@ export default declare((api, options) => {
|
||||
const lazyLoad = template.ast`
|
||||
function ${templateObject}() {
|
||||
const data = ${t.callExpression(helperId, callExpressionInput)};
|
||||
${templateObject} = function() { return data };
|
||||
${t.cloneNode(templateObject)} = function() { return data };
|
||||
return data;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -134,7 +134,8 @@ export default declare(
|
||||
);
|
||||
}
|
||||
|
||||
return template.statement.ast`this.${id} = ${id}`;
|
||||
return template.statement.ast`
|
||||
this.${t.cloneNode(id)} = ${t.cloneNode(id)}`;
|
||||
});
|
||||
|
||||
injectInitialization(classPath, path, assigns);
|
||||
|
||||
@ -156,16 +156,16 @@ function handleNested(path, t, node, parentExport) {
|
||||
let fallthroughValue = t.objectExpression([]);
|
||||
|
||||
if (parentExport) {
|
||||
const memberExpr = t.memberExpression(parentExport, realName);
|
||||
fallthroughValue = template.expression.ast`
|
||||
${parentExport}.${realName} || (
|
||||
${parentExport}.${realName} = ${fallthroughValue}
|
||||
)
|
||||
${t.cloneNode(memberExpr)} ||
|
||||
(${t.cloneNode(memberExpr)} = ${fallthroughValue})
|
||||
`;
|
||||
}
|
||||
|
||||
return template.statement.ast`
|
||||
(function (${t.identifier(name)}) {
|
||||
${namespaceTopLevel}
|
||||
})(${realName} || (${realName} = ${fallthroughValue}));
|
||||
})(${realName} || (${t.cloneNode(realName)} = ${fallthroughValue}));
|
||||
`;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user