feat(compartment-mapper): importHook redirects + updates compartment map when candidate is present in moduleDescriptors
MODIFY
packages/compartment-mapper/src/import-hook.js
packages/compartment-mapper/src/import-hook.js
/** @typedef {import('ses').ImportHook} ImportHook */
/** @typedef {import('ses').StaticModuleType} StaticModuleType */
+/** @typedef {import('ses').RedirectStaticModuleInterface} RedirectStaticModuleInterface */
/** @typedef {import('./types.js').ReadFn} ReadFn */
/** @typedef {import('./types.js').ReadPowers} ReadPowers */
/** @typedef {import('./types.js').HashFn} HashFn */
@@ -70,14 +71,16 @@ export const makeImportHookMaker = (
_packageName,
parse,
shouldDeferError,
+ compartments,
) => {
// per-compartment:
packageLocation = resolveLocation(packageLocation, baseLocation);
const packageSources = sources[packageLocation] || Object.create(null);
sources[packageLocation] = packageSources;
const compartmentDescriptor = compartmentDescriptors[packageLocation] || {};
- const { modules = Object.create(null) } = compartmentDescriptor;
- compartmentDescriptor.modules = modules;
+ const { modules: moduleDescriptors = Object.create(null) } =
+ compartmentDescriptor;
+ compartmentDescriptor.modules = moduleDescriptors;
/**
* @param {string} specifier
@@ -152,6 +155,35 @@ export const makeImportHookMaker = (
const { read } = unpackReadPowers(readPowers);
for (const candidateSpecifier of candidates) {
+ const candidateModuleDescriptor = moduleDescriptors[candidateSpecifier];
+ if (candidateModuleDescriptor !== undefined) {
+ const { compartment: candidateCompartmentName = packageLocation } =
+ candidateModuleDescriptor;
+ const candidateCompartment = compartments[candidateCompartmentName];
+ if (candidateCompartment === undefined) {
+ throw new Error(
+ `compartment missing for candidate ${candidateSpecifier} in ${candidateCompartmentName}`,
+ );
+ }
+ // modify compartmentMap to include this redirect
+ const candidateCompartmentDescriptor =
+ compartmentDescriptors[candidateCompartmentName];
+ if (candidateCompartmentDescriptor === undefined) {
+ throw new Error(
+ `compartmentDescriptor missing for candidate ${candidateSpecifier} in ${candidateCompartmentName}`,
+ );
+ }
+ candidateCompartmentDescriptor.modules[moduleSpecifier] =
+ candidateModuleDescriptor;
+ // return a redirect
+ /** @type {RedirectStaticModuleInterface} */
+ const record = {
+ specifier: candidateSpecifier,
+ compartment: candidateCompartment,
+ };
+ return record;
+ }
+
// Using a specifier as a location.
// This is not always valid.
// But, for Node.js, when the specifier is relative and not a directory
@@ -184,7 +216,7 @@ export const makeImportHookMaker = (
// Facilitate a redirect if the returned record has a different
// module specifier than the requested one.
if (candidateSpecifier !== moduleSpecifier) {
- modules[moduleSpecifier] = {
+ moduleDescriptors[moduleSpecifier] = {
module: candidateSpecifier,
compartment: packageLocation,
};

MODIFY
packages/compartment-mapper/src/import.js
packages/compartment-mapper/src/import.js
@@ -69,7 +69,12 @@ export const loadLocation = async (readPowers, moduleLocation, options) => {
const execute = async (options = {}) => {
const { globals, modules, transforms, __shimTransforms__, Compartment } =
options;
- const makeImportHook = makeImportHookMaker(readPowers, packageLocation);
+ const makeImportHook = makeImportHookMaker(
+ readPowers,
+ packageLocation,
+ undefined,
+ compartmentMap.compartments,
+ );
const { compartment } = link(compartmentMap, {
makeImportHook,
parserForLanguage,

MODIFY
packages/compartment-mapper/src/link.js
packages/compartment-mapper/src/link.js
@@ -213,6 +213,8 @@ const makeModuleMapHook = (
const moduleDescriptor = moduleDescriptors[moduleSpecifier];
if (moduleDescriptor !== undefined) {
+ // "foreignCompartmentName" refers to the compartment which
+ // may differ from the current compartment
const {
compartment: foreignCompartmentName = compartmentName,
module: foreignModuleSpecifier,
@@ -380,7 +382,13 @@ export const link = (
}
};
- const importHook = makeImportHook(location, name, parse, shouldDeferError);
+ const importHook = makeImportHook(
+ location,
+ name,
+ parse,
+ shouldDeferError,
+ compartments,
+ );
const moduleMapHook = makeModuleMapHook(
compartmentDescriptor,
compartments,

MODIFY
packages/compartment-mapper/src/types.js
packages/compartment-mapper/src/types.js
@@ -189,6 +189,7 @@ export {};
* @param {string} packageName
* @param {ParseFn} parse
* @param {ShouldDeferError} shouldDeferError
+ * @param {Record<string, Compartment>} compartments
* @returns {ImportHook}
*/

feat(compartment-mapper): importHook redirects + updates compartment map when candidate is present in moduleDescriptors