Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fcbd5e217 | ||
|
|
22cea023d1 | ||
|
|
70d4477e05 | ||
|
|
838f837379 | ||
|
|
82a8b6f612 | ||
|
|
69fc7ca8da | ||
|
|
0a79496e0a | ||
|
|
9e87edfc2e | ||
|
|
27211cf2d5 | ||
|
|
b5ce199711 | ||
|
|
c71ed91e63 | ||
|
|
f7545d0f1c | ||
|
|
59eecb6bf5 | ||
|
|
d83c6490ab | ||
|
|
7362f57966 | ||
|
|
eaa2c1f6af | ||
|
|
6a916523d4 | ||
|
|
ba7069d52b | ||
|
|
4dd7d0e39b | ||
|
|
90199d0a96 | ||
|
|
b82fd0ad41 | ||
|
|
183da16896 | ||
|
|
87857b0f1b | ||
|
|
e5f6a88233 |
8
.github/ISSUE_TEMPLATE.md
vendored
8
.github/ISSUE_TEMPLATE.md
vendored
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
<!-- Note: sub-optimal but correct code is not a bug -->
|
<!-- Note: sub-optimal but correct code is not a bug -->
|
||||||
|
|
||||||
**ES5 or ES6+ input?**
|
|
||||||
|
|
||||||
<!-- Note: for ES6 see: https://github.com/mishoo/UglifyJS2/tree/harmony#harmony -->
|
|
||||||
|
|
||||||
**Uglify version (`uglifyjs -V`)**
|
**Uglify version (`uglifyjs -V`)**
|
||||||
|
|
||||||
**JavaScript input**
|
**JavaScript input**
|
||||||
@@ -24,6 +20,6 @@
|
|||||||
**JavaScript output or error produced.**
|
**JavaScript output or error produced.**
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Note: `uglify-js` only supports ES5.
|
Note: `uglify-js` only supports JavaScript.
|
||||||
Those wishing to minify ES6 should use `uglify-es`.
|
Those wishing to minify ES6+ should transpile first.
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -685,7 +685,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
|
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
|
||||||
function won't produce any side effect, in which case the whole
|
function won't produce any side effect, in which case the whole
|
||||||
statement would get discarded. The current implementation adds some
|
statement would get discarded. The current implementation adds some
|
||||||
overhead (compression will be slower).
|
overhead (compression will be slower). Make sure symbols under `pure_funcs`
|
||||||
|
are also under `mangle.reserved` to avoid mangling.
|
||||||
|
|
||||||
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
||||||
this, UglifyJS will assume that object property access
|
this, UglifyJS will assume that object property access
|
||||||
@@ -1040,8 +1041,9 @@ var result = UglifyJS.minify(ast, {
|
|||||||
### Working with Uglify AST
|
### Working with Uglify AST
|
||||||
|
|
||||||
Transversal and transformation of the native AST can be performed through
|
Transversal and transformation of the native AST can be performed through
|
||||||
[`TreeWalker`](http://lisperator.net/uglifyjs/walk) and
|
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
|
||||||
[`TreeTransformer`](http://lisperator.net/uglifyjs/transform) respectively.
|
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
|
||||||
|
respectively.
|
||||||
|
|
||||||
### ESTree / SpiderMonkey AST
|
### ESTree / SpiderMonkey AST
|
||||||
|
|
||||||
|
|||||||
357
lib/compress.js
357
lib/compress.js
@@ -295,6 +295,51 @@ merge(Compressor.prototype, {
|
|||||||
self.transform(tt);
|
self.transform(tt);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function read_property(obj, key) {
|
||||||
|
key = get_value(key);
|
||||||
|
if (key instanceof AST_Node) return;
|
||||||
|
var value;
|
||||||
|
if (obj instanceof AST_Array) {
|
||||||
|
var elements = obj.elements;
|
||||||
|
if (key == "length") return make_node_from_constant(elements.length, obj);
|
||||||
|
if (typeof key == "number" && key in elements) value = elements[key];
|
||||||
|
} else if (obj instanceof AST_Object) {
|
||||||
|
key = "" + key;
|
||||||
|
var props = obj.properties;
|
||||||
|
for (var i = props.length; --i >= 0;) {
|
||||||
|
var prop = props[i];
|
||||||
|
if (!(prop instanceof AST_ObjectKeyVal)) return;
|
||||||
|
if (!value && props[i].key === key) value = props[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value instanceof AST_SymbolRef && value.fixed_value() || value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_modified(compressor, tw, node, value, level, immutable) {
|
||||||
|
var parent = tw.parent(level);
|
||||||
|
var lhs = is_lhs(node, parent);
|
||||||
|
if (lhs) return lhs;
|
||||||
|
if (!immutable
|
||||||
|
&& parent instanceof AST_Call
|
||||||
|
&& parent.expression === node
|
||||||
|
&& !parent.is_expr_pure(compressor)
|
||||||
|
&& (!(value instanceof AST_Function)
|
||||||
|
|| !(parent instanceof AST_New) && value.contains_this())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Array) {
|
||||||
|
return is_modified(compressor, tw, parent, parent, level + 1);
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
|
||||||
|
var obj = tw.parent(level + 1);
|
||||||
|
return is_modified(compressor, tw, obj, obj, level + 2);
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_PropAccess && parent.expression === node) {
|
||||||
|
var prop = read_property(value, parent.property);
|
||||||
|
return !immutable && is_modified(compressor, tw, parent, prop, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(function(def){
|
(function(def){
|
||||||
def(AST_Node, noop);
|
def(AST_Node, noop);
|
||||||
|
|
||||||
@@ -385,45 +430,6 @@ merge(Compressor.prototype, {
|
|||||||
|| value instanceof AST_This;
|
|| value instanceof AST_This;
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_property(obj, key) {
|
|
||||||
key = get_value(key);
|
|
||||||
if (key instanceof AST_Node) return;
|
|
||||||
var value;
|
|
||||||
if (obj instanceof AST_Array) {
|
|
||||||
var elements = obj.elements;
|
|
||||||
if (key == "length") return make_node_from_constant(elements.length, obj);
|
|
||||||
if (typeof key == "number" && key in elements) value = elements[key];
|
|
||||||
} else if (obj instanceof AST_Object) {
|
|
||||||
key = "" + key;
|
|
||||||
var props = obj.properties;
|
|
||||||
for (var i = props.length; --i >= 0;) {
|
|
||||||
var prop = props[i];
|
|
||||||
if (!(prop instanceof AST_ObjectKeyVal)) return;
|
|
||||||
if (!value && props[i].key === key) value = props[i].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value instanceof AST_SymbolRef && value.fixed_value() || value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_modified(tw, node, value, level, immutable) {
|
|
||||||
var parent = tw.parent(level);
|
|
||||||
if (is_lhs(node, parent)
|
|
||||||
|| !immutable
|
|
||||||
&& parent instanceof AST_Call
|
|
||||||
&& parent.expression === node
|
|
||||||
&& (!(value instanceof AST_Function)
|
|
||||||
|| !(parent instanceof AST_New) && value.contains_this())) {
|
|
||||||
return true;
|
|
||||||
} else if (parent instanceof AST_Array) {
|
|
||||||
return is_modified(tw, parent, parent, level + 1);
|
|
||||||
} else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
|
|
||||||
var obj = tw.parent(level + 1);
|
|
||||||
return is_modified(tw, obj, obj, level + 2);
|
|
||||||
} else if (parent instanceof AST_PropAccess && parent.expression === node) {
|
|
||||||
return !immutable && is_modified(tw, parent, read_property(value, parent.property), level + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mark_escaped(tw, d, scope, node, value, level, depth) {
|
function mark_escaped(tw, d, scope, node, value, level, depth) {
|
||||||
var parent = tw.parent(level);
|
var parent = tw.parent(level);
|
||||||
if (value && value.is_constant()) return;
|
if (value && value.is_constant()) return;
|
||||||
@@ -530,11 +536,16 @@ merge(Compressor.prototype, {
|
|||||||
tw.safe_ids = save_ids;
|
tw.safe_ids = save_ids;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_DWLoop, function(tw, descend) {
|
def(AST_Do, function(tw) {
|
||||||
var saved_loop = tw.in_loop;
|
var saved_loop = tw.in_loop;
|
||||||
tw.in_loop = this;
|
tw.in_loop = this;
|
||||||
push(tw);
|
push(tw);
|
||||||
descend();
|
this.body.walk(tw);
|
||||||
|
if (has_break_or_continue(this)) {
|
||||||
|
pop(tw);
|
||||||
|
push(tw);
|
||||||
|
}
|
||||||
|
this.condition.walk(tw);
|
||||||
pop(tw);
|
pop(tw);
|
||||||
tw.in_loop = saved_loop;
|
tw.in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
@@ -543,19 +554,17 @@ merge(Compressor.prototype, {
|
|||||||
if (this.init) this.init.walk(tw);
|
if (this.init) this.init.walk(tw);
|
||||||
var saved_loop = tw.in_loop;
|
var saved_loop = tw.in_loop;
|
||||||
tw.in_loop = this;
|
tw.in_loop = this;
|
||||||
if (this.condition) {
|
|
||||||
push(tw);
|
|
||||||
this.condition.walk(tw);
|
|
||||||
pop(tw);
|
|
||||||
}
|
|
||||||
push(tw);
|
push(tw);
|
||||||
|
if (this.condition) this.condition.walk(tw);
|
||||||
this.body.walk(tw);
|
this.body.walk(tw);
|
||||||
pop(tw);
|
|
||||||
if (this.step) {
|
if (this.step) {
|
||||||
push(tw);
|
if (has_break_or_continue(this)) {
|
||||||
this.step.walk(tw);
|
|
||||||
pop(tw);
|
pop(tw);
|
||||||
|
push(tw);
|
||||||
}
|
}
|
||||||
|
this.step.walk(tw);
|
||||||
|
}
|
||||||
|
pop(tw);
|
||||||
tw.in_loop = saved_loop;
|
tw.in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -641,7 +650,7 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
d.single_use = false;
|
d.single_use = false;
|
||||||
}
|
}
|
||||||
if (is_modified(tw, this, value, 0, is_immutable(value))) {
|
if (is_modified(compressor, tw, this, value, 0, is_immutable(value))) {
|
||||||
if (d.single_use) {
|
if (d.single_use) {
|
||||||
d.single_use = "m";
|
d.single_use = "m";
|
||||||
} else {
|
} else {
|
||||||
@@ -713,6 +722,15 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
def(AST_While, function(tw, descend) {
|
||||||
|
var saved_loop = tw.in_loop;
|
||||||
|
tw.in_loop = this;
|
||||||
|
push(tw);
|
||||||
|
descend();
|
||||||
|
pop(tw);
|
||||||
|
tw.in_loop = saved_loop;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("reduce_vars", func);
|
node.DEFMETHOD("reduce_vars", func);
|
||||||
});
|
});
|
||||||
@@ -962,24 +980,12 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
// Stop immediately if these node types are encountered
|
// Stop immediately if these node types are encountered
|
||||||
var parent = scanner.parent();
|
var parent = scanner.parent();
|
||||||
if (node instanceof AST_Assign && node.operator != "=" && lhs.equivalent_to(node.left)
|
if (should_stop(node, parent)) {
|
||||||
|| node instanceof AST_Call && lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression)
|
|
||||||
|| node instanceof AST_Debugger
|
|
||||||
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|
|
||||||
|| node instanceof AST_LoopControl
|
|
||||||
|| node instanceof AST_Try
|
|
||||||
|| node instanceof AST_With
|
|
||||||
|| parent instanceof AST_For && node !== parent.init
|
|
||||||
|| !replace_all
|
|
||||||
&& (node instanceof AST_SymbolRef && !node.is_declared(compressor))) {
|
|
||||||
abort = true;
|
abort = true;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
// Stop only if candidate is found within conditional branches
|
// Stop only if candidate is found within conditional branches
|
||||||
if (!stop_if_hit
|
if (!stop_if_hit && in_conditional(node, parent)) {
|
||||||
&& (parent instanceof AST_Binary && lazy_op[parent.operator] && parent.left !== node
|
|
||||||
|| parent instanceof AST_Conditional && parent.condition !== node
|
|
||||||
|| parent instanceof AST_If && parent.condition !== node)) {
|
|
||||||
stop_if_hit = parent;
|
stop_if_hit = parent;
|
||||||
}
|
}
|
||||||
// Replace variable with assignment when found
|
// Replace variable with assignment when found
|
||||||
@@ -1013,19 +1019,14 @@ merge(Compressor.prototype, {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
var def = candidate.name.definition();
|
var def = candidate.name.definition();
|
||||||
var value = candidate.value;
|
|
||||||
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
||||||
def.replaced++;
|
def.replaced++;
|
||||||
if (funarg && is_identifier_atom(value)) {
|
return maintain_this_binding(parent, node, candidate.value);
|
||||||
return value.transform(compressor);
|
|
||||||
} else {
|
|
||||||
return maintain_this_binding(parent, node, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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: value
|
right: candidate.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
candidate.write_only = false;
|
candidate.write_only = false;
|
||||||
@@ -1034,20 +1035,7 @@ merge(Compressor.prototype, {
|
|||||||
// 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.
|
||||||
var sym;
|
var sym;
|
||||||
if (node instanceof AST_Call
|
if (is_last_node(node, parent) || may_throw(node)) {
|
||||||
|| node instanceof AST_Exit
|
|
||||||
&& (side_effects || lhs instanceof AST_PropAccess || may_modify(lhs))
|
|
||||||
|| node instanceof AST_PropAccess
|
|
||||||
&& (side_effects || node.expression.may_throw_on_access(compressor))
|
|
||||||
|| node instanceof AST_SymbolRef
|
|
||||||
&& (symbol_in_lvalues(node) || side_effects && may_modify(node))
|
|
||||||
|| node instanceof AST_This && symbol_in_lvalues(node)
|
|
||||||
|| node instanceof AST_VarDef && node.value
|
|
||||||
&& (node.name.name in lvalues || side_effects && may_modify(node.name))
|
|
||||||
|| (sym = is_lhs(node.left, node))
|
|
||||||
&& (sym instanceof AST_PropAccess || sym.name in lvalues)
|
|
||||||
|| may_throw
|
|
||||||
&& (in_try ? node.has_side_effects(compressor) : side_effects_external(node))) {
|
|
||||||
stop_after = node;
|
stop_after = node;
|
||||||
if (node instanceof AST_Scope) abort = true;
|
if (node instanceof AST_Scope) abort = true;
|
||||||
}
|
}
|
||||||
@@ -1106,7 +1094,9 @@ merge(Compressor.prototype, {
|
|||||||
var lhs_local = is_lhs_local(lhs);
|
var lhs_local = is_lhs_local(lhs);
|
||||||
if (!side_effects) side_effects = value_has_side_effects(candidate);
|
if (!side_effects) side_effects = value_has_side_effects(candidate);
|
||||||
var replace_all = replace_all_symbols();
|
var replace_all = replace_all_symbols();
|
||||||
var may_throw = candidate.may_throw(compressor);
|
var may_throw = candidate.may_throw(compressor) ? in_try ? function(node) {
|
||||||
|
return node.has_side_effects(compressor);
|
||||||
|
} : side_effects_external : return_false;
|
||||||
var funarg = candidate.name instanceof AST_SymbolFunarg;
|
var funarg = candidate.name instanceof AST_SymbolFunarg;
|
||||||
var hit = funarg;
|
var hit = funarg;
|
||||||
var abort = false, replaced = 0, can_replace = !args || !hit;
|
var abort = false, replaced = 0, can_replace = !args || !hit;
|
||||||
@@ -1158,6 +1148,51 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function should_stop(node, parent) {
|
||||||
|
if (node instanceof AST_Assign) return node.operator != "=" && lhs.equivalent_to(node.left);
|
||||||
|
if (node instanceof AST_Call) {
|
||||||
|
return lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression);
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Debugger) return true;
|
||||||
|
if (node instanceof AST_IterationStatement) return !(node instanceof AST_For);
|
||||||
|
if (node instanceof AST_LoopControl) return true;
|
||||||
|
if (node instanceof AST_Try) return true;
|
||||||
|
if (node instanceof AST_With) return true;
|
||||||
|
if (parent instanceof AST_For) return node !== parent.init;
|
||||||
|
if (replace_all) return false;
|
||||||
|
return node instanceof AST_SymbolRef && !node.is_declared(compressor);
|
||||||
|
}
|
||||||
|
|
||||||
|
function in_conditional(node, parent) {
|
||||||
|
if (parent instanceof AST_Binary) return lazy_op[parent.operator] && parent.left !== node;
|
||||||
|
if (parent instanceof AST_Conditional) return parent.condition !== node;
|
||||||
|
return parent instanceof AST_If && parent.condition !== node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_last_node(node, parent) {
|
||||||
|
if (node instanceof AST_Call) return true;
|
||||||
|
if (node instanceof AST_Exit) {
|
||||||
|
return side_effects || lhs instanceof AST_PropAccess || may_modify(lhs);
|
||||||
|
}
|
||||||
|
if (node instanceof AST_PropAccess) {
|
||||||
|
return side_effects || node.expression.may_throw_on_access(compressor);
|
||||||
|
}
|
||||||
|
if (node instanceof AST_SymbolRef) {
|
||||||
|
if (symbol_in_lvalues(node, parent)) {
|
||||||
|
return !parent || parent.operator != "=" || parent.left !== node;
|
||||||
|
}
|
||||||
|
return side_effects && may_modify(node);
|
||||||
|
}
|
||||||
|
if (node instanceof AST_This) return symbol_in_lvalues(node, parent);
|
||||||
|
if (node instanceof AST_VarDef) {
|
||||||
|
if (!node.value) return false;
|
||||||
|
return node.name.name in lvalues || side_effects && may_modify(node.name);
|
||||||
|
}
|
||||||
|
var sym = is_lhs(node.left, node);
|
||||||
|
if (sym && sym.name in lvalues) return true;
|
||||||
|
if (sym instanceof AST_PropAccess) return true;
|
||||||
|
}
|
||||||
|
|
||||||
function extract_args() {
|
function extract_args() {
|
||||||
var iife, fn = compressor.self();
|
var iife, fn = compressor.self();
|
||||||
if (fn instanceof AST_Function
|
if (fn instanceof AST_Function
|
||||||
@@ -1336,8 +1371,9 @@ merge(Compressor.prototype, {
|
|||||||
if (expr instanceof AST_VarDef) {
|
if (expr instanceof AST_VarDef) {
|
||||||
var def = expr.name.definition();
|
var def = expr.name.definition();
|
||||||
if (!member(expr.name, def.orig)) return;
|
if (!member(expr.name, def.orig)) return;
|
||||||
var declared = def.orig.length - def.eliminated;
|
|
||||||
var referenced = def.references.length - def.replaced;
|
var referenced = def.references.length - def.replaced;
|
||||||
|
if (!referenced) return;
|
||||||
|
var declared = def.orig.length - def.eliminated;
|
||||||
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
||||||
|| (referenced > 1 ? mangleable_var(expr) : !compressor.exposed(def))) {
|
|| (referenced > 1 ? mangleable_var(expr) : !compressor.exposed(def))) {
|
||||||
return make_node(AST_SymbolRef, expr.name, expr.name);
|
return make_node(AST_SymbolRef, expr.name, expr.name);
|
||||||
@@ -1406,7 +1442,7 @@ merge(Compressor.prototype, {
|
|||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
var sym = root_expr(node);
|
var sym = root_expr(node);
|
||||||
if (sym instanceof AST_SymbolRef || sym instanceof AST_This) {
|
if (sym instanceof AST_SymbolRef || sym instanceof AST_This) {
|
||||||
lvalues[sym.name] = lvalues[sym.name] || is_lhs(node, tw.parent());
|
lvalues[sym.name] = lvalues[sym.name] || is_modified(compressor, tw, node, node, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
expr.walk(tw);
|
expr.walk(tw);
|
||||||
@@ -1468,10 +1504,10 @@ merge(Compressor.prototype, {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function symbol_in_lvalues(sym) {
|
function symbol_in_lvalues(sym, parent) {
|
||||||
var lvalue = lvalues[sym.name];
|
var lvalue = lvalues[sym.name];
|
||||||
if (!lvalue) return;
|
if (!lvalue) return;
|
||||||
if (lvalue !== lhs) return true;
|
if (lvalue !== lhs) return !(parent instanceof AST_Call);
|
||||||
scan_rhs = false;
|
scan_rhs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1870,9 +1906,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function join_object_assignments(defn, body) {
|
function join_object_assignments(defn, body) {
|
||||||
if (!(defn instanceof AST_Definitions)) return;
|
|
||||||
var def = defn.definitions[defn.definitions.length - 1];
|
|
||||||
if (!(def.value instanceof AST_Object)) return;
|
|
||||||
var exprs;
|
var exprs;
|
||||||
if (body instanceof AST_Assign) {
|
if (body instanceof AST_Assign) {
|
||||||
exprs = [ body ];
|
exprs = [ body ];
|
||||||
@@ -1880,6 +1913,23 @@ merge(Compressor.prototype, {
|
|||||||
exprs = body.expressions.slice();
|
exprs = body.expressions.slice();
|
||||||
}
|
}
|
||||||
if (!exprs) return;
|
if (!exprs) return;
|
||||||
|
if (defn instanceof AST_Definitions) {
|
||||||
|
var def = defn.definitions[defn.definitions.length - 1];
|
||||||
|
if (trim_object_assignments(def.name, def.value, exprs)) return exprs;
|
||||||
|
}
|
||||||
|
for (var i = exprs.length - 1; --i >= 0;) {
|
||||||
|
var expr = exprs[i];
|
||||||
|
if (!(expr instanceof AST_Assign)) continue;
|
||||||
|
if (expr.operator != "=") continue;
|
||||||
|
if (!(expr.left instanceof AST_SymbolRef)) continue;
|
||||||
|
var tail = exprs.slice(i + 1);
|
||||||
|
if (!trim_object_assignments(expr.left, expr.right, tail)) continue;
|
||||||
|
return exprs.slice(0, i + 1).concat(tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim_object_assignments(name, value, exprs) {
|
||||||
|
if (!(value instanceof AST_Object)) return;
|
||||||
var trimmed = false;
|
var trimmed = false;
|
||||||
do {
|
do {
|
||||||
var node = exprs[0];
|
var node = exprs[0];
|
||||||
@@ -1888,7 +1938,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!(node.left instanceof AST_PropAccess)) break;
|
if (!(node.left instanceof AST_PropAccess)) break;
|
||||||
var sym = node.left.expression;
|
var sym = node.left.expression;
|
||||||
if (!(sym instanceof AST_SymbolRef)) break;
|
if (!(sym instanceof AST_SymbolRef)) break;
|
||||||
if (def.name.name != sym.name) break;
|
if (name.name != sym.name) break;
|
||||||
if (!node.right.is_constant_expression(scope)) break;
|
if (!node.right.is_constant_expression(scope)) break;
|
||||||
var prop = node.left.property;
|
var prop = node.left.property;
|
||||||
if (prop instanceof AST_Node) {
|
if (prop instanceof AST_Node) {
|
||||||
@@ -1901,15 +1951,15 @@ merge(Compressor.prototype, {
|
|||||||
} : function(node) {
|
} : function(node) {
|
||||||
return node.key.name != prop;
|
return node.key.name != prop;
|
||||||
};
|
};
|
||||||
if (!all(def.value.properties, diff)) break;
|
if (!all(value.properties, diff)) break;
|
||||||
def.value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
||||||
key: prop,
|
key: prop,
|
||||||
value: node.right
|
value: node.right
|
||||||
}));
|
}));
|
||||||
exprs.shift();
|
exprs.shift();
|
||||||
trimmed = true;
|
trimmed = true;
|
||||||
} while (exprs.length);
|
} while (exprs.length);
|
||||||
return trimmed && exprs;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function join_consecutive_vars(statements) {
|
function join_consecutive_vars(statements) {
|
||||||
@@ -3613,28 +3663,50 @@ merge(Compressor.prototype, {
|
|||||||
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||||
var defs_by_id = Object.create(null);
|
var defs_by_id = Object.create(null);
|
||||||
return self.transform(new TreeTransformer(function(node, descend) {
|
return self.transform(new TreeTransformer(function(node, descend) {
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_Assign
|
||||||
var sym = node.name, def, value;
|
&& node.operator == "="
|
||||||
if (sym.scope === self
|
&& node.write_only
|
||||||
&& (def = sym.definition()).escaped != 1
|
&& can_hoist(node.left, node.right, 1)) {
|
||||||
&& !def.assignments
|
|
||||||
&& !def.direct_access
|
|
||||||
&& !def.single_use
|
|
||||||
&& !top_retain(def)
|
|
||||||
&& (value = sym.fixed_value()) === node.value
|
|
||||||
&& value instanceof AST_Object) {
|
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
var defs = new Dictionary();
|
var defs = new Dictionary();
|
||||||
var assignments = [];
|
var assignments = [];
|
||||||
value.properties.forEach(function(prop) {
|
var decls = [];
|
||||||
assignments.push(make_node(AST_VarDef, node, {
|
node.right.properties.forEach(function(prop) {
|
||||||
name: make_sym(prop.key),
|
var decl = make_sym(node.left, prop.key);
|
||||||
|
decls.push(make_node(AST_VarDef, node, {
|
||||||
|
name: decl,
|
||||||
|
value: null
|
||||||
|
}));
|
||||||
|
var sym = make_node(AST_SymbolRef, node, {
|
||||||
|
name: decl.name,
|
||||||
|
scope: self,
|
||||||
|
thedef: decl.definition()
|
||||||
|
});
|
||||||
|
sym.reference({});
|
||||||
|
assignments.push(make_node(AST_Assign, node, {
|
||||||
|
operator: "=",
|
||||||
|
left: sym,
|
||||||
|
right: prop.value
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
defs_by_id[node.left.definition().id] = defs;
|
||||||
|
self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
|
||||||
|
definitions: decls
|
||||||
|
}));
|
||||||
|
return make_sequence(node, assignments);
|
||||||
|
}
|
||||||
|
if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) {
|
||||||
|
descend(node, this);
|
||||||
|
var defs = new Dictionary();
|
||||||
|
var var_defs = [];
|
||||||
|
node.value.properties.forEach(function(prop) {
|
||||||
|
var_defs.push(make_node(AST_VarDef, node, {
|
||||||
|
name: make_sym(node.name, prop.key),
|
||||||
value: prop.value
|
value: prop.value
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
defs_by_id[def.id] = defs;
|
defs_by_id[node.name.definition().id] = defs;
|
||||||
return MAP.splice(assignments);
|
return MAP.splice(var_defs);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
||||||
var defs = defs_by_id[node.expression.definition().id];
|
var defs = defs_by_id[node.expression.definition().id];
|
||||||
@@ -3650,8 +3722,20 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_sym(key) {
|
function can_hoist(sym, right, count) {
|
||||||
var new_var = make_node(sym.CTOR, sym, {
|
if (sym.scope !== self) return;
|
||||||
|
var def = sym.definition();
|
||||||
|
if (def.assignments != count) return;
|
||||||
|
if (def.direct_access) return;
|
||||||
|
if (def.escaped == 1) 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, {
|
||||||
name: self.make_var_name(sym.name + "_" + key),
|
name: self.make_var_name(sym.name + "_" + key),
|
||||||
scope: self
|
scope: self
|
||||||
});
|
});
|
||||||
@@ -3837,6 +3921,20 @@ merge(Compressor.prototype, {
|
|||||||
return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
|
return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function has_break_or_continue(loop, parent) {
|
||||||
|
var found = false;
|
||||||
|
var tw = new TreeWalker(function(node) {
|
||||||
|
if (found || node instanceof AST_Scope) return true;
|
||||||
|
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === loop) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (parent instanceof AST_LabeledStatement) tw.push(parent);
|
||||||
|
tw.push(loop);
|
||||||
|
loop.body.walk(tw);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_Do, function(self, compressor){
|
OPT(AST_Do, function(self, compressor){
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
|
var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
|
||||||
@@ -3851,15 +3949,8 @@ merge(Compressor.prototype, {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
var has_loop_control = false;
|
if (!has_break_or_continue(self, compressor.parent())) {
|
||||||
var tw = new TreeWalker(function(node) {
|
return make_node(AST_BlockStatement, self.body, {
|
||||||
if (node instanceof AST_Scope || has_loop_control) return true;
|
|
||||||
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
|
|
||||||
return has_loop_control = true;
|
|
||||||
});
|
|
||||||
var parent = compressor.parent();
|
|
||||||
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
|
|
||||||
if (!has_loop_control) return make_node(AST_BlockStatement, self.body, {
|
|
||||||
body: [
|
body: [
|
||||||
self.body,
|
self.body,
|
||||||
make_node(AST_SimpleStatement, self.condition, {
|
make_node(AST_SimpleStatement, self.condition, {
|
||||||
@@ -3868,6 +3959,7 @@ merge(Compressor.prototype, {
|
|||||||
]
|
]
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
||||||
condition: make_sequence(self.condition, [
|
condition: make_sequence(self.condition, [
|
||||||
self.body.body,
|
self.body.body,
|
||||||
@@ -4573,7 +4665,8 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var stat = is_func && fn.body[0];
|
var stat = is_func && fn.body[0];
|
||||||
if (compressor.option("inline") && stat instanceof AST_Return) {
|
var can_inline = compressor.option("inline") && !self.is_expr_pure(compressor);
|
||||||
|
if (can_inline && stat instanceof AST_Return) {
|
||||||
var value = stat.value;
|
var value = stat.value;
|
||||||
if (!value || value.is_constant_expression()) {
|
if (!value || value.is_constant_expression()) {
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -4587,7 +4680,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (is_func) {
|
if (is_func) {
|
||||||
var def, value, scope, in_loop, level = -1;
|
var def, value, scope, in_loop, level = -1;
|
||||||
if (compressor.option("inline")
|
if (can_inline
|
||||||
&& !fn.uses_arguments
|
&& !fn.uses_arguments
|
||||||
&& !fn.uses_eval
|
&& !fn.uses_eval
|
||||||
&& !(fn.name && fn instanceof AST_Function)
|
&& !(fn.name && fn instanceof AST_Function)
|
||||||
@@ -4772,6 +4865,11 @@ merge(Compressor.prototype, {
|
|||||||
for (var j = 0, defs = stat.definitions.length; j < defs; j++) {
|
for (var j = 0, defs = stat.definitions.length; j < defs; 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();
|
||||||
|
if (redef) {
|
||||||
|
name = name.clone();
|
||||||
|
name.thedef = redef;
|
||||||
|
}
|
||||||
append_var(decls, expressions, name, var_def.value);
|
append_var(decls, expressions, name, var_def.value);
|
||||||
if (in_loop && all(fn.argnames, function(argname) {
|
if (in_loop && all(fn.argnames, function(argname) {
|
||||||
return argname.name != name.name;
|
return argname.name != name.name;
|
||||||
@@ -5460,11 +5558,12 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Infinity, self).optimize(compressor);
|
return make_node(AST_Infinity, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("reduce_vars")
|
var parent = compressor.parent();
|
||||||
&& is_lhs(self, compressor.parent()) !== self) {
|
if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
|
||||||
var d = self.definition();
|
var d = self.definition();
|
||||||
var fixed = self.fixed_value();
|
var fixed = self.fixed_value();
|
||||||
var single_use = d.single_use;
|
var single_use = d.single_use
|
||||||
|
&& !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
|
||||||
if (single_use && fixed instanceof AST_Lambda) {
|
if (single_use && fixed instanceof AST_Lambda) {
|
||||||
if (d.scope !== self.scope
|
if (d.scope !== self.scope
|
||||||
&& (!compressor.option("reduce_funcs")
|
&& (!compressor.option("reduce_funcs")
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ function OutputStream(options) {
|
|||||||
default:
|
default:
|
||||||
return dq > sq ? quote_single() : quote_double();
|
return dq > sq ? quote_single() : quote_double();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function encode_string(str, quote) {
|
function encode_string(str, quote) {
|
||||||
var ret = make_string(str, quote);
|
var ret = make_string(str, quote);
|
||||||
@@ -183,17 +183,17 @@ function OutputStream(options) {
|
|||||||
ret = ret.replace(/--\x3e/g, "--\\x3e");
|
ret = ret.replace(/--\x3e/g, "--\\x3e");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|
||||||
function make_name(name) {
|
function make_name(name) {
|
||||||
name = name.toString();
|
name = name.toString();
|
||||||
name = to_utf8(name, true);
|
name = to_utf8(name, true);
|
||||||
return name;
|
return name;
|
||||||
};
|
}
|
||||||
|
|
||||||
function make_indent(back) {
|
function make_indent(back) {
|
||||||
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
|
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
|
||||||
};
|
}
|
||||||
|
|
||||||
/* -----[ beautification/minification ]----- */
|
/* -----[ beautification/minification ]----- */
|
||||||
|
|
||||||
@@ -351,7 +351,7 @@ function OutputStream(options) {
|
|||||||
current_col = a[n].length;
|
current_col = a[n].length;
|
||||||
}
|
}
|
||||||
last = str;
|
last = str;
|
||||||
};
|
}
|
||||||
|
|
||||||
var space = options.beautify ? function() {
|
var space = options.beautify ? function() {
|
||||||
print(" ");
|
print(" ");
|
||||||
@@ -374,6 +374,11 @@ function OutputStream(options) {
|
|||||||
return ret;
|
return ret;
|
||||||
} : function(col, cont) { return cont() };
|
} : function(col, cont) { return cont() };
|
||||||
|
|
||||||
|
var may_add_newline = options.max_line_len ? function() {
|
||||||
|
ensure_line_len();
|
||||||
|
might_add_newline = OUTPUT.length;
|
||||||
|
} : noop;
|
||||||
|
|
||||||
var newline = options.beautify ? function() {
|
var newline = options.beautify ? function() {
|
||||||
if (newline_insert < 0) return print("\n");
|
if (newline_insert < 0) return print("\n");
|
||||||
if (OUTPUT[newline_insert] != "\n") {
|
if (OUTPUT[newline_insert] != "\n") {
|
||||||
@@ -382,10 +387,7 @@ function OutputStream(options) {
|
|||||||
current_line++;
|
current_line++;
|
||||||
}
|
}
|
||||||
newline_insert++;
|
newline_insert++;
|
||||||
} : options.max_line_len ? function() {
|
} : may_add_newline;
|
||||||
ensure_line_len();
|
|
||||||
might_add_newline = OUTPUT.length;
|
|
||||||
} : noop;
|
|
||||||
|
|
||||||
var semicolon = options.beautify ? function() {
|
var semicolon = options.beautify ? function() {
|
||||||
print(";");
|
print(";");
|
||||||
@@ -396,11 +398,11 @@ function OutputStream(options) {
|
|||||||
function force_semicolon() {
|
function force_semicolon() {
|
||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
print(";");
|
print(";");
|
||||||
};
|
}
|
||||||
|
|
||||||
function next_indent() {
|
function next_indent() {
|
||||||
return indentation + options.indent_level;
|
return indentation + options.indent_level;
|
||||||
};
|
}
|
||||||
|
|
||||||
function with_block(cont) {
|
function with_block(cont) {
|
||||||
var ret;
|
var ret;
|
||||||
@@ -412,34 +414,40 @@ function OutputStream(options) {
|
|||||||
indent();
|
indent();
|
||||||
print("}");
|
print("}");
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|
||||||
function with_parens(cont) {
|
function with_parens(cont) {
|
||||||
print("(");
|
print("(");
|
||||||
|
may_add_newline();
|
||||||
//XXX: still nice to have that for argument lists
|
//XXX: still nice to have that for argument lists
|
||||||
//var ret = with_indent(current_col, cont);
|
//var ret = with_indent(current_col, cont);
|
||||||
var ret = cont();
|
var ret = cont();
|
||||||
|
may_add_newline();
|
||||||
print(")");
|
print(")");
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|
||||||
function with_square(cont) {
|
function with_square(cont) {
|
||||||
print("[");
|
print("[");
|
||||||
|
may_add_newline();
|
||||||
//var ret = with_indent(current_col, cont);
|
//var ret = with_indent(current_col, cont);
|
||||||
var ret = cont();
|
var ret = cont();
|
||||||
|
may_add_newline();
|
||||||
print("]");
|
print("]");
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|
||||||
function comma() {
|
function comma() {
|
||||||
|
may_add_newline();
|
||||||
print(",");
|
print(",");
|
||||||
|
may_add_newline();
|
||||||
space();
|
space();
|
||||||
};
|
}
|
||||||
|
|
||||||
function colon() {
|
function colon() {
|
||||||
print(":");
|
print(":");
|
||||||
space();
|
space();
|
||||||
};
|
}
|
||||||
|
|
||||||
var add_mapping = mappings ? function(token, name) {
|
var add_mapping = mappings ? function(token, name) {
|
||||||
mapping_token = token;
|
mapping_token = token;
|
||||||
@@ -451,7 +459,7 @@ function OutputStream(options) {
|
|||||||
ensure_line_len();
|
ensure_line_len();
|
||||||
}
|
}
|
||||||
return OUTPUT;
|
return OUTPUT;
|
||||||
};
|
}
|
||||||
|
|
||||||
function has_nlb() {
|
function has_nlb() {
|
||||||
var index = OUTPUT.lastIndexOf("\n");
|
var index = OUTPUT.lastIndexOf("\n");
|
||||||
@@ -619,8 +627,7 @@ function OutputStream(options) {
|
|||||||
return stack[stack.length - 2 - (n || 0)];
|
return stack[stack.length - 2 - (n || 0)];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/* -----[ code generators ]----- */
|
/* -----[ code generators ]----- */
|
||||||
|
|
||||||
@@ -630,7 +637,7 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function DEFPRINT(nodetype, generator) {
|
function DEFPRINT(nodetype, generator) {
|
||||||
nodetype.DEFMETHOD("_codegen", generator);
|
nodetype.DEFMETHOD("_codegen", generator);
|
||||||
};
|
}
|
||||||
|
|
||||||
var in_directive = false;
|
var in_directive = false;
|
||||||
var active_scope = null;
|
var active_scope = null;
|
||||||
@@ -679,7 +686,7 @@ function OutputStream(options) {
|
|||||||
} else {
|
} else {
|
||||||
nodetype.DEFMETHOD("needs_parens", func);
|
nodetype.DEFMETHOD("needs_parens", func);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
PARENS(AST_Node, return_false);
|
PARENS(AST_Node, return_false);
|
||||||
|
|
||||||
@@ -865,7 +872,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
in_directive = false;
|
in_directive = false;
|
||||||
};
|
}
|
||||||
|
|
||||||
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
|
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
|
||||||
force_statement(this.body, output);
|
force_statement(this.body, output);
|
||||||
@@ -901,7 +908,7 @@ function OutputStream(options) {
|
|||||||
display_body(self.body, false, output, allow_directives);
|
display_body(self.body, false, output, allow_directives);
|
||||||
});
|
});
|
||||||
} else print_braced_empty(self, output);
|
} else print_braced_empty(self, output);
|
||||||
};
|
}
|
||||||
DEFPRINT(AST_BlockStatement, function(self, output){
|
DEFPRINT(AST_BlockStatement, function(self, output){
|
||||||
print_braced(self, output);
|
print_braced(self, output);
|
||||||
});
|
});
|
||||||
@@ -1064,7 +1071,7 @@ function OutputStream(options) {
|
|||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
force_statement(self.body, output);
|
force_statement(self.body, output);
|
||||||
};
|
}
|
||||||
DEFPRINT(AST_If, function(self, output){
|
DEFPRINT(AST_If, function(self, output){
|
||||||
output.print("if");
|
output.print("if");
|
||||||
output.space();
|
output.space();
|
||||||
@@ -1184,7 +1191,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
node.print(output, parens);
|
node.print(output, parens);
|
||||||
};
|
}
|
||||||
|
|
||||||
DEFPRINT(AST_VarDef, function(self, output){
|
DEFPRINT(AST_VarDef, function(self, output){
|
||||||
self.name.print(output);
|
self.name.print(output);
|
||||||
@@ -1430,7 +1437,7 @@ function OutputStream(options) {
|
|||||||
else
|
else
|
||||||
stat.print(output);
|
stat.print(output);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// self should be AST_New. decide if we want to show parens or not.
|
// self should be AST_New. decide if we want to show parens or not.
|
||||||
function need_constructor_parens(self, output) {
|
function need_constructor_parens(self, output) {
|
||||||
@@ -1438,7 +1445,7 @@ function OutputStream(options) {
|
|||||||
if (self.args.length > 0) return true;
|
if (self.args.length > 0) return true;
|
||||||
|
|
||||||
return output.option("beautify");
|
return output.option("beautify");
|
||||||
};
|
}
|
||||||
|
|
||||||
function best_of(a) {
|
function best_of(a) {
|
||||||
var best = a[0], len = best.length;
|
var best = a[0], len = best.length;
|
||||||
@@ -1449,27 +1456,31 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return best;
|
return best;
|
||||||
};
|
}
|
||||||
|
|
||||||
function make_num(num) {
|
function make_num(num) {
|
||||||
var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
|
var str = num.toString(10).replace(/^0\./, ".").replace("e+", "e");
|
||||||
|
var candidates = [ str ];
|
||||||
if (Math.floor(num) === num) {
|
if (Math.floor(num) === num) {
|
||||||
if (num >= 0) {
|
if (num < 0) {
|
||||||
a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
|
candidates.push("-0x" + (-num).toString(16).toLowerCase());
|
||||||
"0" + num.toString(8)); // same.
|
|
||||||
} else {
|
} else {
|
||||||
a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
|
candidates.push("0x" + num.toString(16).toLowerCase());
|
||||||
"-0" + (-num).toString(8)); // same.
|
|
||||||
}
|
}
|
||||||
if ((m = /^(.*?)(0+)$/.exec(num))) {
|
|
||||||
a.push(m[1] + "e" + m[2].length);
|
|
||||||
}
|
}
|
||||||
} else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
|
var match, len, digits;
|
||||||
a.push(m[2] + "e-" + (m[1].length + m[2].length),
|
if (match = /^\.0+/.exec(str)) {
|
||||||
str.substr(str.indexOf(".")));
|
len = match[0].length;
|
||||||
|
digits = str.slice(len);
|
||||||
|
candidates.push(digits + "e-" + (digits.length + len - 1));
|
||||||
|
} else if (match = /0+$/.exec(str)) {
|
||||||
|
len = match[0].length;
|
||||||
|
candidates.push(str.slice(0, -len) + "e" + len);
|
||||||
|
} else if (match = /^(\d)\.(\d+)e(-?\d+)$/.exec(str)) {
|
||||||
|
candidates.push(match[1] + match[2] + "e" + (match[3] - match[2].length));
|
||||||
|
}
|
||||||
|
return best_of(candidates);
|
||||||
}
|
}
|
||||||
return best_of(a);
|
|
||||||
};
|
|
||||||
|
|
||||||
function make_block(stmt, output) {
|
function make_block(stmt, output) {
|
||||||
if (!stmt || stmt instanceof AST_EmptyStatement)
|
if (!stmt || stmt instanceof AST_EmptyStatement)
|
||||||
@@ -1481,7 +1492,7 @@ function OutputStream(options) {
|
|||||||
stmt.print(output);
|
stmt.print(output);
|
||||||
output.newline();
|
output.newline();
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/* -----[ source map generators ]----- */
|
/* -----[ source map generators ]----- */
|
||||||
|
|
||||||
|
|||||||
36
lib/scope.js
36
lib/scope.js
@@ -55,7 +55,7 @@ function SymbolDef(scope, orig, init) {
|
|||||||
this.mangled_name = null;
|
this.mangled_name = null;
|
||||||
this.undeclared = false;
|
this.undeclared = false;
|
||||||
this.id = SymbolDef.next_id++;
|
this.id = SymbolDef.next_id++;
|
||||||
};
|
}
|
||||||
|
|
||||||
SymbolDef.next_id = 1;
|
SymbolDef.next_id = 1;
|
||||||
|
|
||||||
@@ -344,7 +344,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[name]) continue;
|
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
|
||||||
if (!names[name]) break;
|
if (!names[name]) break;
|
||||||
holes.push(scope.cname);
|
holes.push(scope.cname);
|
||||||
}
|
}
|
||||||
@@ -387,7 +387,7 @@ function _default_mangler_options(options) {
|
|||||||
if (!Array.isArray(options.reserved)) options.reserved = [];
|
if (!Array.isArray(options.reserved)) options.reserved = [];
|
||||||
// Never mangle arguments
|
// Never mangle arguments
|
||||||
push_uniq(options.reserved, "arguments");
|
push_uniq(options.reserved, "arguments");
|
||||||
options._reserved = makePredicate(options.reserved);
|
options.reserved.has = makePredicate(options.reserved);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +453,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
redefined.forEach(mangle);
|
redefined.forEach(mangle);
|
||||||
|
|
||||||
function mangle(def) {
|
function mangle(def) {
|
||||||
if (options._reserved[def.name]) return;
|
if (options.reserved.has[def.name]) return;
|
||||||
def.mangle(options);
|
def.mangle(options);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -504,7 +504,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
function rename(def) {
|
function rename(def) {
|
||||||
if (def.global && options.cache) return;
|
if (def.global && options.cache) return;
|
||||||
if (def.unmangleable(options)) return;
|
if (def.unmangleable(options)) return;
|
||||||
if (options._reserved[def.name]) return;
|
if (options.reserved.has[def.name]) return;
|
||||||
var d = def.redefined();
|
var d = def.redefined();
|
||||||
def.name = d ? d.name : next_name();
|
def.name = d ? d.name : next_name();
|
||||||
def.orig.forEach(function(sym) {
|
def.orig.forEach(function(sym) {
|
||||||
@@ -556,17 +556,21 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
|||||||
});
|
});
|
||||||
|
|
||||||
var base54 = (function() {
|
var base54 = (function() {
|
||||||
var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
|
var freq = Object.create(null);
|
||||||
var digits = "0123456789".split("");
|
function init(chars) {
|
||||||
|
var array = [];
|
||||||
|
for (var i = 0, len = chars.length; i < len; i++) {
|
||||||
|
var ch = chars[i];
|
||||||
|
array.push(ch);
|
||||||
|
freq[ch] = -1e-2 * i;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
var digits = init("0123456789");
|
||||||
|
var leading = init("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_");
|
||||||
var chars, frequency;
|
var chars, frequency;
|
||||||
function reset() {
|
function reset() {
|
||||||
frequency = Object.create(null);
|
frequency = Object.create(freq);
|
||||||
leading.forEach(function(ch) {
|
|
||||||
frequency[ch] = 0;
|
|
||||||
});
|
|
||||||
digits.forEach(function(ch) {
|
|
||||||
frequency[ch] = 0;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
base54.consider = function(str, delta) {
|
base54.consider = function(str, delta) {
|
||||||
for (var i = str.length; --i >= 0;) {
|
for (var i = str.length; --i >= 0;) {
|
||||||
@@ -577,7 +581,7 @@ var base54 = (function() {
|
|||||||
return frequency[b] - frequency[a];
|
return frequency[b] - frequency[a];
|
||||||
}
|
}
|
||||||
base54.sort = function() {
|
base54.sort = function() {
|
||||||
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
|
chars = leading.sort(compare).concat(digits.sort(compare));
|
||||||
};
|
};
|
||||||
base54.reset = reset;
|
base54.reset = reset;
|
||||||
reset();
|
reset();
|
||||||
@@ -591,6 +595,6 @@ var base54 = (function() {
|
|||||||
base = 64;
|
base = 64;
|
||||||
} while (num > 0);
|
} while (num > 0);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
return base54;
|
return base54;
|
||||||
})();
|
})();
|
||||||
|
|||||||
94
lib/utils.js
94
lib/utils.js
@@ -45,27 +45,25 @@
|
|||||||
|
|
||||||
function characters(str) {
|
function characters(str) {
|
||||||
return str.split("");
|
return str.split("");
|
||||||
};
|
}
|
||||||
|
|
||||||
function member(name, array) {
|
function member(name, array) {
|
||||||
return array.indexOf(name) >= 0;
|
return array.indexOf(name) >= 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
function find_if(func, array) {
|
function find_if(func, array) {
|
||||||
for (var i = 0, n = array.length; i < n; ++i) {
|
for (var i = 0, n = array.length; i < n; ++i) {
|
||||||
if (func(array[i]))
|
if (func(array[i])) return array[i];
|
||||||
return array[i];
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function repeat_string(str, i) {
|
function repeat_string(str, i) {
|
||||||
if (i <= 0) return "";
|
if (i <= 0) return "";
|
||||||
if (i == 1) return str;
|
if (i == 1) return str;
|
||||||
var d = repeat_string(str, i >> 1);
|
var d = repeat_string(str, i >> 1);
|
||||||
d += d;
|
d += d;
|
||||||
if (i & 1) d += str;
|
return i & 1 ? d + str : d;
|
||||||
return d;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function configure_error_stack(fn) {
|
function configure_error_stack(fn) {
|
||||||
Object.defineProperty(fn.prototype, "stack", {
|
Object.defineProperty(fn.prototype, "stack", {
|
||||||
@@ -84,27 +82,23 @@ function configure_error_stack(fn) {
|
|||||||
function DefaultsError(msg, defs) {
|
function DefaultsError(msg, defs) {
|
||||||
this.message = msg;
|
this.message = msg;
|
||||||
this.defs = defs;
|
this.defs = defs;
|
||||||
};
|
}
|
||||||
DefaultsError.prototype = Object.create(Error.prototype);
|
DefaultsError.prototype = Object.create(Error.prototype);
|
||||||
DefaultsError.prototype.constructor = DefaultsError;
|
DefaultsError.prototype.constructor = DefaultsError;
|
||||||
DefaultsError.prototype.name = "DefaultsError";
|
DefaultsError.prototype.name = "DefaultsError";
|
||||||
configure_error_stack(DefaultsError);
|
configure_error_stack(DefaultsError);
|
||||||
|
|
||||||
DefaultsError.croak = function(msg, defs) {
|
|
||||||
throw new DefaultsError(msg, defs);
|
|
||||||
};
|
|
||||||
|
|
||||||
function defaults(args, defs, croak) {
|
function defaults(args, defs, croak) {
|
||||||
if (args === true)
|
if (args === true) args = {};
|
||||||
args = {};
|
|
||||||
var ret = args || {};
|
var ret = args || {};
|
||||||
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i))
|
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
|
||||||
DefaultsError.croak("`" + i + "` is not a supported option", defs);
|
throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
||||||
|
}
|
||||||
for (var i in defs) if (HOP(defs, i)) {
|
for (var i in defs) if (HOP(defs, i)) {
|
||||||
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|
||||||
function merge(obj, ext) {
|
function merge(obj, ext) {
|
||||||
var count = 0;
|
var count = 0;
|
||||||
@@ -113,7 +107,7 @@ function merge(obj, ext) {
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
};
|
}
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
function return_false() { return false; }
|
function return_false() { return false; }
|
||||||
@@ -172,43 +166,19 @@ var MAP = (function(){
|
|||||||
function push_uniq(array, el) {
|
function push_uniq(array, el) {
|
||||||
if (array.indexOf(el) < 0)
|
if (array.indexOf(el) < 0)
|
||||||
array.push(el);
|
array.push(el);
|
||||||
};
|
}
|
||||||
|
|
||||||
function string_template(text, props) {
|
function string_template(text, props) {
|
||||||
return text.replace(/\{(.+?)\}/g, function(str, p){
|
return text.replace(/\{(.+?)\}/g, function(str, p){
|
||||||
return props && props[p];
|
return props && props[p];
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
function remove(array, el) {
|
function remove(array, el) {
|
||||||
for (var i = array.length; --i >= 0;) {
|
for (var i = array.length; --i >= 0;) {
|
||||||
if (array[i] === el) array.splice(i, 1);
|
if (array[i] === el) array.splice(i, 1);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function mergeSort(array, cmp) {
|
|
||||||
if (array.length < 2) return array.slice();
|
|
||||||
function merge(a, b) {
|
|
||||||
var r = [], ai = 0, bi = 0, i = 0;
|
|
||||||
while (ai < a.length && bi < b.length) {
|
|
||||||
cmp(a[ai], b[bi]) <= 0
|
|
||||||
? r[i++] = a[ai++]
|
|
||||||
: r[i++] = b[bi++];
|
|
||||||
}
|
}
|
||||||
if (ai < a.length) r.push.apply(r, a.slice(ai));
|
|
||||||
if (bi < b.length) r.push.apply(r, b.slice(bi));
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
function _ms(a) {
|
|
||||||
if (a.length <= 1)
|
|
||||||
return a;
|
|
||||||
var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
|
|
||||||
left = _ms(left);
|
|
||||||
right = _ms(right);
|
|
||||||
return merge(left, right);
|
|
||||||
};
|
|
||||||
return _ms(array);
|
|
||||||
};
|
|
||||||
|
|
||||||
function makePredicate(words) {
|
function makePredicate(words) {
|
||||||
if (!Array.isArray(words)) words = words.split(" ");
|
if (!Array.isArray(words)) words = words.split(" ");
|
||||||
@@ -224,12 +194,12 @@ function all(array, predicate) {
|
|||||||
if (!predicate(array[i]))
|
if (!predicate(array[i]))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
function Dictionary() {
|
function Dictionary() {
|
||||||
this._values = Object.create(null);
|
this._values = Object.create(null);
|
||||||
this._size = 0;
|
this._size = 0;
|
||||||
};
|
}
|
||||||
Dictionary.prototype = {
|
Dictionary.prototype = {
|
||||||
set: function(key, val) {
|
set: function(key, val) {
|
||||||
if (!this.has(key)) ++this._size;
|
if (!this.has(key)) ++this._size;
|
||||||
@@ -290,20 +260,22 @@ function HOP(obj, prop) {
|
|||||||
// a statement.
|
// a statement.
|
||||||
function first_in_statement(stack) {
|
function first_in_statement(stack) {
|
||||||
var node = stack.parent(-1);
|
var node = stack.parent(-1);
|
||||||
for (var i = 0, p; p = stack.parent(i); i++) {
|
for (var i = 0, p; p = stack.parent(i++); node = p) {
|
||||||
if (p instanceof AST_Statement && p.body === node)
|
if (p.TYPE == "Call") {
|
||||||
return true;
|
if (p.expression === node) continue;
|
||||||
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
|
} else if (p instanceof AST_Binary) {
|
||||||
(p.TYPE == "Call" && p.expression === node ) ||
|
if (p.left === node) continue;
|
||||||
(p instanceof AST_Dot && p.expression === node ) ||
|
} else if (p instanceof AST_Conditional) {
|
||||||
(p instanceof AST_Sub && p.expression === node ) ||
|
if (p.condition === node) continue;
|
||||||
(p instanceof AST_Conditional && p.condition === node ) ||
|
} else if (p instanceof AST_PropAccess) {
|
||||||
(p instanceof AST_Binary && p.left === node ) ||
|
if (p.expression === node) continue;
|
||||||
(p instanceof AST_UnaryPostfix && p.expression === node ))
|
} else if (p instanceof AST_Sequence) {
|
||||||
{
|
if (p.expressions[0] === node) continue;
|
||||||
node = p;
|
} else if (p instanceof AST_Statement) {
|
||||||
} else {
|
return p.body === node;
|
||||||
|
} else if (p instanceof AST_UnaryPostfix) {
|
||||||
|
if (p.expression === node) continue;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -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.3.19",
|
"version": "3.3.23",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5327,3 +5327,24 @@ issue_3032: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3096: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var ar = ["a", "b"];
|
||||||
|
var first = ar.pop();
|
||||||
|
return ar + "" + first;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var ar = ["a", "b"];
|
||||||
|
var first = ar.pop();
|
||||||
|
return ar + "" + first;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "ab"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2267,3 +2267,39 @@ issue_3054: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true true"
|
expect_stdout: "true true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3076: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + function() {
|
||||||
|
e && (c = "FAIL");
|
||||||
|
e = 5;
|
||||||
|
return 1;
|
||||||
|
try {
|
||||||
|
var a = 5;
|
||||||
|
} catch (e) {
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
}().toString() && --n > 0);
|
||||||
|
})(2);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1).toString() && --n > 0);
|
||||||
|
var e;
|
||||||
|
})(2),
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -742,3 +742,117 @@ issue_3046: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3071_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var obj = {};
|
||||||
|
obj.one = 1;
|
||||||
|
obj.two = 2;
|
||||||
|
console.log(obj.one);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3071_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
obj = {};
|
||||||
|
obj.one = 1;
|
||||||
|
obj.two = 2;
|
||||||
|
console.log(obj.one);
|
||||||
|
var obj;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3071_2_toplevel: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
obj = {};
|
||||||
|
obj.one = 1;
|
||||||
|
obj.two = 2;
|
||||||
|
console.log(obj.one);
|
||||||
|
var obj;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3071_3: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function(a, b) {
|
||||||
|
(function f(o) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + (o = {
|
||||||
|
p: c++,
|
||||||
|
}) && --n > 0);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function(a, b) {
|
||||||
|
(function f(o) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + (o = {
|
||||||
|
p: c++,
|
||||||
|
}) && --n > 0);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ too_short: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: [
|
expect_exact: [
|
||||||
'function f(a){',
|
"function f(",
|
||||||
'return{',
|
"a){return{",
|
||||||
'c:42,',
|
"c:42,d:a(",
|
||||||
'd:a(),',
|
'),e:"foo"}',
|
||||||
'e:"foo"}}',
|
"}",
|
||||||
]
|
]
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Output exceeds 10 characters"
|
"WARN: Output exceeds 10 characters",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,11 +29,25 @@ just_enough: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: [
|
expect_exact: [
|
||||||
'function f(a){',
|
"function f(a){",
|
||||||
'return{c:42,',
|
"return{c:42,",
|
||||||
'd:a(),e:"foo"}',
|
'd:a(),e:"foo"}',
|
||||||
'}',
|
"}",
|
||||||
]
|
|
||||||
expect_warnings: [
|
|
||||||
]
|
]
|
||||||
|
expect_warnings: []
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_304: {
|
||||||
|
beautify = {
|
||||||
|
max_line_len: 10,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 0, c = 0, d = 0, e = 0;
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"var a=0,",
|
||||||
|
"b=0,c=0,",
|
||||||
|
"d=0,e=0;",
|
||||||
|
]
|
||||||
|
expect_warnings: []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
hex_numbers_in_parentheses_for_prototype_functions: {
|
hex_numbers_in_parentheses_for_prototype_functions: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
|
function f() {
|
||||||
(-2);
|
(-2);
|
||||||
(-2).toFixed(0);
|
(-2).toFixed(0);
|
||||||
|
|
||||||
@@ -9,13 +13,37 @@ hex_numbers_in_parentheses_for_prototype_functions: {
|
|||||||
(0.2);
|
(0.2);
|
||||||
(0.2).toFixed(0);
|
(0.2).toFixed(0);
|
||||||
|
|
||||||
|
(2.34e20);
|
||||||
|
(2.34e20).toFixed(0);
|
||||||
|
|
||||||
(0.00000002);
|
(0.00000002);
|
||||||
(0.00000002).toFixed(0);
|
(0.00000002).toFixed(0);
|
||||||
|
|
||||||
(1000000000000000128);
|
(1000000000000000128);
|
||||||
(1000000000000000128).toFixed(0);
|
(1000000000000000128).toFixed(0);
|
||||||
|
|
||||||
|
(-1000000000000000128);
|
||||||
|
(-1000000000000000128).toFixed(0);
|
||||||
}
|
}
|
||||||
expect_exact: "-2;(-2).toFixed(0);2;2..toFixed(0);.2;.2.toFixed(0);2e-8;2e-8.toFixed(0);0xde0b6b3a7640080;(0xde0b6b3a7640080).toFixed(0);"
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"function f() {",
|
||||||
|
" -2;",
|
||||||
|
" (-2).toFixed(0);",
|
||||||
|
" 2;",
|
||||||
|
" 2..toFixed(0);",
|
||||||
|
" .2;",
|
||||||
|
" .2.toFixed(0);",
|
||||||
|
" 234e18;",
|
||||||
|
" 234e18.toFixed(0);",
|
||||||
|
" 2e-8;",
|
||||||
|
" 2e-8.toFixed(0);",
|
||||||
|
" 0xde0b6b3a7640080;",
|
||||||
|
" (0xde0b6b3a7640080).toFixed(0);",
|
||||||
|
" -0xde0b6b3a7640080;",
|
||||||
|
" (-0xde0b6b3a7640080).toFixed(0);",
|
||||||
|
"}",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
comparisons: {
|
comparisons: {
|
||||||
|
|||||||
@@ -1208,6 +1208,37 @@ join_object_assignments_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
join_object_assignments_4: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o;
|
||||||
|
console.log(o);
|
||||||
|
o = {};
|
||||||
|
o.a = "foo";
|
||||||
|
console.log(o.b);
|
||||||
|
o.b = "bar";
|
||||||
|
console.log(o.a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o;
|
||||||
|
console.log(o),
|
||||||
|
o = {
|
||||||
|
a: "foo",
|
||||||
|
},
|
||||||
|
console.log(o.b),
|
||||||
|
o.b = "bar",
|
||||||
|
console.log(o.a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"undefined",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
join_object_assignments_return_1: {
|
join_object_assignments_return_1: {
|
||||||
options = {
|
options = {
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
|
|||||||
@@ -535,3 +535,110 @@ issue_2705_6: {
|
|||||||
"/* */new(/* */a()||b())(c(),d());",
|
"/* */new(/* */a()||b())(c(),d());",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3065_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
pure_funcs: [ "pureFunc" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function modifyWrapper(a, f, wrapper) {
|
||||||
|
wrapper.a = a;
|
||||||
|
wrapper.f = f;
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
function pureFunc(fun) {
|
||||||
|
return modifyWrapper(1, fun, function(a) {
|
||||||
|
return fun(a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var unused = pureFunc(function(x) {
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3065_2: {
|
||||||
|
rename = true
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
pure_funcs: [ "pureFunc" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
reserved: [ "pureFunc" ],
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function modifyWrapper(a, f, wrapper) {
|
||||||
|
wrapper.a = a;
|
||||||
|
wrapper.f = f;
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
function pureFunc(fun) {
|
||||||
|
return modifyWrapper(1, fun, function(a) {
|
||||||
|
return fun(a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var unused = pureFunc(function(x) {
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3065_3: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "debug" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function debug(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
debug(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
return "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3065_4: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "debug" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var debug = function(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
};
|
||||||
|
debug(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
return "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5654,3 +5654,59 @@ issue_3042_2: {
|
|||||||
"true",
|
"true",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3068_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
continue;
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
continue;
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3068_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
while ("" == typeof a);
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
while ("" == typeof a);
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
function test(a){
|
function test(a){
|
||||||
"aaaaaaaaaaaaaaaa"
|
"aaaaaaaaaaaaaaaa"
|
||||||
;a(err,data),a(err,data)
|
;a(err,data),a(err,
|
||||||
}
|
data)}
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQztBQUFLQyJ9
|
||||||
@@ -100,8 +100,8 @@ describe("bin/uglifyjs", function () {
|
|||||||
exec(command, function (err, stdout, stderr) {
|
exec(command, function (err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
var stderrLines = stderr.split('\n');
|
var stderrLines = stderr.split("\n");
|
||||||
assert.strictEqual(stderrLines[0], 'INFO: Using input source map: test/input/issue-2082/sample.js.map');
|
assert.strictEqual(stderrLines[0], "INFO: Using input source map: test/input/issue-2082/sample.js.map");
|
||||||
assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}');
|
assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -244,7 +244,8 @@ describe("bin/uglifyjs", function () {
|
|||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||||
"",
|
"",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.strictEqual(stderr, "WARN: inline source map not found: test/input/issue-1323/sample.js\n");
|
var stderrLines = stderr.split("\n");
|
||||||
|
assert.strictEqual(stderrLines[0], "WARN: inline source map not found: test/input/issue-1323/sample.js");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -264,7 +265,8 @@ describe("bin/uglifyjs", function () {
|
|||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||||
"",
|
"",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.strictEqual(stderr, "WARN: inline source map not found: test/input/issue-1323/sample.js\n");
|
var stderrLines = stderr.split("\n");
|
||||||
|
assert.strictEqual(stderrLines[0], "WARN: inline source map not found: test/input/issue-1323/sample.js");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ describe("parentheses", function() {
|
|||||||
"(function(){}).name;",
|
"(function(){}).name;",
|
||||||
];
|
];
|
||||||
for (var i = 16; --i >= 0;) {
|
for (var i = 16; --i >= 0;) {
|
||||||
[].push.apply(code, code);
|
code = code.concat(code);
|
||||||
}
|
}
|
||||||
code = code.join("");
|
code = code.join("");
|
||||||
var result = uglify.minify(code, {
|
var result = uglify.minify(code, {
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ function run_compress_tests() {
|
|||||||
}
|
}
|
||||||
if (test.expect_stdout
|
if (test.expect_stdout
|
||||||
&& (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
&& (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
||||||
var stdout = sandbox.run_code(input_code, true);
|
var stdout = run_code(input_code);
|
||||||
if (test.expect_stdout === true) {
|
if (test.expect_stdout === true) {
|
||||||
test.expect_stdout = stdout;
|
test.expect_stdout = stdout;
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ function run_compress_tests() {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
stdout = sandbox.run_code(output, true);
|
stdout = run_code(output);
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
||||||
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
@@ -344,6 +344,11 @@ function evaluate(code) {
|
|||||||
return new Function("return(" + code + ")")();
|
return new Function("return(" + code + ")")();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run_code(code) {
|
||||||
|
var result = sandbox.run_code(code, true);
|
||||||
|
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to reminify original input with standard options
|
// Try to reminify original input with standard options
|
||||||
// to see if it matches expect_stdout.
|
// to see if it matches expect_stdout.
|
||||||
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
||||||
@@ -367,7 +372,7 @@ function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
var stdout = sandbox.run_code(result.code, true);
|
var stdout = run_code(result.code);
|
||||||
if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) {
|
if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) {
|
||||||
stdout = expect_stdout;
|
stdout = expect_stdout;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ var semver = require("semver");
|
|||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
|
|
||||||
function createContext() {
|
function createContext() {
|
||||||
var context = Object.create(null);
|
return vm.createContext(Object.defineProperty({}, "console", {
|
||||||
Object.defineProperty(context, "console", {
|
value: {
|
||||||
value: function() {
|
log: function(msg) {
|
||||||
var con = Object.create(null);
|
|
||||||
Object.defineProperty(con, "log", {
|
|
||||||
value: function(msg) {
|
|
||||||
if (arguments.length == 1 && typeof msg == "string") {
|
if (arguments.length == 1 && typeof msg == "string") {
|
||||||
return console.log("%s", msg);
|
return console.log("%s", msg);
|
||||||
}
|
}
|
||||||
@@ -15,11 +12,8 @@ function createContext() {
|
|||||||
return safe_log(arg, 3);
|
return safe_log(arg, 3);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return con;
|
}));
|
||||||
}()
|
|
||||||
});
|
|
||||||
return vm.createContext(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function safe_log(arg, level) {
|
function safe_log(arg, level) {
|
||||||
@@ -40,7 +34,7 @@ function safe_log(arg, level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function strip_func_ids(text) {
|
function strip_func_ids(text) {
|
||||||
return text.toString().replace(/F[0-9]{6}N/g, "<F<>N>");
|
return ("" + text).replace(/F[0-9]{6}N/g, "<F<>N>");
|
||||||
}
|
}
|
||||||
|
|
||||||
var context;
|
var context;
|
||||||
|
|||||||
Reference in New Issue
Block a user