-
Notifications
You must be signed in to change notification settings - Fork 2k
[CS2] Fix #3709, #3789: ‘throw’ an ‘if’, ‘for’, ‘switch’, ‘while’ #4664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… the returned value of the statement/loop
lydell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! Might be worth leaving it open for a little bit though, in case somebody else can come up with more cases where a closure is needed.
| makeReturn: THIS | ||
|
|
||
| compileNode: (o) -> | ||
| fragments = @expression.compileToFragments o |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any chance that changing this to @expression.compileToFragments o, LEVEL_LIST would work instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the tests still pass with:
diff --git a/src/nodes.coffee b/src/nodes.coffee
index 677d4df0..f3b89902 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 ';'There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would also fiw throw try ....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Er, fix*.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@expression.compileToFragments o, LEVEL_LIST is interesting. Care to explain what that means? I've never fully understood the second parameter there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since CoffeeScript generates a JS string directly and not a JS ast, we carry around a notion of what context the node is gonna be compiled in, so we can generate expr/statement, surround with parentheses, etc not to mess with the precedence/... (like compiling {a:5} toplevel)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good way of putting it, re: there being no JS AST. It's exactly designed as a way of dealing with the situation in this PR (and #4644) - namely that a given JS expression (e.g. If, Obj, Op etc.) that's a child of another expression needs to be compiled in a certain way in order to be valid JS (e.g. wrapped in parens, closures, etc.).
|
Just to add some context -- this is what Expressions are expressions, and their values can be used directly -- statements need to be closure-wrapped to be used as values. There should be a way to use adjust the basic handling mechanism in |
|
Well |
|
Perfect! |
Fixes #3709 and #3789. If the expression to be thrown is of certain types (
If,For,Switch,Whileor a nestedThrow) wrap it in a closure, so that it becomes valid JavaScript.I’m sure there are probably other expression types that should get wrapped, so please suggest any you can think of and I’ll add them to the list. But these should be the most likely ones that people would think to put after
throw, (other than anotherthrow, which is so unlikely it feels silly to even cover the case). And now we have a way to handle all similar cases.I tried to find a way to deduce whether the expression should get wrapped in a closure, by looking at
shouldCacheorisStatementor the like, but I didn’t find a helper that was consistent. Ultimately I don’t think there are too many node types that make sense to put afterthrow, so just listing every possibility should hopefully be good enough.