Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ad8e1081f | ||
|
|
815eff1f7c | ||
|
|
1e9b576ee9 | ||
|
|
3797458365 | ||
|
|
1858c2018c | ||
|
|
ec7f071272 | ||
|
|
f1eb03f2c0 | ||
|
|
0f4cfa877a | ||
|
|
1d5c2becbd | ||
|
|
22a09ea7c5 | ||
|
|
bad664c632 | ||
|
|
8a191c0a84 | ||
|
|
83fb8b4ca1 | ||
|
|
f38e31bd1e | ||
|
|
24e8b47977 | ||
|
|
95618793a4 | ||
|
|
2f3b460212 | ||
|
|
06e135e35f | ||
|
|
ebbf3d4a51 | ||
|
|
a270ba6b59 | ||
|
|
37f35e4ac2 | ||
|
|
50a578c1f6 | ||
|
|
85237b08d4 | ||
|
|
27b159e711 | ||
|
|
82b3eed5ef | ||
|
|
0f7aa41e33 |
1
.github/workflows/ufuzz.yml
vendored
1
.github/workflows/ufuzz.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
jobs:
|
||||
ufuzz:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
name: ${{ matrix.os }}
|
||||
|
||||
42
README.md
42
README.md
@@ -478,42 +478,42 @@ if (result.error) throw result.error;
|
||||
|
||||
## Minify options
|
||||
|
||||
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||
|
||||
- `parse` (default `{}`) — pass an object if you wish to specify some
|
||||
additional [parse options](#parse-options).
|
||||
|
||||
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
||||
Pass an object to specify custom [compress options](#compress-options).
|
||||
|
||||
- `ie8` (default `false`) -- set to `true` to support IE8.
|
||||
|
||||
- `keep_fnames` (default: `false`) -- pass `true` to prevent discarding or mangling
|
||||
of function names. Useful for code relying on `Function.prototype.name`.
|
||||
|
||||
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
||||
an object to specify [mangle options](#mangle-options) (see below).
|
||||
|
||||
- `mangle.properties` (default `false`) — a subcategory of the mangle option.
|
||||
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
||||
|
||||
- `output` (default `null`) — pass an object if you wish to specify
|
||||
additional [output options](#output-options). The defaults are optimized
|
||||
for best compression.
|
||||
|
||||
- `sourceMap` (default `false`) - pass an object if you wish to specify
|
||||
[source map options](#source-map-options).
|
||||
|
||||
- `toplevel` (default `false`) - set to `true` if you wish to enable top level
|
||||
variable and function name mangling and to drop unused variables and functions.
|
||||
|
||||
- `nameCache` (default `null`) - pass an empty object `{}` or a previously
|
||||
- `nameCache` (default `null`) -- pass an empty object `{}` or a previously
|
||||
used `nameCache` object if you wish to cache mangled variable and
|
||||
property names across multiple invocations of `minify()`. Note: this is
|
||||
a read/write property. `minify()` will read the name cache state of this
|
||||
object and update it during minification so that it may be
|
||||
reused or externally persisted by the user.
|
||||
|
||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
||||
- `output` (default `null`) — pass an object if you wish to specify
|
||||
additional [output options](#output-options). The defaults are optimized
|
||||
for best compression.
|
||||
|
||||
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
|
||||
of function names. Useful for code relying on `Function.prototype.name`.
|
||||
- `parse` (default `{}`) — pass an object if you wish to specify some
|
||||
additional [parse options](#parse-options).
|
||||
|
||||
- `sourceMap` (default `false`) -- pass an object if you wish to specify
|
||||
[source map options](#source-map-options).
|
||||
|
||||
- `toplevel` (default `false`) -- set to `true` if you wish to enable top level
|
||||
variable and function name mangling and to drop unused variables and functions.
|
||||
|
||||
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||
|
||||
## Minify options structure
|
||||
|
||||
@@ -682,6 +682,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
code generator would insert.
|
||||
|
||||
- `objects` (default: `true`) -- compact duplicate keys in object literals.
|
||||
|
||||
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
||||
In some cases more than one pass leads to further compressed code. Keep in
|
||||
mind more passes will take more time.
|
||||
|
||||
509
lib/compress.js
509
lib/compress.js
@@ -74,6 +74,7 @@ function Compressor(options, false_by_default) {
|
||||
keep_infinity : false,
|
||||
loops : !false_by_default,
|
||||
negate_iife : !false_by_default,
|
||||
objects : !false_by_default,
|
||||
passes : 1,
|
||||
properties : !false_by_default,
|
||||
pure_getters : !false_by_default && "strict",
|
||||
@@ -1041,7 +1042,8 @@ merge(Compressor.prototype, {
|
||||
|
||||
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
||||
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
||||
return !this.definition().undeclared
|
||||
return this.defined
|
||||
|| !this.definition().undeclared
|
||||
|| compressor.option("unsafe") && global_names[this.name];
|
||||
});
|
||||
|
||||
@@ -1128,6 +1130,8 @@ merge(Compressor.prototype, {
|
||||
if (!stop_if_hit && in_conditional(node, parent)) {
|
||||
stop_if_hit = parent;
|
||||
}
|
||||
// Skip transient nodes caused by single-use variable replacement
|
||||
if (node.single_use && parent instanceof AST_VarDef && parent.value === node) return node;
|
||||
// Replace variable with assignment when found
|
||||
var hit_rhs;
|
||||
if (can_replace
|
||||
@@ -1226,6 +1230,7 @@ merge(Compressor.prototype, {
|
||||
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs, compressor);
|
||||
var scan_rhs = foldable(get_rhs(candidate));
|
||||
if (!scan_lhs && !scan_rhs) continue;
|
||||
var modify_toplevel = false;
|
||||
// Locate symbols which may execute code outside of scanning range
|
||||
var lvalues = get_lvalues(candidate);
|
||||
var lhs_local = is_lhs_local(lhs);
|
||||
@@ -1578,7 +1583,16 @@ merge(Compressor.prototype, {
|
||||
if (candidate instanceof AST_VarDef) {
|
||||
lvalues[candidate.name.name] = lhs;
|
||||
}
|
||||
var scan_iife = scope instanceof AST_Toplevel;
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (scan_iife && node.TYPE == "Call") {
|
||||
var exp = node.expression;
|
||||
if (exp instanceof AST_PropAccess) return;
|
||||
if (exp instanceof AST_Function && !exp.contains_this()) return;
|
||||
modify_toplevel = true;
|
||||
scan_iife = false;
|
||||
return;
|
||||
}
|
||||
var value;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
value = node.fixed_value() || node;
|
||||
@@ -1665,6 +1679,7 @@ merge(Compressor.prototype, {
|
||||
var def = sym.definition();
|
||||
if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;
|
||||
if (def.scope !== scope) return true;
|
||||
if (modify_toplevel && compressor.exposed(def)) return true;
|
||||
return !all(def.references, function(ref) {
|
||||
return ref.scope.resolve() === scope;
|
||||
});
|
||||
@@ -1734,9 +1749,7 @@ merge(Compressor.prototype, {
|
||||
if (stat instanceof AST_If) {
|
||||
var ab = aborts(stat.body);
|
||||
if (can_merge_flow(ab)) {
|
||||
if (ab.label) {
|
||||
remove(ab.label.thedef.references, ab);
|
||||
}
|
||||
if (ab.label) remove(ab.label.thedef.references, ab);
|
||||
CHANGED = true;
|
||||
stat = stat.clone();
|
||||
stat.condition = stat.condition.negate(compressor);
|
||||
@@ -1764,23 +1777,34 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
var ab = aborts(stat.alternative);
|
||||
if (can_merge_flow(ab)) {
|
||||
if (ab.label) {
|
||||
remove(ab.label.thedef.references, ab);
|
||||
}
|
||||
var alt = aborts(stat.alternative);
|
||||
if (can_merge_flow(alt)) {
|
||||
if (alt.label) remove(alt.label.thedef.references, alt);
|
||||
CHANGED = true;
|
||||
stat = stat.clone();
|
||||
stat.body = make_node(AST_BlockStatement, stat.body, {
|
||||
body: as_statement_array(stat.body).concat(extract_functions())
|
||||
});
|
||||
var body = as_statement_array_with_return(stat.alternative, ab);
|
||||
var body = as_statement_array_with_return(stat.alternative, alt);
|
||||
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
||||
body: body
|
||||
});
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (compressor.option("typeofs")) {
|
||||
if (ab && !alt) {
|
||||
mark_locally_defined(stat.condition, null, make_node(AST_BlockStatement, self, {
|
||||
body: statements.slice(i + 1)
|
||||
}));
|
||||
}
|
||||
if (!ab && alt) {
|
||||
mark_locally_defined(stat.condition, make_node(AST_BlockStatement, self, {
|
||||
body: statements.slice(i + 1)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stat instanceof AST_If && stat.body instanceof AST_Return) {
|
||||
@@ -1925,9 +1949,7 @@ merge(Compressor.prototype, {
|
||||
&& loop_body(lct) === self
|
||||
|| stat instanceof AST_Continue
|
||||
&& loop_body(lct) === self) {
|
||||
if (stat.label) {
|
||||
remove(stat.label.thedef.references, stat);
|
||||
}
|
||||
if (stat.label) remove(stat.label.thedef.references, stat);
|
||||
} else {
|
||||
statements[n++] = stat;
|
||||
}
|
||||
@@ -2424,9 +2446,10 @@ merge(Compressor.prototype, {
|
||||
|| this.operator == "=" && this.right.is_number(compressor);
|
||||
});
|
||||
def(AST_Binary, function(compressor) {
|
||||
return binary[this.operator] || this.operator == "+"
|
||||
&& this.left.is_number(compressor)
|
||||
&& this.right.is_number(compressor);
|
||||
if (binary[this.operator]) return true;
|
||||
if (this.operator != "+") return false;
|
||||
return (this.left.is_boolean(compressor) || this.left.is_number(compressor))
|
||||
&& (this.right.is_boolean(compressor) || this.right.is_number(compressor));
|
||||
});
|
||||
var fn = makePredicate([
|
||||
"charCodeAt",
|
||||
@@ -2846,10 +2869,10 @@ merge(Compressor.prototype, {
|
||||
case "+": return +v;
|
||||
case "++":
|
||||
case "--":
|
||||
if (e instanceof AST_SymbolRef) {
|
||||
var refs = e.definition().references;
|
||||
if (refs[refs.length - 1] === e) return v;
|
||||
}
|
||||
if (!(e instanceof AST_SymbolRef)) return this;
|
||||
var refs = e.definition().references;
|
||||
if (refs[refs.length - 1] !== e) return this;
|
||||
return HOP(e, "_eval") ? +(this.operator[0] + 1) + +v : v;
|
||||
}
|
||||
return this;
|
||||
});
|
||||
@@ -2885,7 +2908,20 @@ merge(Compressor.prototype, {
|
||||
case ">=" : result = left >= right; break;
|
||||
default : return this;
|
||||
}
|
||||
return isNaN(result) && compressor.find_parent(AST_With) ? this : result;
|
||||
if (isNaN(result)) return compressor.find_parent(AST_With) ? this : result;
|
||||
if (compressor.option("unsafe_math")
|
||||
&& result
|
||||
&& typeof result == "number"
|
||||
&& (this.operator == "+" || this.operator == "-")) {
|
||||
var digits = Math.max(0, decimals(left), decimals(right));
|
||||
if (digits < 21) return +result.toFixed(digits);
|
||||
}
|
||||
return result;
|
||||
|
||||
function decimals(operand) {
|
||||
var match = /(\.[0-9]*)?(e.+)?$/.exec(+operand);
|
||||
return (match[1] || ".").length - 1 - (match[2] || "").slice(1);
|
||||
}
|
||||
});
|
||||
def(AST_Conditional, function(compressor, cached, depth) {
|
||||
var condition = this.condition._eval(compressor, cached, depth);
|
||||
@@ -2991,7 +3027,26 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
def(AST_Call, function(compressor, cached, depth) {
|
||||
var exp = this.expression;
|
||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||
if (exp instanceof AST_SymbolRef) {
|
||||
var fn = exp.fixed_value();
|
||||
if (!(fn instanceof AST_Lambda)) return this;
|
||||
if (fn.name && fn.name.definition().recursive_refs > 0) return this;
|
||||
if (fn.body.length != 1 || !fn.is_constant_expression()) return this;
|
||||
var stat = fn.body[0];
|
||||
if (!(stat instanceof AST_Return)) return this;
|
||||
var args = eval_args(this.args);
|
||||
if (!args) return this;
|
||||
fn.argnames.forEach(function(sym, i) {
|
||||
var value = args[i];
|
||||
sym.definition().references.forEach(function(node) {
|
||||
node._eval = function() {
|
||||
return value;
|
||||
};
|
||||
cached.push(node);
|
||||
});
|
||||
});
|
||||
return stat.value ? stat.value._eval(compressor, cached, depth) : undefined;
|
||||
} else if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||
var key = exp.property;
|
||||
if (key instanceof AST_Node) {
|
||||
key = key._eval(compressor, cached, depth);
|
||||
@@ -3009,13 +3064,8 @@ merge(Compressor.prototype, {
|
||||
var native_fn = native_fns[val.constructor.name];
|
||||
if (!native_fn || !native_fn[key]) return this;
|
||||
}
|
||||
var args = [];
|
||||
for (var i = 0; i < this.args.length; i++) {
|
||||
var arg = this.args[i];
|
||||
var value = arg._eval(compressor, cached, depth);
|
||||
if (arg === value) return this;
|
||||
args.push(value);
|
||||
}
|
||||
var args = eval_args(this.args);
|
||||
if (!args) return this;
|
||||
if (key == "replace" && typeof args[1] == "function") return this;
|
||||
try {
|
||||
return val[key].apply(val, args);
|
||||
@@ -3029,6 +3079,17 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
function eval_args(args) {
|
||||
var values = [];
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
var value = arg._eval(compressor, cached, depth);
|
||||
if (arg === value) return;
|
||||
values.push(value);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
});
|
||||
def(AST_New, return_this);
|
||||
})(function(node, func) {
|
||||
@@ -3378,19 +3439,20 @@ merge(Compressor.prototype, {
|
||||
def(AST_Lambda, function(scope) {
|
||||
var self = this;
|
||||
var result = true;
|
||||
var inner_scopes = [];
|
||||
var scopes = [];
|
||||
self.walk(new TreeWalker(function(node, descend) {
|
||||
if (!result) return true;
|
||||
if (node instanceof AST_Catch) {
|
||||
inner_scopes.push(node.argname.scope);
|
||||
scopes.push(node.argname.scope);
|
||||
descend();
|
||||
inner_scopes.pop();
|
||||
scopes.pop();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope && node !== self) {
|
||||
inner_scopes.push(node);
|
||||
if (node instanceof AST_Scope) {
|
||||
if (node === self) return;
|
||||
scopes.push(node);
|
||||
descend();
|
||||
inner_scopes.pop();
|
||||
scopes.pop();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
@@ -3398,17 +3460,17 @@ merge(Compressor.prototype, {
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
if (self.variables.has(node.name)) return true;
|
||||
var def = node.definition();
|
||||
if (!self.variables.has(def.name) && !member(def.scope, inner_scopes)) {
|
||||
if (scope) {
|
||||
var scope_def = scope.find_variable(node);
|
||||
if (def.undeclared ? !scope_def : scope_def === def) {
|
||||
result = "f";
|
||||
return true;
|
||||
}
|
||||
if (member(def.scope, scopes)) return true;
|
||||
if (scope) {
|
||||
var scope_def = scope.find_variable(node);
|
||||
if (def.undeclared ? !scope_def : scope_def === def) {
|
||||
result = "f";
|
||||
return true;
|
||||
}
|
||||
result = false;
|
||||
}
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
@@ -3737,9 +3799,7 @@ merge(Compressor.prototype, {
|
||||
def.value = null;
|
||||
head.push(def);
|
||||
} else {
|
||||
var value = def.value
|
||||
&& !def.value.single_use
|
||||
&& def.value.drop_side_effect_free(compressor);
|
||||
var value = def.value && def.value.drop_side_effect_free(compressor);
|
||||
if (value) {
|
||||
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||
side_effects.push(value);
|
||||
@@ -4213,7 +4273,7 @@ merge(Compressor.prototype, {
|
||||
def(AST_Binary, function(compressor, first_in_statement) {
|
||||
var right = this.right.drop_side_effect_free(compressor, first_in_statement);
|
||||
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
||||
if (lazy_op[this.operator]) {
|
||||
if (lazy_op[this.operator] && !(right instanceof AST_Function)) {
|
||||
var node = this;
|
||||
if (right !== node.right) {
|
||||
node = this.clone();
|
||||
@@ -4518,6 +4578,49 @@ merge(Compressor.prototype, {
|
||||
return if_break_in_loop(self, compressor);
|
||||
});
|
||||
|
||||
function mark_locally_defined(condition, consequent, alternative, operator) {
|
||||
if (!(condition instanceof AST_Binary)) return;
|
||||
if (!(condition.left instanceof AST_String)) {
|
||||
if (!operator) operator = condition.operator;
|
||||
if (condition.operator != operator) return;
|
||||
switch (operator) {
|
||||
case "&&":
|
||||
case "||":
|
||||
mark_locally_defined(condition.left, consequent, alternative, operator);
|
||||
mark_locally_defined(condition.right, consequent, alternative, operator);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!(condition.right instanceof AST_UnaryPrefix)) return;
|
||||
if (condition.right.operator != "typeof") return;
|
||||
var sym = condition.right.expression;
|
||||
if (!is_undeclared_ref(sym)) return;
|
||||
var body;
|
||||
var undef = condition.left.getValue() == "undefined";
|
||||
switch (condition.operator) {
|
||||
case "==":
|
||||
body = undef ? alternative : consequent;
|
||||
break;
|
||||
case "!=":
|
||||
body = undef ? consequent : alternative;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (!body) return;
|
||||
var def = sym.definition();
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Scope) {
|
||||
var parent = tw.parent();
|
||||
if (parent instanceof AST_Call && parent.expression === node) return;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef && node.definition() === def) node.defined = true;
|
||||
});
|
||||
body.walk(tw);
|
||||
}
|
||||
|
||||
OPT(AST_If, function(self, compressor) {
|
||||
if (is_empty(self.alternative)) self.alternative = null;
|
||||
|
||||
@@ -4569,11 +4672,6 @@ merge(Compressor.prototype, {
|
||||
self.body = self.alternative || make_node(AST_EmptyStatement, self);
|
||||
self.alternative = tmp;
|
||||
}
|
||||
if (is_empty(self.body) && is_empty(self.alternative)) {
|
||||
return make_node(AST_SimpleStatement, self.condition, {
|
||||
body: self.condition.clone()
|
||||
}).optimize(compressor);
|
||||
}
|
||||
if (self.body instanceof AST_SimpleStatement
|
||||
&& self.alternative instanceof AST_SimpleStatement) {
|
||||
return make_node(AST_SimpleStatement, self, {
|
||||
@@ -4607,15 +4705,22 @@ merge(Compressor.prototype, {
|
||||
}).transform(compressor)
|
||||
}).optimize(compressor);
|
||||
}
|
||||
if (self.body instanceof AST_EmptyStatement
|
||||
&& self.alternative instanceof AST_SimpleStatement) {
|
||||
return make_node(AST_SimpleStatement, self, {
|
||||
if (is_empty(self.body)) {
|
||||
if (is_empty(self.alternative)) return make_node(AST_SimpleStatement, self.condition, {
|
||||
body: self.condition.clone()
|
||||
}).optimize(compressor);
|
||||
if (self.alternative instanceof AST_SimpleStatement) return make_node(AST_SimpleStatement, self, {
|
||||
body: make_node(AST_Binary, self, {
|
||||
operator : "||",
|
||||
left : self.condition,
|
||||
right : self.alternative.body
|
||||
}).transform(compressor)
|
||||
}).optimize(compressor);
|
||||
self = make_node(AST_If, self, {
|
||||
condition: negated,
|
||||
body: self.alternative,
|
||||
alternative: null
|
||||
});
|
||||
}
|
||||
if (self.body instanceof AST_Exit
|
||||
&& self.alternative instanceof AST_Exit
|
||||
@@ -4659,6 +4764,7 @@ merge(Compressor.prototype, {
|
||||
body: [ self, body ]
|
||||
}).optimize(compressor);
|
||||
}
|
||||
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
|
||||
return self;
|
||||
});
|
||||
|
||||
@@ -5646,7 +5752,7 @@ merge(Compressor.prototype, {
|
||||
// "undefined" == typeof x => undefined === x
|
||||
else if (compressor.option("typeofs")
|
||||
&& self.left instanceof AST_String
|
||||
&& self.left.value == "undefined"
|
||||
&& self.left.getValue() == "undefined"
|
||||
&& self.right instanceof AST_UnaryPrefix
|
||||
&& self.right.operator == "typeof") {
|
||||
var expr = self.right.expression;
|
||||
@@ -5766,6 +5872,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (compressor.option("evaluate")) {
|
||||
var associative = true;
|
||||
switch (self.operator) {
|
||||
case "&&":
|
||||
var ll = fuzzy_eval(self.left);
|
||||
@@ -5834,9 +5941,6 @@ merge(Compressor.prototype, {
|
||||
}).optimize(compressor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
var associative = true;
|
||||
switch (self.operator) {
|
||||
case "+":
|
||||
// "foo" + ("bar" + x) => "foobar" + x
|
||||
if (self.left instanceof AST_Constant
|
||||
@@ -5916,13 +6020,39 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "-":
|
||||
// a - -b => a + b
|
||||
if (self.right instanceof AST_UnaryPrefix
|
||||
&& self.right.operator == "-"
|
||||
&& self.left.is_number(compressor)
|
||||
&& self.right.expression.is_number(compressor)) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: "+",
|
||||
left: self.left,
|
||||
right: self.right.expression
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "*":
|
||||
case "/":
|
||||
associative = compressor.option("unsafe_math");
|
||||
// +a - b => a - b
|
||||
// a - +b => a - b
|
||||
if (self.operator != "+") {
|
||||
if (self.left instanceof AST_UnaryPrefix && self.left.operator == "+") {
|
||||
self.left = self.left.expression;
|
||||
}
|
||||
if (self.right instanceof AST_UnaryPrefix && self.right.operator == "+") {
|
||||
self.right = self.right.expression;
|
||||
}
|
||||
}
|
||||
case "&":
|
||||
case "|":
|
||||
case "^":
|
||||
// a + +b => +b + a
|
||||
if (self.left.is_number(compressor)
|
||||
if (self.operator != "-"
|
||||
&& self.operator != "/"
|
||||
&& self.left.is_number(compressor)
|
||||
&& self.right.is_number(compressor)
|
||||
&& reversible()
|
||||
&& !(self.left instanceof AST_Binary
|
||||
@@ -5940,79 +6070,87 @@ merge(Compressor.prototype, {
|
||||
self = best_of(compressor, self, reversed);
|
||||
}
|
||||
}
|
||||
if (associative && self.is_number(compressor)) {
|
||||
// a + (b + c) => (a + b) + c
|
||||
if (self.right instanceof AST_Binary
|
||||
&& self.right.operator == self.operator) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
if (!associative || !self.is_number(compressor)) break;
|
||||
// a + (b + c) => (a + b) + c
|
||||
if (self.right instanceof AST_Binary
|
||||
&& self.right.operator != "%"
|
||||
&& PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]
|
||||
&& self.right.is_number(compressor)
|
||||
&& (self.operator != "+"
|
||||
|| self.right.left.is_boolean(compressor)
|
||||
|| self.right.left.is_number(compressor))) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: align(self.operator, self.right.operator),
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left,
|
||||
right: self.right.left,
|
||||
start: self.left.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
right: self.right.right
|
||||
});
|
||||
}
|
||||
// (n + 2) + 3 => 5 + n
|
||||
// (2 * n) * 3 => 6 + n
|
||||
if (self.right instanceof AST_Constant
|
||||
&& self.left instanceof AST_Binary
|
||||
&& self.left.operator == self.operator) {
|
||||
if (self.left.left instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.left,
|
||||
right: self.right,
|
||||
start: self.left.left.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.right
|
||||
});
|
||||
} else if (self.left.right instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.right,
|
||||
right: self.right,
|
||||
start: self.left.right.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.left
|
||||
});
|
||||
}
|
||||
}
|
||||
// (a | 1) | (2 | d) => (3 | a) | b
|
||||
if (self.left instanceof AST_Binary
|
||||
&& self.left.operator == self.operator
|
||||
&& self.left.right instanceof AST_Constant
|
||||
&& self.right instanceof AST_Binary
|
||||
&& self.right.operator == self.operator
|
||||
&& self.right.left instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.right,
|
||||
right: self.right.left,
|
||||
start: self.left.right.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
right: self.left.left
|
||||
}),
|
||||
right: self.right.right
|
||||
left: self.left,
|
||||
right: self.right.left,
|
||||
start: self.left.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
right: self.right.right
|
||||
});
|
||||
if (self.operator == "+"
|
||||
&& !self.right.is_boolean(compressor)
|
||||
&& !self.right.is_number(compressor)) {
|
||||
self.right = make_node(AST_UnaryPrefix, self.right, {
|
||||
operator: "+",
|
||||
expression: self.right
|
||||
});
|
||||
}
|
||||
}
|
||||
// (2 * n) * 3 => 6 * n
|
||||
// (n + 2) + 3 => n + 5
|
||||
if (self.right instanceof AST_Constant
|
||||
&& self.left instanceof AST_Binary
|
||||
&& self.left.operator != "%"
|
||||
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]
|
||||
&& self.left.is_number(compressor)) {
|
||||
if (self.left.left instanceof AST_Constant
|
||||
&& (self.operator != "+"
|
||||
|| self.left.left.is_boolean(compressor)
|
||||
|| self.left.left.is_number(compressor))) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.left.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.left,
|
||||
right: self.right,
|
||||
start: self.left.left.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.right
|
||||
});
|
||||
} else if (self.left.right instanceof AST_Constant) {
|
||||
var op = align(self.left.operator, self.operator);
|
||||
if (op != "+"
|
||||
|| self.left.right.is_boolean(compressor)
|
||||
|| self.left.right.is_number(compressor)) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.left.operator,
|
||||
left: self.left.left,
|
||||
right: make_node(AST_Binary, self.left, {
|
||||
operator: op,
|
||||
left: self.left.right,
|
||||
right: self.right,
|
||||
start: self.left.right.start,
|
||||
end: self.right.end
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (compressor.option("typeofs")) switch (self.operator) {
|
||||
case "&&":
|
||||
mark_locally_defined(self.left, self.right, null, "&&");
|
||||
break;
|
||||
case "||":
|
||||
mark_locally_defined(self.left, null, self.right, "||");
|
||||
break;
|
||||
}
|
||||
if (compressor.option("unsafe")) {
|
||||
var indexRight = is_indexFn(self.right);
|
||||
if (in_bool
|
||||
@@ -6075,6 +6213,17 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return self;
|
||||
|
||||
function align(ref, op) {
|
||||
switch (ref) {
|
||||
case "-":
|
||||
return op == "+" ? "-" : "+";
|
||||
case "/":
|
||||
return op == "*" ? "/" : "*";
|
||||
default:
|
||||
return op;
|
||||
}
|
||||
}
|
||||
|
||||
function fuzzy_eval(node) {
|
||||
if (node.truthy) return true;
|
||||
if (node.falsy) return false;
|
||||
@@ -6344,24 +6493,39 @@ merge(Compressor.prototype, {
|
||||
var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
|
||||
var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
|
||||
OPT(AST_Assign, function(self, compressor) {
|
||||
var def;
|
||||
if (compressor.option("dead_code")
|
||||
&& self.left instanceof AST_SymbolRef
|
||||
&& (def = self.left.definition()).scope === compressor.find_parent(AST_Lambda)) {
|
||||
if (self.left.is_immutable()) return strip_assignment();
|
||||
var level = 0, node, parent = self;
|
||||
do {
|
||||
node = parent;
|
||||
parent = compressor.parent(level++);
|
||||
if (parent instanceof AST_Exit) {
|
||||
if (in_try(level, parent)) break;
|
||||
if (is_reachable(def.scope, [ def ])) break;
|
||||
def.fixed = false;
|
||||
return strip_assignment();
|
||||
if (compressor.option("dead_code")) {
|
||||
if (self.left instanceof AST_PropAccess) {
|
||||
if (self.operator == "=") {
|
||||
var exp = self.left.expression;
|
||||
if (exp instanceof AST_Lambda
|
||||
|| !compressor.has_directive("use strict")
|
||||
&& exp instanceof AST_Constant
|
||||
&& !exp.may_throw_on_access(compressor)) {
|
||||
return self.left instanceof AST_Dot ? self.right : make_sequence(self, [
|
||||
self.left.property,
|
||||
self.right
|
||||
]).optimize(compressor);
|
||||
}
|
||||
}
|
||||
} while (parent instanceof AST_Binary && parent.right === node
|
||||
|| parent instanceof AST_Sequence && parent.tail_node() === node
|
||||
|| parent instanceof AST_UnaryPrefix);
|
||||
} else if (self.left instanceof AST_SymbolRef) {
|
||||
var def = self.left.definition();
|
||||
if (def.scope === compressor.find_parent(AST_Lambda)) {
|
||||
if (self.left.is_immutable()) return strip_assignment();
|
||||
var level = 0, node, parent = self;
|
||||
do {
|
||||
node = parent;
|
||||
parent = compressor.parent(level++);
|
||||
if (parent instanceof AST_Exit) {
|
||||
if (in_try(level, parent)) break;
|
||||
if (is_reachable(def.scope, [ def ])) break;
|
||||
def.fixed = false;
|
||||
return strip_assignment();
|
||||
}
|
||||
} while (parent instanceof AST_Binary && parent.right === node
|
||||
|| parent instanceof AST_Sequence && parent.tail_node() === node
|
||||
|| parent instanceof AST_UnaryPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
self = self.lift_sequences(compressor);
|
||||
if (!compressor.option("assignments")) return self;
|
||||
@@ -6549,8 +6713,8 @@ merge(Compressor.prototype, {
|
||||
}).optimize(compressor);
|
||||
}
|
||||
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
||||
if (is_true(self.consequent)) {
|
||||
if (is_false(self.alternative)) {
|
||||
if (is_true(consequent)) {
|
||||
if (is_false(alternative)) {
|
||||
// c ? true : false ---> !!c
|
||||
return booleanize(condition);
|
||||
}
|
||||
@@ -6558,11 +6722,11 @@ merge(Compressor.prototype, {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: booleanize(condition),
|
||||
right: self.alternative
|
||||
right: alternative
|
||||
});
|
||||
}
|
||||
if (is_false(self.consequent)) {
|
||||
if (is_true(self.alternative)) {
|
||||
if (is_false(consequent)) {
|
||||
if (is_true(alternative)) {
|
||||
// c ? false : true ---> !c
|
||||
return booleanize(condition.negate(compressor));
|
||||
}
|
||||
@@ -6570,26 +6734,26 @@ merge(Compressor.prototype, {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: booleanize(condition.negate(compressor)),
|
||||
right: self.alternative
|
||||
right: alternative
|
||||
});
|
||||
}
|
||||
if (is_true(self.alternative)) {
|
||||
if (is_true(alternative)) {
|
||||
// c ? x : true ---> !c || x
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: booleanize(condition.negate(compressor)),
|
||||
right: self.consequent
|
||||
right: consequent
|
||||
});
|
||||
}
|
||||
if (is_false(self.alternative)) {
|
||||
if (is_false(alternative)) {
|
||||
// c ? x : false ---> !!c && x
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: booleanize(condition),
|
||||
right: self.consequent
|
||||
right: consequent
|
||||
});
|
||||
}
|
||||
|
||||
if (compressor.option("typeofs")) mark_locally_defined(condition, consequent, alternative);
|
||||
return self;
|
||||
|
||||
function booleanize(node) {
|
||||
@@ -6928,6 +7092,41 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
});
|
||||
|
||||
OPT(AST_Object, function(self, compressor) {
|
||||
if (!compressor.option("objects") || compressor.has_directive("use strict")) return self;
|
||||
var props = self.properties;
|
||||
var keys = new Dictionary();
|
||||
var values = [];
|
||||
self.properties.forEach(function(prop) {
|
||||
if (typeof prop.key != "string") {
|
||||
flush();
|
||||
values.push(prop);
|
||||
return;
|
||||
}
|
||||
if (prop.value.has_side_effects(compressor)) {
|
||||
flush();
|
||||
}
|
||||
keys.add(prop.key, prop.value);
|
||||
});
|
||||
flush();
|
||||
if (self.properties.length != values.length) {
|
||||
return make_node(AST_Object, self, {
|
||||
properties: values
|
||||
});
|
||||
}
|
||||
return self;
|
||||
|
||||
function flush() {
|
||||
keys.each(function(expressions, key) {
|
||||
values.push(make_node(AST_ObjectKeyVal, self, {
|
||||
key: key,
|
||||
value: make_sequence(self, expressions)
|
||||
}));
|
||||
});
|
||||
keys = new Dictionary();
|
||||
}
|
||||
});
|
||||
|
||||
OPT(AST_Return, function(self, compressor) {
|
||||
if (self.value && is_undefined(self.value, compressor)) {
|
||||
self.value = null;
|
||||
|
||||
@@ -1253,6 +1253,7 @@ function parse($TEXT, options) {
|
||||
var ex = expression(true);
|
||||
var len = start.comments_before.length;
|
||||
[].unshift.apply(ex.start.comments_before, start.comments_before);
|
||||
start.comments_before.length = 0;
|
||||
start.comments_before = ex.start.comments_before;
|
||||
start.comments_before_length = len;
|
||||
if (len == 0 && start.comments_before.length > 0) {
|
||||
@@ -1268,6 +1269,7 @@ function parse($TEXT, options) {
|
||||
var end = prev();
|
||||
end.comments_before = ex.end.comments_before;
|
||||
[].push.apply(ex.end.comments_after, end.comments_after);
|
||||
end.comments_after.length = 0;
|
||||
end.comments_after = ex.end.comments_after;
|
||||
ex.end = end;
|
||||
if (ex instanceof AST_Call) mark_pure(ex);
|
||||
|
||||
@@ -214,7 +214,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
function redefine(node, scope) {
|
||||
var name = node.name;
|
||||
var old_def = node.thedef;
|
||||
var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
||||
var new_def = scope.find_variable(name);
|
||||
if (new_def) {
|
||||
var redef;
|
||||
while (redef = new_def.redefined()) new_def = redef;
|
||||
} else {
|
||||
new_def = self.globals.get(name) || scope.def_variable(node);
|
||||
}
|
||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||
node.thedef = new_def;
|
||||
node.reference(options);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.6.4",
|
||||
"version": "3.6.6",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -94,6 +94,3 @@ urls.forEach(function(url) {
|
||||
});
|
||||
});
|
||||
});
|
||||
setInterval(function() {
|
||||
process.stderr.write("\0");
|
||||
}, 5 * 60 * 1000).unref();
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
require("../tools/exit");
|
||||
|
||||
var assert = require("assert");
|
||||
var child_process = require("child_process");
|
||||
var fs = require("fs");
|
||||
|
||||
@@ -96,7 +96,7 @@ asm_mixed: {
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
|
||||
return start |= 0, end |= 0, +exp(logSum(start, end) / (end - start | 0));
|
||||
}
|
||||
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||
return { geometricMean: geometricMean };
|
||||
|
||||
@@ -6258,3 +6258,93 @@ cond_sequence_return: {
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
issue_3520: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
var b = function(c) {
|
||||
for (var i = 2; --i >= 0;) {
|
||||
(function f() {
|
||||
c = 0;
|
||||
var i = void 0;
|
||||
var f = f && f[i];
|
||||
})();
|
||||
a += b;
|
||||
c && b++;
|
||||
}
|
||||
}(b = 1);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
var b = function(c) {
|
||||
for (var i = 2; --i >= 0;) {
|
||||
(function() {
|
||||
c = 0;
|
||||
var f = f && f[void 0];
|
||||
})();
|
||||
a += b;
|
||||
c && b++;
|
||||
}
|
||||
}(b = 1);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
issue_3526_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var b = function() {
|
||||
this.a = "FAIL";
|
||||
}();
|
||||
var a = "PASS";
|
||||
var b;
|
||||
var c = b;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var b = function() {
|
||||
this.a = "FAIL";
|
||||
}();
|
||||
var a = "PASS";
|
||||
var b;
|
||||
var c = b;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3526_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
this.a = "FAIL";
|
||||
}
|
||||
var b = f();
|
||||
var a = "PASS";
|
||||
var b;
|
||||
var c = b;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
this.a = "FAIL";
|
||||
}
|
||||
var b = f();
|
||||
var a = "PASS";
|
||||
var b;
|
||||
var c = b;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -161,6 +161,24 @@ ifs_6: {
|
||||
}
|
||||
}
|
||||
|
||||
ifs_7: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
if (A); else;
|
||||
if (A) while (B); else;
|
||||
if (A); else while (C);
|
||||
if (A) while (B); else while (C);
|
||||
}
|
||||
expect: {
|
||||
A;
|
||||
if (A) while (B);
|
||||
if (!A) while (C);
|
||||
if (A) while (B); else while (C);
|
||||
}
|
||||
}
|
||||
|
||||
cond_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
|
||||
@@ -1013,3 +1013,54 @@ issue_3406: {
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
function_assign: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = "PASS";
|
||||
function h(c) {
|
||||
return c;
|
||||
}
|
||||
h.p = function(b) {
|
||||
return b;
|
||||
}.p = a;
|
||||
return h;
|
||||
}().p);
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = "PASS";
|
||||
function h(c) {
|
||||
return c;
|
||||
}
|
||||
h.p = a;
|
||||
return h;
|
||||
}().p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3552: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
(function() {
|
||||
(1..p += 42) && (a = "FAIL");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
(function() {
|
||||
(1..p += 42) && (a = "FAIL");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -2121,7 +2121,8 @@ issue_3515_1: {
|
||||
expect: {
|
||||
var c = 0;
|
||||
(function() {
|
||||
for (var key20 in !(this[c++] = 0));
|
||||
this[c++] = 0;
|
||||
for (var key20 in !0);
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
@@ -2186,3 +2187,37 @@ issue_3515_3: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
function_assign: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = "PASS";
|
||||
function g(b) {
|
||||
return b;
|
||||
}
|
||||
g.p = a;
|
||||
function h(c) {
|
||||
return c;
|
||||
}
|
||||
h.p = a;
|
||||
return h;
|
||||
}().p);
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = "PASS";
|
||||
function h(c) {
|
||||
return c;
|
||||
}
|
||||
h.p = a;
|
||||
return h;
|
||||
}().p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1757,3 +1757,105 @@ issue_3387_2: {
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
simple_function_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
console.log(sum(1, 2) * sum(3, 4));
|
||||
}
|
||||
expect: {
|
||||
console.log(21);
|
||||
}
|
||||
expect_stdout: "21"
|
||||
}
|
||||
|
||||
simple_function_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var sum = function(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
console.log(sum(1, 2) * sum(3, 4));
|
||||
}
|
||||
expect: {
|
||||
console.log(21);
|
||||
}
|
||||
expect_stdout: "21"
|
||||
}
|
||||
|
||||
recursive_function_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function factorial(a) {
|
||||
return a > 0 ? a * factorial(a - 1) : 1;
|
||||
}
|
||||
console.log(factorial(5));
|
||||
}
|
||||
expect: {
|
||||
console.log(function factorial(a) {
|
||||
return a > 0 ? a * factorial(a - 1) : 1;
|
||||
}(5));
|
||||
}
|
||||
expect_stdout: "120"
|
||||
}
|
||||
|
||||
recursive_function_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var factorial = function(a) {
|
||||
return a > 0 ? a * factorial(a - 1) : 1;
|
||||
}
|
||||
console.log(factorial(5));
|
||||
}
|
||||
expect: {
|
||||
var factorial = function(a) {
|
||||
return a > 0 ? a * factorial(a - 1) : 1;
|
||||
}
|
||||
console.log(factorial(5));
|
||||
}
|
||||
expect_stdout: "120"
|
||||
}
|
||||
|
||||
issue_3558: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return 1 + --a;
|
||||
}
|
||||
console.log(f(true), f(false));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return 1 + --a;
|
||||
}
|
||||
console.log(1, 0);
|
||||
}
|
||||
expect_stdout: "1 0"
|
||||
}
|
||||
|
||||
@@ -1959,3 +1959,405 @@ issue_3493_ie8: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
(function() {
|
||||
(function t() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function e() {
|
||||
try {} catch (t) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, a, r, f, i, u, h, l, v, y, A;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (n) {
|
||||
(function() {
|
||||
(function n() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function c() {
|
||||
try {} catch (c) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_ie8: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
(function() {
|
||||
(function t() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function e() {
|
||||
try {} catch (t) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var c, t, n, o, a, r, f, i, u, h, e, l, v, y;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
(function() {
|
||||
(function t() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function e() {
|
||||
try {} catch (t) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_toplevel: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
(function() {
|
||||
(function t() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function e() {
|
||||
try {} catch (t) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0, n, t = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (c) {
|
||||
(function() {
|
||||
(function c() {
|
||||
t = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function c() {
|
||||
try {} catch (c) {}
|
||||
})();
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_ie8_toplevel: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
(function() {
|
||||
(function t() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function e() {
|
||||
try {} catch (t) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0, n, t = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
(function() {
|
||||
(function o() {
|
||||
t = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function r() {
|
||||
try {} catch (o) {}
|
||||
})();
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_rename: {
|
||||
rename = true
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
(function() {
|
||||
(function e() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function d() {
|
||||
try {
|
||||
} catch (e) {
|
||||
}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, a, r, f, i, u, h, l, v, y, A;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (n) {
|
||||
(function() {
|
||||
(function n() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function c() {
|
||||
try {} catch (c) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_rename_ie8: {
|
||||
rename = true
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
(function() {
|
||||
(function e() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function d() {
|
||||
try {
|
||||
} catch (e) {
|
||||
}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, a, r, f, i, u, e, h, l, v, y;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
(function() {
|
||||
(function n() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function d() {
|
||||
try {} catch (e) {}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_rename_toplevel: {
|
||||
rename = true
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
(function() {
|
||||
(function e() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function d() {
|
||||
try {
|
||||
} catch (e) {
|
||||
}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0, n, t = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (c) {
|
||||
(function() {
|
||||
(function c() {
|
||||
t = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function c() {
|
||||
try {} catch (c) {}
|
||||
})();
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3523_rename_ie8_toplevel: {
|
||||
rename = true
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
(function() {
|
||||
(function e() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function d() {
|
||||
try {
|
||||
} catch (e) {
|
||||
}
|
||||
})();
|
||||
}
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0, n, t = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
(function() {
|
||||
(function o() {
|
||||
t = "PASS";
|
||||
})();
|
||||
})();
|
||||
(function r() {
|
||||
try {} catch (o) {}
|
||||
})();
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3542: {
|
||||
options = {
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
var b = a++;
|
||||
var c = b && function a() {} || b;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
a++;
|
||||
(function a() {});
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
@@ -51,17 +51,20 @@ comparisons: {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y = "0x30";
|
||||
console.log(
|
||||
~x === 42,
|
||||
x % n === 42
|
||||
x % y === 42
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y = "0x30";
|
||||
console.log(
|
||||
42 == ~x,
|
||||
x % n == 42
|
||||
x % y == 42
|
||||
);
|
||||
}
|
||||
expect_stdout: "false true"
|
||||
}
|
||||
|
||||
evaluate_1: {
|
||||
@@ -103,7 +106,7 @@ evaluate_1: {
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_2: {
|
||||
evaluate_1_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
@@ -118,6 +121,8 @@ evaluate_2: {
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3)
|
||||
);
|
||||
@@ -126,18 +131,138 @@ evaluate_2: {
|
||||
console.log(
|
||||
x + 1 + 2,
|
||||
2 * x,
|
||||
3 + +x,
|
||||
+x + 3,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
6 + x--,
|
||||
6 + x*y,
|
||||
x*y + 6,
|
||||
1 + (2 + x + 3),
|
||||
6 + ~x,
|
||||
5 - y + ~x,
|
||||
0 & x,
|
||||
6 + (x |= 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
x * 1 * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
1 | x | 2 | 3,
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
1 * x * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
1 + x-- + 2 + 3,
|
||||
x*y + 2 + 1 + 3,
|
||||
1 + (2 + x + 3),
|
||||
2 + ~x + 3 + 1,
|
||||
2 + ~x + 3 - y,
|
||||
0 & x,
|
||||
2 + (x |= 0) + 3 + 1,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 4212",
|
||||
"number 84",
|
||||
"number 45",
|
||||
"string 14223",
|
||||
"number 43",
|
||||
"number 48",
|
||||
"number 6",
|
||||
"number 47",
|
||||
"number -36",
|
||||
"number -37",
|
||||
"number 0",
|
||||
"number 47",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_2_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
x * 1 * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
1 | x | 2 | 3,
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
2 * x,
|
||||
+x + 3,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
6 + x--,
|
||||
x*y + 6,
|
||||
1 + (2 + x + 3),
|
||||
6 + ~x,
|
||||
5 + ~x - y,
|
||||
0 & x,
|
||||
6 + (x |= 0),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 4212",
|
||||
"number 84",
|
||||
"number 45",
|
||||
"string 14223",
|
||||
"number 43",
|
||||
"number 48",
|
||||
"number 6",
|
||||
"number 47",
|
||||
"number -36",
|
||||
"number -37",
|
||||
"number 0",
|
||||
"number 47",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -148,7 +273,7 @@ evaluate_3: {
|
||||
console.log(1 + Number(x) + 2);
|
||||
}
|
||||
expect: {
|
||||
console.log(3 + +x);
|
||||
console.log(+x + 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +307,352 @@ evaluate_4: {
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_5: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
+a - 2 + 3,
|
||||
+a - 2 - 3,
|
||||
2 + +a + 3,
|
||||
2 + +a - 3,
|
||||
2 - +a + 3,
|
||||
2 - +a - 3,
|
||||
2 + 3 + +a,
|
||||
2 + 3 - +a,
|
||||
2 - 3 + +a,
|
||||
2 - 3 - +a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
a - 2 + 3,
|
||||
a - 2 - 3,
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
2 - a + 3,
|
||||
2 - a - 3,
|
||||
+a + 5,
|
||||
5 - a,
|
||||
+a - 1,
|
||||
-1 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 6",
|
||||
"number 0",
|
||||
"number 2",
|
||||
"number -4",
|
||||
"number 6",
|
||||
"number 0",
|
||||
"number 4",
|
||||
"number -2",
|
||||
"number 6",
|
||||
"number 4",
|
||||
"number 0",
|
||||
"number -2",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_5_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
+a - 2 + 3,
|
||||
+a - 2 - 3,
|
||||
2 + +a + 3,
|
||||
2 + +a - 3,
|
||||
2 - +a + 3,
|
||||
2 - +a - 3,
|
||||
2 + 3 + +a,
|
||||
2 + 3 - +a,
|
||||
2 - 3 + +a,
|
||||
2 - 3 - +a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 5,
|
||||
+a + -1,
|
||||
a - -1,
|
||||
a - 5,
|
||||
+a + 5,
|
||||
+a + -1,
|
||||
5 - a,
|
||||
-1 - a,
|
||||
+a + 5,
|
||||
5 - a,
|
||||
+a - 1,
|
||||
-1 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 6",
|
||||
"number 0",
|
||||
"number 2",
|
||||
"number -4",
|
||||
"number 6",
|
||||
"number 0",
|
||||
"number 4",
|
||||
"number -2",
|
||||
"number 6",
|
||||
"number 4",
|
||||
"number 0",
|
||||
"number -2",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_6: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
[
|
||||
-a + 2 + 3,
|
||||
-a + 2 - 3,
|
||||
-a - 2 + 3,
|
||||
-a - 2 - 3,
|
||||
2 + -a + 3,
|
||||
2 + -a - 3,
|
||||
2 - -a + 3,
|
||||
2 - -a - 3,
|
||||
2 + 3 + -a,
|
||||
2 + 3 - -a,
|
||||
2 - 3 + -a,
|
||||
2 - 3 - -a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
[
|
||||
2 - a + 3,
|
||||
2 - a - 3,
|
||||
-a - 2 + 3,
|
||||
-a - 2 - 3,
|
||||
2 - a + 3,
|
||||
2 - a - 3,
|
||||
2 - -a + 3,
|
||||
2 - -a - 3,
|
||||
5 - a,
|
||||
5 - -a,
|
||||
-1 - a,
|
||||
-1 - -a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 4",
|
||||
"number -2",
|
||||
"number 0",
|
||||
"number -6",
|
||||
"number 4",
|
||||
"number -2",
|
||||
"number 6",
|
||||
"number 0",
|
||||
"number 4",
|
||||
"number 6",
|
||||
"number -2",
|
||||
"number 0",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_6_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
[
|
||||
-a + 2 + 3,
|
||||
-a + 2 - 3,
|
||||
-a - 2 + 3,
|
||||
-a - 2 - 3,
|
||||
2 + -a + 3,
|
||||
2 + -a - 3,
|
||||
2 - -a + 3,
|
||||
2 - -a - 3,
|
||||
2 + 3 + -a,
|
||||
2 + 3 - -a,
|
||||
2 - 3 + -a,
|
||||
2 - 3 - -a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
[
|
||||
5 - a,
|
||||
-1 - a,
|
||||
-a - -1,
|
||||
-a - 5,
|
||||
5 - a,
|
||||
-1 - a,
|
||||
5 - -a,
|
||||
-1 - -a,
|
||||
5 - a,
|
||||
5 - -a,
|
||||
-1 - a,
|
||||
-1 - -a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 4",
|
||||
"number -2",
|
||||
"number 0",
|
||||
"number -6",
|
||||
"number 4",
|
||||
"number -2",
|
||||
"number 6",
|
||||
"number 0",
|
||||
"number 4",
|
||||
"number 6",
|
||||
"number -2",
|
||||
"number 0",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_7: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
+x - 2 + (3 + !y),
|
||||
+x - 2 + (3 - !y),
|
||||
+x - 2 - (3 + !y),
|
||||
+x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
x - 2 + (3 + !y),
|
||||
x - 2 + (3 - !y),
|
||||
x - 2 - (3 + !y),
|
||||
x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 48",
|
||||
"number 46",
|
||||
"number 40",
|
||||
"number 42",
|
||||
"number 44",
|
||||
"number 42",
|
||||
"number 36",
|
||||
"number 38",
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_7_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
+x - 2 + (3 + !y),
|
||||
+x - 2 + (3 - !y),
|
||||
+x - 2 - (3 + !y),
|
||||
+x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 5 + !y,
|
||||
+x + 5 - !y,
|
||||
+x + -1 - !y,
|
||||
+x + -1 + !y,
|
||||
x - -1 + !y,
|
||||
x - -1 - !y,
|
||||
x - 5 - !y,
|
||||
x - 5 + !y,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 48",
|
||||
"number 46",
|
||||
"number 40",
|
||||
"number 42",
|
||||
"number 44",
|
||||
"number 42",
|
||||
"number 36",
|
||||
"number 38",
|
||||
]
|
||||
}
|
||||
|
||||
NaN_redefined: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var NaN;
|
||||
console.log(1 / (0 / 0));
|
||||
}
|
||||
expect: {
|
||||
var NaN;
|
||||
console.log(0 / 0);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_1710: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -230,3 +701,219 @@ unary_binary_parenthesis: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_3531_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
console.log(typeof (a + 1 - .1 - .1 - .1));
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
console.log(typeof (a + 1 - .3));
|
||||
}
|
||||
expect_stdout: "number"
|
||||
}
|
||||
|
||||
issue_3531_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
console.log(1 - (2 - {}));
|
||||
}
|
||||
expect: {
|
||||
console.log(-1 + +{});
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_3531_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "3";
|
||||
console.log(1 - (2 + a));
|
||||
}
|
||||
expect: {
|
||||
var a = "3";
|
||||
console.log(1 - (2 + a));
|
||||
}
|
||||
expect_stdout: "-22"
|
||||
}
|
||||
|
||||
issue_3536: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = 100, b = 10;
|
||||
var c = --a + ("23" - (b++, 1));
|
||||
console.log(typeof c, a, b, c);
|
||||
}
|
||||
expect: {
|
||||
var a = 100, b = 10;
|
||||
var c = --a + ("23" - (b++, 1));
|
||||
console.log(typeof c, a, b, c);
|
||||
}
|
||||
expect_stdout: "number 99 11 121"
|
||||
}
|
||||
|
||||
issue_3539: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = -0 + -"";
|
||||
console.log(0/a, 1/a, -1/a);
|
||||
}
|
||||
expect: {
|
||||
var a = -0;
|
||||
console.log(0/a, 1/a, -1/a);
|
||||
}
|
||||
expect_stdout: "NaN -Infinity Infinity"
|
||||
}
|
||||
|
||||
issue_3547_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
[
|
||||
1/0 + "1" + 0,
|
||||
1/0 + "1" - 0,
|
||||
1/0 - "1" + 0,
|
||||
1/0 - "1" - 0,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
[
|
||||
1/0 + "10",
|
||||
NaN,
|
||||
1/0,
|
||||
1/0,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"string Infinity10",
|
||||
"number NaN",
|
||||
"number Infinity",
|
||||
"number Infinity",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3547_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
[
|
||||
"1" + 1/0 + 0,
|
||||
"1" + 1/0 - 0,
|
||||
"1" - 1/0 + 0,
|
||||
"1" - 1/0 - 0,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
[
|
||||
"1" + 1/0 + 0,
|
||||
NaN,
|
||||
-1/0,
|
||||
-1/0,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 1Infinity0",
|
||||
"number NaN",
|
||||
"number -Infinity",
|
||||
"number -Infinity",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3547_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "3";
|
||||
[
|
||||
a + "2" + 1,
|
||||
a + "2" - 1,
|
||||
a - "2" + 1,
|
||||
a - "2" - 1,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a = "3";
|
||||
[
|
||||
a + "21",
|
||||
a + "2" - 1,
|
||||
a - 1,
|
||||
a - "2" - 1,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 321",
|
||||
"number 31",
|
||||
"number 2",
|
||||
"number 0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3547_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "2";
|
||||
[
|
||||
"3" + a + 1,
|
||||
"3" + a - 1,
|
||||
"3" - a + 1,
|
||||
"3" - a - 1,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var a = "2";
|
||||
[
|
||||
"3" + a + 1,
|
||||
"3" + a - 1,
|
||||
"3" - a + 1,
|
||||
2 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 321",
|
||||
"number 31",
|
||||
"number 2",
|
||||
"number 0",
|
||||
]
|
||||
}
|
||||
|
||||
223
test/compress/objects.js
Normal file
223
test/compress/objects.js
Normal file
@@ -0,0 +1,223 @@
|
||||
duplicate_key: {
|
||||
options = {
|
||||
objects: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
a: 3,
|
||||
};
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
a: 3,
|
||||
b: 2,
|
||||
};
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"a 3",
|
||||
"b 2",
|
||||
]
|
||||
}
|
||||
|
||||
duplicate_key_strict: {
|
||||
options = {
|
||||
objects: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
a: 3,
|
||||
};
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
a: 3,
|
||||
};
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
duplicate_key_side_effect: {
|
||||
options = {
|
||||
objects: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: o = 2,
|
||||
a: 3,
|
||||
};
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: o = 2,
|
||||
a: 3,
|
||||
};
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"a 3",
|
||||
"b 2",
|
||||
]
|
||||
}
|
||||
|
||||
duplicate_key_with_accessor: {
|
||||
options = {
|
||||
objects: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
[
|
||||
{
|
||||
a: 0,
|
||||
b: 1,
|
||||
a: 2,
|
||||
set b(v) {},
|
||||
},
|
||||
{
|
||||
a: 3,
|
||||
b: 4,
|
||||
get a() {
|
||||
return 5;
|
||||
},
|
||||
a: 6,
|
||||
b: 7,
|
||||
a: 8,
|
||||
b: 9,
|
||||
},
|
||||
].forEach(function(o) {
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
[
|
||||
{
|
||||
a: 2,
|
||||
b: 1,
|
||||
set b(v) {},
|
||||
},
|
||||
{
|
||||
a: 3,
|
||||
b: 4,
|
||||
get a() {
|
||||
return 5;
|
||||
},
|
||||
a: 8,
|
||||
b: 9,
|
||||
},
|
||||
].forEach(function(o) {
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
});
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
unsafe_object_repeated: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
objects: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: { b: 1 }, a: 1 };
|
||||
console.log(
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
o.b + 1,
|
||||
o.a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var o = { a: 1 };
|
||||
console.log(
|
||||
o + 1,
|
||||
2,
|
||||
o.b + 1,
|
||||
NaN
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
numeric_literal: {
|
||||
options = {
|
||||
objects: true,
|
||||
side_effects: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
0: 0,
|
||||
"-0": 1,
|
||||
42: 2,
|
||||
"42": 3,
|
||||
0x25: 4,
|
||||
"0x25": 5,
|
||||
1E42: 6,
|
||||
"1E42": 7,
|
||||
"1e+42": 8,
|
||||
};
|
||||
console.log(obj[-0], obj[-""], obj["-0"]);
|
||||
console.log(obj[42], obj["42"]);
|
||||
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
|
||||
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
|
||||
}
|
||||
expect_exact: [
|
||||
'var obj = {',
|
||||
' 0: 0,',
|
||||
' "-0": 1,',
|
||||
' 42: 3,',
|
||||
' 37: 4,',
|
||||
' o: 5,',
|
||||
' 1e42: 8,',
|
||||
' b: 7',
|
||||
'};',
|
||||
'',
|
||||
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||
'',
|
||||
'console.log(obj[42], obj["42"]);',
|
||||
'',
|
||||
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
|
||||
'',
|
||||
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||
]
|
||||
expect_stdout: [
|
||||
"0 0 1",
|
||||
"3 3",
|
||||
"4 5 4 4",
|
||||
"8 7 8",
|
||||
]
|
||||
}
|
||||
@@ -295,3 +295,145 @@ issue_2728_6: {
|
||||
}
|
||||
expect_stdout: "function undefined"
|
||||
}
|
||||
|
||||
typeof_defined_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
"undefined" == typeof A && A;
|
||||
"undefined" != typeof A && A;
|
||||
"undefined" == typeof A || A;
|
||||
"undefined" != typeof A || A;
|
||||
}
|
||||
expect: {
|
||||
"undefined" == typeof A && A;
|
||||
"undefined" != typeof A || A;
|
||||
}
|
||||
}
|
||||
|
||||
typeof_defined_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
"function" == typeof A && A;
|
||||
"function" != typeof A && A;
|
||||
"function" == typeof A || A;
|
||||
"function" != typeof A || A;
|
||||
}
|
||||
expect: {
|
||||
"function" != typeof A && A;
|
||||
"function" == typeof A || A;
|
||||
}
|
||||
}
|
||||
|
||||
typeof_defined_3: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
"undefined" == typeof A && "undefined" == typeof B && (A, B);
|
||||
"undefined" == typeof A && "undefined" != typeof B && (A, B);
|
||||
"undefined" != typeof A && "undefined" == typeof B && (A, B);
|
||||
"undefined" != typeof A && "undefined" != typeof B && (A, B);
|
||||
"undefined" == typeof A && "undefined" == typeof B || (A, B);
|
||||
"undefined" == typeof A && "undefined" != typeof B || (A, B);
|
||||
"undefined" != typeof A && "undefined" == typeof B || (A, B);
|
||||
"undefined" != typeof A && "undefined" != typeof B || (A, B);
|
||||
"undefined" == typeof A || "undefined" == typeof B && (A, B);
|
||||
"undefined" == typeof A || "undefined" != typeof B && (A, B);
|
||||
"undefined" != typeof A || "undefined" == typeof B && (A, B);
|
||||
"undefined" != typeof A || "undefined" != typeof B && (A, B);
|
||||
"undefined" == typeof A || "undefined" == typeof B || (A, B);
|
||||
"undefined" == typeof A || "undefined" != typeof B || (A, B);
|
||||
"undefined" != typeof A || "undefined" == typeof B || (A, B);
|
||||
"undefined" != typeof A || "undefined" != typeof B || (A, B);
|
||||
}
|
||||
expect: {
|
||||
"undefined" == typeof A && "undefined" == typeof B && (A, B);
|
||||
"undefined" == typeof A && "undefined" != typeof B && A;
|
||||
"undefined" != typeof A && "undefined" == typeof B && B;
|
||||
"undefined" == typeof A && "undefined" == typeof B || (A, B);
|
||||
"undefined" == typeof A && "undefined" != typeof B || (A, B);
|
||||
"undefined" != typeof A && "undefined" == typeof B || (A, B);
|
||||
"undefined" != typeof A && "undefined" != typeof B || (A, B);
|
||||
"undefined" == typeof A || "undefined" == typeof B && B;
|
||||
"undefined" != typeof A || "undefined" == typeof B && (A, B);
|
||||
"undefined" != typeof A || "undefined" != typeof B && A;
|
||||
"undefined" == typeof A || "undefined" != typeof B || B;
|
||||
"undefined" != typeof A || "undefined" == typeof B || A;
|
||||
"undefined" != typeof A || "undefined" != typeof B || (A, B);
|
||||
}
|
||||
}
|
||||
|
||||
typeof_defined_4: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
"object" == typeof A && "object" == typeof B && (A, B);
|
||||
"object" == typeof A && "object" != typeof B && (A, B);
|
||||
"object" != typeof A && "object" == typeof B && (A, B);
|
||||
"object" != typeof A && "object" != typeof B && (A, B);
|
||||
"object" == typeof A && "object" == typeof B || (A, B);
|
||||
"object" == typeof A && "object" != typeof B || (A, B);
|
||||
"object" != typeof A && "object" == typeof B || (A, B);
|
||||
"object" != typeof A && "object" != typeof B || (A, B);
|
||||
"object" == typeof A || "object" == typeof B && (A, B);
|
||||
"object" == typeof A || "object" != typeof B && (A, B);
|
||||
"object" != typeof A || "object" == typeof B && (A, B);
|
||||
"object" != typeof A || "object" != typeof B && (A, B);
|
||||
"object" == typeof A || "object" == typeof B || (A, B);
|
||||
"object" == typeof A || "object" != typeof B || (A, B);
|
||||
"object" != typeof A || "object" == typeof B || (A, B);
|
||||
"object" != typeof A || "object" != typeof B || (A, B);
|
||||
}
|
||||
expect: {
|
||||
"object" == typeof A && "object" != typeof B && B;
|
||||
"object" != typeof A && "object" == typeof B && A;
|
||||
"object" != typeof A && "object" != typeof B && (A, B);
|
||||
"object" == typeof A && "object" == typeof B || (A, B);
|
||||
"object" == typeof A && "object" != typeof B || (A, B);
|
||||
"object" != typeof A && "object" == typeof B || (A, B);
|
||||
"object" != typeof A && "object" != typeof B || (A, B);
|
||||
"object" == typeof A || "object" == typeof B && A;
|
||||
"object" == typeof A || "object" != typeof B && (A, B);
|
||||
"object" != typeof A || "object" != typeof B && B;
|
||||
"object" == typeof A || "object" == typeof B || (A, B);
|
||||
"object" == typeof A || "object" != typeof B || A;
|
||||
"object" != typeof A || "object" == typeof B || B;
|
||||
}
|
||||
}
|
||||
|
||||
emberjs_global: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
typeofs: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
if (typeof A === "object") {
|
||||
a = A;
|
||||
} else if (typeof B === "object") {
|
||||
a = B;
|
||||
} else {
|
||||
throw new Error("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
if ("object" != typeof A && "object" != typeof B)
|
||||
throw new Error("PASS");
|
||||
}
|
||||
expect_stdout: Error("PASS")
|
||||
}
|
||||
|
||||
@@ -259,6 +259,30 @@ describe("comments", function() {
|
||||
assert.strictEqual(result.code, code);
|
||||
});
|
||||
|
||||
it("Should handle comments around parenthesis correctly", function() {
|
||||
var code = [
|
||||
"a();",
|
||||
"/* foo */",
|
||||
"(b())",
|
||||
"/* bar */",
|
||||
"c();",
|
||||
].join("\n");
|
||||
var result = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
comments: "all",
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"a();",
|
||||
"/* foo */",
|
||||
"b()",
|
||||
"/* bar */;c();",
|
||||
].join("\n"));
|
||||
});
|
||||
|
||||
it("Should preserve comments around IIFE", function() {
|
||||
var result = UglifyJS.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
|
||||
compress: false,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
setInterval(function() {
|
||||
process.stderr.write("\0");
|
||||
}, 8 * 60 * 1000).unref();
|
||||
require("./run")([
|
||||
"-b",
|
||||
"-b braces",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user