Fix reused nodes - part 2 (#7149)

This commit is contained in:
Nicolò Ribaudo 2018-01-11 19:31:48 +01:00
parent 912bcc186d
commit 252ea5a966
20 changed files with 261 additions and 170 deletions

View File

@ -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(

View File

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

View File

@ -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,
),
);
@ -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() ||

View File

@ -41,7 +41,7 @@ function getPrototypeOfExpression(objectRef, isStatic) {
t.identifier("Object"),
t.identifier("getPrototypeOf"),
),
[targetRef],
[t.cloneNode(targetRef)],
),
);
}
@ -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());
}
/**
@ -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(

View File

@ -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),
]),
);
}
@ -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 = "=";

View File

@ -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));
}
},
};
@ -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()),
]),
);

View File

@ -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;
}
}
@ -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;
@ -272,14 +270,14 @@ 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),
]),
);
@ -287,7 +285,7 @@ export default function(api, opts) {
impureComputedPropertyDeclarators,
argument,
callExpression,
] = createObjectSpread(leftPath, file, ref);
] = createObjectSpread(leftPath, file, t.identifier(refName));
if (impureComputedPropertyDeclarators.length > 0) {
nodes.push(
@ -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);
}

View File

@ -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 {

View File

@ -1,12 +1,12 @@
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;
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;
(_foo = foo) === null || _foo === void 0 ? void 0 : _foo(foo);
(_foo2 = foo) === null || _foo2 === void 0 ? void 0 : _foo2.bar();
(_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;
(_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;

View File

@ -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();
@ -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;
@ -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);
@ -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),
),
),
);
}
}
@ -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;
@ -810,7 +831,7 @@ class BlockScoping {
if (has.hasReturn) {
// typeof ret === "object"
retCheck = buildRetCheck({
RETURN: ret,
RETURN: t.identifier(ret),
});
}
@ -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],
),
);
@ -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) {

View File

@ -122,16 +122,18 @@ export default class ClassTransformer {
if (this.isDerived) {
if (this.extendsNative) {
closureArgs.push(
t.callExpression(this.file.addHelper("wrapNativeSuper"), [superName]),
t.callExpression(this.file.addHelper("wrapNativeSuper"), [
t.cloneNode(superName),
]),
);
} else {
closureArgs.push(superName);
closureArgs.push(t.cloneNode(superName));
}
superName = this.scope.generateUidIdentifierBasedOnNode(superName);
closureParams.push(superName);
this.superName = superName;
this.superName = t.cloneNode(superName);
}
//
@ -143,13 +145,15 @@ export default class ClassTransformer {
t.expressionStatement(
t.callExpression(file.addHelper("classCallCheck"), [
t.thisExpression(),
this.classRef,
t.cloneNode(this.classRef),
]),
),
);
}
body = body.concat(this.staticPropBody.map(fn => fn(this.classRef)));
body = body.concat(
this.staticPropBody.map(fn => fn(t.cloneNode(this.classRef))),
);
if (this.classId) {
// named class with only a constructor
@ -157,7 +161,7 @@ export default class ClassTransformer {
}
//
body.push(t.returnStatement(this.classRef));
body.push(t.returnStatement(t.cloneNode(this.classRef)));
const container = t.arrowFunctionExpression(
closureParams,
@ -167,7 +171,11 @@ export default class ClassTransformer {
}
buildConstructor() {
const func = t.functionDeclaration(this.classRef, [], this.constructorBody);
const func = t.functionDeclaration(
t.cloneNode(this.classRef),
[],
this.constructorBody,
);
t.inherits(func, this.node);
return func;
}
@ -327,14 +335,12 @@ export default class ClassTransformer {
staticProps = defineMap.toComputedObjectFromClass(staticProps);
}
const nullNode = t.nullLiteral();
let args = [
this.classRef, // Constructor
nullNode, // instanceDescriptors
nullNode, // staticDescriptors
nullNode, // instanceInitializers
nullNode, // staticInitializers
t.cloneNode(this.classRef), // Constructor
t.nullLiteral(), // instanceDescriptors
t.nullLiteral(), // staticDescriptors
t.nullLiteral(), // instanceInitializers
t.nullLiteral(), // staticInitializers
];
if (instanceProps) args[1] = instanceProps;
@ -352,7 +358,7 @@ export default class ClassTransformer {
let lastNonNullIndex = 0;
for (let i = 0; i < args.length; i++) {
if (args[i] !== nullNode) lastNonNullIndex = i;
if (!t.isNullLiteral(args[i])) lastNonNullIndex = i;
}
args = args.slice(0, lastNonNullIndex + 1);
@ -400,13 +406,16 @@ export default class ClassTransformer {
bareSuperNode = optimiseCall(
t.logicalExpression(
"||",
t.memberExpression(this.classRef, t.identifier("__proto__")),
t.memberExpression(
t.cloneNode(this.classRef),
t.identifier("__proto__"),
),
t.callExpression(
t.memberExpression(
t.identifier("Object"),
t.identifier("getPrototypeOf"),
),
[this.classRef],
[t.cloneNode(this.classRef)],
),
),
t.thisExpression(),
@ -607,7 +616,7 @@ export default class ClassTransformer {
this.isLoose
? this.file.addHelper("inheritsLoose")
: this.file.addHelper("inherits"),
[this.classRef, this.superName],
[t.cloneNode(this.classRef), t.cloneNode(this.superName)],
),
),
);

View File

@ -112,12 +112,10 @@ export default function(api, options) {
// we need to assign the current value of the assignment to avoid evaluating
// it more than once
const tempValueRef = this.scope.generateUidIdentifierBasedOnNode(
valueRef,
);
const tempValueRef = this.scope.generateUidBasedOnNode(valueRef);
const declar = t.variableDeclaration("var", [
t.variableDeclarator(tempValueRef, valueRef),
t.variableDeclarator(t.identifier(tempValueRef), valueRef),
]);
declar._blockHoist = this.blockHoist;
this.nodes.push(declar);
@ -127,22 +125,26 @@ export default function(api, options) {
const tempConditional = t.conditionalExpression(
t.binaryExpression(
"===",
tempValueRef,
t.identifier(tempValueRef),
this.scope.buildUndefinedNode(),
),
pattern.right,
tempValueRef,
t.identifier(tempValueRef),
);
const left = pattern.left;
if (t.isPattern(left)) {
const tempValueDefault = t.expressionStatement(
t.assignmentExpression("=", tempValueRef, tempConditional),
t.assignmentExpression(
"=",
t.identifier(tempValueRef),
tempConditional,
),
);
tempValueDefault._blockHoist = this.blockHoist;
this.nodes.push(tempValueDefault);
this.push(left, tempValueRef);
this.push(left, t.identifier(tempValueRef));
} else {
this.nodes.push(this.buildVariableAssignment(left, tempConditional));
}

View File

@ -25,7 +25,11 @@ export default function(api, options) {
array = right;
}
const item = t.memberExpression(array, t.cloneNode(i), true);
const item = t.memberExpression(
t.cloneNode(array),
t.cloneNode(i),
true,
);
let assignment;
if (t.isVariableDeclaration(left)) {
assignment = left;
@ -112,11 +116,13 @@ export default function(api, options) {
let right = node.right;
if (!t.isIdentifier(right) || !scope.hasBinding(right.name)) {
const uid = scope.generateUidIdentifier("arr");
const uid = scope.generateUid("arr");
nodes.push(
t.variableDeclaration("var", [t.variableDeclarator(uid, right)]),
t.variableDeclaration("var", [
t.variableDeclarator(t.identifier(uid), right),
]),
);
right = uid;
right = t.identifier(uid);
}
const iterationKey = scope.generateUidIdentifier("i");
@ -130,7 +136,11 @@ export default function(api, options) {
t.inherits(loop, node);
t.ensureBlock(loop);
const iterationValue = t.memberExpression(right, iterationKey, true);
const iterationValue = t.memberExpression(
t.cloneNode(right),
t.cloneNode(iterationKey),
true,
);
const left = node.left;
if (t.isVariableDeclaration(left)) {
@ -221,9 +231,11 @@ export default function(api, options) {
// for (let i of test)
id = scope.generateUidIdentifier("ref");
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(left.declarations[0].id, id),
t.variableDeclarator(left.declarations[0].id, t.identifier(id.name)),
]);
intermediate = t.variableDeclaration("var", [
t.variableDeclarator(t.identifier(id.name)),
]);
intermediate = t.variableDeclaration("var", [t.variableDeclarator(id)]);
} else {
throw file.buildCodeFrameError(
left,
@ -264,8 +276,11 @@ export default function(api, options) {
const left = node.left;
let declar;
const stepKey = scope.generateUidIdentifier("step");
const stepValue = t.memberExpression(stepKey, t.identifier("value"));
const stepKey = scope.generateUid("step");
const stepValue = t.memberExpression(
t.identifier(stepKey),
t.identifier("value"),
);
if (
t.isIdentifier(left) ||
@ -288,18 +303,14 @@ export default function(api, options) {
);
}
//
const iteratorKey = scope.generateUidIdentifier("iterator");
const template = buildForOf({
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
ITERATOR_COMPLETION: scope.generateUidIdentifier(
"iteratorNormalCompletion",
),
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
ITERATOR_KEY: iteratorKey,
STEP_KEY: stepKey,
ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
STEP_KEY: t.identifier(stepKey),
OBJECT: node.right,
});

View File

@ -15,7 +15,7 @@ export default function() {
[],
t.blockStatement([
t.toStatement(node),
t.returnStatement(node.id),
t.returnStatement(t.cloneNode(node.id)),
]),
),
[],

View File

@ -50,9 +50,17 @@ export default function(api, options) {
let isPostUpdateExpression = path.isUpdateExpression() && !node.prefix;
if (isPostUpdateExpression) {
if (node.operator === "++") {
node = t.binaryExpression("+", node.argument, t.numericLiteral(1));
node = t.binaryExpression(
"+",
t.cloneNode(node.argument),
t.numericLiteral(1),
);
} else if (node.operator === "--") {
node = t.binaryExpression("-", node.argument, t.numericLiteral(1));
node = t.binaryExpression(
"-",
t.cloneNode(node.argument),
t.numericLiteral(1),
);
} else {
isPostUpdateExpression = false;
}
@ -74,10 +82,12 @@ export default function(api, options) {
visitor: {
CallExpression(path, state) {
if (path.node.callee.type === TYPE_IMPORT) {
const contextIdent = state.contextIdent;
path.replaceWith(
t.callExpression(
t.memberExpression(contextIdent, t.identifier("import")),
t.memberExpression(
t.identifier(state.contextIdent),
t.identifier("import"),
),
path.node.arguments,
),
);
@ -90,17 +100,20 @@ export default function(api, options) {
!path.scope.hasBinding("__moduleName")
) {
path.replaceWith(
t.memberExpression(state.contextIdent, t.identifier("id")),
t.memberExpression(
t.identifier(state.contextIdent),
t.identifier("id"),
),
);
}
},
Program: {
enter(path, state) {
state.contextIdent = path.scope.generateUidIdentifier("context");
state.contextIdent = path.scope.generateUid("context");
},
exit(path, state) {
const exportIdent = path.scope.generateUidIdentifier("export");
const exportIdent = path.scope.generateUid("export");
const contextIdent = state.contextIdent;
const exportNames = Object.create(null);
@ -134,7 +147,10 @@ export default function(api, options) {
function buildExportCall(name, val) {
return t.expressionStatement(
t.callExpression(exportIdent, [t.stringLiteral(name), val]),
t.callExpression(t.identifier(exportIdent), [
t.stringLiteral(name),
val,
]),
);
}
@ -175,7 +191,7 @@ export default function(api, options) {
if (id) {
nodes.push(declar.node);
nodes.push(buildExportCall("default", id));
nodes.push(buildExportCall("default", t.cloneNode(id)));
addExportName(id.name, "default");
} else {
nodes.push(
@ -206,7 +222,9 @@ export default function(api, options) {
if (canHoist) {
addExportName(name, name);
beforeBody.push(node);
beforeBody.push(buildExportCall(name, node.id));
beforeBody.push(
buildExportCall(name, t.cloneNode(node.id)),
);
removedPaths.push(path);
} else {
bindingIdentifiers = { [name]: node.id };
@ -250,13 +268,17 @@ export default function(api, options) {
modules.forEach(function(specifiers) {
const setterBody = [];
const target = path.scope.generateUidIdentifier(specifiers.key);
const target = path.scope.generateUid(specifiers.key);
for (let specifier of specifiers.imports) {
if (t.isImportNamespaceSpecifier(specifier)) {
setterBody.push(
t.expressionStatement(
t.assignmentExpression("=", specifier.local, target),
t.assignmentExpression(
"=",
specifier.local,
t.identifier(target),
),
),
);
} else if (t.isImportDefaultSpecifier(specifier)) {
@ -272,7 +294,10 @@ export default function(api, options) {
t.assignmentExpression(
"=",
specifier.local,
t.memberExpression(target, specifier.imported),
t.memberExpression(
t.identifier(target),
specifier.imported,
),
),
),
);
@ -280,13 +305,14 @@ export default function(api, options) {
}
if (specifiers.exports.length) {
const exportObjRef = path.scope.generateUidIdentifier(
"exportObj",
);
const exportObj = path.scope.generateUid("exportObj");
setterBody.push(
t.variableDeclaration("var", [
t.variableDeclarator(exportObjRef, t.objectExpression([])),
t.variableDeclarator(
t.identifier(exportObj),
t.objectExpression([]),
),
]),
);
@ -295,8 +321,8 @@ export default function(api, options) {
setterBody.push(
buildExportAll({
KEY: path.scope.generateUidIdentifier("key"),
EXPORT_OBJ: exportObjRef,
TARGET: target,
EXPORT_OBJ: t.identifier(exportObj),
TARGET: t.identifier(target),
}),
);
} else if (t.isExportSpecifier(node)) {
@ -304,8 +330,11 @@ export default function(api, options) {
t.expressionStatement(
t.assignmentExpression(
"=",
t.memberExpression(exportObjRef, node.exported),
t.memberExpression(target, node.local),
t.memberExpression(
t.identifier(exportObj),
node.exported,
),
t.memberExpression(t.identifier(target), node.local),
),
),
);
@ -316,7 +345,9 @@ export default function(api, options) {
setterBody.push(
t.expressionStatement(
t.callExpression(exportIdent, [exportObjRef]),
t.callExpression(t.identifier(exportIdent), [
t.identifier(exportObj),
]),
),
);
}
@ -325,7 +356,7 @@ export default function(api, options) {
setters.push(
t.functionExpression(
null,
[target],
[t.identifier(target)],
t.blockStatement(setterBody),
),
);
@ -368,8 +399,8 @@ export default function(api, options) {
SETTERS: t.arrayExpression(setters),
SOURCES: t.arrayExpression(sources),
BODY: path.node.body,
EXPORT_IDENTIFIER: exportIdent,
CONTEXT_IDENTIFIER: contextIdent,
EXPORT_IDENTIFIER: t.identifier(exportIdent),
CONTEXT_IDENTIFIER: t.identifier(contextIdent),
}),
];
},

View File

@ -68,7 +68,9 @@ export default function(api, options) {
const members = globalName.split(".");
globalToAssign = members.slice(1).reduce((accum, curr) => {
initAssignments.push(
buildPrerequisiteAssignment({ GLOBAL_REFERENCE: accum }),
buildPrerequisiteAssignment({
GLOBAL_REFERENCE: t.cloneNode(accum),
}),
);
return t.memberExpression(accum, t.identifier(curr));
}, t.memberExpression(t.identifier("global"), t.identifier(members[0])));

View File

@ -289,8 +289,7 @@ export default function convertFunctionRest(path) {
const key = scope.generateUidIdentifier("key");
const len = scope.generateUidIdentifier("len");
let arrKey = key;
let arrLen = len;
let arrKey, arrLen;
if (node.params.length) {
// this method has additional params, so we need to subtract
// the index of the current argument position from the
@ -308,6 +307,9 @@ export default function convertFunctionRest(path) {
t.binaryExpression("-", t.cloneNode(len), t.cloneNode(start)),
t.numericLiteral(0),
);
} else {
arrKey = t.identifier(key.name);
arrLen = t.identifier(len.name);
}
const loop = buildRest({

View File

@ -1,4 +1,5 @@
import assert from "assert";
import { template } from "@babel/core";
export default function transpileEnum(path, t) {
const { node } = path;
@ -50,37 +51,41 @@ function makeVar(id, t, kind): VariableDeclaration {
return t.variableDeclaration(kind, [t.variableDeclarator(id)]);
}
const buildEnumWrapper = template(`
(function (ID) {
ASSIGNMENTS;
})(ID || (ID = {}));
`);
const buildStringAssignment = template(`
ENUM["NAME"] = VALUE;
`);
const buildNumericAssignment = template(`
ENUM[ENUM["NAME"] = VALUE] = "NAME";
`);
const buildEnumMember = (isString, options) =>
(isString ? buildStringAssignment : buildNumericAssignment)(options);
/**
* Generates the statement that fills in the variable declared by the enum.
* `(function (E) { ... assignments ... })(E || (E = {}));`
*/
function enumFill(path, t, id) {
const x = translateEnumValues(path, t);
const assignments = x.map(([memberName, memberValue]) => {
const inner = t.assignmentExpression(
"=",
t.memberExpression(id, t.stringLiteral(memberName), /*computed*/ true),
memberValue,
const assignments = x.map(([memberName, memberValue]) =>
buildEnumMember(t.isStringLiteral(memberValue), {
ENUM: t.cloneNode(id),
NAME: memberName,
VALUE: memberValue,
}),
);
const outer = t.isStringLiteral(memberValue)
? inner
: t.assignmentExpression(
"=",
t.memberExpression(id, inner, /*computed*/ true),
t.stringLiteral(memberName),
);
return t.expressionStatement(outer);
});
// E || (E = {})
const callArg = t.logicalExpression(
"||",
id,
t.assignmentExpression("=", id, t.objectExpression([])),
);
const body = t.blockStatement(assignments);
const callee = t.functionExpression(null, [id], body);
return t.expressionStatement(t.callExpression(callee, [callArg]));
return buildEnumWrapper({
ID: t.cloneNode(id),
ASSIGNMENTS: assignments,
});
}
/**

View File

@ -114,9 +114,11 @@ export default function() {
);
}
const id = t.identifier(name);
const thisDotName = t.memberExpression(t.thisExpression(), id);
const assign = t.assignmentExpression("=", thisDotName, id);
const assign = t.assignmentExpression(
"=",
t.memberExpression(t.thisExpression(), t.identifier(name)),
t.identifier(name),
);
return t.expressionStatement(assign);
});

View File

@ -263,14 +263,7 @@ export default class Scope {
return `_${id}`;
}
/**
* Generate a unique identifier based on a node.
*/
generateUidIdentifierBasedOnNode(
parent: Object,
defaultName?: String,
): Object {
generateUidBasedOnNode(parent: Object, defaultName?: String) {
let node = parent;
if (t.isAssignmentExpression(parent)) {
@ -287,7 +280,18 @@ export default class Scope {
let id = parts.join("$");
id = id.replace(/^_/, "") || defaultName || "ref";
return this.generateUidIdentifier(id.slice(0, 20));
return this.generateUid(id.slice(0, 20));
}
/**
* Generate a unique identifier based on a node.
*/
generateUidIdentifierBasedOnNode(
parent: Object,
defaultName?: String,
): Object {
return t.identifier(this.generateUidBasedOnNode(parent, defaultName));
}
/**