Skip to content

Commit 31ab2f9

Browse files
committed
squashme poc
1 parent 6445f79 commit 31ab2f9

File tree

9 files changed

+126
-14
lines changed

9 files changed

+126
-14
lines changed

packages/compartment-mapper/demo/policy/index.mjs

+11-9
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ lockdown({
77
});
88

99
import fs from 'fs';
10-
import os from 'os';
11-
import assert from 'assert';
12-
import zlib from 'zlib';
13-
import path from 'path';
1410

1511
import { importLocation, makeArchive, parseArchive } from '../../index.js';
1612

@@ -98,13 +94,17 @@ const options = {
9894
console,
9995
process,
10096
},
97+
exitModuleImportHook: async specifier => {
98+
const module = await import(specifier);
99+
return module;
100+
},
101101
modules: {
102-
path: await addToCompartment('path', path),
103-
assert: await addToCompartment('assert', assert),
102+
// path: await addToCompartment('path', path),
103+
// assert: await addToCompartment('assert', assert),
104104
buffer: await addToCompartment('buffer', Object.create(null)), // imported but unused
105-
zlib: await addToCompartment('zlib', zlib),
106-
fs: await addToCompartment('fs', fs),
107-
os: await addToCompartment('os', os),
105+
// zlib: await addToCompartment('zlib', zlib),
106+
// fs: await addToCompartment('fs', fs),
107+
// os: await addToCompartment('os', os),
108108
},
109109
};
110110

