aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2019-11-29 18:57:29 +0800
committerGitHub <noreply@github.com>2019-11-29 18:57:29 +0800
commit1283d738539b4f899e4941f556b516c071bfa55a (patch)
treee563bbcfbe2932579f2f1778a0946ac3df945445
parent1b61a81b5d6c9489466fe4707c1b01810a01d03a (diff)
downloadtracifyjs-1283d738539b4f899e4941f556b516c071bfa55a.tar.gz
tracifyjs-1283d738539b4f899e4941f556b516c071bfa55a.zip
fix corner case in parsing directives (#3615)
-rw-r--r--lib/parse.js26
-rw-r--r--test/compress/directives.js95
-rw-r--r--test/compress/functions.js51
-rw-r--r--test/mocha/directives.js12
-rw-r--r--test/mocha/number-literal.js10
5 files changed, 123 insertions, 71 deletions
diff --git a/lib/parse.js b/lib/parse.js
index 16d8dad3..c9ee01fd 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -787,20 +787,18 @@ function parse($TEXT, options) {
handle_regexp();
switch (S.token.type) {
case "string":
- if (S.in_directives) {
- var token = peek();
- if (S.token.raw.indexOf("\\") == -1
- && (is_token(token, "punc", ";")
- || is_token(token, "punc", "}")
- || has_newline_before(token)
- || is_token(token, "eof"))) {
- S.input.add_directive(S.token.value);
+ var dir = S.in_directives;
+ var body = expression(true);
+ if (dir) {
+ var token = body.start;
+ if (body instanceof AST_String && token.raw.indexOf("\\") == -1) {
+ S.input.add_directive(token.value);
} else {
- S.in_directives = false;
+ S.in_directives = dir = false;
}
}
- var dir = S.in_directives, stat = simple_statement();
- return dir ? new AST_Directive(stat.body) : stat;
+ semicolon();
+ return dir ? new AST_Directive(body) : new AST_SimpleStatement({ body: body });
case "num":
case "regexp":
case "operator":
@@ -965,8 +963,10 @@ function parse($TEXT, options) {
return new AST_LabeledStatement({ body: stat, label: label });
}
- function simple_statement(tmp) {
- return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
+ function simple_statement() {
+ var body = expression(true);
+ semicolon();
+ return new AST_SimpleStatement({ body: body });
}
function break_cont(type) {
diff --git a/test/compress/directives.js b/test/compress/directives.js
new file mode 100644
index 00000000..590d1623
--- /dev/null
+++ b/test/compress/directives.js
@@ -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";
+ }
+ }
+}
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 8795afb1..4fea42dc 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -2004,57 +2004,6 @@ deduplicate_parenthesis: {
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: {
options = {
inline: true,
diff --git a/test/mocha/directives.js b/test/mocha/directives.js
index 74660dc6..e872747a 100644
--- a/test/mocha/directives.js
+++ b/test/mocha/directives.js
@@ -54,8 +54,8 @@ describe("Directives", function() {
[
[
'"use strict"\n',
- [ "use strict"],
- [ "use asm"]
+ [ "use strict" ],
+ [ "use asm" ]
],
[
'"use\\\nstrict";',
@@ -80,8 +80,8 @@ describe("Directives", function() {
[
// no ; or newline
'"use strict"',
- [],
- [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
+ [ "use strict" ],
+ [ "use\nstrict", "use \nstrict", "use asm" ]
],
[
';"use strict"',
@@ -116,8 +116,8 @@ describe("Directives", function() {
],
[
'var foo = function() {"use strict"', // no ; or newline
- [],
- [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
+ [ "use strict" ],
+ [ "use\nstrict", "use \nstrict", "use asm" ]
],
[
'var foo = function() {;"use strict"',
diff --git a/test/mocha/number-literal.js b/test/mocha/number-literal.js
index c7560eb5..b87c88bb 100644
--- a/test/mocha/number-literal.js
+++ b/test/mocha/number-literal.js
@@ -2,10 +2,18 @@ var assert = require("assert");
var UglifyJS = require("../node");
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() {
var inputs = [
'"use strict";00;',
- '"use strict"; var foo = 00;'
+ '"use strict"; var foo = 00;',
];
var test = function(input) {
return function() {