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