diff --git a/lib/parse.js b/lib/parse.js index 16d8dad33e..c9ee01fd79 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 0000000000..590d162398 --- /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 8795afb1f6..4fea42dc45 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 74660dc647..e872747af4 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 c7560eb5aa..b87c88bb47 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() {