fix corner case in parsing directives (#3615)

This commit is contained in:
Alex Lam S.L
2019-11-29 18:57:29 +08:00
committed by GitHub
parent 1b61a81b5d
commit 1283d73853
5 changed files with 123 additions and 71 deletions

View File

@@ -787,20 +787,18 @@ function parse($TEXT, options) {
handle_regexp(); handle_regexp();
switch (S.token.type) { switch (S.token.type) {
case "string": case "string":
if (S.in_directives) { var dir = S.in_directives;
var token = peek(); var body = expression(true);
if (S.token.raw.indexOf("\\") == -1 if (dir) {
&& (is_token(token, "punc", ";") var token = body.start;
|| is_token(token, "punc", "}") if (body instanceof AST_String && token.raw.indexOf("\\") == -1) {
|| has_newline_before(token) S.input.add_directive(token.value);
|| is_token(token, "eof"))) {
S.input.add_directive(S.token.value);
} else { } else {
S.in_directives = false; S.in_directives = dir = false;
} }
} }
var dir = S.in_directives, stat = simple_statement(); semicolon();
return dir ? new AST_Directive(stat.body) : stat; return dir ? new AST_Directive(body) : new AST_SimpleStatement({ body: body });
case "num": case "num":
case "regexp": case "regexp":
case "operator": case "operator":
@@ -965,8 +963,10 @@ function parse($TEXT, options) {
return new AST_LabeledStatement({ body: stat, label: label }); return new AST_LabeledStatement({ body: stat, label: label });
} }
function simple_statement(tmp) { function simple_statement() {
return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); var body = expression(true);
semicolon();
return new AST_SimpleStatement({ body: body });
} }
function break_cont(type) { function break_cont(type) {

View File

@@ -0,0 +1,95 @@
simple_statement_is_not_a_directive: {
input: {
"use strict"
.split(" ")
.forEach(function(s) {
console.log(s);
});
console.log(!this); // is strict mode?
(function() {
"directive"
""
"use strict"
"hello world"
.split(" ")
.forEach(function(s) {
console.log(s);
});
console.log(!this); // is strict mode?
})();
}
expect: {
"use strict".split(" ").forEach(function(s) {
console.log(s);
});
console.log(!this);
(function() {
"directive";
"";
"use strict";
"hello world".split(" ").forEach(function(s) {
console.log(s);
});
console.log(!this);
})();
}
expect_stdout: [
"use",
"strict",
"false",
"hello",
"world",
"true",
]
}
drop_lone_use_strict: {
options = {
directives: true,
side_effects: true,
}
input: {
function f1() {
"use strict";
}
function f2() {
"use strict";
function f3() {
"use strict";
}
}
(function f4() {
"use strict";
})();
}
expect: {
function f1() {
}
function f2() {
"use strict";
function f3() {
}
}
}
}
issue_3166: {
options = {
directives: true,
}
input: {
"foo";
"use strict";
function f() {
"use strict";
"bar";
"use asm";
}
}
expect: {
"use strict";
function f() {
"use asm";
}
}
}

View File

@@ -2004,57 +2004,6 @@ deduplicate_parenthesis: {
expect_exact: "({}).a=b;({}.a=b)();(function(){}).a=b;(function(){}.a=b)();" expect_exact: "({}).a=b;({}.a=b)();(function(){}).a=b;(function(){}.a=b)();"
} }
drop_lone_use_strict: {
options = {
directives: true,
side_effects: true,
}
input: {
function f1() {
"use strict";
}
function f2() {
"use strict";
function f3() {
"use strict";
}
}
(function f4() {
"use strict";
})();
}
expect: {
function f1() {
}
function f2() {
"use strict";
function f3() {
}
}
}
}
issue_3166: {
options = {
directives: true,
}
input: {
"foo";
"use strict";
function f() {
"use strict";
"bar";
"use asm";
}
}
expect: {
"use strict";
function f() {
"use asm";
}
}
}
issue_3016_1: { issue_3016_1: {
options = { options = {
inline: true, inline: true,

View File

@@ -54,8 +54,8 @@ describe("Directives", function() {
[ [
[ [
'"use strict"\n', '"use strict"\n',
[ "use strict"], [ "use strict" ],
[ "use asm"] [ "use asm" ]
], ],
[ [
'"use\\\nstrict";', '"use\\\nstrict";',
@@ -80,8 +80,8 @@ describe("Directives", function() {
[ [
// no ; or newline // no ; or newline
'"use strict"', '"use strict"',
[], [ "use strict" ],
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ] [ "use\nstrict", "use \nstrict", "use asm" ]
], ],
[ [
';"use strict"', ';"use strict"',
@@ -116,8 +116,8 @@ describe("Directives", function() {
], ],
[ [
'var foo = function() {"use strict"', // no ; or newline 'var foo = function() {"use strict"', // no ; or newline
[], [ "use strict" ],
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ] [ "use\nstrict", "use \nstrict", "use asm" ]
], ],
[ [
'var foo = function() {;"use strict"', 'var foo = function() {;"use strict"',

View File

@@ -2,10 +2,18 @@ var assert = require("assert");
var UglifyJS = require("../node"); var UglifyJS = require("../node");
describe("Number literals", function() { describe("Number literals", function() {
it("Should allow legacy octal literals in non-strict mode", function() {
[
"'use strict'\n.slice()\n00",
'"use strict"\n.slice()\nvar foo = 00',
].forEach(function(input) {
UglifyJS.parse(input);
});
});
it("Should not allow legacy octal literals in strict mode", function() { it("Should not allow legacy octal literals in strict mode", function() {
var inputs = [ var inputs = [
'"use strict";00;', '"use strict";00;',
'"use strict"; var foo = 00;' '"use strict"; var foo = 00;',
]; ];
var test = function(input) { var test = function(input) {
return function() { return function() {