@endo/compartment-mapper 1.6.2 → 2.0.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.
Files changed (94) hide show
  1. package/package.json +12 -16
  2. package/src/archive-lite.d.ts +7 -7
  3. package/src/archive-lite.d.ts.map +1 -1
  4. package/src/archive-lite.js +78 -27
  5. package/src/archive.d.ts.map +1 -1
  6. package/src/archive.js +7 -0
  7. package/src/bundle-lite.d.ts +3 -3
  8. package/src/bundle-lite.d.ts.map +1 -1
  9. package/src/bundle-lite.js +19 -24
  10. package/src/bundle.d.ts +3 -3
  11. package/src/bundle.d.ts.map +1 -1
  12. package/src/bundle.js +19 -24
  13. package/src/capture-lite.d.ts +2 -2
  14. package/src/capture-lite.d.ts.map +1 -1
  15. package/src/capture-lite.js +217 -25
  16. package/src/compartment-map.d.ts +9 -2
  17. package/src/compartment-map.d.ts.map +1 -1
  18. package/src/compartment-map.js +737 -254
  19. package/src/digest.d.ts +22 -2
  20. package/src/digest.d.ts.map +1 -1
  21. package/src/digest.js +179 -56
  22. package/src/generic-graph.d.ts +84 -0
  23. package/src/generic-graph.d.ts.map +1 -0
  24. package/src/generic-graph.js +356 -0
  25. package/src/guards.d.ts +18 -0
  26. package/src/guards.d.ts.map +1 -0
  27. package/src/guards.js +109 -0
  28. package/src/hooks.md +124 -0
  29. package/src/import-archive-lite.d.ts.map +1 -1
  30. package/src/import-archive-lite.js +15 -11
  31. package/src/import-archive.d.ts +5 -19
  32. package/src/import-archive.d.ts.map +1 -1
  33. package/src/import-archive.js +7 -27
  34. package/src/import-hook.d.ts +4 -3
  35. package/src/import-hook.d.ts.map +1 -1
  36. package/src/import-hook.js +156 -71
  37. package/src/import-lite.d.ts +6 -6
  38. package/src/import-lite.d.ts.map +1 -1
  39. package/src/import-lite.js +8 -5
  40. package/src/import.d.ts +3 -3
  41. package/src/import.d.ts.map +1 -1
  42. package/src/import.js +16 -6
  43. package/src/infer-exports.d.ts.map +1 -1
  44. package/src/infer-exports.js +16 -6
  45. package/src/json.d.ts +1 -1
  46. package/src/json.d.ts.map +1 -1
  47. package/src/json.js +10 -3
  48. package/src/link.d.ts +4 -3
  49. package/src/link.d.ts.map +1 -1
  50. package/src/link.js +70 -58
  51. package/src/node-modules.d.ts +5 -3
  52. package/src/node-modules.d.ts.map +1 -1
  53. package/src/node-modules.js +648 -245
  54. package/src/node-powers.d.ts +6 -5
  55. package/src/node-powers.d.ts.map +1 -1
  56. package/src/node-powers.js +11 -8
  57. package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
  58. package/src/parse-cjs-shared-export-wrapper.js +3 -1
  59. package/src/policy-format.d.ts +22 -5
  60. package/src/policy-format.d.ts.map +1 -1
  61. package/src/policy-format.js +342 -108
  62. package/src/policy.d.ts +13 -28
  63. package/src/policy.d.ts.map +1 -1
  64. package/src/policy.js +161 -106
  65. package/src/types/canonical-name.d.ts +97 -0
  66. package/src/types/canonical-name.d.ts.map +1 -0
  67. package/src/types/canonical-name.ts +151 -0
  68. package/src/types/compartment-map-schema.d.ts +114 -35
  69. package/src/types/compartment-map-schema.d.ts.map +1 -1
  70. package/src/types/compartment-map-schema.ts +202 -37
  71. package/src/types/external.d.ts +173 -29
  72. package/src/types/external.d.ts.map +1 -1
  73. package/src/types/external.ts +221 -27
  74. package/src/types/generic-graph.d.ts +17 -0
  75. package/src/types/generic-graph.d.ts.map +1 -0
  76. package/src/types/generic-graph.ts +17 -0
  77. package/src/types/internal.d.ts +24 -42
  78. package/src/types/internal.d.ts.map +1 -1
  79. package/src/types/internal.ts +52 -50
  80. package/src/types/node-modules.d.ts +101 -17
  81. package/src/types/node-modules.d.ts.map +1 -1
  82. package/src/types/node-modules.ts +142 -17
  83. package/src/types/policy-schema.d.ts +26 -11
  84. package/src/types/policy-schema.d.ts.map +1 -1
  85. package/src/types/policy-schema.ts +29 -16
  86. package/src/types/policy.d.ts +6 -2
  87. package/src/types/policy.d.ts.map +1 -1
  88. package/src/types/policy.ts +7 -2
  89. package/src/types/powers.d.ts +38 -11
  90. package/src/types/powers.d.ts.map +1 -1
  91. package/src/types/powers.ts +50 -17
  92. package/src/types/typescript.d.ts +28 -0
  93. package/src/types/typescript.d.ts.map +1 -1
  94. package/src/types/typescript.ts +37 -1
