enhance inline & unused (#5245)
This commit is contained in:
parent
8d0422b6f3
commit
87a7426598
494
lib/compress.js
494
lib/compress.js
|
|
@ -1859,7 +1859,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (!changed && last_changed == 3) break;
|
if (!changed && last_changed == 3) break;
|
||||||
}
|
}
|
||||||
if (compressor.option("inline") >= 4) {
|
if (compressor.option("inline") >= 4) {
|
||||||
if (inline_last_iife(statements, compressor)) changed = 4;
|
if (inline_iife(statements, compressor)) changed = 4;
|
||||||
if (!changed && last_changed == 4) break;
|
if (!changed && last_changed == 4) break;
|
||||||
}
|
}
|
||||||
if (compressor.sequences_limit > 0) {
|
if (compressor.sequences_limit > 0) {
|
||||||
|
|
@ -3478,23 +3478,23 @@ Compressor.prototype.compress = function(node) {
|
||||||
return statements.length != len;
|
return statements.length != len;
|
||||||
}
|
}
|
||||||
|
|
||||||
function inline_last_iife(statements, compressor) {
|
function inline_iife(statements, compressor) {
|
||||||
if (!in_lambda) return false;
|
var changed = false;
|
||||||
var index = statements.length - 1;
|
var index = statements.length - 1;
|
||||||
var stat = statements[index];
|
if (in_lambda && index >= 0) {
|
||||||
if (!(stat instanceof AST_SimpleStatement)) return false;
|
var inlined = statements[index].try_inline(compressor, block_scope);
|
||||||
var body = stat.body;
|
if (inlined) {
|
||||||
if (body instanceof AST_UnaryPrefix) {
|
statements[index--] = inlined;
|
||||||
if (unary_side_effects[body.operator]) return false;
|
changed = true;
|
||||||
body = body.expression;
|
}
|
||||||
}
|
}
|
||||||
var inlined = make_node(AST_UnaryPrefix, stat, {
|
for (; index >= 0; index--) {
|
||||||
operator: "void",
|
var inlined = statements[index].try_inline(compressor, block_scope, true, in_loop);
|
||||||
expression: body,
|
if (!inlined) continue;
|
||||||
}).try_inline(compressor, block_scope);
|
statements[index] = inlined;
|
||||||
if (!inlined) return false;
|
changed = true;
|
||||||
statements[index] = inlined;
|
}
|
||||||
return true;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sequencesize(statements, compressor) {
|
function sequencesize(statements, compressor) {
|
||||||
|
|
@ -3803,6 +3803,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (stat.init) {
|
if (stat.init) {
|
||||||
prev.definitions = prev.definitions.concat(stat.init.definitions);
|
prev.definitions = prev.definitions.concat(stat.init.definitions);
|
||||||
}
|
}
|
||||||
|
stat = stat.clone();
|
||||||
defs = stat.init = prev;
|
defs = stat.init = prev;
|
||||||
statements[j] = merge_defns(stat);
|
statements[j] = merge_defns(stat);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
@ -6775,7 +6776,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
var sym = def.name.definition();
|
var sym = def.name.definition();
|
||||||
var drop_sym = is_var ? can_drop_symbol(def.name) : is_safe_lexical(sym);
|
var drop_sym = is_var ? can_drop_symbol(def.name) : is_safe_lexical(sym);
|
||||||
if (!drop_sym || !drop_vars || sym.id in in_use_ids) {
|
if (!drop_sym || !drop_vars || sym.id in in_use_ids) {
|
||||||
if (value && indexOf_assign(sym, def) < 0) {
|
if (value && (indexOf_assign(sym, def) < 0 || self_assign(value.tail_node()))) {
|
||||||
value = value.drop_side_effect_free(compressor);
|
value = value.drop_side_effect_free(compressor);
|
||||||
if (value) {
|
if (value) {
|
||||||
AST_Node.warn("Side effects in definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
AST_Node.warn("Side effects in definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
|
|
@ -6865,6 +6866,10 @@ Compressor.prototype.compress = function(node) {
|
||||||
sym.eliminated++;
|
sym.eliminated++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function self_assign(ref) {
|
||||||
|
return ref instanceof AST_SymbolRef && ref.definition() === sym;
|
||||||
|
}
|
||||||
|
|
||||||
function assigned_once(fn, refs) {
|
function assigned_once(fn, refs) {
|
||||||
if (refs.length == 0) return fn === def.name.fixed_value();
|
if (refs.length == 0) return fn === def.name.fixed_value();
|
||||||
return all(refs, function(ref) {
|
return all(refs, function(ref) {
|
||||||
|
|
@ -9832,15 +9837,15 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (!has_default) has_default = 1;
|
if (!has_default) has_default = 1;
|
||||||
var arg = has_default == 1 && self.args[index];
|
var arg = has_default == 1 && self.args[index];
|
||||||
if (arg && !is_undefined(arg)) has_default = 2;
|
if (arg && !is_undefined(arg)) has_default = 2;
|
||||||
if (has_arg_refs(argname.value)) return false;
|
if (has_arg_refs(fn, argname.value)) return false;
|
||||||
argname = argname.name;
|
argname = argname.name;
|
||||||
}
|
}
|
||||||
if (argname instanceof AST_Destructured) {
|
if (argname instanceof AST_Destructured) {
|
||||||
has_destructured = true;
|
has_destructured = true;
|
||||||
if (has_arg_refs(argname)) return false;
|
if (has_arg_refs(fn, argname)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}) && !(fn.rest instanceof AST_Destructured && has_arg_refs(fn.rest));
|
}) && !(fn.rest instanceof AST_Destructured && has_arg_refs(fn, fn.rest));
|
||||||
var can_inline = can_drop && compressor.option("inline") && !self.is_expr_pure(compressor);
|
var can_inline = can_drop && compressor.option("inline") && !self.is_expr_pure(compressor);
|
||||||
if (can_inline && stat instanceof AST_Return) {
|
if (can_inline && stat instanceof AST_Return) {
|
||||||
var value = stat.value;
|
var value = stat.value;
|
||||||
|
|
@ -9946,17 +9951,6 @@ Compressor.prototype.compress = function(node) {
|
||||||
}
|
}
|
||||||
return try_evaluate(compressor, self);
|
return try_evaluate(compressor, self);
|
||||||
|
|
||||||
function has_arg_refs(node) {
|
|
||||||
var found = false;
|
|
||||||
node.walk(new TreeWalker(function(node) {
|
|
||||||
if (found) return true;
|
|
||||||
if (node instanceof AST_SymbolRef && fn.variables.get(node.name) === node.definition()) {
|
|
||||||
return found = true;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_void_lhs(orig) {
|
function make_void_lhs(orig) {
|
||||||
return make_node(AST_Dot, orig, {
|
return make_node(AST_Dot, orig, {
|
||||||
expression: make_node(AST_Array, orig, { elements: [] }),
|
expression: make_node(AST_Array, orig, { elements: [] }),
|
||||||
|
|
@ -10172,7 +10166,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (arg_used.has(name.name)) return false;
|
if (arg_used.has(name.name)) return false;
|
||||||
if (var_exists(defined, name.name)) return false;
|
if (var_exists(defined, name.name)) return false;
|
||||||
if (!all(stat.enclosed, function(def) {
|
if (!all(stat.enclosed, function(def) {
|
||||||
return def.scope === stat || !defined.has(def.name);
|
return def.scope === scope || def.scope === stat || !defined.has(def.name);
|
||||||
})) return false;
|
})) return false;
|
||||||
if (in_loop) in_loop.push(name.definition());
|
if (in_loop) in_loop.push(name.definition());
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -10207,8 +10201,6 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (scope.init === child) continue;
|
if (scope.init === child) continue;
|
||||||
if (scope.object === child) continue;
|
if (scope.object === child) continue;
|
||||||
in_loop = [];
|
in_loop = [];
|
||||||
} else if (scope instanceof AST_SymbolRef) {
|
|
||||||
if (scope.fixed_value() instanceof AST_Scope) return false;
|
|
||||||
}
|
}
|
||||||
} while (!(scope instanceof AST_Scope));
|
} while (!(scope instanceof AST_Scope));
|
||||||
insert = scope.body.indexOf(child) + 1;
|
insert = scope.body.indexOf(child) + 1;
|
||||||
|
|
@ -10270,7 +10262,9 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (value) expressions.push(value);
|
if (value) expressions.push(value);
|
||||||
} else {
|
} else {
|
||||||
var symbol = make_node(AST_SymbolVar, name, name);
|
var symbol = make_node(AST_SymbolVar, name, name);
|
||||||
name.definition().orig.push(symbol);
|
var def = name.definition();
|
||||||
|
def.orig.push(symbol);
|
||||||
|
def.eliminated++;
|
||||||
if (name.unused !== undefined) {
|
if (name.unused !== undefined) {
|
||||||
append_var(decls, expressions, symbol);
|
append_var(decls, expressions, symbol);
|
||||||
if (value) expressions.push(value);
|
if (value) expressions.push(value);
|
||||||
|
|
@ -10316,44 +10310,36 @@ Compressor.prototype.compress = function(node) {
|
||||||
def.references.push(ref);
|
def.references.push(ref);
|
||||||
var symbol = make_node(AST_SymbolVar, name, name);
|
var symbol = make_node(AST_SymbolVar, name, name);
|
||||||
def.orig.push(symbol);
|
def.orig.push(symbol);
|
||||||
|
def.eliminated++;
|
||||||
append_var(decls, expressions, symbol);
|
append_var(decls, expressions, symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function flatten_var(name) {
|
|
||||||
var redef = name.definition().redefined();
|
|
||||||
if (redef) {
|
|
||||||
name = name.clone();
|
|
||||||
name.thedef = redef;
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function flatten_vars(decls, expressions) {
|
function flatten_vars(decls, expressions) {
|
||||||
var args = [ insert, 0 ];
|
var args = [ insert, 0 ];
|
||||||
var decl_var = [], expr_var = [], expr_loop = [], exprs = [];
|
var decl_var = [], expr_var = [], expr_loop = [], exprs = [];
|
||||||
for (var i = 0; i < fn.body.length; i++) {
|
fn.body.filter(in_loop ? function(stat) {
|
||||||
var stat = fn.body[i];
|
if (!(stat instanceof AST_LambdaDefinition)) return true;
|
||||||
if (stat instanceof AST_LambdaDefinition) {
|
var name = make_node(AST_SymbolVar, stat.name, flatten_var(stat.name));
|
||||||
if (in_loop) {
|
var def = name.definition();
|
||||||
var name = make_node(AST_SymbolVar, stat.name, flatten_var(stat.name));
|
def.fixed = false;
|
||||||
var def = name.definition();
|
def.orig.push(name);
|
||||||
def.fixed = false;
|
def.eliminated++;
|
||||||
def.orig.push(name);
|
append_var(decls, expressions, name, to_func_expr(stat, true));
|
||||||
append_var(decls, expressions, name, to_func_expr(stat, true));
|
return false;
|
||||||
} else {
|
} : function(stat) {
|
||||||
var def = stat.name.definition();
|
if (!(stat instanceof AST_LambdaDefinition)) return true;
|
||||||
scope.functions.set(def.name, def);
|
var def = stat.name.definition();
|
||||||
scope.variables.set(def.name, def);
|
scope.functions.set(def.name, def);
|
||||||
scope.enclosed.push(def);
|
scope.variables.set(def.name, def);
|
||||||
scope.var_names().set(def.name, true);
|
scope.enclosed.push(def);
|
||||||
args.push(stat);
|
scope.var_names().set(def.name, true);
|
||||||
}
|
args.push(stat);
|
||||||
continue;
|
return false;
|
||||||
}
|
}).forEach(function(stat) {
|
||||||
if (!(stat instanceof AST_Var)) {
|
if (!(stat instanceof AST_Var)) {
|
||||||
if (stat instanceof AST_SimpleStatement) exprs.push(stat.body);
|
if (stat instanceof AST_SimpleStatement) exprs.push(stat.body);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
for (var j = 0; j < stat.definitions.length; j++) {
|
for (var j = 0; j < stat.definitions.length; j++) {
|
||||||
var var_def = stat.definitions[j];
|
var var_def = stat.definitions[j];
|
||||||
|
|
@ -10365,7 +10351,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
exprs = [];
|
exprs = [];
|
||||||
}
|
}
|
||||||
append_var(decl_var, expr_var, name, value);
|
append_var(decl_var, expr_var, name, value);
|
||||||
if (in_loop && !arg_used.has(name.name)) {
|
if (in_loop && !arg_used.has(name.name) && !fn.functions.has(name.name)) {
|
||||||
var def = fn.variables.get(name.name);
|
var def = fn.variables.get(name.name);
|
||||||
var sym = make_node(AST_SymbolRef, name, name);
|
var sym = make_node(AST_SymbolRef, name, name);
|
||||||
def.references.push(sym);
|
def.references.push(sym);
|
||||||
|
|
@ -10376,7 +10362,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
[].push.apply(decls, decl_var);
|
[].push.apply(decls, decl_var);
|
||||||
[].push.apply(expressions, expr_loop);
|
[].push.apply(expressions, expr_loop);
|
||||||
[].push.apply(expressions, expr_var);
|
[].push.apply(expressions, expr_var);
|
||||||
|
|
@ -10393,9 +10379,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
}
|
}
|
||||||
var args = flatten_vars(decls, expressions);
|
var args = flatten_vars(decls, expressions);
|
||||||
expressions.push(value);
|
expressions.push(value);
|
||||||
if (decls.length) args.push(make_node(AST_Var, fn, {
|
if (decls.length) args.push(make_node(AST_Var, fn, { definitions: decls }));
|
||||||
definitions: decls
|
|
||||||
}));
|
|
||||||
[].splice.apply(scope.body, args);
|
[].splice.apply(scope.body, args);
|
||||||
fn.enclosed.forEach(function(def) {
|
fn.enclosed.forEach(function(def) {
|
||||||
if (scope.var_names().has(def.name)) return;
|
if (scope.var_names().has(def.name)) return;
|
||||||
|
|
@ -11809,9 +11793,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
var reachable = false;
|
var reachable = false;
|
||||||
var find_ref = new TreeWalker(function(node) {
|
var find_ref = new TreeWalker(function(node) {
|
||||||
if (reachable) return true;
|
if (reachable) return true;
|
||||||
if (node instanceof AST_SymbolRef && member(node.definition(), defs)) {
|
if (node instanceof AST_SymbolRef && member(node.definition(), defs)) return reachable = true;
|
||||||
return reachable = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
var scan_scope = new TreeWalker(function(node) {
|
var scan_scope = new TreeWalker(function(node) {
|
||||||
if (reachable) return true;
|
if (reachable) return true;
|
||||||
|
|
@ -12825,12 +12807,72 @@ Compressor.prototype.compress = function(node) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function flatten_var(name) {
|
||||||
|
var redef = name.definition().redefined();
|
||||||
|
if (redef) {
|
||||||
|
name = name.clone();
|
||||||
|
name.thedef = redef;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_arg_refs(fn, node) {
|
||||||
|
var found = false;
|
||||||
|
node.walk(new TreeWalker(function(node) {
|
||||||
|
if (found) return true;
|
||||||
|
if (node instanceof AST_SymbolRef && fn.variables.get(node.name) === node.definition()) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
(function(def) {
|
(function(def) {
|
||||||
def(AST_Node, noop);
|
def(AST_Node, noop);
|
||||||
def(AST_Await, function(compressor, scope) {
|
def(AST_Assign, noop);
|
||||||
return this.expression.try_inline(compressor, scope);
|
def(AST_Await, function(compressor, scope, no_return, in_loop) {
|
||||||
|
return this.expression.try_inline(compressor, scope, no_return, in_loop);
|
||||||
});
|
});
|
||||||
def(AST_Call, function(compressor, scope) {
|
def(AST_Binary, function(compressor, scope, no_return, in_loop) {
|
||||||
|
if (no_return === undefined) return;
|
||||||
|
var self = this;
|
||||||
|
var op = self.operator;
|
||||||
|
if (!lazy_op[op]) return;
|
||||||
|
var inlined = self.right.try_inline(compressor, scope, no_return, in_loop);
|
||||||
|
if (!inlined) return;
|
||||||
|
return make_node(AST_If, self, {
|
||||||
|
condition: make_condition(self.left),
|
||||||
|
body: inlined,
|
||||||
|
alternative: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
function make_condition(cond) {
|
||||||
|
switch (op) {
|
||||||
|
case "&&":
|
||||||
|
return cond;
|
||||||
|
case "||":
|
||||||
|
return cond.negate(compressor);
|
||||||
|
case "??":
|
||||||
|
return make_node(AST_Binary, self, {
|
||||||
|
operator: "===",
|
||||||
|
left: make_node(AST_Undefined, self).transform(compressor),
|
||||||
|
right: cond,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
def(AST_BlockStatement, function(compressor, scope, no_return, in_loop) {
|
||||||
|
if (no_return) return;
|
||||||
|
if (!this.variables) return;
|
||||||
|
var body = this.body;
|
||||||
|
var last = body.length - 1;
|
||||||
|
if (last < 0) return;
|
||||||
|
var inlined = body[last].try_inline(compressor, this, no_return, in_loop);
|
||||||
|
if (!inlined) return;
|
||||||
|
body[last] = inlined;
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
def(AST_Call, function(compressor, scope, no_return, in_loop) {
|
||||||
if (compressor.option("inline") < 4) return;
|
if (compressor.option("inline") < 4) return;
|
||||||
var call = this;
|
var call = this;
|
||||||
if (call.is_expr_pure(compressor)) return;
|
if (call.is_expr_pure(compressor)) return;
|
||||||
|
|
@ -12838,8 +12880,10 @@ Compressor.prototype.compress = function(node) {
|
||||||
if (!(fn instanceof AST_LambdaExpression)) return;
|
if (!(fn instanceof AST_LambdaExpression)) return;
|
||||||
if (fn.name) return;
|
if (fn.name) return;
|
||||||
if (fn.uses_arguments) return;
|
if (fn.uses_arguments) return;
|
||||||
if (is_arrow(fn) && fn.value) return;
|
|
||||||
if (is_generator(fn)) return;
|
if (is_generator(fn)) return;
|
||||||
|
var arrow = is_arrow(fn);
|
||||||
|
if (arrow && fn.value) 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);
|
||||||
var defined = new Dictionary();
|
var defined = new Dictionary();
|
||||||
|
|
@ -12849,28 +12893,82 @@ Compressor.prototype.compress = function(node) {
|
||||||
});
|
});
|
||||||
scope = scope.parent_scope;
|
scope = scope.parent_scope;
|
||||||
}
|
}
|
||||||
if (is_async(fn) && !(compressor.option("awaits") && is_async(scope))) return;
|
if (scope instanceof AST_Toplevel && fn.variables.size() > (arrow ? 0 : 1)) {
|
||||||
|
if (!compressor.toplevel.vars) return;
|
||||||
|
if (fn.functions.size() > 0 && !compressor.toplevel.funcs) return;
|
||||||
|
}
|
||||||
|
var async = is_async(fn);
|
||||||
|
if (async && !(compressor.option("awaits") && is_async(scope))) return;
|
||||||
var names = scope.var_names();
|
var names = scope.var_names();
|
||||||
|
if (in_loop) in_loop = [];
|
||||||
if (!fn.variables.all(function(def, name) {
|
if (!fn.variables.all(function(def, name) {
|
||||||
|
if (in_loop) in_loop.push(def);
|
||||||
if (!defined.has(name) && !names.has(name)) return true;
|
if (!defined.has(name) && !names.has(name)) return true;
|
||||||
if (name != "arguments") return false;
|
if (name != "arguments") return false;
|
||||||
if (scope.uses_arguments) return false;
|
if (scope.uses_arguments) return false;
|
||||||
return def.references.length == def.replaced;
|
return def.references.length == def.replaced;
|
||||||
})) return;
|
})) return;
|
||||||
var safe = true;
|
if (in_loop && in_loop.length > 0 && is_reachable(fn, in_loop)) return;
|
||||||
fn.each_argname(function(argname) {
|
var simple_argnames = true;
|
||||||
if (!all(argname.definition().orig, function(sym) {
|
if (!all(fn.argnames, function(argname) {
|
||||||
return !(sym instanceof AST_SymbolDefun);
|
var abort = false;
|
||||||
})) safe = false;
|
var tw = new TreeWalker(function(node) {
|
||||||
});
|
if (abort) return true;
|
||||||
if (!safe) return;
|
if (node instanceof AST_DefaultValue) {
|
||||||
|
if (has_arg_refs(fn, node.value)) return abort = true;
|
||||||
|
node.name.walk(tw);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_DestructuredKeyVal) {
|
||||||
|
if (node.key instanceof AST_Node && has_arg_refs(fn, node.key)) return abort = true;
|
||||||
|
node.value.walk(tw);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_SymbolFunarg && !all(node.definition().orig, function(sym) {
|
||||||
|
return !(sym instanceof AST_SymbolDefun);
|
||||||
|
})) return abort = true;
|
||||||
|
});
|
||||||
|
argname.walk(tw);
|
||||||
|
if (abort) return false;
|
||||||
|
if (!(argname instanceof AST_SymbolFunarg)) simple_argnames = false;
|
||||||
|
return true;
|
||||||
|
})) return;
|
||||||
|
if (fn.rest) {
|
||||||
|
if (has_arg_refs(fn, fn.rest)) return;
|
||||||
|
simple_argnames = false;
|
||||||
|
}
|
||||||
|
if (no_return && !all(fn.body, function(stat) {
|
||||||
|
var abort = false;
|
||||||
|
stat.walk(new TreeWalker(function(node) {
|
||||||
|
if (abort) return true;
|
||||||
|
if (async && node instanceof AST_Await || node instanceof AST_Return) return abort = true;
|
||||||
|
if (node instanceof AST_Scope && node !== fn) return true;
|
||||||
|
}));
|
||||||
|
return !abort;
|
||||||
|
})) return;
|
||||||
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return;
|
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return;
|
||||||
fn.functions.each(function(def, name) {
|
fn.functions.each(function(def, name) {
|
||||||
scope.functions.set(name, def);
|
scope.functions.set(name, def);
|
||||||
});
|
});
|
||||||
|
var body = [];
|
||||||
fn.variables.each(function(def, name) {
|
fn.variables.each(function(def, name) {
|
||||||
|
names.set(name, true);
|
||||||
|
scope.enclosed.push(def);
|
||||||
scope.variables.set(name, def);
|
scope.variables.set(name, def);
|
||||||
def.single_use = false;
|
def.single_use = false;
|
||||||
|
if (!in_loop || fn.functions.has(name)) return;
|
||||||
|
if (def.references.length == def.replaced) return;
|
||||||
|
var sym = flatten_var(def.orig[0]);
|
||||||
|
if (sym.TYPE != "SymbolVar") return;
|
||||||
|
var ref = make_node(AST_SymbolRef, sym, sym);
|
||||||
|
sym.definition().references.push(ref);
|
||||||
|
body.push(make_node(AST_SimpleStatement, sym, {
|
||||||
|
body: make_node(AST_Assign, sym, {
|
||||||
|
operator: "=",
|
||||||
|
left: ref,
|
||||||
|
right: make_node(AST_Undefined, sym).transform(compressor),
|
||||||
|
}),
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
if (fn.variables.has("NaN")) scope.transform(new TreeTransformer(function(node) {
|
if (fn.variables.has("NaN")) scope.transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_NaN) return make_node(AST_Binary, node, {
|
if (node instanceof AST_NaN) return make_node(AST_Binary, node, {
|
||||||
|
|
@ -12879,12 +12977,28 @@ Compressor.prototype.compress = function(node) {
|
||||||
right: make_node(AST_Number, node, { value: 0 }),
|
right: make_node(AST_Number, node, { value: 0 }),
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
var body = [], defs = Object.create(null), syms = new Dictionary();
|
var defs = Object.create(null), syms = new Dictionary();
|
||||||
if (fn.rest || !all(fn.argnames, function(argname) {
|
if (simple_argnames && all(call.args, function(arg) {
|
||||||
return argname instanceof AST_SymbolFunarg;
|
|
||||||
}) || !all(call.args, function(arg) {
|
|
||||||
return !(arg instanceof AST_Spread);
|
return !(arg instanceof AST_Spread);
|
||||||
})) {
|
})) {
|
||||||
|
var values = call.args.slice();
|
||||||
|
fn.argnames.forEach(function(argname) {
|
||||||
|
var value = values.shift();
|
||||||
|
if (argname.unused) {
|
||||||
|
if (value) body.push(make_node(AST_SimpleStatement, call, { body: value }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
body.push(make_node(AST_Var, call, {
|
||||||
|
definitions: [ make_node(AST_VarDef, call, {
|
||||||
|
name: argname.convert_symbol(AST_SymbolVar, process),
|
||||||
|
value: value || make_node(AST_Undefined, call).transform(compressor),
|
||||||
|
}) ],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
if (values.length) body.push(make_node(AST_SimpleStatement, call, {
|
||||||
|
body: make_sequence(call, values),
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
body.push(make_node(AST_Var, call, {
|
body.push(make_node(AST_Var, call, {
|
||||||
definitions: [ make_node(AST_VarDef, call, {
|
definitions: [ make_node(AST_VarDef, call, {
|
||||||
name: make_node(AST_DestructuredArray, call, {
|
name: make_node(AST_DestructuredArray, call, {
|
||||||
|
|
@ -12897,37 +13011,37 @@ Compressor.prototype.compress = function(node) {
|
||||||
value: make_node(AST_Array, call, { elements: call.args.slice() }),
|
value: make_node(AST_Array, call, { elements: call.args.slice() }),
|
||||||
}) ],
|
}) ],
|
||||||
}));
|
}));
|
||||||
} else {
|
|
||||||
var values = call.args.slice();
|
|
||||||
fn.argnames.forEach(function(argname) {
|
|
||||||
var value = values.shift();
|
|
||||||
if (argname.unused) {
|
|
||||||
if (value) body.push(make_node(AST_SimpleStatement, call, { body: value }));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
body.push(make_node(AST_Var, call, {
|
|
||||||
definitions: [ make_node(AST_VarDef, call, {
|
|
||||||
name: argname.convert_symbol(AST_SymbolVar, process),
|
|
||||||
value: value || make_node(AST_Undefined, call).optimize(compressor),
|
|
||||||
}) ],
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
if (values.length) body.push(make_node(AST_SimpleStatement, call, {
|
|
||||||
body: make_sequence(call, values),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
syms.each(function(orig, id) {
|
syms.each(function(orig, id) {
|
||||||
[].unshift.apply(defs[id].orig, orig);
|
var def = defs[id];
|
||||||
});
|
[].unshift.apply(def.orig, orig);
|
||||||
var inlined = make_node(AST_BlockStatement, call, {
|
def.eliminated += orig.length;
|
||||||
body: body.concat(fn.body, make_node(AST_Return, call, { value: null })),
|
|
||||||
});
|
|
||||||
if (is_async(fn)) scan_local_returns(inlined, function(node) {
|
|
||||||
var value = node.value;
|
|
||||||
if (!value) return;
|
|
||||||
if (is_undefined(value)) return;
|
|
||||||
node.value = make_node(AST_Await, call, { expression: value });
|
|
||||||
});
|
});
|
||||||
|
[].push.apply(body, in_loop ? fn.body.filter(function(stat) {
|
||||||
|
if (!(stat instanceof AST_LambdaDefinition)) return true;
|
||||||
|
var name = make_node(AST_SymbolVar, stat.name, flatten_var(stat.name));
|
||||||
|
var def = name.definition();
|
||||||
|
def.fixed = false;
|
||||||
|
def.orig.push(name);
|
||||||
|
def.eliminated++;
|
||||||
|
body.push(make_node(AST_Var, stat, {
|
||||||
|
definitions: [ make_node(AST_VarDef, stat, {
|
||||||
|
name: name,
|
||||||
|
value: to_func_expr(stat, true),
|
||||||
|
}) ],
|
||||||
|
}));
|
||||||
|
return false;
|
||||||
|
}) : fn.body);
|
||||||
|
var inlined = make_node(AST_BlockStatement, call, { body: body });
|
||||||
|
if (!no_return) {
|
||||||
|
if (async) scan_local_returns(inlined, function(node) {
|
||||||
|
var value = node.value;
|
||||||
|
if (!value) return;
|
||||||
|
if (is_undefined(value)) return;
|
||||||
|
node.value = make_node(AST_Await, call, { expression: value });
|
||||||
|
});
|
||||||
|
body.push(make_node(AST_Return, call, { value: null }));
|
||||||
|
}
|
||||||
return inlined;
|
return inlined;
|
||||||
|
|
||||||
function process(sym, argname) {
|
function process(sym, argname) {
|
||||||
|
|
@ -12936,25 +13050,129 @@ Compressor.prototype.compress = function(node) {
|
||||||
syms.add(def.id, sym);
|
syms.add(def.id, sym);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
def(AST_New, noop);
|
def(AST_Conditional, function(compressor, scope, no_return, in_loop) {
|
||||||
def(AST_Sequence, function(compressor, scope) {
|
var self = this;
|
||||||
var inlined = this.tail_node().try_inline(compressor, scope);
|
var body = self.consequent.try_inline(compressor, scope, no_return, in_loop);
|
||||||
if (inlined) return make_node(AST_BlockStatement, this, {
|
var alt = self.alternative.try_inline(compressor, scope, no_return, in_loop);
|
||||||
body: [
|
if (!body && !alt) return;
|
||||||
make_node(AST_SimpleStatement, this, {
|
return make_node(AST_If, self, {
|
||||||
body: make_sequence(this, this.expressions.slice(0, -1)),
|
condition: self.condition,
|
||||||
}),
|
body: body || make_body(self.consequent),
|
||||||
inlined,
|
alternative: alt || make_body(self.alternative),
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function make_body(value) {
|
||||||
|
if (no_return) return make_node(AST_SimpleStatement, value, { body: value });
|
||||||
|
return make_node(AST_Return, value, { value: value });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_UnaryPrefix, function(compressor, scope) {
|
def(AST_For, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body.try_inline(compressor, scope, true, true);
|
||||||
|
if (body) this.body = body;
|
||||||
|
var inlined = this.init;
|
||||||
|
if (inlined) {
|
||||||
|
inlined = inlined.try_inline(compressor, scope, true, in_loop);
|
||||||
|
if (inlined) {
|
||||||
|
this.init = null;
|
||||||
|
inlined.body.push(this);
|
||||||
|
return inlined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return body && this;
|
||||||
|
});
|
||||||
|
def(AST_ForEnumeration, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body.try_inline(compressor, scope, true, true);
|
||||||
|
if (body) this.body = body;
|
||||||
|
var obj = this.object;
|
||||||
|
if (obj instanceof AST_Sequence) {
|
||||||
|
var inlined = inline_sequence(compressor, scope, true, in_loop, obj, 1);
|
||||||
|
if (inlined) {
|
||||||
|
this.object = obj.tail_node();
|
||||||
|
inlined.body.push(this);
|
||||||
|
return inlined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return body && this;
|
||||||
|
});
|
||||||
|
def(AST_If, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body.try_inline(compressor, scope, no_return, in_loop);
|
||||||
|
if (body) this.body = body;
|
||||||
|
var alt = this.alternative;
|
||||||
|
if (alt) {
|
||||||
|
alt = alt.try_inline(compressor, scope, no_return, in_loop);
|
||||||
|
if (alt) this.alternative = alt;
|
||||||
|
}
|
||||||
|
var cond = this.condition;
|
||||||
|
if (cond instanceof AST_Sequence) {
|
||||||
|
var inlined = inline_sequence(compressor, scope, true, in_loop, cond, 1);
|
||||||
|
if (inlined) {
|
||||||
|
this.condition = cond.tail_node();
|
||||||
|
inlined.body.push(this);
|
||||||
|
return inlined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (body || alt) && this;
|
||||||
|
});
|
||||||
|
def(AST_IterationStatement, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body.try_inline(compressor, scope, true, true);
|
||||||
|
if (!body) return;
|
||||||
|
this.body = body;
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
def(AST_LabeledStatement, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body.try_inline(compressor, scope, no_return, in_loop);
|
||||||
|
if (!body) return;
|
||||||
|
this.body = body;
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
def(AST_New, noop);
|
||||||
|
function inline_sequence(compressor, scope, no_return, in_loop, node, skip) {
|
||||||
|
var body = [], exprs = node.expressions, no_ret = no_return;
|
||||||
|
for (var i = exprs.length - (skip || 0), j = i; --i >= 0; no_ret = true) {
|
||||||
|
var inlined = exprs[i].try_inline(compressor, scope, no_ret, in_loop);
|
||||||
|
if (!inlined) continue;
|
||||||
|
flush();
|
||||||
|
body.push(inlined);
|
||||||
|
}
|
||||||
|
if (body.length == 0) return;
|
||||||
|
flush();
|
||||||
|
if (!no_return && body[0] instanceof AST_SimpleStatement) {
|
||||||
|
body[0] = make_node(AST_Return, node, { value: body[0].body });
|
||||||
|
}
|
||||||
|
return make_node(AST_BlockStatement, node, { body: body.reverse() });
|
||||||
|
|
||||||
|
function flush() {
|
||||||
|
if (j > i + 1) body.push(make_node(AST_SimpleStatement, node, {
|
||||||
|
body: make_sequence(node, exprs.slice(i + 1, j)),
|
||||||
|
}));
|
||||||
|
j = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def(AST_Sequence, function(compressor, scope, no_return, in_loop) {
|
||||||
|
return inline_sequence(compressor, scope, no_return, in_loop, this);
|
||||||
|
});
|
||||||
|
def(AST_SimpleStatement, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body;
|
||||||
|
while (body instanceof AST_UnaryPrefix) {
|
||||||
|
var op = body.operator;
|
||||||
|
if (unary_side_effects[op]) break;
|
||||||
|
if (op == "void") break;
|
||||||
|
body = body.expression;
|
||||||
|
}
|
||||||
|
if (!no_return && !is_undefined(body)) body = make_node(AST_UnaryPrefix, this, {
|
||||||
|
operator: "void",
|
||||||
|
expression: body,
|
||||||
|
});
|
||||||
|
return body.try_inline(compressor, scope, no_return || false, in_loop);
|
||||||
|
});
|
||||||
|
def(AST_UnaryPrefix, function(compressor, scope, no_return, in_loop) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var op = self.operator;
|
var op = self.operator;
|
||||||
if (unary_side_effects[op]) return;
|
if (unary_side_effects[op]) return;
|
||||||
var inlined = self.expression.try_inline(compressor, scope);
|
if (!no_return && op == "void") no_return = false;
|
||||||
|
var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop);
|
||||||
if (!inlined) return;
|
if (!inlined) return;
|
||||||
scan_local_returns(inlined, function(node) {
|
if (!no_return) scan_local_returns(inlined, function(node) {
|
||||||
node.in_bool = false;
|
node.in_bool = false;
|
||||||
var value = node.value;
|
var value = node.value;
|
||||||
if (op == "void") {
|
if (op == "void") {
|
||||||
|
|
@ -12968,7 +13186,21 @@ Compressor.prototype.compress = function(node) {
|
||||||
});
|
});
|
||||||
return inlined;
|
return inlined;
|
||||||
});
|
});
|
||||||
def(AST_Yield, function(compressor, scope) {
|
def(AST_With, function(compressor, scope, no_return, in_loop) {
|
||||||
|
var body = this.body.try_inline(compressor, scope, no_return, in_loop);
|
||||||
|
if (body) this.body = body;
|
||||||
|
var exp = this.expression;
|
||||||
|
if (exp instanceof AST_Sequence) {
|
||||||
|
var inlined = inline_sequence(compressor, scope, true, in_loop, exp, 1);
|
||||||
|
if (inlined) {
|
||||||
|
this.expression = exp.tail_node();
|
||||||
|
inlined.body.push(this);
|
||||||
|
return inlined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return body && this;
|
||||||
|
});
|
||||||
|
def(AST_Yield, function(compressor, scope, no_return, in_loop) {
|
||||||
if (!compressor.option("yields")) return;
|
if (!compressor.option("yields")) return;
|
||||||
if (!this.nested) return;
|
if (!this.nested) return;
|
||||||
var call = this.expression;
|
var call = this.expression;
|
||||||
|
|
@ -12986,7 +13218,7 @@ Compressor.prototype.compress = function(node) {
|
||||||
}
|
}
|
||||||
call = call.clone();
|
call = call.clone();
|
||||||
call.expression = fn;
|
call.expression = fn;
|
||||||
return call.try_inline(compressor, scope);
|
return call.try_inline(compressor, scope, no_return, in_loop);
|
||||||
});
|
});
|
||||||
})(function(node, func) {
|
})(function(node, func) {
|
||||||
node.DEFMETHOD("try_inline", func);
|
node.DEFMETHOD("try_inline", func);
|
||||||
|
|
|
||||||
|
|
@ -1646,10 +1646,8 @@ issue_4962_1: {
|
||||||
})(function g() {});
|
})(function g() {});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function g() {}),
|
(function g() {});
|
||||||
void function() {
|
while (console.log(typeof g));
|
||||||
while (console.log(typeof g));
|
|
||||||
}();
|
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
node_version: ">=12"
|
node_version: ">=12"
|
||||||
|
|
|
||||||
|
|
@ -838,12 +838,10 @@ issue_4202: {
|
||||||
expect: {
|
expect: {
|
||||||
{
|
{
|
||||||
const o = {};
|
const o = {};
|
||||||
(function() {
|
function f() {
|
||||||
function f() {
|
o.p = 42;
|
||||||
o.p = 42;
|
}
|
||||||
}
|
f(f);
|
||||||
f(f);
|
|
||||||
})();
|
|
||||||
console.log(o.p++);
|
console.log(o.p++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1287,12 +1285,10 @@ issue_4261_2: {
|
||||||
expect: {
|
expect: {
|
||||||
{
|
{
|
||||||
const a = 42;
|
const a = 42;
|
||||||
(function() {
|
function g() {
|
||||||
function g() {
|
while (void console.log(a));
|
||||||
while (void console.log(a));
|
}
|
||||||
}
|
while (g());
|
||||||
while (g());
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
|
|
|
||||||
|
|
@ -2027,13 +2027,11 @@ issue_5222: {
|
||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
do {
|
||||||
do {
|
a = void 0,
|
||||||
a = void 0,
|
[ a ] = [];
|
||||||
[ a ] = [];
|
} while (console.log("PASS"));
|
||||||
} while (console.log("PASS"));
|
var a;
|
||||||
var a;
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
|
|
|
||||||
|
|
@ -604,6 +604,254 @@ empty_body: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline_binary_and: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
(function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
return "bar";
|
||||||
|
})() && (function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
return "moo";
|
||||||
|
})();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
if (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
return "bar";
|
||||||
|
}()) {
|
||||||
|
while (console.log("baz"));
|
||||||
|
return void "moo";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_binary_or: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
})() || (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (!function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}())
|
||||||
|
while (console.log("bar"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_conditional: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
})() ? (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
})() : (function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}())
|
||||||
|
while (console.log("bar"));
|
||||||
|
else
|
||||||
|
while (console.log("baz"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_do: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
do (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
})();
|
||||||
|
while (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
do {
|
||||||
|
while (console.log("foo"));
|
||||||
|
} while (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_finally_return: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} finally {
|
||||||
|
return function() {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
}(), 42;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} finally {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_for_init: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}(); function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}(); function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
}()) (function() {
|
||||||
|
while (console.log("moo"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (console.log("foo"));
|
||||||
|
for (; function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}(); function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
}()) {
|
||||||
|
while (console.log("moo"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_for_object: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a in function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}(), function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}()) (function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (console.log("foo"));
|
||||||
|
for (var a in function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}()) {
|
||||||
|
while (console.log("baz"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_if_else: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}(), function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}()) (function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
})();
|
||||||
|
else (function() {
|
||||||
|
while (console.log("moo"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (console.log("foo"));
|
||||||
|
if (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}()) {
|
||||||
|
while (console.log("baz"));
|
||||||
|
} else {
|
||||||
|
while (console.log("moo"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"moo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_label: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: (function() {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
L: {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
inline_loop_1: {
|
inline_loop_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
|
@ -679,6 +927,86 @@ inline_loop_4: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline_loop_5: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a in "foo") {
|
||||||
|
(function() {
|
||||||
|
function f() {}
|
||||||
|
var f;
|
||||||
|
console.log(typeof f, a - f);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a in "foo")
|
||||||
|
f = function() {},
|
||||||
|
void console.log(typeof f, a - f);
|
||||||
|
var f;
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"function NaN",
|
||||||
|
"function NaN",
|
||||||
|
"function NaN",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_loop_6: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a in "foo") {
|
||||||
|
(function() {
|
||||||
|
var f;
|
||||||
|
function f() {}
|
||||||
|
console.log(typeof f, a - f);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a in "foo")
|
||||||
|
f = function() {},
|
||||||
|
void console.log(typeof f, a - f);
|
||||||
|
var f;
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"function NaN",
|
||||||
|
"function NaN",
|
||||||
|
"function NaN",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_loop_7: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a = 0; a < 2; a++) {
|
||||||
|
(function() {
|
||||||
|
var b = b && b[console.log("FAIL")] || "PASS";
|
||||||
|
while (console.log(b));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a = 0; a < 2; a++) {
|
||||||
|
b = void 0;
|
||||||
|
var b = b && b[console.log("FAIL")] || "PASS";
|
||||||
|
while (console.log(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
inline_negate_iife: {
|
inline_negate_iife: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
|
@ -699,6 +1027,111 @@ inline_negate_iife: {
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline_return_binary: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
return "bar";
|
||||||
|
}() || function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
return "moo";
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
return "bar";
|
||||||
|
}() || function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
return "moo";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_return_conditional: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return console ? "foo" : function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
return "baz";
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
if (console)
|
||||||
|
return "foo";
|
||||||
|
else {
|
||||||
|
while (console.log("bar"));
|
||||||
|
return "baz";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_while: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}()) (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}()) {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_with: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
with (+function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}(), -function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}()) ~function() {
|
||||||
|
while (console.log("baz"));
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (console.log("foo"));
|
||||||
|
with (-function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
}()) {
|
||||||
|
while (console.log("baz"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
issue_2476: {
|
issue_2476: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
|
@ -820,16 +1253,14 @@ issue_2604_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "FAIL";
|
var a = "FAIL";
|
||||||
(function() {
|
try {
|
||||||
try {
|
throw 1;
|
||||||
throw 1;
|
} catch (b) {
|
||||||
} catch (b) {
|
(function(b) {
|
||||||
(function(b) {
|
b && b();
|
||||||
b && b();
|
})();
|
||||||
})();
|
b && (a = "PASS");
|
||||||
b && (a = "PASS");
|
}
|
||||||
}
|
|
||||||
})();
|
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
|
@ -862,13 +1293,11 @@ issue_2604_2: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "FAIL";
|
var a = "FAIL";
|
||||||
(function() {
|
try {
|
||||||
try {
|
throw 1;
|
||||||
throw 1;
|
} catch (o) {
|
||||||
} catch (o) {
|
o && (a = "PASS");
|
||||||
o && (a = "PASS");
|
}
|
||||||
}
|
|
||||||
})();
|
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
|
@ -1305,9 +1734,7 @@ issue_2630_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
(function() {
|
while (void (c = 1 + ++c));
|
||||||
while (void (c = 1 + ++c));
|
|
||||||
})(),
|
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
expect_stdout: "2"
|
expect_stdout: "2"
|
||||||
|
|
@ -1338,9 +1765,8 @@ issue_2630_2: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
!function() {
|
while (void (c = 1 + (c += 1)));
|
||||||
while (void (c = 1 + (c += 1)));
|
console.log(c);
|
||||||
}(), console.log(c);
|
|
||||||
}
|
}
|
||||||
expect_stdout: "2"
|
expect_stdout: "2"
|
||||||
}
|
}
|
||||||
|
|
@ -1384,7 +1810,7 @@ issue_2630_3: {
|
||||||
issue_2630_4: {
|
issue_2630_4: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
|
|
@ -1412,6 +1838,35 @@ issue_2630_4: {
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2630_5: {
|
issue_2630_5: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3, a = 1, b = 2;
|
||||||
|
(function() {
|
||||||
|
(function f1() {
|
||||||
|
while (--x >= 0 && f2());
|
||||||
|
}());
|
||||||
|
function f2() {
|
||||||
|
a++ + (b += a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = 3, a = 1, b = 2;
|
||||||
|
while (--x >= 0 && void (b += ++a));
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2630_6: {
|
||||||
options = {
|
options = {
|
||||||
assignments: true,
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
|
@ -4981,10 +5436,9 @@ issue_3833_2: {
|
||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function(a) {
|
var a = void 0;
|
||||||
while (a);
|
while (a);
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
@ -5605,17 +6059,15 @@ issue_4261: {
|
||||||
try {
|
try {
|
||||||
throw 42;
|
throw 42;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
(function() {
|
function g() {
|
||||||
function g() {
|
// `ReferenceError: e is not defined` on Node.js v4-
|
||||||
// `ReferenceError: e is not defined` on Node.js v0.10
|
while (void e.p);
|
||||||
while (void e.p);
|
}
|
||||||
}
|
while (console.log(g()));
|
||||||
while (console.log(g()));
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
node_version: "<0.10 || >=0.12"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_4265: {
|
issue_4265: {
|
||||||
|
|
@ -5975,9 +6427,8 @@ issue_4659_3: {
|
||||||
function f() {
|
function f() {
|
||||||
return a++;
|
return a++;
|
||||||
}
|
}
|
||||||
(function() {
|
f && a++;
|
||||||
while (!console);
|
while (!console);
|
||||||
})(f && a++);
|
|
||||||
(function() {
|
(function() {
|
||||||
var a = console && a;
|
var a = console && a;
|
||||||
})();
|
})();
|
||||||
|
|
@ -7122,9 +7573,7 @@ issue_5237: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
(function() {
|
while (console.log(0/0));
|
||||||
while (console.log(0/0));
|
|
||||||
})();
|
|
||||||
var NaN = console && console.log(NaN);
|
var NaN = console && console.log(NaN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,6 +356,7 @@ mangle_catch_redef_3: {
|
||||||
try {
|
try {
|
||||||
throw 0;
|
throw 0;
|
||||||
} catch (o) {
|
} catch (o) {
|
||||||
|
// prints "FAIL" if inlined on Node.js v4-
|
||||||
(function() {
|
(function() {
|
||||||
function f() {
|
function f() {
|
||||||
o = "FAIL";
|
o = "FAIL";
|
||||||
|
|
@ -366,7 +367,8 @@ mangle_catch_redef_3: {
|
||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
||||||
expect_stdout: true
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_catch_redef_3_toplevel: {
|
mangle_catch_redef_3_toplevel: {
|
||||||
|
|
@ -379,6 +381,7 @@ mangle_catch_redef_3_toplevel: {
|
||||||
try {
|
try {
|
||||||
throw 0;
|
throw 0;
|
||||||
} catch (o) {
|
} catch (o) {
|
||||||
|
// prints "FAIL" if inlined on Node.js v4-
|
||||||
(function() {
|
(function() {
|
||||||
function f() {
|
function f() {
|
||||||
o = "FAIL";
|
o = "FAIL";
|
||||||
|
|
@ -389,7 +392,8 @@ mangle_catch_redef_3_toplevel: {
|
||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
||||||
expect_stdout: true
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_catch_redef_3_ie8: {
|
mangle_catch_redef_3_ie8: {
|
||||||
|
|
@ -402,6 +406,7 @@ mangle_catch_redef_3_ie8: {
|
||||||
try {
|
try {
|
||||||
throw 0;
|
throw 0;
|
||||||
} catch (o) {
|
} catch (o) {
|
||||||
|
// prints "FAIL" if inlined on Node.js v4-
|
||||||
(function() {
|
(function() {
|
||||||
function f() {
|
function f() {
|
||||||
o = "FAIL";
|
o = "FAIL";
|
||||||
|
|
@ -412,7 +417,8 @@ mangle_catch_redef_3_ie8: {
|
||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
||||||
expect_stdout: true
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_catch_redef_3_ie8_toplevel: {
|
mangle_catch_redef_3_ie8_toplevel: {
|
||||||
|
|
@ -425,6 +431,7 @@ mangle_catch_redef_3_ie8_toplevel: {
|
||||||
try {
|
try {
|
||||||
throw 0;
|
throw 0;
|
||||||
} catch (o) {
|
} catch (o) {
|
||||||
|
// prints "FAIL" if inlined on Node.js v4-
|
||||||
(function() {
|
(function() {
|
||||||
function f() {
|
function f() {
|
||||||
o = "FAIL";
|
o = "FAIL";
|
||||||
|
|
@ -435,5 +442,6 @@ mangle_catch_redef_3_ie8_toplevel: {
|
||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
||||||
expect_stdout: true
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
dont_mangle_arguments: {
|
dont_mangle_arguments: {
|
||||||
mangle = {
|
|
||||||
};
|
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
|
@ -21,12 +19,13 @@ dont_mangle_arguments: {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
(function(){
|
(function(){
|
||||||
var arguments = arguments, not_arguments = 9;
|
var arguments = arguments, not_arguments = 9;
|
||||||
console.log(not_arguments, arguments);
|
console.log(not_arguments, arguments);
|
||||||
})(5,6,7);
|
})(5, 6, 7);
|
||||||
}
|
}
|
||||||
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
expect_exact: "(function(){var arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -570,6 +570,50 @@ inlined_assignments: {
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inilne_for: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function() {
|
||||||
|
for (; console.log("PASS"););
|
||||||
|
};
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (; console.log("PASS"););
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
inilne_var: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
A = "PASS";
|
||||||
|
var a = function() {
|
||||||
|
var b = A;
|
||||||
|
for (b in console.log(b));
|
||||||
|
};
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A = "PASS";
|
||||||
|
var b = A;
|
||||||
|
for (b in console.log(b));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
typescript_enum: {
|
typescript_enum: {
|
||||||
rename = true
|
rename = true
|
||||||
options = {
|
options = {
|
||||||
|
|
|
||||||
|
|
@ -1236,7 +1236,8 @@ issues_3267_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
if (Object())
|
var i = Object();
|
||||||
|
if (i)
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
}();
|
}();
|
||||||
|
|
|
||||||
|
|
@ -1054,12 +1054,10 @@ issue_4202: {
|
||||||
"use strict";
|
"use strict";
|
||||||
{
|
{
|
||||||
let o = {};
|
let o = {};
|
||||||
(function() {
|
function f() {
|
||||||
function f() {
|
o.p = 42;
|
||||||
o.p = 42;
|
}
|
||||||
}
|
f(f);
|
||||||
f(f);
|
|
||||||
})();
|
|
||||||
console.log(o.p++);
|
console.log(o.p++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,30 @@ de_morgan_2e: {
|
||||||
node_version: ">=14"
|
node_version: ">=14"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline_binary_nullish: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
})() ?? (function() {
|
||||||
|
while (console.log("bar"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (void 0 === function() {
|
||||||
|
while (console.log("foo"));
|
||||||
|
}())
|
||||||
|
while (console.log("bar"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4679: {
|
issue_4679: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
|
|
||||||
|
|
@ -1363,9 +1363,8 @@ issue_3490_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 42, c = "FAIL";
|
var b = 42, c = "FAIL";
|
||||||
if (function() {
|
var a;
|
||||||
var a;
|
if (c = "PASS", b) while ("" == typeof d);
|
||||||
}(), c = "PASS", b) while ("" == typeof d);
|
|
||||||
console.log(c, b);
|
console.log(c, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS 42"
|
expect_stdout: "PASS 42"
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,8 @@ reduce_vars: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var A = 1;
|
var A = 1;
|
||||||
(function() {
|
console.log(-3);
|
||||||
console.log(-3);
|
console.log(A - 5);
|
||||||
console.log(A - 5);
|
|
||||||
})();
|
|
||||||
(function f1() {
|
(function f1() {
|
||||||
var a = 2;
|
var a = 2;
|
||||||
console.log(a - 5);
|
console.log(a - 5);
|
||||||
|
|
@ -6690,7 +6688,8 @@ issues_3267_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(x) {
|
!function(x) {
|
||||||
if (Object())
|
var i = Object();
|
||||||
|
if (i)
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
}();
|
}();
|
||||||
|
|
|
||||||
|
|
@ -1160,10 +1160,8 @@ issue_3490_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 42, c = "FAIL";
|
var b = 42, c = "FAIL";
|
||||||
if (function() {
|
var a;
|
||||||
var a;
|
if (a && a.p, c = "PASS", b) while ("" == typeof d);
|
||||||
a && a.p;
|
|
||||||
}(), c = "PASS", b) while ("" == typeof d);
|
|
||||||
console.log(c, b);
|
console.log(c, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS 42"
|
expect_stdout: "PASS 42"
|
||||||
|
|
@ -1193,9 +1191,8 @@ issue_3490_2: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 42, c = "FAIL";
|
var b = 42, c = "FAIL";
|
||||||
for (function() {
|
var a;
|
||||||
var a;
|
for (c = "PASS", b; "" == typeof d;);
|
||||||
}(), c = "PASS", b; "" == typeof d;);
|
|
||||||
console.log(c, b);
|
console.log(c, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS 42"
|
expect_stdout: "PASS 42"
|
||||||
|
|
|
||||||
|
|
@ -197,10 +197,8 @@ do_inline_3: {
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
var [] = [ ..."" ];
|
||||||
var [] = [ ..."" ];
|
while (console.log("PASS"));
|
||||||
while (console.log("PASS"));
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ var assert = require("assert");
|
||||||
var exec = require("child_process").exec;
|
var exec = require("child_process").exec;
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var run_code = require("../sandbox").run_code;
|
var run_code = require("../sandbox").run_code;
|
||||||
|
var semver = require("semver");
|
||||||
var to_ascii = require("../node").to_ascii;
|
var to_ascii = require("../node").to_ascii;
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
|
|
@ -12,10 +13,13 @@ describe("bin/uglifyjs", function() {
|
||||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||||
it("Should produce a functional build when using --self", function(done) {
|
it("Should produce a functional build when using --self", function(done) {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
var command = [
|
||||||
exec(command, {
|
uglifyjscmd,
|
||||||
maxBuffer: 1048576
|
"--self",
|
||||||
}, function(err, stdout) {
|
semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc",
|
||||||
|
"--wrap WrappedUglifyJS",
|
||||||
|
].join(" ");
|
||||||
|
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
eval(stdout);
|
eval(stdout);
|
||||||
assert.strictEqual(typeof WrappedUglifyJS, "object");
|
assert.strictEqual(typeof WrappedUglifyJS, "object");
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,26 @@
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var exec = require("child_process").exec;
|
var exec = require("child_process").exec;
|
||||||
|
var semver = require("semver");
|
||||||
var UglifyJS = require("../..");
|
var UglifyJS = require("../..");
|
||||||
|
|
||||||
describe("spidermonkey export/import sanity test", function() {
|
describe("spidermonkey export/import sanity test", function() {
|
||||||
it("Should produce a functional build when using --self with spidermonkey", function(done) {
|
it("Should produce a functional build when using --self with spidermonkey", function(done) {
|
||||||
this.timeout(120000);
|
this.timeout(120000);
|
||||||
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||||
|
var options = semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc";
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey",
|
[
|
||||||
uglifyjs + " -p spidermonkey -cm",
|
uglifyjs,
|
||||||
|
"--self",
|
||||||
|
options,
|
||||||
|
"--wrap SpiderUglify",
|
||||||
|
"-o spidermonkey",
|
||||||
|
].join(" "),
|
||||||
|
[
|
||||||
|
uglifyjs,
|
||||||
|
"-p spidermonkey",
|
||||||
|
options,
|
||||||
|
].join(" "),
|
||||||
].join(" | ");
|
].join(" | ");
|
||||||
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
|
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user