support destructuring of catch variable (#4412)

This commit is contained in:
Alex Lam S.L
2020-12-19 12:28:38 +08:00
committed by GitHub
parent 0f55bd92f1
commit e6dd471f8f
5 changed files with 120 additions and 50 deletions

View File

@@ -786,7 +786,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
var AST_Catch = DEFNODE("Catch", "argname", {
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
$propdoc: {
argname: "[AST_SymbolCatch?] symbol for the exception, or null if not present",
argname: "[(AST_Destructured|AST_SymbolCatch)?] symbol for the exception, or null if not present",
},
walk: function(visitor) {
var node = this;
@@ -796,9 +796,9 @@ var AST_Catch = DEFNODE("Catch", "argname", {
});
},
_validate: function() {
if (this.argname != null) {
if (!(this.argname instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
}
if (this.argname != null) validate_destructured(this.argname, function(node) {
if (!(node instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
});
},
}, AST_Block);
@@ -868,7 +868,7 @@ var AST_Var = DEFNODE("Var", null, {
var AST_VarDef = DEFNODE("VarDef", "name value", {
$documentation: "A variable declaration; only appears in a AST_Definitions node",
$propdoc: {
name: "[AST_SymbolVar] name of the variable",
name: "[AST_Destructured|AST_SymbolVar] name of the variable",
value: "[AST_Node?] initializer, or null of there's no initializer"
},
walk: function(visitor) {

View File

@@ -4949,11 +4949,13 @@ merge(Compressor.prototype, {
walk_body(node, tw);
pop();
if (node.bcatch) {
if (node.bcatch.argname) {
var def = node.bcatch.argname.definition();
references[def.id] = false;
if (def = def.redefined()) references[def.id] = false;
}
if (node.bcatch.argname) node.bcatch.argname.mark_symbol(function(node) {
if (node instanceof AST_SymbolCatch) {
var def = node.definition();
references[def.id] = false;
if (def = def.redefined()) references[def.id] = false;
}
}, tw);
push();
if (node.bfinally) segment.block = node.bcatch;
walk_body(node.bcatch, tw);
@@ -5317,6 +5319,34 @@ merge(Compressor.prototype, {
var unused_fn_names = [];
var calls_to_drop_args = [];
var fns_with_marked_args = [];
var trimmer = new TreeTransformer(function(node) {
if (node instanceof AST_DestructuredArray) {
var trim = true;
for (var i = node.elements.length; --i >= 0;) {
var sym = node.elements[i];
if (!(sym instanceof AST_SymbolDeclaration)) {
node.elements[i] = sym.transform(trimmer);
trim = false;
} else if (sym.definition().id in in_use_ids) {
trim = false;
} else if (trim) {
node.elements.pop();
} else {
node.elements[i] = make_node(AST_Hole, sym);
}
}
return node;
}
if (node instanceof AST_DestructuredKeyVal) {
if (!(node.value instanceof AST_SymbolDeclaration)) {
node.value = node.value.transform(trimmer);
return node;
}
if (typeof node.key != "string") return node;
if (node.value.definition().id in in_use_ids) return node;
return List.skip;
}
});
var tt = new TreeTransformer(function(node, descend, in_list) {
var parent = tt.parent();
if (drop_vars) {
@@ -5383,34 +5413,7 @@ merge(Compressor.prototype, {
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (sym instanceof AST_Destructured) {
sym.transform(new TreeTransformer(function(node) {
if (node instanceof AST_DestructuredArray) {
var trim = true;
for (var i = node.elements.length; --i >= 0;) {
var sym = node.elements[i];
if (!(sym instanceof AST_SymbolFunarg)) {
node.elements[i] = sym.transform(this);
trim = false;
} else if (sym.definition().id in in_use_ids) {
trim = false;
} else if (trim) {
node.elements.pop();
} else {
node.elements[i] = make_node(AST_Hole, sym);
}
}
return node;
}
if (node instanceof AST_DestructuredKeyVal) {
if (!(node.value instanceof AST_SymbolFunarg)) {
node.value = node.value.transform(this);
return node;
}
if (typeof node.key != "string") return node;
if (node.value.definition().id in in_use_ids) return node;
return List.skip;
}
}));
sym.transform(trimmer);
trim = false;
continue;
}
@@ -5429,6 +5432,9 @@ merge(Compressor.prototype, {
fns_with_marked_args.push(node);
}
}
if (node instanceof AST_Catch && node.argname instanceof AST_Destructured) {
node.argname.transform(trimmer);
}
if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) {
// place uninitialized names at the start
var body = [], head = [], tail = [];
@@ -7263,7 +7269,9 @@ merge(Compressor.prototype, {
self.body = tighten_body(self.body, compressor);
if (compressor.option("dead_code")) {
if (has_declarations_only(self)
&& !(self.bcatch && self.bcatch.argname && !can_drop_symbol(self.bcatch.argname))) {
&& !(self.bcatch && self.bcatch.argname && self.bcatch.argname.match_symbol(function(node) {
return node instanceof AST_SymbolCatch && !can_drop_symbol(node);
}, true))) {
var body = [];
if (self.bcatch) {
extract_declarations_from_unreachable_code(compressor, self.bcatch, body);

View File

@@ -1216,7 +1216,7 @@ function parse($TEXT, options) {
var name = null;
if (is("punc", "(")) {
next();
name = as_symbol(AST_SymbolCatch);
name = maybe_destructured(AST_SymbolCatch);
expect(")");
}
bcatch = new AST_Catch({