@@ -919,15 +919,21 @@ merge(Compressor.prototype, {
|
|||||||
type: typeof val
|
type: typeof val
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
function needs_unbinding(compressor, val) {
|
||||||
|
return val instanceof AST_PropAccess
|
||||||
|
|| compressor.has_directive("use strict")
|
||||||
|
&& is_undeclared_ref(val)
|
||||||
|
&& val.name == "eval";
|
||||||
|
}
|
||||||
|
|
||||||
// we shouldn't compress (1,func)(something) to
|
// we shouldn't compress (1,func)(something) to
|
||||||
// func(something) because that changes the meaning of
|
// func(something) because that changes the meaning of
|
||||||
// the func (becomes lexical instead of global).
|
// the func (becomes lexical instead of global).
|
||||||
function maintain_this_binding(parent, orig, val) {
|
function maintain_this_binding(compressor, parent, orig, val) {
|
||||||
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
|
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
|
||||||
|| parent.TYPE == "Call" && parent.expression === orig
|
|| parent.TYPE == "Call" && parent.expression === orig && needs_unbinding(compressor, val)) {
|
||||||
&& (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
|
|
||||||
return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]);
|
return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@@ -1098,7 +1104,7 @@ merge(Compressor.prototype, {
|
|||||||
var def = candidate.name.definition();
|
var def = candidate.name.definition();
|
||||||
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
||||||
def.replaced++;
|
def.replaced++;
|
||||||
return maintain_this_binding(parent, node, candidate.value);
|
return maintain_this_binding(compressor, parent, node, candidate.value);
|
||||||
}
|
}
|
||||||
return make_node(AST_Assign, candidate, {
|
return make_node(AST_Assign, candidate, {
|
||||||
operator: "=",
|
operator: "=",
|
||||||
@@ -3346,7 +3352,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
props.push(value);
|
props.push(value);
|
||||||
return maintain_this_binding(parent, node, make_sequence(node, props.map(function(prop) {
|
return maintain_this_binding(compressor, parent, node, make_sequence(node, props.map(function(prop) {
|
||||||
return prop.transform(tt);
|
return prop.transform(tt);
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
@@ -4477,7 +4483,7 @@ merge(Compressor.prototype, {
|
|||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
if (!(exp instanceof AST_Sequence)) return this;
|
if (!(exp instanceof AST_Sequence)) return this;
|
||||||
var tail = exp.tail_node();
|
var tail = exp.tail_node();
|
||||||
if (tail instanceof AST_PropAccess && !(this instanceof AST_New)) return this;
|
if (needs_unbinding(compressor, tail) && !(this instanceof AST_New)) return this;
|
||||||
var expressions = exp.expressions.slice(0, -1);
|
var expressions = exp.expressions.slice(0, -1);
|
||||||
var node = this.clone();
|
var node = this.clone();
|
||||||
node.expression = tail;
|
node.expression = tail;
|
||||||
@@ -5028,7 +5034,7 @@ merge(Compressor.prototype, {
|
|||||||
var end = expressions.length - 1;
|
var end = expressions.length - 1;
|
||||||
trim_right_for_undefined();
|
trim_right_for_undefined();
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);
|
self = maintain_this_binding(compressor, compressor.parent(), compressor.self(), expressions[0]);
|
||||||
if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
|
if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -5347,7 +5353,7 @@ merge(Compressor.prototype, {
|
|||||||
var ll = fuzzy_eval(self.left);
|
var ll = fuzzy_eval(self.left);
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
||||||
} else if (!(ll instanceof AST_Node)) {
|
} else if (!(ll instanceof AST_Node)) {
|
||||||
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
||||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||||
@@ -5386,7 +5392,7 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||||
} else if (!(ll instanceof AST_Node)) {
|
} else if (!(ll instanceof AST_Node)) {
|
||||||
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
||||||
}
|
}
|
||||||
var rr = self.right.evaluate(compressor);
|
var rr = self.right.evaluate(compressor);
|
||||||
if (!rr) {
|
if (!rr) {
|
||||||
|
|||||||
@@ -1,11 +1,31 @@
|
|||||||
remove_redundant_sequence_items: {
|
remove_sequence: {
|
||||||
options = { side_effects: true };
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
(0, 1, eval)();
|
(0, 1, eval)();
|
||||||
(0, 1, logThis)();
|
(0, 1, logThis)();
|
||||||
(0, 1, _decorators.logThis)();
|
(0, 1, _decorators.logThis)();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
eval();
|
||||||
|
logThis();
|
||||||
|
(0, _decorators.logThis)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_redundant_sequence_items: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(0, 1, eval)();
|
||||||
|
(0, 1, logThis)();
|
||||||
|
(0, 1, _decorators.logThis)();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
(0, eval)();
|
(0, eval)();
|
||||||
logThis();
|
logThis();
|
||||||
(0, _decorators.logThis)();
|
(0, _decorators.logThis)();
|
||||||
@@ -13,13 +33,17 @@ remove_redundant_sequence_items: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dont_remove_this_binding_sequence: {
|
dont_remove_this_binding_sequence: {
|
||||||
options = { side_effects: true };
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
|
"use strict";
|
||||||
(0, eval)();
|
(0, eval)();
|
||||||
(0, logThis)();
|
(0, logThis)();
|
||||||
(0, _decorators.logThis)();
|
(0, _decorators.logThis)();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
"use strict";
|
||||||
(0, eval)();
|
(0, eval)();
|
||||||
logThis();
|
logThis();
|
||||||
(0, _decorators.logThis)();
|
(0, _decorators.logThis)();
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ this_binding_conditionals: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
};
|
}
|
||||||
input: {
|
input: {
|
||||||
|
"use strict";
|
||||||
(1 && a)();
|
(1 && a)();
|
||||||
(0 || a)();
|
(0 || a)();
|
||||||
(0 || 1 && a)();
|
(0 || 1 && a)();
|
||||||
@@ -26,6 +27,7 @@ this_binding_conditionals: {
|
|||||||
(1 ? eval : 0)();
|
(1 ? eval : 0)();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
"use strict";
|
||||||
a();
|
a();
|
||||||
a();
|
a();
|
||||||
a();
|
a();
|
||||||
@@ -53,13 +55,15 @@ this_binding_collapse_vars: {
|
|||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
};
|
}
|
||||||
input: {
|
input: {
|
||||||
|
"use strict";
|
||||||
var c = a; c();
|
var c = a; c();
|
||||||
var d = a.b; d();
|
var d = a.b; d();
|
||||||
var e = eval; e();
|
var e = eval; e();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
"use strict";
|
||||||
a();
|
a();
|
||||||
(0, a.b)();
|
(0, a.b)();
|
||||||
(0, eval)();
|
(0, eval)();
|
||||||
@@ -69,31 +73,88 @@ this_binding_collapse_vars: {
|
|||||||
this_binding_side_effects: {
|
this_binding_side_effects: {
|
||||||
options = {
|
options = {
|
||||||
side_effects : true
|
side_effects : true
|
||||||
};
|
}
|
||||||
input: {
|
input: {
|
||||||
(function (foo) {
|
(function(foo) {
|
||||||
(0, foo)();
|
(0, foo)();
|
||||||
(0, foo.bar)();
|
(0, foo.bar)();
|
||||||
(0, eval)('console.log(foo);');
|
(0, eval)("console.log(foo);");
|
||||||
}());
|
}());
|
||||||
(function (foo) {
|
(function(foo) {
|
||||||
|
"use strict";
|
||||||
|
(0, foo)();
|
||||||
|
(0, foo.bar)();
|
||||||
|
(0, eval)("console.log(foo);");
|
||||||
|
}());
|
||||||
|
(function(foo) {
|
||||||
var eval = console;
|
var eval = console;
|
||||||
(0, foo)();
|
(0, foo)();
|
||||||
(0, foo.bar)();
|
(0, foo.bar)();
|
||||||
(0, eval)('console.log(foo);');
|
(0, eval)("console.log(foo);");
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function (foo) {
|
(function(foo) {
|
||||||
foo();
|
foo();
|
||||||
(0, foo.bar)();
|
(0, foo.bar)();
|
||||||
(0, eval)('console.log(foo);');
|
eval("console.log(foo);");
|
||||||
}());
|
}());
|
||||||
(function (foo) {
|
(function(foo) {
|
||||||
|
"use strict";
|
||||||
|
foo();
|
||||||
|
(0, foo.bar)();
|
||||||
|
(0, eval)("console.log(foo);");
|
||||||
|
}());
|
||||||
|
(function(foo) {
|
||||||
var eval = console;
|
var eval = console;
|
||||||
foo();
|
foo();
|
||||||
(0, foo.bar)();
|
(0, foo.bar)();
|
||||||
(0, eval)('console.log(foo);');
|
eval("console.log(foo);");
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this_binding_sequences: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
return eval("this");
|
||||||
|
}());
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use strict";
|
||||||
|
return eval("this");
|
||||||
|
}());
|
||||||
|
console.log(typeof function() {
|
||||||
|
return (0, eval)("this");
|
||||||
|
}());
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use strict";
|
||||||
|
return (0, eval)("this");
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
return eval("this");
|
||||||
|
}()),
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use strict";
|
||||||
|
return eval("this");
|
||||||
|
}()),
|
||||||
|
console.log(typeof function() {
|
||||||
|
return eval("this");
|
||||||
|
}()),
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use strict";
|
||||||
|
return (0, eval)("this");
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"undefined",
|
||||||
|
"object",
|
||||||
|
"object",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user