03:42
<Jack Works>
there are 2 things in the language have this property, export function and export var.
03:42
<Jack Works>
I can see two way only one way to solve this problem but they all have their own problems
03:49
<Jack Works>

having two stage initialization for virtual modules, just like systemjs

const record = static module {
    export function a() {}
    console.log(a)
}

becomes

const record = {
    bindings: [{export: "a"}],
    initialize(env, context) {
        function a() {}
        env.a = a
        return () => {
            console.log(a)
        }
    }
}
03:50
<Jack Works>
but the problem is, it is allowing the virtual module to run some arbitrary code before the evaluation stage
03:59
<guybedford>
That's correct about the emulation. But SystemJS has very different contraints of course, and yes likely doesn't fit this model. If needing this level of parity you might be better off just using a static record from a string source to do the emulation I think, then passing bindings through import.meta or custom imports?
04:02
<Jack Works>
I'm considering (and my use case need) an eval-free version of downlevel compiling module blocks, so I hope the Virtual Module can do the full emulation
04:06
<Kris Kowal>
What if a is rewritten to env.a at every mention?
04:07
<Jack Works>
What if a is rewritten to env.a at every mention?
The problem is circular reference + function hoist
04:07
<Jack Works>

Consider these two modules compiled into Virtual module:

import {b} from './b'
export function a() {}
console.log(b)
import {a} from './a'
export function b() {}
console.log(a)
04:11
<Jack Works>
oh wait, this works. let me consider that again
05:08
<Jack Works>
I compared it with CommonJS (because the code above works after being compiled into CommonJS).
05:10
<Jack Works>
const record = {
    bindings: [],
    async initialize(env, context) {
        function a() {}
        env.a = a
        
        const mod = await context.import("./b")
        console.log(mod.b)
    }
}

But this is problematic because of then-able

05:13
<Jack Works>

So CommonJS behave more like this. They also have a "pre-evaluation" to setup those bindings (before and after require calls)

"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "b", {
    enumerable: true,
    get: ()=>b
});
const _a = require("./a");
console.log(_a.a);
function b() {}
07:04
<Jack Works>

I can think of some way to alleviate this problem, to make env and context in some kind of dead zone in this pre-evaluation stage, which means

    initialize(env, context) {
        // when in here, context is an empty object with no "meta" or "import" property on it
        // when in here, any other property access than "a" throws a TDZ error
        function a() {}
        env.a = a
        return () => {
            // now access env and context is ok
            env.console.log(a)
        }
    }

Construct all assets => Link stage => Pre-evaluation (run all initialize function with TDZ env and context and collect the return closure) => env and context out of TDZ => Evaluation