@@ -1,24 +1,10 @@
1
- export function parseArchive(archiveBytes: Uint8Array, archiveLocation?: string, options?: Options): Promise<Application>;
2
- export function loadArchive(readPowers: import("@endo/zip").ReadFn | ReadPowers, archiveLocation: string, options?: LoadArchiveOptions): Promise<Application>;
3
- export function importArchive(readPowers: import("@endo/zip").ReadFn | ReadPowers, archiveLocation: string, options: ExecuteOptions & LoadArchiveOptions): Promise<object>;
4
- export type CompartmentConstructor = typeof Compartment;
5
- export type Options = {
6
- expectedSha512?: string | undefined;
7
- computeSha512?: HashFn | undefined;
8
- modules?: Record<string, unknown> | undefined;
9
- importHook?: ExitModuleImportHook | undefined;
10
- Compartment?: typeof Compartment | undefined;
11
- computeSourceLocation?: ComputeSourceLocationHook | undefined;
12
- computeSourceMapLocation?: ComputeSourceMapLocationHook | undefined;
13
- parserForLanguage?: ParserForLanguage | undefined;
14
- };
1
+ export function parseArchive(archiveBytes: Uint8Array, archiveLocation?: string, options?: ParseArchiveOptions): Promise<Application>;
2
+ export function loadArchive(readPowers: ReadFn | ReadPowers, archiveLocation: string, options?: LoadArchiveOptions): Promise<Application>;
3
+ export function importArchive(readPowers: ReadFn | ReadPowers, archiveLocation: string, options: ExecuteOptions & LoadArchiveOptions): Promise<object>;
4
+ import type { ParseArchiveOptions } from './types.js';
15
5
  import type { Application } from './types.js';
6
+ import type { ReadFn } from './types.js';
16
7
  import type { ReadPowers } from './types.js';
17
8
  import type { LoadArchiveOptions } from './types.js';
18
9
  import type { ExecuteOptions } from './types.js';
19
- import type { HashFn } from './types.js';
20
- import type { ExitModuleImportHook } from './types.js';
21
- import type { ComputeSourceLocationHook } from './types.js';
22
- import type { ComputeSourceMapLocationHook } from './types.js';
23
- import type { ParserForLanguage } from './types.js';
24
10
  //# sourceMappingURL=import-archive.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"import-archive.d.ts","sourceRoot":"","sources":["import-archive.js"],"names":[],"mappings":"AA+EO,2CALI,UAAU,oBACV,MAAM,YACN,OAAO,GACL,OAAO,CAAC,WAAW,CAAC,CAW9B;AAQI,wCALI,OAAO,WAAW,EAAE,MAAM,GAAG,UAAU,mBACvC,MAAM,YACN,kBAAkB,GAChB,OAAO,CAAC,WAAW,CAAC,CAO9B;AAQI,0CALI,OAAO,WAAW,EAAE,MAAM,GAAG,UAAU,mBACvC,MAAM,WACN,cAAc,GAAG,kBAAkB,GACjC,OAAO,CAAC,MAAM,CAAC,CAOzB;qCArEW,OAAO,WAAW;;;;;;;;;;;iCAhBtB,YAAY;gCAAZ,YAAY;wCAAZ,YAAY;oCAAZ,YAAY;4BAAZ,YAAY;0CAAZ,YAAY;+CAAZ,YAAY;kDAAZ,YAAY;uCAAZ,YAAY"}
1
+ {"version":3,"file":"import-archive.d.ts","sourceRoot":"","sources":["import-archive.js"],"names":[],"mappings":"AA2DO,2CALI,UAAU,oBACV,MAAM,YACN,mBAAmB,GACjB,OAAO,CAAC,WAAW,CAAC,CAW9B;AAQI,wCALI,MAAM,GAAG,UAAU,mBACnB,MAAM,YACN,kBAAkB,GAChB,OAAO,CAAC,WAAW,CAAC,CAO9B;AAQI,0CALI,MAAM,GAAG,UAAU,mBACnB,MAAM,WACN,cAAc,GAAG,kBAAkB,GACjC,OAAO,CAAC,MAAM,CAAC,CAOzB;yCAnEO,YAAY;iCAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;wCAAZ,YAAY;oCAAZ,YAAY"}
@@ -19,14 +19,12 @@
19
19
  /**
20
20
  * @import {
21
21
  * Application,
22
- * ComputeSourceLocationHook,
23
- * ComputeSourceMapLocationHook,
24
22
  * ExecuteOptions,
25
- * ExitModuleImportHook,
26
- * HashFn,
27
23
  * LoadArchiveOptions,
28
24
  * ReadPowers,
29
25
  * ParserForLanguage,
26
+ * ParseArchiveOptions,
27
+ * ReadFn,
30
28
  * } from './types.js'
31
29
  */
