@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.
Files changed (125) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +29 -0
  3. package/build.config.ts +22 -0
  4. package/client.d.ts +2 -0
  5. package/client.js +1 -0
  6. package/dist/client/index.d.ts +15 -0
  7. package/dist/client/index.js +10 -0
  8. package/dist/externalVersion.js +21 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.js +48 -0
  11. package/dist/locale/en-US.json +61 -0
  12. package/dist/locale/index.d.ts +141 -0
  13. package/dist/locale/index.js +79 -0
  14. package/dist/locale/zh-CN.json +61 -0
  15. package/dist/node_modules/ses/LICENSE +201 -0
  16. package/dist/node_modules/ses/LICENSE-aura +16 -0
  17. package/dist/node_modules/ses/LICENSE-caja +13 -0
  18. package/dist/node_modules/ses/LICENSE-corejs +19 -0
  19. package/dist/node_modules/ses/LICENSE-v8 +9 -0
  20. package/dist/node_modules/ses/assert-shim.js +1 -0
  21. package/dist/node_modules/ses/compartment-shim.js +1 -0
  22. package/dist/node_modules/ses/console-shim.js +1 -0
  23. package/dist/node_modules/ses/dist/lockdown.cjs +13912 -0
  24. package/dist/node_modules/ses/dist/lockdown.umd.js +13912 -0
  25. package/dist/node_modules/ses/dist/lockdown.umd.min.js +1 -0
  26. package/dist/node_modules/ses/dist/ses-hermes.cjs +13912 -0
  27. package/dist/node_modules/ses/dist/ses.cjs +1 -0
  28. package/dist/node_modules/ses/dist/ses.umd.js +13912 -0
  29. package/dist/node_modules/ses/dist/ses.umd.min.js +1 -0
  30. package/dist/node_modules/ses/dist/types.d.cts +606 -0
  31. package/dist/node_modules/ses/index.js +18 -0
  32. package/dist/node_modules/ses/lockdown-shim.js +1 -0
  33. package/dist/node_modules/ses/lockdown.js +1 -0
  34. package/dist/node_modules/ses/package.json +1 -0
  35. package/dist/node_modules/ses/src/assert-shim.js +4 -0
  36. package/dist/node_modules/ses/src/assert-sloppy-mode.js +11 -0
  37. package/dist/node_modules/ses/src/cauterize-property.js +69 -0
  38. package/dist/node_modules/ses/src/commons.js +425 -0
  39. package/dist/node_modules/ses/src/compartment-evaluate.js +93 -0
  40. package/dist/node_modules/ses/src/compartment-shim.js +22 -0
  41. package/dist/node_modules/ses/src/compartment.js +477 -0
  42. package/dist/node_modules/ses/src/console-shim.js +50 -0
  43. package/dist/node_modules/ses/src/enable-property-overrides.js +211 -0
  44. package/dist/node_modules/ses/src/enablements.js +244 -0
  45. package/dist/node_modules/ses/src/error/assert.js +584 -0
  46. package/dist/node_modules/ses/src/error/console.js +541 -0
  47. package/dist/node_modules/ses/src/error/fatal-assert.js +54 -0
  48. package/dist/node_modules/ses/src/error/internal-types.js +98 -0
  49. package/dist/node_modules/ses/src/error/note-log-args.js +77 -0
  50. package/dist/node_modules/ses/src/error/stringify-utils.js +195 -0
  51. package/dist/node_modules/ses/src/error/tame-console.js +197 -0
  52. package/dist/node_modules/ses/src/error/tame-error-constructor.js +284 -0
  53. package/dist/node_modules/ses/src/error/tame-v8-error-constructor.js +386 -0
  54. package/dist/node_modules/ses/src/error/types.js +59 -0
  55. package/dist/node_modules/ses/src/error/unhandled-rejection.js +122 -0
  56. package/dist/node_modules/ses/src/eval-scope.js +89 -0
  57. package/dist/node_modules/ses/src/get-anonymous-intrinsics.js +181 -0
  58. package/dist/node_modules/ses/src/get-source-url.js +50 -0
  59. package/dist/node_modules/ses/src/global-object.js +175 -0
  60. package/dist/node_modules/ses/src/intrinsics.js +192 -0
  61. package/dist/node_modules/ses/src/lockdown-shim.js +37 -0
  62. package/dist/node_modules/ses/src/lockdown.js +558 -0
  63. package/dist/node_modules/ses/src/make-eval-function.js +28 -0
  64. package/dist/node_modules/ses/src/make-evaluate.js +110 -0
  65. package/dist/node_modules/ses/src/make-function-constructor.js +79 -0
  66. package/dist/node_modules/ses/src/make-hardener.js +275 -0
  67. package/dist/node_modules/ses/src/make-safe-evaluator.js +112 -0
  68. package/dist/node_modules/ses/src/module-instance.js +497 -0
  69. package/dist/node_modules/ses/src/module-link.js +159 -0
  70. package/dist/node_modules/ses/src/module-load.js +719 -0
  71. package/dist/node_modules/ses/src/module-proxy.js +200 -0
  72. package/dist/node_modules/ses/src/permits-intrinsics.js +291 -0
  73. package/dist/node_modules/ses/src/permits.js +1761 -0
  74. package/dist/node_modules/ses/src/reporting-types.d.ts +13 -0
  75. package/dist/node_modules/ses/src/reporting.js +105 -0
  76. package/dist/node_modules/ses/src/scope-constants.js +180 -0
  77. package/dist/node_modules/ses/src/shim-arraybuffer-transfer.js +85 -0
  78. package/dist/node_modules/ses/src/sloppy-globals-scope-terminator.js +61 -0
  79. package/dist/node_modules/ses/src/strict-scope-terminator.js +99 -0
  80. package/dist/node_modules/ses/src/tame-date-constructor.js +127 -0
  81. package/dist/node_modules/ses/src/tame-domains.js +41 -0
  82. package/dist/node_modules/ses/src/tame-faux-data-properties.js +210 -0
  83. package/dist/node_modules/ses/src/tame-function-constructors.js +140 -0
  84. package/dist/node_modules/ses/src/tame-function-tostring.js +50 -0
  85. package/dist/node_modules/ses/src/tame-harden.js +29 -0
  86. package/dist/node_modules/ses/src/tame-locale-methods.js +78 -0
  87. package/dist/node_modules/ses/src/tame-math-object.js +41 -0
  88. package/dist/node_modules/ses/src/tame-module-source.js +51 -0
  89. package/dist/node_modules/ses/src/tame-regenerator-runtime.js +29 -0
  90. package/dist/node_modules/ses/src/tame-regexp-constructor.js +65 -0
  91. package/dist/node_modules/ses/src/tame-symbol-constructor.js +64 -0
  92. package/dist/node_modules/ses/src/transforms.js +267 -0
  93. package/dist/node_modules/ses/tools.js +25 -0
  94. package/dist/node_modules/ses/types.d.ts +606 -0
  95. package/dist/server/actions/ui-schema-action.d.ts +27 -0
  96. package/dist/server/actions/ui-schema-action.js +118 -0
  97. package/dist/server/collections/flowModelTreePath.d.ts +11 -0
  98. package/dist/server/collections/flowModelTreePath.js +74 -0
  99. package/dist/server/collections/flowModels.d.ts +11 -0
  100. package/dist/server/collections/flowModels.js +57 -0
  101. package/dist/server/collections/flowsql.d.ts +10 -0
  102. package/dist/server/collections/flowsql.js +51 -0
  103. package/dist/server/dao/ui_schema_node_dao.d.ts +26 -0
  104. package/dist/server/dao/ui_schema_node_dao.js +24 -0
  105. package/dist/server/helper.d.ts +8 -0
  106. package/dist/server/helper.js +9 -0
  107. package/dist/server/index.d.ts +9 -0
  108. package/dist/server/index.js +42 -0
  109. package/dist/server/model.d.ts +12 -0
  110. package/dist/server/model.js +38 -0
  111. package/dist/server/plugin.d.ts +26 -0
  112. package/dist/server/plugin.js +270 -0
  113. package/dist/server/repository.d.ts +116 -0
  114. package/dist/server/repository.js +1209 -0
  115. package/dist/server/server.d.ts +16 -0
  116. package/dist/server/server.js +198 -0
  117. package/dist/server/template/contexts.d.ts +73 -0
  118. package/dist/server/template/contexts.js +233 -0
  119. package/dist/server/template/resolver.d.ts +30 -0
  120. package/dist/server/template/resolver.js +225 -0
  121. package/dist/server/variables/registry.d.ts +42 -0
  122. package/dist/server/variables/registry.js +299 -0
  123. package/package.json +28 -0
  124. package/server.d.ts +2 -0
  125. package/server.js +1 -0
@@ -0,0 +1,541 @@
1
+ // @ts-check
2
+
3
+ // To ensure that this module operates without special privilege, it should
4
+ // not reference the free variable `console` except for its own internal
5
+ // debugging purposes in the declaration of `internalDebugConsole`, which is
6
+ // normally commented out.
7
+
8
+ import {
9
+ WeakSet,
10
+ arrayFilter,
11
+ arrayFlatMap,
12
+ arrayMap,
13
+ arrayPop,
14
+ arrayPush,
15
+ defineProperty,
16
+ freeze,
17
+ fromEntries,
18
+ isError,
19
+ stringEndsWith,
20
+ stringIncludes,
21
+ stringSplit,
22
+ weaksetAdd,
23
+ weaksetHas,
24
+ } from '../commons.js';
25
+
26
+ /**
27
+ * @import {FilterConsole, LogSeverity, VirtualConsole} from './types.js'
28
+ * @import {ErrorInfo, ErrorInfoKind, LogRecord, NoteCallback, LoggedErrorHandler, MakeCausalConsole, MakeLoggingConsoleKit} from "./internal-types.js";
29
+ */
30
+
31
+ /**
32
+ * Explicitly set a function's name, supporting use of arrow functions for which
33
+ * source text doesn't include a name and no initial name is set by
34
+ * NamedEvaluation
35
+ * https://tc39.es/ecma262/multipage/syntax-directed-operations.html#sec-runtime-semantics-namedevaluation
36
+ * Instead, we hope that tooling uses only the explicit `name` property.
37
+ *
38
+ * @template {Function} F
39
+ * @param {string} name
40
+ * @param {F} fn
41
+ * @returns {F}
42
+ */
43
+ const defineName = (name, fn) => defineProperty(fn, 'name', { value: name });
44
+
45
+ // For our internal debugging purposes, uncomment
46
+ // const internalDebugConsole = console;
47
+
48
+ // The permitted console methods, from:
49
+ // Whatwg "living standard" https://console.spec.whatwg.org/
50
+ // Node https://nodejs.org/dist/latest-v14.x/docs/api/console.html
51
+ // MDN https://developer.mozilla.org/en-US/docs/Web/API/Console_API
52
+ // TypeScript https://openstapps.gitlab.io/projectmanagement/interfaces/_node_modules__types_node_globals_d_.console.html
53
+ // Chrome https://developers.google.com/web/tools/chrome-devtools/console/api
54
+
55
+ // All console level methods have parameters (fmt?, ...args)
56
+ // where the argument sequence `fmt?, ...args` formats args according to
57
+ // fmt if fmt is a format string. Otherwise, it just renders them all as values
58
+ // separated by spaces.
59
+ // https://console.spec.whatwg.org/#formatter
60
+ // https://nodejs.org/docs/latest/api/util.html#util_util_format_format_args
61
+
62
+ // For the causal console, all occurrences of `fmt, ...args` or `...args` by
63
+ // itself must check for the presence of an error to ask the
64
+ // `loggedErrorHandler` to handle.
65
+ // In theory we should do a deep inspection to detect for example an array
66
+ // containing an error. We currently do not detect these and may never.
67
+
68
+ /** @typedef {keyof VirtualConsole | 'profile' | 'profileEnd'} ConsoleProps */
69
+
70
+ /**
71
+ * Those console methods whose actual parameters are `(fmt?, ...args)`
72
+ * even if their TypeScript types claim otherwise.
73
+ *
74
+ * Each is paired with what we consider to be their log severity level.
75
+ * This is the same as the log severity of these on other
76
+ * platform console implementations when they all agree.
77
+ *
78
+ * @type {readonly [ConsoleProps, LogSeverity | undefined][]}
79
+ */
80
+ export const consoleLevelMethods = freeze([
81
+ ['debug', 'debug'], // (fmt?, ...args) verbose level on Chrome
82
+ ['log', 'log'], // (fmt?, ...args) info level on Chrome
83
+ ['info', 'info'], // (fmt?, ...args)
84
+ ['warn', 'warn'], // (fmt?, ...args)
85
+ ['error', 'error'], // (fmt?, ...args)
86
+
87
+ ['trace', 'log'], // (fmt?, ...args)
88
+ ['dirxml', 'log'], // (fmt?, ...args) but TS typed (...data)
89
+ ['group', 'log'], // (fmt?, ...args) but TS typed (...label)
90
+ ['groupCollapsed', 'log'], // (fmt?, ...args) but TS typed (...label)
91
+ ]);
92
+
93
+ /**
94
+ * Those console methods other than those already enumerated by
95
+ * `consoleLevelMethods`.
96
+ *
97
+ * Each is paired with what we consider to be their log severity level.
98
+ * This is the same as the log severity of these on other
99
+ * platform console implementations when they all agree.
100
+ *
101
+ * @type {readonly [ConsoleProps, LogSeverity | undefined][]}
102
+ */
103
+ export const consoleOtherMethods = freeze([
104
+ ['assert', 'error'], // (value, fmt?, ...args)
105
+ ['timeLog', 'log'], // (label?, ...args) no fmt string
106
+
107
+ // Insensitive to whether any argument is an error. All arguments can pass
108
+ // thru to baseConsole as is.
109
+ ['clear', undefined], // ()
110
+ ['count', 'info'], // (label?)
111
+ ['countReset', undefined], // (label?)
112
+ ['dir', 'log'], // (item, options?)
113
+ ['groupEnd', 'log'], // ()
114
+ // In theory tabular data may be or contain an error. However, we currently
115
+ // do not detect these and may never.
116
+ ['table', 'log'], // (tabularData, properties?)
117
+ ['time', 'info'], // (label?)
118
+ ['timeEnd', 'info'], // (label?)
119
+
120
+ // Node Inspector only, MDN, and TypeScript, but not whatwg
121
+ ['profile', undefined], // (label?)
122
+ ['profileEnd', undefined], // (label?)
123
+ ['timeStamp', undefined], // (label?)
124
+ ]);
125
+
126
+ /** @type {readonly [ConsoleProps, LogSeverity | undefined][]} */
127
+ const consoleMethodPermits = freeze([
128
+ ...consoleLevelMethods,
129
+ ...consoleOtherMethods,
130
+ ]);
131
+
132
+ /**
133
+ * consoleOmittedProperties is currently unused. I record and maintain it here
134
+ * with the intention that it be treated like the `false` entries in the main
135
+ * SES permits: that seeing these on the original console is expected, but
136
+ * seeing anything else that's outside the permits is surprising and should
137
+ * provide a diagnostic.
138
+ *
139
+ * const consoleOmittedProperties = freeze([
140
+ * 'memory', // Chrome
141
+ * 'exception', // FF, MDN
142
+ * '_ignoreErrors', // Node
143
+ * '_stderr', // Node
144
+ * '_stderrErrorHandler', // Node
145
+ * '_stdout', // Node
146
+ * '_stdoutErrorHandler', // Node
147
+ * '_times', // Node
148
+ * 'context', // Chrome, Node
149
+ * 'record', // Safari
150
+ * 'recordEnd', // Safari
151
+ *
152
+ * 'screenshot', // Safari
153
+ * // Symbols
154
+ * '@@toStringTag', // Chrome: "Object", Safari: "Console"
155
+ * // A variety of other symbols also seen on Node
156
+ * ]);
157
+ */
158
+
159
+ // //////////////////////////// Logging Console ////////////////////////////////
160
+
161
+ /** @type {MakeLoggingConsoleKit} */
162
+ export const makeLoggingConsoleKit = (
163
+ loggedErrorHandler,
164
+ { shouldResetForDebugging = false } = {},
165
+ ) => {
166
+ if (shouldResetForDebugging) {
167
+ // eslint-disable-next-line @endo/no-polymorphic-call
168
+ loggedErrorHandler.resetErrorTagNum();
169
+ }
170
+
171
+ // Not frozen!
172
+ let logArray = [];
173
+
174
+ const loggingConsole = fromEntries(
175
+ arrayMap(consoleMethodPermits, ([name, _]) => {
176
+ /**
177
+ * @param {...any} args
178
+ */
179
+ const method = defineName(name, (...args) => {
180
+ arrayPush(logArray, [name, ...args]);
181
+ });
182
+ return [name, freeze(method)];
183
+ }),
184
+ );
185
+ freeze(loggingConsole);
186
+
187
+ const takeLog = () => {
188
+ const result = freeze(logArray);
189
+ logArray = [];
190
+ return result;
191
+ };
192
+ freeze(takeLog);
193
+
194
+ const typedLoggingConsole = /** @type {VirtualConsole} */ (loggingConsole);
195
+
196
+ return freeze({ loggingConsole: typedLoggingConsole, takeLog });
197
+ };
198
+ freeze(makeLoggingConsoleKit);
199
+
200
+ /**
201
+ * Makes the same calls on a `baseConsole` that were made on a
202
+ * `loggingConsole` to produce this `log`. In this way, a logging console
203
+ * can be used as a buffer to delay the application of these calls to a
204
+ * `baseConsole`.
205
+ *
206
+ * @param {LogRecord[]} log
207
+ * @param {VirtualConsole} baseConsole
208
+ */
209
+ export const pumpLogToConsole = (log, baseConsole) => {
210
+ for (const [name, ...args] of log) {
211
+ // eslint-disable-next-line @endo/no-polymorphic-call
212
+ baseConsole[name](...args);
213
+ }
214
+ };
215
+ // //////////////////////////// Causal Console /////////////////////////////////
216
+
217
+ /** @type {ErrorInfo} */
218
+ const ErrorInfo = {
219
+ NOTE: 'ERROR_NOTE:',
220
+ MESSAGE: 'ERROR_MESSAGE:',
221
+ CAUSE: 'cause:',
222
+ ERRORS: 'errors:',
223
+ };
224
+ freeze(ErrorInfo);
225
+
226
+ /** @type {MakeCausalConsole} */
227
+ export const makeCausalConsole = (baseConsole, loggedErrorHandler) => {
228
+ if (!baseConsole) {
229
+ return undefined;
230
+ }
231
+
232
+ const { getStackString, tagError, takeMessageLogArgs, takeNoteLogArgsArray } =
233
+ loggedErrorHandler;
234
+
235
+ /**
236
+ * @param {ReadonlyArray<any>} logArgs
237
+ * @param {Array<any>} subErrorsSink
238
+ * @returns {any}
239
+ */
240
+ const extractErrorArgs = (logArgs, subErrorsSink) => {
241
+ const argTags = arrayMap(logArgs, arg => {
242
+ if (isError(arg)) {
243
+ arrayPush(subErrorsSink, arg);
244
+ return `(${tagError(arg)})`;
245
+ }
246
+ return arg;
247
+ });
248
+ return argTags;
249
+ };
250
+
251
+ /**
252
+ * @param {LogSeverity} severity
253
+ * @param {Error} error
254
+ * @param {ErrorInfoKind} kind
255
+ * @param {readonly any[]} logArgs
256
+ * @param {Array<Error>} subErrorsSink
257
+ */
258
+ const logErrorInfo = (severity, error, kind, logArgs, subErrorsSink) => {
259
+ const errorTag = tagError(error);
260
+ const errorName =
261
+ kind === ErrorInfo.MESSAGE ? `${errorTag}:` : `${errorTag} ${kind}`;
262
+ const argTags = extractErrorArgs(logArgs, subErrorsSink);
263
+ // eslint-disable-next-line @endo/no-polymorphic-call
264
+ baseConsole[severity](errorName, ...argTags);
265
+ };
266
+
267
+ /**
268
+ * Logs the `subErrors` within a group name mentioning `optTag`.
269
+ *
270
+ * @param {LogSeverity} severity
271
+ * @param {Error[]} subErrors
272
+ * @param {string | undefined} optTag
273
+ * @returns {void}
274
+ */
275
+ const logSubErrors = (severity, subErrors, optTag = undefined) => {
276
+ if (subErrors.length === 0) {
277
+ return;
278
+ }
279
+ if (subErrors.length === 1 && optTag === undefined) {
280
+ // eslint-disable-next-line no-use-before-define
281
+ logError(severity, subErrors[0]);
282
+ return;
283
+ }
284
+ let label;
285
+ if (subErrors.length === 1) {
286
+ label = `Nested error`;
287
+ } else {
288
+ label = `Nested ${subErrors.length} errors`;
289
+ }
290
+ if (optTag !== undefined) {
291
+ label = `${label} under ${optTag}`;
292
+ }
293
+ // eslint-disable-next-line @endo/no-polymorphic-call
294
+ baseConsole.group(label);
295
+ try {
296
+ for (const subError of subErrors) {
297
+ // eslint-disable-next-line no-use-before-define
298
+ logError(severity, subError);
299
+ }
300
+ } finally {
301
+ if (baseConsole.groupEnd) {
302
+ // eslint-disable-next-line @endo/no-polymorphic-call
303
+ baseConsole.groupEnd();
304
+ }
305
+ }
306
+ };
307
+
308
+ const errorsLogged = new WeakSet();
309
+
310
+ /** @type {(severity: LogSeverity) => NoteCallback} */
311
+ const makeNoteCallback = severity => (error, noteLogArgs) => {
312
+ const subErrors = [];
313
+ // Annotation arrived after the error has already been logged,
314
+ // so just log the annotation immediately, rather than remembering it.
315
+ logErrorInfo(severity, error, ErrorInfo.NOTE, noteLogArgs, subErrors);
316
+ logSubErrors(severity, subErrors, tagError(error));
317
+ };
318
+
319
+ /**
320
+ * @param {LogSeverity} severity
321
+ * @param {Error} error
322
+ */
323
+ const logError = (severity, error) => {
324
+ if (weaksetHas(errorsLogged, error)) {
325
+ return;
326
+ }
327
+ const errorTag = tagError(error);
328
+ weaksetAdd(errorsLogged, error);
329
+ const subErrors = [];
330
+ const messageLogArgs = takeMessageLogArgs(error);
331
+ const noteLogArgsArray = takeNoteLogArgsArray(
332
+ error,
333
+ makeNoteCallback(severity),
334
+ );
335
+ // Show the error's most informative error message
336
+ if (messageLogArgs === undefined) {
337
+ // If there is no message log args, then just show the message that
338
+ // the error itself carries.
339
+ // eslint-disable-next-line @endo/no-polymorphic-call
340
+ baseConsole[severity](`${errorTag}:`, error.message);
341
+ } else {
342
+ // If there is one, we take it to be strictly more informative than the
343
+ // message string carried by the error, so show it *instead*.
344
+ logErrorInfo(
345
+ severity,
346
+ error,
347
+ ErrorInfo.MESSAGE,
348
+ messageLogArgs,
349
+ subErrors,
350
+ );
351
+ }
352
+ // After the message but before any other annotations, show the stack.
353
+ let stackString = getStackString(error);
354
+ if (
355
+ typeof stackString === 'string' &&
356
+ stackString.length >= 1 &&
357
+ !stringEndsWith(stackString, '\n')
358
+ ) {
359
+ stackString += '\n';
360
+ }
361
+ // eslint-disable-next-line @endo/no-polymorphic-call
362
+ baseConsole[severity](stackString);
363
+ // Show the other annotations on error
364
+ if (error.cause) {
365
+ logErrorInfo(severity, error, ErrorInfo.CAUSE, [error.cause], subErrors);
366
+ }
367
+ // @ts-expect-error AggregateError has an `errors` property.
368
+ if (error.errors) {
369
+ // @ts-expect-error AggregateError has an `errors` property.
370
+ logErrorInfo(severity, error, ErrorInfo.ERRORS, error.errors, subErrors);
371
+ }
372
+ for (const noteLogArgs of noteLogArgsArray) {
373
+ logErrorInfo(severity, error, ErrorInfo.NOTE, noteLogArgs, subErrors);
374
+ }
375
+ // explain all the errors seen in the messages already emitted.
376
+ logSubErrors(severity, subErrors, errorTag);
377
+ };
378
+
379
+ const levelMethods = arrayMap(consoleLevelMethods, ([level, _]) => {
380
+ /**
381
+ * @param {...any} logArgs
382
+ */
383
+ const levelMethod = defineName(level, (...logArgs) => {
384
+ const subErrors = [];
385
+ const argTags = extractErrorArgs(logArgs, subErrors);
386
+ if (baseConsole[level]) {
387
+ // eslint-disable-next-line @endo/no-polymorphic-call
388
+ baseConsole[level](...argTags);
389
+ }
390
+ // @ts-expect-error ConsoleProp vs LogSeverity mismatch
391
+ logSubErrors(level, subErrors);
392
+ });
393
+ return [level, freeze(levelMethod)];
394
+ });
395
+ const otherMethodNames = arrayFilter(
396
+ consoleOtherMethods,
397
+ ([name, _]) => name in baseConsole,
398
+ );
399
+ const otherMethods = arrayMap(otherMethodNames, ([name, _]) => {
400
+ /**
401
+ * @param {...any} args
402
+ */
403
+ const otherMethod = defineName(name, (...args) => {
404
+ // @ts-ignore
405
+ // eslint-disable-next-line @endo/no-polymorphic-call
406
+ baseConsole[name](...args);
407
+ return undefined;
408
+ });
409
+ return [name, freeze(otherMethod)];
410
+ });
411
+
412
+ const causalConsole = fromEntries([...levelMethods, ...otherMethods]);
413
+ return /** @type {VirtualConsole} */ (freeze(causalConsole));
414
+ };
415
+ freeze(makeCausalConsole);
416
+
417
+ /**
418
+ * @typedef {(...args: unknown[]) => void} Logger
419
+ */
420
+
421
+ /**
422
+ * This is a rather horrible kludge to indent the output to a logger in
423
+ * the case where some arguments are strings containing newlines. Part of
424
+ * the problem is that console-like loggers, including the one in ava,
425
+ * join the string arguments of the log message with a space.
426
+ * Because of this, there's an extra space at the beginning of each of
427
+ * the split lines. So this kludge compensated by putting an extra empty
428
+ * string at the beginning, so that the logger will add the same extra
429
+ * joiner.
430
+ * TODO: Fix this horrible kludge, and indent in a sane manner.
431
+ *
432
+ * @param {string} str
433
+ * @param {string} sep
434
+ * @param {string[]} indents
435
+ * @returns {string[]}
436
+ */
437
+ const indentAfterAllSeps = (str, sep, indents) => {
438
+ const [firstLine, ...restLines] = stringSplit(str, sep);
439
+ const indentedRest = arrayFlatMap(restLines, line => [sep, ...indents, line]);
440
+ return ['', firstLine, ...indentedRest];
441
+ };
442
+
443
+ /**
444
+ * @param {LoggedErrorHandler} loggedErrorHandler
445
+ */
446
+ export const defineCausalConsoleFromLogger = loggedErrorHandler => {
447
+ /**
448
+ * Implement the `VirtualConsole` API badly by turning all calls into
449
+ * calls on `tlogger`. We need to do this to have `console` logging
450
+ * turn into calls to Ava's `t.log`, so these console log messages
451
+ * are output in the right place.
452
+ *
453
+ * @param {Logger} tlogger
454
+ * @returns {VirtualConsole}
455
+ */
456
+ const makeCausalConsoleFromLogger = tlogger => {
457
+ const indents = [];
458
+ const logWithIndent = (...args) => {
459
+ if (indents.length > 0) {
460
+ args = arrayFlatMap(args, arg =>
461
+ typeof arg === 'string' && stringIncludes(arg, '\n')
462
+ ? indentAfterAllSeps(arg, '\n', indents)
463
+ : [arg],
464
+ );
465
+ args = [...indents, ...args];
466
+ }
467
+ return tlogger(...args);
468
+ };
469
+
470
+ const baseConsole = fromEntries([
471
+ ...arrayMap(consoleLevelMethods, ([name]) => [
472
+ name,
473
+ defineName(name, (...args) => logWithIndent(...args)),
474
+ ]),
475
+ ...arrayMap(consoleOtherMethods, ([name]) => [
476
+ name,
477
+ defineName(name, (...args) => logWithIndent(name, ...args)),
478
+ ]),
479
+ ]);
480
+ // https://console.spec.whatwg.org/#grouping
481
+ for (const name of ['group', 'groupCollapsed']) {
482
+ if (baseConsole[name]) {
483
+ baseConsole[name] = defineName(name, (...args) => {
484
+ if (args.length >= 1) {
485
+ // Prefix the logged data with "group" or "groupCollapsed".
486
+ logWithIndent(...args);
487
+ }
488
+ // A single space is enough;
489
+ // the host console will separate them with additional spaces.
490
+ arrayPush(indents, ' ');
491
+ });
492
+ } else {
493
+ baseConsole[name] = defineName(name, () => {});
494
+ }
495
+ }
496
+ baseConsole.groupEnd = defineName(
497
+ 'groupEnd',
498
+ baseConsole.groupEnd
499
+ ? (...args) => {
500
+ arrayPop(indents);
501
+ }
502
+ : () => {},
503
+ );
504
+ harden(baseConsole);
505
+ const causalConsole = makeCausalConsole(
506
+ /** @type {VirtualConsole} */ (baseConsole),
507
+ loggedErrorHandler,
508
+ );
509
+ return /** @type {VirtualConsole} */ (causalConsole);
510
+ };
511
+ return freeze(makeCausalConsoleFromLogger);
512
+ };
513
+ freeze(defineCausalConsoleFromLogger);
514
+
515
+ // ///////////////////////// Filter Console ////////////////////////////////////
516
+
517
+ /** @type {FilterConsole} */
518
+ export const filterConsole = (baseConsole, filter, _topic = undefined) => {
519
+ // TODO do something with optional topic string
520
+ const methodPermits = arrayFilter(
521
+ consoleMethodPermits,
522
+ ([name, _]) => name in baseConsole,
523
+ );
524
+ const methods = arrayMap(methodPermits, ([name, severity]) => {
525
+ /**
526
+ * @param {...any} args
527
+ */
528
+ const method = defineName(name, (...args) => {
529
+ // eslint-disable-next-line @endo/no-polymorphic-call
530
+ if (severity === undefined || filter.canLog(severity)) {
531
+ // @ts-ignore
532
+ // eslint-disable-next-line @endo/no-polymorphic-call
533
+ baseConsole[name](...args);
534
+ }
535
+ });
536
+ return [name, freeze(method)];
537
+ });
538
+ const filteringConsole = fromEntries(methods);
539
+ return /** @type {VirtualConsole} */ (freeze(filteringConsole));
540
+ };
541
+ freeze(filterConsole);
@@ -0,0 +1,54 @@
1
+ // @ts-check
2
+ /* global process */
3
+
4
+ import { freeze } from '../commons.js';
5
+ import { makeAssert } from './assert.js';
6
+ import './types.js';
7
+
8
+ /** @import {Assert} from '../../types.js' */
9
+
10
+ let abandon;
11
+ // Sniff for host-provided functions for terminating the enclosing UOPT (see
12
+ // below). Currently it only checks for the `process.abort` or `process.exit`
13
+ // found on Node. It should also sniff for a vat terminating function expected
14
+ // to be found within the start compartment of SwingSet vats. What else?
15
+ if (typeof process === 'object' && process) {
16
+ abandon = process.abort || process.exit;
17
+ }
18
+ let raise;
19
+ if (typeof abandon === 'function') {
20
+ /** @param {Error} reason */
21
+ raise = reason => {
22
+ // Check `console` each time `raise` is called.
23
+ // eslint-disable-next-line no-restricted-globals
24
+ if (typeof console === 'object' && typeof console.error === 'function') {
25
+ // eslint-disable-next-line @endo/no-polymorphic-call, no-restricted-globals
26
+ console.error('Failed because:', reason);
27
+ }
28
+ abandon(1);
29
+ };
30
+ }
31
+
32
+ /**
33
+ * @type {Partial<{assert: Assert}>}
34
+ *
35
+ * When run in the start compartment, this sniffs to see if there are known
36
+ * forms of host-provided functions for immediately terminating the enclosing
37
+ * Unit of Preemptive Termination. If so, we initialize the exported
38
+ * `fatal` object with its own `assert`, which is like the global `assert`.
39
+ * But rather than throwing the error as global `assert` does,
40
+ * `fatal.assert` logs the error to the current `console`, if any, and terminates
41
+ * this unit of computation.
42
+ *
43
+ * See https://github.com/tc39/proposal-oom-fails-fast for the meaning of a
44
+ * "Unit of Preemptive Termination" (UOPT). This is a unit of
45
+ * computation---like the vat, worker, or process---containing the potentially
46
+ * corrupted state. We preemptively terminate it in order to abandon that
47
+ * corrupted state.
48
+ */
49
+ const fatal = {};
50
+ if (raise) {
51
+ fatal.assert = makeAssert(raise);
52
+ }
53
+ freeze(fatal);
54
+ export { fatal };
@@ -0,0 +1,98 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @import {VirtualConsole} from './types.js'
5
+ */
6
+
7
+ /**
8
+ * @typedef {readonly any[]} LogArgs
9
+ *
10
+ * This is an array suitable to be used as arguments of a console
11
+ * level message *after* the format string argument. It is the result of
12
+ * a `details` template string and consists of alternating literal strings
13
+ * and substitution values, starting with a literal string. At least that
14
+ * first literal string is always present.
15
+ */
16
+
17
+ /**
18
+ * @callback NoteCallback
19
+ *
20
+ * @param {Error} error
21
+ * @param {LogArgs} noteLogArgs
22
+ * @returns {void}
23
+ */
24
+
25
+ /**
26
+ * @callback GetStackString
27
+ * @param {Error} error
28
+ * @returns {string=}
29
+ */
30
+
31
+ /**
32
+ * @typedef {object} LoggedErrorHandler
33
+ *
34
+ * Used to parameterize `makeCausalConsole` to give it access to potentially
35
+ * hidden information to augment the logging of errors.
36
+ *
37
+ * @property {GetStackString} getStackString
38
+ * @property {(error: Error) => string} tagError
39
+ * @property {() => void} resetErrorTagNum for debugging purposes only
40
+ * @property {(error: Error) => (LogArgs | undefined)} getMessageLogArgs
41
+ * @property {(error: Error) => (LogArgs | undefined)} takeMessageLogArgs
42
+ * @property {(error: Error, callback?: NoteCallback) => LogArgs[] } takeNoteLogArgsArray
43
+ */
44
+
45
+ // /////////////////////////////////////////////////////////////////////////////
46
+
47
+ /**
48
+ * @typedef {readonly [string, ...any[]]} LogRecord
49
+ */
50
+
51
+ /**
52
+ * @typedef {object} LoggingConsoleKit
53
+ * @property {VirtualConsole} loggingConsole
54
+ * @property {() => readonly LogRecord[]} takeLog
55
+ */
56
+
57
+ /**
58
+ * @typedef {object} MakeLoggingConsoleKitOptions
59
+ * @property {boolean=} shouldResetForDebugging
60
+ */
61
+
62
+ /**
63
+ * @callback MakeLoggingConsoleKit
64
+ *
65
+ * A logging console just accumulates the contents of all permitted calls,
66
+ * making them available to callers of `takeLog()`. Calling `takeLog()`
67
+ * consumes these, so later calls to `takeLog()` will only provide a log of
68
+ * calls that have happened since then.
69
+ *
70
+ * @param {LoggedErrorHandler} loggedErrorHandler
71
+ * @param {MakeLoggingConsoleKitOptions=} options
72
+ * @returns {LoggingConsoleKit}
73
+ */
74
+
75
+ /**
76
+ * @typedef {{
77
+ * NOTE: 'ERROR_NOTE:',
78
+ * MESSAGE: 'ERROR_MESSAGE:',
79
+ * CAUSE: 'cause:',
80
+ * ERRORS: 'errors:',
81
+ * }} ErrorInfo
82
+ */
83
+
84
+ /**
85
+ * @typedef {ErrorInfo[keyof ErrorInfo]} ErrorInfoKind
86
+ */
87
+
88
+ /**
89
+ * @callback MakeCausalConsole
90
+ *
91
+ * Makes a causal console wrapper of a `baseConsole`, where the causal console
92
+ * calls methods of the `loggedErrorHandler` to customize how it handles logged
93
+ * errors.
94
+ *
95
+ * @param {VirtualConsole | undefined} baseConsole
96
+ * @param {LoggedErrorHandler} loggedErrorHandler
97
+ * @returns {VirtualConsole | undefined}
98
+ */