Skip to content

Commit 95409bd

Browse files
authored
Merge pull request #10294 from ngg/asmjs-4
backport: do not evaluate constants in asm.js, fix IIFE mode detection
2 parents 71be3bf + 7a30012 commit 95409bd

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

lib/ConstPlugin.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class ConstPlugin {
119119

120120
const handler = parser => {
121121
parser.hooks.statementIf.tap("ConstPlugin", statement => {
122+
if (parser.scope.isAsmJs) return;
122123
const param = parser.evaluateExpression(statement.test);
123124
const bool = param.asBool();
124125
if (typeof bool === "boolean") {
@@ -189,6 +190,7 @@ class ConstPlugin {
189190
parser.hooks.expressionConditionalOperator.tap(
190191
"ConstPlugin",
191192
expression => {
193+
if (parser.scope.isAsmJs) return;
192194
const param = parser.evaluateExpression(expression.test);
193195
const bool = param.asBool();
194196
if (typeof bool === "boolean") {
@@ -224,6 +226,7 @@ class ConstPlugin {
224226
parser.hooks.expressionLogicalOperator.tap(
225227
"ConstPlugin",
226228
expression => {
229+
if (parser.scope.isAsmJs) return;
227230
if (
228231
expression.operator === "&&" ||
229232
expression.operator === "||"
@@ -309,6 +312,7 @@ class ConstPlugin {
309312
parser.hooks.evaluateIdentifier
310313
.for("__resourceQuery")
311314
.tap("ConstPlugin", expr => {
315+
if (parser.scope.isAsmJs) return;
312316
if (!parser.state.module) return;
313317
return ParserHelpers.evaluateToString(
314318
getQuery(parser.state.module.resource)
@@ -317,6 +321,7 @@ class ConstPlugin {
317321
parser.hooks.expression
318322
.for("__resourceQuery")
319323
.tap("ConstPlugin", () => {
324+
if (parser.scope.isAsmJs) return;
320325
if (!parser.state.module) return;
321326
parser.state.current.addVariable(
322327
"__resourceQuery",

lib/Parser.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ class Parser extends Tapable {
12291229
this.walkPattern(param);
12301230
}
12311231
if (statement.body.type === "BlockStatement") {
1232-
this.detectStrictMode(statement.body.body);
1232+
this.detectMode(statement.body.body);
12331233
this.prewalkStatement(statement.body);
12341234
this.walkStatement(statement.body);
12351235
} else {
@@ -1697,7 +1697,7 @@ class Parser extends Tapable {
16971697
this.walkPattern(param);
16981698
}
16991699
if (expression.body.type === "BlockStatement") {
1700-
this.detectStrictMode(expression.body.body);
1700+
this.detectMode(expression.body.body);
17011701
this.prewalkStatement(expression.body);
17021702
this.walkStatement(expression.body);
17031703
} else {
@@ -1713,7 +1713,7 @@ class Parser extends Tapable {
17131713
this.walkPattern(param);
17141714
}
17151715
if (expression.body.type === "BlockStatement") {
1716-
this.detectStrictMode(expression.body.body);
1716+
this.detectMode(expression.body.body);
17171717
this.prewalkStatement(expression.body);
17181718
this.walkStatement(expression.body);
17191719
} else {
@@ -1894,6 +1894,7 @@ class Parser extends Tapable {
18941894
this.scope.renames.set(params[i].name, param);
18951895
}
18961896
if (functionExpression.body.type === "BlockStatement") {
1897+
this.detectMode(functionExpression.body.body);
18971898
this.prewalkStatement(functionExpression.body);
18981899
this.walkStatement(functionExpression.body);
18991900
} else {
@@ -2001,6 +2002,7 @@ class Parser extends Tapable {
20012002
inTry: false,
20022003
inShorthand: false,
20032004
isStrict: oldScope.isStrict,
2005+
isAsmJs: oldScope.isAsmJs,
20042006
definitions: oldScope.definitions.createChild(),
20052007
renames: oldScope.renames.createChild()
20062008
};
@@ -2024,6 +2026,7 @@ class Parser extends Tapable {
20242026
inTry: false,
20252027
inShorthand: false,
20262028
isStrict: oldScope.isStrict,
2029+
isAsmJs: oldScope.isAsmJs,
20272030
definitions: oldScope.definitions.createChild(),
20282031
renames: oldScope.renames.createChild()
20292032
};
@@ -2049,6 +2052,7 @@ class Parser extends Tapable {
20492052
inTry: oldScope.inTry,
20502053
inShorthand: false,
20512054
isStrict: oldScope.isStrict,
2055+
isAsmJs: oldScope.isAsmJs,
20522056
definitions: oldScope.definitions.createChild(),
20532057
renames: oldScope.renames.createChild()
20542058
};
@@ -2058,15 +2062,23 @@ class Parser extends Tapable {
20582062
this.scope = oldScope;
20592063
}
20602064

2065+
// TODO webpack 5: remove this methods
2066+
// only for backward-compat
20612067
detectStrictMode(statements) {
2062-
const isStrict =
2068+
this.detectMode(statements);
2069+
}
2070+
2071+
detectMode(statements) {
2072+
const isLiteral =
20632073
statements.length >= 1 &&
20642074
statements[0].type === "ExpressionStatement" &&
2065-
statements[0].expression.type === "Literal" &&
2066-
statements[0].expression.value === "use strict";
2067-
if (isStrict) {
2075+
statements[0].expression.type === "Literal";
2076+
if (isLiteral && statements[0].expression.value === "use strict") {
20682077
this.scope.isStrict = true;
20692078
}
2079+
if (isLiteral && statements[0].expression.value === "use asm") {
2080+
this.scope.isAsmJs = true;
2081+
}
20702082
}
20712083

20722084
enterPatterns(patterns, onIdent) {
@@ -2272,13 +2284,14 @@ class Parser extends Tapable {
22722284
inTry: false,
22732285
inShorthand: false,
22742286
isStrict: false,
2287+
isAsmJs: false,
22752288
definitions: new StackedSetMap(),
22762289
renames: new StackedSetMap()
22772290
};
22782291
const state = (this.state = initialState || {});
22792292
this.comments = comments;
22802293
if (this.hooks.program.call(ast, comments) === undefined) {
2281-
this.detectStrictMode(ast.body);
2294+
this.detectMode(ast.body);
22822295
this.prewalkStatements(ast.body);
22832296
this.blockPrewalkStatements(ast.body);
22842297
this.walkStatements(ast.body);

test/Compiler.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,26 @@ describe("Compiler", () => {
168168
done();
169169
});
170170
});
171+
172+
it("should not evaluate constants in asm.js", done => {
173+
compile("./asmjs", {}, (stats, files) => {
174+
expect(Object.keys(files)).toEqual(["/main.js"]);
175+
const bundle = files["/main.js"];
176+
expect(bundle).toMatch('"use asm";');
177+
expect(bundle).toMatch("101");
178+
expect(bundle).toMatch("102");
179+
expect(bundle).toMatch("103");
180+
expect(bundle).toMatch("104");
181+
expect(bundle).toMatch("105");
182+
expect(bundle).not.toMatch("106");
183+
expect(bundle).not.toMatch("107");
184+
expect(bundle).not.toMatch("108");
185+
expect(bundle).toMatch("109");
186+
expect(bundle).toMatch("110");
187+
done();
188+
});
189+
});
190+
171191
describe("methods", () => {
172192
let compiler;
173193
beforeEach(() => {

test/fixtures/asmjs.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module.exports = function a() {
2+
function b() {
3+
"use asm";
4+
if (0 == 0) {
5+
return 1 == 1 ? 101 : 102;
6+
} else {
7+
return 0 == 1 ? 103 : 104;
8+
}
9+
}
10+
function c() {
11+
if (0 == 0) {
12+
return 1 == 1 ? 105 : 106;
13+
} else {
14+
return 0 == 1 ? 107 : 108;
15+
}
16+
}
17+
var d = (function() {
18+
"use asm";
19+
return 1 == 1 ? 109 : 110;
20+
})();
21+
return b() + c() + d;
22+
};

0 commit comments

Comments
 (0)