@endo/compartment-mapper 1.6.3 → 2.1.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/package.json +24 -14
- package/src/archive-lite.d.ts +7 -7
- package/src/archive-lite.d.ts.map +1 -1
- package/src/archive-lite.js +81 -30
- package/src/archive.d.ts.map +1 -1
- package/src/archive.js +7 -0
- package/src/bundle-lite.d.ts +3 -3
- package/src/bundle-lite.d.ts.map +1 -1
- package/src/bundle-lite.js +19 -24
- package/src/bundle.d.ts +3 -3
- package/src/bundle.d.ts.map +1 -1
- package/src/bundle.js +19 -24
- package/src/capture-lite.d.ts +2 -2
- package/src/capture-lite.d.ts.map +1 -1
- package/src/capture-lite.js +243 -25
- package/src/compartment-map.d.ts +9 -2
- package/src/compartment-map.d.ts.map +1 -1
- package/src/compartment-map.js +738 -254
- package/src/digest.d.ts +22 -2
- package/src/digest.d.ts.map +1 -1
- package/src/digest.js +180 -57
- package/src/generic-graph.d.ts +7 -25
- package/src/generic-graph.d.ts.map +1 -1
- package/src/generic-graph.js +83 -108
- package/src/guards.d.ts +18 -0
- package/src/guards.d.ts.map +1 -0
- package/src/guards.js +109 -0
- package/src/hooks.md +124 -0
- package/src/import-archive-lite.d.ts.map +1 -1
- package/src/import-archive-lite.js +15 -11
- package/src/import-archive.d.ts +5 -19
- package/src/import-archive.d.ts.map +1 -1
- package/src/import-archive.js +7 -27
- package/src/import-hook.d.ts +4 -3
- package/src/import-hook.d.ts.map +1 -1
- package/src/import-hook.js +140 -70
- package/src/import-lite.d.ts +6 -6
- package/src/import-lite.d.ts.map +1 -1
- package/src/import-lite.js +8 -5
- package/src/import.d.ts +3 -3
- package/src/import.d.ts.map +1 -1
- package/src/import.js +16 -6
- package/src/infer-exports.d.ts +4 -2
- package/src/infer-exports.d.ts.map +1 -1
- package/src/infer-exports.js +172 -23
- package/src/link.d.ts +4 -3
- package/src/link.d.ts.map +1 -1
- package/src/link.js +122 -52
- package/src/node-modules.d.ts +4 -3
- package/src/node-modules.d.ts.map +1 -1
- package/src/node-modules.js +513 -151
- package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
- package/src/parse-cjs-shared-export-wrapper.js +3 -1
- package/src/pattern-replacement.d.ts +6 -0
- package/src/pattern-replacement.d.ts.map +1 -0
- package/src/pattern-replacement.js +198 -0
- package/src/policy-format.d.ts +22 -5
- package/src/policy-format.d.ts.map +1 -1
- package/src/policy-format.js +342 -108
- package/src/policy.d.ts +13 -28
- package/src/policy.d.ts.map +1 -1
- package/src/policy.js +161 -106
- package/src/types/canonical-name.d.ts +97 -0
- package/src/types/canonical-name.d.ts.map +1 -0
- package/src/types/canonical-name.ts +151 -0
- package/src/types/compartment-map-schema.d.ts +121 -35
- package/src/types/compartment-map-schema.d.ts.map +1 -1
- package/src/types/compartment-map-schema.ts +211 -37
- package/src/types/external.d.ts +240 -76
- package/src/types/external.d.ts.map +1 -1
- package/src/types/external.ts +305 -74
- package/src/types/generic-graph.d.ts +8 -2
- package/src/types/generic-graph.d.ts.map +1 -1
- package/src/types/generic-graph.ts +7 -2
- package/src/types/internal.d.ts +31 -50
- package/src/types/internal.d.ts.map +1 -1
- package/src/types/internal.ts +60 -58
- package/src/types/node-modules.d.ts +112 -14
- package/src/types/node-modules.d.ts.map +1 -1
- package/src/types/node-modules.ts +152 -13
- package/src/types/pattern-replacement.d.ts +62 -0
- package/src/types/pattern-replacement.d.ts.map +1 -0
- package/src/types/pattern-replacement.ts +70 -0
- package/src/types/policy-schema.d.ts +26 -11
- package/src/types/policy-schema.d.ts.map +1 -1
- package/src/types/policy-schema.ts +29 -16
- package/src/types/policy.d.ts +6 -2
- package/src/types/policy.d.ts.map +1 -1
- package/src/types/policy.ts +7 -2
- package/src/types/powers.d.ts +11 -9
- package/src/types/powers.d.ts.map +1 -1
- package/src/types/powers.ts +11 -10
- package/src/types/typescript.d.ts +28 -0
- package/src/types/typescript.d.ts.map +1 -1
- package/src/types/typescript.ts +37 -1
package/src/compartment-map.js
CHANGED
|
@@ -1,14 +1,43 @@
|
|
|
1
1
|
/* Validates a compartment map against its schema. */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
assertPackagePolicy,
|
|
5
|
+
ATTENUATORS_COMPARTMENT,
|
|
6
|
+
ENTRY_COMPARTMENT,
|
|
7
|
+
} from './policy-format.js';
|
|
4
8
|
|
|
5
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* @import {
|
|
11
|
+
* FileCompartmentDescriptor,
|
|
12
|
+
* FileCompartmentMapDescriptor,
|
|
13
|
+
* FileModuleConfiguration,
|
|
14
|
+
* CompartmentMapDescriptor,
|
|
15
|
+
* EntryDescriptor,
|
|
16
|
+
* ModuleConfiguration,
|
|
17
|
+
* ExitModuleConfiguration,
|
|
18
|
+
* CompartmentModuleConfiguration,
|
|
19
|
+
* CompartmentDescriptor,
|
|
20
|
+
* ScopeDescriptor,
|
|
21
|
+
* BaseModuleConfiguration,
|
|
22
|
+
* DigestedCompartmentMapDescriptor,
|
|
23
|
+
* PackageCompartmentMapDescriptor,
|
|
24
|
+
* PackageCompartmentDescriptor,
|
|
25
|
+
* FileUrlString,
|
|
26
|
+
* LanguageForExtension,
|
|
27
|
+
* LanguageForModuleSpecifier,
|
|
28
|
+
* ModuleConfigurationKind,
|
|
29
|
+
* ModuleConfigurationKindToType,
|
|
30
|
+
* ErrorModuleConfiguration,
|
|
31
|
+
* DigestedCompartmentDescriptor} from './types.js'
|
|
32
|
+
*/
|
|
6
33
|
|
|
7
34
|
// TODO convert to the new `||` assert style.
|
|
8
35
|
// Deferred because this file pervasively uses simple template strings rather than
|
|
9
36
|
// template strings tagged with `assert.details` (aka `X`), and uses
|
|
10
37
|
// this definition of `q` rather than `assert.quote`
|
|
11
38
|
const q = JSON.stringify;
|
|
39
|
+
const { keys, entries } = Object;
|
|
40
|
+
const { isArray } = Array;
|
|
12
41
|
|
|
13
42
|
/** @type {(a: string, b: string) => number} */
|
|
14
43
|
// eslint-disable-next-line no-nested-ternary
|
|
@@ -26,432 +55,887 @@ function* enumerate(iterable) {
|
|
|
26
55
|
}
|
|
27
56
|
}
|
|
28
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Type guard for a string value.
|
|
60
|
+
*
|
|
61
|
+
* @overload
|
|
62
|
+
* @param {unknown} value
|
|
63
|
+
* @param {string} keypath
|
|
64
|
+
* @param {string} url
|
|
65
|
+
* @returns {asserts value is string}
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Type guard for a string value with a custom assertion failure message.
|
|
70
|
+
*
|
|
71
|
+
* @overload
|
|
72
|
+
* @param {unknown} value
|
|
73
|
+
* @param {string} message
|
|
74
|
+
* @returns {asserts value is string}
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Type guard for a string value.
|
|
79
|
+
*
|
|
80
|
+
* @param {unknown} value
|
|
81
|
+
* @param {string} pathOrMessage
|
|
82
|
+
* @param {string} url
|
|
83
|
+
* @returns {asserts value is string}
|
|
84
|
+
*/
|
|
85
|
+
const assertString = (value, pathOrMessage, url) => {
|
|
86
|
+
const keypath = pathOrMessage;
|
|
87
|
+
assert.typeof(
|
|
88
|
+
value,
|
|
89
|
+
'string',
|
|
90
|
+
`${keypath} in ${q(url)} must be a string; got ${q(value)}`,
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Asserts the `label` field valid
|
|
96
|
+
*
|
|
97
|
+
* @param {unknown} allegedLabel
|
|
98
|
+
* @param {string} keypath
|
|
99
|
+
* @param {string} url
|
|
100
|
+
* @returns {asserts alleged is string}
|
|
101
|
+
*/
|
|
102
|
+
const assertLabel = (allegedLabel, keypath, url) => {
|
|
103
|
+
assertString(allegedLabel, keypath, url);
|
|
104
|
+
if (allegedLabel === ATTENUATORS_COMPARTMENT) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (allegedLabel === ENTRY_COMPARTMENT) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
assert(
|
|
111
|
+
/^(?:@[a-z][a-z0-9-.]*\/)?[a-z][a-z0-9-.]*(?:>(?:@[a-z][a-z0-9-.]*\/)?[a-z][a-z0-9-.]*)*$/.test(
|
|
112
|
+
allegedLabel,
|
|
113
|
+
),
|
|
114
|
+
`${keypath} must be a canonical name in ${q(url)}; got ${q(allegedLabel)}`,
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {unknown} allegedObject
|
|
120
|
+
* @param {string} keypath
|
|
121
|
+
* @param {string} url
|
|
122
|
+
* @returns {asserts allegedObject is Record<PropertyKey, unknown>}
|
|
123
|
+
*/
|
|
124
|
+
const assertPlainObject = (allegedObject, keypath, url) => {
|
|
125
|
+
const object = Object(allegedObject);
|
|
126
|
+
assert(
|
|
127
|
+
object === allegedObject &&
|
|
128
|
+
!isArray(object) &&
|
|
129
|
+
!(typeof object === 'function'),
|
|
130
|
+
`${keypath} must be an object; got ${q(allegedObject)} of type ${q(typeof allegedObject)} in ${q(url)}`,
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @param {unknown} value
|
|
137
|
+
* @param {string} keypath
|
|
138
|
+
* @param {string} url
|
|
139
|
+
* @returns {asserts value is boolean}
|
|
140
|
+
*/
|
|
141
|
+
const assertBoolean = (value, keypath, url) => {
|
|
142
|
+
assert.typeof(
|
|
143
|
+
value,
|
|
144
|
+
'boolean',
|
|
145
|
+
`${keypath} in ${q(url)} must be a boolean; got ${q(value)}`,
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
|
|
29
149
|
/**
|
|
30
150
|
* @param {Record<string, unknown>} object
|
|
31
151
|
* @param {string} message
|
|
32
152
|
*/
|
|
33
153
|
const assertEmptyObject = (object, message) => {
|
|
34
|
-
assert(
|
|
154
|
+
assert(keys(object).length === 0, message);
|
|
35
155
|
};
|
|
36
156
|
|
|
37
157
|
/**
|
|
38
158
|
* @param {unknown} conditions
|
|
39
159
|
* @param {string} url
|
|
160
|
+
* @returns {asserts conditions is CompartmentMapDescriptor['tags']}
|
|
40
161
|
*/
|
|
41
162
|
const assertConditions = (conditions, url) => {
|
|
42
163
|
if (conditions === undefined) return;
|
|
43
164
|
assert(
|
|
44
|
-
|
|
45
|
-
`conditions must be an array
|
|
165
|
+
isArray(conditions),
|
|
166
|
+
`conditions must be an array; got ${conditions} in ${q(url)}`,
|
|
46
167
|
);
|
|
47
168
|
for (const [index, value] of enumerate(conditions)) {
|
|
48
|
-
|
|
49
|
-
value,
|
|
50
|
-
'string',
|
|
51
|
-
`conditions[${index}] must be a string, got ${value} in ${q(url)}`,
|
|
52
|
-
);
|
|
169
|
+
assertString(value, `conditions[${index}]`, url);
|
|
53
170
|
}
|
|
54
171
|
};
|
|
55
172
|
|
|
56
173
|
/**
|
|
57
|
-
* @
|
|
58
|
-
* @param {
|
|
174
|
+
* @template {Partial<ModuleConfiguration>} T
|
|
175
|
+
* @param {T} allegedModule
|
|
176
|
+
* @returns {Omit<T, keyof BaseModuleConfiguration>}
|
|
177
|
+
*/
|
|
178
|
+
const getModuleConfigurationSpecificProperties = allegedModule => {
|
|
179
|
+
const {
|
|
180
|
+
retained: _retained,
|
|
181
|
+
deferredError: _deferredError,
|
|
182
|
+
...other
|
|
183
|
+
} = allegedModule;
|
|
184
|
+
return /** @type {Omit<T, keyof BaseModuleConfiguration>} */ (
|
|
185
|
+
Object.fromEntries(entries(other).filter(([key]) => !key.startsWith('_')))
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
*
|
|
191
|
+
* @param {Record<PropertyKey, unknown>} allegedModule
|
|
192
|
+
* @param {string} keypath
|
|
59
193
|
* @param {string} url
|
|
194
|
+
* @returns {asserts allegedModule is ModuleConfiguration}
|
|
60
195
|
*/
|
|
61
|
-
const
|
|
62
|
-
const {
|
|
196
|
+
const assertBaseModuleConfiguration = (allegedModule, keypath, url) => {
|
|
197
|
+
const { deferredError, retained, createdBy } = allegedModule;
|
|
198
|
+
if (deferredError !== undefined) {
|
|
199
|
+
assertString(deferredError, `${keypath}.deferredError`, url);
|
|
200
|
+
}
|
|
201
|
+
if (retained !== undefined) {
|
|
202
|
+
assertBoolean(retained, `${keypath}.retained`, url);
|
|
203
|
+
}
|
|
204
|
+
if (createdBy !== undefined) {
|
|
205
|
+
assertString(createdBy, `${keypath}.createdBy`, url);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @param {ModuleConfiguration} moduleDescriptor
|
|
211
|
+
* @param {string} keypath
|
|
212
|
+
* @param {string} url
|
|
213
|
+
* @returns {asserts allegedModule is CompartmentModuleConfiguration}
|
|
214
|
+
*/
|
|
215
|
+
const assertCompartmentModuleConfiguration = (
|
|
216
|
+
moduleDescriptor,
|
|
217
|
+
keypath,
|
|
218
|
+
url,
|
|
219
|
+
) => {
|
|
220
|
+
const { compartment, module, ...extra } =
|
|
221
|
+
getModuleConfigurationSpecificProperties(
|
|
222
|
+
/** @type {CompartmentModuleConfiguration} */ (moduleDescriptor),
|
|
223
|
+
);
|
|
63
224
|
assertEmptyObject(
|
|
64
225
|
extra,
|
|
65
|
-
`${
|
|
66
|
-
extra,
|
|
67
|
-
compartment,
|
|
68
|
-
})} in ${q(url)}`,
|
|
226
|
+
`${keypath} must not have extra properties; got ${q(extra)} in ${q(url)}`,
|
|
69
227
|
);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`${path}.compartment must be a string, got ${q(compartment)} in ${q(url)}`,
|
|
74
|
-
);
|
|
75
|
-
assert.typeof(
|
|
76
|
-
module,
|
|
77
|
-
'string',
|
|
78
|
-
`${path}.module must be a string, got ${q(module)} in ${q(url)}`,
|
|
79
|
-
);
|
|
80
|
-
if (retained !== undefined) {
|
|
81
|
-
assert.typeof(
|
|
82
|
-
retained,
|
|
83
|
-
'boolean',
|
|
84
|
-
`${path}.retained must be a boolean, got ${q(retained)} in ${q(url)}`,
|
|
85
|
-
);
|
|
86
|
-
}
|
|
228
|
+
|
|
229
|
+
assertString(compartment, `${keypath}.compartment`, url);
|
|
230
|
+
assertString(module, `${keypath}.module`, url);
|
|
87
231
|
};
|
|
88
232
|
|
|
89
233
|
/**
|
|
90
|
-
* @param {
|
|
91
|
-
* @param {string}
|
|
234
|
+
* @param {ModuleConfiguration} moduleDescriptor
|
|
235
|
+
* @param {string} keypath
|
|
92
236
|
* @param {string} url
|
|
237
|
+
* @returns {asserts allegedModule is FileModuleConfiguration}
|
|
93
238
|
*/
|
|
94
|
-
const
|
|
95
|
-
const { location, parser, sha512, ...extra } =
|
|
239
|
+
const assertFileModuleConfiguration = (moduleDescriptor, keypath, url) => {
|
|
240
|
+
const { location, parser, sha512, ...extra } =
|
|
241
|
+
getModuleConfigurationSpecificProperties(
|
|
242
|
+
/** @type {FileModuleConfiguration} */ (moduleDescriptor),
|
|
243
|
+
);
|
|
96
244
|
assertEmptyObject(
|
|
97
245
|
extra,
|
|
98
|
-
`${
|
|
99
|
-
|
|
246
|
+
`${keypath} must not have extra properties; got ${q(
|
|
247
|
+
keys(extra),
|
|
100
248
|
)} in ${q(url)}`,
|
|
101
249
|
);
|
|
102
|
-
|
|
103
|
-
location,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
);
|
|
107
|
-
assert.typeof(
|
|
108
|
-
parser,
|
|
109
|
-
'string',
|
|
110
|
-
`${path}.parser must be a string, got ${q(parser)} in ${q(url)}`,
|
|
111
|
-
);
|
|
250
|
+
if (location !== undefined) {
|
|
251
|
+
assertString(location, `${keypath}.location`, url);
|
|
252
|
+
}
|
|
253
|
+
assertString(parser, `${keypath}.parser`, url);
|
|
112
254
|
|
|
113
255
|
if (sha512 !== undefined) {
|
|
114
|
-
|
|
115
|
-
sha512,
|
|
116
|
-
'string',
|
|
117
|
-
`${path}.sha512 must be a string, got ${q(sha512)} in ${q(url)}`,
|
|
118
|
-
);
|
|
256
|
+
assertString(sha512, `${keypath}.sha512`, url);
|
|
119
257
|
}
|
|
120
258
|
};
|
|
121
259
|
|
|
122
260
|
/**
|
|
123
|
-
* @param {
|
|
124
|
-
* @param {string}
|
|
261
|
+
* @param {ModuleConfiguration} moduleDescriptor
|
|
262
|
+
* @param {string} keypath
|
|
125
263
|
* @param {string} url
|
|
264
|
+
* @returns {asserts allegedModule is ExitModuleConfiguration}
|
|
126
265
|
*/
|
|
127
|
-
const
|
|
128
|
-
const { exit, ...extra } =
|
|
266
|
+
const assertExitModuleConfiguration = (moduleDescriptor, keypath, url) => {
|
|
267
|
+
const { exit, ...extra } = getModuleConfigurationSpecificProperties(
|
|
268
|
+
/** @type {ExitModuleConfiguration} */ (moduleDescriptor),
|
|
269
|
+
);
|
|
129
270
|
assertEmptyObject(
|
|
130
271
|
extra,
|
|
131
|
-
`${
|
|
132
|
-
|
|
272
|
+
`${keypath} must not have extra properties; got ${q(
|
|
273
|
+
keys(extra),
|
|
133
274
|
)} in ${q(url)}`,
|
|
134
275
|
);
|
|
135
|
-
|
|
136
|
-
exit,
|
|
137
|
-
'string',
|
|
138
|
-
`${path}.exit must be a string, got ${q(exit)} in ${q(url)}`,
|
|
139
|
-
);
|
|
276
|
+
assertString(exit, `${keypath}.exit`, url);
|
|
140
277
|
};
|
|
141
278
|
|
|
142
279
|
/**
|
|
280
|
+
*
|
|
281
|
+
* @param {ModuleConfiguration} moduleDescriptor
|
|
282
|
+
* @param {string} keypath
|
|
283
|
+
* @param {string} url
|
|
284
|
+
* @returns {asserts moduleDescriptor is ErrorModuleConfiguration}
|
|
285
|
+
*/
|
|
286
|
+
const assertErrorModuleConfiguration = (moduleDescriptor, keypath, url) => {
|
|
287
|
+
const { deferredError } = moduleDescriptor;
|
|
288
|
+
if (deferredError) {
|
|
289
|
+
assertString(deferredError, `${keypath}.deferredError`, url);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @template {ModuleConfigurationKind[]} Kinds
|
|
295
|
+
* @overload
|
|
143
296
|
* @param {unknown} allegedModule
|
|
144
|
-
* @param {string}
|
|
297
|
+
* @param {string} keypath
|
|
145
298
|
* @param {string} url
|
|
299
|
+
* @param {Kinds} kinds
|
|
300
|
+
* @returns {asserts allegedModule is ModuleConfigurationKindToType<Kinds>}
|
|
146
301
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @overload
|
|
305
|
+
* @param {unknown} allegedModule
|
|
306
|
+
* @param {string} keypath
|
|
307
|
+
* @param {string} url
|
|
308
|
+
* @returns {asserts allegedModule is ModuleConfiguration}
|
|
309
|
+
*/
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @param {unknown} allegedModule
|
|
313
|
+
* @param {string} keypath
|
|
314
|
+
* @param {string} url
|
|
315
|
+
* @param {ModuleConfigurationKind[]} kinds
|
|
316
|
+
*/
|
|
317
|
+
function assertModuleConfiguration(allegedModule, keypath, url, kinds) {
|
|
318
|
+
assertPlainObject(allegedModule, keypath, url);
|
|
319
|
+
assertBaseModuleConfiguration(allegedModule, keypath, url);
|
|
320
|
+
|
|
321
|
+
const finalKinds =
|
|
322
|
+
kinds.length > 0
|
|
323
|
+
? kinds
|
|
324
|
+
: /** @type {ModuleConfigurationKind[]} */ ([
|
|
325
|
+
'compartment',
|
|
326
|
+
'file',
|
|
327
|
+
'exit',
|
|
328
|
+
'error',
|
|
329
|
+
]);
|
|
330
|
+
/** @type {Error[]} */
|
|
331
|
+
const errors = [];
|
|
332
|
+
for (const kind of finalKinds) {
|
|
333
|
+
switch (kind) {
|
|
334
|
+
case 'compartment': {
|
|
335
|
+
try {
|
|
336
|
+
assertCompartmentModuleConfiguration(allegedModule, keypath, url);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
errors.push(error);
|
|
339
|
+
}
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
case 'file': {
|
|
343
|
+
try {
|
|
344
|
+
assertFileModuleConfiguration(allegedModule, keypath, url);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
errors.push(error);
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case 'exit': {
|
|
351
|
+
try {
|
|
352
|
+
assertExitModuleConfiguration(allegedModule, keypath, url);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
errors.push(error);
|
|
355
|
+
}
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
case 'error': {
|
|
359
|
+
try {
|
|
360
|
+
assertErrorModuleConfiguration(allegedModule, keypath, url);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
errors.push(error);
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
default:
|
|
367
|
+
throw new TypeError(
|
|
368
|
+
`Unknown module descriptor kind ${q(kind)} in ${q(url)}`,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
149
373
|
assert(
|
|
150
|
-
|
|
151
|
-
|
|
374
|
+
errors.length < finalKinds.length,
|
|
375
|
+
`invalid module descriptor in ${q(url)} at ${q(keypath)}; expected to match one of ${q(kinds)}: ${errors.map(err => err.message).join('; ')}`,
|
|
152
376
|
);
|
|
377
|
+
}
|
|
153
378
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
`${path}.deferredError must be a string contaiing an error message`,
|
|
379
|
+
/**
|
|
380
|
+
* @param {unknown} allegedModules
|
|
381
|
+
* @param {string} keypath
|
|
382
|
+
* @param {string} url
|
|
383
|
+
* @returns {asserts allegedModules is Record<string, ModuleConfiguration>}
|
|
384
|
+
*/
|
|
385
|
+
const assertModuleConfigurations = (allegedModules, keypath, url) => {
|
|
386
|
+
assertPlainObject(allegedModules, keypath, url);
|
|
387
|
+
for (const [key, value] of entries(allegedModules)) {
|
|
388
|
+
assertString(
|
|
389
|
+
key,
|
|
390
|
+
`all keys of ${keypath}.modules must be strings; got ${key} in ${q(url)}`,
|
|
167
391
|
);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
392
|
+
assertModuleConfiguration(value, `${keypath}.modules[${q(key)}]`, url);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @param {unknown} allegedModules
|
|
398
|
+
* @param {string} keypath
|
|
399
|
+
* @param {string} url
|
|
400
|
+
* @returns {asserts allegedModules is Record<string, FileModuleConfiguration|CompartmentModuleConfiguration>}
|
|
401
|
+
*/
|
|
402
|
+
const assertFileModuleConfigurations = (allegedModules, keypath, url) => {
|
|
403
|
+
assertPlainObject(allegedModules, keypath, url);
|
|
404
|
+
for (const [key, value] of entries(allegedModules)) {
|
|
405
|
+
assertString(
|
|
406
|
+
key,
|
|
407
|
+
`all keys of ${keypath}.modules must be strings; got ${key} in ${q(url)}`,
|
|
173
408
|
);
|
|
409
|
+
assertModuleConfiguration(value, `${keypath}.modules[${q(key)}]`, url, [
|
|
410
|
+
'file',
|
|
411
|
+
'compartment',
|
|
412
|
+
'error',
|
|
413
|
+
]);
|
|
174
414
|
}
|
|
175
415
|
};
|
|
176
416
|
|
|
177
417
|
/**
|
|
178
418
|
* @param {unknown} allegedModules
|
|
179
|
-
* @param {string}
|
|
419
|
+
* @param {string} keypath
|
|
180
420
|
* @param {string} url
|
|
421
|
+
* @returns {asserts allegedModules is Record<string, ModuleConfiguration>}
|
|
181
422
|
*/
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
423
|
+
const assertDigestedModuleConfigurations = (allegedModules, keypath, url) => {
|
|
424
|
+
assertPlainObject(allegedModules, keypath, url);
|
|
425
|
+
for (const [key, value] of entries(allegedModules)) {
|
|
426
|
+
assertString(
|
|
427
|
+
key,
|
|
428
|
+
`all keys of ${keypath}.modules must be strings; got ${key} in ${q(url)}`,
|
|
429
|
+
);
|
|
430
|
+
assertModuleConfiguration(value, `${keypath}.modules[${q(key)}]`, url, [
|
|
431
|
+
'file',
|
|
432
|
+
'exit',
|
|
433
|
+
'error',
|
|
434
|
+
]);
|
|
190
435
|
}
|
|
191
436
|
};
|
|
192
437
|
|
|
193
438
|
/**
|
|
194
439
|
* @param {unknown} allegedParsers
|
|
195
|
-
* @param {string}
|
|
440
|
+
* @param {string} keypath
|
|
196
441
|
* @param {string} url
|
|
442
|
+
* @returns {asserts allegedParsers is LanguageForExtension}
|
|
197
443
|
*/
|
|
198
|
-
const assertParsers = (allegedParsers,
|
|
199
|
-
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const parsers = Object(allegedParsers);
|
|
203
|
-
assert(
|
|
204
|
-
allegedParsers === parsers && !Array.isArray(parsers),
|
|
205
|
-
`${path}.parsers must be an object, got ${allegedParsers} in ${q(url)}`,
|
|
206
|
-
);
|
|
444
|
+
const assertParsers = (allegedParsers, keypath, url) => {
|
|
445
|
+
assertPlainObject(allegedParsers, `${keypath}.parsers`, url);
|
|
207
446
|
|
|
208
|
-
for (const [key, value] of
|
|
209
|
-
|
|
447
|
+
for (const [key, value] of entries(allegedParsers)) {
|
|
448
|
+
assertString(
|
|
210
449
|
key,
|
|
211
|
-
|
|
212
|
-
`all keys of ${path}.parsers must be strings, got ${key} in ${q(url)}`,
|
|
213
|
-
);
|
|
214
|
-
assert.typeof(
|
|
215
|
-
value,
|
|
216
|
-
'string',
|
|
217
|
-
`${path}.parsers[${q(key)}] must be a string, got ${value} in ${q(url)}`,
|
|
450
|
+
`all keys of ${keypath}.parsers must be strings; got ${key} in ${q(url)}`,
|
|
218
451
|
);
|
|
452
|
+
assertString(value, `${keypath}.parsers[${q(key)}]`, url);
|
|
219
453
|
}
|
|
220
454
|
};
|
|
221
455
|
|
|
222
456
|
/**
|
|
223
|
-
* @
|
|
224
|
-
* @param {
|
|
457
|
+
* @overload
|
|
458
|
+
* @param {unknown} allegedTruthyValue
|
|
459
|
+
* @param {string} keypath
|
|
225
460
|
* @param {string} url
|
|
461
|
+
* @returns {asserts allegedTruthyValue is NonNullable<unknown>}
|
|
226
462
|
*/
|
|
227
|
-
|
|
228
|
-
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
*
|
|
466
|
+
* @overload
|
|
467
|
+
* @param {unknown} allegedTruthyValue
|
|
468
|
+
* @param {string} message
|
|
469
|
+
* @returns {asserts allegedTruthyValue is NonNullable<unknown>}
|
|
470
|
+
*/
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
*
|
|
474
|
+
* @param {unknown} allegedTruthyValue
|
|
475
|
+
* @param {string} keypath
|
|
476
|
+
* @param {string} [url]
|
|
477
|
+
* @returns {asserts allegedTruthyValue is NonNullable<unknown>}
|
|
478
|
+
*/
|
|
479
|
+
const assertTruthy = (allegedTruthyValue, keypath, url) => {
|
|
229
480
|
assert(
|
|
230
|
-
|
|
231
|
-
|
|
481
|
+
allegedTruthyValue,
|
|
482
|
+
url
|
|
483
|
+
? `${keypath} in ${q(url)} must be truthy; got ${q(allegedTruthyValue)}`
|
|
484
|
+
: url,
|
|
232
485
|
);
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* @template [T=string]
|
|
490
|
+
* @typedef {(value: unknown, keypath: string, url: string) => void} AssertFn
|
|
491
|
+
*/
|
|
233
492
|
|
|
234
|
-
|
|
493
|
+
/**
|
|
494
|
+
* @template [T=string]
|
|
495
|
+
* @param {unknown} allegedScope
|
|
496
|
+
* @param {string} keypath
|
|
497
|
+
* @param {string} url
|
|
498
|
+
* @param {AssertFn<T>} [assertCompartmentValue]
|
|
499
|
+
* @returns {asserts allegedScope is ScopeDescriptor<T>}
|
|
500
|
+
*/
|
|
501
|
+
const assertScope = (allegedScope, keypath, url, assertCompartmentValue) => {
|
|
502
|
+
assertPlainObject(allegedScope, keypath, url);
|
|
503
|
+
|
|
504
|
+
const { compartment, ...extra } = allegedScope;
|
|
235
505
|
assertEmptyObject(
|
|
236
506
|
extra,
|
|
237
|
-
`${
|
|
238
|
-
|
|
507
|
+
`${keypath} must not have extra properties; got ${q(
|
|
508
|
+
keys(extra),
|
|
239
509
|
)} in ${q(url)}`,
|
|
240
510
|
);
|
|
241
511
|
|
|
242
|
-
|
|
243
|
-
compartment,
|
|
244
|
-
|
|
245
|
-
`${
|
|
246
|
-
|
|
512
|
+
if (assertCompartmentValue) {
|
|
513
|
+
assertCompartmentValue(compartment, `${keypath}.compartment`, url);
|
|
514
|
+
} else {
|
|
515
|
+
assertString(compartment, `${keypath}.compartment`, url);
|
|
516
|
+
}
|
|
247
517
|
};
|
|
248
518
|
|
|
249
519
|
/**
|
|
520
|
+
* @template [T=string]
|
|
250
521
|
* @param {unknown} allegedScopes
|
|
251
|
-
* @param {string}
|
|
522
|
+
* @param {string} keypath
|
|
252
523
|
* @param {string} url
|
|
524
|
+
* @param {AssertFn<T>} [assertCompartmentValue]
|
|
525
|
+
* @returns {asserts allegedScopes is Record<string, ScopeDescriptor<T>>}
|
|
253
526
|
*/
|
|
254
|
-
const assertScopes = (
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
`${path}.scopes must be an object, got ${q(allegedScopes)} in ${q(url)}`,
|
|
262
|
-
);
|
|
527
|
+
const assertScopes = (
|
|
528
|
+
allegedScopes,
|
|
529
|
+
keypath,
|
|
530
|
+
url,
|
|
531
|
+
assertCompartmentValue = assertString,
|
|
532
|
+
) => {
|
|
533
|
+
assertPlainObject(allegedScopes, keypath, url);
|
|
263
534
|
|
|
264
|
-
for (const [key, value] of
|
|
265
|
-
|
|
535
|
+
for (const [key, value] of entries(allegedScopes)) {
|
|
536
|
+
assertString(
|
|
266
537
|
key,
|
|
267
|
-
|
|
268
|
-
|
|
538
|
+
`all keys of ${keypath}.scopes must be strings; got ${key} in ${q(url)}`,
|
|
539
|
+
);
|
|
540
|
+
assertScope(
|
|
541
|
+
value,
|
|
542
|
+
`${keypath}.scopes[${q(key)}]`,
|
|
543
|
+
url,
|
|
544
|
+
assertCompartmentValue,
|
|
269
545
|
);
|
|
270
|
-
assertScope(value, `${path}.scopes[${q(key)}]`, url);
|
|
271
546
|
}
|
|
272
547
|
};
|
|
273
548
|
|
|
274
549
|
/**
|
|
275
550
|
* @param {unknown} allegedTypes
|
|
276
|
-
* @param {string}
|
|
551
|
+
* @param {string} keypath
|
|
277
552
|
* @param {string} url
|
|
553
|
+
* @returns {asserts allegedTypes is LanguageForModuleSpecifier}
|
|
278
554
|
*/
|
|
279
|
-
const assertTypes = (allegedTypes,
|
|
280
|
-
|
|
281
|
-
|
|
555
|
+
const assertTypes = (allegedTypes, keypath, url) => {
|
|
556
|
+
assertPlainObject(allegedTypes, `${keypath}.types`, url);
|
|
557
|
+
|
|
558
|
+
for (const [key, value] of entries(allegedTypes)) {
|
|
559
|
+
assertString(
|
|
560
|
+
key,
|
|
561
|
+
`all keys of ${keypath}.types must be strings; got ${key} in ${q(url)}`,
|
|
562
|
+
);
|
|
563
|
+
assertString(value, `${keypath}.types[${q(key)}]`, url);
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* @template {Record<string, ModuleConfiguration>} [M=Record<string, ModuleConfiguration>]
|
|
569
|
+
* @param {unknown} allegedCompartment
|
|
570
|
+
* @param {string} keypath
|
|
571
|
+
* @param {string} url
|
|
572
|
+
* @param {AssertFn<M>} [moduleConfigurationAssertionFn]
|
|
573
|
+
* @returns {asserts allegedCompartment is CompartmentDescriptor}
|
|
574
|
+
*/
|
|
575
|
+
const assertCompartmentDescriptor = (
|
|
576
|
+
allegedCompartment,
|
|
577
|
+
keypath,
|
|
578
|
+
url,
|
|
579
|
+
moduleConfigurationAssertionFn = assertModuleConfigurations,
|
|
580
|
+
) => {
|
|
581
|
+
assertPlainObject(allegedCompartment, keypath, url);
|
|
582
|
+
|
|
583
|
+
const {
|
|
584
|
+
location,
|
|
585
|
+
name,
|
|
586
|
+
parsers,
|
|
587
|
+
types,
|
|
588
|
+
scopes,
|
|
589
|
+
modules,
|
|
590
|
+
policy,
|
|
591
|
+
sourceDirname,
|
|
592
|
+
retained,
|
|
593
|
+
} = allegedCompartment;
|
|
594
|
+
|
|
595
|
+
assertString(location, `${keypath}.location`, url);
|
|
596
|
+
assertString(name, `${keypath}.name`, url);
|
|
597
|
+
|
|
598
|
+
// TODO: It may be prudent to assert that there exists some module referring
|
|
599
|
+
// to its own compartment
|
|
600
|
+
|
|
601
|
+
moduleConfigurationAssertionFn(modules, keypath, url);
|
|
602
|
+
|
|
603
|
+
if (parsers !== undefined) {
|
|
604
|
+
assertParsers(parsers, keypath, url);
|
|
605
|
+
}
|
|
606
|
+
if (scopes !== undefined) {
|
|
607
|
+
assertScopes(scopes, keypath, url);
|
|
608
|
+
}
|
|
609
|
+
if (types !== undefined) {
|
|
610
|
+
assertTypes(types, keypath, url);
|
|
282
611
|
}
|
|
283
|
-
|
|
612
|
+
if (policy !== undefined) {
|
|
613
|
+
assertPackagePolicy(policy, keypath, url);
|
|
614
|
+
}
|
|
615
|
+
if (sourceDirname !== undefined) {
|
|
616
|
+
assertString(sourceDirname, `${keypath}.sourceDirname`, url);
|
|
617
|
+
}
|
|
618
|
+
if (retained !== undefined) {
|
|
619
|
+
assertBoolean(retained, `${keypath}.retained`, url);
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Ensures a string is a file URL (a {@link FileUrlString})
|
|
625
|
+
*
|
|
626
|
+
* @param {unknown} allegedFileUrlString - a package location to assert
|
|
627
|
+
* @param {string} keypath
|
|
628
|
+
* @param {string} url
|
|
629
|
+
* @returns {asserts allegedFileUrlString is FileUrlString}
|
|
630
|
+
*/
|
|
631
|
+
const assertFileUrlString = (allegedFileUrlString, keypath, url) => {
|
|
632
|
+
assertString(allegedFileUrlString, keypath, url);
|
|
633
|
+
assert(
|
|
634
|
+
allegedFileUrlString.startsWith('file://'),
|
|
635
|
+
`${keypath} must be a file URL in ${q(url)}; got ${q(allegedFileUrlString)}`,
|
|
636
|
+
);
|
|
284
637
|
assert(
|
|
285
|
-
|
|
286
|
-
`${
|
|
638
|
+
allegedFileUrlString.length > 7,
|
|
639
|
+
`${keypath} must contain a non-empty path in ${q(url)}; got ${q(allegedFileUrlString)}`,
|
|
287
640
|
);
|
|
641
|
+
};
|
|
288
642
|
|
|
289
|
-
|
|
290
|
-
|
|
643
|
+
/**
|
|
644
|
+
* @param {unknown} allegedModules
|
|
645
|
+
* @param {string} keypath
|
|
646
|
+
* @param {string} url
|
|
647
|
+
* @returns {asserts allegedModules is Record<string, CompartmentModuleConfiguration>}
|
|
648
|
+
*/
|
|
649
|
+
const assertPackageModuleConfigurations = (allegedModules, keypath, url) => {
|
|
650
|
+
assertPlainObject(allegedModules, keypath, url);
|
|
651
|
+
for (const [key, value] of entries(allegedModules)) {
|
|
652
|
+
assertString(
|
|
291
653
|
key,
|
|
292
|
-
|
|
293
|
-
`all keys of ${path}.types must be strings, got ${key} in ${q(url)}`,
|
|
294
|
-
);
|
|
295
|
-
assert.typeof(
|
|
296
|
-
value,
|
|
297
|
-
'string',
|
|
298
|
-
`${path}.types[${q(key)}] must be a string, got ${value} in ${q(url)}`,
|
|
654
|
+
`all keys of ${keypath}.modules must be strings; got ${key} in ${q(url)}`,
|
|
299
655
|
);
|
|
656
|
+
assertModuleConfiguration(value, `${keypath}.modules[${q(key)}]`, url, [
|
|
657
|
+
'compartment',
|
|
658
|
+
]);
|
|
300
659
|
}
|
|
301
660
|
};
|
|
302
661
|
|
|
303
662
|
/**
|
|
304
|
-
*
|
|
305
|
-
* @param {
|
|
306
|
-
* @param {string}
|
|
663
|
+
*
|
|
664
|
+
* @param {unknown} allegedLocation
|
|
665
|
+
* @param {string} keypath
|
|
666
|
+
* @param {string} url
|
|
667
|
+
* @returns {asserts allegedLocation is PackageCompartmentDescriptor['location']}
|
|
307
668
|
*/
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
) => {
|
|
314
|
-
assertPackagePolicy(allegedPolicy, `${path}.policy`, url);
|
|
669
|
+
const assertPackageLocation = (allegedLocation, keypath, url) => {
|
|
670
|
+
if (allegedLocation === ATTENUATORS_COMPARTMENT) {
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
assertFileUrlString(allegedLocation, keypath, url);
|
|
315
674
|
};
|
|
316
675
|
|
|
317
676
|
/**
|
|
318
677
|
* @param {unknown} allegedCompartment
|
|
319
|
-
* @param {string}
|
|
678
|
+
* @param {string} keypath
|
|
320
679
|
* @param {string} url
|
|
680
|
+
* @returns {asserts allegedCompartment is PackageCompartmentDescriptor}
|
|
321
681
|
*/
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
682
|
+
const assertPackageCompartmentDescriptor = (
|
|
683
|
+
allegedCompartment,
|
|
684
|
+
keypath,
|
|
685
|
+
url,
|
|
686
|
+
) => {
|
|
687
|
+
assertCompartmentDescriptor(
|
|
688
|
+
allegedCompartment,
|
|
689
|
+
keypath,
|
|
690
|
+
url,
|
|
691
|
+
assertPackageModuleConfigurations,
|
|
327
692
|
);
|
|
328
693
|
|
|
329
694
|
const {
|
|
330
695
|
location,
|
|
331
|
-
name,
|
|
332
|
-
label,
|
|
333
|
-
parsers,
|
|
334
|
-
types,
|
|
335
696
|
scopes,
|
|
336
|
-
|
|
337
|
-
|
|
697
|
+
label,
|
|
698
|
+
// these unused vars already validated by assertPackageModuleConfigurations
|
|
699
|
+
name: _name,
|
|
700
|
+
sourceDirname: _sourceDirname,
|
|
701
|
+
modules: _modules,
|
|
702
|
+
parsers: _parsers,
|
|
703
|
+
types: _types,
|
|
704
|
+
policy: _policy,
|
|
705
|
+
version: _version,
|
|
338
706
|
...extra
|
|
339
|
-
} =
|
|
707
|
+
} = /** @type {PackageCompartmentDescriptor} */ (allegedCompartment);
|
|
340
708
|
|
|
341
709
|
assertEmptyObject(
|
|
342
710
|
extra,
|
|
343
|
-
`${
|
|
344
|
-
|
|
711
|
+
`${keypath} must not have extra properties; got ${q(
|
|
712
|
+
keys(extra),
|
|
345
713
|
)} in ${q(url)}`,
|
|
346
714
|
);
|
|
347
715
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
716
|
+
assertPackageLocation(location, `${keypath}.location`, url);
|
|
717
|
+
assertLabel(label, `${keypath}.label`, url);
|
|
718
|
+
assertScopes(scopes, `${keypath}.scopes`, url, assertFileUrlString);
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
*
|
|
723
|
+
* @param {unknown} allegedCompartment
|
|
724
|
+
* @param {string} keypath
|
|
725
|
+
* @param {string} url
|
|
726
|
+
* @returns {asserts allegedCompartment is DigestedCompartmentDescriptor}
|
|
727
|
+
*/
|
|
728
|
+
const assertDigestedCompartmentDescriptor = (
|
|
729
|
+
allegedCompartment,
|
|
730
|
+
keypath,
|
|
731
|
+
url,
|
|
732
|
+
) => {
|
|
733
|
+
assertCompartmentDescriptor(
|
|
734
|
+
allegedCompartment,
|
|
735
|
+
keypath,
|
|
736
|
+
url,
|
|
737
|
+
assertDigestedModuleConfigurations,
|
|
352
738
|
);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
739
|
+
|
|
740
|
+
const {
|
|
741
|
+
name: _name,
|
|
742
|
+
label: _label,
|
|
743
|
+
modules: _modules,
|
|
744
|
+
policy: _policy,
|
|
745
|
+
location: _location,
|
|
746
|
+
...extra
|
|
747
|
+
} = allegedCompartment;
|
|
748
|
+
|
|
749
|
+
assertEmptyObject(
|
|
750
|
+
extra,
|
|
751
|
+
`${keypath} must not have extra properties; got ${q(
|
|
752
|
+
keys(extra),
|
|
753
|
+
)} in ${q(url)}`,
|
|
357
754
|
);
|
|
358
|
-
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* @param {unknown} allegedCompartment
|
|
759
|
+
* @param {string} keypath
|
|
760
|
+
* @param {string} url
|
|
761
|
+
* @returns {asserts allegedCompartment is FileCompartmentDescriptor}
|
|
762
|
+
*/
|
|
763
|
+
const assertFileCompartmentDescriptor = (allegedCompartment, keypath, url) => {
|
|
764
|
+
assertCompartmentDescriptor(
|
|
765
|
+
allegedCompartment,
|
|
766
|
+
keypath,
|
|
767
|
+
url,
|
|
768
|
+
assertFileModuleConfigurations,
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
const {
|
|
772
|
+
location: _location,
|
|
773
|
+
name: _name,
|
|
359
774
|
label,
|
|
360
|
-
|
|
361
|
-
|
|
775
|
+
modules: _modules,
|
|
776
|
+
policy: _policy,
|
|
777
|
+
...extra
|
|
778
|
+
} = /** @type {FileCompartmentDescriptor} */ (allegedCompartment);
|
|
779
|
+
|
|
780
|
+
assertEmptyObject(
|
|
781
|
+
extra,
|
|
782
|
+
`${keypath} must not have extra properties; got ${q(
|
|
783
|
+
keys(extra),
|
|
784
|
+
)} in ${q(url)}`,
|
|
362
785
|
);
|
|
363
786
|
|
|
364
|
-
|
|
365
|
-
assertParsers(parsers, path, url);
|
|
366
|
-
assertScopes(scopes, path, url);
|
|
367
|
-
assertTypes(types, path, url);
|
|
368
|
-
assertPolicy(policy, path, url);
|
|
787
|
+
assertString(label, `${keypath}.label`, url);
|
|
369
788
|
};
|
|
370
789
|
|
|
371
790
|
/**
|
|
372
791
|
* @param {unknown} allegedCompartments
|
|
373
792
|
* @param {string} url
|
|
793
|
+
* @returns {asserts allegedCompartments is Record<string, unknown>}
|
|
374
794
|
*/
|
|
375
|
-
const
|
|
376
|
-
|
|
795
|
+
const assertCompartmentDescriptors = (allegedCompartments, url) => {
|
|
796
|
+
assertPlainObject(allegedCompartments, 'compartments', url);
|
|
797
|
+
const compartmentNames = keys(allegedCompartments);
|
|
377
798
|
assert(
|
|
378
|
-
|
|
379
|
-
`compartments must be
|
|
380
|
-
url,
|
|
381
|
-
)}`,
|
|
799
|
+
compartmentNames.length > 0,
|
|
800
|
+
`compartments must not be empty in ${q(url)}`,
|
|
382
801
|
);
|
|
383
|
-
for (const
|
|
384
|
-
|
|
802
|
+
for (const key of keys(allegedCompartments)) {
|
|
803
|
+
assertString(
|
|
804
|
+
key,
|
|
805
|
+
`all keys of compartments must be strings; got ${key} in ${q(url)}`,
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
assert(
|
|
809
|
+
compartmentNames.every(name => typeof name === 'string'),
|
|
810
|
+
`all keys of compartments must be strings; got ${q(compartmentNames)} in ${q(url)}`,
|
|
811
|
+
);
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* @param {unknown} allegedCompartments
|
|
816
|
+
* @param {string} url
|
|
817
|
+
* @returns {asserts allegedCompartments is Record<string, FileCompartmentDescriptor>}
|
|
818
|
+
*/
|
|
819
|
+
const assertFileCompartmentDescriptors = (allegedCompartments, url) => {
|
|
820
|
+
assertCompartmentDescriptors(allegedCompartments, url);
|
|
821
|
+
for (const [key, value] of entries(allegedCompartments)) {
|
|
822
|
+
assertFileCompartmentDescriptor(value, `compartments[${q(key)}]`, url);
|
|
385
823
|
}
|
|
386
824
|
};
|
|
387
825
|
|
|
826
|
+
/**
|
|
827
|
+
* @param {unknown} allegedCompartments
|
|
828
|
+
* @param {string} url
|
|
829
|
+
* @returns {asserts allegedCompartments is Record<string, PackageCompartmentDescriptor>}
|
|
830
|
+
*/
|
|
831
|
+
const assertPackageCompartmentDescriptors = (allegedCompartments, url) => {
|
|
832
|
+
assertCompartmentDescriptors(allegedCompartments, url);
|
|
833
|
+
for (const [key, value] of entries(allegedCompartments)) {
|
|
834
|
+
assertPackageCompartmentDescriptor(value, `compartments[${q(key)}]`, url);
|
|
835
|
+
}
|
|
836
|
+
};
|
|
388
837
|
/**
|
|
389
838
|
* @param {unknown} allegedEntry
|
|
390
839
|
* @param {string} url
|
|
840
|
+
* @returns {asserts allegedEntry is EntryDescriptor}
|
|
391
841
|
*/
|
|
392
842
|
const assertEntry = (allegedEntry, url) => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
allegedEntry === entry && !Array.isArray(entry),
|
|
396
|
-
`"entry" must be an object in compartment map, got ${allegedEntry} in ${q(
|
|
397
|
-
url,
|
|
398
|
-
)}`,
|
|
399
|
-
);
|
|
400
|
-
const { compartment, module, ...extra } = entry;
|
|
843
|
+
assertPlainObject(allegedEntry, 'entry', url);
|
|
844
|
+
const { compartment, module, ...extra } = allegedEntry;
|
|
401
845
|
assertEmptyObject(
|
|
402
846
|
extra,
|
|
403
|
-
`"entry" must not have extra properties in compartment map
|
|
404
|
-
|
|
847
|
+
`"entry" must not have extra properties in compartment map; got ${q(
|
|
848
|
+
keys(extra),
|
|
405
849
|
)} in ${q(url)}`,
|
|
406
850
|
);
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
'string',
|
|
410
|
-
`entry.compartment must be a string in compartment map, got ${compartment} in ${q(
|
|
411
|
-
url,
|
|
412
|
-
)}`,
|
|
413
|
-
);
|
|
414
|
-
assert.typeof(
|
|
415
|
-
module,
|
|
416
|
-
'string',
|
|
417
|
-
`entry.module must be a string in compartment map, got ${module} in ${q(
|
|
418
|
-
url,
|
|
419
|
-
)}`,
|
|
420
|
-
);
|
|
851
|
+
assertString(compartment, 'entry.compartment', url);
|
|
852
|
+
assertString(module, 'entry.module', url);
|
|
421
853
|
};
|
|
422
854
|
|
|
423
855
|
/**
|
|
424
856
|
* @param {unknown} allegedCompartmentMap
|
|
425
|
-
* @param {string}
|
|
857
|
+
* @param {string} url
|
|
426
858
|
* @returns {asserts allegedCompartmentMap is CompartmentMapDescriptor}
|
|
427
859
|
*/
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
allegedCompartmentMap,
|
|
431
|
-
url = '<unknown-compartment-map.json>',
|
|
432
|
-
) => {
|
|
433
|
-
const compartmentMap = Object(allegedCompartmentMap);
|
|
434
|
-
assert(
|
|
435
|
-
allegedCompartmentMap === compartmentMap && !Array.isArray(compartmentMap),
|
|
436
|
-
`Compartment map must be an object, got ${allegedCompartmentMap} in ${q(
|
|
437
|
-
url,
|
|
438
|
-
)}`,
|
|
439
|
-
);
|
|
860
|
+
const assertCompartmentMap = (allegedCompartmentMap, url) => {
|
|
861
|
+
assertPlainObject(allegedCompartmentMap, 'compartment map', url);
|
|
440
862
|
const {
|
|
441
863
|
// TODO migrate tags to conditions
|
|
442
864
|
// https://github.com/endojs/endo/issues/2388
|
|
443
865
|
tags: conditions,
|
|
444
866
|
entry,
|
|
445
|
-
compartments,
|
|
867
|
+
compartments: _compartments,
|
|
446
868
|
...extra
|
|
447
|
-
} =
|
|
869
|
+
} = allegedCompartmentMap;
|
|
448
870
|
assertEmptyObject(
|
|
449
871
|
extra,
|
|
450
|
-
`Compartment map must not have extra properties
|
|
451
|
-
|
|
872
|
+
`Compartment map must not have extra properties; got ${q(
|
|
873
|
+
keys(extra),
|
|
452
874
|
)} in ${q(url)}`,
|
|
453
875
|
);
|
|
454
876
|
assertConditions(conditions, url);
|
|
455
877
|
assertEntry(entry, url);
|
|
456
|
-
|
|
878
|
+
assertTruthy(
|
|
879
|
+
allegedCompartmentMap.compartments?.[entry.compartment],
|
|
880
|
+
`compartments must contain entry compartment "${entry.compartment}" in ${q(url)}`,
|
|
881
|
+
);
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* @param {unknown} allegedCompartmentMap
|
|
886
|
+
* @param {string} [url]
|
|
887
|
+
* @returns {asserts allegedCompartmentMap is FileCompartmentMapDescriptor}
|
|
888
|
+
*/
|
|
889
|
+
export const assertFileCompartmentMap = (
|
|
890
|
+
allegedCompartmentMap,
|
|
891
|
+
url = '<unknown-compartment-map.json>',
|
|
892
|
+
) => {
|
|
893
|
+
assertCompartmentMap(allegedCompartmentMap, url);
|
|
894
|
+
const { compartments } = allegedCompartmentMap;
|
|
895
|
+
assertFileCompartmentDescriptors(compartments, url);
|
|
896
|
+
};
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
*
|
|
900
|
+
* @param {unknown} allegedCompartments
|
|
901
|
+
* @param {string} url
|
|
902
|
+
* @returns {asserts allegedCompartments is Record<string, DigestedCompartmentDescriptor>}
|
|
903
|
+
*/
|
|
904
|
+
export const assertDigestedCompartmentDescriptors = (
|
|
905
|
+
allegedCompartments,
|
|
906
|
+
url = '<unknown-compartment-map.json>',
|
|
907
|
+
) => {
|
|
908
|
+
assertCompartmentDescriptors(allegedCompartments, url);
|
|
909
|
+
for (const [key, value] of entries(allegedCompartments)) {
|
|
910
|
+
assertDigestedCompartmentDescriptor(value, `compartments[${q(key)}]`, url);
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
*
|
|
916
|
+
* @param {unknown} allegedCompartmentMap
|
|
917
|
+
* @param {string} [url]
|
|
918
|
+
* @returns {asserts allegedCompartmentMap is DigestedCompartmentMapDescriptor}
|
|
919
|
+
*/
|
|
920
|
+
export const assertDigestedCompartmentMap = (
|
|
921
|
+
allegedCompartmentMap,
|
|
922
|
+
url = '<unknown-compartment-map.json>',
|
|
923
|
+
) => {
|
|
924
|
+
assertCompartmentMap(allegedCompartmentMap, url);
|
|
925
|
+
const { compartments } = allegedCompartmentMap;
|
|
926
|
+
assertDigestedCompartmentDescriptors(compartments, url);
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* @param {unknown} allegedCompartmentMap
|
|
931
|
+
* @param {string} [url]
|
|
932
|
+
* @returns {asserts allegedCompartmentMap is PackageCompartmentMapDescriptor}
|
|
933
|
+
*/
|
|
934
|
+
export const assertPackageCompartmentMap = (
|
|
935
|
+
allegedCompartmentMap,
|
|
936
|
+
url = '<unknown-compartment-map.json>',
|
|
937
|
+
) => {
|
|
938
|
+
assertCompartmentMap(allegedCompartmentMap, url);
|
|
939
|
+
const { compartments } = allegedCompartmentMap;
|
|
940
|
+
assertPackageCompartmentDescriptors(compartments, url);
|
|
457
941
|
};
|