05:47
<Jack Works>

where is the module instance cache stored? ExecutionContext? Realm?

const mod = module { console.log('run') }
const mod2 = static module { import 'mod' }

await import(new Module(mod2, async () => mod), {})
await import(new ExecutionContext.Module(mod2, async () => mod, {}))
05:47
<Jack Works>
how many time mod is executed?
06:41
<nicolo-ribaudo>
I would expect it to only be executed once in the original execution context (the one where the module block expression was evaluated).
06:42
<nicolo-ribaudo>
The cache could be a [[ModuleRecord]] internal slot on the Module object
08:03
<Jack Works>
ok thanks!
09:02
<yulia>
I think low-level import reflection or deferred import do obviate one complication of the Compartment design (as written right now), regarding how to communicate a module source or module instance from a host compartment to a child compartment. That isn’t possible to express in terms of the low-level parts, which compels the developer to use import reflection or deferred import explicitly. That might be a good outcome, even for XS. Currently XS depends on a manifest to express the full working set, but these features together would allow tooling to take over more of the tedium.
Yes, it feels like import reflection and deferred import evaluation are both doing the same thing in that they hide some of the complexity that a full-access low level api would give. Module loading is quite complex, so choosing what should be hidden and how is probably a good idea. I do worry though that we will add a lot of things to the static import statement / dynamic import options bag, and that will confuse people (as i've already had feedback on that). But this is a concern for later.
10:29
<Jack Works>
I found we need a isAsync property on the Virtual Module.
10:29
<Jack Works>
Cyclic Module Records requires [[isAsync]] which is not possible for Virtual Module because it does not have a source text to be parsed.
12:55
<Jack Works>

I'm working on a polyfill for Module

https://github.com/DimensionDev/aot-secure-ecmascript/blob/2e45ecaf9d45efce1661b8df106ba421817f0fa5/packages/compartment/src/Module.ts

14:53
<Kris Kowal>
I had wondered about that and XS managed to make it work without it. Very good to know.
14:53
<Kris Kowal>
It might be a spec bug. 🤷‍♂️
15:39
<Jack Works>
I had wondered about that and XS managed to make it work without it. Very good to know.
XS have JS source at build time, they can know if the module has TLA or not.
We need to manually mark it for virtual modules (like needsImportMeta), otherwise I guess we need to rewrite the spec a lot.
17:05
<Kris Kowal>
XS also implemented a draft of the virtual module source protocol.
17:06
<Kris Kowal>
And they are of the opinion that the virtual module source doesn’t have to reveal whether initialize() returns a promise or not.
17:06
<Kris Kowal>
Though, if it is necessary, it is not a problem to require it to be reflected on the virtual module source object.
17:07
<Kris Kowal>
Just might be worth inquiring with vendors whether the spec can be relaxed. Module records capture a lot of details from multiple conflated layers that get initialized at different stages.
17:16
<Kris Kowal>

Clarification:

const mod1 = module { console.log('run') };
const src2 = static module { import 'mod' };
const ctx2 = new ExecutionContext(globalThis);
const mod2 = new ctx2.Module(src2, async () => mod1);
await import(mod1);
await import(mod2);

I expect this to log run once from the host execution context.

17:18
<Kris Kowal>
Linking modules between independent execution contexts is an explicit goal out to full Compartment parity, for supply chain isolation.
17:18
<Kris Kowal>
And notably, shared intrinsics between separate execution contexts.
22:04
<Kris Kowal>
262 lawyer question: Is it already the case that there can be multiple execution contexts in a single realm? https://tc39.es/ecma262/#sec-execution-contexts
22:04
<Kris Kowal>
I suppose the answer might lie in the details of generator, async, async generator functions.
22:06
<littledan>
isn't the callstack a stack of execution contexts?
22:06
<Kris Kowal>
(Trying to discover whether “reify execution context” is the right title for the end boss for compartments.)
22:06
<littledan>
there's always one active execution context within a Realm, and you keep switching between them
22:07
<littledan>
at most, one active
22:07
<Kris Kowal>
Got it.
22:08
<Kris Kowal>
So, “reify execution context” is not yet disqualified.
22:08
<littledan>
well, I'm not sure what you mean
22:08
<shu>
whoa, reify execution contexts?
22:08
<shu>
what information are you trying to surface? that seems like not a good idea
22:08
<Kris Kowal>
Yeah, so that’s a hint I’ve got the wrong word.
22:08
<littledan>
isn't "reify local scope" really the final boss?
22:08
<shu>
localThis
22:08
<Kris Kowal>
That’s definitely not what we’re looking for.
22:09
<Kris Kowal>
Though, when I was young and silly, I used to think that’s exactly what I wanted from my programming language.
22:10
<Kris Kowal>
“Prototype chains and scope chains are basically the same thing. Let’s just have one of those.”
22:10
<Kris Kowal>
I got better.
22:10
<littledan>
too bad you missed out on Io in your youth
22:10
<littledan>
that's what I played around with before I found Factor
22:11
<littledan>
arguments can be sent to functions un-evaluated, and then the function can evaluate them in the context of the calling lexical scope!!! and it's all prototypes
22:11
<Kris Kowal>
My youth was pretty mundane in terms of PLT, except for the bit with church numerals in DOS 6.2 BAT files.
22:11
<littledan>
was Tcl around then?
22:12
<Kris Kowal>
Hey, that’s what Guten Tags does :-)
22:12
<littledan>
Io makes the scope chain literally a prototype chain
22:12
<Kris Kowal>
Tcl was definitely on my tour of programming languages.
22:12
<Kris Kowal>
Io makes the scope chain literally a prototype chain
I would have enjoyed that, indeed.
22:12
<littledan>
see, Tcl isn't as general as Io since the subexpressions just evaluate
22:17
<Kris Kowal>
In any case, resisting digression. The last bit of compartments is being able to isolate modules and scripts such that they execute with a global environment record or module environment record that closes over a particular global object, eval behavior, and dynamic import behavior. Every instance of Function, Module, and eval object has an internal slot that points to whatever this is.
22:18
<Kris Kowal>
And we conceive that whatever this is many-to-1 Realm.
22:18
<Kris Kowal>
Which presumably isn’t possible yet.
22:18
<littledan>
I don't get it, but looking forward to hearing more/why
22:19
<Kris Kowal>
Yeah, this is the final building block that would let us use Module as part of the implementation of a Lava Moat / hardened JavaScript.
22:20
<Kris Kowal>
That is, isolating third-party dependencies and preventing prototype-pollution.
22:21
<Kris Kowal>
That is to say, isolating libraries in a shared realm.
22:25
<Kris Kowal>
With SES, we’re already able to do this with a module-to-program transform, some overly constrained-limitations on what programs are valid, and by pitting all of JavaScript’s sharpest edges against each other.
22:27
<Kris Kowal>
The caveats go away if we have Module and something else that needs a name, like new Thing(globalThis, importHook) => {eval, Function, Module}.
22:28
<Kris Kowal>
Obligatory sketch of a functionally-equivalent isolated Compartment based on these building blocks: https://gist.github.com/kriskowal/f48fb0c68a70ccbde7cd32c85cddc63c
22:30
<Kris Kowal>
new (new Thing(global, {importHook})).Module(source, {importHook}) ensures that module sees only the globals on global and modules through importHook.
22:31
<Kris Kowal>
All the way through machinations like eval('import("module")) in the module source.
22:31
<Kris Kowal>
Script? Don’t know. Suggestion box is open.