@endo/compartment-mapper 1.4.0 → 1.6.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 +292 -111
- package/bundle.d.ts +1 -1
- package/bundle.js +4 -1
- package/functor-lite.d.ts +3 -0
- package/functor-lite.d.ts.map +1 -0
- package/functor-lite.js +4 -0
- package/functor.d.ts +3 -0
- package/functor.d.ts.map +1 -0
- package/functor.js +4 -0
- package/import-archive-all-parsers.d.ts +2 -0
- package/import-archive-all-parsers.d.ts.map +1 -0
- package/import-archive-all-parsers.js +1 -0
- package/index.d.ts +1 -1
- package/index.js +4 -1
- package/package.json +14 -5
- package/script-lite.d.ts +3 -0
- package/script-lite.d.ts.map +1 -0
- package/script-lite.js +4 -0
- package/script.d.ts +3 -0
- package/script.d.ts.map +1 -0
- package/script.js +4 -0
- package/src/archive-lite.d.ts +2 -4
- package/src/archive-lite.d.ts.map +1 -1
- package/src/archive-lite.js +16 -192
- package/src/archive.d.ts.map +1 -1
- package/src/archive.js +8 -0
- package/src/bundle-cjs.d.ts +1 -1
- package/src/bundle-cjs.d.ts.map +1 -1
- package/src/bundle-cjs.js +57 -28
- package/src/bundle-json.d.ts.map +1 -1
- package/src/bundle-json.js +2 -3
- package/src/bundle-lite.d.ts +91 -0
- package/src/bundle-lite.d.ts.map +1 -0
- package/src/bundle-lite.js +668 -0
- package/src/bundle-mjs.d.ts +2 -2
- package/src/bundle-mjs.d.ts.map +1 -1
- package/src/bundle-mjs.js +36 -19
- package/src/bundle.d.ts +48 -10
- package/src/bundle.d.ts.map +1 -1
- package/src/bundle.js +399 -127
- package/src/capture-lite.d.ts.map +1 -1
- package/src/capture-lite.js +10 -188
- package/src/digest.d.ts +5 -0
- package/src/digest.d.ts.map +1 -0
- package/src/digest.js +235 -0
- package/src/import-archive-all-parsers.d.ts +11 -0
- package/src/import-archive-all-parsers.d.ts.map +1 -0
- package/src/import-archive-all-parsers.js +29 -0
- package/src/import-archive-lite.d.ts.map +1 -1
- package/src/import-archive-lite.js +4 -0
- package/src/import-hook.d.ts +3 -16
- package/src/import-hook.d.ts.map +1 -1
- package/src/import-hook.js +11 -18
- package/src/import-lite.d.ts.map +1 -1
- package/src/import-lite.js +7 -2
- package/src/import.d.ts.map +1 -1
- package/src/import.js +2 -0
- package/src/link.d.ts.map +1 -1
- package/src/link.js +2 -0
- package/src/map-parser.d.ts.map +1 -1
- package/src/map-parser.js +4 -1
- package/src/node-modules.d.ts +4 -47
- package/src/node-modules.d.ts.map +1 -1
- package/src/node-modules.js +157 -131
- package/src/parse-archive-cjs.d.ts.map +1 -1
- package/src/parse-archive-cjs.js +8 -3
- package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
- package/src/parse-cjs-shared-export-wrapper.js +2 -10
- package/src/parse-cjs.js +1 -1
- package/src/parse-mjs.js +2 -2
- package/src/policy.d.ts.map +1 -1
- package/src/policy.js +4 -7
- package/src/search.d.ts +6 -12
- package/src/search.d.ts.map +1 -1
- package/src/search.js +29 -12
- package/src/types/compartment-map-schema.d.ts +5 -0
- package/src/types/compartment-map-schema.d.ts.map +1 -1
- package/src/types/compartment-map-schema.ts +5 -0
- package/src/types/external.d.ts +159 -12
- package/src/types/external.d.ts.map +1 -1
- package/src/types/external.ts +180 -12
- package/src/types/internal.d.ts +86 -13
- package/src/types/internal.d.ts.map +1 -1
- package/src/types/internal.ts +107 -13
- package/src/types/node-modules.d.ts +79 -0
- package/src/types/node-modules.d.ts.map +1 -0
- package/src/types/node-modules.ts +89 -0
- package/src/types/node-powers.d.ts +4 -4
- package/src/types/node-powers.d.ts.map +1 -1
- package/src/types/node-powers.ts +4 -4
- package/src/types/powers.d.ts +2 -2
- package/src/types/powers.d.ts.map +1 -1
- package/src/types/powers.ts +2 -2
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
/* eslint no-shadow: 0 */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @import {
|
|
5
|
+
* StaticModuleType,
|
|
6
|
+
* PrecompiledStaticModuleInterface
|
|
7
|
+
* } from 'ses'
|
|
8
|
+
* @import {
|
|
9
|
+
* BundleOptions,
|
|
10
|
+
* CompartmentDescriptor,
|
|
11
|
+
* CompartmentMapDescriptor,
|
|
12
|
+
* CompartmentSources,
|
|
13
|
+
* MaybeReadPowers,
|
|
14
|
+
* ReadFn,
|
|
15
|
+
* ReadPowers,
|
|
16
|
+
* Sources,
|
|
17
|
+
* } from './types.js'
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The bundler kit defines a language-specific behavior for injecting a module
|
|
22
|
+
* into a bundle.
|
|
23
|
+
* Each module must allocate cells for its imports and exports, link those cells
|
|
24
|
+
* to the cells of dependencies, and provide both the linker and evaluation behavior
|
|
25
|
+
* for the module.
|
|
26
|
+
* The linker behavior gets injected in a lexical scope with the linker runtime
|
|
27
|
+
* and has access to the cells of all modules, whereas the evaluation behavior
|
|
28
|
+
* gets injected in the generated script's top level lexical scope, so has
|
|
29
|
+
* no accidental visibility into the linkage runtime.
|
|
30
|
+
*
|
|
31
|
+
* For example, JSON modules produce a single "default" cell ("getCells"):
|
|
32
|
+
*
|
|
33
|
+
* { default: cell('default') },
|
|
34
|
+
*
|
|
35
|
+
* Then, the JSON gets injected verbatim for the evaluation behavior ("getFunctor").
|
|
36
|
+
* The linker simply sets the cell to the value.
|
|
37
|
+
*
|
|
38
|
+
* functors[0]['default'].set(modules[0]);
|
|
39
|
+
*
|
|
40
|
+
* For an ECMAScript or CommonJS module, the evaluation behavior is a function
|
|
41
|
+
* that the linker runtime can call to inject it with the cells it needs by
|
|
42
|
+
* the names it sees for them.
|
|
43
|
+
*
|
|
44
|
+
* @typedef {object} BundlerKit
|
|
45
|
+
* @property {() => string} getFunctor Produces a JavaScript string consisting of
|
|
46
|
+
* a function expression followed by a comma delimiter that will be evaluated in
|
|
47
|
+
* a lexical scope with no free variables except the globals.
|
|
48
|
+
* In the generated bundle runtime, the function will receive an environment
|
|
49
|
+
* record: a record mapping every name of the corresponding module's internal
|
|
50
|
+
* namespace to a "cell" it can use to get, set, or observe the linked
|
|
51
|
+
* variable.
|
|
52
|
+
* @property {() => string} getCells Produces a JavaScript string consisting of
|
|
53
|
+
* a JavaScript object and a trailing comma.
|
|
54
|
+
* The string is evaluated in the linker runtime's lexical context.
|
|
55
|
+
* @property {() => string} getFunctorCall Produces a JavaScript string,
|
|
56
|
+
* a statement that effects the module's evaluation behavior using the cells
|
|
57
|
+
* it imports and exports and the evaluated "functor".
|
|
58
|
+
* @property {() => string} getReexportsWiring Produces a JavaScript string
|
|
59
|
+
* that may include statements that bind the cells reexported by this module.
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @template {unknown} SpecificModuleSource
|
|
64
|
+
* @typedef {object} BundleModule
|
|
65
|
+
* @property {string} key
|
|
66
|
+
* @property {string} exit
|
|
67
|
+
* @property {string} compartmentName
|
|
68
|
+
* @property {string} moduleSpecifier
|
|
69
|
+
* @property {string} sourceDirname
|
|
70
|
+
* @property {string} parser
|
|
71
|
+
* @property {StaticModuleType & SpecificModuleSource} record
|
|
72
|
+
* @property {Record<string, string>} resolvedImports
|
|
73
|
+
* @property {Record<string, number>} indexedImports
|
|
74
|
+
* @property {Uint8Array} bytes
|
|
75
|
+
* @property {number} index
|
|
76
|
+
* @property {BundlerKit} bundlerKit
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @typedef {object} BundleExit
|
|
81
|
+
* @property {string} exit
|
|
82
|
+
* @property {number} index
|
|
83
|
+
* @property {BundlerKit} bundlerKit
|
|
84
|
+
* @property {Record<string, number>} indexedImports
|
|
85
|
+
* @property {Record<string, string>} resolvedImports
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @template {unknown} SpecificModuleSource
|
|
90
|
+
* @callback GetBundlerKit
|
|
91
|
+
* @param {BundleModule<SpecificModuleSource>} module
|
|
92
|
+
* @param {object} params
|
|
93
|
+
* @param {boolean} [params.useEvaluate]
|
|
94
|
+
* @param {string} [params.sourceUrlPrefix]
|
|
95
|
+
* @returns {BundlerKit}
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @template {unknown} SpecificModuleSource
|
|
100
|
+
* @typedef {object} BundlerSupport
|
|
101
|
+
* @property {string} runtime
|
|
102
|
+
* @property {GetBundlerKit<SpecificModuleSource>} getBundlerKit
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
import { resolve } from './node-module-specifier.js';
|
|
106
|
+
import { link } from './link.js';
|
|
107
|
+
import { makeImportHookMaker } from './import-hook.js';
|
|
108
|
+
import { defaultParserForLanguage } from './archive-parsers.js';
|
|
109
|
+
|
|
110
|
+
import mjsSupport from './bundle-mjs.js';
|
|
111
|
+
import cjsSupport from './bundle-cjs.js';
|
|
112
|
+
import jsonSupport from './bundle-json.js';
|
|
113
|
+
|
|
114
|
+
const { quote: q } = assert;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @param {BundleExit} source
|
|
118
|
+
* @returns {BundlerKit}
|
|
119
|
+
*/
|
|
120
|
+
const makeCjsExitBundlerKit = ({ exit, index }) => ({
|
|
121
|
+
getFunctor: () => `\
|
|
122
|
+
null,
|
|
123
|
+
`,
|
|
124
|
+
getCells: () => `\
|
|
125
|
+
namespaceCells(tryRequire(${JSON.stringify(exit)})),
|
|
126
|
+
`,
|
|
127
|
+
getReexportsWiring: () => '',
|
|
128
|
+
getFunctorCall: () => ``,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Produces a list of modules in the order they should be evaluated, and
|
|
133
|
+
* a side-table for following aliases.
|
|
134
|
+
* The modules are produce in topological postorder, such that the entry
|
|
135
|
+
* module appears last.
|
|
136
|
+
* The post-order traversal does not revisit modules that appear in cycles.
|
|
137
|
+
*
|
|
138
|
+
* Synthesizes a unique key for each module and translates
|
|
139
|
+
* each module's imports to their corresponding keys.
|
|
140
|
+
* Some import keys are aliased to other keys, such that walking from
|
|
141
|
+
* key to value in the aliases side table will eventually arrive at
|
|
142
|
+
* the key of a module that is present in the modules list.
|
|
143
|
+
*
|
|
144
|
+
* The first modules are place-holders for the modules that exit
|
|
145
|
+
* the compartment map to the host's module system.
|
|
146
|
+
*
|
|
147
|
+
* @param {Record<string, CompartmentDescriptor>} compartmentDescriptors
|
|
148
|
+
* @param {Record<string, CompartmentSources>} compartmentSources
|
|
149
|
+
* @param {string} entryCompartmentName
|
|
150
|
+
* @param {string} entryModuleSpecifier
|
|
151
|
+
* @param {Array<string>} exitModuleSpecifiers
|
|
152
|
+
*/
|
|
153
|
+
const sortedModules = (
|
|
154
|
+
compartmentDescriptors,
|
|
155
|
+
compartmentSources,
|
|
156
|
+
entryCompartmentName,
|
|
157
|
+
entryModuleSpecifier,
|
|
158
|
+
exitModuleSpecifiers,
|
|
159
|
+
) => {
|
|
160
|
+
/** @type {BundleModule<unknown>[]} */
|
|
161
|
+
const modules = [];
|
|
162
|
+
/** @type {Map<string, string>} aliaes */
|
|
163
|
+
const aliases = new Map();
|
|
164
|
+
/** @type {Set<string>} seen */
|
|
165
|
+
const seen = new Set();
|
|
166
|
+
|
|
167
|
+
for (const exit of exitModuleSpecifiers) {
|
|
168
|
+
modules.push({
|
|
169
|
+
key: exit,
|
|
170
|
+
exit,
|
|
171
|
+
// @ts-expect-error
|
|
172
|
+
index: undefined,
|
|
173
|
+
// @ts-expect-error
|
|
174
|
+
bundlerKit: null,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @param {string} compartmentName
|
|
180
|
+
* @param {string} moduleSpecifier
|
|
181
|
+
*/
|
|
182
|
+
const recur = (compartmentName, moduleSpecifier) => {
|
|
183
|
+
const key = `${compartmentName}#${moduleSpecifier}`;
|
|
184
|
+
if (seen.has(key)) {
|
|
185
|
+
return key;
|
|
186
|
+
}
|
|
187
|
+
seen.add(key);
|
|
188
|
+
|
|
189
|
+
const source = compartmentSources[compartmentName][moduleSpecifier];
|
|
190
|
+
if (source !== undefined) {
|
|
191
|
+
const { record, parser, deferredError, bytes, sourceDirname, exit } =
|
|
192
|
+
source;
|
|
193
|
+
if (exit !== undefined) {
|
|
194
|
+
return exit;
|
|
195
|
+
}
|
|
196
|
+
assert(
|
|
197
|
+
bytes !== undefined,
|
|
198
|
+
`No bytes for ${moduleSpecifier} in ${compartmentName}`,
|
|
199
|
+
);
|
|
200
|
+
assert(
|
|
201
|
+
parser !== undefined,
|
|
202
|
+
`No parser for ${moduleSpecifier} in ${compartmentName}`,
|
|
203
|
+
);
|
|
204
|
+
assert(
|
|
205
|
+
sourceDirname !== undefined,
|
|
206
|
+
`No sourceDirname for ${moduleSpecifier} in ${compartmentName}`,
|
|
207
|
+
);
|
|
208
|
+
if (deferredError) {
|
|
209
|
+
throw Error(
|
|
210
|
+
`Cannot bundle: encountered deferredError ${deferredError}`,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (record) {
|
|
214
|
+
const { imports = [], reexports = [] } =
|
|
215
|
+
/** @type {PrecompiledStaticModuleInterface} */ (record);
|
|
216
|
+
const resolvedImports = Object.create(null);
|
|
217
|
+
for (const importSpecifier of [...imports, ...reexports]) {
|
|
218
|
+
// If we ever support another module resolution algorithm, that
|
|
219
|
+
// should be indicated in the compartment descriptor by name and the
|
|
220
|
+
// corresponding behavior selected here.
|
|
221
|
+
const resolvedSpecifier = resolve(importSpecifier, moduleSpecifier);
|
|
222
|
+
resolvedImports[importSpecifier] = recur(
|
|
223
|
+
compartmentName,
|
|
224
|
+
resolvedSpecifier,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
modules.push({
|
|
229
|
+
key,
|
|
230
|
+
compartmentName,
|
|
231
|
+
moduleSpecifier,
|
|
232
|
+
sourceDirname,
|
|
233
|
+
parser,
|
|
234
|
+
record,
|
|
235
|
+
resolvedImports,
|
|
236
|
+
bytes,
|
|
237
|
+
// @ts-expect-error
|
|
238
|
+
index: undefined,
|
|
239
|
+
// @ts-expect-error
|
|
240
|
+
bundlerKit: null,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return key;
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
const descriptor =
|
|
247
|
+
compartmentDescriptors[compartmentName].modules[moduleSpecifier];
|
|
248
|
+
if (descriptor) {
|
|
249
|
+
const {
|
|
250
|
+
compartment: aliasCompartmentName,
|
|
251
|
+
module: aliasModuleSpecifier,
|
|
252
|
+
} = descriptor;
|
|
253
|
+
if (
|
|
254
|
+
aliasCompartmentName !== undefined &&
|
|
255
|
+
aliasModuleSpecifier !== undefined
|
|
256
|
+
) {
|
|
257
|
+
const aliasKey = recur(aliasCompartmentName, aliasModuleSpecifier);
|
|
258
|
+
aliases.set(key, aliasKey);
|
|
259
|
+
return aliasKey;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
throw Error(
|
|
265
|
+
`Cannot bundle: cannot follow module import ${moduleSpecifier} in compartment ${compartmentName}`,
|
|
266
|
+
);
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
recur(entryCompartmentName, entryModuleSpecifier);
|
|
270
|
+
|
|
271
|
+
return { modules, aliases };
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/** @type {Record<string, BundlerSupport<unknown>>} */
|
|
275
|
+
const bundlerSupportForLanguage = {
|
|
276
|
+
'pre-mjs-json': mjsSupport,
|
|
277
|
+
'pre-cjs-json': cjsSupport,
|
|
278
|
+
json: jsonSupport,
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/** @param {string} language */
|
|
282
|
+
const getRuntime = language =>
|
|
283
|
+
bundlerSupportForLanguage[language]
|
|
284
|
+
? bundlerSupportForLanguage[language].runtime
|
|
285
|
+
: `/*unknown language:${language}*/`;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @param {BundleModule<unknown>} module
|
|
289
|
+
* @param {object} params
|
|
290
|
+
* @param {boolean} [params.useEvaluate]
|
|
291
|
+
* @param {string} [params.sourceUrlPrefix]
|
|
292
|
+
*/
|
|
293
|
+
const getBundlerKitForModule = (module, params) => {
|
|
294
|
+
const language = module.parser;
|
|
295
|
+
assert(language !== undefined);
|
|
296
|
+
if (bundlerSupportForLanguage[language] === undefined) {
|
|
297
|
+
const warning = `/*unknown language:${language}*/`;
|
|
298
|
+
// each item is a function to avoid creating more in-memory copies of the source text etc.
|
|
299
|
+
/** @type {BundlerKit} */
|
|
300
|
+
return {
|
|
301
|
+
getFunctor: () => `(()=>{${warning}}),`,
|
|
302
|
+
getCells: () => `{${warning}},`,
|
|
303
|
+
getFunctorCall: () => warning,
|
|
304
|
+
getReexportsWiring: () => '',
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
const { getBundlerKit } = bundlerSupportForLanguage[language];
|
|
308
|
+
return getBundlerKit(module, params);
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers
|
|
313
|
+
* @param {CompartmentMapDescriptor} compartmentMap
|
|
314
|
+
* @param {BundleOptions} [options]
|
|
315
|
+
* @returns {Promise<string>}
|
|
316
|
+
*/
|
|
317
|
+
export const makeFunctorFromMap = async (
|
|
318
|
+
readPowers,
|
|
319
|
+
compartmentMap,
|
|
320
|
+
options,
|
|
321
|
+
) => {
|
|
322
|
+
const {
|
|
323
|
+
moduleTransforms,
|
|
324
|
+
searchSuffixes,
|
|
325
|
+
sourceMapHook = undefined,
|
|
326
|
+
useEvaluate = false,
|
|
327
|
+
sourceUrlPrefix = undefined,
|
|
328
|
+
format = undefined,
|
|
329
|
+
parserForLanguage: parserForLanguageOption = {},
|
|
330
|
+
} = options || {};
|
|
331
|
+
|
|
332
|
+
/** @type {((module: BundleExit) => BundlerKit) | undefined} */
|
|
333
|
+
let makeExitBundlerKit;
|
|
334
|
+
if (format === 'cjs') {
|
|
335
|
+
makeExitBundlerKit = makeCjsExitBundlerKit;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const parserForLanguage = Object.freeze(
|
|
339
|
+
Object.assign(
|
|
340
|
+
Object.create(null),
|
|
341
|
+
defaultParserForLanguage,
|
|
342
|
+
parserForLanguageOption,
|
|
343
|
+
),
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
const bundlerKitParams = {
|
|
347
|
+
useEvaluate,
|
|
348
|
+
sourceUrlPrefix,
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const {
|
|
352
|
+
compartments,
|
|
353
|
+
entry: { compartment: entryCompartmentName, module: entryModuleSpecifier },
|
|
354
|
+
} = compartmentMap;
|
|
355
|
+
/** @type {string[]} */
|
|
356
|
+
const exitModuleSpecifiers = [];
|
|
357
|
+
/** @type {Sources} */
|
|
358
|
+
const sources = Object.create(null);
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* @param {string} moduleSpecifier
|
|
362
|
+
* @param {string} compartmentName
|
|
363
|
+
*/
|
|
364
|
+
const exitModuleImportHook =
|
|
365
|
+
format !== undefined
|
|
366
|
+
? /**
|
|
367
|
+
* @param {string} moduleSpecifier
|
|
368
|
+
* @param {string} compartmentName
|
|
369
|
+
*/
|
|
370
|
+
async (moduleSpecifier, compartmentName) => {
|
|
371
|
+
const compartmentSources =
|
|
372
|
+
sources[compartmentName] || Object.create(null);
|
|
373
|
+
sources[compartmentName] = compartmentSources;
|
|
374
|
+
compartmentSources[moduleSpecifier] = {
|
|
375
|
+
exit: moduleSpecifier,
|
|
376
|
+
};
|
|
377
|
+
exitModuleSpecifiers.push(moduleSpecifier);
|
|
378
|
+
return { imports: [], exports: [], execute() {} };
|
|
379
|
+
}
|
|
380
|
+
: undefined;
|
|
381
|
+
|
|
382
|
+
const makeImportHook = makeImportHookMaker(readPowers, entryCompartmentName, {
|
|
383
|
+
archiveOnly: true,
|
|
384
|
+
sources,
|
|
385
|
+
compartmentDescriptors: compartments,
|
|
386
|
+
searchSuffixes,
|
|
387
|
+
entryCompartmentName,
|
|
388
|
+
entryModuleSpecifier,
|
|
389
|
+
sourceMapHook,
|
|
390
|
+
importHook: exitModuleImportHook,
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Induce importHook to record all the necessary modules to import the given module specifier.
|
|
394
|
+
const { compartment } = link(compartmentMap, {
|
|
395
|
+
resolve,
|
|
396
|
+
makeImportHook,
|
|
397
|
+
moduleTransforms,
|
|
398
|
+
parserForLanguage,
|
|
399
|
+
});
|
|
400
|
+
await compartment.load(entryModuleSpecifier);
|
|
401
|
+
|
|
402
|
+
const { modules, aliases } = sortedModules(
|
|
403
|
+
compartmentMap.compartments,
|
|
404
|
+
sources,
|
|
405
|
+
entryCompartmentName,
|
|
406
|
+
entryModuleSpecifier,
|
|
407
|
+
exitModuleSpecifiers,
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
// Create an index of modules so we can resolve import specifiers to the
|
|
411
|
+
// index of the corresponding functor.
|
|
412
|
+
const modulesByKey = Object.create(null);
|
|
413
|
+
for (let index = 0; index < modules.length; index += 1) {
|
|
414
|
+
const module = modules[index];
|
|
415
|
+
module.index = index;
|
|
416
|
+
modulesByKey[module.key] = module;
|
|
417
|
+
}
|
|
418
|
+
const parsersInUse = new Set();
|
|
419
|
+
for (const module of modules) {
|
|
420
|
+
if (module.exit !== undefined) {
|
|
421
|
+
if (makeExitBundlerKit === undefined) {
|
|
422
|
+
// makeExitBundlerKit must have been provided to makeImportHookMaker for any modules with an exit property to have been created.
|
|
423
|
+
throw TypeError('Unreachable');
|
|
424
|
+
}
|
|
425
|
+
module.bundlerKit = makeExitBundlerKit(module);
|
|
426
|
+
} else {
|
|
427
|
+
module.indexedImports = Object.fromEntries(
|
|
428
|
+
Object.entries(module.resolvedImports).map(([importSpecifier, key]) => {
|
|
429
|
+
// UNTIL https://github.com/endojs/endo/issues/1514
|
|
430
|
+
// Prefer: key = aliases.get(key) ?? key;
|
|
431
|
+
const alias = aliases.get(key);
|
|
432
|
+
if (alias != null) {
|
|
433
|
+
key = alias;
|
|
434
|
+
}
|
|
435
|
+
const module = modulesByKey[key];
|
|
436
|
+
if (module === undefined) {
|
|
437
|
+
throw new Error(
|
|
438
|
+
`Unable to locate module for key ${q(key)} import specifier ${q(
|
|
439
|
+
importSpecifier,
|
|
440
|
+
)}`,
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
const { index } = module;
|
|
444
|
+
return [importSpecifier, index];
|
|
445
|
+
}),
|
|
446
|
+
);
|
|
447
|
+
parsersInUse.add(module.parser);
|
|
448
|
+
module.bundlerKit = getBundlerKitForModule(module, bundlerKitParams);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Some bundles appeal to the host module system appropriate to their format
|
|
453
|
+
// like `require` for bundles used as CommonJS modules.
|
|
454
|
+
// Each module in the modules array is constructed by a language-specific bundler kit,
|
|
455
|
+
// and in the case of an exit module, is a bundler kit made with
|
|
456
|
+
// makeExitBundlerKit, like makeCjsExitBundlerKit.
|
|
457
|
+
// This will generate a module initialization runtime that in turn needs this
|
|
458
|
+
// namespaceCells utility function to take a host module exports namespace
|
|
459
|
+
// and turn it into a bank of cells for importing and exporting the
|
|
460
|
+
// properties of the module exports namespace object.
|
|
461
|
+
const exitNamespaces =
|
|
462
|
+
exitModuleSpecifiers.length === 0
|
|
463
|
+
? ''
|
|
464
|
+
: `\
|
|
465
|
+
const namespaceCells = namespace => fromEntries(
|
|
466
|
+
getOwnPropertyNames(namespace)
|
|
467
|
+
.map(name => [name, {
|
|
468
|
+
get() {
|
|
469
|
+
return get(namespace, name);
|
|
470
|
+
},
|
|
471
|
+
set() {
|
|
472
|
+
throw new TypeError('Non-writable export');
|
|
473
|
+
},
|
|
474
|
+
observe(observer) {
|
|
475
|
+
observer(get(namespace, name));
|
|
476
|
+
},
|
|
477
|
+
enumerable: true,
|
|
478
|
+
}])
|
|
479
|
+
);
|
|
480
|
+
`;
|
|
481
|
+
|
|
482
|
+
// The linkage runtime creates a cell for every value exported by any of the
|
|
483
|
+
// bundled modules.
|
|
484
|
+
// The interface of a cell is very much like a getter/setter property
|
|
485
|
+
// deescriptor, and additionally has a method for registering an observer to
|
|
486
|
+
// notice when a variable is changed in its originating module, to support
|
|
487
|
+
// live bindings.
|
|
488
|
+
// Each module language defines its own behavior for the generation of its
|
|
489
|
+
// exported cells.
|
|
490
|
+
// After all cells are allocated, each language gets a second opportunity
|
|
491
|
+
// to introduce bindings for cells that the module re-exports from another
|
|
492
|
+
// module, but does not itself own.
|
|
493
|
+
const runtimeLinkageCells = `\
|
|
494
|
+
const cell = (name, value = undefined) => {
|
|
495
|
+
const observers = [];
|
|
496
|
+
return freeze({
|
|
497
|
+
get: freeze(() => {
|
|
498
|
+
return value;
|
|
499
|
+
}),
|
|
500
|
+
set: freeze((newValue) => {
|
|
501
|
+
value = newValue;
|
|
502
|
+
for (let i = 0; i < observers.length; i += 1) {
|
|
503
|
+
const observe = observers[i];
|
|
504
|
+
observe(value);
|
|
505
|
+
}
|
|
506
|
+
}),
|
|
507
|
+
observe: freeze((observe) => {
|
|
508
|
+
observers.push(observe);
|
|
509
|
+
observe(value);
|
|
510
|
+
}),
|
|
511
|
+
enumerable: true,
|
|
512
|
+
});
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const cells = [
|
|
516
|
+
${''.concat(...modules.map(m => m.bundlerKit.getCells()))}\
|
|
517
|
+
];
|
|
518
|
+
|
|
519
|
+
${''.concat(...modules.map(m => m.bundlerKit.getReexportsWiring()))}\
|
|
520
|
+
`;
|
|
521
|
+
|
|
522
|
+
// The linker runtime includes a parallel array of module exports namespace
|
|
523
|
+
// objects for each bundled module, for each respective index of the module
|
|
524
|
+
// functors array.
|
|
525
|
+
// Each namespace has a special '*' property for the namespace object itself,
|
|
526
|
+
// which is what modules obtain with `import * as x from 'x'` notation.
|
|
527
|
+
const moduleNamespaces = `\
|
|
528
|
+
const namespaces = cells.map(cells => freeze(create(null, {
|
|
529
|
+
...cells,
|
|
530
|
+
// Make this appear like an ESM module namespace object.
|
|
531
|
+
[Symbol.toStringTag]: {
|
|
532
|
+
value: 'Module',
|
|
533
|
+
writable: false,
|
|
534
|
+
enumerable: false,
|
|
535
|
+
configurable: false,
|
|
536
|
+
},
|
|
537
|
+
})));
|
|
538
|
+
|
|
539
|
+
for (let index = 0; index < namespaces.length; index += 1) {
|
|
540
|
+
cells[index]['*'] = cell('*', namespaces[index]);
|
|
541
|
+
}
|
|
542
|
+
`;
|
|
543
|
+
|
|
544
|
+
// Each language in use within the bundle has an opportunity to inject
|
|
545
|
+
// utilities into the bundle runtime that it can use in the shared lexical
|
|
546
|
+
// scope of module execution.
|
|
547
|
+
// CommonJS in particular injects a utility function here, if the script
|
|
548
|
+
// entrains any CommonJS modules.
|
|
549
|
+
const languageRuntimeExtensions = `\
|
|
550
|
+
${''.concat(...Array.from(parsersInUse).map(parser => getRuntime(parser)))}\
|
|
551
|
+
`;
|
|
552
|
+
|
|
553
|
+
// This section of the linker runtime causes each of the modules to execute
|
|
554
|
+
// in topological order, using a language-specific calling convention to
|
|
555
|
+
// link its imports and exports to other modules.
|
|
556
|
+
const moduleExecutionRuntime = `\
|
|
557
|
+
${''.concat(...modules.map(m => m.bundlerKit.getFunctorCall()))}\
|
|
558
|
+
`;
|
|
559
|
+
|
|
560
|
+
// The linker runtime receives an array of language-specific representations
|
|
561
|
+
// of each module, which in the simplest case is just a function and a
|
|
562
|
+
// runtime initialization calling convention (a functor).
|
|
563
|
+
// Then, in the style of partial application, it receives runtime options.
|
|
564
|
+
// When driven by makeScript, the script will statically apply the options,
|
|
565
|
+
// but with makeFunctor, the runtime must evaluate and apply runtime options.
|
|
566
|
+
// Scripts are suitable for injection with <script> tags on the web, whereas
|
|
567
|
+
// functors require use of an evaluator at runtime.
|
|
568
|
+
const linkerRuntime = `functors => options => {
|
|
569
|
+
'use strict';
|
|
570
|
+
|
|
571
|
+
const {
|
|
572
|
+
Map,
|
|
573
|
+
Object,
|
|
574
|
+
ReferenceError,
|
|
575
|
+
Reflect,
|
|
576
|
+
TypeError,
|
|
577
|
+
} = globalThis;
|
|
578
|
+
const {
|
|
579
|
+
create,
|
|
580
|
+
defineProperties,
|
|
581
|
+
defineProperty,
|
|
582
|
+
freeze,
|
|
583
|
+
fromEntries,
|
|
584
|
+
getOwnPropertyDescriptors,
|
|
585
|
+
getOwnPropertyNames,
|
|
586
|
+
keys,
|
|
587
|
+
} = Object;
|
|
588
|
+
const { get, set } = Reflect;
|
|
589
|
+
|
|
590
|
+
const {
|
|
591
|
+
${
|
|
592
|
+
!useEvaluate
|
|
593
|
+
? ''
|
|
594
|
+
: `\
|
|
595
|
+
evaluate = eval,
|
|
596
|
+
sourceUrlPrefix = ${JSON.stringify(sourceUrlPrefix)},
|
|
597
|
+
`
|
|
598
|
+
}\
|
|
599
|
+
${
|
|
600
|
+
format !== 'cjs'
|
|
601
|
+
? ''
|
|
602
|
+
: `\
|
|
603
|
+
require: tryRequire = typeof require === 'function' ? require : specifier => {
|
|
604
|
+
throw new TypeError('Cannot import host module: ' + specifier);
|
|
605
|
+
},
|
|
606
|
+
`
|
|
607
|
+
}\
|
|
608
|
+
} = options || {};
|
|
609
|
+
|
|
610
|
+
${
|
|
611
|
+
!useEvaluate
|
|
612
|
+
? ''
|
|
613
|
+
: `\
|
|
614
|
+
const evaluateSource = (source, sourceUrl) => {
|
|
615
|
+
return evaluate(source + '\\n//# sourceURL=' + sourceUrlPrefix + sourceUrl + '\\n');
|
|
616
|
+
};`
|
|
617
|
+
}\
|
|
618
|
+
|
|
619
|
+
${exitNamespaces}\
|
|
620
|
+
|
|
621
|
+
${runtimeLinkageCells}\
|
|
622
|
+
|
|
623
|
+
${moduleNamespaces}\
|
|
624
|
+
|
|
625
|
+
${languageRuntimeExtensions}\
|
|
626
|
+
|
|
627
|
+
${moduleExecutionRuntime}\
|
|
628
|
+
|
|
629
|
+
return cells[cells.length - 1]['*'].get();
|
|
630
|
+
}`;
|
|
631
|
+
|
|
632
|
+
// An array of language-specific representations of each bundled module,
|
|
633
|
+
// which in the simplest case is a function that must be initialized by the
|
|
634
|
+
// linkage runtime using a calling convention.
|
|
635
|
+
// We pass this array into the linkage runtime rather than embedding it in
|
|
636
|
+
// the linkage runtime in order to assure that the runtime's lexical context
|
|
637
|
+
// doesn't overshadow each module's lexical scope.
|
|
638
|
+
const moduleFunctors = `[
|
|
639
|
+
${''.concat(
|
|
640
|
+
...modules.map(
|
|
641
|
+
(m, index) => `\
|
|
642
|
+
// === ${index}. ${m.sourceDirname} ${m.moduleSpecifier} ===
|
|
643
|
+
${m.bundlerKit.getFunctor()}`,
|
|
644
|
+
),
|
|
645
|
+
)}\
|
|
646
|
+
]`;
|
|
647
|
+
|
|
648
|
+
// Functors partially apply the linker runtime.
|
|
649
|
+
// Scripts go on to apply static options and execute immediately.
|
|
650
|
+
return `(${linkerRuntime})(${moduleFunctors})`;
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers
|
|
655
|
+
* @param {CompartmentMapDescriptor} compartmentMap
|
|
656
|
+
* @param {BundleOptions} [options]
|
|
657
|
+
* @returns {Promise<string>}
|
|
658
|
+
*/
|
|
659
|
+
export const makeScriptFromMap = async (
|
|
660
|
+
readPowers,
|
|
661
|
+
compartmentMap,
|
|
662
|
+
options,
|
|
663
|
+
) => {
|
|
664
|
+
// Functors partially apply the linker runtime.
|
|
665
|
+
// Scripts go on to apply static options and execute immediately.
|
|
666
|
+
const functor = await makeFunctorFromMap(readPowers, compartmentMap, options);
|
|
667
|
+
return `${functor}()`;
|
|
668
|
+
};
|
package/src/bundle-mjs.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export const runtime: "function observeImports(map, importName, importIndex) {\n for (const [name, observers] of map.get(importName)) {\n const cell = cells[importIndex][name];\n if (cell === undefined) {\n throw new ReferenceError(`Cannot import name ${name}`);\n }\n for (const observer of observers) {\n cell.observe(observer);\n }\n }\n}\n";
|
|
1
|
+
export const runtime: "function observeImports(map, importName, importIndex) {\n for (const [name, observers] of map.get(importName)) {\n const cell = cells[importIndex][name];\n if (cell === undefined) {\n throw new ReferenceError(`Cannot import name ${name} (has ${Object.getOwnPropertyNames(cells[importIndex]).join(', ')})`);\n }\n for (const observer of observers) {\n cell.observe(observer);\n }\n }\n}\n";
|
|
2
2
|
declare const _default: BundlerSupport<PrecompiledModuleSource>;
|
|
3
3
|
export default _default;
|
|
4
4
|
import type { PrecompiledModuleSource } from 'ses';
|
|
5
|
-
import type { BundlerSupport } from './bundle.js';
|
|
5
|
+
import type { BundlerSupport } from './bundle-lite.js';
|
|
6
6
|
//# sourceMappingURL=bundle-mjs.d.ts.map
|
package/src/bundle-mjs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle-mjs.d.ts","sourceRoot":"","sources":["bundle-mjs.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bundle-mjs.d.ts","sourceRoot":"","sources":["bundle-mjs.js"],"names":[],"mappings":"AAwCA,ubAYE;wBAES,eAAe,uBAAuB,CAAC;;6CApDP,KAAK;oCACd,kBAAkB"}
|