Skip to content

Commit

Permalink
do not evaluate constants in asm.js, fix IIFE mode detection
Browse files Browse the repository at this point in the history
backports PR #10288
fixes #10283
  • Loading branch information
ngg committed Jan 23, 2020
1 parent 627510d commit a7a07bc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 9 deletions.
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
25 changes: 16 additions & 9 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,17 @@ class Parser extends Tapable {
this.scope = oldScope;
}

detectStrictMode(statements) {
const isStrict =
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 +2278,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;
};

0 comments on commit a7a07bc

Please sign in to comment.