32
30
 
@@ -39,28 +37,10 @@ import {
39
37
 
40
38
  const { assign, create, freeze } = Object;
41
39
 
42
- // Must give the type of Compartment a name to capture the external meaning of
43
- // Compartment Otherwise @param {typeof Compartment} takes the Compartment to
44
- // mean the const variable defined within the function.
45
- //
46
- /** @typedef {typeof Compartment} CompartmentConstructor */
47
-
48
- /**
49
- * @typedef {object} Options
50
- * @property {string} [expectedSha512]
51
- * @property {HashFn} [computeSha512]
52
- * @property {Record<string, unknown>} [modules]
53
- * @property {ExitModuleImportHook} [importHook]
54
- * @property {CompartmentConstructor} [Compartment]
55
- * @property {ComputeSourceLocationHook} [computeSourceLocation]
56
- * @property {ComputeSourceMapLocationHook} [computeSourceMapLocation]
57
- * @property {ParserForLanguage} [parserForLanguage]
58
- */
59
-
60
40
  /**
61
41
  * Add the default parserForLanguage option.
62
- * @param {Options} [options]
63
- * @returns {Options}
42
+ * @param {ParseArchiveOptions} [options]
43
+ * @returns {ParseArchiveOptions}
64
44
  */
65
45
  const assignParserForLanguage = (options = {}) => {
66
46
  const { parserForLanguage: parserForLanguageOption, ...rest } = options;
@@ -74,7 +54,7 @@ const assignParserForLanguage = (options = {}) => {
74
54
  /**
75
55
  * @param {Uint8Array} archiveBytes
76
56
  * @param {string} [archiveLocation]
77
- * @param {Options} [options]
57
+ * @param {ParseArchiveOptions} [options]
78
58
  * @returns {Promise<Application>}
79
59
  */
80
60
  export const parseArchive = async (
@@ -89,7 +69,7 @@ export const parseArchive = async (
89
69
  );
90
70
 
91
71
  /**
92
- * @param {import('@endo/zip').ReadFn | ReadPowers} readPowers
72
+ * @param {ReadFn | ReadPowers} readPowers
93
73
  * @param {string} archiveLocation
94
74
  * @param {LoadArchiveOptions} [options]
95
75
  * @returns {Promise<Application>}
@@ -102,7 +82,7 @@ export const loadArchive = async (readPowers, archiveLocation, options) =>
102
82
  );
103
83
 
104
84
  /**
105
- * @param {import('@endo/zip').ReadFn | ReadPowers} readPowers
85
+ * @param {ReadFn | ReadPowers} readPowers
106
86
  * @param {string} archiveLocation
107
87
  * @param {ExecuteOptions & LoadArchiveOptions} options
108
88
  * @returns {Promise<object>}
@@ -2,18 +2,19 @@
2
2
  * Synchronous import for dynamic requires.
3
3
  *
4
4
  * @param {ReadNowPowers} readPowers
5
- * @param {string} baseLocation
5
+ * @param {FileUrlString} baseLocation
6
6
  * @param {MakeImportNowHookMakerOptions} options
7
7
  * @returns {ImportNowHookMaker}
8
8
  */
9
- export function makeImportNowHookMaker(readPowers: ReadNowPowers, baseLocation: string, { sources, compartmentDescriptors, computeSha512, searchSuffixes, archiveOnly, sourceMapHook, importNowHook: exitModuleImportNowHook, }: MakeImportNowHookMakerOptions): ImportNowHookMaker;
9
+ export function makeImportNowHookMaker(readPowers: ReadNowPowers, baseLocation: FileUrlString, { sources, compartmentDescriptors, computeSha512, searchSuffixes, archiveOnly, sourceMapHook, importNowHook: exitModuleImportNowHook, moduleSourceHook, log, }: MakeImportNowHookMakerOptions): ImportNowHookMaker;
10
10
  export function exitModuleImportHookMaker({ modules, exitModuleImportHook, entryCompartmentName, }: {
11
11
  modules?: Record<string, any> | undefined;
12
12
  exitModuleImportHook?: ExitModuleImportHook | undefined;
13
13
  entryCompartmentName: string;
14
14
  }): ExitModuleImportHook | undefined;
15
- export function makeImportHookMaker(readPowers: ReadFn | ReadPowers, baseLocation: string, { sources, compartmentDescriptors, archiveOnly, computeSha512, searchSuffixes, sourceMapHook, entryCompartmentName, entryModuleSpecifier, importHook: exitModuleImportHook, }: MakeImportHookMakerOptions): ImportHookMaker;
15
+ export function makeImportHookMaker(readPowers: ReadFn | ReadPowers, baseLocation: FileUrlString, { sources, compartmentDescriptors, archiveOnly, computeSha512, searchSuffixes, sourceMapHook, entryCompartmentName, entryModuleSpecifier, importHook: exitModuleImportHook, moduleSourceHook, log, }: MakeImportHookMakerOptions): ImportHookMaker;
16
16
  import type { ReadNowPowers } from './types.js';
17
+ import type { FileUrlString } from './types.js';
17
18
  import type { MakeImportNowHookMakerOptions } from './types.js';
18
19
  import type { ImportNowHookMaker } from './types.js';
19
20
  import type { ExitModuleImportHook } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"import-hook.d.ts","sourceRoot":"","sources":["import-hook.js"],"names":[],"mappings":"AAkoBA;;;;;;;GAOG;AACH,mDALW,aAAa,gBACb,MAAM,2IACN,6BAA6B,GAC3B,kBAAkB,CAkN9B;AAnoBM,oGALJ;IAAqC,OAAO;IACN,oBAAoB;IACnC,oBAAoB,EAAnC,MAAM;CACd,GAAU,oBAAoB,GAAC,SAAS,CA8B1C;AAiPM,gDALI,MAAM,GAAC,UAAU,gBACjB,MAAM,iLACN,0BAA0B,GACxB,eAAe,CA8J3B;mCAzlBS,YAAY;mDAAZ,YAAY;wCAAZ,YAAY;0CAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;gDAAZ,YAAY;qCAAZ,YAAY"}
1
+ {"version":3,"file":"import-hook.d.ts","sourceRoot":"","sources":["import-hook.js"],"names":[],"mappings":"AAouBA;;;;;;;GAOG;AACH,mDALW,aAAa,gBACb,aAAa,kKACb,6BAA6B,GAC3B,kBAAkB,CAqM9B;AA9tBM,oGALJ;IAAqC,OAAO;IACN,oBAAoB;IACnC,oBAAoB,EAAnC,MAAM;CACd,GAAU,oBAAoB,GAAC,SAAS,CA8B1C;AA0UM,gDALI,MAAM,GAAC,UAAU,gBACjB,aAAa,wMACb,0BAA0B,GACxB,eAAe,CA6K3B;mCAtrBS,YAAY;mCAAZ,YAAY;mDAAZ,YAAY;wCAAZ,YAAY;0CAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;gDAAZ,YAAY;qCAAZ,YAAY"}
@@ -29,14 +29,19 @@
29
29
  * ImportNowHookMaker,
30
30
  * MakeImportHookMakerOptions,
31
31
  * MakeImportNowHookMakerOptions,
32
- * ModuleDescriptor,
33
32
  * ParseResult,
34
33
  * ReadFn,
35
34
  * ReadPowers,
36
35
  * ReadNowPowers,
37
36
  * StrictlyRequiredFn,
37
+ * DeferErrorFn,
38
+ * ErrorModuleSource,
39
+ * FileUrlString,
38
40
  * CompartmentSources,
39
- * DeferErrorFn
41
+ * CompartmentModuleConfiguration,
42
+ * LogOptions,
43
+ * CanonicalName,
44
+ * LocalModuleSource
40
45
  * } from './types.js'
41
46
  */
42
47
 
@@ -44,14 +49,14 @@ import { asyncTrampoline, syncTrampoline } from '@endo/trampoline';
44
49
  import { resolve } from './node-module-specifier.js';
45
50
  import {
46
51
  attenuateModuleHook,
47
- ATTENUATORS_COMPARTMENT,
48
- enforceModulePolicy,
52
+ enforcePolicyByModule,
53
+ enforcePackagePolicyByCanonicalName,
49
54
  } from './policy.js';
55
+ import { ATTENUATORS_COMPARTMENT } from './policy-format.js';
50
56
  import { unpackReadPowers } from './powers.js';
51
57
 
52
58
  // q, as in quote, for quoting strings in error messages.
53
- const q = JSON.stringify;
54
-
59
+ const { quote: q } = assert;
55
60
  const { apply } = Reflect;
56
61
 
57
62
  /**
@@ -62,7 +67,7 @@ const { apply } = Reflect;
62
67
  */
63
68
  const freeze = Object.freeze;
64
69
 
65
- const { entries, keys, assign, create } = Object;
70
+ const { keys, assign, create } = Object;
66
71
 
67
72
  const { hasOwnProperty } = Object.prototype;
68
73
  /**
@@ -71,12 +76,15 @@ const { hasOwnProperty } = Object.prototype;
71
76
  */
72
77
  const has = (haystack, needle) => apply(hasOwnProperty, haystack, [needle]);
73
78
 
79
+ const noop = () => {};
80
+
74
81
  /**
75
82
  * @param {string} rel - a relative URL
76
- * @param {string} abs - a fully qualified URL
77
- * @returns {string}
83
+ * @param {FileUrlString} abs - a fully qualified URL
84
+ * @returns {FileUrlString}
78
85
  */
79
- const resolveLocation = (rel, abs) => new URL(rel, abs).toString();
86
+ const resolveLocation = (rel, abs) =>
87
+ /** @type {FileUrlString} */ (new URL(rel, abs).toString());
80
88
 
81
89
  // this is annoying
82
90
  function getImportsFromRecord(record) {
@@ -98,14 +106,14 @@ const nodejsConventionSearchSuffixes = [
98
106
 
99
107
  /**
100
108
  * Returns `true` if `absoluteModuleSpecifier` is within the path `compartmentLocation`.
101
- * @param {string} absoluteModudeSpecifier Absolute path to module specifier
109
+ * @param {string} absoluteModuleSpecifier Absolute path to module specifier
102
110
  * @param {string} compartmentLocation Absolute path to compartment location
103
111
  * @returns {boolean}
104
112
  */
105
113
  const isLocationWithinCompartment = (
106
- absoluteModudeSpecifier,
114
+ absoluteModuleSpecifier,
107
115
  compartmentLocation,
108
- ) => absoluteModudeSpecifier.startsWith(compartmentLocation);
116
+ ) => absoluteModuleSpecifier.startsWith(compartmentLocation);
109
117
 
110
118
  /**
111
119
  * Computes the relative path to a module from its compartment location (including a leading `./`)
@@ -159,30 +167,15 @@ const findRedirect = ({
159
167
  return undefined;
160
168
  }
161
169
 
162
- // this tests the compartment referred to by the absolute path
163
- // is a dependency of the compartment descriptor
164
- if (compartmentDescriptor.compartments.has(location)) {
165
- return {
166
- specifier: relativeSpecifier(moduleSpecifierLocation, location),
167
- compartment: compartments[location],
168
- };
169
- }
170
-
171
- // this tests if the compartment descriptor is a dependency of the
172
- // compartment referred to by the absolute path.
173
- // it may be in scope, but disallowed by policy.
174
- if (
175
- someCompartmentDescriptor.compartments.has(
176
- compartmentDescriptor.location,
177
- )
178
- ) {
179
- enforceModulePolicy(
180
- compartmentDescriptor.name,
170
+ if (compartmentDescriptor.policy) {
171
+ enforcePackagePolicyByCanonicalName(
181
172
  someCompartmentDescriptor,
173
+ compartmentDescriptor,
182
174
  {
183
- errorHint: `Blocked in import hook. ${q(absoluteModuleSpecifier)} is part of the compartment map and resolves to ${location}`,
175
+ errorHint: `Blocked in importNow hook by package policy. ${q(absoluteModuleSpecifier)} is part of the compartment map and resolves to ${location}`,
184
176
  },
185
177
  );
178
+
186
179
  return {
187
180
  specifier: relativeSpecifier(moduleSpecifierLocation, location),
188
181
  compartment: compartments[location],
@@ -194,7 +187,8 @@ const findRedirect = ({
194
187
  // go up a directory
195
188
  const parentLocation = new URL('../', someLocation).href;
196
189
 
197
- // afaict this behavior is consistent across both windows and posix
190
+ // afaict this behavior is consistent across both windows and posix:
191
+ // if this is true, we hit the filesystem root
198
192
  if (parentLocation === someLocation) {
199
193
  throw new Error(
200
194
  `Could not import unknown module: ${q(absoluteModuleSpecifier)}`,
@@ -263,6 +257,66 @@ const nominateCandidates = (moduleSpecifier, searchSuffixes) => {
263
257
  return candidates;
264
258
  };
265
259
 
260
+ /**
261
+ * Executes the moduleSource hook for a {@link LocalModuleSource}.
262
+ *
263
+ * Preprocesses the fields for the hook.
264
+ *
265
+ * @param {import('./types.js').ModuleSourceHook | undefined} moduleSourceHook Hook function
266
+ * @param {LocalModuleSource} moduleSource Original `LocalModuleSource` object
267
+ * @param {CanonicalName} canonicalName Canonical name of the compartment/package
268
+ * @param {LogOptions} options Options
269
+ * @returns {void}
270
+ */
271
+ const executeLocalModuleSourceHook = (
272
+ moduleSourceHook,
273
+ moduleSource,
274
+ canonicalName,
275
+ { log = noop } = {},
276
+ ) => {
277
+ if (!moduleSourceHook) {
278
+ return;
279
+ }
280
+
281
+ const {
282
+ sourceLocation: location,
283
+ parser: language,
284
+ bytes,
285
+ record,
286
+ sha512,
287
+ } = moduleSource;
288
+ /** @type {string[]|undefined} */
289
+ let imports;
290
+ /** @type {string[]|undefined} */
291
+ let exports;
292
+ /** @type {string[]|undefined} */
293
+ let reexports;
294
+
295
+ if ('imports' in record) {
296
+ ({ imports } = record);
297
+ }
298
+ if ('exports' in record) {
299
+ ({ exports } = record);
300
+ }
301
+ if ('reexports' in record) {
302
+ ({ reexports } = record);
303
+ }
304
+
305
+ moduleSourceHook({
306
+ moduleSource: {
307
+ location,
308
+ language,
309
+ bytes,
310
+ imports,
311
+ exports,
312
+ reexports,
313
+ sha512,
314
+ },
315
+ canonicalName,
316
+ log,
317
+ });
318
+ };
319
+
266
320
  /**
267
321
  * Returns a generator which applies {@link ChooseModuleDescriptorOperators} in
268
322
  * `operators` using the options in options to ultimately result in a
@@ -296,7 +350,9 @@ function* chooseModuleDescriptor(
296
350
  readPowers,
297
351
  archiveOnly,
298
352
  sourceMapHook,
353
+ moduleSourceHook,
299
354
  strictlyRequiredForCompartment,
355
+ log = noop,
300
356
  },
301
357
  { maybeRead, parse, shouldDeferError = () => false },
302
358
  ) {
@@ -338,6 +394,20 @@ function* chooseModuleDescriptor(
338
394
  // name, they are usable as URL's.
339
395
  const moduleLocation = resolveLocation(candidateSpecifier, packageLocation);
340
396
 
397
+ // check if moduleLocation is within the compartment if it is not, then
398
+ // create a redirect record using absolute path which will be resolved by
399
+ // findRedirect
400
+ const { fileURLToPath } = unpackReadPowers(readPowers);
401
+ if (
402
+ typeof fileURLToPath === 'function' &&
403
+ !isLocationWithinCompartment(moduleLocation, packageLocation)
404
+ ) {
405
+ return {
406
+ specifier: fileURLToPath(moduleLocation),
407
+ compartment: compartments[packageLocation],
408
+ };
409
+ }
410
+
341
411
  // "next" values must have type assertions for narrowing because we have
342
412
  // multiple yielded types
343
413
  const moduleBytes = /** @type {Uint8Array|undefined} */ (
@@ -379,6 +449,7 @@ function* chooseModuleDescriptor(
379
449
  retained: true,
380
450
  module: candidateSpecifier,
381
451
  compartment: packageLocation,
452
+ __createdBy: 'import-hook',
382
453
  };
383
454
  }
384
455
  /** @type {StaticModuleType} */
@@ -405,7 +476,9 @@ function* chooseModuleDescriptor(
405
476
  const packageRelativeLocation = moduleLocation.slice(
406
477
  packageLocation.length,
407
478
  );
408
- packageSources[candidateSpecifier] = {
479
+
480
+ /** @type {LocalModuleSource} */
481
+ const localModuleSource = {
409
482
  location: packageRelativeLocation,
410
483
  sourceLocation: moduleLocation,
411
484
  sourceDirname,
@@ -414,6 +487,16 @@ function* chooseModuleDescriptor(
414
487
  record: concreteRecord,
415
488
  sha512,
416
489
  };
490
+
491
+ packageSources[candidateSpecifier] = localModuleSource;
492
+
493
+ executeLocalModuleSourceHook(
494
+ moduleSourceHook,
495
+ localModuleSource,
496
+ compartmentDescriptor.label,
497
+ { log },
498
+ );
499
+
417
500
  if (!shouldDeferError(parser)) {
418
501
  for (const importSpecifier of getImportsFromRecord(record)) {
419
502
  strictlyRequiredForCompartment(packageLocation).add(
@@ -443,9 +526,7 @@ const makeDeferError = (
443
526
  packageSources,
444
527
  ) => {
445
528
  /**
446
- * @param {string} specifier
447
- * @param {Error} error - error to throw on execute
448
- * @returns {StaticModuleType}
529
+ * @type {DeferErrorFn}
449
530
  */
450
531
  const deferError = (specifier, error) => {
451
532
  // strictlyRequired is populated with imports declared by modules whose parser is not using heuristics to figure
@@ -467,9 +548,11 @@ const makeDeferError = (
467
548
  throw error;
468
549
  },
469
550
  });
470
- packageSources[specifier] = {
551
+ /** @type {ErrorModuleSource} */
552
+ const moduleSource = {
471
553
  deferredError: error.message,
472
554
  };
555
+ packageSources[specifier] = moduleSource;
473
556
 
474
557
  return record;
475
558
  };
@@ -478,7 +561,7 @@ const makeDeferError = (
478
561
 
479
562
  /**
480
563
  * @param {ReadFn|ReadPowers} readPowers
481
- * @param {string} baseLocation
564
+ * @param {FileUrlString} baseLocation
482
565
  * @param {MakeImportHookMakerOptions} options
483
566
  * @returns {ImportHookMaker}
484
567
  */
@@ -495,6 +578,8 @@ export const makeImportHookMaker = (
495
578
  entryCompartmentName,
496
579
  entryModuleSpecifier,
497
580
  importHook: exitModuleImportHook = undefined,
581
+ moduleSourceHook,
582
+ log = noop,
498
583
  },
499
584
  ) => {
500
585
  // Set of specifiers for modules (scoped to compartment) whose parser is not
@@ -566,12 +651,23 @@ export const makeImportHookMaker = (
566
651
  if (record) {
567
652
  // It'd be nice to check the policy before importing it, but we can only throw a policy error if the
568
653
  // hook returns something. Otherwise, we need to fall back to the 'cannot find' error below.
569
- enforceModulePolicy(moduleSpecifier, compartmentDescriptor, {
654
+ enforcePolicyByModule(moduleSpecifier, compartmentDescriptor, {
570
655
  exit: true,
571
656
  errorHint: `Blocked in loading. ${q(
572
657
  moduleSpecifier,
573
658
  )} was not in the compartment map and an attempt was made to load it as a builtin`,
574
659
  });
660
+
661
+ if (moduleSourceHook) {
662
+ moduleSourceHook({
663
+ moduleSource: {
664
+ exit: moduleSpecifier,
665
+ },
666
+ canonicalName: compartmentDescriptor.label,
667
+ log,
668
+ });
669
+ }
670
+
575
671
  if (archiveOnly) {
576
672
  // Return a place-holder.
577
673
  // Archived compartments are not executed.
@@ -615,7 +711,9 @@ export const makeImportHookMaker = (
615
711
  readPowers,
616
712
  archiveOnly,
617
713
  sourceMapHook,
714
+ moduleSourceHook,
618
715
  strictlyRequiredForCompartment,
716
+ log,
619
717
  },
620
718
  { maybeRead, parse, shouldDeferError },
621
719
  );
@@ -644,7 +742,7 @@ export const makeImportHookMaker = (
644
742
  * Synchronous import for dynamic requires.
645
743
  *
646
744
  * @param {ReadNowPowers} readPowers
647
- * @param {string} baseLocation
745
+ * @param {FileUrlString} baseLocation
648
746
  * @param {MakeImportNowHookMakerOptions} options
649
747
  * @returns {ImportNowHookMaker}
650
748
  */
@@ -659,13 +757,14 @@ export function makeImportNowHookMaker(
659
757
  archiveOnly = false,
660
758
  sourceMapHook = undefined,
661
759
  importNowHook: exitModuleImportNowHook = undefined,
760
+ moduleSourceHook,
761
+ log = noop,
662
762
  },
663
763
  ) {
664
764
  // Set of specifiers for modules (scoped to compartment) whose parser is not
665
765
  // using heuristics to determine imports.
666
766
  /** @type {Map<string, Set<string>>} compartment name ->* module specifier */
667
767
  const strictlyRequired = new Map();
668
-
669
768
  /**
670
769
  * @param {string} compartmentName
671
770
  */
@@ -689,10 +788,13 @@ export function makeImportNowHookMaker(
689
788
  compartments,
690
789
  shouldDeferError,
691
790
  }) => {
791
+ packageLocation = resolveLocation(packageLocation, baseLocation);
792
+ const packageSources = sources[packageLocation] || create(null);
793
+ sources[packageLocation] = packageSources;
692
794
  const deferError = makeDeferError(
693
795
  strictlyRequiredForCompartment,
694
796
  packageLocation,
695
- sources,
797
+ packageSources,
696
798
  );
697
799
 
698
800
  /**
@@ -714,9 +816,9 @@ export function makeImportNowHookMaker(
714
816
  if (exitRecord) {
715
817
  // It'd be nice to check the policy before importing it, but we can only throw a policy error if the
716
818
  // hook returns something. Otherwise, we need to fall back to the 'cannot find' error below.
717
- enforceModulePolicy(moduleSpecifier, compartmentDescriptor, {
819
+ enforcePolicyByModule(moduleSpecifier, compartmentDescriptor, {
718
820
  exit: true,
719
- errorHint: `Blocked in loading. ${q(
821
+ errorHint: `Blocked exit module in loading. ${q(
720
822
  moduleSpecifier,
721
823
  )} was not in the compartment map and an attempt was made to load it as a builtin`,
722
824
  });
@@ -744,37 +846,17 @@ export function makeImportNowHookMaker(
744
846
  };
745
847
  }
746
848
 
747
- const compartmentDescriptor = compartmentDescriptors[packageLocation] || {};
849
+ const compartmentDescriptor =
850
+ compartmentDescriptors[packageLocation] || create(null);
748
851
 
749
- packageLocation = resolveLocation(packageLocation, baseLocation);
750
- const packageSources = sources[packageLocation] || create(null);
751
- sources[packageLocation] = packageSources;
752
852
  const {
753
853
  modules:
754
- moduleDescriptors = /** @type {Record<string, ModuleDescriptor>} */ (
854
+ moduleDescriptors = /** @type {Record<string, CompartmentModuleConfiguration>} */ (
755
855
  create(null)
756
856
  ),
757
857
  } = compartmentDescriptor;
758
- compartmentDescriptor.modules = moduleDescriptors;
759
858
 
760
- let { policy } = compartmentDescriptor;
761
- policy = policy || create(null);
762
-
763
- // Associates modules with compartment descriptors based on policy
764
- // in cases where the association was not made when building the
765
- // compartment map but is indicated by the policy.
766
- if ('packages' in policy && typeof policy.packages === 'object') {
767
- for (const [packageName, packagePolicyItem] of entries(policy.packages)) {
768
- if (
769
- !(packageName in compartmentDescriptor.modules) &&
770
- packageName in compartmentDescriptor.scopes &&
771
- packagePolicyItem
772
- ) {
773
- compartmentDescriptor.modules[packageName] =
774
- compartmentDescriptor.scopes[packageName];
775
- }
776
- }
777
- }
859
+ compartmentDescriptor.modules = moduleDescriptors;
778
860
 
779
861
  const { maybeReadNow, isAbsolute } = readPowers;
780
862
 
@@ -809,7 +891,8 @@ export function makeImportNowHookMaker(
809
891
  }
810
892
  } else if (
811
893
  moduleSpecifier !== '.' &&
812
- !moduleSpecifier.startsWith('./')
894
+ !moduleSpecifier.startsWith('./') &&
895
+ !moduleSpecifier.startsWith('../')
813
896
  ) {
814
897
  // could be a builtin, which means we should not bother bouncing on the trampoline to find it.
815
898
  return importExitModuleOrFail(moduleSpecifier, compartmentDescriptor);
@@ -834,7 +917,9 @@ export function makeImportNowHookMaker(
834
917
  readPowers,
835
918
  archiveOnly,
836
919
  sourceMapHook,
920
+ moduleSourceHook,
837
921
  strictlyRequiredForCompartment,
922
+ log,
838
923
  },
839
924
  {
840
925
  maybeRead: maybeReadNow,
@@ -1,22 +1,22 @@
1
1
  /**
2
2
  * @overload
3
3
  * @param {ReadNowPowers} readPowers
4
- * @param {CompartmentMapDescriptor} compartmentMap
4
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
5
5
  * @param {SyncImportLocationOptions} [opts]
6
6
  * @returns {Promise<Application>}
7
7
  */
8
- export function loadFromMap(readPowers: ReadNowPowers, compartmentMap: CompartmentMapDescriptor, opts?: SyncImportLocationOptions | undefined): Promise<Application>;
8
+ export function loadFromMap(readPowers: ReadNowPowers, compartmentMap: PackageCompartmentMapDescriptor, opts?: SyncImportLocationOptions | undefined): Promise<Application>;
9
9
  /**
10
10
  * @overload
11
11
  * @param {ReadFn | ReadPowers} readPowers
12
- * @param {CompartmentMapDescriptor} compartmentMap
12
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
13
13
  * @param {ImportLocationOptions} [opts]
14
14
  * @returns {Promise<Application>}
15
15
  */
16
- export function loadFromMap(readPowers: ReadFn | ReadPowers, compartmentMap: CompartmentMapDescriptor, opts?: ImportLocationOptions | undefined): Promise<Application>;
17
- export function importFromMap(readPowers: ReadFn | ReadPowers, compartmentMap: CompartmentMapDescriptor, options?: ImportLocationOptions): Promise<SomeObject>;
16
+ export function loadFromMap(readPowers: ReadFn | ReadPowers, compartmentMap: PackageCompartmentMapDescriptor, opts?: ImportLocationOptions | undefined): Promise<Application>;
17
+ export function importFromMap(readPowers: ReadFn | ReadPowers, compartmentMap: PackageCompartmentMapDescriptor, options?: ImportLocationOptions): Promise<SomeObject>;
18
18
  import type { ReadNowPowers } from './types.js';
19
- import type { CompartmentMapDescriptor } from './types.js';
19
+ import type { PackageCompartmentMapDescriptor } from './types.js';
20
20
  import type { SyncImportLocationOptions } from './types.js';
21
21
  import type { Application } from './types.js';
22
22
  import type { ReadFn } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"import-lite.d.ts","sourceRoot":"","sources":["import-lite.js"],"names":[],"mappings":";;;;;;;AAyEG,wCACQ,aAAa,kBACb,wBAAwB,iDAEtB,OAAO,CAAC,WAAW,CAAC,CAChC;;;;;;;;AAGE,wCACQ,MAAM,GAAG,UAAU,kBACnB,wBAAwB,6CAEtB,OAAO,CAAC,WAAW,CAAC,CAChC;AA4JM,0CANI,MAAM,GAAG,UAAU,kBACnB,wBAAwB,YACxB,qBAAqB,GACnB,OAAO,CAAC,UAAU,CAAC,CAU/B;mCAxNS,YAAY;8CAAZ,YAAY;+CAAZ,YAAY;iCAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;2CAAZ,YAAY;gCAAZ,YAAY"}
1
+ {"version":3,"file":"import-lite.d.ts","sourceRoot":"","sources":["import-lite.js"],"names":[],"mappings":";;;;;;;AAyEG,wCACQ,aAAa,kBACb,+BAA+B,iDAE7B,OAAO,CAAC,WAAW,CAAC,CAChC;;;;;;;;AAGE,wCACQ,MAAM,GAAG,UAAU,kBACnB,+BAA+B,6CAE7B,OAAO,CAAC,WAAW,CAAC,CAChC;AA+JM,0CANI,MAAM,GAAG,UAAU,kBACnB,+BAA+B,YAC/B,qBAAqB,GACnB,OAAO,CAAC,UAAU,CAAC,CAU/B;mCA3NS,YAAY;qDAAZ,YAAY;+CAAZ,YAAY;iCAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;2CAAZ,YAAY;gCAAZ,YAAY"}