aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-04-11 02:48:15 +0800
committerGitHub <noreply@github.com>2018-04-11 02:48:15 +0800
commit4dd7d0e39baacdd3bf7dc87fc547df66e327f206 (patch)
tree1854302f42b89b6b71b3e69a01470d1369462e61
parent90199d0a961bb75cc5bf6d8ade8bf5b0098cb341 (diff)
downloadtracifyjs-4dd7d0e39baacdd3bf7dc87fc547df66e327f206.tar.gz
tracifyjs-4dd7d0e39baacdd3bf7dc87fc547df66e327f206.zip
extend `hoist_props` (#3073)
- handle `AST_Assign` the same way as `AST_VarDef` - inject `AST_Var` as succeeding statement fixes #3071
-rw-r--r--lib/compress.js77
-rw-r--r--test/compress/hoist_props.js82
2 files changed, 136 insertions, 23 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 7660e677..66dc10cf 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3639,28 +3639,47 @@ merge(Compressor.prototype, {
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
var defs_by_id = Object.create(null);
return self.transform(new TreeTransformer(function(node, descend) {
- if (node instanceof AST_VarDef) {
- var sym = node.name, def, value;
- if (sym.scope === self
- && (def = sym.definition()).escaped != 1
- && !def.assignments
- && !def.direct_access
- && !def.single_use
- && !top_retain(def)
- && (value = sym.fixed_value()) === node.value
- && value instanceof AST_Object) {
- descend(node, this);
- var defs = new Dictionary();
- var assignments = [];
- value.properties.forEach(function(prop) {
- assignments.push(make_node(AST_VarDef, node, {
- name: make_sym(prop.key),
- value: prop.value
- }));
+ if (node instanceof AST_Assign && node.operator == "=" && can_hoist(node.left, node.right, 1)) {
+ descend(node, this);
+ var defs = new Dictionary();
+ var assignments = [];
+ var decls = [];
+ node.right.properties.forEach(function(prop) {
+ var decl = make_sym(node.left, prop.key);
+ decls.push(make_node(AST_VarDef, node, {
+ name: decl,
+ value: null
+ }));
+ var sym = make_node(AST_SymbolRef, node, {
+ name: decl.name,
+ scope: self,
+ thedef: decl.definition()
});
- defs_by_id[def.id] = defs;
- return MAP.splice(assignments);
- }
+ sym.reference({});
+ assignments.push(make_node(AST_Assign, node, {
+ operator: "=",
+ left: sym,
+ right: prop.value
+ }));
+ });
+ defs_by_id[node.left.definition().id] = defs;
+ self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
+ definitions: decls
+ }));
+ return make_sequence(node, assignments);
+ }
+ if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) {
+ descend(node, this);
+ var defs = new Dictionary();
+ var var_defs = [];
+ node.value.properties.forEach(function(prop) {
+ var_defs.push(make_node(AST_VarDef, node, {
+ name: make_sym(node.name, prop.key),
+ value: prop.value
+ }));
+ });
+ defs_by_id[node.name.definition().id] = defs;
+ return MAP.splice(var_defs);
}
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
var defs = defs_by_id[node.expression.definition().id];
@@ -3676,8 +3695,20 @@ merge(Compressor.prototype, {
}
}
- function make_sym(key) {
- var new_var = make_node(sym.CTOR, sym, {
+ function can_hoist(sym, right, count) {
+ if (sym.scope !== self) return;
+ var def = sym.definition();
+ if (def.assignments != count) return;
+ if (def.direct_access) return;
+ if (def.escaped == 1) return;
+ if (def.single_use) return;
+ if (top_retain(def)) return;
+ if (sym.fixed_value() !== right) return;
+ return right instanceof AST_Object;
+ }
+
+ function make_sym(sym, key) {
+ var new_var = make_node(AST_SymbolVar, sym, {
name: self.make_var_name(sym.name + "_" + key),
scope: self
});
diff --git a/test/compress/hoist_props.js b/test/compress/hoist_props.js
index b16f7425..0e399167 100644
--- a/test/compress/hoist_props.js
+++ b/test/compress/hoist_props.js
@@ -742,3 +742,85 @@ issue_3046: {
}
expect_stdout: "1"
}
+
+issue_3071_1: {
+ options = {
+ evaluate: true,
+ inline: true,
+ join_vars: true,
+ hoist_props: true,
+ passes: 3,
+ reduce_vars: true,
+ sequences: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ (function() {
+ var obj = {};
+ obj.one = 1;
+ obj.two = 2;
+ console.log(obj.one);
+ })();
+ }
+ expect: {
+ console.log(1);
+ }
+ expect_stdout: "1"
+}
+
+issue_3071_2: {
+ options = {
+ evaluate: true,
+ inline: true,
+ join_vars: true,
+ hoist_props: true,
+ passes: 3,
+ reduce_vars: true,
+ sequences: true,
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ (function() {
+ obj = {};
+ obj.one = 1;
+ obj.two = 2;
+ console.log(obj.one);
+ var obj;
+ })();
+ }
+ expect: {
+ console.log(1);
+ }
+ expect_stdout: "1"
+}
+
+issue_3071_2_toplevel: {
+ options = {
+ evaluate: true,
+ inline: true,
+ join_vars: true,
+ hoist_props: true,
+ passes: 3,
+ reduce_vars: true,
+ sequences: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ (function() {
+ obj = {};
+ obj.one = 1;
+ obj.two = 2;
+ console.log(obj.one);
+ var obj;
+ })();
+ }
+ expect: {
+ console.log(1);
+ }
+ expect_stdout: "1"
+}