Skip to content

Instantly share code, notes, and snippets.

@kriskowal
Last active July 9, 2022 00:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kriskowal/f48fb0c68a70ccbde7cd32c85cddc63c to your computer and use it in GitHub Desktop.
Save kriskowal/f48fb0c68a70ccbde7cd32c85cddc63c to your computer and use it in GitHub Desktop.
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