aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-01-11 17:08:21 +0800
committerGitHub <noreply@github.com>2018-01-11 17:08:21 +0800
commitf1e1bb419ab642763c43dec95e07165f477a43be (patch)
tree6d95a87f66f386a675bf9024a8f3c69fbe591073
parent6a0af85c8bf8673498e89ad7226d6e8cc80b2c15 (diff)
downloadtracifyjs-f1e1bb419ab642763c43dec95e07165f477a43be.tar.gz
tracifyjs-f1e1bb419ab642763c43dec95e07165f477a43be.zip
join object assignments (#2763)
-rw-r--r--lib/compress.js48
-rw-r--r--test/compress/properties.js62
2 files changed, 109 insertions, 1 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 3e7269d0..b093832c 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -869,6 +869,7 @@ merge(Compressor.prototype, {
}
function tighten_body(statements, compressor) {
+ var scope = compressor.find_parent(AST_Scope);
var CHANGED, max_iter = 10;
do {
CHANGED = false;
@@ -900,7 +901,6 @@ merge(Compressor.prototype, {
// Will not attempt to collapse assignments into or past code blocks
// which are not sequentially executed, e.g. loops and conditionals.
function collapse(statements, compressor) {
- var scope = compressor.find_parent(AST_Scope);
if (scope.uses_eval || scope.uses_with) return statements;
var args;
var candidates = [];
@@ -1696,6 +1696,41 @@ merge(Compressor.prototype, {
statements.length = n;
}
+ function join_object_assignments(defn, body) {
+ if (!(defn instanceof AST_Definitions)) return;
+ var exprs;
+ if (body instanceof AST_Assign) {
+ exprs = [ body ];
+ } else if (body instanceof AST_Sequence) {
+ exprs = body.expressions.slice();
+ }
+ if (!exprs) return;
+ do {
+ var node = exprs[0];
+ if (!(node instanceof AST_Assign)) break;
+ if (!(node.left instanceof AST_PropAccess)) break;
+ var sym = node.left.expression;
+ if (!(sym instanceof AST_SymbolRef)) break;
+ var def = find_if(function(def) {
+ return def.name.name == sym.name
+ && def.value instanceof AST_Object;
+ }, defn.definitions);
+ if (!def) break;
+ if (!node.right.is_constant_expression(scope)) break;
+ var prop = node.left.property;
+ if (prop instanceof AST_Node) {
+ prop = prop.evaluate(compressor);
+ }
+ if (prop instanceof AST_Node) break;
+ def.value.properties.push(make_node(AST_ObjectKeyVal, node, {
+ key: prop,
+ value: node.right
+ }));
+ exprs.shift();
+ } while (exprs.length);
+ return exprs;
+ }
+
function join_consecutive_vars(statements, compressor) {
var defs;
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
@@ -1728,6 +1763,17 @@ merge(Compressor.prototype, {
} else {
statements[++j] = stat;
}
+ } else if (stat instanceof AST_SimpleStatement) {
+ var exprs = join_object_assignments(prev, stat.body);
+ if (exprs) {
+ if (exprs.length > 0) {
+ stat.body = make_sequence(stat.body, exprs);
+ statements[++j] = stat;
+ }
+ CHANGED = true;
+ } else {
+ statements[++j] = stat;
+ }
} else {
statements[++j] = stat;
}
diff --git a/test/compress/properties.js b/test/compress/properties.js
index b2ce5f61..d70eb85a 100644
--- a/test/compress/properties.js
+++ b/test/compress/properties.js
@@ -1100,3 +1100,65 @@ const_prop_assign_pure: {
x();
}
}
+
+join_object_assignments_1: {
+ options = {
+ evaluate: true,
+ join_vars: true,
+ }
+ input: {
+ console.log(function() {
+ var x = {
+ a: 1,
+ c: (console.log("c"), "C"),
+ };
+ x.b = 2;
+ x[3] = function() {
+ console.log(x);
+ },
+ x["a"] = /foo/,
+ x.bar = x;
+ return x;
+ }());
+ }
+ expect: {
+ console.log(function() {
+ var x = {
+ a: 1,
+ c: (console.log("c"), "C"),
+ b: 2,
+ 3: function() {
+ console.log(x);
+ },
+ a: /foo/,
+ };
+ x.bar = x;
+ return x;
+ }());
+ }
+ expect_stdout: true
+}
+
+join_object_assignments_2: {
+ options = {
+ evaluate: true,
+ hoist_props: true,
+ join_vars: true,
+ passes: 3,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var o = {
+ foo: 1,
+ };
+ o.bar = 2;
+ o.baz = 3;
+ console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
+ }
+ expect: {
+ console.log(1, 4, 6);
+ }
+ expect_stdout: "1 4 6"
+}