Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a82003d6ac | ||
|
|
da9f1622fc | ||
|
|
8a4c7077bb | ||
|
|
0a63f2f2b0 | ||
|
|
931ac66638 | ||
|
|
35338a100f | ||
|
|
d57b606e73 | ||
|
|
00ada04111 | ||
|
|
a31c477fea | ||
|
|
bde7418ce1 | ||
|
|
70bb304a0a | ||
|
|
9d3b1efd86 | ||
|
|
482e1baea3 |
198
lib/compress.js
198
lib/compress.js
@@ -1293,6 +1293,7 @@ merge(Compressor.prototype, {
|
||||
return lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression);
|
||||
}
|
||||
if (node instanceof AST_Debugger) return true;
|
||||
if (node instanceof AST_Defun) return funarg && lhs.name === node.name.name;
|
||||
if (node instanceof AST_IterationStatement) return !(node instanceof AST_For);
|
||||
if (node instanceof AST_LoopControl) return true;
|
||||
if (node instanceof AST_Try) return true;
|
||||
@@ -2282,8 +2283,7 @@ merge(Compressor.prototype, {
|
||||
// returns true if this node may be null, undefined or contain `AST_Accessor`
|
||||
(function(def) {
|
||||
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
|
||||
return !compressor.option("pure_getters")
|
||||
|| this._dot_throw(compressor);
|
||||
return !compressor.option("pure_getters") || this._dot_throw(compressor);
|
||||
});
|
||||
function is_strict(compressor) {
|
||||
return /strict/.test(compressor.option("pure_getters"));
|
||||
@@ -2291,7 +2291,15 @@ merge(Compressor.prototype, {
|
||||
def(AST_Node, is_strict);
|
||||
def(AST_Array, return_false);
|
||||
def(AST_Assign, function(compressor) {
|
||||
return this.operator == "=" && this.right._dot_throw(compressor);
|
||||
if (this.operator != "=") return false;
|
||||
var rhs = this.right;
|
||||
if (!rhs._dot_throw(compressor)) return false;
|
||||
var sym = this.left;
|
||||
if (!(sym instanceof AST_SymbolRef)) return true;
|
||||
if (rhs instanceof AST_Binary && rhs.operator == "||" && sym.name == rhs.left.name) {
|
||||
return rhs.right._dot_throw(compressor);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
def(AST_Binary, function(compressor) {
|
||||
return lazy_op[this.operator] && (this.left._dot_throw(compressor) || this.right._dot_throw(compressor));
|
||||
@@ -3392,16 +3400,28 @@ merge(Compressor.prototype, {
|
||||
def(AST_Lambda, function(scope) {
|
||||
var self = this;
|
||||
var result = true;
|
||||
self.walk(new TreeWalker(function(node) {
|
||||
var inner_scopes = [];
|
||||
self.walk(new TreeWalker(function(node, descend) {
|
||||
if (!result) return true;
|
||||
if (node instanceof AST_Catch) {
|
||||
inner_scopes.push(node.argname.scope);
|
||||
descend();
|
||||
inner_scopes.pop();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope && node !== self) {
|
||||
inner_scopes.push(node);
|
||||
descend();
|
||||
inner_scopes.pop();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
if (self.inlined) {
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
var def = node.definition();
|
||||
if (member(def, self.enclosed)
|
||||
&& !self.variables.has(def.name)) {
|
||||
if (!self.variables.has(def.name) && !member(def.scope, inner_scopes)) {
|
||||
if (scope) {
|
||||
var scope_def = scope.find_variable(node);
|
||||
if (def.undeclared ? !scope_def : scope_def === def) {
|
||||
@@ -3618,7 +3638,7 @@ merge(Compressor.prototype, {
|
||||
var value = null;
|
||||
if (node instanceof AST_Assign) {
|
||||
if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) {
|
||||
value = node.right;
|
||||
value = get_rhs(node);
|
||||
}
|
||||
} else if (!in_use) {
|
||||
value = make_node(AST_Number, node, {
|
||||
@@ -3843,6 +3863,15 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function get_rhs(assign) {
|
||||
var rhs = assign.right;
|
||||
if (!assign.write_only) return rhs;
|
||||
if (!(rhs instanceof AST_Binary && lazy_op[rhs.operator])) return rhs;
|
||||
var sym = assign.left;
|
||||
if (!(sym instanceof AST_SymbolRef) || sym.name != rhs.left.name) return rhs;
|
||||
return rhs.right.has_side_effects(compressor) ? rhs : rhs.right;
|
||||
}
|
||||
|
||||
function scan_ref_scoped(node, descend) {
|
||||
var node_def, props = [], sym = assign_as_unused(node, props);
|
||||
if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) {
|
||||
@@ -3850,9 +3879,10 @@ merge(Compressor.prototype, {
|
||||
prop.walk(tw);
|
||||
});
|
||||
if (node instanceof AST_Assign) {
|
||||
node.right.walk(tw);
|
||||
var right = get_rhs(node);
|
||||
right.walk(tw);
|
||||
if (node.left === sym) {
|
||||
if (!node_def.chained && sym.fixed_value(true) === node.right) {
|
||||
if (!node_def.chained && sym.fixed_value(true) === right) {
|
||||
fixed_ids[node_def.id] = node;
|
||||
}
|
||||
if (!node.write_only) {
|
||||
@@ -4038,10 +4068,11 @@ merge(Compressor.prototype, {
|
||||
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||
var defs_by_id = Object.create(null);
|
||||
self.transform(new TreeTransformer(function(node, descend) {
|
||||
if (node instanceof AST_Assign
|
||||
&& node.operator == "="
|
||||
&& node.write_only
|
||||
&& can_hoist(node.left, node.right, 1)) {
|
||||
if (node instanceof AST_Assign) {
|
||||
if (node.operator != "=") return;
|
||||
if (!node.write_only) return;
|
||||
if (node.left.scope !== self) return;
|
||||
if (!can_hoist(node.left, node.right, 1)) return;
|
||||
descend(node, this);
|
||||
var defs = new Dictionary();
|
||||
var assignments = [];
|
||||
@@ -4070,17 +4101,9 @@ merge(Compressor.prototype, {
|
||||
}));
|
||||
return make_sequence(node, assignments);
|
||||
}
|
||||
if (node instanceof AST_Unary
|
||||
&& !unary_side_effects[node.operator]
|
||||
&& node.expression instanceof AST_SymbolRef
|
||||
&& node.expression.definition().id in defs_by_id) {
|
||||
node = node.clone();
|
||||
node.expression = make_node(AST_Object, node, {
|
||||
properties: []
|
||||
});
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) {
|
||||
if (node instanceof AST_Scope) return node === self ? undefined : node;
|
||||
if (node instanceof AST_VarDef) {
|
||||
if (!can_hoist(node.name, node.value, 0)) return;
|
||||
descend(node, this);
|
||||
var defs = new Dictionary();
|
||||
var var_defs = [];
|
||||
@@ -4093,32 +4116,6 @@ merge(Compressor.prototype, {
|
||||
defs_by_id[node.name.definition().id] = defs;
|
||||
return MAP.splice(var_defs);
|
||||
}
|
||||
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
||||
var defs = defs_by_id[node.expression.definition().id];
|
||||
if (defs) {
|
||||
var def = defs.get(node.getProperty());
|
||||
var sym = make_node(AST_SymbolRef, node, {
|
||||
name: def.name,
|
||||
scope: node.expression.scope,
|
||||
thedef: def
|
||||
});
|
||||
sym.reference({});
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
|
||||
function can_hoist(sym, right, count) {
|
||||
if (sym.scope !== self) return;
|
||||
var def = sym.definition();
|
||||
if (def.assignments != count) return;
|
||||
if (def.direct_access) return;
|
||||
if (def.escaped.depth == 1) return;
|
||||
if (def.references.length == count) return;
|
||||
if (def.single_use) return;
|
||||
if (top_retain(def)) return;
|
||||
if (sym.fixed_value() !== right) return;
|
||||
return right instanceof AST_Object;
|
||||
}
|
||||
|
||||
function make_sym(sym, key) {
|
||||
var new_var = make_node(AST_SymbolVar, sym, {
|
||||
@@ -4131,6 +4128,43 @@ merge(Compressor.prototype, {
|
||||
return new_var;
|
||||
}
|
||||
}));
|
||||
self.transform(new TreeTransformer(function(node, descend) {
|
||||
if (node instanceof AST_PropAccess) {
|
||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||
var defs = defs_by_id[node.expression.definition().id];
|
||||
if (!defs) return;
|
||||
var def = defs.get(node.getProperty());
|
||||
var sym = make_node(AST_SymbolRef, node, {
|
||||
name: def.name,
|
||||
scope: node.expression.scope,
|
||||
thedef: def
|
||||
});
|
||||
sym.reference({});
|
||||
return sym;
|
||||
}
|
||||
if (node instanceof AST_Unary) {
|
||||
if (unary_side_effects[node.operator]) return;
|
||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||
if (!(node.expression.definition().id in defs_by_id)) return;
|
||||
var opt = node.clone();
|
||||
opt.expression = make_node(AST_Object, node, {
|
||||
properties: []
|
||||
});
|
||||
return opt;
|
||||
}
|
||||
}));
|
||||
|
||||
function can_hoist(sym, right, count) {
|
||||
var def = sym.definition();
|
||||
if (def.assignments != count) return;
|
||||
if (def.direct_access) return;
|
||||
if (def.escaped.depth == 1) return;
|
||||
if (def.references.length == count) return;
|
||||
if (def.single_use) return;
|
||||
if (top_retain(def)) return;
|
||||
if (sym.fixed_value() !== right) return;
|
||||
return right instanceof AST_Object;
|
||||
}
|
||||
});
|
||||
|
||||
// drop_side_effect_free()
|
||||
@@ -4163,12 +4197,14 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
def(AST_Assign, function(compressor) {
|
||||
var left = this.left;
|
||||
if (left.has_side_effects(compressor)
|
||||
|| compressor.has_directive("use strict")
|
||||
&& left instanceof AST_PropAccess
|
||||
&& left.expression.is_constant()) {
|
||||
return this;
|
||||
if (left instanceof AST_PropAccess) {
|
||||
var expr = left.expression;
|
||||
if (expr instanceof AST_Assign && !expr.may_throw_on_access(compressor)) {
|
||||
expr.write_only = true;
|
||||
}
|
||||
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
||||
}
|
||||
if (left.has_side_effects(compressor)) return this;
|
||||
this.write_only = true;
|
||||
if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) {
|
||||
return this.right.drop_side_effect_free(compressor);
|
||||
@@ -4243,8 +4279,9 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
def(AST_Constant, return_null);
|
||||
def(AST_Dot, function(compressor, first_in_statement) {
|
||||
if (this.expression.may_throw_on_access(compressor)) return this;
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
var expr = this.expression;
|
||||
if (expr.may_throw_on_access(compressor)) return this;
|
||||
return expr.drop_side_effect_free(compressor, first_in_statement);
|
||||
});
|
||||
def(AST_Function, function(compressor) {
|
||||
return this.name && compressor.option("ie8") ? this : null;
|
||||
@@ -5200,25 +5237,26 @@ merge(Compressor.prototype, {
|
||||
return return_value(stat);
|
||||
}
|
||||
|
||||
function var_exists(catches, name) {
|
||||
return catches[name] || identifier_atom[name] || scope.var_names()[name];
|
||||
function var_exists(defined, name) {
|
||||
return defined[name] || identifier_atom[name] || scope.var_names()[name];
|
||||
}
|
||||
|
||||
function can_inject_args(catches, safe_to_inject) {
|
||||
function can_inject_args(catches, used, safe_to_inject) {
|
||||
for (var i = 0; i < fn.argnames.length; i++) {
|
||||
var arg = fn.argnames[i];
|
||||
if (arg.__unused) continue;
|
||||
if (!safe_to_inject || var_exists(catches, arg.name)) return false;
|
||||
used[arg.name] = true;
|
||||
if (in_loop) in_loop.push(arg.definition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function can_inject_vars(catches, safe_to_inject) {
|
||||
function can_inject_vars(catches, used, safe_to_inject) {
|
||||
for (var i = 0; i < fn.body.length; i++) {
|
||||
var stat = fn.body[i];
|
||||
if (stat instanceof AST_Defun) {
|
||||
if (!safe_to_inject || var_exists(catches, stat.name.name)) return false;
|
||||
if (!safe_to_inject || var_exists(used, stat.name.name)) return false;
|
||||
continue;
|
||||
}
|
||||
if (!(stat instanceof AST_Var)) continue;
|
||||
@@ -5247,8 +5285,9 @@ merge(Compressor.prototype, {
|
||||
var safe_to_inject = (!(scope instanceof AST_Toplevel) || compressor.toplevel.vars)
|
||||
&& (exp !== fn || fn.parent_scope === compressor.find_parent(AST_Scope));
|
||||
var inline = compressor.option("inline");
|
||||
if (!can_inject_vars(catches, inline >= 3 && safe_to_inject)) return false;
|
||||
if (!can_inject_args(catches, inline >= 2 && safe_to_inject)) return false;
|
||||
var used = Object.create(catches);
|
||||
if (!can_inject_args(catches, used, inline >= 2 && safe_to_inject)) return false;
|
||||
if (!can_inject_vars(catches, used, inline >= 3 && safe_to_inject)) return false;
|
||||
return !in_loop || in_loop.length == 0 || !is_reachable(fn, in_loop);
|
||||
}
|
||||
|
||||
@@ -5556,20 +5595,29 @@ merge(Compressor.prototype, {
|
||||
self.right = tmp;
|
||||
}
|
||||
}
|
||||
if (commutativeOperators[self.operator]) {
|
||||
if (self.right.is_constant()
|
||||
&& !self.left.is_constant()) {
|
||||
// if right is a constant, whatever side effects the
|
||||
// left side might have could not influence the
|
||||
// result. hence, force switch.
|
||||
|
||||
if (!(self.left instanceof AST_Binary
|
||||
&& PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
|
||||
reverse();
|
||||
}
|
||||
if (commutativeOperators[self.operator] && self.right.is_constant() && !self.left.is_constant()) {
|
||||
// if right is a constant, whatever side effects the
|
||||
// left side might have could not influence the
|
||||
// result. hence, force switch.
|
||||
if (!(self.left instanceof AST_Binary
|
||||
&& PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
|
||||
reverse();
|
||||
}
|
||||
}
|
||||
self = self.lift_sequences(compressor);
|
||||
if (compressor.option("assignments") && lazy_op[self.operator]) {
|
||||
var assign = self.right;
|
||||
// a || (a = x) => a = a || x
|
||||
// a && (a = x) => a = a && x
|
||||
if (self.left instanceof AST_SymbolRef
|
||||
&& assign instanceof AST_Assign
|
||||
&& assign.operator == "="
|
||||
&& self.left.equivalent_to(assign.left)) {
|
||||
self.right = assign.right;
|
||||
assign.right = self;
|
||||
return assign;
|
||||
}
|
||||
}
|
||||
if (compressor.option("comparisons")) switch (self.operator) {
|
||||
case "===":
|
||||
case "!==":
|
||||
|
||||
@@ -136,8 +136,7 @@ function OutputStream(options) {
|
||||
|
||||
function make_string(str, quote) {
|
||||
var dq = 0, sq = 0;
|
||||
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
|
||||
function(s, i) {
|
||||
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s, i) {
|
||||
switch (s) {
|
||||
case '"': ++dq; return '"';
|
||||
case "'": ++sq; return "'";
|
||||
@@ -599,7 +598,6 @@ function OutputStream(options) {
|
||||
}
|
||||
print(encoded);
|
||||
},
|
||||
encode_string : encode_string,
|
||||
next_indent : next_indent,
|
||||
with_indent : with_indent,
|
||||
with_block : with_block,
|
||||
@@ -1383,8 +1381,27 @@ function OutputStream(options) {
|
||||
if (regexp.raw_source) {
|
||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||
}
|
||||
str = output.to_utf8(str);
|
||||
output.print(str);
|
||||
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(seq) {
|
||||
switch (seq[1]) {
|
||||
case "\n": return "\\n";
|
||||
case "\r": return "\\r";
|
||||
case "\t": return "\t";
|
||||
case "\b": return "\b";
|
||||
case "\f": return "\f";
|
||||
case "\0": return "\0";
|
||||
case "\x0B": return "\v";
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
default: return seq;
|
||||
}
|
||||
}).replace(/[\n\r\u2028\u2029]/g, function(c) {
|
||||
switch (c) {
|
||||
case "\n": return "\\n";
|
||||
case "\r": return "\\r";
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
}
|
||||
}));
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||
output.print(" ");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.5.15",
|
||||
"version": "3.6.1",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -23,12 +23,12 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.20.0",
|
||||
"commander": "2.20.0",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~6.1.1",
|
||||
"semver": "~6.0.0"
|
||||
"acorn": "~7.1.0",
|
||||
"semver": "~6.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/compress.js && node test/mocha.js"
|
||||
|
||||
@@ -311,3 +311,65 @@ issue_3375: {
|
||||
}
|
||||
expect_stdout: "string"
|
||||
}
|
||||
|
||||
issue_3427: {
|
||||
options = {
|
||||
assignments: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var a;
|
||||
a || (a = {});
|
||||
})();
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_3429_1: {
|
||||
options = {
|
||||
assignments: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
(function(b) {
|
||||
b && (b = a = "FAIL");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
(function(b) {
|
||||
b = b && (a = "FAIL");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3429_2: {
|
||||
options = {
|
||||
assignments: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
(function(b) {
|
||||
b || (b = a = "FAIL");
|
||||
})(42);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
(function(b) {
|
||||
b = b || (a = "FAIL");
|
||||
})(42);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
@@ -6197,3 +6197,43 @@ Infinity_assignment: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_3439_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function(a) {
|
||||
function a() {}
|
||||
return a;
|
||||
}(42));
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function(a) {
|
||||
function a() {}
|
||||
return a;
|
||||
}(42));
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_3439_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
var a = 42;
|
||||
function a() {}
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function() {
|
||||
return 42;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "number"
|
||||
}
|
||||
|
||||
@@ -2028,3 +2028,37 @@ issue_3375: {
|
||||
}
|
||||
expect_stdout: "0 0"
|
||||
}
|
||||
|
||||
issue_3427_1: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var a;
|
||||
a = a || {};
|
||||
})();
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_3427_2: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var s = "PASS";
|
||||
console.log(s = s || "FAIL");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var s = "PASS";
|
||||
console.log(s = s || "FAIL");
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -3148,3 +3148,51 @@ issue_3402: {
|
||||
"function",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3439: {
|
||||
options = {
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
return function(a) {
|
||||
function a() {}
|
||||
return a;
|
||||
}(42);
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function(a) {
|
||||
function a() {}
|
||||
return a;
|
||||
}(42));
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_3444: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(h) {
|
||||
return f;
|
||||
function f() {
|
||||
g();
|
||||
}
|
||||
function g() {
|
||||
h("PASS");
|
||||
}
|
||||
})(console.log)();
|
||||
}
|
||||
expect: {
|
||||
(function(h) {
|
||||
return function() {
|
||||
void h("PASS");
|
||||
};
|
||||
})(console.log)();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -886,3 +886,31 @@ issue_3411: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3440: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
function f() {
|
||||
console.log(o.p);
|
||||
}
|
||||
var o = {
|
||||
p: "PASS",
|
||||
};
|
||||
return f;
|
||||
})()();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var o_p = "PASS";
|
||||
return function() {
|
||||
console.log(o_p);
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1187,3 +1187,23 @@ drop_arguments: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3427: {
|
||||
options = {
|
||||
assignments: true,
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
(function(b) {
|
||||
b.p = 42;
|
||||
})(a || (a = {}));
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
@@ -35,3 +35,140 @@ regexp_2: {
|
||||
}
|
||||
expect_stdout: '["PASS","pass"]'
|
||||
}
|
||||
|
||||
issue_3434_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
"\n": RegExp("\n"),
|
||||
"\r": RegExp("\r"),
|
||||
"\t": RegExp("\t"),
|
||||
"\b": RegExp("\b"),
|
||||
"\f": RegExp("\f"),
|
||||
"\0": RegExp("\0"),
|
||||
"\x0B": RegExp("\x0B"),
|
||||
"\u2028": RegExp("\u2028"),
|
||||
"\u2029": RegExp("\u2029"),
|
||||
};
|
||||
for (var c in o)
|
||||
console.log(o[c].test("\\"), o[c].test(c));
|
||||
}
|
||||
expect_exact: [
|
||||
"var o = {",
|
||||
' "\\n": /\\n/,',
|
||||
' "\\r": /\\r/,',
|
||||
' "\\t": /\t/,',
|
||||
' "\\b": /\b/,',
|
||||
' "\\f": /\f/,',
|
||||
' "\\0": /\0/,',
|
||||
' "\\v": /\v/,',
|
||||
' "\\u2028": /\\u2028/,',
|
||||
' "\\u2029": /\\u2029/',
|
||||
"};",
|
||||
"",
|
||||
'for (var c in o) console.log(o[c].test("\\\\"), o[c].test(c));',
|
||||
]
|
||||
expect_stdout: [
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3434_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
"\n": RegExp("\\\n"),
|
||||
"\r": RegExp("\\\r"),
|
||||
"\t": RegExp("\\\t"),
|
||||
"\b": RegExp("\\\b"),
|
||||
"\f": RegExp("\\\f"),
|
||||
"\0": RegExp("\\\0"),
|
||||
"\x0B": RegExp("\\\x0B"),
|
||||
"\u2028": RegExp("\\\u2028"),
|
||||
"\u2029": RegExp("\\\u2029"),
|
||||
};
|
||||
for (var c in o)
|
||||
console.log(o[c].test("\\"), o[c].test(c));
|
||||
}
|
||||
expect_exact: [
|
||||
"var o = {",
|
||||
' "\\n": /\\n/,',
|
||||
' "\\r": /\\r/,',
|
||||
' "\\t": /\t/,',
|
||||
' "\\b": /\b/,',
|
||||
' "\\f": /\f/,',
|
||||
' "\\0": /\0/,',
|
||||
' "\\v": /\v/,',
|
||||
' "\\u2028": /\\u2028/,',
|
||||
' "\\u2029": /\\u2029/',
|
||||
"};",
|
||||
"",
|
||||
'for (var c in o) console.log(o[c].test("\\\\"), o[c].test(c));',
|
||||
]
|
||||
expect_stdout: [
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3434_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
RegExp("\n");
|
||||
RegExp("\r");
|
||||
RegExp("\\n");
|
||||
RegExp("\\\n");
|
||||
RegExp("\\\\n");
|
||||
RegExp("\\\\\n");
|
||||
RegExp("\\\\\\n");
|
||||
RegExp("\\\\\\\n");
|
||||
RegExp("\u2028");
|
||||
RegExp("\u2029");
|
||||
RegExp("\n\r\u2028\u2029");
|
||||
RegExp("\\\nfo\n[\n]o\\bbb");
|
||||
}
|
||||
expect: {
|
||||
/\n/;
|
||||
/\r/;
|
||||
/\n/;
|
||||
/\n/;
|
||||
/\\n/;
|
||||
/\\\n/;
|
||||
/\\\n/;
|
||||
/\\\n/;
|
||||
/\u2028/;
|
||||
/\u2029/;
|
||||
/\n\r\u2028\u2029/;
|
||||
/\nfo\n[\n]o\bbb/;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -960,12 +960,12 @@ if (require.main !== module) {
|
||||
}
|
||||
|
||||
function println(msg) {
|
||||
if (typeof msg != "undefined") process.stdout.write(msg);
|
||||
if (typeof msg != "undefined") process.stdout.write(typeof msg == "string" ? msg : msg.stack);
|
||||
process.stdout.write("\n");
|
||||
}
|
||||
|
||||
function errorln(msg) {
|
||||
if (typeof msg != "undefined") process.stderr.write(msg);
|
||||
if (typeof msg != "undefined") process.stderr.write(typeof msg == "string" ? msg : msg.stack);
|
||||
process.stderr.write("\n");
|
||||
}
|
||||
|
||||
@@ -980,7 +980,7 @@ function try_beautify(code, toplevel, result, printfn) {
|
||||
});
|
||||
if (beautified.error) {
|
||||
printfn("// !!! beautify failed !!!");
|
||||
printfn(beautified.error.stack);
|
||||
printfn(beautified.error);
|
||||
} else if (sandbox.same_stdout(sandbox.run_code(beautified.code, toplevel), result)) {
|
||||
printfn("// (beautified)");
|
||||
printfn(beautified.code);
|
||||
@@ -1007,7 +1007,7 @@ function log_suspects(minify_options, component) {
|
||||
var result = UglifyJS.minify(original_code, m);
|
||||
if (result.error) {
|
||||
errorln("Error testing options." + component + "." + name);
|
||||
errorln(result.error.stack);
|
||||
errorln(result.error);
|
||||
} else {
|
||||
var r = sandbox.run_code(result.code, m.toplevel);
|
||||
return sandbox.same_stdout(original_result, r);
|
||||
@@ -1029,7 +1029,7 @@ function log_rename(options) {
|
||||
var result = UglifyJS.minify(original_code, m);
|
||||
if (result.error) {
|
||||
errorln("Error testing options.rename");
|
||||
errorln(result.error.stack);
|
||||
errorln(result.error);
|
||||
} else {
|
||||
var r = sandbox.run_code(result.code, m.toplevel);
|
||||
if (sandbox.same_stdout(original_result, r)) {
|
||||
@@ -1056,17 +1056,17 @@ function log(options) {
|
||||
errorln();
|
||||
errorln();
|
||||
errorln("original result:");
|
||||
errorln(errored ? original_result.stack : original_result);
|
||||
errorln(original_result);
|
||||
errorln("uglified result:");
|
||||
errorln(typeof uglify_result == "string" ? uglify_result : uglify_result.stack);
|
||||
errorln(uglify_result);
|
||||
} else {
|
||||
errorln("// !!! uglify failed !!!");
|
||||
errorln(uglify_code.stack);
|
||||
errorln(uglify_code);
|
||||
if (errored) {
|
||||
errorln();
|
||||
errorln();
|
||||
errorln("original stacktrace:");
|
||||
errorln(original_result.stack);
|
||||
errorln(original_result);
|
||||
}
|
||||
}
|
||||
errorln("minify(options):");
|
||||
@@ -1115,7 +1115,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
println();
|
||||
println();
|
||||
println("original result:");
|
||||
println(original_result.stack);
|
||||
println(original_result);
|
||||
println();
|
||||
}
|
||||
if (!ok && isFinite(num_iterations)) {
|
||||
|
||||
@@ -2993,6 +2993,7 @@
|
||||
"caption",
|
||||
"caption-side",
|
||||
"captionSide",
|
||||
"capture",
|
||||
"captureEvents",
|
||||
"captureStackTrace",
|
||||
"captureStream",
|
||||
@@ -4957,6 +4958,7 @@
|
||||
"oncandidatewindowupdate",
|
||||
"oncanplay",
|
||||
"oncanplaythrough",
|
||||
"once",
|
||||
"oncellchange",
|
||||
"onchange",
|
||||
"onchargingchange",
|
||||
@@ -5343,6 +5345,7 @@
|
||||
"parseInt",
|
||||
"part",
|
||||
"participants",
|
||||
"passive",
|
||||
"password",
|
||||
"pasteHTML",
|
||||
"path",
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
var fs = require("fs");
|
||||
|
||||
exports.FILES = [
|
||||
"../lib/utils.js",
|
||||
"../lib/ast.js",
|
||||
"../lib/parse.js",
|
||||
"../lib/transform.js",
|
||||
"../lib/scope.js",
|
||||
"../lib/output.js",
|
||||
"../lib/compress.js",
|
||||
"../lib/sourcemap.js",
|
||||
"../lib/mozilla-ast.js",
|
||||
"../lib/propmangle.js",
|
||||
"../lib/minify.js",
|
||||
"./exports.js",
|
||||
].map(function(file) {
|
||||
return require.resolve(file);
|
||||
});
|
||||
require.resolve("../lib/utils.js"),
|
||||
require.resolve("../lib/ast.js"),
|
||||
require.resolve("../lib/parse.js"),
|
||||
require.resolve("../lib/transform.js"),
|
||||
require.resolve("../lib/scope.js"),
|
||||
require.resolve("../lib/output.js"),
|
||||
require.resolve("../lib/compress.js"),
|
||||
require.resolve("../lib/sourcemap.js"),
|
||||
require.resolve("../lib/mozilla-ast.js"),
|
||||
require.resolve("../lib/propmangle.js"),
|
||||
require.resolve("../lib/minify.js"),
|
||||
require.resolve("./exports.js"),
|
||||
];
|
||||
|
||||
new Function("MOZ_SourceMap", "exports", function() {
|
||||
var code = exports.FILES.map(function(file) {
|
||||
|
||||
Reference in New Issue
Block a user