Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d13b71297e | ||
|
|
457f958af3 | ||
|
|
53517db3e4 | ||
|
|
c13caf4876 | ||
|
|
fbfa6178a6 | ||
|
|
5315dd95b0 | ||
|
|
31a7bf2a22 | ||
|
|
f0a29902ac | ||
|
|
0d820e4c0a | ||
|
|
f01f580d6c | ||
|
|
c01ff76288 | ||
|
|
83a42716c3 | ||
|
|
2557148bba | ||
|
|
dd22eda888 | ||
|
|
f4c77886e7 | ||
|
|
df547ffd97 | ||
|
|
70551febc8 | ||
|
|
44499a6643 | ||
|
|
470a7d4df1 | ||
|
|
551420132c | ||
|
|
b0040ba654 | ||
|
|
c93ca6ee53 | ||
|
|
df506439b1 | ||
|
|
36b2d35bf3 | ||
|
|
79c60032a5 | ||
|
|
a3754068dd | ||
|
|
2ba5f391e0 | ||
|
|
87119e44a0 | ||
|
|
b499e03f82 | ||
|
|
a478f275e4 | ||
|
|
e9e76dcf04 | ||
|
|
0dcedad2d5 | ||
|
|
36a430cd1e | ||
|
|
41a6eb892a | ||
|
|
91d87ae663 | ||
|
|
5beb7e4797 | ||
|
|
46caaa82ba | ||
|
|
5d258259a4 | ||
|
|
14c35739dd | ||
|
|
f5ceff6e4b | ||
|
|
4d6771b9b1 | ||
|
|
d17191111a | ||
|
|
0ff607cb80 | ||
|
|
1988495d71 | ||
|
|
fdc10086da | ||
|
|
746f5f6c62 | ||
|
|
d83d3d741a | ||
|
|
99ac73a635 | ||
|
|
a2e4c2fd97 | ||
|
|
94785e8e14 | ||
|
|
4dbdac9c31 | ||
|
|
78c8efd851 | ||
|
|
af310ba2d0 | ||
|
|
2f3930d1b9 | ||
|
|
d1a78920d9 | ||
|
|
d9cd3d33c8 | ||
|
|
22b47cdd63 | ||
|
|
4cf612dc9f | ||
|
|
a19d31dd33 | ||
|
|
01d6e0f223 | ||
|
|
ab050e7a94 | ||
|
|
75aa6ef848 | ||
|
|
519a00bd8a | ||
|
|
3ff0feddee | ||
|
|
74396acc86 | ||
|
|
036bca980c | ||
|
|
18c2b1841b |
13
README.md
13
README.md
@@ -87,6 +87,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
||||||
want to disable `negate_iife` under
|
want to disable `negate_iife` under
|
||||||
compressor options.
|
compressor options.
|
||||||
|
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
|
||||||
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
|
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
|
||||||
`spidermonkey` to write UglifyJS or SpiderMonkey AST
|
`spidermonkey` to write UglifyJS or SpiderMonkey AST
|
||||||
as JSON to STDOUT respectively.
|
as JSON to STDOUT respectively.
|
||||||
@@ -735,6 +736,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||||
example: `/*@__PURE__*/foo();`
|
example: `/*@__PURE__*/foo();`
|
||||||
|
|
||||||
|
- `strings` (default: `true`) -- compact string concatenations.
|
||||||
|
|
||||||
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||||
|
|
||||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
||||||
@@ -845,8 +848,14 @@ can pass additional arguments that control the code output:
|
|||||||
statement.
|
statement.
|
||||||
|
|
||||||
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
||||||
comments, `"some"` to preserve some comments, a regular expression string
|
comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
|
||||||
(e.g. `/^!/`) or a function.
|
`@license`, or `@preserve` (case-insensitive), a regular expression string
|
||||||
|
(e.g. `/^!/`), or a function which returns `boolean`, e.g.
|
||||||
|
```js
|
||||||
|
function(node, comment) {
|
||||||
|
return comment.value.indexOf("@type " + node.TYPE) >= 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- `indent_level` (default `4`)
|
- `indent_level` (default `4`)
|
||||||
|
|
||||||
|
|||||||
20
bin/uglifyjs
20
bin/uglifyjs
@@ -36,6 +36,7 @@ program.option("-c, --compress [options]", "Enable compressor/specify compressor
|
|||||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
||||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
||||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
||||||
|
program.option("-O, --output-opts [options]", "Output options (beautify disabled).", parse_js());
|
||||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||||
@@ -53,13 +54,14 @@ program.option("--toplevel", "Compress and/or mangle variables in toplevel scope
|
|||||||
program.option("--verbose", "Print diagnostic messages.");
|
program.option("--verbose", "Print diagnostic messages.");
|
||||||
program.option("--warn", "Print warning messages.");
|
program.option("--warn", "Print warning messages.");
|
||||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
||||||
|
program.option("--reduce-test", "Reduce a standalone `console.log` based test case.");
|
||||||
program.arguments("[files...]").parseArgv(process.argv);
|
program.arguments("[files...]").parseArgv(process.argv);
|
||||||
if (program.configFile) {
|
if (program.configFile) {
|
||||||
options = JSON.parse(read_file(program.configFile));
|
options = JSON.parse(read_file(program.configFile));
|
||||||
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
||||||
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
||||||
expression: true
|
expression: true
|
||||||
}).getValue();
|
}).value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||||
@@ -93,6 +95,10 @@ if (program.beautify) {
|
|||||||
options.output.beautify = true;
|
options.output.beautify = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (program.outputOpts) {
|
||||||
|
if (program.beautify) fatal("--beautify cannot be used with --output-opts");
|
||||||
|
options.output = typeof program.outputOpts == "object" ? program.outputOpts : {};
|
||||||
|
}
|
||||||
if (program.comments) {
|
if (program.comments) {
|
||||||
if (typeof options.output != "object") options.output = {};
|
if (typeof options.output != "object") options.output = {};
|
||||||
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
||||||
@@ -210,7 +216,15 @@ function run() {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
}
|
}
|
||||||
var result = UglifyJS.minify(files, options);
|
if (program.reduceTest) {
|
||||||
|
// load on demand - assumes dev tree checked out
|
||||||
|
var reduce_test = require("../test/reduce");
|
||||||
|
var testcase = files[0] || files[Object.keys(files)[0]];
|
||||||
|
var result = reduce_test(testcase, options, {verbose: true});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var result = UglifyJS.minify(files, options);
|
||||||
|
}
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
var ex = result.error;
|
var ex = result.error;
|
||||||
if (ex.name == "SyntaxError") {
|
if (ex.name == "SyntaxError") {
|
||||||
@@ -370,7 +384,7 @@ function parse_js(flag) {
|
|||||||
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
||||||
|
|
||||||
function to_string(value) {
|
function to_string(value) {
|
||||||
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
|
return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
|
||||||
quote_keys: true
|
quote_keys: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
20
lib/ast.js
20
lib/ast.js
@@ -169,10 +169,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
|||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
function walk_body(node, visitor) {
|
function walk_body(node, visitor) {
|
||||||
var body = node.body;
|
node.body.forEach(function(node) {
|
||||||
if (body instanceof AST_Statement) {
|
|
||||||
body._walk(visitor);
|
|
||||||
} else body.forEach(function(node) {
|
|
||||||
node._walk(visitor);
|
node._walk(visitor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -351,7 +348,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
filename: "wrap=" + JSON.stringify(name)
|
filename: "wrap=" + JSON.stringify(name)
|
||||||
}).transform(new TreeTransformer(function(node) {
|
}).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(body);
|
return List.splice(body);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@@ -370,7 +367,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
filename: "enclose=" + JSON.stringify(args_values)
|
filename: "enclose=" + JSON.stringify(args_values)
|
||||||
}).transform(new TreeTransformer(function(node) {
|
}).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(body);
|
return List.splice(body);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -618,7 +615,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
|
|||||||
getProperty: function() {
|
getProperty: function() {
|
||||||
var p = this.property;
|
var p = this.property;
|
||||||
if (p instanceof AST_Constant) {
|
if (p instanceof AST_Constant) {
|
||||||
return p.getValue();
|
return p.value;
|
||||||
}
|
}
|
||||||
if (p instanceof AST_UnaryPrefix
|
if (p instanceof AST_UnaryPrefix
|
||||||
&& p.operator == "void"
|
&& p.operator == "void"
|
||||||
@@ -824,9 +821,6 @@ var AST_This = DEFNODE("This", null, {
|
|||||||
|
|
||||||
var AST_Constant = DEFNODE("Constant", null, {
|
var AST_Constant = DEFNODE("Constant", null, {
|
||||||
$documentation: "Base class for all constants",
|
$documentation: "Base class for all constants",
|
||||||
getValue: function() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var AST_String = DEFNODE("String", "value quote", {
|
var AST_String = DEFNODE("String", "value quote", {
|
||||||
@@ -967,11 +961,13 @@ TreeWalker.prototype = {
|
|||||||
in_boolean_context: function() {
|
in_boolean_context: function() {
|
||||||
var self = this.self();
|
var self = this.self();
|
||||||
for (var i = 0, p; p = this.parent(i); i++) {
|
for (var i = 0, p; p = this.parent(i); i++) {
|
||||||
if (p instanceof AST_SimpleStatement
|
if (p instanceof AST_Conditional && p.condition === self
|
||||||
|| p instanceof AST_Conditional && p.condition === self
|
|
||||||
|| p instanceof AST_DWLoop && p.condition === self
|
|| p instanceof AST_DWLoop && p.condition === self
|
||||||
|| p instanceof AST_For && p.condition === self
|
|| p instanceof AST_For && p.condition === self
|
||||||
|| p instanceof AST_If && p.condition === self
|
|| p instanceof AST_If && p.condition === self
|
||||||
|
|| p instanceof AST_Return && p.in_bool
|
||||||
|
|| p instanceof AST_Sequence && p.tail_node() !== self
|
||||||
|
|| p instanceof AST_SimpleStatement
|
||||||
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
|
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
1175
lib/compress.js
1175
lib/compress.js
File diff suppressed because it is too large
Load Diff
126
lib/output.js
126
lib/output.js
@@ -43,8 +43,6 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
|
||||||
|
|
||||||
function is_some_comments(comment) {
|
function is_some_comments(comment) {
|
||||||
// multiline comment
|
// multiline comment
|
||||||
return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
|
return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
|
||||||
@@ -121,15 +119,20 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
} : function(str) {
|
} : function(str) {
|
||||||
var s = "";
|
var s = "";
|
||||||
for (var i = 0; i < str.length; i++) {
|
for (var i = 0, j = 0; i < str.length; i++) {
|
||||||
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|
var code = str.charCodeAt(i);
|
||||||
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
|
if (is_surrogate_pair_head(code)) {
|
||||||
s += "\\u" + str.charCodeAt(i).toString(16);
|
if (is_surrogate_pair_tail(str.charCodeAt(i + 1))) {
|
||||||
} else {
|
i++;
|
||||||
s += str[i];
|
continue;
|
||||||
|
}
|
||||||
|
} else if (!is_surrogate_pair_tail(code)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
s += str.slice(j, i) + "\\u" + code.toString(16);
|
||||||
|
j = i + 1;
|
||||||
}
|
}
|
||||||
return s;
|
return j == 0 ? str : s + str.slice(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
function make_string(str, quote) {
|
function make_string(str, quote) {
|
||||||
@@ -378,7 +381,7 @@ function OutputStream(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function force_semicolon() {
|
function force_semicolon() {
|
||||||
might_need_semicolon = false;
|
if (might_need_semicolon) print(";");
|
||||||
print(";");
|
print(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,17 +588,7 @@ function OutputStream(options) {
|
|||||||
force_semicolon : force_semicolon,
|
force_semicolon : force_semicolon,
|
||||||
to_utf8 : to_utf8,
|
to_utf8 : to_utf8,
|
||||||
print_name : function(name) { print(make_name(name)) },
|
print_name : function(name) { print(make_name(name)) },
|
||||||
print_string : function(str, quote, escape_directive) {
|
print_string : function(str, quote) { print(encode_string(str, quote)) },
|
||||||
var encoded = encode_string(str, quote);
|
|
||||||
if (escape_directive === true && encoded.indexOf("\\") === -1) {
|
|
||||||
// Insert semicolons to break directive prologue
|
|
||||||
if (!EXPECT_DIRECTIVE.test(OUTPUT)) {
|
|
||||||
force_semicolon();
|
|
||||||
}
|
|
||||||
force_semicolon();
|
|
||||||
}
|
|
||||||
print(encoded);
|
|
||||||
},
|
|
||||||
next_indent : next_indent,
|
next_indent : next_indent,
|
||||||
with_indent : with_indent,
|
with_indent : with_indent,
|
||||||
with_block : with_block,
|
with_block : with_block,
|
||||||
@@ -633,17 +626,10 @@ function OutputStream(options) {
|
|||||||
nodetype.DEFMETHOD("_codegen", generator);
|
nodetype.DEFMETHOD("_codegen", generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var in_directive = false;
|
var use_asm = false;
|
||||||
var active_scope = null;
|
|
||||||
var use_asm = null;
|
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
||||||
var self = this, generator = self._codegen;
|
var self = this, generator = self._codegen;
|
||||||
if (self instanceof AST_Scope) {
|
|
||||||
active_scope = self;
|
|
||||||
} else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
|
||||||
use_asm = active_scope;
|
|
||||||
}
|
|
||||||
function doit() {
|
function doit() {
|
||||||
stream.prepend_comments(self);
|
stream.prepend_comments(self);
|
||||||
self.add_source_map(stream);
|
self.add_source_map(stream);
|
||||||
@@ -657,9 +643,6 @@ function OutputStream(options) {
|
|||||||
doit();
|
doit();
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
if (self === use_asm) {
|
|
||||||
use_asm = null;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||||
|
|
||||||
@@ -799,7 +782,9 @@ function OutputStream(options) {
|
|||||||
PARENS(AST_Number, function(output) {
|
PARENS(AST_Number, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_PropAccess && p.expression === this) {
|
if (p instanceof AST_PropAccess && p.expression === this) {
|
||||||
var value = this.getValue();
|
var value = this.value;
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/115
|
||||||
|
// https://github.com/mishoo/UglifyJS2/pull/1009
|
||||||
if (value < 0 || /^0/.test(make_num(value))) {
|
if (value < 0 || /^0/.test(make_num(value))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -828,7 +813,18 @@ function OutputStream(options) {
|
|||||||
/* -----[ PRINTERS ]----- */
|
/* -----[ PRINTERS ]----- */
|
||||||
|
|
||||||
DEFPRINT(AST_Directive, function(self, output) {
|
DEFPRINT(AST_Directive, function(self, output) {
|
||||||
output.print_string(self.value, self.quote);
|
var quote = self.quote;
|
||||||
|
var value = self.value;
|
||||||
|
switch (output.option("quote_style")) {
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
if (value.indexOf('"') == -1) quote = '"';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (value.indexOf("'") == -1) quote = "'";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output.print(quote + value + quote);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Debugger, function(self, output) {
|
DEFPRINT(AST_Debugger, function(self, output) {
|
||||||
@@ -840,30 +836,27 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function display_body(body, is_toplevel, output, allow_directives) {
|
function display_body(body, is_toplevel, output, allow_directives) {
|
||||||
var last = body.length - 1;
|
var last = body.length - 1;
|
||||||
in_directive = allow_directives;
|
var in_directive = allow_directives;
|
||||||
|
var was_asm = use_asm;
|
||||||
body.forEach(function(stmt, i) {
|
body.forEach(function(stmt, i) {
|
||||||
if (in_directive === true && !(stmt instanceof AST_Directive ||
|
if (in_directive) {
|
||||||
stmt instanceof AST_EmptyStatement ||
|
if (stmt instanceof AST_Directive) {
|
||||||
(stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
|
if (stmt.value == "use asm") use_asm = true;
|
||||||
)) {
|
} else if (!(stmt instanceof AST_EmptyStatement)) {
|
||||||
in_directive = false;
|
if (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) {
|
||||||
}
|
output.force_semicolon();
|
||||||
if (!(stmt instanceof AST_EmptyStatement)) {
|
}
|
||||||
output.indent();
|
in_directive = false;
|
||||||
stmt.print(output);
|
|
||||||
if (!(i == last && is_toplevel)) {
|
|
||||||
output.newline();
|
|
||||||
if (is_toplevel) output.newline();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_directive === true &&
|
if (stmt instanceof AST_EmptyStatement) return;
|
||||||
stmt instanceof AST_SimpleStatement &&
|
output.indent();
|
||||||
stmt.body instanceof AST_String
|
stmt.print(output);
|
||||||
) {
|
if (i == last && is_toplevel) return;
|
||||||
in_directive = false;
|
output.newline();
|
||||||
}
|
if (is_toplevel) output.newline();
|
||||||
});
|
});
|
||||||
in_directive = false;
|
use_asm = was_asm;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
|
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
|
||||||
@@ -1221,7 +1214,7 @@ function OutputStream(options) {
|
|||||||
output.print_string(prop);
|
output.print_string(prop);
|
||||||
output.print("]");
|
output.print("]");
|
||||||
} else {
|
} else {
|
||||||
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
if (expr instanceof AST_Number && expr.value >= 0) {
|
||||||
if (!/[xa-f.)]/i.test(output.last())) {
|
if (!/[xa-f.)]/i.test(output.last())) {
|
||||||
output.print(".");
|
output.print(".");
|
||||||
}
|
}
|
||||||
@@ -1345,27 +1338,34 @@ function OutputStream(options) {
|
|||||||
output.print("this");
|
output.print("this");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Constant, function(self, output) {
|
DEFPRINT(AST_Constant, function(self, output) {
|
||||||
output.print(self.getValue());
|
output.print(self.value);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_String, function(self, output) {
|
DEFPRINT(AST_String, function(self, output) {
|
||||||
output.print_string(self.getValue(), self.quote, in_directive);
|
output.print_string(self.value, self.quote);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Number, function(self, output) {
|
DEFPRINT(AST_Number, function(self, output) {
|
||||||
if (use_asm && self.start && self.start.raw != null) {
|
if (use_asm && self.start && self.start.raw != null) {
|
||||||
output.print(self.start.raw);
|
output.print(self.start.raw);
|
||||||
} else {
|
} else {
|
||||||
output.print(make_num(self.getValue()));
|
output.print(make_num(self.value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_RegExp, function(self, output) {
|
DEFPRINT(AST_RegExp, function(self, output) {
|
||||||
var regexp = self.getValue();
|
var regexp = self.value;
|
||||||
var str = regexp.toString();
|
var str = regexp.toString();
|
||||||
|
var end = str.lastIndexOf("/");
|
||||||
if (regexp.raw_source) {
|
if (regexp.raw_source) {
|
||||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
str = "/" + regexp.raw_source + str.slice(end);
|
||||||
|
} else if (end == 1) {
|
||||||
|
str = "/(?:)" + str.slice(end);
|
||||||
|
} else if (str.indexOf("/", 1) < end) {
|
||||||
|
str = "/" + str.slice(1, end).replace(/\\\\|[^/]?\//g, function(match) {
|
||||||
|
return match[0] == "\\" ? match : match.slice(0, -1) + "\\/";
|
||||||
|
}) + str.slice(end);
|
||||||
}
|
}
|
||||||
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(seq) {
|
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(match) {
|
||||||
switch (seq[1]) {
|
switch (match[1]) {
|
||||||
case "\n": return "\\n";
|
case "\n": return "\\n";
|
||||||
case "\r": return "\\r";
|
case "\r": return "\\r";
|
||||||
case "\t": return "\t";
|
case "\t": return "\t";
|
||||||
@@ -1375,7 +1375,7 @@ function OutputStream(options) {
|
|||||||
case "\x0B": return "\v";
|
case "\x0B": return "\v";
|
||||||
case "\u2028": return "\\u2028";
|
case "\u2028": return "\\u2028";
|
||||||
case "\u2029": return "\\u2029";
|
case "\u2029": return "\\u2029";
|
||||||
default: return seq;
|
default: return match;
|
||||||
}
|
}
|
||||||
}).replace(/[\n\r\u2028\u2029]/g, function(c) {
|
}).replace(/[\n\r\u2028\u2029]/g, function(c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|||||||
11
lib/parse.js
11
lib/parse.js
@@ -133,14 +133,10 @@ function is_letter(code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function is_surrogate_pair_head(code) {
|
function is_surrogate_pair_head(code) {
|
||||||
if (typeof code == "string")
|
|
||||||
code = code.charCodeAt(0);
|
|
||||||
return code >= 0xd800 && code <= 0xdbff;
|
return code >= 0xd800 && code <= 0xdbff;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_surrogate_pair_tail(code) {
|
function is_surrogate_pair_tail(code) {
|
||||||
if (typeof code == "string")
|
|
||||||
code = code.charCodeAt(0);
|
|
||||||
return code >= 0xdc00 && code <= 0xdfff;
|
return code >= 0xdc00 && code <= 0xdfff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,9 +786,10 @@ function parse($TEXT, options) {
|
|||||||
var dir = S.in_directives;
|
var dir = S.in_directives;
|
||||||
var body = expression(true);
|
var body = expression(true);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
var token = body.start;
|
if (body instanceof AST_String) {
|
||||||
if (body instanceof AST_String && token.raw.indexOf("\\") == -1) {
|
var value = body.start.raw.slice(1, -1);
|
||||||
S.input.add_directive(token.value);
|
S.input.add_directive(value);
|
||||||
|
body.value = value;
|
||||||
} else {
|
} else {
|
||||||
S.in_directives = dir = false;
|
S.in_directives = dir = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,6 +428,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
if (options.cache && node instanceof AST_Toplevel) {
|
if (options.cache && node instanceof AST_Toplevel) {
|
||||||
node.globals.each(mangle);
|
node.globals.each(mangle);
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_Defun && tw.has_directive("use asm")) {
|
||||||
|
var sym = new AST_SymbolRef(node.name);
|
||||||
|
sym.scope = node;
|
||||||
|
sym.reference(options);
|
||||||
|
}
|
||||||
node.variables.each(function(def) {
|
node.variables.each(function(def) {
|
||||||
if (!defer_redef(def)) mangle(def);
|
if (!defer_redef(def)) mangle(def);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
|
|
||||||
(function(DEF) {
|
(function(DEF) {
|
||||||
function do_list(list, tw) {
|
function do_list(list, tw) {
|
||||||
return MAP(list, function(node) {
|
return List(list, function(node) {
|
||||||
return node.transform(tw, true);
|
return node.transform(tw, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
20
lib/utils.js
20
lib/utils.js
@@ -113,8 +113,8 @@ function return_true() { return true; }
|
|||||||
function return_this() { return this; }
|
function return_this() { return this; }
|
||||||
function return_null() { return null; }
|
function return_null() { return null; }
|
||||||
|
|
||||||
var MAP = (function() {
|
var List = (function() {
|
||||||
function MAP(a, f, backwards) {
|
function List(a, f, backwards) {
|
||||||
var ret = [], top = [], i;
|
var ret = [], top = [], i;
|
||||||
function doit() {
|
function doit() {
|
||||||
var val = f(a[i], i);
|
var val = f(a[i], i);
|
||||||
@@ -149,14 +149,14 @@ var MAP = (function() {
|
|||||||
}
|
}
|
||||||
return top.concat(ret);
|
return top.concat(ret);
|
||||||
}
|
}
|
||||||
MAP.at_top = function(val) { return new AtTop(val) };
|
List.at_top = function(val) { return new AtTop(val); };
|
||||||
MAP.splice = function(val) { return new Splice(val) };
|
List.splice = function(val) { return new Splice(val); };
|
||||||
MAP.last = function(val) { return new Last(val) };
|
List.last = function(val) { return new Last(val); };
|
||||||
var skip = MAP.skip = {};
|
var skip = List.skip = {};
|
||||||
function AtTop(val) { this.v = val }
|
function AtTop(val) { this.v = val; }
|
||||||
function Splice(val) { this.v = val }
|
function Splice(val) { this.v = val; }
|
||||||
function Last(val) { this.v = val }
|
function Last(val) { this.v = val; }
|
||||||
return MAP;
|
return List;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function push_uniq(array, el) {
|
function push_uniq(array, el) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.7.2",
|
"version": "3.8.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ holes_and_undefined: {
|
|||||||
constant_join: {
|
constant_join: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -65,6 +66,7 @@ constant_join: {
|
|||||||
constant_join_2: {
|
constant_join_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -94,9 +96,11 @@ constant_join_2: {
|
|||||||
constant_join_3: {
|
constant_join_3: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var foo, bar, baz;
|
||||||
var a = [ null ].join();
|
var a = [ null ].join();
|
||||||
var b = [ , ].join();
|
var b = [ , ].join();
|
||||||
var c = [ , 1, , 3 ].join();
|
var c = [ , 1, , 3 ].join();
|
||||||
@@ -111,6 +115,7 @@ constant_join_3: {
|
|||||||
var l = [ foo, bar + "baz" ].join("");
|
var l = [ foo, bar + "baz" ].join("");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var foo, bar, baz;
|
||||||
var a = "";
|
var a = "";
|
||||||
var b = "";
|
var b = "";
|
||||||
var c = ",1,,3";
|
var c = ",1,,3";
|
||||||
|
|||||||
@@ -166,3 +166,69 @@ asm_nested_functions: {
|
|||||||
}
|
}
|
||||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3636_1: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function n(stdlib, foreign, buffer) {
|
||||||
|
"use asm";
|
||||||
|
function add(x, y) {
|
||||||
|
x = x | 0;
|
||||||
|
y = y | 0;
|
||||||
|
return x + y | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: add
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function n(o, e, u) {
|
||||||
|
"use asm";
|
||||||
|
function d(n, o) {
|
||||||
|
n = n | 0;
|
||||||
|
o = o | 0;
|
||||||
|
return n + o | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: d
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3636_2: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var n = function(stdlib, foreign, buffer) {
|
||||||
|
"use asm";
|
||||||
|
function add(x, y) {
|
||||||
|
x = x | 0;
|
||||||
|
y = y | 0;
|
||||||
|
return x + y | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: add
|
||||||
|
};
|
||||||
|
};
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var n = function(n, o, e) {
|
||||||
|
"use asm";
|
||||||
|
function r(n, o) {
|
||||||
|
n = n | 0;
|
||||||
|
o = o | 0;
|
||||||
|
return n + o | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: r
|
||||||
|
};
|
||||||
|
};
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,3 +86,70 @@ issue_3465_3: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2737_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(bar) {
|
||||||
|
for (;bar();) break;
|
||||||
|
})(function qux() {
|
||||||
|
return console.log("PASS"), qux;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(bar) {
|
||||||
|
for (;bar();) break;
|
||||||
|
})(function() {
|
||||||
|
return console.log("PASS"), 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3658: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
console || f();
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
console || f();
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3690: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return function() {
|
||||||
|
return a = [ this ];
|
||||||
|
}() ? "PASS" : "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return function() {
|
||||||
|
return 1;
|
||||||
|
}() ? "PASS" : "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -5863,8 +5863,8 @@ issue_2974: {
|
|||||||
var c = 0;
|
var c = 0;
|
||||||
(function(b) {
|
(function(b) {
|
||||||
var a = 2;
|
var a = 2;
|
||||||
for (; b.null = -4, c++, b.null && --a > 0;);
|
for (;c++, (!0).null && --a > 0;);
|
||||||
})(!0),
|
})(),
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
@@ -7399,3 +7399,369 @@ issue_3628_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "foo bar"
|
expect_stdout: "foo bar"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3641: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b;
|
||||||
|
try {
|
||||||
|
a = "foo";
|
||||||
|
b = (a += (A.p = 0, "bar")) % 0;
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b;
|
||||||
|
try {
|
||||||
|
a = "foo";
|
||||||
|
b = (a += (A.p = 0, "bar")) % 0;
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "foo undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3651: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = "PASS";
|
||||||
|
try {
|
||||||
|
a = function() {
|
||||||
|
try {
|
||||||
|
var c = 1;
|
||||||
|
while (0 < --c);
|
||||||
|
} catch (e) {} finally {
|
||||||
|
throw 42;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
b = "FAIL";
|
||||||
|
a.p;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = "PASS";
|
||||||
|
try {
|
||||||
|
a = function() {
|
||||||
|
try {
|
||||||
|
var c = 1;
|
||||||
|
while (0 < --c);
|
||||||
|
} catch (e) {} finally {
|
||||||
|
throw 42;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
b = "FAIL";
|
||||||
|
a.p;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3671: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
try {
|
||||||
|
a++;
|
||||||
|
A += 0;
|
||||||
|
a = 1 + a;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
try {
|
||||||
|
a++;
|
||||||
|
A += 0;
|
||||||
|
a = 1 + a;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
call_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
a = console;
|
||||||
|
(function() {})();
|
||||||
|
a.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(function() {})();
|
||||||
|
(a = console).log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
call_1_symbol: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {}
|
||||||
|
a = console;
|
||||||
|
f();
|
||||||
|
a.log(typeof f);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {}
|
||||||
|
f();
|
||||||
|
(a = console).log(typeof f);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
call_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
a = console;
|
||||||
|
(function() {
|
||||||
|
return 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
})();
|
||||||
|
a.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(function() {
|
||||||
|
return 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
})();
|
||||||
|
(a = console).log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
call_2_symbol: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
return 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
a = console;
|
||||||
|
f();
|
||||||
|
a.log(typeof f);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
return 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
(a = console).log(typeof f);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
call_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
a = console;
|
||||||
|
(function() {
|
||||||
|
a = {
|
||||||
|
log: function() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
a.log("FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
a = console;
|
||||||
|
(function() {
|
||||||
|
a = {
|
||||||
|
log: function() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
a.log("FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
call_3_symbol: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
a = {
|
||||||
|
log: function() {
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = console;
|
||||||
|
f();
|
||||||
|
a.log("FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
a = {
|
||||||
|
log: function() {
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = console;
|
||||||
|
f();
|
||||||
|
a.log("FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3698_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var log = console.log;
|
||||||
|
var a, b = 0, c = 0;
|
||||||
|
(function() {
|
||||||
|
a = b;
|
||||||
|
})(b++, (b++, c++));
|
||||||
|
log(a, b, c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var log = console.log;
|
||||||
|
var a, b = 0, c = 0;
|
||||||
|
(function() {
|
||||||
|
a = b;
|
||||||
|
})(b++, (b++, c++));
|
||||||
|
log(a, b, c);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3698_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var log = console.log;
|
||||||
|
var a, b = 0, c = 0, d = 1;
|
||||||
|
(function f() {
|
||||||
|
a = b;
|
||||||
|
d-- && f();
|
||||||
|
})(b++, (b++, c++));
|
||||||
|
log(a, b, c, d);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var log = console.log;
|
||||||
|
var a, b = 0, c = 0, d = 1;
|
||||||
|
(function f() {
|
||||||
|
a = b;
|
||||||
|
d-- && f();
|
||||||
|
})(b++, (b++, c++));
|
||||||
|
log(a, b, c, d);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2 1 -1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3698_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 0;
|
||||||
|
(function f(c) {
|
||||||
|
{
|
||||||
|
b++;
|
||||||
|
var bar_1 = (b = 1 + b, c = 0);
|
||||||
|
a-- && f();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b = 0;
|
||||||
|
(function f(c) {
|
||||||
|
var bar_1 = (b = 1 + ++b, c = 0);
|
||||||
|
a-- && f();
|
||||||
|
})();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3700: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
a = "PASS";
|
||||||
|
(function() {
|
||||||
|
throw 0;
|
||||||
|
})();
|
||||||
|
a = 1 + a;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
a = "PASS";
|
||||||
|
(function() {
|
||||||
|
throw 0;
|
||||||
|
})();
|
||||||
|
a = 1 + a;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ unsafe_comps: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var obj1, obj2;
|
var obj1, obj2;
|
||||||
obj2 < obj1 ? g1() : f1();
|
(obj2 < obj1 ? g1 : f1)();
|
||||||
obj1 < obj2 ? f2() : g2();
|
(obj1 < obj2 ? f2 : g2)();
|
||||||
obj1 < obj2 ? g3() : f3();
|
(obj1 < obj2 ? g3 : f3)();
|
||||||
obj2 < obj1 ? f4() : g4();
|
(obj2 < obj1 ? f4 : g4)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ concat_1: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_2: {
|
concat_2: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + (2 + 3),
|
1 + (2 + 3),
|
||||||
@@ -55,7 +57,9 @@ concat_2: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_3: {
|
concat_3: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + 2 + (3 + 4 + 5),
|
1 + 2 + (3 + 4 + 5),
|
||||||
@@ -84,7 +88,9 @@ concat_3: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_4: {
|
concat_4: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + "2" + (3 + 4 + 5),
|
1 + "2" + (3 + 4 + 5),
|
||||||
@@ -113,7 +119,9 @@ concat_4: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_5: {
|
concat_5: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
"1" + 2 + (3 + 4 + 5),
|
"1" + 2 + (3 + 4 + 5),
|
||||||
@@ -142,7 +150,9 @@ concat_5: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_6: {
|
concat_6: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
"1" + "2" + (3 + 4 + 5),
|
"1" + "2" + (3 + 4 + 5),
|
||||||
@@ -171,6 +181,9 @@ concat_6: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_7: {
|
concat_7: {
|
||||||
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
"" + 1,
|
"" + 1,
|
||||||
@@ -197,6 +210,9 @@ concat_7: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_8: {
|
concat_8: {
|
||||||
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + "",
|
1 + "",
|
||||||
@@ -221,3 +237,20 @@ concat_8: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3689: {
|
||||||
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return a + ("" + (a[0] = 0));
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return a + ("" + (a[0] = 0));
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect_stdout: "00"
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ ifs_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
foo ? x() : bar ? y() : baz && z();
|
foo ? x() : bar ? y() : baz && z();
|
||||||
foo ? x() : bar ? y() : baz ? z() : t();
|
(foo ? x : bar ? y : baz ? z : t)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,11 +289,50 @@ cond_5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
(some_condition() && some_other_condition() ? do_something : alternate)();
|
||||||
some_condition() && some_other_condition() && do_something();
|
some_condition() && some_other_condition() && do_something();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_6: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x ? a : b;
|
||||||
|
x ? a : a;
|
||||||
|
|
||||||
|
x ? y ? a : b : c;
|
||||||
|
x ? y ? a : a : b;
|
||||||
|
x ? y ? a : b : b;
|
||||||
|
x ? y ? a : b : a;
|
||||||
|
x ? y ? a : a : a;
|
||||||
|
|
||||||
|
x ? a : y ? b : c;
|
||||||
|
x ? a : y ? a : b;
|
||||||
|
x ? a : y ? b : b;
|
||||||
|
x ? a : y ? b : a;
|
||||||
|
x ? a : y ? a : a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x ? a : b;
|
||||||
|
x, a;
|
||||||
|
|
||||||
|
x ? y ? a : b : c;
|
||||||
|
x ? (y, a) : b;
|
||||||
|
x && y ? a : b;
|
||||||
|
!x || y ? a : b;
|
||||||
|
x && y, a;
|
||||||
|
|
||||||
|
x ? a : y ? b : c;
|
||||||
|
x || y ? a : b;
|
||||||
|
x ? a : (y, b);
|
||||||
|
!x && y ? b : a;
|
||||||
|
!x && y, a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cond_7: {
|
cond_7: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -663,6 +702,87 @@ cond_9: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_10: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
if (1 == a) return "foo";
|
||||||
|
if (2 == a) return "foo";
|
||||||
|
if (3 == a) return "foo";
|
||||||
|
if (4 == a) return 42;
|
||||||
|
if (5 == a) return "foo";
|
||||||
|
if (6 == a) return "foo";
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return 1 == a || 2 == a || 3 == a ? "foo" : 4 == a ? 42 : 5 == a || 6 == a ? "foo" : "bar";
|
||||||
|
}
|
||||||
|
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
|
||||||
|
}
|
||||||
|
expect_stdout: "foo foo foo 42 foo foo bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
cond_11: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
p: "foo",
|
||||||
|
q: function() {
|
||||||
|
return this.p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function f() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
function g(a) {
|
||||||
|
return a ? f() : o.q();
|
||||||
|
}
|
||||||
|
console.log(g(0), g(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
p: "foo",
|
||||||
|
q: function() {
|
||||||
|
return this.p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function f() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
function g(a) {
|
||||||
|
return a ? f() : o.q();
|
||||||
|
}
|
||||||
|
console.log(g(0), g(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "foo bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
cond_12: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x ? y && a : a;
|
||||||
|
x ? y || a : a;
|
||||||
|
x ? a : y && a;
|
||||||
|
x ? a : y || a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(!x || y) && a;
|
||||||
|
x && y || a;
|
||||||
|
(x || y) && a;
|
||||||
|
!x && y || a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ternary_boolean_consequent: {
|
ternary_boolean_consequent: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -1515,3 +1635,34 @@ issue_3576: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3668: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
var undefined = typeof f;
|
||||||
|
if (!f) return undefined;
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
var undefined = typeof f;
|
||||||
|
return f ? void 0 : undefined;
|
||||||
|
} catch (e) {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -141,207 +141,6 @@ try_catch_finally: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
accessor: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
({
|
|
||||||
get a() {},
|
|
||||||
set a(v){
|
|
||||||
this.b = 2;
|
|
||||||
},
|
|
||||||
b: 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
expect: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2233_1: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
Array.isArray;
|
|
||||||
Boolean;
|
|
||||||
console.log;
|
|
||||||
Date;
|
|
||||||
decodeURI;
|
|
||||||
decodeURIComponent;
|
|
||||||
encodeURI;
|
|
||||||
encodeURIComponent;
|
|
||||||
Error.name;
|
|
||||||
escape;
|
|
||||||
eval;
|
|
||||||
EvalError;
|
|
||||||
Function.length;
|
|
||||||
isFinite;
|
|
||||||
isNaN;
|
|
||||||
JSON;
|
|
||||||
Math.random;
|
|
||||||
Number.isNaN;
|
|
||||||
parseFloat;
|
|
||||||
parseInt;
|
|
||||||
RegExp;
|
|
||||||
Object.defineProperty;
|
|
||||||
String.fromCharCode;
|
|
||||||
RangeError;
|
|
||||||
ReferenceError;
|
|
||||||
SyntaxError;
|
|
||||||
TypeError;
|
|
||||||
unescape;
|
|
||||||
URIError;
|
|
||||||
}
|
|
||||||
expect: {}
|
|
||||||
expect_stdout: true
|
|
||||||
}
|
|
||||||
|
|
||||||
global_timeout_and_interval_symbols: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
// These global symbols do not exist in the test sandbox
|
|
||||||
// and must be tested separately.
|
|
||||||
clearInterval;
|
|
||||||
clearTimeout;
|
|
||||||
setInterval;
|
|
||||||
setTimeout;
|
|
||||||
}
|
|
||||||
expect: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2233_2: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
reduce_funcs: true,
|
|
||||||
reduce_vars: true,
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var RegExp;
|
|
||||||
Array.isArray;
|
|
||||||
RegExp;
|
|
||||||
UndeclaredGlobal;
|
|
||||||
function foo() {
|
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
|
||||||
Math.sin;
|
|
||||||
Number.isNaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var RegExp;
|
|
||||||
UndeclaredGlobal;
|
|
||||||
function foo() {
|
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
|
||||||
Number.isNaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2233_3: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
reduce_funcs: true,
|
|
||||||
reduce_vars: true,
|
|
||||||
side_effects: true,
|
|
||||||
toplevel: true,
|
|
||||||
unsafe: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var RegExp;
|
|
||||||
Array.isArray;
|
|
||||||
RegExp;
|
|
||||||
UndeclaredGlobal;
|
|
||||||
function foo() {
|
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
|
||||||
Math.sin;
|
|
||||||
Number.isNaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
UndeclaredGlobal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
global_fns: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
Boolean(1, 2);
|
|
||||||
decodeURI(1, 2);
|
|
||||||
decodeURIComponent(1, 2);
|
|
||||||
Date(1, 2);
|
|
||||||
encodeURI(1, 2);
|
|
||||||
encodeURIComponent(1, 2);
|
|
||||||
Error(1, 2);
|
|
||||||
escape(1, 2);
|
|
||||||
EvalError(1, 2);
|
|
||||||
isFinite(1, 2);
|
|
||||||
isNaN(1, 2);
|
|
||||||
Number(1, 2);
|
|
||||||
Object(1, 2);
|
|
||||||
parseFloat(1, 2);
|
|
||||||
parseInt(1, 2);
|
|
||||||
RangeError(1, 2);
|
|
||||||
ReferenceError(1, 2);
|
|
||||||
String(1, 2);
|
|
||||||
SyntaxError(1, 2);
|
|
||||||
TypeError(1, 2);
|
|
||||||
unescape(1, 2);
|
|
||||||
URIError(1, 2);
|
|
||||||
try {
|
|
||||||
Function(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
RegExp(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Array(NaN);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
try {
|
|
||||||
Function(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
RegExp(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Array(NaN);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_stdout: [
|
|
||||||
"SyntaxError",
|
|
||||||
"SyntaxError",
|
|
||||||
"RangeError",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
collapse_vars_assignment: {
|
collapse_vars_assignment: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -863,23 +662,6 @@ issue_2749: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_builtin: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
(!w).constructor(x);
|
|
||||||
Math.abs(y);
|
|
||||||
[ 1, 2, z ].valueOf();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
w, x;
|
|
||||||
y;
|
|
||||||
z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2860_1: {
|
issue_2860_1: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -941,24 +723,6 @@ issue_2929: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_string_replace: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
"foo".replace("f", function() {
|
|
||||||
console.log("PASS");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
"foo".replace("f", function() {
|
|
||||||
console.log("PASS");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_3402: {
|
issue_3402: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -1066,6 +830,7 @@ issue_3552: {
|
|||||||
unreachable_assign: {
|
unreachable_assign: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
|
strings: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(A = "P" + (A = "A" + (B = "S" + (A = B = "S"))), A, B);
|
console.log(A = "P" + (A = "A" + (B = "S" + (A = B = "S"))), A, B);
|
||||||
|
|||||||
@@ -93,3 +93,41 @@ issue_3166: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
valid_after_invalid_1: {
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use\x20strict";
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use\x20strict";
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_after_invalid_2: {
|
||||||
|
options = {
|
||||||
|
directives: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use\x20strict";
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -699,18 +699,6 @@ iife: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_value: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
foo(), bar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_1539: {
|
issue_1539: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -1203,10 +1191,10 @@ issue_2105_1: {
|
|||||||
input: {
|
input: {
|
||||||
!function(factory) {
|
!function(factory) {
|
||||||
factory();
|
factory();
|
||||||
}( function() {
|
}(function() {
|
||||||
return function(fn) {
|
return function(fn) {
|
||||||
fn()().prop();
|
fn()().prop();
|
||||||
}( function() {
|
}(function() {
|
||||||
function bar() {
|
function bar() {
|
||||||
var quux = function() {
|
var quux = function() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -1217,7 +1205,7 @@ issue_2105_1: {
|
|||||||
return { prop: foo };
|
return { prop: foo };
|
||||||
}
|
}
|
||||||
return bar;
|
return bar;
|
||||||
} );
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -1247,10 +1235,10 @@ issue_2105_2: {
|
|||||||
input: {
|
input: {
|
||||||
!function(factory) {
|
!function(factory) {
|
||||||
factory();
|
factory();
|
||||||
}( function() {
|
}(function() {
|
||||||
return function(fn) {
|
return function(fn) {
|
||||||
fn()().prop();
|
fn()().prop();
|
||||||
}( function() {
|
}(function() {
|
||||||
function bar() {
|
function bar() {
|
||||||
var quux = function() {
|
var quux = function() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -1261,7 +1249,7 @@ issue_2105_2: {
|
|||||||
return { prop: foo };
|
return { prop: foo };
|
||||||
}
|
}
|
||||||
return bar;
|
return bar;
|
||||||
} );
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -1270,6 +1258,44 @@ issue_2105_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2105_3: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function(factory) {
|
||||||
|
factory();
|
||||||
|
}(function() {
|
||||||
|
return function(fn) {
|
||||||
|
fn()().prop();
|
||||||
|
}(function() {
|
||||||
|
function bar() {
|
||||||
|
var quux = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
}, foo = function() {
|
||||||
|
console.log;
|
||||||
|
quux();
|
||||||
|
};
|
||||||
|
return { prop: foo };
|
||||||
|
}
|
||||||
|
return bar;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!void void {
|
||||||
|
prop: function() {
|
||||||
|
console.log;
|
||||||
|
void console.log("PASS");
|
||||||
|
}
|
||||||
|
}.prop();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2226_1: {
|
issue_2226_1: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -2266,3 +2292,124 @@ issue_3598: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self_assign: {
|
||||||
|
options = {
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function d(a) {
|
||||||
|
a = a;
|
||||||
|
}
|
||||||
|
function e(a, b) {
|
||||||
|
a = b;
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
function f(a, b, c) {
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
c = a;
|
||||||
|
}
|
||||||
|
function g(a, b, c) {
|
||||||
|
a = a * b + c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function d(a) {}
|
||||||
|
function e(a, b) {}
|
||||||
|
function f(a, b, c) {}
|
||||||
|
function g(a, b, c) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function_argument_reference: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 42;
|
||||||
|
function f(a) {
|
||||||
|
b <<= a;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = 42;
|
||||||
|
function f(a) {
|
||||||
|
b <<= a;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_parameter_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a;
|
||||||
|
function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
f(a = 1 + a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3664: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a, b = (a = (a = [ b && console.log("FAIL") ]).p = 0, 0);
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var b = ([ b && console.log("FAIL") ].p = 0, 0);
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3673: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(a = [ a ]).p = 42;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
(a = [ a ]).p = 42;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -266,12 +266,7 @@ issue_2084: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
!function() {
|
23..toString(),
|
||||||
var c;
|
|
||||||
c = 1 + (c = -1),
|
|
||||||
c = 1 + (c = 0),
|
|
||||||
0 !== 23..toString() && (c = 1 + c);
|
|
||||||
}(),
|
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
expect_stdout: "0"
|
expect_stdout: "0"
|
||||||
@@ -1281,7 +1276,7 @@ issue_2630_3: {
|
|||||||
(function() {
|
(function() {
|
||||||
(function f1(a) {
|
(function f1(a) {
|
||||||
f2();
|
f2();
|
||||||
--x >= 0 && f1({});
|
--x >= 0 && f1();
|
||||||
})(a++);
|
})(a++);
|
||||||
function f2() {
|
function f2() {
|
||||||
a++;
|
a++;
|
||||||
@@ -1911,14 +1906,14 @@ issue_2737_2: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
(function(bar) {
|
(function(bar) {
|
||||||
for (;bar(); ) break;
|
for (;bar();) break;
|
||||||
})(function qux() {
|
})(function qux() {
|
||||||
return console.log("PASS"), qux;
|
return console.log("PASS"), qux;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function(bar) {
|
(function(bar) {
|
||||||
for (;bar(); ) break;
|
for (;bar();) break;
|
||||||
})(function qux() {
|
})(function qux() {
|
||||||
return console.log("PASS"), qux;
|
return console.log("PASS"), qux;
|
||||||
});
|
});
|
||||||
@@ -2249,7 +2244,7 @@ issue_3076: {
|
|||||||
var c = "PASS";
|
var c = "PASS";
|
||||||
(function(b) {
|
(function(b) {
|
||||||
var n = 2;
|
var n = 2;
|
||||||
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1).toString() && --n > 0);
|
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1..toString()) && --n > 0);
|
||||||
var e;
|
var e;
|
||||||
})(2),
|
})(2),
|
||||||
console.log(c);
|
console.log(c);
|
||||||
@@ -3705,3 +3700,88 @@ pr_3595_4: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3679_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var f = function() {};
|
||||||
|
f.g = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
f.g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3679_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
var f = function() {};
|
||||||
|
f.g = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
f.g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3679_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
functions: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var f = function() {};
|
||||||
|
f.p = "PASS";
|
||||||
|
f.g = function() {
|
||||||
|
console.log(f.p);
|
||||||
|
};
|
||||||
|
f.g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
function f() {};
|
||||||
|
f.p = "PASS";
|
||||||
|
(f.g = function() {
|
||||||
|
console.log(f.p);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ issue_2519: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function testFunc() {
|
function testFunc() {
|
||||||
return 1 * ((6 + 5) / 2);
|
return +((6 + 5) / 2);
|
||||||
}
|
}
|
||||||
console.log(testFunc());
|
console.log(testFunc());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2361,3 +2361,40 @@ issue_3542: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3703: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f() {
|
||||||
|
var b;
|
||||||
|
function g() {
|
||||||
|
a = "FAIL";
|
||||||
|
}
|
||||||
|
var c = g;
|
||||||
|
function h() {
|
||||||
|
f;
|
||||||
|
}
|
||||||
|
a ? b |= c : b.p;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function() {
|
||||||
|
var b;
|
||||||
|
var c = function g() {
|
||||||
|
a = "FAIL";
|
||||||
|
};
|
||||||
|
a ? b |= c : b.p;
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ non_hoisted_function_after_return: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function foo(x) {
|
function foo(x) {
|
||||||
return x ? bar() : baz();
|
return (x ? bar : baz)();
|
||||||
function bar() { return 7 }
|
function bar() { return 7 }
|
||||||
function baz() { return 8 }
|
function baz() { return 8 }
|
||||||
}
|
}
|
||||||
@@ -181,7 +181,7 @@ non_hoisted_function_after_return_strict: {
|
|||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function foo(x) {
|
function foo(x) {
|
||||||
return x ? bar() : baz();
|
return (x ? bar : baz)();
|
||||||
function bar() { return 7 }
|
function bar() { return 7 }
|
||||||
function baz() { return 8 }
|
function baz() { return 8 }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ mangle_props: {
|
|||||||
obj[1/0],
|
obj[1/0],
|
||||||
obj["Infinity"],
|
obj["Infinity"],
|
||||||
obj[-1/0],
|
obj[-1/0],
|
||||||
obj[-1/0],
|
obj[-(1/0)],
|
||||||
obj["-Infinity"],
|
obj["-Infinity"],
|
||||||
obj[null],
|
obj[null],
|
||||||
obj["null"]
|
obj["null"]
|
||||||
|
|||||||
@@ -1,98 +1,111 @@
|
|||||||
issue_269_1: {
|
issue_269_1: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
f(
|
var x = {};
|
||||||
String(x),
|
console.log(
|
||||||
Number(x),
|
String(x),
|
||||||
Boolean(x),
|
Number(x),
|
||||||
|
Boolean(x),
|
||||||
|
|
||||||
String(),
|
String(),
|
||||||
Number(),
|
Number(),
|
||||||
Boolean()
|
Boolean()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
f(
|
var x = {};
|
||||||
x + '', +x, !!x,
|
console.log(
|
||||||
'', 0, false
|
x + "", +x, !!x,
|
||||||
);
|
"", 0, false
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_269_dangers: {
|
issue_269_dangers: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
f(
|
var x = {};
|
||||||
String(x, x),
|
console.log(
|
||||||
Number(x, x),
|
String(x, x),
|
||||||
Boolean(x, x)
|
Number(x, x),
|
||||||
);
|
Boolean(x, x)
|
||||||
}
|
);
|
||||||
expect: {
|
}
|
||||||
f(String(x, x), Number(x, x), Boolean(x, x));
|
expect: {
|
||||||
}
|
var x = {};
|
||||||
|
console.log(String(x, x), Number(x, x), Boolean(x, x));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_269_in_scope: {
|
issue_269_in_scope: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var String, Number, Boolean;
|
var String, Number, Boolean;
|
||||||
f(
|
var x = {};
|
||||||
String(x),
|
console.log(
|
||||||
Number(x, x),
|
String(x),
|
||||||
Boolean(x)
|
Number(x, x),
|
||||||
);
|
Boolean(x)
|
||||||
}
|
);
|
||||||
expect: {
|
}
|
||||||
var String, Number, Boolean;
|
expect: {
|
||||||
f(String(x), Number(x, x), Boolean(x));
|
var String, Number, Boolean;
|
||||||
}
|
var x = {};
|
||||||
|
console.log(String(x), Number(x, x), Boolean(x));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
strings_concat: {
|
strings_concat: {
|
||||||
options = {
|
options = {
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
f(
|
var x = {};
|
||||||
String(x + 'str'),
|
console.log(
|
||||||
String('str' + x)
|
String(x + "str"),
|
||||||
);
|
String("str" + x)
|
||||||
}
|
);
|
||||||
expect: {
|
}
|
||||||
f(
|
expect: {
|
||||||
x + 'str',
|
var x = {};
|
||||||
'str' + x
|
console.log(
|
||||||
);
|
x + "str",
|
||||||
}
|
"str" + x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
regexp: {
|
regexp: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
RegExp("foo");
|
RegExp("foo");
|
||||||
RegExp("bar", "ig");
|
RegExp("bar", "ig");
|
||||||
RegExp(foo);
|
RegExp(foo);
|
||||||
RegExp("bar", ig);
|
RegExp("bar", ig);
|
||||||
RegExp("should", "fail");
|
RegExp("should", "fail");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
/foo/;
|
/foo/;
|
||||||
/bar/ig;
|
/bar/ig;
|
||||||
RegExp(foo);
|
RegExp(foo);
|
||||||
RegExp("bar", ig);
|
RegExp("bar", ig);
|
||||||
RegExp("should", "fail");
|
RegExp("should", "fail");
|
||||||
}
|
}
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,2]',
|
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,8]',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ cond_5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
(some_condition() && some_other_condition() ? do_something : alternate)();
|
||||||
if (some_condition() && some_other_condition()) do_something();
|
if (some_condition() && some_other_condition()) do_something();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -728,7 +728,7 @@ issue_2630_3: {
|
|||||||
(function() {
|
(function() {
|
||||||
(function f1() {
|
(function f1() {
|
||||||
f2();
|
f2();
|
||||||
--x >= 0 && f1({});
|
--x >= 0 && f1();
|
||||||
})(a++);
|
})(a++);
|
||||||
function f2() {
|
function f2() {
|
||||||
a++;
|
a++;
|
||||||
@@ -1369,7 +1369,7 @@ recursive_iife_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function f(a, b) {
|
console.log(function f(a, b) {
|
||||||
return b || f("FAIL", "PASS");
|
return b || f(0, "PASS");
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -1388,7 +1388,7 @@ recursive_iife_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function f(a, b) {
|
console.log(function f(a, b) {
|
||||||
return b || f("FAIL", "PASS");
|
return b || f(0, "PASS");
|
||||||
}(0, 0));
|
}(0, 0));
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -1416,7 +1416,7 @@ recursive_iife_3: {
|
|||||||
var a = 1, c = "PASS";
|
var a = 1, c = "PASS";
|
||||||
(function() {
|
(function() {
|
||||||
(function f(b, d, e) {
|
(function f(b, d, e) {
|
||||||
a-- && f(null, 42, 0);
|
a-- && f(0, 42, 0);
|
||||||
e && (c = "FAIL");
|
e && (c = "FAIL");
|
||||||
d && d.p;
|
d && d.p;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ while_becomes_for: {
|
|||||||
while (foo()) bar();
|
while (foo()) bar();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; foo(); ) bar();
|
for (;foo();) bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ drop_if_break_1: {
|
|||||||
if (foo()) break;
|
if (foo()) break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; !foo(););
|
for (;!foo(););
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ drop_if_break_2: {
|
|||||||
if (foo()) break;
|
if (foo()) break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && !foo(););
|
for (;bar() && !foo(););
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ drop_if_break_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && (x(), y(), !foo());) z(), k();
|
for (;bar() && (x(), y(), !foo());) z(), k();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ drop_if_else_break_1: {
|
|||||||
for (;;) if (foo()) bar(); else break;
|
for (;;) if (foo()) bar(); else break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; foo(); ) bar();
|
for (;foo();) bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ drop_if_else_break_2: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && foo();) baz();
|
for (;bar() && foo();) baz();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ drop_if_else_break_3: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && foo();) {
|
for (;bar() && foo();) {
|
||||||
baz();
|
baz();
|
||||||
stuff1();
|
stuff1();
|
||||||
stuff2();
|
stuff2();
|
||||||
@@ -138,7 +138,7 @@ drop_if_else_break_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && (x(), y(), foo());) baz(), z(), k();
|
for (;bar() && (x(), y(), foo());) baz(), z(), k();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,13 +523,13 @@ issue_2740_1: {
|
|||||||
loops: true,
|
loops: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
for (; ; ) break;
|
for (;;) break;
|
||||||
for (a(); ; ) break;
|
for (a();;) break;
|
||||||
for (; b(); ) break;
|
for (;b();) break;
|
||||||
for (c(); d(); ) break;
|
for (c(); d();) break;
|
||||||
for (; ; e()) break;
|
for (;;e()) break;
|
||||||
for (f(); ; g()) break;
|
for (f();; g()) break;
|
||||||
for (; h(); i()) break;
|
for (;h(); i()) break;
|
||||||
for (j(); k(); l()) break;
|
for (j(); k(); l()) break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -574,9 +574,11 @@ issue_2740_3: {
|
|||||||
console.log(x, y);
|
console.log(x, y);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
L1: for (var x = 0; x < 3; x++)
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
for (var y = 0; y < 2; y++)
|
var y = 0;
|
||||||
|
if (y < 2)
|
||||||
break L1;
|
break L1;
|
||||||
|
}
|
||||||
console.log(x, y);
|
console.log(x, y);
|
||||||
}
|
}
|
||||||
expect_stdout: "0 0"
|
expect_stdout: "0 0"
|
||||||
@@ -668,7 +670,7 @@ issue_3371: {
|
|||||||
function a() {
|
function a() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
}
|
}
|
||||||
for (; a(); );
|
for (;a(););
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -753,3 +755,175 @@ empty_for_in_side_effects: {
|
|||||||
"WARN: Side effects in object of for-in loop [test/compress/loops.js:1,17]",
|
"WARN: Side effects in object of for-in loop [test/compress/loops.js:1,17]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3631_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
L: do {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = 1;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
do {
|
||||||
|
var b;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3631_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a = 1; a--; console.log(b))
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_if_break: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
try {
|
||||||
|
while (a) {
|
||||||
|
if (b) {
|
||||||
|
break;
|
||||||
|
var c = 42;
|
||||||
|
console.log(c);
|
||||||
|
} else {
|
||||||
|
var d = false;
|
||||||
|
throw d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("E:", e);
|
||||||
|
}
|
||||||
|
console.log(a, b, c, d);
|
||||||
|
}
|
||||||
|
f(0, 0);
|
||||||
|
f(0, 1);
|
||||||
|
f(1, 0);
|
||||||
|
f(1, 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
try {
|
||||||
|
for (;a && !b;) {
|
||||||
|
var d = false;
|
||||||
|
throw d;
|
||||||
|
var c;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("E:", e);
|
||||||
|
}
|
||||||
|
console.log(a, b, c, d);
|
||||||
|
}
|
||||||
|
f(0, 0);
|
||||||
|
f(0, 1);
|
||||||
|
f(1, 0);
|
||||||
|
f(1, 1);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0 undefined undefined",
|
||||||
|
"0 1 undefined undefined",
|
||||||
|
"E: false",
|
||||||
|
"1 0 undefined false",
|
||||||
|
"1 1 undefined undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_return: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
while (a) return 42;
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
if (a) return 42;
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "foo 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3634_1: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 0;
|
||||||
|
L: while (++b < 2)
|
||||||
|
while (1)
|
||||||
|
if (b) break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 0;
|
||||||
|
L: for (;++b < 2;)
|
||||||
|
for (;1;)
|
||||||
|
if (b) break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3634_2: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 0;
|
||||||
|
L: while (++b < 2)
|
||||||
|
while (1)
|
||||||
|
if (!b)
|
||||||
|
continue L;
|
||||||
|
else
|
||||||
|
break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 0;
|
||||||
|
L: for (;++b < 2;)
|
||||||
|
for (;1;)
|
||||||
|
if (!b)
|
||||||
|
continue L;
|
||||||
|
else
|
||||||
|
break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ evaluate_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
1 * x * 2,
|
2 * x,
|
||||||
+x + 1 + 2,
|
+x + 1 + 2,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
@@ -173,7 +173,7 @@ evaluate_2: {
|
|||||||
var x = "42", y = null;
|
var x = "42", y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
1 * x * 2,
|
2 * x,
|
||||||
+x + 1 + 2,
|
+x + 1 + 2,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
@@ -669,6 +669,9 @@ issue_1710: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unary_binary_parenthesis: {
|
unary_binary_parenthesis: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
var v = [ 0, 1, NaN, Infinity, null, undefined, true, false, "", "foo", /foo/ ];
|
var v = [ 0, 1, NaN, Infinity, null, undefined, true, false, "", "foo", /foo/ ];
|
||||||
v.forEach(function(x) {
|
v.forEach(function(x) {
|
||||||
@@ -979,3 +982,272 @@ unsafe_math_swap_constant: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "6 6 7 6 6 8 9 10"
|
expect_stdout: "6 6 7 6 6 8 9 10"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identity_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
0 + a;
|
||||||
|
a + 0;
|
||||||
|
0 - a;
|
||||||
|
a - 0;
|
||||||
|
1 * a;
|
||||||
|
a * 1;
|
||||||
|
1 / a;
|
||||||
|
a / 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
0 + a;
|
||||||
|
a + 0;
|
||||||
|
0 - a;
|
||||||
|
+a;
|
||||||
|
+a;
|
||||||
|
+a;
|
||||||
|
1 / a;
|
||||||
|
+a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
identity_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
0 + !a;
|
||||||
|
!a + 0;
|
||||||
|
0 - !a;
|
||||||
|
!a - 0;
|
||||||
|
1 * !a;
|
||||||
|
!a * 1;
|
||||||
|
1 / !a;
|
||||||
|
!a / 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
+!a;
|
||||||
|
+!a;
|
||||||
|
0 - !a;
|
||||||
|
+!a;
|
||||||
|
+!a;
|
||||||
|
+!a;
|
||||||
|
1 / !a;
|
||||||
|
+!a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
identity_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
0 + --a;
|
||||||
|
--a + 0;
|
||||||
|
0 - --a;
|
||||||
|
--a - 0;
|
||||||
|
1 * --a;
|
||||||
|
--a * 1;
|
||||||
|
1 / --a;
|
||||||
|
--a / 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
--a;
|
||||||
|
--a;
|
||||||
|
0 - --a;
|
||||||
|
--a;
|
||||||
|
--a;
|
||||||
|
--a;
|
||||||
|
1 / --a;
|
||||||
|
--a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3653: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(0 + (0 - (console && 0)));
|
||||||
|
console.log(0 - (0 - (console && 0)));
|
||||||
|
console.log(1 * (0 - (console && 0)));
|
||||||
|
console.log(1 / (0 - (console && 0)));
|
||||||
|
console.log((0 - (console && 0)) + 0);
|
||||||
|
console.log((0 - (console && 0)) - 0);
|
||||||
|
console.log((0 - (console && 0)) * 1);
|
||||||
|
console.log((0 - (console && 0)) / 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(0 - (0 - (console && 0)));
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(1 / (0 - (console && 0)));
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
console.log(0 - (console && 0));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"Infinity",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3655: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(0 + (0 + 0 * -[].length));
|
||||||
|
console.log(0 - (0 + 0 * -[].length));
|
||||||
|
console.log(1 * (0 + 0 * -[].length));
|
||||||
|
console.log(1 / (0 + 0 * -[].length));
|
||||||
|
console.log((0 + 0 * -[].length) + 0);
|
||||||
|
console.log((0 + 0 * -[].length) - 0);
|
||||||
|
console.log((0 + 0 * -[].length) * 1);
|
||||||
|
console.log((0 + 0 * -[].length) / 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(0 - (0 + 0 * -[].length));
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(1 / (0 + 0 * -[].length));
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
console.log(0 + 0 * -[].length);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"Infinity",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3676_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [];
|
||||||
|
console.log(false - (a - (a[1] = 42)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = [];
|
||||||
|
console.log(false - (a - (a[1] = 42)));
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3676_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log(false - ((a = []) - (a[1] = 42)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log(false - ((a = []) - (a[1] = 42)));
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3682_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = -0;
|
||||||
|
console.log(1 / (a - 1 + 1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = -0;
|
||||||
|
console.log(1 / (a - 1 + 1));
|
||||||
|
}
|
||||||
|
expect_stdout: "Infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3682_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = -0, b = 1;
|
||||||
|
console.log(1 / (a - (b - b)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = -0, b = 1;
|
||||||
|
console.log(1 / (a - (b - b)));
|
||||||
|
}
|
||||||
|
expect_stdout: "-Infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3682_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = -0, b = 1, c = -1;
|
||||||
|
console.log(1 / (a - (+b + +c)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = -0, b = 1, c = -1;
|
||||||
|
console.log(1 / (a - (+b + +c)));
|
||||||
|
}
|
||||||
|
expect_stdout: "-Infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3684: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(1 / (-1 * (0 & console) + 0));
|
||||||
|
console.log(1 / ((0 & console) / -1 + 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1 / (-1 * (0 & console) + 0));
|
||||||
|
console.log(1 / ((0 & console) / -1 + 0));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"Infinity",
|
||||||
|
"Infinity",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3695: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [];
|
||||||
|
console.log(+(a * (a[0] = false)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = [];
|
||||||
|
console.log(+(a * (a[0] = false)));
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
@@ -817,6 +817,29 @@ issue_2208_5: {
|
|||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2208_6: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
properties: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = 42;
|
||||||
|
console.log(("FAIL", {
|
||||||
|
p: function() {
|
||||||
|
return this.a;
|
||||||
|
}
|
||||||
|
}.p)());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 42;
|
||||||
|
console.log(function() {
|
||||||
|
return this.a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2256: {
|
issue_2256: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
|||||||
@@ -2071,13 +2071,8 @@ issue_1670_6: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function(a) {
|
(function(a) {
|
||||||
switch (1) {
|
a = 1;
|
||||||
case a = 1:
|
console.log(a);
|
||||||
console.log(a);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(2);
|
|
||||||
}
|
|
||||||
})(1);
|
})(1);
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
@@ -6801,3 +6796,80 @@ issue_3622: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3631_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
L: do {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = 1;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
L: do {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = 1;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3631_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3666: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
var a = "FAIL";
|
||||||
|
} finally {
|
||||||
|
for (;!a;)
|
||||||
|
var c = a++;
|
||||||
|
var a = "PASS", b = c = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
var a = "FAIL";
|
||||||
|
} finally {
|
||||||
|
for (;!a;)
|
||||||
|
a++;
|
||||||
|
var b = a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -186,3 +186,72 @@ issue_3434_3: {
|
|||||||
/\nfo\n[\n]o\bbb/;
|
/\nfo\n[\n]o\bbb/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3434_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[
|
||||||
|
[ "", RegExp("") ],
|
||||||
|
[ "/", RegExp("/") ],
|
||||||
|
[ "//", RegExp("//") ],
|
||||||
|
[ "\/", RegExp("\\/") ],
|
||||||
|
[ "///", RegExp("///") ],
|
||||||
|
[ "/\/", RegExp("/\\/") ],
|
||||||
|
[ "\//", RegExp("\\//") ],
|
||||||
|
[ "\\/", RegExp("\\\\/") ],
|
||||||
|
[ "////", RegExp("////") ],
|
||||||
|
[ "//\/", RegExp("//\\/") ],
|
||||||
|
[ "/\//", RegExp("/\\//") ],
|
||||||
|
[ "/\\/", RegExp("/\\\\/") ],
|
||||||
|
[ "\///", RegExp("\\///") ],
|
||||||
|
[ "\/\/", RegExp("\\/\\/") ],
|
||||||
|
[ "\\//", RegExp("\\\\//") ],
|
||||||
|
[ "\\\/", RegExp("\\\\\\/") ],
|
||||||
|
].forEach(function(test) {
|
||||||
|
console.log(test[1].test("\\"), test[1].test(test[0]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
[ "", /(?:)/ ],
|
||||||
|
[ "/", /\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "/", /\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "\\/", /\\\// ],
|
||||||
|
[ "////", /\/\/\/\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "/\\/", /\/\\\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "\\//", /\\\/\// ],
|
||||||
|
[ "\\/", /\\\// ],
|
||||||
|
].forEach(function(test) {
|
||||||
|
console.log(test[1].test("\\"), test[1].test(test[0]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -910,15 +910,23 @@ call: {
|
|||||||
console.log(this === b ? "bar" : "baz");
|
console.log(this === b ? "bar" : "baz");
|
||||||
};
|
};
|
||||||
(a, b)();
|
(a, b)();
|
||||||
|
(a, b).c();
|
||||||
(a, b.c)();
|
(a, b.c)();
|
||||||
|
(a, b)["c"]();
|
||||||
|
(a, b["c"])();
|
||||||
(a, function() {
|
(a, function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
})();
|
})();
|
||||||
new (a, b)();
|
new (a, b)();
|
||||||
|
new (a, b).c();
|
||||||
new (a, b.c)();
|
new (a, b.c)();
|
||||||
|
new (a, b)["c"]();
|
||||||
|
new (a, b["c"])();
|
||||||
new (a, function() {
|
new (a, function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
})();
|
})();
|
||||||
|
console.log(typeof (a, b).c);
|
||||||
|
console.log(typeof (a, b)["c"]);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = function() {
|
var a = function() {
|
||||||
@@ -931,23 +939,39 @@ call: {
|
|||||||
console.log(this === b ? "bar" : "baz");
|
console.log(this === b ? "bar" : "baz");
|
||||||
},
|
},
|
||||||
b(),
|
b(),
|
||||||
|
b.c(),
|
||||||
(a, b.c)(),
|
(a, b.c)(),
|
||||||
|
b["c"](),
|
||||||
|
(a, b["c"])(),
|
||||||
function() {
|
function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
}(),
|
}(),
|
||||||
new b(),
|
new b(),
|
||||||
new b.c(),
|
new b.c(),
|
||||||
|
new b.c(),
|
||||||
|
new b["c"](),
|
||||||
|
new b["c"](),
|
||||||
new function() {
|
new function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
}();
|
}(),
|
||||||
|
console.log((a, typeof b.c)),
|
||||||
|
console.log((a, typeof b["c"]));
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"foo",
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
"bar",
|
||||||
"baz",
|
"baz",
|
||||||
"true",
|
"true",
|
||||||
"foo",
|
"foo",
|
||||||
"baz",
|
"baz",
|
||||||
|
"baz",
|
||||||
|
"baz",
|
||||||
|
"baz",
|
||||||
"false",
|
"false",
|
||||||
|
"function",
|
||||||
|
"function",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,3 +1093,22 @@ issue_3490_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS 42"
|
expect_stdout: "PASS 42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3703: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
while ((a = "PASS", 0).foo = 0);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
while (a = "PASS", (0).foo = 0);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
277
test/compress/side_effects.js
Normal file
277
test/compress/side_effects.js
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
accessor: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
get a() {},
|
||||||
|
set a(v){
|
||||||
|
this.b = 2;
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Array.isArray;
|
||||||
|
Boolean;
|
||||||
|
console.log;
|
||||||
|
Date;
|
||||||
|
decodeURI;
|
||||||
|
decodeURIComponent;
|
||||||
|
encodeURI;
|
||||||
|
encodeURIComponent;
|
||||||
|
Error.name;
|
||||||
|
escape;
|
||||||
|
eval;
|
||||||
|
EvalError;
|
||||||
|
Function.length;
|
||||||
|
isFinite;
|
||||||
|
isNaN;
|
||||||
|
JSON;
|
||||||
|
Math.random;
|
||||||
|
Number.isNaN;
|
||||||
|
parseFloat;
|
||||||
|
parseInt;
|
||||||
|
RegExp;
|
||||||
|
Object.defineProperty;
|
||||||
|
String.fromCharCode;
|
||||||
|
RangeError;
|
||||||
|
ReferenceError;
|
||||||
|
SyntaxError;
|
||||||
|
TypeError;
|
||||||
|
unescape;
|
||||||
|
URIError;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
global_timeout_and_interval_symbols: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// These global symbols do not exist in the test sandbox
|
||||||
|
// and must be tested separately.
|
||||||
|
clearInterval;
|
||||||
|
clearTimeout;
|
||||||
|
setInterval;
|
||||||
|
setTimeout;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_2: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var RegExp;
|
||||||
|
Array.isArray;
|
||||||
|
RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Math.sin;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_3: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var RegExp;
|
||||||
|
Array.isArray;
|
||||||
|
RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Math.sin;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
UndeclaredGlobal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_fns: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Boolean(1, 2);
|
||||||
|
decodeURI(1, 2);
|
||||||
|
decodeURIComponent(1, 2);
|
||||||
|
Date(1, 2);
|
||||||
|
encodeURI(1, 2);
|
||||||
|
encodeURIComponent(1, 2);
|
||||||
|
Error(1, 2);
|
||||||
|
escape(1, 2);
|
||||||
|
EvalError(1, 2);
|
||||||
|
isFinite(1, 2);
|
||||||
|
isNaN(1, 2);
|
||||||
|
Number(1, 2);
|
||||||
|
Object(1, 2);
|
||||||
|
parseFloat(1, 2);
|
||||||
|
parseInt(1, 2);
|
||||||
|
RangeError(1, 2);
|
||||||
|
ReferenceError(1, 2);
|
||||||
|
String(1, 2);
|
||||||
|
SyntaxError(1, 2);
|
||||||
|
TypeError(1, 2);
|
||||||
|
unescape(1, 2);
|
||||||
|
URIError(1, 2);
|
||||||
|
try {
|
||||||
|
Function(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RegExp(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
Function(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RegExp(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"SyntaxError",
|
||||||
|
"SyntaxError",
|
||||||
|
"RangeError",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_builtin_1: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(!w).constructor(x);
|
||||||
|
Math.abs(y);
|
||||||
|
[ 1, 2, z ].valueOf();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w, x;
|
||||||
|
y;
|
||||||
|
z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_builtin_2: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
constructor.call(o, 42);
|
||||||
|
__defineGetter__.call(o, "foo", function() {
|
||||||
|
return o.p;
|
||||||
|
});
|
||||||
|
__defineSetter__.call(o, void 0, function(a) {
|
||||||
|
o.p = a;
|
||||||
|
});
|
||||||
|
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {};
|
||||||
|
constructor.call(o, 42);
|
||||||
|
__defineGetter__.call(o, "foo", function() {
|
||||||
|
return o.p;
|
||||||
|
});
|
||||||
|
__defineSetter__.call(o, void 0, function(a) {
|
||||||
|
o.p = a;
|
||||||
|
});
|
||||||
|
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||||
|
}
|
||||||
|
expect_stdout: "object PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string_replace: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_value: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo(), bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -103,6 +103,7 @@ if_return: {
|
|||||||
booleans: true,
|
booleans: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
passes: 2,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,81 @@ unicode_parse_variables: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unicode_escaped_identifier: {
|
||||||
|
input: {
|
||||||
|
var \u0061 = "\ud800\udc00";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="\ud800\udc00";console.log(a);'
|
||||||
|
expect_stdout: "\ud800\udc00"
|
||||||
|
}
|
||||||
|
|
||||||
|
unicode_identifier_ascii_only: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var \u0061 = "testing \udbc4\udd11";
|
||||||
|
var bar = "h\u0065llo";
|
||||||
|
console.log(a, \u0062\u0061r);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="testing \\udbc4\\udd11";var bar="hello";console.log(a,bar);'
|
||||||
|
expect_stdout: "testing \udbc4\udd11 hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
unicode_string_literals: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "6 length unicode character: \udbc4\udd11";
|
||||||
|
console.log(\u0061);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="6 length unicode character: \\udbc4\\udd11";console.log(a);'
|
||||||
|
expect_stdout: "6 length unicode character: \udbc4\udd11"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_escape_style: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "\x01";
|
||||||
|
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
|
||||||
|
var \u0100 = "\u0100";
|
||||||
|
var \u1000 = "\u1000";
|
||||||
|
var \u1000 = "\ud800\udc00";
|
||||||
|
var \u3f80 = "\udbc0\udc00";
|
||||||
|
console.log(\u0061, \ua0081, \u0100, \u1000, \u3f80);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \\u1000="\\ud800\\udc00";var \\u3f80="\\udbc0\\udc00";console.log(a,\\ua0081,\\u0100,\\u1000,\\u3f80);'
|
||||||
|
expect_stdout: "\u0001 \u0010 \u0100 \ud800\udc00 \udbc0\udc00"
|
||||||
|
}
|
||||||
|
|
||||||
|
escape_non_escaped_identifier: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var µþ = "µþ";
|
||||||
|
console.log(\u00b5þ);
|
||||||
|
}
|
||||||
|
expect_exact: 'var \\u00b5\\u00fe="\\xb5\\xfe";console.log(\\u00b5\\u00fe);'
|
||||||
|
expect_stdout: "µþ"
|
||||||
|
}
|
||||||
|
|
||||||
|
non_escape_2_non_escape: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var µþ = "µþ";
|
||||||
|
console.log(\u00b5þ);
|
||||||
|
}
|
||||||
|
expect_exact: 'var µþ="µþ";console.log(µþ);'
|
||||||
|
expect_stdout: "µþ"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2242_1: {
|
issue_2242_1: {
|
||||||
beautify = {
|
beautify = {
|
||||||
ascii_only: false,
|
ascii_only: false,
|
||||||
@@ -24,6 +99,7 @@ issue_2242_1: {
|
|||||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
expect_stdout: "\ud83d \ude00 \ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2242_2: {
|
issue_2242_2: {
|
||||||
@@ -34,6 +110,7 @@ issue_2242_2: {
|
|||||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||||
|
expect_stdout: "\ud83d \ude00 \ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2242_3: {
|
issue_2242_3: {
|
||||||
@@ -44,6 +121,7 @@ issue_2242_3: {
|
|||||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||||
|
expect_stdout: "\ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2242_4: {
|
issue_2242_4: {
|
||||||
@@ -54,6 +132,7 @@ issue_2242_4: {
|
|||||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
expect_stdout: "\ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2569: {
|
issue_2569: {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
exports["Compressor"] = Compressor;
|
exports["Compressor"] = Compressor;
|
||||||
exports["defaults"] = defaults;
|
exports["defaults"] = defaults;
|
||||||
exports["JS_Parse_Error"] = JS_Parse_Error;
|
exports["JS_Parse_Error"] = JS_Parse_Error;
|
||||||
|
exports["List"] = List;
|
||||||
exports["mangle_properties"] = mangle_properties;
|
exports["mangle_properties"] = mangle_properties;
|
||||||
exports["minify"] = minify;
|
exports["minify"] = minify;
|
||||||
exports["OutputStream"] = OutputStream;
|
exports["OutputStream"] = OutputStream;
|
||||||
|
|||||||
17
test/input/issue-1482/beautify.js
Normal file
17
test/input/issue-1482/beautify.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
if (x) foo();
|
||||||
|
|
||||||
|
if (x) foo(); else baz();
|
||||||
|
|
||||||
|
if (x) foo(); else if (y) bar(); else baz();
|
||||||
|
|
||||||
|
if (x) if (y) foo(); else bar(); else baz();
|
||||||
|
|
||||||
|
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
if (x) foo();
|
||||||
|
if (x) foo(); else baz();
|
||||||
|
if (x) foo(); else if (y) bar(); else baz();
|
||||||
|
if (x) if (y) foo(); else bar(); else baz();
|
||||||
|
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||||
|
}
|
||||||
@@ -1,17 +1 @@
|
|||||||
if (x) foo();
|
if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo();function f(){if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo()}
|
||||||
|
|
||||||
if (x) foo(); else baz();
|
|
||||||
|
|
||||||
if (x) foo(); else if (y) bar(); else baz();
|
|
||||||
|
|
||||||
if (x) if (y) foo(); else bar(); else baz();
|
|
||||||
|
|
||||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
|
||||||
|
|
||||||
function f() {
|
|
||||||
if (x) foo();
|
|
||||||
if (x) foo(); else baz();
|
|
||||||
if (x) foo(); else if (y) bar(); else baz();
|
|
||||||
if (x) if (y) foo(); else bar(); else baz();
|
|
||||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
|
||||||
}
|
|
||||||
|
|||||||
9
test/input/reduce/label.js
Normal file
9
test/input/reduce/label.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
var o = this;
|
||||||
|
|
||||||
|
for (var k in o) L17060: {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a;
|
||||||
|
|
||||||
|
console.log(k);
|
||||||
16
test/input/reduce/label.reduced.js
Normal file
16
test/input/reduce/label.reduced.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
var o = this;
|
||||||
|
|
||||||
|
for (var k in o) {
|
||||||
|
0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a;
|
||||||
|
|
||||||
|
console.log(k);
|
||||||
|
// output: a
|
||||||
|
//
|
||||||
|
// minify: k
|
||||||
|
//
|
||||||
|
// options: {
|
||||||
|
// "mangle": false
|
||||||
|
// }
|
||||||
18
test/input/reduce/unsafe_math.js
Normal file
18
test/input/reduce/unsafe_math.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
var _calls_ = 10, a = 100, b = 10, c = 0;
|
||||||
|
|
||||||
|
function f0(b_1, a, undefined_2) {
|
||||||
|
a++ + ++b;
|
||||||
|
{
|
||||||
|
var expr2 = (b + 1 - .1 - .1 - .1 || a || 3).toString();
|
||||||
|
L20778: for (var key2 in expr2) {
|
||||||
|
(c = c + 1) + [ --b + b_1, typeof f0 == "function" && --_calls_ >= 0 && f0(--b + typeof (undefined_2 = 1 === 1 ? a : b), --b + {
|
||||||
|
c: (c = c + 1) + null
|
||||||
|
}, a++ + (typeof f0 == "function" && --_calls_ >= 0 && f0(typeof (c = 1 + c, 3 / "a" * ("c" >>> 23..toString()) >= (b_1 && (b_1[(c = c + 1) + a--] = (- -0,
|
||||||
|
true + {})))), 3, 25))), 1 === 1 ? a : b ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var a_1 = f0([ , 0 ].length === 2);
|
||||||
|
|
||||||
|
console.log(null, a, b, c, Infinity, NaN, undefined);
|
||||||
19
test/input/reduce/unsafe_math.reduced.js
Normal file
19
test/input/reduce/unsafe_math.reduced.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
var b = 0;
|
||||||
|
|
||||||
|
var expr2 = (0 - 1 - .1 - .1).toString();
|
||||||
|
|
||||||
|
for (var key2 in expr2) {
|
||||||
|
--b;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(b);
|
||||||
|
// output: -19
|
||||||
|
//
|
||||||
|
// minify: -4
|
||||||
|
//
|
||||||
|
// options: {
|
||||||
|
// "compress": {
|
||||||
|
// "unsafe_math": true
|
||||||
|
// },
|
||||||
|
// "mangle": false
|
||||||
|
// }
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
limit: 5000,
|
limit: 10000,
|
||||||
timeout: function(limit) {
|
timeout: function(limit) {
|
||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
}
|
}
|
||||||
@@ -55,11 +55,11 @@ process.nextTick(function run() {
|
|||||||
var elapsed = Date.now();
|
var elapsed = Date.now();
|
||||||
var timer;
|
var timer;
|
||||||
var done = function() {
|
var done = function() {
|
||||||
reset();
|
|
||||||
elapsed = Date.now() - elapsed;
|
elapsed = Date.now() - elapsed;
|
||||||
if (elapsed > task.limit) {
|
if (elapsed > task.limit) {
|
||||||
throw new Error("Timed out: " + elapsed + "ms > " + task.limit + "ms");
|
throw new Error("Timed out: " + elapsed + "ms > " + task.limit + "ms");
|
||||||
}
|
}
|
||||||
|
reset();
|
||||||
log_titles(console.log, task.titles, green('\u221A '));
|
log_titles(console.log, task.titles, green('\u221A '));
|
||||||
process.nextTick(run);
|
process.nextTick(run);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
||||||
exec(command, function(err, stdout) {
|
exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
assert.strictEqual(stdout, read("test/input/issue-1482/beautify.js"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -188,6 +188,22 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should work with `--output-opts`", function(done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O';
|
||||||
|
exec(command, function(err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/issue-520/input.js -bO";
|
||||||
|
exec(command, function(err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should process inline source map", function(done) {
|
it("Should process inline source map", function(done) {
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjscmd,
|
uglifyjscmd,
|
||||||
|
|||||||
@@ -69,13 +69,13 @@ describe("Directives", function() {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"use \\\nstrict";"use strict";',
|
'"use \\\nstrict";"use strict";',
|
||||||
[],
|
[ "use strict" ],
|
||||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"\\76";',
|
'"\\76";',
|
||||||
[],
|
[ "\\76" ],
|
||||||
[ ">", "\\76" ]
|
[ ">" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
// no ; or newline
|
// no ; or newline
|
||||||
@@ -106,13 +106,13 @@ describe("Directives", function() {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'function foo() {"use \\\nstrict";"use strict";',
|
'function foo() {"use \\\nstrict";"use strict";',
|
||||||
[],
|
[ "use strict" ],
|
||||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'var foo = function() {"\\76";',
|
'var foo = function() {"\\76";',
|
||||||
[],
|
[ "\\76" ],
|
||||||
[ ">", "\\76" ]
|
[ ">" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'var foo = function() {"use strict"', // no ; or newline
|
'var foo = function() {"use strict"', // no ; or newline
|
||||||
@@ -156,21 +156,24 @@ describe("Directives", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should test EXPECT_DIRECTIVE RegExp", function() {
|
it("Should print semicolon to separate strings from directives", function() {
|
||||||
[
|
[
|
||||||
[ "", true ],
|
[ "", ';"";' ],
|
||||||
[ "'test';", true ],
|
[ '"test";', '"test";;"";' ],
|
||||||
[ "'test';;", true ],
|
[ '"test";;', '"test";;"";' ],
|
||||||
[ "'tests';\n", true ],
|
[ '"tests";\n', '"tests";;"";' ],
|
||||||
[ "'tests'", false ],
|
[ '"tests"', '"tests";;"";' ],
|
||||||
[ "'tests'; \n\t", true ],
|
[ '"tests"; \n\t', '"tests";;"";' ],
|
||||||
[ "'tests';\n\n", true ],
|
[ '"tests";\n\n', '"tests";;"";' ],
|
||||||
[ "\n\n\"use strict\";\n\n", true ],
|
[ '\n\n"use strict";\n\n', '"use strict";;"";' ],
|
||||||
].forEach(function(test) {
|
].forEach(function(test) {
|
||||||
|
var ast = UglifyJS.parse(test[0]);
|
||||||
|
ast.body.push(new UglifyJS.AST_SimpleStatement({
|
||||||
|
body: new UglifyJS.AST_String({ value: "" })
|
||||||
|
}));
|
||||||
var out = UglifyJS.OutputStream();
|
var out = UglifyJS.OutputStream();
|
||||||
out.print(test[0]);
|
ast.print(out);
|
||||||
out.print_string("", null, true);
|
assert.strictEqual(out.get(), 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() {
|
||||||
@@ -178,8 +181,8 @@ describe("Directives", function() {
|
|||||||
'"use strict";',
|
'"use strict";',
|
||||||
"'use strict';",
|
"'use strict';",
|
||||||
'"use strict";',
|
'"use strict";',
|
||||||
'"use strict";;',
|
'"use strict";',
|
||||||
"'use strict';",
|
";'use strict';",
|
||||||
"console.log('use strict');"
|
"console.log('use strict');"
|
||||||
].join(""), {
|
].join(""), {
|
||||||
compress: false,
|
compress: false,
|
||||||
@@ -201,19 +204,23 @@ describe("Directives", function() {
|
|||||||
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() {
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
'{"use\x20strict"}',
|
'"use strict";"use\\x20strict";',
|
||||||
|
'"use strict";"use\\x20strict";'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'{"use\\x20strict"}',
|
||||||
'{"use strict"}'
|
'{"use strict"}'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'function foo(){"use\x20strict";}', // Valid place for directives
|
'function foo(){"use\\x20strict";}', // Valid place for directives
|
||||||
'function foo(){"use strict"}'
|
'function foo(){"use\\x20strict"}'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'try{"use\x20strict"}catch(e){}finally{"use\x20strict"}',
|
'try{"use\\x20strict"}catch(e){}finally{"use\\x20strict"}',
|
||||||
'try{"use strict"}catch(e){}finally{"use strict"}'
|
'try{"use strict"}catch(e){}finally{"use strict"}'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'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) {
|
].forEach(function(test) {
|
||||||
@@ -225,16 +232,6 @@ describe("Directives", function() {
|
|||||||
assert.strictEqual(result.code, test[1], test[0]);
|
assert.strictEqual(result.code, test[1], test[0]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should add double semicolon when relying on automatic semicolon insertion", function() {
|
|
||||||
var result = UglifyJS.minify('"use strict";"use\\x20strict";', {
|
|
||||||
compress: false,
|
|
||||||
output: {
|
|
||||||
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() {
|
||||||
[
|
[
|
||||||
// 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
|
||||||
@@ -249,9 +246,9 @@ describe("Directives", function() {
|
|||||||
'"use strict";'
|
'"use strict";'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"\\\'use strict\\\'";', // Not a directive as it contains quotes
|
'"\\\'use strict\\\'";',
|
||||||
0,
|
0,
|
||||||
';"\'use strict\'";',
|
'"\\\'use strict\\\'";',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"'\"use strict\"';",
|
"'\"use strict\"';",
|
||||||
@@ -273,7 +270,7 @@ describe("Directives", function() {
|
|||||||
'"\'use strict\'";',
|
'"\'use strict\'";',
|
||||||
1,
|
1,
|
||||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||||
"'\\'use strict\\'';",
|
'"\'use strict\'";',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"'\\'use strict\\'';", // Not a valid directive
|
"'\\'use strict\\'';", // Not a valid directive
|
||||||
@@ -305,7 +302,7 @@ describe("Directives", function() {
|
|||||||
"'\"use strict\"';",
|
"'\"use strict\"';",
|
||||||
2,
|
2,
|
||||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||||
'"\\\"use strict\\\"";',
|
"'\"use strict\"';",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"\\"use strict\\"";', // Not a valid directive
|
'"\\"use strict\\"";', // Not a valid directive
|
||||||
@@ -353,8 +350,7 @@ describe("Directives", function() {
|
|||||||
[
|
[
|
||||||
// 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;',
|
||||||
// Yet, the parser noticed that "use strict" wasn't a directive
|
'"use asm";"use\\x20strict";1+1;'
|
||||||
'"use asm";;"use strict";1+1;',
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'function f(){ "use strict" }',
|
'function f(){ "use strict" }',
|
||||||
|
|||||||
167
test/mocha/reduce.js
Normal file
167
test/mocha/reduce.js
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
var assert = require("assert");
|
||||||
|
var exec = require("child_process").exec;
|
||||||
|
var fs = require("fs");
|
||||||
|
var reduce_test = require("../reduce");
|
||||||
|
var semver = require("semver");
|
||||||
|
|
||||||
|
function read(path) {
|
||||||
|
return fs.readFileSync(path, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("test/reduce.js", function() {
|
||||||
|
this.timeout(60000);
|
||||||
|
it("Should reduce test case", function() {
|
||||||
|
var result = reduce_test(read("test/input/reduce/unsafe_math.js"), {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
}, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, read("test/input/reduce/unsafe_math.reduced.js"));
|
||||||
|
});
|
||||||
|
it("Should eliminate unreferenced labels", function() {
|
||||||
|
var result = reduce_test(read("test/input/reduce/label.js"), {
|
||||||
|
mangle: false,
|
||||||
|
}, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, read("test/input/reduce/label.reduced.js"));
|
||||||
|
});
|
||||||
|
it("Should handle test cases with --toplevel", function() {
|
||||||
|
var result = reduce_test([
|
||||||
|
"var Infinity = 42;",
|
||||||
|
"console.log(Infinity);",
|
||||||
|
].join("\n"), {
|
||||||
|
toplevel: true,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure with minify options provided:",
|
||||||
|
"// {",
|
||||||
|
'// "toplevel": true',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should handle test result of NaN", function() {
|
||||||
|
var result = reduce_test("throw 0 / 0;");
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure with minify options provided:",
|
||||||
|
"// {",
|
||||||
|
'// "compress": {},',
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should print correct output for irreducible test case", function() {
|
||||||
|
var result = reduce_test([
|
||||||
|
"console.log(function f(a) {",
|
||||||
|
" return f.length;",
|
||||||
|
"}());",
|
||||||
|
].join("\n"), {
|
||||||
|
compress: {
|
||||||
|
keep_fargs: false,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"console.log(function f(a) {",
|
||||||
|
" return f.length;",
|
||||||
|
"}());",
|
||||||
|
"// output: 1",
|
||||||
|
"// ",
|
||||||
|
"// minify: 0",
|
||||||
|
"// ",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "keep_fargs": false',
|
||||||
|
"// },",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should fail when invalid option is supplied", function() {
|
||||||
|
var result = reduce_test("", {
|
||||||
|
compress: {
|
||||||
|
unsafe_regex: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var err = result.error;
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.strictEqual(err.stack.split(/\n/)[0], "DefaultsError: `unsafe_regex` is not a supported option");
|
||||||
|
});
|
||||||
|
it("Should report on test case with invalid syntax", function() {
|
||||||
|
var result = reduce_test("var 0 = 1;");
|
||||||
|
var err = result.error;
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Name expected");
|
||||||
|
});
|
||||||
|
it("Should format multi-line output correctly", function() {
|
||||||
|
var code = [
|
||||||
|
"var a = 0;",
|
||||||
|
"",
|
||||||
|
"for (var b in [ 1, 2, 3 ]) {",
|
||||||
|
" a = +a + 1 - .2;",
|
||||||
|
" console.log(a);",
|
||||||
|
"}",
|
||||||
|
].join("\n");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
code,
|
||||||
|
"// output: 0.8",
|
||||||
|
"// 1.6",
|
||||||
|
"// 2.4",
|
||||||
|
"// ",
|
||||||
|
"// minify: 0.8",
|
||||||
|
"// 1.6",
|
||||||
|
"// 2.4000000000000004",
|
||||||
|
"// ",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "unsafe_math": true',
|
||||||
|
"// },",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should reduce infinite loops with reasonable performance", function() {
|
||||||
|
if (semver.satisfies(process.version, "0.10")) return;
|
||||||
|
this.timeout(120000);
|
||||||
|
var code = [
|
||||||
|
"var a = 9007199254740992, b = 1;",
|
||||||
|
"",
|
||||||
|
"while (a++ + (1 - b) < a) {",
|
||||||
|
" 0;",
|
||||||
|
"}",
|
||||||
|
].join("\n");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code.replace(/ timed out after [0-9]+ms/, " timed out."), [
|
||||||
|
code,
|
||||||
|
"// output: ",
|
||||||
|
"// minify: Error: Script execution timed out.",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "unsafe_math": true',
|
||||||
|
"// },",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -59,13 +59,13 @@ describe("String literals", function() {
|
|||||||
|
|
||||||
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||||
var tests = [
|
var tests = [
|
||||||
['"\\76";', ';">";'],
|
[ ';"\\76";', ';">";' ],
|
||||||
['"\\0"', '"\\0";'],
|
[ ';"\\0";', ';"\\0";' ],
|
||||||
['"\\08"', '"\\x008";'],
|
[ ';"\\08"', ';"\\x008";' ],
|
||||||
['"\\008"', '"\\x008";'],
|
[ ';"\\008"', ';"\\x008";' ],
|
||||||
['"\\0008"', '"\\x008";'],
|
[ ';"\\0008"', ';"\\x008";' ],
|
||||||
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
[ ';"use\\\n strict";\n"\\07";', ';"use strict";"\07";' ],
|
||||||
['"use\\\n strict";\n"\\07";', ';"use strict";"\07";']
|
[ '"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";' ],
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var test in tests) {
|
for (var test in tests) {
|
||||||
@@ -75,8 +75,8 @@ describe("String literals", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Should not throw error when digit is 8 or 9", function() {
|
it("Should not throw error when digit is 8 or 9", function() {
|
||||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\x008";');
|
assert.equal(UglifyJS.parse('"use strict";;"\\08"').print_to_string(), '"use strict";;"\\x008";');
|
||||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\x009";');
|
assert.equal(UglifyJS.parse('"use strict";;"\\09"').print_to_string(), '"use strict";;"\\x009";');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not unescape unpaired surrogates", function() {
|
it("Should not unescape unpaired surrogates", function() {
|
||||||
@@ -93,7 +93,7 @@ describe("String literals", function() {
|
|||||||
for (; i <= 0xFFFF; i++) {
|
for (; i <= 0xFFFF; i++) {
|
||||||
code.push("\\u" + i.toString(16));
|
code.push("\\u" + i.toString(16));
|
||||||
}
|
}
|
||||||
code = '"' + code.join() + '"';
|
code = ';"' + code.join() + '"';
|
||||||
var normal = UglifyJS.minify(code, {
|
var normal = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
|
|||||||
564
test/reduce.js
Normal file
564
test/reduce.js
Normal file
@@ -0,0 +1,564 @@
|
|||||||
|
var crypto = require("crypto");
|
||||||
|
var U = require("./node");
|
||||||
|
var List = U.List;
|
||||||
|
var os = require("os");
|
||||||
|
var sandbox = require("./sandbox");
|
||||||
|
|
||||||
|
// Reduce a ufuzz-style `console.log` based test case by iteratively replacing
|
||||||
|
// AST nodes with various permutations. Each AST_Statement in the tree is also
|
||||||
|
// speculatively dropped to determine whether it is needed. If the altered
|
||||||
|
// tree and the last known good tree produce the same non-nil error-free output
|
||||||
|
// after being run, then the permutation survives to the next generation and
|
||||||
|
// is the basis for subsequent iterations. The test case is reduced as a
|
||||||
|
// consequence of complex expressions being replaced with simpler ones.
|
||||||
|
// This function assumes that the testcase will not result in a parse or
|
||||||
|
// runtime Error. Note that a reduced test case will have different runtime
|
||||||
|
// output - it is not functionally equivalent to the original. The only criteria
|
||||||
|
// is that once the generated reduced test case is run without minification, it
|
||||||
|
// will produce different output from the code minified with `minify_options`.
|
||||||
|
// Returns a `minify` result object with an additonal boolean property `reduced`.
|
||||||
|
|
||||||
|
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
||||||
|
if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string();
|
||||||
|
minify_options = minify_options || { compress: {}, mangle: false };
|
||||||
|
reduce_options = reduce_options || {};
|
||||||
|
var max_iterations = reduce_options.max_iterations || 1000;
|
||||||
|
var max_timeout = reduce_options.max_timeout || 10000;
|
||||||
|
var verbose = reduce_options.verbose;
|
||||||
|
var minify_options_json = JSON.stringify(minify_options, null, 2);
|
||||||
|
var result_cache = Object.create(null);
|
||||||
|
// the initial timeout to assess the viability of the test case must be large
|
||||||
|
var differs = producesDifferentResultWhenMinified(result_cache, testcase, minify_options, max_timeout);
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
console.error("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
|
||||||
|
}
|
||||||
|
if (!differs) {
|
||||||
|
// same stdout result produced when minified
|
||||||
|
return {
|
||||||
|
code: "// Can't reproduce test failure with minify options provided:"
|
||||||
|
+ "\n// " + to_comment(minify_options_json)
|
||||||
|
};
|
||||||
|
} else if (differs.timed_out) {
|
||||||
|
return {
|
||||||
|
code: "// Can't reproduce test failure within " + max_timeout + "ms:"
|
||||||
|
+ "\n// " + to_comment(minify_options_json)
|
||||||
|
};
|
||||||
|
} else if (differs.error) {
|
||||||
|
return differs;
|
||||||
|
} else {
|
||||||
|
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
|
||||||
|
// Replace expressions with constants that will be parsed into
|
||||||
|
// AST_Nodes as required. Each AST_Node has its own permutation count,
|
||||||
|
// so these replacements can't be shared.
|
||||||
|
// Although simpler replacements are generally faster and better,
|
||||||
|
// feel free to experiment with a different replacement set.
|
||||||
|
var REPLACEMENTS = [
|
||||||
|
// "null", "''", "false", "'foo'", "undefined", "9",
|
||||||
|
"1", "0",
|
||||||
|
];
|
||||||
|
|
||||||
|
// There's a relationship between each node's _permute counter and
|
||||||
|
// REPLACEMENTS.length which is why fractional _permutes were needed.
|
||||||
|
// One could scale all _permute operations by a factor of `steps`
|
||||||
|
// to only deal with integer operations, but this works well enough.
|
||||||
|
var steps = 4; // must be a power of 2
|
||||||
|
var step = 1 / steps; // 0.25 is exactly representable in floating point
|
||||||
|
|
||||||
|
var tt = new U.TreeTransformer(function(node, descend, in_list) {
|
||||||
|
if (CHANGED) return;
|
||||||
|
|
||||||
|
// quick ignores
|
||||||
|
if (node instanceof U.AST_Accessor) return;
|
||||||
|
if (node instanceof U.AST_Directive) return;
|
||||||
|
if (node instanceof U.AST_Label) return;
|
||||||
|
if (node instanceof U.AST_LabelRef) return;
|
||||||
|
if (!in_list && node instanceof U.AST_SymbolDeclaration) return;
|
||||||
|
if (node instanceof U.AST_Toplevel) return;
|
||||||
|
|
||||||
|
var parent = tt.parent();
|
||||||
|
|
||||||
|
// ensure that the _permute prop is a number.
|
||||||
|
// can not use `node.start._permute |= 0;` as it will erase fractional part.
|
||||||
|
if (typeof node.start._permute === "undefined") node.start._permute = 0;
|
||||||
|
|
||||||
|
// if node reached permutation limit - skip over it.
|
||||||
|
// no structural AST changes before this point.
|
||||||
|
if (node.start._permute >= REPLACEMENTS.length) return;
|
||||||
|
|
||||||
|
if (parent instanceof U.AST_Assign
|
||||||
|
&& parent.left === node
|
||||||
|
|| parent instanceof U.AST_Unary
|
||||||
|
&& parent.expression === node
|
||||||
|
&& ["++", "--", "delete"].indexOf(parent.operator) >= 0) {
|
||||||
|
// ignore lvalues
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((parent instanceof U.AST_For || parent instanceof U.AST_ForIn)
|
||||||
|
&& parent.init === node && node instanceof U.AST_Var) {
|
||||||
|
// preserve for (var ...)
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// node specific permutations with no parent logic
|
||||||
|
|
||||||
|
if (node instanceof U.AST_Array) {
|
||||||
|
var expr = node.elements[0];
|
||||||
|
if (expr && !(expr instanceof U.AST_Hole)) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Binary) {
|
||||||
|
CHANGED = true;
|
||||||
|
return [
|
||||||
|
node.left,
|
||||||
|
node.right,
|
||||||
|
][ ((node.start._permute += step) * steps | 0) % 2 ];
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Catch || node instanceof U.AST_Finally) {
|
||||||
|
// drop catch or finally block
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Conditional) {
|
||||||
|
CHANGED = true;
|
||||||
|
return [
|
||||||
|
node.condition,
|
||||||
|
node.consequent,
|
||||||
|
node.alternative,
|
||||||
|
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_BlockStatement) {
|
||||||
|
if (in_list) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.splice(node.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Call) {
|
||||||
|
var expr = [
|
||||||
|
node.expression,
|
||||||
|
node.args[0],
|
||||||
|
null, // intentional
|
||||||
|
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||||
|
if (expr) {
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
if (node.expression instanceof U.AST_Function) {
|
||||||
|
// hoist and return expressions from the IIFE function expression
|
||||||
|
var body = node.expression.body;
|
||||||
|
node.expression.body = [];
|
||||||
|
var seq = [];
|
||||||
|
body.forEach(function(node) {
|
||||||
|
var expr = expr instanceof U.AST_Exit ? node.value : node.body;
|
||||||
|
if (expr instanceof U.AST_Node && !is_statement(expr)) {
|
||||||
|
// collect expressions from each statements' body
|
||||||
|
seq.push(expr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CHANGED = true;
|
||||||
|
return to_sequence(seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Defun) {
|
||||||
|
switch (((node.start._permute += step) * steps | 0) % 2) {
|
||||||
|
case 0:
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
case 1:
|
||||||
|
if (!has_exit(node)) {
|
||||||
|
// hoist function declaration body
|
||||||
|
var body = node.body;
|
||||||
|
node.body = [];
|
||||||
|
body.push(node); // retain function with empty body to be dropped later
|
||||||
|
CHANGED = true;
|
||||||
|
return List.splice(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_DWLoop) {
|
||||||
|
var expr = [
|
||||||
|
node.condition,
|
||||||
|
node.body,
|
||||||
|
null, // intentional
|
||||||
|
][ (node.start._permute * steps | 0) % 3 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (!expr) {
|
||||||
|
if (node.body[0] instanceof U.AST_Break) {
|
||||||
|
if (node instanceof U.AST_Do) {
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
expr = node.condition; // AST_While - fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_PropAccess) {
|
||||||
|
var expr = [
|
||||||
|
node.expression,
|
||||||
|
node.property instanceof U.AST_Node && node.property,
|
||||||
|
][ node.start._permute++ % 2 ];
|
||||||
|
if (expr) {
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_For) {
|
||||||
|
var expr = [
|
||||||
|
node.init,
|
||||||
|
node.condition,
|
||||||
|
node.step,
|
||||||
|
node.body,
|
||||||
|
][ (node.start._permute * steps | 0) % 4 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_ForIn) {
|
||||||
|
var expr = [
|
||||||
|
node.init,
|
||||||
|
node.object,
|
||||||
|
node.body,
|
||||||
|
][ (node.start._permute * steps | 0) % 3 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_If) {
|
||||||
|
var expr = [
|
||||||
|
node.condition,
|
||||||
|
node.body,
|
||||||
|
node.alternative,
|
||||||
|
][ (node.start._permute * steps | 0) % 3 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr) {
|
||||||
|
// replace if statement with its condition, then block or else block
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Object) {
|
||||||
|
// first property's value
|
||||||
|
var expr = node.properties[0] instanceof U.AST_ObjectKeyVal && node.properties[0].value;
|
||||||
|
if (expr) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_SimpleStatement) {
|
||||||
|
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
|
||||||
|
// hoist simple statement IIFE function expression body
|
||||||
|
node.start._permute++;
|
||||||
|
if (!has_exit(node.body.expression)) {
|
||||||
|
var body = node.body.expression.body;
|
||||||
|
node.body.expression.body = [];
|
||||||
|
CHANGED = true;
|
||||||
|
return List.splice(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Switch) {
|
||||||
|
var expr = [
|
||||||
|
node.expression, // switch expression
|
||||||
|
node.body[0] && node.body[0].expression, // first case expression or undefined
|
||||||
|
node.body[0] && node.body[0], // first case body or undefined
|
||||||
|
][ (node.start._permute * steps | 0) % 4 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return expr instanceof U.AST_SwitchBranch ? new U.AST_BlockStatement({
|
||||||
|
body: expr.body.slice(),
|
||||||
|
start: {},
|
||||||
|
}) : to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Try) {
|
||||||
|
var body = [
|
||||||
|
node.body,
|
||||||
|
node.bcatch && node.bcatch.body,
|
||||||
|
node.bfinally && node.bfinally.body,
|
||||||
|
null, // intentional
|
||||||
|
][ (node.start._permute * steps | 0) % 4 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (body) {
|
||||||
|
// replace try statement with try block, catch block, or finally block
|
||||||
|
CHANGED = true;
|
||||||
|
return new U.AST_BlockStatement({
|
||||||
|
body: body,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// replace try with a break or return if first in try statement
|
||||||
|
if (node.body[0] instanceof U.AST_Break
|
||||||
|
|| node.body[0] instanceof U.AST_Return) {
|
||||||
|
CHANGED = true;
|
||||||
|
return node.body[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Unary) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return node.expression;
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Var) {
|
||||||
|
if (node.definitions.length == 1 && node.definitions[0].value) {
|
||||||
|
// first declaration value
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(node.definitions[0].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_LabeledStatement) {
|
||||||
|
if (node.body instanceof U.AST_Statement
|
||||||
|
&& !has_loopcontrol(node.body, node.body, node)) {
|
||||||
|
// replace labelled statement with its non-labelled body
|
||||||
|
node.start._permute = REPLACEMENTS.length;
|
||||||
|
CHANGED = true;
|
||||||
|
return node.body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_list) {
|
||||||
|
// special case to drop object properties and switch branches
|
||||||
|
if (parent instanceof U.AST_Object
|
||||||
|
|| parent instanceof U.AST_Switch && parent.expression != node) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace or skip statement
|
||||||
|
if (node instanceof U.AST_Statement) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove this node unless its the sole element of a (transient) sequence
|
||||||
|
if (!(parent instanceof U.AST_Sequence) || parent.expressions.length > 1) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace this node
|
||||||
|
var newNode = U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
|
||||||
|
expression: true,
|
||||||
|
});
|
||||||
|
if (is_statement(node)) {
|
||||||
|
newNode = new U.AST_SimpleStatement({
|
||||||
|
body: newNode,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
newNode.start._permute = ++node.start._permute;
|
||||||
|
CHANGED = true;
|
||||||
|
return newNode;
|
||||||
|
}, function(node, in_list) {
|
||||||
|
if (node instanceof U.AST_Sequence) {
|
||||||
|
// expand single-element sequence
|
||||||
|
if (node.expressions.length == 1) return node.expressions[0];
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Try) {
|
||||||
|
// expand orphaned try block
|
||||||
|
if (!node.bcatch && !node.bfinally) return new U.AST_BlockStatement({
|
||||||
|
body: node.body,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Var) {
|
||||||
|
// remove empty var statement
|
||||||
|
if (node.definitions.length == 0) return in_list ? List.skip : new U.AST_EmptyStatement({
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var pass = 1; pass <= 3; ++pass) {
|
||||||
|
var testcase_ast = U.parse(testcase);
|
||||||
|
testcase_ast.walk(new U.TreeWalker(function(node) {
|
||||||
|
// unshare start props to retain visit data between iterations
|
||||||
|
node.start = JSON.parse(JSON.stringify(node.start));
|
||||||
|
node.start._permute = 0;
|
||||||
|
}));
|
||||||
|
for (var c = 0; c < max_iterations; ++c) {
|
||||||
|
if (verbose) {
|
||||||
|
if (pass == 1 && c % 25 == 0) {
|
||||||
|
console.error("// reduce test pass "
|
||||||
|
+ pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var CHANGED = false;
|
||||||
|
var code_ast = testcase_ast.clone(true).transform(tt);
|
||||||
|
if (!CHANGED) break;
|
||||||
|
try {
|
||||||
|
var code = code_ast.print_to_string();
|
||||||
|
} catch (ex) {
|
||||||
|
// AST is not well formed.
|
||||||
|
// no harm done - just log the error, ignore latest change and continue iterating.
|
||||||
|
console.error("*** Error generating code from AST.");
|
||||||
|
console.error(ex);
|
||||||
|
console.error("*** Discarding permutation and continuing.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout);
|
||||||
|
if (diff) {
|
||||||
|
if (diff.timed_out) {
|
||||||
|
// can't trust the validity of `code_ast` and `code` when timed out.
|
||||||
|
// no harm done - just ignore latest change and continue iterating.
|
||||||
|
} else if (diff.error) {
|
||||||
|
// something went wrong during minify() - could be malformed AST or genuine bug.
|
||||||
|
// no harm done - just log code & error, ignore latest change and continue iterating.
|
||||||
|
console.error("*** Error during minification.");
|
||||||
|
console.error(code);
|
||||||
|
console.error(diff.error);
|
||||||
|
console.error("*** Discarding permutation and continuing.");
|
||||||
|
} else if (is_error(diff.unminified_result)
|
||||||
|
&& is_error(diff.minified_result)
|
||||||
|
&& diff.unminified_result.name == diff.minified_result.name) {
|
||||||
|
// ignore difference in error messages caused by minification
|
||||||
|
} else {
|
||||||
|
// latest permutation is valid, so use it as the basis of new changes
|
||||||
|
testcase_ast = code_ast;
|
||||||
|
testcase = code;
|
||||||
|
differs = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == 0) break;
|
||||||
|
if (verbose) {
|
||||||
|
console.error("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testcase = U.minify(testcase, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
braces: true,
|
||||||
|
comments: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
testcase.code += [
|
||||||
|
"",
|
||||||
|
"// output: " + to_comment(differs.unminified_result),
|
||||||
|
"// minify: " + to_comment(differs.minified_result),
|
||||||
|
"// options: " + to_comment(minify_options_json),
|
||||||
|
].join("\n").replace(/\u001b\[\d+m/g, "");
|
||||||
|
return testcase;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function to_comment(value) {
|
||||||
|
return ("" + value).replace(/\n/g, "\n// ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_exit(fn) {
|
||||||
|
var found = false;
|
||||||
|
var tw = new U.TreeWalker(function(node) {
|
||||||
|
if (found) return found;
|
||||||
|
if (node instanceof U.AST_Exit) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
if (node instanceof U.AST_Scope && node !== fn) {
|
||||||
|
return true; // don't descend into nested functions
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fn.walk(tw);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_loopcontrol(body, loop, label) {
|
||||||
|
var found = false;
|
||||||
|
var tw = new U.TreeWalker(function(node) {
|
||||||
|
if (found) return true;
|
||||||
|
if (node instanceof U.AST_LoopControl && this.loopcontrol_target(node) === loop) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (label instanceof U.AST_LabeledStatement) tw.push(label);
|
||||||
|
tw.push(loop);
|
||||||
|
body.walk(tw);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_error(result) {
|
||||||
|
return typeof result == "object" && typeof result.name == "string" && typeof result.message == "string";
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_timed_out(result) {
|
||||||
|
return is_error(result) && /timed out/.test(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_statement(node) {
|
||||||
|
return node instanceof U.AST_Statement && !(node instanceof U.AST_Function);
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge_sequence(array, node) {
|
||||||
|
if (node instanceof U.AST_Sequence) {
|
||||||
|
array.push.apply(array, node.expressions);
|
||||||
|
} else {
|
||||||
|
array.push(node);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_sequence(expressions) {
|
||||||
|
if (expressions.length == 0) return new U.AST_Number({value: 0, start: {}});
|
||||||
|
if (expressions.length == 1) return expressions[0];
|
||||||
|
return new U.AST_Sequence({
|
||||||
|
expressions: expressions.reduce(merge_sequence, []),
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_statement(node) {
|
||||||
|
return is_statement(node) ? node : new U.AST_SimpleStatement({
|
||||||
|
body: node,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_code(result_cache, code, toplevel, timeout) {
|
||||||
|
var key = crypto.createHash("sha1").update(code).digest("base64");
|
||||||
|
return result_cache[key] || (result_cache[key] = sandbox.run_code(code, toplevel, timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
function producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout) {
|
||||||
|
var minified = U.minify(code, minify_options);
|
||||||
|
if (minified.error) return minified;
|
||||||
|
|
||||||
|
var toplevel = minify_options.toplevel;
|
||||||
|
var elapsed = Date.now();
|
||||||
|
var unminified_result = run_code(result_cache, code, toplevel, max_timeout);
|
||||||
|
elapsed = Date.now() - elapsed;
|
||||||
|
var timeout = Math.min(100 * elapsed, max_timeout);
|
||||||
|
var minified_result = run_code(result_cache, minified.code, toplevel, timeout);
|
||||||
|
|
||||||
|
if (sandbox.same_stdout(unminified_result, minified_result)) {
|
||||||
|
return is_timed_out(unminified_result) && is_timed_out(minified_result) && {
|
||||||
|
timed_out: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
unminified_result: unminified_result,
|
||||||
|
minified_result: minified_result,
|
||||||
|
elapsed: elapsed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Error.stackTraceLimit = Infinity;
|
||||||
@@ -54,14 +54,15 @@ function createContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run_code = function(code, toplevel) {
|
exports.run_code = function(code, toplevel, timeout) {
|
||||||
|
timeout = timeout || 5000;
|
||||||
var stdout = "";
|
var stdout = "";
|
||||||
var original_write = process.stdout.write;
|
var original_write = process.stdout.write;
|
||||||
process.stdout.write = function(chunk) {
|
process.stdout.write = function(chunk) {
|
||||||
stdout += chunk;
|
stdout += chunk;
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: 5000 });
|
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: timeout });
|
||||||
return stdout;
|
return stdout;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return ex;
|
return ex;
|
||||||
@@ -76,8 +77,9 @@ function strip_func_ids(text) {
|
|||||||
|
|
||||||
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||||
if (typeof expected != typeof actual) return false;
|
if (typeof expected != typeof actual) return false;
|
||||||
if (typeof expected != "string") {
|
if (typeof expected == "object" && typeof expected.name == "string" && typeof expected.message == "string") {
|
||||||
if (expected.name != actual.name) return false;
|
if (expected.name !== actual.name) return false;
|
||||||
|
if (typeof actual.message != "string") return false;
|
||||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ require("../../tools/exit");
|
|||||||
var UglifyJS = require("../..");
|
var UglifyJS = require("../..");
|
||||||
var randomBytes = require("crypto").randomBytes;
|
var randomBytes = require("crypto").randomBytes;
|
||||||
var sandbox = require("../sandbox");
|
var sandbox = require("../sandbox");
|
||||||
|
var reduce_test = require("../reduce");
|
||||||
|
|
||||||
var MAX_GENERATED_TOPLEVELS_PER_RUN = 1;
|
var MAX_GENERATED_TOPLEVELS_PER_RUN = 1;
|
||||||
var MAX_GENERATION_RECURSION_DEPTH = 12;
|
var MAX_GENERATION_RECURSION_DEPTH = 12;
|
||||||
@@ -1051,6 +1052,7 @@ function log_rename(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function log(options) {
|
function log(options) {
|
||||||
|
var options_copy = JSON.parse(options);
|
||||||
options = JSON.parse(options);
|
options = JSON.parse(options);
|
||||||
if (!ok) errorln("\n\n\n\n\n\n!!!!!!!!!!\n\n\n");
|
if (!ok) errorln("\n\n\n\n\n\n!!!!!!!!!!\n\n\n");
|
||||||
errorln("//=============================================================");
|
errorln("//=============================================================");
|
||||||
@@ -1069,6 +1071,18 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
errorln("uglified result:");
|
errorln("uglified result:");
|
||||||
errorln(uglify_result);
|
errorln(uglify_result);
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
var reduced = reduce_test(original_code, options_copy, {
|
||||||
|
verbose: false,
|
||||||
|
}).code;
|
||||||
|
if (reduced) {
|
||||||
|
errorln();
|
||||||
|
errorln("// reduced test case (output will differ)");
|
||||||
|
errorln();
|
||||||
|
errorln(reduced);
|
||||||
|
errorln();
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errorln("// !!! uglify failed !!!");
|
errorln("// !!! uglify failed !!!");
|
||||||
errorln(uglify_code);
|
errorln(uglify_code);
|
||||||
@@ -1089,6 +1103,20 @@ function log(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fuzzy_match(original, uglified) {
|
||||||
|
uglified = uglified.split(" ");
|
||||||
|
var i = uglified.length;
|
||||||
|
original = original.split(" ", i);
|
||||||
|
while (--i >= 0) {
|
||||||
|
if (original[i] === uglified[i]) continue;
|
||||||
|
var a = +original[i];
|
||||||
|
var b = +uglified[i];
|
||||||
|
if (Math.abs((b - a) / a) < 1e-10) continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
var fallback_options = [ JSON.stringify({
|
var fallback_options = [ JSON.stringify({
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false
|
mangle: false
|
||||||
@@ -1111,8 +1139,12 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
uglify_code = uglify_code.code;
|
uglify_code = uglify_code.code;
|
||||||
uglify_result = sandbox.run_code(uglify_code, o.toplevel);
|
uglify_result = sandbox.run_code(uglify_code, o.toplevel);
|
||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
if (!ok && o.compress.unsafe_math) {
|
if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) {
|
||||||
ok = sandbox.same_stdout(sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3")), uglify_result, o.toplevel);
|
ok = fuzzy_match(original_result, uglify_result);
|
||||||
|
if (!ok) {
|
||||||
|
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"));
|
||||||
|
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uglify_code = uglify_code.error;
|
uglify_code = uglify_code.error;
|
||||||
|
|||||||
@@ -12,17 +12,16 @@ function spawn(endTime) {
|
|||||||
], {
|
], {
|
||||||
stdio: [ "ignore", "pipe", "pipe" ]
|
stdio: [ "ignore", "pipe", "pipe" ]
|
||||||
}).on("exit", respawn);
|
}).on("exit", respawn);
|
||||||
var line = "";
|
var stdout = "";
|
||||||
child.stdout.on("data", function(data) {
|
child.stdout.on("data", function(data) {
|
||||||
line += data;
|
stdout += data;
|
||||||
});
|
});
|
||||||
child.stderr.once("data", function() {
|
var stderr = "";
|
||||||
process.exitCode = 1;
|
child.stderr.on("data", trap).pipe(process.stdout);
|
||||||
}).pipe(process.stdout);
|
|
||||||
var keepAlive = setInterval(function() {
|
var keepAlive = setInterval(function() {
|
||||||
var end = line.lastIndexOf("\r");
|
var end = stdout.lastIndexOf("\r");
|
||||||
console.log(line.slice(line.lastIndexOf("\r", end - 1) + 1, end));
|
console.log(stdout.slice(stdout.lastIndexOf("\r", end - 1) + 1, end));
|
||||||
line = line.slice(end + 1);
|
stdout = stdout.slice(end + 1);
|
||||||
}, ping);
|
}, ping);
|
||||||
var timer = setTimeout(function() {
|
var timer = setTimeout(function() {
|
||||||
clearInterval(keepAlive);
|
clearInterval(keepAlive);
|
||||||
@@ -31,9 +30,17 @@ function spawn(endTime) {
|
|||||||
}, endTime - Date.now());
|
}, endTime - Date.now());
|
||||||
|
|
||||||
function respawn() {
|
function respawn() {
|
||||||
console.log(line);
|
console.log(stdout.replace(/[^\r\n]*\r/g, ""));
|
||||||
clearInterval(keepAlive);
|
clearInterval(keepAlive);
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
spawn(endTime);
|
spawn(endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function trap(data) {
|
||||||
|
stderr += data;
|
||||||
|
if (~stderr.indexOf("\nminify(options):\n")) {
|
||||||
|
process.exitCode = 1;
|
||||||
|
child.stderr.removeListener("data", trap);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
exports["Dictionary"] = Dictionary;
|
exports["Dictionary"] = Dictionary;
|
||||||
|
exports["List"] = List;
|
||||||
exports["minify"] = minify;
|
exports["minify"] = minify;
|
||||||
exports["parse"] = parse;
|
exports["parse"] = parse;
|
||||||
exports["push_uniq"] = push_uniq;
|
exports["push_uniq"] = push_uniq;
|
||||||
|
|||||||
Reference in New Issue
Block a user