flugrekorder 1.0.1 → 1.0.2-beta.1

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.
@@ -72,6 +72,8 @@ var Flugrekorder = (() => {
72
72
  _generator = new WeakMap();
73
73
  var graphOf = /* @__PURE__ */ new WeakMap();
74
74
  var allProxies = /* @__PURE__ */ new WeakSet();
75
+ var slotProtos = /* @__PURE__ */ new WeakMap();
76
+ var bindCache = /* @__PURE__ */ new WeakMap();
75
77
  function isProxiable(value) {
76
78
  return value !== null && (typeof value === "object" || typeof value === "function");
77
79
  }
@@ -106,9 +108,66 @@ var Flugrekorder = (() => {
106
108
  return { trap: o.trap, parent: o.parent, key: String(o.key) };
107
109
  return o;
108
110
  }
111
+ var slotError = /incompatible receiver|this is not/i;
112
+ function hasInternalSlots(target) {
113
+ if (typeof target !== "object" || target === null) return false;
114
+ const direct = Object.getPrototypeOf(target);
115
+ if (!direct) return false;
116
+ if (slotProtos.has(direct)) return slotProtos.get(direct);
117
+ const probe = new Proxy(target, {
118
+ set: () => true,
119
+ defineProperty: () => true,
120
+ deleteProperty: () => true,
121
+ setPrototypeOf: () => true
122
+ });
123
+ let proto = direct;
124
+ while (proto && proto !== Object.prototype) {
125
+ for (const key of Object.getOwnPropertyNames(proto)) {
126
+ if (key === "constructor") continue;
127
+ const desc = Object.getOwnPropertyDescriptor(proto, key);
128
+ const fn = desc?.get ?? (typeof desc?.value === "function" ? desc.value : null);
129
+ if (fn) {
130
+ let slots = false;
131
+ try {
132
+ fn.call(probe);
133
+ } catch (e) {
134
+ if (e instanceof TypeError && slotError.test(String(e))) slots = true;
135
+ }
136
+ slotProtos.set(direct, slots);
137
+ return slots;
138
+ }
139
+ }
140
+ proto = Object.getPrototypeOf(proto);
141
+ }
142
+ slotProtos.set(direct, false);
143
+ return false;
144
+ }
145
+ 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);
150
+ }
109
151
  var specs = {
110
152
  get: {
111
- post: (result, [, key], wrap) => key === "prototype" ? result : wrap(result)
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));
168
+ }
169
+ return wrap(result);
170
+ }
112
171
  },
113
172
  set: {
114
173
  pre: ([target, key, value, receiver], wrap) => [
@@ -1 +1 @@
1
- {"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\tpost: (result, [, key], wrap) =>\n\t\t\tkey === 'prototype' ? result : wrap(result),\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
1
+ {"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// Per-prototype cache: true if any getter on this prototype (or its chain)\n// throws TypeError when called through a blank Proxy — the signature of an\n// internal slot check. Keyed by the direct prototype of the proxied target\n// so all instances of the same type share one probe result.\nconst slotProtos = new WeakMap<object, boolean>();\n\n// Stable bound-method cache: (target, key) → fn.bind(target).\n// Ensures the same proxied bound function is returned every time the same\n// method is accessed on the same target — required for graph proxy stability.\nconst bindCache = new WeakMap<object, Map<PropertyKey, Function>>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Internal slot detection ──────────────────────────────────────────────────\n\n/**\n * Returns true if `target`'s prototype chain contains a getter that throws\n * TypeError when called through a Proxy — the JS-observable signature of an\n * ECMAScript internal slot check (e.g. Map, Set, WeakMap, WeakSet, Date).\n * Result is cached per prototype so the probe runs at most once per type.\n */\n// Slot-check TypeErrors have specific messages; filter by them to avoid\n// misclassifying TypeErrors thrown for other reasons (e.g. wrong arg count).\nconst slotError = /incompatible receiver|this is not/i;\n\nfunction hasInternalSlots(target: Proxiable): boolean {\n\tif (typeof target !== 'object' || target === null) return false;\n\n\tconst direct = Object.getPrototypeOf(target as object) as object | null;\n\tif (!direct) return false;\n\tif (slotProtos.has(direct)) return slotProtos.get(direct)!;\n\n\tconst probe = new Proxy(target as object, {\n\t\tset: () => true,\n\t\tdefineProperty: () => true,\n\t\tdeleteProperty: () => true,\n\t\tsetPrototypeOf: () => true,\n\t});\n\tlet proto: object | null = direct;\n\n\twhile (proto && proto !== Object.prototype) {\n\t\tfor (const key of Object.getOwnPropertyNames(proto)) {\n\t\t\tif (key === 'constructor') continue;\n\t\t\tconst desc = Object.getOwnPropertyDescriptor(proto, key);\n\t\t\tconst fn =\n\t\t\t\tdesc?.get ??\n\t\t\t\t(typeof desc?.value === 'function' ? (desc.value as Function) : null);\n\t\t\tif (fn) {\n\t\t\t\tlet slots = false;\n\t\t\t\ttry {\n\t\t\t\t\tfn.call(probe);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (e instanceof TypeError && slotError.test(String(e))) slots = true;\n\t\t\t\t}\n\t\t\t\tslotProtos.set(direct, slots);\n\t\t\t\treturn slots;\n\t\t\t}\n\t\t}\n\t\tproto = Object.getPrototypeOf(proto) as object | null;\n\t}\n\n\tslotProtos.set(direct, false);\n\treturn false;\n}\n\n/** Returns a stable bound version of `fn` for `(target, key)` — created once, reused on every access. */\nfunction boundMethod(target: object, key: PropertyKey, fn: Function): Function {\n\tif (!bindCache.has(target)) bindCache.set(target, new Map());\n\tconst cache = bindCache.get(target)!;\n\tif (!cache.has(key)) cache.set(key, fn.bind(target));\n\treturn cache.get(key)!;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\t// For targets with internal slots (Map, Set, WeakMap, WeakSet, Date …),\n\t\t// use the real target as the Reflect.get receiver so that getter-based\n\t\t// slot checks (e.g. Map.prototype.size) don't throw TypeError.\n\t\tpre: ([target, key, receiver], _wrap, _known) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\thasInternalSlots(target as Proxiable) ? target : receiver,\n\t\t],\n\t\t// For the same targets, bind method results to the real target before\n\t\t// wrapping so that apply-level slot checks (e.g. Map.prototype.get)\n\t\t// also pass. The bind cache ensures proxy stability.\n\t\tpost: (result, [target, key], wrap) => {\n\t\t\tif (key === 'prototype') return result;\n\t\t\tif (typeof result === 'function' && hasInternalSlots(target as Proxiable)) {\n\t\t\t\treturn wrap(boundMethod(target as object, key as PropertyKey, result));\n\t\t\t}\n\t\t\treturn wrap(result);\n\t\t},\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
@@ -72,6 +72,8 @@ _byTarget = new WeakMap();
72
72
  _generator = new WeakMap();
73
73
  var graphOf = /* @__PURE__ */ new WeakMap();
74
74
  var allProxies = /* @__PURE__ */ new WeakSet();
75
+ var slotProtos = /* @__PURE__ */ new WeakMap();
76
+ var bindCache = /* @__PURE__ */ new WeakMap();
75
77
  function isProxiable(value) {
76
78
  return value !== null && (typeof value === "object" || typeof value === "function");
77
79
  }
@@ -106,9 +108,66 @@ function serializeOrigin(o) {
106
108
  return { trap: o.trap, parent: o.parent, key: String(o.key) };
107
109
  return o;
108
110
  }
111
+ var slotError = /incompatible receiver|this is not/i;
112
+ function hasInternalSlots(target) {
113
+ if (typeof target !== "object" || target === null) return false;
114
+ const direct = Object.getPrototypeOf(target);
115
+ if (!direct) return false;
116
+ if (slotProtos.has(direct)) return slotProtos.get(direct);
117
+ const probe = new Proxy(target, {
118
+ set: () => true,
119
+ defineProperty: () => true,
120
+ deleteProperty: () => true,
121
+ setPrototypeOf: () => true
122
+ });
123
+ let proto = direct;
124
+ while (proto && proto !== Object.prototype) {
125
+ for (const key of Object.getOwnPropertyNames(proto)) {
126
+ if (key === "constructor") continue;
127
+ const desc = Object.getOwnPropertyDescriptor(proto, key);
128
+ const fn = desc?.get ?? (typeof desc?.value === "function" ? desc.value : null);
129
+ if (fn) {
130
+ let slots = false;
131
+ try {
132
+ fn.call(probe);
133
+ } catch (e) {
134
+ if (e instanceof TypeError && slotError.test(String(e))) slots = true;
135
+ }
136
+ slotProtos.set(direct, slots);
137
+ return slots;
138
+ }
139
+ }
140
+ proto = Object.getPrototypeOf(proto);
141
+ }
142
+ slotProtos.set(direct, false);
143
+ return false;
144
+ }
145
+ 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);
150
+ }
109
151
  var specs = {
110
152
  get: {
111
- post: (result, [, key], wrap) => key === "prototype" ? result : wrap(result)
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));
168
+ }
169
+ return wrap(result);
170
+ }
112
171
  },
