footprintjs 9.23.0 → 9.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,9 +9,60 @@
9
9
  * found on element proxies, then the same root on nested and terminal ones).
10
10
  * So every read trap resolves through the CURRENT value and falls back to the
11
11
  * captured object only when the path is gone or no longer holds an object.
12
+ *
13
+ * The READ side of every object proxy lives here — {@link liveObject},
14
+ * {@link liveGetTrap}, {@link liveInspectionTraps}, and the ONE per-member
15
+ * proxy cache {@link cachedMember} (9.23.2); the WRITE side is
16
+ * `writeTraps.ts`. A factory only wires them (9.23.1).
17
+ */
18
+ /**
19
+ * A proxy per member NAME under one parent proxy, validated by the raw
20
+ * member's identity. The map is allocated on the FIRST insert: an element
21
+ * proxy over `{ id, n }` reads only primitives and must not pay for one
22
+ * (10,000 of them in the naive re-read loop — measured, `bench/nested-reads.ts`).
12
23
  */
24
+ export declare class MemberCache {
25
+ private entries?;
26
+ /** The proxy cached under `prop`, if it was built over exactly this raw `value`. */
27
+ hit(prop: string, value: object): unknown;
28
+ remember(prop: string, value: object, proxy: unknown): void;
29
+ /** Forget `prop` — a write replaced its value, so the next read must build over the new one. */
30
+ delete(prop: string): void;
31
+ }
32
+ /**
33
+ * WHY the cache: `o.arr === o.arr` must hold within a stage, and
34
+ * `for (i < N) s.k.arr[i]` must build ONE array proxy — whose element cache
35
+ * then serves every index — not N (the 9.22.0 perf review, finding 4: the
36
+ * nested get trap built a fresh array proxy, with a fresh empty element
37
+ * cache, on every `.arr`). The top-level scope has cached its child proxies
38
+ * this way since before 9.22.0; this is that leaf, shared by all four.
39
+ *
40
+ * Validated by IDENTITY, invalidated by replacement: every write through a
41
+ * proxy rebuilds the containers on its path (`structuralWrite.setInPath`),
42
+ * so after `s.k.arr[0].n = 1` the raw `arr` is a new array, the ref check
43
+ * misses, and the next read builds a proxy over the NEW value. A hit can
44
+ * never be stale — every proxy reads live (`liveGetTrap`), so the cached one
45
+ * and a fresh one answer the same.
46
+ *
47
+ * Keyed by NAME under THIS parent, never by the raw value alone: a diamond
48
+ * (one array under `k.a` and `k.b`) needs two proxies, each bound to its own
49
+ * path and sink. Only what `build` actually WRAPPED is kept — a member handed
50
+ * back raw (a `Date`, a frozen object, a cycle edge) is not worth an entry.
51
+ * `build` is the caller's stable child step, not a closure made per read: a
52
+ * hit allocates nothing, and a primitive member skips the cache entirely.
53
+ */
54
+ export declare function cachedMember(cache: MemberCache, prop: string, value: unknown, build: (value: unknown, path: string[]) => unknown, segments: readonly string[]): unknown;
13
55
  /** The object at `segments` under the current root, or `raw` when it is gone. */
14
56
  export declare function liveObject(raw: Record<string, unknown>, current: unknown): Record<string, unknown>;
57
+ /**
58
+ * WHY one get trap: the names a proxy answers ITSELF (promise/matcher guards,
59
+ * `constructor`, and the JSON law — serializing a proxied value equals
60
+ * serializing the raw one, `jsonProjection.ts`) must be the same three lines
61
+ * on every object proxy; any other member is handed to `child` with its full
62
+ * path — through the parent's {@link cachedMember} — and only THAT step
63
+ * differs per factory (the cycle policy).
64
+ */
65
+ export declare function liveGetTrap(live: () => Record<string, unknown>, segments: readonly string[], child: (value: unknown, path: string[]) => unknown, members: MemberCache): ProxyHandler<object>['get'];
15
66
  /**
16
67
  * The three inspection traps (`in`, `Object.keys`, descriptors) answered from
17
68
  * the live object. The one Proxy invariant that could bite — a non-extensible
@@ -9,13 +9,95 @@
9
9
  * found on element proxies, then the same root on nested and terminal ones).
10
10
  * So every read trap resolves through the CURRENT value and falls back to the
11
11
  * captured object only when the path is gone or no longer holds an object.
12
+ *
13
+ * The READ side of every object proxy lives here — {@link liveObject},
14
+ * {@link liveGetTrap}, {@link liveInspectionTraps}, and the ONE per-member
15
+ * proxy cache {@link cachedMember} (9.23.2); the WRITE side is
16
+ * `writeTraps.ts`. A factory only wires them (9.23.1).
17
+ */
18
+ import { toJSONView } from './jsonProjection.js';
19
+ /**
20
+ * A proxy per member NAME under one parent proxy, validated by the raw
21
+ * member's identity. The map is allocated on the FIRST insert: an element
22
+ * proxy over `{ id, n }` reads only primitives and must not pay for one
23
+ * (10,000 of them in the naive re-read loop — measured, `bench/nested-reads.ts`).
12
24
  */
25
+ export class MemberCache {
26
+ entries;
27
+ /** The proxy cached under `prop`, if it was built over exactly this raw `value`. */
28
+ hit(prop, value) {
29
+ const cached = this.entries?.get(prop);
30
+ return cached !== undefined && cached.ref === value ? cached.proxy : undefined;
31
+ }
32
+ remember(prop, value, proxy) {
33
+ (this.entries ??= new Map()).set(prop, { ref: value, proxy });
34
+ }
35
+ /** Forget `prop` — a write replaced its value, so the next read must build over the new one. */
36
+ delete(prop) {
37
+ this.entries?.delete(prop);
38
+ }
39
+ }
40
+ /**
41
+ * WHY the cache: `o.arr === o.arr` must hold within a stage, and
42
+ * `for (i < N) s.k.arr[i]` must build ONE array proxy — whose element cache
43
+ * then serves every index — not N (the 9.22.0 perf review, finding 4: the
44
+ * nested get trap built a fresh array proxy, with a fresh empty element
45
+ * cache, on every `.arr`). The top-level scope has cached its child proxies
46
+ * this way since before 9.22.0; this is that leaf, shared by all four.
47
+ *
48
+ * Validated by IDENTITY, invalidated by replacement: every write through a
49
+ * proxy rebuilds the containers on its path (`structuralWrite.setInPath`),
50
+ * so after `s.k.arr[0].n = 1` the raw `arr` is a new array, the ref check
51
+ * misses, and the next read builds a proxy over the NEW value. A hit can
52
+ * never be stale — every proxy reads live (`liveGetTrap`), so the cached one
53
+ * and a fresh one answer the same.
54
+ *
55
+ * Keyed by NAME under THIS parent, never by the raw value alone: a diamond
56
+ * (one array under `k.a` and `k.b`) needs two proxies, each bound to its own
57
+ * path and sink. Only what `build` actually WRAPPED is kept — a member handed
58
+ * back raw (a `Date`, a frozen object, a cycle edge) is not worth an entry.
59
+ * `build` is the caller's stable child step, not a closure made per read: a
60
+ * hit allocates nothing, and a primitive member skips the cache entirely.
61
+ */
62
+ export function cachedMember(cache, prop, value, build, segments) {
63
+ if (value === null || typeof value !== 'object')
64
+ return build(value, [...segments, prop]);
65
+ const hit = cache.hit(prop, value);
66
+ if (hit !== undefined)
67
+ return hit;
68
+ const proxy = build(value, [...segments, prop]);
69
+ if (proxy !== value)
70
+ cache.remember(prop, value, proxy);
71
+ return proxy;
72
+ }
13
73
  /** The object at `segments` under the current root, or `raw` when it is gone. */
14
74
  export function liveObject(raw, current) {
15
75
  return current !== null && typeof current === 'object' && !Array.isArray(current)
16
76
  ? current
17
77
  : raw;
18
78
  }
