improve handling of non-trivial assignment values (#5227)
This commit is contained in:
335
lib/compress.js
335
lib/compress.js
@@ -1397,9 +1397,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
operator: "+",
|
operator: "+",
|
||||||
expression: make_ref(exp, fixed)
|
expression: make_ref(exp, fixed)
|
||||||
}),
|
}),
|
||||||
right: make_node(AST_Number, node, {
|
right: make_node(AST_Number, node, { value: 1 }),
|
||||||
value: 1
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
d.fixed.assigns = fixed && fixed.assigns ? fixed.assigns.slice() : [];
|
d.fixed.assigns = fixed && fixed.assigns ? fixed.assigns.slice() : [];
|
||||||
@@ -1410,7 +1408,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
exp.fixed = function() {
|
exp.fixed = function() {
|
||||||
return make_node(AST_UnaryPrefix, node, {
|
return make_node(AST_UnaryPrefix, node, {
|
||||||
operator: "+",
|
operator: "+",
|
||||||
expression: make_ref(exp, fixed)
|
expression: make_ref(exp, fixed),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exp.fixed.assigns = fixed && fixed.assigns;
|
exp.fixed.assigns = fixed && fixed.assigns;
|
||||||
@@ -1501,11 +1499,11 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var fixed = this.definition().fixed;
|
var fixed = this.definition().fixed;
|
||||||
if (fixed) {
|
if (fixed) {
|
||||||
if (this.fixed) fixed = this.fixed;
|
if (this.fixed) fixed = this.fixed;
|
||||||
return fixed instanceof AST_Node ? fixed : fixed();
|
return (fixed instanceof AST_Node ? fixed : fixed()).tail_node();
|
||||||
}
|
}
|
||||||
fixed = fixed === 0 && this.fixed;
|
fixed = fixed === 0 && this.fixed;
|
||||||
if (!fixed) return fixed;
|
if (!fixed) return fixed;
|
||||||
var value = fixed instanceof AST_Node ? fixed : fixed();
|
var value = (fixed instanceof AST_Node ? fixed : fixed()).tail_node();
|
||||||
return value.is_constant() && value;
|
return value.is_constant() && value;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1699,7 +1697,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
function merge_sequence(array, node) {
|
function merge_sequence(array, node) {
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
array.push.apply(array, node.expressions);
|
[].push.apply(array, node.expressions);
|
||||||
} else {
|
} else {
|
||||||
array.push(node);
|
array.push(node);
|
||||||
}
|
}
|
||||||
@@ -1813,6 +1811,31 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Certain combination of unused name + side effect leads to invalid AST:
|
||||||
|
// https://github.com/mishoo/UglifyJS/issues/44
|
||||||
|
// https://github.com/mishoo/UglifyJS/issues/1838
|
||||||
|
// https://github.com/mishoo/UglifyJS/issues/3371
|
||||||
|
// We fix it at this stage by moving the `var` outside the `for`.
|
||||||
|
function patch_for_init(node, in_list) {
|
||||||
|
var block;
|
||||||
|
if (node.init instanceof AST_BlockStatement) {
|
||||||
|
block = node.init;
|
||||||
|
node.init = block.body.pop();
|
||||||
|
block.body.push(node);
|
||||||
|
}
|
||||||
|
if (node.init instanceof AST_Defun) {
|
||||||
|
if (!block) block = make_node(AST_BlockStatement, node, { body: [ node ] });
|
||||||
|
block.body.splice(-1, 0, node.init);
|
||||||
|
node.init = null;
|
||||||
|
} else if (node.init instanceof AST_SimpleStatement) {
|
||||||
|
node.init = node.init.body;
|
||||||
|
} else if (is_empty(node.init)) {
|
||||||
|
node.init = null;
|
||||||
|
}
|
||||||
|
if (!block) return;
|
||||||
|
return in_list ? List.splice(block.body) : block;
|
||||||
|
}
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
var in_lambda = last_of(compressor, function(node) {
|
var in_lambda = last_of(compressor, function(node) {
|
||||||
return node instanceof AST_Lambda;
|
return node instanceof AST_Lambda;
|
||||||
@@ -1972,12 +1995,12 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var def = candidate.name.definition();
|
var def = candidate.name.definition();
|
||||||
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
||||||
def.replaced++;
|
def.replaced++;
|
||||||
return maintain_this_binding(compressor, parent, node, candidate.value);
|
return maintain_this_binding(compressor, parent, node, rvalue);
|
||||||
}
|
}
|
||||||
return make_node(AST_Assign, candidate, {
|
return make_node(AST_Assign, candidate, {
|
||||||
operator: "=",
|
operator: "=",
|
||||||
left: make_node(AST_SymbolRef, candidate.name, candidate.name),
|
left: make_node(AST_SymbolRef, candidate.name, candidate.name),
|
||||||
right: candidate.value,
|
right: rvalue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var assign = candidate;
|
var assign = candidate;
|
||||||
@@ -1986,7 +2009,9 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!(assign instanceof AST_Assign)) break;
|
if (!(assign instanceof AST_Assign)) break;
|
||||||
assign = assign.right;
|
assign = assign.right;
|
||||||
}
|
}
|
||||||
return candidate;
|
assign = candidate.clone();
|
||||||
|
assign.right = rvalue;
|
||||||
|
return assign;
|
||||||
}
|
}
|
||||||
// These node types have child nodes that execute sequentially,
|
// These node types have child nodes that execute sequentially,
|
||||||
// but are otherwise not safe to scan into or beyond them.
|
// but are otherwise not safe to scan into or beyond them.
|
||||||
@@ -2083,7 +2108,9 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
// Skip (non-executed) functions and (leading) default case in switch statements
|
// Skip (non-executed) functions and (leading) default case in switch statements
|
||||||
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
||||||
}, patch_sequence);
|
}, function(node) {
|
||||||
|
return patch_sequence(node, multi_replacer);
|
||||||
|
});
|
||||||
while (--stat_index >= 0) {
|
while (--stat_index >= 0) {
|
||||||
// Treat parameters as collapsible in IIFE, i.e.
|
// Treat parameters as collapsible in IIFE, i.e.
|
||||||
// function(a, b){ ... }(x());
|
// function(a, b){ ... }(x());
|
||||||
@@ -2122,7 +2149,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var well_defined = true;
|
var well_defined = true;
|
||||||
var lvalues = get_lvalues(candidate);
|
var lvalues = get_lvalues(candidate);
|
||||||
var lhs_local = is_lhs_local(lhs);
|
var lhs_local = is_lhs_local(lhs);
|
||||||
var rvalue = get_rvalue(candidate);
|
var rhs_value = get_rvalue(candidate);
|
||||||
|
var rvalue;
|
||||||
|
if (rhs_value instanceof AST_Sequence
|
||||||
|
&& !(candidate instanceof AST_Assign && candidate.operator != "=")) {
|
||||||
|
rvalue = rhs_value.tail_node();
|
||||||
|
} else {
|
||||||
|
rvalue = rhs_value;
|
||||||
|
}
|
||||||
if (!side_effects) side_effects = value_has_side_effects();
|
if (!side_effects) side_effects = value_has_side_effects();
|
||||||
var check_destructured = in_try || !lhs_local ? function(node) {
|
var check_destructured = in_try || !lhs_local ? function(node) {
|
||||||
return node instanceof AST_Destructured;
|
return node instanceof AST_Destructured;
|
||||||
@@ -2163,7 +2197,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
value_def.single_use = false;
|
value_def.single_use = false;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (replaced && !remove_candidate(candidate)) statements.splice(stat_index, 1);
|
if (replaced) remove_candidate(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
@@ -2768,6 +2802,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (remaining < 1) return;
|
if (remaining < 1) return;
|
||||||
|
rhs = rhs.tail_node();
|
||||||
var value = rhs instanceof AST_Assign && rhs.operator == "=" ? rhs.left : rhs;
|
var value = rhs instanceof AST_Assign && rhs.operator == "=" ? rhs.left : rhs;
|
||||||
if (!(value instanceof AST_SymbolRef)) return;
|
if (!(value instanceof AST_SymbolRef)) return;
|
||||||
var def = value.definition();
|
var def = value.definition();
|
||||||
@@ -3002,24 +3037,21 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function remove_candidate(expr) {
|
function remove_candidate(expr) {
|
||||||
|
var value = rvalue === rhs_value ? null : make_sequence(rhs_value, rhs_value.expressions.slice(0, -1));
|
||||||
var index = expr.name_index;
|
var index = expr.name_index;
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
var argname = scope.argnames[index];
|
var argname = scope.argnames[index];
|
||||||
if (argname instanceof AST_DefaultValue) {
|
if (argname instanceof AST_DefaultValue) {
|
||||||
argname.value = make_node(AST_Number, argname, {
|
argname.value = value || make_node(AST_Number, argname, { value: 0 });
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
argname.name.definition().fixed = false;
|
argname.name.definition().fixed = false;
|
||||||
} else {
|
} else {
|
||||||
var args = compressor.parent().args;
|
var args = compressor.parent().args;
|
||||||
if (args[index]) {
|
if (args[index]) {
|
||||||
args[index] = make_node(AST_Number, args[index], {
|
args[index] = value || make_node(AST_Number, args[index], { value: 0 });
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
argname.definition().fixed = false;
|
argname.definition().fixed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
var end = hit_stack.length - 1;
|
var end = hit_stack.length - 1;
|
||||||
if (hit_stack[end - 1].body === hit_stack[end]) end--;
|
if (hit_stack[end - 1].body === hit_stack[end]) end--;
|
||||||
@@ -3034,20 +3066,46 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (value_def) value_def.replaced++;
|
if (value_def) value_def.replaced++;
|
||||||
node = node.clone();
|
node = node.clone();
|
||||||
node.value = null;
|
node.value = null;
|
||||||
return node;
|
return value ? List.splice([ value, node ]) : node;
|
||||||
}
|
}
|
||||||
return in_list ? List.skip : null;
|
if (!value) return in_list ? List.skip : null;
|
||||||
}, patch_sequence);
|
return is_statement(node) ? make_node(AST_SimpleStatement, value, { body: value }) : value;
|
||||||
|
}, function(node, in_list) {
|
||||||
|
if (node instanceof AST_Definitions) {
|
||||||
|
var body = [], defns = node.definitions;
|
||||||
|
for (var index = 0, pos = 0; index < defns.length; index++) {
|
||||||
|
var defn = defns[index];
|
||||||
|
if (defn instanceof AST_VarDef) continue;
|
||||||
|
flush();
|
||||||
|
pos = index + 1;
|
||||||
|
body.push(make_node(AST_SimpleStatement, defn, { body: defn }));
|
||||||
|
}
|
||||||
|
if (pos == 0) return;
|
||||||
|
flush();
|
||||||
|
if (body.length == 1) return body[0];
|
||||||
|
return in_list ? List.splice(body) : make_node(AST_BlockStatement, node, { body: body });
|
||||||
|
}
|
||||||
|
if (node instanceof AST_For) return patch_for_init(node, in_list);
|
||||||
|
return patch_sequence(node, this);
|
||||||
|
|
||||||
|
function flush() {
|
||||||
|
if (pos < index) {
|
||||||
|
var cropped = node.clone();
|
||||||
|
cropped.definitions = defns.slice(pos, index);
|
||||||
|
body.push(cropped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
abort = false;
|
abort = false;
|
||||||
hit = false;
|
hit = false;
|
||||||
hit_index = 0;
|
hit_index = 0;
|
||||||
return statements[stat_index].transform(tt);
|
if (!(statements[stat_index] = statements[stat_index].transform(tt))) statements.splice(stat_index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function patch_sequence(node) {
|
function patch_sequence(node, tt) {
|
||||||
if (node instanceof AST_Sequence) switch (node.expressions.length) {
|
if (node instanceof AST_Sequence) switch (node.expressions.length) {
|
||||||
case 0: return null;
|
case 0: return null;
|
||||||
case 1: return maintain_this_binding(compressor, this.parent(), node, node.expressions[0]);
|
case 1: return maintain_this_binding(compressor, tt.parent(), node, node.expressions[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3779,11 +3837,18 @@ Compressor.prototype.compress = function(node) {
|
|||||||
} else if (stat instanceof AST_If) {
|
} else if (stat instanceof AST_If) {
|
||||||
stat.condition = join_assigns_expr(stat.condition);
|
stat.condition = join_assigns_expr(stat.condition);
|
||||||
} else if (stat instanceof AST_SimpleStatement) {
|
} else if (stat instanceof AST_SimpleStatement) {
|
||||||
var exprs = join_assigns(prev, stat.body);
|
var exprs = join_assigns(prev, stat.body), next;
|
||||||
if (exprs) {
|
if (exprs) {
|
||||||
changed = true;
|
changed = true;
|
||||||
if (!exprs.length) continue;
|
if (!exprs.length) continue;
|
||||||
stat.body = make_sequence(stat.body, exprs);
|
stat.body = make_sequence(stat.body, exprs);
|
||||||
|
} else if (prev instanceof AST_Definitions
|
||||||
|
&& (next = statements[i + 1])
|
||||||
|
&& prev.TYPE == next.TYPE
|
||||||
|
&& (next = next.definitions[0]).value) {
|
||||||
|
changed = true;
|
||||||
|
next.value = make_sequence(stat, [ stat.body, next.value ]);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
} else if (stat instanceof AST_Switch) {
|
} else if (stat instanceof AST_Switch) {
|
||||||
stat.expression = join_assigns_expr(stat.expression);
|
stat.expression = join_assigns_expr(stat.expression);
|
||||||
@@ -6690,7 +6755,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
value = null;
|
value = null;
|
||||||
trim_defns.push(def);
|
trim_defns.push(def);
|
||||||
}
|
}
|
||||||
var old_def;
|
var old_def, fn;
|
||||||
if (!value && !(node instanceof AST_Let)) {
|
if (!value && !(node instanceof AST_Let)) {
|
||||||
if (parent instanceof AST_ExportDeclaration) {
|
if (parent instanceof AST_ExportDeclaration) {
|
||||||
flush();
|
flush();
|
||||||
@@ -6704,17 +6769,18 @@ Compressor.prototype.compress = function(node) {
|
|||||||
} else if (compressor.option("functions")
|
} else if (compressor.option("functions")
|
||||||
&& !compressor.option("ie")
|
&& !compressor.option("ie")
|
||||||
&& drop_sym
|
&& drop_sym
|
||||||
|
&& value
|
||||||
&& var_defs[sym.id] == 1
|
&& var_defs[sym.id] == 1
|
||||||
&& sym.assignments == 0
|
&& sym.assignments == 0
|
||||||
&& value instanceof AST_LambdaExpression
|
&& (fn = value.tail_node()) instanceof AST_LambdaExpression
|
||||||
&& !is_arguments(sym)
|
&& !is_arguments(sym)
|
||||||
&& !is_arrow(value)
|
&& !is_arrow(fn)
|
||||||
&& assigned_once(value, sym.references)
|
&& assigned_once(fn, sym.references)
|
||||||
&& can_declare_defun(value)
|
&& can_declare_defun(fn)
|
||||||
&& (old_def = rename_def(value, def.name.name)) !== false) {
|
&& (old_def = rename_def(fn, def.name.name)) !== false) {
|
||||||
AST_Node.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
|
AST_Node.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
|
||||||
var ctor;
|
var ctor;
|
||||||
switch (value.CTOR) {
|
switch (fn.CTOR) {
|
||||||
case AST_AsyncFunction:
|
case AST_AsyncFunction:
|
||||||
ctor = AST_AsyncDefun;
|
ctor = AST_AsyncDefun;
|
||||||
break;
|
break;
|
||||||
@@ -6728,7 +6794,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
ctor = AST_GeneratorDefun;
|
ctor = AST_GeneratorDefun;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var defun = make_node(ctor, def, value);
|
var defun = make_node(ctor, def, fn);
|
||||||
defun.name = make_node(AST_SymbolDefun, def.name, def.name);
|
defun.name = make_node(AST_SymbolDefun, def.name, def.name);
|
||||||
var name_def = def.name.scope.resolve().def_function(defun.name);
|
var name_def = def.name.scope.resolve().def_function(defun.name);
|
||||||
if (old_def) old_def.forEach(function(node) {
|
if (old_def) old_def.forEach(function(node) {
|
||||||
@@ -6737,6 +6803,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
node.reference();
|
node.reference();
|
||||||
});
|
});
|
||||||
body.push(defun);
|
body.push(defun);
|
||||||
|
if (value !== fn) [].push.apply(side_effects, value.expressions.slice(0, -1));
|
||||||
} else {
|
} else {
|
||||||
if (drop_sym
|
if (drop_sym
|
||||||
&& var_defs[sym.id] > 1
|
&& var_defs[sym.id] > 1
|
||||||
@@ -6759,7 +6826,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
head.push(def);
|
head.push(def);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = value && !value.single_use && value.drop_side_effect_free(compressor);
|
value = value && value.drop_side_effect_free(compressor);
|
||||||
if (value) {
|
if (value) {
|
||||||
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
side_effects.push(value);
|
side_effects.push(value);
|
||||||
@@ -6867,13 +6934,18 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
var seq;
|
||||||
|
if (tail.length > 0 && (seq = tail[0].value) instanceof AST_Sequence) {
|
||||||
|
tail[0].value = seq.tail_node();
|
||||||
|
body.push(make_node(AST_SimpleStatement, node, {
|
||||||
|
body: make_sequence(seq, seq.expressions.slice(0, -1)),
|
||||||
|
}));
|
||||||
|
}
|
||||||
node.definitions = head.concat(tail);
|
node.definitions = head.concat(tail);
|
||||||
body.push(node);
|
body.push(node);
|
||||||
}
|
}
|
||||||
if (side_effects.length > 0) {
|
if (side_effects.length > 0) {
|
||||||
body.push(make_node(AST_SimpleStatement, node, {
|
body.push(make_node(AST_SimpleStatement, node, { body: make_sequence(node, side_effects) }));
|
||||||
body: make_sequence(node, side_effects)
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return insert_statements(body, node, in_list);
|
return insert_statements(body, node, in_list);
|
||||||
}
|
}
|
||||||
@@ -6922,33 +6994,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}, function(node, in_list) {
|
}, function(node, in_list) {
|
||||||
if (node instanceof AST_BlockStatement) return trim_block(node, tt.parent(), in_list);
|
if (node instanceof AST_BlockStatement) return trim_block(node, tt.parent(), in_list);
|
||||||
// Certain combination of unused name + side effect leads to invalid AST:
|
if (node instanceof AST_For) return patch_for_init(node, in_list);
|
||||||
// https://github.com/mishoo/UglifyJS/issues/44
|
|
||||||
// https://github.com/mishoo/UglifyJS/issues/1838
|
|
||||||
// https://github.com/mishoo/UglifyJS/issues/3371
|
|
||||||
// We fix it at this stage by moving the `var` outside the `for`.
|
|
||||||
if (node instanceof AST_For) {
|
|
||||||
var block;
|
|
||||||
if (node.init instanceof AST_BlockStatement) {
|
|
||||||
block = node.init;
|
|
||||||
node.init = block.body.pop();
|
|
||||||
block.body.push(node);
|
|
||||||
}
|
|
||||||
if (node.init instanceof AST_Defun) {
|
|
||||||
if (!block) {
|
|
||||||
block = make_node(AST_BlockStatement, node, {
|
|
||||||
body: [ node ]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
block.body.splice(-1, 0, node.init);
|
|
||||||
node.init = null;
|
|
||||||
} else if (node.init instanceof AST_SimpleStatement) {
|
|
||||||
node.init = node.init.body;
|
|
||||||
} else if (is_empty(node.init)) {
|
|
||||||
node.init = null;
|
|
||||||
}
|
|
||||||
return !block ? node : in_list ? List.splice(block.body) : block;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_ForIn) {
|
if (node instanceof AST_ForIn) {
|
||||||
if (!drop_vars || !compressor.option("loops")) return;
|
if (!drop_vars || !compressor.option("loops")) return;
|
||||||
if (!is_empty(node.body)) return;
|
if (!is_empty(node.body)) return;
|
||||||
@@ -8749,15 +8795,21 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var body = [], var_defs = [], refs = [];
|
var body = [], var_defs = [], refs = [];
|
||||||
var body_exprs = sequencesize(self.body, body, var_defs, refs);
|
var body_exprs = sequencesize(self.body, body, var_defs, refs);
|
||||||
var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
|
var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
|
||||||
if (body_exprs && alt_exprs) {
|
if (body_exprs instanceof AST_BlockStatement || alt_exprs instanceof AST_BlockStatement) {
|
||||||
|
if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
|
||||||
|
body.push(self);
|
||||||
|
if (body_exprs instanceof AST_BlockStatement) self.body = body_exprs;
|
||||||
|
if (alt_exprs instanceof AST_BlockStatement) self.alternative = alt_exprs;
|
||||||
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||||
|
} else if (body_exprs && alt_exprs) {
|
||||||
if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
|
if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
|
||||||
if (body_exprs.length == 0) {
|
if (body_exprs.length == 0) {
|
||||||
body.push(make_node(AST_SimpleStatement, self.condition, {
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
|
body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
|
||||||
operator : "||",
|
operator: "||",
|
||||||
left : self.condition,
|
left: self.condition,
|
||||||
right : make_sequence(self.alternative, alt_exprs)
|
right: make_sequence(self.alternative, alt_exprs),
|
||||||
}).transform(compressor) : self.condition.clone()
|
}).transform(compressor) : self.condition.clone(),
|
||||||
}).optimize(compressor));
|
}).optimize(compressor));
|
||||||
} else if (alt_exprs.length == 0) {
|
} else if (alt_exprs.length == 0) {
|
||||||
if (self_condition_length === negated_length && !negated_is_best
|
if (self_condition_length === negated_length && !negated_is_best
|
||||||
@@ -8769,79 +8821,64 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
body.push(make_node(AST_SimpleStatement, self, {
|
body.push(make_node(AST_SimpleStatement, self, {
|
||||||
body: make_node(AST_Binary, self, {
|
body: make_node(AST_Binary, self, {
|
||||||
operator : negated_is_best ? "||" : "&&",
|
operator: negated_is_best ? "||" : "&&",
|
||||||
left : negated_is_best ? negated : self.condition,
|
left: negated_is_best ? negated : self.condition,
|
||||||
right : make_sequence(self.body, body_exprs)
|
right: make_sequence(self.body, body_exprs),
|
||||||
}).transform(compressor)
|
}).transform(compressor),
|
||||||
}).optimize(compressor));
|
}).optimize(compressor));
|
||||||
} else {
|
} else {
|
||||||
body.push(make_node(AST_SimpleStatement, self, {
|
body.push(make_node(AST_SimpleStatement, self, {
|
||||||
body: make_node(AST_Conditional, self, {
|
body: make_node(AST_Conditional, self, {
|
||||||
condition : self.condition,
|
condition: self.condition,
|
||||||
consequent : make_sequence(self.body, body_exprs),
|
consequent: make_sequence(self.body, body_exprs),
|
||||||
alternative : make_sequence(self.alternative, alt_exprs)
|
alternative: make_sequence(self.alternative, alt_exprs),
|
||||||
})
|
}),
|
||||||
}).optimize(compressor));
|
}).optimize(compressor));
|
||||||
}
|
}
|
||||||
refs.forEach(function(ref) {
|
refs.forEach(function(ref) {
|
||||||
ref.definition().references.push(ref);
|
ref.definition().references.push(ref);
|
||||||
});
|
});
|
||||||
return make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||||
body: body
|
|
||||||
}).optimize(compressor);
|
|
||||||
}
|
}
|
||||||
if (is_empty(self.body)) {
|
if (is_empty(self.body)) self = make_node(AST_If, self, {
|
||||||
self = make_node(AST_If, self, {
|
condition: negated,
|
||||||
condition: negated,
|
body: self.alternative,
|
||||||
body: self.alternative,
|
alternative: null,
|
||||||
alternative: null
|
});
|
||||||
});
|
if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
|
||||||
}
|
|
||||||
if (self.body instanceof AST_Exit
|
|
||||||
&& self.alternative instanceof AST_Exit
|
|
||||||
&& self.body.TYPE == self.alternative.TYPE) {
|
|
||||||
var exit = make_node(self.body.CTOR, self, {
|
var exit = make_node(self.body.CTOR, self, {
|
||||||
value: make_node(AST_Conditional, self, {
|
value: make_node(AST_Conditional, self, {
|
||||||
condition : self.condition,
|
condition: self.condition,
|
||||||
consequent : self.body.value || make_node(AST_Undefined, self.body).transform(compressor),
|
consequent: self.body.value || make_node(AST_Undefined, self.body).transform(compressor),
|
||||||
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).transform(compressor)
|
alternative: self.alternative.value
|
||||||
})
|
|| make_node(AST_Undefined, self.alternative).transform(compressor),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
if (exit instanceof AST_Return) {
|
if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
|
||||||
exit.in_bool = self.body.in_bool || self.alternative.in_bool;
|
|
||||||
}
|
|
||||||
return exit;
|
return exit;
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_If
|
if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
|
||||||
&& !self.body.alternative
|
|
||||||
&& !self.alternative) {
|
|
||||||
self = make_node(AST_If, self, {
|
self = make_node(AST_If, self, {
|
||||||
condition: make_node(AST_Binary, self.condition, {
|
condition: make_node(AST_Binary, self.condition, {
|
||||||
operator: "&&",
|
operator: "&&",
|
||||||
left: self.condition,
|
left: self.condition,
|
||||||
right: self.body.condition
|
right: self.body.condition,
|
||||||
}),
|
}),
|
||||||
body: self.body.body,
|
body: self.body.body,
|
||||||
alternative: null
|
alternative: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (aborts(self.body)) {
|
if (aborts(self.body) && self.alternative) {
|
||||||
if (self.alternative) {
|
var alt = self.alternative;
|
||||||
var alt = self.alternative;
|
self.alternative = null;
|
||||||
self.alternative = null;
|
return make_node(AST_BlockStatement, self, { body: [ self, alt ] }).optimize(compressor);
|
||||||
return make_node(AST_BlockStatement, self, {
|
|
||||||
body: [ self, alt ]
|
|
||||||
}).optimize(compressor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (aborts(self.alternative)) {
|
if (aborts(self.alternative)) {
|
||||||
var body = self.body;
|
var body = self.body;
|
||||||
self.body = self.alternative;
|
self.body = self.alternative;
|
||||||
self.condition = negated_is_best ? negated : self.condition.negate(compressor);
|
self.condition = negated_is_best ? negated : self.condition.negate(compressor);
|
||||||
self.alternative = null;
|
self.alternative = null;
|
||||||
return make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, { body: [ self, body ] }).optimize(compressor);
|
||||||
body: [ self, body ]
|
|
||||||
}).optimize(compressor);
|
|
||||||
}
|
}
|
||||||
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
|
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
|
||||||
return self;
|
return self;
|
||||||
@@ -8852,10 +8889,19 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var exprs = [];
|
var exprs = [];
|
||||||
for (var i = 0; i < stat.body.length; i++) {
|
for (var i = 0; i < stat.body.length; i++) {
|
||||||
var line = stat.body[i];
|
var line = stat.body[i];
|
||||||
|
if (line instanceof AST_EmptyStatement) continue;
|
||||||
|
if (line instanceof AST_Exit) {
|
||||||
|
if (exprs.length == 0) return;
|
||||||
|
line = line.clone();
|
||||||
|
exprs.push(line.value || make_node(AST_Undefined, line).transform(compressor));
|
||||||
|
line.value = make_sequence(stat, exprs);
|
||||||
|
var block = stat.clone();
|
||||||
|
block.body = block.body.slice(i + 1);
|
||||||
|
block.body.unshift(line);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
if (line instanceof AST_LambdaDefinition) {
|
if (line instanceof AST_LambdaDefinition) {
|
||||||
defuns.push(line);
|
defuns.push(line);
|
||||||
} else if (line instanceof AST_EmptyStatement) {
|
|
||||||
continue;
|
|
||||||
} else if (line instanceof AST_SimpleStatement) {
|
} else if (line instanceof AST_SimpleStatement) {
|
||||||
if (!compressor.option("sequences") && exprs.length > 0) return;
|
if (!compressor.option("sequences") && exprs.length > 0) return;
|
||||||
exprs.push(line.body);
|
exprs.push(line.body);
|
||||||
@@ -9320,9 +9366,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
args[pos++] = make_sequence(call, side_effects);
|
args[pos++] = make_sequence(call, side_effects);
|
||||||
side_effects = [];
|
side_effects = [];
|
||||||
} else {
|
} else {
|
||||||
args[pos++] = make_node(AST_Number, args[i], {
|
args[pos++] = make_node(AST_Number, args[i], { value: 0 });
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9924,10 +9968,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
var line = fn.body[i];
|
var line = fn.body[i];
|
||||||
if (line instanceof AST_Var) {
|
if (line instanceof AST_Var) {
|
||||||
var assigned = var_assigned || !declarations_only(line);
|
if (var_assigned) {
|
||||||
if (assigned) {
|
if (!stat) continue;
|
||||||
|
if (!(stat instanceof AST_SimpleStatement)) return false;
|
||||||
|
if (!declarations_only(line)) stat = null;
|
||||||
|
} else if (!declarations_only(line)) {
|
||||||
|
if (stat && !(stat instanceof AST_SimpleStatement)) return false;
|
||||||
|
stat = null;
|
||||||
var_assigned = true;
|
var_assigned = true;
|
||||||
if (stat) return false;
|
|
||||||
}
|
}
|
||||||
} else if (line instanceof AST_AsyncDefun
|
} else if (line instanceof AST_AsyncDefun
|
||||||
|| line instanceof AST_Defun
|
|| line instanceof AST_Defun
|
||||||
@@ -10191,7 +10239,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
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 = [];
|
var decl_var = [], expr_var = [], expr_loop = [], exprs = [];
|
||||||
for (var i = 0; i < fn.body.length; i++) {
|
for (var i = 0; i < fn.body.length; i++) {
|
||||||
var stat = fn.body[i];
|
var stat = fn.body[i];
|
||||||
if (stat instanceof AST_LambdaDefinition) {
|
if (stat instanceof AST_LambdaDefinition) {
|
||||||
@@ -10209,11 +10257,20 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(stat instanceof AST_Var)) continue;
|
if (!(stat instanceof AST_Var)) {
|
||||||
|
if (stat instanceof AST_SimpleStatement) exprs.push(stat.body);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
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];
|
||||||
var name = flatten_var(var_def.name);
|
var name = flatten_var(var_def.name);
|
||||||
append_var(decl_var, expr_var, name, var_def.value);
|
var value = var_def.value;
|
||||||
|
if (value && exprs.length > 0) {
|
||||||
|
exprs.push(value);
|
||||||
|
value = make_sequence(var_def, exprs);
|
||||||
|
exprs = [];
|
||||||
|
}
|
||||||
|
append_var(decl_var, expr_var, name, value);
|
||||||
if (in_loop && !arg_used.has(name.name)) {
|
if (in_loop && !arg_used.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);
|
||||||
@@ -12211,9 +12268,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function pop_seq(node) {
|
function pop_seq(node) {
|
||||||
if (!(node instanceof AST_Sequence)) return make_node(AST_Number, node, {
|
if (!(node instanceof AST_Sequence)) return make_node(AST_Number, node, { value: 0 });
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
return make_sequence(node, node.expressions.slice(0, -1));
|
return make_sequence(node, node.expressions.slice(0, -1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -12526,35 +12581,25 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var exp = self.expression.expression;
|
var exp = self.expression.expression;
|
||||||
if (is_undeclared_ref(exp)) switch (exp.name) {
|
if (is_undeclared_ref(exp)) switch (exp.name) {
|
||||||
case "Array":
|
case "Array":
|
||||||
self.expression = make_node(AST_Array, self.expression, {
|
self.expression = make_node(AST_Array, self.expression, { elements: [] });
|
||||||
elements: []
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "Function":
|
case "Function":
|
||||||
self.expression = make_node(AST_Function, self.expression, {
|
self.expression = make_node(AST_Function, self.expression, {
|
||||||
argnames: [],
|
argnames: [],
|
||||||
body: []
|
body: [],
|
||||||
}).init_vars(exp.scope);
|
}).init_vars(exp.scope);
|
||||||
break;
|
break;
|
||||||
case "Number":
|
case "Number":
|
||||||
self.expression = make_node(AST_Number, self.expression, {
|
self.expression = make_node(AST_Number, self.expression, { value: 0 });
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "Object":
|
case "Object":
|
||||||
self.expression = make_node(AST_Object, self.expression, {
|
self.expression = make_node(AST_Object, self.expression, { properties: [] });
|
||||||
properties: []
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "RegExp":
|
case "RegExp":
|
||||||
self.expression = make_node(AST_RegExp, self.expression, {
|
self.expression = make_node(AST_RegExp, self.expression, { value: /t/ });
|
||||||
value: /t/
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "String":
|
case "String":
|
||||||
self.expression = make_node(AST_String, self.expression, {
|
self.expression = make_node(AST_String, self.expression, { value: "" });
|
||||||
value: ""
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ logical_assignments: {
|
|||||||
node_version: ">=15"
|
node_version: ">=15"
|
||||||
}
|
}
|
||||||
|
|
||||||
logical_collapse_vars: {
|
logical_collapse_vars_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
}
|
}
|
||||||
@@ -509,6 +509,27 @@ logical_collapse_vars: {
|
|||||||
node_version: ">=15"
|
node_version: ">=15"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logical_collapse_vars_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
b ||= (a = "FAIL", {});
|
||||||
|
return b;
|
||||||
|
})(console).log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
return b ||= (a = "FAIL", {});
|
||||||
|
})(console).log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=15"
|
||||||
|
}
|
||||||
|
|
||||||
logical_reduce_vars: {
|
logical_reduce_vars: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
|||||||
@@ -346,9 +346,7 @@ collapse_vars_if: {
|
|||||||
return "x" != "Bar" + x / 4 ? g9 : g5;
|
return "x" != "Bar" + x / 4 ? g9 : g5;
|
||||||
}
|
}
|
||||||
function f3(x) {
|
function f3(x) {
|
||||||
if (x)
|
return x ? 1 : 2;
|
||||||
return 1;
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1912,6 +1910,42 @@ collapse_vars_regexp: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapse_arg_sequence: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
a("foo");
|
||||||
|
})((console.log("bar"), console.log));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(0, console.log)("foo");
|
||||||
|
})(console.log("bar"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_for_init: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a = (Math, console), b = a.log("PASS"); b;);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
Math;
|
||||||
|
for (var a, b = console.log("PASS"); b;);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_1537: {
|
issue_1537: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -2667,6 +2701,24 @@ chained_4: {
|
|||||||
expect_stdout: "foo undefined"
|
expect_stdout: "foo undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chained_5: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
var a = (console, console.log(a));
|
||||||
|
a && ++a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
console;
|
||||||
|
var a;
|
||||||
|
(a = console.log(a)) && ++a;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
boolean_binary_1: {
|
boolean_binary_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -2906,6 +2958,43 @@ compound_assignment_2: {
|
|||||||
expect_stdout: "4"
|
expect_stdout: "4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compound_assignment_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
a += (console.log("PASS"), 2);
|
||||||
|
a.p;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
(a += (console.log("PASS"), 2)).p;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
compound_assignment_4: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
A = "PASS";
|
||||||
|
var a = "";
|
||||||
|
a += (a = "FAIL", A);
|
||||||
|
a.p;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A = "PASS";
|
||||||
|
var a = "";
|
||||||
|
(a += (a = "FAIL", A)).p;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2187_1: {
|
issue_2187_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -3030,10 +3119,10 @@ issue_2203_2: {
|
|||||||
a: "FAIL",
|
a: "FAIL",
|
||||||
b: function() {
|
b: function() {
|
||||||
return function(c) {
|
return function(c) {
|
||||||
return (String, (Object, function() {
|
return (Object, function() {
|
||||||
return this;
|
return this;
|
||||||
}())).a;
|
}()).a;
|
||||||
}();
|
}(String);
|
||||||
}
|
}
|
||||||
}.b());
|
}.b());
|
||||||
}
|
}
|
||||||
@@ -3764,17 +3853,17 @@ issue_2437_1: {
|
|||||||
console.log(foo());
|
console.log(foo());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
var req, detectFunc, result;
|
||||||
if (xhrDesc) {
|
console.log((
|
||||||
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
|
xhrDesc ? (result = !!(req = new XMLHttpRequest).onreadystatechange,
|
||||||
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc||{})
|
||||||
result;
|
) : (
|
||||||
}
|
(req = new XMLHttpRequest).onreadystatechange = detectFunc = function(){},
|
||||||
var req = new XMLHttpRequest(), detectFunc = function(){};
|
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
|
||||||
return req.onreadystatechange = detectFunc,
|
req.onreadystatechange = null
|
||||||
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
|
),
|
||||||
req.onreadystatechange = null, result;
|
result
|
||||||
}());
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3815,15 +3904,15 @@ issue_2437_2: {
|
|||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
var req;
|
||||||
if (xhrDesc)
|
xhrDesc ? (
|
||||||
return (req = new XMLHttpRequest()).onreadystatechange,
|
(req = new XMLHttpRequest).onreadystatechange,
|
||||||
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {});
|
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {})
|
||||||
var req = new XMLHttpRequest();
|
) : (
|
||||||
req.onreadystatechange = function(){},
|
(req = new XMLHttpRequest).onreadystatechange = function(){},
|
||||||
req[SYMBOL_FAKE_ONREADYSTATECHANGE_1],
|
req[SYMBOL_FAKE_ONREADYSTATECHANGE_1],
|
||||||
req.onreadystatechange = null;
|
req.onreadystatechange = null
|
||||||
}();
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6445,7 +6534,8 @@ assign_undeclared: {
|
|||||||
console.log(typeof B);
|
console.log(typeof B);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
B = new (console.log(42), function() {})();
|
console.log(42);
|
||||||
|
B = new function() {}();
|
||||||
console.log(typeof B);
|
console.log(typeof B);
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
@@ -9141,9 +9231,7 @@ issue_4908: {
|
|||||||
console.log(d[1]);
|
console.log(d[1]);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = 0, b;
|
var a = 0, b, c = (console || a++, a), d = [ (d = a) && d, d += 42 ];
|
||||||
console || a++;
|
|
||||||
var c = a, d = [ (d = a) && d, d += 42 ];
|
|
||||||
console.log(d[1]);
|
console.log(d[1]);
|
||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
|
|||||||
@@ -158,6 +158,28 @@ process_boolean_returns: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapse_arg_sequence: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a = (console.log("bar"), console.log)) {
|
||||||
|
a("foo");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a = console.log("bar")) {
|
||||||
|
(0, console.log)("foo");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
collapse_value_1: {
|
collapse_value_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
|||||||
@@ -395,7 +395,8 @@ funarg_unused_6_keep_fargs: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
var {} = (console, 42);
|
console;
|
||||||
|
var {} = 42;
|
||||||
})();
|
})();
|
||||||
console.log(typeof a);
|
console.log(typeof a);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1728,7 +1728,8 @@ issue_2768: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "FAIL";
|
var a = "FAIL";
|
||||||
var c = (d = a, void (d && (a = "PASS")));
|
d = a;
|
||||||
|
var c = void (d && (a = "PASS"));
|
||||||
var d;
|
var d;
|
||||||
console.log(a, typeof c);
|
console.log(a, typeof c);
|
||||||
}
|
}
|
||||||
@@ -2382,7 +2383,8 @@ issue_3664: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
console.log(function() {
|
||||||
var a, b = (a = (a = [ b && console.log("FAIL") ]).p = 0, 0);
|
a = (a = [ b && console.log("FAIL") ]).p = 0;
|
||||||
|
var a, b = 0;
|
||||||
return "PASS";
|
return "PASS";
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
@@ -2551,10 +2553,9 @@ issue_3899: {
|
|||||||
console.log(typeof a);
|
console.log(typeof a);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function a() {
|
console.log(typeof function() {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
});
|
||||||
console.log(typeof a);
|
|
||||||
}
|
}
|
||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ issue_4664: {
|
|||||||
expect: {
|
expect: {
|
||||||
(function f() {
|
(function f() {
|
||||||
new function(a) {
|
new function(a) {
|
||||||
console.log(typeof f, a, typeof this);
|
console.log(typeof f, 2 ** 30, typeof this);
|
||||||
}((A = 0, 2 ** 30));
|
}(A = 0);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: "function 1073741824 object"
|
expect_stdout: "function 1073741824 object"
|
||||||
|
|||||||
@@ -3039,18 +3039,17 @@ issue_2437: {
|
|||||||
console.log(foo());
|
console.log(foo());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
var req, detectFunc, result;
|
||||||
if (xhrDesc) {
|
console.log((
|
||||||
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
|
xhrDesc ? (
|
||||||
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
result = !!(req = new XMLHttpRequest).onreadystatechange,
|
||||||
result;
|
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {})
|
||||||
}
|
) : (
|
||||||
function detectFunc() {}
|
(req = new XMLHttpRequest).onreadystatechange = detectFunc = function(){},
|
||||||
var req = new XMLHttpRequest();
|
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,req.onreadystatechange = null
|
||||||
return req.onreadystatechange = detectFunc,
|
),
|
||||||
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
|
result
|
||||||
req.onreadystatechange = null, result;
|
));
|
||||||
}());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3826,16 +3825,14 @@ inlined_single_use: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(f) {
|
console.log(function(f) {
|
||||||
var a = function() {
|
a = function() {
|
||||||
A;
|
A;
|
||||||
};
|
},
|
||||||
var b = function() {
|
b = function() {
|
||||||
a(B);
|
a(B);
|
||||||
};
|
},
|
||||||
(function() {
|
void 0;
|
||||||
b;
|
var a, b;
|
||||||
});
|
|
||||||
return;
|
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
@@ -5290,6 +5287,42 @@ direct_inline_catch_redefined: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statement_var_inline: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
(function() {
|
||||||
|
var a = {};
|
||||||
|
function g() {
|
||||||
|
a.p;
|
||||||
|
}
|
||||||
|
g(console.log("PASS"));
|
||||||
|
var b = function h(c) {
|
||||||
|
c && c.q;
|
||||||
|
}();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var c, a = {};
|
||||||
|
function g() {
|
||||||
|
a.p;
|
||||||
|
}
|
||||||
|
g(console.log("PASS"));
|
||||||
|
c && c.q;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4171_1: {
|
issue_4171_1: {
|
||||||
options = {
|
options = {
|
||||||
functions: true,
|
functions: true,
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ issue_4736: {
|
|||||||
(function() {
|
(function() {
|
||||||
(function() {
|
(function() {
|
||||||
0,
|
0,
|
||||||
console.log(1073741824);
|
console.log(1 << 30);
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@@ -336,7 +336,7 @@ issue_4859: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function f(a) {
|
(function f(a) {
|
||||||
console.log(Infinity);
|
console.log(2 + 1 / 0);
|
||||||
return f;
|
return f;
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1282,10 +1282,7 @@ assign_sequence_var: {
|
|||||||
console.log(a, b, c);
|
console.log(a, b, c);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = 0, b = 1;
|
var a = 0, b = 1, c = (console.log(a), a++, b = 2, 3);
|
||||||
console.log(a),
|
|
||||||
a++;
|
|
||||||
var b = 2, c = 3;
|
|
||||||
console.log(a, b, c);
|
console.log(a, b, c);
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
|
|||||||
@@ -181,10 +181,10 @@ issue_2203_2: {
|
|||||||
a: "FAIL",
|
a: "FAIL",
|
||||||
b: function() {
|
b: function() {
|
||||||
return function() {
|
return function() {
|
||||||
return (String, (Object, function() {
|
return (Object, function() {
|
||||||
return this;
|
return this;
|
||||||
}())).a;
|
}()).a;
|
||||||
}();
|
}(String);
|
||||||
}
|
}
|
||||||
}.b());
|
}.b());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -910,9 +910,7 @@ hoist_decl: {
|
|||||||
var d;
|
var d;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
var a, b = (w(), x()), c, d;
|
||||||
w();
|
|
||||||
var b = x(), c, d;
|
|
||||||
for (y(); 0;) z();
|
for (y(); 0;) z();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,8 +205,8 @@ describe("sourcemaps", function() {
|
|||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code, [
|
assert.strictEqual(result.code, [
|
||||||
"var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
|
"var Foo=function(){console.log(3)},bar=(new Foo,function(o){return o});",
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElDQWxDQyxLREEyQyxJQUFJSCxJQ0MvQyxTQUFjRyxHQUNWLE9BQU9BIn0=",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
|
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user