Skip to content

Commit

Permalink
improve compression of undefined, NaN & Infinitiy
Browse files Browse the repository at this point in the history
- migrate transformation logic from `OutputStream` to `Compressor`
- always turn `undefined` into `void 0` (unless `unsafe`)
- always keep `NaN` except when avoiding local variable redefinition
- introduce `keep_infinity` to suppress `1/0` transform, except when avoiding local variable redefinition

supersedes #1723
fixes #1730
  • Loading branch information
alexlamsl committed Mar 31, 2017
1 parent da0273e commit e58fddc
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 16 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ to set `true`; it's effectively a shortcut for `foo=true`).
integer argument larger than 1 to further reduce code size in some cases.
Note: raising the number of passes will increase uglify compress time.

- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome.

### The `unsafe` option

It enables some transformations that *might* break code logic in certain
Expand Down
9 changes: 6 additions & 3 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function Compressor(options, false_by_default) {
join_vars : !false_by_default,
keep_fargs : true,
keep_fnames : false,
keep_infinity : false,
loops : !false_by_default,
negate_iife : !false_by_default,
passes : 1,
Expand Down Expand Up @@ -3528,7 +3529,9 @@ merge(Compressor.prototype, {
});

OPT(AST_Infinity, function(self, compressor){
return make_node(AST_Binary, self, {
var retain = compressor.option("keep_infinity")
&& !compressor.find_parent(AST_Scope).find_variable("Infinity");
return retain ? self : make_node(AST_Binary, self, {
operator: "/",
left: make_node(AST_Number, self, {
value: 1
Expand All @@ -3540,15 +3543,15 @@ merge(Compressor.prototype, {
});

OPT(AST_NaN, function(self, compressor){
return make_node(AST_Binary, self, {
return compressor.find_parent(AST_Scope).find_variable("NaN") ? make_node(AST_Binary, self, {
operator: "/",
left: make_node(AST_Number, self, {
value: 0
}),
right: make_node(AST_Number, self, {
value: 0
})
});
}) : self;
});

var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
Expand Down
8 changes: 4 additions & 4 deletions test/compress/conditionals.js
Original file line number Diff line number Diff line change
Expand Up @@ -840,8 +840,8 @@ equality_conditionals_false: {
f(0, true, 0),
f(1, 2, 3),
f(1, null, 3),
f(0/0),
f(0/0, "foo");
f(NaN),
f(NaN, "foo");
}
expect_stdout: true
}
Expand Down Expand Up @@ -888,8 +888,8 @@ equality_conditionals_true: {
f(0, true, 0),
f(1, 2, 3),
f(1, null, 3),
f(0/0),
f(0/0, "foo");
f(NaN),
f(NaN, "foo");
}
expect_stdout: true
}
Expand Down
8 changes: 4 additions & 4 deletions test/compress/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ and: {
a = 7;

a = false;
a = 0/0;
a = NaN;
a = 0;
a = void 0;
a = null;
Expand All @@ -67,7 +67,7 @@ and: {
a = 6 << condition && -4.5;

a = condition && false;
a = console.log("b") && 0/0;
a = console.log("b") && NaN;
a = console.log("c") && 0;
a = 2 * condition && void 0;
a = condition + 3 && null;
Expand Down Expand Up @@ -149,7 +149,7 @@ or: {
a = 6 << condition || -4.5;

a = condition || false;
a = console.log("b") || 0/0;
a = console.log("b") || NaN;
a = console.log("c") || 0;
a = 2 * condition || void 0;
a = condition + 3 || null;
Expand Down Expand Up @@ -533,7 +533,7 @@ unsafe_array: {
[1, 2, 3, a][0] + 1,
2,
3,
0/0,
NaN,
"1,21",
5,
(void 0)[1] + 1
Expand Down
68 changes: 66 additions & 2 deletions test/compress/issue-1105.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: false,
}
input: {
var f = console.log;
Expand Down Expand Up @@ -224,10 +225,73 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
};
if (o) {
f(void 0, void 0);
f(0/0, 0/0);
f(NaN, NaN);
f(1/0, 1/0);
f(-1/0, -1/0);
f(0/0, 0/0);
f(NaN, NaN);
}
with (o) {
f(undefined, void 0);
f(NaN, 0/0);
f(Infinity, 1/0);
f(-Infinity, -1/0);
f(9 + undefined, 9 + void 0);
}
}
expect_stdout: true
}

assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
options = {
unused: true,
evaluate: true,
dead_code: true,
conditionals: true,
comparisons: true,
booleans: true,
hoist_funs: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: true,
}
input: {
var f = console.log;
var o = {
undefined : 3,
NaN : 4,
Infinity : 5,
};
if (o) {
f(undefined, void 0);
f(NaN, 0/0);
f(Infinity, 1/0);
f(-Infinity, -(1/0));
f(2 + 7 + undefined, 2 + 7 + void 0);
}
with (o) {
f(undefined, void 0);
f(NaN, 0/0);
f(Infinity, 1/0);
f(-Infinity, -(1/0));
f(2 + 7 + undefined, 2 + 7 + void 0);
}
}
expect: {
var f = console.log, o = {
undefined : 3,
NaN : 4,
Infinity : 5
};
if (o) {
f(void 0, void 0);
f(NaN, NaN);
f(Infinity, 1/0);
f(-Infinity, -1/0);
f(NaN, NaN);
}
with (o) {
f(undefined, void 0);
Expand Down
32 changes: 31 additions & 1 deletion test/compress/issue-597.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NaN_and_Infinity_must_have_parens: {
}
expect: {
(1/0).toString();
(0/0).toString();
NaN.toString();
}
}

Expand All @@ -24,6 +24,36 @@ NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
}
}

NaN_and_Infinity_must_have_parens_evaluate: {
options = {
evaluate: true,
}
input: {
(123456789 / 0).toString();
(+"foo").toString();
}
expect: {
(1/0).toString();
NaN.toString();
}
}

NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined_evaluate: {
options = {
evaluate: true,
}
input: {
var Infinity, NaN;
(123456789 / 0).toString();
(+"foo").toString();
}
expect: {
var Infinity, NaN;
(1/0).toString();
(0/0).toString();
}
}

beautify_off_1: {
options = {
evaluate: true,
Expand Down
2 changes: 1 addition & 1 deletion test/compress/numbers.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ unary_binary_parenthesis: {
});
}
expect: {
var v = [ 0, 1, 0/0, 1/0, null, void 0, true, false, "", "foo", /foo/ ];
var v = [ 0, 1, NaN, 1/0, null, void 0, true, false, "", "foo", /foo/ ];
v.forEach(function(x) {
v.forEach(function(y) {
console.log(
Expand Down
2 changes: 1 addition & 1 deletion test/compress/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ sub_properties: {
a[3.14] = 3;
a.if = 4;
a["foo bar"] = 5;
a[0/0] = 6;
a[NaN] = 6;
a[null] = 7;
a[void 0] = 8;
}
Expand Down

0 comments on commit e58fddc

Please sign in to comment.