Last active
July 9, 2022 00:59
-
-
Save kriskowal/f48fb0c68a70ccbde7cd32c85cddc63c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Compartment { | |
#modules = new Map(); | |
#descriptors = new Map(); | |
#referrers = new Map(); | |
#globalThis = Object.create(null); | |
constructor({ resolveHook, loadHook, globals }) { | |
this.#resolveHook = resolveHook; | |
this.#loadHook = loadHook; | |
this.#importHook = async (importSpecifier, importMeta) => { | |
const referrerSpecifier = this.#referrers.get(importMeta); | |
const fullSpecifier = this.#resolveHook(importSpecifier, referrerSpecifier); | |
return this.#load(fullSpecifier); | |
}; | |
this.#context = new ExecutionContext(this.#globalThis, this.#importHook); | |
Object.assign(this.#globalThis, this.#context); | |
Object.assign(this.#globalThis, globals); | |
}; | |
get globalThis() { | |
return this.#globalThis; | |
} | |
evaluate(script) { | |
return this.#context.eval(script); | |
}; | |
async #descriptor(specifier) { | |
let eventualDescriptor = this.#descriptors.get(specifier); | |
if (!eventualDescriptocr) { | |
eventualDescriptor = this.#loadHook(specifier); | |
this.#descriptors.set(specifier, eventualDescriptor); | |
} | |
return eventualDescriptor; | |
}; | |
async load(specifier) { | |
let eventualModule = this.#modules.get(specifier); | |
if (!eventualModule) { | |
const descriptor = await this.#descriptor(specifier); | |
eventualModule = await this.#load(descriptor); | |
this.#modules.set(specifier, eventualModule); | |
} | |
return eventualModule; | |
} | |
async #load(descriptor, specifier) { | |
if ('source' in descriptor) { | |
const importMeta = Object.create(null); | |
Object.assign(importMeta, descriptor.importMeta); | |
this.#referrers.set(importMeta, specifier); | |
return new this.#context.Module( | |
descriptor.source, | |
this.#importHook, | |
importMeta, | |
); | |
} else if ('specifier' in descriptor) { | |
const compartment = descriptor.compartment || this; | |
return compartment.load(descriptor); | |
} else if ('module' in descriptor) { | |
return descriptor.module; | |
} else { | |
throw new Error('Weird descriptor'); | |
} | |
}; | |
async import(specifier) { | |
return import(await this.#load(specifier)); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment