flugrekorder 1.1.0 → 1.2.0-beta.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.
@@ -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
- var _byId, _byProxy, _byTarget, _generator;
40
- var Graph = class {
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, origin, id) {
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
- var graphOf = /* @__PURE__ */ new WeakMap();
74
- var allProxies = /* @__PURE__ */ new WeakSet();
75
- var slotProtos = /* @__PURE__ */ new WeakMap();
76
- var bindCache = /* @__PURE__ */ new WeakMap();
77
- function isProxiable(value) {
78
- return value !== null && (typeof value === "object" || typeof value === "function");
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 serializeProxiable(v, graph, seen) {
81
- const node = graph.getByProxy(v) ?? graph.getByTarget(v);
82
- if (node !== void 0) return { $proxy: node.id };
83
- if (Array.isArray(v))
84
- return v.map((item) => serialize(item, graph, seen));
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 result = Object.fromEntries(
88
- Object.entries(v).map(([k, val]) => [
89
- k,
90
- serialize(val, graph, seen)
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 result;
146
+ return Object.fromEntries(entries);
95
147
  }
96
- var mappings = [
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
- const { map = String } = mappings.find(({ match }) => match.test(typeof v)) ?? {};
103
- return map(v, graph, seen);
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 serializeOrigin(o) {
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
- var slotError = /incompatible receiver|this is not/i;
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
- if (slotProtos.has(direct)) return slotProtos.get(direct);
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))) slots = true;
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
- if (!bindCache.has(target)) bindCache.set(target, /* @__PURE__ */ new Map());
147
- const cache = bindCache.get(target);
148
- if (!cache.has(key)) cache.set(key, fn.bind(target));
149
- return cache.get(key);
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
- var specs = {
152
- get: {
153
- // For targets with internal slots (Map, Set, WeakMap, WeakSet, Date …),
154
- // use the real target as the Reflect.get receiver so that getter-based
155
- // slot checks (e.g. Map.prototype.size) don't throw TypeError.
156
- pre: ([target, key, receiver], _wrap, _known) => [
157
- target,
158
- key,
159
- hasInternalSlots(target) ? target : receiver
160
- ],
161
- // For the same targets, bind method results to the real target before
162
- // wrapping so that apply-level slot checks (e.g. Map.prototype.get)
163
- // also pass. The bind cache ensures proxy stability.
164
- post: (result, [target, key], wrap) => {
165
- if (key === "prototype") return result;
166
- if (typeof result === "function" && hasInternalSlots(target)) {
167
- return wrap(boundMethod(target, key, result));
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
- return wrap(result);
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
- set: {
173
- pre: ([target, key, value, receiver], wrap) => [
174
- target,
175
- key,
176
- wrap(value),
177
- receiver
178
- ]
179
- },
180
- apply: {
181
- // thisArg is wrapped normally (it's always a graph node).
182
- // Call arguments are wrapped with known — only existing graph nodes
183
- // get proxied; plain data passes through and is inlined by serialize().
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
- defineProperty: {
200
- pre: (args, wrap) => {
201
- const [target, key, descriptor] = args;
202
- const patch = {};
203
- if (descriptor.value != null) patch.value = wrap(descriptor.value);
204
- if (typeof descriptor.get === "function")
205
- patch.get = wrap(descriptor.get);
206
- if (typeof descriptor.set === "function")
207
- patch.set = wrap(descriptor.set);
208
- return Object.keys(patch).length > 0 ? [target, key, { ...descriptor, ...patch }] : args;
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
- getOwnPropertyDescriptor: {
212
- post: (result, _args, wrap) => {
213
- const desc = result;
214
- if (!desc) return result;
215
- const patch = {};
216
- if (desc.value != null) patch.value = wrap(desc.value);
217
- if (typeof desc.get === "function")
218
- patch.get = wrap(desc.get);
219
- if (typeof desc.set === "function")
220
- patch.set = wrap(desc.set);
221
- return Object.keys(patch).length > 0 ? { ...desc, ...patch } : result;
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
- function makeProxy(target, graph, config, origin) {
226
- if (allProxies.has(target)) return target;
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, origin) : value
482
+ (value) => isProxiable(value) ? makeProxy(value, graph, config, origin2) : value
232
483
  );
233
484
  const id = graph.nextId();
234
- graph.register(chained, target, origin, id);
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.getByProxy(pxy).id;
246
- const childOrigin = /get|set|defineProperty|getOwnPropertyDescriptor/.test(trap) ? {
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) || allProxies.has(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 (allProxies.has(v)) return v;
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 args = spec.pre ? spec.pre(rawArgs, wrap, known) : rawArgs;
266
- const result = Reflect[trap](...args);
267
- const output = spec.post ? spec.post(result, args, wrap) : result;
268
- config.write({
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: serializeOrigin(childOrigin),
272
- args: args.map((arg) => serialize(arg, graph)),
273
- result: serialize(output, graph)
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, origin, proxyId);
281
- graphOf.set(pxy, graph);
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 { stream, callback } = options;
287
- const write = stream ? (r) => stream.write(`${JSON.stringify(r)}
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
- return makeProxy(target, graph, { write, recursive, only }, null);
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) && allProxies.has(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