@endo/compartment-mapper 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -328,6 +328,20 @@ These will be appended to each module from the archive, for debugging purposes.
328
328
  The `@endo/bundle-source` and `@endo/import-bundle` tools integrate source maps
329
329
  for an end-to-end debugging experience.
330
330
 
331
+ # XS (experimental)
332
+
333
+ The Compartment Mapper can use native XS `Compartment` and `ModuleSource` under
334
+ certain conditions:
335
+
336
+ 1. The application must be an XS script that was compiled with the `xs`
337
+ package condition.
338
+ This causes `ses`, `@endo/module-source`, and `@endo/import-bundle` to
339
+ provide slightly different implementations that can fall through to native
340
+ behavior.
341
+ 2. The application must opt-in with the `__native__: true` option on any
342
+ of the compartment mapper methods that import modules like `importLocation`
343
+ and `importArchive`.
344
+
331
345
  # Design
332
346
 
333
347
  Each of the workflows the compartment mapper executes a portion of one sequence
@@ -0,0 +1,2 @@
1
+ export { defaultParserForLanguage } from "./src/import-archive-all-parsers.js";
2
+ //# sourceMappingURL=import-archive-all-parsers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-archive-all-parsers.d.ts","sourceRoot":"","sources":["import-archive-all-parsers.js"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export { defaultParserForLanguage } from './src/import-archive-all-parsers.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@endo/compartment-mapper",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "The compartment mapper assembles Node applications in a sandbox",
5
5
  "keywords": [
6
6
  "node",
@@ -32,7 +32,12 @@
32
32
  "./capture-lite.js": "./capture-lite.js",
33
33
  "./import-archive.js": "./import-archive.js",
34
34
  "./import-archive-lite.js": "./import-archive-lite.js",
35
- "./import-archive-parsers.js": "./import-archive-parsers.js",
35
+ "./import-archive-parsers.js": {
36
+ "xs": "./import-archive-all-parsers.js",
37
+ "node": "./import-archive-all-parsers.js",
38
+ "default": "./import-archive-parsers.js"
39
+ },
40
+ "./import-archive-all-parsers.js": "./import-archive-all-parsers.js",
36
41
  "./bundle.js": "./bundle.js",
37
42
  "./node-powers.js": "./node-powers.js",
38
43
  "./node-modules.js": "./node-modules.js",
@@ -52,10 +57,10 @@
52
57
  },
53
58
  "dependencies": {
54
59
  "@endo/cjs-module-analyzer": "^1.0.9",
55
- "@endo/module-source": "^1.1.2",
60
+ "@endo/module-source": "^1.2.0",
56
61
  "@endo/trampoline": "^1.0.3",
57
62
  "@endo/zip": "^1.0.9",
58
- "ses": "^1.10.0"
63
+ "ses": "^1.11.0"
59
64
  },
60
65
  "devDependencies": {
61
66
  "ava": "^6.1.3",
@@ -109,5 +114,5 @@
109
114
  "typeCoverage": {
110
115
  "atLeast": 86.14
111
116
  },
112
- "gitHead": "5486ed1f238104716b6a8321b977fbc508ef80e1"
117
+ "gitHead": "e0683e0bfdbfc84351af332c9e78813d7b67ef89"
113
118
  }
