const {resolve} = Promise; // fails
Andrea Giammarchi
andrea.giammarchi at gmail.com
Fri Jul 20 00:17:07 UTC 2018
> 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/ac32bf1f/attachment-0001.html>
More information about the es-discuss
mailing list