Skip to content

Commit

Permalink
Fix reused nodes - part 2 (babel#7149)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo authored and aminmarashi committed Mar 17, 2018
1 parent 0c98970 commit 2191e70
Show file tree
Hide file tree
Showing 20 changed files with 261 additions and 170 deletions.
2 changes: 1 addition & 1 deletion packages/babel-core/src/transformation/file/file.js
Expand Up @@ -131,7 +131,7 @@ export default class File {
const res = generator(name);
if (res) return res;
} else if (runtime) {
return t.memberExpression(runtime, t.identifier(name));
return t.memberExpression(t.cloneNode(runtime), t.identifier(name));
}

const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-helper-function-name/src/index.js
Expand Up @@ -154,7 +154,7 @@ export default function({ node, parent, scope, id }, localBinding = false) {
scope.getBinding(id.name) === binding
) {
// always going to reference this method
node.id = id;
node.id = t.cloneNode(id);
node.id[t.NOT_LOCAL_BINDING] = true;
return;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-helper-remap-async-to-generator/src/index.js
Expand Up @@ -22,7 +22,7 @@ const awaitVisitor = {
path.replaceWith(
t.yieldExpression(
wrapAwait
? t.callExpression(wrapAwait, [argument.node])
? t.callExpression(t.cloneNode(wrapAwait), [argument.node])
: argument.node,
),
);
Expand Down Expand Up @@ -73,7 +73,7 @@ export default function(path: NodePath, file: Object, helpers: Object) {
path.node.async = false;
path.node.generator = true;

wrapFunction(path, helpers.wrapAsync);
wrapFunction(path, t.cloneNode(helpers.wrapAsync));

const isProperty =
path.isObjectMethod() ||
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-helper-replace-supers/src/index.js
Expand Up @@ -41,7 +41,7 @@ function getPrototypeOfExpression(objectRef, isStatic) {
t.identifier("Object"),
t.identifier("getPrototypeOf"),
),
[targetRef],
[t.cloneNode(targetRef)],
),
);
}
Expand Down Expand Up @@ -141,7 +141,7 @@ export default class ReplaceSupers {
};

getObjectRef() {
return this.opts.objectRef || this.opts.getObjectRef();
return t.cloneNode(this.opts.objectRef || this.opts.getObjectRef());
}

/**
Expand Down Expand Up @@ -244,7 +244,7 @@ export default class ReplaceSupers {
ref = ref || path.scope.generateUidIdentifier("ref");
return [
t.variableDeclaration("var", [
t.variableDeclarator(t.cloneNode(ref), node.left),
t.variableDeclarator(t.cloneNode(ref), t.cloneNode(node.left)),
]),
t.expressionStatement(
t.assignmentExpression(
Expand Down
14 changes: 7 additions & 7 deletions packages/babel-helper-simple-access/src/index.js
Expand Up @@ -33,20 +33,20 @@ const simpleAssignmentVisitor = {
t.assignmentExpression("+=", arg.node, t.numericLiteral(1)),
);
} else {
const varName = path.scope.generateDeclaredUidIdentifier("old");
const varName = path.scope.generateDeclaredUidIdentifier("old").name;

const assignment = t.binaryExpression(
const binary = t.binaryExpression(
path.node.operator.slice(0, 1),
varName,
t.identifier(varName),
t.numericLiteral(1),
);

// i++ => (_tmp = i, i = _tmp + 1, _tmp)
path.replaceWith(
t.sequenceExpression([
t.assignmentExpression("=", varName, arg.node),
t.assignmentExpression("=", arg.node, assignment),
varName,
t.assignmentExpression("=", t.identifier(varName), arg.node),
t.assignmentExpression("=", t.cloneNode(arg.node), binary),
t.identifier(varName),
]),
);
}
Expand Down Expand Up @@ -78,7 +78,7 @@ const simpleAssignmentVisitor = {

path.node.right = t.binaryExpression(
path.node.operator.slice(0, -1),
path.node.left,
t.cloneNode(path.node.left),
path.node.right,
);
path.node.operator = "=";
Expand Down
19 changes: 11 additions & 8 deletions packages/babel-plugin-proposal-function-sent/src/index.js
Expand Up @@ -7,23 +7,26 @@ export default function() {
t.isIdentifier(node.meta, { name: "function" }) &&
t.isIdentifier(node.property, { name: "sent" });

const hasBeenReplaced = (node, sentId) =>
t.isAssignmentExpression(node) &&
t.isIdentifier(node.left, { name: sentId });

const yieldVisitor = {
Function(path) {
path.skip();
},

YieldExpression(path) {
const replaced = t.isAssignmentExpression(path.parent, {
left: this.sentId,
});
if (!replaced) {
path.replaceWith(t.assignmentExpression("=", this.sentId, path.node));
if (!hasBeenReplaced(path.parent, this.sentId)) {
path.replaceWith(
t.assignmentExpression("=", t.identifier(this.sentId), path.node),
);
}
},

MetaProperty(path) {
if (isFunctionSent(path.node)) {
path.replaceWith(this.sentId);
path.replaceWith(t.identifier(this.sentId));
}
},
};
Expand All @@ -41,12 +44,12 @@ export default function() {
throw new Error("Parent generator function not found");
}

const sentId = path.scope.generateUidIdentifier("function.sent");
const sentId = path.scope.generateUid("function.sent");

fnPath.traverse(yieldVisitor, { sentId });
fnPath.node.body.body.unshift(
t.variableDeclaration("let", [
t.variableDeclarator(sentId, t.yieldExpression()),
t.variableDeclarator(t.identifier(sentId), t.yieldExpression()),
]),
);

Expand Down
23 changes: 9 additions & 14 deletions packages/babel-plugin-proposal-object-rest-spread/src/index.js
Expand Up @@ -43,7 +43,7 @@ export default function(api, opts) {
} else if (t.isLiteral(prop.key)) {
keys.push(t.stringLiteral(String(prop.key.value)));
} else {
keys.push(prop.key);
keys.push(t.cloneNode(prop.key));
allLiteral = false;
}
}
Expand All @@ -58,12 +58,10 @@ export default function(api, opts) {
for (const propPath of path.get("properties")) {
const key = propPath.get("key");
if (propPath.node.computed && !key.isPure()) {
const identifier = path.scope.generateUidIdentifierBasedOnNode(
key.node,
);
const declarator = t.variableDeclarator(identifier, key.node);
const name = path.scope.generateUidBasedOnNode(key.node);
const declarator = t.variableDeclarator(t.identifier(name), key.node);
impureComputedPropertyDeclarators.push(declarator);
key.replaceWith(identifier);
key.replaceWith(t.identifier(name));
}
}
return impureComputedPropertyDeclarators;
Expand Down Expand Up @@ -272,22 +270,22 @@ export default function(api, opts) {
if (leftPath.isObjectPattern() && hasRestElement(leftPath)) {
const nodes = [];

const ref = path.scope.generateUidIdentifierBasedOnNode(
const refName = path.scope.generateUidBasedOnNode(
path.node.right,
"ref",
);

nodes.push(
t.variableDeclaration("var", [
t.variableDeclarator(ref, path.node.right),
t.variableDeclarator(t.identifier(refName), path.node.right),
]),
);

const [
impureComputedPropertyDeclarators,
argument,
callExpression,
] = createObjectSpread(leftPath, file, ref);
] = createObjectSpread(leftPath, file, t.identifier(refName));

if (impureComputedPropertyDeclarators.length > 0) {
nodes.push(
Expand All @@ -296,17 +294,14 @@ export default function(api, opts) {
}

const nodeWithoutSpread = t.cloneNode(path.node);
nodeWithoutSpread.right = ref;
nodeWithoutSpread.right = t.identifier(refName);
nodes.push(t.expressionStatement(nodeWithoutSpread));
nodes.push(
t.toStatement(
t.assignmentExpression("=", argument, callExpression),
),
);

if (ref) {
nodes.push(t.expressionStatement(ref));
}
nodes.push(t.expressionStatement(t.identifier(refName)));

path.replaceWithMultiple(nodes);
}
Expand Down
Expand Up @@ -42,7 +42,9 @@ export default function(api, options) {
check = t.assignmentExpression(
"=",
t.cloneNode(ref),
t.cloneNode(chain),
// Here `chain` MUST NOT be cloned because it could be updated
// when generating the memoised context of a call espression
chain,
);
node[replaceKey] = ref;
} else {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 41 additions & 18 deletions packages/babel-plugin-transform-block-scoping/src/index.js
Expand Up @@ -524,7 +524,7 @@ class BlockScoping {
this.hoistVarDeclarations();

// turn outsideLetReferences into an array
const args = values(outsideRefs);
const args = values(outsideRefs).map(id => t.cloneNode(id));
const params = args.map(id => t.cloneNode(id));

const isSwitch = this.blockPath.isSwitchStatement();
Expand Down Expand Up @@ -569,10 +569,12 @@ class BlockScoping {
let placeholderPath;
let index;
if (this.has.hasReturn || this.has.hasBreakContinue) {
const ret = this.scope.generateUidIdentifier("ret");
const ret = this.scope.generateUid("ret");

this.body.push(
t.variableDeclaration("var", [t.variableDeclarator(ret, call)]),
t.variableDeclaration("var", [
t.variableDeclarator(t.identifier(ret), call),
]),
);
placeholderPath = "declarations.0.init" + basePath;
index = this.body.length - 1;
Expand Down Expand Up @@ -600,12 +602,14 @@ class BlockScoping {

let fnPath;
if (this.loop) {
const ref = this.scope.generateUidIdentifier("loop");
const loopId = this.scope.generateUid("loop");
const p = this.loopPath.insertBefore(
t.variableDeclaration("var", [t.variableDeclarator(ref, fn)]),
t.variableDeclaration("var", [
t.variableDeclarator(t.identifier(loopId), fn),
]),
);

placeholder.replaceWith(ref);
placeholder.replaceWith(t.identifier(loopId));
fnPath = p[0].get("declarations.0.init");
} else {
placeholder.replaceWith(fn);
Expand Down Expand Up @@ -637,20 +641,33 @@ class BlockScoping {
const param = fn.params[i];
if (!state.reassignments[param.name]) continue;

const newParam = this.scope.generateUidIdentifier(param.name);
fn.params[i] = newParam;
const paramName = param.name;
const newParamName = this.scope.generateUid(param.name);
fn.params[i] = t.identifier(newParamName);

this.scope.rename(param.name, newParam.name, fn);
this.scope.rename(paramName, newParamName, fn);

state.returnStatements.forEach(returnStatement => {
returnStatement.insertBefore(
t.expressionStatement(t.assignmentExpression("=", param, newParam)),
t.expressionStatement(
t.assignmentExpression(
"=",
t.identifier(paramName),
t.identifier(newParamName),
),
),
);
});

// assign outer reference as it's been modified internally and needs to be retained
fn.body.body.push(
t.expressionStatement(t.assignmentExpression("=", param, newParam)),
t.expressionStatement(
t.assignmentExpression(
"=",
t.identifier(paramName),
t.identifier(newParamName),
),
),
);
}
}
Expand Down Expand Up @@ -793,14 +810,18 @@ class BlockScoping {
const declar = node.declarations[i];
if (!declar.init) continue;

const expr = t.assignmentExpression("=", declar.id, declar.init);
const expr = t.assignmentExpression(
"=",
t.cloneNode(declar.id),
t.cloneNode(declar.init),
);
replace.push(t.inherits(expr, declar));
}

return replace;
}

buildHas(ret: { type: "Identifier" }) {
buildHas(ret: string) {
const body = this.body;

let retCheck;
Expand All @@ -810,7 +831,7 @@ class BlockScoping {
if (has.hasReturn) {
// typeof ret === "object"
retCheck = buildRetCheck({
RETURN: ret,
RETURN: t.identifier(ret),
});
}

Expand All @@ -827,7 +848,7 @@ class BlockScoping {
const single = cases[0];
body.push(
t.ifStatement(
t.binaryExpression("===", ret, single.test),
t.binaryExpression("===", t.identifier(ret), single.test),
single.consequent[0],
),
);
Expand All @@ -837,13 +858,15 @@ class BlockScoping {
for (let i = 0; i < cases.length; i++) {
const caseConsequent = cases[i].consequent[0];
if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) {
caseConsequent.label = this.loopLabel =
this.loopLabel || this.scope.generateUidIdentifier("loop");
if (!this.loopLabel) {
this.loopLabel = this.scope.generateUidIdentifier("loop");
}
caseConsequent.label = t.cloneNode(this.loopLabel);
}
}
}

body.push(t.switchStatement(ret, cases));
body.push(t.switchStatement(t.identifier(ret), cases));
}
} else {
if (has.hasReturn) {
Expand Down

0 comments on commit 2191e70

Please sign in to comment.