@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,284 @@
1
+ import {
2
+ FERAL_ERROR,
3
+ apply,
4
+ construct,
5
+ defineProperties,
6
+ setPrototypeOf,
7
+ getOwnPropertyDescriptor,
8
+ defineProperty,
9
+ getOwnPropertyDescriptors,
10
+ } from '../commons.js';
11
+ import { NativeErrors } from '../permits.js';
12
+ import { tameV8ErrorConstructor } from './tame-v8-error-constructor.js';
13
+
14
+ // Present on at least FF and XS. Proposed by Error-proposal. The original
15
+ // is dangerous, so tameErrorConstructor replaces it with a safe one.
16
+ // We grab the original here before it gets replaced.
17
+ const stackDesc = getOwnPropertyDescriptor(FERAL_ERROR.prototype, 'stack');
18
+ const stackGetter = stackDesc && stackDesc.get;
19
+
20
+ // Use concise methods to obtain named functions without constructors.
21
+ const tamedMethods = {
22
+ getStackString(error) {
23
+ if (typeof stackGetter === 'function') {
24
+ return apply(stackGetter, error, []);
25
+ } else if ('stack' in error) {
26
+ // The fallback is to just use the de facto `error.stack` if present
27
+ return `${error.stack}`;
28
+ }
29
+ return '';
30
+ },
31
+ };
32
+ let initialGetStackString = tamedMethods.getStackString;
33
+
34
+ export default function tameErrorConstructor(
35
+ errorTaming = 'safe',
36
+ stackFiltering = 'concise',
37
+ ) {
38
+ const ErrorPrototype = FERAL_ERROR.prototype;
39
+
40
+ const { captureStackTrace: originalCaptureStackTrace } = FERAL_ERROR;
41
+ const platform =
42
+ typeof originalCaptureStackTrace === 'function' ? 'v8' : 'unknown';
43
+
44
+ const makeErrorConstructor = (_ = {}) => {
45
+ // eslint-disable-next-line no-shadow
46
+ const ResultError = function Error(...rest) {
47
+ let error;
48
+ if (new.target === undefined) {
49
+ error = apply(FERAL_ERROR, this, rest);
50
+ } else {
51
+ error = construct(FERAL_ERROR, rest, new.target);
52
+ }
53
+ if (platform === 'v8') {
54
+ // TODO Likely expensive!
55
+ apply(originalCaptureStackTrace, FERAL_ERROR, [error, ResultError]);
56
+ }
57
+ return error;
58
+ };
59
+ defineProperties(ResultError, {
60
+ length: { value: 1 },
61
+ prototype: {
62
+ value: ErrorPrototype,
63
+ writable: false,
64
+ enumerable: false,
65
+ configurable: false,
66
+ },
67
+ });
68
+ return ResultError;
69
+ };
70
+ const InitialError = makeErrorConstructor({ powers: 'original' });
71
+ const SharedError = makeErrorConstructor({ powers: 'none' });
72
+ defineProperties(ErrorPrototype, {
73
+ constructor: { value: SharedError },
74
+ });
75
+
76
+ for (const NativeError of NativeErrors) {
77
+ setPrototypeOf(NativeError, SharedError);
78
+ }
79
+
80
+ // https://v8.dev/docs/stack-trace-api#compatibility advises that
81
+ // programmers can "always" set `Error.stackTraceLimit`
82
+ // even on non-v8 platforms. On non-v8
83
+ // it will have no effect, but this advice only makes sense
84
+ // if the assignment itself does not fail, which it would
85
+ // if `Error` were naively frozen. Hence, we add setters that
86
+ // accept but ignore the assignment on non-v8 platforms.
87
+ defineProperties(InitialError, {
88
+ stackTraceLimit: {
89
+ get() {
90
+ if (typeof FERAL_ERROR.stackTraceLimit === 'number') {
91
+ // FERAL_ERROR.stackTraceLimit is only on v8
92
+ return FERAL_ERROR.stackTraceLimit;
93
+ }
94
+ return undefined;
95
+ },
96
+ set(newLimit) {
97
+ if (typeof newLimit !== 'number') {
98
+ // silently do nothing. This behavior doesn't precisely
99
+ // emulate v8 edge-case behavior. But given the purpose
100
+ // of this emulation, having edge cases err towards
101
+ // harmless seems the safer option.
102
+ return;
103
+ }
104
+ if (typeof FERAL_ERROR.stackTraceLimit === 'number') {
105
+ // FERAL_ERROR.stackTraceLimit is only on v8
106
+ FERAL_ERROR.stackTraceLimit = newLimit;
107
+ // We place the useless return on the next line to ensure
108
+ // that anything we place after the if in the future only
109
+ // happens if the then-case does not.
110
+ // eslint-disable-next-line no-useless-return
111
+ return;
112
+ }
113
+ },
114
+ // WTF on v8 stackTraceLimit is enumerable
115
+ enumerable: false,
116
+ configurable: true,
117
+ },
118
+ });
119
+
120
+ if (errorTaming === 'unsafe-debug' && platform === 'v8') {
121
+ // This case is a kludge to work around
122
+ // https://github.com/endojs/endo/issues/1798
123
+ // https://github.com/endojs/endo/issues/2348
124
+ // https://github.com/Agoric/agoric-sdk/issues/8662
125
+
126
+ defineProperties(InitialError, {
127
+ prepareStackTrace: {
128
+ get() {
129
+ return FERAL_ERROR.prepareStackTrace;
130
+ },
131
+ set(newPrepareStackTrace) {
132
+ FERAL_ERROR.prepareStackTrace = newPrepareStackTrace;
133
+ },
134
+ enumerable: false,
135
+ configurable: true,
136
+ },
137
+ captureStackTrace: {
138
+ value: FERAL_ERROR.captureStackTrace,
139
+ writable: true,
140
+ enumerable: false,
141
+ configurable: true,
142
+ },
143
+ });
144
+
145
+ const descs = getOwnPropertyDescriptors(InitialError);
146
+ defineProperties(SharedError, {
147
+ stackTraceLimit: descs.stackTraceLimit,
148
+ prepareStackTrace: descs.prepareStackTrace,
149
+ captureStackTrace: descs.captureStackTrace,
150
+ });
151
+
152
+ return {
153
+ '%InitialGetStackString%': initialGetStackString,
154
+ '%InitialError%': InitialError,
155
+ '%SharedError%': SharedError,
156
+ };
157
+ }
158
+
159
+ // The default SharedError much be completely powerless even on v8,
160
+ // so the lenient `stackTraceLimit` accessor does nothing on all
161
+ // platforms.
162
+ defineProperties(SharedError, {
163
+ stackTraceLimit: {
164
+ get() {
165
+ return undefined;
166
+ },
167
+ set(_newLimit) {
168
+ // do nothing
169
+ },
170
+ enumerable: false,
171
+ configurable: true,
172
+ },
173
+ });
174
+
175
+ if (platform === 'v8') {
176
+ // `SharedError.prepareStackTrace`, if it exists, must also be
177
+ // powerless. However, from what we've heard, depd expects to be able to
178
+ // assign to it without the assignment throwing. It is normally a function
179
+ // that returns a stack string to be magically added to error objects.
180
+ // However, as long as we're adding a lenient standin, we may as well
181
+ // accommodate any who expect to get a function they can call and get
182
+ // a string back. This prepareStackTrace is a do-nothing function that
183
+ // always returns the empty string.
184
+ defineProperties(SharedError, {
185
+ prepareStackTrace: {
186
+ get() {
187
+ return () => '';
188
+ },
189
+ set(_prepareFn) {
190
+ // do nothing
191
+ },
192
+ enumerable: false,
193
+ configurable: true,
194
+ },
195
+ captureStackTrace: {
196
+ value: (errorish, _constructorOpt) => {
197
+ defineProperty(errorish, 'stack', {
198
+ value: '',
199
+ });
200
+ },
201
+ writable: false,
202
+ enumerable: false,
203
+ configurable: true,
204
+ },
205
+ });
206
+ }
207
+
208
+ if (platform === 'v8') {
209
+ initialGetStackString = tameV8ErrorConstructor(
210
+ FERAL_ERROR,
211
+ InitialError,
212
+ errorTaming,
213
+ stackFiltering,
214
+ );
215
+ } else if (errorTaming === 'unsafe' || errorTaming === 'unsafe-debug') {
216
+ // v8 has too much magic around their 'stack' own property for it to
217
+ // coexist cleanly with this accessor. So only install it on non-v8
218
+
219
+ // Error.prototype.stack property as proposed at
220
+ // https://tc39.es/proposal-error-stacks/
221
+ // with the fix proposed at
222
+ // https://github.com/tc39/proposal-error-stacks/issues/46
223
+ // On others, this still protects from the override mistake,
224
+ // essentially like enable-property-overrides.js would
225
+ // once this accessor property itself is frozen, as will happen
226
+ // later during lockdown.
227
+ //
228
+ // However, there is here a change from the intent in the current
229
+ // state of the proposal. If experience tells us whether this change
230
+ // is a good idea, we should modify the proposal accordingly. There is
231
+ // much code in the world that assumes `error.stack` is a string. So
232
+ // where the proposal accommodates secure operation by making the
233
+ // property optional, we instead accommodate secure operation by
234
+ // having the secure form always return only the stable part, the
235
+ // stringified error instance, and omitting all the frame information
236
+ // rather than omitting the property.
237
+ defineProperties(ErrorPrototype, {
238
+ stack: {
239
+ get() {
240
+ return initialGetStackString(this);
241
+ },
242
+ set(newValue) {
243
+ defineProperties(this, {
244
+ stack: {
245
+ value: newValue,
246
+ writable: true,
247
+ enumerable: true,
248
+ configurable: true,
249
+ },
250
+ });
251
+ },
252
+ },
253
+ });
254
+ } else {
255
+ // v8 has too much magic around their 'stack' own property for it to
256
+ // coexist cleanly with this accessor. So only install it on non-v8
257
+ defineProperties(ErrorPrototype, {
258
+ stack: {
259
+ get() {
260
+ // https://github.com/tc39/proposal-error-stacks/issues/46
261
+ // allows this to not add an unpleasant newline. Otherwise
262
+ // we should fix this.
263
+ return `${this}`;
264
+ },
265
+ set(newValue) {
266
+ defineProperties(this, {
267
+ stack: {
268
+ value: newValue,
269
+ writable: true,
270
+ enumerable: true,
271
+ configurable: true,
272
+ },
273
+ });
274
+ },
275
+ },
276
+ });
277
+ }
278
+
279
+ return {
280
+ '%InitialGetStackString%': initialGetStackString,
281
+ '%InitialError%': InitialError,
282
+ '%SharedError%': SharedError,
283
+ };
284
+ }
@@ -0,0 +1,386 @@
1
+ import {
2
+ WeakMap,
3
+ WeakSet,
4
+ apply,
5
+ arrayFilter,
6
+ arrayJoin,
7
+ arrayMap,
8
+ arraySlice,
9
+ create,
10
+ defineProperties,
11
+ fromEntries,
12
+ reflectSet,
13
+ regexpExec,
14
+ regexpTest,
15
+ weakmapGet,
16
+ weakmapSet,
17
+ weaksetAdd,
18
+ weaksetHas,
19
+ TypeError,
20
+ } from '../commons.js';
21
+
22
+ // Permit names from https://v8.dev/docs/stack-trace-api
23
+ // Permiting only the names used by error-stack-shim/src/v8StackFrames
24
+ // callSiteToFrame to shim the error stack proposal.
25
+ const safeV8CallSiteMethodNames = [
26
+ // suppress 'getThis' definitely
27
+ 'getTypeName',
28
+ // suppress 'getFunction' definitely
29
+ 'getFunctionName',
30
+ 'getMethodName',
31
+ 'getFileName',
32
+ 'getLineNumber',
33
+ 'getColumnNumber',
34
+ 'getEvalOrigin',
35
+ 'isToplevel',
36
+ 'isEval',
37
+ 'isNative',
38
+ 'isConstructor',
39
+ 'isAsync',
40
+ // suppress 'isPromiseAll' for now
41
+ // suppress 'getPromiseIndex' for now
42
+
43
+ // Additional names found by experiment, absent from
44
+ // https://v8.dev/docs/stack-trace-api
45
+ 'getPosition',
46
+ 'getScriptNameOrSourceURL',
47
+
48
+ 'toString', // TODO replace to use only permitted info
49
+ ];
50
+
51
+ // TODO this is a ridiculously expensive way to attenuate callsites.
52
+ // Before that matters, we should switch to a reasonable representation.
53
+ const safeV8CallSiteFacet = callSite => {
54
+ const methodEntry = name => {
55
+ const method = callSite[name];
56
+ return [name, () => apply(method, callSite, [])];
57
+ };
58
+ const o = fromEntries(arrayMap(safeV8CallSiteMethodNames, methodEntry));
59
+ return create(o, {});
60
+ };
61
+
62
+ const safeV8SST = sst => arrayMap(sst, safeV8CallSiteFacet);
63
+
64
+ // If it has `/node_modules/` anywhere in it, on Node it is likely
65
+ // to be a dependent package of the current package, and so to
66
+ // be an infrastructure frame to be dropped from concise stack traces.
67
+ const FILENAME_NODE_DEPENDENTS_CENSOR = /\/node_modules\//;
68
+
69
+ // If it begins with `internal/` or `node:internal` then it is likely
70
+ // part of the node infrustructre itself, to be dropped from concise
71
+ // stack traces.
72
+ const FILENAME_NODE_INTERNALS_CENSOR = /^(?:node:)?internal\//;
73
+
74
+ // Frames within SES `assert.js` should be dropped from concise stack traces, as
75
+ // these are just steps towards creating the error object in question.
76
+ const FILENAME_ASSERT_CENSOR = /\/packages\/ses\/src\/error\/assert\.js$/;
77
+
78
+ // Frames within the `eventual-send` shim should be dropped so that concise
79
+ // deep stacks omit the internals of the eventual-sending mechanism causing
80
+ // asynchronous messages to be sent.
81
+ // Note that the eventual-send package will move from agoric-sdk to
82
+ // Endo, so this rule will be of general interest.
83
+ const FILENAME_EVENTUAL_SEND_CENSOR = /\/packages\/eventual-send\/src\//;
84
+
85
+ // Frames within the `ses-ava` package should be dropped from concise stack
86
+ // traces, as they just support exposing error details to AVA.
87
+ const FILENAME_SES_AVA_CENSOR = /\/packages\/ses-ava\/src\/ses-ava-test\.js$/;
88
+
89
+ // Any stack frame whose `fileName` matches any of these censor patterns
90
+ // will be omitted from concise stacks.
91
+ // TODO Enable users to configure FILENAME_CENSORS via `lockdown` options.
92
+ const FILENAME_CENSORS = [
93
+ FILENAME_NODE_DEPENDENTS_CENSOR,
94
+ FILENAME_NODE_INTERNALS_CENSOR,
95
+ FILENAME_ASSERT_CENSOR,
96
+ FILENAME_EVENTUAL_SEND_CENSOR,
97
+ FILENAME_SES_AVA_CENSOR,
98
+ ];
99
+
100
+ // Should a stack frame with this as its fileName be included in a concise
101
+ // stack trace?
102
+ // Exported only so it can be unit tested.
103
+ // TODO Move so that it applies not just to v8.
104
+ export const filterFileName = fileName => {
105
+ if (!fileName) {
106
+ // Stack frames with no fileName should appear in concise stack traces.
107
+ return true;
108
+ }
109
+ for (const filter of FILENAME_CENSORS) {
110
+ if (regexpTest(filter, fileName)) {
111
+ return false;
112
+ }
113
+ }
114
+ return true;
115
+ };
116
+
117
+ // The ad-hoc rule of the current pattern is that any likely-file-path or
118
+ // likely url-path prefix, ending in a `/.../` should get dropped.
119
+ // Anything to the left of the likely path text is kept.
120
+ // Everything to the right of `/.../` is kept. Thus
121
+ // `'Object.bar (/vat-v1/.../eventual-send/test/deep-send.test.js:13:21)'`
122
+ // simplifies to
123
+ // `'Object.bar (eventual-send/test/deep-send.test.js:13:21)'`.
124
+ //
125
+ // See thread starting at
126
+ // https://github.com/Agoric/agoric-sdk/issues/2326#issuecomment-773020389
127
+ const CALLSITE_ELLIPSIS_PATTERN1 = /^((?:.*[( ])?)[:/\w_-]*\/\.\.\.\/(.+)$/;
128
+
129
+ // The ad-hoc rule of the current pattern is that any likely-file-path or
130
+ // likely url-path prefix consisting of `.../` should get dropped.
131
+ // Anything to the left of the likely path text is kept.
132
+ // Everything to the right of `.../` is kept. Thus
133
+ // `'Object.bar (.../eventual-send/test/deep-send.test.js:13:21)'`
134
+ // simplifies to
135
+ // `'Object.bar (eventual-send/test/deep-send.test.js:13:21)'`.
136
+ //
137
+ // See thread starting at
138
+ // https://github.com/Agoric/agoric-sdk/issues/2326#issuecomment-773020389
139
+ const CALLSITE_ELLIPSIS_PATTERN2 = /^((?:.*[( ])?)\.\.\.\/(.+)$/;
140
+
141
+ // The ad-hoc rule of the current pattern is that any likely-file-path or
142
+ // likely url-path prefix, ending in a `/` and prior to `package/` should get
143
+ // dropped.
144
+ // Anything to the left of the likely path prefix text is kept. `package/` and
145
+ // everything to its right is kept. Thus
146
+ // `'Object.bar (/Users/markmiller/src/ongithub/agoric/agoric-sdk/packages/eventual-send/test/deep-send.test.js:13:21)'`
147
+ // simplifies to
148
+ // `'Object.bar (packages/eventual-send/test/deep-send.test.js:13:21)'`.
149
+ // Note that `/packages/` is a convention for monorepos encouraged by
150
+ // lerna.
151
+ const CALLSITE_PACKAGES_PATTERN = /^((?:.*[( ])?)[:/\w_-]*\/(packages\/.+)$/;
152
+
153
+ // The ad-hoc rule of the current pattern is that any likely-file-path or
154
+ // likely url-path prefix of the form `file://` but not `file:///` gets
155
+ // dropped.
156
+ // Anything to the left of the likely path prefix text is kept. Everything to
157
+ // the right of `file://` is kept. Thus
158
+ // `'Object.bar (file:///Users/markmiller/src/ongithub/endojs/endo/packages/eventual-send/test/deep-send.test.js:13:21)'` is unchanged but
159
+ // `'Object.bar (file://test/deep-send.test.js:13:21)'`
160
+
161
+ // simplifies to
162
+ // `'Object.bar (test/deep-send.test.js:13:21)'`.
163
+ // The reason is that `file:///` usually precedes an absolute path which is
164
+ // clickable without removing the `file:///`, whereas `file://` usually precedes
165
+ // a relative path which, for whatever vscode reason, is not clickable until the
166
+ // `file://` is removed.
167
+ const CALLSITE_FILE_2SLASH_PATTERN = /^((?:.*[( ])?)file:\/\/([^/].*)$/;
168
+
169
+ // The use of these callSite patterns below assumes that any match will bind
170
+ // capture groups containing the parts of the original string we want
171
+ // to keep. The parts outside those capture groups will be dropped from concise
172
+ // stacks.
173
+ // TODO Enable users to configure CALLSITE_PATTERNS via `lockdown` options.
174
+ const CALLSITE_PATTERNS = [
175
+ CALLSITE_ELLIPSIS_PATTERN1,
176
+ CALLSITE_ELLIPSIS_PATTERN2,
177
+ CALLSITE_PACKAGES_PATTERN,
178
+ CALLSITE_FILE_2SLASH_PATTERN,
179
+ ];
180
+
181
+ // For a stack frame that should be included in a concise stack trace, if
182
+ // `callSiteString` is the original stringified stack frame, return the
183
+ // possibly-shorter stringified stack frame that should be shown instead.
184
+ // Exported only so it can be unit tested.
185
+ // TODO Move so that it applies not just to v8.
186
+ /**
187
+ * @param {string} callSiteString
188
+ */
189
+ export const shortenCallSiteString = callSiteString => {
190
+ for (const filter of CALLSITE_PATTERNS) {
191
+ const match = regexpExec(filter, callSiteString);
192
+ if (match) {
193
+ return arrayJoin(arraySlice(match, 1), '');
194
+ }
195
+ }
196
+ return callSiteString;
197
+ };
198
+
199
+ export const tameV8ErrorConstructor = (
200
+ OriginalError,
201
+ InitialError,
202
+ errorTaming,
203
+ stackFiltering,
204
+ ) => {
205
+ if (errorTaming === 'unsafe-debug') {
206
+ throw TypeError(
207
+ 'internal: v8+unsafe-debug special case should already be done',
208
+ );
209
+ }
210
+ // TODO: Proper CallSite types
211
+ /** @typedef {{}} CallSite */
212
+
213
+ const originalCaptureStackTrace = OriginalError.captureStackTrace;
214
+
215
+ const omitFrames =
216
+ stackFiltering === 'concise' || stackFiltering === 'omit-frames';
217
+
218
+ const shortenPaths =
219
+ stackFiltering === 'concise' || stackFiltering === 'shorten-paths';
220
+
221
+ // const callSiteFilter = _callSite => true;
222
+ const callSiteFilter = callSite => {
223
+ if (omitFrames) {
224
+ // eslint-disable-next-line @endo/no-polymorphic-call
225
+ return filterFileName(callSite.getFileName());
226
+ }
227
+ return true;
228
+ };
229
+
230
+ const callSiteStringifier = callSite => {
231
+ let callSiteString = `${callSite}`;
232
+ if (shortenPaths) {
233
+ callSiteString = shortenCallSiteString(callSiteString);
234
+ }
235
+ return `\n at ${callSiteString}`;
236
+ };
237
+
238
+ const stackStringFromSST = (_error, sst) =>
239
+ arrayJoin(
240
+ arrayMap(arrayFilter(sst, callSiteFilter), callSiteStringifier),
241
+ '',
242
+ );
243
+
244
+ /**
245
+ * @typedef {object} StructuredStackInfo
246
+ * @property {CallSite[]} callSites
247
+ * @property {undefined} [stackString]
248
+ */
249
+
250
+ /**
251
+ * @typedef {object} ParsedStackInfo
252
+ * @property {undefined} [callSites]
253
+ * @property {string} stackString
254
+ */
255
+
256
+ // Mapping from error instance to the stack for that instance.
257
+ // The stack info is either the structured stack trace
258
+ // or the generated tamed stack string
259
+ /** @type {WeakMap<Error, ParsedStackInfo | StructuredStackInfo>} */
260
+ const stackInfos = new WeakMap();
261
+
262
+ // Use concise methods to obtain named functions without constructors.
263
+ const tamedMethods = {
264
+ // The optional `optFn` argument is for cutting off the bottom of
265
+ // the stack --- for capturing the stack only above the topmost
266
+ // call to that function. Since this isn't the "real" captureStackTrace
267
+ // but instead calls the real one, if no other cutoff is provided,
268
+ // we cut this one off.
269
+ captureStackTrace(error, optFn = tamedMethods.captureStackTrace) {
270
+ if (typeof originalCaptureStackTrace === 'function') {
271
+ // OriginalError.captureStackTrace is only on v8
272
+ apply(originalCaptureStackTrace, OriginalError, [error, optFn]);
273
+ return;
274
+ }
275
+ reflectSet(error, 'stack', '');
276
+ },
277
+ // Shim of proposed special power, to reside by default only
278
+ // in the start compartment, for getting the stack traceback
279
+ // string associated with an error.
280
+ // See https://tc39.es/proposal-error-stacks/
281
+ getStackString(error) {
282
+ let stackInfo = weakmapGet(stackInfos, error);
283
+
284
+ if (stackInfo === undefined) {
285
+ // The following will call `prepareStackTrace()` synchronously
286
+ // which will populate stackInfos
287
+ // eslint-disable-next-line no-void
288
+ void error.stack;
289
+ stackInfo = weakmapGet(stackInfos, error);
290
+ if (!stackInfo) {
291
+ stackInfo = { stackString: '' };
292
+ weakmapSet(stackInfos, error, stackInfo);
293
+ }
294
+ }
295
+
296
+ // prepareStackTrace() may generate the stackString
297
+ // if errorTaming === 'unsafe'
298
+
299
+ if (stackInfo.stackString !== undefined) {
300
+ return stackInfo.stackString;
301
+ }
302
+
303
+ const stackString = stackStringFromSST(error, stackInfo.callSites);
304
+ weakmapSet(stackInfos, error, { stackString });
305
+
306
+ return stackString;
307
+ },
308
+ prepareStackTrace(error, sst) {
309
+ if (errorTaming === 'unsafe') {
310
+ const stackString = stackStringFromSST(error, sst);
311
+ weakmapSet(stackInfos, error, { stackString });
312
+ return `${error}${stackString}`;
313
+ } else {
314
+ weakmapSet(stackInfos, error, { callSites: sst });
315
+ return '';
316
+ }
317
+ },
318
+ };
319
+
320
+ // A prepareFn is a prepareStackTrace function.
321
+ // An sst is a `structuredStackTrace`, which is an array of
322
+ // callsites.
323
+ // A user prepareFn is a prepareFn defined by a client of this API,
324
+ // and provided by assigning to `Error.prepareStackTrace`.
325
+ // A user prepareFn should only receive an attenuated sst, which
326
+ // is an array of attenuated callsites.
327
+ // A system prepareFn is the prepareFn created by this module to
328
+ // be installed on the real `Error` constructor, to receive
329
+ // an original sst, i.e., an array of unattenuated callsites.
330
+ // An input prepareFn is a function the user assigns to
331
+ // `Error.prepareStackTrace`, which might be a user prepareFn or
332
+ // a system prepareFn previously obtained by reading
333
+ // `Error.prepareStackTrace`.
334
+
335
+ const defaultPrepareFn = tamedMethods.prepareStackTrace;
336
+
337
+ OriginalError.prepareStackTrace = defaultPrepareFn;
338
+
339
+ // A weakset branding some functions as system prepareFns, all of which
340
+ // must be defined by this module, since they can receive an
341
+ // unattenuated sst.
342
+ const systemPrepareFnSet = new WeakSet([defaultPrepareFn]);
343
+
344
+ const systemPrepareFnFor = inputPrepareFn => {
345
+ if (weaksetHas(systemPrepareFnSet, inputPrepareFn)) {
346
+ return inputPrepareFn;
347
+ }
348
+ // Use concise methods to obtain named functions without constructors.
349
+ const systemMethods = {
350
+ prepareStackTrace(error, sst) {
351
+ weakmapSet(stackInfos, error, { callSites: sst });
352
+ return inputPrepareFn(error, safeV8SST(sst));
353
+ },
354
+ };
355
+ weaksetAdd(systemPrepareFnSet, systemMethods.prepareStackTrace);
356
+ return systemMethods.prepareStackTrace;
357
+ };
358
+
359
+ // Note `stackTraceLimit` accessor already defined by
360
+ // tame-error-constructor.js
361
+ defineProperties(InitialError, {
362
+ captureStackTrace: {
363
+ value: tamedMethods.captureStackTrace,
364
+ writable: true,
365
+ enumerable: false,
366
+ configurable: true,
367
+ },
368
+ prepareStackTrace: {
369
+ get() {
370
+ return OriginalError.prepareStackTrace;
371
+ },
372
+ set(inputPrepareStackTraceFn) {
373
+ if (typeof inputPrepareStackTraceFn === 'function') {
374
+ const systemPrepareFn = systemPrepareFnFor(inputPrepareStackTraceFn);
375
+ OriginalError.prepareStackTrace = systemPrepareFn;
376
+ } else {
377
+ OriginalError.prepareStackTrace = defaultPrepareFn;
378
+ }
379
+ },
380
+ enumerable: false,
381
+ configurable: true,
382
+ },
383
+ });
384
+
385
+ return tamedMethods.getStackString;
386
+ };