Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9ef659bcb | ||
|
|
35c2149dbd | ||
|
|
89a35f9fcd | ||
|
|
1a4e99dc2d | ||
|
|
cb870f6fd6 | ||
|
|
a0c0c294c5 | ||
|
|
fbdb7eeda3 | ||
|
|
1bc0fccc8c | ||
|
|
20252c6483 | ||
|
|
e396912ea2 | ||
|
|
5ebfa78f56 | ||
|
|
950609f578 | ||
|
|
4a44d95f09 | ||
|
|
36718948be | ||
|
|
21bd4c4a9d | ||
|
|
998c9792da | ||
|
|
ccd77d70db | ||
|
|
d75a946707 | ||
|
|
696a20f10d | ||
|
|
224c91b6c1 | ||
|
|
8065e27a7d | ||
|
|
584e253f33 | ||
|
|
fb5e08e4ec | ||
|
|
e3d328f741 | ||
|
|
8922f08fbf | ||
|
|
15a4074d1a | ||
|
|
c624b43739 | ||
|
|
a8e040b133 | ||
|
|
5e30f3a48b | ||
|
|
46570a4eb6 | ||
|
|
01b84074d7 |
16
README.md
16
README.md
@@ -1373,3 +1373,19 @@ To allow for better optimizations, the compiler makes various assumptions:
|
|||||||
// TypeError: const 'a' has already been declared
|
// TypeError: const 'a' has already been declared
|
||||||
```
|
```
|
||||||
UglifyJS may modify the input which in turn may suppress those errors.
|
UglifyJS may modify the input which in turn may suppress those errors.
|
||||||
|
- Later versions of Chrome and Node.js will give incorrect results with the
|
||||||
|
following:
|
||||||
|
```javascript
|
||||||
|
try {
|
||||||
|
class A {
|
||||||
|
static 42;
|
||||||
|
static get 42() {}
|
||||||
|
}
|
||||||
|
console.log("PASS");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
// Expected: "PASS"
|
||||||
|
// Actual: "FAIL"
|
||||||
|
```
|
||||||
|
UglifyJS may modify the input which in turn may suppress those errors.
|
||||||
|
|||||||
@@ -851,6 +851,9 @@ var AST_DefClass = DEFNODE("DefClass", null, {
|
|||||||
$propdoc: {
|
$propdoc: {
|
||||||
name: "[AST_SymbolDefClass] the name of this class",
|
name: "[AST_SymbolDefClass] the name of this class",
|
||||||
},
|
},
|
||||||
|
resolve: function(def_class) {
|
||||||
|
return def_class ? this : this.parent_scope.resolve();
|
||||||
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
if (!(this.name instanceof AST_SymbolDefClass)) throw new Error("name must be AST_SymbolDefClass");
|
if (!(this.name instanceof AST_SymbolDefClass)) throw new Error("name must be AST_SymbolDefClass");
|
||||||
},
|
},
|
||||||
|
|||||||
276
lib/compress.js
276
lib/compress.js
@@ -649,7 +649,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
if (!HOP(tw.safe_ids, def.id)) {
|
if (!HOP(tw.safe_ids, def.id)) {
|
||||||
if (!safe) return false;
|
if (!safe) return false;
|
||||||
if (safe.read) {
|
if (safe.read || tw.in_loop) {
|
||||||
var scope = tw.find_parent(AST_BlockScope);
|
var scope = tw.find_parent(AST_BlockScope);
|
||||||
if (scope instanceof AST_Class) return false;
|
if (scope instanceof AST_Class) return false;
|
||||||
if (def.scope.resolve() !== scope.resolve()) return false;
|
if (def.scope.resolve() !== scope.resolve()) return false;
|
||||||
@@ -751,6 +751,34 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function make_fixed(save, fn) {
|
||||||
|
var prev_save, prev_value;
|
||||||
|
return function() {
|
||||||
|
var current = save();
|
||||||
|
if (prev_save !== current) {
|
||||||
|
prev_save = current;
|
||||||
|
prev_value = fn(current);
|
||||||
|
}
|
||||||
|
return prev_value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_fixed_default(compressor, node, save) {
|
||||||
|
var prev_save, prev_seq;
|
||||||
|
return function() {
|
||||||
|
var current = save();
|
||||||
|
var ev;
|
||||||
|
if (!is_undefined(current, compressor) && (ev = fuzzy_eval(compressor, current, true)) !== undefined) {
|
||||||
|
return ev instanceof AST_Node ? node : current;
|
||||||
|
}
|
||||||
|
if (prev_save !== current) {
|
||||||
|
prev_save = current;
|
||||||
|
prev_seq = make_sequence(node, [ current, node.value ]);
|
||||||
|
}
|
||||||
|
return prev_seq;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function scan_declaration(tw, compressor, lhs, fixed, visit) {
|
function scan_declaration(tw, compressor, lhs, fixed, visit) {
|
||||||
var scanner = new TreeWalker(function(node) {
|
var scanner = new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_DefaultValue) {
|
if (node instanceof AST_DefaultValue) {
|
||||||
@@ -759,15 +787,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
node.value.walk(tw);
|
node.value.walk(tw);
|
||||||
pop(tw);
|
pop(tw);
|
||||||
var save = fixed;
|
var save = fixed;
|
||||||
if (save) fixed = function() {
|
if (save) fixed = make_fixed_default(compressor, node, save);
|
||||||
var value = save();
|
|
||||||
var ev;
|
|
||||||
if (is_undefined(value, compressor)
|
|
||||||
|| (ev = fuzzy_eval(compressor, value, true)) === undefined) {
|
|
||||||
return make_sequence(node, [ value, node.value ]);
|
|
||||||
}
|
|
||||||
return ev instanceof AST_Node ? node : value;
|
|
||||||
};
|
|
||||||
node.name.walk(scanner);
|
node.name.walk(scanner);
|
||||||
fixed = save;
|
fixed = save;
|
||||||
return true;
|
return true;
|
||||||
@@ -777,18 +797,17 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var save = fixed;
|
var save = fixed;
|
||||||
node.elements.forEach(function(node, index) {
|
node.elements.forEach(function(node, index) {
|
||||||
if (node instanceof AST_Hole) return reset_flags(node);
|
if (node instanceof AST_Hole) return reset_flags(node);
|
||||||
if (save) fixed = function() {
|
if (save) fixed = make_fixed(save, function(value) {
|
||||||
return make_node(AST_Sub, node, {
|
return make_node(AST_Sub, node, {
|
||||||
expression: save(),
|
expression: value,
|
||||||
property: make_node(AST_Number, node, { value: index }),
|
property: make_node(AST_Number, node, { value: index }),
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
node.walk(scanner);
|
node.walk(scanner);
|
||||||
});
|
});
|
||||||
if (node.rest) {
|
if (node.rest) {
|
||||||
var fixed_node;
|
var fixed_node;
|
||||||
if (save) fixed = compressor.option("rests") && function() {
|
if (save) fixed = compressor.option("rests") && make_fixed(save, function(value) {
|
||||||
var value = save();
|
|
||||||
if (!(value instanceof AST_Array)) return node;
|
if (!(value instanceof AST_Array)) return node;
|
||||||
for (var i = 0, len = node.elements.length; i < len; i++) {
|
for (var i = 0, len = node.elements.length; i < len; i++) {
|
||||||
if (value.elements[i] instanceof AST_Spread) return node;
|
if (value.elements[i] instanceof AST_Spread) return node;
|
||||||
@@ -796,7 +815,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!fixed_node) fixed_node = make_node(AST_Array, node);
|
if (!fixed_node) fixed_node = make_node(AST_Array, node);
|
||||||
fixed_node.elements = value.elements.slice(len);
|
fixed_node.elements = value.elements.slice(len);
|
||||||
return fixed_node;
|
return fixed_node;
|
||||||
};
|
});
|
||||||
node.rest.walk(scanner);
|
node.rest.walk(scanner);
|
||||||
}
|
}
|
||||||
fixed = save;
|
fixed = save;
|
||||||
@@ -812,7 +831,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
node.key.walk(tw);
|
node.key.walk(tw);
|
||||||
pop(tw);
|
pop(tw);
|
||||||
}
|
}
|
||||||
if (save) fixed = function() {
|
if (save) fixed = make_fixed(save, function(value) {
|
||||||
var key = node.key;
|
var key = node.key;
|
||||||
var type = AST_Sub;
|
var type = AST_Sub;
|
||||||
if (typeof key == "string") {
|
if (typeof key == "string") {
|
||||||
@@ -823,10 +842,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return make_node(type, node, {
|
return make_node(type, node, {
|
||||||
expression: save(),
|
expression: value,
|
||||||
property: key
|
property: key,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
|
||||||
node.value.walk(scanner);
|
node.value.walk(scanner);
|
||||||
});
|
});
|
||||||
if (node.rest) {
|
if (node.rest) {
|
||||||
@@ -2040,13 +2059,17 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (is_lhs(node, parent)) {
|
if (is_lhs(node, parent)) {
|
||||||
if (value_def && !hit_rhs) assign_used = true;
|
if (value_def && !hit_rhs) assign_used = true;
|
||||||
return node;
|
return node;
|
||||||
} else if (value_def) {
|
}
|
||||||
|
if (!hit_rhs && verify_ref && node.fixed !== lhs.fixed) {
|
||||||
|
abort = true;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (value_def) {
|
||||||
if (stop_if_hit && assign_pos == 0) assign_pos = remaining - replaced;
|
if (stop_if_hit && assign_pos == 0) assign_pos = remaining - replaced;
|
||||||
if (!hit_rhs) replaced++;
|
if (!hit_rhs) replaced++;
|
||||||
return node;
|
return node;
|
||||||
} else {
|
|
||||||
replaced++;
|
|
||||||
}
|
}
|
||||||
|
replaced++;
|
||||||
changed = abort = true;
|
changed = abort = true;
|
||||||
AST_Node.info("Collapsing {node} [{file}:{line},{col}]", {
|
AST_Node.info("Collapsing {node} [{file}:{line},{col}]", {
|
||||||
node: node,
|
node: node,
|
||||||
@@ -2221,6 +2244,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var candidate = hit_stack[hit_stack.length - 1];
|
var candidate = hit_stack[hit_stack.length - 1];
|
||||||
var assign_pos = -1;
|
var assign_pos = -1;
|
||||||
var assign_used = false;
|
var assign_used = false;
|
||||||
|
var verify_ref = false;
|
||||||
var remaining;
|
var remaining;
|
||||||
var value_def = null;
|
var value_def = null;
|
||||||
var stop_after = null;
|
var stop_after = null;
|
||||||
@@ -2248,8 +2272,11 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var lvalues = get_lvalues(candidate);
|
var lvalues = get_lvalues(candidate);
|
||||||
var lhs_local = is_lhs_local(lhs);
|
var lhs_local = is_lhs_local(lhs);
|
||||||
var rhs_value = get_rvalue(candidate);
|
var rhs_value = get_rvalue(candidate);
|
||||||
var rvalue = !compound && rhs_value instanceof AST_Sequence ? rhs_value.tail_node() : rhs_value;
|
var rvalue = rhs_value;
|
||||||
if (!side_effects) side_effects = value_has_side_effects();
|
if (!side_effects) {
|
||||||
|
if (!compound && rvalue instanceof AST_Sequence) rvalue = rvalue.tail_node();
|
||||||
|
side_effects = value_has_side_effects();
|
||||||
|
}
|
||||||
var check_destructured = in_try || !lhs_local ? function(node) {
|
var check_destructured = in_try || !lhs_local ? function(node) {
|
||||||
return node instanceof AST_Destructured;
|
return node instanceof AST_Destructured;
|
||||||
} : return_false;
|
} : return_false;
|
||||||
@@ -2936,6 +2963,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (matches < remaining) {
|
if (matches < remaining) {
|
||||||
remaining = matches;
|
remaining = matches;
|
||||||
assign_pos = 0;
|
assign_pos = 0;
|
||||||
|
verify_ref = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (expr.operator == "=") mangleable_var(expr.right);
|
if (expr.operator == "=") mangleable_var(expr.right);
|
||||||
@@ -3163,47 +3191,42 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var end = hit_stack.length - 1;
|
var end = hit_stack.length - 1;
|
||||||
if (hit_stack[end - 1].body === hit_stack[end]) end--;
|
var last = hit_stack[end];
|
||||||
|
if (last instanceof AST_VarDef || hit_stack[end - 1].body === last) end--;
|
||||||
var tt = new TreeTransformer(function(node, descend, in_list) {
|
var tt = new TreeTransformer(function(node, descend, in_list) {
|
||||||
if (hit) return node;
|
if (hit) return node;
|
||||||
if (node !== hit_stack[hit_index]) return node;
|
if (node !== hit_stack[hit_index]) return node;
|
||||||
hit_index++;
|
hit_index++;
|
||||||
if (hit_index <= end) return handle_custom_scan_order(node, tt);
|
if (hit_index <= end) return handle_custom_scan_order(node, tt);
|
||||||
hit = true;
|
hit = true;
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_Definitions) {
|
||||||
declare_only.set(node.name.name, (declare_only.get(node.name.name) || 0) + 1);
|
declare_only.set(last.name.name, (declare_only.get(last.name.name) || 0) + 1);
|
||||||
if (value_def) value_def.replaced++;
|
if (value_def) value_def.replaced++;
|
||||||
|
var defns = node.definitions;
|
||||||
|
var index = defns.indexOf(last);
|
||||||
|
var defn = last.clone();
|
||||||
|
defn.value = null;
|
||||||
|
if (!value) {
|
||||||
|
node.definitions[index] = defn;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
var body = [ make_node(AST_SimpleStatement, value, { body: value }) ];
|
||||||
|
if (index > 0) {
|
||||||
|
var head = node.clone();
|
||||||
|
head.definitions = defns.slice(0, index);
|
||||||
|
body.unshift(head);
|
||||||
node = node.clone();
|
node = node.clone();
|
||||||
node.value = null;
|
node.definitions = defns.slice(index);
|
||||||
return value ? List.splice([ value, node ]) : node;
|
}
|
||||||
|
body.push(node);
|
||||||
|
node.definitions[0] = defn;
|
||||||
|
return in_list ? List.splice(body) : make_node(AST_BlockStatement, node, { body: body });
|
||||||
}
|
}
|
||||||
if (!value) return in_list ? List.skip : null;
|
if (!value) return in_list ? List.skip : null;
|
||||||
return is_statement(node) ? make_node(AST_SimpleStatement, value, { body: value }) : value;
|
return is_statement(node) ? make_node(AST_SimpleStatement, value, { body: value }) : value;
|
||||||
}, function(node, in_list) {
|
}, function(node, in_list) {
|
||||||
if (node instanceof AST_Definitions) {
|
|
||||||
var body = [], defns = node.definitions;
|
|
||||||
for (var index = 0, pos = 0; index < defns.length; index++) {
|
|
||||||
var defn = defns[index];
|
|
||||||
if (defn instanceof AST_VarDef) continue;
|
|
||||||
flush();
|
|
||||||
pos = index + 1;
|
|
||||||
body.push(make_node(AST_SimpleStatement, defn, { body: defn }));
|
|
||||||
}
|
|
||||||
if (pos == 0) return;
|
|
||||||
flush();
|
|
||||||
if (body.length == 1) return body[0];
|
|
||||||
return in_list ? List.splice(body) : make_node(AST_BlockStatement, node, { body: body });
|
|
||||||
}
|
|
||||||
if (node instanceof AST_For) return patch_for_init(node, in_list);
|
if (node instanceof AST_For) return patch_for_init(node, in_list);
|
||||||
return patch_sequence(node, this);
|
return patch_sequence(node, tt);
|
||||||
|
|
||||||
function flush() {
|
|
||||||
if (pos < index) {
|
|
||||||
var cropped = node.clone();
|
|
||||||
cropped.definitions = defns.slice(pos, index);
|
|
||||||
body.push(cropped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
abort = false;
|
abort = false;
|
||||||
hit = false;
|
hit = false;
|
||||||
@@ -3249,9 +3272,13 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
var def = lhs.definition();
|
var def = lhs.definition();
|
||||||
if (def.references.length - def.replaced == referenced) return true;
|
if (def.references.length - def.replaced == referenced) return true;
|
||||||
return def.fixed && lhs.fixed && def.references.filter(function(ref) {
|
if (!def.fixed) return false;
|
||||||
|
if (!lhs.fixed) return false;
|
||||||
|
if (def.references.filter(function(ref) {
|
||||||
return ref.fixed === lhs.fixed;
|
return ref.fixed === lhs.fixed;
|
||||||
}).length == referenced;
|
}).length != referenced) return false;
|
||||||
|
verify_ref = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function symbol_in_lvalues(sym, parent) {
|
function symbol_in_lvalues(sym, parent) {
|
||||||
@@ -3269,7 +3296,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (def.scope.resolve() !== scope) return true;
|
if (def.scope.resolve() !== scope) return true;
|
||||||
if (modify_toplevel && compressor.exposed(def)) return true;
|
if (modify_toplevel && compressor.exposed(def)) return true;
|
||||||
return !all(def.references, function(ref) {
|
return !all(def.references, function(ref) {
|
||||||
return ref.scope.resolve() === scope;
|
return ref.scope.resolve(true) === scope;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4767,6 +4794,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
var scan_modified = new TreeWalker(function(node) {
|
var scan_modified = new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Assign) modified(node.left);
|
if (node instanceof AST_Assign) modified(node.left);
|
||||||
|
if (node instanceof AST_ForEnumeration) modified(node.init);
|
||||||
if (node instanceof AST_Unary && UNARY_POSTFIX[node.operator]) modified(node.expression);
|
if (node instanceof AST_Unary && UNARY_POSTFIX[node.operator]) modified(node.expression);
|
||||||
});
|
});
|
||||||
function modified(node) {
|
function modified(node) {
|
||||||
@@ -5425,7 +5453,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);
|
return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
def(AST_ObjectIdentity, return_true);
|
|
||||||
def(AST_Sequence, function() {
|
def(AST_Sequence, function() {
|
||||||
return this.tail_node().safe_to_spread();
|
return this.tail_node().safe_to_spread();
|
||||||
});
|
});
|
||||||
@@ -6054,18 +6081,15 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Call) {
|
if (node instanceof AST_Call) {
|
||||||
var exp = node.expression;
|
var exp = node.expression;
|
||||||
var tail = exp.tail_node();
|
if (exp instanceof AST_LambdaExpression) {
|
||||||
if (!(tail instanceof AST_LambdaExpression)) {
|
|
||||||
descend();
|
|
||||||
return mark_expression(exp);
|
|
||||||
}
|
|
||||||
if (exp !== tail) exp.expressions.slice(0, -1).forEach(function(node) {
|
|
||||||
node.walk(tw);
|
|
||||||
});
|
|
||||||
node.args.forEach(function(arg) {
|
node.args.forEach(function(arg) {
|
||||||
arg.walk(tw);
|
arg.walk(tw);
|
||||||
});
|
});
|
||||||
tail.walk(tw);
|
exp.walk(tw);
|
||||||
|
} else {
|
||||||
|
descend();
|
||||||
|
mark_expression(exp);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Class) {
|
if (node instanceof AST_Class) {
|
||||||
@@ -6078,9 +6102,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (prop.static) {
|
if (prop.static) {
|
||||||
prop.value.walk(tw);
|
prop.value.walk(tw);
|
||||||
} else {
|
} else {
|
||||||
push(tw);
|
push();
|
||||||
|
segment.block = node;
|
||||||
prop.value.walk(tw);
|
prop.value.walk(tw);
|
||||||
pop(tw);
|
pop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@@ -6145,6 +6170,8 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (node === self) root = segment;
|
if (node === self) root = segment;
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
if (node.name) references[node.name.definition().id] = false;
|
if (node.name) references[node.name.definition().id] = false;
|
||||||
|
var parent = tw.parent();
|
||||||
|
var in_iife = parent && parent.TYPE == "Call" && parent.expression === node;
|
||||||
var marker = node.uses_arguments && !tw.has_directive("use strict") ? function(node) {
|
var marker = node.uses_arguments && !tw.has_directive("use strict") ? function(node) {
|
||||||
if (node instanceof AST_SymbolFunarg) references[node.definition().id] = false;
|
if (node instanceof AST_SymbolFunarg) references[node.definition().id] = false;
|
||||||
} : function(node) {
|
} : function(node) {
|
||||||
@@ -6160,11 +6187,13 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|| node.parent_scope.find_variable(ref.name) === def)) {
|
|| node.parent_scope.find_variable(ref.name) === def)) {
|
||||||
references[def.id] = false;
|
references[def.id] = false;
|
||||||
references[ldef.id] = false;
|
references[ldef.id] = false;
|
||||||
} else {
|
} else if (in_iife) {
|
||||||
var save = segment;
|
var save = segment;
|
||||||
pop();
|
pop();
|
||||||
mark(ref, true);
|
mark(ref, true);
|
||||||
segment = save;
|
segment = save;
|
||||||
|
} else {
|
||||||
|
mark(ref, true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -6187,7 +6216,8 @@ Compressor.prototype.compress = function(node) {
|
|||||||
} else {
|
} else {
|
||||||
descend();
|
descend();
|
||||||
}
|
}
|
||||||
return mark_expression(exp);
|
mark_expression(exp);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Switch) {
|
if (node instanceof AST_Switch) {
|
||||||
node.expression.walk(tw);
|
node.expression.walk(tw);
|
||||||
@@ -6219,9 +6249,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (node instanceof AST_Try) {
|
if (node instanceof AST_Try) {
|
||||||
var save_try = in_try;
|
var save_try = in_try;
|
||||||
in_try = node;
|
in_try = node;
|
||||||
var save = segment;
|
|
||||||
walk_body(node, tw);
|
walk_body(node, tw);
|
||||||
segment = save;
|
|
||||||
if (node.bcatch) {
|
if (node.bcatch) {
|
||||||
if (node.bcatch.argname) node.bcatch.argname.mark_symbol(function(node) {
|
if (node.bcatch.argname) node.bcatch.argname.mark_symbol(function(node) {
|
||||||
if (node instanceof AST_SymbolCatch) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
@@ -6239,7 +6267,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
in_try = save_try;
|
in_try = save_try;
|
||||||
segment = save;
|
|
||||||
if (node.bfinally) node.bfinally.walk(tw);
|
if (node.bfinally) node.bfinally.walk(tw);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -6289,12 +6316,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mark_expression(exp) {
|
function mark_expression(exp) {
|
||||||
if (compressor.option("ie")) {
|
if (!compressor.option("ie")) return;
|
||||||
var sym = root_expr(exp);
|
var sym = root_expr(exp);
|
||||||
if (sym instanceof AST_SymbolRef) sym.walk(tw);
|
if (sym instanceof AST_SymbolRef) sym.walk(tw);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function walk_cond(condition, consequent, alternative) {
|
function walk_cond(condition, consequent, alternative) {
|
||||||
var save = segment;
|
var save = segment;
|
||||||
@@ -6847,7 +6872,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Call) calls_to_drop_args.push(node);
|
if (node instanceof AST_Call) {
|
||||||
|
calls_to_drop_args.push(node);
|
||||||
|
node.args = node.args.map(function(arg) {
|
||||||
|
return arg.transform(tt);
|
||||||
|
});
|
||||||
|
node.expression = node.expression.transform(tt);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
if (scope !== self) return;
|
if (scope !== self) return;
|
||||||
if (drop_funcs && node !== self && node instanceof AST_DefClass) {
|
if (drop_funcs && node !== self && node instanceof AST_DefClass) {
|
||||||
var def = node.name.definition();
|
var def = node.name.definition();
|
||||||
@@ -7114,6 +7146,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (def.orig.length > 1) return null;
|
if (def.orig.length > 1) return null;
|
||||||
if (def.assignments > 0) return false;
|
if (def.assignments > 0) return false;
|
||||||
if (def.name == name) return def;
|
if (def.name == name) return def;
|
||||||
|
if (compressor.option("keep_fnames")) return false;
|
||||||
var forbidden;
|
var forbidden;
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "await":
|
case "await":
|
||||||
@@ -7818,7 +7851,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var consts = new Dictionary();
|
var consts = new Dictionary();
|
||||||
var dirs = [];
|
var dirs = [];
|
||||||
var hoisted = [];
|
var hoisted = [];
|
||||||
var vars = new Dictionary(), vars_found = 0;
|
var vars = new Dictionary();
|
||||||
var tt = new TreeTransformer(function(node, descend, in_list) {
|
var tt = new TreeTransformer(function(node, descend, in_list) {
|
||||||
if (node === self) return;
|
if (node === self) return;
|
||||||
if (node instanceof AST_Directive) {
|
if (node instanceof AST_Directive) {
|
||||||
@@ -7846,7 +7879,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
})) return node;
|
})) return node;
|
||||||
node.definitions.forEach(function(defn) {
|
node.definitions.forEach(function(defn) {
|
||||||
vars.set(defn.name.name, defn);
|
vars.set(defn.name.name, defn);
|
||||||
++vars_found;
|
|
||||||
});
|
});
|
||||||
var seq = node.to_assignments();
|
var seq = node.to_assignments();
|
||||||
if (p instanceof AST_ForEnumeration && p.init === node) {
|
if (p instanceof AST_ForEnumeration && p.init === node) {
|
||||||
@@ -7865,7 +7897,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.transform(tt);
|
self.transform(tt);
|
||||||
if (vars_found > 0) {
|
if (vars.size() > 0) {
|
||||||
// collect only vars which don't show up in self's arguments list
|
// collect only vars which don't show up in self's arguments list
|
||||||
var defns = [];
|
var defns = [];
|
||||||
if (self instanceof AST_Lambda) self.each_argname(function(argname) {
|
if (self instanceof AST_Lambda) self.each_argname(function(argname) {
|
||||||
@@ -9633,8 +9665,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
fixed.escaped = def.escaped;
|
fixed.escaped = def.escaped;
|
||||||
name.fixed = fixed;
|
name.fixed = fixed;
|
||||||
def.references.forEach(function(ref) {
|
def.references.forEach(function(ref) {
|
||||||
var assigns = ref.fixed && ref.fixed.assigns;
|
if (!ref.fixed) return;
|
||||||
if (assigns && assigns[0] === defn) assigns[0] = assign;
|
var assigns = ref.fixed.assigns;
|
||||||
|
if (!assigns) return;
|
||||||
|
if (assigns[0] !== defn) return;
|
||||||
|
if (assigns.length > 1 || ref.fixed.to_binary || ref.fixed.to_prefix) {
|
||||||
|
assigns[0] = assign;
|
||||||
|
} else {
|
||||||
|
ref.fixed = fixed;
|
||||||
|
if (def.fixed === ref.fixed) def.fixed = fixed;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def.references.push(name);
|
def.references.push(name);
|
||||||
}
|
}
|
||||||
@@ -11100,9 +11140,15 @@ Compressor.prototype.compress = function(node) {
|
|||||||
&& assign instanceof AST_Assign
|
&& assign instanceof AST_Assign
|
||||||
&& assign.operator == "="
|
&& assign.operator == "="
|
||||||
&& self.left.equivalent_to(assign.left)) {
|
&& self.left.equivalent_to(assign.left)) {
|
||||||
self.right = assign.right;
|
return make_node(AST_Assign, self, {
|
||||||
assign.right = self;
|
operator: "=",
|
||||||
return assign;
|
left: assign.left,
|
||||||
|
right: make_node(AST_Binary, self, {
|
||||||
|
operator: self.operator,
|
||||||
|
left: self.left,
|
||||||
|
right: assign.right,
|
||||||
|
}),
|
||||||
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("comparisons")) switch (self.operator) {
|
if (compressor.option("comparisons")) switch (self.operator) {
|
||||||
@@ -12901,15 +12947,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
||||||
if (!compressor.option("properties")) return;
|
if (!compressor.option("properties")) return;
|
||||||
if (key === "__proto__") return;
|
if (key === "__proto__") return;
|
||||||
var expr = this.expression;
|
var self = this;
|
||||||
if (expr instanceof AST_Object) {
|
var expr = self.expression;
|
||||||
|
if (!(expr instanceof AST_Object)) return;
|
||||||
var props = expr.properties;
|
var props = expr.properties;
|
||||||
for (var i = props.length; --i >= 0;) {
|
for (var i = props.length; --i >= 0;) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
if (prop.key !== key) continue;
|
if (prop.key !== key) continue;
|
||||||
if (!all(props, can_hoist_property)) return;
|
if (!all(props, can_hoist_property)) return;
|
||||||
if (!safe_to_flatten(prop.value, compressor)) return;
|
if (!safe_to_flatten(prop.value, compressor)) return;
|
||||||
var scope, values = [];
|
var call, scope, values = [];
|
||||||
for (var j = 0; j < props.length; j++) {
|
for (var j = 0; j < props.length; j++) {
|
||||||
var value = props[j].value;
|
var value = props[j].value;
|
||||||
if (props[j] instanceof AST_ObjectMethod) {
|
if (props[j] instanceof AST_ObjectMethod) {
|
||||||
@@ -12924,21 +12971,21 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var ctor;
|
var ctor;
|
||||||
if (arrow) {
|
if (arrow) {
|
||||||
ctor = is_async(value) ? AST_AsyncArrow : AST_Arrow;
|
ctor = is_async(value) ? AST_AsyncArrow : AST_Arrow;
|
||||||
} else if (i === j && !(compressor.parent() instanceof AST_Call)) {
|
} else if (i != j
|
||||||
return;
|
|| (call = compressor.parent()) instanceof AST_Call && call.expression === self) {
|
||||||
} else {
|
|
||||||
ctor = value.CTOR;
|
ctor = value.CTOR;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
value = make_node(ctor, value, value);
|
value = make_node(ctor, value, value);
|
||||||
}
|
}
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
return make_node(AST_Sub, this, {
|
return make_node(AST_Sub, self, {
|
||||||
expression: make_node(AST_Array, expr, { elements: values }),
|
expression: make_node(AST_Array, expr, { elements: values }),
|
||||||
property: make_node(AST_Number, this, { value: i }),
|
property: make_node(AST_Number, self, { value: i }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Dot, function(self, compressor) {
|
OPT(AST_Dot, function(self, compressor) {
|
||||||
@@ -13134,6 +13181,19 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function insert_assign(def, assign) {
|
||||||
|
var visited = [];
|
||||||
|
def.references.forEach(function(ref) {
|
||||||
|
var fixed = ref.fixed;
|
||||||
|
if (!fixed || !push_uniq(visited, fixed)) return;
|
||||||
|
if (fixed.assigns) {
|
||||||
|
fixed.assigns.unshift(assign);
|
||||||
|
} else {
|
||||||
|
fixed.assigns = [ assign ];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function init_ref(compressor, name) {
|
function init_ref(compressor, name) {
|
||||||
var sym = make_node(AST_SymbolRef, name, name);
|
var sym = make_node(AST_SymbolRef, name, name);
|
||||||
var assign = make_node(AST_Assign, name, {
|
var assign = make_node(AST_Assign, name, {
|
||||||
@@ -13147,16 +13207,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return assign.right;
|
return assign.right;
|
||||||
};
|
};
|
||||||
sym.fixed.assigns = [ assign ];
|
sym.fixed.assigns = [ assign ];
|
||||||
var visited = [];
|
insert_assign(def, assign);
|
||||||
def.references.forEach(function(ref) {
|
|
||||||
var fixed = ref.fixed;
|
|
||||||
if (!fixed || !push_uniq(visited, fixed)) return;
|
|
||||||
if (fixed.assigns) {
|
|
||||||
fixed.assigns.unshift(assign);
|
|
||||||
} else {
|
|
||||||
fixed.assigns = [ assign ];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
def.assignments++;
|
def.assignments++;
|
||||||
def.references.push(sym);
|
def.references.push(sym);
|
||||||
@@ -13260,6 +13311,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (fn.body[0] instanceof AST_Directive) return;
|
if (fn.body[0] instanceof AST_Directive) return;
|
||||||
if (fn.contains_this()) return;
|
if (fn.contains_this()) return;
|
||||||
if (!scope) scope = find_scope(compressor);
|
if (!scope) scope = find_scope(compressor);
|
||||||
|
if (in_async_generator(scope)) return;
|
||||||
var defined = new Dictionary();
|
var defined = new Dictionary();
|
||||||
defined.set("NaN", true);
|
defined.set("NaN", true);
|
||||||
while (!(scope instanceof AST_Scope)) {
|
while (!(scope instanceof AST_Scope)) {
|
||||||
@@ -13334,7 +13386,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
var body = [];
|
var body = [];
|
||||||
fn.variables.each(function(def, name) {
|
fn.variables.each(function(def, name) {
|
||||||
if (name == "arguments") return;
|
if (!arrow && name == "arguments" && def.orig.length == 1) return;
|
||||||
names.set(name, true);
|
names.set(name, true);
|
||||||
scope.enclosed.push(def);
|
scope.enclosed.push(def);
|
||||||
scope.variables.set(name, def);
|
scope.variables.set(name, def);
|
||||||
@@ -13364,12 +13416,12 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (value) body.push(make_node(AST_SimpleStatement, call, { body: value }));
|
if (value) body.push(make_node(AST_SimpleStatement, call, { body: value }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
body.push(make_node(AST_Var, call, {
|
var defn = make_node(AST_VarDef, call, {
|
||||||
definitions: [ make_node(AST_VarDef, call, {
|
|
||||||
name: argname.convert_symbol(AST_SymbolVar, process),
|
name: argname.convert_symbol(AST_SymbolVar, process),
|
||||||
value: value || make_node(AST_Undefined, call).transform(compressor),
|
value: value || make_node(AST_Undefined, call).transform(compressor),
|
||||||
}) ],
|
});
|
||||||
}));
|
if (argname instanceof AST_SymbolFunarg) insert_assign(argname.definition(), defn);
|
||||||
|
body.push(make_node(AST_Var, call, { definitions: [ defn ] }));
|
||||||
});
|
});
|
||||||
if (values.length) body.push(make_node(AST_SimpleStatement, call, {
|
if (values.length) body.push(make_node(AST_SimpleStatement, call, {
|
||||||
body: make_sequence(call, values),
|
body: make_sequence(call, values),
|
||||||
@@ -13500,6 +13552,12 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_LabeledStatement, function(compressor, scope, no_return, in_loop) {
|
def(AST_LabeledStatement, function(compressor, scope, no_return, in_loop) {
|
||||||
var body = this.body.try_inline(compressor, scope, no_return, in_loop);
|
var body = this.body.try_inline(compressor, scope, no_return, in_loop);
|
||||||
if (!body) return;
|
if (!body) return;
|
||||||
|
if (this.body instanceof AST_IterationStatement && body instanceof AST_BlockStatement) {
|
||||||
|
var loop = body.body.pop();
|
||||||
|
this.body = loop;
|
||||||
|
body.body.push(this);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
this.body = body;
|
this.body = body;
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -96,15 +96,14 @@ function minify(files, options) {
|
|||||||
}, true);
|
}, true);
|
||||||
if (options.validate) AST_Node.enable_validation();
|
if (options.validate) AST_Node.enable_validation();
|
||||||
var timings = options.timings && { start: Date.now() };
|
var timings = options.timings && { start: Date.now() };
|
||||||
if (options.rename === undefined) options.rename = options.compress && options.mangle;
|
|
||||||
if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]);
|
if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]);
|
||||||
if (options.ie8) options.ie = options.ie || options.ie8;
|
if (options.ie8) options.ie = options.ie || options.ie8;
|
||||||
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output" ]);
|
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output", "rename" ]);
|
||||||
if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle" ]);
|
if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle", "rename" ]);
|
||||||
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]);
|
||||||
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]);
|
||||||
if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]);
|
if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]);
|
||||||
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output" ]);
|
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]);
|
||||||
var quoted_props;
|
var quoted_props;
|
||||||
if (options.mangle) {
|
if (options.mangle) {
|
||||||
options.mangle = defaults(options.mangle, {
|
options.mangle = defaults(options.mangle, {
|
||||||
@@ -135,6 +134,7 @@ function minify(files, options) {
|
|||||||
init_cache(options.mangle.cache);
|
init_cache(options.mangle.cache);
|
||||||
init_cache(options.mangle.properties.cache);
|
init_cache(options.mangle.properties.cache);
|
||||||
}
|
}
|
||||||
|
if (options.rename === undefined) options.rename = options.compress && options.mangle;
|
||||||
if (options.sourceMap) {
|
if (options.sourceMap) {
|
||||||
options.sourceMap = defaults(options.sourceMap, {
|
options.sourceMap = defaults(options.sourceMap, {
|
||||||
content: null,
|
content: null,
|
||||||
@@ -190,8 +190,8 @@ function minify(files, options) {
|
|||||||
if (options.validate) toplevel.validate_ast();
|
if (options.validate) toplevel.validate_ast();
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
if (options.rename) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.rename);
|
||||||
toplevel.expand_names(options.mangle);
|
toplevel.expand_names(options.rename);
|
||||||
}
|
}
|
||||||
if (timings) timings.compress = Date.now();
|
if (timings) timings.compress = Date.now();
|
||||||
if (options.compress) {
|
if (options.compress) {
|
||||||
|
|||||||
@@ -1194,10 +1194,10 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function for_() {
|
function for_() {
|
||||||
var await = is("name", "await") && next();
|
var await_token = is("name", "await") && next();
|
||||||
expect("(");
|
expect("(");
|
||||||
var init = null;
|
var init = null;
|
||||||
if (await || !is("punc", ";")) {
|
if (await_token || !is("punc", ";")) {
|
||||||
init = is("keyword", "const")
|
init = is("keyword", "const")
|
||||||
? (next(), const_(true))
|
? (next(), const_(true))
|
||||||
: is("name", "let") && is_vardefs()
|
: is("name", "let") && is_vardefs()
|
||||||
@@ -1206,7 +1206,7 @@ function parse($TEXT, options) {
|
|||||||
? (next(), var_(true))
|
? (next(), var_(true))
|
||||||
: expression(true);
|
: expression(true);
|
||||||
var ctor;
|
var ctor;
|
||||||
if (await) {
|
if (await_token) {
|
||||||
expect_token("name", "of");
|
expect_token("name", "of");
|
||||||
ctor = AST_ForAwaitOf;
|
ctor = AST_ForAwaitOf;
|
||||||
} else if (is("operator", "in")) {
|
} else if (is("operator", "in")) {
|
||||||
|
|||||||
@@ -469,6 +469,7 @@ AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
|
|||||||
this.uses_arguments = false;
|
this.uses_arguments = false;
|
||||||
this.def_variable(new AST_SymbolFunarg({
|
this.def_variable(new AST_SymbolFunarg({
|
||||||
name: "arguments",
|
name: "arguments",
|
||||||
|
scope: this,
|
||||||
start: this.start,
|
start: this.start,
|
||||||
end: this.end,
|
end: this.end,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -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.15.3",
|
"version": "3.15.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -183,13 +183,11 @@ function parse_test(file) {
|
|||||||
function reminify(orig_options, input_code, input_formatted, stdout) {
|
function reminify(orig_options, input_code, input_formatted, stdout) {
|
||||||
for (var i = 0; i < minify_options.length; i++) {
|
for (var i = 0; i < minify_options.length; i++) {
|
||||||
var options = JSON.parse(minify_options[i]);
|
var options = JSON.parse(minify_options[i]);
|
||||||
if (options.compress) [
|
[
|
||||||
"keep_fargs",
|
"keep_fargs",
|
||||||
"keep_fnames",
|
"keep_fnames",
|
||||||
].forEach(function(name) {
|
].forEach(function(name) {
|
||||||
if (name in orig_options) {
|
if (name in orig_options) options[name] = orig_options[name];
|
||||||
options.compress[name] = orig_options[name];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
var options_formatted = JSON.stringify(options, null, 4);
|
var options_formatted = JSON.stringify(options, null, 4);
|
||||||
options.validate = true;
|
options.validate = true;
|
||||||
|
|||||||
@@ -1018,3 +1018,91 @@ issue_5356: {
|
|||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5414_1: {
|
||||||
|
options = {
|
||||||
|
arrows: true,
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(() => {
|
||||||
|
(() => {
|
||||||
|
if (!console)
|
||||||
|
var arguments = 42;
|
||||||
|
while (console.log(arguments));
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(() => {
|
||||||
|
if (!console)
|
||||||
|
var arguments = 42;
|
||||||
|
while (console.log(arguments));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5414_2: {
|
||||||
|
options = {
|
||||||
|
arrows: true,
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(() => {
|
||||||
|
(() => {
|
||||||
|
if (!console)
|
||||||
|
var arguments = 42;
|
||||||
|
while (console.log(arguments));
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(() => {
|
||||||
|
if (!console)
|
||||||
|
var arguments = 42;
|
||||||
|
while (console.log(arguments));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5416: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = () => {
|
||||||
|
while ((() => {
|
||||||
|
console;
|
||||||
|
var a = function g(arguments) {
|
||||||
|
console.log(arguments);
|
||||||
|
}();
|
||||||
|
})());
|
||||||
|
};
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = () => {
|
||||||
|
{
|
||||||
|
arguments = void 0;
|
||||||
|
console;
|
||||||
|
console.log(arguments);
|
||||||
|
var arguments;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -939,6 +939,8 @@ keep_fnames: {
|
|||||||
class Foo {}
|
class Foo {}
|
||||||
console.log(Foo.name, class Bar {}.name);
|
console.log(Foo.name, class Bar {}.name);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "Foo Bar"
|
||||||
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_805_1: {
|
issue_805_1: {
|
||||||
@@ -2502,3 +2504,100 @@ issue_5352: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=12"
|
node_version: ">=12"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5387: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
class A extends a {}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
})({
|
||||||
|
f() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}.f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
class A extends a {}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
})({
|
||||||
|
f() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}.f);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5389: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(m, n) {
|
||||||
|
console.log(m, n);
|
||||||
|
}
|
||||||
|
var a = log;
|
||||||
|
class A {
|
||||||
|
[a = "FAIL"] = a = "PASS";
|
||||||
|
}
|
||||||
|
var b = new A();
|
||||||
|
log(a, b.FAIL);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(m, n) {
|
||||||
|
console.log(m, n);
|
||||||
|
}
|
||||||
|
var a = log;
|
||||||
|
class A {
|
||||||
|
[a = "FAIL"] = a = "PASS";
|
||||||
|
}
|
||||||
|
var b = new A();
|
||||||
|
log(a, b.FAIL);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
node_version: ">=12"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5436: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
class A {
|
||||||
|
p = a;
|
||||||
|
}
|
||||||
|
var b = "FAIL";
|
||||||
|
A == b && b();
|
||||||
|
return new A();
|
||||||
|
}
|
||||||
|
console.log(f("PASS").p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
class A {
|
||||||
|
p = a;
|
||||||
|
}
|
||||||
|
var b = "FAIL";
|
||||||
|
A == b && b();
|
||||||
|
return new A();
|
||||||
|
}
|
||||||
|
console.log(f("PASS").p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=12"
|
||||||
|
}
|
||||||
|
|||||||
@@ -9925,3 +9925,57 @@ issue_5309_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5394: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw A.p = (console.log("FAIL"), []), !1;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(typeof e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
throw !(A.p = (console.log("FAIL"), []));
|
||||||
|
} catch (e) {
|
||||||
|
console.log(typeof e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5396: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
merge_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b;
|
||||||
|
function f() {}
|
||||||
|
b = 0;
|
||||||
|
new function g(c) {
|
||||||
|
var d = a && g(e), e = ++d, i = [ 42 ];
|
||||||
|
for (var j in i)
|
||||||
|
console.log("PASS"),
|
||||||
|
i;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b;
|
||||||
|
function f() {}
|
||||||
|
b = 0;
|
||||||
|
(function g(c) {
|
||||||
|
a && g();
|
||||||
|
for (var j in [ 42 ])
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2209,3 +2209,33 @@ issue_5340_3: {
|
|||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5407: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
for (var i = 0; i < 2; i++)
|
||||||
|
(function(b = 4) {
|
||||||
|
console.log(b);
|
||||||
|
a = 2;
|
||||||
|
})(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
for (var i = 0; i < 2; i++)
|
||||||
|
(function(b = 4) {
|
||||||
|
console.log(b);
|
||||||
|
a = 2;
|
||||||
|
})(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"4",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3497,3 +3497,72 @@ issue_5370: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5405_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var [ a ] = [ {} ];
|
||||||
|
console.log(a === a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var [ a ] = [ {} ];
|
||||||
|
console.log(true ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5405_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var { p: a } = { p: [] };
|
||||||
|
console.log(a === a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var { p: a } = { p: [] };
|
||||||
|
console.log(true ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5423: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b;
|
||||||
|
function f({
|
||||||
|
[function() {
|
||||||
|
if (++a)
|
||||||
|
return 42;
|
||||||
|
}()]: c
|
||||||
|
}) {}
|
||||||
|
f(b = f);
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b;
|
||||||
|
function f({
|
||||||
|
[function() {
|
||||||
|
if (++a)
|
||||||
|
return 42;
|
||||||
|
}()]: c
|
||||||
|
}) {}
|
||||||
|
f(b = f);
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3349,3 +3349,30 @@ issue_5362_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5380: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_fnames: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function f(b) {
|
||||||
|
return function g() {
|
||||||
|
for (b in { PASS: 42 });
|
||||||
|
}(), b;
|
||||||
|
}("FAIL");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function f(b) {
|
||||||
|
return function g() {
|
||||||
|
for (b in { PASS: 42 });
|
||||||
|
}(), b;
|
||||||
|
}("FAIL");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3557,6 +3557,27 @@ functions_inner_var: {
|
|||||||
expect_stdout: "undefined undefined"
|
expect_stdout: "undefined undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions_keep_fnames: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
keep_fnames: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var FAIL = function PASS() {};
|
||||||
|
FAIL.p = 42;
|
||||||
|
console.log(FAIL.name, FAIL.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var FAIL = function PASS() {};
|
||||||
|
FAIL.p = 42;
|
||||||
|
console.log(FAIL.name, FAIL.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2437: {
|
issue_2437: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -8329,3 +8350,51 @@ issue_5376_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: Error("PASS")
|
expect_stdout: Error("PASS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5401: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: for (var a in function() {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
}(), a) do {
|
||||||
|
continue L;
|
||||||
|
} while (console.log("FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
L: for (var a in a) do {
|
||||||
|
continue L;
|
||||||
|
} while (console.log("FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5409: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
merge_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
(a = console) || FAIL(a);
|
||||||
|
(function(b) {
|
||||||
|
console.log(b && b);
|
||||||
|
while (!console);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(a = console) || FAIL(a);
|
||||||
|
a = void 0;
|
||||||
|
console.log(a && a);
|
||||||
|
while (!console);
|
||||||
|
return;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -224,8 +224,7 @@ issue_4489: {
|
|||||||
console.log(k);
|
console.log(k);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!(A = 0);
|
for (var k in !(A = 0));
|
||||||
for (var k in true);
|
|
||||||
console.log(k);
|
console.log(k);
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
@@ -407,9 +406,9 @@ issue_4893_2: {
|
|||||||
expect: {
|
expect: {
|
||||||
try{
|
try{
|
||||||
(function() {
|
(function() {
|
||||||
var b;
|
var a;
|
||||||
b = null;
|
a = null;
|
||||||
b.p += 42;
|
a.p += 42;
|
||||||
})();
|
})();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -530,3 +529,77 @@ issue_5378: {
|
|||||||
"undefined",
|
"undefined",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5411_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
b++;
|
||||||
|
b = a;
|
||||||
|
var b = b, c = c && c[b];
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b, c, a = "PASS";
|
||||||
|
b++;
|
||||||
|
b = a;
|
||||||
|
c = c && c[b];
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5411_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
b++;
|
||||||
|
b = a;
|
||||||
|
var b = b, c = c && c[b];
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b, c;
|
||||||
|
b++;
|
||||||
|
b = "PASS",
|
||||||
|
c = c && c[b];
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5411_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = console;
|
||||||
|
a++;
|
||||||
|
var a = A = a;
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = console;
|
||||||
|
a = A = ++a;
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1258,8 +1258,7 @@ issues_3267_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
var i = Object();
|
if (Object())
|
||||||
if (i)
|
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
}();
|
}();
|
||||||
|
|||||||
@@ -3702,3 +3702,33 @@ issue_5182: {
|
|||||||
]
|
]
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5420: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
do {
|
||||||
|
var a = "FAIL 1";
|
||||||
|
a && a.p;
|
||||||
|
a = "FAIL 2";
|
||||||
|
try {
|
||||||
|
continue;
|
||||||
|
} catch (e) {}
|
||||||
|
var b = "FAIL 3";
|
||||||
|
} while (console.log(b || "PASS"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
do {
|
||||||
|
var a = "FAIL 1";
|
||||||
|
a && a.p;
|
||||||
|
a = "FAIL 2";
|
||||||
|
try {
|
||||||
|
continue;
|
||||||
|
} catch (e) {}
|
||||||
|
var b = "FAIL 3";
|
||||||
|
} while (console.log(b || "PASS"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -6689,8 +6689,7 @@ issues_3267_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(x) {
|
!function(x) {
|
||||||
var i = Object();
|
if (Object())
|
||||||
if (i)
|
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
}();
|
}();
|
||||||
@@ -7862,3 +7861,38 @@ issue_5324: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5434: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
for (var i = 0; i < 2; i++) {
|
||||||
|
var b = "FAIL";
|
||||||
|
f && f();
|
||||||
|
a = b;
|
||||||
|
var f = function() {
|
||||||
|
b = "PASS";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
for (var i = 0; i < 2; i++) {
|
||||||
|
var b = "FAIL";
|
||||||
|
f && f();
|
||||||
|
a = b;
|
||||||
|
var f = function() {
|
||||||
|
b = "PASS";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1323,3 +1323,43 @@ issue_5370: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5391: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
objects: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = function f({
|
||||||
|
p: {},
|
||||||
|
...c
|
||||||
|
}) {
|
||||||
|
while (c.q);
|
||||||
|
}({
|
||||||
|
p: {
|
||||||
|
r: a++,
|
||||||
|
r: 0,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function({
|
||||||
|
p: {},
|
||||||
|
...c
|
||||||
|
}) {
|
||||||
|
while (c.q);
|
||||||
|
})({
|
||||||
|
p: 0,
|
||||||
|
});
|
||||||
|
console.log(NaN);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
node_version: ">=8.3.0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1166,3 +1166,31 @@ issue_5006: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5382: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
f() {
|
||||||
|
({ ...this });
|
||||||
|
},
|
||||||
|
get p() {
|
||||||
|
console.log("PASS");
|
||||||
|
},
|
||||||
|
}).f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
({
|
||||||
|
f() {
|
||||||
|
({ ...this });
|
||||||
|
},
|
||||||
|
get p() {
|
||||||
|
console.log("PASS");
|
||||||
|
},
|
||||||
|
}).f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8.3.0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1451,3 +1451,99 @@ issue_5177: {
|
|||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5385_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function*() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
return console.log("foo");
|
||||||
|
} finally {
|
||||||
|
return console.log("bar");
|
||||||
|
}
|
||||||
|
console.log("baz");
|
||||||
|
})();
|
||||||
|
})().next();
|
||||||
|
console.log("moo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(async function*() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
return console.log("foo");
|
||||||
|
} finally {
|
||||||
|
return console.log("bar");
|
||||||
|
}
|
||||||
|
console.log("baz");
|
||||||
|
})();
|
||||||
|
})().next();
|
||||||
|
console.log("moo");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"moo",
|
||||||
|
]
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5385_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function*() {
|
||||||
|
return function() {
|
||||||
|
try {
|
||||||
|
return console.log("foo");
|
||||||
|
} finally {
|
||||||
|
return console.log("bar");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
})().next();
|
||||||
|
console.log("moo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(async function*() {
|
||||||
|
return function() {
|
||||||
|
try {
|
||||||
|
return console.log("foo");
|
||||||
|
} finally {
|
||||||
|
return console.log("bar");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
})().next();
|
||||||
|
console.log("moo");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"moo",
|
||||||
|
]
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5425: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
ie: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
yields: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
var b = function* f() {}(a ? a = "PASS" : 42);
|
||||||
|
console.log(a, typeof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function* f() {})(a && (a = "PASS"));
|
||||||
|
console.log(a, typeof f);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ describe("test/reduce.js", function() {
|
|||||||
"// }",
|
"// }",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
});
|
});
|
||||||
it("Should transform `export default` correctly", function() {
|
it("Should transform `export default class` correctly", function() {
|
||||||
var result = reduce_test(read("test/input/reduce/export_default.js"), {
|
var result = reduce_test(read("test/input/reduce/export_default.js"), {
|
||||||
compress: false,
|
compress: false,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
@@ -448,4 +448,41 @@ describe("test/reduce.js", function() {
|
|||||||
"// }",
|
"// }",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
});
|
});
|
||||||
|
it("Should transform `export default function` correctly", function() {
|
||||||
|
var code = [
|
||||||
|
"for (var k in this)",
|
||||||
|
" console.log(k);",
|
||||||
|
"export default (function f() {});",
|
||||||
|
"console.log(k);",
|
||||||
|
].join("\n");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should transform `export default (42)` correctly", function() {
|
||||||
|
var code = [
|
||||||
|
"export default (42);",
|
||||||
|
"for (var k in this)",
|
||||||
|
" console.log(k);",
|
||||||
|
].join("\n");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {",
|
||||||
|
'// "compress": false,',
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -52,12 +52,17 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
|||||||
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
||||||
};
|
};
|
||||||
exports.patch_module_statements = function(code) {
|
exports.patch_module_statements = function(code) {
|
||||||
var count = 0, imports = [];
|
var count = 0, has_default = "", imports = [], strict_mode = "";
|
||||||
code = code.replace(/\bexport(?:\s*\{[^{}]*}\s*?(?:$|\n|;)|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) {
|
code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) {
|
||||||
|
strict_mode = match;
|
||||||
|
return "";
|
||||||
|
}).replace(/\bexport(?:\s*\{[^{}]*}\s*?(?:$|\n|;)|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) {
|
||||||
|
if (/^export\s+default/.test(match)) has_default = "var _uglify_export_default_;";
|
||||||
if (!header) return "";
|
if (!header) return "";
|
||||||
if (header.length == 1) return "0, " + header;
|
if (header.length == 1) return "0, " + header;
|
||||||
do {
|
var name = "_uglify_export_default_";
|
||||||
var name = "_export_default_" + ++count;
|
if (/^class\b/.test(header)) do {
|
||||||
|
name = "_uglify_export_default_" + ++count;
|
||||||
} while (code.indexOf(name) >= 0);
|
} while (code.indexOf(name) >= 0);
|
||||||
return header.slice(0, -1) + " " + name + header.slice(-1);
|
return header.slice(0, -1) + " " + name + header.slice(-1);
|
||||||
}).replace(/\bimport\.meta\b/g, function() {
|
}).replace(/\bimport\.meta\b/g, function() {
|
||||||
@@ -76,7 +81,7 @@ exports.patch_module_statements = function(code) {
|
|||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
imports.push("");
|
imports.push("");
|
||||||
return imports.join("\n") + code;
|
return strict_mode + has_default + imports.join("\n") + code;
|
||||||
};
|
};
|
||||||
|
|
||||||
function is_error(result) {
|
function is_error(result) {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
|
|
||||||
var SUPPORT = function(matrix) {
|
var SUPPORT = function(matrix) {
|
||||||
for (var name in matrix) {
|
for (var name in matrix) {
|
||||||
matrix[name] = typeof sandbox.run_code(matrix[name]) == "string";
|
matrix[name] = !sandbox.is_error(sandbox.run_code(matrix[name]));
|
||||||
}
|
}
|
||||||
return matrix;
|
return matrix;
|
||||||
}({
|
}({
|
||||||
@@ -1824,7 +1824,13 @@ function createClassLiteral(recurmax, stmtDepth, canThrow, name) {
|
|||||||
declared.push(internal);
|
declared.push(internal);
|
||||||
}
|
}
|
||||||
if (SUPPORT.class_field && rng(2)) {
|
if (SUPPORT.class_field && rng(2)) {
|
||||||
s += internal || createObjectKey(recurmax, stmtDepth, canThrow);
|
if (internal) {
|
||||||
|
s += internal;
|
||||||
|
} else if (fixed && bug_static_class_field) {
|
||||||
|
s += getDotKey();
|
||||||
|
} else {
|
||||||
|
s += createObjectKey(recurmax, stmtDepth, canThrow);
|
||||||
|
}
|
||||||
if (rng(5)) {
|
if (rng(5)) {
|
||||||
async = bug_async_class_await && fixed && 0;
|
async = bug_async_class_await && fixed && 0;
|
||||||
generator = false;
|
generator = false;
|
||||||
@@ -2110,7 +2116,7 @@ function try_beautify(code, toplevel, result, printfn, options) {
|
|||||||
} else if (options) {
|
} else if (options) {
|
||||||
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
|
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
|
||||||
var expected, actual;
|
var expected, actual;
|
||||||
if (typeof uglify_code != "string" || uglified.error) {
|
if (sandbox.is_error(uglify_code) || uglified.error) {
|
||||||
expected = uglify_code;
|
expected = uglify_code;
|
||||||
actual = uglified.error;
|
actual = uglified.error;
|
||||||
} else {
|
} else {
|
||||||
@@ -2147,7 +2153,7 @@ function log_suspects(minify_options, component) {
|
|||||||
m[component] = o;
|
m[component] = o;
|
||||||
m.validate = true;
|
m.validate = true;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (typeof uglify_code != "string") {
|
if (sandbox.is_error(uglify_code)) {
|
||||||
return !sandbox.same_stdout(uglify_code, result.error);
|
return !sandbox.same_stdout(uglify_code, result.error);
|
||||||
} else if (result.error) {
|
} else if (result.error) {
|
||||||
errorln("Error testing options." + component + "." + name);
|
errorln("Error testing options." + component + "." + name);
|
||||||
@@ -2175,7 +2181,7 @@ function log_suspects_global(options, toplevel) {
|
|||||||
m[component] = false;
|
m[component] = false;
|
||||||
m.validate = true;
|
m.validate = true;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (typeof uglify_code != "string") {
|
if (sandbox.is_error(uglify_code)) {
|
||||||
return !sandbox.same_stdout(uglify_code, result.error);
|
return !sandbox.same_stdout(uglify_code, result.error);
|
||||||
} else if (result.error) {
|
} else if (result.error) {
|
||||||
errorln("Error testing options." + component);
|
errorln("Error testing options." + component);
|
||||||
@@ -2204,7 +2210,16 @@ function log(options) {
|
|||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
errorln("//-------------------------------------------------------------");
|
errorln("//-------------------------------------------------------------");
|
||||||
if (typeof uglify_code == "string") {
|
if (sandbox.is_error(uglify_code)) {
|
||||||
|
errorln("// !!! uglify failed !!!");
|
||||||
|
errorln(uglify_code);
|
||||||
|
if (original_erred) {
|
||||||
|
errorln();
|
||||||
|
errorln();
|
||||||
|
errorln("original stacktrace:");
|
||||||
|
errorln(original_result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
errorln("// uglified code");
|
errorln("// uglified code");
|
||||||
try_beautify(uglify_code, toplevel, uglify_result, errorln);
|
try_beautify(uglify_code, toplevel, uglify_result, errorln);
|
||||||
errorln();
|
errorln();
|
||||||
@@ -2213,15 +2228,6 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
errorln("uglified result:");
|
errorln("uglified result:");
|
||||||
errorln(uglify_result);
|
errorln(uglify_result);
|
||||||
} else {
|
|
||||||
errorln("// !!! uglify failed !!!");
|
|
||||||
errorln(uglify_code);
|
|
||||||
if (errored) {
|
|
||||||
errorln();
|
|
||||||
errorln();
|
|
||||||
errorln("original stacktrace:");
|
|
||||||
errorln(original_result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
errorln("//-------------------------------------------------------------");
|
errorln("//-------------------------------------------------------------");
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -2426,22 +2432,23 @@ var beautify_options = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
var minify_options = require("./options.json");
|
var minify_options = require("./options.json");
|
||||||
if (typeof sandbox.run_code("A:if (0) B:; else B:;") != "string") {
|
if (sandbox.is_error(sandbox.run_code("A:if (0) B:; else B:;"))) {
|
||||||
minify_options.forEach(function(o) {
|
minify_options.forEach(function(o) {
|
||||||
if (!("mangle" in o)) o.mangle = {};
|
if (!("mangle" in o)) o.mangle = {};
|
||||||
if (o.mangle) o.mangle.v8 = true;
|
if (o.mangle) o.mangle.v8 = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var bug_async_arrow_rest = function() {};
|
var bug_async_arrow_rest = function() {};
|
||||||
if (SUPPORT.arrow && SUPPORT.async && SUPPORT.rest && typeof sandbox.run_code("async (a = f(...[], b)) => 0;") != "string") {
|
if (SUPPORT.arrow && SUPPORT.async && SUPPORT.rest && sandbox.is_error(sandbox.run_code("async (a = f(...[], b)) => 0;"))) {
|
||||||
bug_async_arrow_rest = function(ex) {
|
bug_async_arrow_rest = function(ex) {
|
||||||
return ex.name == "SyntaxError" && ex.message == "Rest parameter must be last formal parameter";
|
return ex.name == "SyntaxError" && ex.message == "Rest parameter must be last formal parameter";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var bug_async_class_await = SUPPORT.async && SUPPORT.class_field && typeof sandbox.run_code("var await; async function f() { class A { static p = await; } }") != "string";
|
var bug_async_class_await = SUPPORT.async && SUPPORT.class_field && sandbox.is_error(sandbox.run_code("var await; async function f() { class A { static p = await; } }"));
|
||||||
var bug_for_of_async = SUPPORT.for_await_of && typeof sandbox.run_code("var async; for (async of []);") != "string";
|
var bug_for_of_async = SUPPORT.for_await_of && sandbox.is_error(sandbox.run_code("var async; for (async of []);"));
|
||||||
var bug_for_of_var = SUPPORT.for_of && SUPPORT.let && typeof sandbox.run_code("try {} catch (e) { for (var e of []); }") != "string";
|
var bug_for_of_var = SUPPORT.for_of && SUPPORT.let && sandbox.is_error(sandbox.run_code("try {} catch (e) { for (var e of []); }"));
|
||||||
if (SUPPORT.destructuring && typeof sandbox.run_code("console.log([ 1 ], {} = 2);") != "string") {
|
var bug_static_class_field = SUPPORT.class_field && sandbox.is_error(sandbox.run_code("class A { static 42; static get 42() {} }"));
|
||||||
|
if (SUPPORT.destructuring && sandbox.is_error(sandbox.run_code("console.log([ 1 ], {} = 2);"))) {
|
||||||
beautify_options.output.v8 = true;
|
beautify_options.output.v8 = true;
|
||||||
minify_options.forEach(function(o) {
|
minify_options.forEach(function(o) {
|
||||||
if (!("output" in o)) o.output = {};
|
if (!("output" in o)) o.output = {};
|
||||||
@@ -2450,7 +2457,7 @@ if (SUPPORT.destructuring && typeof sandbox.run_code("console.log([ 1 ], {} = 2)
|
|||||||
}
|
}
|
||||||
beautify_options = JSON.stringify(beautify_options);
|
beautify_options = JSON.stringify(beautify_options);
|
||||||
minify_options = minify_options.map(JSON.stringify);
|
minify_options = minify_options.map(JSON.stringify);
|
||||||
var original_code, original_result, errored;
|
var original_code, original_result, original_erred;
|
||||||
var uglify_code, uglify_result, ok;
|
var uglify_code, uglify_result, ok;
|
||||||
for (var round = 1; round <= num_iterations; round++) {
|
for (var round = 1; round <= num_iterations; round++) {
|
||||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
@@ -2458,7 +2465,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
original_code = createTopLevelCode();
|
original_code = createTopLevelCode();
|
||||||
var orig_result = [ run_code(original_code), run_code(original_code, true) ];
|
var orig_result = [ run_code(original_code), run_code(original_code, true) ];
|
||||||
if (orig_result.some(function(result, toplevel) {
|
if (orig_result.some(function(result, toplevel) {
|
||||||
if (typeof result == "string") return;
|
if (!sandbox.is_error(result)) return;
|
||||||
println();
|
println();
|
||||||
println();
|
println();
|
||||||
println("//=============================================================");
|
println("//=============================================================");
|
||||||
@@ -2480,19 +2487,20 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
o.validate = true;
|
o.validate = true;
|
||||||
uglify_code = UglifyJS.minify(original_code, o);
|
uglify_code = UglifyJS.minify(original_code, o);
|
||||||
original_result = orig_result[toplevel ? 1 : 0];
|
original_result = orig_result[toplevel ? 1 : 0];
|
||||||
errored = typeof original_result != "string";
|
original_erred = sandbox.is_error(original_result);
|
||||||
if (!uglify_code.error) {
|
if (!uglify_code.error) {
|
||||||
uglify_code = uglify_code.code;
|
uglify_code = uglify_code.code;
|
||||||
uglify_result = run_code(uglify_code, toplevel);
|
uglify_result = run_code(uglify_code, toplevel);
|
||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
|
var uglify_erred = sandbox.is_error(uglify_result);
|
||||||
// ignore v8 parser bug
|
// ignore v8 parser bug
|
||||||
if (!ok && bug_async_arrow_rest(uglify_result)) ok = true;
|
if (!ok && uglify_erred && bug_async_arrow_rest(uglify_result)) ok = true;
|
||||||
// ignore runtime platform bugs
|
// ignore runtime platform bugs
|
||||||
if (!ok && uglify_result.message == "Script execution aborted.") ok = true;
|
if (!ok && uglify_erred && uglify_result.message == "Script execution aborted.") ok = true;
|
||||||
// handle difference caused by time-outs
|
// handle difference caused by time-outs
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
if (errored && is_error_timeout(original_result)) {
|
if (original_erred && is_error_timeout(original_result)) {
|
||||||
if (is_error_timeout(uglify_result)) {
|
if (uglify_erred && is_error_timeout(uglify_result)) {
|
||||||
// ignore difference in error message
|
// ignore difference in error message
|
||||||
ok = true;
|
ok = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -2500,21 +2508,23 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = run_code(original_code, toplevel, 10000);
|
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = run_code(original_code, toplevel, 10000);
|
||||||
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
|
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
|
||||||
}
|
}
|
||||||
} else if (is_error_timeout(uglify_result)) {
|
} else if (uglify_erred && is_error_timeout(uglify_result)) {
|
||||||
// ignore spurious time-outs
|
// ignore spurious time-outs
|
||||||
var waited_result = run_code(uglify_code, toplevel, 10000);
|
var waited_result = run_code(uglify_code, toplevel, 10000);
|
||||||
ok = sandbox.same_stdout(original_result, waited_result);
|
ok = sandbox.same_stdout(original_result, waited_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore declaration order of global variables
|
// ignore declaration order of global variables
|
||||||
if (!ok && !toplevel && uglify_result.name != "SyntaxError" && original_result.name != "SyntaxError") {
|
if (!ok && !toplevel) {
|
||||||
|
if (!(original_erred && original_result.name == "SyntaxError") && !(uglify_erred && uglify_result.name == "SyntaxError")) {
|
||||||
ok = sandbox.same_stdout(run_code(sort_globals(original_code)), run_code(sort_globals(uglify_code)));
|
ok = sandbox.same_stdout(run_code(sort_globals(original_code)), run_code(sort_globals(uglify_code)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ignore numerical imprecision caused by `unsafe_math`
|
// ignore numerical imprecision caused by `unsafe_math`
|
||||||
if (!ok && o.compress && o.compress.unsafe_math && typeof original_result == typeof uglify_result) {
|
if (!ok && o.compress && o.compress.unsafe_math) {
|
||||||
if (typeof original_result == "string") {
|
if (typeof original_result == "string" && typeof uglify_result == "string") {
|
||||||
ok = fuzzy_match(original_result, uglify_result);
|
ok = fuzzy_match(original_result, uglify_result);
|
||||||
} else if (sandbox.is_error(original_result)) {
|
} else if (original_erred && uglify_erred) {
|
||||||
ok = original_result.name == uglify_result.name && fuzzy_match(original_result.message, uglify_result.message);
|
ok = original_result.name == uglify_result.name && fuzzy_match(original_result.message, uglify_result.message);
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -2523,19 +2533,19 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore difference in error message caused by Temporal Dead Zone
|
// ignore difference in error message caused by Temporal Dead Zone
|
||||||
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
|
if (!ok && original_erred && uglify_erred && original_result.name == "ReferenceError" && uglify_result.name == "ReferenceError") ok = true;
|
||||||
// ignore difference due to implicit strict-mode in `class`
|
// ignore difference due to implicit strict-mode in `class`
|
||||||
if (!ok && /\bclass\b/.test(original_code)) {
|
if (!ok && /\bclass\b/.test(original_code)) {
|
||||||
var original_strict = run_code('"use strict";\n' + original_code, toplevel);
|
var original_strict = run_code('"use strict";\n' + original_code, toplevel);
|
||||||
if (/^(Syntax|Type)Error$/.test(uglify_result.name)) {
|
if (uglify_erred && /^(Syntax|Type)Error$/.test(uglify_result.name)) {
|
||||||
ok = typeof original_strict != "string";
|
ok = sandbox.is_error(original_strict);
|
||||||
} else {
|
} else {
|
||||||
ok = sandbox.same_stdout(original_strict, uglify_result);
|
ok = sandbox.same_stdout(original_strict, uglify_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore difference in error message caused by `import` symbol redeclaration
|
// ignore difference in error message caused by `import` symbol redeclaration
|
||||||
if (!ok && errored && /\bimport\b/.test(original_code)) {
|
if (!ok && original_erred && uglify_erred && /\bimport\b/.test(original_code)) {
|
||||||
if (is_error_redeclaration(uglify_result) && is_error_redeclaration(original_result)) ok = true;
|
if (is_error_redeclaration(original_result) && is_error_redeclaration(uglify_result)) ok = true;
|
||||||
}
|
}
|
||||||
// ignore difference due to `__proto__` assignment
|
// ignore difference due to `__proto__` assignment
|
||||||
if (!ok && /\b__proto__\b/.test(original_code)) {
|
if (!ok && /\b__proto__\b/.test(original_code)) {
|
||||||
@@ -2544,25 +2554,33 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
ok = sandbox.same_stdout(original_proto, uglify_proto);
|
ok = sandbox.same_stdout(original_proto, uglify_proto);
|
||||||
}
|
}
|
||||||
// ignore difference in error message caused by `in`
|
// ignore difference in error message caused by `in`
|
||||||
if (!ok && errored && is_error_in(uglify_result) && is_error_in(original_result)) ok = true;
|
if (!ok && original_erred && uglify_erred) {
|
||||||
|
if (is_error_in(original_result) && is_error_in(uglify_result)) ok = true;
|
||||||
|
}
|
||||||
// ignore difference in error message caused by spread syntax
|
// ignore difference in error message caused by spread syntax
|
||||||
if (!ok && errored && is_error_spread(uglify_result) && is_error_spread(original_result)) ok = true;
|
if (!ok && original_erred && uglify_erred) {
|
||||||
|
if (is_error_spread(original_result) && is_error_spread(uglify_result)) ok = true;
|
||||||
|
}
|
||||||
// ignore difference in depth of termination caused by infinite recursion
|
// ignore difference in depth of termination caused by infinite recursion
|
||||||
if (!ok && errored && is_error_recursion(original_result)) {
|
if (!ok && original_erred && is_error_recursion(original_result)) {
|
||||||
if (is_error_recursion(uglify_result) || typeof uglify_result == "string") ok = true;
|
if (!uglify_erred || is_error_recursion(uglify_result)) ok = true;
|
||||||
}
|
}
|
||||||
// ignore difference in error message caused by destructuring
|
// ignore difference in error message caused by destructuring
|
||||||
if (!ok && errored && is_error_destructuring(uglify_result) && is_error_destructuring(original_result)) {
|
if (!ok && original_erred && uglify_erred) {
|
||||||
ok = true;
|
if (is_error_destructuring(original_result) && is_error_destructuring(uglify_result)) ok = true;
|
||||||
}
|
}
|
||||||
// ignore difference in error message caused by call on class
|
// ignore difference in error message caused by call on class
|
||||||
if (!ok && errored && is_error_class_constructor(uglify_result) && is_error_class_constructor(original_result)) {
|
if (!ok && original_erred && uglify_erred) {
|
||||||
|
if (is_error_class_constructor(original_result) && is_error_class_constructor(uglify_result)) {
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ignore difference in error message caused by setting getter-only property
|
// ignore difference in error message caused by setting getter-only property
|
||||||
if (!ok && errored && is_error_getter_only_property(uglify_result) && is_error_getter_only_property(original_result)) {
|
if (!ok && original_erred && uglify_erred) {
|
||||||
|
if (is_error_getter_only_property(original_result) && is_error_getter_only_property(uglify_result)) {
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ignore errors above when caught by try-catch
|
// ignore errors above when caught by try-catch
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
var orig_skipped = patch_try_catch(original_code, toplevel);
|
var orig_skipped = patch_try_catch(original_code, toplevel);
|
||||||
@@ -2573,7 +2591,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uglify_code = uglify_code.error;
|
uglify_code = uglify_code.error;
|
||||||
ok = errored && uglify_code.name == original_result.name;
|
ok = original_erred && 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);
|
||||||
if (!ok && isFinite(num_iterations)) {
|
if (!ok && isFinite(num_iterations)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user