Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport: do not evaluate constants in asm.js, fix IIFE mode detection #10294

Merged
merged 3 commits into from Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/ConstPlugin.js
Expand Up @@ -119,6 +119,7 @@ class ConstPlugin {

const handler = parser => {
parser.hooks.statementIf.tap("ConstPlugin", statement => {
if (parser.scope.isAsmJs) return;
const param = parser.evaluateExpression(statement.test);
const bool = param.asBool();
if (typeof bool === "boolean") {
Expand Down Expand Up @@ -189,6 +190,7 @@ class ConstPlugin {
parser.hooks.expressionConditionalOperator.tap(
"ConstPlugin",
expression => {
if (parser.scope.isAsmJs) return;
const param = parser.evaluateExpression(expression.test);
const bool = param.asBool();
if (typeof bool === "boolean") {
Expand Down Expand Up @@ -224,6 +226,7 @@ class ConstPlugin {
parser.hooks.expressionLogicalOperator.tap(
"ConstPlugin",
expression => {
if (parser.scope.isAsmJs) return;
if (
expression.operator === "&&" ||
expression.operator === "||"
Expand Down Expand Up @@ -309,6 +312,7 @@ class ConstPlugin {
parser.hooks.evaluateIdentifier
.for("__resourceQuery")
.tap("ConstPlugin", expr => {
if (parser.scope.isAsmJs) return;
if (!parser.state.module) return;
return ParserHelpers.evaluateToString(
getQuery(parser.state.module.resource)
Expand All @@ -317,6 +321,7 @@ class ConstPlugin {
parser.hooks.expression
.for("__resourceQuery")
.tap("ConstPlugin", () => {
if (parser.scope.isAsmJs) return;
if (!parser.state.module) return;
parser.state.current.addVariable(
"__resourceQuery",
Expand Down
29 changes: 21 additions & 8 deletions lib/Parser.js
Expand Up @@ -1229,7 +1229,7 @@ class Parser extends Tapable {
this.walkPattern(param);
}
if (statement.body.type === "BlockStatement") {
this.detectStrictMode(statement.body.body);
this.detectMode(statement.body.body);
this.prewalkStatement(statement.body);
this.walkStatement(statement.body);
} else {
Expand Down Expand Up @@ -1697,7 +1697,7 @@ class Parser extends Tapable {
this.walkPattern(param);
}
if (expression.body.type === "BlockStatement") {
this.detectStrictMode(expression.body.body);
this.detectMode(expression.body.body);
this.prewalkStatement(expression.body);
this.walkStatement(expression.body);
} else {
Expand All @@ -1713,7 +1713,7 @@ class Parser extends Tapable {
this.walkPattern(param);
}
if (expression.body.type === "BlockStatement") {
this.detectStrictMode(expression.body.body);
this.detectMode(expression.body.body);
this.prewalkStatement(expression.body);
this.walkStatement(expression.body);
} else {
Expand Down Expand Up @@ -1894,6 +1894,7 @@ class Parser extends Tapable {
this.scope.renames.set(params[i].name, param);
}
if (functionExpression.body.type === "BlockStatement") {
this.detectMode(functionExpression.body.body);
this.prewalkStatement(functionExpression.body);
this.walkStatement(functionExpression.body);
} else {
Expand Down Expand Up @@ -2001,6 +2002,7 @@ class Parser extends Tapable {
inTry: false,
inShorthand: false,
isStrict: oldScope.isStrict,
isAsmJs: oldScope.isAsmJs,
definitions: oldScope.definitions.createChild(),
renames: oldScope.renames.createChild()
};
Expand All @@ -2024,6 +2026,7 @@ class Parser extends Tapable {
inTry: false,
inShorthand: false,
isStrict: oldScope.isStrict,
isAsmJs: oldScope.isAsmJs,
definitions: oldScope.definitions.createChild(),
renames: oldScope.renames.createChild()
};
Expand All @@ -2049,6 +2052,7 @@ class Parser extends Tapable {
inTry: oldScope.inTry,
inShorthand: false,
isStrict: oldScope.isStrict,
isAsmJs: oldScope.isAsmJs,
definitions: oldScope.definitions.createChild(),
renames: oldScope.renames.createChild()
};
Expand All @@ -2058,15 +2062,23 @@ class Parser extends Tapable {
this.scope = oldScope;
}

// TODO webpack 5: remove this methods
// only for backward-compat
detectStrictMode(statements) {
const isStrict =
this.detectMode(statements);
}

detectMode(statements) {
const isLiteral =
statements.length >= 1 &&
statements[0].type === "ExpressionStatement" &&
statements[0].expression.type === "Literal" &&
statements[0].expression.value === "use strict";
if (isStrict) {
statements[0].expression.type === "Literal";
if (isLiteral && statements[0].expression.value === "use strict") {
this.scope.isStrict = true;
}
if (isLiteral && statements[0].expression.value === "use asm") {
this.scope.isAsmJs = true;
}
}

enterPatterns(patterns, onIdent) {
Expand Down Expand Up @@ -2272,13 +2284,14 @@ class Parser extends Tapable {
inTry: false,
inShorthand: false,
isStrict: false,
isAsmJs: false,
definitions: new StackedSetMap(),
renames: new StackedSetMap()
};
const state = (this.state = initialState || {});
this.comments = comments;
if (this.hooks.program.call(ast, comments) === undefined) {
this.detectStrictMode(ast.body);
this.detectMode(ast.body);
this.prewalkStatements(ast.body);
this.blockPrewalkStatements(ast.body);
this.walkStatements(ast.body);
Expand Down
20 changes: 20 additions & 0 deletions test/Compiler.test.js
Expand Up @@ -168,6 +168,26 @@ describe("Compiler", () => {
done();
});
});

it("should not evaluate constants in asm.js", done => {
compile("./asmjs", {}, (stats, files) => {
expect(Object.keys(files)).toEqual(["/main.js"]);
const bundle = files["/main.js"];
expect(bundle).toMatch('"use asm";');
expect(bundle).toMatch("101");
expect(bundle).toMatch("102");
expect(bundle).toMatch("103");
expect(bundle).toMatch("104");
expect(bundle).toMatch("105");
expect(bundle).not.toMatch("106");
expect(bundle).not.toMatch("107");
expect(bundle).not.toMatch("108");
expect(bundle).toMatch("109");
expect(bundle).toMatch("110");
done();
});
});

describe("methods", () => {
let compiler;
beforeEach(() => {
Expand Down
22 changes: 22 additions & 0 deletions test/fixtures/asmjs.js
@@ -0,0 +1,22 @@
module.exports = function a() {
function b() {
"use asm";
if (0 == 0) {
return 1 == 1 ? 101 : 102;
} else {
return 0 == 1 ? 103 : 104;
}
}
function c() {
if (0 == 0) {
return 1 == 1 ? 105 : 106;
} else {
return 0 == 1 ? 107 : 108;
}
}
var d = (function() {
"use asm";
return 1 == 1 ? 109 : 110;
})();
return b() + c() + d;
};