Fix duplicated assertThisInitialized calls in constructors (#9458)
This commit is contained in:
committed by
Nicolò Ribaudo
parent
d1514f57bd
commit
045d019149
@@ -32,25 +32,6 @@ const verifyConstructorVisitor = traverse.visitors.merge([
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
ThisExpression(path, state) {
|
||||
if (!state.isDerived) return;
|
||||
|
||||
const { node, parentPath } = path;
|
||||
if (parentPath.isMemberExpression({ object: node })) {
|
||||
// In cases like this.foo or this[foo], there is no need to add
|
||||
// assertThisInitialized, since they already throw if this is
|
||||
// undefined.
|
||||
return;
|
||||
}
|
||||
|
||||
const assertion = t.callExpression(
|
||||
state.file.addHelper("assertThisInitialized"),
|
||||
[node],
|
||||
);
|
||||
path.replaceWith(assertion);
|
||||
path.skip();
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -84,7 +65,6 @@ export default function transformClass(
|
||||
instancePropRefs: {},
|
||||
staticPropBody: [],
|
||||
body: [],
|
||||
bareSupers: new Set(),
|
||||
superThises: [],
|
||||
pushedConstructor: false,
|
||||
pushedInherits: false,
|
||||
@@ -217,34 +197,22 @@ export default function transformClass(
|
||||
|
||||
replaceSupers.replace();
|
||||
|
||||
// TODO this needs to be cleaned up. But, one step at a time.
|
||||
const state = {
|
||||
returns: [],
|
||||
bareSupers: new Set(),
|
||||
};
|
||||
const superReturns = [];
|
||||
path.traverse(
|
||||
traverse.visitors.merge([
|
||||
environmentVisitor,
|
||||
{
|
||||
ReturnStatement(path, state) {
|
||||
ReturnStatement(path) {
|
||||
if (!path.getFunctionParent().isArrowFunctionExpression()) {
|
||||
state.returns.push(path);
|
||||
}
|
||||
},
|
||||
|
||||
Super(path, state) {
|
||||
const { node, parentPath } = path;
|
||||
if (parentPath.isCallExpression({ callee: node })) {
|
||||
state.bareSupers.add(parentPath);
|
||||
superReturns.push(path);
|
||||
}
|
||||
},
|
||||
},
|
||||
]),
|
||||
state,
|
||||
);
|
||||
|
||||
if (isConstructor) {
|
||||
pushConstructor(state, node, path);
|
||||
pushConstructor(superReturns, node, path);
|
||||
} else {
|
||||
pushMethod(node, path);
|
||||
}
|
||||
@@ -378,15 +346,43 @@ export default function transformClass(
|
||||
|
||||
path.traverse(findThisesVisitor);
|
||||
|
||||
let guaranteedSuperBeforeFinish = !!classState.bareSupers.size;
|
||||
|
||||
let thisRef = function() {
|
||||
const ref = path.scope.generateDeclaredUidIdentifier("this");
|
||||
thisRef = () => t.cloneNode(ref);
|
||||
return ref;
|
||||
};
|
||||
|
||||
for (const bareSuper of classState.bareSupers) {
|
||||
for (const thisPath of classState.superThises) {
|
||||
const { node, parentPath } = thisPath;
|
||||
if (parentPath.isMemberExpression({ object: node })) {
|
||||
thisPath.replaceWith(thisRef());
|
||||
continue;
|
||||
}
|
||||
thisPath.replaceWith(
|
||||
t.callExpression(classState.file.addHelper("assertThisInitialized"), [
|
||||
thisRef(),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
const bareSupers = new Set();
|
||||
path.traverse(
|
||||
traverse.visitors.merge([
|
||||
environmentVisitor,
|
||||
{
|
||||
Super(path) {
|
||||
const { node, parentPath } = path;
|
||||
if (parentPath.isCallExpression({ callee: node })) {
|
||||
bareSupers.add(parentPath);
|
||||
}
|
||||
},
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
let guaranteedSuperBeforeFinish = !!bareSupers.size;
|
||||
|
||||
for (const bareSuper of bareSupers) {
|
||||
wrapSuperCall(bareSuper, classState.superName, thisRef, body);
|
||||
|
||||
if (guaranteedSuperBeforeFinish) {
|
||||
@@ -408,19 +404,6 @@ export default function transformClass(
|
||||
}
|
||||
}
|
||||
|
||||
for (const thisPath of classState.superThises) {
|
||||
const { node, parentPath } = thisPath;
|
||||
if (parentPath.isMemberExpression({ object: node })) {
|
||||
thisPath.replaceWith(thisRef());
|
||||
continue;
|
||||
}
|
||||
thisPath.replaceWith(
|
||||
t.callExpression(classState.file.addHelper("assertThisInitialized"), [
|
||||
thisRef(),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
let wrapReturn;
|
||||
|
||||
if (classState.isLoose) {
|
||||
@@ -535,7 +518,7 @@ export default function transformClass(
|
||||
* Replace the constructor body of our class.
|
||||
*/
|
||||
function pushConstructor(
|
||||
replaceSupers,
|
||||
superReturns,
|
||||
method: { type: "ClassMethod" },
|
||||
path: NodePath,
|
||||
) {
|
||||
@@ -548,8 +531,7 @@ export default function transformClass(
|
||||
userConstructorPath: path,
|
||||
userConstructor: method,
|
||||
hasConstructor: true,
|
||||
bareSupers: replaceSupers.bareSupers,
|
||||
superReturns: replaceSupers.returns,
|
||||
superReturns,
|
||||
});
|
||||
|
||||
const { construct } = classState;
|
||||
|
||||
Reference in New Issue
Block a user