const {resolve} = Promise; // fails
Andrea Giammarchi
andrea.giammarchi at gmail.com
Fri Jul 20 08:35:00 UTC 2018
FYI, in case anyone is interested on my user-land solution, there is a
(dual) module now, and it's called `self-aware` [1]
It's a slightly revisited, 100% code covered, generic method "patcher" to
fix Promise and/or others.
Best Regards
[1] https://github.com/WebReflection/self-aware#self-aware
On Fri, Jul 20, 2018 at 2:17 AM Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:
> > one without precedent in the language
>
> that's how languages move forward, right?
>
> > It also means you can't `Promise.resolve.call(SubPromise)`
>
> you can make it more complex and yet have a fallback to the invoker, not a
> real issue, just more rules to write down.
>
> ```js
> const withLazyBoundObjects = new WeakMap;
> const withLazyBoundMethods = obj => {
> const descriptors = Object.getOwnPropertyDescriptors(obj);
> Object.keys(descriptors).forEach(key => {
> const desc = descriptors[key];
> const {value} = desc;
> if (desc.configurable && typeof value === 'function') {
> delete desc.value;
> delete desc.writable;
> desc.get = function () {"use strict";
> const self = this || obj;
> let methods = withLazyBoundObjects.get(self);
> if (!methods)
> withLazyBoundObjects.set(self, methods = Object.create(null));
> return methods[key] || (methods[key] = function () {
> return value.apply(this || self, arguments);
> });
> };
> }
> });
> return Object.defineProperties(obj, descriptors);
> };
>
> withLazyBoundMethods(Promise);
>
> class SubPromise extends Promise {}
>
> console.log([
> (0,Promise.resolve)() instanceof SubPromise,
> Promise.resolve() instanceof SubPromise,
> (0,SubPromise.resolve)() instanceof SubPromise,
> SubPromise.resolve() instanceof SubPromise,
> Promise.resolve.call(SubPromise) instanceof SubPromise
> ]);
>
> // [false, false, true, true, true]
> ```
>
>
>
> On Fri, Jul 20, 2018 at 1:59 AM Jordan Harband <ljharb at gmail.com> wrote:
>
>> That's certainly a clever solution, but one without precedent in the
>> language. It also means you can't `Promise.resolve.call(SubPromise)`,
>> although perhaps you could avoid that by skipping `.bind` and creating a
>> normal function wrapper inside the getter - I'm curious how that might be
>> implemented as well as specified.
>>
>> On Thu, Jul 19, 2018 at 4:54 PM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>>> My code doesn't suffer what Domenic says.
>>>
>>> Once again:
>>>
>>> ```js
>>> const withLazyBoundObjects = new WeakMap;
>>> const withLazyBoundMethods = obj => {
>>> const descriptors = Object.getOwnPropertyDescriptors(obj);
>>> Object.keys(descriptors).forEach(key => {
>>> const desc = descriptors[key];
>>> const {value} = desc;
>>> if (desc.configurable && typeof value === 'function') {
>>> delete desc.value;
>>> delete desc.writable;
>>> desc.get = function (...args) {
>>> let methods = withLazyBoundObjects.get(this || obj);
>>> if (!methods)
>>> withLazyBoundObjects.set(this, methods = Object.create(null));
>>> return methods[key] || (methods[key] = value.bind(this));
>>> };
>>> }
>>> });
>>> return Object.defineProperties(obj, descriptors);
>>> };
>>>
>>> // patch the Promise
>>> withLazyBoundMethods(Promise);
>>>
>>> // have a class that extends Promise
>>> class SubPromise extends Promise {}
>>>
>>> // test inheritance
>>> SubPromise.resolve() instanceof SubPromise; // true
>>> (0,SubPromise.resolve)() instanceof SubPromise; // true
>>>
>>> // even the Promise ?
>>> Promise.resolve() instanceof SubPromise; // false, it's Promise
>>> (0,Promise.resolve)() instanceof SubPromise; // false, it's Promise
>>> ```
>>>
>>> So, why cannot we have above behavior in core?
>>>
>>>
>>>
>>> On Fri, Jul 20, 2018 at 1:36 AM Jordan Harband <ljharb at gmail.com> wrote:
>>>
>>>> > TL;DR why aren't public static methods that need context **all**
>>>> lazily defined as bound (once) on demand? That would make every single
>>>> public static method consistent, accordingly with the Class you extracted
>>>> them from, right? That's not clever, that's usually developers expectations
>>>> because historically all public static methods don't need the Class to work.
>>>>
>>>> I believe
>>>> https://github.com/tc39/ecma262/issues/544#issuecomment-236487230
>>>> answers this - specifically, expressing that the claimed better design is
>>>> for *nothing* to be bound.
>>>>
>>>> On Thu, Jul 19, 2018 at 4:22 PM, Andrea Giammarchi <
>>>> andrea.giammarchi at gmail.com> wrote:
>>>>
>>>>> Reading that looks like nobody answered my question, explained through
>>>>> some code that wouldn't have any issue with subclassing.
>>>>>
>>>>> So no, there's no answer to my latest question in there, unless I've
>>>>> missed it.
>>>>>
>>>>> On Thu, Jul 19, 2018 at 7:56 PM Jordan Harband <ljharb at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> This question has been answered here:
>>>>>> https://github.com/tc39/ecma262/issues/544
>>>>>>
>>>>>> On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi <
>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>
>>>>>>> > Per the KISS principle, let’s avoid to be clever.
>>>>>>>
>>>>>>> I think my next code example is less clever, but the only reason
>>>>>>> I've written hacks or code was not to be advocated or adopted, just to
>>>>>>> explain what could happen internally.
>>>>>>>
>>>>>>> TL;DR why aren't public static methods that need context **all**
>>>>>>> lazily defined as bound (once) on demand? That would make every single
>>>>>>> public static method consistent, accordingly with the Class you extracted
>>>>>>> them from, right? That's not clever, that's usually developers expectations
>>>>>>> because historically all public static methods don't need the Class to work.
>>>>>>>
>>>>>>> On Thu, Jul 19, 2018 at 5:23 PM Claude Pache <claude.pache at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> > Le 19 juil. 2018 à 16:32, Andrea Giammarchi <
>>>>>>>> andrea.giammarchi at gmail.com> a écrit :
>>>>>>>> >
>>>>>>>> > I know it's about subclassing, which is why I've asked why, once
>>>>>>>> there's no context, the default/base one is not considered, but since
>>>>>>>> everyone came back with the subclassing issue, which is actually what I've
>>>>>>>> said myself on twitter about the current state, how about changing all
>>>>>>>> public static methods that need it, to be getters ?
>>>>>>>> >
>>>>>>>> > ```js
>>>>>>>> > class Promise {
>>>>>>>> > #resolve(...args) {
>>>>>>>> > return this.nativeImplementation(...args);
>>>>>>>> > }
>>>>>>>> > get resolve() {
>>>>>>>> > return #resolve.bind(this);
>>>>>>>> > }
>>>>>>>> > }
>>>>>>>> > ```
>>>>>>>> >
>>>>>>>> > we could argue `Promise.resolve === Promise.resolve` should be
>>>>>>>> preserved, as behavior, so that we need a lazy defined getter ... **but**
>>>>>>>> why not making public static restructuring from known constructors work
>>>>>>>> regardless, under all circumstances ?
>>>>>>>> >
>>>>>>>>
>>>>>>>> Nice hack... But it imposes all subclasses of `Promise` that
>>>>>>>> override the `resolve` method to use a similar trick, because the following
>>>>>>>> will break:
>>>>>>>>
>>>>>>>> ```js
>>>>>>>> class MyPromise extends Promise {
>>>>>>>> static resolve() {
>>>>>>>> // do fancy stuff
>>>>>>>> return super.resolve()
>>>>>>>> }
>>>>>>>> }
>>>>>>>>
>>>>>>>> const {resolve} = MyPromise
>>>>>>>>
>>>>>>>> resolve() // TypeError: undefined is not an object
>>>>>>>> ```
>>>>>>>>
>>>>>>>> Per the KISS principle, let’s avoid to be clever.
>>>>>>>>
>>>>>>>> —Claude
>>>>>>>>
>>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> es-discuss mailing list
>>>>>>> es-discuss at mozilla.org
>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>
>>>>>>>
>>>>>>
>>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180720/96214ed8/attachment.html>
More information about the es-discuss
mailing list