Skip to content

Commit

Permalink
Fix reused nodes - part 1 (babel#7149)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist authored and aminmarashi committed Mar 17, 2018
1 parent 721cd68 commit 0c98970
Show file tree
Hide file tree
Showing 30 changed files with 202 additions and 117 deletions.
2 changes: 1 addition & 1 deletion packages/babel-core/src/transformation/file/file.js
Expand Up @@ -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");
Expand Down
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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 {
Expand Down
17 changes: 13 additions & 4 deletions packages/babel-helper-replace-supers/src/index.js
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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,
),
),
),
];
Expand Down
17 changes: 13 additions & 4 deletions packages/babel-plugin-proposal-class-properties/src/index.js
Expand Up @@ -54,15 +54,19 @@ 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(),
});
};

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(),
});
};
Expand Down Expand Up @@ -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()],
),
),
Expand Down Expand Up @@ -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;
Expand Down
46 changes: 26 additions & 20 deletions packages/babel-plugin-proposal-decorators/src/index.js
Expand Up @@ -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);
Expand Down Expand Up @@ -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"),
Expand All @@ -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),
]),
);
}
Expand All @@ -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),
]);
}

Expand All @@ -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)),
]);
Expand All @@ -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 {
Expand Down Expand Up @@ -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),
]),
);
},
Expand Down
Expand Up @@ -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) {
Expand Down
Expand Up @@ -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) {
Expand Down
20 changes: 13 additions & 7 deletions packages/babel-plugin-proposal-object-rest-spread/src/index.js
Expand Up @@ -95,7 +95,7 @@ export default function(api, opts) {
impureComputedPropertyDeclarators,
restElement.argument,
t.callExpression(file.addHelper("objectWithoutProperties"), [
objRef,
t.cloneNode(objRef),
keyExpression,
]),
];
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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)),
]),
);
},
Expand Down
11 changes: 7 additions & 4 deletions packages/babel-plugin-proposal-optional-chaining/src/index.js
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
Expand All @@ -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"));
}
}
Expand All @@ -83,7 +86,7 @@ export default function(api, options) {
scope.buildUndefinedNode(),
),
),
nil,
scope.buildUndefinedNode(),
replacementPath.node,
),
);
Expand Down
@@ -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;
4 changes: 2 additions & 2 deletions packages/babel-plugin-proposal-pipeline-operator/src/index.js
Expand Up @@ -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,
]),
);
Expand Down

0 comments on commit 0c98970

Please sign in to comment.