retrofit try-catch-finally as block-scoped (#4178)
- support optional catch binding
This commit is contained in:
12
lib/ast.js
12
lib/ast.js
@@ -702,28 +702,30 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
|
||||
if (!(this.bfinally instanceof AST_Finally)) throw new Error("bfinally must be AST_Finally");
|
||||
}
|
||||
},
|
||||
}, AST_Block);
|
||||
}, AST_BlockScope);
|
||||
|
||||
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"
|
||||
argname: "[AST_SymbolCatch?] symbol for the exception, or null if not present",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
node.argname.walk(visitor);
|
||||
if (node.argname) node.argname.walk(visitor);
|
||||
walk_body(node, visitor);
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
if (!(this.argname instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
|
||||
if (this.argname != null) {
|
||||
if (!(this.argname instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
|
||||
}
|
||||
},
|
||||
}, AST_BlockScope);
|
||||
|
||||
var AST_Finally = DEFNODE("Finally", null, {
|
||||
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
||||
}, AST_Block);
|
||||
}, AST_BlockScope);
|
||||
|
||||
/* -----[ VAR ]----- */
|
||||
|
||||
|
||||
@@ -4457,9 +4457,11 @@ merge(Compressor.prototype, {
|
||||
walk_body(node, tw);
|
||||
pop();
|
||||
if (node.bcatch) {
|
||||
var def = node.bcatch.argname.definition();
|
||||
references[def.id] = false;
|
||||
if (def = def.redefined()) references[def.id] = false;
|
||||
if (node.bcatch.argname) {
|
||||
var def = node.bcatch.argname.definition();
|
||||
references[def.id] = false;
|
||||
if (def = def.redefined()) references[def.id] = false;
|
||||
}
|
||||
push();
|
||||
if (node.bfinally) segment.block = node.bcatch;
|
||||
walk_body(node.bcatch, tw);
|
||||
@@ -7055,7 +7057,7 @@ merge(Compressor.prototype, {
|
||||
child = scope;
|
||||
scope = compressor.parent(++level);
|
||||
if (scope instanceof AST_Catch) {
|
||||
catches[scope.argname.name] = true;
|
||||
if (scope.argname) catches[scope.argname.name] = true;
|
||||
} else if (scope instanceof AST_DWLoop) {
|
||||
in_loop = [];
|
||||
} else if (scope instanceof AST_For) {
|
||||
|
||||
@@ -1099,10 +1099,12 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_Catch, function(output) {
|
||||
var self = this;
|
||||
output.print("catch");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
self.argname.print(output);
|
||||
});
|
||||
if (self.argname) {
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
self.argname.print(output);
|
||||
});
|
||||
}
|
||||
output.space();
|
||||
print_braced(self, output);
|
||||
});
|
||||
|
||||
@@ -1130,9 +1130,12 @@ function parse($TEXT, options) {
|
||||
if (is("keyword", "catch")) {
|
||||
var start = S.token;
|
||||
next();
|
||||
expect("(");
|
||||
var name = as_symbol(AST_SymbolCatch);
|
||||
expect(")");
|
||||
var name = null;
|
||||
if (is("punc", "(")) {
|
||||
next();
|
||||
name = as_symbol(AST_SymbolCatch);
|
||||
expect(")");
|
||||
}
|
||||
bcatch = new AST_Catch({
|
||||
start : start,
|
||||
argname : name,
|
||||
|
||||
10
lib/scope.js
10
lib/scope.js
@@ -114,6 +114,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Try) {
|
||||
walk_scope(function() {
|
||||
walk_body(node, tw);
|
||||
});
|
||||
if (node.bcatch) node.bcatch.walk(tw);
|
||||
if (node.bfinally) node.bfinally.walk(tw);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_BlockScope) {
|
||||
walk_scope(descend);
|
||||
return true;
|
||||
@@ -468,7 +476,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
if (!options.ie8 && node instanceof AST_Catch) {
|
||||
if (!options.ie8 && node instanceof AST_Catch && node.argname) {
|
||||
var def = node.argname.definition();
|
||||
var redef = defer_redef(def, node.argname);
|
||||
descend();
|
||||
|
||||
@@ -116,7 +116,7 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
||||
});
|
||||
DEF(AST_Catch, function(self, tw) {
|
||||
self.argname = self.argname.transform(tw);
|
||||
if (self.argname) self.argname = self.argname.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
DEF(AST_Definitions, function(self, tw) {
|
||||
|
||||
Reference in New Issue
Block a user