@@ -1,7 +1,4 @@
1
- export function makeArchiveCompartmentMap(compartmentMap: CompartmentMapDescriptor, sources: Sources): {
2
- archiveCompartmentMap: CompartmentMapDescriptor;
3
- archiveSources: Sources;
4
- };
1
+ export function makeArchiveCompartmentMap(compartmentMap: CompartmentMapDescriptor, sources: Sources): ArchiveResult;
5
2
  export function makeAndHashArchiveFromMap(powers: ReadFn | ReadPowers, compartmentMap: CompartmentMapDescriptor, options?: ArchiveLiteOptions | undefined): Promise<{
6
3
  bytes: Uint8Array;
7
4
  sha512?: string;
@@ -12,6 +9,7 @@ export function hashFromMap(powers: HashPowers, compartmentMap: CompartmentMapDe
12
9
  export function writeArchiveFromMap(write: WriteFn, readPowers: ReadFn | ReadPowers, archiveLocation: string, compartmentMap: CompartmentMapDescriptor, options?: ArchiveLiteOptions | undefined): Promise<void>;
13
10
  import type { CompartmentMapDescriptor } from './types.js';
14
11
  import type { Sources } from './types.js';
12
+ import type { ArchiveResult } from './types.js';
15
13
  import type { ReadFn } from './types.js';
16
14
  import type { ReadPowers } from './types.js';
17
15
  import type { ArchiveLiteOptions } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"archive-lite.d.ts","sourceRoot":"","sources":["archive-lite.js"],"names":[],"mappings":"AAiRO,0DAJI,wBAAwB,WACxB,OAAO,GACL;IAAC,qBAAqB,EAAE,wBAAwB,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAC,CAmCtF;AAyGM,kDALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC,CAmBzD;AAQM,2CALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,UAAU,CAAC,CAS/B;AAQM,mCALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,UAAU,CAAC,CAS/B;AAQM,oCALI,UAAU,kBACV,wBAAwB,6CAEtB,OAAO,CAAC,MAAM,CAAC,CAU3B;AASM,2CANI,OAAO,cACP,MAAM,GAAG,UAAU,mBACnB,MAAM,kBACN,wBAAwB,2DAgBlC;8CAncS,YAAY;6BAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;wCAAZ,YAAY;gCAAZ,YAAY;6BAAZ,YAAY"}
1
+ {"version":3,"file":"archive-lite.d.ts","sourceRoot":"","sources":["archive-lite.js"],"names":[],"mappings":"AAmHO,0DAJI,wBAAwB,WACxB,OAAO,GACL,aAAa,CAiBzB;AAyGM,kDALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC,CAmBzD;AAQM,2CALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,UAAU,CAAC,CAS/B;AAQM,mCALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,UAAU,CAAC,CAS/B;AAQM,oCALI,UAAU,kBACV,wBAAwB,6CAEtB,OAAO,CAAC,MAAM,CAAC,CAU3B;AASM,2CANI,OAAO,cACP,MAAM,GAAG,UAAU,mBACnB,MAAM,kBACN,wBAAwB,2DAgBlC;8CApRS,YAAY;6BAAZ,YAAY;mCAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;wCAAZ,YAAY;gCAAZ,YAAY;6BAAZ,YAAY"}
@@ -33,12 +33,11 @@
33
33
  /**
34
34
  * @import {
35
35
  * ArchiveLiteOptions,
36
+ * ArchiveResult,
36
37
  * ArchiveWriter,
37
38
  * CaptureSourceLocationHook,
38
- * CompartmentDescriptor,
39
39
  * CompartmentMapDescriptor,
40
40
  * HashPowers,
41
- * ModuleDescriptor,
42
41
  * ReadFn,
43
42
  * ReadPowers,
44
43
  * Sources,
@@ -54,12 +53,8 @@ import {
54
53
  makeImportHookMaker,
55
54
  } from './import-hook.js';
56
55
  import { unpackReadPowers } from './powers.js';
57
- import {
58
- assertCompartmentMap,
59
- stringCompare,
60
- pathCompare,
61
- } from './compartment-map.js';
62
56
  import { detectAttenuators } from './policy.js';
57
+ import { digestCompartmentMap } from './digest.js';
63
58
 
64
59
  const textEncoder = new TextEncoder();
65
60
 
@@ -72,160 +67,7 @@ const { assign, create, freeze } = Object;
72
67
  */
73
68
  const resolveLocation = (rel, abs) => new URL(rel, abs).toString();
74
69
 
75
- const { keys, entries, fromEntries } = Object;
76
-
77
- /**
78
- * We attempt to produce compartment maps that are consistent regardless of
79
- * whether the packages were originally laid out on disk for development or
80
- * production, and other trivia like the fully qualified path of a specific
81
- * installation.
82
- *
83
- * Naming compartments for the self-ascribed name and version of each Node.js
84
- * package is insufficient because they are not guaranteed to be unique.
85
- * Dependencies do not necessarilly come from the npm registry and may be
86
- * for example derived from fully qualified URL's or Github org and project
87
- * names.
88
- * Package managers are also not required to fully deduplicate the hard
89
- * copy of each package even when they are identical resources.
90
- * Duplication is undesirable, but we elect to defer that problem to solutions
91
- * in the package managers, as the alternative would be to consistently hash
92
- * the original sources of the packages themselves, which may not even be
93
- * available much less pristine for us.
94
- *
95
- * So, instead, we use the lexically least path of dependency names, delimited
96
- * by hashes.
97
- * The compartment maps generated by the ./node-modules.js tooling pre-compute
98
- * these traces for our use here.
99
- * We sort the compartments lexically on their self-ascribed name and version,
100
- * and use the lexically least dependency name path as a tie-breaker.
101
- * The dependency path is logical and orthogonal to the package manager's
102
- * actual installation location, so should be orthogonal to the vagaries of the
103
- * package manager's deduplication algorithm.
104
- *
105
- * @param {Record<string, CompartmentDescriptor>} compartments
106
- * @returns {Record<string, string>} map from old to new compartment names.
107
- */
108
- const renameCompartments = compartments => {
109
- /** @type {Record<string, string>} */
110
- const compartmentRenames = create(null);
111
- let index = 0;
112
- let prev = '';
113
-
114
- // The sort below combines two comparators to avoid depending on sort
115
- // stability, which became standard as recently as 2019.
116
- // If that date seems quaint, please accept my regards from the distant past.
117
- // We are very proud of you.
118
- const compartmentsByPath = Object.entries(compartments)
119
- .map(([name, compartment]) => ({
120
- name,
121
- path: compartment.path,
122
- label: compartment.label,
123
- }))
124
- .sort((a, b) => {
125
- if (a.label === b.label) {
126
- assert(a.path !== undefined && b.path !== undefined);
127
- return pathCompare(a.path, b.path);
128
- }
129
- return stringCompare(a.label, b.label);
130
- });
131
-
132
- for (const { name, label } of compartmentsByPath) {
133
- if (label === prev) {
134
- compartmentRenames[name] = `${label}-n${index}`;
135
- index += 1;
136
- } else {
137
- compartmentRenames[name] = label;
138
- prev = label;
139
- index = 1;
140
- }
141
- }
142
- return compartmentRenames;
143
- };
144
-
145
- /**
146
- * @param {Record<string, CompartmentDescriptor>} compartments
147
- * @param {Sources} sources
148
- * @param {Record<string, string>} compartmentRenames
149
- */
150
- const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
151
- const result = create(null);
152
- for (const compartmentName of keys(compartmentRenames)) {
153
- const compartment = compartments[compartmentName];
154
- const { name, label, retained: compartmentRetained, policy } = compartment;
155
- if (compartmentRetained) {
156
- // rename module compartments
157
- /** @type {Record<string, ModuleDescriptor>} */
158
- const modules = create(null);
159
- const compartmentModules = compartment.modules;
160
- if (compartment.modules) {
161
- for (const name of keys(compartmentModules).sort()) {
162
- const { retained: moduleRetained, ...retainedModule } =
163
- compartmentModules[name];
164
- if (moduleRetained) {
165
- if (retainedModule.compartment !== undefined) {
166
- modules[name] = {
167
- ...retainedModule,
168
- compartment: compartmentRenames[retainedModule.compartment],
169
- };
170
- } else {
171
- modules[name] = retainedModule;
172
- }
173
- }
174
- }
175
- }
176
-
177
- // integrate sources into modules
178
- const compartmentSources = sources[compartmentName];
179
- if (compartmentSources) {
180
- for (const name of keys(compartmentSources).sort()) {
181
- const source = compartmentSources[name];
182
- const { location, parser, exit, sha512, deferredError } = source;
183
- if (location !== undefined) {
184
- modules[name] = {
185
- location,
186
- parser,
187
- sha512,
188
- };
189
- } else if (exit !== undefined) {
190
- modules[name] = {
191
- exit,
192
- };
193
- } else if (deferredError !== undefined) {
194
- modules[name] = {
195
- deferredError,
196
- };
197
- }
198
- }
199
- }
200
-
201
- result[compartmentRenames[compartmentName]] = {
202
- name,
203
- label,
204
- location: compartmentRenames[compartmentName],
205
- modules,
206
- policy,
207
- // `scopes`, `types`, and `parsers` are not necessary since every
208
- // loadable module is captured in `modules`.
209
- };
210
- }
211
- }
212
-
213
- return result;
214
- };
215
-
216
- /**
217
- * @param {Sources} sources
218
- * @param {Record<string, string>} compartmentRenames
219
- * @returns {Sources}
220
- */
221
- const renameSources = (sources, compartmentRenames) => {
222
- return fromEntries(
223
- entries(sources).map(([name, compartmentSources]) => [
224
- compartmentRenames[name],
225
- compartmentSources,
226
- ]),
227
- );
228
- };
70
+ const { keys } = Object;
229
71
 
