diff --git a/lib/coffeescript/nodes.js b/lib/coffeescript/nodes.js index 1d5609bd96..6406e29c28 100644 --- a/lib/coffeescript/nodes.js +++ b/lib/coffeescript/nodes.js @@ -4774,7 +4774,7 @@ compileNode(o) { var fragments; - fragments = this.expression.compileToFragments(o); + fragments = this.expression.compileToFragments(o, LEVEL_LIST); unshiftAfterComments(fragments, this.makeCode('throw ')); fragments.unshift(this.makeCode(this.tab)); fragments.push(this.makeCode(';')); diff --git a/src/nodes.coffee b/src/nodes.coffee index 677d4df028..f3b8990274 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -3255,7 +3255,7 @@ exports.Throw = class Throw extends Base makeReturn: THIS compileNode: (o) -> - fragments = @expression.compileToFragments o + fragments = @expression.compileToFragments o, LEVEL_LIST unshiftAfterComments fragments, @makeCode 'throw ' fragments.unshift @makeCode @tab fragments.push @makeCode ';' diff --git a/test/exception_handling.coffee b/test/exception_handling.coffee index 3c3240b778..416bdc534f 100644 --- a/test/exception_handling.coffee +++ b/test/exception_handling.coffee @@ -89,10 +89,8 @@ test "try/catch with empty catch as last statement in a function body", -> catch err eq nonce, fn() - -# Catch leads to broken scoping: #1595 - -test "try/catch with a reused variable name.", -> +test "#1595: try/catch with a reused variable name", -> + # `catch` shouldn’t lead to broken scoping. do -> try inner = 5 @@ -100,11 +98,7 @@ test "try/catch with a reused variable name.", -> # nothing eq typeof inner, 'undefined' - -# Allowed to destructure exceptions: #2580 - -test "try/catch with destructuring the exception object", -> - +test "#2580: try/catch with destructuring the exception object", -> result = try missing.object catch {message} @@ -112,8 +106,6 @@ test "try/catch with destructuring the exception object", -> eq message, 'missing is not defined' - - test "Try catch finally as implicit arguments", -> first = (x) -> x @@ -130,8 +122,8 @@ test "Try catch finally as implicit arguments", -> catch e eq bar, yes -# Catch Should Not Require Param: #2900 -test "parameter-less catch clause", -> +test "#2900: parameter-less catch clause", -> + # `catch` should not require a parameter. try throw new Error 'failed' catch @@ -140,3 +132,53 @@ test "parameter-less catch clause", -> try throw new Error 'failed' catch finally ok true ok try throw new Error 'failed' catch then true + +test "#3709: throwing an if statement", -> + # `throw if` should return a closure around the `if` block, so that the + # output is valid JavaScript. + try + throw if no + new Error 'drat!' + else + new Error 'no escape!' + catch err + eq err.message, 'no escape!' + + try + throw if yes then new Error 'huh?' else null + catch err + eq err.message, 'huh?' + +test "#3709: throwing a switch statement", -> + i = 3 + try + throw switch i + when 2 + new Error 'not this one' + when 3 + new Error 'oh no!' + catch err + eq err.message, 'oh no!' + +test "#3709: throwing a for loop", -> + # `throw for` should return a closure around the `for` block, so that the + # output is valid JavaScript. + try + throw for i in [0..3] + i * 2 + catch err + arrayEq err, [0, 2, 4, 6] + +test "#3709: throwing a while loop", -> + i = 0 + try + throw while i < 3 + i++ + catch err + eq i, 3 + +test "#3789: throwing a throw", -> + try + throw throw throw new Error 'whoa!' + catch err + eq err.message, 'whoa!'