From 912bcc186d48021fa61007c59a9431b994d6840d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 11 Jan 2018 19:31:48 +0100 Subject: [PATCH] Fix reused nodes - part 1 (#7149) --- .../src/transformation/file/file.js | 2 +- .../src/index.js | 9 ++-- .../babel-helper-replace-supers/src/index.js | 17 +++++-- .../src/index.js | 17 +++++-- .../src/index.js | 46 +++++++++++-------- .../src/index.js | 9 +++- .../src/index.js | 9 +++- .../src/index.js | 20 +++++--- .../src/index.js | 11 +++-- .../fixtures/general/function-call/output.js | 18 ++++---- .../src/index.js | 4 +- .../src/index.js | 5 +- .../src/index.js | 2 +- .../src/loose.js | 2 +- .../src/vanilla.js | 6 +-- .../src/index.js | 14 +++--- .../src/index.js | 39 ++++++++++------ .../src/index.js | 6 ++- .../src/index.js | 6 ++- .../src/params.js | 6 +-- .../src/rest.js | 21 +++++---- .../src/index.js | 10 +++- .../src/index.js | 2 +- .../src/index.js | 5 +- .../src/index.js | 7 ++- .../babel-traverse/src/path/lib/hoister.js | 2 +- .../babel-traverse/src/path/modification.js | 6 ++- .../babel-traverse/src/path/replacement.js | 8 +++- packages/babel-traverse/src/scope/index.js | 7 ++- .../converters/gatherSequenceExpressions.js | 3 +- 30 files changed, 202 insertions(+), 117 deletions(-) diff --git a/packages/babel-core/src/transformation/file/file.js b/packages/babel-core/src/transformation/file/file.js index 044c6eb85d..d04b29bcbb 100644 --- a/packages/babel-core/src/transformation/file/file.js +++ b/packages/babel-core/src/transformation/file/file.js @@ -123,7 +123,7 @@ export default class File { addHelper(name: string): Object { const declar = this.declarations[name]; - if (declar) return declar; + if (declar) return t.cloneNode(declar); const generator = this.get("helperGenerator"); const runtime = this.get("helpersNamespace"); diff --git a/packages/babel-helper-explode-assignable-expression/src/index.js b/packages/babel-helper-explode-assignable-expression/src/index.js index cbe6f6fcae..d569c90ff6 100644 --- a/packages/babel-helper-explode-assignable-expression/src/index.js +++ b/packages/babel-helper-explode-assignable-expression/src/index.js @@ -33,7 +33,7 @@ function getObjRef(node, nodes, file, scope) { const temp = scope.generateUidIdentifierBasedOnNode(ref); scope.push({ id: temp }); - nodes.push(t.assignmentExpression("=", temp, ref)); + nodes.push(t.assignmentExpression("=", t.cloneNode(temp), t.cloneNode(ref))); return temp; } @@ -44,7 +44,7 @@ function getPropRef(node, nodes, file, scope) { const temp = scope.generateUidIdentifierBasedOnNode(prop); scope.push({ id: temp }); - nodes.push(t.assignmentExpression("=", temp, prop)); + nodes.push(t.assignmentExpression("=", t.cloneNode(temp), t.cloneNode(prop))); return temp; } @@ -68,12 +68,13 @@ export default function( let ref, uid; if (t.isIdentifier(node)) { - ref = node; + ref = t.cloneNode(node); uid = obj; } else { const prop = getPropRef(node, nodes, file, scope); const computed = node.computed || t.isLiteral(prop); - uid = ref = t.memberExpression(obj, prop, computed); + uid = t.memberExpression(t.cloneNode(obj), t.cloneNode(prop), computed); + ref = t.memberExpression(t.cloneNode(obj), t.cloneNode(prop), computed); } return { diff --git a/packages/babel-helper-replace-supers/src/index.js b/packages/babel-helper-replace-supers/src/index.js index a034093a0d..a2066b5afb 100644 --- a/packages/babel-helper-replace-supers/src/index.js +++ b/packages/babel-helper-replace-supers/src/index.js @@ -206,9 +206,12 @@ export default class ReplaceSupers { return; } else if (t.isMemberExpression(parent) && !methodNode.static) { // super.test -> objectRef.prototype.test - return t.memberExpression(superRef, t.identifier("prototype")); + return t.memberExpression( + t.cloneNode(superRef), + t.identifier("prototype"), + ); } else { - return superRef; + return t.cloneNode(superRef); } } @@ -240,12 +243,18 @@ export default class ReplaceSupers { // super.age += 2; -> let _ref = super.age; super.age = _ref + 2; ref = ref || path.scope.generateUidIdentifier("ref"); return [ - t.variableDeclaration("var", [t.variableDeclarator(ref, node.left)]), + t.variableDeclaration("var", [ + t.variableDeclarator(t.cloneNode(ref), node.left), + ]), t.expressionStatement( t.assignmentExpression( "=", node.left, - t.binaryExpression(node.operator.slice(0, -1), ref, node.right), + t.binaryExpression( + node.operator.slice(0, -1), + t.cloneNode(ref), + node.right, + ), ), ), ]; diff --git a/packages/babel-plugin-proposal-class-properties/src/index.js b/packages/babel-plugin-proposal-class-properties/src/index.js index 83822ca3a2..38ecd56fbd 100644 --- a/packages/babel-plugin-proposal-class-properties/src/index.js +++ b/packages/babel-plugin-proposal-class-properties/src/index.js @@ -54,7 +54,7 @@ export default function(api, options) { value: VALUE }); `({ - REF: ref, + REF: t.cloneNode(ref), KEY: t.isIdentifier(key) && !computed ? t.stringLiteral(key.name) : key, VALUE: value || scope.buildUndefinedNode(), }); @@ -62,7 +62,11 @@ export default function(api, options) { const buildClassPropertyLoose = (ref, { key, value, computed }, scope) => { return template.statement`MEMBER = VALUE`({ - MEMBER: t.memberExpression(ref, key, computed || t.isLiteral(key)), + MEMBER: t.memberExpression( + t.cloneNode(ref), + key, + computed || t.isLiteral(key), + ), VALUE: value || scope.buildUndefinedNode(), }); }; @@ -199,7 +203,10 @@ export default function(api, options) { instanceBody = [ t.expressionStatement( t.callExpression( - t.memberExpression(initialisePropsRef, t.identifier("call")), + t.memberExpression( + t.cloneNode(initialisePropsRef), + t.identifier("call"), + ), [t.thisExpression()], ), ), @@ -227,7 +234,9 @@ export default function(api, options) { if (path.isClassExpression()) { path.scope.push({ id: ref }); - path.replaceWith(t.assignmentExpression("=", ref, path.node)); + path.replaceWith( + t.assignmentExpression("=", t.cloneNode(ref), path.node), + ); } else if (!path.node.id) { // Anonymous class declaration path.node.id = ref; diff --git a/packages/babel-plugin-proposal-decorators/src/index.js b/packages/babel-plugin-proposal-decorators/src/index.js index a5d33b21a8..67884c1302 100644 --- a/packages/babel-plugin-proposal-decorators/src/index.js +++ b/packages/babel-plugin-proposal-decorators/src/index.js @@ -75,8 +75,8 @@ export default function() { .reverse() .reduce(function(acc, decorator) { return buildClassDecorator({ - CLASS_REF: name, - DECORATOR: decorator, + CLASS_REF: t.cloneNode(name), + DECORATOR: t.cloneNode(decorator), INNER: acc, }).expression; }, classPath.node); @@ -166,9 +166,11 @@ export default function() { "=", descriptor, t.callExpression(state.addHelper("applyDecoratedDescriptor"), [ - target, - property, - t.arrayExpression(decorators.map(dec => dec.expression)), + t.cloneNode(target), + t.cloneNode(property), + t.arrayExpression( + decorators.map(dec => t.cloneNode(dec.expression)), + ), t.objectExpression([ t.objectProperty( t.identifier("enumerable"), @@ -182,21 +184,23 @@ export default function() { } else { acc = acc.concat( t.callExpression(state.addHelper("applyDecoratedDescriptor"), [ - target, - property, - t.arrayExpression(decorators.map(dec => dec.expression)), + t.cloneNode(target), + t.cloneNode(property), + t.arrayExpression( + decorators.map(dec => t.cloneNode(dec.expression)), + ), t.isObjectProperty(node) || t.isClassProperty(node, { static: true }) ? buildGetObjectInitializer({ TEMP: path.scope.generateDeclaredUidIdentifier("init"), - TARGET: target, - PROPERTY: property, + TARGET: t.cloneNode(target), + PROPERTY: t.cloneNode(property), }).expression : buildGetDescriptor({ - TARGET: target, - PROPERTY: property, + TARGET: t.cloneNode(target), + PROPERTY: t.cloneNode(property), }).expression, - target, + t.cloneNode(target), ]), ); } @@ -205,9 +209,9 @@ export default function() { }, []); return t.sequenceExpression([ - t.assignmentExpression("=", name, path.node), + t.assignmentExpression("=", t.cloneNode(name), path.node), t.sequenceExpression(exprs), - name, + t.cloneNode(name), ]); } @@ -222,7 +226,9 @@ export default function() { return; } - const ref = node.id || path.scope.generateUidIdentifier("class"); + const ref = node.id + ? t.cloneNode(node.id) + : path.scope.generateUidIdentifier("class"); const letDeclaration = t.variableDeclaration("let", [ t.variableDeclarator(ref, t.toExpression(node)), ]); @@ -232,7 +238,7 @@ export default function() { path.parentPath.replaceWithMultiple([ letDeclaration, t.exportNamedDeclaration(null, [ - t.exportSpecifier(ref, t.identifier("default")), + t.exportSpecifier(t.cloneNode(ref), t.identifier("default")), ]), ]); } else { @@ -261,10 +267,10 @@ export default function() { path.replaceWith( t.callExpression(state.addHelper("initializerDefineProperty"), [ - path.get("left.object").node, + t.cloneNode(path.get("left.object").node), t.stringLiteral(path.get("left.property").node.name), - path.get("right.arguments")[0].node, - path.get("right.arguments")[1].node, + t.cloneNode(path.get("right.arguments")[0].node), + t.cloneNode(path.get("right.arguments")[1].node), ]), ); }, diff --git a/packages/babel-plugin-proposal-export-default-from/src/index.js b/packages/babel-plugin-proposal-export-default-from/src/index.js index 4d0e6c5661..c5c226f80b 100644 --- a/packages/babel-plugin-proposal-export-default-from/src/index.js +++ b/packages/babel-plugin-proposal-export-default-from/src/index.js @@ -16,8 +16,13 @@ export default function() { const uid = scope.generateUidIdentifier(exported.name); const nodes = [ - t.importDeclaration([t.importDefaultSpecifier(uid)], node.source), - t.exportNamedDeclaration(null, [t.exportSpecifier(uid, exported)]), + t.importDeclaration( + [t.importDefaultSpecifier(uid)], + t.cloneNode(node.source), + ), + t.exportNamedDeclaration(null, [ + t.exportSpecifier(t.cloneNode(uid), exported), + ]), ]; if (specifiers.length >= 1) { diff --git a/packages/babel-plugin-proposal-export-namespace-from/src/index.js b/packages/babel-plugin-proposal-export-namespace-from/src/index.js index 06b08c4afe..ec07791beb 100644 --- a/packages/babel-plugin-proposal-export-namespace-from/src/index.js +++ b/packages/babel-plugin-proposal-export-namespace-from/src/index.js @@ -26,8 +26,13 @@ export default function() { const uid = scope.generateUidIdentifier(exported.name); nodes.push( - t.importDeclaration([t.importNamespaceSpecifier(uid)], node.source), - t.exportNamedDeclaration(null, [t.exportSpecifier(uid, exported)]), + t.importDeclaration( + [t.importNamespaceSpecifier(uid)], + t.cloneNode(node.source), + ), + t.exportNamedDeclaration(null, [ + t.exportSpecifier(t.cloneNode(uid), exported), + ]), ); if (node.specifiers.length >= 1) { diff --git a/packages/babel-plugin-proposal-object-rest-spread/src/index.js b/packages/babel-plugin-proposal-object-rest-spread/src/index.js index 60d7aa2679..c8566b8508 100644 --- a/packages/babel-plugin-proposal-object-rest-spread/src/index.js +++ b/packages/babel-plugin-proposal-object-rest-spread/src/index.js @@ -95,7 +95,7 @@ export default function(api, opts) { impureComputedPropertyDeclarators, restElement.argument, t.callExpression(file.addHelper("objectWithoutProperties"), [ - objRef, + t.cloneNode(objRef), keyExpression, ]), ]; @@ -124,7 +124,7 @@ export default function(api, opts) { parentPath.ensureBlock(); parentPath.get("body").unshiftContainer("body", declar); - paramPath.replaceWith(uid); + paramPath.replaceWith(t.cloneNode(uid)); } } @@ -180,7 +180,10 @@ export default function(api, opts) { ); // replace foo() with _foo this.originalPath.replaceWith( - t.variableDeclarator(this.originalPath.node.id, initRef), + t.variableDeclarator( + this.originalPath.node.id, + t.cloneNode(initRef), + ), ); return; @@ -247,8 +250,9 @@ export default function(api, opts) { const specifiers = []; for (const name in path.getOuterBindingIdentifiers(path)) { - const id = t.identifier(name); - specifiers.push(t.exportSpecifier(id, id)); + specifiers.push( + t.exportSpecifier(t.identifier(name), t.identifier(name)), + ); } // Split the declaration and export list into two declarations so that the variable @@ -324,7 +328,9 @@ export default function(api, opts) { path.ensureBlock(); node.body.body.unshift( - t.variableDeclaration("var", [t.variableDeclarator(left, temp)]), + t.variableDeclaration("var", [ + t.variableDeclarator(left, t.cloneNode(temp)), + ]), ); return; @@ -344,7 +350,7 @@ export default function(api, opts) { node.body.body.unshift( t.variableDeclaration(node.left.kind, [ - t.variableDeclarator(pattern, key), + t.variableDeclarator(pattern, t.cloneNode(key)), ]), ); }, diff --git a/packages/babel-plugin-proposal-optional-chaining/src/index.js b/packages/babel-plugin-proposal-optional-chaining/src/index.js index 8779ae2743..92dadca1aa 100644 --- a/packages/babel-plugin-proposal-optional-chaining/src/index.js +++ b/packages/babel-plugin-proposal-optional-chaining/src/index.js @@ -7,7 +7,6 @@ export default function(api, options) { function optional(path, replacementPath) { const { scope } = path; const optionals = []; - const nil = scope.buildUndefinedNode(); let objectPath = path; while (objectPath.isMemberExpression() || objectPath.isCallExpression()) { @@ -40,7 +39,11 @@ export default function(api, options) { } else { ref = scope.maybeGenerateMemoised(chain); if (ref) { - check = t.assignmentExpression("=", ref, chain); + check = t.assignmentExpression( + "=", + t.cloneNode(ref), + t.cloneNode(chain), + ); node[replaceKey] = ref; } else { check = ref = chain; @@ -65,7 +68,7 @@ export default function(api, options) { context = object; } - node.arguments.unshift(context); + node.arguments.unshift(t.cloneNode(context)); node.callee = t.memberExpression(node.callee, t.identifier("call")); } } @@ -83,7 +86,7 @@ export default function(api, options) { scope.buildUndefinedNode(), ), ), - nil, + scope.buildUndefinedNode(), replacementPath.node, ), ); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/function-call/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/function-call/output.js index 711583284c..e8e6cfba96 100644 --- a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/function-call/output.js +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/function-call/output.js @@ -1,12 +1,12 @@ -var _foo, _foo2, _foo$bar, _foo3, _foo4, _foo4$bar, _foo5, _foo6, _foo7, _foo$bar2, _foo8, _foo$bar3, _foo9, _foo$bar3$call, _foo10, _foo10$bar, _foo11, _foo11$bar, _foo11$bar$call; +var _foo, _foo2, _foo$bar, _foo3, _foo3$bar, _foo4, _foo5, _foo6, _foo$bar2, _foo$bar3, _foo$bar3$call, _foo7, _foo7$bar, _foo8, _foo8$bar, _foo8$bar$call; (_foo = foo) === null || _foo === void 0 ? void 0 : _foo(foo); (_foo2 = foo) === null || _foo2 === void 0 ? void 0 : _foo2.bar(); -(_foo$bar = (_foo3 = foo).bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.call(_foo3, foo.bar, false); -(_foo4 = foo) === null || _foo4 === void 0 ? void 0 : (_foo4$bar = _foo4.bar) === null || _foo4$bar === void 0 ? void 0 : _foo4$bar.call(_foo4, foo.bar, true); -(_foo5 = foo) === null || _foo5 === void 0 ? void 0 : _foo5().bar; -(_foo6 = foo) === null || _foo6 === void 0 ? void 0 : (_foo7 = _foo6()) === null || _foo7 === void 0 ? void 0 : _foo7.bar; -(_foo$bar2 = (_foo8 = foo).bar) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2.call(_foo8).baz; -(_foo$bar3 = (_foo9 = foo).bar) === null || _foo$bar3 === void 0 ? void 0 : (_foo$bar3$call = _foo$bar3.call(_foo9)) === null || _foo$bar3$call === void 0 ? void 0 : _foo$bar3$call.baz; -(_foo10 = foo) === null || _foo10 === void 0 ? void 0 : (_foo10$bar = _foo10.bar) === null || _foo10$bar === void 0 ? void 0 : _foo10$bar.call(_foo10).baz; -(_foo11 = foo) === null || _foo11 === void 0 ? void 0 : (_foo11$bar = _foo11.bar) === null || _foo11$bar === void 0 ? void 0 : (_foo11$bar$call = _foo11$bar.call(_foo11)) === null || _foo11$bar$call === void 0 ? void 0 : _foo11$bar$call.baz; +(_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.call(foo, foo.bar, false); +(_foo3 = foo) === null || _foo3 === void 0 ? void 0 : (_foo3$bar = _foo3.bar) === null || _foo3$bar === void 0 ? void 0 : _foo3$bar.call(_foo3, foo.bar, true); +(_foo4 = foo) === null || _foo4 === void 0 ? void 0 : _foo4().bar; +(_foo5 = foo) === null || _foo5 === void 0 ? void 0 : (_foo6 = _foo5()) === null || _foo6 === void 0 ? void 0 : _foo6.bar; +(_foo$bar2 = foo.bar) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2.call(foo).baz; +(_foo$bar3 = foo.bar) === null || _foo$bar3 === void 0 ? void 0 : (_foo$bar3$call = _foo$bar3.call(foo)) === null || _foo$bar3$call === void 0 ? void 0 : _foo$bar3$call.baz; +(_foo7 = foo) === null || _foo7 === void 0 ? void 0 : (_foo7$bar = _foo7.bar) === null || _foo7$bar === void 0 ? void 0 : _foo7$bar.call(_foo7).baz; +(_foo8 = foo) === null || _foo8 === void 0 ? void 0 : (_foo8$bar = _foo8.bar) === null || _foo8$bar === void 0 ? void 0 : (_foo8$bar$call = _foo8$bar.call(_foo8)) === null || _foo8$bar$call === void 0 ? void 0 : _foo8$bar$call.baz; diff --git a/packages/babel-plugin-proposal-pipeline-operator/src/index.js b/packages/babel-plugin-proposal-pipeline-operator/src/index.js index 0f6ae6e9b0..758211975b 100644 --- a/packages/babel-plugin-proposal-pipeline-operator/src/index.js +++ b/packages/babel-plugin-proposal-pipeline-operator/src/index.js @@ -44,10 +44,10 @@ export default function() { const call = optimizeArrow ? right.body - : t.callExpression(right, [placeholder]); + : t.callExpression(right, [t.cloneNode(placeholder)]); path.replaceWith( t.sequenceExpression([ - t.assignmentExpression("=", placeholder, left), + t.assignmentExpression("=", t.cloneNode(placeholder), left), call, ]), ); diff --git a/packages/babel-plugin-proposal-throw-expressions/src/index.js b/packages/babel-plugin-proposal-throw-expressions/src/index.js index ebd82e4de9..f502049263 100644 --- a/packages/babel-plugin-proposal-throw-expressions/src/index.js +++ b/packages/babel-plugin-proposal-throw-expressions/src/index.js @@ -10,11 +10,10 @@ export default function() { const { operator, argument } = path.node; if (operator !== "throw") return; - const arg = t.identifier("e"); const arrow = t.functionExpression( null, - [arg], - t.blockStatement([t.throwStatement(arg)]), + [t.identifier("e")], + t.blockStatement([t.throwStatement(t.identifier("e"))]), ); path.replaceWith(t.callExpression(arrow, [argument])); diff --git a/packages/babel-plugin-transform-classes/src/index.js b/packages/babel-plugin-transform-classes/src/index.js index 93904772e4..a93fe739ed 100644 --- a/packages/babel-plugin-transform-classes/src/index.js +++ b/packages/babel-plugin-transform-classes/src/index.js @@ -34,7 +34,7 @@ export default function(api, options) { path.replaceWith(node.declaration); path.insertAfter( t.exportNamedDeclaration(null, [ - t.exportSpecifier(ref, t.identifier("default")), + t.exportSpecifier(t.cloneNode(ref), t.identifier("default")), ]), ); }, diff --git a/packages/babel-plugin-transform-classes/src/loose.js b/packages/babel-plugin-transform-classes/src/loose.js index bbe95a26a2..fc87cfb222 100644 --- a/packages/babel-plugin-transform-classes/src/loose.js +++ b/packages/babel-plugin-transform-classes/src/loose.js @@ -34,7 +34,7 @@ export default class LooseClassTransformer extends VanillaTransformer { classRef = this._protoAlias; } const methodName = t.memberExpression( - classRef, + t.cloneNode(classRef), node.key, node.computed || t.isLiteral(node.key), ); diff --git a/packages/babel-plugin-transform-classes/src/vanilla.js b/packages/babel-plugin-transform-classes/src/vanilla.js index 083eb90e25..17a8375b63 100644 --- a/packages/babel-plugin-transform-classes/src/vanilla.js +++ b/packages/babel-plugin-transform-classes/src/vanilla.js @@ -387,12 +387,12 @@ export default class ClassTransformer { // special case single arguments spread bareSuperNode.arguments[1] = bareSuperNode.arguments[1].argument; bareSuperNode.callee = t.memberExpression( - superRef, + t.cloneNode(superRef), t.identifier("apply"), ); } else { bareSuperNode.callee = t.memberExpression( - superRef, + t.cloneNode(superRef), t.identifier("call"), ); } @@ -456,7 +456,7 @@ export default class ClassTransformer { const superRef = this.superName || t.identifier("Function"); let thisRef = function() { const ref = path.scope.generateDeclaredUidIdentifier("this"); - thisRef = () => ref; + thisRef = () => t.cloneNode(ref); return ref; }; diff --git a/packages/babel-plugin-transform-computed-properties/src/index.js b/packages/babel-plugin-transform-computed-properties/src/index.js index 511c82fa9d..7fb80c227b 100644 --- a/packages/babel-plugin-transform-computed-properties/src/index.js +++ b/packages/babel-plugin-transform-computed-properties/src/index.js @@ -34,7 +34,7 @@ export default function(api, options) { t.assignmentExpression( "=", t.memberExpression( - objId, + t.cloneNode(objId), prop.key, prop.computed || t.isLiteral(prop.key), ), @@ -62,7 +62,7 @@ export default function(api, options) { body.push( ...buildMutatorMapAssign({ MUTATOR_MAP_REF: getMutatorId(), - KEY: key, + KEY: t.cloneNode(key), VALUE: getValue(prop), KIND: t.identifier(prop.kind), }), @@ -74,7 +74,7 @@ export default function(api, options) { if (prop.kind === "get" || prop.kind === "set") { pushMutatorDefine(info, prop); } else { - pushAssign(info.objId, prop, info.body); + pushAssign(t.cloneNode(info.objId), prop, info.body); } } } @@ -100,7 +100,7 @@ export default function(api, options) { body.push( t.expressionStatement( t.callExpression(state.addHelper("defineProperty"), [ - objId, + t.cloneNode(objId), key, getValue(prop), ]), @@ -165,7 +165,7 @@ export default function(api, options) { ); } - return mutatorRef; + return t.cloneNode(mutatorRef); }; const single = pushComputedProps({ @@ -183,7 +183,7 @@ export default function(api, options) { t.expressionStatement( t.callExpression( state.addHelper("defineEnumerableProperties"), - [objId, mutatorRef], + [t.cloneNode(objId), t.cloneNode(mutatorRef)], ), ), ); @@ -192,7 +192,7 @@ export default function(api, options) { if (single) { path.replaceWith(single); } else { - body.push(t.expressionStatement(objId)); + body.push(t.expressionStatement(t.cloneNode(objId))); path.replaceWithMultiple(body); } }, diff --git a/packages/babel-plugin-transform-destructuring/src/index.js b/packages/babel-plugin-transform-destructuring/src/index.js index 1713bc3a8e..bdd84137a8 100644 --- a/packages/babel-plugin-transform-destructuring/src/index.js +++ b/packages/babel-plugin-transform-destructuring/src/index.js @@ -62,10 +62,12 @@ export default function(api, options) { let node; if (op) { - node = t.expressionStatement(t.assignmentExpression(op, id, init)); + node = t.expressionStatement( + t.assignmentExpression(op, id, t.cloneNode(init)), + ); } else { node = t.variableDeclaration(this.kind, [ - t.variableDeclarator(id, init), + t.variableDeclarator(id, t.cloneNode(init)), ]); } @@ -76,13 +78,14 @@ export default function(api, options) { buildVariableDeclaration(id, init) { const declar = t.variableDeclaration("var", [ - t.variableDeclarator(id, init), + t.variableDeclarator(t.cloneNode(id), t.cloneNode(init)), ]); declar._blockHoist = this.blockHoist; return declar; } - push(id, init) { + push(id, _init) { + const init = t.cloneNode(_init); if (t.isObjectPattern(id)) { this.pushObjectPattern(id, init); } else if (t.isArrayPattern(id)) { @@ -164,7 +167,7 @@ export default function(api, options) { if (t.isIdentifier(key) && !prop.computed) { key = t.stringLiteral(prop.key.name); } - keys.push(key); + keys.push(t.cloneNode(key)); } keys = t.arrayExpression(keys); @@ -173,7 +176,7 @@ export default function(api, options) { const value = t.callExpression( this.addHelper("objectWithoutProperties"), - [objRef, keys], + [t.cloneNode(objRef), keys], ); this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value)); } @@ -182,7 +185,11 @@ export default function(api, options) { if (t.isLiteral(prop.key)) prop.computed = true; const pattern = prop.value; - const objRef = t.memberExpression(propRef, prop.key, prop.computed); + const objRef = t.memberExpression( + t.cloneNode(propRef), + prop.key, + prop.computed, + ); if (t.isPattern(pattern)) { this.push(pattern, objRef); @@ -221,7 +228,7 @@ export default function(api, options) { if (t.isRestElement(prop)) { this.pushObjectRest(pattern, objRef, prop, i); } else { - this.pushObjectProperty(prop, t.cloneNode(objRef)); + this.pushObjectProperty(prop, objRef); } } } @@ -344,7 +351,9 @@ export default function(api, options) { if (!t.isArrayExpression(ref) && !t.isMemberExpression(ref)) { const memo = this.scope.maybeGenerateMemoised(ref, true); if (memo) { - this.nodes.push(this.buildVariableDeclaration(memo, ref)); + this.nodes.push( + this.buildVariableDeclaration(memo, t.cloneNode(ref)), + ); ref = memo; } } @@ -367,8 +376,9 @@ export default function(api, options) { const specifiers = []; for (const name in path.getOuterBindingIdentifiers(path)) { - const id = t.identifier(name); - specifiers.push(t.exportSpecifier(id, id)); + specifiers.push( + t.exportSpecifier(t.identifier(name), t.identifier(name)), + ); } // Split the declaration and export list into two declarations so that the variable @@ -484,7 +494,7 @@ export default function(api, options) { destructuring.init(node.left, ref || node.right); if (ref) { - nodes.push(t.expressionStatement(ref)); + nodes.push(t.expressionStatement(t.cloneNode(ref))); } path.replaceWithMultiple(nodes); @@ -526,7 +536,10 @@ export default function(api, options) { } else { nodes.push( t.inherits( - destructuring.buildVariableAssignment(declar.id, declar.init), + destructuring.buildVariableAssignment( + declar.id, + t.cloneNode(declar.init), + ), declar, ), ); diff --git a/packages/babel-plugin-transform-new-target/src/index.js b/packages/babel-plugin-transform-new-target/src/index.js index 562a023cbc..93825672f6 100644 --- a/packages/babel-plugin-transform-new-target/src/index.js +++ b/packages/babel-plugin-transform-new-target/src/index.js @@ -54,7 +54,11 @@ export default function() { path.replaceWith( t.conditionalExpression( - t.binaryExpression("instanceof", t.thisExpression(), node.id), + t.binaryExpression( + "instanceof", + t.thisExpression(), + t.cloneNode(node.id), + ), constructor, scope.buildUndefinedNode(), ), diff --git a/packages/babel-plugin-transform-object-super/src/index.js b/packages/babel-plugin-transform-object-super/src/index.js index 83c7b5dec2..e0c6c14cfa 100644 --- a/packages/babel-plugin-transform-object-super/src/index.js +++ b/packages/babel-plugin-transform-object-super/src/index.js @@ -39,8 +39,10 @@ export default function() { }); if (objectRef) { - path.scope.push({ id: objectRef }); - path.replaceWith(t.assignmentExpression("=", objectRef, path.node)); + path.scope.push({ id: t.cloneNode(objectRef) }); + path.replaceWith( + t.assignmentExpression("=", t.cloneNode(objectRef), path.node), + ); } }, }, diff --git a/packages/babel-plugin-transform-parameters/src/params.js b/packages/babel-plugin-transform-parameters/src/params.js index dc9a87dec7..391c87160e 100644 --- a/packages/babel-plugin-transform-parameters/src/params.js +++ b/packages/babel-plugin-transform-parameters/src/params.js @@ -69,7 +69,7 @@ export default function convertFunctionParams(path, loose) { if (left.isIdentifier()) { body.push( buildLooseDefaultParam({ - ASSIGNMENT_IDENTIFIER: left.node, + ASSIGNMENT_IDENTIFIER: t.cloneNode(left.node), DEFAULT_VALUE: right.node, UNDEFINED: undefinedNode, }), @@ -81,7 +81,7 @@ export default function convertFunctionParams(path, loose) { buildLooseDestructuredDefaultParam({ ASSIGNMENT_IDENTIFIER: left.node, DEFAULT_VALUE: right.node, - PARAMETER_NAME: paramName, + PARAMETER_NAME: t.cloneNode(paramName), UNDEFINED: undefinedNode, }), ); @@ -123,7 +123,7 @@ export default function convertFunctionParams(path, loose) { ]); body.push(defNode); - param.replaceWith(uid); + param.replaceWith(t.cloneNode(uid)); } if (!state.iife && !param.isIdentifier()) { diff --git a/packages/babel-plugin-transform-parameters/src/rest.js b/packages/babel-plugin-transform-parameters/src/rest.js index 8424580dc3..0e11c78fc3 100644 --- a/packages/babel-plugin-transform-parameters/src/rest.js +++ b/packages/babel-plugin-transform-parameters/src/rest.js @@ -168,7 +168,11 @@ function optimiseIndexGetter(path, argsId, offset) { // Avoid unnecessary '+ 0' index = path.parent.property; } else { - index = t.binaryExpression("+", path.parent.property, offsetLiteral); + index = t.binaryExpression( + "+", + path.parent.property, + t.cloneNode(offsetLiteral), + ); } const { scope } = path; @@ -180,7 +184,7 @@ function optimiseIndexGetter(path, argsId, offset) { ARGUMENTS: argsId, OFFSET: offsetLiteral, INDEX: index, - REF: temp, + REF: t.cloneNode(temp), }), ); } else { @@ -262,15 +266,16 @@ export default function convertFunctionRest(path) { // There are only "shorthand" references if (!state.deopted && !state.references.length) { for (const { path, cause } of (state.candidates: Array)) { + const clonedArgsId = t.cloneNode(argsId); switch (cause) { case "indexGetter": - optimiseIndexGetter(path, argsId, state.offset); + optimiseIndexGetter(path, clonedArgsId, state.offset); break; case "lengthGetter": - optimiseLengthGetter(path, argsId, state.offset); + optimiseLengthGetter(path, clonedArgsId, state.offset); break; default: - path.replaceWith(argsId); + path.replaceWith(clonedArgsId); } } return true; @@ -290,7 +295,7 @@ export default function convertFunctionRest(path) { // this method has additional params, so we need to subtract // the index of the current argument position from the // position in the array that we want to populate - arrKey = t.binaryExpression("-", key, start); + arrKey = t.binaryExpression("-", t.cloneNode(key), t.cloneNode(start)); // we need to work out the size of the array that we're // going to store all the rest parameters @@ -299,8 +304,8 @@ export default function convertFunctionRest(path) { // with <0 if there are less arguments than params as it'll // cause an error arrLen = t.conditionalExpression( - t.binaryExpression(">", len, start), - t.binaryExpression("-", len, start), + t.binaryExpression(">", t.cloneNode(len), t.cloneNode(start)), + t.binaryExpression("-", t.cloneNode(len), t.cloneNode(start)), t.numericLiteral(0), ); } diff --git a/packages/babel-plugin-transform-proto-to-assign/src/index.js b/packages/babel-plugin-transform-proto-to-assign/src/index.js index bb635e296f..09ae0e71e2 100644 --- a/packages/babel-plugin-transform-proto-to-assign/src/index.js +++ b/packages/babel-plugin-transform-proto-to-assign/src/index.js @@ -34,8 +34,14 @@ export default function() { t.expressionStatement(t.assignmentExpression("=", temp, left)), ); } - nodes.push(buildDefaultsCallExpression(path.node, temp || left, file)); - if (temp) nodes.push(temp); + nodes.push( + buildDefaultsCallExpression( + path.node, + t.cloneNode(temp || left), + file, + ), + ); + if (temp) nodes.push(t.cloneNode(temp)); path.replaceWithMultiple(nodes); }, diff --git a/packages/babel-plugin-transform-spread/src/index.js b/packages/babel-plugin-transform-spread/src/index.js index 01a877c774..d9827ca8bd 100644 --- a/packages/babel-plugin-transform-spread/src/index.js +++ b/packages/babel-plugin-transform-spread/src/index.js @@ -118,7 +118,7 @@ export default function(api, options) { contextLiteral = t.thisExpression(); } - node.arguments.unshift(contextLiteral); + node.arguments.unshift(t.cloneNode(contextLiteral)); }, NewExpression(path, state) { diff --git a/packages/babel-plugin-transform-template-literals/src/index.js b/packages/babel-plugin-transform-template-literals/src/index.js index f910003fab..6acc478537 100644 --- a/packages/babel-plugin-transform-template-literals/src/index.js +++ b/packages/babel-plugin-transform-template-literals/src/index.js @@ -96,7 +96,10 @@ export default function(api, options) { } path.replaceWith( - t.callExpression(node.tag, [templateObject, ...quasi.expressions]), + t.callExpression(node.tag, [ + t.cloneNode(templateObject), + ...quasi.expressions, + ]), ); }, diff --git a/packages/babel-plugin-transform-typeof-symbol/src/index.js b/packages/babel-plugin-transform-typeof-symbol/src/index.js index d06f6b4979..c32eba7c06 100644 --- a/packages/babel-plugin-transform-typeof-symbol/src/index.js +++ b/packages/babel-plugin-transform-typeof-symbol/src/index.js @@ -48,12 +48,11 @@ export default function() { const call = t.callExpression(helper, [node.argument]); const arg = path.get("argument"); if (arg.isIdentifier() && !path.scope.hasBinding(arg.node.name)) { - const undefLiteral = t.stringLiteral("undefined"); - const unary = t.unaryExpression("typeof", node.argument); + const unary = t.unaryExpression("typeof", t.cloneNode(node.argument)); path.replaceWith( t.conditionalExpression( - t.binaryExpression("===", unary, undefLiteral), - undefLiteral, + t.binaryExpression("===", unary, t.stringLiteral("undefined")), + t.stringLiteral("undefined"), call, ), ); diff --git a/packages/babel-traverse/src/path/lib/hoister.js b/packages/babel-traverse/src/path/lib/hoister.js index ec7b279913..0f6fa03959 100644 --- a/packages/babel-traverse/src/path/lib/hoister.js +++ b/packages/babel-traverse/src/path/lib/hoister.js @@ -222,6 +222,6 @@ export default class PathHoister { uid = t.JSXExpressionContainer(uid); } - this.path.replaceWith(uid); + this.path.replaceWith(t.cloneNode(uid)); } } diff --git a/packages/babel-traverse/src/path/modification.js b/packages/babel-traverse/src/path/modification.js index 19b28c7197..e111c76b0a 100644 --- a/packages/babel-traverse/src/path/modification.js +++ b/packages/babel-traverse/src/path/modification.js @@ -110,9 +110,11 @@ export function insertAfter(nodes) { if (this.node) { const temp = this.scope.generateDeclaredUidIdentifier(); nodes.unshift( - t.expressionStatement(t.assignmentExpression("=", temp, this.node)), + t.expressionStatement( + t.assignmentExpression("=", t.cloneNode(temp), this.node), + ), ); - nodes.push(t.expressionStatement(temp)); + nodes.push(t.expressionStatement(t.cloneNode(temp))); } return this.replaceExpressionWithStatements(nodes); } else if (Array.isArray(this.container)) { diff --git a/packages/babel-traverse/src/path/replacement.js b/packages/babel-traverse/src/path/replacement.js index e3f99aefde..3ce5762877 100644 --- a/packages/babel-traverse/src/path/replacement.js +++ b/packages/babel-traverse/src/path/replacement.js @@ -237,7 +237,9 @@ export function replaceExpressionWithStatements(nodes: Array) { if (!uid) { const callee = this.get("callee"); uid = callee.scope.generateDeclaredUidIdentifier("ret"); - callee.get("body").pushContainer("body", t.returnStatement(uid)); + callee + .get("body") + .pushContainer("body", t.returnStatement(t.cloneNode(uid))); loop.setData("expressionReplacementReturnUid", uid); } else { uid = t.identifier(uid.name); @@ -245,7 +247,9 @@ export function replaceExpressionWithStatements(nodes: Array) { path .get("expression") - .replaceWith(t.assignmentExpression("=", uid, path.node.expression)); + .replaceWith( + t.assignmentExpression("=", t.cloneNode(uid), path.node.expression), + ); } else { path.replaceWith(t.returnStatement(path.node.expression)); } diff --git a/packages/babel-traverse/src/scope/index.js b/packages/babel-traverse/src/scope/index.js index 1473b89254..e06f1f8e96 100644 --- a/packages/babel-traverse/src/scope/index.js +++ b/packages/babel-traverse/src/scope/index.js @@ -213,7 +213,7 @@ export default class Scope { generateDeclaredUidIdentifier(name: string = "temp") { const id = this.generateUidIdentifier(name); this.push({ id }); - return id; + return t.cloneNode(id); } /** @@ -326,7 +326,10 @@ export default class Scope { return null; } else { const id = this.generateUidIdentifierBasedOnNode(node); - if (!dontPush) this.push({ id }); + if (!dontPush) { + this.push({ id }); + return t.cloneNode(id); + } return id; } } diff --git a/packages/babel-types/src/converters/gatherSequenceExpressions.js b/packages/babel-types/src/converters/gatherSequenceExpressions.js index 779f362114..4b526767e2 100644 --- a/packages/babel-types/src/converters/gatherSequenceExpressions.js +++ b/packages/babel-types/src/converters/gatherSequenceExpressions.js @@ -14,6 +14,7 @@ import { assignmentExpression, conditionalExpression, } from "../builders/generated"; +import cloneNode from "../clone/cloneNode"; export default function gatherSequenceExpressions( nodes: Array, @@ -38,7 +39,7 @@ export default function gatherSequenceExpressions( for (const key in bindings) { declars.push({ kind: node.kind, - id: bindings[key], + id: cloneNode(bindings[key]), }); }