inlining of static methods & constants (#2211)
- guard by `unsafe` - support `Array`, `Math`, `Number`, `Object` & `String` fixes #2207
This commit is contained in:
129
lib/compress.js
129
lib/compress.js
@@ -1718,6 +1718,40 @@ merge(Compressor.prototype, {
|
||||
this._eval = fixed._eval;
|
||||
return value;
|
||||
});
|
||||
var global_objs = {
|
||||
Array: Array,
|
||||
Boolean: Boolean,
|
||||
Math: Math,
|
||||
Number: Number,
|
||||
RegExp: RegExp,
|
||||
Object: Object,
|
||||
String: String,
|
||||
};
|
||||
function convert_to_predicate(obj) {
|
||||
for (var key in obj) {
|
||||
obj[key] = makePredicate(obj[key]);
|
||||
}
|
||||
}
|
||||
var static_values = {
|
||||
Math: [
|
||||
"E",
|
||||
"LN10",
|
||||
"LN2",
|
||||
"LOG2E",
|
||||
"LOG10E",
|
||||
"PI",
|
||||
"SQRT1_2",
|
||||
"SQRT2",
|
||||
],
|
||||
Number: [
|
||||
"MAX_VALUE",
|
||||
"MIN_VALUE",
|
||||
"NaN",
|
||||
"NEGATIVE_INFINITY",
|
||||
"POSITIVE_INFINITY",
|
||||
],
|
||||
};
|
||||
convert_to_predicate(static_values);
|
||||
def(AST_PropAccess, function(compressor){
|
||||
if (compressor.option("unsafe")) {
|
||||
var key = this.property;
|
||||
@@ -1725,11 +1759,16 @@ merge(Compressor.prototype, {
|
||||
key = ev(key, compressor);
|
||||
if (key === this.property) return this;
|
||||
}
|
||||
var val = ev(this.expression, compressor);
|
||||
if (val === this.expression) return this;
|
||||
if (val && HOP(val, key)) {
|
||||
return val[key];
|
||||
var exp = this.expression;
|
||||
var val;
|
||||
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
|
||||
if (!(static_values[exp.name] || return_false)(key)) return this;
|
||||
val = global_objs[exp.name];
|
||||
} else {
|
||||
val = ev(exp, compressor);
|
||||
if (!val || val === exp || !HOP(val, key)) return this;
|
||||
}
|
||||
return val[key];
|
||||
}
|
||||
return this;
|
||||
});
|
||||
@@ -1739,22 +1778,22 @@ merge(Compressor.prototype, {
|
||||
"valueOf",
|
||||
];
|
||||
var native_fns = {
|
||||
Array: makePredicate([
|
||||
Array: [
|
||||
"indexOf",
|
||||
"join",
|
||||
"lastIndexOf",
|
||||
"slice",
|
||||
].concat(object_fns)),
|
||||
Boolean: makePredicate(object_fns),
|
||||
Number: makePredicate([
|
||||
].concat(object_fns),
|
||||
Boolean: object_fns,
|
||||
Number: [
|
||||
"toExponential",
|
||||
"toFixed",
|
||||
"toPrecision",
|
||||
].concat(object_fns)),
|
||||
RegExp: makePredicate([
|
||||
].concat(object_fns),
|
||||
RegExp: [
|
||||
"test",
|
||||
].concat(object_fns)),
|
||||
String: makePredicate([
|
||||
].concat(object_fns),
|
||||
String: [
|
||||
"charAt",
|
||||
"charCodeAt",
|
||||
"concat",
|
||||
@@ -1769,8 +1808,45 @@ merge(Compressor.prototype, {
|
||||
"substr",
|
||||
"substring",
|
||||
"trim",
|
||||
].concat(object_fns)),
|
||||
].concat(object_fns),
|
||||
};
|
||||
convert_to_predicate(native_fns);
|
||||
var static_fns = {
|
||||
Array: [
|
||||
"isArray",
|
||||
],
|
||||
Math: [
|
||||
"abs",
|
||||
"acos",
|
||||
"asin",
|
||||
"atan",
|
||||
"ceil",
|
||||
"cos",
|
||||
"exp",
|
||||
"floor",
|
||||
"log",
|
||||
"round",
|
||||
"sin",
|
||||
"sqrt",
|
||||
"tan",
|
||||
"atan2",
|
||||
"pow",
|
||||
"max",
|
||||
"min"
|
||||
],
|
||||
Number: [
|
||||
"isFinite",
|
||||
"isNaN",
|
||||
],
|
||||
Object: [
|
||||
"keys",
|
||||
"getOwnPropertyNames",
|
||||
],
|
||||
String: [
|
||||
"fromCharCode",
|
||||
],
|
||||
};
|
||||
convert_to_predicate(static_fns);
|
||||
def(AST_Call, function(compressor){
|
||||
var exp = this.expression;
|
||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||
@@ -1779,18 +1855,23 @@ merge(Compressor.prototype, {
|
||||
key = ev(key, compressor);
|
||||
if (key === exp.property) return this;
|
||||
}
|
||||
var val = ev(exp.expression, compressor);
|
||||
if (val === exp.expression) return this;
|
||||
if ((val && native_fns[val.constructor.name] || return_false)(key)) {
|
||||
var args = [];
|
||||
for (var i = 0, len = this.args.length; i < len; i++) {
|
||||
var arg = this.args[i];
|
||||
var value = ev(arg, compressor);
|
||||
if (arg === value) return this;
|
||||
args.push(value);
|
||||
}
|
||||
return val[key].apply(val, args);
|
||||
var val;
|
||||
var e = exp.expression;
|
||||
if (e instanceof AST_SymbolRef && e.undeclared()) {
|
||||
if (!(static_fns[e.name] || return_false)(key)) return this;
|
||||
val = global_objs[e.name];
|
||||
} else {
|
||||
val = ev(e, compressor);
|
||||
if (val === e || !(val && native_fns[val.constructor.name] || return_false)(key)) return this;
|
||||
}
|
||||
var args = [];
|
||||
for (var i = 0, len = this.args.length; i < len; i++) {
|
||||
var arg = this.args[i];
|
||||
var value = ev(arg, compressor);
|
||||
if (arg === value) return this;
|
||||
args.push(value);
|
||||
}
|
||||
return val[key].apply(val, args);
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
@@ -1085,3 +1085,75 @@ string_charCodeAt: {
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_2207_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(String.fromCharCode(65));
|
||||
console.log(Math.max(3, 6, 2, 7, 3, 4));
|
||||
console.log(Math.cos(1.2345));
|
||||
console.log(Math.cos(1.2345) - Math.sin(4.321));
|
||||
console.log(Math.pow(Math.PI, Math.E - Math.LN10));
|
||||
}
|
||||
expect: {
|
||||
console.log("A");
|
||||
console.log(7);
|
||||
console.log(Math.cos(1.2345));
|
||||
console.log(1.2543732512566947);
|
||||
console.log(1.6093984514472044);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2207_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Math.E);
|
||||
console.log(Math.LN10);
|
||||
console.log(Math.LN2);
|
||||
console.log(Math.LOG2E);
|
||||
console.log(Math.LOG10E);
|
||||
console.log(Math.PI);
|
||||
console.log(Math.SQRT1_2);
|
||||
console.log(Math.SQRT2);
|
||||
}
|
||||
expect: {
|
||||
console.log(Math.E);
|
||||
console.log(Math.LN10);
|
||||
console.log(Math.LN2);
|
||||
console.log(Math.LOG2E);
|
||||
console.log(Math.LOG10E);
|
||||
console.log(Math.PI);
|
||||
console.log(Math.SQRT1_2);
|
||||
console.log(Math.SQRT2);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2207_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Number.MAX_VALUE);
|
||||
console.log(Number.MIN_VALUE);
|
||||
console.log(Number.NaN);
|
||||
console.log(Number.NEGATIVE_INFINITY);
|
||||
console.log(Number.POSITIVE_INFINITY);
|
||||
}
|
||||
expect: {
|
||||
console.log(Number.MAX_VALUE);
|
||||
console.log(5e-324);
|
||||
console.log(NaN);
|
||||
console.log(-1/0);
|
||||
console.log(1/0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user