@endo/compartment-mapper 1.2.2 → 1.3.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/archive-lite.d.ts.map +1 -0
- package/archive-parsers.d.ts.map +1 -0
- package/archive.d.ts.map +1 -0
- package/bundle.d.ts.map +1 -0
- package/capture-lite.d.ts.map +1 -0
- package/import-archive-lite.d.ts.map +1 -0
- package/import-archive-parsers.d.ts.map +1 -0
- package/import-archive.d.ts.map +1 -0
- package/import-lite.d.ts.map +1 -0
- package/import-parsers.d.ts.map +1 -0
- package/import.d.ts.map +1 -0
- package/index.d.ts.map +1 -0
- package/node-modules.d.ts.map +1 -0
- package/node-powers.d.ts +1 -1
- package/node-powers.d.ts.map +1 -0
- package/node-powers.js +5 -1
- package/package.json +15 -11
- package/src/compartment-map.d.ts +1 -1
- package/src/compartment-map.d.ts.map +1 -1
- package/src/compartment-map.js +1 -1
- package/src/import-hook.d.ts +14 -1
- package/src/import-hook.d.ts.map +1 -1
- package/src/import-hook.js +493 -144
- package/src/import-lite.d.ts +20 -3
- package/src/import-lite.d.ts.map +1 -1
- package/src/import-lite.js +137 -15
- package/src/import.d.ts +45 -5
- package/src/import.d.ts.map +1 -1
- package/src/import.js +52 -6
- package/src/link.d.ts +2 -11
- package/src/link.d.ts.map +1 -1
- package/src/link.js +76 -154
- package/src/map-parser.d.ts +4 -0
- package/src/map-parser.d.ts.map +1 -0
- package/src/map-parser.js +339 -0
- package/src/node-modules.d.ts +2 -5
- package/src/node-modules.d.ts.map +1 -1
- package/src/node-modules.js +12 -5
- package/src/node-powers.d.ts +29 -23
- package/src/node-powers.d.ts.map +1 -1
- package/src/node-powers.js +102 -25
- package/src/parse-archive-cjs.js +2 -1
- package/src/parse-archive-mjs.js +2 -1
- package/src/parse-bytes.d.ts.map +1 -1
- package/src/parse-bytes.js +2 -6
- package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
- package/src/parse-cjs-shared-export-wrapper.js +23 -6
- package/src/parse-cjs.js +3 -2
- package/src/parse-json.d.ts +5 -3
- package/src/parse-json.d.ts.map +1 -1
- package/src/parse-json.js +9 -9
- package/src/parse-mjs.js +2 -1
- package/src/parse-pre-cjs.js +3 -2
- package/src/parse-pre-mjs.js +2 -1
- package/src/parse-text.d.ts.map +1 -1
- package/src/parse-text.js +2 -6
- package/src/policy.d.ts +21 -14
- package/src/policy.d.ts.map +1 -1
- package/src/policy.js +53 -43
- package/src/powers.d.ts +8 -1
- package/src/powers.d.ts.map +1 -1
- package/src/powers.js +60 -10
- package/src/search.d.ts.map +1 -1
- package/src/search.js +1 -2
- package/src/types.d.ts +343 -21
- package/src/types.d.ts.map +1 -1
- package/src/types.js +369 -22
package/src/link.js
CHANGED
|
@@ -9,27 +9,34 @@
|
|
|
9
9
|
// @ts-check
|
|
10
10
|
|
|
11
11
|
/** @import {ModuleMapHook} from 'ses' */
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @import {
|
|
14
|
+
* CompartmentDescriptor,
|
|
15
|
+
* CompartmentMapDescriptor,
|
|
16
|
+
* ImportNowHookMaker,
|
|
17
|
+
* LanguageForExtension,
|
|
18
|
+
* LinkOptions,
|
|
19
|
+
* LinkResult,
|
|
20
|
+
* ModuleDescriptor,
|
|
21
|
+
* ParseFn,
|
|
22
|
+
* ParseFnAsync,
|
|
23
|
+
* ParserForLanguage,
|
|
24
|
+
* ParserImplementation,
|
|
25
|
+
* ShouldDeferError,
|
|
26
|
+
* } from './types.js'
|
|
27
|
+
*/
|
|
21
28
|
/** @import {ERef} from '@endo/eventual-send' */
|
|
22
29
|
|
|
30
|
+
import { makeMapParsers } from './map-parser.js';
|
|
23
31
|
import { resolve as resolveFallback } from './node-module-specifier.js';
|
|
24
|
-
import { parseExtension } from './extension.js';
|
|
25
32
|
import {
|
|
26
|
-
enforceModulePolicy,
|
|
27
33
|
ATTENUATORS_COMPARTMENT,
|
|
28
34
|
attenuateGlobals,
|
|
35
|
+
enforceModulePolicy,
|
|
29
36
|
makeDeferredAttenuatorsProvider,
|
|
30
37
|
} from './policy.js';
|
|
31
38
|
|
|
32
|
-
const { assign, create, entries, freeze
|
|
39
|
+
const { assign, create, entries, freeze } = Object;
|
|
33
40
|
const { hasOwnProperty } = Object.prototype;
|
|
34
41
|
const { apply } = Reflect;
|
|
35
42
|
const { allSettled } = Promise;
|
|
@@ -52,130 +59,6 @@ const q = JSON.stringify;
|
|
|
52
59
|
*/
|
|
53
60
|
const has = (object, key) => apply(hasOwnProperty, object, [key]);
|
|
54
61
|
|
|
55
|
-
/**
|
|
56
|
-
* Decide if extension is clearly indicating a parser/language for a file
|
|
57
|
-
*
|
|
58
|
-
* @param {string} extension
|
|
59
|
-
* @returns {boolean}
|
|
60
|
-
*/
|
|
61
|
-
const extensionImpliesLanguage = extension => extension !== 'js';
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* `makeExtensionParser` produces a `parser` that parses the content of a
|
|
65
|
-
* module according to the corresponding module language, given the extension
|
|
66
|
-
* of the module specifier and the configuration of the containing compartment.
|
|
67
|
-
* We do not yet support import assertions and we do not have a mechanism
|
|
68
|
-
* for validating the MIME type of the module content against the
|
|
69
|
-
* language implied by the extension or file name.
|
|
70
|
-
*
|
|
71
|
-
* @param {Record<string, string>} languageForExtension - maps a file extension
|
|
72
|
-
* to the corresponding language.
|
|
73
|
-
* @param {Record<string, string>} languageForModuleSpecifier - In a rare case,
|
|
74
|
-
* the type of a module is implied by package.json and should not be inferred
|
|
75
|
-
* from its extension.
|
|
76
|
-
* @param {ParserForLanguage} parserForLanguage
|
|
77
|
-
* @param {ModuleTransforms} moduleTransforms
|
|
78
|
-
* @returns {ParseFn}
|
|
79
|
-
*/
|
|
80
|
-
const makeExtensionParser = (
|
|
81
|
-
languageForExtension,
|
|
82
|
-
languageForModuleSpecifier,
|
|
83
|
-
parserForLanguage,
|
|
84
|
-
moduleTransforms,
|
|
85
|
-
) => {
|
|
86
|
-
return async (bytes, specifier, location, packageLocation, options) => {
|
|
87
|
-
await null;
|
|
88
|
-
let language;
|
|
89
|
-
const extension = parseExtension(location);
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
!extensionImpliesLanguage(extension) &&
|
|
93
|
-
has(languageForModuleSpecifier, specifier)
|
|
94
|
-
) {
|
|
95
|
-
language = languageForModuleSpecifier[specifier];
|
|
96
|
-
} else {
|
|
97
|
-
language = languageForExtension[extension] || extension;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let sourceMap;
|
|
101
|
-
|
|
102
|
-
if (has(moduleTransforms, language)) {
|
|
103
|
-
try {
|
|
104
|
-
({
|
|
105
|
-
bytes,
|
|
106
|
-
parser: language,
|
|
107
|
-
sourceMap,
|
|
108
|
-
} = await moduleTransforms[language](
|
|
109
|
-
bytes,
|
|
110
|
-
specifier,
|
|
111
|
-
location,
|
|
112
|
-
packageLocation,
|
|
113
|
-
{
|
|
114
|
-
// At time of writing, sourceMap is always undefined, but keeping
|
|
115
|
-
// it here is more resilient if the surrounding if block becomes a
|
|
116
|
-
// loop for multi-step transforms.
|
|
117
|
-
sourceMap,
|
|
118
|
-
},
|
|
119
|
-
));
|
|
120
|
-
} catch (err) {
|
|
121
|
-
throw Error(
|
|
122
|
-
`Error transforming ${q(language)} source in ${q(location)}: ${
|
|
123
|
-
err.message
|
|
124
|
-
}`,
|
|
125
|
-
{ cause: err },
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!has(parserForLanguage, language)) {
|
|
131
|
-
throw Error(
|
|
132
|
-
`Cannot parse module ${specifier} at ${location}, no parser configured for the language ${language}`,
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
const { parse } = /** @type {ParserImplementation} */ (
|
|
136
|
-
parserForLanguage[language]
|
|
137
|
-
);
|
|
138
|
-
return parse(bytes, specifier, location, packageLocation, {
|
|
139
|
-
sourceMap,
|
|
140
|
-
...options,
|
|
141
|
-
});
|
|
142
|
-
};
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @param {LanguageForExtension} languageForExtension
|
|
147
|
-
* @param {Record<string, string>} languageForModuleSpecifier - In a rare case, the type of a module
|
|
148
|
-
* is implied by package.json and should not be inferred from its extension.
|
|
149
|
-
* @param {ParserForLanguage} parserForLanguage
|
|
150
|
-
* @param {ModuleTransforms} moduleTransforms
|
|
151
|
-
* @returns {ParseFn}
|
|
152
|
-
*/
|
|
153
|
-
export const mapParsers = (
|
|
154
|
-
languageForExtension,
|
|
155
|
-
languageForModuleSpecifier,
|
|
156
|
-
parserForLanguage,
|
|
157
|
-
moduleTransforms = {},
|
|
158
|
-
) => {
|
|
159
|
-
const languageForExtensionEntries = [];
|
|
160
|
-
const problems = [];
|
|
161
|
-
for (const [extension, language] of entries(languageForExtension)) {
|
|
162
|
-
if (has(parserForLanguage, language)) {
|
|
163
|
-
languageForExtensionEntries.push([extension, language]);
|
|
164
|
-
} else {
|
|
165
|
-
problems.push(`${q(language)} for extension ${q(extension)}`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (problems.length > 0) {
|
|
169
|
-
throw Error(`No parser available for language: ${problems.join(', ')}`);
|
|
170
|
-
}
|
|
171
|
-
return makeExtensionParser(
|
|
172
|
-
fromEntries(languageForExtensionEntries),
|
|
173
|
-
languageForModuleSpecifier,
|
|
174
|
-
parserForLanguage,
|
|
175
|
-
moduleTransforms,
|
|
176
|
-
);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
62
|
/**
|
|
180
63
|
* For a full, absolute module specifier like "dependency",
|
|
181
64
|
* produce the module specifier in the dependency, like ".".
|
|
@@ -328,36 +211,57 @@ const makeModuleMapHook = (
|
|
|
328
211
|
return moduleMapHook;
|
|
329
212
|
};
|
|
330
213
|
|
|
214
|
+
/**
|
|
215
|
+
* @type {ImportNowHookMaker}
|
|
216
|
+
*/
|
|
217
|
+
const impossibleImportNowHookMaker = () => {
|
|
218
|
+
return function impossibleImportNowHook() {
|
|
219
|
+
throw new Error('Provided read powers do not support dynamic requires');
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
|
|
331
223
|
/**
|
|
332
224
|
* Assemble a DAG of compartments as declared in a compartment map starting at
|
|
333
225
|
* the named compartment and building all compartments that it depends upon,
|
|
334
226
|
* recursively threading the modules exported by one compartment into the
|
|
335
227
|
* compartment that imports them.
|
|
336
|
-
* Returns the root of the compartment DAG.
|
|
337
|
-
* Does not load or execute any modules.
|
|
338
|
-
* Uses makeImportHook with the given "location" string of each compartment in
|
|
339
|
-
* the DAG.
|
|
340
|
-
* Passes the given globals and external modules into the root compartment
|
|
341
|
-
* only.
|
|
342
228
|
*
|
|
229
|
+
* - Returns the root of the compartment DAG.
|
|
230
|
+
* - Does not load or execute any modules.
|
|
231
|
+
* - Uses `makeImportHook` with the given "location" string of each compartment
|
|
232
|
+
* in the DAG.
|
|
233
|
+
* - Passes the given globals and external modules into the root compartment
|
|
234
|
+
* only.
|
|
235
|
+
*
|
|
236
|
+
* @param {CompartmentMapDescriptor} compartmentMap
|
|
237
|
+
* @param {LinkOptions} options
|
|
238
|
+
* @returns {LinkResult} the root compartment of the compartment DAG
|
|
239
|
+
*/
|
|
240
|
+
|
|
241
|
+
/**
|
|
343
242
|
* @param {CompartmentMapDescriptor} compartmentMap
|
|
344
243
|
* @param {LinkOptions} options
|
|
244
|
+
* @returns {LinkResult}
|
|
345
245
|
*/
|
|
346
246
|
export const link = (
|
|
347
247
|
{ entry, compartments: compartmentDescriptors },
|
|
348
|
-
|
|
248
|
+
options,
|
|
249
|
+
) => {
|
|
250
|
+
const {
|
|
349
251
|
resolve = resolveFallback,
|
|
350
252
|
makeImportHook,
|
|
253
|
+
makeImportNowHook = impossibleImportNowHookMaker,
|
|
351
254
|
parserForLanguage: parserForLanguageOption = {},
|
|
352
255
|
languageForExtension: languageForExtensionOption = {},
|
|
353
256
|
globals = {},
|
|
354
257
|
transforms = [],
|
|
355
|
-
moduleTransforms
|
|
258
|
+
moduleTransforms,
|
|
259
|
+
syncModuleTransforms,
|
|
356
260
|
__shimTransforms__ = [],
|
|
357
261
|
archiveOnly = false,
|
|
358
262
|
Compartment = defaultCompartment,
|
|
359
|
-
}
|
|
360
|
-
|
|
263
|
+
} = options;
|
|
264
|
+
|
|
361
265
|
const { compartment: entryCompartmentName } = entry;
|
|
362
266
|
|
|
363
267
|
/** @type {Record<string, Compartment>} */
|
|
@@ -382,19 +286,28 @@ export const link = (
|
|
|
382
286
|
assign(create(null), parserForLanguageOption),
|
|
383
287
|
);
|
|
384
288
|
|
|
289
|
+
const mapParsers = makeMapParsers({
|
|
290
|
+
parserForLanguage,
|
|
291
|
+
moduleTransforms,
|
|
292
|
+
syncModuleTransforms,
|
|
293
|
+
});
|
|
294
|
+
|
|
385
295
|
for (const [compartmentName, compartmentDescriptor] of entries(
|
|
386
296
|
compartmentDescriptors,
|
|
387
297
|
)) {
|
|
388
|
-
// TODO: The default assignments seem to break type inference
|
|
389
298
|
const {
|
|
390
299
|
location,
|
|
391
300
|
name,
|
|
392
|
-
modules = create(null),
|
|
393
301
|
parsers: languageForExtensionOverrides = {},
|
|
394
302
|
types: languageForModuleSpecifierOverrides = {},
|
|
395
|
-
scopes = create(null),
|
|
396
303
|
} = compartmentDescriptor;
|
|
397
304
|
|
|
305
|
+
// this is for retaining the correct type inference about these values
|
|
306
|
+
// without use of `let`
|
|
307
|
+
const { scopes: _scopes, modules: _modules } = compartmentDescriptor;
|
|
308
|
+
const modules = _modules || create(null);
|
|
309
|
+
const scopes = _scopes || create(null);
|
|
310
|
+
|
|
398
311
|
// Capture the default.
|
|
399
312
|
// The `moduleMapHook` writes back to the compartment map.
|
|
400
313
|
compartmentDescriptor.modules = modules;
|
|
@@ -412,12 +325,12 @@ export const link = (
|
|
|
412
325
|
),
|
|
413
326
|
);
|
|
414
327
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
moduleTransforms,
|
|
328
|
+
// TS is kind of dumb about this, so we can use a type assertion to avoid a
|
|
329
|
+
// pointless ternary.
|
|
330
|
+
const parse = /** @type {ParseFn|ParseFnAsync} */ (
|
|
331
|
+
mapParsers(languageForExtension, languageForModuleSpecifier)
|
|
420
332
|
);
|
|
333
|
+
|
|
421
334
|
/** @type {ShouldDeferError} */
|
|
422
335
|
const shouldDeferError = language => {
|
|
423
336
|
if (language && has(parserForLanguage, language)) {
|
|
@@ -441,6 +354,14 @@ export const link = (
|
|
|
441
354
|
shouldDeferError,
|
|
442
355
|
compartments,
|
|
443
356
|
});
|
|
357
|
+
|
|
358
|
+
const importNowHook = makeImportNowHook({
|
|
359
|
+
packageLocation: location,
|
|
360
|
+
packageName: name,
|
|
361
|
+
parse,
|
|
362
|
+
compartments,
|
|
363
|
+
});
|
|
364
|
+
|
|
444
365
|
const moduleMapHook = makeModuleMapHook(
|
|
445
366
|
compartmentDescriptor,
|
|
446
367
|
compartments,
|
|
@@ -453,6 +374,7 @@ export const link = (
|
|
|
453
374
|
name: location,
|
|
454
375
|
resolveHook,
|
|
455
376
|
importHook,
|
|
377
|
+
importNowHook,
|
|
456
378
|
moduleMapHook,
|
|
457
379
|
transforms,
|
|
458
380
|
__shimTransforms__,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export function makeMapParsers({ parserForLanguage, moduleTransforms, syncModuleTransforms, }: MakeMapParsersOptions): MapParsersFn;
|
|
2
|
+
import type { MakeMapParsersOptions } from './types.js';
|
|
3
|
+
import type { MapParsersFn } from './types.js';
|
|
4
|
+
//# sourceMappingURL=map-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-parser.d.ts","sourceRoot":"","sources":["map-parser.js"],"names":[],"mappings":"AAqSO,+FAHI,qBAAqB,GACnB,YAAY,CA+CxB;2CAxTS,YAAY;kCAAZ,YAAY"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exports {@link makeMapParsers}, which creates a function which matches a
|
|
3
|
+
* module to a parser based on reasons.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// @ts-check
|
|
9
|
+
|
|
10
|
+
import { syncTrampoline, asyncTrampoline } from '@endo/trampoline';
|
|
11
|
+
import { parseExtension } from './extension.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @import {
|
|
15
|
+
* LanguageForExtension,
|
|
16
|
+
* LanguageForModuleSpecifier,
|
|
17
|
+
* MakeMapParsersOptions,
|
|
18
|
+
* MapParsersFn,
|
|
19
|
+
* ModuleTransform,
|
|
20
|
+
* ModuleTransforms,
|
|
21
|
+
* ParseFn,
|
|
22
|
+
* ParseFnAsync,
|
|
23
|
+
* ParseResult,
|
|
24
|
+
* ParserForLanguage,
|
|
25
|
+
* SyncModuleTransform,
|
|
26
|
+
* SyncModuleTransforms
|
|
27
|
+
* } from './types.js';
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const { entries, fromEntries, keys, hasOwnProperty, values } = Object;
|
|
31
|
+
const { apply } = Reflect;
|
|
32
|
+
// q, as in quote, for strings in error messages.
|
|
33
|
+
const q = JSON.stringify;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {Record<string, unknown>} object
|
|
37
|
+
* @param {string} key
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
const has = (object, key) => apply(hasOwnProperty, object, [key]);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Decide if extension is clearly indicating a parser/language for a file
|
|
44
|
+
*
|
|
45
|
+
* @param {string} extension
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
const extensionImpliesLanguage = extension => extension !== 'js';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Produces a `parser` that parses the content of a module according to the
|
|
52
|
+
* corresponding module language, given the extension of the module specifier
|
|
53
|
+
* and the configuration of the containing compartment. We do not yet support
|
|
54
|
+
* import assertions and we do not have a mechanism for validating the MIME type
|
|
55
|
+
* of the module content against the language implied by the extension or file
|
|
56
|
+
* name.
|
|
57
|
+
*
|
|
58
|
+
* @param {boolean} preferSynchronous
|
|
59
|
+
* @param {Record<string, string>} languageForExtension - maps a file extension
|
|
60
|
+
* to the corresponding language.
|
|
61
|
+
* @param {Record<string, string>} languageForModuleSpecifier - In a rare case,
|
|
62
|
+
* the type of a module is implied by package.json and should not be inferred
|
|
63
|
+
* from its extension.
|
|
64
|
+
* @param {ParserForLanguage} parserForLanguage
|
|
65
|
+
* @param {ModuleTransforms} moduleTransforms
|
|
66
|
+
* @param {SyncModuleTransforms} syncModuleTransforms
|
|
67
|
+
* @returns {ParseFnAsync|ParseFn}
|
|
68
|
+
*/
|
|
69
|
+
const makeExtensionParser = (
|
|
70
|
+
preferSynchronous,
|
|
71
|
+
languageForExtension,
|
|
72
|
+
languageForModuleSpecifier,
|
|
73
|
+
parserForLanguage,
|
|
74
|
+
moduleTransforms,
|
|
75
|
+
syncModuleTransforms,
|
|
76
|
+
) => {
|
|
77
|
+
/** @type {Record<string, ModuleTransform | SyncModuleTransform>} */
|
|
78
|
+
let transforms;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Function returning a generator which executes a parser for a module in either sync or async context.
|
|
82
|
+
*
|
|
83
|
+
* @param {Uint8Array} bytes
|
|
84
|
+
* @param {string} specifier
|
|
85
|
+
* @param {string} location
|
|
86
|
+
* @param {string} packageLocation
|
|
87
|
+
* @param {*} options
|
|
88
|
+
* @returns {Generator<ReturnType<ModuleTransform>|ReturnType<SyncModuleTransform>, ParseResult, Awaited<ReturnType<ModuleTransform>|ReturnType<SyncModuleTransform>>>}
|
|
89
|
+
*/
|
|
90
|
+
function* getParserGenerator(
|
|
91
|
+
bytes,
|
|
92
|
+
specifier,
|
|
93
|
+
location,
|
|
94
|
+
packageLocation,
|
|
95
|
+
options,
|
|
96
|
+
) {
|
|
97
|
+
/** @type {string} */
|
|
98
|
+
let language;
|
|
99
|
+
const extension = parseExtension(location);
|
|
100
|
+
|
|
101
|
+
if (
|
|
102
|
+
!extensionImpliesLanguage(extension) &&
|
|
103
|
+
has(languageForModuleSpecifier, specifier)
|
|
104
|
+
) {
|
|
105
|
+
language = languageForModuleSpecifier[specifier];
|
|
106
|
+
} else {
|
|
107
|
+
language = languageForExtension[extension] || extension;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** @type {string|undefined} */
|
|
111
|
+
let sourceMap;
|
|
112
|
+
|
|
113
|
+
if (has(transforms, language)) {
|
|
114
|
+
try {
|
|
115
|
+
({
|
|
116
|
+
bytes,
|
|
117
|
+
parser: language,
|
|
118
|
+
sourceMap,
|
|
119
|
+
} = yield transforms[language](
|
|
120
|
+
bytes,
|
|
121
|
+
specifier,
|
|
122
|
+
location,
|
|
123
|
+
packageLocation,
|
|
124
|
+
{
|
|
125
|
+
// At time of writing, sourceMap is always undefined, but keeping
|
|
126
|
+
// it here is more resilient if the surrounding if block becomes a
|
|
127
|
+
// loop for multi-step transforms.
|
|
128
|
+
sourceMap,
|
|
129
|
+
},
|
|
130
|
+
));
|
|
131
|
+
} catch (err) {
|
|
132
|
+
throw Error(
|
|
133
|
+
`Error transforming ${q(language)} source in ${q(location)}: ${err.message}`,
|
|
134
|
+
{ cause: err },
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (!has(parserForLanguage, language)) {
|
|
139
|
+
throw Error(
|
|
140
|
+
`Cannot parse module ${specifier} at ${location}, no parser configured for the language ${language}`,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const { parse } = parserForLanguage[language];
|
|
144
|
+
return parse(bytes, specifier, location, packageLocation, {
|
|
145
|
+
sourceMap,
|
|
146
|
+
...options,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @type {ParseFn}
|
|
152
|
+
*/
|
|
153
|
+
const syncParser = (bytes, specifier, location, packageLocation, options) => {
|
|
154
|
+
const result = syncTrampoline(
|
|
155
|
+
getParserGenerator,
|
|
156
|
+
bytes,
|
|
157
|
+
specifier,
|
|
158
|
+
location,
|
|
159
|
+
packageLocation,
|
|
160
|
+
options,
|
|
161
|
+
);
|
|
162
|
+
if ('then' in result && typeof result.then === 'function') {
|
|
163
|
+
throw new TypeError(
|
|
164
|
+
'Sync parser cannot return a Thenable; ensure parser is actually synchronous',
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
};
|
|
169
|
+
syncParser.isSyncParser = true;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @type {ParseFnAsync}
|
|
173
|
+
*/
|
|
174
|
+
const asyncParser = async (
|
|
175
|
+
bytes,
|
|
176
|
+
specifier,
|
|
177
|
+
location,
|
|
178
|
+
packageLocation,
|
|
179
|
+
options,
|
|
180
|
+
) => {
|
|
181
|
+
return asyncTrampoline(
|
|
182
|
+
getParserGenerator,
|
|
183
|
+
bytes,
|
|
184
|
+
specifier,
|
|
185
|
+
location,
|
|
186
|
+
packageLocation,
|
|
187
|
+
options,
|
|
188
|
+
);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Unfortunately, typescript was not smart enough to figure out the return
|
|
192
|
+
// type depending on a boolean in arguments, so it has to be
|
|
193
|
+
// ParseFnAsync|ParseFn
|
|
194
|
+
if (preferSynchronous) {
|
|
195
|
+
transforms = syncModuleTransforms;
|
|
196
|
+
return syncParser;
|
|
197
|
+
} else {
|
|
198
|
+
// we can fold syncModuleTransforms into moduleTransforms because
|
|
199
|
+
// async supports sync, but not vice-versa
|
|
200
|
+
transforms = {
|
|
201
|
+
...syncModuleTransforms,
|
|
202
|
+
...moduleTransforms,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
return asyncParser;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Creates a synchronous parser
|
|
211
|
+
*
|
|
212
|
+
* @overload
|
|
213
|
+
* @param {LanguageForExtension} languageForExtension
|
|
214
|
+
* @param {LanguageForModuleSpecifier} languageForModuleSpecifier - In a rare case,
|
|
215
|
+
* the type of a module is implied by package.json and should not be inferred
|
|
216
|
+
* from its extension.
|
|
217
|
+
* @param {ParserForLanguage} parserForLanguage
|
|
218
|
+
* @param {ModuleTransforms} [moduleTransforms]
|
|
219
|
+
* @param {SyncModuleTransforms} [syncModuleTransforms]
|
|
220
|
+
* @param {true} preferSynchronous If `true`, will create a `ParseFn`
|
|
221
|
+
* @returns {ParseFn}
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Creates an asynchronous parser
|
|
226
|
+
*
|
|
227
|
+
* @overload
|
|
228
|
+
* @param {LanguageForExtension} languageForExtension
|
|
229
|
+
* @param {LanguageForModuleSpecifier} languageForModuleSpecifier - In a rare case,
|
|
230
|
+
* the type of a module is implied by package.json and should not be inferred
|
|
231
|
+
* from its extension.
|
|
232
|
+
* @param {ParserForLanguage} parserForLanguage
|
|
233
|
+
* @param {ModuleTransforms} [moduleTransforms]
|
|
234
|
+
* @param {SyncModuleTransforms} [syncModuleTransforms]
|
|
235
|
+
* @param {false} [preferSynchronous]
|
|
236
|
+
* @returns {ParseFnAsync}
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @param {LanguageForExtension} languageForExtension
|
|
241
|
+
* @param {LanguageForModuleSpecifier} languageForModuleSpecifier - In a rare case,
|
|
242
|
+
* the type of a module is implied by package.json and should not be inferred
|
|
243
|
+
* from its extension.
|
|
244
|
+
* @param {ParserForLanguage} parserForLanguage
|
|
245
|
+
* @param {ModuleTransforms} [moduleTransforms]
|
|
246
|
+
* @param {SyncModuleTransforms} [syncModuleTransforms]
|
|
247
|
+
* @param {boolean} [preferSynchronous] If `true`, will create a `ParseFn`
|
|
248
|
+
* @returns {ParseFnAsync|ParseFn}
|
|
249
|
+
*/
|
|
250
|
+
function mapParsers(
|
|
251
|
+
languageForExtension,
|
|
252
|
+
languageForModuleSpecifier,
|
|
253
|
+
parserForLanguage,
|
|
254
|
+
moduleTransforms = {},
|
|
255
|
+
syncModuleTransforms = {},
|
|
256
|
+
preferSynchronous = false,
|
|
257
|
+
) {
|
|
258
|
+
const languageForExtensionEntries = [];
|
|
259
|
+
const problems = [];
|
|
260
|
+
for (const [extension, language] of entries(languageForExtension)) {
|
|
261
|
+
if (has(parserForLanguage, language)) {
|
|
262
|
+
languageForExtensionEntries.push([extension, language]);
|
|
263
|
+
} else {
|
|
264
|
+
problems.push(`${q(language)} for extension ${q(extension)}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (problems.length > 0) {
|
|
268
|
+
throw Error(`No parser available for language: ${problems.join(', ')}`);
|
|
269
|
+
}
|
|
270
|
+
return makeExtensionParser(
|
|
271
|
+
preferSynchronous,
|
|
272
|
+
fromEntries(languageForExtensionEntries),
|
|
273
|
+
languageForModuleSpecifier,
|
|
274
|
+
parserForLanguage,
|
|
275
|
+
moduleTransforms,
|
|
276
|
+
syncModuleTransforms,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Prepares a function to map parsers after verifying whether synchronous
|
|
282
|
+
* behavior is preferred. Synchronous behavior is selected if all parsers are
|
|
283
|
+
* synchronous and no async transforms are provided.
|
|
284
|
+
*
|
|
285
|
+
* _Note:_ The type argument for {@link MapParsersFn} _could_ be inferred from
|
|
286
|
+
* the function arguments _if_ {@link ParserForLanguage} contained only values
|
|
287
|
+
* of type `ParserImplementation & {synchronous: true}` (and also considering
|
|
288
|
+
* the emptiness of `moduleTransforms`); may only be worth the effort if it was
|
|
289
|
+
* causing issues in practice.
|
|
290
|
+
*
|
|
291
|
+
* @param {MakeMapParsersOptions} options
|
|
292
|
+
* @returns {MapParsersFn}
|
|
293
|
+
*/
|
|
294
|
+
export const makeMapParsers = ({
|
|
295
|
+
parserForLanguage,
|
|
296
|
+
moduleTransforms,
|
|
297
|
+
syncModuleTransforms,
|
|
298
|
+
}) => {
|
|
299
|
+
/**
|
|
300
|
+
* Async `mapParsers()` function; returned when a non-synchronous parser is
|
|
301
|
+
* present _or_ when `moduleTransforms` is non-empty.
|
|
302
|
+
*
|
|
303
|
+
* @type {MapParsersFn<ParseFnAsync>}
|
|
304
|
+
*/
|
|
305
|
+
const asyncParseFn = (languageForExtension, languageForModuleSpecifier) =>
|
|
306
|
+
mapParsers(
|
|
307
|
+
languageForExtension,
|
|
308
|
+
languageForModuleSpecifier,
|
|
309
|
+
parserForLanguage,
|
|
310
|
+
moduleTransforms,
|
|
311
|
+
syncModuleTransforms,
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
if (moduleTransforms && keys(moduleTransforms).length > 0) {
|
|
315
|
+
return asyncParseFn;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// all parsers must explicitly be flagged `synchronous` to return a
|
|
319
|
+
// `MapParsersFn<ParseFn>`
|
|
320
|
+
if (values(parserForLanguage).some(({ synchronous }) => !synchronous)) {
|
|
321
|
+
return asyncParseFn;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Synchronous `mapParsers()` function; returned when all parsers are
|
|
326
|
+
* synchronous and `moduleTransforms` is empty.
|
|
327
|
+
*
|
|
328
|
+
* @type {MapParsersFn<ParseFn>}
|
|
329
|
+
*/
|
|
330
|
+
return (languageForExtension, languageForModuleSpecifier) =>
|
|
331
|
+
mapParsers(
|
|
332
|
+
languageForExtension,
|
|
333
|
+
languageForModuleSpecifier,
|
|
334
|
+
parserForLanguage,
|
|
335
|
+
moduleTransforms,
|
|
336
|
+
syncModuleTransforms,
|
|
337
|
+
true,
|
|
338
|
+
);
|
|
339
|
+
};
|
package/src/node-modules.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
export function compartmentMapForNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers, packageLocation: string, conditions: Set<string>, packageDescriptor: object, moduleSpecifier: string, options?:
|
|
2
|
-
dev?: boolean | undefined;
|
|
3
|
-
commonDependencies?: object;
|
|
4
|
-
policy?: object;
|
|
5
|
-
} | undefined): Promise<CompartmentMapDescriptor>;
|
|
1
|
+
export function compartmentMapForNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers, packageLocation: string, conditions: Set<string>, packageDescriptor: object, moduleSpecifier: string, options?: CompartmentMapForNodeModulesOptions | undefined): Promise<CompartmentMapDescriptor>;
|
|
6
2
|
export function mapNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers, moduleLocation: string, options?: {
|
|
7
3
|
tags?: Set<string> | undefined;
|
|
8
4
|
conditions?: Set<string> | undefined;
|
|
@@ -49,6 +45,7 @@ export type ReadDescriptorFn = (packageLocation: string) => Promise<object>;
|
|
|
49
45
|
import type { ReadFn } from './types.js';
|
|
50
46
|
import type { ReadPowers } from './types.js';
|
|
51
47
|
import type { MaybeReadPowers } from './types.js';
|
|
48
|
+
import type { CompartmentMapForNodeModulesOptions } from './types.js';
|
|
52
49
|
import type { CompartmentMapDescriptor } from './types.js';
|
|
53
50
|
import type { LanguageForExtension } from './types.js';
|
|
54
51
|
import type { Language } from './types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-modules.d.ts","sourceRoot":"","sources":["node-modules.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node-modules.d.ts","sourceRoot":"","sources":["node-modules.js"],"names":[],"mappings":"AAwvBO,yDARI,MAAM,GAAG,UAAU,GAAG,eAAe,mBACrC,MAAM,cACN,GAAG,CAAC,MAAM,CAAC,qBACX,MAAM,mBACN,MAAM,8DAEJ,OAAO,CAAC,wBAAwB,CAAC,CA+C7C;AAaM,2CAVI,MAAM,GAAG,UAAU,GAAG,eAAe,kBACrC,MAAM;;;;yBAKN,MAAM;aACN,MAAM;gBACJ,OAAO,CAAC,wBAAwB,CAAC,CAmC7C;;;;;;;oBAjzBY,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;;WAKnB,MAAM;UACN,MAAM;UACN,KAAK,CAAC,MAAM,CAAC;iBACb,KAAK,CAAC,MAAM,CAAC;qBACb,OAAO;qBACP,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;qBACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;yBACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;aAEtB,oBAAoB;;;;;WAEpB,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC;;0CAKzB,MAAM,CAAC,MAAM,EAAE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC;iDA+E/C,MAAM,KACJ,OAAO,CAAC,MAAM,CAAC;4BAhHF,YAAY;gCACR,YAAY;qCAHP,YAAY;yDAPQ,YAAY;8CAGvB,YAAY;0CAEhB,YAAY;8BADxB,YAAY"}
|