@nocobase/plugin-flow-engine 2.0.0-alpha.2
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/LICENSE +661 -0
- package/README.md +29 -0
- package/build.config.ts +22 -0
- package/client.d.ts +2 -0
- package/client.js +1 -0
- package/dist/client/index.d.ts +15 -0
- package/dist/client/index.js +10 -0
- package/dist/externalVersion.js +21 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +48 -0
- package/dist/locale/en-US.json +61 -0
- package/dist/locale/index.d.ts +141 -0
- package/dist/locale/index.js +79 -0
- package/dist/locale/zh-CN.json +61 -0
- package/dist/node_modules/ses/LICENSE +201 -0
- package/dist/node_modules/ses/LICENSE-aura +16 -0
- package/dist/node_modules/ses/LICENSE-caja +13 -0
- package/dist/node_modules/ses/LICENSE-corejs +19 -0
- package/dist/node_modules/ses/LICENSE-v8 +9 -0
- package/dist/node_modules/ses/assert-shim.js +1 -0
- package/dist/node_modules/ses/compartment-shim.js +1 -0
- package/dist/node_modules/ses/console-shim.js +1 -0
- package/dist/node_modules/ses/dist/lockdown.cjs +13912 -0
- package/dist/node_modules/ses/dist/lockdown.umd.js +13912 -0
- package/dist/node_modules/ses/dist/lockdown.umd.min.js +1 -0
- package/dist/node_modules/ses/dist/ses-hermes.cjs +13912 -0
- package/dist/node_modules/ses/dist/ses.cjs +1 -0
- package/dist/node_modules/ses/dist/ses.umd.js +13912 -0
- package/dist/node_modules/ses/dist/ses.umd.min.js +1 -0
- package/dist/node_modules/ses/dist/types.d.cts +606 -0
- package/dist/node_modules/ses/index.js +18 -0
- package/dist/node_modules/ses/lockdown-shim.js +1 -0
- package/dist/node_modules/ses/lockdown.js +1 -0
- package/dist/node_modules/ses/package.json +1 -0
- package/dist/node_modules/ses/src/assert-shim.js +4 -0
- package/dist/node_modules/ses/src/assert-sloppy-mode.js +11 -0
- package/dist/node_modules/ses/src/cauterize-property.js +69 -0
- package/dist/node_modules/ses/src/commons.js +425 -0
- package/dist/node_modules/ses/src/compartment-evaluate.js +93 -0
- package/dist/node_modules/ses/src/compartment-shim.js +22 -0
- package/dist/node_modules/ses/src/compartment.js +477 -0
- package/dist/node_modules/ses/src/console-shim.js +50 -0
- package/dist/node_modules/ses/src/enable-property-overrides.js +211 -0
- package/dist/node_modules/ses/src/enablements.js +244 -0
- package/dist/node_modules/ses/src/error/assert.js +584 -0
- package/dist/node_modules/ses/src/error/console.js +541 -0
- package/dist/node_modules/ses/src/error/fatal-assert.js +54 -0
- package/dist/node_modules/ses/src/error/internal-types.js +98 -0
- package/dist/node_modules/ses/src/error/note-log-args.js +77 -0
- package/dist/node_modules/ses/src/error/stringify-utils.js +195 -0
- package/dist/node_modules/ses/src/error/tame-console.js +197 -0
- package/dist/node_modules/ses/src/error/tame-error-constructor.js +284 -0
- package/dist/node_modules/ses/src/error/tame-v8-error-constructor.js +386 -0
- package/dist/node_modules/ses/src/error/types.js +59 -0
- package/dist/node_modules/ses/src/error/unhandled-rejection.js +122 -0
- package/dist/node_modules/ses/src/eval-scope.js +89 -0
- package/dist/node_modules/ses/src/get-anonymous-intrinsics.js +181 -0
- package/dist/node_modules/ses/src/get-source-url.js +50 -0
- package/dist/node_modules/ses/src/global-object.js +175 -0
- package/dist/node_modules/ses/src/intrinsics.js +192 -0
- package/dist/node_modules/ses/src/lockdown-shim.js +37 -0
- package/dist/node_modules/ses/src/lockdown.js +558 -0
- package/dist/node_modules/ses/src/make-eval-function.js +28 -0
- package/dist/node_modules/ses/src/make-evaluate.js +110 -0
- package/dist/node_modules/ses/src/make-function-constructor.js +79 -0
- package/dist/node_modules/ses/src/make-hardener.js +275 -0
- package/dist/node_modules/ses/src/make-safe-evaluator.js +112 -0
- package/dist/node_modules/ses/src/module-instance.js +497 -0
- package/dist/node_modules/ses/src/module-link.js +159 -0
- package/dist/node_modules/ses/src/module-load.js +719 -0
- package/dist/node_modules/ses/src/module-proxy.js +200 -0
- package/dist/node_modules/ses/src/permits-intrinsics.js +291 -0
- package/dist/node_modules/ses/src/permits.js +1761 -0
- package/dist/node_modules/ses/src/reporting-types.d.ts +13 -0
- package/dist/node_modules/ses/src/reporting.js +105 -0
- package/dist/node_modules/ses/src/scope-constants.js +180 -0
- package/dist/node_modules/ses/src/shim-arraybuffer-transfer.js +85 -0
- package/dist/node_modules/ses/src/sloppy-globals-scope-terminator.js +61 -0
- package/dist/node_modules/ses/src/strict-scope-terminator.js +99 -0
- package/dist/node_modules/ses/src/tame-date-constructor.js +127 -0
- package/dist/node_modules/ses/src/tame-domains.js +41 -0
- package/dist/node_modules/ses/src/tame-faux-data-properties.js +210 -0
- package/dist/node_modules/ses/src/tame-function-constructors.js +140 -0
- package/dist/node_modules/ses/src/tame-function-tostring.js +50 -0
- package/dist/node_modules/ses/src/tame-harden.js +29 -0
- package/dist/node_modules/ses/src/tame-locale-methods.js +78 -0
- package/dist/node_modules/ses/src/tame-math-object.js +41 -0
- package/dist/node_modules/ses/src/tame-module-source.js +51 -0
- package/dist/node_modules/ses/src/tame-regenerator-runtime.js +29 -0
- package/dist/node_modules/ses/src/tame-regexp-constructor.js +65 -0
- package/dist/node_modules/ses/src/tame-symbol-constructor.js +64 -0
- package/dist/node_modules/ses/src/transforms.js +267 -0
- package/dist/node_modules/ses/tools.js +25 -0
- package/dist/node_modules/ses/types.d.ts +606 -0
- package/dist/server/actions/ui-schema-action.d.ts +27 -0
- package/dist/server/actions/ui-schema-action.js +118 -0
- package/dist/server/collections/flowModelTreePath.d.ts +11 -0
- package/dist/server/collections/flowModelTreePath.js +74 -0
- package/dist/server/collections/flowModels.d.ts +11 -0
- package/dist/server/collections/flowModels.js +57 -0
- package/dist/server/collections/flowsql.d.ts +10 -0
- package/dist/server/collections/flowsql.js +51 -0
- package/dist/server/dao/ui_schema_node_dao.d.ts +26 -0
- package/dist/server/dao/ui_schema_node_dao.js +24 -0
- package/dist/server/helper.d.ts +8 -0
- package/dist/server/helper.js +9 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +42 -0
- package/dist/server/model.d.ts +12 -0
- package/dist/server/model.js +38 -0
- package/dist/server/plugin.d.ts +26 -0
- package/dist/server/plugin.js +270 -0
- package/dist/server/repository.d.ts +116 -0
- package/dist/server/repository.js +1209 -0
- package/dist/server/server.d.ts +16 -0
- package/dist/server/server.js +198 -0
- package/dist/server/template/contexts.d.ts +73 -0
- package/dist/server/template/contexts.js +233 -0
- package/dist/server/template/resolver.d.ts +30 -0
- package/dist/server/template/resolver.js +225 -0
- package/dist/server/variables/registry.d.ts +42 -0
- package/dist/server/variables/registry.js +299 -0
- package/package.json +28 -0
- package/server.d.ts +2 -0
- package/server.js +1 -0
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
import { getEnvironmentOption as getenv } from '@endo/env-options';
|
|
2
|
+
import {
|
|
3
|
+
Map,
|
|
4
|
+
Set,
|
|
5
|
+
TypeError,
|
|
6
|
+
arrayJoin,
|
|
7
|
+
arrayMap,
|
|
8
|
+
arrayPush,
|
|
9
|
+
arraySome,
|
|
10
|
+
create,
|
|
11
|
+
freeze,
|
|
12
|
+
generatorNext,
|
|
13
|
+
generatorThrow,
|
|
14
|
+
getOwnPropertyNames,
|
|
15
|
+
isArray,
|
|
16
|
+
isPrimitive,
|
|
17
|
+
mapGet,
|
|
18
|
+
mapHas,
|
|
19
|
+
mapSet,
|
|
20
|
+
promiseThen,
|
|
21
|
+
setAdd,
|
|
22
|
+
values,
|
|
23
|
+
weakmapGet,
|
|
24
|
+
weakmapHas,
|
|
25
|
+
} from './commons.js';
|
|
26
|
+
import { makeError, annotateError, q, b, X } from './error/assert.js';
|
|
27
|
+
|
|
28
|
+
const noop = () => {};
|
|
29
|
+
|
|
30
|
+
const asyncTrampoline = async (generatorFunc, args, errorWrapper) => {
|
|
31
|
+
await null;
|
|
32
|
+
const iterator = generatorFunc(...args);
|
|
33
|
+
let result = generatorNext(iterator);
|
|
34
|
+
while (!result.done) {
|
|
35
|
+
try {
|
|
36
|
+
// eslint-disable-next-line no-await-in-loop
|
|
37
|
+
const val = await result.value;
|
|
38
|
+
result = generatorNext(iterator, val);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
result = generatorThrow(iterator, errorWrapper(error));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return result.value;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const syncTrampoline = (generatorFunc, args) => {
|
|
47
|
+
const iterator = generatorFunc(...args);
|
|
48
|
+
let result = generatorNext(iterator);
|
|
49
|
+
while (!result.done) {
|
|
50
|
+
try {
|
|
51
|
+
result = generatorNext(iterator, result.value);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
result = generatorThrow(iterator, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result.value;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// `makeAlias` constructs compartment specifier tuples for the `aliases`
|
|
60
|
+
// private field of compartments.
|
|
61
|
+
// These aliases allow a compartment to alias an internal module specifier to a
|
|
62
|
+
// module specifier in an external compartment, and also to create internal
|
|
63
|
+
// aliases.
|
|
64
|
+
// Both are facilitated by the moduleMap Compartment constructor option.
|
|
65
|
+
export const makeAlias = (compartment, specifier) =>
|
|
66
|
+
freeze({ compartment, specifier });
|
|
67
|
+
|
|
68
|
+
// `resolveAll` pre-computes resolutions of all imports within the compartment
|
|
69
|
+
// in which a module was loaded.
|
|
70
|
+
const resolveAll = (imports, resolveHook, fullReferrerSpecifier) => {
|
|
71
|
+
const resolvedImports = create(null);
|
|
72
|
+
for (const importSpecifier of imports) {
|
|
73
|
+
const fullSpecifier = resolveHook(importSpecifier, fullReferrerSpecifier);
|
|
74
|
+
resolvedImports[importSpecifier] = fullSpecifier;
|
|
75
|
+
}
|
|
76
|
+
return freeze(resolvedImports);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const loadModuleSource = (
|
|
80
|
+
compartmentPrivateFields,
|
|
81
|
+
moduleAliases,
|
|
82
|
+
compartment,
|
|
83
|
+
moduleSpecifier,
|
|
84
|
+
moduleSource,
|
|
85
|
+
enqueueJob,
|
|
86
|
+
selectImplementation,
|
|
87
|
+
moduleLoads,
|
|
88
|
+
importMeta,
|
|
89
|
+
) => {
|
|
90
|
+
const { resolveHook, name: compartmentName } = weakmapGet(
|
|
91
|
+
compartmentPrivateFields,
|
|
92
|
+
compartment,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const { imports } = moduleSource;
|
|
96
|
+
if (
|
|
97
|
+
!isArray(imports) ||
|
|
98
|
+
arraySome(imports, specifier => typeof specifier !== 'string')
|
|
99
|
+
) {
|
|
100
|
+
throw makeError(
|
|
101
|
+
X`Invalid module source: 'imports' must be an array of strings, got ${imports} for module ${q(moduleSpecifier)} of compartment ${q(compartmentName)}`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// resolve all imports relative to this referrer module.
|
|
106
|
+
const resolvedImports = resolveAll(imports, resolveHook, moduleSpecifier);
|
|
107
|
+
const moduleRecord = freeze({
|
|
108
|
+
compartment,
|
|
109
|
+
moduleSource,
|
|
110
|
+
moduleSpecifier,
|
|
111
|
+
resolvedImports,
|
|
112
|
+
importMeta,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Enqueue jobs to load this module's shallow dependencies.
|
|
116
|
+
for (const fullSpecifier of values(resolvedImports)) {
|
|
117
|
+
// Behold: recursion.
|
|
118
|
+
// eslint-disable-next-line no-use-before-define
|
|
119
|
+
enqueueJob(memoizedLoadWithErrorAnnotation, [
|
|
120
|
+
compartmentPrivateFields,
|
|
121
|
+
moduleAliases,
|
|
122
|
+
compartment,
|
|
123
|
+
fullSpecifier,
|
|
124
|
+
enqueueJob,
|
|
125
|
+
selectImplementation,
|
|
126
|
+
moduleLoads,
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return moduleRecord;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
function* loadWithoutErrorAnnotation(
|
|
134
|
+
compartmentPrivateFields,
|
|
135
|
+
moduleAliases,
|
|
136
|
+
compartment,
|
|
137
|
+
moduleSpecifier,
|
|
138
|
+
enqueueJob,
|
|
139
|
+
selectImplementation,
|
|
140
|
+
moduleLoads,
|
|
141
|
+
) {
|
|
142
|
+
const {
|
|
143
|
+
importHook,
|
|
144
|
+
importNowHook,
|
|
145
|
+
moduleMap,
|
|
146
|
+
moduleMapHook,
|
|
147
|
+
moduleRecords,
|
|
148
|
+
parentCompartment,
|
|
149
|
+
} = weakmapGet(compartmentPrivateFields, compartment);
|
|
150
|
+
|
|
151
|
+
if (mapHas(moduleRecords, moduleSpecifier)) {
|
|
152
|
+
return mapGet(moduleRecords, moduleSpecifier);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Follow moduleMap, or moduleMapHook if present.
|
|
156
|
+
let moduleDescriptor = moduleMap[moduleSpecifier];
|
|
157
|
+
if (moduleDescriptor === undefined && moduleMapHook !== undefined) {
|
|
158
|
+
moduleDescriptor = moduleMapHook(moduleSpecifier);
|
|
159
|
+
}
|
|
160
|
+
if (moduleDescriptor === undefined) {
|
|
161
|
+
const moduleHook = selectImplementation(importHook, importNowHook);
|
|
162
|
+
if (moduleHook === undefined) {
|
|
163
|
+
const moduleHookName = selectImplementation(
|
|
164
|
+
'importHook',
|
|
165
|
+
'importNowHook',
|
|
166
|
+
);
|
|
167
|
+
throw makeError(
|
|
168
|
+
X`${b(moduleHookName)} needed to load module ${q(
|
|
169
|
+
moduleSpecifier,
|
|
170
|
+
)} in compartment ${q(compartment.name)}`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
moduleDescriptor = moduleHook(moduleSpecifier);
|
|
174
|
+
// Uninitialized module namespaces throw if we attempt to coerce them into
|
|
175
|
+
// promises.
|
|
176
|
+
if (!weakmapHas(moduleAliases, moduleDescriptor)) {
|
|
177
|
+
moduleDescriptor = yield moduleDescriptor;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (typeof moduleDescriptor === 'string') {
|
|
182
|
+
// eslint-disable-next-line @endo/no-polymorphic-call
|
|
183
|
+
throw makeError(
|
|
184
|
+
X`Cannot map module ${q(moduleSpecifier)} to ${q(
|
|
185
|
+
moduleDescriptor,
|
|
186
|
+
)} in parent compartment, use {source} module descriptor`,
|
|
187
|
+
TypeError,
|
|
188
|
+
);
|
|
189
|
+
} else if (!isPrimitive(moduleDescriptor)) {
|
|
190
|
+
// In this shim (and not in XS, and not in the standard we imagine), we
|
|
191
|
+
// allow a module namespace object to stand in for a module descriptor that
|
|
192
|
+
// describes its original {compartment, specifier} so that it can be used
|
|
193
|
+
// to create a link.
|
|
194
|
+
let aliasDescriptor = weakmapGet(moduleAliases, moduleDescriptor);
|
|
195
|
+
if (aliasDescriptor !== undefined) {
|
|
196
|
+
moduleDescriptor = aliasDescriptor;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (moduleDescriptor.namespace !== undefined) {
|
|
200
|
+
// { namespace: string, compartment?: Compartment }
|
|
201
|
+
// Namespace module descriptors link to a module instance.
|
|
202
|
+
|
|
203
|
+
if (typeof moduleDescriptor.namespace === 'string') {
|
|
204
|
+
// The default compartment is the *parent*, not this child compartment.
|
|
205
|
+
// This is a difference from the legacy {specifier, compartment} module
|
|
206
|
+
// descriptor.
|
|
207
|
+
const {
|
|
208
|
+
compartment: aliasCompartment = parentCompartment,
|
|
209
|
+
namespace: aliasSpecifier,
|
|
210
|
+
} = moduleDescriptor;
|
|
211
|
+
if (
|
|
212
|
+
isPrimitive(aliasCompartment) ||
|
|
213
|
+
!weakmapHas(compartmentPrivateFields, aliasCompartment)
|
|
214
|
+
) {
|
|
215
|
+
throw makeError(
|
|
216
|
+
X`Invalid compartment in module descriptor for specifier ${q(moduleSpecifier)} in compartment ${q(compartment.name)}`,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
// Behold: recursion.
|
|
220
|
+
// eslint-disable-next-line no-use-before-define
|
|
221
|
+
const aliasRecord = yield memoizedLoadWithErrorAnnotation(
|
|
222
|
+
compartmentPrivateFields,
|
|
223
|
+
moduleAliases,
|
|
224
|
+
aliasCompartment,
|
|
225
|
+
aliasSpecifier,
|
|
226
|
+
enqueueJob,
|
|
227
|
+
selectImplementation,
|
|
228
|
+
moduleLoads,
|
|
229
|
+
);
|
|
230
|
+
mapSet(moduleRecords, moduleSpecifier, aliasRecord);
|
|
231
|
+
return aliasRecord;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// All remaining objects must either be a module namespace, or be
|
|
235
|
+
// promoted into a module namespace with a virtual module source.
|
|
236
|
+
if (!isPrimitive(moduleDescriptor.namespace)) {
|
|
237
|
+
const { namespace } = moduleDescriptor;
|
|
238
|
+
// Brand-check SES shim module exports namespaces:
|
|
239
|
+
aliasDescriptor = weakmapGet(moduleAliases, namespace);
|
|
240
|
+
if (aliasDescriptor !== undefined) {
|
|
241
|
+
moduleDescriptor = aliasDescriptor;
|
|
242
|
+
// Fall through to processing the resulting {compartment, specifier}
|
|
243
|
+
// alias.
|
|
244
|
+
} else {
|
|
245
|
+
// Promote an arbitrary object to a module namespace with a virtual
|
|
246
|
+
// module source.
|
|
247
|
+
// { namespace: Object }
|
|
248
|
+
const exports = getOwnPropertyNames(namespace);
|
|
249
|
+
/** @type {import('../types.js').VirtualModuleSource} */
|
|
250
|
+
const moduleSource = {
|
|
251
|
+
imports: [],
|
|
252
|
+
exports,
|
|
253
|
+
execute(env) {
|
|
254
|
+
for (const name of exports) {
|
|
255
|
+
env[name] = namespace[name];
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
const importMeta = undefined;
|
|
260
|
+
const moduleRecord = loadModuleSource(
|
|
261
|
+
compartmentPrivateFields,
|
|
262
|
+
moduleAliases,
|
|
263
|
+
compartment,
|
|
264
|
+
moduleSpecifier,
|
|
265
|
+
moduleSource,
|
|
266
|
+
enqueueJob,
|
|
267
|
+
selectImplementation,
|
|
268
|
+
moduleLoads,
|
|
269
|
+
importMeta,
|
|
270
|
+
);
|
|
271
|
+
mapSet(moduleRecords, moduleSpecifier, moduleRecord);
|
|
272
|
+
return moduleRecord;
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
throw makeError(
|
|
276
|
+
X`Invalid compartment in module descriptor for specifier ${q(moduleSpecifier)} in compartment ${q(compartment.name)}`,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (moduleDescriptor.source !== undefined) {
|
|
282
|
+
// Module source descriptors create an instance from a module source.
|
|
283
|
+
// The descriptor may contain the module source, or refer to a source
|
|
284
|
+
// loaded in a particular compartment.
|
|
285
|
+
|
|
286
|
+
if (typeof moduleDescriptor.source === 'string') {
|
|
287
|
+
// { source: string, importMeta?, specifier?: string, compartment? }
|
|
288
|
+
// A string source is the specifier for a different module source.
|
|
289
|
+
// That source may come from this compartment's parent (default), or
|
|
290
|
+
// from a specified compartment, and the specified compartment may be
|
|
291
|
+
// this compartment to make a duplicate.
|
|
292
|
+
|
|
293
|
+
const {
|
|
294
|
+
source: loaderSpecifier,
|
|
295
|
+
specifier: instanceSpecifier = moduleSpecifier,
|
|
296
|
+
compartment: loaderCompartment = parentCompartment,
|
|
297
|
+
importMeta = undefined,
|
|
298
|
+
} = moduleDescriptor;
|
|
299
|
+
|
|
300
|
+
// Induce the compartment, possibly a different compartment
|
|
301
|
+
// to load a module source.
|
|
302
|
+
|
|
303
|
+
// Behold: recursion.
|
|
304
|
+
// eslint-disable-next-line no-use-before-define
|
|
305
|
+
const loaderRecord = yield memoizedLoadWithErrorAnnotation(
|
|
306
|
+
compartmentPrivateFields,
|
|
307
|
+
moduleAliases,
|
|
308
|
+
loaderCompartment,
|
|
309
|
+
loaderSpecifier,
|
|
310
|
+
enqueueJob,
|
|
311
|
+
selectImplementation,
|
|
312
|
+
moduleLoads,
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// Extract the source of the module from the loader compartment's
|
|
316
|
+
// record.
|
|
317
|
+
const { moduleSource } = loaderRecord;
|
|
318
|
+
|
|
319
|
+
// Instantiate that source in our own compartment, possibly with a
|
|
320
|
+
// different specifier for resolving its own imports.
|
|
321
|
+
const moduleRecord = loadModuleSource(
|
|
322
|
+
compartmentPrivateFields,
|
|
323
|
+
moduleAliases,
|
|
324
|
+
compartment,
|
|
325
|
+
instanceSpecifier,
|
|
326
|
+
moduleSource,
|
|
327
|
+
enqueueJob,
|
|
328
|
+
selectImplementation,
|
|
329
|
+
moduleLoads,
|
|
330
|
+
importMeta,
|
|
331
|
+
);
|
|
332
|
+
mapSet(moduleRecords, moduleSpecifier, moduleRecord);
|
|
333
|
+
return moduleRecord;
|
|
334
|
+
} else {
|
|
335
|
+
// { source: ModuleSource, importMeta?, specifier?: string }
|
|
336
|
+
// We assume all non-string module sources are any of the supported
|
|
337
|
+
// kinds of module source: PrecompiledModuleSource,
|
|
338
|
+
// VirtualModuleSource, or a native ModuleSource.
|
|
339
|
+
|
|
340
|
+
const {
|
|
341
|
+
source: moduleSource,
|
|
342
|
+
specifier: aliasSpecifier = moduleSpecifier,
|
|
343
|
+
importMeta,
|
|
344
|
+
} = moduleDescriptor;
|
|
345
|
+
|
|
346
|
+
const aliasRecord = loadModuleSource(
|
|
347
|
+
compartmentPrivateFields,
|
|
348
|
+
moduleAliases,
|
|
349
|
+
compartment,
|
|
350
|
+
aliasSpecifier,
|
|
351
|
+
moduleSource,
|
|
352
|
+
enqueueJob,
|
|
353
|
+
selectImplementation,
|
|
354
|
+
moduleLoads,
|
|
355
|
+
importMeta,
|
|
356
|
+
);
|
|
357
|
+
mapSet(moduleRecords, moduleSpecifier, aliasRecord);
|
|
358
|
+
return aliasRecord;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (moduleDescriptor.archive !== undefined) {
|
|
363
|
+
// { archive: Archive, path: string }
|
|
364
|
+
// We do not support this XS-native module descriptor.
|
|
365
|
+
throw makeError(
|
|
366
|
+
X`Unsupported archive module descriptor for specifier ${q(moduleSpecifier)} in compartment ${q(compartment.name)}`,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// { record, specifier?, compartment?, importMeta? }
|
|
371
|
+
// A (legacy) module descriptor for when we find the module source (record)
|
|
372
|
+
// but at a different specifier than requested.
|
|
373
|
+
// Providing this {specifier, record} descriptor serves as an ergonomic
|
|
374
|
+
// short-hand for stashing the record, returning a {compartment, specifier}
|
|
375
|
+
// reference, bouncing the module hook, then producing the source (record)
|
|
376
|
+
// when module hook receives the response specifier.
|
|
377
|
+
if (moduleDescriptor.record !== undefined) {
|
|
378
|
+
const {
|
|
379
|
+
compartment: aliasCompartment = compartment,
|
|
380
|
+
specifier: aliasSpecifier = moduleSpecifier,
|
|
381
|
+
record: moduleSource,
|
|
382
|
+
importMeta,
|
|
383
|
+
} = moduleDescriptor;
|
|
384
|
+
|
|
385
|
+
const aliasRecord = loadModuleSource(
|
|
386
|
+
compartmentPrivateFields,
|
|
387
|
+
moduleAliases,
|
|
388
|
+
aliasCompartment,
|
|
389
|
+
aliasSpecifier,
|
|
390
|
+
moduleSource,
|
|
391
|
+
enqueueJob,
|
|
392
|
+
selectImplementation,
|
|
393
|
+
moduleLoads,
|
|
394
|
+
importMeta,
|
|
395
|
+
);
|
|
396
|
+
mapSet(moduleRecords, moduleSpecifier, aliasRecord);
|
|
397
|
+
mapSet(moduleRecords, aliasSpecifier, aliasRecord);
|
|
398
|
+
return aliasRecord;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// { specifier: string, compartment: Compartment }
|
|
402
|
+
// A (legacy) module descriptor that describes a link to a module instance
|
|
403
|
+
// in a specified compartment.
|
|
404
|
+
if (
|
|
405
|
+
moduleDescriptor.compartment !== undefined &&
|
|
406
|
+
moduleDescriptor.specifier !== undefined
|
|
407
|
+
) {
|
|
408
|
+
if (
|
|
409
|
+
isPrimitive(moduleDescriptor.compartment) ||
|
|
410
|
+
!weakmapHas(compartmentPrivateFields, moduleDescriptor.compartment) ||
|
|
411
|
+
typeof moduleDescriptor.specifier !== 'string'
|
|
412
|
+
) {
|
|
413
|
+
throw makeError(
|
|
414
|
+
X`Invalid compartment in module descriptor for specifier ${q(moduleSpecifier)} in compartment ${q(compartment.name)}`,
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
// Behold: recursion.
|
|
418
|
+
// eslint-disable-next-line no-use-before-define
|
|
419
|
+
const aliasRecord = yield memoizedLoadWithErrorAnnotation(
|
|
420
|
+
compartmentPrivateFields,
|
|
421
|
+
moduleAliases,
|
|
422
|
+
moduleDescriptor.compartment,
|
|
423
|
+
moduleDescriptor.specifier,
|
|
424
|
+
enqueueJob,
|
|
425
|
+
selectImplementation,
|
|
426
|
+
moduleLoads,
|
|
427
|
+
);
|
|
428
|
+
mapSet(moduleRecords, moduleSpecifier, aliasRecord);
|
|
429
|
+
return aliasRecord;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// A (legacy) behavior: If we do not recognize the module descriptor as a
|
|
433
|
+
// module descriptor, we assume that it is a module source (record):
|
|
434
|
+
const moduleSource = moduleDescriptor;
|
|
435
|
+
const moduleRecord = loadModuleSource(
|
|
436
|
+
compartmentPrivateFields,
|
|
437
|
+
moduleAliases,
|
|
438
|
+
compartment,
|
|
439
|
+
moduleSpecifier,
|
|
440
|
+
moduleSource,
|
|
441
|
+
enqueueJob,
|
|
442
|
+
selectImplementation,
|
|
443
|
+
moduleLoads,
|
|
444
|
+
);
|
|
445
|
+
// Memoize.
|
|
446
|
+
mapSet(moduleRecords, moduleSpecifier, moduleRecord);
|
|
447
|
+
return moduleRecord;
|
|
448
|
+
} else {
|
|
449
|
+
throw makeError(
|
|
450
|
+
X`module descriptor must be a string or object for specifier ${q(
|
|
451
|
+
moduleSpecifier,
|
|
452
|
+
)} in compartment ${q(compartment.name)}`,
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const memoizedLoadWithErrorAnnotation = (
|
|
458
|
+
compartmentPrivateFields,
|
|
459
|
+
moduleAliases,
|
|
460
|
+
compartment,
|
|
461
|
+
moduleSpecifier,
|
|
462
|
+
enqueueJob,
|
|
463
|
+
selectImplementation,
|
|
464
|
+
moduleLoads,
|
|
465
|
+
) => {
|
|
466
|
+
const { name: compartmentName } = weakmapGet(
|
|
467
|
+
compartmentPrivateFields,
|
|
468
|
+
compartment,
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
// Prevent data-lock from recursion into branches visited in dependent loads.
|
|
472
|
+
let compartmentLoading = mapGet(moduleLoads, compartment);
|
|
473
|
+
if (compartmentLoading === undefined) {
|
|
474
|
+
compartmentLoading = new Map();
|
|
475
|
+
mapSet(moduleLoads, compartment, compartmentLoading);
|
|
476
|
+
}
|
|
477
|
+
let moduleLoading = mapGet(compartmentLoading, moduleSpecifier);
|
|
478
|
+
if (moduleLoading !== undefined) {
|
|
479
|
+
return moduleLoading;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
moduleLoading = selectImplementation(asyncTrampoline, syncTrampoline)(
|
|
483
|
+
loadWithoutErrorAnnotation,
|
|
484
|
+
[
|
|
485
|
+
compartmentPrivateFields,
|
|
486
|
+
moduleAliases,
|
|
487
|
+
compartment,
|
|
488
|
+
moduleSpecifier,
|
|
489
|
+
enqueueJob,
|
|
490
|
+
selectImplementation,
|
|
491
|
+
moduleLoads,
|
|
492
|
+
],
|
|
493
|
+
error => {
|
|
494
|
+
// eslint-disable-next-line @endo/no-polymorphic-call
|
|
495
|
+
annotateError(
|
|
496
|
+
error,
|
|
497
|
+
X`${error.message}, loading ${q(moduleSpecifier)} in compartment ${q(
|
|
498
|
+
compartmentName,
|
|
499
|
+
)}`,
|
|
500
|
+
);
|
|
501
|
+
throw error;
|
|
502
|
+
},
|
|
503
|
+
);
|
|
504
|
+
|
|
505
|
+
mapSet(compartmentLoading, moduleSpecifier, moduleLoading);
|
|
506
|
+
|
|
507
|
+
return moduleLoading;
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* If `aggregateErrors` is `false`, the `errors` property of the fulfilled object
|
|
512
|
+
* will always be empty.
|
|
513
|
+
* @param {{errors?: Error[], noAggregateErrors?: boolean}} [options]
|
|
514
|
+
*/
|
|
515
|
+
const asyncJobQueue = ({ errors = [], noAggregateErrors = false } = {}) => {
|
|
516
|
+
/** @type {Set<Promise<undefined>>} */
|
|
517
|
+
const pendingJobs = new Set();
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Enqueues a job that starts immediately but won't be awaited until drainQueue is called.
|
|
521
|
+
*
|
|
522
|
+
* @template {(...args: any[]) => Promise<void>} F
|
|
523
|
+
* @param {F} func - An async function to execute
|
|
524
|
+
* @param {Parameters<F>} args - Arguments to pass to the function
|
|
525
|
+
* @returns {void}
|
|
526
|
+
*/
|
|
527
|
+
const enqueueJob = (func, args) => {
|
|
528
|
+
setAdd(
|
|
529
|
+
pendingJobs,
|
|
530
|
+
promiseThen(func(...args), noop, error => {
|
|
531
|
+
if (noAggregateErrors) {
|
|
532
|
+
throw error;
|
|
533
|
+
} else {
|
|
534
|
+
arrayPush(errors, error);
|
|
535
|
+
}
|
|
536
|
+
}),
|
|
537
|
+
);
|
|
538
|
+
};
|
|
539
|
+
/**
|
|
540
|
+
* Sequentially awaits pending jobs and returns an array of errors
|
|
541
|
+
*/
|
|
542
|
+
const drainQueue = async () => {
|
|
543
|
+
await null;
|
|
544
|
+
for (const job of pendingJobs) {
|
|
545
|
+
// eslint-disable-next-line no-await-in-loop
|
|
546
|
+
await job;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
return { enqueueJob, drainQueue, errors };
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* If `aggregateErrors` is `false`, the `errors` property of the returned object
|
|
554
|
+
* will always be empty.
|
|
555
|
+
* @param {{errors?: Error[], noAggregateErrors?: boolean}} [options]
|
|
556
|
+
*/
|
|
557
|
+
const syncJobQueue = ({ errors = [], noAggregateErrors = false } = {}) => {
|
|
558
|
+
let current = [];
|
|
559
|
+
let next = [];
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Enqueues a job
|
|
563
|
+
*
|
|
564
|
+
* @template {(...args: any[]) => void} F
|
|
565
|
+
* @param {F} func - An async function to execute
|
|
566
|
+
* @param {Parameters<F>} args - Arguments to pass to the function
|
|
567
|
+
* @returns {void}
|
|
568
|
+
*/
|
|
569
|
+
const enqueueJob = (func, args) => {
|
|
570
|
+
arrayPush(next, [func, args]);
|
|
571
|
+
};
|
|
572
|
+
const drainQueue = () => {
|
|
573
|
+
// Attention: load bearing flow order. Calling another enqueued function in the
|
|
574
|
+
// synchronous usecase must happen after the one that enqueued it has finished.
|
|
575
|
+
// Jobs enqueued in one pass do not interleave with jobs resulting from them.
|
|
576
|
+
// It's necessary for efficient memoization and to break cycles.
|
|
577
|
+
for (const [func, args] of current) {
|
|
578
|
+
try {
|
|
579
|
+
func(...args);
|
|
580
|
+
} catch (error) {
|
|
581
|
+
if (noAggregateErrors) {
|
|
582
|
+
throw error;
|
|
583
|
+
} else {
|
|
584
|
+
arrayPush(errors, error);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
current = next;
|
|
589
|
+
next = [];
|
|
590
|
+
if (current.length > 0) drainQueue();
|
|
591
|
+
};
|
|
592
|
+
return { enqueueJob, drainQueue, errors };
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* @param {object} options
|
|
597
|
+
* @param {Array<Error>} options.errors
|
|
598
|
+
* @param {string} options.errorPrefix
|
|
599
|
+
*/
|
|
600
|
+
const throwAggregateError = ({ errors, errorPrefix }) => {
|
|
601
|
+
// Throw an aggregate error if there were any errors.
|
|
602
|
+
if (errors.length > 0) {
|
|
603
|
+
const verbose =
|
|
604
|
+
/** @type {'' | 'verbose'} */
|
|
605
|
+
(getenv('COMPARTMENT_LOAD_ERRORS', '', ['verbose'])) === 'verbose';
|
|
606
|
+
throw TypeError(
|
|
607
|
+
`${errorPrefix} (${errors.length} underlying failures: ${arrayJoin(
|
|
608
|
+
arrayMap(errors, error => error.message + (verbose ? error.stack : '')),
|
|
609
|
+
', ',
|
|
610
|
+
)}`,
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
const preferSync = (_asyncImpl, syncImpl) => syncImpl;
|
|
616
|
+
const preferAsync = (asyncImpl, _syncImpl) => asyncImpl;
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* `load` asynchronously gathers the module records for a module and its
|
|
620
|
+
* transitive dependencies.
|
|
621
|
+
* The module records refer to each other by a reference to the dependency's
|
|
622
|
+
* compartment and the specifier of the module within its own compartment.
|
|
623
|
+
* This graph is then ready to be synchronously linked and executed.
|
|
624
|
+
* @param {WeakMap<Compartment, any>} compartmentPrivateFields
|
|
625
|
+
* @param {WeakMap<object, object>} moduleAliases
|
|
626
|
+
* @param {Compartment} compartment
|
|
627
|
+
* @param {string} moduleSpecifier - The module specifier to load.
|
|
628
|
+
* @param {{ noAggregateErrors?: boolean}} options
|
|
629
|
+
*/
|
|
630
|
+
export const load = async (
|
|
631
|
+
compartmentPrivateFields,
|
|
632
|
+
moduleAliases,
|
|
633
|
+
compartment,
|
|
634
|
+
moduleSpecifier,
|
|
635
|
+
{ noAggregateErrors = false } = {},
|
|
636
|
+
) => {
|
|
637
|
+
const { name: compartmentName } = weakmapGet(
|
|
638
|
+
compartmentPrivateFields,
|
|
639
|
+
compartment,
|
|
640
|
+
);
|
|
641
|
+
|
|
642
|
+
/** @type {Map<object, Map<string, Promise<Record<any, any>>>>} */
|
|
643
|
+
const moduleLoads = new Map();
|
|
644
|
+
|
|
645
|
+
const { enqueueJob, drainQueue, errors } = asyncJobQueue({
|
|
646
|
+
noAggregateErrors,
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
enqueueJob(memoizedLoadWithErrorAnnotation, [
|
|
650
|
+
compartmentPrivateFields,
|
|
651
|
+
moduleAliases,
|
|
652
|
+
compartment,
|
|
653
|
+
moduleSpecifier,
|
|
654
|
+
enqueueJob,
|
|
655
|
+
preferAsync,
|
|
656
|
+
moduleLoads,
|
|
657
|
+
]);
|
|
658
|
+
|
|
659
|
+
await drainQueue();
|
|
660
|
+
|
|
661
|
+
throwAggregateError({
|
|
662
|
+
errors,
|
|
663
|
+
errorPrefix: `Failed to load module ${q(moduleSpecifier)} in package ${q(
|
|
664
|
+
compartmentName,
|
|
665
|
+
)}`,
|
|
666
|
+
});
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* `loadNow` synchronously gathers the module records for a specified module
|
|
671
|
+
* and its transitive dependencies.
|
|
672
|
+
* The module records refer to each other by a reference to the dependency's
|
|
673
|
+
* compartment and the specifier of the module within its own compartment.
|
|
674
|
+
* This graph is then ready to be synchronously linked and executed.
|
|
675
|
+
* @param {WeakMap<Compartment, any>} compartmentPrivateFields
|
|
676
|
+
* @param {WeakMap<object, object>} moduleAliases
|
|
677
|
+
* @param {Compartment} compartment
|
|
678
|
+
* @param {string} moduleSpecifier - The module specifier to load.
|
|
679
|
+
* @param {{ noAggregateErrors?: boolean}} options
|
|
680
|
+
*/
|
|
681
|
+
|
|
682
|
+
export const loadNow = (
|
|
683
|
+
compartmentPrivateFields,
|
|
684
|
+
moduleAliases,
|
|
685
|
+
compartment,
|
|
686
|
+
moduleSpecifier,
|
|
687
|
+
{ noAggregateErrors = false } = {},
|
|
688
|
+
) => {
|
|
689
|
+
const { name: compartmentName } = weakmapGet(
|
|
690
|
+
compartmentPrivateFields,
|
|
691
|
+
compartment,
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
/** @type {Map<object, Map<string, Promise<Record<any, any>>>>} */
|
|
695
|
+
const moduleLoads = new Map();
|
|
696
|
+
|
|
697
|
+
const { enqueueJob, drainQueue, errors } = syncJobQueue({
|
|
698
|
+
noAggregateErrors,
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
enqueueJob(memoizedLoadWithErrorAnnotation, [
|
|
702
|
+
compartmentPrivateFields,
|
|
703
|
+
moduleAliases,
|
|
704
|
+
compartment,
|
|
705
|
+
moduleSpecifier,
|
|
706
|
+
enqueueJob,
|
|
707
|
+
preferSync,
|
|
708
|
+
moduleLoads,
|
|
709
|
+
]);
|
|
710
|
+
|
|
711
|
+
drainQueue();
|
|
712
|
+
|
|
713
|
+
throwAggregateError({
|
|
714
|
+
errors,
|
|
715
|
+
errorPrefix: `Failed to load module ${q(moduleSpecifier)} in package ${q(
|
|
716
|
+
compartmentName,
|
|
717
|
+
)}`,
|
|
718
|
+
});
|
|
719
|
+
};
|