Merge branch 'master' into harmony-v3.0.5
This commit is contained in:
12
README.md
12
README.md
@@ -399,13 +399,19 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
compressor from discarding function names. Useful for code relying on
|
compressor from discarding function names. Useful for code relying on
|
||||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||||
|
|
||||||
- `passes` -- default `1`. Number of times to run compress. Use an
|
- `passes` -- default `1`. Number of times to run compress with a maximum of 3.
|
||||||
integer argument larger than 1 to further reduce code size in some cases.
|
In some cases more than one pass leads to further compressed code. Keep in
|
||||||
Note: raising the number of passes will increase uglify compress time.
|
mind more passes will take more time.
|
||||||
|
|
||||||
- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
|
- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
|
||||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||||
|
|
||||||
|
- `side_effects` -- default `false`. Pass `true` to potentially drop functions
|
||||||
|
marked as "pure". A function call is marked as "pure" if a comment annotation
|
||||||
|
`/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For example:
|
||||||
|
`/*@__PURE__*/foo()`;
|
||||||
|
|
||||||
|
|
||||||
### The `unsafe` option
|
### The `unsafe` option
|
||||||
|
|
||||||
It enables some transformations that *might* break code logic in certain
|
It enables some transformations that *might* break code logic in certain
|
||||||
|
|||||||
@@ -932,7 +932,7 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
|||||||
$documentation: "Base class for literal object properties",
|
$documentation: "Base class for literal object properties",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
|
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
|
||||||
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
|
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
@@ -1018,10 +1018,6 @@ var AST_NewTarget = DEFNODE("NewTarget", null, {
|
|||||||
$documentation: "A reference to new.target"
|
$documentation: "A reference to new.target"
|
||||||
});
|
});
|
||||||
|
|
||||||
var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
|
||||||
$documentation: "The name of a property accessor (setter/getter function)"
|
|
||||||
}, AST_Symbol);
|
|
||||||
|
|
||||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|||||||
@@ -361,16 +361,27 @@ merge(Compressor.prototype, {
|
|||||||
// So existing transformation rules can work on them.
|
// So existing transformation rules can work on them.
|
||||||
node.argnames.forEach(function(arg, i) {
|
node.argnames.forEach(function(arg, i) {
|
||||||
var d = arg.definition();
|
var d = arg.definition();
|
||||||
|
if (!node.uses_arguments && d.fixed === undefined) {
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
return iife.args[i] || make_node(AST_Undefined, iife);
|
return iife.args[i] || make_node(AST_Undefined, iife);
|
||||||
};
|
};
|
||||||
mark(d, true);
|
mark(d, true);
|
||||||
|
} else {
|
||||||
|
d.fixed = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
descend();
|
descend();
|
||||||
pop();
|
pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_Accessor) {
|
||||||
|
var save_ids = safe_ids;
|
||||||
|
safe_ids = Object.create(null);
|
||||||
|
descend();
|
||||||
|
safe_ids = save_ids;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (node instanceof AST_Binary
|
if (node instanceof AST_Binary
|
||||||
&& (node.operator == "&&" || node.operator == "||")) {
|
&& (node.operator == "&&" || node.operator == "||")) {
|
||||||
node.left.walk(tw);
|
node.left.walk(tw);
|
||||||
@@ -498,7 +509,9 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
function reset_def(def) {
|
function reset_def(def) {
|
||||||
def.escaped = false;
|
def.escaped = false;
|
||||||
if (!def.global || def.orig[0] instanceof AST_SymbolConst || compressor.toplevel(def)) {
|
if (def.scope.uses_eval) {
|
||||||
|
def.fixed = false;
|
||||||
|
} else if (!def.global || def.orig[0] instanceof AST_SymbolConst || compressor.toplevel(def)) {
|
||||||
def.fixed = undefined;
|
def.fixed = undefined;
|
||||||
} else {
|
} else {
|
||||||
def.fixed = false;
|
def.fixed = false;
|
||||||
@@ -1240,12 +1253,12 @@ merge(Compressor.prototype, {
|
|||||||
&& !node.expression.has_side_effects(compressor);
|
&& !node.expression.has_side_effects(compressor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// may_eq_null()
|
// may_throw_on_access()
|
||||||
// returns true if this node may evaluate to null or undefined
|
// returns true if this node may be null, undefined or contain `AST_Accessor`
|
||||||
(function(def) {
|
(function(def) {
|
||||||
AST_Node.DEFMETHOD("may_eq_null", function(compressor) {
|
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
|
||||||
var pure_getters = compressor.option("pure_getters");
|
var pure_getters = compressor.option("pure_getters");
|
||||||
return !pure_getters || this._eq_null(pure_getters);
|
return !pure_getters || this._throw_on_access(pure_getters);
|
||||||
});
|
});
|
||||||
|
|
||||||
function is_strict(pure_getters) {
|
function is_strict(pure_getters) {
|
||||||
@@ -1257,7 +1270,12 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Undefined, return_true);
|
def(AST_Undefined, return_true);
|
||||||
def(AST_Constant, return_false);
|
def(AST_Constant, return_false);
|
||||||
def(AST_Array, return_false);
|
def(AST_Array, return_false);
|
||||||
def(AST_Object, return_false);
|
def(AST_Object, function(pure_getters) {
|
||||||
|
if (!is_strict(pure_getters)) return false;
|
||||||
|
for (var i = this.properties.length; --i >=0;)
|
||||||
|
if (this.properties[i].value instanceof AST_Accessor) return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
def(AST_Function, return_false);
|
def(AST_Function, return_false);
|
||||||
def(AST_UnaryPostfix, return_false);
|
def(AST_UnaryPostfix, return_false);
|
||||||
def(AST_UnaryPrefix, function() {
|
def(AST_UnaryPrefix, function() {
|
||||||
@@ -1266,33 +1284,33 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Binary, function(pure_getters) {
|
def(AST_Binary, function(pure_getters) {
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
return this.left._eq_null(pure_getters);
|
return this.left._throw_on_access(pure_getters);
|
||||||
case "||":
|
case "||":
|
||||||
return this.left._eq_null(pure_getters)
|
return this.left._throw_on_access(pure_getters)
|
||||||
&& this.right._eq_null(pure_getters);
|
&& this.right._throw_on_access(pure_getters);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
def(AST_Assign, function(pure_getters) {
|
def(AST_Assign, function(pure_getters) {
|
||||||
return this.operator == "="
|
return this.operator == "="
|
||||||
&& this.right._eq_null(pure_getters);
|
&& this.right._throw_on_access(pure_getters);
|
||||||
})
|
})
|
||||||
def(AST_Conditional, function(pure_getters) {
|
def(AST_Conditional, function(pure_getters) {
|
||||||
return this.consequent._eq_null(pure_getters)
|
return this.consequent._throw_on_access(pure_getters)
|
||||||
|| this.alternative._eq_null(pure_getters);
|
|| this.alternative._throw_on_access(pure_getters);
|
||||||
})
|
})
|
||||||
def(AST_Sequence, function(pure_getters) {
|
def(AST_Sequence, function(pure_getters) {
|
||||||
return this.expressions[this.expressions.length - 1]._eq_null(pure_getters);
|
return this.expressions[this.expressions.length - 1]._throw_on_access(pure_getters);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(pure_getters) {
|
def(AST_SymbolRef, function(pure_getters) {
|
||||||
if (this.is_undefined) return true;
|
if (this.is_undefined) return true;
|
||||||
if (!is_strict(pure_getters)) return false;
|
if (!is_strict(pure_getters)) return false;
|
||||||
var fixed = this.fixed_value();
|
var fixed = this.fixed_value();
|
||||||
return !fixed || fixed._eq_null(pure_getters);
|
return !fixed || fixed._throw_on_access(pure_getters);
|
||||||
});
|
});
|
||||||
})(function(node, func) {
|
})(function(node, func) {
|
||||||
node.DEFMETHOD("_eq_null", func);
|
node.DEFMETHOD("_throw_on_access", func);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ boolean/negation helpers ]----- */
|
/* -----[ boolean/negation helpers ]----- */
|
||||||
@@ -1853,11 +1871,11 @@ merge(Compressor.prototype, {
|
|||||||
return any(this.elements, compressor);
|
return any(this.elements, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Dot, function(compressor){
|
def(AST_Dot, function(compressor){
|
||||||
return this.expression.may_eq_null(compressor)
|
return this.expression.may_throw_on_access(compressor)
|
||||||
|| this.expression.has_side_effects(compressor);
|
|| this.expression.has_side_effects(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Sub, function(compressor){
|
def(AST_Sub, function(compressor){
|
||||||
return this.expression.may_eq_null(compressor)
|
return this.expression.may_throw_on_access(compressor)
|
||||||
|| this.expression.has_side_effects(compressor)
|
|| this.expression.has_side_effects(compressor)
|
||||||
|| this.property.has_side_effects(compressor);
|
|| this.property.has_side_effects(compressor);
|
||||||
});
|
});
|
||||||
@@ -2492,6 +2510,7 @@ merge(Compressor.prototype, {
|
|||||||
var args = trim(this.args, compressor, first_in_statement);
|
var args = trim(this.args, compressor, first_in_statement);
|
||||||
return args && make_sequence(this, args);
|
return args && make_sequence(this, args);
|
||||||
});
|
});
|
||||||
|
def(AST_Accessor, return_null);
|
||||||
def(AST_Function, return_null);
|
def(AST_Function, return_null);
|
||||||
def(AST_Binary, function(compressor, first_in_statement){
|
def(AST_Binary, function(compressor, first_in_statement){
|
||||||
var right = this.right.drop_side_effect_free(compressor);
|
var right = this.right.drop_side_effect_free(compressor);
|
||||||
@@ -2559,11 +2578,11 @@ merge(Compressor.prototype, {
|
|||||||
return values && make_sequence(this, values);
|
return values && make_sequence(this, values);
|
||||||
});
|
});
|
||||||
def(AST_Dot, function(compressor, first_in_statement){
|
def(AST_Dot, function(compressor, first_in_statement){
|
||||||
if (this.expression.may_eq_null(compressor)) return this;
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
||||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||||
});
|
});
|
||||||
def(AST_Sub, function(compressor, first_in_statement){
|
def(AST_Sub, function(compressor, first_in_statement){
|
||||||
if (this.expression.may_eq_null(compressor)) return this;
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
||||||
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement);
|
if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement);
|
||||||
var property = this.property.drop_side_effect_free(compressor);
|
var property = this.property.drop_side_effect_free(compressor);
|
||||||
|
|||||||
@@ -111,23 +111,19 @@
|
|||||||
},
|
},
|
||||||
Property: function(M) {
|
Property: function(M) {
|
||||||
var key = M.key;
|
var key = M.key;
|
||||||
var name = key.type == "Identifier" ? key.name : key.value;
|
|
||||||
var args = {
|
var args = {
|
||||||
start : my_start_token(key),
|
start : my_start_token(key),
|
||||||
end : my_end_token(M.value),
|
end : my_end_token(M.value),
|
||||||
key : name,
|
key : key.type == "Identifier" ? key.name : key.value,
|
||||||
value : from_moz(M.value)
|
value : from_moz(M.value)
|
||||||
};
|
};
|
||||||
switch (M.kind) {
|
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
||||||
case "init":
|
args.key = new AST_SymbolMethod({
|
||||||
return new AST_ObjectKeyVal(args);
|
name: args.key
|
||||||
case "set":
|
});
|
||||||
args.value.name = from_moz(key);
|
args.value = new AST_Accessor(args.value);
|
||||||
return new AST_ObjectSetter(args);
|
if (M.kind == "get") return new AST_ObjectGetter(args);
|
||||||
case "get":
|
if (M.kind == "set") return new AST_ObjectSetter(args);
|
||||||
args.value.name = from_moz(key);
|
|
||||||
return new AST_ObjectGetter(args);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ArrayExpression: function(M) {
|
ArrayExpression: function(M) {
|
||||||
return new AST_Array({
|
return new AST_Array({
|
||||||
@@ -260,10 +256,7 @@
|
|||||||
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
||||||
|
|
||||||
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
||||||
return {
|
return to_moz_scope("Program", M);
|
||||||
type: "Program",
|
|
||||||
body: M.body.map(to_moz)
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
|
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
|
||||||
@@ -271,7 +264,7 @@
|
|||||||
type: "FunctionDeclaration",
|
type: "FunctionDeclaration",
|
||||||
id: to_moz(M.name),
|
id: to_moz(M.name),
|
||||||
params: M.argnames.map(to_moz),
|
params: M.argnames.map(to_moz),
|
||||||
body: to_moz_block(M)
|
body: to_moz_scope("BlockStatement", M)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -280,7 +273,7 @@
|
|||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
id: to_moz(M.name),
|
id: to_moz(M.name),
|
||||||
params: M.argnames.map(to_moz),
|
params: M.argnames.map(to_moz),
|
||||||
body: to_moz_block(M)
|
body: to_moz_scope("BlockStatement", M)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -386,11 +379,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
||||||
var key = (
|
var key = {
|
||||||
is_identifier(M.key)
|
type: "Literal",
|
||||||
? {type: "Identifier", name: M.key}
|
value: M.key instanceof AST_SymbolMethod ? M.key.name : M.key
|
||||||
: {type: "Literal", value: M.key}
|
};
|
||||||
);
|
|
||||||
var kind;
|
var kind;
|
||||||
if (M instanceof AST_ObjectKeyVal) {
|
if (M instanceof AST_ObjectKeyVal) {
|
||||||
kind = "init";
|
kind = "init";
|
||||||
@@ -551,8 +543,8 @@
|
|||||||
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
||||||
exports, my_start_token, my_end_token, from_moz
|
exports, my_start_token, my_end_token, from_moz
|
||||||
);
|
);
|
||||||
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
|
me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
|
||||||
to_moz, to_moz_block
|
to_moz, to_moz_block, to_moz_scope
|
||||||
);
|
);
|
||||||
MOZ_TO_ME[moztype] = moz_to_me;
|
MOZ_TO_ME[moztype] = moz_to_me;
|
||||||
def_to_moz(mytype, me_to_moz);
|
def_to_moz(mytype, me_to_moz);
|
||||||
@@ -610,4 +602,14 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function to_moz_scope(type, node) {
|
||||||
|
var body = node.body.map(to_moz);
|
||||||
|
if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
|
||||||
|
body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: type,
|
||||||
|
body: body
|
||||||
|
};
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
20
lib/parse.js
20
lib/parse.js
@@ -976,24 +976,20 @@ function parse($TEXT, options) {
|
|||||||
handle_regexp();
|
handle_regexp();
|
||||||
switch (S.token.type) {
|
switch (S.token.type) {
|
||||||
case "string":
|
case "string":
|
||||||
var dir = false;
|
if (S.in_directives) {
|
||||||
if (S.in_directives === true) {
|
tmp = peek();
|
||||||
if ((is_token(peek(), "punc", ";") || peek().nlb) && S.token.raw.indexOf("\\") === -1) {
|
if (S.token.raw.indexOf("\\") == -1
|
||||||
|
&& (tmp.nlb
|
||||||
|
|| is_token(tmp, "eof")
|
||||||
|
|| is_token(tmp, "punc", ";")
|
||||||
|
|| is_token(tmp, "punc", "}"))) {
|
||||||
S.input.add_directive(S.token.value);
|
S.input.add_directive(S.token.value);
|
||||||
} else {
|
} else {
|
||||||
S.in_directives = false;
|
S.in_directives = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var dir = S.in_directives, stat = simple_statement();
|
var dir = S.in_directives, stat = simple_statement();
|
||||||
if (dir) {
|
return dir ? new AST_Directive(stat.body) : stat;
|
||||||
return new AST_Directive({
|
|
||||||
start : stat.body.start,
|
|
||||||
end : stat.body.end,
|
|
||||||
quote : stat.body.quote,
|
|
||||||
value : stat.body.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return stat;
|
|
||||||
case "template_head":
|
case "template_head":
|
||||||
case "num":
|
case "num":
|
||||||
case "regexp":
|
case "regexp":
|
||||||
|
|||||||
@@ -473,11 +473,6 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
|||||||
return def && def.unmangleable(options);
|
return def && def.unmangleable(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
// property accessors are not mangleable
|
|
||||||
AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// labels are always mangleable
|
// labels are always mangleable
|
||||||
AST_Label.DEFMETHOD("unmangleable", function(){
|
AST_Label.DEFMETHOD("unmangleable", function(){
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
15
package.json
15
package.json
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||||
"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.0.4",
|
"version": "3.0.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -33,20 +33,9 @@
|
|||||||
"source-map": "~0.5.1"
|
"source-map": "~0.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~0.6.0",
|
"acorn": "~5.0.3",
|
||||||
"escodegen": "~1.3.3",
|
|
||||||
"esfuzz": "~0.3.1",
|
|
||||||
"estraverse": "~1.5.1",
|
|
||||||
"mocha": "~2.3.4"
|
"mocha": "~2.3.4"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
|
||||||
"uglify-to-browserify": "~1.0.0"
|
|
||||||
},
|
|
||||||
"browserify": {
|
|
||||||
"transform": [
|
|
||||||
"uglify-to-browserify"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test/run-tests.js"
|
"test": "node test/run-tests.js"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -278,3 +278,19 @@ try_catch_finally: {
|
|||||||
"1",
|
"1",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accessor: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
get a() {},
|
||||||
|
set a(v){
|
||||||
|
this.b = 2;
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -119,3 +119,62 @@ chained: {
|
|||||||
a.b.c;
|
a.b.c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impure_getter_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).a;
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).b;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).a;
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).b;
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
impure_getter_2: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// will produce incorrect output because getter is not pure
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).a;
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).b;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,20 +41,20 @@ reduce_vars: {
|
|||||||
var A = 1;
|
var A = 1;
|
||||||
(function() {
|
(function() {
|
||||||
console.log(-3);
|
console.log(-3);
|
||||||
console.log(-4);
|
console.log(A - 5);
|
||||||
})();
|
})();
|
||||||
(function f1() {
|
(function f1() {
|
||||||
var a = 2;
|
var a = 2;
|
||||||
console.log(-3);
|
console.log(a - 5);
|
||||||
eval("console.log(a);");
|
eval("console.log(a);");
|
||||||
})();
|
})();
|
||||||
(function f2(eval) {
|
(function f2(eval) {
|
||||||
var a = 2;
|
var a = 2;
|
||||||
console.log(-3);
|
console.log(a - 5);
|
||||||
eval("console.log(a);");
|
eval("console.log(a);");
|
||||||
})(eval);
|
})(eval);
|
||||||
"yes";
|
"yes";
|
||||||
console.log(2);
|
console.log(A + 1);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -1749,7 +1749,10 @@ redefine_arguments_3: {
|
|||||||
console.log(function() {
|
console.log(function() {
|
||||||
var arguments;
|
var arguments;
|
||||||
return typeof arguments;
|
return typeof arguments;
|
||||||
}(), "number", "undefined");
|
}(), "number", function(x) {
|
||||||
|
var arguments = x;
|
||||||
|
return typeof arguments;
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "object number undefined"
|
expect_stdout: "object number undefined"
|
||||||
}
|
}
|
||||||
@@ -2461,3 +2464,76 @@ issue_1865: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1922_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
arguments[0] = 2;
|
||||||
|
return a;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
arguments[0] = 2;
|
||||||
|
return a;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1922_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a;
|
||||||
|
eval("a = 1");
|
||||||
|
return a;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a;
|
||||||
|
eval("a = 1");
|
||||||
|
return a;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log({
|
||||||
|
get a() {
|
||||||
|
a = 2;
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}.b, a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
console.log({
|
||||||
|
get a() {
|
||||||
|
a = 2;
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}.b, a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -361,18 +361,28 @@ describe("Directives", function() {
|
|||||||
var tests = [
|
var tests = [
|
||||||
[
|
[
|
||||||
'"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");',
|
'"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");',
|
||||||
'"use strict";"use foo";doSomething("foo");'
|
'"use strict";"use foo";doSomething("foo");',
|
||||||
|
'function f(){ "use strict" }',
|
||||||
|
'function f(){ "use asm" }',
|
||||||
|
'function f(){ "use nondirective" }',
|
||||||
|
'function f(){ ;"use strict" }',
|
||||||
|
'function f(){ "use \n"; }',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
||||||
'"use asm";"use\\x20strict";1+1;',
|
'"use asm";"use\\x20strict";1+1;',
|
||||||
'"use asm";;"use strict";1+1;' // Yet, the parser noticed that "use strict" wasn't a directive
|
'"use asm";;"use strict";1+1;', // Yet, the parser noticed that "use strict" wasn't a directive
|
||||||
|
'function f(){"use strict"}',
|
||||||
|
'function f(){"use asm"}',
|
||||||
|
'function f(){"use nondirective"}',
|
||||||
|
'function f(){}',
|
||||||
|
'function f(){}',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < tests.length; i++) {
|
for (var i = 0; i < tests.length; i++) {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
uglify.minify(tests[i][0], {compress: {collapse_vars: true, side_effects: true}}).code,
|
uglify.minify(tests[i][0]).code,
|
||||||
tests[i][1],
|
tests[i][1],
|
||||||
tests[i][0]
|
tests[i][0]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,103 +1,73 @@
|
|||||||
// Testing UglifyJS <-> SpiderMonkey AST conversion
|
// Testing UglifyJS <-> SpiderMonkey AST conversion
|
||||||
// through generative testing.
|
"use strict";
|
||||||
|
|
||||||
var UglifyJS = require("./node"),
|
var acorn = require("acorn");
|
||||||
escodegen = require("escodegen"),
|
var ufuzz = require("./ufuzz");
|
||||||
esfuzz = require("esfuzz"),
|
var UglifyJS = require("..");
|
||||||
estraverse = require("estraverse"),
|
|
||||||
prefix = "\r ";
|
|
||||||
|
|
||||||
// Normalizes input AST for UglifyJS in order to get correct comparison.
|
function try_beautify(code) {
|
||||||
|
var beautified = UglifyJS.minify(code, {
|
||||||
function normalizeInput(ast) {
|
compress: false,
|
||||||
return estraverse.replace(ast, {
|
mangle: false,
|
||||||
enter: function(node, parent) {
|
output: {
|
||||||
switch (node.type) {
|
beautify: true,
|
||||||
// Internally mark all the properties with semi-standard type "Property".
|
bracketize: true
|
||||||
case "ObjectExpression":
|
|
||||||
node.properties.forEach(function (property) {
|
|
||||||
property.type = "Property";
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Since UglifyJS doesn"t recognize different types of property keys,
|
|
||||||
// decision on SpiderMonkey node type is based on check whether key
|
|
||||||
// can be valid identifier or not - so we do in input AST.
|
|
||||||
case "Property":
|
|
||||||
var key = node.key;
|
|
||||||
if (key.type === "Literal" && typeof key.value === "string" && UglifyJS.is_identifier(key.value)) {
|
|
||||||
node.key = {
|
|
||||||
type: "Identifier",
|
|
||||||
name: key.value
|
|
||||||
};
|
|
||||||
} else if (key.type === "Identifier" && !UglifyJS.is_identifier(key.name)) {
|
|
||||||
node.key = {
|
|
||||||
type: "Literal",
|
|
||||||
value: key.name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// UglifyJS internally flattens all the expression sequences - either
|
|
||||||
// to one element (if sequence contains only one element) or flat list.
|
|
||||||
case "SequenceExpression":
|
|
||||||
node.expressions = node.expressions.reduce(function flatten(list, expr) {
|
|
||||||
return list.concat(expr.type === "SequenceExpression" ? expr.expressions.reduce(flatten, []) : [expr]);
|
|
||||||
}, []);
|
|
||||||
if (node.expressions.length === 1) {
|
|
||||||
return node.expressions[0];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (beautified.error) {
|
||||||
|
console.log("// !!! beautify failed !!!");
|
||||||
|
console.log(beautified.error.stack);
|
||||||
|
console.log(code);
|
||||||
|
} else {
|
||||||
|
console.log("// (beautified)");
|
||||||
|
console.log(beautified.code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(options) {
|
function test(original, estree, description) {
|
||||||
console.log("--- UglifyJS <-> Mozilla AST conversion");
|
var transformed = UglifyJS.minify(UglifyJS.AST_Node.from_mozilla_ast(estree), {
|
||||||
|
compress: false,
|
||||||
|
mangle: false
|
||||||
|
});
|
||||||
|
if (transformed.error || original !== transformed.code) {
|
||||||
|
console.log("//=============================================================");
|
||||||
|
console.log("// !!!!!! Failed... round", round);
|
||||||
|
console.log("// original code");
|
||||||
|
try_beautify(original);
|
||||||
|
console.log();
|
||||||
|
console.log();
|
||||||
|
console.log("//-------------------------------------------------------------");
|
||||||
|
console.log("//", description);
|
||||||
|
if (transformed.error) {
|
||||||
|
console.log(transformed.error.stack);
|
||||||
|
} else {
|
||||||
|
try_beautify(transformed.code);
|
||||||
|
}
|
||||||
|
console.log("!!!!!! Failed... round", round);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var counter = 0; counter < options.iterations; counter++) {
|
var num_iterations = ufuzz.num_iterations;
|
||||||
process.stdout.write(prefix + counter + "/" + options.iterations);
|
for (var round = 1; round <= num_iterations; round++) {
|
||||||
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
var ast1 = normalizeInput(esfuzz.generate({
|
var code = ufuzz.createTopLevelCode();
|
||||||
maxDepth: options.maxDepth
|
var uglified = UglifyJS.minify(code, {
|
||||||
}));
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
var ast2 =
|
output: {
|
||||||
UglifyJS
|
ast: true
|
||||||
.AST_Node
|
|
||||||
.from_mozilla_ast(ast1)
|
|
||||||
.to_mozilla_ast();
|
|
||||||
|
|
||||||
var astPair = [
|
|
||||||
{name: 'expected', value: ast1},
|
|
||||||
{name: 'actual', value: ast2}
|
|
||||||
];
|
|
||||||
|
|
||||||
var jsPair = astPair.map(function(item) {
|
|
||||||
return {
|
|
||||||
name: item.name,
|
|
||||||
value: escodegen.generate(item.value)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||||
if (jsPair[0].value !== jsPair[1].value) {
|
try {
|
||||||
var fs = require("fs");
|
test(uglified.code, acorn.parse(code), "acorn.parse()");
|
||||||
var acorn = require("acorn");
|
} catch (e) {
|
||||||
|
console.log("//=============================================================");
|
||||||
fs.existsSync("tmp") || fs.mkdirSync("tmp");
|
console.log("// acorn parser failed... round", round);
|
||||||
|
console.log(e);
|
||||||
jsPair.forEach(function (item) {
|
console.log("// original code");
|
||||||
var fileName = "tmp/dump_" + item.name;
|
console.log(code);
|
||||||
var ast = acorn.parse(item.value);
|
|
||||||
fs.writeFileSync(fileName + ".js", item.value);
|
|
||||||
fs.writeFileSync(fileName + ".json", JSON.stringify(ast, null, 2));
|
|
||||||
});
|
|
||||||
|
|
||||||
process.stdout.write("\n");
|
|
||||||
throw new Error("Got different outputs, check out tmp/dump_*.{js,json} for codes and ASTs.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log();
|
||||||
process.stdout.write(prefix + "Probability of error is less than " + (100 / options.iterations) + "%, stopping.\n");
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -23,12 +23,6 @@ mocha_tests();
|
|||||||
var run_sourcemaps_tests = require('./sourcemaps');
|
var run_sourcemaps_tests = require('./sourcemaps');
|
||||||
run_sourcemaps_tests();
|
run_sourcemaps_tests();
|
||||||
|
|
||||||
var run_ast_conversion_tests = require("./mozilla-ast");
|
|
||||||
|
|
||||||
run_ast_conversion_tests({
|
|
||||||
iterations: 1000
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -----[ utils ]----- */
|
/* -----[ utils ]----- */
|
||||||
|
|
||||||
function tmpl() {
|
function tmpl() {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
|
|
||||||
function safe_log(arg) {
|
function safe_log(arg, level) {
|
||||||
if (arg) switch (typeof arg) {
|
if (arg) switch (typeof arg) {
|
||||||
case "function":
|
case "function":
|
||||||
return arg.toString();
|
return arg.toString();
|
||||||
case "object":
|
case "object":
|
||||||
if (/Error$/.test(arg.name)) return arg.toString();
|
if (/Error$/.test(arg.name)) return arg.toString();
|
||||||
arg.constructor.toString();
|
arg.constructor.toString();
|
||||||
for (var key in arg) {
|
if (level--) for (var key in arg) {
|
||||||
arg[key] = safe_log(arg[key]);
|
if (!Object.getOwnPropertyDescriptor(arg, key).get) {
|
||||||
|
arg[key] = safe_log(arg[key], level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arg;
|
return arg;
|
||||||
@@ -48,7 +50,9 @@ exports.run_code = function(code) {
|
|||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
console: {
|
console: {
|
||||||
log: function() {
|
log: function() {
|
||||||
return console.log.apply(console, [].map.call(arguments, safe_log));
|
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
||||||
|
return safe_log(arg, 3);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, { timeout: 5000 });
|
}, { timeout: 5000 });
|
||||||
|
|||||||
212
test/ufuzz.js
212
test/ufuzz.js
@@ -48,8 +48,9 @@ var STMT_COUNT_FROM_GLOBAL = true; // count statement depth from nearest functio
|
|||||||
var num_iterations = +process.argv[2] || 1/0;
|
var num_iterations = +process.argv[2] || 1/0;
|
||||||
var verbose = false; // log every generated test
|
var verbose = false; // log every generated test
|
||||||
var verbose_interval = false; // log every 100 generated tests
|
var verbose_interval = false; // log every 100 generated tests
|
||||||
var verbose_error = false;
|
|
||||||
var use_strict = false;
|
var use_strict = false;
|
||||||
|
var catch_redef = require.main === module;
|
||||||
|
var generate_directive = require.main === module;
|
||||||
for (var i = 2; i < process.argv.length; ++i) {
|
for (var i = 2; i < process.argv.length; ++i) {
|
||||||
switch (process.argv[i]) {
|
switch (process.argv[i]) {
|
||||||
case '-v':
|
case '-v':
|
||||||
@@ -58,9 +59,6 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
case '-V':
|
case '-V':
|
||||||
verbose_interval = true;
|
verbose_interval = true;
|
||||||
break;
|
break;
|
||||||
case '-E':
|
|
||||||
verbose_error = true;
|
|
||||||
break;
|
|
||||||
case '-t':
|
case '-t':
|
||||||
MAX_GENERATED_TOPLEVELS_PER_RUN = +process.argv[++i];
|
MAX_GENERATED_TOPLEVELS_PER_RUN = +process.argv[++i];
|
||||||
if (!MAX_GENERATED_TOPLEVELS_PER_RUN) throw new Error('Must generate at least one toplevel per run');
|
if (!MAX_GENERATED_TOPLEVELS_PER_RUN) throw new Error('Must generate at least one toplevel per run');
|
||||||
@@ -79,6 +77,12 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
STMT_SECOND_LEVEL_OVERRIDE = STMT_ARG_TO_ID[name];
|
STMT_SECOND_LEVEL_OVERRIDE = STMT_ARG_TO_ID[name];
|
||||||
if (!(STMT_SECOND_LEVEL_OVERRIDE >= 0)) throw new Error('Unknown statement name; use -? to get a list');
|
if (!(STMT_SECOND_LEVEL_OVERRIDE >= 0)) throw new Error('Unknown statement name; use -? to get a list');
|
||||||
break;
|
break;
|
||||||
|
case '--no-catch-redef':
|
||||||
|
catch_redef = false;
|
||||||
|
break;
|
||||||
|
case '--no-directive':
|
||||||
|
generate_directive = false;
|
||||||
|
break;
|
||||||
case '--use-strict':
|
case '--use-strict':
|
||||||
use_strict = true;
|
use_strict = true;
|
||||||
break;
|
break;
|
||||||
@@ -103,11 +107,12 @@ for (var i = 2; i < process.argv.length; ++i) {
|
|||||||
console.log('<number>: generate this many cases (if used must be first arg)');
|
console.log('<number>: generate this many cases (if used must be first arg)');
|
||||||
console.log('-v: print every generated test case');
|
console.log('-v: print every generated test case');
|
||||||
console.log('-V: print every 100th generated test case');
|
console.log('-V: print every 100th generated test case');
|
||||||
console.log('-E: print generated test case with runtime error');
|
|
||||||
console.log('-t <int>: generate this many toplevels per run (more take longer)');
|
console.log('-t <int>: generate this many toplevels per run (more take longer)');
|
||||||
console.log('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
console.log('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
||||||
console.log('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
console.log('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
||||||
console.log('-s2 <statement name>: force the second level statement to be this one (see list below)');
|
console.log('-s2 <statement name>: force the second level statement to be this one (see list below)');
|
||||||
|
console.log('--no-catch-redef: do not redefine catch variables');
|
||||||
|
console.log('--no-directive: do not generate directives');
|
||||||
console.log('--use-strict: generate "use strict"');
|
console.log('--use-strict: generate "use strict"');
|
||||||
console.log('--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise');
|
console.log('--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise');
|
||||||
console.log('--only-stmt <statement names>: a comma delimited white list of statements that may be generated');
|
console.log('--only-stmt <statement names>: a comma delimited white list of statements that may be generated');
|
||||||
@@ -192,12 +197,33 @@ var ASSIGNMENTS = [
|
|||||||
'=',
|
'=',
|
||||||
'=',
|
'=',
|
||||||
'=',
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
'=',
|
||||||
|
|
||||||
'==',
|
|
||||||
'!=',
|
|
||||||
'===',
|
|
||||||
'!==',
|
|
||||||
'+=',
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
'+=',
|
||||||
|
|
||||||
'-=',
|
'-=',
|
||||||
'*=',
|
'*=',
|
||||||
'/=',
|
'/=',
|
||||||
@@ -207,7 +233,8 @@ var ASSIGNMENTS = [
|
|||||||
'<<=',
|
'<<=',
|
||||||
'>>=',
|
'>>=',
|
||||||
'>>>=',
|
'>>>=',
|
||||||
'%=' ];
|
'%=',
|
||||||
|
];
|
||||||
|
|
||||||
var UNARY_SAFE = [
|
var UNARY_SAFE = [
|
||||||
'+',
|
'+',
|
||||||
@@ -276,6 +303,7 @@ var TYPEOF_OUTCOMES = [
|
|||||||
'symbol',
|
'symbol',
|
||||||
'crap' ];
|
'crap' ];
|
||||||
|
|
||||||
|
var unique_vars = [];
|
||||||
var loops = 0;
|
var loops = 0;
|
||||||
var funcs = 0;
|
var funcs = 0;
|
||||||
var labels = 10000;
|
var labels = 10000;
|
||||||
@@ -290,6 +318,10 @@ function strictMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createTopLevelCode() {
|
function createTopLevelCode() {
|
||||||
|
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
|
||||||
|
unique_vars.length = 0;
|
||||||
|
loops = 0;
|
||||||
|
funcs = 0;
|
||||||
return [
|
return [
|
||||||
strictMode(),
|
strictMode(),
|
||||||
'var a = 100, b = 10, c = 0;',
|
'var a = 100, b = 10, c = 0;',
|
||||||
@@ -325,33 +357,36 @@ function createArgs() {
|
|||||||
return args.join(', ');
|
return args.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterDirective(s) {
|
||||||
|
if (!generate_directive && !s[1] && /\("/.test(s[2])) s[2] = ';' + s[2];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||||
if (--recurmax < 0) { return ';'; }
|
if (--recurmax < 0) { return ';'; }
|
||||||
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
||||||
var func = funcs++;
|
var func = funcs++;
|
||||||
var namesLenBefore = VAR_NAMES.length;
|
var namesLenBefore = VAR_NAMES.length;
|
||||||
var name = (inGlobal || rng(5) > 0) ? 'f' + func : createVarName(MANDATORY, noDecl);
|
var name;
|
||||||
if (name === 'a' || name === 'b' || name === 'c') name = 'f' + func; // quick hack to prevent assignment to func names of being called
|
if (inGlobal || rng(5) > 0) name = 'f' + func;
|
||||||
var s = '';
|
else {
|
||||||
|
unique_vars.push('a', 'b', 'c');
|
||||||
|
name = createVarName(MANDATORY, noDecl);
|
||||||
|
unique_vars.length -= 3;
|
||||||
|
}
|
||||||
|
var s = [
|
||||||
|
'function ' + name + '(' + createParams() + '){',
|
||||||
|
strictMode()
|
||||||
|
];
|
||||||
if (rng(5) === 0) {
|
if (rng(5) === 0) {
|
||||||
// functions with functions. lower the recursion to prevent a mess.
|
// functions with functions. lower the recursion to prevent a mess.
|
||||||
s = [
|
s.push(createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth));
|
||||||
'function ' + name + '(' + createParams() + '){',
|
|
||||||
strictMode(),
|
|
||||||
createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth),
|
|
||||||
'}',
|
|
||||||
''
|
|
||||||
].join('\n');
|
|
||||||
} else {
|
} else {
|
||||||
// functions with statements
|
// functions with statements
|
||||||
s = [
|
s.push(createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
|
||||||
'function ' + name + '(' + createParams() + '){',
|
|
||||||
strictMode(),
|
|
||||||
createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
|
||||||
'}',
|
|
||||||
''
|
|
||||||
].join('\n');
|
|
||||||
}
|
}
|
||||||
|
s.push('}', '');
|
||||||
|
s = filterDirective(s).join('\n');
|
||||||
|
|
||||||
VAR_NAMES.length = namesLenBefore;
|
VAR_NAMES.length = namesLenBefore;
|
||||||
|
|
||||||
@@ -359,7 +394,6 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
|||||||
// avoid "function statements" (decl inside statements)
|
// avoid "function statements" (decl inside statements)
|
||||||
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name + '(' + createArgs() + ');';
|
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name + '(' + createArgs() + ');';
|
||||||
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +440,7 @@ function getLabel(label) {
|
|||||||
return label && " L" + label;
|
return label && " L" + label;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth, target) {
|
||||||
++stmtDepth;
|
++stmtDepth;
|
||||||
var loop = ++loops;
|
var loop = ++loops;
|
||||||
if (--recurmax < 0) {
|
if (--recurmax < 0) {
|
||||||
@@ -414,10 +448,11 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow to forcefully generate certain structures at first or second recursion level
|
// allow to forcefully generate certain structures at first or second recursion level
|
||||||
var target = 0;
|
if (target === undefined) {
|
||||||
if (stmtDepth === 1 && STMT_FIRST_LEVEL_OVERRIDE >= 0) target = STMT_FIRST_LEVEL_OVERRIDE;
|
if (stmtDepth === 1 && STMT_FIRST_LEVEL_OVERRIDE >= 0) target = STMT_FIRST_LEVEL_OVERRIDE;
|
||||||
else if (stmtDepth === 2 && STMT_SECOND_LEVEL_OVERRIDE >= 0) target = STMT_SECOND_LEVEL_OVERRIDE;
|
else if (stmtDepth === 2 && STMT_SECOND_LEVEL_OVERRIDE >= 0) target = STMT_SECOND_LEVEL_OVERRIDE;
|
||||||
else target = STMTS_TO_USE[rng(STMTS_TO_USE.length)];
|
else target = STMTS_TO_USE[rng(STMTS_TO_USE.length)];
|
||||||
|
}
|
||||||
|
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case STMT_BLOCK:
|
case STMT_BLOCK:
|
||||||
@@ -460,20 +495,22 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
case STMT_VAR:
|
case STMT_VAR:
|
||||||
switch (rng(3)) {
|
switch (rng(3)) {
|
||||||
case 0:
|
case 0:
|
||||||
|
unique_vars.push('c');
|
||||||
var name = createVarName(MANDATORY);
|
var name = createVarName(MANDATORY);
|
||||||
if (name === 'c') name = 'a';
|
unique_vars.pop();
|
||||||
return 'var ' + name + ';';
|
return 'var ' + name + ';';
|
||||||
case 1:
|
case 1:
|
||||||
// initializer can only have one expression
|
// initializer can only have one expression
|
||||||
|
unique_vars.push('c');
|
||||||
var name = createVarName(MANDATORY);
|
var name = createVarName(MANDATORY);
|
||||||
if (name === 'c') name = 'b';
|
unique_vars.pop();
|
||||||
return 'var ' + name + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
return 'var ' + name + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||||
default:
|
default:
|
||||||
// initializer can only have one expression
|
// initializer can only have one expression
|
||||||
|
unique_vars.push('c');
|
||||||
var n1 = createVarName(MANDATORY);
|
var n1 = createVarName(MANDATORY);
|
||||||
if (n1 === 'c') n1 = 'b';
|
|
||||||
var n2 = createVarName(MANDATORY);
|
var n2 = createVarName(MANDATORY);
|
||||||
if (n2 === 'c') n2 = 'b';
|
unique_vars.pop();
|
||||||
return 'var ' + n1 + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ', ' + n2 + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
return 'var ' + n1 + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ', ' + n2 + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||||
}
|
}
|
||||||
case STMT_RETURN_ETC:
|
case STMT_RETURN_ETC:
|
||||||
@@ -514,8 +551,11 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
var catchName = createVarName(MANDATORY);
|
var catchName = createVarName(MANDATORY);
|
||||||
var freshCatchName = VAR_NAMES.length !== nameLenBefore;
|
var freshCatchName = VAR_NAMES.length !== nameLenBefore;
|
||||||
|
if (!catch_redef) unique_vars.push(catchName);
|
||||||
s += ' catch (' + catchName + ') { ' + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + ' }';
|
s += ' catch (' + catchName + ') { ' + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + ' }';
|
||||||
if (freshCatchName) VAR_NAMES.splice(nameLenBefore, 1); // remove catch name
|
// remove catch name
|
||||||
|
if (!catch_redef) unique_vars.pop();
|
||||||
|
if (freshCatchName) VAR_NAMES.splice(nameLenBefore, 1);
|
||||||
}
|
}
|
||||||
if (n !== 0) s += ' finally { ' + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + ' }';
|
if (n !== 0) s += ' finally { ' + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + ' }';
|
||||||
return s;
|
return s;
|
||||||
@@ -593,8 +633,9 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
case p++:
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
|
unique_vars.push('c');
|
||||||
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
||||||
if (name == 'c') name = 'a';
|
unique_vars.pop();
|
||||||
var s = [];
|
var s = [];
|
||||||
switch (rng(5)) {
|
switch (rng(5)) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -636,7 +677,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
strictMode()
|
strictMode()
|
||||||
);
|
);
|
||||||
if (instantiate) for (var i = rng(4); --i >= 0;) {
|
if (instantiate) for (var i = rng(4); --i >= 0;) {
|
||||||
if (rng(2)) s.push('this.' + getDotKey() + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ';');
|
if (rng(2)) s.push('this.' + getDotKey(true) + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ';');
|
||||||
else s.push('this[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ';');
|
else s.push('this[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ';');
|
||||||
}
|
}
|
||||||
s.push(
|
s.push(
|
||||||
@@ -646,7 +687,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
VAR_NAMES.length = nameLenBefore;
|
VAR_NAMES.length = nameLenBefore;
|
||||||
return s.join('\n');
|
return filterDirective(s).join('\n');
|
||||||
case p++:
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
||||||
@@ -689,19 +730,19 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
") || " + rng(10) + ").toString()[" +
|
") || " + rng(10) + ").toString()[" +
|
||||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "] ";
|
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "] ";
|
||||||
case p++:
|
case p++:
|
||||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return createArrayLiteral(recurmax, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return createObjectLiteral(recurmax, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
return createArrayLiteral(recurmax, stmtDepth, canThrow) + '[' +
|
||||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||||
case p++:
|
case p++:
|
||||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
return createObjectLiteral(recurmax, stmtDepth, canThrow) + '[' +
|
||||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||||
case p++:
|
case p++:
|
||||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + getDotKey();
|
return createArrayLiteral(recurmax, stmtDepth, canThrow) + '.' + getDotKey();
|
||||||
case p++:
|
case p++:
|
||||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + getDotKey();
|
return createObjectLiteral(recurmax, stmtDepth, canThrow) + '.' + getDotKey();
|
||||||
case p++:
|
case p++:
|
||||||
var name = getVarName();
|
var name = getVarName();
|
||||||
return name + ' && ' + name + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
return name + ' && ' + name + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||||
@@ -713,7 +754,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createArrayLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
function createArrayLiteral(recurmax, stmtDepth, canThrow) {
|
||||||
recurmax--;
|
recurmax--;
|
||||||
var arr = "[";
|
var arr = "[";
|
||||||
for (var i = rng(6); --i >= 0;) {
|
for (var i = rng(6); --i >= 0;) {
|
||||||
@@ -746,18 +787,56 @@ var KEYS = [
|
|||||||
"3",
|
"3",
|
||||||
].concat(SAFE_KEYS);
|
].concat(SAFE_KEYS);
|
||||||
|
|
||||||
function getDotKey() {
|
function getDotKey(assign) {
|
||||||
return SAFE_KEYS[rng(SAFE_KEYS.length)];
|
var key;
|
||||||
|
do {
|
||||||
|
key = SAFE_KEYS[rng(SAFE_KEYS.length)];
|
||||||
|
} while (assign && key == "length");
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createObjectLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
function createAccessor(recurmax, stmtDepth, canThrow) {
|
||||||
recurmax--;
|
var namesLenBefore = VAR_NAMES.length;
|
||||||
var obj = "({";
|
var s;
|
||||||
for (var i = rng(6); --i >= 0;) {
|
var prop1 = getDotKey();
|
||||||
var key = KEYS[rng(KEYS.length)];
|
if (rng(2) == 0) {
|
||||||
obj += key + ":(" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "), ";
|
s = [
|
||||||
|
'get ' + prop1 + '(){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
createStatement(recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth, STMT_RETURN_ETC),
|
||||||
|
'},'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
var prop2;
|
||||||
|
do {
|
||||||
|
prop2 = getDotKey();
|
||||||
|
} while (prop1 == prop2);
|
||||||
|
s = [
|
||||||
|
'set ' + prop1 + '(' + createVarName(MANDATORY) + '){',
|
||||||
|
strictMode(),
|
||||||
|
createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
|
'this.' + prop2 + createAssignment() + _createBinaryExpr(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
||||||
|
'},'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
return obj + "})";
|
VAR_NAMES.length = namesLenBefore;
|
||||||
|
return filterDirective(s).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function createObjectLiteral(recurmax, stmtDepth, canThrow) {
|
||||||
|
recurmax--;
|
||||||
|
var obj = ['({'];
|
||||||
|
for (var i = rng(6); --i >= 0;) {
|
||||||
|
if (rng(20) == 0) {
|
||||||
|
obj.push(createAccessor(recurmax, stmtDepth, canThrow));
|
||||||
|
} else {
|
||||||
|
var key = KEYS[rng(KEYS.length)];
|
||||||
|
obj.push(key + ':(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + '),');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj.push('})');
|
||||||
|
return obj.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
@@ -787,7 +866,7 @@ function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||||
case 4:
|
case 4:
|
||||||
assignee = getVarName();
|
assignee = getVarName();
|
||||||
expr = '(' + assignee + '.' + getDotKey() + createAssignment()
|
expr = '(' + assignee + '.' + getDotKey(true) + createAssignment()
|
||||||
+ _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
+ _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||||
default:
|
default:
|
||||||
@@ -844,17 +923,24 @@ function getVarName() {
|
|||||||
|
|
||||||
function createVarName(maybe, dontStore) {
|
function createVarName(maybe, dontStore) {
|
||||||
if (!maybe || rng(2)) {
|
if (!maybe || rng(2)) {
|
||||||
var name = VAR_NAMES[rng(VAR_NAMES.length)];
|
|
||||||
var suffix = rng(3);
|
var suffix = rng(3);
|
||||||
if (suffix) {
|
var name;
|
||||||
name += '_' + suffix;
|
do {
|
||||||
if (!dontStore) VAR_NAMES.push(name);
|
name = VAR_NAMES[rng(VAR_NAMES.length)];
|
||||||
}
|
if (suffix) name += '_' + suffix;
|
||||||
|
} while (unique_vars.indexOf(name) >= 0);
|
||||||
|
if (suffix && !dontStore) VAR_NAMES.push(name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (require.main !== module) {
|
||||||
|
exports.createTopLevelCode = createTopLevelCode;
|
||||||
|
exports.num_iterations = num_iterations;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function try_beautify(code, result) {
|
function try_beautify(code, result) {
|
||||||
var beautified = UglifyJS.minify(code, {
|
var beautified = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
@@ -973,10 +1059,6 @@ var uglify_code, uglify_result, ok;
|
|||||||
for (var round = 1; round <= num_iterations; round++) {
|
for (var round = 1; round <= num_iterations; round++) {
|
||||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
|
|
||||||
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
|
|
||||||
loops = 0;
|
|
||||||
funcs = 0;
|
|
||||||
|
|
||||||
original_code = createTopLevelCode();
|
original_code = createTopLevelCode();
|
||||||
original_result = sandbox.run_code(original_code);
|
original_result = sandbox.run_code(original_code);
|
||||||
(typeof original_result != "string" ? fallback_options : minify_options).forEach(function(options) {
|
(typeof original_result != "string" ? fallback_options : minify_options).forEach(function(options) {
|
||||||
@@ -992,7 +1074,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
||||||
else if (verbose_error && typeof original_result != "string") {
|
else if (typeof original_result != "string") {
|
||||||
console.log("//=============================================================");
|
console.log("//=============================================================");
|
||||||
console.log("// original code");
|
console.log("// original code");
|
||||||
try_beautify(original_code, original_result);
|
try_beautify(original_code, original_result);
|
||||||
|
|||||||
Reference in New Issue
Block a user