implement directives (#3203)

fixes #3166
This commit is contained in:
Alex Lam S.L
2018-06-28 18:16:49 +08:00
committed by GitHub
parent 957d5537a8
commit 76df77c08c
9 changed files with 238 additions and 209 deletions

View File

@@ -620,6 +620,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `dead_code` (default: `true`) -- remove unreachable code - `dead_code` (default: `true`) -- remove unreachable code
- `directives` (default: `true`) -- remove redundant or non-standard directives
- `drop_console` (default: `false`) -- Pass `true` to discard calls to - `drop_console` (default: `false`) -- Pass `true` to discard calls to
`console.*` functions. If you wish to drop a specific function call `console.*` functions. If you wish to drop a specific function call
such as `console.info` and/or retain side effects from function arguments such as `console.info` and/or retain side effects from function arguments

View File

@@ -54,6 +54,7 @@ function Compressor(options, false_by_default) {
comparisons : !false_by_default, comparisons : !false_by_default,
conditionals : !false_by_default, conditionals : !false_by_default,
dead_code : !false_by_default, dead_code : !false_by_default,
directives : !false_by_default,
drop_console : false, drop_console : false,
drop_debugger : !false_by_default, drop_debugger : !false_by_default,
evaluate : !false_by_default, evaluate : !false_by_default,
@@ -3264,8 +3265,10 @@ merge(Compressor.prototype, {
/* -----[ optimizers ]----- */ /* -----[ optimizers ]----- */
var directives = makePredicate(["use asm", "use strict"]);
OPT(AST_Directive, function(self, compressor) { OPT(AST_Directive, function(self, compressor) {
if (compressor.has_directive(self.value) !== self) { if (compressor.option("directives")
&& (!directives[self.value] || compressor.has_directive(self.value) !== self)) {
return make_node(AST_EmptyStatement, self); return make_node(AST_EmptyStatement, self);
} }
return self; return self;

View File

@@ -2025,6 +2025,7 @@ deduplicate_parenthesis: {
drop_lone_use_strict: { drop_lone_use_strict: {
options = { options = {
directives: true,
side_effects: true, side_effects: true,
} }
input: { input: {
@@ -2052,6 +2053,27 @@ drop_lone_use_strict: {
} }
} }
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

@@ -8,7 +8,7 @@ function read(path) {
describe("bin/uglifyjs", function() { describe("bin/uglifyjs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("should produce a functional build when using --self", function(done) { it("Should produce a functional build when using --self", function(done) {
this.timeout(30000); this.timeout(30000);
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS'; var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
@@ -68,7 +68,7 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("should not append source map to output when not using --source-map url=inline", function(done) { it("Should not append source map to output when not using --source-map url=inline", function(done) {
var command = uglifyjscmd + ' test/input/issue-1323/sample.js'; var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
@@ -76,7 +76,7 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("should not consider source map file content as source map file name (issue #2082)", function(done) { it("Should not consider source map file content as source map file name (issue #2082)", function(done) {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"test/input/issue-2082/sample.js", "test/input/issue-2082/sample.js",

View File

@@ -2,14 +2,12 @@ var assert = require("assert");
var UglifyJS = require("../node"); var UglifyJS = require("../node");
describe("Directives", function() { describe("Directives", function() {
it ("Should allow tokenizer to store directives state", function() { it("Should allow tokenizer to store directives state", function() {
var tokenizer = UglifyJS.tokenizer("", "foo.js"); var tokenizer = UglifyJS.tokenizer("", "foo.js");
// Stack level 0 // Stack level 0
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 2 // Stack level 2
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
@@ -17,7 +15,6 @@ describe("Directives", function() {
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 3 // Stack level 3
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
tokenizer.add_directive("use strict"); tokenizer.add_directive("use strict");
@@ -25,13 +22,11 @@ describe("Directives", function() {
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), true); assert.strictEqual(tokenizer.has_directive("use asm"), true);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 2 // Stack level 2
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 3 // Stack level 3
tokenizer.push_directives_stack(); tokenizer.push_directives_stack();
tokenizer.add_directive("use thing"); tokenizer.add_directive("use thing");
@@ -39,152 +34,138 @@ describe("Directives", function() {
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); // Directives are strict! assert.strictEqual(tokenizer.has_directive("use asm"), false); // Directives are strict!
assert.strictEqual(tokenizer.has_directive("use thing"), true); assert.strictEqual(tokenizer.has_directive("use thing"), true);
// Stack level 2 // Stack level 2
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), true); assert.strictEqual(tokenizer.has_directive("use strict"), true);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 1 // Stack level 1
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
// Stack level 0 // Stack level 0
tokenizer.pop_directives_stack(); tokenizer.pop_directives_stack();
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
assert.strictEqual(tokenizer.has_directive("use asm"), false); assert.strictEqual(tokenizer.has_directive("use asm"), false);
assert.strictEqual(tokenizer.has_directive("use thing"), false); assert.strictEqual(tokenizer.has_directive("use thing"), false);
}); });
it("Should know which strings are directive and which ones are not", function() { it("Should know which strings are directive and which ones are not", function() {
var test_directive = function(tokenizer, test) { [
test.directives.map(function(directive) { [
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test.input); '"use strict"\n',
}); [ "use strict"],
test.non_directives.map(function(fake_directive) { [ "use asm"]
assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test.input); ],
}); [
} '"use\\\nstrict";',
[],
var tests = [ [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
{ ],
input: '"use strict"\n', [
directives: ["use strict"], '"use strict"\n"use asm"\n"use bar"\n',
non_directives: ["use asm"] [ "use strict", "use asm", "use bar" ],
}, [ "use foo", "use\\x20strict" ]
{ ],
input: '"use\\\nstrict";', [
directives: [], '"use \\\nstrict";"use strict";',
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [],
}, [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
{ ],
input: '"use strict"\n"use asm"\n"use bar"\n', [
directives: ["use strict", "use asm", "use bar"], '"\\76";',
non_directives: ["use foo", "use\\x20strict"] [],
}, [ ">", "\\76" ]
{ ],
input: '"use \\\nstrict";"use strict";', [
directives: [], // no ; or newline
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] '"use strict"',
}, [],
{ [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
input: '"\\76";', ],
directives: [], [
non_directives: [">", "\\76"] ';"use strict"',
}, [],
{ [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
input: '"use strict"', // no ; or newline ],
directives: [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
},
{
input: ';"use strict"',
directives: [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
},
// Duplicate above code but put it in a function // Duplicate above code but put it in a function
{ [
input: 'function foo() {"use strict"\n', 'function foo() {"use strict"\n',
directives: ["use strict"], [ "use strict" ],
non_directives: ["use asm"] [ "use asm" ]
}, ],
{ [
input: 'function foo() {"use\\\nstrict";', 'function foo() {"use\\\nstrict";',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: 'function foo() {"use strict"\n"use asm"\n"use bar"\n', 'function foo() {"use strict"\n"use asm"\n"use bar"\n',
directives: ["use strict", "use asm", "use bar"], [ "use strict", "use asm", "use bar" ],
non_directives: ["use foo", "use\\x20strict"] [ "use foo", "use\\x20strict" ]
}, ],
{ [
input: 'function foo() {"use \\\nstrict";"use strict";', 'function foo() {"use \\\nstrict";"use strict";',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: 'var foo = function() {"\\76";', 'var foo = function() {"\\76";',
directives: [], [],
non_directives: [">", "\\76"] [ ">", "\\76" ]
}, ],
{ [
input: 'var foo = function() {"use strict"', // no ; or newline 'var foo = function() {"use strict"', // no ; or newline
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: 'var foo = function() {;"use strict"', 'var foo = function() {;"use strict"',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
// Special cases // Special cases
{ [
input: '"1";"2";"3";"4";;"5"', '"1";"2";"3";"4";;"5"',
directives: ["1", "2", "3", "4"], [ "1", "2", "3", "4" ],
non_directives: ["5", "6", "use strict", "use asm"] [ "5", "6", "use strict", "use asm" ]
}, ],
{ [
input: 'if(1){"use strict";', 'if(1){"use strict";',
directives: [], [],
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"] [ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
}, ],
{ [
input: '"use strict";try{"use asm";', '"use strict";try{"use asm";',
directives: ["use strict"], [ "use strict" ],
non_directives: ["use\nstrict", "use \nstrict", "use asm"] [ "use\nstrict", "use \nstrict", "use asm" ]
} ],
]; ].forEach(function(test) {
var tokenizer = UglifyJS.tokenizer(test[0] + "]", "foo.js");
for (var i = 0; i < tests.length; i++) { assert.throws(function() {
// Fail parser deliberately to get state at failure UglifyJS.parse(tokenizer);
var tokenizer = UglifyJS.tokenizer(tests[i].input + "]", "foo.js"); }, function(e) {
return e instanceof UglifyJS.JS_Parse_Error
try { && e.message === "Unexpected token: punc (])"
var parser = UglifyJS.parse(tokenizer); }, test[0]);
throw new Error("Expected parser to fail"); test[1].forEach(function(directive) {
} catch (e) { assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test[0]);
assert.strictEqual(e instanceof UglifyJS.JS_Parse_Error, true); });
assert.strictEqual(e.message, "Unexpected token: punc (])"); test[2].forEach(function(fake_directive) {
} assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test[0]);
});
test_directive(tokenizer, tests[i]); });
}
}); });
it("Should test EXPECT_DIRECTIVE RegExp", function() { it("Should test EXPECT_DIRECTIVE RegExp", function() {
[ [
["", true], [ "", true ],
["'test';", true], [ "'test';", true ],
["'test';;", true], [ "'test';;", true ],
["'tests';\n", true], [ "'tests';\n", true ],
["'tests'", false], [ "'tests'", false ],
["'tests'; \n\t", true], [ "'tests'; \n\t", true ],
["'tests';\n\n", true], [ "'tests';\n\n", true ],
["\n\n\"use strict\";\n\n", true] [ "\n\n\"use strict\";\n\n", true ],
].forEach(function(test) { ].forEach(function(test) {
var out = UglifyJS.OutputStream(); var out = UglifyJS.OutputStream();
out.print(test[0]); out.print(test[0]);
@@ -192,19 +173,33 @@ describe("Directives", function() {
assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]); assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]);
}); });
}); });
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() { it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
assert.strictEqual( var result = UglifyJS.minify([
UglifyJS.minify( '"use strict";',
'"use strict";\'use strict\';"use strict";"use strict";;\'use strict\';console.log(\'use strict\');', "'use strict';",
{output: {beautify: true, quote_style: 3}, compress: false} '"use strict";',
).code, '"use strict";;',
'"use strict";\n\n\'use strict\';\n\n"use strict";\n\n"use strict";\n\n;\'use strict\';\n\nconsole.log(\'use strict\');' "'use strict';",
); "console.log('use strict');"
].join(""), {
compress: false,
output: {
beautify: true,
quote_style: 3
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
'"use strict";',
"'use strict';",
'"use strict";',
'"use strict";',
";'use strict';",
"console.log('use strict');"
].join("\n\n"));
}); });
it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() { it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() {
var tests = [ [
[ [
'{"use\x20strict"}', '{"use\x20strict"}',
'{"use strict"}' '{"use strict"}'
@@ -221,26 +216,27 @@ describe("Directives", function() {
'if(1){"use\x20strict"} else {"use strict"}', 'if(1){"use\x20strict"} else {"use strict"}',
'if(1){"use strict"}else{"use strict"}' 'if(1){"use strict"}else{"use strict"}'
] ]
]; ].forEach(function(test) {
var result = UglifyJS.minify(test[0], {
for (var i = 0; i < tests.length; i++) { compress: false,
assert.strictEqual( mangle: false
UglifyJS.minify(tests[i][0], {compress: false, mangle: false}).code, });
tests[i][1], if (result.error) throw result.error;
tests[i][0] assert.strictEqual(result.code, test[1], test[0]);
); });
}
}); });
it("Should add double semicolon when relying on automatic semicolon insertion", function() { it("Should add double semicolon when relying on automatic semicolon insertion", function() {
var code = UglifyJS.minify('"use strict";"use\\x20strict";', var result = UglifyJS.minify('"use strict";"use\\x20strict";', {
{output: {semicolons: false}, compress: false} compress: false,
).code; output: {
assert.strictEqual(code, '"use strict";;"use strict"\n'); semicolons: false
}
});
if (result.error) throw result.error;
assert.strictEqual(result.code, '"use strict";;"use strict"\n');
}); });
it("Should check quote style of directives", function() { it("Should check quote style of directives", function() {
var tests = [ [
// 0. Prefer double quotes, unless string contains more double quotes than single quotes // 0. Prefer double quotes, unless string contains more double quotes than single quotes
[ [
'"testing something";', '"testing something";',
@@ -337,45 +333,53 @@ describe("Directives", function() {
3, 3,
"'\"use strict\"';", "'\"use strict\"';",
], ],
]; ].forEach(function(test) {
for (var i = 0; i < tests.length; i++) { var result = UglifyJS.minify(test[0], {
assert.strictEqual( compress: false,
UglifyJS.minify(tests[i][0], {output:{quote_style: tests[i][1]}, compress: false}).code, output: {
tests[i][2], quote_style: test[1]
tests[i][0] + " using mode " + tests[i][1] }
); });
} if (result.error) throw result.error;
assert.strictEqual(result.code, test[2], test[0] + " using mode " + test[1]);
});
}); });
it("Should be able to compress without side effects", function() { it("Should be able to compress without side effects", function() {
// NOTE: the "use asm" directive disables any optimisation after being defined [
var tests = [
[ [
'"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");', '"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");',
'"use strict";"use foo";doSomething("foo");', '"use strict";doSomething("foo");'
'function f(){ "use strict" }',
'function f(){ "use asm" }',
'function f(){ "use nondirective" }',
'function f(){ ;"use strict" }',
'function f(){ "use \n"; }',
], ],
[ [
// Nothing gets optimised in the compressor because "use asm" is the first statement // Nothing gets optimised in the compressor because "use asm" is the first statement
'"use asm";"use\\x20strict";1+1;', '"use asm";"use\\x20strict";1+1;',
'"use asm";;"use strict";1+1;', // Yet, the parser noticed that "use strict" wasn't a directive // Yet, the parser noticed that "use strict" wasn't a directive
'function f(){"use strict"}', '"use asm";;"use strict";1+1;',
'function f(){"use asm"}', ],
'function f(){"use nondirective"}', [
'function f(){}', 'function f(){ "use strict" }',
'function f(){}', 'function f(){}'
] ],
]; [
'function f(){ "use asm" }',
for (var i = 0; i < tests.length; i++) { 'function f(){"use asm"}'
assert.strictEqual( ],
UglifyJS.minify(tests[i][0]).code, [
tests[i][1], 'function f(){ "use nondirective" }',
tests[i][0] 'function f(){}'
); ],
} [
'function f(){ ;"use strict" }',
'function f(){}'
],
[
'function f(){ "use \\n"; }',
'function f(){}'
],
].forEach(function(test) {
var result = UglifyJS.minify(test[0]);
if (result.error) throw result.error;
assert.strictEqual(result.code, test[1], test[0]);
});
}); });
}); });

View File

@@ -35,7 +35,7 @@ describe("bin/uglifyjs with input file globs", function() {
done(); done();
}); });
}); });
it("should throw with non-matching glob string", function(done) { it("Should throw with non-matching glob string", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/blah.*"'; var command = uglifyjscmd + ' "test/input/issue-1242/blah.*"';
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
@@ -53,7 +53,7 @@ describe("bin/uglifyjs with input file globs", function() {
done(); done();
}); });
}); });
it("should handle special characters in glob string", function(done) { it("Should handle special characters in glob string", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1632/^{*}[???](*)+$.??" -cm'; var command = uglifyjscmd + ' "test/input/issue-1632/^{*}[???](*)+$.??" -cm';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
@@ -63,7 +63,7 @@ describe("bin/uglifyjs with input file globs", function() {
done(); done();
}); });
}); });
it("should handle array of glob strings - matching and otherwise", function(done) { it("Should handle array of glob strings - matching and otherwise", function(done) {
var dir = "test/input/issue-1242"; var dir = "test/input/issue-1242";
var command = uglifyjscmd + ' "' + [ var command = uglifyjscmd + ' "' + [
path.join(dir, "b*.es5"), path.join(dir, "b*.es5"),

View File

@@ -187,7 +187,7 @@ describe("minify", function() {
}); });
describe("#__PURE__", function() { describe("#__PURE__", function() {
it("should drop #__PURE__ hint after use", function() { it("Should drop #__PURE__ hint after use", function() {
var result = UglifyJS.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', { var result = UglifyJS.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
output: { output: {
comments: "all", comments: "all",
@@ -197,7 +197,7 @@ describe("minify", function() {
var code = result.code; var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();"); assert.strictEqual(code, "// comment1 comment2\nbar();");
}); });
it("should drop #__PURE__ hint if function is retained", function() { it("Should drop #__PURE__ hint if function is retained", function() {
var result = UglifyJS.minify("var a = /*#__PURE__*/(function(){ foo(); })();", { var result = UglifyJS.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
output: { output: {
comments: "all", comments: "all",
@@ -210,7 +210,7 @@ describe("minify", function() {
}); });
describe("JS_Parse_Error", function() { describe("JS_Parse_Error", function() {
it("should return syntax error", function() { it("Should return syntax error", function() {
var result = UglifyJS.minify("function f(a{}"); var result = UglifyJS.minify("function f(a{}");
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
@@ -219,7 +219,7 @@ describe("minify", function() {
assert.strictEqual(err.line, 1); assert.strictEqual(err.line, 1);
assert.strictEqual(err.col, 12); assert.strictEqual(err.col, 12);
}); });
it("should reject duplicated label name", function() { it("Should reject duplicated label name", function() {
var result = UglifyJS.minify("L:{L:{}}"); var result = UglifyJS.minify("L:{L:{}}");
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
@@ -231,7 +231,7 @@ describe("minify", function() {
}); });
describe("global_defs", function() { describe("global_defs", function() {
it("should throw for non-trivial expressions", function() { it("Should throw for non-trivial expressions", function() {
var result = UglifyJS.minify("alert(42);", { var result = UglifyJS.minify("alert(42);", {
compress: { compress: {
global_defs: { global_defs: {
@@ -243,7 +243,7 @@ describe("minify", function() {
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword (debugger)"); assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword (debugger)");
}); });
it("should skip inherited properties", function() { it("Should skip inherited properties", function() {
var foo = Object.create({ skip: this }); var foo = Object.create({ skip: this });
foo.bar = 42; foo.bar = 42;
var result = UglifyJS.minify("alert(FOO);", { var result = UglifyJS.minify("alert(FOO);", {

View File

@@ -53,7 +53,6 @@ describe("sourcemaps", function() {
assert.strictEqual(map.version, 3); assert.strictEqual(map.version, 3);
assert.deepEqual(map.names, [ "x" ]); assert.deepEqual(map.names, [ "x" ]);
}); });
it("Should give correct names", function() { it("Should give correct names", function() {
var map = source_map([ var map = source_map([
"({", "({",
@@ -67,7 +66,6 @@ describe("sourcemaps", function() {
].join("\n")); ].join("\n"));
assert.deepEqual(map.names, [ "enabled", "x" ]); assert.deepEqual(map.names, [ "enabled", "x" ]);
}); });
it("Should mark array/object literals", function() { it("Should mark array/object literals", function() {
var result = UglifyJS.minify([ var result = UglifyJS.minify([
"var obj = {};", "var obj = {};",
@@ -80,7 +78,6 @@ describe("sourcemaps", function() {
assert.strictEqual(result.code, "({}).wat([]);"); assert.strictEqual(result.code, "({}).wat([]);");
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}'); assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}');
}); });
it("Should give correct sourceRoot", function() { it("Should give correct sourceRoot", function() {
var code = "console.log(42);"; var code = "console.log(42);";
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
@@ -212,6 +209,9 @@ describe("sourcemaps", function() {
}); });
it("Should work with max_line_len", function() { it("Should work with max_line_len", function() {
var result = UglifyJS.minify(read("./test/input/issue-505/input.js"), { var result = UglifyJS.minify(read("./test/input/issue-505/input.js"), {
compress: {
directives: false,
},
output: { output: {
max_line_len: 20 max_line_len: 20
}, },
@@ -261,7 +261,6 @@ describe("sourcemaps", function() {
var map = prepare_map(orig); var map = prepare_map(orig);
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]); assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
}); });
it("Should copy sourcesContent if sources are relative", function() { it("Should copy sourcesContent if sources are relative", function() {
var relativeMap = get_map(); var relativeMap = get_map();
relativeMap.sources = ['./index.js']; relativeMap.sources = ['./index.js'];
@@ -270,7 +269,6 @@ describe("sourcemaps", function() {
assert.equal(map.sourcesContent.length, 1); assert.equal(map.sourcesContent.length, 1);
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]); assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
}); });
it("Should not have invalid mappings from inputSourceMap", function() { it("Should not have invalid mappings from inputSourceMap", function() {
var map = prepare_map(get_map()); var map = prepare_map(get_map());
// The original source has only 2 lines, check that mappings don't have more lines // The original source has only 2 lines, check that mappings don't have more lines

View File

@@ -3,7 +3,7 @@ var exec = require("child_process").exec;
var UglifyJS = require("../.."); var UglifyJS = require("../..");
describe("spidermonkey export/import sanity test", function() { describe("spidermonkey export/import sanity test", function() {
it("should produce a functional build when using --self with spidermonkey", function(done) { it("Should produce a functional build when using --self with spidermonkey", function(done) {
this.timeout(60000); this.timeout(60000);
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
@@ -23,7 +23,7 @@ describe("spidermonkey export/import sanity test", function() {
}); });
}); });
it("should not add unnecessary escape slashes to regexps", function() { it("Should not add unnecessary escape slashes to regexps", function() {
var input = "/[\\\\/]/;"; var input = "/[\\\\/]/;";
var ast = UglifyJS.parse(input).to_mozilla_ast(); var ast = UglifyJS.parse(input).to_mozilla_ast();
assert.equal( assert.equal(