inline property access of object literal (#2209)

- only if property value is side-effect-free
- guard by `unsafe`

fixes #2208
This commit is contained in:
Alex Lam S.L
2017-07-06 21:51:58 +08:00
committed by GitHub
parent 9306da3c58
commit 4b6ca5e742
4 changed files with 195 additions and 40 deletions

View File

@@ -4307,6 +4307,17 @@ merge(Compressor.prototype, {
return self;
});
AST_Lambda.DEFMETHOD("contains_this", function() {
var result;
var self = this;
self.walk(new TreeWalker(function(node) {
if (result) return true;
if (node instanceof AST_This) return result = true;
if (node !== self && node instanceof AST_Scope) return true;
}));
return result;
});
OPT(AST_Dot, function(self, compressor){
var def = self.resolve_defines(compressor);
if (def) {
@@ -4321,6 +4332,20 @@ merge(Compressor.prototype, {
})
}).optimize(compressor);
}
if (compressor.option("unsafe") && self.expression instanceof AST_Object) {
var values = self.expression.properties;
for (var i = values.length; --i >= 0;) {
if (values[i].key === prop) {
var value = values[i].value;
if (value instanceof AST_Function ? !value.contains_this() : !value.has_side_effects(compressor)) {
var obj = self.expression.clone();
obj.properties = obj.properties.slice();
obj.properties.splice(i, 1);
return make_sequence(self, [ obj, value ]).optimize(compressor);
}
}
}
}
if (compressor.option("unsafe_proto")
&& self.expression instanceof AST_Dot
&& self.expression.property == "prototype") {

View File

@@ -250,22 +250,26 @@ unsafe_constant: {
unsafe_object: {
options = {
evaluate : true,
unsafe : true
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var o = { a: 1 };
console.log(
({a:1}) + 1,
({a:1}).a + 1,
({a:1}).b + 1,
({a:1}).a.b + 1
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
);
}
expect: {
var o = { a: 1 };
console.log(
({a:1}) + 1,
o + 1,
2,
({a:1}).b + 1,
o.b + 1,
1..b + 1
);
}
@@ -274,22 +278,26 @@ unsafe_object: {
unsafe_object_nested: {
options = {
evaluate : true,
unsafe : true
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var o = { a: { b: 1 } };
console.log(
({a:{b:1}}) + 1,
({a:{b:1}}).a + 1,
({a:{b:1}}).b + 1,
({a:{b:1}}).a.b + 1
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
);
}
expect: {
var o = { a: { b: 1 } };
console.log(
({a:{b:1}}) + 1,
({a:{b:1}}).a + 1,
({a:{b:1}}).b + 1,
o + 1,
o.a + 1,
o.b + 1,
2
);
}
@@ -298,21 +306,25 @@ unsafe_object_nested: {
unsafe_object_complex: {
options = {
evaluate : true,
unsafe : true
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var o = { a: { b: 1 }, b: 1 };
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
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
);
}
expect: {
var o = { a: { b: 1 }, b: 1 };
console.log(
({a:{b:1},b:1}) + 1,
({a:{b:1},b:1}).a + 1,
o + 1,
o.a + 1,
2,
2
);
@@ -322,22 +334,26 @@ unsafe_object_complex: {
unsafe_object_repeated: {
options = {
evaluate : true,
unsafe : true
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var o = { a: { b: 1 }, a: 1 };
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
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
);
}
expect: {
var o = { a: { b: 1 }, a: 1 };
console.log(
({a:{b:1},a:1}) + 1,
o + 1,
2,
({a:{b:1},a:1}).b + 1,
o.b + 1,
1..b + 1
);
}
@@ -386,9 +402,9 @@ unsafe_function: {
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
({b:function(){}}, {b:1}) + 1,
({a:{b:1}}, function(){}) + 1,
({b:function(){}}, {b:1}).b + 1
);
}
expect_stdout: true
@@ -636,8 +652,8 @@ unsafe_prototype_function: {
var d = ({toString: 0}) + "";
var e = (({valueOf: 0}) + "")[2];
var f = (({toString: 0}) + "")[2];
var g = ({valueOf: 0}).valueOf();
var h = "" + ({toString: 0});
var g = ({}, 0)();
var h = ({}, 0)();
}
}

View File

@@ -37,6 +37,7 @@ object: {
VALUE: 42,
},
},
side_effects: true,
unsafe: true,
}
input: {
@@ -140,9 +141,9 @@ mixed: {
console.log(CONFIG);
}
expect_warnings: [
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
]
}

View File

@@ -657,3 +657,116 @@ accessor_this: {
expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'
expect_stdout: "1 2 2"
}
issue_2208_1: {
options = {
inline: true,
side_effects: true,
unsafe: true,
}
input: {
console.log({
p: function() {
return 42;
}
}.p());
}
expect: {
console.log(42);
}
expect_stdout: "42"
}
issue_2208_2: {
options = {
inline: true,
side_effects: true,
unsafe: true,
}
input: {
console.log({
a: 42,
p: function() {
return this.a;
}
}.p());
}
expect: {
console.log({
a: 42,
p: function() {
return this.a;
}
}.p());
}
expect_stdout: "42"
}
issue_2208_3: {
options = {
inline: true,
side_effects: true,
unsafe: true,
}
input: {
a = 42;
console.log({
p: function() {
return function() {
return this.a;
}();
}
}.p());
}
expect: {
a = 42;
console.log(function() {
return this.a;
}());
}
expect_stdout: "42"
}
issue_2208_4: {
options = {
inline: true,
side_effects: true,
unsafe: true,
}
input: {
function foo() {}
console.log({
a: foo(),
p: function() {
return 42;
}
}.p());
}
expect: {
function foo() {}
console.log((foo(), function() {
return 42;
})());
}
expect_stdout: "42"
}
issue_2208_5: {
options = {
inline: true,
side_effects: true,
unsafe: true,
}
input: {
console.log({
p: "FAIL",
p: function() {
return 42;
}
}.p());
}
expect: {
console.log(42);
}
expect_stdout: "42"
}