diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2021-05-29 05:48:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-29 12:48:34 +0800 |
commit | 260431f4e00be191a9c5db191c66e552898b0708 (patch) | |
tree | b25f73cd0c7696c7e7547b49cbb17b4521802c9f /lib/compress.js | |
parent | 7fa1dea9d032c1ed282f84507e79cee57294945d (diff) | |
download | tracifyjs-260431f4e00be191a9c5db191c66e552898b0708.tar.gz tracifyjs-260431f4e00be191a9c5db191c66e552898b0708.zip |
improve handling of lexical scope (#4979)
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 86 |
1 files changed, 43 insertions, 43 deletions
diff --git a/lib/compress.js b/lib/compress.js index 6419c363..cba78462 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -449,6 +449,13 @@ merge(Compressor.prototype, { }); } + function has_escaped(d, scope, node, parent) { + if (parent instanceof AST_Assign) return parent.operator == "=" && parent.right === node; + if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New; + if (parent instanceof AST_Exit) return parent.value === node && scope.resolve() !== d.scope.resolve(); + if (parent instanceof AST_VarDef) return parent.value === node; + } + var RE_POSITIVE_INTEGER = /^(0|[1-9][0-9]*)$/; (function(def) { def(AST_Node, noop); @@ -594,7 +601,7 @@ merge(Compressor.prototype, { var safe = tw.safe_ids[def.id]; if (!HOP(tw.safe_ids, def.id)) { if (!safe) return false; - if (safe.read && def.scope !== tw.find_parent(AST_Scope)) return false; + if (safe.read && def.scope.resolve() !== tw.find_parent(AST_Scope)) return false; safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids; } if (def.fixed != null && safe.read) { @@ -630,13 +637,6 @@ merge(Compressor.prototype, { return value.is_constant() || is_lambda(value) || value instanceof AST_ObjectIdentity; } - function has_escaped(d, node, parent) { - if (parent instanceof AST_Assign) return parent.operator == "=" && parent.right === node; - if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New; - if (parent instanceof AST_Exit) return parent.value === node && node.scope !== d.scope; - if (parent instanceof AST_VarDef) return parent.value === node; - } - function value_in_use(node, parent) { if (parent instanceof AST_Array) return true; if (parent instanceof AST_Binary) return lazy_op[parent.operator]; @@ -648,11 +648,11 @@ merge(Compressor.prototype, { function mark_escaped(tw, d, scope, node, value, level, depth) { var parent = tw.parent(level); if (value && value.is_constant()) return; - if (has_escaped(d, node, parent)) { + if (has_escaped(d, scope, node, parent)) { d.escaped.push(parent); if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1; if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth; - if (d.scope !== scope) d.escaped.cross_scope = true; + if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true; return; } else if (value_in_use(node, parent)) { mark_escaped(tw, d, scope, parent, parent, level + 1, depth); @@ -1212,7 +1212,7 @@ merge(Compressor.prototype, { var recursive = recursive_ref(tw, d); if (recursive) recursive.enclosed.forEach(function(def) { if (d === def) return; - if (def.scope === recursive) return; + if (def.scope.resolve() === recursive) return; var assigns = def.fixed && def.fixed.assigns; if (!assigns) return; if (assigns[assigns.length - 1] instanceof AST_VarDef) return; @@ -1607,11 +1607,12 @@ merge(Compressor.prototype, { function safe_to_trim(stat) { if (stat instanceof AST_LambdaDefinition) { var def = stat.name.definition(); - return def.scope === stat.name.scope || all(def.references, function(ref) { - var scope = ref.scope; + var scope = stat.name.scope; + return def.scope === scope || all(def.references, function(ref) { + var s = ref.scope; do { - if (scope === stat.name.scope) return true; - } while (scope = scope.parent_scope); + if (s === scope) return true; + } while (s = s.parent_scope); }); } return !is_lexical_definition(stat); @@ -2791,7 +2792,9 @@ merge(Compressor.prototype, { if (!value) { value = node; var def = node.definition(); - if (!def.undeclared && (def.assignments || !def.escaped || def.escaped.cross_scope)) { + if (!def.undeclared + && (def.assignments || !def.escaped || def.escaped.cross_scope) + && (has_escaped(def, node.scope, node, tw.parent()) || !same_scope(def))) { well_defined = false; } } @@ -2880,7 +2883,7 @@ merge(Compressor.prototype, { function is_lhs_local(lhs) { var sym = root_expr(lhs); return sym instanceof AST_SymbolRef - && sym.definition().scope === scope + && sym.definition().scope.resolve() === scope && !(in_loop && (lvalues.has(sym.name) && lvalues.get(sym.name)[0] !== lhs || candidate instanceof AST_Unary @@ -2921,7 +2924,7 @@ merge(Compressor.prototype, { function may_modify(sym) { var def = sym.definition(); if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false; - if (def.scope !== scope) return true; + if (def.scope.resolve() !== scope) return true; if (modify_toplevel && compressor.exposed(def)) return true; return !all(def.references, function(ref) { return ref.scope.resolve() === scope; @@ -2935,7 +2938,7 @@ merge(Compressor.prototype, { if (lhs) { if (node instanceof AST_Dot) return side_effects_external(node.expression, true); if (node instanceof AST_Sub) return side_effects_external(node.expression, true); - if (node instanceof AST_SymbolRef) return node.definition().scope !== scope; + if (node instanceof AST_SymbolRef) return node.definition().scope.resolve() !== scope; } return false; } @@ -3818,7 +3821,7 @@ merge(Compressor.prototype, { }); }); def(AST_ObjectIdentity, function(compressor, force) { - return is_strict(compressor, force) && !this.scope.new; + return is_strict(compressor, force) && !this.scope.resolve().new; }); def(AST_Sequence, function(compressor) { return this.tail_node()._dot_throw(compressor); @@ -5021,7 +5024,7 @@ merge(Compressor.prototype, { if (!(lhs instanceof AST_PropAccess)) return true; var node = lhs.expression; return !(node instanceof AST_ObjectIdentity) - || !node.scope.new + || !node.scope.resolve().new || lhs instanceof AST_Sub && lhs.property.has_side_effects(compressor) || this.right.has_side_effects(compressor); }); @@ -6773,7 +6776,7 @@ merge(Compressor.prototype, { } function track_assigns(def, node) { - if (def.scope !== self) return false; + if (def.scope.resolve() !== self) return false; if (!def.fixed || !node.fixed) assign_in_use[def.id] = false; return assign_in_use[def.id] !== false; } @@ -6833,14 +6836,15 @@ merge(Compressor.prototype, { function scan_ref_scoped(node, descend, init) { if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) { var def = node.left.definition(); - if (def.scope === self) assignments.add(def.id, node); + if (def.scope.resolve() === self) assignments.add(def.id, node); } if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) { var def = node.expression.definition(); - if (def.scope === self) assignments.add(def.id, node); + if (def.scope.resolve() === self) assignments.add(def.id, node); } var node_def, props = [], sym = assign_as_unused(node, props); - if (sym && self.variables.get(sym.name) === (node_def = sym.definition()) + if (sym && ((node_def = sym.definition()).scope.resolve() === self + || self.variables.get(sym.name) === node_def) && !(is_arguments(node_def) && !all(self.argnames, function(argname) { return !argname.match_symbol(function(node) { if (node instanceof AST_SymbolFunarg) { @@ -6861,7 +6865,7 @@ merge(Compressor.prototype, { }); if (node instanceof AST_Assign) { var right = get_rhs(node), shared = false; - if (init && node.write_only === true && node_def.scope === self && !right.has_side_effects(compressor)) { + if (init && node.write_only === true && !right.has_side_effects(compressor)) { initializations.add(node_def.id, right); } else { right.walk(tw); @@ -6892,7 +6896,7 @@ merge(Compressor.prototype, { var sym = get_init_symbol(node); if (!sym) return; var def = sym.definition(); - if (def.scope !== self) { + if (def.scope.resolve() !== self) { var d = find_variable(sym.name); if (d === def || d && d.redefined() === def) return; } @@ -7324,33 +7328,32 @@ merge(Compressor.prototype, { if (node instanceof AST_Assign) { if (node.operator != "=") return; if (!node.write_only) return; - if (node.left.scope !== self) return; if (!can_hoist(node.left, node.right, 1)) return; 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); + var decl = make_sym(AST_SymbolVar, node.left, prop.key); decls.push(make_node(AST_VarDef, node, { name: decl, - value: null + value: null, })); var sym = make_node(AST_SymbolRef, node, { name: decl.name, scope: self, - thedef: decl.definition() + thedef: decl.definition(), }); sym.reference(); assignments.push(make_node(AST_Assign, node, { operator: "=", left: sym, - right: prop.value + 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 + definitions: decls, })); return make_sequence(node, assignments); } @@ -7362,16 +7365,16 @@ merge(Compressor.prototype, { 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 + name: make_sym(node.name.CTOR, node.name, prop.key), + value: prop.value, })); }); defs_by_id[node.name.definition().id] = defs; return List.splice(var_defs); } - function make_sym(sym, key) { - var new_var = self.make_var(AST_SymbolVar, sym, sym.name + "_" + key); + function make_sym(type, sym, key) { + var new_var = self.make_var(type, sym, sym.name + "_" + key); defs.set(key, new_var.definition()); return new_var; } @@ -7386,7 +7389,7 @@ merge(Compressor.prototype, { var sym = make_node(AST_SymbolRef, node, { name: def.name, scope: node.expression.scope, - thedef: def + thedef: def, }); sym.reference(); return sym; @@ -7401,9 +7404,7 @@ merge(Compressor.prototype, { if (!(sym instanceof AST_SymbolRef)) return; if (!(sym.definition().id in defs_by_id)) return; var opt = node.clone(); - opt[prop] = make_node(AST_Object, sym, { - properties: [] - }); + opt[prop] = make_node(AST_Object, sym, { properties: [] }); return opt; } })); @@ -7423,8 +7424,7 @@ merge(Compressor.prototype, { && all(right.properties, can_hoist_property) && all(def.references, function(ref) { return ref.fixed_value() === right; - }) - && can_drop_symbol(sym); + }); } }); |