230
72
  /**
231
73
  * @param {ArchiveWriter} archive
@@ -269,41 +111,23 @@ const captureSourceLocations = async (sources, captureSourceLocation) => {
269
111
  /**
270
112
  * @param {CompartmentMapDescriptor} compartmentMap
271
113
  * @param {Sources} sources
272
- * @returns {{archiveCompartmentMap: CompartmentMapDescriptor, archiveSources: Sources}}
114
+ * @returns {ArchiveResult}
273
115
  */
274
116
  export const makeArchiveCompartmentMap = (compartmentMap, sources) => {
275
117
  const {
276
- compartments,
277
- entry: { compartment: entryCompartmentName, module: entryModuleSpecifier },
278
- } = compartmentMap;
279
-
280
- const compartmentRenames = renameCompartments(compartments);
281
- const archiveCompartments = translateCompartmentMap(
282
- compartments,
283
- sources,
118
+ compartmentMap: archiveCompartmentMap,
119
+ sources: archiveSources,
120
+ oldToNewCompartmentNames,
121
+ newToOldCompartmentNames,
122
+ compartmentRenames,
123
+ } = digestCompartmentMap(compartmentMap, sources);
124
+ return {
125
+ archiveCompartmentMap,
126
+ archiveSources,
127
+ oldToNewCompartmentNames,
128
+ newToOldCompartmentNames,
284
129
  compartmentRenames,
285
- );
286
- const archiveEntryCompartmentName = compartmentRenames[entryCompartmentName];
287
- const archiveSources = renameSources(sources, compartmentRenames);
288
-
289
- const archiveCompartmentMap = {
290
- // TODO migrate tags to conditions
291
- // https://github.com/endojs/endo/issues/2388
292
- tags: [],
293
- entry: {
294
- compartment: archiveEntryCompartmentName,
295
- module: entryModuleSpecifier,
296
- },
297
- compartments: archiveCompartments,
298
130
  };
299
-
300
- // Cross-check:
301
- // We assert that we have constructed a valid compartment map, not because it
302
- // might not be, but to ensure that the assertCompartmentMap function can
303
- // accept all valid compartment maps.
304
- assertCompartmentMap(archiveCompartmentMap);
305
-
306
- return { archiveCompartmentMap, archiveSources };
307
131
  };
