Merge branch 'master' into harmony
This commit is contained in:
20
README.md
20
README.md
@@ -67,10 +67,13 @@ The available options are:
|
|||||||
JS that was generated from some other original
|
JS that was generated from some other original
|
||||||
code.
|
code.
|
||||||
--screw-ie8 Use this flag if you don't wish to support
|
--screw-ie8 Use this flag if you don't wish to support
|
||||||
Internet Explorer 6-8 quirks.
|
Internet Explorer 6/7/8.
|
||||||
By default UglifyJS will not try to be IE-proof.
|
By default UglifyJS will not try to be IE-proof.
|
||||||
--support-ie8 Use this flag to support Internet Explorer 6-8 quirks.
|
--support-ie8 Use this flag to support Internet Explorer 6/7/8.
|
||||||
Note: may break standards compliant `catch` identifiers.
|
Equivalent to setting `screw_ie8: false` in `minify()`
|
||||||
|
for `compress`, `mangle` and `output` options.
|
||||||
|
Note: `--support-ie8` may generate incorrect code
|
||||||
|
for `try`/`catch` in ES5 compliant browsers.
|
||||||
--expr Parse a single expression, rather than a
|
--expr Parse a single expression, rather than a
|
||||||
program (for parsing JSON)
|
program (for parsing JSON)
|
||||||
-p, --prefix Skip prefix for original filenames that appear
|
-p, --prefix Skip prefix for original filenames that appear
|
||||||
@@ -285,6 +288,17 @@ of mangled property names.
|
|||||||
Using the name cache is not necessary if you compress all your files in a
|
Using the name cache is not necessary if you compress all your files in a
|
||||||
single call to UglifyJS.
|
single call to UglifyJS.
|
||||||
|
|
||||||
|
#### Mangling unquoted names (`--mangle-props=unquoted` or `--mangle-props=2`)
|
||||||
|
|
||||||
|
Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
|
||||||
|
so that it is not mangled throughout the entire script even when used in an
|
||||||
|
unquoted style (`o.foo`). Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props=2 -mc
|
||||||
|
var o={"foo":1,a:3};o.foo+=o.a,console.log(o.foo);
|
||||||
|
```
|
||||||
|
|
||||||
#### Debugging property name mangling
|
#### Debugging property name mangling
|
||||||
|
|
||||||
You can also pass `--mangle-props-debug` in order to mangle property names
|
You can also pass `--mangle-props-debug` in order to mangle property names
|
||||||
|
|||||||
10
bin/uglifyjs
10
bin/uglifyjs
@@ -26,8 +26,8 @@ mangling you need to use `-c` and `-m`.\
|
|||||||
.describe("source-map-inline", "Write base64-encoded source map to the end of js output. Disabled by default")
|
.describe("source-map-inline", "Write base64-encoded source map to the end of js output. Disabled by default")
|
||||||
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
|
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
|
||||||
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
||||||
.describe("screw-ie8", "Do not support Internet Explorer 6-8 quirks. This flag is enabled by default.")
|
.describe("screw-ie8", "Do not support Internet Explorer 6/7/8. This flag is enabled by default.")
|
||||||
.describe("support-ie8", "Support non-standard Internet Explorer 6-8 javascript. Note: may break standards compliant `catch` identifiers.")
|
.describe("support-ie8", "Support non-standard Internet Explorer 6/7/8 javascript. Note: may generate incorrect code for try/catch in ES5 compliant browsers.")
|
||||||
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
|
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
|
||||||
.describe("p", "Skip prefix for original filenames that appear in source maps. \
|
.describe("p", "Skip prefix for original filenames that appear in source maps. \
|
||||||
For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \
|
For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \
|
||||||
@@ -428,10 +428,11 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
|
|
||||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint
|
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint
|
||||||
var TL_CACHE = readNameCache("vars");
|
var TL_CACHE = readNameCache("vars");
|
||||||
|
if (MANGLE) MANGLE.cache = TL_CACHE;
|
||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
if (SCOPE_IS_NEEDED) {
|
||||||
time_it("scope", function(){
|
time_it("scope", function(){
|
||||||
TOPLEVEL.figure_out_scope({ screw_ie8: screw_ie8, cache: TL_CACHE });
|
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||||
if (ARGS.lint) {
|
if (ARGS.lint) {
|
||||||
TOPLEVEL.scope_warnings();
|
TOPLEVEL.scope_warnings();
|
||||||
}
|
}
|
||||||
@@ -446,7 +447,7 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
if (SCOPE_IS_NEEDED) {
|
||||||
time_it("scope", function(){
|
time_it("scope", function(){
|
||||||
TOPLEVEL.figure_out_scope({ screw_ie8: screw_ie8, cache: TL_CACHE });
|
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||||
if (MANGLE && !TL_CACHE) {
|
if (MANGLE && !TL_CACHE) {
|
||||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
TOPLEVEL.compute_char_frequency(MANGLE);
|
||||||
}
|
}
|
||||||
@@ -454,7 +455,6 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (MANGLE) time_it("mangle", function(){
|
if (MANGLE) time_it("mangle", function(){
|
||||||
MANGLE.cache = TL_CACHE;
|
|
||||||
TOPLEVEL.mangle_names(MANGLE);
|
TOPLEVEL.mangle_names(MANGLE);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
198
lib/compress.js
198
lib/compress.js
@@ -152,6 +152,12 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("clear_opt_flags", function(){
|
AST_Node.DEFMETHOD("clear_opt_flags", function(){
|
||||||
this.walk(new TreeWalker(function(node){
|
this.walk(new TreeWalker(function(node){
|
||||||
|
if (node instanceof AST_SymbolRef) {
|
||||||
|
var d = node.definition();
|
||||||
|
if (d && d.init) {
|
||||||
|
delete d.init._evaluated;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||||
node._squeezed = false;
|
node._squeezed = false;
|
||||||
node._optimized = false;
|
node._optimized = false;
|
||||||
@@ -349,7 +355,7 @@ merge(Compressor.prototype, {
|
|||||||
if (ref.scope.uses_eval || ref.scope.uses_with) break;
|
if (ref.scope.uses_eval || ref.scope.uses_with) break;
|
||||||
|
|
||||||
// Constant single use vars can be replaced in any scope.
|
// Constant single use vars can be replaced in any scope.
|
||||||
if (!(var_decl.value instanceof AST_RegExp) && var_decl.value.is_constant(compressor)) {
|
if (var_decl.value.is_constant()) {
|
||||||
var ctt = new TreeTransformer(function(node) {
|
var ctt = new TreeTransformer(function(node) {
|
||||||
if (node === ref)
|
if (node === ref)
|
||||||
return replace_var(node, ctt.parent(), true);
|
return replace_var(node, ctt.parent(), true);
|
||||||
@@ -989,6 +995,11 @@ merge(Compressor.prototype, {
|
|||||||
node.DEFMETHOD("is_string", func);
|
node.DEFMETHOD("is_string", func);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function isLHS(node, parent) {
|
||||||
|
return parent instanceof AST_Unary && (parent.operator === "++" || parent.operator === "--")
|
||||||
|
|| parent instanceof AST_Assign && parent.left === node;
|
||||||
|
}
|
||||||
|
|
||||||
function best_of(ast1, ast2) {
|
function best_of(ast1, ast2) {
|
||||||
return ast1.print_to_string().length >
|
return ast1.print_to_string().length >
|
||||||
ast2.print_to_string().length
|
ast2.print_to_string().length
|
||||||
@@ -1006,39 +1017,61 @@ merge(Compressor.prototype, {
|
|||||||
// constant; otherwise it's the original or a replacement node.
|
// constant; otherwise it's the original or a replacement node.
|
||||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||||
if (!compressor.option("evaluate")) return [ this ];
|
if (!compressor.option("evaluate")) return [ this ];
|
||||||
|
var val;
|
||||||
try {
|
try {
|
||||||
var val = this._eval(compressor);
|
val = this._eval(compressor);
|
||||||
return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
|
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex !== def) throw ex;
|
if (ex !== def) throw ex;
|
||||||
return [ this ];
|
return [ this ];
|
||||||
}
|
}
|
||||||
|
var node;
|
||||||
|
try {
|
||||||
|
node = make_node_from_constant(compressor, val, this);
|
||||||
|
} catch(ex) {
|
||||||
|
return [ this ];
|
||||||
|
}
|
||||||
|
return [ best_of(node, this), val ];
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("is_constant", function(compressor){
|
var unaryPrefix = makePredicate("! ~ - +");
|
||||||
|
AST_Node.DEFMETHOD("is_constant", function(){
|
||||||
// Accomodate when compress option evaluate=false
|
// Accomodate when compress option evaluate=false
|
||||||
// as well as the common constant expressions !0 and !1
|
// as well as the common constant expressions !0 and -1
|
||||||
return this instanceof AST_Constant
|
if (this instanceof AST_Constant) {
|
||||||
|| (this instanceof AST_UnaryPrefix && this.operator == "!"
|
return !(this instanceof AST_RegExp);
|
||||||
&& this.expression instanceof AST_Constant)
|
} else {
|
||||||
|| this.evaluate(compressor).length > 1;
|
return this instanceof AST_UnaryPrefix
|
||||||
|
&& this.expression instanceof AST_Constant
|
||||||
|
&& unaryPrefix(this.operator);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// Obtain the constant value of an expression already known to be constant.
|
// Obtain the constant value of an expression already known to be constant.
|
||||||
// Result only valid iff this.is_constant(compressor) is true.
|
// Result only valid iff this.is_constant() is true.
|
||||||
AST_Node.DEFMETHOD("constant_value", function(compressor){
|
AST_Node.DEFMETHOD("constant_value", function(compressor){
|
||||||
// Accomodate when option evaluate=false.
|
// Accomodate when option evaluate=false.
|
||||||
if (this instanceof AST_Constant) return this.value;
|
if (this instanceof AST_Constant && !(this instanceof AST_RegExp)) {
|
||||||
// Accomodate the common constant expressions !0 and !1 when option evaluate=false.
|
return this.value;
|
||||||
if (this instanceof AST_UnaryPrefix
|
|
||||||
&& this.operator == "!"
|
|
||||||
&& this.expression instanceof AST_Constant) {
|
|
||||||
return !this.expression.value;
|
|
||||||
}
|
}
|
||||||
var result = this.evaluate(compressor)
|
// Accomodate the common constant expressions !0 and -1 when option evaluate=false.
|
||||||
|
if (this instanceof AST_UnaryPrefix
|
||||||
|
&& this.expression instanceof AST_Constant) switch (this.operator) {
|
||||||
|
case "!":
|
||||||
|
return !this.expression.value;
|
||||||
|
case "~":
|
||||||
|
return ~this.expression.value;
|
||||||
|
case "-":
|
||||||
|
return -this.expression.value;
|
||||||
|
case "+":
|
||||||
|
return +this.expression.value;
|
||||||
|
default:
|
||||||
|
throw new Error(string_template("Cannot evaluate unary expression {value}", {
|
||||||
|
value: this.print_to_string()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
var result = this.evaluate(compressor);
|
||||||
if (result.length > 1) {
|
if (result.length > 1) {
|
||||||
return result[1];
|
return result[1];
|
||||||
}
|
}
|
||||||
// should never be reached
|
throw new Error(string_template("Cannot evaluate constant [{file}:{line},{col}]", this.start));
|
||||||
return undefined;
|
|
||||||
});
|
});
|
||||||
def(AST_Statement, function(){
|
def(AST_Statement, function(){
|
||||||
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
||||||
@@ -1071,6 +1104,32 @@ merge(Compressor.prototype, {
|
|||||||
if (this.segments.length !== 1) throw def;
|
if (this.segments.length !== 1) throw def;
|
||||||
return this.segments[0].value;
|
return this.segments[0].value;
|
||||||
});
|
});
|
||||||
|
def(AST_Array, function(compressor){
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
return this.elements.map(function(element) {
|
||||||
|
return ev(element, compressor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw def;
|
||||||
|
});
|
||||||
|
def(AST_Object, function(compressor){
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
var val = {};
|
||||||
|
for (var i = 0, len = this.properties.length; i < len; i++) {
|
||||||
|
var prop = this.properties[i];
|
||||||
|
var key = prop.key;
|
||||||
|
if (key instanceof AST_Node) {
|
||||||
|
key = ev(key, compressor);
|
||||||
|
}
|
||||||
|
if (typeof Object.prototype[key] === 'function') {
|
||||||
|
throw def;
|
||||||
|
}
|
||||||
|
val[key] = ev(prop.value, compressor);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
throw def;
|
||||||
|
});
|
||||||
def(AST_UnaryPrefix, function(compressor){
|
def(AST_UnaryPrefix, function(compressor){
|
||||||
var e = this.expression;
|
var e = this.expression;
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
@@ -1140,6 +1199,12 @@ merge(Compressor.prototype, {
|
|||||||
try {
|
try {
|
||||||
var d = this.definition();
|
var d = this.definition();
|
||||||
if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
|
if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
if (!HOP(d.init, '_evaluated')) {
|
||||||
|
d.init._evaluated = ev(d.init, compressor);
|
||||||
|
}
|
||||||
|
return d.init._evaluated;
|
||||||
|
}
|
||||||
return ev(d.init, compressor);
|
return ev(d.init, compressor);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1147,11 +1212,16 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
throw def;
|
throw def;
|
||||||
});
|
});
|
||||||
def(AST_Dot, function(compressor){
|
def(AST_PropAccess, function(compressor){
|
||||||
if (compressor.option("unsafe") && this.property == "length") {
|
if (compressor.option("unsafe")) {
|
||||||
var str = ev(this.expression, compressor);
|
var key = this.property;
|
||||||
if (typeof str == "string")
|
if (key instanceof AST_Node) {
|
||||||
return str.length;
|
key = ev(key, compressor);
|
||||||
|
}
|
||||||
|
var val = ev(this.expression, compressor);
|
||||||
|
if (val && HOP(val, key)) {
|
||||||
|
return val[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw def;
|
throw def;
|
||||||
});
|
});
|
||||||
@@ -2494,6 +2564,16 @@ merge(Compressor.prototype, {
|
|||||||
var commutativeOperators = makePredicate("== === != !== * & | ^");
|
var commutativeOperators = makePredicate("== === != !== * & | ^");
|
||||||
|
|
||||||
OPT(AST_Binary, function(self, compressor){
|
OPT(AST_Binary, function(self, compressor){
|
||||||
|
var lhs = self.left.evaluate(compressor);
|
||||||
|
var rhs = self.right.evaluate(compressor);
|
||||||
|
if (lhs.length > 1 && lhs[0].is_constant() !== self.left.is_constant()
|
||||||
|
|| rhs.length > 1 && rhs[0].is_constant() !== self.right.is_constant()) {
|
||||||
|
return make_node(AST_Binary, self, {
|
||||||
|
operator: self.operator,
|
||||||
|
left: lhs[0],
|
||||||
|
right: rhs[0]
|
||||||
|
}).optimize(compressor);
|
||||||
|
}
|
||||||
function reverse(op, force) {
|
function reverse(op, force) {
|
||||||
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
|
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
|
||||||
if (op) self.operator = op;
|
if (op) self.operator = op;
|
||||||
@@ -2566,32 +2646,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (compressor.option("conditionals")) {
|
|
||||||
if (self.operator == "&&") {
|
|
||||||
var ll = self.left.evaluate(compressor);
|
|
||||||
if (ll.length > 1) {
|
|
||||||
if (ll[1]) {
|
|
||||||
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, self.right.evaluate(compressor)[0]);
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, ll[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (self.operator == "||") {
|
|
||||||
var ll = self.left.evaluate(compressor);
|
|
||||||
if (ll.length > 1) {
|
|
||||||
if (ll[1]) {
|
|
||||||
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, ll[0]);
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, self.right.evaluate(compressor)[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
|
if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
@@ -2665,6 +2719,30 @@ merge(Compressor.prototype, {
|
|||||||
return self.left;
|
return self.left;
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate")) {
|
if (compressor.option("evaluate")) {
|
||||||
|
switch (self.operator) {
|
||||||
|
case "&&":
|
||||||
|
if (self.left.is_constant()) {
|
||||||
|
if (self.left.constant_value(compressor)) {
|
||||||
|
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
||||||
|
return maintain_this_binding(compressor.parent(), self, self.right);
|
||||||
|
} else {
|
||||||
|
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||||
|
return maintain_this_binding(compressor.parent(), self, self.left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "||":
|
||||||
|
if (self.left.is_constant()) {
|
||||||
|
if (self.left.constant_value(compressor)) {
|
||||||
|
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
||||||
|
return maintain_this_binding(compressor.parent(), self, self.left);
|
||||||
|
} else {
|
||||||
|
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
||||||
|
return maintain_this_binding(compressor.parent(), self, self.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (self.operator == "+") {
|
if (self.operator == "+") {
|
||||||
if (self.left instanceof AST_Constant
|
if (self.left instanceof AST_Constant
|
||||||
&& self.right instanceof AST_Binary
|
&& self.right instanceof AST_Binary
|
||||||
@@ -2738,14 +2816,6 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_SymbolRef, function(self, compressor){
|
OPT(AST_SymbolRef, function(self, compressor){
|
||||||
function isLHS(symbol, parent) {
|
|
||||||
return (
|
|
||||||
parent instanceof AST_Binary &&
|
|
||||||
parent.operator === '=' &&
|
|
||||||
parent.left === symbol
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.undeclared() && !isLHS(self, compressor.parent())) {
|
if (self.undeclared() && !isLHS(self, compressor.parent())) {
|
||||||
var defines = compressor.option("global_defs");
|
var defines = compressor.option("global_defs");
|
||||||
if (defines && HOP(defines, self.name)) {
|
if (defines && HOP(defines, self.name)) {
|
||||||
@@ -2899,14 +2969,14 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// y?1:1 --> 1
|
// y?1:1 --> 1
|
||||||
if (consequent.is_constant(compressor)
|
if (consequent.is_constant()
|
||||||
&& alternative.is_constant(compressor)
|
&& alternative.is_constant()
|
||||||
&& consequent.equivalent_to(alternative)) {
|
&& consequent.equivalent_to(alternative)) {
|
||||||
var consequent_value = consequent.constant_value(compressor);
|
var consequent_value = consequent.evaluate(compressor)[0];
|
||||||
if (self.condition.has_side_effects(compressor)) {
|
if (self.condition.has_side_effects(compressor)) {
|
||||||
return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent_value, self)]);
|
return AST_Seq.from_array([self.condition, consequent_value]);
|
||||||
} else {
|
} else {
|
||||||
return make_node_from_constant(compressor, consequent_value, self);
|
return consequent_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3023,7 +3093,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self.evaluate(compressor)[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Dot, function(self, compressor){
|
OPT(AST_Dot, function(self, compressor){
|
||||||
|
|||||||
31
lib/scope.js
31
lib/scope.js
@@ -232,6 +232,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
var cls = null;
|
var cls = null;
|
||||||
var globals = self.globals = new Dictionary();
|
var globals = self.globals = new Dictionary();
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
|
function isModified(node, level) {
|
||||||
|
var parent = tw.parent(level);
|
||||||
|
if (parent instanceof AST_Unary && (parent.operator === "++" || parent.operator === "--")
|
||||||
|
|| parent instanceof AST_Assign && parent.left === node
|
||||||
|
|| parent instanceof AST_Call && parent.expression === node) {
|
||||||
|
return true;
|
||||||
|
} else if (parent instanceof AST_PropAccess && parent.expression === node) {
|
||||||
|
return isModified(parent, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
var prev_func = func;
|
var prev_func = func;
|
||||||
func = node;
|
func = node;
|
||||||
@@ -252,8 +263,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
var parent = tw.parent();
|
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||||
if (name == "eval" && parent instanceof AST_Call) {
|
|
||||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||||
s.uses_eval = true;
|
s.uses_eval = true;
|
||||||
}
|
}
|
||||||
@@ -275,11 +285,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
sym = g;
|
sym = g;
|
||||||
}
|
}
|
||||||
node.thedef = sym;
|
node.thedef = sym;
|
||||||
if (parent instanceof AST_Unary && (parent.operator === '++' || parent.operator === '--')
|
if (isModified(node, 0)) {
|
||||||
|| parent instanceof AST_Assign && parent.left === node) {
|
|
||||||
sym.modified = true;
|
sym.modified = true;
|
||||||
}
|
}
|
||||||
node.reference();
|
node.reference(options);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -323,13 +332,18 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
|||||||
this.variables.set(symbol.name, def);
|
this.variables.set(symbol.name, def);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_SymbolRef.DEFMETHOD("reference", function() {
|
AST_SymbolRef.DEFMETHOD("reference", function(options) {
|
||||||
var def = this.definition();
|
var def = this.definition();
|
||||||
def.references.push(this);
|
def.references.push(this);
|
||||||
var s = this.scope;
|
var s = this.scope;
|
||||||
while (s) {
|
while (s) {
|
||||||
push_uniq(s.enclosed, def);
|
push_uniq(s.enclosed, def);
|
||||||
if (s === def.scope) break;
|
if (s === def.scope) break;
|
||||||
|
if (options.keep_fnames) {
|
||||||
|
s.variables.each(function(d) {
|
||||||
|
push_uniq(def.scope.enclosed, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
s = s.parent_scope;
|
s = s.parent_scope;
|
||||||
}
|
}
|
||||||
this.frame = this.scope.nesting - def.scope.nesting;
|
this.frame = this.scope.nesting - def.scope.nesting;
|
||||||
@@ -401,11 +415,6 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("references", function(sym){
|
|
||||||
if (sym instanceof AST_Symbol) sym = sym.definition();
|
|
||||||
return this.enclosed.indexOf(sym) < 0 ? null : sym;
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
||||||
var def = this.definition();
|
var def = this.definition();
|
||||||
return def && def.unmangleable(options);
|
return def && def.unmangleable(options);
|
||||||
|
|||||||
@@ -147,3 +147,53 @@ spread_with_logical_expression_at_middle: {
|
|||||||
var a = [1, 1, ...[2, 3, 5], 8]
|
var a = [1, 1, ...[2, 3, 5], 8]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_loop: {
|
||||||
|
options = {
|
||||||
|
unsafe : true,
|
||||||
|
unused : true,
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f0() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0, len = a.length; i < len; i++) {
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
a[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++)
|
||||||
|
a[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -635,166 +635,6 @@ ternary_boolean_alternative: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conditional_and: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
|
|
||||||
a = true && condition;
|
|
||||||
a = 1 && console.log("a");
|
|
||||||
a = 2 * 3 && 2 * condition;
|
|
||||||
a = 5 == 5 && condition + 3;
|
|
||||||
a = "string" && 4 - condition;
|
|
||||||
a = 5 + "" && condition / 5;
|
|
||||||
a = -4.5 && 6 << condition;
|
|
||||||
a = 6 && 7;
|
|
||||||
|
|
||||||
a = false && condition;
|
|
||||||
a = NaN && console.log("b");
|
|
||||||
a = 0 && console.log("c");
|
|
||||||
a = undefined && 2 * condition;
|
|
||||||
a = null && condition + 3;
|
|
||||||
a = 2 * 3 - 6 && 4 - condition;
|
|
||||||
a = 10 == 7 && condition / 5;
|
|
||||||
a = !"string" && 6 % condition;
|
|
||||||
a = 0 && 7;
|
|
||||||
|
|
||||||
// don't compress these
|
|
||||||
|
|
||||||
a = condition && true;
|
|
||||||
a = console.log("a") && 2;
|
|
||||||
a = 4 - condition && "string";
|
|
||||||
a = 6 << condition && -4.5;
|
|
||||||
|
|
||||||
a = condition && false;
|
|
||||||
a = console.log("b") && NaN;
|
|
||||||
a = console.log("c") && 0;
|
|
||||||
a = 2 * condition && undefined;
|
|
||||||
a = condition + 3 && null;
|
|
||||||
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
|
|
||||||
a = condition;
|
|
||||||
a = console.log("a");
|
|
||||||
a = 2 * condition;
|
|
||||||
a = condition + 3;
|
|
||||||
a = 4 - condition;
|
|
||||||
a = condition / 5;
|
|
||||||
a = 6 << condition;
|
|
||||||
a = 7;
|
|
||||||
|
|
||||||
a = false;
|
|
||||||
a = NaN;
|
|
||||||
a = 0;
|
|
||||||
a = void 0;
|
|
||||||
a = null;
|
|
||||||
a = 0;
|
|
||||||
a = false;
|
|
||||||
a = false;
|
|
||||||
a = 0;
|
|
||||||
|
|
||||||
a = condition && true;
|
|
||||||
a = console.log("a") && 2;
|
|
||||||
a = 4 - condition && "string";
|
|
||||||
a = 6 << condition && -4.5;
|
|
||||||
|
|
||||||
a = condition && false;
|
|
||||||
a = console.log("b") && NaN;
|
|
||||||
a = console.log("c") && 0;
|
|
||||||
a = 2 * condition && void 0;
|
|
||||||
a = condition + 3 && null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_or: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
|
|
||||||
a = true || condition;
|
|
||||||
a = 1 || console.log("a");
|
|
||||||
a = 2 * 3 || 2 * condition;
|
|
||||||
a = 5 == 5 || condition + 3;
|
|
||||||
a = "string" || 4 - condition;
|
|
||||||
a = 5 + "" || condition / 5;
|
|
||||||
a = -4.5 || 6 << condition;
|
|
||||||
a = 6 || 7;
|
|
||||||
|
|
||||||
a = false || condition;
|
|
||||||
a = 0 || console.log("b");
|
|
||||||
a = NaN || console.log("c");
|
|
||||||
a = undefined || 2 * condition;
|
|
||||||
a = null || condition + 3;
|
|
||||||
a = 2 * 3 - 6 || 4 - condition;
|
|
||||||
a = 10 == 7 || condition / 5;
|
|
||||||
a = !"string" || 6 % condition;
|
|
||||||
a = null || 7;
|
|
||||||
|
|
||||||
a = console.log(undefined && condition || null);
|
|
||||||
a = console.log(undefined || condition && null);
|
|
||||||
|
|
||||||
// don't compress these
|
|
||||||
|
|
||||||
a = condition || true;
|
|
||||||
a = console.log("a") || 2;
|
|
||||||
a = 4 - condition || "string";
|
|
||||||
a = 6 << condition || -4.5;
|
|
||||||
|
|
||||||
a = condition || false;
|
|
||||||
a = console.log("b") || NaN;
|
|
||||||
a = console.log("c") || 0;
|
|
||||||
a = 2 * condition || undefined;
|
|
||||||
a = condition + 3 || null;
|
|
||||||
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
|
|
||||||
a = true;
|
|
||||||
a = 1;
|
|
||||||
a = 6;
|
|
||||||
a = true;
|
|
||||||
a = "string";
|
|
||||||
a = "5";
|
|
||||||
a = -4.5;
|
|
||||||
a = 6;
|
|
||||||
|
|
||||||
a = condition;
|
|
||||||
a = console.log("b");
|
|
||||||
a = console.log("c");
|
|
||||||
a = 2 * condition;
|
|
||||||
a = condition + 3;
|
|
||||||
a = 4 - condition;
|
|
||||||
a = condition / 5;
|
|
||||||
a = 6 % condition;
|
|
||||||
a = 7;
|
|
||||||
|
|
||||||
a = console.log(null);
|
|
||||||
a = console.log(condition && null);
|
|
||||||
|
|
||||||
a = condition || true;
|
|
||||||
a = console.log("a") || 2;
|
|
||||||
a = 4 - condition || "string";
|
|
||||||
a = 6 << condition || -4.5;
|
|
||||||
|
|
||||||
a = condition || false;
|
|
||||||
a = console.log("b") || NaN;
|
|
||||||
a = console.log("c") || 0;
|
|
||||||
a = 2 * condition || void 0;
|
|
||||||
a = condition + 3 || null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trivial_boolean_ternary_expressions : {
|
trivial_boolean_ternary_expressions : {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -906,3 +746,26 @@ issue_1154: {
|
|||||||
function g6() { return g(), "number"; }
|
function g6() { return g(), "number"; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_evaluate: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate : false
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(b) {
|
||||||
|
a = b ? !0 : !0;
|
||||||
|
a = b ? ~1 : ~1;
|
||||||
|
a = b ? -2 : -2;
|
||||||
|
a = b ? +3 : +3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(b) {
|
||||||
|
a = !0;
|
||||||
|
a = ~1;
|
||||||
|
a = -2;
|
||||||
|
a = +3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,187 @@
|
|||||||
|
and: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
// compress these
|
||||||
|
|
||||||
|
a = true && condition;
|
||||||
|
a = 1 && console.log("a");
|
||||||
|
a = 2 * 3 && 2 * condition;
|
||||||
|
a = 5 == 5 && condition + 3;
|
||||||
|
a = "string" && 4 - condition;
|
||||||
|
a = 5 + "" && condition / 5;
|
||||||
|
a = -4.5 && 6 << condition;
|
||||||
|
a = 6 && 7;
|
||||||
|
|
||||||
|
a = false && condition;
|
||||||
|
a = NaN && console.log("b");
|
||||||
|
a = 0 && console.log("c");
|
||||||
|
a = undefined && 2 * condition;
|
||||||
|
a = null && condition + 3;
|
||||||
|
a = 2 * 3 - 6 && 4 - condition;
|
||||||
|
a = 10 == 7 && condition / 5;
|
||||||
|
a = !"string" && 6 % condition;
|
||||||
|
a = 0 && 7;
|
||||||
|
|
||||||
|
// don't compress these
|
||||||
|
|
||||||
|
a = condition && true;
|
||||||
|
a = console.log("a") && 2;
|
||||||
|
a = 4 - condition && "string";
|
||||||
|
a = 6 << condition && -4.5;
|
||||||
|
|
||||||
|
a = condition && false;
|
||||||
|
a = console.log("b") && NaN;
|
||||||
|
a = console.log("c") && 0;
|
||||||
|
a = 2 * condition && undefined;
|
||||||
|
a = condition + 3 && null;
|
||||||
|
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
|
||||||
|
a = condition;
|
||||||
|
a = console.log("a");
|
||||||
|
a = 2 * condition;
|
||||||
|
a = condition + 3;
|
||||||
|
a = 4 - condition;
|
||||||
|
a = condition / 5;
|
||||||
|
a = 6 << condition;
|
||||||
|
a = 7;
|
||||||
|
|
||||||
|
a = false;
|
||||||
|
a = NaN;
|
||||||
|
a = 0;
|
||||||
|
a = void 0;
|
||||||
|
a = null;
|
||||||
|
a = 0;
|
||||||
|
a = false;
|
||||||
|
a = false;
|
||||||
|
a = 0;
|
||||||
|
|
||||||
|
a = condition && true;
|
||||||
|
a = console.log("a") && 2;
|
||||||
|
a = 4 - condition && "string";
|
||||||
|
a = 6 << condition && -4.5;
|
||||||
|
|
||||||
|
a = condition && false;
|
||||||
|
a = console.log("b") && NaN;
|
||||||
|
a = console.log("c") && 0;
|
||||||
|
a = 2 * condition && void 0;
|
||||||
|
a = condition + 3 && null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
or: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
// compress these
|
||||||
|
|
||||||
|
a = true || condition;
|
||||||
|
a = 1 || console.log("a");
|
||||||
|
a = 2 * 3 || 2 * condition;
|
||||||
|
a = 5 == 5 || condition + 3;
|
||||||
|
a = "string" || 4 - condition;
|
||||||
|
a = 5 + "" || condition / 5;
|
||||||
|
a = -4.5 || 6 << condition;
|
||||||
|
a = 6 || 7;
|
||||||
|
|
||||||
|
a = false || condition;
|
||||||
|
a = 0 || console.log("b");
|
||||||
|
a = NaN || console.log("c");
|
||||||
|
a = undefined || 2 * condition;
|
||||||
|
a = null || condition + 3;
|
||||||
|
a = 2 * 3 - 6 || 4 - condition;
|
||||||
|
a = 10 == 7 || condition / 5;
|
||||||
|
a = !"string" || 6 % condition;
|
||||||
|
a = null || 7;
|
||||||
|
|
||||||
|
a = console.log(undefined && condition || null);
|
||||||
|
a = console.log(undefined || condition && null);
|
||||||
|
|
||||||
|
// don't compress these
|
||||||
|
|
||||||
|
a = condition || true;
|
||||||
|
a = console.log("a") || 2;
|
||||||
|
a = 4 - condition || "string";
|
||||||
|
a = 6 << condition || -4.5;
|
||||||
|
|
||||||
|
a = condition || false;
|
||||||
|
a = console.log("b") || NaN;
|
||||||
|
a = console.log("c") || 0;
|
||||||
|
a = 2 * condition || undefined;
|
||||||
|
a = condition + 3 || null;
|
||||||
|
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
|
||||||
|
a = true;
|
||||||
|
a = 1;
|
||||||
|
a = 6;
|
||||||
|
a = true;
|
||||||
|
a = "string";
|
||||||
|
a = "5";
|
||||||
|
a = -4.5;
|
||||||
|
a = 6;
|
||||||
|
|
||||||
|
a = condition;
|
||||||
|
a = console.log("b");
|
||||||
|
a = console.log("c");
|
||||||
|
a = 2 * condition;
|
||||||
|
a = condition + 3;
|
||||||
|
a = 4 - condition;
|
||||||
|
a = condition / 5;
|
||||||
|
a = 6 % condition;
|
||||||
|
a = 7;
|
||||||
|
|
||||||
|
a = console.log(null);
|
||||||
|
a = console.log(condition && null);
|
||||||
|
|
||||||
|
a = condition || true;
|
||||||
|
a = console.log("a") || 2;
|
||||||
|
a = 4 - condition || "string";
|
||||||
|
a = 6 << condition || -4.5;
|
||||||
|
|
||||||
|
a = condition || false;
|
||||||
|
a = console.log("b") || NaN;
|
||||||
|
a = console.log("c") || 0;
|
||||||
|
a = 2 * condition || void 0;
|
||||||
|
a = condition + 3 || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unary_prefix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = !0 && b;
|
||||||
|
a = !0 || b;
|
||||||
|
a = ~1 && b;
|
||||||
|
a = ~1 || b;
|
||||||
|
a = -2 && b;
|
||||||
|
a = -2 || b;
|
||||||
|
a = +3 && b;
|
||||||
|
a = +3 || b;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = b;
|
||||||
|
a = !0;
|
||||||
|
a = b;
|
||||||
|
a = -2;
|
||||||
|
a = b;
|
||||||
|
a = -2;
|
||||||
|
a = b;
|
||||||
|
a = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
negative_zero: {
|
negative_zero: {
|
||||||
options = { evaluate: true }
|
options = { evaluate: true }
|
||||||
input: {
|
input: {
|
||||||
@@ -95,12 +279,18 @@ pow_with_number_constants: {
|
|||||||
evaluate: true
|
evaluate: true
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = 5 ** NaN; /* NaN exponent results to NaN */
|
var a = 5 ** NaN;
|
||||||
var b = 42 ** +0; /* +0 exponent results to NaN */
|
/* NaN exponent results to NaN */
|
||||||
var c = 42 ** -0; /* -0 exponent results to NaN */
|
var b = 42 ** +0;
|
||||||
var d = NaN ** 1; /* NaN with non-zero exponent is NaN */
|
/* +0 exponent results to NaN */
|
||||||
var e = 2 ** Infinity; /* abs(base) > 1 with Infinity as exponent is Infinity */
|
var c = 42 ** -0;
|
||||||
var f = 2 ** -Infinity; /* abs(base) > 1 with -Infinity as exponent is +0 */
|
/* -0 exponent results to NaN */
|
||||||
|
var d = NaN ** 1;
|
||||||
|
/* NaN with non-zero exponent is NaN */
|
||||||
|
var e = 2 ** Infinity;
|
||||||
|
/* abs(base) > 1 with Infinity as exponent is Infinity */
|
||||||
|
var f = 2 ** -Infinity;
|
||||||
|
/* abs(base) > 1 with -Infinity as exponent is +0 */
|
||||||
var g = (-7) ** (0.5);
|
var g = (-7) ** (0.5);
|
||||||
var h = 2324334 ** 34343443;
|
var h = 2324334 ** 34343443;
|
||||||
var i = (-2324334) ** 34343443;
|
var i = (-2324334) ** 34343443;
|
||||||
@@ -125,3 +315,380 @@ pow_with_number_constants: {
|
|||||||
var m = 3 ** -10;
|
var m = 3 ** -10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_constant: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
true.a,
|
||||||
|
false.a,
|
||||||
|
null.a,
|
||||||
|
undefined.a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
true.a,
|
||||||
|
false.a,
|
||||||
|
null.a,
|
||||||
|
(void 0).a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:1}) + 1,
|
||||||
|
({a:1}).a + 1,
|
||||||
|
({a:1}).b + 1,
|
||||||
|
({a:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:1}) + 1,
|
||||||
|
2,
|
||||||
|
({a:1}).b + 1,
|
||||||
|
1..b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_nested: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1}}) + 1,
|
||||||
|
({a:{b:1}}).a + 1,
|
||||||
|
({a:{b:1}}).b + 1,
|
||||||
|
({a:{b:1}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1}}) + 1,
|
||||||
|
({a:{b:1}}).a + 1,
|
||||||
|
({a:{b:1}}).b + 1,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:1}) + 1,
|
||||||
|
({a:{b:1},b:1}).a + 1,
|
||||||
|
({a:{b:1},b:1}).b + 1,
|
||||||
|
({a:{b:1},b:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:1}) + 1,
|
||||||
|
({a:{b:1},b:1}).a + 1,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_repeated: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},a:1}) + 1,
|
||||||
|
({a:{b:1},a:1}).a + 1,
|
||||||
|
({a:{b:1},a:1}).b + 1,
|
||||||
|
({a:{b:1},a:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},a:1}) + 1,
|
||||||
|
2,
|
||||||
|
({a:{b:1},a:1}).b + 1,
|
||||||
|
1..b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_function: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a + 1,
|
||||||
|
({a:{b:1},b:function(){}}).b + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a + 1,
|
||||||
|
({a:{b:1},b:function(){}}).b + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_integer_key: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({0:1}) + 1,
|
||||||
|
({0:1})[0] + 1,
|
||||||
|
({0:1})["0"] + 1,
|
||||||
|
({0:1})[1] + 1,
|
||||||
|
({0:1})[0][1] + 1,
|
||||||
|
({0:1})[0]["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({0:1}) + 1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
({0:1})[1] + 1,
|
||||||
|
1[1] + 1,
|
||||||
|
1["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_integer_key_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({0:{1:1},1:1}) + 1,
|
||||||
|
({0:{1:1},1:1})[0] + 1,
|
||||||
|
({0:{1:1},1:1})["0"] + 1,
|
||||||
|
({0:{1:1},1:1})[1] + 1,
|
||||||
|
({0:{1:1},1:1})[0][1] + 1,
|
||||||
|
({0:{1:1},1:1})[0]["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({0:{1:1},1:1}) + 1,
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_float_key: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({2.72:1}) + 1,
|
||||||
|
({2.72:1})[2.72] + 1,
|
||||||
|
({2.72:1})["2.72"] + 1,
|
||||||
|
({2.72:1})[3.14] + 1,
|
||||||
|
({2.72:1})[2.72][3.14] + 1,
|
||||||
|
({2.72:1})[2.72]["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({2.72:1}) + 1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
({2.72:1})[3.14] + 1,
|
||||||
|
1[3.14] + 1,
|
||||||
|
1["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_float_key_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({2.72:{3.14:1},3.14:1}) + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})["2.72"] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[3.14] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72][3.14] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72]["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_array: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
[1, , 3][1],
|
||||||
|
[1, 2, 3, a] + 1,
|
||||||
|
[1, 2, 3, 4] + 1,
|
||||||
|
[1, 2, 3, a][0] + 1,
|
||||||
|
[1, 2, 3, 4][0] + 1,
|
||||||
|
[1, 2, 3, 4][6 - 5] + 1,
|
||||||
|
[1, , 3, 4][6 - 5] + 1,
|
||||||
|
[[1, 2], [3, 4]][0] + 1,
|
||||||
|
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
||||||
|
[[1, 2], , [3, 4]][6 - 5][1] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
void 0,
|
||||||
|
[1, 2, 3, a] + 1,
|
||||||
|
"1,2,3,41",
|
||||||
|
[1, 2, 3, a][0] + 1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
NaN,
|
||||||
|
"1,21",
|
||||||
|
5,
|
||||||
|
(void 0)[1] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234" + 1,
|
||||||
|
"1234"[0] + 1,
|
||||||
|
"1234"[6 - 5] + 1,
|
||||||
|
("12" + "34")[0] + 1,
|
||||||
|
("12" + "34")[6 - 5] + 1,
|
||||||
|
[1, 2, 3, 4].join("")[0] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"12341",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_array_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
[1, 2, 3, 4].a + 1,
|
||||||
|
[1, 2, 3, 4]["a"] + 1,
|
||||||
|
[1, 2, 3, 4][3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
[1, 2, 3, 4].a + 1,
|
||||||
|
[1, 2, 3, 4]["a"] + 1,
|
||||||
|
[1, 2, 3, 4][3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234".a + 1,
|
||||||
|
"1234"["a"] + 1,
|
||||||
|
"1234"[3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"1234".a + 1,
|
||||||
|
"1234"["a"] + 1,
|
||||||
|
"1234"[3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_prototype_function: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = ({valueOf: 0}) < 1;
|
||||||
|
var b = ({toString: 0}) < 1;
|
||||||
|
var c = ({valueOf: 0}) + "";
|
||||||
|
var d = ({toString: 0}) + "";
|
||||||
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
|
var f = (({toString: 0}) + "")[2];
|
||||||
|
var g = ({valueOf: 0}).valueOf();
|
||||||
|
var h = ({toString: 0}).toString();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = ({valueOf: 0}) < 1;
|
||||||
|
var b = ({toString: 0}) < 1;
|
||||||
|
var c = ({valueOf: 0}) + "";
|
||||||
|
var d = ({toString: 0}) + "";
|
||||||
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
|
var f = (({toString: 0}) + "")[2];
|
||||||
|
var g = ({valueOf: 0}).valueOf();
|
||||||
|
var h = "" + ({toString: 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
122
test/compress/issue-1431.js
Normal file
122
test/compress/issue-1431.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
level_one: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(r) {
|
||||||
|
return function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return r(n);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level_two: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function r(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(t) {
|
||||||
|
return function() {
|
||||||
|
function r(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return t(n);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level_three: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function r(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
function() {
|
||||||
|
function t(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(t) {
|
||||||
|
return function() {
|
||||||
|
function r(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
function() {
|
||||||
|
function t(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return t(n);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,29 @@
|
|||||||
do_not_update_lhs: {
|
do_not_update_lhs: {
|
||||||
options = { global_defs: { DEBUG: false } };
|
options = {
|
||||||
input: { DEBUG = false; }
|
global_defs: { DEBUG: 0 }
|
||||||
expect: { DEBUG = false; }
|
}
|
||||||
|
input: {
|
||||||
|
DEBUG++;
|
||||||
|
DEBUG += 1;
|
||||||
|
DEBUG = 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
DEBUG++;
|
||||||
|
DEBUG += 1;
|
||||||
|
DEBUG = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_update_rhs: {
|
do_update_rhs: {
|
||||||
options = { global_defs: { DEBUG: false } };
|
options = {
|
||||||
input: { MY_DEBUG = DEBUG; }
|
global_defs: { DEBUG: 0 }
|
||||||
expect: { MY_DEBUG = false; }
|
}
|
||||||
|
input: {
|
||||||
|
MY_DEBUG = DEBUG;
|
||||||
|
MY_DEBUG += DEBUG;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
MY_DEBUG = 0;
|
||||||
|
MY_DEBUG += 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,56 @@ dot_properties_es5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate_length: {
|
sub_properties: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
properties: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a[0] = 0;
|
||||||
|
a["0"] = 1;
|
||||||
|
a[3.14] = 2;
|
||||||
|
a["3" + ".14"] = 3;
|
||||||
|
a["i" + "f"] = 4;
|
||||||
|
a["foo" + " bar"] = 5;
|
||||||
|
a[0 / 0] = 6;
|
||||||
|
a[null] = 7;
|
||||||
|
a[undefined] = 8;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a[0] = 0;
|
||||||
|
a[0] = 1;
|
||||||
|
a[3.14] = 2;
|
||||||
|
a[3.14] = 3;
|
||||||
|
a.if = 4;
|
||||||
|
a["foo bar"] = 5;
|
||||||
|
a[NaN] = 6;
|
||||||
|
a[null] = 7;
|
||||||
|
a[void 0] = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_array_length: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
unsafe: true,
|
||||||
|
evaluate: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a = [1, 2, 3].length;
|
||||||
|
a = [1, 2, 3].join()["len" + "gth"];
|
||||||
|
a = [1, 2, b].length;
|
||||||
|
a = [1, 2, 3].join(b).length;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 3;
|
||||||
|
a = 5;
|
||||||
|
a = [1, 2, b].length;
|
||||||
|
a = [1, 2, 3].join(b).length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_string_length: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
|
|||||||
@@ -136,30 +136,30 @@ modified: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function f2() {
|
function f2() {
|
||||||
var a = 1, b = 2, c = 3;
|
var b = 2, c = 3;
|
||||||
b = c;
|
b = c;
|
||||||
console.log(a + b);
|
console.log(1 + b);
|
||||||
console.log(b + c);
|
console.log(b + 3);
|
||||||
console.log(4);
|
console.log(4);
|
||||||
console.log(a + b + c);
|
console.log(1 + b + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f3() {
|
function f3() {
|
||||||
var a = 1, b = 2, c = 3;
|
var b = 2, c = 3;
|
||||||
b *= c;
|
b *= c;
|
||||||
console.log(a + b);
|
console.log(1 + b);
|
||||||
console.log(b + c);
|
console.log(b + 3);
|
||||||
console.log(4);
|
console.log(4);
|
||||||
console.log(a + b + c);
|
console.log(1 + b + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f4() {
|
function f4() {
|
||||||
var a = 1, b = 2, c = 3;
|
var b = 2, c = 3;
|
||||||
b = c;
|
b = c;
|
||||||
console.log(a + b);
|
console.log(1 + b);
|
||||||
console.log(b + c);
|
console.log(b + c);
|
||||||
console.log(a + c);
|
console.log(1 + c);
|
||||||
console.log(a + b + c);
|
console.log(1 + b + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f5(a) {
|
function f5(a) {
|
||||||
@@ -169,3 +169,184 @@ modified: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true,
|
||||||
|
unused : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = {
|
||||||
|
b:1
|
||||||
|
};
|
||||||
|
console.log(a.b + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:{
|
||||||
|
c:1
|
||||||
|
},
|
||||||
|
d:2
|
||||||
|
};
|
||||||
|
console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
console.log(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:{
|
||||||
|
c:1
|
||||||
|
},
|
||||||
|
d:2
|
||||||
|
};
|
||||||
|
console.log(a.b + 3, 6, 6, 2..c + 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_object: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = {};
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(a + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:1
|
||||||
|
};
|
||||||
|
a.b = 2;
|
||||||
|
console.log(a.b + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = {};
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:1
|
||||||
|
};
|
||||||
|
a.b = 2;
|
||||||
|
console.log(a.b + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_array: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = [];
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(a + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = [1];
|
||||||
|
a[2] = 3;
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
var a = [1];
|
||||||
|
a.push(2);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = [];
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = [1];
|
||||||
|
a[2] = 3;
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
var a = [1];
|
||||||
|
a.push(2);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_equality: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true,
|
||||||
|
unused : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = {};
|
||||||
|
console.log(a === a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = [];
|
||||||
|
console.log(a === a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
var a = {a:1, b:2};
|
||||||
|
var b = a;
|
||||||
|
var c = a;
|
||||||
|
console.log(b === c);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f3(){
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
var b = a;
|
||||||
|
var c = a;
|
||||||
|
console.log(b === c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f3(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ do_screw_try_catch: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dont_screw_try_catch: {
|
dont_screw_try_catch: {
|
||||||
|
// This test is known to generate incorrect code for screw_ie8=false.
|
||||||
|
// Update expected result in the event this bug is ever fixed.
|
||||||
options = { screw_ie8: false };
|
options = { screw_ie8: false };
|
||||||
mangle = { screw_ie8: false };
|
mangle = { screw_ie8: false };
|
||||||
beautify = { screw_ie8: false };
|
beautify = { screw_ie8: false };
|
||||||
@@ -102,6 +104,8 @@ do_screw_try_catch_undefined: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dont_screw_try_catch_undefined: {
|
dont_screw_try_catch_undefined: {
|
||||||
|
// This test is known to generate incorrect code for screw_ie8=false.
|
||||||
|
// Update expected result in the event this bug is ever fixed.
|
||||||
options = { screw_ie8: false };
|
options = { screw_ie8: false };
|
||||||
mangle = { screw_ie8: false };
|
mangle = { screw_ie8: false };
|
||||||
beautify = { screw_ie8: false };
|
beautify = { screw_ie8: false };
|
||||||
@@ -123,8 +127,8 @@ dont_screw_try_catch_undefined: {
|
|||||||
} catch (n) {
|
} catch (n) {
|
||||||
console.log("caught: "+n)
|
console.log("caught: "+n)
|
||||||
}
|
}
|
||||||
console.log("undefined is " + void 0);
|
console.log("undefined is " + n);
|
||||||
return void 0===o
|
return o === n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
test/input/issue-1431/sample.js
Normal file
14
test/input/issue-1431/sample.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function g(op) {
|
||||||
|
return op(1) + op(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(f(g)() == 5);
|
||||||
@@ -70,4 +70,34 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should work with --keep-fnames (mangle only)", function (done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should work with --keep-fnames (mangle & compress)", function (done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should work with keep_fnames under mangler options", function (done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,12 +70,12 @@ function test_directory(dir) {
|
|||||||
return path.resolve(tests_dir, dir);
|
return path.resolve(tests_dir, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
function as_toplevel(input) {
|
function as_toplevel(input, mangle_options) {
|
||||||
if (input instanceof U.AST_BlockStatement) input = input.body;
|
if (input instanceof U.AST_BlockStatement) input = input.body;
|
||||||
else if (input instanceof U.AST_Statement) input = [ input ];
|
else if (input instanceof U.AST_Statement) input = [ input ];
|
||||||
else throw new Error("Unsupported input syntax");
|
else throw new Error("Unsupported input syntax");
|
||||||
var toplevel = new U.AST_Toplevel({ body: input });
|
var toplevel = new U.AST_Toplevel({ body: input });
|
||||||
toplevel.figure_out_scope();
|
toplevel.figure_out_scope(mangle_options);
|
||||||
return toplevel;
|
return toplevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,11 +103,11 @@ function run_compress_tests() {
|
|||||||
var output_options = test.beautify || {};
|
var output_options = test.beautify || {};
|
||||||
var expect;
|
var expect;
|
||||||
if (test.expect) {
|
if (test.expect) {
|
||||||
expect = make_code(as_toplevel(test.expect), output_options);
|
expect = make_code(as_toplevel(test.expect, test.mangle), output_options);
|
||||||
} else {
|
} else {
|
||||||
expect = test.expect_exact;
|
expect = test.expect_exact;
|
||||||
}
|
}
|
||||||
var input = as_toplevel(test.input);
|
var input = as_toplevel(test.input, test.mangle);
|
||||||
var input_code = make_code(test.input, {
|
var input_code = make_code(test.input, {
|
||||||
beautify: true,
|
beautify: true,
|
||||||
quote_style: 3,
|
quote_style: 3,
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ exports.minify = function(files, options) {
|
|||||||
if (options.compress) {
|
if (options.compress) {
|
||||||
var compress = { warnings: options.warnings };
|
var compress = { warnings: options.warnings };
|
||||||
UglifyJS.merge(compress, options.compress);
|
UglifyJS.merge(compress, options.compress);
|
||||||
toplevel.figure_out_scope();
|
toplevel.figure_out_scope(options.mangle);
|
||||||
var sq = UglifyJS.Compressor(compress);
|
var sq = UglifyJS.Compressor(compress);
|
||||||
toplevel = sq.compress(toplevel);
|
toplevel = sq.compress(toplevel);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user