Fixes #2580 -- Try/Catch is allowed to destructure the error object.

This commit is contained in:
Jeremy Ashkenas 2012-10-23 17:57:22 -04:00
parent 158d37215a
commit 0ba628159f
6 changed files with 101 additions and 76 deletions

View File

@ -336,6 +336,8 @@
Catch: [
o('CATCH Identifier Block', function() {
return [$2, $3];
}), o('CATCH Object Block', function() {
return [new Value($2), $3];
})
],
Throw: [

View File

@ -2398,20 +2398,24 @@
};
Try.prototype.compileNode = function(o) {
var catchPart, ensurePart, errorPart, tryPart;
var catchPart, ensurePart, placeholder, tryPart;
o.indent += TAB;
errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' ';
tryPart = this.attempt.compile(o, LEVEL_TOP);
catchPart = (function() {
var _ref2;
var _base, _ref2;
if (this.recovery) {
if (typeof (_base = this.error).isObject === "function" ? _base.isObject() : void 0) {
placeholder = new Literal('_error');
this.recovery.unshift(new Assign(this.error, placeholder));
this.error = placeholder;
}
if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) {
throw SyntaxError("catch variable may not be \"" + this.error.value + "\"");
}
if (!o.scope.check(this.error.value)) {
o.scope.add(this.error.value, 'param');
}
return " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}";
return " catch (" + (this.error.compile(o)) + ") {\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}";
} else if (!(this.ensure || this.recovery)) {
return ' catch (_error) {}';
}

File diff suppressed because one or more lines are too long

View File

@ -383,6 +383,7 @@ grammar =
# A catch clause names its error and runs a block of code.
Catch: [
o 'CATCH Identifier Block', -> [$2, $3]
o 'CATCH Object Block', -> [new Value($2), $3]
]
# Throw an exception object.

View File

@ -1604,14 +1604,17 @@ exports.Try = class Try extends Base
# is optional, the *catch* is not.
compileNode: (o) ->
o.indent += TAB
errorPart = if @error then " (#{ @error.compile o }) " else ' '
tryPart = @attempt.compile o, LEVEL_TOP
catchPart = if @recovery
if @error.isObject?()
placeholder = new Literal '_error'
@recovery.unshift new Assign @error, placeholder
@error = placeholder
if @error.value in STRICT_PROSCRIBED
throw SyntaxError "catch variable may not be \"#{@error.value}\""
o.scope.add @error.value, 'param' unless o.scope.check @error.value
" catch#{errorPart}{\n#{ @recovery.compile o, LEVEL_TOP }\n#{@tab}}"
" catch (#{ @error.compile o }) {\n#{ @recovery.compile o, LEVEL_TOP }\n#{@tab}}"
else unless @ensure or @recovery
' catch (_error) {}'

View File

@ -99,4 +99,17 @@ test "try/catch with a reused variable name.", ->
catch inner
# nothing
eq typeof inner, 'undefined'
# Allowed to destructure exceptions: #2580
test "try/catch with destructuring the exception object", ->
result = try
missing.object
catch {message}
message
eq message, 'missing is not defined'