-
Notifications
You must be signed in to change notification settings - Fork 47
Is it expected that module namespace objects are treated as thenables? #47
Comments
Yep! |
oh wow, that's very surprising - so i could |
Yes, almost. Your current version will keep the export default "Default-Export";
export function then(resolve) {
// |this| is bound to the module namespace object when calling during
// promise resolution.
resolve(this.default);
}
import("./t.js").then(v => print(v)); // Prints "Default-Export" |
Is that specifically called out? "then" functions usually don't get called with a resolve function, that's typically only for the Promise constructor executor. |
What happens here is, we end up in 25.4.1.3.2 Promise Resolve Functions, where |
hmm, this is confusing! @domenic can you elaborate more on the motivation for this to work like that? |
I'm doubly confused now. One that ModuleRecords would be treated as thenables, and two that .then would ever get passed a resolver function as an arg. |
To verify my understanding: does this mean that importing a single
module's namespace statically could result in a different value compared to
importing that same module dynamically?
…On Sun, 6 Aug 2017, 16:31 Jordan Harband, ***@***.***> wrote:
I'm doubly confused now. One that ModuleRecords would be treated as
thenables, and two that .then would ever get passed a resolver function as
an arg.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#47 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGni9VeszwSP5kd1GcUdiQzYmmyzhclyks5sVdxFgaJpZM4OuLW0>
.
|
All objects are treated as thenables when you use them as the resolution value of a promise.
That's always the case when assimilating thenables. Remember that
This all comes from the usual invariant that you can't have promises for thenables. That's enforced by the promise machinery, and not something we could break if we wanted to.
I don't know what these terms mean. But maybe let me answer a related question. Doing |
(deleted previous comment as I misread the spec) The specs says that the module namespace gets resolved every time import() is called. This means you could write a then() export that rejects first time and fulfills second time. So the first import() caller see a rejection and the second does not. This seems at odds with the spirit of the recent changes to store and rethrow module evaluation errors. I would also suggest that the modules-as-thenables pattern will not remain an unused corner-case. It provides the unique ability to encapsulate arbitrary multi-tick async work (including nested dynamic imports) beneath a single top-level import(). |
I feel like there should at least be a way to dynamically get the actual module given that statically you can (even if its part of a future proposal). It just seems weird that this: import * as scene from "./scene.js"
async function displayAnimation() {
while (true) {
const currentFrame = scene.then()
display(currentFrame)
}
} Couldn't be safely refactored into this to use lazy-loading: async function displayAnimation() {
const scene = await import('./scene.js')
while (true) {
const currentFrame = scene.then()
display(currentFrame)
}
} A few possible ideas to getting the real module:
// terrible name, but I couldn't think of anything else
import.boxed('./thenableModule.js')
// -> Promise{ { module: thenableModule } )
// rather not see this, seems like there'd be more interesting
// uses of the second argument
import('./thenableModule.js', module => {
...
})
// also terrible name
import.callback('./thenableModule.js', module => {
...
})
import('./thenableModule.js', module => {
module[Symbol.preventThenable] === true // Or something like that
// possibly even an internal
// field [[IsThenable]]
}) |
Given that this is working as intended, and the thread has turned into a place for people to start creating new proposals, I think it's time to close this. |
I understand that this is probably working as intended from the thenable object perspective, but I have two main concerns:
|
Yep. These are all valid concerns about the thenable protocol. They apply to every API that stores and returns objects via promises. (For example, it's a breaking change to add a A new proposal to solve that general issue would be a reasonable thing to bring the committee, but I believe it's out of scope for dynamic import. |
Specifically for dynamic import, however, with modules the idea is that the ModuleRecord is reusable - that's why it's frozen. When it's thenable, however, this means that two different Would it be unreasonable for |
Yes, I believe that would be unreasonable. import() is like every other promise-returning/value-retrieving function. All of them can get different resolution values in the face of malicious then()ables. |
It's quite different, though - it's function-like syntax, per the readme. |
Let me rephrase: "its behavior is like every other promise-returning/value-retrieving function when a thenable is the value retrieved". |
I'm not arguing against thenable coercion here, that's surprising but well-established - I'm asking whether |
Right. And I'll say again: I think the answer should be the same for |
Module file "m.js":
When loaded with
jsc -m ./m.js
ord8 --harmony_dynamic_import --module ./m.js
, it prints "Is it expected that module namespace objects are treated as thenables?". So, is it expected?The text was updated successfully, but these errors were encountered: