Cyril the discussion is now rather about about asynchronous export. However, what you linked is not a polyfill for import, that's more like a half backed require.
The polyfill for dynamic import where you actually use `import(path)` as specified on stage 3 is here: https://github.com/WebReflection/import.js The universal attempt to add `.import()` as CommonJS module is here: https://github.com/WebReflection/common-js Latter does what you wrote but on both client and server (it also probably resolves relative paths in a slightly different (more accurate?) way. That pattern never convinced CommonJS chaps that believes nobody wants asynchronous requires in this world (I actually do as much as I want asynchronous exports too ^_^) Regards On Sat, Apr 22, 2017 at 3:41 PM, Cyril Auburtin <[email protected]> wrote: > If the discussion is about a polyfill for import() > <https://github.com/tc39/proposal-dynamic-import> (not the static import) > > it's not too hard: https://gist.github.com/caub/ > 458cfe944f8abcf7b1aec608d0a878cc > > ```js > (async()=>{ > const [Stuff, {foo, bar}] = await Promise.all(['./x', > './y'].map(require)); > // .. > })() > > > ``` > > 2017-04-22 16:31 GMT+02:00 Andrea Giammarchi <[email protected]> > : > >> > Why not just allow `export await` in all export syntactic forms? >> >> that would work for me, and it would be like my initial, and second, >> example: `export default await Promise.all(...).then(...)` >> >> however, just to better understand what you're up to, I wonder if the >> module would be held, in a non blocking way, until all asynchronous exports >> have been resolved (desired) as opposite of introducing complexity for >> hybrid modules where you have to await everything to be sure it won't break >> (shenanigans) >> >> TL;DR unless the following would be possible too, please consider making >> modules available only once fully resolved through their exports >> >> ```js >> import await * as module from './module.js'; >> ``` >> >> Regards >> >> >> >> >> On Sat, Apr 22, 2017 at 3:08 PM, Matthew Robb <[email protected]> >> wrote: >> >>> I know you probably didn't want things to go this direction in the >>> conversation but this made me think up a generic way to do this. Why not >>> just allow `export await` in all export syntactic forms? This would not be >>> the same as top level await but a signal that the export will be the result >>> of an asynchronous operation that follows the await. >>> >>> Then you could potentially do `export default await (async ()=>{ >>> >>> })();` >>> >>> On Apr 21, 2017 3:10 PM, "Bradley Meck" <[email protected]> wrote: >>> >>> > how's that different from a Promise ? >>> >>> `later` is not const and could change over time. Could even be set via >>> something like: >>> >>> ``` >>> setInterval(() => later = Date.now(), 1e3); >>> ``` >>> >>> On Fri, Apr 21, 2017 at 2:00 PM, Andrea Giammarchi < >>> [email protected]> wrote: >>> >>>> > let later; >>>> > export default {then(notify) { if (ready) notify(later); else >>>> queue(notify); }} >>>> >>>> how's that different from a Promise ? >>>> >>>> Don't get me wrong, I have a module [1] that does that already (use a >>>> symbol as key and that's it) but yet for an importer, if that has to be >>>> handled like a Promise, then why not just a Promise ? >>>> >>>> This is the bit I don't get. >>>> >>>> Thanks >>>> >>>> [1] https://github.com/WebReflection/broadcast#broadcast-- >>>> >>>> >>>> >>>> On Fri, Apr 21, 2017 at 7:38 PM, Bradley Meck <[email protected]> >>>> wrote: >>>> >>>>> > 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 < >>>>> [email protected]> 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 <[email protected] >>>>>> > 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 < >>>>>>> [email protected]> 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 < >>>>>>>> [email protected]> 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 < >>>>>>>>> [email protected]> 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 < >>>>>>>>>> [email protected]> 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 < >>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>> >>>>>>>>>>>> I really like that idea >>>>>>>>>>>> >>>>>>>>>>>> On Apr 21, 2017, at 08:22, Andrea Giammarchi < >>>>>>>>>>>> [email protected]> 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 < >>>>>>>>>>>> [email protected]> 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/planning? >>>>>>>>>>>>> >>>>>>>>>>>>> Thank you. >>>>>>>>>>>>> Best Regards >>>>>>>>>>>>> >>>>>>>>>>>>> [1] https://github.com/WebReflection/import.js#importjs >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>> es-discuss mailing list >>>>>>>>>>>> [email protected] >>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>> es-discuss mailing list >>>>>>>>>>>> [email protected] >>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> [email protected] >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

