enhance unsafe for Array (#3349)

This commit is contained in:
Alex Lam S.L
2019-03-20 06:37:51 +08:00
committed by GitHub
parent b9615f7a62
commit f2286c33f1
3 changed files with 158 additions and 9 deletions

View File

@@ -4003,17 +4003,17 @@ merge(Compressor.prototype, {
return this; return this;
}); });
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, first_in_statement);
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
if (lazy_op[this.operator]) { if (lazy_op[this.operator]) {
if (right === this.right) return this; if (right === this.right) return this;
var node = this.clone(); var node = this.clone();
node.right = right; node.right = right.drop_side_effect_free(compressor);
return node; return node;
} else { } else {
var left = this.left.drop_side_effect_free(compressor, first_in_statement); var left = this.left.drop_side_effect_free(compressor, first_in_statement);
if (!left) return this.right.drop_side_effect_free(compressor, first_in_statement); if (!left) return right;
return make_sequence(this, [ left, right ]); return make_sequence(this, [ left, right.drop_side_effect_free(compressor) ]);
} }
}); });
def(AST_Call, function(compressor, first_in_statement) { def(AST_Call, function(compressor, first_in_statement) {
@@ -4666,12 +4666,30 @@ merge(Compressor.prototype, {
if (compressor.option("unsafe")) { if (compressor.option("unsafe")) {
if (is_undeclared_ref(exp)) switch (exp.name) { if (is_undeclared_ref(exp)) switch (exp.name) {
case "Array": case "Array":
if (self.args.length != 1) { if (self.args.length == 1) {
return make_node(AST_Array, self, { var first = self.args[0];
elements: self.args if (first instanceof AST_Number) try {
}).optimize(compressor); var length = first.getValue();
if (length > 6) break;
var elements = Array(length);
for (var i = 0; i < length; i++) elements[i] = make_node(AST_Hole, self);
return make_node(AST_Array, self, {
elements: elements
});
} catch (ex) {
compressor.warn("Invalid array length: {length} [{file}:{line},{col}]", {
length: length,
file: self.start.file,
line: self.start.line,
col: self.start.col
});
break;
}
if (!first.is_boolean(compressor) && !first.is_string(compressor)) break;
} }
break; return make_node(AST_Array, self, {
elements: self.args
});
case "Object": case "Object":
if (self.args.length == 0) { if (self.args.length == 0) {
return make_node(AST_Object, self, { return make_node(AST_Object, self, {

View File

@@ -239,3 +239,113 @@ index_length: {
} }
expect_stdout: "1 2" expect_stdout: "1 2"
} }
constructor_bad: {
options = {
unsafe: true
}
input: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
new Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
new Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect_stdout: [
"PASS",
"PASS",
]
expect_warnings: [
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:13,12]",
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:17,16]",
]
}
constructor_good: {
options = {
unsafe: true
}
input: {
console.log(Array());
console.log(Array(0));
console.log(Array(1));
console.log(Array(6));
console.log(Array(7));
console.log(Array(1, 2));
console.log(Array(false));
console.log(Array("foo"));
console.log(Array(Array));
console.log(new Array());
console.log(new Array(0));
console.log(new Array(1));
console.log(new Array(6));
console.log(new Array(7));
console.log(new Array(1, 2));
console.log(new Array(false));
console.log(new Array("foo"));
console.log(new Array(Array));
}
expect: {
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
}
expect_stdout: true
expect_warnings: []
}

View File

@@ -6716,3 +6716,24 @@ issue_3297: {
} }
expect_stdout: "true" expect_stdout: "true"
} }
drop_side_effect_free: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 123;
"" + (a && (a.b = 0) || a);
console.log(a);
}
expect: {
var a = 123;
a.b = 0;
console.log(a);
}
expect_stdout: "123"
}