Skip to content

Commit

Permalink
feat(endo): Add assemble
Browse files Browse the repository at this point in the history
The compartment assembler takes a compartment map and builds the
corresponding compartment instances, feeding the modules exported by
each dependency into the dependee compartment's module map.
  • Loading branch information
kriskowal committed Jun 19, 2020
1 parent 4514f0a commit 84fd542
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions packages/endo/src/assemble.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* global Compartment */

import { resolve } from "./node-module-specifier.js";

const { entries } = Object;

const defaultCompartment = Compartment;

// q, as in quote, for strings in error messages.
const q = JSON.stringify;

// Assemble a DAG of compartments as declared in a compartment map starting at
// the named compartment and building all compartments that it depends upon,
// recursively threading the modules exported by one compartment into the
// compartment that imports them.
// Returns the root of the compartment DAG.
// Does not load or execute any modules.
// Uses makeImportHook with the given "root" string of each compartment in the
// DAG.
// Passes the given endowments and external modules into the root compartment
// only.
export const assemble = ({
name,
compartments,
makeImportHook,
parents = [],
loaded = {},
endowments = {},
modules = {},
Compartment = defaultCompartment
}) => {
const descriptor = compartments[name];
if (descriptor === undefined) {
throw new Error(
`Cannot assemble compartment graph with missing compartment descriptor named ${q(
name
)}, needed by ${parents.map(q).join(", ")}`
);
}
const result = loaded[name];
if (result !== undefined) {
return result;
}
if (parents.includes(name)) {
throw new Error(`Cannot assemble compartment graph that includes a cycle`);
}

for (const [inner, outer] of entries(descriptor.modules || {})) {
const { compartment: compartmentName, module: moduleSpecifier } = outer;
const compartment = assemble({
name: compartmentName,
compartments,
makeImportHook,
parents: [...parents, name],
loaded,
Compartment
});
modules[inner] = compartment.module(moduleSpecifier);
}

const compartment = new Compartment(endowments, modules, {
resolveHook: resolve,
importHook: makeImportHook(descriptor.root)
});

loaded[name] = compartment;
return compartment;
};

0 comments on commit 84fd542

Please sign in to comment.