308
132
 
309
133
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["archive.js"],"names":[],"mappings":"AA2DO,2CALI,MAAM,GAAG,UAAU,kBACnB,MAAM,yCAEJ,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC,CAiBzD;AAQM,oCALI,MAAM,GAAG,UAAU,kBACnB,MAAM,yCAEJ,OAAO,CAAC,UAAU,CAAC,CAsC/B;AAQM,oCALI,MAAM,GAAG,UAAU,kBACnB,MAAM,yCAEJ,OAAO,CAAC,UAAU,CAAC,CAuC/B;AAQM,qCALI,UAAU,kBACV,MAAM,yCAEJ,OAAO,CAAC,MAAM,CAAC,CAuC3B;AASM,oCANI,OAAO,cACP,MAAM,GAAG,UAAU,mBACnB,MAAM,kBACN,MAAM,uDA8ChB;4BA5OS,YAAY;gCAAZ,YAAY;oCAAZ,YAAY;gCAAZ,YAAY;6BAAZ,YAAY"}
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["archive.js"],"names":[],"mappings":"AA2DO,2CALI,MAAM,GAAG,UAAU,kBACnB,MAAM,yCAEJ,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC,CAiBzD;AAQM,oCALI,MAAM,GAAG,UAAU,kBACnB,MAAM,yCAEJ,OAAO,CAAC,UAAU,CAAC,CAwC/B;AAQM,oCALI,MAAM,GAAG,UAAU,kBACnB,MAAM,yCAEJ,OAAO,CAAC,UAAU,CAAC,CAyC/B;AAQM,qCALI,UAAU,kBACV,MAAM,yCAEJ,OAAO,CAAC,MAAM,CAAC,CAyC3B;AASM,oCANI,OAAO,cACP,MAAM,GAAG,UAAU,mBACnB,MAAM,kBACN,MAAM,uDAgDhB;4BApPS,YAAY;gCAAZ,YAAY;oCAAZ,YAAY;gCAAZ,YAAY;6BAAZ,YAAY"}
package/src/archive.js CHANGED
@@ -85,6 +85,7 @@ export const makeArchive = async (powers, moduleLocation, options = {}) => {
85
85
  dev,
86
86
  tags,
87
87
  conditions = tags,
88
+ strict = false,
88
89
  commonDependencies,
89
90
  policy,
90
91
  languageForExtension,
@@ -99,6 +100,7 @@ export const makeArchive = async (powers, moduleLocation, options = {}) => {
99
100
  } = assignParserForLanguage(options);
100
101
  const compartmentMap = await mapNodeModules(powers, moduleLocation, {
101
102
  dev,
103
+ strict,
102
104
  conditions,
103
105
  commonDependencies,
104
106
  policy,
@@ -129,6 +131,7 @@ export const mapLocation = async (powers, moduleLocation, options = {}) => {
129
131
  dev,
130
132
  tags,
131
133
  conditions = tags,
134
+ strict = false,
132
135
  commonDependencies,
133
136
  policy,
134
137
  parserForLanguage,
@@ -144,6 +147,7 @@ export const mapLocation = async (powers, moduleLocation, options = {}) => {
144
147
 
145
148
  const compartmentMap = await mapNodeModules(powers, moduleLocation, {
146
149
  dev,
150
+ strict,
147
151
  conditions,
148
152
  commonDependencies,
149
153
  policy,
@@ -174,6 +178,7 @@ export const hashLocation = async (powers, moduleLocation, options = {}) => {
174
178
  dev,
175
179
  tags,
176
180
  conditions = tags,
181
+ strict = false,
177
182
  commonDependencies,
178
183
  policy,
179
184
  parserForLanguage,
@@ -189,6 +194,7 @@ export const hashLocation = async (powers, moduleLocation, options = {}) => {
189
194
 
190
195
  const compartmentMap = await mapNodeModules(powers, moduleLocation, {
191
196
  dev,
197
+ strict,
192
198
  conditions,
193
199
  commonDependencies,
194
200
  policy,
@@ -226,6 +232,7 @@ export const writeArchive = async (
226
232
  dev,
227
233
  tags,
228
234
  conditions = tags,
235
+ strict = false,
229
236
  commonDependencies,
230
237
  policy,
231
238
  parserForLanguage,
@@ -240,6 +247,7 @@ export const writeArchive = async (
240
247
  } = assignParserForLanguage(options);
241
248
  const compartmentMap = await mapNodeModules(readPowers, moduleLocation, {
242
249
  dev,
250
+ strict,
243
251
  conditions,
244
252
  commonDependencies,
245
253
  policy,
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["bundle.js"],"names":[],"mappings":"AAgOO,uCALI,MAAM,GAAG,UAAU,GAAG,eAAe,kBACrC,MAAM,yCAEJ,OAAO,CAAC,MAAM,CAAC,CAgN3B;AASM,mCANI,OAAO,QACP,MAAM,kBACN,MAAM,kBACN,MAAM,uDAahB;;;;;;;;;;;gBA5aa,MAAM,MAAM;;;;;;;cAOZ,MAAM,MAAM;;;;;;;oBAIZ,MAAM,MAAM;;;;;wBAIZ,MAAM,MAAM;;yBAKH,oBAAoB,SAA9B,OAAS;SAER,MAAM;qBACN,MAAM;qBACN,MAAM;YACN,MAAM;YACN,gBAAgB,GAAG,oBAAoB;qBACvC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;oBACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;WACtB,UAAU;WACV,MAAM;gBACN,UAAU;;0BAID,oBAAoB,SAA9B,OAAS,aAEX,YAAY,CAAC,oBAAoB,CAAC,KAChC,UAAU;2BAIA,oBAAoB,SAA9B,OAAS;aAER,MAAM;mBACN,aAAa,CAAC,oBAAoB,CAAC;;4BAlDvC,YAAY;gCAAZ,YAAY;qCAAZ,YAAY;oCAAZ,YAAY;6BAAZ,YAAY;sCAVZ,KAAK"}
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["bundle.js"],"names":[],"mappings":"AAsOO,uCALI,MAAM,GAAG,UAAU,GAAG,eAAe,kBACrC,MAAM,yCAEJ,OAAO,CAAC,MAAM,CAAC,CAgN3B;AASM,mCANI,OAAO,QACP,MAAM,kBACN,MAAM,kBACN,MAAM,uDAahB;;;;;;;;;;;gBAlba,MAAM,MAAM;;;;;;;cAOZ,MAAM,MAAM;;;;;;;oBAIZ,MAAM,MAAM;;;;;wBAIZ,MAAM,MAAM;;yBAKH,oBAAoB,SAA9B,OAAS;SAER,MAAM;qBACN,MAAM;qBACN,MAAM;YACN,MAAM;YACN,gBAAgB,GAAG,oBAAoB;qBACvC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;oBACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;WACtB,UAAU;WACV,MAAM;gBACN,UAAU;;0BAID,oBAAoB,SAA9B,OAAS,aAEX,YAAY,CAAC,oBAAoB,CAAC,KAChC,UAAU;2BAIA,oBAAoB,SAA9B,OAAS;aAER,MAAM;mBACN,aAAa,CAAC,oBAAoB,CAAC;;4BAlDvC,YAAY;gCAAZ,YAAY;qCAAZ,YAAY;oCAAZ,YAAY;6BAAZ,YAAY;sCAVZ,KAAK"}
package/src/bundle.js CHANGED
@@ -117,8 +117,14 @@ const sortedModules = (
117
117
  const source = compartmentSources[compartmentName][moduleSpecifier];
118
118
  if (source !== undefined) {
119
119
  const { record, parser, deferredError, bytes } = source;
120
- assert(parser !== undefined);
121
- assert(bytes !== undefined);
120
+ assert(
121
+ bytes !== undefined,
122
+ `No bytes for ${moduleSpecifier} in ${compartmentName}`,
123
+ );
124
+ assert(
125
+ parser !== undefined,
126
+ `No parser for ${moduleSpecifier} in ${compartmentName}`,
127
+ );
122
128
  if (deferredError) {
123
129
  throw Error(
124
130
  `Cannot bundle: encountered deferredError ${deferredError}`,
@@ -1 +1 @@
1
- {"version":3,"file":"capture-lite.d.ts","sourceRoot":"","sources":["capture-lite.js"],"names":[],"mappings":"AAsQO,uCALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,aAAa,CAAC,CAmElC;4BA9RS,YAAY;gCAAZ,YAAY;8CAAZ,YAAY;wCAAZ,YAAY;mCAAZ,YAAY"}
1
+ {"version":3,"file":"capture-lite.d.ts","sourceRoot":"","sources":["capture-lite.js"],"names":[],"mappings":"AAoFO,uCALI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,aAAa,CAAC,CAmElC;4BA9GS,YAAY;gCAAZ,YAAY;8CAAZ,YAAY;wCAAZ,YAAY;mCAAZ,YAAY"}
@@ -33,20 +33,13 @@
33
33
  * @import {
34
34
  * CaptureLiteOptions,
35
35
  * CaptureResult,
36
- * CompartmentDescriptor,
37
36
  * CompartmentMapDescriptor,
38
- * ModuleDescriptor,
39
37
  * ReadFn,
40
38
  * ReadPowers,
41
39
  * Sources,
42
40
  * } from './types.js'
43
41
  */
44
42
 
45
- import {
46
- assertCompartmentMap,
47
- pathCompare,
48
- stringCompare,
49
- } from './compartment-map.js';
50
43
  import {
51
44
  exitModuleImportHookMaker,
52
45
  makeImportHookMaker,
@@ -55,161 +48,12 @@ import { link } from './link.js';
55
48
  import { resolve } from './node-module-specifier.js';
56
49
  import { detectAttenuators } from './policy.js';
57
50
  import { unpackReadPowers } from './powers.js';
51
+ import { digestCompartmentMap } from './digest.js';
58
52
 
59
- const { freeze, assign, create, fromEntries, entries, keys } = Object;
53
+ const { freeze, assign, create } = Object;
60
54
 
61
55
  const defaultCompartment = Compartment;
62
56
 
63
- /**
64
- * We attempt to produce compartment maps that are consistent regardless of
65
- * whether the packages were originally laid out on disk for development or
66
- * production, and other trivia like the fully qualified path of a specific
67
- * installation.
68
- *
69
- * Naming compartments for the self-ascribed name and version of each Node.js
70
- * package is insufficient because they are not guaranteed to be unique.
71
- * Dependencies do not necessarilly come from the npm registry and may be
72
- * for example derived from fully qualified URL's or Github org and project
73
- * names.
74
- * Package managers are also not required to fully deduplicate the hard
75
- * copy of each package even when they are identical resources.
76
- * Duplication is undesirable, but we elect to defer that problem to solutions
77
- * in the package managers, as the alternative would be to consistently hash
78
- * the original sources of the packages themselves, which may not even be
79
- * available much less pristine for us.
80
- *
81
- * So, instead, we use the lexically least path of dependency names, delimited
82
- * by hashes.
83
- * The compartment maps generated by the ./node-modules.js tooling pre-compute
84
- * these traces for our use here.
85
- * We sort the compartments lexically on their self-ascribed name and version,
86
- * and use the lexically least dependency name path as a tie-breaker.
87
- * The dependency path is logical and orthogonal to the package manager's
88
- * actual installation location, so should be orthogonal to the vagaries of the
89
- * package manager's deduplication algorithm.
90
- *
91
- * @param {Record<string, CompartmentDescriptor>} compartments
92
- * @returns {Record<string, string>} map from old to new compartment names.
93
- */
94
- const renameCompartments = compartments => {
95
- /** @type {Record<string, string>} */
96
- const compartmentRenames = create(null);
97
- let index = 0;
98
- let prev = '';
99
-
100
- // The sort below combines two comparators to avoid depending on sort
101
- // stability, which became standard as recently as 2019.
102
- // If that date seems quaint, please accept my regards from the distant past.
103
- // We are very proud of you.
104
- const compartmentsByPath = Object.entries(compartments)
105
- .map(([name, compartment]) => ({
106
- name,
107
- path: compartment.path,
108
- label: compartment.label,
109
- }))
110
- .sort((a, b) => {
111
- if (a.label === b.label) {
112
- assert(a.path !== undefined && b.path !== undefined);
113
- return pathCompare(a.path, b.path);
114
- }
115
- return stringCompare(a.label, b.label);
116
- });
117
-
118
- for (const { name, label } of compartmentsByPath) {
119
- if (label === prev) {
120
- compartmentRenames[name] = `${label}-n${index}`;
121
- index += 1;
122
- } else {
123
- compartmentRenames[name] = label;
124
- prev = label;
125
- index = 1;
126
- }
127
- }
128
- return compartmentRenames;
129
- };
130
-
131
- /**
132
- * @param {Record<string, CompartmentDescriptor>} compartments
133
- * @param {Sources} sources
134
- * @param {Record<string, string>} compartmentRenames
135
- */
136
- const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
137
- const result = create(null);
138
- for (const compartmentName of keys(compartmentRenames)) {
139
- const compartment = compartments[compartmentName];
140
- const { name, label, retained, policy } = compartment;
141
- if (retained) {
142
- // rename module compartments
143
- /** @type {Record<string, ModuleDescriptor>} */
144
- const modules = create(null);
145
- const compartmentModules = compartment.modules;
146
- if (compartment.modules) {
147
- for (const name of keys(compartmentModules).sort()) {
148
- const module = compartmentModules[name];
149
- if (module.compartment !== undefined) {
150
- modules[name] = {
151
- ...module,
152
- compartment: compartmentRenames[module.compartment],
153
- };
154
- } else {
155
- modules[name] = module;
156
- }
157
- }
158
- }
159
-
160
- // integrate sources into modules
161
- const compartmentSources = sources[compartmentName];
162
- if (compartmentSources) {
163
- for (const name of keys(compartmentSources).sort()) {
164
- const source = compartmentSources[name];
165
- const { location, parser, exit, sha512, deferredError } = source;
166
- if (location !== undefined) {
167
- modules[name] = {
168
- location,
169
- parser,
170
- sha512,
171
- };
172
- } else if (exit !== undefined) {
173
- modules[name] = {
174
- exit,
175
- };
176
- } else if (deferredError !== undefined) {
177
- modules[name] = {
178
- deferredError,
179
- };
180
- }
181
- }
182
- }
183
-
184
- result[compartmentRenames[compartmentName]] = {
185
- name,
186
- label,
187
- location: compartmentRenames[compartmentName],
188
- modules,
189
- policy,
190
- // `scopes`, `types`, and `parsers` are not necessary since every
191
- // loadable module is captured in `modules`.
192
- };
193
- }
194
- }
195
-
196
- return result;
197
- };
198
-
199
- /**
200
- * @param {Sources} sources
201
- * @param {Record<string, string>} compartmentRenames
202
- * @returns {Sources}
203
- */
204
- const renameSources = (sources, compartmentRenames) => {
205
- return fromEntries(
206
- entries(sources).map(([name, compartmentSources]) => [
207
- compartmentRenames[name],
208
- compartmentSources,
209
- ]),
210
- );
211
- };
212
-
213
57
  /**
214
58
  * @param {CompartmentMapDescriptor} compartmentMap
215
59
  * @param {Sources} sources
@@ -217,40 +61,18 @@ const renameSources = (sources, compartmentRenames) => {
217
61
  */
218
62
  const captureCompartmentMap = (compartmentMap, sources) => {
219
63
  const {
220
- compartments,
221
- entry: { compartment: entryCompartmentName, module: entryModuleSpecifier },
222
- } = compartmentMap;
223
-
224
- const compartmentRenames = renameCompartments(compartments);
225
- const captureCompartments = translateCompartmentMap(
226
- compartments,
227
- sources,
64
+ compartmentMap: captureCompartmentMap,
65
+ sources: captureSources,
66
+ newToOldCompartmentNames,
228
67
  compartmentRenames,
229
- );
230
- const captureEntryCompartmentName = compartmentRenames[entryCompartmentName];
231
- const captureSources = renameSources(sources, compartmentRenames);
232
-
233
- const captureCompartmentMap = {
234
- // TODO graceful migration from tags to conditions
235
- // https://github.com/endojs/endo/issues/2388
236
- tags: [],
237
- entry: {
238
- compartment: captureEntryCompartmentName,
239
- module: entryModuleSpecifier,
240
- },
241
- compartments: captureCompartments,
242
- };
243
-
244
- // Cross-check:
245
- // We assert that we have constructed a valid compartment map, not because it
246
- // might not be, but to ensure that the assertCompartmentMap function can
247
- // accept all valid compartment maps.
248
- assertCompartmentMap(captureCompartmentMap);
249
-
68
+ oldToNewCompartmentNames,
69
+ } = digestCompartmentMap(compartmentMap, sources);
250
70
  return {
251
71
  captureCompartmentMap,
252
72
  captureSources,
253
73
  compartmentRenames,
74
+ newToOldCompartmentNames,
75
+ oldToNewCompartmentNames,
254
76
  };
255
77
  };
256
78
 
@@ -0,0 +1,5 @@
1
+ export function digestCompartmentMap(compartmentMap: CompartmentMapDescriptor, sources: Sources): DigestResult;
2
+ import type { CompartmentMapDescriptor } from './types.js';
3
+ import type { Sources } from './types.js';
4
+ import type { DigestResult } from './types.js';
5
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["digest.js"],"names":[],"mappings":"AAwLO,qDAJI,wBAAwB,WACxB,OAAO,GACL,YAAY,CAoDxB;8CA3NS,YAAY;6BAAZ,YAAY;kCAAZ,YAAY"}