@@ -124,6 +124,7 @@ console.log('\n\n________________________________________________ Archive\n');
124124
const archive = await makeArchive(readPower, entrypointPath, {
125125
modules: options.modules,
126126
policy: options.policy,
127+
exitModuleImportHook: options.exitModuleImportHook,
127128
});
128129
console.log('>----------makeArchive -> parseArchive');
129130
const application = await parseArchive(archive, '<unknown>', {
@@ -133,6 +134,7 @@ console.log('\n\n________________________________________________ Archive\n');
133134
const { namespace } = await application.import({
134135
globals: options.globals,
135136
modules: options.modules,
137+
exitModuleImportHook: options.exitModuleImportHook,
136138
});
137139
console.log('>----------import -> end');
138140
console.log(2, namespace.poem);

packages/compartment-mapper/src/archive.js

+2
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ const digestLocation = async (powers, moduleLocation, options) => {
259259
searchSuffixes = undefined,
260260
commonDependencies = undefined,
261261
policy = undefined,
262+
exitModuleImportHook = undefined,
262263
} = options || {};
263264
const { read, computeSha512 } = unpackReadPowers(powers);
264265
const {
@@ -299,6 +300,7 @@ const digestLocation = async (powers, moduleLocation, options) => {
299300
sources,
300301
compartments,
301302
exitModules,
303+
exitModuleImportHook, // should it get the archiveOnly hint somehow?
302304
computeSha512,
303305
searchSuffixes,
304306
);

packages/compartment-mapper/src/import-archive.js

+31-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
/** @typedef {import('./types.js').ComputeSourceLocationHook} ComputeSourceLocationHook */
1515
/** @typedef {import('./types.js').LoadArchiveOptions} LoadArchiveOptions */
1616
/** @typedef {import('./types.js').ExecuteOptions} ExecuteOptions */
17+
/** @typedef {import('./types.js').ExitModuleImportHook} ExitModuleImportHook */
1718

1819
import { ZipReader } from '@endo/zip';
1920
import { link } from './link.js';
@@ -78,6 +79,7 @@ const postponeErrorToExecute = errorMessage => {
7879
* @param {string} archiveLocation
7980
* @param {HashFn} [computeSha512]
8081
* @param {ComputeSourceLocationHook} [computeSourceLocation]
82+
* @param {ExitModuleImportHook} [exitModuleImportHook]
8183
* @returns {ArchiveImportHookMaker}
8284
*/
8385
const makeArchiveImportHookMaker = (
@@ -86,6 +88,7 @@ const makeArchiveImportHookMaker = (
8688
archiveLocation,
8789
computeSha512 = undefined,
8890
computeSourceLocation = undefined,
91+
exitModuleImportHook = undefined,
8992
) => {
9093
// per-assembly:
9194
/** @type {ArchiveImportHookMaker} */
@@ -97,6 +100,23 @@ const makeArchiveImportHookMaker = (
97100
// per-module:
98101
const module = modules[moduleSpecifier];
99102
if (module === undefined) {
103+
if (exitModuleImportHook) {
104+
console.error('#################x');
105+
const ns = await exitModuleImportHook(moduleSpecifier);
106+
if (ns) {
107+
return {
108+
record: freeze({
109+
imports: [],
110+
exports: Object.keys(ns),
111+
execute: moduleExports => {
112+
moduleExports.default = ns;
113+
Object.assign(moduleExports, ns);
114+
},
115+
}),
116+
specifier: moduleSpecifier,
117+
};
118+
}
119+
}
100120
throw new Error(
101121
`Cannot find module ${q(moduleSpecifier)} in package ${q(
102122
packageLocation,
@@ -205,6 +225,7 @@ export const parseArchive = async (
205225
computeSourceLocation = undefined,
206226
Compartment = DefaultCompartment,
207227
modules = undefined,
228+
exitModuleImportHook = undefined,
208229
} = options;
209230

210231
const archive = new ZipReader(archiveBytes, { name: archiveLocation });
@@ -264,6 +285,7 @@ export const parseArchive = async (
264285
archiveLocation,
265286
computeSha512,
266287
computeSourceLocation,
288+
exitModuleImportHook,
267289
);
268290
// A weakness of the current Compartment design is that the `modules` map
269291
// must be given a module namespace object that passes a brand check.
@@ -291,14 +313,21 @@ export const parseArchive = async (
291313

292314
/** @type {ExecuteFn} */
293315
const execute = async options => {
294-
const { globals, modules, transforms, __shimTransforms__, Compartment } =
295-
options || {};
316+
const {
317+
globals,
318+
modules,
319+
transforms,
320+
__shimTransforms__,
321+
Compartment,
322+
exitModuleImportHook,
323+
} = options || {};
296324
const makeImportHook = makeArchiveImportHookMaker(
297325
get,
298326
compartments,
299327
archiveLocation,
300328
computeSha512,
301329
computeSourceLocation,
330+
exitModuleImportHook,
302331
);
303332
const { compartment, pendingJobsPromise } = link(compartmentMap, {
304333
makeImportHook,

packages/compartment-mapper/src/import-hook.js

+16
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const nodejsConventionSearchSuffixes = [
6565
* @param {Sources} sources
6666
* @param {Record<string, CompartmentDescriptor>} compartmentDescriptors
6767
* @param {Record<string, any>} exitModules
68+
* @param {ImportHook=} exitModuleImportHook
6869
* @param {HashFn=} computeSha512
6970
* @param {Array<string>} searchSuffixes - Suffixes to search if the unmodified specifier is not found.
7071
* Pass [] to emulate Node.js’s strict behavior.
@@ -80,6 +81,7 @@ export const makeImportHookMaker = (
8081
sources = Object.create(null),
8182
compartmentDescriptors = Object.create(null),
8283
exitModules = Object.create(null),
84+
exitModuleImportHook = undefined,
8385
computeSha512 = undefined,
8486
searchSuffixes = nodejsConventionSearchSuffixes,
8587
) => {
@@ -156,6 +158,20 @@ export const makeImportHookMaker = (
156158
// Archived compartments are not executed.
157159
return freeze({ imports: [], exports: [], execute() {} });
158160
}
161+
if (exitModuleImportHook) {
162+
console.error('#################i');
163+
const ns = await exitModuleImportHook(moduleSpecifier);
164+
if (ns) {
165+
return freeze({
166+
imports: [],
167+
exports: Object.keys(ns),
168+
execute: moduleExports => {
169+
moduleExports.default = ns; // Why is typescript complaining about this?
170+
Object.assign(moduleExports, ns);
171+
},
172+
});
173+
}
174+
}
159175
return deferError(
160176
moduleSpecifier,
161177
new Error(

packages/compartment-mapper/src/import.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,21 @@ export const loadLocation = async (readPowers, moduleLocation, options) => {
7070

7171
/** @type {ExecuteFn} */
7272
const execute = async (options = {}) => {
73-
const { globals, modules, transforms, __shimTransforms__, Compartment } =
74-
options;
73+
const {
74+
globals,
75+
modules,
76+
transforms,
77+
__shimTransforms__,
78+
Compartment,
79+
exitModuleImportHook,
80+
} = options;
7581
const makeImportHook = makeImportHookMaker(
7682
readPowers,
7783
packageLocation,
7884
undefined,
7985
compartmentMap.compartments,
80-
undefined,
86+
modules,
87+
exitModuleImportHook,
8188
undefined,
8289
searchSuffixes,
8390
);

packages/compartment-mapper/src/types.js

+8
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,12 @@ export {};
225225
* @returns {string|undefined} sourceLocation
226226
*/
227227

228+
/**
229+
* @callback ExitModuleImportHook
230+
* @param {string} specifier
231+
* @returns {Promise<object>} module namespace
232+
*/
233+
228234
/**
229235
* @typedef {object} LoadArchiveOptions
230236
* @property {string} [expectedSha512]
@@ -239,6 +245,7 @@ export {};
239245
* @property {Array<Transform>} [transforms]
240246
* @property {Array<Transform>} [__shimTransforms__]
241247
* @property {Record<string, object>} [modules]
248+
* @property {ExitModuleImportHook} [exitModuleImportHook]
242249
* @property {Record<string, object>} [attenuations]
243250
* @property {Compartment} [Compartment]
244251
*/
@@ -310,6 +317,7 @@ export {};
310317
* @typedef {object} ArchiveOptions
311318
* @property {ModuleTransforms} [moduleTransforms]
312319
* @property {Record<string, any>} [modules]
320+
* @property {ExitModuleImportHook} [exitModuleImportHook]
313321
* @property {boolean} [dev]
314322
* @property {object} [policy]
315323
* @property {Set<string>} [tags]

packages/compartment-mapper/test/fixtures-policy/node_modules/app/importActualBuiltin.js

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compartment-mapper/test/scaffold.js

+18
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export function scaffold(
7878
tags = undefined,
7979
searchSuffixes = undefined,
8080
commonDependencies = undefined,
81+
additionalOptions = {},
8182
} = {},
8283
) {
8384
// wrapping each time allows for convenient use of test.only
@@ -120,11 +121,13 @@ export function scaffold(
120121
tags,
121122
searchSuffixes,
122123
commonDependencies,
124+
...additionalOptions,
123125
});
124126
const { namespace } = await application.import({
125127
globals: { ...globals, ...addGlobals },
126128
modules,
127129
Compartment,
130+
...additionalOptions,
128131
});
129132
return namespace;
130133
});
@@ -142,6 +145,7 @@ export function scaffold(
142145
tags,
143146
searchSuffixes,
144147
commonDependencies,
148+
...additionalOptions,
145149
});
146150
return namespace;
147151
});
@@ -159,6 +163,7 @@ export function scaffold(
159163
tags,
160164
searchSuffixes,
161165
commonDependencies,
166+
...additionalOptions,
162167
});
163168
const application = await parseArchive(archive, '<unknown>', {
164169
modules: Object.fromEntries(
@@ -175,6 +180,7 @@ export function scaffold(
175180
globals: { ...globals, ...addGlobals },
176181
modules,
177182
Compartment,
183+
...additionalOptions,
178184
});
179185
return namespace;
180186
},
@@ -194,6 +200,7 @@ export function scaffold(
194200
tags,
195201
searchSuffixes,
196202
commonDependencies,
203+
...additionalOptions,
197204
});
198205
const prefixArchive = new Uint8Array(archive.length + 10);
199206
prefixArchive.set(archive, 10);
@@ -206,6 +213,7 @@ export function scaffold(
206213
globals: { ...globals, ...addGlobals },
207214
modules,
208215
Compartment,
216+
...additionalOptions,
209217
});
210218
return namespace;
211219
},
@@ -237,6 +245,7 @@ export function scaffold(
237245
tags,
238246
searchSuffixes,
239247
commonDependencies,
248+
...additionalOptions,
240249
});
241250
const application = await loadArchive(fakeRead, 'app.agar', {
242251
modules,
@@ -246,6 +255,7 @@ export function scaffold(
246255
globals: { ...globals, ...addGlobals },
247256
modules,
248257
Compartment,
258+
...additionalOptions,
249259
});
250260
return namespace;
251261
},
@@ -277,11 +287,13 @@ export function scaffold(
277287
tags,
278288
searchSuffixes,
279289
commonDependencies,
290+
...additionalOptions,
280291
});
281292
const { namespace } = await importArchive(fakeRead, 'app.agar', {
282293
globals: { ...globals, ...addGlobals },
283294
modules,
284295
Compartment,
296+
...additionalOptions,
285297
});
286298
return namespace;
287299
},
@@ -299,6 +311,7 @@ export function scaffold(
299311
tags,
300312
searchSuffixes,
301313
commonDependencies,
314+
...additionalOptions,
302315
});
303316

304317
const archiveBytes = await makeArchive(readPowers, fixture, {
@@ -307,6 +320,7 @@ export function scaffold(
307320
tags,
308321
searchSuffixes,
309322
commonDependencies,
323+
...additionalOptions,
310324
});
311325

312326
const { computeSha512 } = readPowers;
@@ -319,6 +333,7 @@ export function scaffold(
319333
tags,
320334
computeSha512,
321335
expectedSha512,
336+
...additionalOptions,
322337
},
323338
);
324339

@@ -336,6 +351,7 @@ export function scaffold(
336351
tags,
337352
searchSuffixes,
338353
commonDependencies,
354+
...additionalOptions,
339355
});
340356

341357
const archive = await makeArchive(readPowers, fixture, {
@@ -344,6 +360,7 @@ export function scaffold(
344360
tags,
345361
searchSuffixes,
346362
commonDependencies,
363+
...additionalOptions,
347364
});
348365

349366
const reader = new ZipReader(archive);
@@ -360,6 +377,7 @@ export function scaffold(
360377
parseArchive(corruptArchive, 'app.agar', {
361378
computeSha512,
362379
expectedSha512,
380+
...additionalOptions,
363381
}),
364382
{
365383
message: /compartment map failed a SHA-512 integrity check/,

0 commit comments

Comments
 (0)