Virtual module cannot express "export function x"
Current format only allows export var x = function equivalent.
In order to support export function x, we need to add an extra stage on initialization.
initialize(env, context) {
function x() {}
env.x = x
// this runs when VirtualModuleRecord.[[InitializeEnvironment]]
return () => {
// this runs when VirtualModuleRecord.[[ExecuteModule]]
}
}
Indeed. The initialization of modules has two steps: InitializeEnvironment and ExecuteModule. The InitializeEnvironment step can be skipped if the module body does not require it.
Both steps are especially meaningful with circular dependencies. Currently virtual modules only have one step, a function which is named initialize, which XS calls as its ExecuteModule step! Oops.
But I would prefer virtual modules to have two explicit hooks: initialize and execute. The initialize hook could be absent, but should be a synchronous function if present. The execute hook should be required but could be an asynchronous function.
The problem with 2 separate hooks they're not in the same lexical context.
const a = module {
export function a()
a()
}
Two separate hooks are not friendly to down-level compiling.
const a = {
initialize(env) {
function a() {}
env.a = a
},
execute(env) {
a() // Oops!
}
}
By this form, it can naturally inherit the lexical context.
initialize(env, context) {
function a() {}
env.a = a
// this runs when VirtualModuleRecord.[[InitializeEnvironment]]
return () => {
// this runs when VirtualModuleRecord.[[ExecuteModule]]
a() // Fine!
}
}
Would it make sense to have separate protocols for exec and init+exec?
I’m inclined to rename the existing initialize method (back) to execute given the distinctions revealed in this issue.
can't a transpiler just introduce a new unique variable? babel does that all over the place.
@devsnek To have separate initialize/execute methods? It doesn't work if they are called more than once, because they would use the same variable.
Babel compiles to SystemJS (the only module system that can emulate ESM) in a similar way to what's proposed in https://github.com/tc39/proposal-compartments/issues/70#issuecomment-1183039998:
System.register([], function (_export, _context) {
"use strict";
function a() {}
_export("a", a);
return {
setters: [],
execute: function () {
a();
}
};
});