Since nobody gave their advice, I'll give my own one :-)

The particular case of the Existential Operator (conditional property access 
and conditional method call) is probably the more usual one.
The case that I 've come across, which is maybe the more common one not covered 
by the Existential Operator, 
consists of using a static method, but thinking of it as if it were a method of 
its first argument. 
Some syntactic sugar could help to both replace it to the correct position (at 
the right side of the object)
and integrate it well with the Existential Operator. 
Thus, I think we could explore rather that direction.

Ok, I stop my monologue here...

—Claude

Le 23 mai 2014 à 09:18, Claude Pache <[email protected]> a écrit :

> 
> Le 22 mai 2014 à 23:58, Claude Pache <[email protected]> a écrit :
> 
>> Hi,
>> 
>> Today, I came to a case where I wanted to grab a reference to some getter of 
>> the DOM,
>> but to not fail if it doesn't exists:
>> 
>> ```javascript
>> try {
>>   originalElementsGetter = 
>> Object.getOwnPropertyDescriptor(window.HTMLFormElement.prototype, 
>> 'elements').get
>> }
>> catch(e) {
>>   originalElementsGetter = undefined
>> }
>> ```
>> 
>> (If you are curious: the context is monkey-patching `<form>.elements`, so 
>> that it includes
>> the `<output>` elements of the form, for I've just discovered that IE 
>> forgets to include them.)
>> 
>> This seems to be a typical case for the Existential Operator (?.) we spoke 
>> recently about
>> (although, in my precise case, a try/catch does the trick).
>> However, the Existential Operator works only on properties and methods:
>> 
>> ```javascript
>> // Bad: if window.HTMLFormElement?.prototype is undefined, 
>> Object.getOwnPropertyDescriptor will protest loudly.
>> originalElementsGetter = 
>> Object.getOwnPropertyDescriptor(window.HTMLFormElement?.prototype, 
>> 'elements')?.get
>> 
>> // Here is what I could use:
>> Object.defineProperty(Object.prototype, '$getOwnPropertyDescriptor', {
>>   value: function(prop) { return Object.getOwnPropertyDescriptor(this, prop) 
>> }
>> , writable: true
>> , configurable: true
>> })
>> oldElementsGetter = 
>> window.HTMLFormElement?.prototype?.$getOwnPropertyDescriptor('elements')?.get
>> ```
>> 
>> Can we do better?
>> 
>> I want to propose a mechanism that can simply express the following
>> (only partially fulfilled by the Existential Operator):
>> 
>> 1. check for nully (null or undefined) values at precise spots of an 
>> expression being evaluated;
>> 2. if a nully is found, stop the evaluation of the entire current 
>> (sub)expression, and yield undefined;
>> 3. or, instead of yielding undefined, provide an alternate value;
>> 4. and be able to determine precisely what "the current subexpression" of 
>> point 2 means.
>> 
>> So, let's introduce the Conditional Fail Operator (`??`), and, its 
>> counterpart, the Recover Operator (`!!`).
>> (You could think of them as a throw/catch-like mechanism, or, better, as a 
>> break/block-like mechanism.)
>> For the sake of illustration, I have artificially lengthen my original 
>> example:
>> 
>> ```javascript
>> originalElementsGetter = 
>> Object.getOwnPropertyDescriptor(window.HTMLFormElement??.prototype??, 
>> 'elements')??.get??
>>                         !! 
>> Object.getOwnPropertyDescriptor(window.HTMLElement??.prototype??, 
>> 'elements')??.get??
>>                         !! 
>> Object.getOwnPropertyDescriptor(window.Element??.prototype??, 
>> 'elements')??.get
>> ```
>> 
>> The semantics are the following:
>> 
>> * `??` is a unary operator that is used as suffix. If its operand is nully 
>> (null or undefined),
>>   the evaluation of a certain expression (more precisely defined below) that 
>> it is part of, fails immediately.
>>   Otherwise, the operand is just returned as is.
>> * `!!` is a short-circuiting binary operator. It evaluates its LHS.
>>   If the evaluation is not interrupted by a `??`, it returns the result.
>>   But if the evaluation is interrupted by a `??`, it evaluates its RHS and 
>> returns the result.
>> * For any assignement operator (`=`, `+=`, etc.), if the evaluation of its 
>> RHS is interrupted by a `??`,
>>   the RHS is replaced by `undefined` and the assignment is performed 
>> normally.
>> * All other operators and function calls are transparent to the failure 
>> signal send by `??`
>>   (you have to stop it by an explicit `!!`).
> 
> I see a nasty footgun in the last two bullets, in case someone refactors from 
> `foo.bar = baz??` to `fooMap.set('bar', baz??)`, for the latter will fail 
> silently.
> But we do want function calls to be transparent to  `??`-failure signals, as 
> it can seen in my original example.
> The best alternative I can see, is the following:
> 
> * All operators (excluding `!!`, of course, but including assignments) and 
> function calls are transparent to failure signals.
> * If a failure signal remains uncaught, an error is thrown (and this 
> condition may even be statically determined and produce an early error).
>    This will catch (!) early failed-assignment bugs, and force the programmer 
> to be more explicit.
> 
> With this amendment, my example must be completed with a final `!! undefined`:
> 
> ```javascript
> originalElementsGetter = 
> Object.getOwnPropertyDescriptor(window.HTMLFormElement??.prototype??, 
> 'elements')??.get??
>                         !! 
> Object.getOwnPropertyDescriptor(window.HTMLElement??.prototype??, 
> 'elements')??.get??
>                         !! 
> Object.getOwnPropertyDescriptor(window.Element??.prototype??, 
> 'elements')??.get??
>                         !! undefined
> ```
> 
> —Claude
> 
>> 
>> As I have shown in [1], it seems relatively easy to spec such a behaviour 
>> using a custom Abrupt Completion.
>> The proposed spec needs to be refined in order to avoid precocious 
>> GetValue(...) calls,
>> but I am able to write a complete strawman in case there is interest.
>> 
>> WDYT?
>> 
>> —Claude
>> 
>> [1] 
>> http://esdiscuss.org/topic/specifying-the-existential-operator-using-abrupt-completion

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to