aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js48
-rw-r--r--test/compress/collapse_vars.js23
-rw-r--r--test/compress/drop-unused.js66
-rw-r--r--test/mocha/release.js2
4 files changed, 124 insertions, 15 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 63830d09..08248309 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -2004,7 +2004,7 @@ merge(Compressor.prototype, {
if (this.properties[i].value instanceof AST_Accessor) return true;
return false;
});
- def(AST_Function, return_false);
+ def(AST_Lambda, return_false);
def(AST_UnaryPostfix, return_false);
def(AST_UnaryPrefix, function() {
return this.operator == "void";
@@ -2023,8 +2023,9 @@ merge(Compressor.prototype, {
})
def(AST_Dot, function(compressor) {
if (!is_strict(compressor)) return false;
- if (this.expression instanceof AST_Function && this.property == "prototype") return false;
- return true;
+ var exp = this.expression;
+ if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();
+ return !(exp instanceof AST_Lambda && this.property == "prototype");
});
def(AST_Sequence, function(compressor) {
return this.tail_node()._dot_throw(compressor);
@@ -3009,11 +3010,18 @@ merge(Compressor.prototype, {
if (self.uses_eval || self.uses_with) return;
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
- var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node) {
+ var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node, props) {
+ var sym;
if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) {
- return node.left;
+ sym = node.left;
+ } else if (node instanceof AST_Unary && node.write_only) {
+ sym = node.expression;
}
- if (node instanceof AST_Unary && node.write_only) return node.expression;
+ while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) {
+ if (sym instanceof AST_Sub) props.unshift(sym.property);
+ sym = sym.expression;
+ }
+ return sym;
};
var in_use = [];
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
@@ -3089,17 +3097,26 @@ merge(Compressor.prototype, {
function before(node, descend, in_list) {
var parent = tt.parent();
if (drop_vars) {
- var sym = assign_as_unused(node);
+ var props = [], sym = assign_as_unused(node, props);
if (sym instanceof AST_SymbolRef) {
var def = sym.definition();
var in_use = def.id in in_use_ids;
+ var value = null;
if (node instanceof AST_Assign) {
- if (!in_use || def.id in fixed_ids && fixed_ids[def.id] !== node) {
- return maintain_this_binding(parent, node, node.right.transform(tt));
+ if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) {
+ value = node.right;
}
- } else if (!in_use) return make_node(AST_Number, node, {
- value: 0
- });
+ } else if (!in_use) {
+ value = make_node(AST_Number, node, {
+ value: 0
+ });
+ }
+ if (value) {
+ props.push(value);
+ return maintain_this_binding(parent, node, make_sequence(node, props.map(function(prop) {
+ return prop.transform(tt);
+ })));
+ }
}
}
if (scope !== self) return;
@@ -3277,12 +3294,15 @@ merge(Compressor.prototype, {
self.transform(tt);
function scan_ref_scoped(node, descend) {
- var node_def, sym = assign_as_unused(node);
+ var node_def, props = [], sym = assign_as_unused(node, props);
if (sym instanceof AST_SymbolRef
&& self.variables.get(sym.name) === (node_def = sym.definition())) {
+ props.forEach(function(prop) {
+ prop.walk(tw);
+ });
if (node instanceof AST_Assign) {
node.right.walk(tw);
- if (!node_def.chained && node.left.fixed_value() === node.right) {
+ if (node.left === sym && !node_def.chained && sym.fixed_value() === node.right) {
fixed_ids[node_def.id] = node;
}
}
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index bcb9cb91..d0a5df85 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -4619,3 +4619,26 @@ issue_2914_2: {
}
expect_stdout: "0"
}
+
+issue_805: {
+ options = {
+ collapse_vars: true,
+ pure_getters: "strict",
+ reduce_vars: true,
+ }
+ input: {
+ function f() {
+ function Foo(){}
+ Foo.prototype = {};
+ Foo.prototype.bar = 42;
+ return Foo;
+ }
+ }
+ expect: {
+ function f() {
+ function Foo(){}
+ (Foo.prototype = {}).bar = 42;
+ return Foo;
+ }
+ }
+}
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index e99d7ab1..ee8e6c0c 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -1719,3 +1719,69 @@ issue_2846: {
}
expect_stdout: "0"
}
+
+issue_805_1: {
+ options = {
+ inline: true,
+ passes: 2,
+ pure_getters: "strict",
+ reduce_vars: true,
+ sequences: true,
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ (function(a) {
+ var unused = function() {};
+ unused.prototype[a()] = 42;
+ (unused.prototype.bar = function() {
+ console.log("bar");
+ })();
+ return unused;
+ })(function() {
+ console.log("foo");
+ return "foo";
+ });
+ }
+ expect: {
+ console.log("foo"),
+ console.log("bar");
+ }
+ expect_stdout: [
+ "foo",
+ "bar",
+ ]
+}
+
+issue_805_2: {
+ options = {
+ inline: true,
+ passes: 2,
+ pure_getters: "strict",
+ reduce_vars: true,
+ sequences: true,
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ (function(a) {
+ function unused() {}
+ unused.prototype[a()] = 42;
+ (unused.prototype.bar = function() {
+ console.log("bar");
+ })();
+ return unused;
+ })(function() {
+ console.log("foo");
+ return "foo";
+ });
+ }
+ expect: {
+ console.log("foo"),
+ console.log("bar");
+ }
+ expect_stdout: [
+ "foo",
+ "bar",
+ ]
+}
diff --git a/test/mocha/release.js b/test/mocha/release.js
index 063d0fc7..656ade8d 100644
--- a/test/mocha/release.js
+++ b/test/mocha/release.js
@@ -38,7 +38,7 @@ describe("test/jetstream.js", function() {
this.timeout(20 * 60 * 1000);
[
"-mc",
- "-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
+ "-mc keep_fargs=false,passes=3,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
].forEach(function(options) {
it("Should pass with options " + options, function(done) {
var args = options.split(/ /);