Excellent summary. I'm not convinced types are the way to go about this but
a stronger try/catch is something I'd really enjoy.

In two lines most of the code I read today bypasses the built in exception
handling mechanism in favor of CPS or (err,callback) because of how weak
catch is and asynchronousity. Now generators let us solve the
asynchronousity issue letting but we're still stuck with try/catch.

Brendan, the reason I find generators related is that most of the time I
want to distinguish I/O exceptions (which I want to handle closely) from
things like SyntaxError and ReferenceError (which I usually don't want to
handle at the same granularity). I think the language should help me do
that.





On Wed, Nov 20, 2013 at 7:30 PM, Adam Crabtree <[email protected]> wrote:

> Better error handling in JavaScript is incredibly important. As I see it,
> there are 3 fundamental roadblock or obstacles that undermine the utility
> of JavaScript's error handling:
>
> 1. Lack of typed catch
> 2. Lack of Error.create (solved from what I understand to some degree by
> Object.setPrototypeOf)
> 3. Lack of optimization of try/catch code (in V8)[1]
>
> I'll only talk about #1, but, briefly, #3 is additionally important
> because of its real world ramifications (e.g., node.js' explicit non-use of
> try/catch to avoid it[2]). I conjecture fixing #3 has not been made a
> higher priority because of the weakness of JavaScript error handling due to
> #1 and #2.
>
> Regarding typed catch, typed catch is not just sugar. The above instanceof
> check works, but rethrowing obfuscates the reported throw line. node.js
> again is an example of a codebase that adapts to this by never attempting a
> typed catch to avoid rethrowing.
>
> Async code, control-flow, and async generators all largely owe their
> origins in JavaScript to try/catch.
>
> As an aside, node.js error handling is fundamentally broken and
> inconsistent and promises violate assumptions by catching errors
> originating in core.[3]
>
> Thunks (callback(err, result)) and consequently promises arose out of
> async programming in JavaScript and the inability to catch errors from a
> different event loop tick.
>
> Because try/catch could not catch errors in another tick, errors could not
> be caught and thus should not be thrown, and thus the thunk was born.
> Promises are a monadic alternative to callbacks, but not to try/catch
> unless you wrap all function calls (even synchronous non-IO) in a promise,
> which will slow your execution by separating synchronous execution across
> event loop ticks per the spec, effectively a non-starter. CPS is a true
> alternative to try/catch/throw, except for the lack of proper tail calls.
>
> So, we have 3 options:
> 1. Monadic approach (e.g., Maybe)
> 2. CPS (requiring a trampoline in lieu of PTC)
> 3. try/catch/throw (requiring workarounds to avoid DEOPT)
>
> There are tradeoffs to each approach. #3 is the language default since the
> first two have significant architectural implications, or at least require
> opt-in. There is technically a 4th common alternative of never catching. In
> node though, this leads to requiring a process restart and DoS liability
> since core shares the same stack as userland (application) code and
> throwing places it into an undefined state by not allowing the stack to
> unwind (they should be catching). I wrote the async trycatch module[4] to
> solve this.
>
> *Summary:*
> With async generators and the ability to use the default language error
> handling construct (try/catch) across async IO, try/catch is the best error
> handling mechanism in JavaScript, no longer requiring ugly hacks like my
> trycatch module. However, without typed catch, error handling is ugly and
> inconvenient, resulting in anti-patterns like the following
>
> try{
>   // some code
>   JSON.parse(foo)
>   // some code
> } catch(e) { /* not always what you think it is */ }
>
> that typed catch would easily solve.
>
> Cheers,
> Adam Crabtree
>
> [1] https://code.google.com/p/v8/issues/detail?id=1065
> [2] https://github.com/joyent/node/issues/5149#issuecomment-15761301
> [3]
> http://nodejs.org/docs/latest/api/domain.html#domain_warning_don_t_ignore_errors
> [4] https://github.com/CrabDude/trycatch
>
>
> On Wed, Nov 20, 2013 at 8:05 AM, Jeremy Martin <[email protected]> wrote:
>
>> I can't speak for Benjamin, but I would like to "+1" the notion that
>> try/catches could benefit from some form of error pattern matching.  Here's
>> an example that attempts to avoid conflation with async control-flow
>> considerations:
>>
>> ```javascript
>> try {
>>     JSON.parse(getJSONString());
>> } catch (err) {
>>     if (err instanceof SyntaxError) {
>>         // handle the error
>>     } else {
>>         throw err;
>>     }
>> }
>> ```
>>
>> Discriminatory error handling like this is not all that uncommon, and
>> could potentially benefit from an expansion of the existing guards strawman
>> [1].  For example:
>>
>> ```javascript
>> try {
>>     JSON.parse(getJSONString());
>> } catch (err :: SyntaxError) {
>>     // handle the error
>> }
>> ```
>>
>> This of course has larger implications, though, as you'd presumably need
>> to support multiple "guarded" catches, and behavior for a failed guard is
>> different in the try/catch scenario than with parameters or properties.
>>
>> [1] http://wiki.ecmascript.org/doku.php?id=strawman:guards
>>
>>
>> On Wed, Nov 20, 2013 at 10:24 AM, Brendan Eich <[email protected]>wrote:
>>
>>> Benjamin (Inglor) Gruenbaum wrote:
>>>
>>>> Hi, thanks for the comment and sorry for the unclarity.
>>>>
>>>> I was refering to my original post in this thread about try/catch with
>>>> generators: http://esdiscuss.org/topic/try-catch-conditional-
>>>> exceptions-in-light-of-generators#content-0
>>>>
>>>
>>> Yes, but the Domenic pointed out that the reference error there has
>>> nothing to do with generators so much as async control flow in general (it
>>> could be in a function passed as a callback or downward funarg, and called
>>> "later" by any means). And you seemed to agreed.
>>>
>>> It's true that yield allows part of a function to run in a later event
>>> loop turn -- or just in a later iteration of a loop in the same turn.
>>> Generators by themselves are not async in the event loop sense. So first
>>> you need to identify the problem precisely.
>>>
>>> If you write
>>>
>>>   function f() { ... setCallback(function g() {... RefErrHere ... }) ...
>>> }
>>>
>>> you need test coverage over the body of g.
>>>
>>> If you write
>>>
>>>   function* f() { ... yield; RefErrHere ... }
>>>
>>> same deal. There is no difference in kind.
>>>
>>> So, is the problem you are citing a general one of test coverage over
>>> async control flow?
>>>
>>>
>>> /be
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [email protected]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>>
>>
>> --
>> Jeremy Martin
>> 661.312.3853
>> http://devsmash.com
>> @jmar777
>>
>> _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
> --
> Better a little with righteousness
>        than much gain with injustice.
> Proverbs 16:8
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to