reduce this within functions (#2421)

- only replace same-scope usages
- augment `test/ufuzz.js` to test for `this`


fixes #2420
This commit is contained in:
Alex Lam S.L
2017-11-04 00:31:37 +08:00
committed by GitHub
parent a48f87abf2
commit c8b6f4733d
3 changed files with 129 additions and 31 deletions

View File

@@ -285,7 +285,7 @@ merge(Compressor.prototype, {
self.transform(tt);
});
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor) {
AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
var reduce_vars = compressor.option("reduce_vars");
var unused = compressor.option("unused");
// Stack of look-up tables to keep track of whether a `SymbolDef` has been
@@ -564,7 +564,10 @@ merge(Compressor.prototype, {
}
function is_immutable(value) {
return value && (value.is_constant() || value instanceof AST_Lambda);
if (!value) return false;
return value.is_constant()
|| value instanceof AST_Lambda
|| value instanceof AST_This;
}
function read_property(obj, key) {
@@ -4211,11 +4214,22 @@ merge(Compressor.prototype, {
var value = fixed.optimize(compressor);
return value === fixed ? fixed.clone(true) : value;
}
if (compressor.option("evaluate") && fixed) {
if (d.should_replace === undefined) {
var init = fixed.evaluate(compressor);
if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
init = make_node_from_constant(init, fixed);
if (fixed && d.should_replace === undefined) {
var init;
if (fixed instanceof AST_This) {
if (!(d.orig[0] instanceof AST_SymbolFunarg)
&& all(d.references, function(ref) {
return d.scope === ref.scope;
})) {
init = fixed;
}
} else {
var ev = fixed.evaluate(compressor);
if (ev !== fixed && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))) {
init = make_node_from_constant(ev, fixed);
}
}
if (init) {
var value_length = init.optimize(compressor).print_to_string().length;
var fn;
if (has_symbol_ref(fixed)) {
@@ -4244,7 +4258,6 @@ merge(Compressor.prototype, {
return d.should_replace();
}
}
}
return self;
function has_symbol_ref(value) {

View File

@@ -3295,3 +3295,87 @@ escaped_prop: {
}
expect_stdout: "2"
}
issue_2420_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function run() {
var self = this;
if (self.count++)
self.foo();
else
self.bar();
}
var o = {
count: 0,
foo: function() { console.log("foo"); },
bar: function() { console.log("bar"); },
};
run.call(o);
run.call(o);
}
expect: {
function run() {
if (this.count++)
this.foo();
else
this.bar();
}
var o = {
count: 0,
foo: function() { console.log("foo"); },
bar: function() { console.log("bar"); },
};
run.call(o);
run.call(o);
}
expect_stdout: [
"bar",
"foo",
]
}
issue_2420_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function f() {
var that = this;
if (that.bar)
that.foo();
else
!function(that, self) {
console.log(this === that, self === this, that === self);
}(that, this);
}
f.call({
bar: 1,
foo: function() { console.log("foo", this.bar); },
});
f.call({});
}
expect: {
function f() {
if (this.bar)
this.foo();
else
!function(that, self) {
console.log(this === that, self === this, that === self);
}(this, this);
}
f.call({
bar: 1,
foo: function() { console.log("foo", this.bar); },
});
f.call({});
}
expect_stdout: [
"foo 1",
"false false true",
]
}

View File

@@ -162,6 +162,7 @@ var VALUES = [
'"object"',
'"number"',
'"function"',
'this',
];
var BINARY_OPS_NO_COMMA = [