fix corner case in mangle (#4966)

fixes #4965
This commit is contained in:
Alex Lam S.L
2021-05-25 23:21:52 +01:00
committed by GitHub
parent eff45eac0e
commit 7caab39e26
3 changed files with 94 additions and 20 deletions

View File

@@ -1341,3 +1341,16 @@ To allow for better optimizations, the compiler makes various assumptions:
// Actual: "FAIL" // Actual: "FAIL"
``` ```
UglifyJS may modify the input which in turn may suppress those errors. UglifyJS may modify the input which in turn may suppress those errors.
- Earlier versions of JavaScript will throw `TypeError` with the following:
```javascript
(function() {
{
const a = "foo";
}
{
const a = "bar";
}
})();
// TypeError: const 'a' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.

View File

@@ -87,7 +87,7 @@ SymbolDef.prototype = {
var def = scope.variables.get(name) var def = scope.variables.get(name)
|| scope instanceof AST_Toplevel && scope.globals.get(name) || scope instanceof AST_Toplevel && scope.globals.get(name)
|| self.orig[0] instanceof AST_SymbolConst && find_if(function(def) { || self.orig[0] instanceof AST_SymbolConst && find_if(function(def) {
return def.name == name && def !== self; return def.name == name;
}, scope.enclosed); }, scope.enclosed);
if (def && def !== self) return def.redefined() || def; if (def && def !== self) return def.redefined() || def;
}, },
@@ -123,7 +123,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 1: setup scope chaining and handle definitions // pass 1: setup scope chaining and handle definitions
var self = this; var self = this;
var const_names = null;
var defun = null; var defun = null;
var exported = false; var exported = false;
var next_def_id = 0; var next_def_id = 0;
@@ -202,7 +201,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} else if (node instanceof AST_SymbolConst) { } else if (node instanceof AST_SymbolConst) {
var def = scope.def_variable(node); var def = scope.def_variable(node);
def.defun = defun; def.defun = defun;
const_names.add(def.name, def);
if (exported) def.exported = true; if (exported) def.exported = true;
} else if (node instanceof AST_SymbolDefun) { } else if (node instanceof AST_SymbolDefun) {
var def = defun.def_function(node, tw.parent()); var def = defun.def_function(node, tw.parent());
@@ -225,21 +223,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
function walk_scope(descend) { function walk_scope(descend) {
node.init_vars(scope); node.init_vars(scope);
var save_names = const_names;
var save_defun = defun; var save_defun = defun;
var save_scope = scope; var save_scope = scope;
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) defun = node;
const_names = new Dictionary();
defun = node;
}
scope = node; scope = node;
descend(); descend();
if (node instanceof AST_Scope) const_names.each(function(defs, name) {
if (defs.length > 1 && !node.variables.has(name)) push_uniq(node.enclosed, defs[0]);
});
scope = save_scope; scope = save_scope;
defun = save_defun; defun = save_defun;
const_names = save_names;
} }
function entangle(defun, scope) { function entangle(defun, scope) {
@@ -680,9 +670,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
if (def.scope.parent_scope.find_variable(sym.name)) return false; if (def.scope.parent_scope.find_variable(sym.name)) return false;
redef = scope.def_variable(sym); redef = scope.def_variable(sym);
scope.to_mangle.push(redef); scope.to_mangle.push(redef);
} else if (redef.mangled_name) {
names_in_use(def.scope, options)[redef.mangled_name] = true;
return false;
} }
redefined.push(def); redefined.push(def);
def.references.forEach(reference); def.references.forEach(reference);

View File

@@ -1539,6 +1539,7 @@ issue_4848: {
issue_4954_1: { issue_4954_1: {
rename = true rename = true
input: { input: {
"use strict";
(function() { (function() {
{ {
const a = "foo"; const a = "foo";
@@ -1551,18 +1552,23 @@ issue_4954_1: {
})(); })();
} }
expect: { expect: {
"use strict";
(function() { (function() {
{ {
const a = "foo"; const a = "foo";
console.log(a); console.log(a);
} }
{ {
const a = "bar"; const b = "bar";
console.log(a); console.log(b);
} }
})(); })();
} }
expect_stdout: true expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
} }
issue_4954_2: { issue_4954_2: {
@@ -1610,11 +1616,79 @@ issue_4960: {
{ {
const o = console.log("PASS"); const o = console.log("PASS");
} }
try {} catch (c) { try {} catch (o) {
const o = console.log("FAIL"); const c = console.log("FAIL");
} }
})(); })();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=4" node_version: ">=4"
} }
issue_4965_1: {
mangle = {}
input: {
"use strict";
try {
c;
} catch (a) {
{
const a = 1;
}
{
const a = console.log(typeof c);
}
}
}
expect: {
"use strict";
try {
c;
} catch (t) {
{
const c = 1;
}
{
const t = console.log(typeof c);
}
}
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_4965_2: {
mangle = {}
input: {
"use strict";
try {
throw 1;
} catch (e) {
try {
{
const e = 2;
}
} finally {
const e = 3;
console.log(typeof t);
}
}
}
expect: {
"use strict";
try {
throw 1;
} catch (o) {
try {
{
const t = 2;
}
} finally {
const o = 3;
console.log(typeof t);
}
}
}
expect_stdout: "undefined"
node_version: ">=4"
}