fix corner case in mangle (#4174)

This commit is contained in:
Alex Lam S.L
2020-10-04 01:24:41 +01:00
committed by GitHub
parent 04017215cc
commit 95ef4d5377
3 changed files with 88 additions and 38 deletions

View File

@@ -59,13 +59,9 @@ function SymbolDef(id, scope, orig, init) {
} }
SymbolDef.prototype = { SymbolDef.prototype = {
unmangleable: function(options) { forEach: function(fn) {
return this.global && !options.toplevel this.orig.forEach(fn);
|| this.undeclared this.references.forEach(fn);
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun);
}, },
mangle: function(options) { mangle: function(options) {
var cache = options.cache && options.cache.props; var cache = options.cache && options.cache.props;
@@ -85,7 +81,15 @@ SymbolDef.prototype = {
}, },
redefined: function() { redefined: function() {
return this.defun && this.defun.variables.get(this.name); return this.defun && this.defun.variables.get(this.name);
} },
unmangleable: function(options) {
return this.global && !options.toplevel
|| this.undeclared
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun);
},
}; };
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
@@ -100,15 +104,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
var next_def_id = 0; var next_def_id = 0;
var scope = self.parent_scope = null; var scope = self.parent_scope = null;
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_Defun) {
node.name.walk(tw);
walk_scope(function() {
node.argnames.forEach(function(argname) {
argname.walk(tw);
});
walk_body(node, tw);
});
return true;
}
if (node instanceof AST_BlockScope) { if (node instanceof AST_BlockScope) {
node.init_scope_vars(scope); walk_scope(descend);
var save_defun = defun;
var save_scope = scope;
if (node instanceof AST_Scope) defun = node;
scope = node;
descend();
scope = save_scope;
defun = save_defun;
return true; return true;
} }
if (node instanceof AST_With) { if (node instanceof AST_With) {
@@ -122,25 +129,41 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.thedef = node; node.thedef = node;
node.references = []; node.references = [];
} }
if (node instanceof AST_SymbolDefun) { if (node instanceof AST_SymbolCatch) {
// This should be defined in the parent scope, as we encounter the scope.def_variable(node).defun = defun;
// AST_Defun node before getting to its AST_Symbol. } else if (node instanceof AST_SymbolDefun) {
(node.scope = defun.parent_scope.resolve()).def_function(node, defun); defun.def_function(node, tw.parent());
entangle(defun, scope);
} else if (node instanceof AST_SymbolFunarg) {
defun.def_variable(node);
entangle(defun, scope);
} else if (node instanceof AST_SymbolLambda) { } else if (node instanceof AST_SymbolLambda) {
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun); var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
if (options.ie8) def.defun = defun.parent_scope.resolve(); if (options.ie8) def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolVar) { } else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); defun.def_variable(node, null);
if (defun !== scope) { entangle(defun, scope);
node.mark_enclosed(options); }
var def = scope.find_variable(node);
if (node.thedef !== def) { function walk_scope(descend) {
node.thedef = def; node.init_scope_vars(scope);
} var save_defun = defun;
node.reference(options); var save_scope = scope;
} if (node instanceof AST_Scope) defun = node;
} else if (node instanceof AST_SymbolCatch) { scope = node;
scope.def_variable(node).defun = defun; descend();
scope = save_scope;
defun = save_defun;
}
function entangle(defun, scope) {
if (defun === scope) return;
node.mark_enclosed(options);
var def = scope.find_variable(node);
if (node.thedef === def) return;
node.thedef = def;
def.orig.push(node);
node.mark_enclosed(options);
} }
}); });
self.make_def = function(orig, init) { self.make_def = function(orig, init) {
@@ -227,7 +250,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
new_def = scope.def_variable(node); new_def = scope.def_variable(node);
} }
old_def.defun = new_def.scope; old_def.defun = new_def.scope;
old_def.orig.concat(old_def.references).forEach(function(node) { old_def.forEach(function(node) {
node.redef = true; node.redef = true;
node.thedef = new_def; node.thedef = new_def;
node.reference(options); node.reference(options);
@@ -341,7 +364,7 @@ function next_mangled_name(scope, options, def) {
var holes = scope.cname_holes; var holes = scope.cname_holes;
var names = Object.create(null); var names = Object.create(null);
var scopes = [ scope ]; var scopes = [ scope ];
def.references.forEach(function(sym) { def.forEach(function(sym) {
var scope = sym.scope; var scope = sym.scope;
do { do {
if (scopes.indexOf(scope) < 0) { if (scopes.indexOf(scope) < 0) {
@@ -525,7 +548,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
var redef = def.redefined(); var redef = def.redefined();
var name = redef ? redef.rename || redef.name : next_name(); var name = redef ? redef.rename || redef.name : next_name();
def.rename = name; def.rename = name;
def.orig.concat(def.references).forEach(function(sym) { def.forEach(function(sym) {
if (sym.definition() === def) sym.name = name; if (sym.definition() === def) sym.name = name;
}); });
} }

View File

@@ -4960,3 +4960,30 @@ issue_4171_2: {
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
catch_defun: {
mangle = {
toplevel: true,
}
input: {
try {
throw 42;
} catch (a) {
function f() {
return typeof a;
}
}
console.log(f());
}
expect: {
try {
throw 42;
} catch (o) {
function t() {
return typeof o;
}
}
console.log(t());
}
expect_stdout: true
}

View File

@@ -5374,11 +5374,11 @@ defun_catch_4: {
try { try {
throw 42; throw 42;
} catch (a) { } catch (a) {
function a() {}
console.log(a); console.log(a);
} }
} }
expect_stdout: "42" expect_stdout: true
node_version: "<=4"
} }
defun_catch_5: { defun_catch_5: {
@@ -5400,10 +5400,10 @@ defun_catch_5: {
throw 42; throw 42;
} catch (a) { } catch (a) {
console.log(a); console.log(a);
function a() {}
} }
} }
expect_stdout: "42" expect_stdout: true
node_version: "<=4"
} }
defun_catch_6: { defun_catch_6: {