flugrekorder 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +354 -72
- package/dist/flugrekorder.d.mts +49 -24
- package/dist/flugrekorder.d.ts +49 -24
- package/dist/flugrekorder.global.js +422 -175
- package/dist/flugrekorder.global.js.map +1 -1
- package/dist/flugrekorder.js +425 -176
- package/dist/flugrekorder.js.map +1 -1
- package/dist/flugrekorder.mjs +421 -176
- package/dist/flugrekorder.mjs.map +1 -1
- package/package.json +13 -25
package/dist/flugrekorder.js
CHANGED
|
@@ -28,16 +28,25 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
|
|
|
28
28
|
var flugrekorder_exports = {};
|
|
29
29
|
__export(flugrekorder_exports, {
|
|
30
30
|
create: () => create,
|
|
31
|
+
format: () => format,
|
|
31
32
|
getAncestors: () => getAncestors,
|
|
32
33
|
getOrigin: () => getOrigin,
|
|
33
34
|
getPath: () => getPath,
|
|
34
35
|
getProxyById: () => getProxyById,
|
|
35
36
|
getTarget: () => getTarget,
|
|
36
|
-
isFlugrekorder: () => isFlugrekorder
|
|
37
|
+
isFlugrekorder: () => isFlugrekorder,
|
|
38
|
+
isProxiable: () => isProxiable
|
|
37
39
|
});
|
|
38
40
|
module.exports = __toCommonJS(flugrekorder_exports);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
|
|
42
|
+
// source/types.ts
|
|
43
|
+
function isProxiable(value) {
|
|
44
|
+
return value !== null && (typeof value === "object" || typeof value === "function");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// source/graph.ts
|
|
48
|
+
var _index, _all, _byId, _byProxy, _byTarget, _generator;
|
|
49
|
+
var _Graph = class _Graph {
|
|
41
50
|
constructor(id) {
|
|
42
51
|
__privateAdd(this, _byId, /* @__PURE__ */ new Map());
|
|
43
52
|
__privateAdd(this, _byProxy, /* @__PURE__ */ new WeakMap());
|
|
@@ -46,9 +55,26 @@ var Graph = class {
|
|
|
46
55
|
let counter = typeof id === "number" ? id : 0;
|
|
47
56
|
__privateSet(this, _generator, typeof id === "function" ? id : () => `#${++counter}`);
|
|
48
57
|
}
|
|
58
|
+
/** Returns the Graph that owns `pxy`, or `undefined` for non-proxies. */
|
|
59
|
+
static for(pxy) {
|
|
60
|
+
return __privateGet(_Graph, _index).get(pxy);
|
|
61
|
+
}
|
|
62
|
+
/** Returns `true` if `pxy` is a proxy created by this module. */
|
|
63
|
+
static isProxy(pxy) {
|
|
64
|
+
return __privateGet(_Graph, _all).has(pxy);
|
|
65
|
+
}
|
|
66
|
+
/** Marks `pxy` as a known proxy across all graphs (double-wrap guard). */
|
|
67
|
+
static track(pxy) {
|
|
68
|
+
__privateGet(_Graph, _all).add(pxy);
|
|
69
|
+
}
|
|
49
70
|
nextId() {
|
|
50
71
|
return __privateGet(this, _generator).call(this);
|
|
51
72
|
}
|
|
73
|
+
/** Returns the underlying target if `value` is a proxy known to this graph, otherwise `value` unchanged. */
|
|
74
|
+
unwrap(value) {
|
|
75
|
+
if (!isProxiable(value)) return value;
|
|
76
|
+
return __privateGet(this, _byProxy).get(value)?.target ?? value;
|
|
77
|
+
}
|
|
52
78
|
getByProxy(v) {
|
|
53
79
|
return __privateGet(this, _byProxy).get(v);
|
|
54
80
|
}
|
|
@@ -58,62 +84,89 @@ var Graph = class {
|
|
|
58
84
|
getById(id) {
|
|
59
85
|
return __privateGet(this, _byId).get(id);
|
|
60
86
|
}
|
|
61
|
-
register(proxy, target,
|
|
62
|
-
const node = { id, proxy, target, origin };
|
|
87
|
+
register(proxy, target, origin2, id) {
|
|
88
|
+
const node = { id, proxy, target, origin: origin2 };
|
|
63
89
|
__privateGet(this, _byId).set(id, node);
|
|
64
90
|
__privateGet(this, _byProxy).set(proxy, node);
|
|
65
91
|
__privateGet(this, _byTarget).set(target, node);
|
|
92
|
+
__privateGet(_Graph, _index).set(proxy, this);
|
|
66
93
|
return node;
|
|
67
94
|
}
|
|
68
95
|
};
|
|
96
|
+
_index = new WeakMap();
|
|
97
|
+
_all = new WeakMap();
|
|
69
98
|
_byId = new WeakMap();
|
|
70
99
|
_byProxy = new WeakMap();
|
|
71
100
|
_byTarget = new WeakMap();
|
|
72
101
|
_generator = new WeakMap();
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
var
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
102
|
+
__privateAdd(_Graph, _index, /* @__PURE__ */ new WeakMap());
|
|
103
|
+
__privateAdd(_Graph, _all, /* @__PURE__ */ new WeakSet());
|
|
104
|
+
var Graph = _Graph;
|
|
105
|
+
|
|
106
|
+
// source/serialize.ts
|
|
107
|
+
var defaults = {
|
|
108
|
+
depth: Infinity,
|
|
109
|
+
redactors: [],
|
|
110
|
+
truncate: Infinity
|
|
111
|
+
};
|
|
112
|
+
function redact(redactors, key, value, target) {
|
|
113
|
+
for (const redactor of redactors) {
|
|
114
|
+
const result = redactor(key, value, target);
|
|
115
|
+
if (result === false) continue;
|
|
116
|
+
return result === true ? "[redacted]" : result;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
79
119
|
}
|
|
80
|
-
function
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
120
|
+
function proxiable(v, graph, seen, serial, depth) {
|
|
121
|
+
const proxyNode = graph.getByProxy(v);
|
|
122
|
+
if (proxyNode !== void 0) return { $proxy: proxyNode.id };
|
|
123
|
+
const targetNode = graph.getByTarget(v);
|
|
124
|
+
if (targetNode !== void 0) return { $unwrap: { $proxy: targetNode.id } };
|
|
125
|
+
if (depth >= serial.depth) return "[\u2026]";
|
|
126
|
+
if (Array.isArray(v)) {
|
|
127
|
+
return v.map(
|
|
128
|
+
(item) => serialize(item, graph, seen, serial, depth + 1)
|
|
129
|
+
);
|
|
130
|
+
}
|
|
85
131
|
if (seen.has(v)) return { $proxy: "?" };
|
|
86
132
|
seen.add(v);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
133
|
+
const entries = [];
|
|
134
|
+
for (const [k, val] of Object.entries(v)) {
|
|
135
|
+
if (serial.redactors.length > 0) {
|
|
136
|
+
const decision = redact(serial.redactors, k, val, v);
|
|
137
|
+
if (decision === null) continue;
|
|
138
|
+
if (decision !== false) {
|
|
139
|
+
entries.push([k, decision]);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
entries.push([k, serialize(val, graph, seen, serial, depth + 1)]);
|
|
144
|
+
}
|
|
93
145
|
seen.delete(v);
|
|
94
|
-
return
|
|
146
|
+
return Object.fromEntries(entries);
|
|
95
147
|
}
|
|
96
|
-
|
|
97
|
-
{ match: /number|boolean|bigint/, map: (v) => v },
|
|
98
|
-
{ match: /object|function/, map: serializeProxiable }
|
|
99
|
-
];
|
|
100
|
-
function serialize(v, graph, seen = /* @__PURE__ */ new Set()) {
|
|
148
|
+
function serialize(v, graph, seen = /* @__PURE__ */ new Set(), serial = defaults, depth = 0) {
|
|
101
149
|
if (v === null || v === void 0) return v;
|
|
102
|
-
|
|
103
|
-
return
|
|
150
|
+
if (isProxiable(v)) return proxiable(v, graph, seen, serial, depth);
|
|
151
|
+
return typeof v === "string" ? v.length > serial.truncate ? `${v.slice(0, serial.truncate)}\u2026` : v : v;
|
|
104
152
|
}
|
|
105
|
-
function
|
|
153
|
+
function origin(o) {
|
|
106
154
|
if (!o) return null;
|
|
107
155
|
if ("key" in o)
|
|
108
156
|
return { trap: o.trap, parent: o.parent, key: String(o.key) };
|
|
109
157
|
return o;
|
|
110
158
|
}
|
|
111
|
-
|
|
159
|
+
|
|
160
|
+
// source/slots.ts
|
|
161
|
+
var slotProtos = /* @__PURE__ */ new WeakMap();
|
|
162
|
+
var bindCache = /* @__PURE__ */ new WeakMap();
|
|
163
|
+
var slotError = /incompatible receiver|this is not|illegal invocation/i;
|
|
112
164
|
function hasInternalSlots(target) {
|
|
113
165
|
if (typeof target !== "object" || target === null) return false;
|
|
114
166
|
const direct = Object.getPrototypeOf(target);
|
|
115
167
|
if (!direct) return false;
|
|
116
|
-
|
|
168
|
+
const cached = slotProtos.get(direct);
|
|
169
|
+
if (cached !== void 0) return cached;
|
|
117
170
|
const probe = new Proxy(target, {
|
|
118
171
|
set: () => true,
|
|
119
172
|
defineProperty: () => true,
|
|
@@ -131,7 +184,8 @@ function hasInternalSlots(target) {
|
|
|
131
184
|
try {
|
|
132
185
|
fn.call(probe);
|
|
133
186
|
} catch (e) {
|
|
134
|
-
if (e instanceof TypeError && slotError.test(String(e)))
|
|
187
|
+
if (e instanceof TypeError && slotError.test(String(e)))
|
|
188
|
+
slots = true;
|
|
135
189
|
}
|
|
136
190
|
slotProtos.set(direct, slots);
|
|
137
191
|
return slots;
|
|
@@ -143,207 +197,402 @@ function hasInternalSlots(target) {
|
|
|
143
197
|
return false;
|
|
144
198
|
}
|
|
145
199
|
function boundMethod(target, key, fn) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
200
|
+
let cache = bindCache.get(target);
|
|
201
|
+
if (!cache) {
|
|
202
|
+
cache = /* @__PURE__ */ new Map();
|
|
203
|
+
bindCache.set(target, cache);
|
|
204
|
+
}
|
|
205
|
+
const existing = cache.get(key);
|
|
206
|
+
if (existing) return existing;
|
|
207
|
+
const bound = fn.bind(target);
|
|
208
|
+
cache.set(key, bound);
|
|
209
|
+
return bound;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// source/specs.ts
|
|
213
|
+
var TypedArray = Object.getPrototypeOf(Int8Array);
|
|
214
|
+
var ecmaBuiltins = [
|
|
215
|
+
Promise,
|
|
216
|
+
Map,
|
|
217
|
+
Set,
|
|
218
|
+
WeakMap,
|
|
219
|
+
WeakSet,
|
|
220
|
+
Date,
|
|
221
|
+
RegExp,
|
|
222
|
+
ArrayBuffer,
|
|
223
|
+
TypedArray,
|
|
224
|
+
DataView
|
|
225
|
+
];
|
|
226
|
+
function isECMABuiltin(v) {
|
|
227
|
+
return ecmaBuiltins.some((B) => v instanceof B);
|
|
228
|
+
}
|
|
229
|
+
function isUnsafeBinding(v) {
|
|
230
|
+
return isProxiable(v) && hasInternalSlots(v) && !isECMABuiltin(v);
|
|
150
231
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
key,
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
232
|
+
function makeSpecs(bind) {
|
|
233
|
+
return {
|
|
234
|
+
get: {
|
|
235
|
+
// For targets with internal slots (Map, Set, WeakMap, WeakSet, Date …)
|
|
236
|
+
// or when bind is true, use the real target as the Reflect.get
|
|
237
|
+
// receiver so that getter-based slot checks and #private field reads
|
|
238
|
+
// (e.g. `get value() { return this.#count; }`) don't throw TypeError.
|
|
239
|
+
pre: ([target, key, receiver], _wrap, _known) => [
|
|
240
|
+
target,
|
|
241
|
+
key,
|
|
242
|
+
hasInternalSlots(target) || bind ? target : receiver
|
|
243
|
+
],
|
|
244
|
+
// For the same targets, bind method results to the real target before
|
|
245
|
+
// wrapping so that apply-level slot checks (e.g. Map.prototype.get)
|
|
246
|
+
// and #private field access inside methods also pass.
|
|
247
|
+
// The bind cache ensures proxy stability.
|
|
248
|
+
post: (result, [target, key], wrap) => {
|
|
249
|
+
if (key === "prototype") return result;
|
|
250
|
+
if (hasInternalSlots(target) || bind) {
|
|
251
|
+
if (typeof result === "function")
|
|
252
|
+
return wrap(
|
|
253
|
+
boundMethod(
|
|
254
|
+
target,
|
|
255
|
+
key,
|
|
256
|
+
result
|
|
257
|
+
)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
if (isUnsafeBinding(result)) return result;
|
|
261
|
+
return wrap(result);
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
set: {
|
|
265
|
+
pre: ([target, key, value, receiver], wrap) => [
|
|
266
|
+
target,
|
|
267
|
+
key,
|
|
268
|
+
// Don't wrap when target has slots (Map/Set internals) or when the
|
|
269
|
+
// value is an unsafe C++ binding (TCP handles, etc.).
|
|
270
|
+
hasInternalSlots(target) || isUnsafeBinding(value) ? value : wrap(value),
|
|
271
|
+
receiver
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
apply: {
|
|
275
|
+
// thisArg is wrapped normally (it's always a graph node).
|
|
276
|
+
// Call arguments are wrapped with known — only existing graph nodes
|
|
277
|
+
// get proxied; plain data passes through and is inlined by serialize().
|
|
278
|
+
pre: ([target, thisArg, callArgs], wrap, known) => [
|
|
279
|
+
target,
|
|
280
|
+
wrap(thisArg),
|
|
281
|
+
callArgs.map(known)
|
|
282
|
+
],
|
|
283
|
+
post: (result, _args, wrap) => wrap(result)
|
|
284
|
+
},
|
|
285
|
+
construct: {
|
|
286
|
+
pre: ([target, callArgs, newTarget], wrap) => [
|
|
287
|
+
target,
|
|
288
|
+
callArgs.map(wrap),
|
|
289
|
+
newTarget
|
|
290
|
+
],
|
|
291
|
+
post: (result, _args, wrap) => wrap(result)
|
|
292
|
+
},
|
|
293
|
+
defineProperty: {
|
|
294
|
+
pre: (args, wrap) => {
|
|
295
|
+
const [target, key, descriptor] = args;
|
|
296
|
+
const patch = {};
|
|
297
|
+
if (descriptor.value != null && !isUnsafeBinding(descriptor.value))
|
|
298
|
+
patch.value = wrap(descriptor.value);
|
|
299
|
+
if (typeof descriptor.get === "function")
|
|
300
|
+
patch.get = wrap(descriptor.get);
|
|
301
|
+
if (typeof descriptor.set === "function")
|
|
302
|
+
patch.set = wrap(descriptor.set);
|
|
303
|
+
return Object.keys(patch).length > 0 ? [target, key, { ...descriptor, ...patch }] : args;
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
getOwnPropertyDescriptor: {
|
|
307
|
+
post: (result, _args, wrap) => {
|
|
308
|
+
const desc = result;
|
|
309
|
+
if (!desc) return result;
|
|
310
|
+
const patch = {};
|
|
311
|
+
if (desc.value != null && !isUnsafeBinding(desc.value))
|
|
312
|
+
patch.value = wrap(desc.value);
|
|
313
|
+
if (typeof desc.get === "function")
|
|
314
|
+
patch.get = wrap(desc.get);
|
|
315
|
+
if (typeof desc.set === "function")
|
|
316
|
+
patch.set = wrap(desc.set);
|
|
317
|
+
return Object.keys(patch).length > 0 ? { ...desc, ...patch } : result;
|
|
168
318
|
}
|
|
169
|
-
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// source/errors.ts
|
|
324
|
+
function isError(input) {
|
|
325
|
+
return input ? input instanceof Error : false;
|
|
326
|
+
}
|
|
327
|
+
function createErrorGuard(name, contains) {
|
|
328
|
+
const checks = [
|
|
329
|
+
isError,
|
|
330
|
+
(sub) => typeof sub === "object" && sub?.name === name
|
|
331
|
+
];
|
|
332
|
+
if (contains instanceof RegExp) {
|
|
333
|
+
checks.push((v) => contains.test(String(v)));
|
|
334
|
+
}
|
|
335
|
+
return (input) => checks.every((predicate) => predicate(input));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// source/retry.ts
|
|
339
|
+
function unwrap(graph, value) {
|
|
340
|
+
return graph?.unwrap(value) ?? value;
|
|
341
|
+
}
|
|
342
|
+
var isDataCloneDOMException = createErrorGuard("DataCloneError");
|
|
343
|
+
var isTypeErrorPrivateMember = createErrorGuard("TypeError", /private member/i);
|
|
344
|
+
var isTypeErrorIllegalInvocation = createErrorGuard("TypeError", /illegal invocation/i);
|
|
345
|
+
var retryFlows = [
|
|
346
|
+
{
|
|
347
|
+
// Native methods (console.log, DOM APIs, http.Server) check the internal
|
|
348
|
+
// [[Receiver]] slot and throw "Illegal invocation" when called through a
|
|
349
|
+
// proxy. Unwrap the real target from the graph and retry as the receiver.
|
|
350
|
+
is: (trap, error) => trap === "apply" && isTypeErrorIllegalInvocation(error),
|
|
351
|
+
trap: "apply:native",
|
|
352
|
+
handle: (graph, fn, thisArg, argList) => {
|
|
353
|
+
const realThis = unwrap(graph, thisArg);
|
|
354
|
+
return {
|
|
355
|
+
args: [fn, realThis, argList],
|
|
356
|
+
result: Reflect.apply(fn, realThis, argList)
|
|
357
|
+
};
|
|
170
358
|
}
|
|
171
359
|
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
pre: ([target, thisArg, callArgs], wrap, known) => [
|
|
185
|
-
target,
|
|
186
|
-
wrap(thisArg),
|
|
187
|
-
callArgs.map(known)
|
|
188
|
-
],
|
|
189
|
-
post: (result, _args, wrap) => wrap(result)
|
|
190
|
-
},
|
|
191
|
-
construct: {
|
|
192
|
-
pre: ([target, callArgs, newTarget], wrap) => [
|
|
193
|
-
target,
|
|
194
|
-
callArgs.map(wrap),
|
|
195
|
-
newTarget
|
|
196
|
-
],
|
|
197
|
-
post: (result, _args, wrap) => wrap(result)
|
|
360
|
+
{
|
|
361
|
+
// structuredClone and postMessage can't clone proxy objects — they throw a
|
|
362
|
+
// DataCloneError. Unwrap any proxy arguments to their real targets and retry.
|
|
363
|
+
is: (trap, error) => trap === "apply" && isDataCloneDOMException(error),
|
|
364
|
+
trap: "apply:structure",
|
|
365
|
+
handle: (graph, fn, thisArg, argList) => {
|
|
366
|
+
const unwrappedArgs = argList.map((arg) => unwrap(graph, arg));
|
|
367
|
+
return {
|
|
368
|
+
args: [fn, thisArg, unwrappedArgs],
|
|
369
|
+
result: Reflect.apply(fn, thisArg, unwrappedArgs)
|
|
370
|
+
};
|
|
371
|
+
}
|
|
198
372
|
},
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
373
|
+
{
|
|
374
|
+
// Private fields (#field) use brand checking — accessing #field on a proxy
|
|
375
|
+
// (rather than the original instance) throws "Cannot read private member".
|
|
376
|
+
// Unwrap the real instance from the graph and use it as the receiver.
|
|
377
|
+
is: (trap, error, bind) => bind !== false && trap === "apply" && isTypeErrorPrivateMember(error),
|
|
378
|
+
trap: "apply:private",
|
|
379
|
+
handle: (graph, fn, thisArg, argList) => {
|
|
380
|
+
const realThis = unwrap(graph, thisArg);
|
|
381
|
+
return {
|
|
382
|
+
args: [fn, realThis, argList],
|
|
383
|
+
result: Reflect.apply(fn, realThis, argList)
|
|
384
|
+
};
|
|
209
385
|
}
|
|
210
386
|
},
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
387
|
+
{
|
|
388
|
+
// A getter that reads a #private field hits the same brand check, but the
|
|
389
|
+
// apply retry doesn't apply here. Re-invoke Reflect.get with the real target
|
|
390
|
+
// as its own receiver so the brand check passes.
|
|
391
|
+
is: (trap, error, bind) => bind !== false && trap === "get" && isTypeErrorPrivateMember(error),
|
|
392
|
+
handle: (_graph, target, propertyKey) => ({
|
|
393
|
+
result: Reflect.get(target, propertyKey, target)
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
];
|
|
397
|
+
|
|
398
|
+
// source/inspection.ts
|
|
399
|
+
function getTarget(pxy) {
|
|
400
|
+
return Graph.for(pxy)?.getByProxy(pxy)?.target ?? null;
|
|
401
|
+
}
|
|
402
|
+
function getProxyById(id, pxy) {
|
|
403
|
+
return Graph.for(pxy)?.getById(id)?.proxy;
|
|
404
|
+
}
|
|
405
|
+
function getOrigin(pxy) {
|
|
406
|
+
return Graph.for(pxy)?.getByProxy(pxy)?.origin ?? null;
|
|
407
|
+
}
|
|
408
|
+
function getAncestors(pxy) {
|
|
409
|
+
const graph = Graph.for(pxy);
|
|
410
|
+
if (!graph) return [];
|
|
411
|
+
const result = [];
|
|
412
|
+
let node = graph.getByProxy(pxy);
|
|
413
|
+
while (node) {
|
|
414
|
+
result.unshift({ proxy: node.proxy, origin: node.origin });
|
|
415
|
+
if (!node.origin) break;
|
|
416
|
+
const parentId = "parent" in node.origin ? node.origin.parent : node.origin.source;
|
|
417
|
+
node = graph.getById(parentId);
|
|
418
|
+
}
|
|
419
|
+
return result;
|
|
420
|
+
}
|
|
421
|
+
function getPath(pxy) {
|
|
422
|
+
const ancestors = getAncestors(pxy);
|
|
423
|
+
const parts = [];
|
|
424
|
+
for (const { origin: o } of ancestors) {
|
|
425
|
+
if (!o) continue;
|
|
426
|
+
if ("key" in o) {
|
|
427
|
+
parts.push(String(o.key));
|
|
428
|
+
} else {
|
|
429
|
+
if (parts.length > 0) {
|
|
430
|
+
parts[parts.length - 1] += "()";
|
|
431
|
+
} else {
|
|
432
|
+
parts.push("()");
|
|
433
|
+
}
|
|
222
434
|
}
|
|
223
435
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
436
|
+
return parts.join(".");
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// source/format.ts
|
|
440
|
+
function resolve(id, proxy) {
|
|
441
|
+
if (!proxy) return id;
|
|
442
|
+
const p = getProxyById(id, proxy);
|
|
443
|
+
return p !== void 0 ? getPath(p) : id;
|
|
444
|
+
}
|
|
445
|
+
function display(v, proxy, limit = 80) {
|
|
446
|
+
if (v === null || v === void 0) return String(v);
|
|
447
|
+
if (typeof v !== "object") return String(v);
|
|
448
|
+
if (!Array.isArray(v) && "$proxy" in v)
|
|
449
|
+
return resolve(v.$proxy, proxy);
|
|
450
|
+
if (!Array.isArray(v) && "$unwrap" in v)
|
|
451
|
+
return `\u2193${resolve(v.$unwrap.$proxy, proxy)}`;
|
|
452
|
+
const raw = Array.isArray(v) ? `[${v.map((i) => display(i, proxy)).join(", ")}]` : JSON.stringify(v);
|
|
453
|
+
return raw.length > limit ? `${raw.slice(0, limit)}\u2026` : raw;
|
|
454
|
+
}
|
|
455
|
+
function format(rekording, proxy) {
|
|
456
|
+
const { id, trap, origin: origin2, args, result } = rekording;
|
|
457
|
+
if (origin2 && "parent" in origin2) {
|
|
458
|
+
const parent = resolve(origin2.parent, proxy);
|
|
459
|
+
const path = parent ? `${parent}.${origin2.key}` : String(origin2.key);
|
|
460
|
+
if (trap === "set") return `${path} = ${display(args[2], proxy)}`;
|
|
461
|
+
if (trap === "get") return `${path} \u2192 ${display(result, proxy)}`;
|
|
462
|
+
return `${trap} ${path}`;
|
|
463
|
+
}
|
|
464
|
+
if (origin2 && "source" in origin2) {
|
|
465
|
+
const path = resolve(origin2.source, proxy);
|
|
466
|
+
const callArgs = (Array.isArray(trap === "construct" ? args[1] : args[2]) ? trap === "construct" ? args[1] : args[2] : []).map((a) => display(a, proxy)).join(", ");
|
|
467
|
+
if (/^apply(:|$)/.test(trap))
|
|
468
|
+
return `${path}(${callArgs})`;
|
|
469
|
+
if (trap === "construct" || trap === "construct:native")
|
|
470
|
+
return `new ${path}(${callArgs})`;
|
|
471
|
+
}
|
|
472
|
+
return `${trap} on ${id}`;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// source/flugrekorder.ts
|
|
476
|
+
function makeProxy(target, graph, config, origin2) {
|
|
477
|
+
if (Graph.isProxy(target)) return target;
|
|
227
478
|
const existing = graph.getByTarget(target);
|
|
228
479
|
if (existing) return existing.proxy;
|
|
229
480
|
if (target instanceof Promise) {
|
|
230
481
|
const chained = target.then(
|
|
231
|
-
(value) => isProxiable(value) ? makeProxy(value, graph, config,
|
|
482
|
+
(value) => isProxiable(value) ? makeProxy(value, graph, config, origin2) : value
|
|
232
483
|
);
|
|
233
484
|
const id = graph.nextId();
|
|
234
|
-
graph.register(chained, target,
|
|
235
|
-
graphOf.set(chained, graph);
|
|
485
|
+
graph.register(chained, target, origin2, id);
|
|
236
486
|
return chained;
|
|
237
487
|
}
|
|
238
488
|
const proxyId = graph.nextId();
|
|
239
|
-
let pxy;
|
|
240
489
|
const traps = Object.getOwnPropertyNames(Reflect).filter((trap) => config.only === null || config.only.has(trap));
|
|
241
490
|
const handler = Object.fromEntries(
|
|
242
491
|
traps.map((trap) => [
|
|
243
492
|
trap,
|
|
244
493
|
(...rawArgs) => {
|
|
245
|
-
const selfId = graph.
|
|
246
|
-
|
|
494
|
+
const selfId = graph.getByTarget(target).id;
|
|
495
|
+
let childOrigin = /get|set|defineProperty|getOwnPropertyDescriptor/.test(trap) ? {
|
|
247
496
|
trap,
|
|
248
497
|
parent: selfId,
|
|
249
498
|
key: rawArgs[1]
|
|
250
499
|
} : /apply|construct/.test(trap) ? { trap, source: selfId } : null;
|
|
251
500
|
const wrap = (v) => {
|
|
252
|
-
if (!isProxiable(v) ||
|
|
501
|
+
if (!isProxiable(v) || Graph.isProxy(v))
|
|
253
502
|
return v;
|
|
254
503
|
if (!config.recursive) return v;
|
|
255
504
|
return makeProxy(v, graph, config, childOrigin);
|
|
256
505
|
};
|
|
257
506
|
const known = (v) => {
|
|
258
507
|
if (!isProxiable(v)) return v;
|
|
259
|
-
if (
|
|
508
|
+
if (Graph.isProxy(v)) return v;
|
|
260
509
|
const existing2 = graph.getByTarget(v);
|
|
261
510
|
if (existing2) return existing2.proxy;
|
|
262
511
|
return v;
|
|
263
512
|
};
|
|
264
|
-
const spec = specs[trap] ?? {};
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
513
|
+
const spec = config.specs[trap] ?? {};
|
|
514
|
+
const preArgs = spec.pre ? spec.pre(rawArgs, wrap, known) : rawArgs;
|
|
515
|
+
let effectiveTrap = trap;
|
|
516
|
+
let effectiveArgs = preArgs;
|
|
517
|
+
let result;
|
|
518
|
+
try {
|
|
519
|
+
result = Reflect[trap](...preArgs);
|
|
520
|
+
} catch (e) {
|
|
521
|
+
const flow = retryFlows.find(
|
|
522
|
+
({ is }) => is(trap, e, config.bind)
|
|
523
|
+
);
|
|
524
|
+
if (flow) {
|
|
525
|
+
const invoke = flow.handle;
|
|
526
|
+
const output2 = invoke(graph, ...preArgs);
|
|
527
|
+
if (flow.trap) {
|
|
528
|
+
effectiveTrap = flow.trap;
|
|
529
|
+
childOrigin = {
|
|
530
|
+
trap: flow.trap,
|
|
531
|
+
source: selfId
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (output2?.args) effectiveArgs = output2.args;
|
|
535
|
+
result = output2.result;
|
|
536
|
+
} else {
|
|
537
|
+
throw e;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const output = spec.post ? spec.post(result, effectiveArgs, wrap) : result;
|
|
541
|
+
const rekording = {
|
|
269
542
|
id: graph.nextId(),
|
|
270
|
-
trap,
|
|
271
|
-
origin:
|
|
272
|
-
args:
|
|
273
|
-
|
|
274
|
-
|
|
543
|
+
trap: effectiveTrap,
|
|
544
|
+
origin: origin(childOrigin),
|
|
545
|
+
args: effectiveArgs.map(
|
|
546
|
+
(arg) => serialize(arg, graph, /* @__PURE__ */ new Set(), config.serial)
|
|
547
|
+
),
|
|
548
|
+
result: serialize(output, graph, /* @__PURE__ */ new Set(), config.serial),
|
|
549
|
+
timestamp: Date.now()
|
|
550
|
+
};
|
|
551
|
+
if (!config.filter || config.filter(rekording))
|
|
552
|
+
config.write(rekording);
|
|
275
553
|
return output;
|
|
276
554
|
}
|
|
277
555
|
])
|
|
278
556
|
);
|
|
279
|
-
pxy = new Proxy(target, handler);
|
|
280
|
-
graph.register(pxy, target,
|
|
281
|
-
|
|
282
|
-
allProxies.add(pxy);
|
|
557
|
+
const pxy = new Proxy(target, handler);
|
|
558
|
+
graph.register(pxy, target, origin2, proxyId);
|
|
559
|
+
Graph.track(pxy);
|
|
283
560
|
return pxy;
|
|
284
561
|
}
|
|
285
562
|
function create(target, options) {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
`) : (
|
|
289
|
-
// biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion
|
|
290
|
-
callback
|
|
291
|
-
);
|
|
563
|
+
const write = "stream" in options ? (r) => options.stream.write(`${JSON.stringify(r)}
|
|
564
|
+
`) : options.callback;
|
|
292
565
|
const recursive = options.recursive !== false;
|
|
293
566
|
const only = options.only ? new Set(options.only) : null;
|
|
567
|
+
const filter = options.filter ?? null;
|
|
568
|
+
const { redact: redact2 } = options;
|
|
569
|
+
const serial = {
|
|
570
|
+
depth: options.depth ?? Infinity,
|
|
571
|
+
redactors: redact2 ? Array.isArray(redact2) ? redact2 : [redact2] : [],
|
|
572
|
+
truncate: options.truncate ?? Infinity
|
|
573
|
+
};
|
|
294
574
|
const graph = new Graph(options.id ?? 0);
|
|
295
|
-
|
|
575
|
+
const specs = makeSpecs(options.bind);
|
|
576
|
+
return makeProxy(
|
|
577
|
+
target,
|
|
578
|
+
graph,
|
|
579
|
+
{ write, recursive, only, filter, serial, specs, bind: options.bind },
|
|
580
|
+
null
|
|
581
|
+
);
|
|
296
582
|
}
|
|
297
583
|
function isFlugrekorder(value) {
|
|
298
|
-
return isProxiable(value) &&
|
|
299
|
-
}
|
|
300
|
-
function getTarget(pxy) {
|
|
301
|
-
return graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;
|
|
302
|
-
}
|
|
303
|
-
function getProxyById(id, pxy) {
|
|
304
|
-
return graphOf.get(pxy)?.getById(id)?.proxy;
|
|
305
|
-
}
|
|
306
|
-
function getOrigin(pxy) {
|
|
307
|
-
return graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;
|
|
308
|
-
}
|
|
309
|
-
function getAncestors(pxy) {
|
|
310
|
-
const graph = graphOf.get(pxy);
|
|
311
|
-
if (!graph) return [];
|
|
312
|
-
const result = [];
|
|
313
|
-
let node = graph.getByProxy(pxy);
|
|
314
|
-
while (node) {
|
|
315
|
-
result.unshift({ proxy: node.proxy, origin: node.origin });
|
|
316
|
-
if (!node.origin) break;
|
|
317
|
-
const parentId = "parent" in node.origin ? node.origin.parent : node.origin.source;
|
|
318
|
-
node = graph.getById(parentId);
|
|
319
|
-
}
|
|
320
|
-
return result;
|
|
321
|
-
}
|
|
322
|
-
function getPath(pxy) {
|
|
323
|
-
const ancestors = getAncestors(pxy);
|
|
324
|
-
const parts = [];
|
|
325
|
-
for (const { origin: o } of ancestors) {
|
|
326
|
-
if (!o) continue;
|
|
327
|
-
if ("key" in o) {
|
|
328
|
-
parts.push(String(o.key));
|
|
329
|
-
} else {
|
|
330
|
-
if (parts.length > 0) {
|
|
331
|
-
parts[parts.length - 1] += "()";
|
|
332
|
-
} else {
|
|
333
|
-
parts.push("()");
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return parts.join(".");
|
|
584
|
+
return isProxiable(value) && Graph.isProxy(value);
|
|
338
585
|
}
|
|
339
586
|
// Annotate the CommonJS export names for ESM import in node:
|
|
340
587
|
0 && (module.exports = {
|
|
341
588
|
create,
|
|
589
|
+
format,
|
|
342
590
|
getAncestors,
|
|
343
591
|
getOrigin,
|
|
344
592
|
getPath,
|
|
345
593
|
getProxyById,
|
|
346
594
|
getTarget,
|
|
347
|
-
isFlugrekorder
|
|
595
|
+
isFlugrekorder,
|
|
596
|
+
isProxiable
|
|
348
597
|
});
|
|
349
598
|
//# sourceMappingURL=flugrekorder.js.map
|