fix corner case in global_defs (#3218)

fixes #3217
This commit is contained in:
Alex Lam S.L
2018-07-19 18:14:36 +08:00
committed by GitHub
parent cea685f8d9
commit 7cf72b8d66
3 changed files with 53 additions and 47 deletions

View File

@@ -59,7 +59,7 @@ function Compressor(options, false_by_default) {
drop_debugger : !false_by_default,
evaluate : !false_by_default,
expression : false,
global_defs : {},
global_defs : false,
hoist_funs : false,
hoist_props : !false_by_default,
hoist_vars : false,
@@ -149,6 +149,7 @@ merge(Compressor.prototype, {
return false;
},
compress: function(node) {
node = node.resolve_defines(this);
if (this.option("expression")) {
node.process_expression(true);
}
@@ -2410,22 +2411,6 @@ merge(Compressor.prototype, {
}
(function(def) {
AST_Node.DEFMETHOD("resolve_defines", function(compressor) {
if (!compressor.option("global_defs")) return;
var def = this._find_defs(compressor, "");
if (def) {
var node, parent = this, level = 0;
do {
node = parent;
parent = compressor.parent(level++);
} while (parent instanceof AST_PropAccess && parent.expression === node);
if (is_lhs(node, parent)) {
compressor.warn('global_defs ' + this.print_to_string() + ' redefined [{file}:{line},{col}]', this.start);
} else {
return def;
}
}
});
function to_node(value, orig) {
if (value instanceof AST_Node) return make_node(value.CTOR, orig, value);
if (Array.isArray(value)) return make_node(AST_Array, orig, {
@@ -2447,25 +2432,43 @@ merge(Compressor.prototype, {
}
return make_node_from_constant(value, orig);
}
function warn(compressor, node) {
compressor.warn("global_defs " + node.print_to_string() + " redefined [{file}:{line},{col}]", node.start);
}
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
if (!compressor.option("global_defs")) return this;
this.figure_out_scope({ ie8: compressor.option("ie8") });
return this.transform(new TreeTransformer(function(node) {
var def = node._find_defs(compressor, "");
if (!def) return;
var level = 0, child = node, parent;
while (parent = this.parent(level++)) {
if (!(parent instanceof AST_PropAccess)) break;
if (parent.expression !== child) break;
child = parent;
}
if (is_lhs(child, parent)) {
warn(compressor, node);
return;
}
return def;
}));
});
def(AST_Node, noop);
def(AST_Dot, function(compressor, suffix) {
return this.expression._find_defs(compressor, "." + this.property + suffix);
});
def(AST_SymbolDeclaration, function(compressor) {
if (!this.global()) return;
if (HOP(compressor.option("global_defs"), this.name)) warn(compressor, this);
});
def(AST_SymbolRef, function(compressor, suffix) {
if (!this.global()) return;
var name;
var defines = compressor.option("global_defs");
if (defines && HOP(defines, (name = this.name + suffix))) {
var node = to_node(defines[name], this);
var top = compressor.find_parent(AST_Toplevel);
node.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolRef) {
node.scope = top;
node.thedef = top.def_global(node);
}
}));
return node;
}
var name = this.name + suffix;
if (HOP(defines, name)) return to_node(defines[name], this);
});
})(function(node, func) {
node.DEFMETHOD("_find_defs", func);
@@ -5718,10 +5721,6 @@ merge(Compressor.prototype, {
}
OPT(AST_SymbolRef, function(self, compressor) {
var def = self.resolve_defines(compressor);
if (def) {
return def.optimize(compressor);
}
if (!compressor.option("ie8")
&& is_undeclared_ref(self)
// testing against `self.scope.uses_with` is an optimization
@@ -6405,10 +6404,6 @@ merge(Compressor.prototype, {
col: self.start.col
});
}
var def = self.resolve_defines(compressor);
if (def) {
return def.optimize(compressor);
}
if (is_lhs(self, compressor.parent())) return self;
if (compressor.option("unsafe_proto")
&& self.expression instanceof AST_Dot
@@ -6464,14 +6459,6 @@ merge(Compressor.prototype, {
}
return self;
});
OPT(AST_VarDef, function(self, compressor) {
var defines = compressor.option("global_defs");
if (defines && HOP(defines, self.name.name)) {
compressor.warn('global_defs ' + self.name.name + ' redefined [{file}:{line},{col}]', self.start);
}
return self;
});
})(function(node, optimizer) {
node.DEFMETHOD("optimize", function(compressor) {
var self = this;