Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dfda6e212 | ||
|
|
d08c772eb3 | ||
|
|
90ed54401b | ||
|
|
d8106b6c63 | ||
|
|
dda4eb96e1 | ||
|
|
7305ba0296 | ||
|
|
2c21dc5e8e | ||
|
|
d0faa471db | ||
|
|
6ad823d1e8 | ||
|
|
43ad4e9775 |
@@ -214,12 +214,13 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
|||||||
clone: function(deep) {
|
clone: function(deep) {
|
||||||
var node = this._clone(deep);
|
var node = this._clone(deep);
|
||||||
if (deep) {
|
if (deep) {
|
||||||
var refs = node.label.references;
|
var label = node.label;
|
||||||
var label = this.label;
|
var def = this.label;
|
||||||
node.walk(new TreeWalker(function(node) {
|
node.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_LoopControl
|
if (node instanceof AST_LoopControl
|
||||||
&& node.label && node.label.thedef === label) {
|
&& node.label && node.label.thedef === def) {
|
||||||
refs.push(node);
|
node.label.thedef = label;
|
||||||
|
label.references.push(node);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
127
lib/compress.js
127
lib/compress.js
@@ -271,6 +271,14 @@ merge(Compressor.prototype, {
|
|||||||
if (d.fixed === undefined || !is_safe(d)
|
if (d.fixed === undefined || !is_safe(d)
|
||||||
|| is_modified(node, 0, node.fixed_value() instanceof AST_Lambda)) {
|
|| is_modified(node, 0, node.fixed_value() instanceof AST_Lambda)) {
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
|
} else {
|
||||||
|
var parent = tw.parent();
|
||||||
|
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|
||||||
|
|| parent instanceof AST_Call && node !== parent.expression
|
||||||
|
|| parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
|
||||||
|
|| parent instanceof AST_VarDef && node === parent.value) {
|
||||||
|
d.escaped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolCatch) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
@@ -359,7 +367,19 @@ merge(Compressor.prototype, {
|
|||||||
pop();
|
pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Catch || node instanceof AST_SwitchBranch) {
|
if (node instanceof AST_Try) {
|
||||||
|
push();
|
||||||
|
walk_body(node, tw);
|
||||||
|
pop();
|
||||||
|
if (node.bcatch) {
|
||||||
|
push();
|
||||||
|
node.bcatch.walk(tw);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
if (node.bfinally) node.bfinally.walk(tw);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_SwitchBranch) {
|
||||||
push();
|
push();
|
||||||
descend();
|
descend();
|
||||||
pop();
|
pop();
|
||||||
@@ -393,6 +413,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reset_def(def) {
|
function reset_def(def) {
|
||||||
|
def.escaped = false;
|
||||||
if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) {
|
if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) {
|
||||||
def.fixed = undefined;
|
def.fixed = undefined;
|
||||||
} else {
|
} else {
|
||||||
@@ -1549,23 +1570,20 @@ merge(Compressor.prototype, {
|
|||||||
: ev(this.alternative, compressor);
|
: ev(this.alternative, compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor){
|
def(AST_SymbolRef, function(compressor){
|
||||||
if (this._evaluating) throw def;
|
if (!compressor.option("reduce_vars") || this._evaluating) throw def;
|
||||||
this._evaluating = true;
|
this._evaluating = true;
|
||||||
try {
|
try {
|
||||||
var fixed = this.fixed_value();
|
var fixed = this.fixed_value();
|
||||||
if (compressor.option("reduce_vars") && fixed) {
|
if (!fixed) throw def;
|
||||||
if (compressor.option("unsafe")) {
|
var value = ev(fixed, compressor);
|
||||||
if (!HOP(fixed, "_evaluated")) {
|
if (!HOP(fixed, "_eval")) fixed._eval = function() {
|
||||||
fixed._evaluated = ev(fixed, compressor);
|
return value;
|
||||||
}
|
};
|
||||||
return fixed._evaluated;
|
if (value && typeof value == "object" && this.definition().escaped) throw def;
|
||||||
}
|
return value;
|
||||||
return ev(fixed, compressor);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
this._evaluating = false;
|
this._evaluating = false;
|
||||||
}
|
}
|
||||||
throw def;
|
|
||||||
});
|
});
|
||||||
def(AST_PropAccess, function(compressor){
|
def(AST_PropAccess, function(compressor){
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
@@ -1980,7 +1998,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (drop_vars && node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
|
if (drop_vars && node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn && tt.parent().init === node)) {
|
||||||
var def = node.definitions.filter(function(def){
|
var def = node.definitions.filter(function(def){
|
||||||
if (def.value) def.value = def.value.transform(tt);
|
if (def.value) def.value = def.value.transform(tt);
|
||||||
var sym = def.name.definition();
|
var sym = def.name.definition();
|
||||||
@@ -2058,26 +2076,32 @@ merge(Compressor.prototype, {
|
|||||||
return maintain_this_binding(tt.parent(), node, node.right.transform(tt));
|
return maintain_this_binding(tt.parent(), node, node.right.transform(tt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// certain combination of unused name + side effect leads to:
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/44
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/1830
|
||||||
|
// that's an invalid AST.
|
||||||
|
// We fix it at this stage by moving the `var` outside the `for`.
|
||||||
if (node instanceof AST_For) {
|
if (node instanceof AST_For) {
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
|
|
||||||
if (node.init instanceof AST_BlockStatement) {
|
if (node.init instanceof AST_BlockStatement) {
|
||||||
// certain combination of unused name + side effect leads to:
|
var block = node.init;
|
||||||
// https://github.com/mishoo/UglifyJS2/issues/44
|
node.init = block.body.pop();
|
||||||
// that's an invalid AST.
|
block.body.push(node);
|
||||||
// We fix it at this stage by moving the `var` outside the `for`.
|
return in_list ? MAP.splice(block.body) : block;
|
||||||
|
|
||||||
var body = node.init.body.slice(0, -1);
|
|
||||||
node.init = node.init.body.slice(-1)[0].body;
|
|
||||||
body.push(node);
|
|
||||||
|
|
||||||
return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
|
|
||||||
body: body
|
|
||||||
});
|
|
||||||
} else if (is_empty(node.init)) {
|
} else if (is_empty(node.init)) {
|
||||||
node.init = null;
|
node.init = null;
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
|
||||||
|
descend(node, this);
|
||||||
|
if (node.body instanceof AST_BlockStatement) {
|
||||||
|
var block = node.body;
|
||||||
|
node.body = block.body.pop();
|
||||||
|
block.body.push(node);
|
||||||
|
return in_list ? MAP.splice(block.body) : block;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope && node !== self)
|
if (node instanceof AST_Scope && node !== self)
|
||||||
return node;
|
return node;
|
||||||
@@ -2380,7 +2404,7 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("dead_code") && self instanceof AST_While) {
|
if (compressor.option("dead_code") && self instanceof AST_While) {
|
||||||
var a = [];
|
var a = [];
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
||||||
return make_node(AST_BlockStatement, self, { body: a });
|
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (self instanceof AST_Do) {
|
if (self instanceof AST_Do) {
|
||||||
var has_loop_control = false;
|
var has_loop_control = false;
|
||||||
@@ -2389,7 +2413,8 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
|
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
|
||||||
return has_loop_control = true;
|
return has_loop_control = true;
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
var parent = compressor.parent();
|
||||||
|
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
|
||||||
if (!has_loop_control) return self.body;
|
if (!has_loop_control) return self.body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2459,7 +2484,7 @@ merge(Compressor.prototype, {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
||||||
return make_node(AST_BlockStatement, self, { body: a });
|
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (cond !== self.condition) {
|
if (cond !== self.condition) {
|
||||||
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
||||||
@@ -2711,9 +2736,9 @@ merge(Compressor.prototype, {
|
|||||||
var body = [];
|
var body = [];
|
||||||
if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
|
if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
|
||||||
if (self.bfinally) body = body.concat(self.bfinally.body);
|
if (self.bfinally) body = body.concat(self.bfinally.body);
|
||||||
return body.length > 0 ? make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, {
|
||||||
body: body
|
body: body
|
||||||
}).optimize(compressor) : make_node(AST_EmptyStatement, self);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
@@ -3595,7 +3620,9 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Infinity, self).optimize(compressor);
|
return make_node(AST_Infinity, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
if (compressor.option("evaluate")
|
||||||
|
&& compressor.option("reduce_vars")
|
||||||
|
&& is_lhs(self, compressor.parent()) !== self) {
|
||||||
var d = self.definition();
|
var d = self.definition();
|
||||||
var fixed = self.fixed_value();
|
var fixed = self.fixed_value();
|
||||||
if (fixed) {
|
if (fixed) {
|
||||||
@@ -3603,21 +3630,45 @@ merge(Compressor.prototype, {
|
|||||||
var init = fixed.evaluate(compressor);
|
var init = fixed.evaluate(compressor);
|
||||||
if (init !== fixed) {
|
if (init !== fixed) {
|
||||||
init = make_node_from_constant(init, fixed);
|
init = make_node_from_constant(init, fixed);
|
||||||
var value = best_of_expression(init.optimize(compressor), fixed).print_to_string().length;
|
var value = init.optimize(compressor).print_to_string().length;
|
||||||
|
var fn;
|
||||||
|
if (has_symbol_ref(fixed)) {
|
||||||
|
fn = function() {
|
||||||
|
var result = init.optimize(compressor);
|
||||||
|
return result === init ? result.clone(true) : result;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
value = Math.min(value, fixed.print_to_string().length);
|
||||||
|
fn = function() {
|
||||||
|
var result = best_of_expression(init.optimize(compressor), fixed);
|
||||||
|
return result === init || result === fixed ? result.clone(true) : result;
|
||||||
|
};
|
||||||
|
}
|
||||||
var name = d.name.length;
|
var name = d.name.length;
|
||||||
var freq = d.references.length;
|
var overhead = 0;
|
||||||
var overhead = d.global || !freq ? 0 : (name + 2 + value) / freq;
|
if (compressor.option("unused") && (!d.global || compressor.option("toplevel"))) {
|
||||||
d.should_replace = value <= name + overhead ? init : false;
|
overhead = (name + 2 + value) / d.references.length;
|
||||||
|
}
|
||||||
|
d.should_replace = value <= name + overhead ? fn : false;
|
||||||
} else {
|
} else {
|
||||||
d.should_replace = false;
|
d.should_replace = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d.should_replace) {
|
if (d.should_replace) {
|
||||||
return best_of_expression(d.should_replace.optimize(compressor), fixed).clone(true);
|
return d.should_replace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
|
function has_symbol_ref(value) {
|
||||||
|
var found;
|
||||||
|
value.walk(new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_SymbolRef) found = true;
|
||||||
|
if (found) return true;
|
||||||
|
}));
|
||||||
|
return found;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function is_atomic(lhs, self) {
|
function is_atomic(lhs, self) {
|
||||||
|
|||||||
@@ -190,11 +190,7 @@ function OutputStream(options) {
|
|||||||
var might_need_space = false;
|
var might_need_space = false;
|
||||||
var might_need_semicolon = false;
|
var might_need_semicolon = false;
|
||||||
var might_add_newline = 0;
|
var might_add_newline = 0;
|
||||||
var last = null;
|
var last = "";
|
||||||
|
|
||||||
function last_char() {
|
|
||||||
return last.charAt(last.length - 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
var ensure_line_len = options.max_line_len ? function() {
|
var ensure_line_len = options.max_line_len ? function() {
|
||||||
if (current_col > options.max_line_len) {
|
if (current_col > options.max_line_len) {
|
||||||
@@ -218,10 +214,11 @@ function OutputStream(options) {
|
|||||||
function print(str) {
|
function print(str) {
|
||||||
str = String(str);
|
str = String(str);
|
||||||
var ch = str.charAt(0);
|
var ch = str.charAt(0);
|
||||||
|
var prev = last.charAt(last.length - 1);
|
||||||
if (might_need_semicolon) {
|
if (might_need_semicolon) {
|
||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
|
|
||||||
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
|
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
|
||||||
if (options.semicolons || requireSemicolonChars(ch)) {
|
if (options.semicolons || requireSemicolonChars(ch)) {
|
||||||
OUTPUT += ";";
|
OUTPUT += ";";
|
||||||
current_col++;
|
current_col++;
|
||||||
@@ -258,7 +255,6 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (might_need_space) {
|
if (might_need_space) {
|
||||||
var prev = last_char();
|
|
||||||
if ((is_identifier_char(prev)
|
if ((is_identifier_char(prev)
|
||||||
&& (is_identifier_char(ch) || ch == "\\"))
|
&& (is_identifier_char(ch) || ch == "\\"))
|
||||||
|| (ch == "/" && ch == prev)
|
|| (ch == "/" && ch == prev)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"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": "2.8.22",
|
"version": "2.8.23",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ if (!args.length) {
|
|||||||
}
|
}
|
||||||
args.push("--stats");
|
args.push("--stats");
|
||||||
var urls = [
|
var urls = [
|
||||||
"https://code.jquery.com/jquery-3.1.1.js",
|
"https://code.jquery.com/jquery-3.2.1.js",
|
||||||
"https://code.angularjs.org/1.6.1/angular.js",
|
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
||||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||||
"https://unpkg.com/react@15.3.2/dist/react.js",
|
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||||
|
|||||||
@@ -1029,3 +1029,38 @@ delete_assign_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1830_1: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
L: for (var b = console.log(1); !1;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
L: for (console.log(1); !1;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1830_2: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
L: for (var a = 1, b = console.log(a); --a;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
var a = 1;
|
||||||
|
L: for (console.log(a); --a;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -93,3 +93,57 @@ issue_485_crashing_1530: {
|
|||||||
this, void 0;
|
this, void 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1841_1: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 10;
|
||||||
|
!function(arg) {
|
||||||
|
for (var key in "hi")
|
||||||
|
var n = arg.baz, n = [ b = 42 ];
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 10;
|
||||||
|
!function() {
|
||||||
|
for (var key in "hi") {
|
||||||
|
b = 42;
|
||||||
|
}
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_exact: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1841_2: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
pure_getters: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 10;
|
||||||
|
!function(arg) {
|
||||||
|
for (var key in "hi")
|
||||||
|
var n = arg.baz, n = [ b = 42 ];
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 10;
|
||||||
|
!function(arg) {
|
||||||
|
for (var key in "hi") {
|
||||||
|
arg.baz, b = 42;
|
||||||
|
}
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_exact: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ f7: {
|
|||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_exact: [
|
expect_exact: [
|
||||||
"var a = 100, b = 10;",
|
"var b = 10;",
|
||||||
"",
|
"",
|
||||||
"!function() {",
|
"!function() {",
|
||||||
" for (;b = a, !1; ) ;",
|
" for (;b = 100, !1; ) ;",
|
||||||
"}(), console.log(a, b);",
|
"}(), console.log(100, b);",
|
||||||
]
|
]
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
134
test/compress/issue-1833.js
Normal file
134
test/compress/issue-1833.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
iife_for: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: for (;;) break L;
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: for (;;) break L;
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_for_in: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: for (var a in x) break L;
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: for (var a in x) break L;
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_do: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: do {
|
||||||
|
break L;
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: do {
|
||||||
|
break L;
|
||||||
|
} while (1);
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_while: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: while (1) break L;
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: while (1) break L;
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_do: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: do {
|
||||||
|
continue L;
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
L: do {
|
||||||
|
continue L;
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_while: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
L: while (0) continue L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(){L:;}"
|
||||||
|
}
|
||||||
@@ -300,7 +300,7 @@ unsafe_evaluate_array: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_evaluate_equality: {
|
unsafe_evaluate_equality_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate : true,
|
evaluate : true,
|
||||||
reduce_vars : true,
|
reduce_vars : true,
|
||||||
@@ -308,47 +308,62 @@ unsafe_evaluate_equality: {
|
|||||||
unused : true
|
unused : true
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f0(){
|
function f0() {
|
||||||
var a = {};
|
var a = {};
|
||||||
console.log(a === a);
|
return a === a;
|
||||||
}
|
}
|
||||||
|
function f1() {
|
||||||
function f1(){
|
|
||||||
var a = [];
|
var a = [];
|
||||||
console.log(a === a);
|
return a === a;
|
||||||
}
|
}
|
||||||
|
console.log(f0(), f1());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function f1() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.log(f0(), f1());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
function f2(){
|
unsafe_evaluate_equality_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate : true,
|
||||||
|
passes : 2,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true,
|
||||||
|
unused : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f2() {
|
||||||
var a = {a:1, b:2};
|
var a = {a:1, b:2};
|
||||||
var b = a;
|
var b = a;
|
||||||
var c = a;
|
var c = a;
|
||||||
console.log(b === c);
|
return b === c;
|
||||||
}
|
}
|
||||||
|
function f3() {
|
||||||
function f3(){
|
|
||||||
var a = [1, 2, 3];
|
var a = [1, 2, 3];
|
||||||
var b = a;
|
var b = a;
|
||||||
var c = a;
|
var c = a;
|
||||||
console.log(b === c);
|
return b === c;
|
||||||
}
|
}
|
||||||
|
console.log(f2(), f3());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f0(){
|
function f2() {
|
||||||
console.log(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
function f3() {
|
||||||
function f1(){
|
return true;
|
||||||
console.log(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function f2(){
|
|
||||||
console.log(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function f3(){
|
|
||||||
console.log(true);
|
|
||||||
}
|
}
|
||||||
|
console.log(f2(), f3());
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
passes: {
|
passes: {
|
||||||
@@ -1995,3 +2010,115 @@ catch_var: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1814_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
const a = 42;
|
||||||
|
!function() {
|
||||||
|
var b = a;
|
||||||
|
!function(a) {
|
||||||
|
console.log(a++, b);
|
||||||
|
}(0);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
const a = 42;
|
||||||
|
!function() {
|
||||||
|
!function(a) {
|
||||||
|
console.log(a++, 42);
|
||||||
|
}(0);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "0 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1814_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
const a = "32";
|
||||||
|
!function() {
|
||||||
|
var b = a + 1;
|
||||||
|
!function(a) {
|
||||||
|
console.log(a++, b);
|
||||||
|
}(0);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
const a = "32";
|
||||||
|
!function() {
|
||||||
|
!function(a) {
|
||||||
|
console.log(a++, "321");
|
||||||
|
}(0);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "0 '321'"
|
||||||
|
}
|
||||||
|
|
||||||
|
try_abort: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
try {
|
||||||
|
var a = 1;
|
||||||
|
throw "";
|
||||||
|
var b = 2;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
try {
|
||||||
|
var a = 1;
|
||||||
|
throw "";
|
||||||
|
var b = 2;
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "1 undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1865: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(some) {
|
||||||
|
some.thing = false;
|
||||||
|
}
|
||||||
|
console.log(function() {
|
||||||
|
var some = { thing: true };
|
||||||
|
f(some);
|
||||||
|
return some.thing;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(some) {
|
||||||
|
some.thing = false;
|
||||||
|
}
|
||||||
|
console.log(function() {
|
||||||
|
var some = { thing: true };
|
||||||
|
f(some);
|
||||||
|
return some.thing;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,35 @@
|
|||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
|
|
||||||
|
function safe_log(arg) {
|
||||||
|
if (arg) switch (typeof arg) {
|
||||||
|
case "function":
|
||||||
|
return arg.toString();
|
||||||
|
case "object":
|
||||||
|
if (/Error$/.test(arg.name)) return arg.toString();
|
||||||
|
arg.constructor.toString();
|
||||||
|
for (var key in arg) {
|
||||||
|
arg[key] = safe_log(arg[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
var FUNC_TOSTRING = [
|
var FUNC_TOSTRING = [
|
||||||
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
||||||
" var ids = [];",
|
" var id = 0;",
|
||||||
" return function() {",
|
" return function() {",
|
||||||
" var i = ids.indexOf(this);",
|
' if (this === Array) return "[Function: Array]";',
|
||||||
" if (i < 0) {",
|
' if (this === Object) return "[Function: Object]";',
|
||||||
" i = ids.length;",
|
" var i = this.name;",
|
||||||
" ids.push(this);",
|
' if (typeof i != "number") {',
|
||||||
|
" i = ++id;",
|
||||||
|
' Object.defineProperty(this, "name", {',
|
||||||
|
" get: function() {",
|
||||||
|
" return i;",
|
||||||
|
" }",
|
||||||
|
" });",
|
||||||
" }",
|
" }",
|
||||||
' return "[Function: __func_" + i + "__]";',
|
' return "[Function: " + i + "]";',
|
||||||
" }",
|
" }",
|
||||||
"}();",
|
"}();",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
@@ -21,16 +41,14 @@ exports.run_code = function(code) {
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
vm.runInNewContext([
|
vm.runInNewContext([
|
||||||
"!function() {",
|
|
||||||
FUNC_TOSTRING,
|
FUNC_TOSTRING,
|
||||||
|
"!function() {",
|
||||||
code,
|
code,
|
||||||
"}();",
|
"}();",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
console: {
|
console: {
|
||||||
log: function() {
|
log: function() {
|
||||||
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
return console.log.apply(console, [].map.call(arguments, safe_log));
|
||||||
return typeof arg == "function" || arg && /Error$/.test(arg.name) ? arg.toString() : arg;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, { timeout: 5000 });
|
}, { timeout: 5000 });
|
||||||
|
|||||||
291
test/ufuzz.js
291
test/ufuzz.js
@@ -2,7 +2,7 @@
|
|||||||
// derived from https://github.com/qfox/uglyfuzzer by Peter van der Zee
|
// derived from https://github.com/qfox/uglyfuzzer by Peter van der Zee
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// check both cli and file modes of nodejs (!). See #1695 for details. and the various settings of uglify.
|
// check both CLI and file modes of nodejs (!). See #1695 for details. and the various settings of uglify.
|
||||||
// bin/uglifyjs s.js -c && bin/uglifyjs s.js -c passes=3 && bin/uglifyjs s.js -c passes=3 -m
|
// bin/uglifyjs s.js -c && bin/uglifyjs s.js -c passes=3 && bin/uglifyjs s.js -c passes=3 -m
|
||||||
// cat s.js | node && node s.js && bin/uglifyjs s.js -c | node && bin/uglifyjs s.js -c passes=3 | node && bin/uglifyjs s.js -c passes=3 -m | node
|
// cat s.js | node && node s.js && bin/uglifyjs s.js -c | node && bin/uglifyjs s.js -c passes=3 | node && bin/uglifyjs s.js -c passes=3 -m | node
|
||||||
|
|
||||||
@@ -20,49 +20,26 @@ var MAX_GENERATED_TOPLEVELS_PER_RUN = 1;
|
|||||||
var MAX_GENERATION_RECURSION_DEPTH = 12;
|
var MAX_GENERATION_RECURSION_DEPTH = 12;
|
||||||
var INTERVAL_COUNT = 100;
|
var INTERVAL_COUNT = 100;
|
||||||
|
|
||||||
var STMT_BLOCK = 0;
|
var STMT_ARG_TO_ID = Object.create(null);
|
||||||
var STMT_IF_ELSE = 1;
|
var STMTS_TO_USE = [];
|
||||||
var STMT_DO_WHILE = 2;
|
function STMT_(name) {
|
||||||
var STMT_WHILE = 3;
|
return STMT_ARG_TO_ID[name] = STMTS_TO_USE.push(STMTS_TO_USE.length) - 1;
|
||||||
var STMT_FOR_LOOP = 4;
|
}
|
||||||
var STMT_SEMI = 5;
|
|
||||||
var STMT_EXPR = 6;
|
var STMT_BLOCK = STMT_("block");
|
||||||
var STMT_SWITCH = 7;
|
var STMT_IF_ELSE = STMT_("ifelse");
|
||||||
var STMT_VAR = 8;
|
var STMT_DO_WHILE = STMT_("dowhile");
|
||||||
var STMT_RETURN_ETC = 9;
|
var STMT_WHILE = STMT_("while");
|
||||||
var STMT_FUNC_EXPR = 10;
|
var STMT_FOR_LOOP = STMT_("forloop");
|
||||||
var STMT_TRY = 11;
|
var STMT_FOR_IN = STMT_("forin");
|
||||||
var STMT_C = 12;
|
var STMT_SEMI = STMT_("semi");
|
||||||
var STMTS_TO_USE = [
|
var STMT_EXPR = STMT_("expr");
|
||||||
STMT_BLOCK,
|
var STMT_SWITCH = STMT_("switch");
|
||||||
STMT_IF_ELSE,
|
var STMT_VAR = STMT_("var");
|
||||||
STMT_DO_WHILE,
|
var STMT_RETURN_ETC = STMT_("stop");
|
||||||
STMT_WHILE,
|
var STMT_FUNC_EXPR = STMT_("funcexpr");
|
||||||
STMT_FOR_LOOP,
|
var STMT_TRY = STMT_("try");
|
||||||
STMT_SEMI,
|
var STMT_C = STMT_("c");
|
||||||
STMT_EXPR,
|
|
||||||
STMT_SWITCH,
|
|
||||||
STMT_VAR,
|
|
||||||
STMT_RETURN_ETC,
|
|
||||||
STMT_FUNC_EXPR,
|
|
||||||
STMT_TRY,
|
|
||||||
STMT_C,
|
|
||||||
];
|
|
||||||
var STMT_ARG_TO_ID = {
|
|
||||||
block: STMT_BLOCK,
|
|
||||||
ifelse: STMT_IF_ELSE,
|
|
||||||
dowhile: STMT_DO_WHILE,
|
|
||||||
while: STMT_WHILE,
|
|
||||||
forloop: STMT_FOR_LOOP,
|
|
||||||
semi: STMT_SEMI,
|
|
||||||
expr: STMT_EXPR,
|
|
||||||
switch: STMT_SWITCH,
|
|
||||||
var: STMT_VAR,
|
|
||||||
stop: STMT_RETURN_ETC,
|
|
||||||
funcexpr: STMT_FUNC_EXPR,
|
|
||||||
try: STMT_TRY,
|
|
||||||
c: STMT_C,
|
|
||||||
};
|
|
||||||
|
|
||||||
var STMT_FIRST_LEVEL_OVERRIDE = -1;
|
var STMT_FIRST_LEVEL_OVERRIDE = -1;
|
||||||
var STMT_SECOND_LEVEL_OVERRIDE = -1;
|
var STMT_SECOND_LEVEL_OVERRIDE = -1;
|
||||||
@@ -72,6 +49,7 @@ var num_iterations = +process.argv[2] || 1/0;
|
|||||||
var verbose = false; // log every generated test
|
var verbose = false; // log every generated test
|
||||||
var verbose_interval = false; // log every 100 generated tests
|
var verbose_interval = false; // log every 100 generated tests
|
||||||
var verbose_error = false;
|
var verbose_error = false;
|
||||||
|
var use_strict = false;
|
||||||
for (var i = 2; i < process.argv.length; ++i) {
|
for (var i = 2; i < process.argv.length; ++i) {
|
||||||
switch (process.argv[i]) {
|
switch (process.argv[i]) {
|
||||||
case '-v':
|
case '-v':
|
||||||
@@ -101,6 +79,9 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
STMT_SECOND_LEVEL_OVERRIDE = STMT_ARG_TO_ID[name];
|
STMT_SECOND_LEVEL_OVERRIDE = STMT_ARG_TO_ID[name];
|
||||||
if (!(STMT_SECOND_LEVEL_OVERRIDE >= 0)) throw new Error('Unknown statement name; use -? to get a list');
|
if (!(STMT_SECOND_LEVEL_OVERRIDE >= 0)) throw new Error('Unknown statement name; use -? to get a list');
|
||||||
break;
|
break;
|
||||||
|
case '--use-strict':
|
||||||
|
use_strict = true;
|
||||||
|
break;
|
||||||
case '--stmt-depth-from-func':
|
case '--stmt-depth-from-func':
|
||||||
STMT_COUNT_FROM_GLOBAL = false;
|
STMT_COUNT_FROM_GLOBAL = false;
|
||||||
break;
|
break;
|
||||||
@@ -127,6 +108,7 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
console.log('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
console.log('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
||||||
console.log('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
console.log('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
||||||
console.log('-s2 <statement name>: force the second level statement to be this one (see list below)');
|
console.log('-s2 <statement name>: force the second level statement to be this one (see list below)');
|
||||||
|
console.log('--use-strict: generate "use strict"');
|
||||||
console.log('--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise');
|
console.log('--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise');
|
||||||
console.log('--only-stmt <statement names>: a comma delimited white list of statements that may be generated');
|
console.log('--only-stmt <statement names>: a comma delimited white list of statements that may be generated');
|
||||||
console.log('--without-stmt <statement names>: a comma delimited black list of statements never to generate');
|
console.log('--without-stmt <statement names>: a comma delimited black list of statements never to generate');
|
||||||
@@ -296,15 +278,26 @@ var TYPEOF_OUTCOMES = [
|
|||||||
|
|
||||||
var loops = 0;
|
var loops = 0;
|
||||||
var funcs = 0;
|
var funcs = 0;
|
||||||
|
var labels = 10000;
|
||||||
|
|
||||||
function rng(max) {
|
function rng(max) {
|
||||||
var r = randomBytes(2).readUInt16LE(0) / 65536;
|
var r = randomBytes(2).readUInt16LE(0) / 65536;
|
||||||
return Math.floor(max * r);
|
return Math.floor(max * r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function strictMode() {
|
||||||
|
return use_strict && rng(4) == 0 ? '"use strict";' : '';
|
||||||
|
}
|
||||||
|
|
||||||
function createTopLevelCode() {
|
function createTopLevelCode() {
|
||||||
if (rng(2) === 0) return createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0);
|
return [
|
||||||
return createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, IN_GLOBAL, ANY_TYPE, CANNOT_THROW, 0);
|
strictMode(),
|
||||||
|
'var a = 100, b = 10, c = 0;',
|
||||||
|
rng(2) == 0
|
||||||
|
? createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0)
|
||||||
|
: createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, IN_GLOBAL, ANY_TYPE, CANNOT_THROW, 0),
|
||||||
|
'console.log(null, a, b, c);' // preceding `null` makes for a cleaner output (empty string still shows up etc)
|
||||||
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFunctions(n, recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
function createFunctions(n, recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||||
@@ -342,10 +335,22 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
|||||||
var s = '';
|
var s = '';
|
||||||
if (rng(5) === 0) {
|
if (rng(5) === 0) {
|
||||||
// functions with functions. lower the recursion to prevent a mess.
|
// functions with functions. lower the recursion to prevent a mess.
|
||||||
s = 'function ' + name + '(' + createParams() + '){' + createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth) + '}\n';
|
s = [
|
||||||
|
'function ' + name + '(' + createParams() + '){',
|
||||||
|
strictMode(),
|
||||||
|
createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth),
|
||||||
|
'}',
|
||||||
|
''
|
||||||
|
].join('\n');
|
||||||
} else {
|
} else {
|
||||||
// functions with statements
|
// functions with statements
|
||||||
s = 'function ' + name + '(' + createParams() + '){' + createStatements(3, recurmax, canThrow, CANNOT_THROW, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}\n';
|
s = [
|
||||||
|
'function ' + name + '(' + createParams() + '){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'}',
|
||||||
|
''
|
||||||
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
VAR_NAMES.length = namesLenBefore;
|
VAR_NAMES.length = namesLenBefore;
|
||||||
@@ -367,6 +372,40 @@ function createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotRe
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableLoopControl(flag, defaultValue) {
|
||||||
|
return Array.isArray(flag) && flag.indexOf("") < 0 ? flag.concat("") : flag || defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLabel(canBreak, canContinue) {
|
||||||
|
var label;
|
||||||
|
if (rng(10) < 3) {
|
||||||
|
label = ++labels;
|
||||||
|
if (Array.isArray(canBreak)) {
|
||||||
|
canBreak = canBreak.slice();
|
||||||
|
} else {
|
||||||
|
canBreak = canBreak ? [ "" ] : [];
|
||||||
|
}
|
||||||
|
canBreak.push(label);
|
||||||
|
if (Array.isArray(canContinue)) {
|
||||||
|
canContinue = canContinue.slice();
|
||||||
|
} else {
|
||||||
|
canContinue = canContinue ? [ "" ] : [];
|
||||||
|
}
|
||||||
|
canContinue.push(label);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
break: canBreak,
|
||||||
|
continue: canContinue,
|
||||||
|
target: label ? "L" + label + ": " : ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLabel(label) {
|
||||||
|
if (!Array.isArray(label)) return "";
|
||||||
|
label = label[rng(label.length)];
|
||||||
|
return label && " L" + label;
|
||||||
|
}
|
||||||
|
|
||||||
function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
||||||
++stmtDepth;
|
++stmtDepth;
|
||||||
var loop = ++loops;
|
var loop = ++loops;
|
||||||
@@ -382,17 +421,36 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
|
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case STMT_BLOCK:
|
case STMT_BLOCK:
|
||||||
return '{' + createStatements(rng(5) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + '}';
|
var label = createLabel(canBreak);
|
||||||
|
return label.target + '{' + createStatements(rng(5) + 1, recurmax, canThrow, label.break, canContinue, cannotReturn, stmtDepth) + '}';
|
||||||
case STMT_IF_ELSE:
|
case STMT_IF_ELSE:
|
||||||
return 'if (' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + (rng(2) === 1 ? ' else ' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) : '');
|
return 'if (' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + (rng(2) === 1 ? ' else ' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) : '');
|
||||||
case STMT_DO_WHILE:
|
case STMT_DO_WHILE:
|
||||||
return '{var brake' + loop + ' = 5; do {' + createStatement(recurmax, canThrow, CAN_BREAK, CAN_CONTINUE, cannotReturn, stmtDepth) + '} while ((' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ') && --brake' + loop + ' > 0);}';
|
var label = createLabel(canBreak, canContinue);
|
||||||
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
|
return '{var brake' + loop + ' = 5; ' + label.target + 'do {' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + '} while ((' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ') && --brake' + loop + ' > 0);}';
|
||||||
case STMT_WHILE:
|
case STMT_WHILE:
|
||||||
return '{var brake' + loop + ' = 5; while ((' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ') && --brake' + loop + ' > 0)' + createStatement(recurmax, canThrow, CAN_BREAK, CAN_CONTINUE, cannotReturn, stmtDepth) + '}';
|
var label = createLabel(canBreak, canContinue);
|
||||||
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
|
return '{var brake' + loop + ' = 5; ' + label.target + 'while ((' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ') && --brake' + loop + ' > 0)' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + '}';
|
||||||
case STMT_FOR_LOOP:
|
case STMT_FOR_LOOP:
|
||||||
return 'for (var brake' + loop + ' = 5; (' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ') && brake' + loop + ' > 0; --brake' + loop + ')' + createStatement(recurmax, canThrow, CAN_BREAK, CAN_CONTINUE, cannotReturn, stmtDepth);
|
var label = createLabel(canBreak, canContinue);
|
||||||
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
|
return label.target + 'for (var brake' + loop + ' = 5; (' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ') && brake' + loop + ' > 0; --brake' + loop + ')' + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);
|
||||||
|
case STMT_FOR_IN:
|
||||||
|
var label = createLabel(canBreak, canContinue);
|
||||||
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
|
var optElementVar = '';
|
||||||
|
if (rng(5) > 1) {
|
||||||
|
optElementVar = 'c = 1 + c; var ' + createVarName(MANDATORY) + ' = expr' + loop + '[key' + loop + ']; ';
|
||||||
|
}
|
||||||
|
return '{var expr' + loop + ' = ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + '; ' + label.target + ' for (var key' + loop + ' in expr' + loop + ') {' + optElementVar + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + '}}';
|
||||||
case STMT_SEMI:
|
case STMT_SEMI:
|
||||||
return ';';
|
return use_strict && rng(20) === 0 ? '"use strict";' : ';';
|
||||||
case STMT_EXPR:
|
case STMT_EXPR:
|
||||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';';
|
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';';
|
||||||
case STMT_SWITCH:
|
case STMT_SWITCH:
|
||||||
@@ -424,8 +482,8 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
if (canBreak && rng(5) === 0) return 'break;';
|
if (canBreak && rng(5) === 0) return 'break' + getLabel(canBreak) + ';';
|
||||||
if (canContinue && rng(5) === 0) return 'continue;';
|
if (canContinue && rng(5) === 0) return 'continue' + getLabel(canContinue) + ';';
|
||||||
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||||
if (rng(3) == 0) return '/*3*/return;';
|
if (rng(3) == 0) return '/*3*/return;';
|
||||||
return 'return ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
return 'return ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||||
@@ -470,25 +528,27 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
|
|
||||||
function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
||||||
var hadDefault = false;
|
var hadDefault = false;
|
||||||
var s = '';
|
var s = [''];
|
||||||
|
canBreak = enableLoopControl(canBreak, CAN_BREAK);
|
||||||
while (n-- > 0) {
|
while (n-- > 0) {
|
||||||
//hadDefault = n > 0; // disables weird `default` clause positioning (use when handling destabilizes)
|
//hadDefault = n > 0; // disables weird `default` clause positioning (use when handling destabilizes)
|
||||||
if (hadDefault || rng(5) > 0) {
|
if (hadDefault || rng(5) > 0) {
|
||||||
s += '' +
|
s.push(
|
||||||
'case ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':\n' +
|
'case ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':',
|
||||||
createStatements(rng(3) + 1, recurmax, canThrow, CAN_BREAK, canContinue, cannotReturn, stmtDepth) +
|
createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
'\n' +
|
rng(10) > 0 ? ' break;' : '/* fall-through */',
|
||||||
(rng(10) > 0 ? ' break;' : '/* fall-through */') +
|
''
|
||||||
'\n';
|
);
|
||||||
} else {
|
} else {
|
||||||
hadDefault = true;
|
hadDefault = true;
|
||||||
s += '' +
|
s.push(
|
||||||
'default:\n' +
|
'default:',
|
||||||
createStatements(rng(3) + 1, recurmax, canThrow, CAN_BREAK, canContinue, cannotReturn, stmtDepth) +
|
createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
'\n';
|
''
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
function createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
@@ -530,37 +590,66 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
return createExpression(recurmax, noComma, stmtDepth, canThrow) + '?' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':' + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
return createExpression(recurmax, noComma, stmtDepth, canThrow) + '?' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':' + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||||
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
||||||
if (name === 'c') name = 'a';
|
if (name == 'c') name = 'a';
|
||||||
var s = '';
|
var s = [];
|
||||||
switch(rng(4)) {
|
switch (rng(5)) {
|
||||||
case 0:
|
case 0:
|
||||||
s = '(function ' + name + '(){' + createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '})()';
|
s.push(
|
||||||
|
'(function ' + name + '(){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'})()'
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
s = '+function ' + name + '(){' + createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}()';
|
s.push(
|
||||||
|
'+function ' + name + '(){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'}()'
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
s = '!function ' + name + '(){' + createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}()';
|
s.push(
|
||||||
|
'!function ' + name + '(){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'}()'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
s.push(
|
||||||
|
'void function ' + name + '(){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'}()'
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
s = 'void function ' + name + '(){' + createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}()';
|
var instantiate = rng(4) ? 'new ' : '';
|
||||||
|
s.push(
|
||||||
|
instantiate + 'function ' + name + '(){',
|
||||||
|
strictMode()
|
||||||
|
);
|
||||||
|
if (instantiate) for (var i = rng(4); --i >= 0;) {
|
||||||
|
if (rng(2)) s.push('this.' + getDotKey() + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ';');
|
||||||
|
else s.push('this[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ';');
|
||||||
|
}
|
||||||
|
s.push(
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'}'
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
VAR_NAMES.length = nameLenBefore;
|
VAR_NAMES.length = nameLenBefore;
|
||||||
return s;
|
return s.join('\n');
|
||||||
case p++:
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
||||||
case p++:
|
|
||||||
return [
|
|
||||||
'new function() {',
|
|
||||||
rng(2) ? '' : createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
|
||||||
'return ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
|
||||||
'}'
|
|
||||||
].join('\n');
|
|
||||||
case p++:
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
// more like a parser test but perhaps comment nodes mess up the analysis?
|
// more like a parser test but perhaps comment nodes mess up the analysis?
|
||||||
@@ -682,22 +771,23 @@ function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
// intentionally generate more hardcore ops
|
// intentionally generate more hardcore ops
|
||||||
if (--recurmax < 0) return createValue();
|
if (--recurmax < 0) return createValue();
|
||||||
|
var assignee, expr;
|
||||||
switch (rng(30)) {
|
switch (rng(30)) {
|
||||||
case 0:
|
case 0:
|
||||||
return '(c = c + 1, ' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
return '(c = c + 1, ' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
case 1:
|
case 1:
|
||||||
return '(' + createUnarySafePrefix() + '(' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + '))';
|
return '(' + createUnarySafePrefix() + '(' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||||
case 2:
|
case 2:
|
||||||
var assignee = getVarName();
|
assignee = getVarName();
|
||||||
return '(' + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
return '(' + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
case 3:
|
case 3:
|
||||||
var assignee = getVarName();
|
assignee = getVarName();
|
||||||
var expr = '(' + assignee + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow)
|
expr = '(' + assignee + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow)
|
||||||
+ ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
+ ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||||
case 4:
|
case 4:
|
||||||
var assignee = getVarName();
|
assignee = getVarName();
|
||||||
var expr = '(' + assignee + '.' + getDotKey() + createAssignment()
|
expr = '(' + assignee + '.' + getDotKey() + createAssignment()
|
||||||
+ _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
+ _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||||
default:
|
default:
|
||||||
@@ -802,8 +892,8 @@ var default_options = {
|
|||||||
mangle: {
|
mangle: {
|
||||||
"cache": null,
|
"cache": null,
|
||||||
"eval": false,
|
"eval": false,
|
||||||
|
"ie8": false,
|
||||||
"keep_fnames": false,
|
"keep_fnames": false,
|
||||||
"screw_ie8": true,
|
|
||||||
"toplevel": false,
|
"toplevel": false,
|
||||||
},
|
},
|
||||||
output: infer_options(UglifyJS.OutputStream),
|
output: infer_options(UglifyJS.OutputStream),
|
||||||
@@ -858,17 +948,27 @@ function log(options) {
|
|||||||
} else {
|
} else {
|
||||||
console.log("// !!! uglify failed !!!");
|
console.log("// !!! uglify failed !!!");
|
||||||
console.log(uglify_code.stack);
|
console.log(uglify_code.stack);
|
||||||
|
if (typeof original_result != "string") {
|
||||||
|
console.log();
|
||||||
|
console.log();
|
||||||
|
console.log("original stacktrace:");
|
||||||
|
console.log(original_result.stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log("minify(options):");
|
console.log("minify(options):");
|
||||||
options = JSON.parse(options);
|
options = JSON.parse(options);
|
||||||
console.log(options);
|
console.log(options);
|
||||||
console.log();
|
console.log();
|
||||||
if (!ok) {
|
if (!ok && typeof uglify_code == "string") {
|
||||||
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
||||||
console.log("!!!!!! Failed... round", round);
|
console.log("!!!!!! Failed... round", round);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fallback_options = [ JSON.stringify({
|
||||||
|
compress: false,
|
||||||
|
mangle: false
|
||||||
|
}) ];
|
||||||
var minify_options = require("./ufuzz.json").map(function(options) {
|
var minify_options = require("./ufuzz.json").map(function(options) {
|
||||||
options.fromString = true;
|
options.fromString = true;
|
||||||
return JSON.stringify(options);
|
return JSON.stringify(options);
|
||||||
@@ -882,13 +982,9 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
loops = 0;
|
loops = 0;
|
||||||
funcs = 0;
|
funcs = 0;
|
||||||
|
|
||||||
original_code = [
|
original_code = createTopLevelCode();
|
||||||
"var a = 100, b = 10, c = 0;",
|
original_result = sandbox.run_code(original_code);
|
||||||
createTopLevelCode(),
|
(typeof original_result != "string" ? fallback_options : minify_options).forEach(function(options) {
|
||||||
"console.log(null, a, b, c);" // preceding `null` makes for a cleaner output (empty string still shows up etc)
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
minify_options.forEach(function(options) {
|
|
||||||
try {
|
try {
|
||||||
uglify_code = UglifyJS.minify(original_code, JSON.parse(options)).code;
|
uglify_code = UglifyJS.minify(original_code, JSON.parse(options)).code;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -897,9 +993,10 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
|
|
||||||
ok = typeof uglify_code == "string";
|
ok = typeof uglify_code == "string";
|
||||||
if (ok) {
|
if (ok) {
|
||||||
original_result = sandbox.run_code(original_code);
|
|
||||||
uglify_result = sandbox.run_code(uglify_code);
|
uglify_result = sandbox.run_code(uglify_code);
|
||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
|
} else if (typeof original_result != "string") {
|
||||||
|
ok = uglify_code.name == original_result.name;
|
||||||
}
|
}
|
||||||
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
||||||
else if (verbose_error && typeof original_result != "string") {
|
else if (verbose_error && typeof original_result != "string") {
|
||||||
|
|||||||
Reference in New Issue
Block a user