fix corner case in unsafe (#3646)
This commit is contained in:
@@ -2872,9 +2872,11 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function convert_to_predicate(obj) {
|
||||
var map = Object.create(null);
|
||||
Object.keys(obj).forEach(function(key) {
|
||||
obj[key] = makePredicate(obj[key]);
|
||||
map[key] = makePredicate(obj[key]);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
AST_Lambda.DEFMETHOD("first_statement", function() {
|
||||
@@ -2897,7 +2899,7 @@ merge(Compressor.prototype, {
|
||||
"toString",
|
||||
"valueOf",
|
||||
];
|
||||
var native_fns = {
|
||||
var native_fns = convert_to_predicate({
|
||||
Array: [
|
||||
"indexOf",
|
||||
"join",
|
||||
@@ -2933,9 +2935,8 @@ merge(Compressor.prototype, {
|
||||
"toUpperCase",
|
||||
"trim",
|
||||
].concat(object_fns),
|
||||
};
|
||||
convert_to_predicate(native_fns);
|
||||
var static_fns = {
|
||||
});
|
||||
var static_fns = convert_to_predicate({
|
||||
Array: [
|
||||
"isArray",
|
||||
],
|
||||
@@ -2975,8 +2976,7 @@ merge(Compressor.prototype, {
|
||||
String: [
|
||||
"fromCharCode",
|
||||
],
|
||||
};
|
||||
convert_to_predicate(static_fns);
|
||||
});
|
||||
|
||||
// methods to evaluate a constant expression
|
||||
(function(def) {
|
||||
@@ -3199,7 +3199,7 @@ merge(Compressor.prototype, {
|
||||
Object: Object,
|
||||
String: String,
|
||||
};
|
||||
var static_values = {
|
||||
var static_values = convert_to_predicate({
|
||||
Math: [
|
||||
"E",
|
||||
"LN10",
|
||||
@@ -3217,8 +3217,7 @@ merge(Compressor.prototype, {
|
||||
"NEGATIVE_INFINITY",
|
||||
"POSITIVE_INFINITY",
|
||||
],
|
||||
};
|
||||
convert_to_predicate(static_values);
|
||||
});
|
||||
var regexp_props = makePredicate("global ignoreCase multiline source");
|
||||
def(AST_PropAccess, function(compressor, cached, depth) {
|
||||
if (compressor.option("unsafe")) {
|
||||
|
||||
@@ -141,207 +141,6 @@ try_catch_finally: {
|
||||
]
|
||||
}
|
||||
|
||||
accessor: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
get a() {},
|
||||
set a(v){
|
||||
this.b = 2;
|
||||
},
|
||||
b: 1
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
collapse_vars_assignment: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -863,23 +662,6 @@ issue_2749: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_builtin: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(!w).constructor(x);
|
||||
Math.abs(y);
|
||||
[ 1, 2, z ].valueOf();
|
||||
}
|
||||
expect: {
|
||||
w, x;
|
||||
y;
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2860_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
@@ -941,24 +723,6 @@ issue_2929: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_string_replace: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3402: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
|
||||
@@ -699,18 +699,6 @@ iife: {
|
||||
}
|
||||
}
|
||||
|
||||
drop_value: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||
}
|
||||
expect: {
|
||||
foo(), bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1539: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
|
||||
277
test/compress/side_effects.js
Normal file
277
test/compress/side_effects.js
Normal file
@@ -0,0 +1,277 @@
|
||||
accessor: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
get a() {},
|
||||
set a(v){
|
||||
this.b = 2;
|
||||
},
|
||||
b: 1
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
unsafe_builtin_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(!w).constructor(x);
|
||||
Math.abs(y);
|
||||
[ 1, 2, z ].valueOf();
|
||||
}
|
||||
expect: {
|
||||
w, x;
|
||||
y;
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_builtin_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
constructor.call(o, 42);
|
||||
__defineGetter__.call(o, "foo", function() {
|
||||
return o.p;
|
||||
});
|
||||
__defineSetter__.call(o, void 0, function(a) {
|
||||
o.p = a;
|
||||
});
|
||||
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
constructor.call(o, 42);
|
||||
__defineGetter__.call(o, "foo", function() {
|
||||
return o.p;
|
||||
});
|
||||
__defineSetter__.call(o, void 0, function(a) {
|
||||
o.p = a;
|
||||
});
|
||||
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||
}
|
||||
expect_stdout: "object PASS PASS"
|
||||
}
|
||||
|
||||
unsafe_string_replace: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
drop_value: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||
}
|
||||
expect: {
|
||||
foo(), bar();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user