Merge branch 'master' into harmony
This commit is contained in:
@@ -1357,6 +1357,7 @@ merge(Compressor.prototype, {
|
||||
if (compressor.has_directive("use asm")) return self;
|
||||
if (compressor.option("unused")
|
||||
&& !self.uses_eval
|
||||
&& !self.uses_with
|
||||
) {
|
||||
var in_use = [];
|
||||
var in_use_ids = {}; // avoid expensive linear scans of in_use
|
||||
|
||||
@@ -88,7 +88,8 @@ function OutputStream(options) {
|
||||
|
||||
function make_string(str, quote) {
|
||||
var dq = 0, sq = 0;
|
||||
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){
|
||||
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
|
||||
function(s, i){
|
||||
switch (s) {
|
||||
case '"': ++dq; return '"';
|
||||
case "'": ++sq; return "'";
|
||||
@@ -101,8 +102,9 @@ function OutputStream(options) {
|
||||
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
case "\0": return "\\x00";
|
||||
case "\ufeff": return "\\ufeff";
|
||||
case "\0":
|
||||
return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
|
||||
}
|
||||
return s;
|
||||
});
|
||||
@@ -611,7 +613,7 @@ function OutputStream(options) {
|
||||
|
||||
PARENS(AST_New, function(output){
|
||||
var p = output.parent();
|
||||
if (no_constructor_parens(this, output)
|
||||
if (!need_constructor_parens(this, output)
|
||||
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
|
||||
|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
|
||||
return true;
|
||||
@@ -1175,7 +1177,7 @@ function OutputStream(options) {
|
||||
/* -----[ other expressions ]----- */
|
||||
DEFPRINT(AST_Call, function(self, output){
|
||||
self.expression.print(output);
|
||||
if (self instanceof AST_New && no_constructor_parens(self, output))
|
||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||
return;
|
||||
output.with_parens(function(){
|
||||
self.args.forEach(function(expr, i){
|
||||
@@ -1531,13 +1533,9 @@ function OutputStream(options) {
|
||||
};
|
||||
|
||||
// self should be AST_New. decide if we want to show parens or not.
|
||||
function no_constructor_parens(self, output) {
|
||||
return self.args.length == 0 && !output.option("beautify") ||
|
||||
!(self.expression instanceof AST_SymbolRef ||
|
||||
self.expression instanceof AST_Call ||
|
||||
self.expression instanceof AST_Function ||
|
||||
self.expression instanceof AST_Assign
|
||||
);
|
||||
function need_constructor_parens(self, output) {
|
||||
// Always print parentheses with arguments
|
||||
return self.args.length > 0;
|
||||
};
|
||||
|
||||
function best_of(a) {
|
||||
|
||||
63
lib/parse.js
63
lib/parse.js
@@ -234,7 +234,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
tokcol : 0,
|
||||
newline_before : false,
|
||||
regex_allowed : false,
|
||||
comments_before : []
|
||||
comments_before : [],
|
||||
directives : {},
|
||||
directive_stack : []
|
||||
};
|
||||
|
||||
function peek() { return S.text.charAt(S.pos); };
|
||||
@@ -403,8 +405,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
for (;;) {
|
||||
var ch = next(true, true);
|
||||
if (ch == "\\") {
|
||||
// read OctalEscapeSequence (XXX: deprecated if "strict mode")
|
||||
// https://github.com/mishoo/UglifyJS/issues/178
|
||||
var octal_len = 0, first = null;
|
||||
ch = read_while(function(ch){
|
||||
if (ch >= "0" && ch <= "7") {
|
||||
@@ -417,8 +417,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
|
||||
else ch = read_escaped_char(true);
|
||||
if (octal_len > 0) {
|
||||
if (ch !== "0" && next_token.has_directive("use strict"))
|
||||
parse_error("Octal literals are not allowed in strict mode");
|
||||
ch = String.fromCharCode(parseInt(ch, 8));
|
||||
} else {
|
||||
ch = read_escaped_char(true);
|
||||
}
|
||||
}
|
||||
else if ("\r\n\u2028\u2029".indexOf(ch) >= 0) parse_error("Unterminated string constant");
|
||||
else if (ch == quote) break;
|
||||
@@ -640,6 +645,35 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return S;
|
||||
};
|
||||
|
||||
next_token.add_directive = function(directive) {
|
||||
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
||||
|
||||
if (S.directives[directive] === undefined) {
|
||||
S.directives[directive] = 1;
|
||||
} else {
|
||||
S.directives[directive]++;
|
||||
}
|
||||
}
|
||||
|
||||
next_token.push_directives_stack = function() {
|
||||
S.directive_stack.push([]);
|
||||
}
|
||||
|
||||
next_token.pop_directives_stack = function() {
|
||||
var directives = S.directive_stack[S.directive_stack.length - 1];
|
||||
|
||||
for (var i = 0; i < directives.length; i++) {
|
||||
S.directives[directives[i]]--;
|
||||
}
|
||||
|
||||
S.directive_stack.pop();
|
||||
}
|
||||
|
||||
next_token.has_directive = function(directive) {
|
||||
return S.directives[directive] !== undefined &&
|
||||
S.directives[directive] > 0;
|
||||
}
|
||||
|
||||
return next_token;
|
||||
|
||||
};
|
||||
@@ -818,9 +852,15 @@ function parse($TEXT, options) {
|
||||
handle_regexp();
|
||||
switch (S.token.type) {
|
||||
case "string":
|
||||
if (S.in_directives) {
|
||||
if (is_token(peek(), "punc", ";") || peek().nlb) {
|
||||
S.input.add_directive(S.token.raw.substr(1, S.token.raw.length - 2));
|
||||
} else {
|
||||
S.in_directives = false;
|
||||
}
|
||||
}
|
||||
var dir = S.in_directives, stat = simple_statement();
|
||||
// XXXv2: decide how to fix directives
|
||||
if (dir && stat.body instanceof AST_String && !is("punc", ",")) {
|
||||
if (dir) {
|
||||
return new AST_Directive({
|
||||
start : stat.body.start,
|
||||
end : stat.body.end,
|
||||
@@ -1153,10 +1193,13 @@ function parse($TEXT, options) {
|
||||
S.in_directives = true;
|
||||
S.in_loop = 0;
|
||||
S.labels = [];
|
||||
if (block)
|
||||
if (block) {
|
||||
S.input.push_directives_stack();
|
||||
var a = block_();
|
||||
else
|
||||
S.input.pop_directives_stack();
|
||||
} else {
|
||||
var a = expression(false);
|
||||
}
|
||||
--S.in_function;
|
||||
S.in_loop = loop;
|
||||
S.labels = labels;
|
||||
@@ -2082,8 +2125,10 @@ function parse($TEXT, options) {
|
||||
return (function(){
|
||||
var start = S.token;
|
||||
var body = [];
|
||||
S.input.push_directives_stack();
|
||||
while (!is("eof"))
|
||||
body.push(statement());
|
||||
S.input.pop_directives_stack();
|
||||
var end = prev();
|
||||
var toplevel = options.toplevel;
|
||||
if (toplevel) {
|
||||
|
||||
@@ -6,12 +6,13 @@ ascii_only_true: {
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
return "\x000\x001\x007\x008\x00" +
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\x0B\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\x0B\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||
}
|
||||
|
||||
ascii_only_false: {
|
||||
@@ -22,11 +23,12 @@ ascii_only_false: {
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
return "\x000\x001\x007\x008\x00" +
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x00\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\x0B\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\x0B\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ concat_1: {
|
||||
var d = 1 + x() + 2 + 3 + "boo";
|
||||
|
||||
var e = 1 + x() + 2 + "X" + 3 + "boo";
|
||||
|
||||
// be careful with concatentation with "\0" with octal-looking strings.
|
||||
var f = "\0" + 360 + "\0" + 8 + "\0";
|
||||
}
|
||||
expect: {
|
||||
var a = "foobar" + x() + "moofoo" + y() + "xyz" + q();
|
||||
@@ -18,5 +21,6 @@ concat_1: {
|
||||
var c = 1 + x() + 2 + "boo";
|
||||
var d = 1 + x() + 2 + 3 + "boo";
|
||||
var e = 1 + x() + 2 + "X3boo";
|
||||
var f = "\x00360\08\0";
|
||||
}
|
||||
}
|
||||
|
||||
147
test/compress/issue-1105.js
Normal file
147
test/compress/issue-1105.js
Normal file
@@ -0,0 +1,147 @@
|
||||
with_in_global_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
var o = 42;
|
||||
with(o) {
|
||||
var foo = 'something'
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
expect: {
|
||||
var o=42;
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o);
|
||||
}
|
||||
}
|
||||
with_in_function_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
var o = 42;
|
||||
with(o) {
|
||||
var foo = "something"
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var o=42;
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o)
|
||||
}
|
||||
}
|
||||
}
|
||||
compress_with_with_in_other_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
var o = 42;
|
||||
with(o) {
|
||||
var foo = "something"
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
function bar() {
|
||||
var unused = 42;
|
||||
return something();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var o = 42;
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o)
|
||||
}
|
||||
function bar() {
|
||||
return something()
|
||||
}
|
||||
}
|
||||
}
|
||||
with_using_existing_variable_outside_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var o = {};
|
||||
var unused = {}; // Doesn't get removed because upper scope uses with
|
||||
function foo() {
|
||||
with(o) {
|
||||
var foo = "something"
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
foo()
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var o = {};
|
||||
var unused = {};
|
||||
function foo() {
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o)
|
||||
}
|
||||
foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
check_drop_unused_in_peer_function: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function outer() {
|
||||
var o = {};
|
||||
var unused = {}; // should be kept
|
||||
function foo() { // should be kept
|
||||
function not_in_use() {
|
||||
var nested_unused = "foo"; // should be dropped
|
||||
return 24;
|
||||
}
|
||||
var unused = {}; // should be kept
|
||||
with (o) {
|
||||
var foo = "something";
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
function bar() {
|
||||
var unused = {}; // should be dropped
|
||||
doSomethingElse();
|
||||
}
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function outer() {
|
||||
var o = {};
|
||||
var unused = {}; // should be kept
|
||||
function foo() { // should be kept
|
||||
function not_in_use() {
|
||||
return 24;
|
||||
}
|
||||
var unused = {}; // should be kept
|
||||
with (o)
|
||||
var foo = "something";
|
||||
doSomething(o);
|
||||
}
|
||||
function bar() {
|
||||
doSomethingElse();
|
||||
}
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,30 @@ new_statement: {
|
||||
expect_exact: "new x(1);new x(1)(2);new x(1)(2)(3);new new x(1);new new x(1)(2);new new x(1)(2);(new new x(1))(2);"
|
||||
}
|
||||
|
||||
new_statements_2: {
|
||||
input: {
|
||||
new x;
|
||||
new new x;
|
||||
new new new x;
|
||||
new true;
|
||||
new (0);
|
||||
new (!0);
|
||||
new (bar = function(foo) {this.foo=foo;})(123);
|
||||
new (bar = function(foo) {this.foo=foo;})();
|
||||
}
|
||||
expect_exact: "new x;new(new x);new(new(new x));new true;new 0;new(!0);new(bar=function(foo){this.foo=foo})(123);new(bar=function(foo){this.foo=foo});"
|
||||
}
|
||||
|
||||
new_statements_3: {
|
||||
input: {
|
||||
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;})();
|
||||
}
|
||||
expect_exact: "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_with_rewritten_true_value: {
|
||||
options = { booleans: true }
|
||||
input: {
|
||||
@@ -18,3 +42,11 @@ new_with_rewritten_true_value: {
|
||||
}
|
||||
expect_exact: "new(!0);"
|
||||
}
|
||||
|
||||
new_with_many_parameters: {
|
||||
input: {
|
||||
new foo.bar("baz");
|
||||
new x(/123/, 456);
|
||||
}
|
||||
expect_exact: 'new foo.bar("baz");new x(/123/,456);'
|
||||
}
|
||||
|
||||
61
test/mocha/directives.js
Normal file
61
test/mocha/directives.js
Normal file
@@ -0,0 +1,61 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
|
||||
describe("Directives", function() {
|
||||
it ("Should allow tokenizer to store directives state", function() {
|
||||
var tokenizer = uglify.tokenizer("", "foo.js");
|
||||
|
||||
// Stack level 0
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
|
||||
// Stack level 2
|
||||
tokenizer.push_directives_stack();
|
||||
tokenizer.push_directives_stack();
|
||||
tokenizer.add_directive("use strict");
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), true);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
|
||||
// Stack level 3
|
||||
tokenizer.push_directives_stack();
|
||||
tokenizer.add_directive("use strict");
|
||||
tokenizer.add_directive("use asm");
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), true);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), true);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
|
||||
// Stack level 2
|
||||
tokenizer.pop_directives_stack();
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), true);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
|
||||
// Stack level 3
|
||||
tokenizer.push_directives_stack();
|
||||
tokenizer.add_directive("use thing");
|
||||
tokenizer.add_directive("use\\\nasm");
|
||||
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 thing"), true);
|
||||
|
||||
// Stack level 2
|
||||
tokenizer.pop_directives_stack();
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), true);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
|
||||
// Stack level 1
|
||||
tokenizer.pop_directives_stack();
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
|
||||
// Stack level 0
|
||||
tokenizer.pop_directives_stack();
|
||||
assert.strictEqual(tokenizer.has_directive("use strict"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use asm"), false);
|
||||
assert.strictEqual(tokenizer.has_directive("use thing"), false);
|
||||
});
|
||||
});
|
||||
@@ -5,19 +5,31 @@ describe("New", function() {
|
||||
it("Should attach callback parens after some tokens", 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;})(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})(123);",
|
||||
"new (bar = function(foo) {\n this.foo = foo;\n});"
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
|
||||
@@ -31,4 +31,51 @@ describe("String literals", function() {
|
||||
var output = UglifyJS.parse('var a = "a\\\nb";').print_to_string();
|
||||
assert.equal(output, 'var a="ab";');
|
||||
});
|
||||
});
|
||||
|
||||
it("Should throw error in strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||
var inputs = [
|
||||
'"use strict";\n"\\76";',
|
||||
'"use strict";\nvar foo = "\\76";',
|
||||
'"use strict";\n"\\1";',
|
||||
'"use strict";\n"\\07";',
|
||||
'"use strict";\n"\\011"'
|
||||
];
|
||||
|
||||
var test = function(input) {
|
||||
return function() {
|
||||
var output = UglifyJS.parse(input);
|
||||
}
|
||||
};
|
||||
|
||||
var error = function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
||||
e.message === "Octal literals are not allowed in strict mode";
|
||||
}
|
||||
|
||||
for (var input in inputs) {
|
||||
assert.throws(test(inputs[input]), error);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||
var tests = [
|
||||
['"\\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
|
||||
];
|
||||
|
||||
for (var test in tests) {
|
||||
var output = UglifyJS.parse(tests[test][0]).print_to_string();
|
||||
assert.equal(output, tests[test][1]);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should not throw error when digit is 8 or 9", function() {
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\08";');
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\09";');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user