[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
This commit is contained in:
Geoffrey Booth 2017-08-25 11:11:10 -07:00 committed by GitHub
parent c81e2d4767
commit 7c627f9dfd
3 changed files with 57 additions and 15 deletions

View File

@ -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(';'));

View File

@ -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 ';'

View File

@ -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` shouldnt 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!'