@nocobase/plugin-flow-engine 2.0.0-alpha.10
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 +25 -0
- package/dist/server/plugin.js +191 -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 +52 -0
- package/dist/server/variables/registry.js +333 -0
- package/dist/server/variables/utils.d.ts +17 -0
- package/dist/server/variables/utils.js +113 -0
- package/package.json +28 -0
- package/server.d.ts +2 -0
- package/server.js +1 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
// Copyright (C) 2019 Agoric, under Apache License 2.0
|
|
2
|
+
// @ts-check
|
|
3
|
+
|
|
4
|
+
// To ensure that this module operates without special privilege, it should
|
|
5
|
+
// not reference the free variable `console` except for its own internal
|
|
6
|
+
// debugging purposes in the declaration of `internalDebugConsole`, which is
|
|
7
|
+
// normally commented out.
|
|
8
|
+
|
|
9
|
+
// This module however has top level mutable state which is observable to code
|
|
10
|
+
// given access to the `loggedErrorHandler`, such as the causal console
|
|
11
|
+
// of `console.js`. However, for code that does not have such access, this
|
|
12
|
+
// module should not be observably impure.
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
RangeError,
|
|
16
|
+
TypeError,
|
|
17
|
+
WeakMap,
|
|
18
|
+
arrayJoin,
|
|
19
|
+
arrayMap,
|
|
20
|
+
arrayPop,
|
|
21
|
+
arrayPush,
|
|
22
|
+
assign,
|
|
23
|
+
freeze,
|
|
24
|
+
defineProperty,
|
|
25
|
+
globalThis,
|
|
26
|
+
is,
|
|
27
|
+
isError,
|
|
28
|
+
regexpTest,
|
|
29
|
+
stringIndexOf,
|
|
30
|
+
stringReplace,
|
|
31
|
+
stringSlice,
|
|
32
|
+
stringStartsWith,
|
|
33
|
+
weakmapDelete,
|
|
34
|
+
weakmapGet,
|
|
35
|
+
weakmapHas,
|
|
36
|
+
weakmapSet,
|
|
37
|
+
AggregateError,
|
|
38
|
+
getOwnPropertyDescriptors,
|
|
39
|
+
ownKeys,
|
|
40
|
+
create,
|
|
41
|
+
objectPrototype,
|
|
42
|
+
hasOwn,
|
|
43
|
+
} from '../commons.js';
|
|
44
|
+
import { an, bestEffortStringify } from './stringify-utils.js';
|
|
45
|
+
import './types.js';
|
|
46
|
+
import './internal-types.js';
|
|
47
|
+
import { makeNoteLogArgsArrayKit } from './note-log-args.js';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @import {BaseAssert, Assert, AssertionFunctions, AssertionUtilities, StringablePayload, DetailsToken, MakeAssert} from '../../types.js'
|
|
51
|
+
* @import {LogArgs, NoteCallback, LoggedErrorHandler} from "./internal-types.js";
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
// For our internal debugging purposes, uncomment
|
|
55
|
+
// const internalDebugConsole = console;
|
|
56
|
+
|
|
57
|
+
// /////////////////////////////////////////////////////////////////////////////
|
|
58
|
+
|
|
59
|
+
/** @type {WeakMap<StringablePayload, any>} */
|
|
60
|
+
const declassifiers = new WeakMap();
|
|
61
|
+
|
|
62
|
+
/** @type {AssertionUtilities['quote']} */
|
|
63
|
+
const quote = (payload, spaces = undefined) => {
|
|
64
|
+
const result = freeze({
|
|
65
|
+
toString: freeze(() => bestEffortStringify(payload, spaces)),
|
|
66
|
+
});
|
|
67
|
+
weakmapSet(declassifiers, result, payload);
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
freeze(quote);
|
|
71
|
+
|
|
72
|
+
const canBeBare = freeze(/^[\w:-]( ?[\w:-])*$/);
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @type {AssertionUtilities['bare']}
|
|
76
|
+
*/
|
|
77
|
+
const bare = (payload, spaces = undefined) => {
|
|
78
|
+
if (typeof payload !== 'string' || !regexpTest(canBeBare, payload)) {
|
|
79
|
+
return quote(payload, spaces);
|
|
80
|
+
}
|
|
81
|
+
const result = freeze({
|
|
82
|
+
toString: freeze(() => payload),
|
|
83
|
+
});
|
|
84
|
+
weakmapSet(declassifiers, result, payload);
|
|
85
|
+
return result;
|
|
86
|
+
};
|
|
87
|
+
freeze(bare);
|
|
88
|
+
|
|
89
|
+
// /////////////////////////////////////////////////////////////////////////////
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @typedef {object} HiddenDetails
|
|
93
|
+
*
|
|
94
|
+
* Captures the arguments passed to the `details` template string tag.
|
|
95
|
+
*
|
|
96
|
+
* @property {TemplateStringsArray | string[]} template
|
|
97
|
+
* @property {any[]} args
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @type {WeakMap<DetailsToken, HiddenDetails>}
|
|
102
|
+
*
|
|
103
|
+
* Maps from a details token which a `details` template literal returned
|
|
104
|
+
* to a record of the contents of that template literal expression.
|
|
105
|
+
*/
|
|
106
|
+
const hiddenDetailsMap = new WeakMap();
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param {HiddenDetails} hiddenDetails
|
|
110
|
+
* @returns {string}
|
|
111
|
+
*/
|
|
112
|
+
const getMessageString = ({ template, args }) => {
|
|
113
|
+
const parts = [template[0]];
|
|
114
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
115
|
+
const arg = args[i];
|
|
116
|
+
let argStr;
|
|
117
|
+
if (weakmapHas(declassifiers, arg)) {
|
|
118
|
+
argStr = `${arg}`;
|
|
119
|
+
} else if (isError(arg)) {
|
|
120
|
+
argStr = `(${an(arg.name)})`;
|
|
121
|
+
} else {
|
|
122
|
+
argStr = `(${an(typeof arg)})`;
|
|
123
|
+
}
|
|
124
|
+
arrayPush(parts, argStr, template[i + 1]);
|
|
125
|
+
}
|
|
126
|
+
return arrayJoin(parts, '');
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Give detailsTokens a toString behavior. To minimize the overhead of
|
|
131
|
+
* creating new detailsTokens, we do this with an
|
|
132
|
+
* inherited `this` sensitive `toString` method, even though we normally
|
|
133
|
+
* avoid `this` sensitivity. To protect the method from inappropriate
|
|
134
|
+
* `this` application, it does something interesting only for objects
|
|
135
|
+
* registered in `redactedDetails`, which should be exactly the detailsTokens.
|
|
136
|
+
*
|
|
137
|
+
* The printing behavior must not reveal anything redacted, so we just use
|
|
138
|
+
* the same `getMessageString` we use to construct the redacted message
|
|
139
|
+
* string for a thrown assertion error.
|
|
140
|
+
*/
|
|
141
|
+
const DetailsTokenProto = freeze({
|
|
142
|
+
toString() {
|
|
143
|
+
const hiddenDetails = weakmapGet(hiddenDetailsMap, this);
|
|
144
|
+
if (hiddenDetails === undefined) {
|
|
145
|
+
return '[Not a DetailsToken]';
|
|
146
|
+
}
|
|
147
|
+
return getMessageString(hiddenDetails);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
freeze(DetailsTokenProto.toString);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Normally this is the function exported as `assert.details` and often
|
|
154
|
+
* spelled `X`. However, if the `{errorTaming: 'unsafe'}` or
|
|
155
|
+
* `{errorTaming: 'unsafe-debug'}` option is
|
|
156
|
+
* given to `lockdown`, then `unredactedDetails` is used instead.
|
|
157
|
+
*
|
|
158
|
+
* There are some unconditional uses of `redactedDetails` in this module. All
|
|
159
|
+
* of them should be uses where the template literal has no redacted
|
|
160
|
+
* substitution values. In those cases, the two are equivalent.
|
|
161
|
+
*
|
|
162
|
+
* @type {AssertionUtilities['details']}
|
|
163
|
+
*/
|
|
164
|
+
const redactedDetails = (template, ...args) => {
|
|
165
|
+
// Keep in mind that the vast majority of calls to `details` creates
|
|
166
|
+
// a details token that is never used, so this path must remain as fast as
|
|
167
|
+
// possible. Hence we store what we've got with little processing, postponing
|
|
168
|
+
// all the work to happen only if needed, for example, if an assertion fails.
|
|
169
|
+
const detailsToken = freeze({ __proto__: DetailsTokenProto });
|
|
170
|
+
weakmapSet(hiddenDetailsMap, detailsToken, { template, args });
|
|
171
|
+
return /** @type {DetailsToken} */ (/** @type {unknown} */ (detailsToken));
|
|
172
|
+
};
|
|
173
|
+
freeze(redactedDetails);
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* `unredactedDetails` is like `details` except that it does not redact
|
|
177
|
+
* anything. It acts like `details` would act if all substitution values
|
|
178
|
+
* were wrapped with the `quote` function above (the function normally
|
|
179
|
+
* spelled `q`). If the `{errorTaming: 'unsafe'}`
|
|
180
|
+
* or `{errorTaming: 'unsafe-debug'}` option is given to
|
|
181
|
+
* `lockdown`, then the lockdown-shim arranges for the global `assert` to be
|
|
182
|
+
* one whose `details` property is `unredactedDetails`.
|
|
183
|
+
* This setting optimizes the debugging and testing experience at the price
|
|
184
|
+
* of safety. `unredactedDetails` also sacrifices the speed of `details`,
|
|
185
|
+
* which is usually fine in debugging and testing.
|
|
186
|
+
*
|
|
187
|
+
* @type {AssertionUtilities['details']}
|
|
188
|
+
*/
|
|
189
|
+
const unredactedDetails = (template, ...args) => {
|
|
190
|
+
args = arrayMap(args, arg =>
|
|
191
|
+
weakmapHas(declassifiers, arg) ? arg : quote(arg),
|
|
192
|
+
);
|
|
193
|
+
return redactedDetails(template, ...args);
|
|
194
|
+
};
|
|
195
|
+
freeze(unredactedDetails);
|
|
196
|
+
export { unredactedDetails };
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @param {HiddenDetails} hiddenDetails
|
|
200
|
+
* @returns {LogArgs}
|
|
201
|
+
*/
|
|
202
|
+
const getLogArgs = ({ template, args }) => {
|
|
203
|
+
const logArgs = [template[0]];
|
|
204
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
205
|
+
let arg = args[i];
|
|
206
|
+
if (weakmapHas(declassifiers, arg)) {
|
|
207
|
+
arg = weakmapGet(declassifiers, arg);
|
|
208
|
+
}
|
|
209
|
+
// Remove the extra spaces (since console.error puts them
|
|
210
|
+
// between each cause).
|
|
211
|
+
const priorWithoutSpace = stringReplace(arrayPop(logArgs) || '', / $/, '');
|
|
212
|
+
if (priorWithoutSpace !== '') {
|
|
213
|
+
arrayPush(logArgs, priorWithoutSpace);
|
|
214
|
+
}
|
|
215
|
+
const nextWithoutSpace = stringReplace(template[i + 1], /^ /, '');
|
|
216
|
+
arrayPush(logArgs, arg, nextWithoutSpace);
|
|
217
|
+
}
|
|
218
|
+
if (logArgs[logArgs.length - 1] === '') {
|
|
219
|
+
arrayPop(logArgs);
|
|
220
|
+
}
|
|
221
|
+
return logArgs;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @type {WeakMap<Error, LogArgs>}
|
|
226
|
+
*
|
|
227
|
+
* Maps from an error object to the log args that are a more informative
|
|
228
|
+
* alternative message for that error. When logging the error, these
|
|
229
|
+
* log args should be preferred to `error.message`.
|
|
230
|
+
*/
|
|
231
|
+
const hiddenMessageLogArgs = new WeakMap();
|
|
232
|
+
|
|
233
|
+
// So each error tag will be unique.
|
|
234
|
+
let errorTagNum = 0;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @type {WeakMap<Error, string>}
|
|
238
|
+
*/
|
|
239
|
+
const errorTags = new WeakMap();
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @param {Error} err
|
|
243
|
+
* @param {string=} optErrorName
|
|
244
|
+
* @returns {string}
|
|
245
|
+
*/
|
|
246
|
+
const tagError = (err, optErrorName = err.name) => {
|
|
247
|
+
let errorTag = weakmapGet(errorTags, err);
|
|
248
|
+
if (errorTag !== undefined) {
|
|
249
|
+
return errorTag;
|
|
250
|
+
}
|
|
251
|
+
errorTagNum += 1;
|
|
252
|
+
errorTag = `${optErrorName}#${errorTagNum}`;
|
|
253
|
+
weakmapSet(errorTags, err, errorTag);
|
|
254
|
+
return errorTag;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Make reasonable best efforts to make a `Passable` error.
|
|
259
|
+
* - `sanitizeError` will remove any "extraneous" own properties already added
|
|
260
|
+
* by the host,
|
|
261
|
+
* such as `fileName`,`lineNumber` on FireFox or `line` on Safari.
|
|
262
|
+
* - If any such "extraneous" properties were removed, `sanitizeError` will
|
|
263
|
+
* annotate
|
|
264
|
+
* the error with them, so they still appear on the causal console
|
|
265
|
+
* log output for diagnostic purposes, but not be otherwise visible.
|
|
266
|
+
* - `sanitizeError` will ensure that any expected properties already
|
|
267
|
+
* added by the host are data
|
|
268
|
+
* properties, converting accessor properties to data properties as needed,
|
|
269
|
+
* such as `stack` on v8 (Chrome, Brave, Edge?)
|
|
270
|
+
* - `sanitizeError` will freeze the error, preventing any correct engine from
|
|
271
|
+
* adding or
|
|
272
|
+
* altering any of the error's own properties `sanitizeError` is done.
|
|
273
|
+
*
|
|
274
|
+
* However, `sanitizeError` will not, for example, `harden`
|
|
275
|
+
* (i.e., deeply freeze)
|
|
276
|
+
* or ensure that the `cause` or `errors` property satisfy the `Passable`
|
|
277
|
+
* constraints. The purpose of `sanitizeError` is only to protect against
|
|
278
|
+
* mischief the host may have already added to the error as created,
|
|
279
|
+
* not to ensure that the error is actually Passable. For that,
|
|
280
|
+
* see `toPassableError` in `@endo/pass-style`.
|
|
281
|
+
*
|
|
282
|
+
* @param {Error} error
|
|
283
|
+
*/
|
|
284
|
+
export const sanitizeError = error => {
|
|
285
|
+
const descs = getOwnPropertyDescriptors(error);
|
|
286
|
+
const {
|
|
287
|
+
name: _nameDesc,
|
|
288
|
+
message: _messageDesc,
|
|
289
|
+
errors: _errorsDesc = undefined,
|
|
290
|
+
cause: _causeDesc = undefined,
|
|
291
|
+
stack: _stackDesc = undefined,
|
|
292
|
+
...restDescs
|
|
293
|
+
} = descs;
|
|
294
|
+
|
|
295
|
+
const restNames = ownKeys(restDescs);
|
|
296
|
+
if (restNames.length >= 1) {
|
|
297
|
+
for (const name of restNames) {
|
|
298
|
+
delete error[name];
|
|
299
|
+
}
|
|
300
|
+
const droppedNote = create(objectPrototype, restDescs);
|
|
301
|
+
// eslint-disable-next-line no-use-before-define
|
|
302
|
+
note(
|
|
303
|
+
error,
|
|
304
|
+
redactedDetails`originally with properties ${quote(droppedNote)}`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
for (const name of ownKeys(error)) {
|
|
308
|
+
// @ts-expect-error TS still confused by symbols as property names
|
|
309
|
+
const desc = descs[name];
|
|
310
|
+
if (desc && hasOwn(desc, 'get')) {
|
|
311
|
+
defineProperty(error, name, {
|
|
312
|
+
value: error[name], // invoke the getter to convert to data property
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
freeze(error);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* @type {AssertionUtilities['error']}
|
|
321
|
+
*/
|
|
322
|
+
const makeError = (
|
|
323
|
+
optDetails = redactedDetails`Assert failed`,
|
|
324
|
+
errConstructor = globalThis.Error,
|
|
325
|
+
{
|
|
326
|
+
errorName = undefined,
|
|
327
|
+
cause = undefined,
|
|
328
|
+
errors = undefined,
|
|
329
|
+
sanitize = true,
|
|
330
|
+
} = {},
|
|
331
|
+
) => {
|
|
332
|
+
if (typeof optDetails === 'string') {
|
|
333
|
+
// If it is a string, use it as the literal part of the template so
|
|
334
|
+
// it doesn't get quoted.
|
|
335
|
+
optDetails = redactedDetails([optDetails]);
|
|
336
|
+
}
|
|
337
|
+
const hiddenDetails = weakmapGet(hiddenDetailsMap, optDetails);
|
|
338
|
+
if (hiddenDetails === undefined) {
|
|
339
|
+
throw TypeError(`unrecognized details ${quote(optDetails)}`);
|
|
340
|
+
}
|
|
341
|
+
const messageString = getMessageString(hiddenDetails);
|
|
342
|
+
const opts = cause && { cause };
|
|
343
|
+
let error;
|
|
344
|
+
if (
|
|
345
|
+
typeof AggregateError !== 'undefined' &&
|
|
346
|
+
errConstructor === AggregateError
|
|
347
|
+
) {
|
|
348
|
+
error = AggregateError(errors || [], messageString, opts);
|
|
349
|
+
} else {
|
|
350
|
+
error = /** @type {ErrorConstructor} */ (errConstructor)(
|
|
351
|
+
messageString,
|
|
352
|
+
opts,
|
|
353
|
+
);
|
|
354
|
+
if (errors !== undefined) {
|
|
355
|
+
// Since we need to tolerate `errors` on an AggregateError, may as
|
|
356
|
+
// well tolerate it on all errors.
|
|
357
|
+
defineProperty(error, 'errors', {
|
|
358
|
+
value: errors,
|
|
359
|
+
writable: true,
|
|
360
|
+
enumerable: false,
|
|
361
|
+
configurable: true,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
weakmapSet(hiddenMessageLogArgs, error, getLogArgs(hiddenDetails));
|
|
366
|
+
if (errorName !== undefined) {
|
|
367
|
+
tagError(error, errorName);
|
|
368
|
+
}
|
|
369
|
+
if (sanitize) {
|
|
370
|
+
sanitizeError(error);
|
|
371
|
+
}
|
|
372
|
+
// The next line is a particularly fruitful place to put a breakpoint.
|
|
373
|
+
return error;
|
|
374
|
+
};
|
|
375
|
+
freeze(makeError);
|
|
376
|
+
|
|
377
|
+
// /////////////////////////////////////////////////////////////////////////////
|
|
378
|
+
|
|
379
|
+
const { addLogArgs, takeLogArgsArray } = makeNoteLogArgsArrayKit();
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @type {WeakMap<Error, NoteCallback[]>}
|
|
383
|
+
*
|
|
384
|
+
* An augmented console will normally only take the hidden noteArgs array once,
|
|
385
|
+
* when it logs the error being annotated. Once that happens, further
|
|
386
|
+
* annotations of that error should go to the console immediately. We arrange
|
|
387
|
+
* that by accepting a note-callback function from the console as an optional
|
|
388
|
+
* part of that taking operation. Normally there will only be at most one
|
|
389
|
+
* callback per error, but that depends on console behavior which we should not
|
|
390
|
+
* assume. We make this an array of callbacks so multiple registrations
|
|
391
|
+
* are independent.
|
|
392
|
+
*/
|
|
393
|
+
const hiddenNoteCallbackArrays = new WeakMap();
|
|
394
|
+
|
|
395
|
+
/** @type {AssertionUtilities['note']} */
|
|
396
|
+
const note = (error, detailsNote) => {
|
|
397
|
+
if (typeof detailsNote === 'string') {
|
|
398
|
+
// If it is a string, use it as the literal part of the template so
|
|
399
|
+
// it doesn't get quoted.
|
|
400
|
+
detailsNote = redactedDetails([detailsNote]);
|
|
401
|
+
}
|
|
402
|
+
const hiddenDetails = weakmapGet(hiddenDetailsMap, detailsNote);
|
|
403
|
+
if (hiddenDetails === undefined) {
|
|
404
|
+
throw TypeError(`unrecognized details ${quote(detailsNote)}`);
|
|
405
|
+
}
|
|
406
|
+
const logArgs = getLogArgs(hiddenDetails);
|
|
407
|
+
const callbacks = weakmapGet(hiddenNoteCallbackArrays, error);
|
|
408
|
+
if (callbacks !== undefined) {
|
|
409
|
+
for (const callback of callbacks) {
|
|
410
|
+
callback(error, logArgs);
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
addLogArgs(error, logArgs);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
freeze(note);
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* The unprivileged form that just uses the de facto `error.stack` property.
|
|
420
|
+
* The start compartment normally has a privileged `globalThis.getStackString`
|
|
421
|
+
* which should be preferred if present.
|
|
422
|
+
*
|
|
423
|
+
* @param {Error} error
|
|
424
|
+
* @returns {string}
|
|
425
|
+
*/
|
|
426
|
+
const defaultGetStackString = error => {
|
|
427
|
+
if (!('stack' in error)) {
|
|
428
|
+
return '';
|
|
429
|
+
}
|
|
430
|
+
const stackString = `${error.stack}`;
|
|
431
|
+
const pos = stringIndexOf(stackString, '\n');
|
|
432
|
+
if (stringStartsWith(stackString, ' ') || pos === -1) {
|
|
433
|
+
return stackString;
|
|
434
|
+
}
|
|
435
|
+
return stringSlice(stackString, pos + 1); // exclude the initial newline
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
/** @type {LoggedErrorHandler} */
|
|
439
|
+
const loggedErrorHandler = {
|
|
440
|
+
getStackString: globalThis.getStackString || defaultGetStackString,
|
|
441
|
+
tagError: error => tagError(error),
|
|
442
|
+
resetErrorTagNum: () => {
|
|
443
|
+
errorTagNum = 0;
|
|
444
|
+
},
|
|
445
|
+
getMessageLogArgs: error => weakmapGet(hiddenMessageLogArgs, error),
|
|
446
|
+
takeMessageLogArgs: error => {
|
|
447
|
+
const result = weakmapGet(hiddenMessageLogArgs, error);
|
|
448
|
+
weakmapDelete(hiddenMessageLogArgs, error);
|
|
449
|
+
return result;
|
|
450
|
+
},
|
|
451
|
+
takeNoteLogArgsArray: (error, callback) => {
|
|
452
|
+
const result = takeLogArgsArray(error);
|
|
453
|
+
if (callback !== undefined) {
|
|
454
|
+
const callbacks = weakmapGet(hiddenNoteCallbackArrays, error);
|
|
455
|
+
if (callbacks) {
|
|
456
|
+
arrayPush(callbacks, callback);
|
|
457
|
+
} else {
|
|
458
|
+
weakmapSet(hiddenNoteCallbackArrays, error, [callback]);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return result || [];
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
freeze(loggedErrorHandler);
|
|
465
|
+
export { loggedErrorHandler };
|
|
466
|
+
|
|
467
|
+
// /////////////////////////////////////////////////////////////////////////////
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* @type {MakeAssert}
|
|
471
|
+
*/
|
|
472
|
+
const makeAssert = (optRaise = undefined, unredacted = false) => {
|
|
473
|
+
const details = unredacted ? unredactedDetails : redactedDetails;
|
|
474
|
+
const assertFailedDetails = details`Check failed`;
|
|
475
|
+
|
|
476
|
+
/** @type {AssertionFunctions['fail']} */
|
|
477
|
+
const fail = (
|
|
478
|
+
optDetails = assertFailedDetails,
|
|
479
|
+
errConstructor = undefined,
|
|
480
|
+
options = undefined,
|
|
481
|
+
) => {
|
|
482
|
+
const reason = makeError(optDetails, errConstructor, options);
|
|
483
|
+
if (optRaise !== undefined) {
|
|
484
|
+
// @ts-ignore returns `never` doesn't mean it isn't callable
|
|
485
|
+
optRaise(reason);
|
|
486
|
+
}
|
|
487
|
+
throw reason;
|
|
488
|
+
};
|
|
489
|
+
freeze(fail);
|
|
490
|
+
|
|
491
|
+
/** @type {AssertionUtilities['Fail']} */
|
|
492
|
+
const Fail = (template, ...args) => fail(details(template, ...args));
|
|
493
|
+
|
|
494
|
+
// Don't freeze or export `baseAssert` until we add methods.
|
|
495
|
+
// TODO If I change this from a `function` function to an arrow
|
|
496
|
+
// function, I seem to get type errors from TypeScript. Why?
|
|
497
|
+
/** @type {BaseAssert} */
|
|
498
|
+
function baseAssert(
|
|
499
|
+
flag,
|
|
500
|
+
optDetails = undefined,
|
|
501
|
+
errConstructor = undefined,
|
|
502
|
+
options = undefined,
|
|
503
|
+
) {
|
|
504
|
+
flag || fail(optDetails, errConstructor, options);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** @type {AssertionFunctions['equal']} */
|
|
508
|
+
const equal = (
|
|
509
|
+
actual,
|
|
510
|
+
expected,
|
|
511
|
+
optDetails = undefined,
|
|
512
|
+
errConstructor = undefined,
|
|
513
|
+
options = undefined,
|
|
514
|
+
) => {
|
|
515
|
+
is(actual, expected) ||
|
|
516
|
+
fail(
|
|
517
|
+
optDetails || details`Expected ${actual} is same as ${expected}`,
|
|
518
|
+
errConstructor || RangeError,
|
|
519
|
+
options,
|
|
520
|
+
);
|
|
521
|
+
};
|
|
522
|
+
freeze(equal);
|
|
523
|
+
|
|
524
|
+
/** @type {AssertionFunctions['typeof']} */
|
|
525
|
+
const assertTypeof = (specimen, typename, optDetails) => {
|
|
526
|
+
// This will safely fall through if typename is not a string,
|
|
527
|
+
// which is what we want.
|
|
528
|
+
// eslint-disable-next-line valid-typeof
|
|
529
|
+
if (typeof specimen === typename) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
typeof typename === 'string' || Fail`${quote(typename)} must be a string`;
|
|
533
|
+
|
|
534
|
+
if (optDetails === undefined) {
|
|
535
|
+
// Embed the type phrase without quotes.
|
|
536
|
+
const typeWithDeterminer = an(typename);
|
|
537
|
+
optDetails = details`${specimen} must be ${bare(typeWithDeterminer)}`;
|
|
538
|
+
}
|
|
539
|
+
fail(optDetails, TypeError);
|
|
540
|
+
};
|
|
541
|
+
freeze(assertTypeof);
|
|
542
|
+
|
|
543
|
+
/** @type {AssertionFunctions['string']} */
|
|
544
|
+
const assertString = (specimen, optDetails = undefined) =>
|
|
545
|
+
assertTypeof(specimen, 'string', optDetails);
|
|
546
|
+
|
|
547
|
+
// Note that "assert === baseAssert"
|
|
548
|
+
/** @type {Assert} */
|
|
549
|
+
const assert = assign(baseAssert, {
|
|
550
|
+
error: makeError,
|
|
551
|
+
fail,
|
|
552
|
+
equal,
|
|
553
|
+
typeof: assertTypeof,
|
|
554
|
+
string: assertString,
|
|
555
|
+
note,
|
|
556
|
+
details,
|
|
557
|
+
Fail,
|
|
558
|
+
quote,
|
|
559
|
+
bare,
|
|
560
|
+
makeAssert,
|
|
561
|
+
});
|
|
562
|
+
return freeze(assert);
|
|
563
|
+
};
|
|
564
|
+
freeze(makeAssert);
|
|
565
|
+
export { makeAssert };
|
|
566
|
+
|
|
567
|
+
/** @type {Assert} */
|
|
568
|
+
const assert = makeAssert();
|
|
569
|
+
export { assert };
|
|
570
|
+
|
|
571
|
+
// Internal, to obviate polymorphic dispatch, but may become rigorously
|
|
572
|
+
// consistent with @endo/error:
|
|
573
|
+
|
|
574
|
+
/** @type {AssertionFunctions['equal']} */
|
|
575
|
+
const assertEqual = assert.equal;
|
|
576
|
+
|
|
577
|
+
export {
|
|
578
|
+
assertEqual,
|
|
579
|
+
makeError,
|
|
580
|
+
note as annotateError,
|
|
581
|
+
redactedDetails as X,
|
|
582
|
+
quote as q,
|
|
583
|
+
bare as b,
|
|
584
|
+
};
|