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 `!!`).


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