Merge branch 'master' into fix-harmony
This commit is contained in:
@@ -58,4 +58,313 @@ describe("Directives", function() {
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
});
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
test.non_directives.map(function(fake_directive) {
|
||||
assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test.input);
|
||||
});
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{
|
||||
input: '"use strict"\n',
|
||||
directives: ["use strict"],
|
||||
non_directives: ["use asm"]
|
||||
},
|
||||
{
|
||||
input: '"use\\\nstrict";',
|
||||
directives: [],
|
||||
non_directives: ["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"],
|
||||
non_directives: ["use foo", "use\\x20strict"]
|
||||
},
|
||||
{
|
||||
input: '"use \\\nstrict";"use strict";',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: '"\\76";',
|
||||
directives: [],
|
||||
non_directives: [">", "\\76"]
|
||||
},
|
||||
{
|
||||
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
|
||||
{
|
||||
input: 'function foo() {"use strict"\n',
|
||||
directives: ["use strict"],
|
||||
non_directives: ["use asm"]
|
||||
},
|
||||
{
|
||||
input: 'function foo() {"use\\\nstrict";',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: 'function foo() {"use strict"\n"use asm"\n"use bar"\n',
|
||||
directives: ["use strict", "use asm", "use bar"],
|
||||
non_directives: ["use foo", "use\\x20strict"]
|
||||
},
|
||||
{
|
||||
input: 'function foo() {"use \\\nstrict";"use strict";',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: 'var foo = function() {"\\76";',
|
||||
directives: [],
|
||||
non_directives: [">", "\\76"]
|
||||
},
|
||||
{
|
||||
input: 'var foo = function() {"use strict"', // no ; or newline
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: 'var foo = function() {;"use strict"',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
// Special cases
|
||||
{
|
||||
input: '"1";"2";"3";"4";;"5"',
|
||||
directives: ["1", "2", "3", "4"],
|
||||
non_directives: ["5", "6", "use strict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: 'if(1){"use strict";',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: '"use strict";try{"use asm";',
|
||||
directives: ["use strict"],
|
||||
non_directives: ["use\nstrict", "use \nstrict", "use asm"]
|
||||
}
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
// Fail parser deliberately to get state at failure
|
||||
var tokenizer = uglify.tokenizer(tests[i].input + "]", "foo.js");
|
||||
|
||||
try {
|
||||
var parser = uglify.parse(tokenizer);
|
||||
throw new Error("Expected parser to fail");
|
||||
} catch (e) {
|
||||
assert.strictEqual(e instanceof uglify.JS_Parse_Error, true);
|
||||
assert.strictEqual(e.message, "SyntaxError: Unexpected token: punc (])");
|
||||
}
|
||||
|
||||
test_directive(tokenizer, tests[i]);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should test EXPECT_DIRECTIVE RegExp", function() {
|
||||
var tests = [
|
||||
["", true],
|
||||
["'test';", true],
|
||||
["'test';;", true],
|
||||
["'tests';\n", true],
|
||||
["'tests'", false],
|
||||
["'tests'; \n\t", true],
|
||||
["'tests';\n\n", true],
|
||||
["\n\n\"use strict\";\n\n", true]
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(uglify.EXPECT_DIRECTIVE.test(tests[i][0]), tests[i][1], tests[i][0]);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
|
||||
assert.strictEqual(
|
||||
uglify.minify(
|
||||
'"use strict";\'use strict\';"use strict";"use strict";;\'use strict\';console.log(\'use strict\');',
|
||||
{fromString: true, output: {beautify: true, quote_style: 3}, compress: false}
|
||||
).code,
|
||||
'"use strict";\n\n\'use strict\';\n\n"use strict";\n\n"use strict";\n\n;\'use strict\';\n\nconsole.log(\'use strict\');'
|
||||
);
|
||||
});
|
||||
|
||||
it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() {
|
||||
var tests = [
|
||||
[
|
||||
'{"use\x20strict"}',
|
||||
'{"use strict"}'
|
||||
],
|
||||
[
|
||||
'function foo(){"use\x20strict";}', // Valid place for directives
|
||||
'function foo(){"use strict"}'
|
||||
],
|
||||
[
|
||||
'try{"use\x20strict"}catch(e){}finally{"use\x20strict"}',
|
||||
'try{"use strict"}catch(e){}finally{"use strict"}'
|
||||
],
|
||||
[
|
||||
'if(1){"use\x20strict"} else {"use strict"}',
|
||||
'if(1){"use strict"}else{"use strict"}'
|
||||
]
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i][0], {fromString: true, quote_style: 3, compress: false, mangle: false}).code,
|
||||
tests[i][1],
|
||||
tests[i][0]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should add double semicolon when relying on automatic semicolon insertion", function() {
|
||||
var code = uglify.minify('"use strict";"use\\x20strict";',
|
||||
{fromString: true, output: {semicolons: false}, compress: false}
|
||||
).code;
|
||||
assert.strictEqual(code, '"use strict";;"use strict"\n');
|
||||
});
|
||||
|
||||
it("Should check quote style of directives", function() {
|
||||
var tests = [
|
||||
// 0. Prefer double quotes, unless string contains more double quotes than single quotes
|
||||
[
|
||||
'"testing something";',
|
||||
0,
|
||||
'"testing something";'
|
||||
],
|
||||
[
|
||||
"'use strict';",
|
||||
0,
|
||||
'"use strict";'
|
||||
],
|
||||
[
|
||||
'"\\\'use strict\\\'";', // Not a directive as it contains quotes
|
||||
0,
|
||||
';"\'use strict\'";',
|
||||
],
|
||||
[
|
||||
"'\"use strict\"';",
|
||||
0,
|
||||
"'\"use strict\"';",
|
||||
],
|
||||
// 1. Always use single quote
|
||||
[
|
||||
'"testing something";',
|
||||
1,
|
||||
"'testing something';"
|
||||
],
|
||||
[
|
||||
"'use strict';",
|
||||
1,
|
||||
"'use strict';"
|
||||
],
|
||||
[
|
||||
'"\'use strict\'";',
|
||||
1,
|
||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||
"'\\'use strict\\'';",
|
||||
],
|
||||
[
|
||||
"'\\'use strict\\'';", // Not a valid directive
|
||||
1,
|
||||
"'\\'use strict\\'';" // But no ; necessary as directive stays invalid
|
||||
],
|
||||
[
|
||||
"'\"use strict\"';",
|
||||
1,
|
||||
"'\"use strict\"';",
|
||||
],
|
||||
// 2. Always use double quote
|
||||
[
|
||||
'"testing something";',
|
||||
2,
|
||||
'"testing something";'
|
||||
],
|
||||
[
|
||||
"'use strict';",
|
||||
2,
|
||||
'"use strict";'
|
||||
],
|
||||
[
|
||||
'"\'use strict\'";',
|
||||
2,
|
||||
"\"'use strict'\";",
|
||||
],
|
||||
[
|
||||
"'\"use strict\"';",
|
||||
2,
|
||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||
'"\\\"use strict\\\"";',
|
||||
],
|
||||
[
|
||||
'"\\"use strict\\"";', // Not a valid directive
|
||||
2,
|
||||
'"\\"use strict\\"";' // But no ; necessary as directive stays invalid
|
||||
],
|
||||
// 3. Always use original
|
||||
[
|
||||
'"testing something";',
|
||||
3,
|
||||
'"testing something";'
|
||||
],
|
||||
[
|
||||
"'use strict';",
|
||||
3,
|
||||
"'use strict';",
|
||||
],
|
||||
[
|
||||
'"\'use strict\'";',
|
||||
3,
|
||||
'"\'use strict\'";',
|
||||
],
|
||||
[
|
||||
"'\"use strict\"';",
|
||||
3,
|
||||
"'\"use strict\"';",
|
||||
],
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i][0], {fromString: true, output:{quote_style: tests[i][1]}, compress: false}).code,
|
||||
tests[i][2],
|
||||
tests[i][0] + " using mode " + tests[i][1]
|
||||
);
|
||||
}
|
||||
});
|
||||
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 foo";doSomething("foo");'
|
||||
],
|
||||
[
|
||||
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
||||
'"use asm";"use\\x20strict";1+1;',
|
||||
'"use asm";;"use strict";1+1;' // Yet, the parser noticed that "use strict" wasn't a directive
|
||||
]
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i][0], {fromString: true, compress: {collapse_vars: true, side_effects: true}}).code,
|
||||
tests[i][1],
|
||||
tests[i][0]
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -71,7 +71,7 @@ describe("Getters and setters", function() {
|
||||
var fail = function(data) {
|
||||
return function (e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
||||
e.message === "Invalid getter/setter name: " + data.operator;
|
||||
e.message === "SyntaxError: Invalid getter/setter name: " + data.operator;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -7,5 +7,56 @@ describe("minify", function() {
|
||||
var result = Uglify.minify(js, {fromString: true});
|
||||
assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
|
||||
});
|
||||
});
|
||||
|
||||
describe("keep_quoted_props", function() {
|
||||
it("Should preserve quotes in object literals", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true, output: {
|
||||
keep_quoted_props: true
|
||||
}});
|
||||
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
|
||||
});
|
||||
|
||||
it("Should preserve quote styles when quote_style is 3", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true, output: {
|
||||
keep_quoted_props: true,
|
||||
quote_style: 3
|
||||
}});
|
||||
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
|
||||
});
|
||||
|
||||
it("Should not preserve quotes in object literals when disabled", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true, output: {
|
||||
keep_quoted_props: false,
|
||||
quote_style: 3
|
||||
}});
|
||||
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
|
||||
});
|
||||
});
|
||||
|
||||
describe("mangleProperties", function() {
|
||||
it("Shouldn't mangle quoted properties", function() {
|
||||
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
compress: {
|
||||
properties: false
|
||||
},
|
||||
mangleProperties: {
|
||||
ignore_quoted: true
|
||||
},
|
||||
output: {
|
||||
keep_quoted_props: true,
|
||||
quote_style: 3
|
||||
}
|
||||
});
|
||||
assert.strictEqual(result.code,
|
||||
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,49 @@ var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
|
||||
describe("New", function() {
|
||||
it("Should attach callback parens after some tokens", function() {
|
||||
it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() {
|
||||
var tests = [
|
||||
"new x(1);",
|
||||
"new x;",
|
||||
"new new x;",
|
||||
"new (function(foo){this.foo=foo;})(1);",
|
||||
"new (function(foo){this.foo=foo;})();",
|
||||
"new (function test(foo){this.foo=foo;})(1);",
|
||||
"new (function test(foo){this.foo=foo;})();",
|
||||
"new true;",
|
||||
"new (0);",
|
||||
"new (!0);",
|
||||
"new (bar = function(foo) {this.foo=foo;})(123);",
|
||||
"new (bar = function(foo) {this.foo=foo;})();"
|
||||
];
|
||||
var expected = [
|
||||
"new x(1);",
|
||||
"new x();",
|
||||
"new new x()();",
|
||||
"new function(foo) {\n this.foo = foo;\n}(1);",
|
||||
"new function(foo) {\n this.foo = foo;\n}();",
|
||||
"new function test(foo) {\n this.foo = foo;\n}(1);",
|
||||
"new function test(foo) {\n this.foo = foo;\n}();",
|
||||
"new true();",
|
||||
"new 0();",
|
||||
"new (!0)();",
|
||||
"new (bar = function(foo) {\n this.foo = foo;\n})(123);",
|
||||
"new (bar = function(foo) {\n this.foo = foo;\n})();"
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i], {
|
||||
fromString: true,
|
||||
output: {beautify: true},
|
||||
compress: false,
|
||||
mangle: false
|
||||
}).code,
|
||||
expected[i]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should not add trailing parentheses for new expressions with zero arguments in non-beautify mode", function() {
|
||||
var tests = [
|
||||
"new x(1);",
|
||||
"new x;",
|
||||
@@ -20,22 +62,22 @@ describe("New", function() {
|
||||
var expected = [
|
||||
"new x(1);",
|
||||
"new x;",
|
||||
"new (new x);",
|
||||
"new function(foo) {\n this.foo = foo;\n}(1);",
|
||||
"new function(foo) {\n this.foo = foo;\n};",
|
||||
"new function test(foo) {\n this.foo = foo;\n}(1);",
|
||||
"new function test(foo) {\n this.foo = foo;\n};",
|
||||
"new(new x);",
|
||||
"new function(foo){this.foo=foo}(1);",
|
||||
"new function(foo){this.foo=foo};",
|
||||
"new function test(foo){this.foo=foo}(1);",
|
||||
"new function test(foo){this.foo=foo};",
|
||||
"new true;",
|
||||
"new 0;",
|
||||
"new (!0);",
|
||||
"new (bar = function(foo) {\n this.foo = foo;\n})(123);",
|
||||
"new (bar = function(foo) {\n this.foo = foo;\n});"
|
||||
"new(!0);",
|
||||
"new(bar=function(foo){this.foo=foo})(123);",
|
||||
"new(bar=function(foo){this.foo=foo});"
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i], {
|
||||
fromString: true,
|
||||
output: {beautify: true},
|
||||
output: {beautify: false},
|
||||
compress: false,
|
||||
mangle: false
|
||||
}).code,
|
||||
|
||||
@@ -59,13 +59,13 @@ describe("String literals", function() {
|
||||
|
||||
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||
var tests = [
|
||||
['"\\76";', '">";'],
|
||||
['"\\76";', ';">";'],
|
||||
['"\\0"', '"\\0";'],
|
||||
['"\\08"', '"\\08";'],
|
||||
['"\\008"', '"\\08";'],
|
||||
['"\\0008"', '"\\08";'],
|
||||
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
||||
// ['"use\\\n strict";\n"\\07";', '"use\\\n strict";\n"\\u0007";'] // TODO No way to store this content literally yet as directive
|
||||
['"use\\\n strict";\n"\\07";', ';"use strict";"\07";']
|
||||
];
|
||||
|
||||
for (var test in tests) {
|
||||
|
||||
16
test/mocha/with.js
Normal file
16
test/mocha/with.js
Normal file
@@ -0,0 +1,16 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
|
||||
describe("With", function() {
|
||||
it ("Should throw syntaxError when using with statement in strict mode", function() {
|
||||
var code = '"use strict";\nthrow NotEarlyError;\nwith ({}) { }';
|
||||
var test = function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "SyntaxError: Strict mode may not include a with statement";
|
||||
}
|
||||
assert.throws(test, error);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user