79
+ /**
80
+ * WHY one get trap: the names a proxy answers ITSELF (promise/matcher guards,
81
+ * `constructor`, and the JSON law — serializing a proxied value equals
82
+ * serializing the raw one, `jsonProjection.ts`) must be the same three lines
83
+ * on every object proxy; any other member is handed to `child` with its full
84
+ * path — through the parent's {@link cachedMember} — and only THAT step
85
+ * differs per factory (the cycle policy).
86
+ */
87
+ export function liveGetTrap(live, segments, child, members) {
88
+ return (_target, prop) => {
89
+ const raw = live();
90
+ if (typeof prop === 'symbol')
91
+ return raw[prop];
92
+ if (prop === 'then' || prop === 'asymmetricMatch')
93
+ return undefined;
94
+ if (prop === 'constructor')
95
+ return Object;
96
+ if (prop === 'toJSON')
97
+ return () => toJSONView(raw);
98
+ return cachedMember(members, prop, raw[prop], child, segments);
99
+ };
100
+ }
19
101
  /**
20
102
  * The three inspection traps (`in`, `Object.keys`, descriptors) answered from
21
103
  * the live object. The one Proxy invariant that could bite — a non-extensible
@@ -40,4 +122,4 @@ export function liveInspectionTraps(live) {
40
122
  },
41
123
  };
42
124
  }
43
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGl2ZVZpZXcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3JlYWN0aXZlL2xpdmVWaWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7OztHQVdHO0FBRUgsaUZBQWlGO0FBQ2pGLE1BQU0sVUFBVSxVQUFVLENBQUMsR0FBNEIsRUFBRSxPQUFnQjtJQUN2RSxPQUFPLE9BQU8sS0FBSyxJQUFJLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDL0UsQ0FBQyxDQUFFLE9BQW1DO1FBQ3RDLENBQUMsQ0FBQyxHQUFHLENBQUM7QUFDVixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FDakMsSUFBa0I7SUFFbEIsT0FBTztRQUNMLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSTtZQUNkLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFDRCxPQUFPLENBQUMsTUFBTTtZQUNaLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDeEUsQ0FBQztRQUNELHdCQUF3QixDQUFDLE1BQU0sRUFBRSxJQUFJO1lBQ25DLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQztnQkFBRSxPQUFPLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDdkYsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLElBQUksRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2pFLE9BQU8sVUFBVSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLFVBQVUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztRQUNyRyxDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIHJlYWN0aXZlL2xpdmVWaWV3IOKAlCB3aGF0IGEgcHJveHkgc3RhbmRzIGZvciwgQVMgSVQgU1RBTkRTIE5PVy5cbiAqXG4gKiBFdmVyeSB3cml0ZSB0aHJvdWdoIHRoZSB0eXBlZCBzY29wZSByZWJ1aWxkcyB0aGUgcm9vdCBpbW11dGFibHlcbiAqIChgc3RydWN0dXJhbFdyaXRlLnNldEluUGF0aGAsIGEgZnJlc2ggbWVyZ2UpLCBzbyB0aGUgb2JqZWN0IGEgcHJveHkgd2FzXG4gKiBjcmVhdGVkIG92ZXIgaXMgdGhlIFBSRS13cml0ZSB2YWx1ZSBmb3IgZXZlciBhZnRlci4gQSBoZWxkIHByb3h5IHRoYXQgcmVhZFxuICogZnJvbSBpdCBzYXcgaXRzIG93biB3cml0ZXMgdmFuaXNoOiBgby54ICs9IDFgIHR3aWNlIGdhdmUgMiwgYG8uYiA9IG8uYSAqIDEwYFxuICogdXNlZCB0aGUgb2xkIGBhYCwgYCd4JyBpbiBvYCB3YXMgZmFsc2UgcmlnaHQgYWZ0ZXIgYG8ueCA9IDFgICg5LjIyLjAg4oCUIGZpcnN0XG4gKiBmb3VuZCBvbiBlbGVtZW50IHByb3hpZXMsIHRoZW4gdGhlIHNhbWUgcm9vdCBvbiBuZXN0ZWQgYW5kIHRlcm1pbmFsIG9uZXMpLlxuICogU28gZXZlcnkgcmVhZCB0cmFwIHJlc29sdmVzIHRocm91Z2ggdGhlIENVUlJFTlQgdmFsdWUgYW5kIGZhbGxzIGJhY2sgdG8gdGhlXG4gKiBjYXB0dXJlZCBvYmplY3Qgb25seSB3aGVuIHRoZSBwYXRoIGlzIGdvbmUgb3Igbm8gbG9uZ2VyIGhvbGRzIGFuIG9iamVjdC5cbiAqL1xuXG4vKiogVGhlIG9iamVjdCBhdCBgc2VnbWVudHNgIHVuZGVyIHRoZSBjdXJyZW50IHJvb3QsIG9yIGByYXdgIHdoZW4gaXQgaXMgZ29uZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXZlT2JqZWN0KHJhdzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGN1cnJlbnQ6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIHJldHVybiBjdXJyZW50ICE9PSBudWxsICYmIHR5cGVvZiBjdXJyZW50ID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShjdXJyZW50KVxuICAgID8gKGN1cnJlbnQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pXG4gICAgOiByYXc7XG59XG5cbi8qKlxuICogVGhlIHRocmVlIGluc3BlY3Rpb24gdHJhcHMgKGBpbmAsIGBPYmplY3Qua2V5c2AsIGRlc2NyaXB0b3JzKSBhbnN3ZXJlZCBmcm9tXG4gKiB0aGUgbGl2ZSBvYmplY3QuIFRoZSBvbmUgUHJveHkgaW52YXJpYW50IHRoYXQgY291bGQgYml0ZSDigJQgYSBub24tZXh0ZW5zaWJsZVxuICogdGFyZ2V0IG11c3QgcmVwb3J0IGV4YWN0bHkgaXRzIG93biBrZXlzLCBhbmQgYSBwcm9wZXJ0eSB0aGUgdGFyZ2V0IGxhY2tzXG4gKiBtdXN0IGJlIHJlcG9ydGVkIGNvbmZpZ3VyYWJsZSDigJQgaXMgaG9ub3VyZWQ6IHRoZSBhbGxvd2xpc3QgYWxyZWFkeSByZWZ1c2VzXG4gKiBmcm96ZW4gYW5kIHNlYWxlZCB2YWx1ZXMsIHNvIHRoZSBgcHJldmVudEV4dGVuc2lvbnNgLW9ubHkgY29ybmVyIGFuc3dlcnNcbiAqIGZyb20gdGhlIHRhcmdldCwgYW5kIGEgbGl2ZSBkZXNjcmlwdG9yIGlzIGFsd2F5cyByZXBvcnRlZCBjb25maWd1cmFibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXZlSW5zcGVjdGlvblRyYXBzKFxuICBsaXZlOiAoKSA9PiBvYmplY3QsXG4pOiBQaWNrPFByb3h5SGFuZGxlcjxvYmplY3Q+LCAnaGFzJyB8ICdvd25LZXlzJyB8ICdnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3InPiB7XG4gIHJldHVybiB7XG4gICAgaGFzKHRhcmdldCwgcHJvcCkge1xuICAgICAgcmV0dXJuIFJlZmxlY3QuaGFzKE9iamVjdC5pc0V4dGVuc2libGUodGFyZ2V0KSA/IGxpdmUoKSA6IHRhcmdldCwgcHJvcCk7XG4gICAgfSxcbiAgICBvd25LZXlzKHRhcmdldCkge1xuICAgICAgcmV0dXJuIFJlZmxlY3Qub3duS2V5cyhPYmplY3QuaXNFeHRlbnNpYmxlKHRhcmdldCkgPyBsaXZlKCkgOiB0YXJnZXQpO1xuICAgIH0sXG4gICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcCkge1xuICAgICAgaWYgKCFPYmplY3QuaXNFeHRlbnNpYmxlKHRhcmdldCkpIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcCk7XG4gICAgICBjb25zdCBkZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihsaXZlKCksIHByb3ApO1xuICAgICAgcmV0dXJuIGRlc2NyaXB0b3IgJiYgIWRlc2NyaXB0b3IuY29uZmlndXJhYmxlID8geyAuLi5kZXNjcmlwdG9yLCBjb25maWd1cmFibGU6IHRydWUgfSA6IGRlc2NyaXB0b3I7XG4gICAgfSxcbiAgfTtcbn1cbiJdfQ==
125
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGl2ZVZpZXcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3JlYWN0aXZlL2xpdmVWaWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWpEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDZCxPQUFPLENBQWdEO0lBRS9ELG9GQUFvRjtJQUNwRixHQUFHLENBQUMsSUFBWSxFQUFFLEtBQWE7UUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkMsT0FBTyxNQUFNLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDakYsQ0FBQztJQUVELFFBQVEsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLEtBQWM7UUFDbEQsQ0FBQyxJQUFJLENBQUMsT0FBTyxLQUFLLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRCxnR0FBZ0c7SUFDaEcsTUFBTSxDQUFDLElBQVk7UUFDakIsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0IsQ0FBQztDQUNGO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQzFCLEtBQWtCLEVBQ2xCLElBQVksRUFDWixLQUFjLEVBQ2QsS0FBa0QsRUFDbEQsUUFBMkI7SUFFM0IsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFBRSxPQUFPLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxHQUFHLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzFGLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ25DLElBQUksR0FBRyxLQUFLLFNBQVM7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUNsQyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUMsR0FBRyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLEtBQUssS0FBSyxLQUFLO1FBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3hELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELGlGQUFpRjtBQUNqRixNQUFNLFVBQVUsVUFBVSxDQUFDLEdBQTRCLEVBQUUsT0FBZ0I7SUFDdkUsT0FBTyxPQUFPLEtBQUssSUFBSSxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBQy9FLENBQUMsQ0FBRSxPQUFtQztRQUN0QyxDQUFDLENBQUMsR0FBRyxDQUFDO0FBQ1YsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUN6QixJQUFtQyxFQUNuQyxRQUEyQixFQUMzQixLQUFrRCxFQUNsRCxPQUFvQjtJQUVwQixPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQ3ZCLE1BQU0sR0FBRyxHQUFHLElBQUksRUFBRSxDQUFDO1FBQ25CLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUTtZQUFFLE9BQVEsR0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hELElBQUksSUFBSSxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssaUJBQWlCO1lBQUUsT0FBTyxTQUFTLENBQUM7UUFDcEUsSUFBSSxJQUFJLEtBQUssYUFBYTtZQUFFLE9BQU8sTUFBTSxDQUFDO1FBQzFDLElBQUksSUFBSSxLQUFLLFFBQVE7WUFBRSxPQUFPLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwRCxPQUFPLFlBQVksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDakUsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQ2pDLElBQWtCO0lBRWxCLE9BQU87UUFDTCxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUk7WUFDZCxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBQ0QsT0FBTyxDQUFDLE1BQU07WUFDWixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFDRCx3QkFBd0IsQ0FBQyxNQUFNLEVBQUUsSUFBSTtZQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUM7Z0JBQUUsT0FBTyxNQUFNLENBQUMsd0JBQXdCLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3ZGLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNqRSxPQUFPLFVBQVUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxVQUFVLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7UUFDckcsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiByZWFjdGl2ZS9saXZlVmlldyDigJQgd2hhdCBhIHByb3h5IHN0YW5kcyBmb3IsIEFTIElUIFNUQU5EUyBOT1cuXG4gKlxuICogRXZlcnkgd3JpdGUgdGhyb3VnaCB0aGUgdHlwZWQgc2NvcGUgcmVidWlsZHMgdGhlIHJvb3QgaW1tdXRhYmx5XG4gKiAoYHN0cnVjdHVyYWxXcml0ZS5zZXRJblBhdGhgLCBhIGZyZXNoIG1lcmdlKSwgc28gdGhlIG9iamVjdCBhIHByb3h5IHdhc1xuICogY3JlYXRlZCBvdmVyIGlzIHRoZSBQUkUtd3JpdGUgdmFsdWUgZm9yIGV2ZXIgYWZ0ZXIuIEEgaGVsZCBwcm94eSB0aGF0IHJlYWRcbiAqIGZyb20gaXQgc2F3IGl0cyBvd24gd3JpdGVzIHZhbmlzaDogYG8ueCArPSAxYCB0d2ljZSBnYXZlIDIsIGBvLmIgPSBvLmEgKiAxMGBcbiAqIHVzZWQgdGhlIG9sZCBgYWAsIGAneCcgaW4gb2Agd2FzIGZhbHNlIHJpZ2h0IGFmdGVyIGBvLnggPSAxYCAoOS4yMi4wIOKAlCBmaXJzdFxuICogZm91bmQgb24gZWxlbWVudCBwcm94aWVzLCB0aGVuIHRoZSBzYW1lIHJvb3Qgb24gbmVzdGVkIGFuZCB0ZXJtaW5hbCBvbmVzKS5cbiAqIFNvIGV2ZXJ5IHJlYWQgdHJhcCByZXNvbHZlcyB0aHJvdWdoIHRoZSBDVVJSRU5UIHZhbHVlIGFuZCBmYWxscyBiYWNrIHRvIHRoZVxuICogY2FwdHVyZWQgb2JqZWN0IG9ubHkgd2hlbiB0aGUgcGF0aCBpcyBnb25lIG9yIG5vIGxvbmdlciBob2xkcyBhbiBvYmplY3QuXG4gKlxuICogVGhlIFJFQUQgc2lkZSBvZiBldmVyeSBvYmplY3QgcHJveHkgbGl2ZXMgaGVyZSDigJQge0BsaW5rIGxpdmVPYmplY3R9LFxuICoge0BsaW5rIGxpdmVHZXRUcmFwfSwge0BsaW5rIGxpdmVJbnNwZWN0aW9uVHJhcHN9LCBhbmQgdGhlIE9ORSBwZXItbWVtYmVyXG4gKiBwcm94eSBjYWNoZSB7QGxpbmsgY2FjaGVkTWVtYmVyfSAoOS4yMy4yKTsgdGhlIFdSSVRFIHNpZGUgaXNcbiAqIGB3cml0ZVRyYXBzLnRzYC4gQSBmYWN0b3J5IG9ubHkgd2lyZXMgdGhlbSAoOS4yMy4xKS5cbiAqL1xuXG5pbXBvcnQgeyB0b0pTT05WaWV3IH0gZnJvbSAnLi9qc29uUHJvamVjdGlvbi5qcyc7XG5cbi8qKlxuICogQSBwcm94eSBwZXIgbWVtYmVyIE5BTUUgdW5kZXIgb25lIHBhcmVudCBwcm94eSwgdmFsaWRhdGVkIGJ5IHRoZSByYXdcbiAqIG1lbWJlcidzIGlkZW50aXR5LiBUaGUgbWFwIGlzIGFsbG9jYXRlZCBvbiB0aGUgRklSU1QgaW5zZXJ0OiBhbiBlbGVtZW50XG4gKiBwcm94eSBvdmVyIGB7IGlkLCBuIH1gIHJlYWRzIG9ubHkgcHJpbWl0aXZlcyBhbmQgbXVzdCBub3QgcGF5IGZvciBvbmVcbiAqICgxMCwwMDAgb2YgdGhlbSBpbiB0aGUgbmFpdmUgcmUtcmVhZCBsb29wIOKAlCBtZWFzdXJlZCwgYGJlbmNoL25lc3RlZC1yZWFkcy50c2ApLlxuICovXG5leHBvcnQgY2xhc3MgTWVtYmVyQ2FjaGUge1xuICBwcml2YXRlIGVudHJpZXM/OiBNYXA8c3RyaW5nLCB7IHJlZjogb2JqZWN0OyBwcm94eTogdW5rbm93biB9PjtcblxuICAvKiogVGhlIHByb3h5IGNhY2hlZCB1bmRlciBgcHJvcGAsIGlmIGl0IHdhcyBidWlsdCBvdmVyIGV4YWN0bHkgdGhpcyByYXcgYHZhbHVlYC4gKi9cbiAgaGl0KHByb3A6IHN0cmluZywgdmFsdWU6IG9iamVjdCk6IHVua25vd24ge1xuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuZW50cmllcz8uZ2V0KHByb3ApO1xuICAgIHJldHVybiBjYWNoZWQgIT09IHVuZGVmaW5lZCAmJiBjYWNoZWQucmVmID09PSB2YWx1ZSA/IGNhY2hlZC5wcm94eSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJlbWVtYmVyKHByb3A6IHN0cmluZywgdmFsdWU6IG9iamVjdCwgcHJveHk6IHVua25vd24pOiB2b2lkIHtcbiAgICAodGhpcy5lbnRyaWVzID8/PSBuZXcgTWFwKCkpLnNldChwcm9wLCB7IHJlZjogdmFsdWUsIHByb3h5IH0pO1xuICB9XG5cbiAgLyoqIEZvcmdldCBgcHJvcGAg4oCUIGEgd3JpdGUgcmVwbGFjZWQgaXRzIHZhbHVlLCBzbyB0aGUgbmV4dCByZWFkIG11c3QgYnVpbGQgb3ZlciB0aGUgbmV3IG9uZS4gKi9cbiAgZGVsZXRlKHByb3A6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZW50cmllcz8uZGVsZXRlKHByb3ApO1xuICB9XG59XG5cbi8qKlxuICogV0hZIHRoZSBjYWNoZTogYG8uYXJyID09PSBvLmFycmAgbXVzdCBob2xkIHdpdGhpbiBhIHN0YWdlLCBhbmRcbiAqIGBmb3IgKGkgPCBOKSBzLmsuYXJyW2ldYCBtdXN0IGJ1aWxkIE9ORSBhcnJheSBwcm94eSDigJQgd2hvc2UgZWxlbWVudCBjYWNoZVxuICogdGhlbiBzZXJ2ZXMgZXZlcnkgaW5kZXgg4oCUIG5vdCBOICh0aGUgOS4yMi4wIHBlcmYgcmV2aWV3LCBmaW5kaW5nIDQ6IHRoZVxuICogbmVzdGVkIGdldCB0cmFwIGJ1aWx0IGEgZnJlc2ggYXJyYXkgcHJveHksIHdpdGggYSBmcmVzaCBlbXB0eSBlbGVtZW50XG4gKiBjYWNoZSwgb24gZXZlcnkgYC5hcnJgKS4gVGhlIHRvcC1sZXZlbCBzY29wZSBoYXMgY2FjaGVkIGl0cyBjaGlsZCBwcm94aWVzXG4gKiB0aGlzIHdheSBzaW5jZSBiZWZvcmUgOS4yMi4wOyB0aGlzIGlzIHRoYXQgbGVhZiwgc2hhcmVkIGJ5IGFsbCBmb3VyLlxuICpcbiAqIFZhbGlkYXRlZCBieSBJREVOVElUWSwgaW52YWxpZGF0ZWQgYnkgcmVwbGFjZW1lbnQ6IGV2ZXJ5IHdyaXRlIHRocm91Z2ggYVxuICogcHJveHkgcmVidWlsZHMgdGhlIGNvbnRhaW5lcnMgb24gaXRzIHBhdGggKGBzdHJ1Y3R1cmFsV3JpdGUuc2V0SW5QYXRoYCksXG4gKiBzbyBhZnRlciBgcy5rLmFyclswXS5uID0gMWAgdGhlIHJhdyBgYXJyYCBpcyBhIG5ldyBhcnJheSwgdGhlIHJlZiBjaGVja1xuICogbWlzc2VzLCBhbmQgdGhlIG5leHQgcmVhZCBidWlsZHMgYSBwcm94eSBvdmVyIHRoZSBORVcgdmFsdWUuIEEgaGl0IGNhblxuICogbmV2ZXIgYmUgc3RhbGUg4oCUIGV2ZXJ5IHByb3h5IHJlYWRzIGxpdmUgKGBsaXZlR2V0VHJhcGApLCBzbyB0aGUgY2FjaGVkIG9uZVxuICogYW5kIGEgZnJlc2ggb25lIGFuc3dlciB0aGUgc2FtZS5cbiAqXG4gKiBLZXllZCBieSBOQU1FIHVuZGVyIFRISVMgcGFyZW50LCBuZXZlciBieSB0aGUgcmF3IHZhbHVlIGFsb25lOiBhIGRpYW1vbmRcbiAqIChvbmUgYXJyYXkgdW5kZXIgYGsuYWAgYW5kIGBrLmJgKSBuZWVkcyB0d28gcHJveGllcywgZWFjaCBib3VuZCB0byBpdHMgb3duXG4gKiBwYXRoIGFuZCBzaW5rLiBPbmx5IHdoYXQgYGJ1aWxkYCBhY3R1YWxseSBXUkFQUEVEIGlzIGtlcHQg4oCUIGEgbWVtYmVyIGhhbmRlZFxuICogYmFjayByYXcgKGEgYERhdGVgLCBhIGZyb3plbiBvYmplY3QsIGEgY3ljbGUgZWRnZSkgaXMgbm90IHdvcnRoIGFuIGVudHJ5LlxuICogYGJ1aWxkYCBpcyB0aGUgY2FsbGVyJ3Mgc3RhYmxlIGNoaWxkIHN0ZXAsIG5vdCBhIGNsb3N1cmUgbWFkZSBwZXIgcmVhZDogYVxuICogaGl0IGFsbG9jYXRlcyBub3RoaW5nLCBhbmQgYSBwcmltaXRpdmUgbWVtYmVyIHNraXBzIHRoZSBjYWNoZSBlbnRpcmVseS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhY2hlZE1lbWJlcihcbiAgY2FjaGU6IE1lbWJlckNhY2hlLFxuICBwcm9wOiBzdHJpbmcsXG4gIHZhbHVlOiB1bmtub3duLFxuICBidWlsZDogKHZhbHVlOiB1bmtub3duLCBwYXRoOiBzdHJpbmdbXSkgPT4gdW5rbm93bixcbiAgc2VnbWVudHM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuKTogdW5rbm93biB7XG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSByZXR1cm4gYnVpbGQodmFsdWUsIFsuLi5zZWdtZW50cywgcHJvcF0pO1xuICBjb25zdCBoaXQgPSBjYWNoZS5oaXQocHJvcCwgdmFsdWUpO1xuICBpZiAoaGl0ICE9PSB1bmRlZmluZWQpIHJldHVybiBoaXQ7XG4gIGNvbnN0IHByb3h5ID0gYnVpbGQodmFsdWUsIFsuLi5zZWdtZW50cywgcHJvcF0pO1xuICBpZiAocHJveHkgIT09IHZhbHVlKSBjYWNoZS5yZW1lbWJlcihwcm9wLCB2YWx1ZSwgcHJveHkpO1xuICByZXR1cm4gcHJveHk7XG59XG5cbi8qKiBUaGUgb2JqZWN0IGF0IGBzZWdtZW50c2AgdW5kZXIgdGhlIGN1cnJlbnQgcm9vdCwgb3IgYHJhd2Agd2hlbiBpdCBpcyBnb25lLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpdmVPYmplY3QocmF3OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgY3VycmVudDogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIGN1cnJlbnQgIT09IG51bGwgJiYgdHlwZW9mIGN1cnJlbnQgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGN1cnJlbnQpXG4gICAgPyAoY3VycmVudCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilcbiAgICA6IHJhdztcbn1cblxuLyoqXG4gKiBXSFkgb25lIGdldCB0cmFwOiB0aGUgbmFtZXMgYSBwcm94eSBhbnN3ZXJzIElUU0VMRiAocHJvbWlzZS9tYXRjaGVyIGd1YXJkcyxcbiAqIGBjb25zdHJ1Y3RvcmAsIGFuZCB0aGUgSlNPTiBsYXcg4oCUIHNlcmlhbGl6aW5nIGEgcHJveGllZCB2YWx1ZSBlcXVhbHNcbiAqIHNlcmlhbGl6aW5nIHRoZSByYXcgb25lLCBganNvblByb2plY3Rpb24udHNgKSBtdXN0IGJlIHRoZSBzYW1lIHRocmVlIGxpbmVzXG4gKiBvbiBldmVyeSBvYmplY3QgcHJveHk7IGFueSBvdGhlciBtZW1iZXIgaXMgaGFuZGVkIHRvIGBjaGlsZGAgd2l0aCBpdHMgZnVsbFxuICogcGF0aCDigJQgdGhyb3VnaCB0aGUgcGFyZW50J3Mge0BsaW5rIGNhY2hlZE1lbWJlcn0g4oCUIGFuZCBvbmx5IFRIQVQgc3RlcFxuICogZGlmZmVycyBwZXIgZmFjdG9yeSAodGhlIGN5Y2xlIHBvbGljeSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXZlR2V0VHJhcChcbiAgbGl2ZTogKCkgPT4gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIHNlZ21lbnRzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgY2hpbGQ6ICh2YWx1ZTogdW5rbm93biwgcGF0aDogc3RyaW5nW10pID0+IHVua25vd24sXG4gIG1lbWJlcnM6IE1lbWJlckNhY2hlLFxuKTogUHJveHlIYW5kbGVyPG9iamVjdD5bJ2dldCddIHtcbiAgcmV0dXJuIChfdGFyZ2V0LCBwcm9wKSA9PiB7XG4gICAgY29uc3QgcmF3ID0gbGl2ZSgpO1xuICAgIGlmICh0eXBlb2YgcHJvcCA9PT0gJ3N5bWJvbCcpIHJldHVybiAocmF3IGFzIGFueSlbcHJvcF07XG4gICAgaWYgKHByb3AgPT09ICd0aGVuJyB8fCBwcm9wID09PSAnYXN5bW1ldHJpY01hdGNoJykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAocHJvcCA9PT0gJ2NvbnN0cnVjdG9yJykgcmV0dXJuIE9iamVjdDtcbiAgICBpZiAocHJvcCA9PT0gJ3RvSlNPTicpIHJldHVybiAoKSA9PiB0b0pTT05WaWV3KHJhdyk7XG4gICAgcmV0dXJuIGNhY2hlZE1lbWJlcihtZW1iZXJzLCBwcm9wLCByYXdbcHJvcF0sIGNoaWxkLCBzZWdtZW50cyk7XG4gIH07XG59XG5cbi8qKlxuICogVGhlIHRocmVlIGluc3BlY3Rpb24gdHJhcHMgKGBpbmAsIGBPYmplY3Qua2V5c2AsIGRlc2NyaXB0b3JzKSBhbnN3ZXJlZCBmcm9tXG4gKiB0aGUgbGl2ZSBvYmplY3QuIFRoZSBvbmUgUHJveHkgaW52YXJpYW50IHRoYXQgY291bGQgYml0ZSDigJQgYSBub24tZXh0ZW5zaWJsZVxuICogdGFyZ2V0IG11c3QgcmVwb3J0IGV4YWN0bHkgaXRzIG93biBrZXlzLCBhbmQgYSBwcm9wZXJ0eSB0aGUgdGFyZ2V0IGxhY2tzXG4gKiBtdXN0IGJlIHJlcG9ydGVkIGNvbmZpZ3VyYWJsZSDigJQgaXMgaG9ub3VyZWQ6IHRoZSBhbGxvd2xpc3QgYWxyZWFkeSByZWZ1c2VzXG4gKiBmcm96ZW4gYW5kIHNlYWxlZCB2YWx1ZXMsIHNvIHRoZSBgcHJldmVudEV4dGVuc2lvbnNgLW9ubHkgY29ybmVyIGFuc3dlcnNcbiAqIGZyb20gdGhlIHRhcmdldCwgYW5kIGEgbGl2ZSBkZXNjcmlwdG9yIGlzIGFsd2F5cyByZXBvcnRlZCBjb25maWd1cmFibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXZlSW5zcGVjdGlvblRyYXBzKFxuICBsaXZlOiAoKSA9PiBvYmplY3QsXG4pOiBQaWNrPFByb3h5SGFuZGxlcjxvYmplY3Q+LCAnaGFzJyB8ICdvd25LZXlzJyB8ICdnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3InPiB7XG4gIHJldHVybiB7XG4gICAgaGFzKHRhcmdldCwgcHJvcCkge1xuICAgICAgcmV0dXJuIFJlZmxlY3QuaGFzKE9iamVjdC5pc0V4dGVuc2libGUodGFyZ2V0KSA/IGxpdmUoKSA6IHRhcmdldCwgcHJvcCk7XG4gICAgfSxcbiAgICBvd25LZXlzKHRhcmdldCkge1xuICAgICAgcmV0dXJuIFJlZmxlY3Qub3duS2V5cyhPYmplY3QuaXNFeHRlbnNpYmxlKHRhcmdldCkgPyBsaXZlKCkgOiB0YXJnZXQpO1xuICAgIH0sXG4gICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcCkge1xuICAgICAgaWYgKCFPYmplY3QuaXNFeHRlbnNpYmxlKHRhcmdldCkpIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcCk7XG4gICAgICBjb25zdCBkZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihsaXZlKCksIHByb3ApO1xuICAgICAgcmV0dXJuIGRlc2NyaXB0b3IgJiYgIWRlc2NyaXB0b3IuY29uZmlndXJhYmxlID8geyAuLi5kZXNjcmlwdG9yLCBjb25maWd1cmFibGU6IHRydWUgfSA6IGRlc2NyaXB0b3I7XG4gICAgfSxcbiAgfTtcbn1cbiJdfQ==
@@ -0,0 +1,59 @@
1
+ /**
2
+ * reactive/writeTraps — where a proxy's writes LAND, and the two traps that
3
+ * send them there.
4
+ *
5
+ * Every object proxy in this folder (nested, terminal, element) intercepts
6
+ * the same three things — a property set, a property delete, and an array
7
+ * mutation somewhere below it — and differs only in where the write goes:
8
+ * a nested/terminal proxy commits under a TOP-LEVEL KEY (an object write as
9
+ * `merge` of a patch, an array write or a delete as `set` of the rebuilt
10
+ * root); an element proxy commits the WHOLE OWNING ARRAY back through the
11
+ * array proxy's own callback. That difference is a {@link WriteSink}; the
12
+ * traps are written once over it (9.23.1 — the 9.22.0 stale-read bug was
13
+ * fixed in one copy of these traps and then found again in the other two).
14
+ */
15
+ import type { MemberCache } from './liveView.js';
16
+ /**
17
+ * The seam between a proxy and state. `path` is measured from the sink's
18
+ * root — the key's value for {@link rootKeySink}, the element for
19
+ * {@link elementSink}; `[]` is the root itself.
20
+ */
21
+ export interface WriteSink {
22
+ /** The value at `path`, as it stands NOW (read-your-writes; never a tracked read). */
23
+ readAt(path: readonly string[]): unknown;
24
+ /** Put an already-unwrapped `value` at `path`. The sink chooses the verb. */
25
+ put(path: readonly string[], value: unknown): void;
26
+ /** Remove the key at `path`. */
27
+ remove(path: readonly string[]): void;
28
+ }
29
+ /** The two ways a value reaches a state key: what the sink writes through. */
30
+ export interface RootKeyTarget {
31
+ setValue(key: string, value: unknown): void;
32
+ updateValue(key: string, value: unknown): void;
33
+ }
34
+ /**
35
+ * WHY: a write below a top-level key has TWO verbs (reactive/README.md, law
36
+ * 3) — an object leaf is a `merge` of a nested patch, an array leaf or a
37
+ * delete rebuilds the root immutably and commits a `set` of the key. Only the
38
+ * sink knows that; the traps do not. Every write drops the key's cached child
39
+ * proxy (`cache`), so the next read is built over the new value.
40
+ */
41
+ export declare function rootKeySink(target: RootKeyTarget, readSilent: (key: string) => unknown, rootKey: string, cache: Pick<MemberCache, 'delete'>): WriteSink;
42
+ /**
43
+ * WHY: a write inside an array element is an array write — it rebuilds the
44
+ * owning array immutably and hands the WHOLE new array to the array proxy's
45
+ * commit, the funnel `push` already uses. `path` is measured from the
46
+ * element; `[]` is the element slot itself.
47
+ */
48
+ export declare function elementSink(getCurrent: () => unknown[], commit: (next: unknown[]) => void, index: number): WriteSink;
49
+ /**
50
+ * WHY one set trap: the assigned value is unwrapped HERE (landmine 1 — the
51
+ * JSON round-trip applies to what the caller handed in, never to the
52
+ * surrounding state) and handed to the sink at the proxy's path plus the key.
53
+ */
54
+ export declare function sinkSetTrap(sink: WriteSink, segments: readonly string[]): ProxyHandler<object>['set'];
55
+ /**
56
+ * WHY one delete trap: `merge` cannot express a removal (a patch of
57
+ * `undefined` reads as absent), so a delete always rebuilds through the sink.
58
+ */
59
+ export declare function sinkDeleteTrap(sink: WriteSink, segments: readonly string[]): ProxyHandler<object>['deleteProperty'];
@@ -0,0 +1,132 @@
1
+ /**
2
+ * reactive/writeTraps — where a proxy's writes LAND, and the two traps that
3
+ * send them there.
4
+ *
5
+ * Every object proxy in this folder (nested, terminal, element) intercepts
6
+ * the same three things — a property set, a property delete, and an array
7
+ * mutation somewhere below it — and differs only in where the write goes:
8
+ * a nested/terminal proxy commits under a TOP-LEVEL KEY (an object write as
9
+ * `merge` of a patch, an array write or a delete as `set` of the rebuilt
10
+ * root); an element proxy commits the WHOLE OWNING ARRAY back through the
11
+ * array proxy's own callback. That difference is a {@link WriteSink}; the
12
+ * traps are written once over it (9.23.1 — the 9.22.0 stale-read bug was
13
+ * fixed in one copy of these traps and then found again in the other two).
14
+ */
15
+ import { nativeGet } from '../memory/pathOps.js';
16
+ import { buildNestedPatch } from './pathBuilder.js';
17
+ import { deleteInPath, setInPath, unwrapProxy } from './structuralWrite.js';
18
+ /**
19
+ * WHY: a write below a top-level key has TWO verbs (reactive/README.md, law
20
+ * 3) — an object leaf is a `merge` of a nested patch, an array leaf or a
21
+ * delete rebuilds the root immutably and commits a `set` of the key. Only the
22
+ * sink knows that; the traps do not. Every write drops the key's cached child
23
+ * proxy (`cache`), so the next read is built over the new value.
24
+ */
25
+ export function rootKeySink(target, readSilent, rootKey, cache) {
26
+ return new RootKeySink(target, readSilent, rootKey, cache);
27
+ }
28
+ /** One allocation per top-level read miss (the methods live on the prototype). */
29
+ class RootKeySink {
30
+ target;
31
+ readSilent;
32
+ rootKey;
33
+ cache;
34
+ constructor(target, readSilent, rootKey, cache) {
35
+ this.target = target;
36
+ this.readSilent = readSilent;
37
+ this.rootKey = rootKey;
38
+ this.cache = cache;
39
+ }
40
+ /** An empty path is the key's own value — `nativeGet(v, [])` would return it unchanged, so the walk is skipped. */
41
+ readAt(path) {
42
+ const root = this.readSilent(this.rootKey);
43
+ return path.length === 0 ? root : nativeGet(root, path);
44
+ }
45
+ put(path, value) {
46
+ if (!Array.isArray(value))
47
+ this.target.updateValue(this.rootKey, buildNestedPatch(path, value));
48
+ else
49
+ this.target.setValue(this.rootKey, path.length === 0 ? value : setInPath(this.readAt([]), path, value));
50
+ this.cache.delete(this.rootKey);
51
+ }
52
+ remove(path) {
53
+ this.target.setValue(this.rootKey, deleteInPath(this.readAt([]), path));
54
+ this.cache.delete(this.rootKey);
55
+ }
56
+ }
57
+ /**
58
+ * WHY: a write inside an array element is an array write — it rebuilds the
59
+ * owning array immutably and hands the WHOLE new array to the array proxy's
60
+ * commit, the funnel `push` already uses. `path` is measured from the
61
+ * element; `[]` is the element slot itself.
62
+ */
63
+ export function elementSink(getCurrent, commit, index) {
64
+ return new ElementSink(getCurrent, commit, index);
65
+ }
66
+ /** One allocation per element proxy (the methods live on the prototype) — a 10k-element loop builds 10k of these. */
67
+ class ElementSink {
68
+ getCurrent;
69
+ commit;
70
+ index;
71
+ constructor(getCurrent, commit, index) {
72
+ this.getCurrent = getCurrent;
73
+ this.commit = commit;
74
+ this.index = index;
75
+ }
76
+ readAt(path) {
77
+ return readInElement(this.getCurrent, this.index, path);
78
+ }
79
+ put(path, value) {
80
+ replaceInElement(this.getCurrent, this.commit, this.index, path, value);
81
+ }
82
+ remove(path) {
83
+ removeInElement(this.getCurrent, this.commit, this.index, path);
84
+ }
85
+ }
86
+ /** The value at `path` inside element `index`, as it stands NOW (read-your-writes). */
87
+ function readInElement(getCurrent, index, path) {
88
+ const element = getCurrent()[index];
89
+ return path.length === 0 ? element : nativeGet(element, path);
90
+ }
91
+ /** A copy of the array with `value` at `path` inside element `index`; a gone element has nothing to write into. */
92
+ function replaceInElement(getCurrent, commit, index, path, value) {
93
+ const next = [...getCurrent()];
94
+ if (index >= next.length)
95
+ return;
96
+ next[index] = path.length === 0 ? value : setInPath(next[index], path, value);
97
+ commit(next);
98
+ }
99
+ /** A copy of the array with the key at `path` inside element `index` removed. */
100
+ function removeInElement(getCurrent, commit, index, path) {
101
+ const next = [...getCurrent()];
102
+ if (index >= next.length)
103
+ return;
104
+ next[index] = deleteInPath(next[index], path);
105
+ commit(next);
106
+ }
107
+ /**
108
+ * WHY one set trap: the assigned value is unwrapped HERE (landmine 1 — the
109
+ * JSON round-trip applies to what the caller handed in, never to the
110
+ * surrounding state) and handed to the sink at the proxy's path plus the key.
111
+ */
112
+ export function sinkSetTrap(sink, segments) {
113
+ return (_target, prop, value) => {
114
+ if (typeof prop !== 'string')
115
+ return true;
116
+ sink.put([...segments, prop], unwrapProxy(value));
117
+ return true;
118
+ };
119
+ }
120
+ /**
121
+ * WHY one delete trap: `merge` cannot express a removal (a patch of
122
+ * `undefined` reads as absent), so a delete always rebuilds through the sink.
123
+ */
124
+ export function sinkDeleteTrap(sink, segments) {
125
+ return (_target, prop) => {
126
+ if (typeof prop !== 'string')
127
+ return true;
128
+ sink.remove([...segments, prop]);
129
+ return true;
130
+ };
131
+ }
132
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVUcmFwcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcmVhY3RpdmUvd3JpdGVUcmFwcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7OztHQWFHO0FBRUgsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRWpELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBc0I1RTs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUN6QixNQUFxQixFQUNyQixVQUFvQyxFQUNwQyxPQUFlLEVBQ2YsS0FBa0M7SUFFbEMsT0FBTyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUM3RCxDQUFDO0FBRUQsa0ZBQWtGO0FBQ2xGLE1BQU0sV0FBVztJQUVJO0lBQ0E7SUFDQTtJQUNBO0lBSm5CLFlBQ21CLE1BQXFCLEVBQ3JCLFVBQW9DLEVBQ3BDLE9BQWUsRUFDZixLQUFrQztRQUhsQyxXQUFNLEdBQU4sTUFBTSxDQUFlO1FBQ3JCLGVBQVUsR0FBVixVQUFVLENBQTBCO1FBQ3BDLFlBQU8sR0FBUCxPQUFPLENBQVE7UUFDZixVQUFLLEdBQUwsS0FBSyxDQUE2QjtJQUNsRCxDQUFDO0lBRUosbUhBQW1IO0lBQ25ILE1BQU0sQ0FBQyxJQUF1QjtRQUM1QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxPQUFPLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBZ0IsQ0FBQyxDQUFDO0lBQ3RFLENB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Q0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogcmVhY3RpdmUvd3JpdGVUcmFwcyDigJQgd2hlcmUgYSBwcm94eSdzIHdyaXRlcyBMQU5ELCBhbmQgdGhlIHR3byB0cmFwcyB0aGF0XG4gKiBzZW5kIHRoZW0gdGhlcmUuXG4gKlxuICogRXZlcnkgb2JqZWN0IHByb3h5IGluIHRoaXMgZm9sZGVyIChuZXN0ZWQsIHRlcm1pbmFsLCBlbGVtZW50KSBpbnRlcmNlcHRzXG4gKiB0aGUgc2FtZSB0aHJlZSB0aGluZ3Mg4oCUIGEgcHJvcGVydHkgc2V0LCBhIHByb3BlcnR5IGRlbGV0ZSwgYW5kIGFuIGFycmF5XG4gKiBtdXRhdGlvbiBzb21ld2hlcmUgYmVsb3cgaXQg4oCUIGFuZCBkaWZmZXJzIG9ubHkgaW4gd2hlcmUgdGhlIHdyaXRlIGdvZXM6XG4gKiBhIG5lc3RlZC90ZXJtaW5hbCBwcm94eSBjb21taXRzIHVuZGVyIGEgVE9QLUxFVkVMIEtFWSAoYW4gb2JqZWN0IHdyaXRlIGFzXG4gKiBgbWVyZ2VgIG9mIGEgcGF0Y2gsIGFuIGFycmF5IHdyaXRlIG9yIGEgZGVsZXRlIGFzIGBzZXRgIG9mIHRoZSByZWJ1aWx0XG4gKiByb290KTsgYW4gZWxlbWVudCBwcm94eSBjb21taXRzIHRoZSBXSE9MRSBPV05JTkcgQVJSQVkgYmFjayB0aHJvdWdoIHRoZVxuICogYXJyYXkgcHJveHkncyBvd24gY2FsbGJhY2suIFRoYXQgZGlmZmVyZW5jZSBpcyBhIHtAbGluayBXcml0ZVNpbmt9OyB0aGVcbiAqIHRyYXBzIGFyZSB3cml0dGVuIG9uY2Ugb3ZlciBpdCAoOS4yMy4xIOKAlCB0aGUgOS4yMi4wIHN0YWxlLXJlYWQgYnVnIHdhc1xuICogZml4ZWQgaW4gb25lIGNvcHkgb2YgdGhlc2UgdHJhcHMgYW5kIHRoZW4gZm91bmQgYWdhaW4gaW4gdGhlIG90aGVyIHR3bykuXG4gKi9cblxuaW1wb3J0IHsgbmF0aXZlR2V0IH0gZnJvbSAnLi4vbWVtb3J5L3BhdGhPcHMuanMnO1xuaW1wb3J0IHR5cGUgeyBNZW1iZXJDYWNoZSB9IGZyb20gJy4vbGl2ZVZpZXcuanMnO1xuaW1wb3J0IHsgYnVpbGROZXN0ZWRQYXRjaCB9IGZyb20gJy4vcGF0aEJ1aWxkZXIuanMnO1xuaW1wb3J0IHsgZGVsZXRlSW5QYXRoLCBzZXRJblBhdGgsIHVud3JhcFByb3h5IH0gZnJvbSAnLi9zdHJ1Y3R1cmFsV3JpdGUuanMnO1xuXG4vKipcbiAqIFRoZSBzZWFtIGJldHdlZW4gYSBwcm94eSBhbmQgc3RhdGUuIGBwYXRoYCBpcyBtZWFzdXJlZCBmcm9tIHRoZSBzaW5rJ3NcbiAqIHJvb3Qg4oCUIHRoZSBrZXkncyB2YWx1ZSBmb3Ige0BsaW5rIHJvb3RLZXlTaW5rfSwgdGhlIGVsZW1lbnQgZm9yXG4gKiB7QGxpbmsgZWxlbWVudFNpbmt9OyBgW11gIGlzIHRoZSByb290IGl0c2VsZi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXcml0ZVNpbmsge1xuICAvKiogVGhlIHZhbHVlIGF0IGBwYXRoYCwgYXMgaXQgc3RhbmRzIE5PVyAocmVhZC15b3VyLXdyaXRlczsgbmV2ZXIgYSB0cmFja2VkIHJlYWQpLiAqL1xuICByZWFkQXQocGF0aDogcmVhZG9ubHkgc3RyaW5nW10pOiB1bmtub3duO1xuICAvKiogUHV0IGFuIGFscmVhZHktdW53cmFwcGVkIGB2YWx1ZWAgYXQgYHBhdGhgLiBUaGUgc2luayBjaG9vc2VzIHRoZSB2ZXJiLiAqL1xuICBwdXQocGF0aDogcmVhZG9ubHkgc3RyaW5nW10sIHZhbHVlOiB1bmtub3duKTogdm9pZDtcbiAgLyoqIFJlbW92ZSB0aGUga2V5IGF0IGBwYXRoYC4gKi9cbiAgcmVtb3ZlKHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdKTogdm9pZDtcbn1cblxuLyoqIFRoZSB0d28gd2F5cyBhIHZhbHVlIHJlYWNoZXMgYSBzdGF0ZSBrZXk6IHdoYXQgdGhlIHNpbmsgd3JpdGVzIHRocm91Z2guICovXG5leHBvcnQgaW50ZXJmYWNlIFJvb3RLZXlUYXJnZXQge1xuICBzZXRWYWx1ZShrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB2b2lkO1xuICB1cGRhdGVWYWx1ZShrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB2b2lkO1xufVxuXG4vKipcbiAqIFdIWTogYSB3cml0ZSBiZWxvdyBhIHRvcC1sZXZlbCBrZXkgaGFzIFRXTyB2ZXJicyAocmVhY3RpdmUvUkVBRE1FLm1kLCBsYXdcbiAqIDMpIOKAlCBhbiBvYmplY3QgbGVhZiBpcyBhIGBtZXJnZWAgb2YgYSBuZXN0ZWQgcGF0Y2gsIGFuIGFycmF5IGxlYWYgb3IgYVxuICogZGVsZXRlIHJlYnVpbGRzIHRoZSByb290IGltbXV0YWJseSBhbmQgY29tbWl0cyBhIGBzZXRgIG9mIHRoZSBrZXkuIE9ubHkgdGhlXG4gKiBzaW5rIGtub3dzIHRoYXQ7IHRoZSB0cmFwcyBkbyBub3QuIEV2ZXJ5IHdyaXRlIGRyb3BzIHRoZSBrZXkncyBjYWNoZWQgY2hpbGRcbiAqIHByb3h5IChgY2FjaGVgKSwgc28gdGhlIG5leHQgcmVhZCBpcyBidWlsdCBvdmVyIHRoZSBuZXcgdmFsdWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb290S2V5U2luayhcbiAgdGFyZ2V0OiBSb290S2V5VGFyZ2V0LFxuICByZWFkU2lsZW50OiAoa2V5OiBzdHJpbmcpID0+IHVua25vd24sXG4gIHJvb3RLZXk6IHN0cmluZyxcbiAgY2FjaGU6IFBpY2s8TWVtYmVyQ2FjaGUsICdkZWxldGUnPixcbik6IFdyaXRlU2luayB7XG4gIHJldHVybiBuZXcgUm9vdEtleVNpbmsodGFyZ2V0LCByZWFkU2lsZW50LCByb290S2V5LCBjYWNoZSk7XG59XG5cbi8qKiBPbmUgYWxsb2NhdGlvbiBwZXIgdG9wLWxldmVsIHJlYWQgbWlzcyAodGhlIG1ldGhvZHMgbGl2ZSBvbiB0aGUgcHJvdG90eXBlKS4gKi9cbmNsYXNzIFJvb3RLZXlTaW5rIGltcGxlbWVudHMgV3JpdGVTaW5rIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSB0YXJnZXQ6IFJvb3RLZXlUYXJnZXQsXG4gICAgcHJpdmF0ZSByZWFkb25seSByZWFkU2lsZW50OiAoa2V5OiBzdHJpbmcpID0+IHVua25vd24sXG4gICAgcHJpdmF0ZSByZWFkb25seSByb290S2V5OiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYWNoZTogUGljazxNZW1iZXJDYWNoZSwgJ2RlbGV0ZSc+LFxuICApIHt9XG5cbiAgLyoqIEFuIGVtcHR5IHBhdGggaXMgdGhlIGtleSdzIG93biB2YWx1ZSDigJQgYG5hdGl2ZUdldCh2LCBbXSlgIHdvdWxkIHJldHVybiBpdCB1bmNoYW5nZWQsIHNvIHRoZSB3YWxrIGlzIHNraXBwZWQuICovXG4gIHJlYWRBdChwYXRoOiByZWFkb25seSBzdHJpbmdbXSk6IHVua25vd24ge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJlYWRTaWxlbnQodGhpcy5yb290S2V5KTtcbiAgICByZXR1cm4gcGF0aC5sZW5ndGggPT09IDAgPyByb290IDogbmF0aXZlR2V0KHJvb3QsIHBhdGggYXMgc3RyaW5nW10pO1xuICB9XG5cbiAgcHV0KHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHRoaXMudGFyZ2V0LnVwZGF0ZVZhbHVlKHRoaXMucm9vdEtleSwgYnVpbGROZXN0ZWRQYXRjaChwYXRoIGFzIHN0cmluZ1tdLCB2YWx1ZSkpO1xuICAgIGVsc2UgdGhpcy50YXJnZXQuc2V0VmFsdWUodGhpcy5yb290S2V5LCBwYXRoLmxlbmd0aCA9PT0gMCA/IHZhbHVlIDogc2V0SW5QYXRoKHRoaXMucmVhZEF0KFtdKSwgcGF0aCwgdmFsdWUpKTtcbiAgICB0aGlzLmNhY2hlLmRlbGV0ZSh0aGlzLnJvb3RLZXkpO1xuICB9XG5cbiAgcmVtb3ZlKHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdGhpcy50YXJnZXQuc2V0VmFsdWUodGhpcy5yb290S2V5LCBkZWxldGVJblBhdGgodGhpcy5yZWFkQXQoW10pLCBwYXRoKSk7XG4gICAgdGhpcy5jYWNoZS5kZWxldGUodGhpcy5yb290S2V5KTtcbiAgfVxufVxuXG4vKipcbiAqIFdIWTogYSB3cml0ZSBpbnNpZGUgYW4gYXJyYXkgZWxlbWVudCBpcyBhbiBhcnJheSB3cml0ZSDigJQgaXQgcmVidWlsZHMgdGhlXG4gKiBvd25pbmcgYXJyYXkgaW1tdXRhYmx5IGFuZCBoYW5kcyB0aGUgV0hPTEUgbmV3IGFycmF5IHRvIHRoZSBhcnJheSBwcm94eSdzXG4gKiBjb21taXQsIHRoZSBmdW5uZWwgYHB1c2hgIGFscmVhZHkgdXNlcy4gYHBhdGhgIGlzIG1lYXN1cmVkIGZyb20gdGhlXG4gKiBlbGVtZW50OyBgW11gIGlzIHRoZSBlbGVtZW50IHNsb3QgaXRzZWxmLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZWxlbWVudFNpbmsoZ2V0Q3VycmVudDogKCkgPT4gdW5rbm93bltdLCBjb21taXQ6IChuZXh0OiB1bmtub3duW10pID0+IHZvaWQsIGluZGV4OiBudW1iZXIpOiBXcml0ZVNpbmsge1xuICByZXR1cm4gbmV3IEVsZW1lbnRTaW5rKGdldEN1cnJlbnQsIGNvbW1pdCwgaW5kZXgpO1xufVxuXG4vKiogT25lIGFsbG9jYXRpb24gcGVyIGVsZW1lbnQgcHJveHkgKHRoZSBtZXRob2RzIGxpdmUgb24gdGhlIHByb3RvdHlwZSkg4oCUIGEgMTBrLWVsZW1lbnQgbG9vcCBidWlsZHMgMTBrIG9mIHRoZXNlLiAqL1xuY2xhc3MgRWxlbWVudFNpbmsgaW1wbGVtZW50cyBXcml0ZVNpbmsge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGdldEN1cnJlbnQ6ICgpID0+IHVua25vd25bXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbW1pdDogKG5leHQ6IHVua25vd25bXSkgPT4gdm9pZCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGluZGV4OiBudW1iZXIsXG4gICkge31cblxuICByZWFkQXQocGF0aDogcmVhZG9ubHkgc3RyaW5nW10pOiB1bmtub3duIHtcbiAgICByZXR1cm4gcmVhZEluRWxlbWVudCh0aGlzLmdldEN1cnJlbnQsIHRoaXMuaW5kZXgsIHBhdGgpO1xuICB9XG5cbiAgcHV0KHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgIHJlcGxhY2VJbkVsZW1lbnQodGhpcy5nZXRDdXJyZW50LCB0aGlzLmNvbW1pdCwgdGhpcy5pbmRleCwgcGF0aCwgdmFsdWUpO1xuICB9XG5cbiAgcmVtb3ZlKHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgcmVtb3ZlSW5FbGVtZW50KHRoaXMuZ2V0Q3VycmVudCwgdGhpcy5jb21taXQsIHRoaXMuaW5kZXgsIHBhdGgpO1xuICB9XG59XG5cbi8qKiBUaGUgdmFsdWUgYXQgYHBhdGhgIGluc2lkZSBlbGVtZW50IGBpbmRleGAsIGFzIGl0IHN0YW5kcyBOT1cgKHJlYWQteW91ci13cml0ZXMpLiAqL1xuZnVuY3Rpb24gcmVhZEluRWxlbWVudChnZXRDdXJyZW50OiAoKSA9PiB1bmtub3duW10sIGluZGV4OiBudW1iZXIsIHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdKTogdW5rbm93biB7XG4gIGNvbnN0IGVsZW1lbnQgPSBnZXRDdXJyZW50KClbaW5kZXhdO1xuICByZXR1cm4gcGF0aC5sZW5ndGggPT09IDAgPyBlbGVtZW50IDogbmF0aXZlR2V0KGVsZW1lbnQsIHBhdGggYXMgc3RyaW5nW10pO1xufVxuXG4vKiogQSBjb3B5IG9mIHRoZSBhcnJheSB3aXRoIGB2YWx1ZWAgYXQgYHBhdGhgIGluc2lkZSBlbGVtZW50IGBpbmRleGA7IGEgZ29uZSBlbGVtZW50IGhhcyBub3RoaW5nIHRvIHdyaXRlIGludG8uICovXG5mdW5jdGlvbiByZXBsYWNlSW5FbGVtZW50KFxuICBnZXRDdXJyZW50OiAoKSA9PiB1bmtub3duW10sXG4gIGNvbW1pdDogKG5leHQ6IHVua25vd25bXSkgPT4gdm9pZCxcbiAgaW5kZXg6IG51bWJlcixcbiAgcGF0aDogcmVhZG9ubHkgc3RyaW5nW10sXG4gIHZhbHVlOiB1bmtub3duLFxuKTogdm9pZCB7XG4gIGNvbnN0IG5leHQgPSBbLi4uZ2V0Q3VycmVudCgpXTtcbiAgaWYgKGluZGV4ID49IG5leHQubGVuZ3RoKSByZXR1cm47XG4gIG5leHRbaW5kZXhdID0gcGF0aC5sZW5ndGggPT09IDAgPyB2YWx1ZSA6IHNldEluUGF0aChuZXh0W2luZGV4XSwgcGF0aCwgdmFsdWUpO1xuICBjb21taXQobmV4dCk7XG59XG5cbi8qKiBBIGNvcHkgb2YgdGhlIGFycmF5IHdpdGggdGhlIGtleSBhdCBgcGF0aGAgaW5zaWRlIGVsZW1lbnQgYGluZGV4YCByZW1vdmVkLiAqL1xuZnVuY3Rpb24gcmVtb3ZlSW5FbGVtZW50KFxuICBnZXRDdXJyZW50OiAoKSA9PiB1bmtub3duW10sXG4gIGNvbW1pdDogKG5leHQ6IHVua25vd25bXSkgPT4gdm9pZCxcbiAgaW5kZXg6IG51bWJlcixcbiAgcGF0aDogcmVhZG9ubHkgc3RyaW5nW10sXG4pOiB2b2lkIHtcbiAgY29uc3QgbmV4dCA9IFsuLi5nZXRDdXJyZW50KCldO1xuICBpZiAoaW5kZXggPj0gbmV4dC5sZW5ndGgpIHJldHVybjtcbiAgbmV4dFtpbmRleF0gPSBkZWxldGVJblBhdGgobmV4dFtpbmRleF0sIHBhdGgpO1xuICBjb21taXQobmV4dCk7XG59XG5cbi8qKlxuICogV0hZIG9uZSBzZXQgdHJhcDogdGhlIGFzc2lnbmVkIHZhbHVlIGlzIHVud3JhcHBlZCBIRVJFIChsYW5kbWluZSAxIOKAlCB0aGVcbiAqIEpTT04gcm91bmQtdHJpcCBhcHBsaWVzIHRvIHdoYXQgdGhlIGNhbGxlciBoYW5kZWQgaW4sIG5ldmVyIHRvIHRoZVxuICogc3Vycm91bmRpbmcgc3RhdGUpIGFuZCBoYW5kZWQgdG8gdGhlIHNpbmsgYXQgdGhlIHByb3h5J3MgcGF0aCBwbHVzIHRoZSBrZXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaW5rU2V0VHJhcChzaW5rOiBXcml0ZVNpbmssIHNlZ21lbnRzOiByZWFkb25seSBzdHJpbmdbXSk6IFByb3h5SGFuZGxlcjxvYmplY3Q+WydzZXQnXSB7XG4gIHJldHVybiAoX3RhcmdldCwgcHJvcCwgdmFsdWUpID0+IHtcbiAgICBpZiAodHlwZW9mIHByb3AgIT09ICdzdHJpbmcnKSByZXR1cm4gdHJ1ZTtcbiAgICBzaW5rLnB1dChbLi4uc2VnbWVudHMsIHByb3BdLCB1bndyYXBQcm94eSh2YWx1ZSkpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG4vKipcbiAqIFdIWSBvbmUgZGVsZXRlIHRyYXA6IGBtZXJnZWAgY2Fubm90IGV4cHJlc3MgYSByZW1vdmFsIChhIHBhdGNoIG9mXG4gKiBgdW5kZWZpbmVkYCByZWFkcyBhcyBhYnNlbnQpLCBzbyBhIGRlbGV0ZSBhbHdheXMgcmVidWlsZHMgdGhyb3VnaCB0aGUgc2luay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNpbmtEZWxldGVUcmFwKHNpbms6IFdyaXRlU2luaywgc2VnbWVudHM6IHJlYWRvbmx5IHN0cmluZ1tdKTogUHJveHlIYW5kbGVyPG9iamVjdD5bJ2RlbGV0ZVByb3BlcnR5J10ge1xuICByZXR1cm4gKF90YXJnZXQsIHByb3ApID0+IHtcbiAgICBpZiAodHlwZW9mIHByb3AgIT09ICdzdHJpbmcnKSByZXR1cm4gdHJ1ZTtcbiAgICBzaW5rLnJlbW92ZShbLi4uc2VnbWVudHMsIHByb3BdKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cbiJdfQ==