proposal-throw-expressions: Require parentheses around `throw` expressions

Neither #17 nor #18 were able to achieve consensus at the September, 2023 plenary session. As a result, I am considering alternative approaches to the syntax to achieve consensus. The approach that seems to be most likely to reach consensus is to require throw expressions be surrounded by parentheses.

There are two mutually-exclusive mechanisms we could employ to achieve this:

  1. #21 - Move throw expressions to Expression, making them mutually exclusive with ,, and change the operand to allow Expression.
  2. #22 - Move throw expressions to ParenthesizedExpression, making them mutually exclusive with ,, and change the operand to allow Expression.

Option 1 allows throw expressions to be unparenthesized in a small number of cases where Expression is directly referenced within the specification, but most of those cases have arguable utility (i.e., if (throw e)).

Option 2 always requires throw expressions be parenthesized, even in the cases where they would be allowed in Option 1 (i.e., if ((throw e))).

It is important to note that if we opt to go ahead with Option 2 (#22) and that ended up shipping in Stage 4, we would still be able to change this to Option 1 (#21) in the future without introducing a breaking change. However, if we opt to go with Option 1 (#21), we would not be able to go back to Option 2 once this feature ships.

About this issue

  • Original URL
  • State: open
  • Created 5 months ago
  • Reactions: 1
  • Comments: 19 (8 by maintainers)

Most upvoted comments

To be honest, I also think forcing parens everywhere are bad to ergonomics.

Perhaps Error.prototype.throw() or globalThis.throwError()

Or we could introduce meta method syntax like do.throw(error).

Yes, and I was ok with the original fix for that of having an additional syntactic restriction where it threw an error if you tried to combine the throw expression with the comma operator, since that’s such a rare scenario anyways (to me, that’s not that different from how the ?? operator can’t be mixed with && or || - some operators just can’t be mixed together in the language).

I know that there’s other arguments against it, like how it’s apparently unintuitive with how it behaves in function parameters lists and what-not - I don’t really agree, but won’t rehash that discussion.

I’ve got to say, neither option seems that appealing to me. The beauty of the original proposal was that it was just lifting a syntax a restriction, allowing “throw” to just be used as an expression. The original proposal was technically a syntax change, but not really a syntax addition, so even though the problem this proposal was solving was relatively small, it was fine, because no new syntax was (conceptually) being added.

If “throw” is required to be in parentheses, then we’ve gone from “lifting a syntactic restriction” to “adding syntax rules”, and suddenly this proposal is required to pass a much higher usefulness threshold for it to be worth this cost, and I don’t think it pays for itself.

If we can’t have the original proposal, personally I would prefer:

  • Nothing
  • Or do expressions - yes it’s less elegant, but it does the job
  • Or maybe a new built in function that does nothing more than throw an error. Perhaps Error.prototype.throw() or globalThis.throwError() (that could actually be a good idea - perhaps I should start a separate thread for it - but I also hesitate with it, because it means there’s now two official ways to throw an error instead of one, which seems less than ideal.).

Anything but a syntax addition.

Can we take this off-topic conversation to another thread?

@tmikov non-errors (and even non-objects) can be thrown

If your request is to make ThrowExpression a top level production, I can do that under a different name. As I’d stated, I’m not a fan of having ThrowExpression itself be the name of the top level production.