Skip to content

Commit 5fd73d6

Browse files
authored
acorn-optimizer: improve for-var elimination (#24353)
- Simplify `var` handling in `for` loops by handling them directly during traversal instead of store-restore. - Allow to remove unused `var` in a plain C-style `for` loop. Split out from #24348.
1 parent d4cd0c7 commit 5fd73d6

File tree

2 files changed

+18
-34
lines changed

2 files changed

+18
-34
lines changed

test/js_optimizer/JSDCE-fors-output.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ for (var i in x) {}
22

33
for (var i of [ 1, 2, 3 ]) {}
44

5-
for (var j = 0; ;) {}
5+
for (;;) {}

tools/acorn-optimizer.mjs

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -145,35 +145,6 @@ function restoreInnerScopes(node, map) {
145145
});
146146
}
147147

148-
// If we empty out a var from
149-
// for (var i in x) {}
150-
// for (var j = 0;;) {}
151-
// then it will be invalid. We saved it on the side;
152-
// restore it here.
153-
function restoreForVars(node) {
154-
let restored = 0;
155-
function fix(init) {
156-
if (init && init.type === 'EmptyStatement') {
157-
assertAt(init.oldDeclarations, init);
158-
init.type = 'VariableDeclaration';
159-
init.declarations = init.oldDeclarations;
160-
restored++;
161-
}
162-
}
163-
simpleWalk(node, {
164-
ForStatement(node) {
165-
fix(node.init);
166-
},
167-
ForInStatement(node) {
168-
fix(node.left);
169-
},
170-
ForOfStatement(node) {
171-
fix(node.left);
172-
},
173-
});
174-
return restored;
175-
}
176-
177148
function hasSideEffects(node) {
178149
// Conservative analysis.
179150
const map = ignoreInnerScopes(node);
@@ -272,8 +243,24 @@ function JSDCE(ast, aggressive) {
272243
}
273244
function cleanUp(ast, names) {
274245
recursiveWalk(ast, {
246+
ForStatement(node, c) {
247+
visitChildren(node, c);
248+
// If we had `for (var x = ...; ...)` and we removed `x`, we need to change to `for (; ...)`.
249+
if (node.init?.type === 'EmptyStatement') {
250+
node.init = null;
251+
}
252+
},
253+
ForInStatement(node, c) {
254+
// We can't remove the var in a for-in, as that would result in an invalid syntax. Skip the LHS.
255+
c(node.right);
256+
c(node.body);
257+
},
258+
ForOfStatement(node, c) {
259+
// We can't remove the var in a for-of, as that would result in an invalid syntax. Skip the LHS.
260+
c(node.right);
261+
c(node.body);
262+
},
275263
VariableDeclaration(node, _c) {
276-
const old = node.declarations;
277264
let removedHere = 0;
278265
node.declarations = node.declarations.filter((node) => {
279266
assert(node.type === 'VariableDeclarator');
@@ -294,8 +281,6 @@ function JSDCE(ast, aggressive) {
294281
removed += removedHere;
295282
if (node.declarations.length === 0) {
296283
emptyOut(node);
297-
// If this is in a for, we may need to restore it.
298-
node.oldDeclarations = old;
299284
}
300285
},
301286
ExpressionStatement(node, _c) {
@@ -316,7 +301,6 @@ function JSDCE(ast, aggressive) {
316301
FunctionExpression() {},
317302
ArrowFunctionExpression() {},
318303
});
319-
removed -= restoreForVars(ast);
320304
}
321305

322306
function handleFunction(node, c, defun) {

0 commit comments

Comments
 (0)