Skip to content

Commit 7c627f9

Browse files
[CS2] Fix #3709, #3789: ‘throw’ an ‘if’, ‘for’, ‘switch’, ‘while’ (#4664)
* Fix #3709: throwing an if, for, switch or while should throw the returned value of the statement/loop * Fix #3789: don’t throw a throw (unless it’s in a closure) * LEVEL_LIST works better than a list of node types
1 parent c81e2d4 commit 7c627f9

File tree

3 files changed

+57
-15
lines changed

3 files changed

+57
-15
lines changed

lib/coffeescript/nodes.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nodes.coffee

+1-1
Original file line numberDiff line numberDiff line change
@@ -3255,7 +3255,7 @@ exports.Throw = class Throw extends Base
32553255
makeReturn: THIS
32563256

32573257
compileNode: (o) ->
3258-
fragments = @expression.compileToFragments o
3258+
fragments = @expression.compileToFragments o, LEVEL_LIST
32593259
unshiftAfterComments fragments, @makeCode 'throw '
32603260
fragments.unshift @makeCode @tab
32613261
fragments.push @makeCode ';'

test/exception_handling.coffee

+55-13
Original file line numberDiff line numberDiff line change
@@ -89,31 +89,23 @@ test "try/catch with empty catch as last statement in a function body", ->
8989
catch err
9090
eq nonce, fn()
9191

92-
93-
# Catch leads to broken scoping: #1595
94-
95-
test "try/catch with a reused variable name.", ->
92+
test "#1595: try/catch with a reused variable name", ->
93+
# `catch` shouldn’t lead to broken scoping.
9694
do ->
9795
try
9896
inner = 5
9997
catch inner
10098
# nothing
10199
eq typeof inner, 'undefined'
102100

103-
104-
# Allowed to destructure exceptions: #2580
105-
106-
test "try/catch with destructuring the exception object", ->
107-
101+
test "#2580: try/catch with destructuring the exception object", ->
108102
result = try
109103
missing.object
110104
catch {message}
111105
message
112106

113107
eq message, 'missing is not defined'
114108

115-
116-
117109
test "Try catch finally as implicit arguments", ->
118110
first = (x) -> x
119111

@@ -130,8 +122,8 @@ test "Try catch finally as implicit arguments", ->
130122
catch e
131123
eq bar, yes
132124

133-
# Catch Should Not Require Param: #2900
134-
test "parameter-less catch clause", ->
125+
test "#2900: parameter-less catch clause", ->
126+
# `catch` should not require a parameter.
135127
try
136128
throw new Error 'failed'
137129
catch
@@ -140,3 +132,53 @@ test "parameter-less catch clause", ->
140132
try throw new Error 'failed' catch finally ok true
141133

142134
ok try throw new Error 'failed' catch then true
135+
136+
test "#3709: throwing an if statement", ->
137+
# `throw if` should return a closure around the `if` block, so that the
138+
# output is valid JavaScript.
139+
try
140+
throw if no
141+
new Error 'drat!'
142+
else
143+
new Error 'no escape!'
144+
catch err
145+
eq err.message, 'no escape!'
146+
147+
try
148+
throw if yes then new Error 'huh?' else null
149+
catch err
150+
eq err.message, 'huh?'
151+
152+
test "#3709: throwing a switch statement", ->
153+
i = 3
154+
try
155+
throw switch i
156+
when 2
157+
new Error 'not this one'
158+
when 3
159+
new Error 'oh no!'
160+
catch err
161+
eq err.message, 'oh no!'
162+
163+
test "#3709: throwing a for loop", ->
164+
# `throw for` should return a closure around the `for` block, so that the
165+
# output is valid JavaScript.
166+
try
167+
throw for i in [0..3]
168+
i * 2
169+
catch err
170+
arrayEq err, [0, 2, 4, 6]
171+
172+
test "#3709: throwing a while loop", ->
173+
i = 0
174+
try
175+
throw while i < 3
176+
i++
177+
catch err
178+
eq i, 3
179+
180+
test "#3789: throwing a throw", ->
181+
try
182+
throw throw throw new Error 'whoa!'
183+
catch err
184+
eq err.message, 'whoa!'

0 commit comments

Comments
 (0)