dynamic import() polyfill + question

Bradley Meck bradley.meck at gmail.com
Fri Apr 21 18:38:35 UTC 2017


> how asynchronous export helps here ?

>>> I cannot think about a single use case for wanting that: it's not
usable from within the module, it won't be usable outside unless checked
via ... an interval ?

As stated in previous email:

>> The previous email was stating there are use cases for updating exports.

If you are updating exports that in general means live bindings /
asynchronous work.

> already covered by `export default new Promise(async () => {})` , right ?

Kind of, this sacrifices live binding since `default` can only ever have 1
value. Something could use a thenable to export multiple values over time
however similar to a live binding:

```
let later;
export default {then(notify) { if (ready) notify(later); else
queue(notify); }}
```

> how is the module consumer supposed to know when these exports are ready?

> if it's an event emitted, libraries trusting the event that already
happened will never know, so we are back to polling, which is a very bad
approach, IMO, and if the solution is a Promise then it's covered already.

Please read my previous email:

>> The answer is no pattern has been standardized so it depends on your
proposed solution. A `then()`-able is already in spec and seems like a
possible choice (though I wouldn't use a Promise); top level await could be
another but blocks the module graph. TDZ poll/checking on imports could be
another (though not-preferable) solution. I am sure we could bikeshed other
approaches.

> so if two importers happen at different times the second importer can
compromise with undesired features the first one or vice-verssa?

No, ESM modules are only evaluated once. Such checks are most likely done
up front. However, enabling a debugger for example might cause a new set of
exports to be loaded/exported.

> So, like I've said, I don't see real-world scenarios for exported modules
that changes without notice.
It looks unpractical and undesired.

As stated in previous email:

> Exporting asynchronously doesn't provide any coordination point ...

The rest of my email(s) have been talking about coordination.

On Fri, Apr 21, 2017 at 1:28 PM, Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:

> > It could be something that is being mocked/spied upon.
>
> how asynchronous export helps here ?
>
>
>
> > It could be part of a circular dependency and so the modules do get a
> hold of eachother without finishing evaluation.
>
> already covered by `export default new Promise(async () => {})` , right ?
>
>
>
> > It could be that it lazily/async populates its exports due to costs.
>
> how is the module consumer supposed to know when these exports are ready?
>
> if it's an event emitted, libraries trusting the event that already
> happened will never know, so we are back to polling, which is a very bad
> approach, IMO, and if the solution is a Promise then it's covered already.
>
>
>
> > It could be that it is relying upon context to determine if something
> should be exported (debug flag etc.)
>
> so if two importers happen at different times the second importer can
> compromise with undesired features the first one or vice-verssa?
>
> Dynamic exports are possible since ever on CommonJS world (same as
> imports) and I've truly rarely seen the need to lazy export or lazy import.
> Conditional import yes, and conditional exports too but never at distance.
>
> So, like I've said, I don't see real-world scenarios for exported modules
> that changes without notice.
> It looks unpractical and undesired.
>
> Can you point at me at a single module that needs to do that?
> Maybe I'm missing something.
>
> Thanks
>
>
>
>
> On Fri, Apr 21, 2017 at 7:18 PM, Bradley Meck <bradley.meck at gmail.com>
> wrote:
>
>> > Let me ask again: as a module consumer, how are you supposed to know
>> when an export is available?
>>
>> The previous email was stating there are use cases for updating exports.
>>
>> The answer is no pattern has been standardized so it depends on your
>> proposed solution. A `then()`-able is already in spec and seems like a
>> possible choice (though I wouldn't use a Promise); top level await could be
>> another but blocks the module graph. TDZ poll/checking on imports could be
>> another (though not-preferable) solution. I am sure we could bikeshed other
>> approaches.
>>
>> I don't see "None of these haven't been solved already through better
>> pattern." as a response to all the use cases I described.
>>
>> On Fri, Apr 21, 2017 at 1:13 PM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>>> None of these haven't been solved already through better pattern.
>>>
>>> Let me ask again: as a module consumer, how are you supposed to know
>>> when an export is available?
>>>
>>> On Fri, Apr 21, 2017 at 7:08 PM, Bradley Meck <bradley.meck at gmail.com>
>>> wrote:
>>>
>>>> Could be several reasons, it could be exporting a counter/log that
>>>> changes over time.
>>>>
>>>> It could be something that is being mocked/spied upon.
>>>>
>>>> It could be part of a circular dependency and so the modules do get a
>>>> hold of eachother without finishing evaluation.
>>>>
>>>> It could be that it lazily/async populates its exports due to costs.
>>>>
>>>> It could be that it is relying upon context to determine if something
>>>> should be exported (debug flag etc.)
>>>>
>>>> Probably plenty more reasons.
>>>>
>>>> On Fri, Apr 21, 2017 at 11:58 AM, Andrea Giammarchi <
>>>> andrea.giammarchi at gmail.com> wrote:
>>>>
>>>>> > a Promise cannot change value over time, unlike a live binding.
>>>>>
>>>>> when is a module that changes values and without any notification
>>>>> desirable?
>>>>>
>>>>> I cannot think about a single use case for wanting that: it's not
>>>>> usable from within the module, it won't be usable outside unless checked
>>>>> via ... an interval ?
>>>>>
>>>>> The main point here is that asynchronous import might also inevitably
>>>>> mean asynchronous exports.
>>>>>
>>>>> Early access to unusable modules doesn't seem a real-world solution to
>>>>> me.
>>>>>
>>>>> What am I missing?
>>>>>
>>>>> Best Regards
>>>>>
>>>>>
>>>>>
>>>>> On Fri, Apr 21, 2017 at 5:48 PM, Bradley Meck <bradley.meck at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> I have been thinking about this some, I do think there is something
>>>>>> here, but am not sure it warrants any changes. Exporting asynchronously
>>>>>> doesn't provide any coordination point so the general idea is to export a
>>>>>> Promise, but a Promise cannot change value over time, unlike a live
>>>>>> binding. So, a more appropriate way might be to export a "ready" binding
>>>>>> that is a Promise. Without some kind of async coordination like a
>>>>>> `.then()`-able you would also suffer from `undefined` being a possible
>>>>>> initialized and uninitialized value.
>>>>>>
>>>>>> ```
>>>>>> let later;
>>>>>> export {later};
>>>>>> export const ready = someAsyncWork().then(v => later = v);
>>>>>> ```
>>>>>>
>>>>>> This does still mean that `later` can be accessed before it is ready,
>>>>>> in my opinion somewhat against the idea of a TDZ wanting to wait for access
>>>>>> to be ready.
>>>>>>
>>>>>> I would be interested in something like:
>>>>>>
>>>>>> ```
>>>>>> async let later;
>>>>>> export {later};
>>>>>> export const ready = someAsyncWork().then(v => later = v);
>>>>>> ```
>>>>>>
>>>>>> That preserves the TDZ until assignment. Or, something that wraps
>>>>>> `later` in a non-promise `.then()`-able that `import` understands and can
>>>>>> unwrap to a live binding.
>>>>>>
>>>>>> All of that said, I am not sure this specific of a use warrants
>>>>>> language changes as I can think of problems with the ideas I have proposed
>>>>>> as well.
>>>>>>
>>>>>> On Fri, Apr 21, 2017 at 11:24 AM, Benoit Marchant <marchant at mac.com>
>>>>>> wrote:
>>>>>>
>>>>>>> I really like that idea
>>>>>>>
>>>>>>> On Apr 21, 2017, at 08:22, Andrea Giammarchi <
>>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>>
>>>>>>> nobody has any thought on this ?
>>>>>>>
>>>>>>> Maybe the following pattern would be just about enough to solve a
>>>>>>> generic asynchronous import/export ?
>>>>>>>
>>>>>>> ```js
>>>>>>> export default new Promise(async $export => {
>>>>>>>
>>>>>>>     const utils = await import('./utils.js').default;
>>>>>>>
>>>>>>>     $export({module: 'asynchronous', utils});
>>>>>>>
>>>>>>> });
>>>>>>> ```
>>>>>>>
>>>>>>> Best Regards
>>>>>>>
>>>>>>> On Thu, Apr 20, 2017 at 11:51 AM, Andrea Giammarchi <
>>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>>
>>>>>>>> Even if unpolyfillable through simple `function import() {}`
>>>>>>>> declaration,
>>>>>>>> I've managed to create a polyfill/payground for the ESnext's
>>>>>>>> dynamic import() [1]
>>>>>>>>
>>>>>>>> This also made me wonder if there's any plan to provide a way to
>>>>>>>> asynchronously
>>>>>>>> export modules that depends on those that use asynchronous import.
>>>>>>>>
>>>>>>>> Since AFAIK modules have no top-level await, the only pattern I can
>>>>>>>> see right now
>>>>>>>> to import something asynchronous is the following one:
>>>>>>>>
>>>>>>>> ```js
>>>>>>>> // module ./js/c.js
>>>>>>>> export default Promise.all([
>>>>>>>>   import('./js/a.js'),
>>>>>>>>   import('./js/a.js')
>>>>>>>> ]).then([a, b] => {
>>>>>>>>   const module = {a, b, c() {}};
>>>>>>>>   return module;
>>>>>>>> });
>>>>>>>>
>>>>>>>> // module that uses ./js/c.js
>>>>>>>> import('./js/c.js').then(m => m.default).then(c => {
>>>>>>>>   c.a(); c.b(); c.c();
>>>>>>>> });
>>>>>>>> ```
>>>>>>>>
>>>>>>>> However, above boilerplate doesn't seem ideal compared with
>>>>>>>> something like the following:
>>>>>>>>
>>>>>>>> ```js
>>>>>>>> // module ./js/c.js
>>>>>>>> export default await Promise.all([
>>>>>>>>   import('./js/a.js'),
>>>>>>>>   import('./js/a.js')
>>>>>>>> ]).then([a, b] => {
>>>>>>>>   const module = {a, b, c() {}};
>>>>>>>>   return module;
>>>>>>>> });
>>>>>>>>
>>>>>>>> // module that uses ./js/c.js
>>>>>>>> import * as c from './js/c.js';
>>>>>>>> ```
>>>>>>>>
>>>>>>>> But again, AFAIK that's not possible.
>>>>>>>>
>>>>>>>> The clear advantage is that the module consumer wouldn't need to
>>>>>>>> know, or care,
>>>>>>>> if the loaded module depends on some dynamic, asynchronous, import,
>>>>>>>> meaning modules can be updated and eventually moved to async
>>>>>>>> transparently
>>>>>>>> for any module consumer.
>>>>>>>>
>>>>>>>> As summary, is any solution worth exploring/improving/fixing/pla
>>>>>>>> nning?
>>>>>>>>
>>>>>>>> Thank you.
>>>>>>>> Best Regards
>>>>>>>>
>>>>>>>> [1] https://github.com/WebReflection/import.js#importjs
>>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> es-discuss mailing list
>>>>>>> es-discuss at mozilla.org
>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> 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/20170421/55e4a951/attachment-0001.html>


More information about the es-discuss mailing list