Compare commits

...

15 Commits

Author SHA1 Message Date
Alex Lam S.L
f1a77e4fc0 v3.5.5 2019-04-19 15:22:46 +08:00
Alex Lam S.L
b55a2fd531 fix corner case in functions (#3367)
fixes #3366
2019-04-19 02:55:43 +08:00
Alex Lam S.L
e8a2c0b5bf fix corner case in functions (#3365)
fixes #3364
2019-04-18 17:03:52 +08:00
Alex Lam S.L
21cd7e3f57 reduce test exports (#3361) 2019-04-17 16:19:08 +08:00
Alex Lam S.L
5172ba5f2a introduce functions (#3360)
`var f = function() {};` => `function f() {}`
2019-04-15 22:23:11 +08:00
Alex Lam S.L
a57b069409 v3.5.4 2019-04-10 02:40:42 +08:00
Alex Lam S.L
4454656c3b update dependencies (#3358)
- commander@2.20.0
- semver@6.0.0
2019-04-10 02:39:56 +08:00
Alex Lam S.L
fa43768ce0 v3.5.3 2019-04-01 18:12:03 +08:00
Alex Lam S.L
a74e600fa0 mangle shadowed lambda under ie8 correctly (#3356)
fixes #3355
2019-04-01 15:22:00 +08:00
Ruben Bridgewater
4b21526310 Fix test expectation (#3357)
The test expects a specific precision value that is not met on all V8 versions anymore due to a recent consolidation of different algorithms across the V8 code base.

This makes sure the preceision is tested against one digit less to keep the test working on all V8 versions.

Refs: 98453126c1
Refs: https://github.com/nodejs/node/issues/25060#issuecomment-477953457
2019-03-30 02:08:27 +08:00
Alex Lam S.L
a7a7b1daed v3.5.2 2019-03-23 14:25:14 +08:00
Alex Lam S.L
7436977aa5 fix infinite loop triggered by #3347 (#3354)
fixes #3353
2019-03-23 14:21:54 +08:00
Alex Lam S.L
e3c565b46f v3.5.1 2019-03-21 13:54:14 +08:00
Alex Lam S.L
54b0b49b68 enhance inline (#3352) 2019-03-21 02:58:33 +08:00
Alex Lam S.L
65648d84a5 enhance collapse_vars (#3351) 2019-03-20 23:31:21 +08:00
13 changed files with 592 additions and 86 deletions

View File

@@ -636,6 +636,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `expression` (default: `false`) -- Pass `true` to preserve completion values - `expression` (default: `false`) -- Pass `true` to preserve completion values
from terminal statements without `return`, e.g. in bookmarklets. from terminal statements without `return`, e.g. in bookmarklets.
- `functions` (default: `true`) -- convert declarations from `var`to `function`
whenever possible.
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation) - `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
- `hoist_funs` (default: `false`) -- hoist function declarations - `hoist_funs` (default: `false`) -- hoist function declarations

View File

@@ -60,6 +60,7 @@ function Compressor(options, false_by_default) {
drop_debugger : !false_by_default, drop_debugger : !false_by_default,
evaluate : !false_by_default, evaluate : !false_by_default,
expression : false, expression : false,
functions : !false_by_default,
global_defs : false, global_defs : false,
hoist_funs : false, hoist_funs : false,
hoist_props : !false_by_default, hoist_props : !false_by_default,
@@ -150,7 +151,7 @@ Compressor.prototype = new TreeTransformer;
merge(Compressor.prototype, { merge(Compressor.prototype, {
option: function(key) { return this.options[key] }, option: function(key) { return this.options[key] },
exposed: function(def) { exposed: function(def) {
if (def.global) for (var i = 0, len = def.orig.length; i < len; i++) if (def.global) for (var i = 0; i < def.orig.length; i++)
if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"]) if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"])
return true; return true;
return false; return false;
@@ -1241,7 +1242,7 @@ merge(Compressor.prototype, {
// Scan case expressions first in a switch statement // Scan case expressions first in a switch statement
if (node instanceof AST_Switch) { if (node instanceof AST_Switch) {
node.expression = node.expression.transform(scanner); node.expression = node.expression.transform(scanner);
for (var i = 0, len = node.body.length; !abort && i < len; i++) { for (var i = 0; !abort && i < node.body.length; i++) {
var branch = node.body[i]; var branch = node.body[i];
if (branch instanceof AST_Case) { if (branch instanceof AST_Case) {
if (!hit) { if (!hit) {
@@ -1361,6 +1362,7 @@ merge(Compressor.prototype, {
hit_stack.push(expr); hit_stack.push(expr);
if (expr instanceof AST_Assign) { if (expr instanceof AST_Assign) {
candidates.push(hit_stack.slice()); candidates.push(hit_stack.slice());
extract_candidates(expr.left);
extract_candidates(expr.right); extract_candidates(expr.right);
} else if (expr instanceof AST_Binary) { } else if (expr instanceof AST_Binary) {
extract_candidates(expr.left); extract_candidates(expr.left);
@@ -1376,6 +1378,8 @@ merge(Compressor.prototype, {
extract_candidates(expr.alternative); extract_candidates(expr.alternative);
} else if (expr instanceof AST_Definitions) { } else if (expr instanceof AST_Definitions) {
expr.definitions.forEach(extract_candidates); expr.definitions.forEach(extract_candidates);
} else if (expr instanceof AST_Dot) {
extract_candidates(expr.expression);
} else if (expr instanceof AST_DWLoop) { } else if (expr instanceof AST_DWLoop) {
extract_candidates(expr.condition); extract_candidates(expr.condition);
if (!(expr.body instanceof AST_Block)) { if (!(expr.body instanceof AST_Block)) {
@@ -1407,6 +1411,9 @@ merge(Compressor.prototype, {
expr.expressions.forEach(extract_candidates); expr.expressions.forEach(extract_candidates);
} else if (expr instanceof AST_SimpleStatement) { } else if (expr instanceof AST_SimpleStatement) {
extract_candidates(expr.body); extract_candidates(expr.body);
} else if (expr instanceof AST_Sub) {
extract_candidates(expr.expression);
extract_candidates(expr.property);
} else if (expr instanceof AST_Switch) { } else if (expr instanceof AST_Switch) {
extract_candidates(expr.expression); extract_candidates(expr.expression);
expr.body.forEach(extract_candidates); expr.body.forEach(extract_candidates);
@@ -1465,6 +1472,7 @@ merge(Compressor.prototype, {
return node; return node;
} }
if (parent instanceof AST_IterationStatement) return node; if (parent instanceof AST_IterationStatement) return node;
if (parent instanceof AST_PropAccess) return node;
if (parent instanceof AST_Sequence) { if (parent instanceof AST_Sequence) {
return find_stop(parent, level + 1, parent.tail_node() !== node); return find_stop(parent, level + 1, parent.tail_node() !== node);
} }
@@ -1880,7 +1888,7 @@ merge(Compressor.prototype, {
} }
function next_index(i) { function next_index(i) {
for (var j = i + 1, len = statements.length; j < len; j++) { for (var j = i + 1; j < statements.length; j++) {
var stat = statements[j]; var stat = statements[j];
if (!(stat instanceof AST_Var && declarations_only(stat))) { if (!(stat instanceof AST_Var && declarations_only(stat))) {
break; break;
@@ -1971,7 +1979,7 @@ merge(Compressor.prototype, {
function to_simple_statement(block, decls) { function to_simple_statement(block, decls) {
if (!(block instanceof AST_BlockStatement)) return block; if (!(block instanceof AST_BlockStatement)) return block;
var stat = null; var stat = null;
for (var i = 0, len = block.body.length; i < len; i++) { for (var i = 0; i < block.body.length; i++) {
var line = block.body[i]; var line = block.body[i];
if (line instanceof AST_Var && declarations_only(line)) { if (line instanceof AST_Var && declarations_only(line)) {
decls.push(line); decls.push(line);
@@ -2111,7 +2119,7 @@ merge(Compressor.prototype, {
function join_consecutive_vars(statements) { function join_consecutive_vars(statements) {
var defs; var defs;
for (var i = 0, j = -1, len = statements.length; i < len; i++) { for (var i = 0, j = -1; i < statements.length; i++) {
var stat = statements[i]; var stat = statements[i];
var prev = statements[j]; var prev = statements[j];
if (stat instanceof AST_Definitions) { if (stat instanceof AST_Definitions) {
@@ -2239,7 +2247,11 @@ merge(Compressor.prototype, {
}); });
def(AST_SymbolRef, function() { def(AST_SymbolRef, function() {
var fixed = this.fixed_value(); var fixed = this.fixed_value();
return fixed && fixed.is_truthy(); if (!fixed) return false;
this.is_truthy = return_false;
var result = fixed.is_truthy();
delete this.is_truthy;
return result;
}); });
})(function(node, func) { })(function(node, func) {
node.DEFMETHOD("is_truthy", func); node.DEFMETHOD("is_truthy", func);
@@ -2293,7 +2305,11 @@ merge(Compressor.prototype, {
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false; if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
if (this.is_immutable()) return false; if (this.is_immutable()) return false;
var fixed = this.fixed_value(); var fixed = this.fixed_value();
return !fixed || fixed._dot_throw(compressor); if (!fixed) return true;
this._dot_throw = return_true;
var result = fixed._dot_throw(compressor);
delete this._dot_throw;
return result;
}); });
def(AST_UnaryPrefix, function() { def(AST_UnaryPrefix, function() {
return this.operator == "void"; return this.operator == "void";
@@ -2335,7 +2351,11 @@ merge(Compressor.prototype, {
}); });
def(AST_SymbolRef, function(compressor) { def(AST_SymbolRef, function(compressor) {
var fixed = this.fixed_value(); var fixed = this.fixed_value();
return fixed && fixed.is_boolean(compressor); if (!fixed) return false;
this.is_boolean = return_false;
var result = fixed.is_boolean(compressor);
delete this.is_boolean;
return result;
}); });
var unary = makePredicate("! delete"); var unary = makePredicate("! delete");
def(AST_UnaryPrefix, function() { def(AST_UnaryPrefix, function() {
@@ -2420,7 +2440,11 @@ merge(Compressor.prototype, {
}); });
def(AST_SymbolRef, function(compressor) { def(AST_SymbolRef, function(compressor) {
var fixed = this.fixed_value(); var fixed = this.fixed_value();
return fixed && fixed.is_number(compressor); if (!fixed) return false;
this.is_number = return_false;
var result = fixed.is_number(compressor);
delete this.is_number;
return result;
}); });
var unary = makePredicate("+ - ~ ++ --"); var unary = makePredicate("+ - ~ ++ --");
def(AST_Unary, function() { def(AST_Unary, function() {
@@ -2449,7 +2473,11 @@ merge(Compressor.prototype, {
def(AST_String, return_true); def(AST_String, return_true);
def(AST_SymbolRef, function(compressor) { def(AST_SymbolRef, function(compressor) {
var fixed = this.fixed_value(); var fixed = this.fixed_value();
return fixed && fixed.is_string(compressor); if (!fixed) return false;
this.is_string = return_false;
var result = fixed.is_string(compressor);
delete this.is_string;
return result;
}); });
def(AST_UnaryPrefix, function() { def(AST_UnaryPrefix, function() {
return this.operator == "typeof"; return this.operator == "typeof";
@@ -2692,7 +2720,7 @@ merge(Compressor.prototype, {
def(AST_Array, function(compressor, cached, depth) { def(AST_Array, function(compressor, cached, depth) {
if (compressor.option("unsafe")) { if (compressor.option("unsafe")) {
var elements = []; var elements = [];
for (var i = 0, len = this.elements.length; i < len; i++) { for (var i = 0; i < this.elements.length; i++) {
var element = this.elements[i]; var element = this.elements[i];
var value = element._eval(compressor, cached, depth); var value = element._eval(compressor, cached, depth);
if (element === value) return this; if (element === value) return this;
@@ -2705,7 +2733,7 @@ merge(Compressor.prototype, {
def(AST_Object, function(compressor, cached, depth) { def(AST_Object, function(compressor, cached, depth) {
if (compressor.option("unsafe")) { if (compressor.option("unsafe")) {
var val = {}; var val = {};
for (var i = 0, len = this.properties.length; i < len; i++) { for (var i = 0; i < this.properties.length; i++) {
var prop = this.properties[i]; var prop = this.properties[i];
var key = prop.key; var key = prop.key;
if (key instanceof AST_Symbol) { if (key instanceof AST_Symbol) {
@@ -2900,7 +2928,7 @@ merge(Compressor.prototype, {
if (!native_fn || !native_fn[key]) return this; if (!native_fn || !native_fn[key]) return this;
} }
var args = []; var args = [];
for (var i = 0, len = this.args.length; i < len; i++) { for (var i = 0; i < this.args.length; i++) {
var arg = this.args[i]; var arg = this.args[i];
var value = arg._eval(compressor, cached, depth); var value = arg._eval(compressor, cached, depth);
if (arg === value) return this; if (arg === value) return this;
@@ -3436,9 +3464,7 @@ merge(Compressor.prototype, {
if (node instanceof AST_Definitions && scope === self) { if (node instanceof AST_Definitions && scope === self) {
node.definitions.forEach(function(def) { node.definitions.forEach(function(def) {
var node_def = def.name.definition(); var node_def = def.name.definition();
if (def.name instanceof AST_SymbolVar) {
var_defs_by_id.add(node_def.id, def); var_defs_by_id.add(node_def.id, def);
}
if (!drop_vars) { if (!drop_vars) {
if (!(node_def.id in in_use_ids)) { if (!(node_def.id in in_use_ids)) {
in_use_ids[node_def.id] = true; in_use_ids[node_def.id] = true;
@@ -3545,7 +3571,6 @@ merge(Compressor.prototype, {
if (def.value && sym.id in fixed_ids && fixed_ids[sym.id] !== def) { if (def.value && sym.id in fixed_ids && fixed_ids[sym.id] !== def) {
def.value = def.value.drop_side_effect_free(compressor); def.value = def.value.drop_side_effect_free(compressor);
} }
if (def.name instanceof AST_SymbolVar) {
var var_defs = var_defs_by_id.get(sym.id); var var_defs = var_defs_by_id.get(sym.id);
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) { if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name)); compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
@@ -3566,8 +3591,20 @@ merge(Compressor.prototype, {
sym.eliminated++; sym.eliminated++;
return; return;
} }
} if (!def.value) {
if (def.value) { head.push(def);
} else if (compressor.option("functions")
&& def.value === def.name.fixed_value()
&& def.value instanceof AST_Function
&& !def.value.name
&& !def.value.variables.get(def.name.name)
&& (!compressor.has_directive("use strict") || parent instanceof AST_Scope)) {
compressor.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
var defun = make_node(AST_Defun, def, def.value);
defun.name = make_node(AST_SymbolDefun, def.name, def.name);
def.name.scope.resolve().def_function(defun.name);
body.push(defun);
} else {
if (side_effects.length > 0) { if (side_effects.length > 0) {
if (tail.length > 0) { if (tail.length > 0) {
side_effects.push(def.value); side_effects.push(def.value);
@@ -3580,8 +3617,6 @@ merge(Compressor.prototype, {
side_effects = []; side_effects = [];
} }
tail.push(def); tail.push(def);
} else {
head.push(def);
} }
} else if (sym.orig[0] instanceof AST_SymbolCatch) { } else if (sym.orig[0] instanceof AST_SymbolCatch) {
var value = def.value && def.value.drop_side_effect_free(compressor); var value = def.value && def.value.drop_side_effect_free(compressor);
@@ -4642,7 +4677,7 @@ merge(Compressor.prototype, {
&& !fn.uses_arguments && !fn.uses_arguments
&& !fn.pinned()) { && !fn.pinned()) {
var pos = 0, last = 0; var pos = 0, last = 0;
for (var i = 0, len = self.args.length; i < len; i++) { for (var i = 0; i < self.args.length; i++) {
var trim = i >= fn.argnames.length; var trim = i >= fn.argnames.length;
if (trim || fn.argnames[i].__unused) { if (trim || fn.argnames[i].__unused) {
var node = self.args[i].drop_side_effect_free(compressor); var node = self.args[i].drop_side_effect_free(compressor);
@@ -5020,7 +5055,7 @@ merge(Compressor.prototype, {
} }
function can_inject_args(catches, safe_to_inject) { function can_inject_args(catches, safe_to_inject) {
for (var i = 0, len = fn.argnames.length; i < len; i++) { for (var i = 0; i < fn.argnames.length; i++) {
var arg = fn.argnames[i]; var arg = fn.argnames[i];
if (arg.__unused) continue; if (arg.__unused) continue;
if (!safe_to_inject if (!safe_to_inject
@@ -5035,7 +5070,7 @@ merge(Compressor.prototype, {
} }
function can_inject_vars(catches, safe_to_inject) { function can_inject_vars(catches, safe_to_inject) {
for (var i = 0, len = fn.body.length; i < len; i++) { for (var i = 0; i < fn.body.length; i++) {
var stat = fn.body[i]; var stat = fn.body[i];
if (!(stat instanceof AST_Var)) continue; if (!(stat instanceof AST_Var)) continue;
if (!safe_to_inject) return false; if (!safe_to_inject) return false;
@@ -5065,7 +5100,7 @@ merge(Compressor.prototype, {
} }
} while (!(scope instanceof AST_Scope)); } while (!(scope instanceof AST_Scope));
var safe_to_inject = (!(scope instanceof AST_Toplevel) || compressor.toplevel.vars) var safe_to_inject = (!(scope instanceof AST_Toplevel) || compressor.toplevel.vars)
&& fn.parent_scope === compressor.find_parent(AST_Scope); && (exp !== fn || fn.parent_scope === compressor.find_parent(AST_Scope));
var inline = compressor.option("inline"); var inline = compressor.option("inline");
if (!can_inject_vars(catches, inline >= 3 && safe_to_inject)) return false; if (!can_inject_vars(catches, inline >= 3 && safe_to_inject)) return false;
if (!can_inject_args(catches, inline >= 2 && safe_to_inject)) return false; if (!can_inject_args(catches, inline >= 2 && safe_to_inject)) return false;
@@ -5115,10 +5150,10 @@ merge(Compressor.prototype, {
function flatten_vars(decls, expressions) { function flatten_vars(decls, expressions) {
var pos = expressions.length; var pos = expressions.length;
for (var i = 0, lines = fn.body.length; i < lines; i++) { for (var i = 0; i < fn.body.length; i++) {
var stat = fn.body[i]; var stat = fn.body[i];
if (!(stat instanceof AST_Var)) continue; if (!(stat instanceof AST_Var)) continue;
for (var j = 0, defs = stat.definitions.length; j < defs; j++) { for (var j = 0; j < stat.definitions.length; j++) {
var var_def = stat.definitions[j]; var var_def = stat.definitions[j];
var name = var_def.name; var name = var_def.name;
var redef = name.definition().redefined(); var redef = name.definition().redefined();

View File

@@ -123,7 +123,7 @@ function OutputStream(options) {
}); });
} : function(str) { } : function(str) {
var s = ""; var s = "";
for (var i = 0, len = str.length; i < len; i++) { for (var i = 0; i < str.length; i++) {
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1]) if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) { || is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
s += "\\u" + str.charCodeAt(i).toString(16); s += "\\u" + str.charCodeAt(i).toString(16);

View File

@@ -164,10 +164,6 @@ function is_unicode_connector_punctuation(ch) {
return UNICODE.connector_punctuation.test(ch); return UNICODE.connector_punctuation.test(ch);
} }
function is_identifier(name) {
return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
}
function is_identifier_start(code) { function is_identifier_start(code) {
return code == 36 || code == 95 || is_letter(code); return code == 36 || code == 95 || is_letter(code);
} }
@@ -272,10 +268,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
function find_eol() { function find_eol() {
var text = S.text; var text = S.text;
for (var i = S.pos, n = S.text.length; i < n; ++i) { for (var i = S.pos; i < S.text.length; ++i) {
var ch = text[i]; if (NEWLINE_CHARS[text[i]]) return i;
if (NEWLINE_CHARS[ch])
return i;
} }
return -1; return -1;
} }

View File

@@ -61,8 +61,6 @@ SymbolDef.next_id = 1;
SymbolDef.prototype = { SymbolDef.prototype = {
unmangleable: function(options) { unmangleable: function(options) {
if (!options) options = {};
return this.global && !options.toplevel return this.global && !options.toplevel
|| this.undeclared || this.undeclared
|| !options.eval && this.scope.pinned() || !options.eval && this.scope.pinned()
@@ -198,24 +196,20 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} }
if (node instanceof AST_SymbolLambda) { if (node instanceof AST_SymbolLambda) {
var def = node.thedef; var def = node.thedef;
if (def.orig.length == 1) {
redefine(node, node.scope.parent_scope); redefine(node, node.scope.parent_scope);
node.thedef.init = def.init; node.thedef.init = def.init;
}
return true; return true;
} }
})); }));
function redefine(node, scope) { function redefine(node, scope) {
var name = node.name; var name = node.name;
var refs = node.thedef.references; var old_def = node.thedef;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
refs.forEach(function(ref) { old_def.orig.concat(old_def.references).forEach(function(node) {
ref.thedef = def; node.thedef = new_def;
ref.reference(options);
});
node.thedef = def;
node.reference(options); node.reference(options);
});
} }
}); });
@@ -300,7 +294,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
AST_Lambda.DEFMETHOD("resolve", return_this); AST_Lambda.DEFMETHOD("resolve", return_this);
AST_Scope.DEFMETHOD("resolve", function() { AST_Scope.DEFMETHOD("resolve", function() {
return this.parent_scope; return this.parent_scope.resolve();
}); });
AST_Toplevel.DEFMETHOD("resolve", return_this); AST_Toplevel.DEFMETHOD("resolve", return_this);
@@ -337,7 +331,7 @@ function next_mangled_name(scope, options, def) {
} while (scope = scope.parent_scope); } while (scope = scope.parent_scope);
}); });
var name; var name;
for (var i = 0, len = holes.length; i < len; i++) { for (var i = 0; i < holes.length; i++) {
name = base54(holes[i]); name = base54(holes[i]);
if (names[name]) continue; if (names[name]) continue;
holes.splice(i, 1); holes.splice(i, 1);
@@ -346,7 +340,7 @@ function next_mangled_name(scope, options, def) {
} }
while (true) { while (true) {
name = base54(++scope.cname); name = base54(++scope.cname);
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue; if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
if (!names[name]) break; if (!names[name]) break;
holes.push(scope.cname); holes.push(scope.cname);
} }
@@ -426,7 +420,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
var name; var name;
do { do {
name = base54(++lname); name = base54(++lname);
} while (!is_identifier(name)); } while (RESERVED_WORDS[name]);
node.mangled_name = name; node.mangled_name = name;
return true; return true;
} }
@@ -497,7 +491,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
var name; var name;
do { do {
name = base54(cname++); name = base54(cname++);
} while (avoid[name] || !is_identifier(name)); } while (avoid[name] || RESERVED_WORDS[name]);
return name; return name;
} }
@@ -559,7 +553,7 @@ var base54 = (function() {
var freq = Object.create(null); var freq = Object.create(null);
function init(chars) { function init(chars) {
var array = []; var array = [];
for (var i = 0, len = chars.length; i < len; i++) { for (var i = 0; i < chars.length; i++) {
var ch = chars[i]; var ch = chars[i];
array.push(ch); array.push(ch);
freq[ch] = -1e-2 * i; freq[ch] = -1e-2 * i;

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "3.5.0", "version": "3.5.5",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },
@@ -23,12 +23,12 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"commander": "~2.19.0", "commander": "~2.20.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
}, },
"devDependencies": { "devDependencies": {
"acorn": "~6.1.1", "acorn": "~6.1.1",
"semver": "~5.6.0" "semver": "~6.0.0"
}, },
"scripts": { "scripts": {
"test": "node test/run-tests.js" "test": "node test/run-tests.js"

View File

@@ -3895,11 +3895,11 @@ issue_2436_10: {
o = { b: 3 }; o = { b: 3 };
return n; return n;
} }
console.log((c = o, [ console.log([
c.a, (c = o).a,
f(c.b), f(c.b),
c.b, c.b,
]).join(" ")); ].join(" "));
var c; var c;
} }
expect_stdout: "1 2 2" expect_stdout: "1 2 2"
@@ -6121,3 +6121,39 @@ issue_3327: {
} }
expect_stdout: "PASS 42" expect_stdout: "PASS 42"
} }
assign_left: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a, b) {
(b = a, b.p).q = "PASS";
return a.p.q;
}({p: {}}));
}
expect: {
console.log(function(a, b) {
(b = a).p.q = "PASS";
return a.p.q;
}({p: {}}));
}
expect_stdout: "PASS"
}
sub_property: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a, b) {
return a[(b = a, b.length - 1)];
}([ "FAIL", "PASS" ]));
}
expect: {
console.log(function(a, b) {
return a[(b = a).length - 1];
}([ "FAIL", "PASS" ]));
}
expect_stdout: "PASS"
}

View File

@@ -1124,14 +1124,14 @@ issue_2207_1: {
console.log(Math.max(3, 6, 2, 7, 3, 4)); console.log(Math.max(3, 6, 2, 7, 3, 4));
console.log(Math.cos(1.2345)); console.log(Math.cos(1.2345));
console.log(Math.cos(1.2345) - Math.sin(4.321)); console.log(Math.cos(1.2345) - Math.sin(4.321));
console.log(Math.pow(Math.PI, Math.E - Math.LN10)); console.log(Math.pow(Math.PI, Math.E - Math.LN10).toFixed(15));
} }
expect: { expect: {
console.log("A"); console.log("A");
console.log(7); console.log(7);
console.log(Math.cos(1.2345)); console.log(Math.cos(1.2345));
console.log(1.2543732512566947); console.log(1.2543732512566947);
console.log(1.6093984514472044); console.log("1.609398451447204");
} }
expect_stdout: true expect_stdout: true
} }

View File

@@ -2675,3 +2675,340 @@ cross_references_3: {
"9 27", "9 27",
] ]
} }
loop_inline: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(o) {
function g(p) {
return o[p];
}
function h(q) {
while (g(q));
}
return h;
}([ 1, "foo", 0 ])(2));
}
expect: {
console.log(function(o) {
return function(q) {
while (p = q, o[p]);
var p;
};
}([ 1, "foo", 0 ])(2));
}
expect_stdout: "undefined"
}
functions: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
!function() {
var a = function() {
return "a";
};
var b = function x() {
return !!x;
};
var c = function(c) {
return c;
};
if (c(b(a()))) {
var d = function() {};
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect: {
!function() {
function a() {
return "a";
}
var b = function x() {
return !!x;
};
var c = function(c) {
return c;
};
if (c(b(a()))) {
function d() {}
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect_stdout: "a true 42 function function function"
}
functions_use_strict: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
!function() {
var a = function() {
return "a";
};
var b = function x() {
return !!x;
};
var c = function(c) {
return c;
};
if (c(b(a()))) {
var d = function() {};
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect: {
"use strict";
!function() {
function a() {
return "a";
}
var b = function x() {
return !!x;
};
var c = function(c) {
return c;
};
if (c(b(a()))) {
var d = function() {};
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect_stdout: "a true 42 function function function"
}
issue_2437: {
options = {
collapse_vars: true,
conditionals: true,
functions: true,
inline: true,
join_vars: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function foo() {
return bar();
}
function bar() {
if (xhrDesc) {
var req = new XMLHttpRequest();
var result = !!req.onreadystatechange;
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
return result;
} else {
var req = new XMLHttpRequest();
var detectFunc = function(){};
req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null;
return result;
}
}
console.log(foo());
}
expect: {
console.log(function() {
if (xhrDesc) {
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
result;
}
function detectFunc() {}
var req;
(req = new XMLHttpRequest()).onreadystatechange = detectFunc;
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
return req.onreadystatechange = null, result;
}());
}
}
issue_2485: {
options = {
functions: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
var foo = function(bar) {
var n = function(a, b) {
return a + b;
};
var sumAll = function(arg) {
return arg.reduce(n, 0);
};
var runSumAll = function(arg) {
return sumAll(arg);
};
bar.baz = function(arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));
}
expect: {
var foo = function(bar) {
function n(a, b) {
return a + b;
}
function runSumAll(arg) {
return function(arg) {
return arg.reduce(n, 0);
}(arg);
}
bar.baz = function(arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));
}
expect_stdout: "6"
}
issue_3364: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {}
input: {
var s = 2, a = 100, b = 10, c = 0;
function f(p, e, r) {
try {
for (var i = 1; i-- > 0;)
var a = function(x) {
function g(y) {
y && y[a++];
}
var x = g(--s >= 0 && f(c++));
for (var j = 1; --j > 0;);
}();
} catch (e) {
try {
return;
} catch (z) {
for (var k = 1; --k > 0;) {
for (var l = 1; l > 0; --l) {
var n = function() {};
for (var k in n)
var o = (n, k);
}
}
}
}
}
var r = f();
console.log(c);
}
expect: {
var s = 2, c = 0;
(function n(r, o, a) {
try {
for (var f = 1; f-- >0;)
var t = function(r) {
(function(r) {
r && r[t++];
})(--s >= 0 && n(c++));
for (var o = 1; --o > 0;);
}();
} catch (o) {
try {
return;
} catch (r) {
for (var v = 1; --v > 0;)
for (var i = 1; i > 0;--i) {
function u() {}
for (var v in u);
}
}
}
})();
console.log(c);
}
expect_stdout: "2"
}
issue_3366: {
options = {
functions: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
function g() {
return function() {};
}
var a = g();
(function() {
this && a && console.log("PASS");
})();
}
f();
}
expect: {
(function() {
function a() {}
(function() {
this && a && console.log("PASS");
})();
})();
}
expect_stdout: "PASS"
}

View File

@@ -861,3 +861,111 @@ issue_3215_4: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_3355_1: {
mangle = {
ie8: false,
}
input: {
(function f() {
var f;
})();
(function g() {
})();
console.log(typeof f === typeof g);
}
expect: {
(function o() {
var o;
})();
(function o() {
})();
console.log(typeof f === typeof g);
}
expect_stdout: "true"
}
issue_3355_2: {
mangle = {
ie8: true,
}
input: {
(function f() {
var f;
})();
(function g() {
})();
console.log(typeof f === typeof g);
}
expect: {
(function f() {
var f;
})();
(function g() {
})();
console.log(typeof f === typeof g);
}
expect_stdout: "true"
}
issue_3355_3: {
mangle = {
ie8: false,
}
input: {
!function(a) {
"aaaaaaaaaa";
a();
var b = function c() {
var c = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect: {
!function(a) {
"aaaaaaaaaa";
a();
var o = function a() {
var a = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect_stdout: "PASS"
}
issue_3355_4: {
mangle = {
ie8: true,
}
input: {
!function(a) {
"aaaaaaaaaa";
a();
var b = function c() {
var c = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect: {
!function(a) {
"aaaaaaaaaa";
a();
var o = function n() {
var n = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect_stdout: "PASS"
}

View File

@@ -1,7 +1,5 @@
exports["base54"] = base54;
exports["Compressor"] = Compressor; exports["Compressor"] = Compressor;
exports["defaults"] = defaults; exports["defaults"] = defaults;
exports["is_identifier"] = is_identifier;
exports["JS_Parse_Error"] = JS_Parse_Error; exports["JS_Parse_Error"] = JS_Parse_Error;
exports["mangle_properties"] = mangle_properties; exports["mangle_properties"] = mangle_properties;
exports["minify"] = minify; exports["minify"] = minify;
@@ -9,7 +7,6 @@ exports["OutputStream"] = OutputStream;
exports["parse"] = parse; exports["parse"] = parse;
exports["push_uniq"] = push_uniq; exports["push_uniq"] = push_uniq;
exports["reserve_quoted_keys"] = reserve_quoted_keys; exports["reserve_quoted_keys"] = reserve_quoted_keys;
exports["SourceMap"] = SourceMap;
exports["string_template"] = string_template; exports["string_template"] = string_template;
exports["tokenizer"] = tokenizer; exports["tokenizer"] = tokenizer;
exports["TreeTransformer"] = TreeTransformer; exports["TreeTransformer"] = TreeTransformer;

View File

@@ -3,7 +3,7 @@
"use strict"; "use strict";
var site = "https://browserbench.org/JetStream"; var site = "https://browserbench.org/JetStream1.1";
if (typeof phantom == "undefined") { if (typeof phantom == "undefined") {
require("../tools/exit"); require("../tools/exit");
var args = process.argv.slice(2); var args = process.argv.slice(2);

View File

@@ -73,8 +73,10 @@ exports.run_code = function(code, reuse) {
process.stdout.write = original_write; process.stdout.write = original_write;
if (!reuse || code.indexOf(".prototype") >= 0) { if (!reuse || code.indexOf(".prototype") >= 0) {
context = null; context = null;
} else for (var key in context) { } else {
delete context[key]; vm.runInContext(Object.keys(context).map(function(name) {
return "delete " + name;
}).join("\n"), context);
} }
} }
}; };