[strawman] Symbol.thenable proposal

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

[strawman] Symbol.thenable proposal

Gus Caplan
Hello all,

In an effort to curtail the interesting behavior of Promise.resolve (especially
with regard to dynamic import), I have created a proposal for a well-known
symbol which will allow an object to not be treated as a "thenable."

I am privy to the current protocol proposal which might be a better fit for
this, but due to dynamic import already being stage 3, I don't feel we should
wait for it to come to fruition.

Comments and suggestions are of course quite welcome at the repo [1].

Thanks,
-Gus



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Guy Bedford-2
It's worth noting that the driving use case here is coming from NodeJS development hitting issues where the guaranteed result for dynamic import resolution can't be assumed to be a module namespace, although please correct me if I'm wrong here Gus.

Alternatively could this mitigation be handled by creating a `Promise.resolveStrict` primitive that explicitly opts-out of thenable resolution in the promise chain?

I'd think we are getting further and further away now from third-party promise implementation interops, that such approaches might make sense to consider at this point, in the name of returning to more well-defined semantics.

On Fri, Apr 13, 2018 at 3:33 AM Gus Caplan <[hidden email]> wrote:
Hello all,

In an effort to curtail the interesting behavior of Promise.resolve (especially
with regard to dynamic import), I have created a proposal for a well-known
symbol which will allow an object to not be treated as a "thenable."

I am privy to the current protocol proposal which might be a better fit for
this, but due to dynamic import already being stage 3, I don't feel we should
wait for it to come to fruition.

Comments and suggestions are of course quite welcome at the repo [1].

Thanks,
-Gus


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

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Jordan Harband
`await import(path)` wouldn't ever be able to do anything besides Promise.resolve; I'm pretty confident that this proposal, or something like it, is the only possibility to make ModuleRecords (for modules that export a `then` function) not be considered thenable.

On Fri, Apr 13, 2018 at 8:02 AM, Guy Bedford <[hidden email]> wrote:
It's worth noting that the driving use case here is coming from NodeJS development hitting issues where the guaranteed result for dynamic import resolution can't be assumed to be a module namespace, although please correct me if I'm wrong here Gus.

Alternatively could this mitigation be handled by creating a `Promise.resolveStrict` primitive that explicitly opts-out of thenable resolution in the promise chain?

I'd think we are getting further and further away now from third-party promise implementation interops, that such approaches might make sense to consider at this point, in the name of returning to more well-defined semantics.

On Fri, Apr 13, 2018 at 3:33 AM Gus Caplan <[hidden email]> wrote:
Hello all,

In an effort to curtail the interesting behavior of Promise.resolve (especially
with regard to dynamic import), I have created a proposal for a well-known
symbol which will allow an object to not be treated as a "thenable."

I am privy to the current protocol proposal which might be a better fit for
this, but due to dynamic import already being stage 3, I don't feel we should
wait for it to come to fruition.

Comments and suggestions are of course quite welcome at the repo [1].

Thanks,
-Gus


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

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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Isiah Meadows-2
I can't remember where, but I recall seeing this discussed elsewhere
(maybe in the TC39 meeting notes?) and the conclusion was basically
¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra
symbol just to make something not considered a thenable - all these
Promise libraries have been able to get away with it for this long;
what makes ES promises any different here? (Dynamic import is probably
the only possible case I can think of short certain proxies in terms
of things that could be considered thenables but shouldn't always.)

Worst case, you can just return a value that happens to have a promise
in a property, like in `{value: somePromise}` - nobody resolves that
except `co` IIRC.
-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Fri, Apr 13, 2018 at 4:20 PM, Jordan Harband <[hidden email]> wrote:

> `await import(path)` wouldn't ever be able to do anything besides
> Promise.resolve; I'm pretty confident that this proposal, or something like
> it, is the only possibility to make ModuleRecords (for modules that export a
> `then` function) not be considered thenable.
>
> On Fri, Apr 13, 2018 at 8:02 AM, Guy Bedford <[hidden email]> wrote:
>>
>> It's worth noting that the driving use case here is coming from NodeJS
>> development hitting issues where the guaranteed result for dynamic import
>> resolution can't be assumed to be a module namespace, although please
>> correct me if I'm wrong here Gus.
>>
>> Alternatively could this mitigation be handled by creating a
>> `Promise.resolveStrict` primitive that explicitly opts-out of thenable
>> resolution in the promise chain?
>>
>> I'd think we are getting further and further away now from third-party
>> promise implementation interops, that such approaches might make sense to
>> consider at this point, in the name of returning to more well-defined
>> semantics.
>>
>> On Fri, Apr 13, 2018 at 3:33 AM Gus Caplan <[hidden email]> wrote:
>>>
>>> Hello all,
>>>
>>> In an effort to curtail the interesting behavior of Promise.resolve
>>> (especially
>>> with regard to dynamic import), I have created a proposal for a
>>> well-known
>>> symbol which will allow an object to not be treated as a "thenable."
>>>
>>> I am privy to the current protocol proposal which might be a better fit
>>> for
>>> this, but due to dynamic import already being stage 3, I don't feel we
>>> should
>>> wait for it to come to fruition.
>>>
>>> Comments and suggestions are of course quite welcome at the repo [1].
>>>
>>> Thanks,
>>> -Gus
>>>
>>> [1]: https://github.com/devsnek/proposal-symbol-thenable
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Guy Bedford-2
To state even more clearly how this is directly affecting API decisions in NodeJS, we're considering supporting a dynamic import hook for `vm.Script`, and one of the API suggestions is:

new vm.Script(`import('x').then(x => console.log(x))`, {
  async resolveDynamicImport (specifier) {
    return getNamespacefor(specifier);
  }
});

The issue here being that this API is guaranteed to result in an error for module namespaces exporting a `then` function.

Yes, effectively not allowing variable dictionary object returns in promise-based APIs becomes the fix, but this does seem a rather arbitrary restriction on API development.

I think the proposal here would be a much-needed addition to be able lock-down guarantees in scenarios such as this.

On Sat, Apr 14, 2018 at 3:00 AM Isiah Meadows <[hidden email]> wrote:
I can't remember where, but I recall seeing this discussed elsewhere
(maybe in the TC39 meeting notes?) and the conclusion was basically
¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra
symbol just to make something not considered a thenable - all these
Promise libraries have been able to get away with it for this long;
what makes ES promises any different here? (Dynamic import is probably
the only possible case I can think of short certain proxies in terms
of things that could be considered thenables but shouldn't always.)

Worst case, you can just return a value that happens to have a promise
in a property, like in `{value: somePromise}` - nobody resolves that
except `co` IIRC.
-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Fri, Apr 13, 2018 at 4:20 PM, Jordan Harband <[hidden email]> wrote:
> `await import(path)` wouldn't ever be able to do anything besides
> Promise.resolve; I'm pretty confident that this proposal, or something like
> it, is the only possibility to make ModuleRecords (for modules that export a
> `then` function) not be considered thenable.
>
> On Fri, Apr 13, 2018 at 8:02 AM, Guy Bedford <[hidden email]> wrote:
>>
>> It's worth noting that the driving use case here is coming from NodeJS
>> development hitting issues where the guaranteed result for dynamic import
>> resolution can't be assumed to be a module namespace, although please
>> correct me if I'm wrong here Gus.
>>
>> Alternatively could this mitigation be handled by creating a
>> `Promise.resolveStrict` primitive that explicitly opts-out of thenable
>> resolution in the promise chain?
>>
>> I'd think we are getting further and further away now from third-party
>> promise implementation interops, that such approaches might make sense to
>> consider at this point, in the name of returning to more well-defined
>> semantics.
>>
>> On Fri, Apr 13, 2018 at 3:33 AM Gus Caplan <[hidden email]> wrote:
>>>
>>> Hello all,
>>>
>>> In an effort to curtail the interesting behavior of Promise.resolve
>>> (especially
>>> with regard to dynamic import), I have created a proposal for a
>>> well-known
>>> symbol which will allow an object to not be treated as a "thenable."
>>>
>>> I am privy to the current protocol proposal which might be a better fit
>>> for
>>> this, but due to dynamic import already being stage 3, I don't feel we
>>> should
>>> wait for it to come to fruition.
>>>
>>> Comments and suggestions are of course quite welcome at the repo [1].
>>>
>>> Thanks,
>>> -Gus
>>>
>>> [1]: https://github.com/devsnek/proposal-symbol-thenable
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Michael Theriot
In reply to this post by Gus Caplan
Currently 'then' is effectively a reserved key and I'd expect any extension that allows the language to ignore it likewise include a means of changing the key entirely.

On Apr 12, 2018, at 9:33 PM, Gus Caplan <[hidden email]> wrote:

Hello all,

In an effort to curtail the interesting behavior of Promise.resolve (especially
with regard to dynamic import), I have created a proposal for a well-known
symbol which will allow an object to not be treated as a "thenable."

I am privy to the current protocol proposal which might be a better fit for
this, but due to dynamic import already being stage 3, I don't feel we should
wait for it to come to fruition.

Comments and suggestions are of course quite welcome at the repo [1].

Thanks,
-Gus


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

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Gus Caplan
I don't understand why you would expect that, can you explain a bit more?

-Gus

On 14 Apr 2018 10:53, Michael Theriot <[hidden email]> wrote:
Currently 'then' is effectively a reserved key and I'd expect any extension that allows the language to ignore it likewise include a means of changing the key entirely.

On Apr 12, 2018, at 9:33 PM, Gus Caplan <[hidden email]> wrote:

Hello all,

In an effort to curtail the interesting behavior of Promise.resolve (especially
with regard to dynamic import), I have created a proposal for a well-known
symbol which will allow an object to not be treated as a "thenable."

I am privy to the current protocol proposal which might be a better fit for
this, but due to dynamic import already being stage 3, I don't feel we should
wait for it to come to fruition.

Comments and suggestions are of course quite welcome at the repo [1].

Thanks,
-Gus


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


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Michael Theriot
A hypothetical proposal addressing that would intersect with this.

On Sat, Apr 14, 2018 at 2:01 PM, <[hidden email]> wrote:
I don't understand why you would expect that, can you explain a bit more?

-Gus

On 14 Apr 2018 10:53, Michael Theriot <[hidden email]> wrote:
Currently 'then' is effectively a reserved key and I'd expect any extension that allows the language to ignore it likewise include a means of changing the key entirely.

On Apr 12, 2018, at 9:33 PM, Gus Caplan <[hidden email]> wrote:

Hello all,

In an effort to curtail the interesting behavior of Promise.resolve (especially
with regard to dynamic import), I have created a proposal for a well-known
symbol which will allow an object to not be treated as a "thenable."

I am privy to the current protocol proposal which might be a better fit for
this, but due to dynamic import already being stage 3, I don't feel we should
wait for it to come to fruition.

Comments and suggestions are of course quite welcome at the repo [1].

Thanks,
-Gus


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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Gus Caplan
It's a fair point, i assume the usage would be like if the property
exists then ignore thenable behaviour and if it is falsy then none of
any of this behaviour would occur, so a Module Namespace Object could
have like [whateverSymbolName]: null, if thats sorta what you are proposing?

On 2018-04-14 13:11:34, Michael Theriot wrote:

> A hypothetical proposal addressing that would intersect with this.
>
> On Sat, Apr 14, 2018 at 2:01 PM, <[hidden email] <mailto:[hidden email]>> wrote:
>
>     I don't understand why you would expect that, can you explain a bit
>     more?
>
>     -Gus
>
>     On 14 Apr 2018 10:53, Michael Theriot <[hidden email]
>     <mailto:[hidden email]>> wrote:
>
>         Currently 'then' is effectively a reserved key and I'd expect
>         any extension that allows the language to ignore it likewise
>         include a means of changing the key entirely.
>
>         On Apr 12, 2018, at 9:33 PM, Gus Caplan <[hidden email]
>         <mailto:[hidden email]>> wrote:
>
>             Hello all,
>
>             In an effort to curtail the interesting behavior of
>             Promise.resolve (especially
>             with regard to dynamic import), I have created a proposal
>             for a well-known
>             symbol which will allow an object to not be treated as a
>             "thenable."
>
>             I am privy to the current protocol proposal which might be a
>             better fit for
>             this, but due to dynamic import already being stage 3, I
>             don't feel we should
>             wait for it to come to fruition.
>
>             Comments and suggestions are of course quite welcome at the
>             repo [1].
>
>             Thanks,
>             -Gus
>
>             [1]: https://github.com/devsnek/proposal-symbol-thenable
>             <https://github.com/devsnek/proposal-symbol-thenable>
>
>             _______________________________________________
>             es-discuss mailing list
>             [hidden email] <mailto:[hidden email]>
>             https://mail.mozilla.org/listinfo/es-discuss
>             <https://mail.mozilla.org/listinfo/es-discuss>
>
>
>

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

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Jordan Harband
This proposal is that Symbol.thenable can be false, or true (which is a no-op). A future proposal could make it *also* be a string or symbol (IsPropertyKey), and then change the method name.

In other words, I don't think there's a conflict, and I think that changing the method name could and should be a followon proposal.

On Sat, Apr 14, 2018 at 1:25 PM, Gus Caplan <[hidden email]> wrote:
It's a fair point, i assume the usage would be like if the property
exists then ignore thenable behaviour and if it is falsy then none of
any of this behaviour would occur, so a Module Namespace Object could
have like [whateverSymbolName]: null, if thats sorta what you are proposing?

On 2018-04-14 13:11:34, Michael Theriot wrote:
> A hypothetical proposal addressing that would intersect with this.
>
> On Sat, Apr 14, 2018 at 2:01 PM, <[hidden email] <mailto:[hidden email]>> wrote:
>
>     I don't understand why you would expect that, can you explain a bit
>     more?
>
>     -Gus
>
>     On 14 Apr 2018 10:53, Michael Theriot <[hidden email]
>     <mailto:[hidden email]>> wrote:
>
>         Currently 'then' is effectively a reserved key and I'd expect
>         any extension that allows the language to ignore it likewise
>         include a means of changing the key entirely.
>
>         On Apr 12, 2018, at 9:33 PM, Gus Caplan <[hidden email]
>         <mailto:[hidden email]>> wrote:
>
>             Hello all,
>
>             In an effort to curtail the interesting behavior of
>             Promise.resolve (especially
>             with regard to dynamic import), I have created a proposal
>             for a well-known
>             symbol which will allow an object to not be treated as a
>             "thenable."
>
>             I am privy to the current protocol proposal which might be a
>             better fit for
>             this, but due to dynamic import already being stage 3, I
>             don't feel we should
>             wait for it to come to fruition.
>
>             Comments and suggestions are of course quite welcome at the
>             repo [1].
>
>             Thanks,
>             -Gus
>
>             [1]: https://github.com/devsnek/proposal-symbol-thenable
>             <https://github.com/devsnek/proposal-symbol-thenable>
>
>             _______________________________________________
>             es-discuss mailing list
>             [hidden email] <mailto:[hidden email]>
>             https://mail.mozilla.org/listinfo/es-discuss
>             <https://mail.mozilla.org/listinfo/es-discuss>
>
>
>


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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Isiah Meadows-2
In reply to this post by Isiah Meadows-2
Not sure how this is relevant, since this is about types rather than
identity, and I'd say typing values is *far* from a solved problem
beyond the basic concept of "all values have a type"...\* ;-)

\* https://en.wikipedia.org/wiki/Type_system

-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Sat, Apr 14, 2018 at 5:59 PM, Claude Petit <[hidden email]> wrote:

> I don't want to be annoying, but object identity is something solved since a long long time by classical OOP   ¯\_(ツ)_/ ¯   But I might by "wrong" as usual...
>
> -----Original Message-----
> From: Isiah Meadows <[hidden email]>
> Sent: Friday, April 13, 2018 9:01 PM
> To: Jordan Harband <[hidden email]>
> Cc: es-discuss <[hidden email]>
> Subject: Re: [strawman] Symbol.thenable proposal
>
> I can't remember where, but I recall seeing this discussed elsewhere (maybe in the TC39 meeting notes?) and the conclusion was basically
> ¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra symbol just to make something not considered a thenable - all these Promise libraries have been able to get away with it for this long; what makes ES promises any different here? (Dynamic import is probably the only possible case I can think of short certain proxies in terms of things that could be considered thenables but shouldn't always.)
>
> Worst case, you can just return a value that happens to have a promise in a property, like in `{value: somePromise}` - nobody resolves that except `co` IIRC.
> -----
>
> Isiah Meadows
> [hidden email]
>
> Looking for web consulting? Or a new website?
> Send me an email and we can get started.
> www.isiahmeadows.com
>
>
> On Fri, Apr 13, 2018 at 4:20 PM, Jordan Harband <[hidden email]> wrote:
>> `await import(path)` wouldn't ever be able to do anything besides
>> Promise.resolve; I'm pretty confident that this proposal, or something
>> like it, is the only possibility to make ModuleRecords (for modules
>> that export a `then` function) not be considered thenable.
>>
>> On Fri, Apr 13, 2018 at 8:02 AM, Guy Bedford <[hidden email]> wrote:
>>>
>>> It's worth noting that the driving use case here is coming from
>>> NodeJS development hitting issues where the guaranteed result for
>>> dynamic import resolution can't be assumed to be a module namespace,
>>> although please correct me if I'm wrong here Gus.
>>>
>>> Alternatively could this mitigation be handled by creating a
>>> `Promise.resolveStrict` primitive that explicitly opts-out of
>>> thenable resolution in the promise chain?
>>>
>>> I'd think we are getting further and further away now from
>>> third-party promise implementation interops, that such approaches
>>> might make sense to consider at this point, in the name of returning
>>> to more well-defined semantics.
>>>
>>> On Fri, Apr 13, 2018 at 3:33 AM Gus Caplan <[hidden email]> wrote:
>>>>
>>>> Hello all,
>>>>
>>>> In an effort to curtail the interesting behavior of Promise.resolve
>>>> (especially with regard to dynamic import), I have created a
>>>> proposal for a well-known symbol which will allow an object to not
>>>> be treated as a "thenable."
>>>>
>>>> I am privy to the current protocol proposal which might be a better
>>>> fit for this, but due to dynamic import already being stage 3, I
>>>> don't feel we should wait for it to come to fruition.
>>>>
>>>> Comments and suggestions are of course quite welcome at the repo [1].
>>>>
>>>> Thanks,
>>>> -Gus
>>>>
>>>> [1]: https://github.com/devsnek/proposal-symbol-thenable
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> [hidden email]
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
>
> ---
> This email has been checked for viruses by AVG.
> http://www.avg.com
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: [strawman] Symbol.thenable proposal

doodad-js Admin
I mean you could have an interface IThenable that you implement to a class/constructor. Then each instantiated object of such class/constructor can be "identified" as a Thenable. Yes, that involves a type system.

-----Original Message-----
From: [hidden email] <[hidden email]> On Behalf Of Isiah Meadows
Sent: Sunday, April 15, 2018 6:06 PM
To: Claude Petit <[hidden email]>
Cc: Jordan Harband <[hidden email]>; es-discuss <[hidden email]>
Subject: Re: [strawman] Symbol.thenable proposal

Not sure how this is relevant, since this is about types rather than identity, and I'd say typing values is *far* from a solved problem beyond the basic concept of "all values have a type"...\* ;-)

\* https://en.wikipedia.org/wiki/Type_system

-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Sat, Apr 14, 2018 at 5:59 PM, Claude Petit <[hidden email]> wrote:

> I don't want to be annoying, but object identity is something solved since a long long time by classical OOP   ¯\_(ツ)_/ ¯   But I might by "wrong" as usual...
>
> -----Original Message-----
> From: Isiah Meadows <[hidden email]>
> Sent: Friday, April 13, 2018 9:01 PM
> To: Jordan Harband <[hidden email]>
> Cc: es-discuss <[hidden email]>
> Subject: Re: [strawman] Symbol.thenable proposal
>
> I can't remember where, but I recall seeing this discussed elsewhere
> (maybe in the TC39 meeting notes?) and the conclusion was basically
> ¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra
> symbol just to make something not considered a thenable - all these
> Promise libraries have been able to get away with it for this long;
> what makes ES promises any different here? (Dynamic import is probably
> the only possible case I can think of short certain proxies in terms
> of things that could be considered thenables but shouldn't always.)
>
> Worst case, you can just return a value that happens to have a promise in a property, like in `{value: somePromise}` - nobody resolves that except `co` IIRC.
> -----
>
> Isiah Meadows
> [hidden email]
>
> Looking for web consulting? Or a new website?
> Send me an email and we can get started.
> www.isiahmeadows.com
>
>
> On Fri, Apr 13, 2018 at 4:20 PM, Jordan Harband <[hidden email]> wrote:
>> `await import(path)` wouldn't ever be able to do anything besides
>> Promise.resolve; I'm pretty confident that this proposal, or
>> something like it, is the only possibility to make ModuleRecords (for
>> modules that export a `then` function) not be considered thenable.
>>
>> On Fri, Apr 13, 2018 at 8:02 AM, Guy Bedford <[hidden email]> wrote:
>>>
>>> It's worth noting that the driving use case here is coming from
>>> NodeJS development hitting issues where the guaranteed result for
>>> dynamic import resolution can't be assumed to be a module namespace,
>>> although please correct me if I'm wrong here Gus.
>>>
>>> Alternatively could this mitigation be handled by creating a
>>> `Promise.resolveStrict` primitive that explicitly opts-out of
>>> thenable resolution in the promise chain?
>>>
>>> I'd think we are getting further and further away now from
>>> third-party promise implementation interops, that such approaches
>>> might make sense to consider at this point, in the name of returning
>>> to more well-defined semantics.
>>>
>>> On Fri, Apr 13, 2018 at 3:33 AM Gus Caplan <[hidden email]> wrote:
>>>>
>>>> Hello all,
>>>>
>>>> In an effort to curtail the interesting behavior of Promise.resolve
>>>> (especially with regard to dynamic import), I have created a
>>>> proposal for a well-known symbol which will allow an object to not
>>>> be treated as a "thenable."
>>>>
>>>> I am privy to the current protocol proposal which might be a better
>>>> fit for this, but due to dynamic import already being stage 3, I
>>>> don't feel we should wait for it to come to fruition.
>>>>
>>>> Comments and suggestions are of course quite welcome at the repo [1].
>>>>
>>>> Thanks,
>>>> -Gus
>>>>
>>>> [1]: https://github.com/devsnek/proposal-symbol-thenable
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> [hidden email]
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
>
> ---
> This email has been checked for viruses by AVG.
> http://www.avg.com
>

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: [strawman] Symbol.thenable proposal

Gus Caplan
that's the protocol proposal i mention on my proposal repo (https://github.com/devsnek/proposal-symbol-thenable)

-Gus

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Tab Atkins Jr.
In reply to this post by Isiah Meadows-2
On Fri, Apr 13, 2018 at 6:00 PM, Isiah Meadows <[hidden email]> wrote:
> I can't remember where, but I recall seeing this discussed elsewhere
> (maybe in the TC39 meeting notes?) and the conclusion was basically
> ¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra
> symbol just to make something not considered a thenable - all these
> Promise libraries have been able to get away with it for this long;
> what makes ES promises any different here? (Dynamic import is probably
> the only possible case I can think of short certain proxies in terms
> of things that could be considered thenables but shouldn't always.)

Having a reserved property key is a big footgun; you *can't* reliably
resolve a promise to an arbitrary object, because if the object
happens to have a "then" key, it'll try to recursively resolve it.

Userland may "get away with it" because "then" isn't a common key, but
it's still a hassle, same as how __proto__ being a special key in JS
causes problems with JSON usage - it's rare, but not unknown, and
problematic because it's an obvious layering violation.

> Worst case, you can just return a value that happens to have a promise
> in a property, like in `{value: somePromise}` - nobody resolves that
> except `co` IIRC.

Note that this isn't about nesting promises (or even promise-likes)
without recursive resolution, it's about nesting *thenables* into a
promise without (attempted) recursive resolution, which is a much
larger conceptual class: the presence of a "then" property says
absolutely nothing about the type of an object. We've just been making
a statistical judgement about the posterior probability of an object
being promise-like based on the presence of a particular key, which is
very dubious.

I'm still strongly of the opinion that we messed this up; the reason
we went with thenables was because it's how userland did it, and they
were working under the constraints of a proliferation of promise-likes
and the difficulty of userland type-testing; real Promise usage
promulgated much quicker than the pessimistic estimates, tho, making
the relative trade-off of "free" compatibility with promise-likes vs
the layering violation of reserving a property name on every object
forever much less favorable.  We should have instead relied on the
actual Promise type, with a Symbol escape-hatch opting a userland
object into being a promise-like.  Doing the reverse and letting
objects opt *out* of being treated as promise-like is probably the
most we can do at this point, unfortunately. Generic data-handling
will just have to manually add such a Symbol to objects they're
resolving to, which sucks but is better than the alternative of always
using a wrapper object.

(Note that having a "strictResolve" method won't help; it might
prevent the precise promise you construct from recursing into the
object, but if you then resolve *another* promise to that promise,
it'll go ahead and try to recurse again.  Maybe strictResolve() could
auto-add the "I'm not a promise-like" symbol to the object it resolves
to? That would be a bit more ergonomic for generic handling.)

~TJ
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Ben Newman
I agree with Tab that allowing developers to opt out of thenable behavior is the only recourse now, but I don't think `Symbol.thenable` is the best way to grant that power.

In the case of module namespaces, since module authors cannot use `Symbol.thenable` as the name of an export, there's no way to export a `then` function while also opting out of thenable behavior by _exporting_ `Symbol.thenable` as `false`.

Instead, this proposal seems to imply that `Symbol.thenable` would have to be added automatically to every module namespace object, which could be bad news for module authors who (for whatever reason) actually wanted to export a `then` function to make the namespace thenable.

In general, whether or not we're talking about module namespace objects, we're beginning to realize that the presence of a function-valued `.then` property is not enough information to decide thenability in all cases, though of course it must remain the default behavior because that's how promise libraries have been written, and folks still do use promise libraries instead of the native `Promise` (e.g. Bluebird).

If an object does not have a `.then` function, then clearly it should not be treated as thenable, so I wonder if there might be a way to disambiguate individual `then` functions according to developer intent. Specifically, what if the developer could set `object.then.able = false` to prevent `object` from being treated as thenable, even though it has a function-valued `then` property? In addition to checking for the presence of a `then` method, `Promise` implementations would also need to check that `then.able !== false` before treating the object as thenable. If the `.able` property is absent from the `then` function (or truthy), the normal thenability behavior would continue to apply.

This proposal addresses the module namespace problem I described above, since you can set `then.able = false` before exporting `then` from a module. Note: because of function hoisting, it might be possible to get access to the `then` function before `then.able` has been set, but I don't think that's a problem for dynamic `import()`, since the module has to finish evaluating before the `import()` promise resolves.

While I think `then.able` is kinda cute (which is worth… something?), I would also be totally open to alternatives like setting `then[Symbol.thenable] = false`. The essential idea is to use properties of the `then` function itself (rather than sibling properties of the object) to indicate whether the object should be thenable.

Ben

His errors are volitional and are the portals of discovery.
-- James Joyce

On Mon, Apr 16, 2018 at 1:36 PM, Tab Atkins Jr. <[hidden email]> wrote:
On Fri, Apr 13, 2018 at 6:00 PM, Isiah Meadows <[hidden email]> wrote:
> I can't remember where, but I recall seeing this discussed elsewhere
> (maybe in the TC39 meeting notes?) and the conclusion was basically
> ¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra
> symbol just to make something not considered a thenable - all these
> Promise libraries have been able to get away with it for this long;
> what makes ES promises any different here? (Dynamic import is probably
> the only possible case I can think of short certain proxies in terms
> of things that could be considered thenables but shouldn't always.)

Having a reserved property key is a big footgun; you *can't* reliably
resolve a promise to an arbitrary object, because if the object
happens to have a "then" key, it'll try to recursively resolve it.

Userland may "get away with it" because "then" isn't a common key, but
it's still a hassle, same as how __proto__ being a special key in JS
causes problems with JSON usage - it's rare, but not unknown, and
problematic because it's an obvious layering violation.

> Worst case, you can just return a value that happens to have a promise
> in a property, like in `{value: somePromise}` - nobody resolves that
> except `co` IIRC.

Note that this isn't about nesting promises (or even promise-likes)
without recursive resolution, it's about nesting *thenables* into a
promise without (attempted) recursive resolution, which is a much
larger conceptual class: the presence of a "then" property says
absolutely nothing about the type of an object. We've just been making
a statistical judgement about the posterior probability of an object
being promise-like based on the presence of a particular key, which is
very dubious.

I'm still strongly of the opinion that we messed this up; the reason
we went with thenables was because it's how userland did it, and they
were working under the constraints of a proliferation of promise-likes
and the difficulty of userland type-testing; real Promise usage
promulgated much quicker than the pessimistic estimates, tho, making
the relative trade-off of "free" compatibility with promise-likes vs
the layering violation of reserving a property name on every object
forever much less favorable.  We should have instead relied on the
actual Promise type, with a Symbol escape-hatch opting a userland
object into being a promise-like.  Doing the reverse and letting
objects opt *out* of being treated as promise-like is probably the
most we can do at this point, unfortunately. Generic data-handling
will just have to manually add such a Symbol to objects they're
resolving to, which sucks but is better than the alternative of always
using a wrapper object.

(Note that having a "strictResolve" method won't help; it might
prevent the precise promise you construct from recursing into the
object, but if you then resolve *another* promise to that promise,
it'll go ahead and try to recurse again.  Maybe strictResolve() could
auto-add the "I'm not a promise-like" symbol to the object it resolves
to? That would be a bit more ergonomic for generic handling.)

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


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Jordan Harband
I think the purpose of this proposal is to *forbid* module authors from making their Module Record namespace object thenable, since doing that causes confusion.

Setting a property on the function doesn't work when the "then" is inherited but the object still wants to be non-thenable; I think that the property has to go on the object - the thing that's not thenable - not on the "then" function itself, which wouldn't even have to be touched or looked at if the object is non-thenable.

On Mon, Apr 16, 2018 at 1:15 PM, Ben Newman <[hidden email]> wrote:
I agree with Tab that allowing developers to opt out of thenable behavior is the only recourse now, but I don't think `Symbol.thenable` is the best way to grant that power.

In the case of module namespaces, since module authors cannot use `Symbol.thenable` as the name of an export, there's no way to export a `then` function while also opting out of thenable behavior by _exporting_ `Symbol.thenable` as `false`.

Instead, this proposal seems to imply that `Symbol.thenable` would have to be added automatically to every module namespace object, which could be bad news for module authors who (for whatever reason) actually wanted to export a `then` function to make the namespace thenable.

In general, whether or not we're talking about module namespace objects, we're beginning to realize that the presence of a function-valued `.then` property is not enough information to decide thenability in all cases, though of course it must remain the default behavior because that's how promise libraries have been written, and folks still do use promise libraries instead of the native `Promise` (e.g. Bluebird).

If an object does not have a `.then` function, then clearly it should not be treated as thenable, so I wonder if there might be a way to disambiguate individual `then` functions according to developer intent. Specifically, what if the developer could set `object.then.able = false` to prevent `object` from being treated as thenable, even though it has a function-valued `then` property? In addition to checking for the presence of a `then` method, `Promise` implementations would also need to check that `then.able !== false` before treating the object as thenable. If the `.able` property is absent from the `then` function (or truthy), the normal thenability behavior would continue to apply.

This proposal addresses the module namespace problem I described above, since you can set `then.able = false` before exporting `then` from a module. Note: because of function hoisting, it might be possible to get access to the `then` function before `then.able` has been set, but I don't think that's a problem for dynamic `import()`, since the module has to finish evaluating before the `import()` promise resolves.

While I think `then.able` is kinda cute (which is worth… something?), I would also be totally open to alternatives like setting `then[Symbol.thenable] = false`. The essential idea is to use properties of the `then` function itself (rather than sibling properties of the object) to indicate whether the object should be thenable.

Ben

His errors are volitional and are the portals of discovery.
-- James Joyce

On Mon, Apr 16, 2018 at 1:36 PM, Tab Atkins Jr. <[hidden email]> wrote:
On Fri, Apr 13, 2018 at 6:00 PM, Isiah Meadows <[hidden email]> wrote:
> I can't remember where, but I recall seeing this discussed elsewhere
> (maybe in the TC39 meeting notes?) and the conclusion was basically
> ¯\_(ツ)_/¯. I'm not convinced myself it's actually worth the extra
> symbol just to make something not considered a thenable - all these
> Promise libraries have been able to get away with it for this long;
> what makes ES promises any different here? (Dynamic import is probably
> the only possible case I can think of short certain proxies in terms
> of things that could be considered thenables but shouldn't always.)

Having a reserved property key is a big footgun; you *can't* reliably
resolve a promise to an arbitrary object, because if the object
happens to have a "then" key, it'll try to recursively resolve it.

Userland may "get away with it" because "then" isn't a common key, but
it's still a hassle, same as how __proto__ being a special key in JS
causes problems with JSON usage - it's rare, but not unknown, and
problematic because it's an obvious layering violation.

> Worst case, you can just return a value that happens to have a promise
> in a property, like in `{value: somePromise}` - nobody resolves that
> except `co` IIRC.

Note that this isn't about nesting promises (or even promise-likes)
without recursive resolution, it's about nesting *thenables* into a
promise without (attempted) recursive resolution, which is a much
larger conceptual class: the presence of a "then" property says
absolutely nothing about the type of an object. We've just been making
a statistical judgement about the posterior probability of an object
being promise-like based on the presence of a particular key, which is
very dubious.

I'm still strongly of the opinion that we messed this up; the reason
we went with thenables was because it's how userland did it, and they
were working under the constraints of a proliferation of promise-likes
and the difficulty of userland type-testing; real Promise usage
promulgated much quicker than the pessimistic estimates, tho, making
the relative trade-off of "free" compatibility with promise-likes vs
the layering violation of reserving a property name on every object
forever much less favorable.  We should have instead relied on the
actual Promise type, with a Symbol escape-hatch opting a userland
object into being a promise-like.  Doing the reverse and letting
objects opt *out* of being treated as promise-like is probably the
most we can do at this point, unfortunately. Generic data-handling
will just have to manually add such a Symbol to objects they're
resolving to, which sucks but is better than the alternative of always
using a wrapper object.

(Note that having a "strictResolve" method won't help; it might
prevent the precise promise you construct from recursing into the
object, but if you then resolve *another* promise to that promise,
it'll go ahead and try to recurse again.  Maybe strictResolve() could
auto-add the "I'm not a promise-like" symbol to the object it resolves
to? That would be a bit more ergonomic for generic handling.)

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


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



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

T.J. Crowder-2
In reply to this post by Tab Atkins Jr.
On Mon, Apr 16, 2018 at 6:36 PM, Tab Atkins Jr.
<[hidden email]> wrote:
>
> I'm still strongly of the opinion that we messed this up...
> Doing the reverse and letting
> objects opt *out* of being treated as promise-like is probably the
> most we can do at this point, unfortunately.

I was going to play devil's advocate here ("Is it **really** too late? Probably, but we should at least explore it..."), toying with the idea of a more strict kind of promise (I called it NativePromise), but I ran into a wall which may affect Symbol.thenable = false as well:

```js
someThirdPartyPromise.then(() => import("foo")).then(/*...*/);
```

That converts the promise from `import()` (which understands Symbol.thenable = false) into a non-native Promise, and thus triggers the bug Symbol.thenable is meant to resolve, since when `import()`'s promise resolves, it hands a thenable to the 3rd-party promise that doesn't handle Symbol.thenable = false. Boom.

How does this proposal address that? Because if it doesn't, and third-party libs are supposed to update to support Symbol.thenable = false, we should at least discuss making promises opt-in via Symbol.thenable = true for a special class or type of promise.

My thought (which, again, ran into the wall above) was: Add a new type of promise (call it NativePromise) which doesn't support thenables, just objects with Symbol.promise = true (note I didn't call it "thenable"). (I also toyed with well-known symbols for `then`, `catch`, and `finally` instead, but that's probably overkill). All language-generated and host-provided promises would be NativePromises (this would be a breaking change for `async` functions, thus impact assessment would be required). Notes:

* `import()` would use NativePromise and thus not be confused by a module exporting a `then` function
* NativePromise would be thenable
* Promise would continue to support thenables
* NativePromise would not, and thus would not be Promises/A+-compliant
* NativePromise and Promise would be fully interoperable (both would have Symbol.promise = true and `then`)
* Actively-maintained 3rd-party promise libs like Bluebird would implement Symbol.promise = true to get full interoperability with NativePromise
* NativePromise would only have one-way interoperability with any 3rd-party lib that didn't implement Symbol.promise = true

Again, that's where I ran into the wall above, which I think impacts Symbol.thenable = false as well.

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: [strawman] Symbol.thenable proposal

Gus Caplan
I don't see any problems with polyfills having to update, that's kinda how progress happens...

On 17 Apr 2018 08:13, "T.J. Crowder" <[hidden email]> wrote:
On Mon, Apr 16, 2018 at 6:36 PM, Tab Atkins Jr.
<[hidden email]> wrote:
>
> I'm still strongly of the opinion that we messed this up...
> Doing the reverse and letting
> objects opt *out* of being treated as promise-like is probably the
> most we can do at this point, unfortunately.

I was going to play devil's advocate here ("Is it **really** too late? Probably, but we should at least explore it..."), toying with the idea of a more strict kind of promise (I called it NativePromise), but I ran into a wall which may affect Symbol.thenable = false as well:

```js
someThirdPartyPromise.then(() => import("foo")).then(/*...*/);
```

That converts the promise from `import()` (which understands Symbol.thenable = false) into a non-native Promise, and thus triggers the bug Symbol.thenable is meant to resolve, since when `import()`'s promise resolves, it hands a thenable to the 3rd-party promise that doesn't handle Symbol.thenable = false. Boom.

How does this proposal address that? Because if it doesn't, and third-party libs are supposed to update to support Symbol.thenable = false, we should at least discuss making promises opt-in via Symbol.thenable = true for a special class or type of promise.

My thought (which, again, ran into the wall above) was: Add a new type of promise (call it NativePromise) which doesn't support thenables, just objects with Symbol.promise = true (note I didn't call it "thenable"). (I also toyed with well-known symbols for `then`, `catch`, and `finally` instead, but that's probably overkill). All language-generated and host-provided promises would be NativePromises (this would be a breaking change for `async` functions, thus impact assessment would be required). Notes:

* `import()` would use NativePromise and thus not be confused by a module exporting a `then` function
* NativePromise would be thenable
* Promise would continue to support thenables
* NativePromise would not, and thus would not be Promises/A+-compliant
* NativePromise and Promise would be fully interoperable (both would have Symbol.promise = true and `then`)
* Actively-maintained 3rd-party promise libs like Bluebird would implement Symbol.promise = true to get full interoperability with NativePromise
* NativePromise would only have one-way interoperability with any 3rd-party lib that didn't implement Symbol.promise = true

Again, that's where I ran into the wall above, which I think impacts Symbol.thenable = false as well.

-- T.J. Crowder


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