113
172
  set: {
114
173
  pre: ([target, key, value, receiver], wrap) => [
@@ -1 +1 @@
1
- {"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\tpost: (result, [, key], wrap) =>\n\t\t\tkey === 'prototype' ? result : wrap(result),\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
1
+ {"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// Per-prototype cache: true if any getter on this prototype (or its chain)\n// throws TypeError when called through a blank Proxy — the signature of an\n// internal slot check. Keyed by the direct prototype of the proxied target\n// so all instances of the same type share one probe result.\nconst slotProtos = new WeakMap<object, boolean>();\n\n// Stable bound-method cache: (target, key) → fn.bind(target).\n// Ensures the same proxied bound function is returned every time the same\n// method is accessed on the same target — required for graph proxy stability.\nconst bindCache = new WeakMap<object, Map<PropertyKey, Function>>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Internal slot detection ──────────────────────────────────────────────────\n\n/**\n * Returns true if `target`'s prototype chain contains a getter that throws\n * TypeError when called through a Proxy — the JS-observable signature of an\n * ECMAScript internal slot check (e.g. Map, Set, WeakMap, WeakSet, Date).\n * Result is cached per prototype so the probe runs at most once per type.\n */\n// Slot-check TypeErrors have specific messages; filter by them to avoid\n// misclassifying TypeErrors thrown for other reasons (e.g. wrong arg count).\nconst slotError = /incompatible receiver|this is not/i;\n\nfunction hasInternalSlots(target: Proxiable): boolean {\n\tif (typeof target !== 'object' || target === null) return false;\n\n\tconst direct = Object.getPrototypeOf(target as object) as object | null;\n\tif (!direct) return false;\n\tif (slotProtos.has(direct)) return slotProtos.get(direct)!;\n\n\tconst probe = new Proxy(target as object, {\n\t\tset: () => true,\n\t\tdefineProperty: () => true,\n\t\tdeleteProperty: () => true,\n\t\tsetPrototypeOf: () => true,\n\t});\n\tlet proto: object | null = direct;\n\n\twhile (proto && proto !== Object.prototype) {\n\t\tfor (const key of Object.getOwnPropertyNames(proto)) {\n\t\t\tif (key === 'constructor') continue;\n\t\t\tconst desc = Object.getOwnPropertyDescriptor(proto, key);\n\t\t\tconst fn =\n\t\t\t\tdesc?.get ??\n\t\t\t\t(typeof desc?.value === 'function' ? (desc.value as Function) : null);\n\t\t\tif (fn) {\n\t\t\t\tlet slots = false;\n\t\t\t\ttry {\n\t\t\t\t\tfn.call(probe);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (e instanceof TypeError && slotError.test(String(e))) slots = true;\n\t\t\t\t}\n\t\t\t\tslotProtos.set(direct, slots);\n\t\t\t\treturn slots;\n\t\t\t}\n\t\t}\n\t\tproto = Object.getPrototypeOf(proto) as object | null;\n\t}\n\n\tslotProtos.set(direct, false);\n\treturn false;\n}\n\n/** Returns a stable bound version of `fn` for `(target, key)` — created once, reused on every access. */\nfunction boundMethod(target: object, key: PropertyKey, fn: Function): Function {\n\tif (!bindCache.has(target)) bindCache.set(target, new Map());\n\tconst cache = bindCache.get(target)!;\n\tif (!cache.has(key)) cache.set(key, fn.bind(target));\n\treturn cache.get(key)!;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\t// For targets with internal slots (Map, Set, WeakMap, WeakSet, Date …),\n\t\t// use the real target as the Reflect.get receiver so that getter-based\n\t\t// slot checks (e.g. Map.prototype.size) don't throw TypeError.\n\t\tpre: ([target, key, receiver], _wrap, _known) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\thasInternalSlots(target as Proxiable) ? target : receiver,\n\t\t],\n\t\t// For the same targets, bind method results to the real target before\n\t\t// wrapping so that apply-level slot checks (e.g. Map.prototype.get)\n\t\t// also pass. The bind cache ensures proxy stability.\n\t\tpost: (result, [target, key], wrap) => {\n\t\t\tif (key === 'prototype') return result;\n\t\t\tif (typeof result === 'function' && hasInternalSlots(target as Proxiable)) {\n\t\t\t\treturn wrap(boundMethod(target as object, key as PropertyKey, result));\n\t\t\t}\n\t\t\treturn wrap(result);\n\t\t},\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
@@ -43,6 +43,8 @@ _byTarget = new WeakMap();
43
43
  _generator = new WeakMap();
44
44
  var graphOf = /* @__PURE__ */ new WeakMap();
45
45
  var allProxies = /* @__PURE__ */ new WeakSet();
46
+ var slotProtos = /* @__PURE__ */ new WeakMap();
47
+ var bindCache = /* @__PURE__ */ new WeakMap();
46
48
  function isProxiable(value) {
47
49
  return value !== null && (typeof value === "object" || typeof value === "function");
48
50
  }
@@ -77,9 +79,66 @@ function serializeOrigin(o) {
77
79
  return { trap: o.trap, parent: o.parent, key: String(o.key) };
78
80
  return o;
79
81
  }
82
+ var slotError = /incompatible receiver|this is not/i;
83
+ function hasInternalSlots(target) {
84
+ if (typeof target !== "object" || target === null) return false;
85
+ const direct = Object.getPrototypeOf(target);
86
+ if (!direct) return false;
87
+ if (slotProtos.has(direct)) return slotProtos.get(direct);
88
+ const probe = new Proxy(target, {
89
+ set: () => true,
90
+ defineProperty: () => true,
91
+ deleteProperty: () => true,
92
+ setPrototypeOf: () => true
93
+ });
94
+ let proto = direct;
95
+ while (proto && proto !== Object.prototype) {
96
+ for (const key of Object.getOwnPropertyNames(proto)) {
97
+ if (key === "constructor") continue;
98
+ const desc = Object.getOwnPropertyDescriptor(proto, key);
99
+ const fn = desc?.get ?? (typeof desc?.value === "function" ? desc.value : null);
100
+ if (fn) {
101
+ let slots = false;
102
+ try {
103
+ fn.call(probe);
104
+ } catch (e) {
105
+ if (e instanceof TypeError && slotError.test(String(e))) slots = true;
106
+ }
107
+ slotProtos.set(direct, slots);
108
+ return slots;
109
+ }
110
+ }
111
+ proto = Object.getPrototypeOf(proto);
112
+ }
113
+ slotProtos.set(direct, false);
114
+ return false;
115
+ }
116
+ function boundMethod(target, key, fn) {
117
+ if (!bindCache.has(target)) bindCache.set(target, /* @__PURE__ */ new Map());
118
+ const cache = bindCache.get(target);
119
+ if (!cache.has(key)) cache.set(key, fn.bind(target));
120
+ return cache.get(key);
121
+ }
80
122
  var specs = {
81
123
  get: {
82
- post: (result, [, key], wrap) => key === "prototype" ? result : wrap(result)
124
+ // For targets with internal slots (Map, Set, WeakMap, WeakSet, Date …),
125
+ // use the real target as the Reflect.get receiver so that getter-based
126
+ // slot checks (e.g. Map.prototype.size) don't throw TypeError.
127
+ pre: ([target, key, receiver], _wrap, _known) => [
128
+ target,
129
+ key,
130
+ hasInternalSlots(target) ? target : receiver
131
+ ],
132
+ // For the same targets, bind method results to the real target before
133
+ // wrapping so that apply-level slot checks (e.g. Map.prototype.get)
134
+ // also pass. The bind cache ensures proxy stability.
135
+ post: (result, [target, key], wrap) => {
136
+ if (key === "prototype") return result;
137
+ if (typeof result === "function" && hasInternalSlots(target)) {
138
+ return wrap(boundMethod(target, key, result));
139
+ }
140
+ return wrap(result);
141
+ }
83
142
  },
84
143
  set: {
85
144
  pre: ([target, key, value, receiver], wrap) => [
@@ -1 +1 @@
1
- {"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\tpost: (result, [, key], wrap) =>\n\t\t\tkey === 'prototype' ? result : wrap(result),\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":";;;;;;;;;AAAA;AAsFA,IAAM,QAAN,MAAY;AAAA,EAMX,YAAY,IAA6B;AALzC,8BAAQ,oBAAI,IAAuB;AACnC,iCAAW,oBAAI,QAA8B;AAC7C,kCAAY,oBAAI,QAA8B;AAC9C;AAGC,QAAI,UAAU,OAAO,OAAO,WAAW,KAAK;AAE5C,uBAAK,YAAa,OAAO,OAAO,aAAa,KAAK,MAAM,IAAI,EAAE,OAAO;AAAA,EACtE;AAAA,EAEA,SAAiB;AAChB,WAAO,mBAAK,YAAL;AAAA,EACR;AAAA,EAEA,WAAW,GAAqC;AAC/C,WAAO,mBAAK,UAAS,IAAI,CAAC;AAAA,EAC3B;AAAA,EACA,YAAY,GAAqC;AAChD,WAAO,mBAAK,WAAU,IAAI,CAAC;AAAA,EAC5B;AAAA,EACA,QAAQ,IAAmC;AAC1C,WAAO,mBAAK,OAAM,IAAI,EAAE;AAAA,EACzB;AAAA,EAEA,SACC,OACA,QACA,QACA,IACY;AACZ,UAAM,OAAkB,EAAE,IAAI,OAAO,QAAQ,OAAO;AAEpD,uBAAK,OAAM,IAAI,IAAI,IAAI;AACvB,uBAAK,UAAS,IAAI,OAAO,IAAI;AAC7B,uBAAK,WAAU,IAAI,QAAQ,IAAI;AAE/B,WAAO;AAAA,EACR;AACD;AAvCC;AACA;AACA;AACA;AAwCD,IAAM,UAAU,oBAAI,QAA0B;AAI9C,IAAM,aAAa,oBAAI,QAAmB;AAK1C,SAAS,YAAY,OAAoC;AACxD,SACC,UAAU,SACT,OAAO,UAAU,YAAY,OAAO,UAAU;AAEjD;AASA,SAAS,mBACR,GACA,OACA,MACa;AAIb,QAAM,OACL,MAAM,WAAsB,CAAC,KAAK,MAAM,YAAuB,CAAC;AAEjE,MAAI,SAAS,OAAW,QAAO,EAAE,QAAQ,KAAK,GAAG;AAEjD,MAAI,MAAM,QAAQ,CAAC;AAClB,WAAwB,EAAG,IAAI,CAAC,SAAS,UAAU,MAAM,OAAO,IAAI,CAAC;AAEtE,MAAI,KAAK,IAAI,CAAC,EAAG,QAAO,EAAE,QAAQ,IAAI;AAEtC,OAAK,IAAI,CAAC;AAEV,QAAM,SAAS,OAAO;AAAA,IACrB,OAAO,QAAgB,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,GAAG,MAAM;AAAA,MAC3C;AAAA,MACA,UAAU,KAAK,OAAO,IAAI;AAAA,IAC3B,CAAC;AAAA,EACF;AAEA,OAAK,OAAO,CAAC;AAEb,SAAO;AACR;AAGA,IAAM,WAA2B;AAAA,EAChC,EAAE,OAAO,yBAAyB,KAAK,CAAC,MAAkB,EAAE;AAAA,EAC5D,EAAE,OAAO,mBAAmB,KAAK,mBAAmB;AACrD;AAGA,SAAS,UACR,GACA,OACA,OAAO,oBAAI,IAAa,GACX;AACb,MAAI,MAAM,QAAQ,MAAM,OAAW,QAAO;AAE1C,QAAM,EAAE,MAAM,OAAO,IACpB,SAAS,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM,KAAK,OAAO,CAAC,CAAC,KAAK,CAAC;AAExD,SAAO,IAAI,GAAG,OAAO,IAAI;AAC1B;AAGA,SAAS,gBAAgB,GAA6B;AACrD,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,SAAS;AACZ,WAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,QAAQ,KAAK,OAAO,EAAE,GAAG,EAAE;AAE7D,SAAO;AACR;AAKA,IAAM,QAAuC;AAAA,EAC5C,KAAK;AAAA,IACJ,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,GAAG,SACvB,QAAQ,cAAc,SAAS,KAAK,MAAM;AAAA,EAC5C;AAAA,EACA,KAAK;AAAA,IACJ,KAAK,CAAC,CAAC,QAAQ,KAAK,OAAO,QAAQ,GAAG,SAAS;AAAA,MAC9C;AAAA,MACA;AAAA,MACA,KAAK,KAAK;AAAA,MACV;AAAA,IACD;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAAA;AAAA;AAAA,IAIN,KAAK,CAAC,CAAC,QAAQ,SAAS,QAAQ,GAAG,MAAM,UAAU;AAAA,MAClD;AAAA,MACA,KAAK,OAAO;AAAA,MACK,SAAU,IAAI,KAAK;AAAA,IACrC;AAAA,IACA,MAAM,CAAC,QAAQ,OAAO,SAAS,KAAK,MAAM;AAAA,EAC3C;AAAA,EACA,WAAW;AAAA,IACV,KAAK,CAAC,CAAC,QAAQ,UAAU,SAAS,GAAG,SAAS;AAAA,MAC7C;AAAA,MACiB,SAAU,IAAI,IAAI;AAAA,MACnC;AAAA,IACD;AAAA,IACA,MAAM,CAAC,QAAQ,OAAO,SAAS,KAAK,MAAM;AAAA,EAC3C;AAAA,EACA,gBAAgB;AAAA,IACf,KAAK,CAAC,MAAM,SAAS;AACpB,YAAM,CAAC,QAAQ,KAAK,UAAU,IAE7B;AACD,YAAM,QAA4B,CAAC;AAEnC,UAAI,WAAW,SAAS,KAAM,OAAM,QAAQ,KAAK,WAAW,KAAK;AACjE,UAAI,OAAO,WAAW,QAAQ;AAC7B,cAAM,MAAqB,KAAK,WAAW,GAAG;AAC/C,UAAI,OAAO,WAAW,QAAQ;AAC7B,cAAM,MAA4B,KAAK,WAAW,GAAG;AAEtD,aAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAChC,CAAC,QAAQ,KAAK,EAAE,GAAG,YAAY,GAAG,MAAM,CAAC,IACzC;AAAA,IACJ;AAAA,EACD;AAAA,EACA,0BAA0B;AAAA,IACzB,MAAM,CAAC,QAAQ,OAAO,SAAS;AAC9B,YAAM,OAAuC;AAE7C,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,QAA4B,CAAC;AAEnC,UAAI,KAAK,SAAS,KAAM,OAAM,QAAQ,KAAK,KAAK,KAAK;AACrD,UAAI,OAAO,KAAK,QAAQ;AACvB,cAAM,MAAqB,KAAK,KAAK,GAAG;AACzC,UAAI,OAAO,KAAK,QAAQ;AACvB,cAAM,MAA4B,KAAK,KAAK,GAAG;AAEhD,aAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAChC,EAAE,GAAG,MAAM,GAAG,MAAM,IACpB;AAAA,IACJ;AAAA,EACD;AACD;AASA,SAAS,UACR,QACA,OACA,QACA,QACI;AAEJ,MAAI,WAAW,IAAe,MAAM,EAAG,QAAO;AAG9C,QAAM,WAAW,MAAM,YAAuB,MAAM;AAEpD,MAAI,SAAU,QAAU,SAAS;AAKjC,MAAI,kBAAkB,SAAS;AAC9B,UAAM,UAEJ,OAAO;AAAA,MAAK,CAAC,UACZ,YAAY,KAAK,IACd,UAAqB,OAAO,OAAO,QAAQ,MAAM,IACjD;AAAA,IACJ;AAIF,UAAM,KAAK,MAAM,OAAO;AAExB,UAAM,SAAoB,SAAoB,QAAQ,QAAQ,EAAE;AAChE,YAAQ,IAAe,SAAS,KAAK;AAErC,WAAO;AAAA,EACR;AAEA,QAAM,UAAU,MAAM,OAAO;AAE7B,MAAI;AAEJ,QAAM,QACL,OAAO,oBAAoB,OAAO,EAChC,OAAO,CAAC,SAAS,OAAO,SAAS,QAAQ,OAAO,KAAK,IAAI,IAAI,CAAC;AAEjE,QAAM,UAAmC,OAAO;AAAA,IAC/C,MAAM,IAAI,CAAC,SAAS;AAAA,MACnB;AAAA,MACA,IAAI,YAA4B;AAC/B,cAAM,SAAqB,MAAM,WAAW,GAAG,EAAG;AAElD,cAAM,cACL,kDAAkD,KAAK,IAAI,IACxD;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR,KAAsB,QAAQ,CAAC;AAAA,QAChC,IACC,kBAAkB,KAAK,IAAI,IAC1B,EAAE,MAAsB,QAAQ,OAAO,IACvC;AAEL,cAAM,OAAgB,CAAC,MAAM;AAC5B,cAAI,CAAC,YAAY,CAAC,KAAK,WAAW,IAAe,CAAC;AACjD,mBAAO;AACR,cAAI,CAAC,OAAO,UAAW,QAAO;AAE9B,iBAAO,UAAqB,GAAG,OAAO,QAAQ,WAAW;AAAA,QAC1D;AAGA,cAAM,QAAiB,CAAC,MAAM;AAC7B,cAAI,CAAC,YAAY,CAAC,EAAG,QAAO;AAC5B,cAAI,WAAW,IAAe,CAAC,EAAG,QAAO;AAEzC,gBAAMA,YAAW,MAAM,YAAuB,CAAC;AAE/C,cAAIA,UAAU,QAAOA,UAAS;AAE9B,iBAAO;AAAA,QACR;AAEA,cAAM,OAAO,MAAM,IAAI,KAAK,CAAC;AAC7B,cAAM,OAAO,KAAK,MACf,KAAK,IAAI,SAAS,MAAM,KAAK,IAC7B;AAEH,cAAM,SAAoB,QAAQ,IAAI,EAAG,GAAG,IAAI;AAChD,cAAM,SAAS,KAAK,OACjB,KAAK,KAAK,QAAQ,MAAM,IAAI,IAC5B;AAEH,eAAO,MAAM;AAAA,UACZ,IAAI,MAAM,OAAO;AAAA,UACjB;AAAA,UACA,QAAQ,gBAAgB,WAAW;AAAA,UACnC,MAAM,KAAK,IAAI,CAAC,QAAQ,UAAU,KAAK,KAAK,CAAC;AAAA,UAC7C,QAAQ,UAAU,QAAQ,KAAK;AAAA,QAChC,CAAC;AAED,eAAO;AAAA,MACR;AAAA,IACD,CAAC;AAAA,EACF;AAEA,QAAmB,IAAI,MAAiB,QAAQ,OAAO;AAEvD,QAAM,SAAoB,KAAgB,QAAQ,QAAQ,OAAO;AACjE,UAAQ,IAAe,KAAK,KAAK;AACjC,aAAW,IAAe,GAAG;AAE7B,SAAO;AACR;AAiBO,SAAS,OACf,QACA,SACI;AACJ,QAAM,EAAE,QAAQ,SAAS,IAAI;AAC7B,QAAM,QAAgC,SACnC,CAAC,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,CAAC,CAAC;AAAA,CAAI;AAAA;AAAA,IAE7C;AAAA;AACF,QAAM,YAAY,QAAQ,cAAc;AACxC,QAAM,OAAO,QAAQ,OAAO,IAAI,IAAI,QAAQ,IAAI,IAAI;AACpD,QAAM,QAAQ,IAAI,MAAM,QAAQ,MAAM,CAAC;AAEvC,SAAO,UAAU,QAAQ,OAAO,EAAE,OAAO,WAAW,KAAK,GAAG,IAAI;AACjE;AAGO,SAAS,eAAe,OAAoC;AAClE,SAAO,YAAY,KAAK,KAAK,WAAW,IAAe,KAAK;AAC7D;AAGO,SAAS,UAAU,KAAkC;AAC3D,SAAO,QAAQ,IAAI,GAAG,GAAG,WAAW,GAAG,GAAG,UAAU;AACrD;AAMO,SAAS,aACf,IACA,KACwB;AACxB,SAAO,QAAQ,IAAI,GAAG,GAAG,QAAQ,EAAE,GAAG;AACvC;AAGO,SAAS,UAAU,KAAwB;AACjD,SAAO,QAAQ,IAAI,GAAG,GAAG,WAAW,GAAG,GAAG,UAAU;AACrD;AAOO,SAAS,aACf,KAC8C;AAC9C,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAE7B,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,QAAM,SAAsD,CAAC;AAC7D,MAAI,OAAO,MAAM,WAAW,GAAG;AAE/B,SAAO,MAAM;AACZ,WAAO,QAAQ,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AACzD,QAAI,CAAC,KAAK,OAAQ;AAElB,UAAM,WACL,YAAY,KAAK,SAAS,KAAK,OAAO,SAAS,KAAK,OAAO;AAE5D,WAAO,MAAM,QAAQ,QAAQ;AAAA,EAC9B;AAEA,SAAO;AACR;AAOO,SAAS,QAAQ,KAAwB;AAC/C,QAAM,YAAY,aAAa,GAAG;AAClC,QAAM,QAAuB,CAAC;AAE9B,aAAW,EAAE,QAAQ,EAAE,KAAK,WAAW;AACtC,QAAI,CAAC,EAAG;AACR,QAAI,SAAS,GAAG;AACf,YAAM,KAAK,OAAO,EAAE,GAAG,CAAC;AAAA,IACzB,OAAO;AACN,UAAI,MAAM,SAAS,GAAG;AACrB,cAAM,MAAM,SAAS,CAAC,KAAK;AAAA,MAC5B,OAAO;AACN,cAAM,KAAK,IAAI;AAAA,MAChB;AAAA,IACD;AAAA,EACD;AAEA,SAAO,MAAM,KAAK,GAAG;AACtB;","names":["existing"]}
1
+ {"version":3,"sources":["../source/flugrekorder.ts"],"sourcesContent":["import type { Writable } from 'node:stream';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Any value that can be wrapped in a Proxy — objects and functions. */\n// biome-ignore lint/complexity/noBannedTypes: Function is intentional — Proxiable must accept any callable\nexport type Proxiable = object | Function;\n\n/** Reflect traps that operate on a property — carry a parent ID and key in their origin. */\nexport type PropertyTrap =\n\t| 'get'\n\t| 'set'\n\t| 'defineProperty'\n\t| 'getOwnPropertyDescriptor';\n\n/** Reflect traps that invoke a callable — carry a source ID in their origin. */\nexport type CallTrap = 'apply' | 'construct';\n\n/** Describes how a proxy was created — which trap fired, on which parent, and under which key or source. Null for root proxies. */\nexport type Origin =\n\t| { trap: PropertyTrap; parent: string; key: string | symbol }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** Origin with symbol keys coerced to strings — safe to include in a Rekording. */\ntype SerializedOrigin =\n\t| { trap: PropertyTrap; parent: string; key: string }\n\t| { trap: CallTrap; source: string }\n\t| null;\n\n/** A JSON-safe representation of any value. Proxiable values are replaced with `{ $proxy: id }` tags. */\nexport type Serialized =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| null\n\t| undefined\n\t| { readonly $proxy: string }\n\t| Array<Serialized>\n\t| { [key: string]: Serialized };\n\n/** A single recorded interaction — one Reflect trap firing on one proxy. */\nexport type Rekording = {\n\tid: string;\n\ttrap: string;\n\torigin: SerializedOrigin;\n\targs: Array<Serialized>;\n\tresult: Serialized;\n};\n\n/** Resolved runtime configuration — derived from CreateOptions and passed through the proxy factory. */\ntype Config = {\n\twrite: (r: Rekording) => void;\n\trecursive: boolean;\n\tonly: Set<string> | null;\n};\n\n/** A function that conditionally wraps a value in a proxy. */\ntype Wrapper = (v: unknown) => unknown;\n\n/** Pre/post hooks for a Reflect trap — transform args before dispatch and/or wrap the result. */\ntype Spec = {\n\tpre?: (\n\t\targs: Array<unknown>,\n\t\twrap: Wrapper,\n\t\tknown: Wrapper,\n\t) => Array<unknown>;\n\tpost?: (result: unknown, args: Array<unknown>, wrap: Wrapper) => unknown;\n};\n\n// ─── Graph ────────────────────────────────────────────────────────────────────\n\n/** A node in the proxy graph — links a proxy to its original target, its origin, and its ID. */\ntype GraphNode = {\n\treadonly id: string;\n\treadonly proxy: Proxiable;\n\treadonly target: Proxiable;\n\treadonly origin: Origin;\n};\n\n/**\n * Session-scoped proxy registry.\n * Each `create()` call produces its own Graph so proxied trees are\n * independent and GC-eligible once no longer referenced.\n */\nclass Graph {\n\t#byId = new Map<string, GraphNode>();\n\t#byProxy = new WeakMap<Proxiable, GraphNode>();\n\t#byTarget = new WeakMap<Proxiable, GraphNode>();\n\t#generator: () => string;\n\n\tconstructor(id: number | (() => string)) {\n\t\tlet counter = typeof id === 'number' ? id : 0;\n\n\t\tthis.#generator = typeof id === 'function' ? id : () => `#${++counter}`;\n\t}\n\n\tnextId(): string {\n\t\treturn this.#generator();\n\t}\n\n\tgetByProxy(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byProxy.get(v);\n\t}\n\tgetByTarget(v: Proxiable): GraphNode | undefined {\n\t\treturn this.#byTarget.get(v);\n\t}\n\tgetById(id: string): GraphNode | undefined {\n\t\treturn this.#byId.get(id);\n\t}\n\n\tregister(\n\t\tproxy: Proxiable,\n\t\ttarget: Proxiable,\n\t\torigin: Origin,\n\t\tid: string,\n\t): GraphNode {\n\t\tconst node: GraphNode = { id, proxy, target, origin };\n\n\t\tthis.#byId.set(id, node);\n\t\tthis.#byProxy.set(proxy, node);\n\t\tthis.#byTarget.set(target, node);\n\n\t\treturn node;\n\t}\n}\n\n// Module-level weak index: proxy → owning graph.\n// WeakMap — does not prevent GC of either the proxy or the graph.\nconst graphOf = new WeakMap<Proxiable, Graph>();\n\n// All known proxies across all graphs — guards against double-wrapping.\n// WeakSet — does not prevent GC.\nconst allProxies = new WeakSet<Proxiable>();\n\n// Per-prototype cache: true if any getter on this prototype (or its chain)\n// throws TypeError when called through a blank Proxy — the signature of an\n// internal slot check. Keyed by the direct prototype of the proxied target\n// so all instances of the same type share one probe result.\nconst slotProtos = new WeakMap<object, boolean>();\n\n// Stable bound-method cache: (target, key) → fn.bind(target).\n// Ensures the same proxied bound function is returned every time the same\n// method is accessed on the same target — required for graph proxy stability.\nconst bindCache = new WeakMap<object, Map<PropertyKey, Function>>();\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\n/** Returns true for any value that can meaningfully be wrapped in a Proxy. */\nfunction isProxiable(value: unknown): value is Proxiable {\n\treturn (\n\t\tvalue !== null &&\n\t\t(typeof value === 'object' || typeof value === 'function')\n\t);\n}\n\n/** Maps a typeof pattern to a serialization handler. */\ntype Mapping = {\n\tmatch: RegExp;\n\tmap: (v: unknown, graph: Graph, seen: Set<unknown>) => Serialized;\n};\n\n/** Serializes an object or function value — tags known proxies by ID, inlines arrays and plain objects. */\nfunction serializeProxiable(\n\tv: unknown,\n\tgraph: Graph,\n\tseen: Set<unknown>,\n): Serialized {\n\t// Check for a known proxy BEFORE Array.isArray: iterating a proxied\n\t// array via its proxy triggers get traps which call serialize again,\n\t// causing infinite recursion. A proxy is always tagged by ID.\n\tconst node =\n\t\tgraph.getByProxy(<Proxiable>v) ?? graph.getByTarget(<Proxiable>v);\n\n\tif (node !== undefined) return { $proxy: node.id };\n\t// Plain (unproxied) arrays are safe to iterate directly.\n\tif (Array.isArray(v))\n\t\treturn (<Array<unknown>>v).map((item) => serialize(item, graph, seen));\n\t// Plain (unproxied) objects: serialize by value with a circular-reference guard.\n\tif (seen.has(v)) return { $proxy: '?' };\n\n\tseen.add(v);\n\n\tconst result = Object.fromEntries(\n\t\tObject.entries(<object>v).map(([k, val]) => [\n\t\t\tk,\n\t\t\tserialize(val, graph, seen),\n\t\t]),\n\t);\n\n\tseen.delete(v);\n\n\treturn result;\n}\n\n/** Ordered serialization handlers — first match wins; unmatched values fall through to String(). */\nconst mappings: Array<Mapping> = [\n\t{ match: /number|boolean|bigint/, map: (v) => <Serialized>v },\n\t{ match: /object|function/, map: serializeProxiable },\n];\n\n/** Converts any value to a JSON-safe Serialized form, tagging graph members by ID. */\nfunction serialize(\n\tv: unknown,\n\tgraph: Graph,\n\tseen = new Set<unknown>(),\n): Serialized {\n\tif (v === null || v === undefined) return v;\n\n\tconst { map = String } =\n\t\tmappings.find(({ match }) => match.test(typeof v)) ?? {};\n\n\treturn map(v, graph, seen);\n}\n\n/** Converts an Origin to its serialized form — coerces symbol keys to strings. */\nfunction serializeOrigin(o: Origin): SerializedOrigin {\n\tif (!o) return null;\n\tif ('key' in o)\n\t\treturn { trap: o.trap, parent: o.parent, key: String(o.key) };\n\n\treturn o;\n}\n\n// ─── Internal slot detection ──────────────────────────────────────────────────\n\n/**\n * Returns true if `target`'s prototype chain contains a getter that throws\n * TypeError when called through a Proxy — the JS-observable signature of an\n * ECMAScript internal slot check (e.g. Map, Set, WeakMap, WeakSet, Date).\n * Result is cached per prototype so the probe runs at most once per type.\n */\n// Slot-check TypeErrors have specific messages; filter by them to avoid\n// misclassifying TypeErrors thrown for other reasons (e.g. wrong arg count).\nconst slotError = /incompatible receiver|this is not/i;\n\nfunction hasInternalSlots(target: Proxiable): boolean {\n\tif (typeof target !== 'object' || target === null) return false;\n\n\tconst direct = Object.getPrototypeOf(target as object) as object | null;\n\tif (!direct) return false;\n\tif (slotProtos.has(direct)) return slotProtos.get(direct)!;\n\n\tconst probe = new Proxy(target as object, {\n\t\tset: () => true,\n\t\tdefineProperty: () => true,\n\t\tdeleteProperty: () => true,\n\t\tsetPrototypeOf: () => true,\n\t});\n\tlet proto: object | null = direct;\n\n\twhile (proto && proto !== Object.prototype) {\n\t\tfor (const key of Object.getOwnPropertyNames(proto)) {\n\t\t\tif (key === 'constructor') continue;\n\t\t\tconst desc = Object.getOwnPropertyDescriptor(proto, key);\n\t\t\tconst fn =\n\t\t\t\tdesc?.get ??\n\t\t\t\t(typeof desc?.value === 'function' ? (desc.value as Function) : null);\n\t\t\tif (fn) {\n\t\t\t\tlet slots = false;\n\t\t\t\ttry {\n\t\t\t\t\tfn.call(probe);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (e instanceof TypeError && slotError.test(String(e))) slots = true;\n\t\t\t\t}\n\t\t\t\tslotProtos.set(direct, slots);\n\t\t\t\treturn slots;\n\t\t\t}\n\t\t}\n\t\tproto = Object.getPrototypeOf(proto) as object | null;\n\t}\n\n\tslotProtos.set(direct, false);\n\treturn false;\n}\n\n/** Returns a stable bound version of `fn` for `(target, key)` — created once, reused on every access. */\nfunction boundMethod(target: object, key: PropertyKey, fn: Function): Function {\n\tif (!bindCache.has(target)) bindCache.set(target, new Map());\n\tconst cache = bindCache.get(target)!;\n\tif (!cache.has(key)) cache.set(key, fn.bind(target));\n\treturn cache.get(key)!;\n}\n\n// ─── Specs ────────────────────────────────────────────────────────────────────\n\n/** Per-trap hooks that transform arguments and results to maintain proxy transparency. */\nconst specs: Partial<Record<string, Spec>> = {\n\tget: {\n\t\t// For targets with internal slots (Map, Set, WeakMap, WeakSet, Date …),\n\t\t// use the real target as the Reflect.get receiver so that getter-based\n\t\t// slot checks (e.g. Map.prototype.size) don't throw TypeError.\n\t\tpre: ([target, key, receiver], _wrap, _known) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\thasInternalSlots(target as Proxiable) ? target : receiver,\n\t\t],\n\t\t// For the same targets, bind method results to the real target before\n\t\t// wrapping so that apply-level slot checks (e.g. Map.prototype.get)\n\t\t// also pass. The bind cache ensures proxy stability.\n\t\tpost: (result, [target, key], wrap) => {\n\t\t\tif (key === 'prototype') return result;\n\t\t\tif (typeof result === 'function' && hasInternalSlots(target as Proxiable)) {\n\t\t\t\treturn wrap(boundMethod(target as object, key as PropertyKey, result));\n\t\t\t}\n\t\t\treturn wrap(result);\n\t\t},\n\t},\n\tset: {\n\t\tpre: ([target, key, value, receiver], wrap) => [\n\t\t\ttarget,\n\t\t\tkey,\n\t\t\twrap(value),\n\t\t\treceiver,\n\t\t],\n\t},\n\tapply: {\n\t\t// thisArg is wrapped normally (it's always a graph node).\n\t\t// Call arguments are wrapped with known — only existing graph nodes\n\t\t// get proxied; plain data passes through and is inlined by serialize().\n\t\tpre: ([target, thisArg, callArgs], wrap, known) => [\n\t\t\ttarget,\n\t\t\twrap(thisArg),\n\t\t\t(<Array<unknown>>callArgs).map(known),\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tconstruct: {\n\t\tpre: ([target, callArgs, newTarget], wrap) => [\n\t\t\ttarget,\n\t\t\t(<Array<unknown>>callArgs).map(wrap),\n\t\t\tnewTarget,\n\t\t],\n\t\tpost: (result, _args, wrap) => wrap(result),\n\t},\n\tdefineProperty: {\n\t\tpre: (args, wrap) => {\n\t\t\tconst [target, key, descriptor] = <\n\t\t\t\t[unknown, unknown, PropertyDescriptor]\n\t\t\t>args;\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (descriptor.value != null) patch.value = wrap(descriptor.value);\n\t\t\tif (typeof descriptor.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(descriptor.get);\n\t\t\tif (typeof descriptor.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(descriptor.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? [target, key, { ...descriptor, ...patch }]\n\t\t\t\t: args;\n\t\t},\n\t},\n\tgetOwnPropertyDescriptor: {\n\t\tpost: (result, _args, wrap) => {\n\t\t\tconst desc = <PropertyDescriptor | undefined>result;\n\n\t\t\tif (!desc) return result;\n\n\t\t\tconst patch: PropertyDescriptor = {};\n\n\t\t\tif (desc.value != null) patch.value = wrap(desc.value);\n\t\t\tif (typeof desc.get === 'function')\n\t\t\t\tpatch.get = <() => unknown>wrap(desc.get);\n\t\t\tif (typeof desc.set === 'function')\n\t\t\t\tpatch.set = <(v: unknown) => void>wrap(desc.set);\n\n\t\t\treturn Object.keys(patch).length > 0\n\t\t\t\t? { ...desc, ...patch }\n\t\t\t\t: result;\n\t\t},\n\t},\n};\n\n// ─── Core proxy factory ───────────────────────────────────────────────────────\n\n/**\n * Creates a recording proxy for `target` within `graph`.\n * Reuses existing proxies for stability, handles Promises specially,\n * and registers every new proxy in both the graph and the module-level index.\n */\nfunction makeProxy<T extends Proxiable>(\n\ttarget: T,\n\tgraph: Graph,\n\tconfig: Config,\n\torigin: Origin,\n): T {\n\t// Already a proxy (in any graph) — return unchanged, preventing double-wrapping.\n\tif (allProxies.has(<Proxiable>target)) return target;\n\n\t// Already have a proxy for this original — reuse it (stability guarantee).\n\tconst existing = graph.getByTarget(<Proxiable>target);\n\n\tif (existing) return <T>existing.proxy;\n\n\t// Promises cannot be proxied directly: native methods like .then() check for\n\t// the [[PromiseState]] internal slot and throw if `this` is a Proxy. Instead,\n\t// return a new Promise that resolves to a proxy of the settled value.\n\tif (target instanceof Promise) {\n\t\tconst chained = <T>(\n\t\t\t(<unknown>(\n\t\t\t\ttarget.then((value) =>\n\t\t\t\t\tisProxiable(value)\n\t\t\t\t\t\t? makeProxy(<Proxiable>value, graph, config, origin)\n\t\t\t\t\t\t: value,\n\t\t\t\t)\n\t\t\t))\n\t\t);\n\t\t// Register with a placeholder node so stability lookups work.\n\t\tconst id = graph.nextId();\n\n\t\tgraph.register(<Proxiable>chained, <Proxiable>target, origin, id);\n\t\tgraphOf.set(<Proxiable>chained, graph);\n\n\t\treturn chained;\n\t}\n\n\tconst proxyId = graph.nextId();\n\n\tlet pxy!: T;\n\n\tconst traps = (<Array<keyof typeof Reflect>>(\n\t\tObject.getOwnPropertyNames(Reflect)\n\t)).filter((trap) => config.only === null || config.only.has(trap));\n\n\tconst handler: ProxyHandler<Proxiable> = Object.fromEntries(\n\t\ttraps.map((trap) => [\n\t\t\ttrap,\n\t\t\t(...rawArgs: Array<unknown>) => {\n\t\t\t\tconst selfId = (<GraphNode>graph.getByProxy(pxy)).id;\n\n\t\t\t\tconst childOrigin: Origin =\n\t\t\t\t\t/get|set|defineProperty|getOwnPropertyDescriptor/.test(trap)\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttrap: <PropertyTrap>trap,\n\t\t\t\t\t\t\t\tparent: selfId,\n\t\t\t\t\t\t\t\tkey: <string | symbol>rawArgs[1],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: /apply|construct/.test(trap)\n\t\t\t\t\t\t\t? { trap: <CallTrap>trap, source: selfId }\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\tconst wrap: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v) || allProxies.has(<Proxiable>v))\n\t\t\t\t\t\treturn v;\n\t\t\t\t\tif (!config.recursive) return v;\n\n\t\t\t\t\treturn makeProxy(<Proxiable>v, graph, config, childOrigin);\n\t\t\t\t};\n\n\t\t\t\t// Only wraps values already in the graph — new plain data passes through.\n\t\t\t\tconst known: Wrapper = (v) => {\n\t\t\t\t\tif (!isProxiable(v)) return v;\n\t\t\t\t\tif (allProxies.has(<Proxiable>v)) return v;\n\n\t\t\t\t\tconst existing = graph.getByTarget(<Proxiable>v);\n\n\t\t\t\t\tif (existing) return existing.proxy;\n\n\t\t\t\t\treturn v;\n\t\t\t\t};\n\n\t\t\t\tconst spec = specs[trap] ?? {};\n\t\t\t\tconst args = spec.pre\n\t\t\t\t\t? spec.pre(rawArgs, wrap, known)\n\t\t\t\t\t: rawArgs;\n\t\t\t\t// biome-ignore lint/complexity/noBannedTypes: dynamic Reflect dispatch requires Function cast\n\t\t\t\tconst result = (<Function>Reflect[trap])(...args);\n\t\t\t\tconst output = spec.post\n\t\t\t\t\t? spec.post(result, args, wrap)\n\t\t\t\t\t: result;\n\n\t\t\t\tconfig.write({\n\t\t\t\t\tid: graph.nextId(),\n\t\t\t\t\ttrap,\n\t\t\t\t\torigin: serializeOrigin(childOrigin),\n\t\t\t\t\targs: args.map((arg) => serialize(arg, graph)),\n\t\t\t\t\tresult: serialize(output, graph),\n\t\t\t\t});\n\n\t\t\t\treturn output;\n\t\t\t},\n\t\t]),\n\t);\n\n\tpxy = <T>(<unknown>new Proxy(<Proxiable>target, handler));\n\n\tgraph.register(<Proxiable>pxy, <Proxiable>target, origin, proxyId);\n\tgraphOf.set(<Proxiable>pxy, graph);\n\tallProxies.add(<Proxiable>pxy);\n\n\treturn pxy;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\ntype CreateOptions = {\n\tid?: number | (() => string);\n\trecursive?: boolean;\n\tonly?: string[];\n} & (\n\t| { stream: Writable; callback?: never }\n\t| { callback: (record: Rekording) => void; stream?: never }\n);\n\n/**\n * Wraps `target` in a transparent recording proxy.\n * Every Reflect trap that fires emits a `Rekording` to `callback` or `stream`.\n */\nexport function create<T extends Proxiable>(\n\ttarget: T,\n\toptions: CreateOptions,\n): T {\n\tconst { stream, callback } = options;\n\tconst write: (r: Rekording) => void = stream\n\t\t? (r) => stream.write(`${JSON.stringify(r)}\\n`)\n\t\t: // biome-ignore lint/style/noNonNullAssertion: CreateOptions guarantees stream or callback is set — TypeScript cannot express this mutual exclusion\n\t\t\tcallback!;\n\tconst recursive = options.recursive !== false;\n\tconst only = options.only ? new Set(options.only) : null;\n\tconst graph = new Graph(options.id ?? 0);\n\n\treturn makeProxy(target, graph, { write, recursive, only }, null);\n}\n\n/** Returns `true` if `value` is a proxy created by this module. */\nexport function isFlugrekorder(value: unknown): value is Proxiable {\n\treturn isProxiable(value) && allProxies.has(<Proxiable>value);\n}\n\n/** Returns the original unwrapped target of a proxy, or `null` for non-proxies. */\nexport function getTarget(pxy: Proxiable): Proxiable | null {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.target ?? null;\n}\n\n/**\n * Looks up a proxy by its recorded ID within the same graph as `pxy`.\n * Use this to resolve `{ $proxy: id }` references in recorded args and results back to live proxies.\n */\nexport function getProxyById(\n\tid: string,\n\tpxy: Proxiable,\n): Proxiable | undefined {\n\treturn graphOf.get(pxy)?.getById(id)?.proxy;\n}\n\n/** Returns the `Origin` of a proxy — how and from where it was created. Returns `null` for root proxies and non-proxies. */\nexport function getOrigin(pxy: Proxiable): Origin {\n\treturn graphOf.get(pxy)?.getByProxy(pxy)?.origin ?? null;\n}\n\n/**\n * Walks the origin chain from the root proxy down to `pxy`.\n * Returns an ordered array of `{ proxy, origin }` pairs, root first.\n * Returns an empty array for non-proxies.\n */\nexport function getAncestors(\n\tpxy: Proxiable,\n): Array<{ proxy: Proxiable; origin: Origin }> {\n\tconst graph = graphOf.get(pxy);\n\n\tif (!graph) return [];\n\n\tconst result: Array<{ proxy: Proxiable; origin: Origin }> = [];\n\tlet node = graph.getByProxy(pxy);\n\n\twhile (node) {\n\t\tresult.unshift({ proxy: node.proxy, origin: node.origin });\n\t\tif (!node.origin) break;\n\n\t\tconst parentId =\n\t\t\t'parent' in node.origin ? node.origin.parent : node.origin.source;\n\n\t\tnode = graph.getById(parentId);\n\t}\n\n\treturn result;\n}\n\n/**\n * Returns a human-readable dotted path string for a proxy.\n * Function and constructor calls are annotated with `()`.\n * Returns an empty string for the root proxy and for non-proxies.\n */\nexport function getPath(pxy: Proxiable): string {\n\tconst ancestors = getAncestors(pxy);\n\tconst parts: Array<string> = [];\n\n\tfor (const { origin: o } of ancestors) {\n\t\tif (!o) continue;\n\t\tif ('key' in o) {\n\t\t\tparts.push(String(o.key));\n\t\t} else {\n\t\t\tif (parts.length > 0) {\n\t\t\t\tparts[parts.length - 1] += '()';\n\t\t\t} else {\n\t\t\t\tparts.push('()');\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join('.');\n}\n"],"mappings":"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","names":["existing"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flugrekorder",
3
- "version": "1.0.1",
3
+ "version": "1.0.2-beta.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },