feat(endo): Add import
The import function most directly models the Node.js command line:
pass the path to the entry module and the capability to read files on
the corresponding file system.
Importing a module creates a compartment graph and executes the entry
module of the root compartment.
MODIFY
packages/endo/src/assemble.js
packages/endo/src/assemble.js
@@ -15,8 +15,8 @@ const q = JSON.stringify;
// 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.
+// Uses makeImportHook with the given "location" string of each compartment in
+// the DAG.
// Passes the given endowments and external modules into the root compartment
// only.
export const assemble = ({
@@ -60,7 +60,7 @@ export const assemble = ({
const compartment = new Compartment(endowments, modules, {
resolveHook: resolve,
- importHook: makeImportHook(descriptor.root)
+ importHook: makeImportHook(descriptor.location)
});
loaded[name] = compartment;

ADD
packages/endo/src/import.js
+/* global StaticModuleRecord */
+/* eslint no-shadow: 0 */
+
+import { compartmentMapForNodeModules } from "./compartmap.js";
+import { search } from "./search.js";
+import { assemble } from "./assemble.js";
+
+const decoder = new TextDecoder();
+
+const resolve = (rel, abs) => new URL(rel, abs).toString();
+
+const makeImportHookMaker = (read, baseLocation) => {
+ const makeImportHook = packageLocation => {
+ packageLocation = resolve(packageLocation, baseLocation);
+ const importHook = async moduleSpecifier => {
+ const moduleLocation = resolve(moduleSpecifier, packageLocation);
+ const moduleBytes = await read(moduleLocation);
+ const moduleSource = decoder.decode(moduleBytes);
+ return new StaticModuleRecord(moduleSource, moduleLocation);
+ };
+ return importHook;
+ };
+ return makeImportHook;
+};
+
+export const loadPath = async (read, modulePath) => {
+ const {
+ packageLocation,
+ packageDescriptorText,
+ moduleSpecifier
+ } = await search(read, modulePath);
+
+ const packageDescriptor = JSON.parse(packageDescriptorText);
+ const compartmentMap = await compartmentMapForNodeModules(
+ read,
+ packageLocation,
+ [],
+ packageDescriptor
+ );
+
+ const { compartments, main } = compartmentMap;
+
+ const makeImportHook = makeImportHookMaker(read, packageLocation);
+
+ const execute = async (endowments, modules) => {
+ const compartment = assemble({
+ name: main,
+ compartments,
+ makeImportHook,
+ endowments,
+ modules
+ });
+ return compartment.import(moduleSpecifier);
+ };
+
+ return { execute };
+};
+
+export const importPath = async (read, modulePath, endowments, modules) => {
+ const application = await loadPath(read, modulePath);
+ return application.execute(endowments, modules);
+};

feat(endo): Add import (#351)

The import function most directly models the Node.js command line:
pass the path to the entry module and the capability to read files on
the corresponding file system.
Importing a module creates a compartment graph and executes the entry
module of the root compartment.