do not evaluate constants in asm.js, fix IIFE mode detection
fixes #10283
This commit is contained in:
parent
04a613c8bd
commit
aea4fd97b5
|
@ -131,6 +131,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") {
|
||||
|
@ -201,6 +202,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") {
|
||||
|
@ -236,6 +238,7 @@ class ConstPlugin {
|
|||
parser.hooks.expressionLogicalOperator.tap(
|
||||
"ConstPlugin",
|
||||
expression => {
|
||||
if (parser.scope.isAsmJs) return;
|
||||
if (
|
||||
expression.operator === "&&" ||
|
||||
expression.operator === "||"
|
||||
|
@ -321,6 +324,7 @@ class ConstPlugin {
|
|||
parser.hooks.evaluateIdentifier
|
||||
.for("__resourceQuery")
|
||||
.tap("ConstPlugin", expr => {
|
||||
if (parser.scope.isAsmJs) return;
|
||||
if (!parser.state.module) return;
|
||||
return evaluateToString(getQuery(parser.state.module.resource))(
|
||||
expr
|
||||
|
@ -329,6 +333,7 @@ class ConstPlugin {
|
|||
parser.hooks.expression
|
||||
.for("__resourceQuery")
|
||||
.tap("ConstPlugin", expr => {
|
||||
if (parser.scope.isAsmJs) return;
|
||||
if (!parser.state.module) return;
|
||||
const dep = new CachedConstDependency(
|
||||
JSON.stringify(getQuery(parser.state.module.resource)),
|
||||
|
|
|
@ -78,6 +78,7 @@ class VariableInfo {
|
|||
* @property {boolean | "arrow"} topLevelScope
|
||||
* @property {boolean} inShorthand
|
||||
* @property {boolean} isStrict
|
||||
* @property {boolean} isAsmJs
|
||||
* @property {boolean} inTry
|
||||
*/
|
||||
|
||||
|
@ -1455,7 +1456,7 @@ class JavascriptParser extends Parser {
|
|||
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 {
|
||||
|
@ -1935,7 +1936,7 @@ class JavascriptParser extends Parser {
|
|||
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 {
|
||||
|
@ -1953,7 +1954,7 @@ class JavascriptParser extends Parser {
|
|||
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 {
|
||||
|
@ -2172,6 +2173,7 @@ class JavascriptParser extends Parser {
|
|||
this.setVariable(params[i].name, varInfo);
|
||||
}
|
||||
if (functionExpression.body.type === "BlockStatement") {
|
||||
this.detectMode(functionExpression.body.body);
|
||||
this.prewalkStatement(functionExpression.body);
|
||||
this.walkStatement(functionExpression.body);
|
||||
} else {
|
||||
|
@ -2495,6 +2497,7 @@ class JavascriptParser extends Parser {
|
|||
inTry: false,
|
||||
inShorthand: false,
|
||||
isStrict: oldScope.isStrict,
|
||||
isAsmJs: oldScope.isAsmJs,
|
||||
definitions: oldScope.definitions.createChild()
|
||||
};
|
||||
|
||||
|
@ -2516,6 +2519,7 @@ class JavascriptParser extends Parser {
|
|||
inTry: false,
|
||||
inShorthand: false,
|
||||
isStrict: oldScope.isStrict,
|
||||
isAsmJs: oldScope.isAsmJs,
|
||||
definitions: oldScope.definitions.createChild()
|
||||
};
|
||||
|
||||
|
@ -2539,6 +2543,7 @@ class JavascriptParser extends Parser {
|
|||
inTry: oldScope.inTry,
|
||||
inShorthand: false,
|
||||
isStrict: oldScope.isStrict,
|
||||
isAsmJs: oldScope.isAsmJs,
|
||||
definitions: oldScope.definitions.createChild()
|
||||
};
|
||||
|
||||
|
@ -2547,15 +2552,17 @@ class JavascriptParser extends Parser {
|
|||
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) {
|
||||
|
@ -2790,6 +2797,7 @@ class JavascriptParser extends Parser {
|
|||
inTry: false,
|
||||
inShorthand: false,
|
||||
isStrict: false,
|
||||
isAsmJs: false,
|
||||
definitions: new StackedMap()
|
||||
};
|
||||
/** @type {ParserState} */
|
||||
|
@ -2800,7 +2808,7 @@ class JavascriptParser extends Parser {
|
|||
this.lastStatementEndPos = NaN;
|
||||
this.statementStartPos = NaN;
|
||||
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);
|
||||
|
|
|
@ -170,6 +170,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(() => {
|
||||
|
|
|
@ -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;
|
||||
};
|
Loading…
Reference in New Issue