opshot 0.4.0 → 0.5.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.
package/dist/index.js CHANGED
@@ -1,2019 +1,14 @@
1
1
  import * as React from 'react';
2
2
  import { memo, useState, useReducer, useRef, useEffect, createElement, useLayoutEffect } from 'react';
3
3
 
4
- // node_modules/proxy-compare/dist/index.js
5
- var GET_ORIGINAL_SYMBOL = /* @__PURE__ */ Symbol();
6
- var getProto = Object.getPrototypeOf;
7
- var objectsToTrack = /* @__PURE__ */ new WeakMap();
8
- var isObjectToTrack = (obj) => obj && (objectsToTrack.has(obj) ? objectsToTrack.get(obj) : getProto(obj) === Object.prototype || getProto(obj) === Array.prototype);
9
- var getUntracked = (obj) => {
10
- if (isObjectToTrack(obj)) {
11
- return obj[GET_ORIGINAL_SYMBOL] || null;
12
- }
13
- return null;
14
- };
15
- var markToTrack = (obj, mark = true) => {
16
- objectsToTrack.set(obj, mark);
17
- };
18
-
19
- // node_modules/valtio/esm/vanilla.mjs
20
- var isObject = (x) => typeof x === "object" && x !== null;
21
- var canProxyDefault = (x) => isObject(x) && !refSet.has(x) && (Array.isArray(x) || !(Symbol.iterator in x)) && !(x instanceof WeakMap) && !(x instanceof WeakSet) && !(x instanceof Error) && !(x instanceof Number) && !(x instanceof Date) && !(x instanceof String) && !(x instanceof RegExp) && !(x instanceof ArrayBuffer) && !(x instanceof Promise);
22
- var createSnapshotDefault = (target, version) => {
23
- const cache = snapCache.get(target);
24
- if ((cache == null ? void 0 : cache[0]) === version) {
25
- return cache[1];
26
- }
27
- const snap = Array.isArray(target) ? [] : Object.create(Object.getPrototypeOf(target));
28
- markToTrack(snap, true);
29
- snapCache.set(target, [version, snap]);
30
- Reflect.ownKeys(target).forEach((key) => {
31
- if (Object.getOwnPropertyDescriptor(snap, key)) {
32
- return;
33
- }
34
- const value = Reflect.get(target, key);
35
- const { enumerable } = Reflect.getOwnPropertyDescriptor(
36
- target,
37
- key
38
- );
39
- const desc = {
40
- value,
41
- enumerable,
42
- // This is intentional to avoid copying with proxy-compare.
43
- // It's still non-writable, so it avoids assigning a value.
44
- configurable: true
45
- };
46
- if (refSet.has(value)) {
47
- markToTrack(value, false);
48
- } else if (proxyStateMap.has(value)) {
49
- const [target2, ensureVersion] = proxyStateMap.get(
50
- value
51
- );
52
- desc.value = createSnapshotDefault(target2, ensureVersion());
53
- }
54
- Object.defineProperty(snap, key, desc);
55
- });
56
- return snap;
57
- };
58
- var createHandlerDefault = (isInitializing, addPropListener, removePropListener, notifyUpdate) => ({
59
- deleteProperty(target, prop) {
60
- Reflect.get(target, prop);
61
- removePropListener(prop);
62
- const deleted = Reflect.deleteProperty(target, prop);
63
- if (deleted) {
64
- notifyUpdate(void 0 );
65
- }
66
- return deleted;
67
- },
68
- set(target, prop, value, receiver) {
69
- const hasPrevValue = !isInitializing() && Reflect.has(target, prop);
70
- const prevValue = Reflect.get(target, prop, receiver);
71
- if (hasPrevValue && (objectIs(prevValue, value) || proxyCache.has(value) && objectIs(prevValue, proxyCache.get(value)))) {
72
- return true;
73
- }
74
- removePropListener(prop);
75
- if (isObject(value)) {
76
- value = getUntracked(value) || value;
77
- }
78
- const nextValue = !proxyStateMap.has(value) && canProxy(value) ? proxy(value) : value;
79
- addPropListener(prop, nextValue);
80
- Reflect.set(target, prop, nextValue, receiver);
81
- notifyUpdate(void 0 );
82
- return true;
83
- }
84
- });
85
- var proxyStateMap = /* @__PURE__ */ new WeakMap();
86
- var refSet = /* @__PURE__ */ new WeakSet();
87
- var snapCache = /* @__PURE__ */ new WeakMap();
88
- var versionHolder = [1];
89
- var proxyCache = /* @__PURE__ */ new WeakMap();
90
- var objectIs = Object.is;
91
- var newProxy = (target, handler) => new Proxy(target, handler);
92
- var canProxy = canProxyDefault;
93
- var createSnapshot = createSnapshotDefault;
94
- var createHandler = createHandlerDefault;
95
- function proxy(baseObject = {}) {
96
- if (!isObject(baseObject)) {
97
- throw new Error("object required");
98
- }
99
- const found = proxyCache.get(baseObject);
100
- if (found) {
101
- return found;
102
- }
103
- let version = versionHolder[0];
104
- const listeners = /* @__PURE__ */ new Set();
105
- const notifyUpdate = (op, nextVersion = ++versionHolder[0]) => {
106
- if (version !== nextVersion) {
107
- checkVersion = version = nextVersion;
108
- listeners.forEach((listener) => listener(op, nextVersion));
109
- }
110
- };
111
- let checkVersion = version;
112
- const ensureVersion = (nextCheckVersion = versionHolder[0]) => {
113
- if (checkVersion !== nextCheckVersion) {
114
- checkVersion = nextCheckVersion;
115
- propProxyStates.forEach(([propProxyState]) => {
116
- const propVersion = propProxyState[1](nextCheckVersion);
117
- if (propVersion > version) {
118
- version = propVersion;
119
- }
120
- });
121
- }
122
- return version;
123
- };
124
- const createPropListener = (prop) => (op, nextVersion) => {
125
- let newOp;
126
- if (op) {
127
- newOp = [...op];
128
- newOp[1] = [prop, ...newOp[1]];
129
- }
130
- notifyUpdate(newOp, nextVersion);
131
- };
132
- const propProxyStates = /* @__PURE__ */ new Map();
133
- const addPropListener = (prop, propValue) => {
134
- const propProxyState = !refSet.has(propValue) && proxyStateMap.get(propValue);
135
- if (propProxyState) {
136
- if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && propProxyStates.has(prop)) {
137
- throw new Error("prop listener already exists");
138
- }
139
- if (listeners.size) {
140
- const remove = propProxyState[2](createPropListener(prop));
141
- propProxyStates.set(prop, [propProxyState, remove]);
142
- } else {
143
- propProxyStates.set(prop, [propProxyState]);
144
- }
145
- }
146
- };
147
- const removePropListener = (prop) => {
148
- var _a;
149
- const entry = propProxyStates.get(prop);
150
- if (entry) {
151
- propProxyStates.delete(prop);
152
- (_a = entry[1]) == null ? void 0 : _a.call(entry);
153
- }
154
- };
155
- const addListener = (listener) => {
156
- listeners.add(listener);
157
- if (listeners.size === 1) {
158
- propProxyStates.forEach(([propProxyState, prevRemove], prop) => {
159
- if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && prevRemove) {
160
- throw new Error("remove already exists");
161
- }
162
- const remove = propProxyState[2](createPropListener(prop));
163
- propProxyStates.set(prop, [propProxyState, remove]);
164
- });
165
- }
166
- const removeListener = () => {
167
- listeners.delete(listener);
168
- if (listeners.size === 0) {
169
- propProxyStates.forEach(([propProxyState, remove], prop) => {
170
- if (remove) {
171
- remove();
172
- propProxyStates.set(prop, [propProxyState]);
173
- }
174
- });
175
- }
176
- };
177
- return removeListener;
178
- };
179
- let initializing = true;
180
- const handler = createHandler(
181
- () => initializing,
182
- addPropListener,
183
- removePropListener,
184
- notifyUpdate
185
- );
186
- const proxyObject = newProxy(baseObject, handler);
187
- proxyCache.set(baseObject, proxyObject);
188
- const proxyState = [baseObject, ensureVersion, addListener];
189
- proxyStateMap.set(proxyObject, proxyState);
190
- Reflect.ownKeys(baseObject).forEach((key) => {
191
- const desc = Object.getOwnPropertyDescriptor(
192
- baseObject,
193
- key
194
- );
195
- if ("value" in desc && desc.writable) {
196
- proxyObject[key] = baseObject[key];
197
- }
198
- });
199
- initializing = false;
200
- return proxyObject;
201
- }
202
- function getVersion(proxyObject) {
203
- const proxyState = proxyStateMap.get(proxyObject);
204
- return proxyState == null ? void 0 : proxyState[1]();
205
- }
206
- function subscribe(proxyObject, callback, notifyInSync) {
207
- const proxyState = proxyStateMap.get(proxyObject);
208
- if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && !proxyState) {
209
- console.warn("Please use proxy object");
210
- }
211
- const ops = [];
212
- const addListener = proxyState[2];
213
- const listener = (op) => {
214
- if (op) {
215
- ops.push(op);
216
- }
217
- {
218
- callback(ops.splice(0));
219
- return;
220
- }
221
- };
222
- const removeListener = addListener(listener);
223
- return () => {
224
- removeListener();
225
- };
226
- }
227
- function snapshot(proxyObject) {
228
- const proxyState = proxyStateMap.get(proxyObject);
229
- if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && !proxyState) {
230
- console.warn("Please use proxy object");
231
- }
232
- const [target, ensureVersion] = proxyState;
233
- return createSnapshot(target, ensureVersion());
234
- }
235
- function unstable_getInternalStates() {
236
- return {
237
- proxyStateMap,
238
- refSet,
239
- snapCache,
240
- versionHolder,
241
- proxyCache
242
- };
243
- }
244
- function unstable_replaceInternalFunction(name, fn) {
245
- switch (name) {
246
- case "objectIs":
247
- objectIs = fn(objectIs);
248
- break;
249
- case "newProxy":
250
- newProxy = fn(newProxy);
251
- break;
252
- case "canProxy":
253
- canProxy = fn(canProxy);
254
- break;
255
- case "createSnapshot":
256
- createSnapshot = fn(createSnapshot);
257
- break;
258
- case "createHandler":
259
- createHandler = fn(createHandler);
260
- break;
261
- default:
262
- throw new Error("unknown function");
263
- }
264
- }
265
-
266
- // src/declarations.ts
267
- function createDeclarationTrie() {
268
- return { ignored: false, unsafe: false, children: /* @__PURE__ */ new Map() };
269
- }
270
- function declarationChild(trie, key) {
271
- return trie?.children.get(String(key));
272
- }
273
- function ensureDeclarationChild(trie, key) {
274
- const name = String(key);
275
- const existing = trie.children.get(name);
276
- if (existing !== void 0) return existing;
277
- const child = createDeclarationTrie();
278
- trie.children.set(name, child);
279
- return child;
280
- }
281
- function declarationAtPath(trie, path) {
282
- let current = trie;
283
- for (const segment of path) current = ensureDeclarationChild(current, segment);
284
- return current;
285
- }
286
- function graftDeclarationChildren(source, target) {
287
- for (const [key, sourceChild] of source.children) {
288
- const targetChild = ensureDeclarationChild(target, key);
289
- if (sourceChild.ignored) targetChild.ignored = true;
290
- if (sourceChild.unsafe) targetChild.unsafe = true;
291
- graftDeclarationChildren(sourceChild, targetChild);
292
- }
293
- }
294
- function hasDeclarations(trie) {
295
- if (trie.ignored || trie.unsafe) return true;
296
- for (const child of trie.children.values()) {
297
- if (hasDeclarations(child)) return true;
298
- }
299
- return false;
300
- }
301
-
302
- // src/identity.ts
303
- var isObjectLike = (value) => value !== null && (typeof value === "object" || typeof value === "function");
304
- var targetRegistry = /* @__PURE__ */ new WeakMap();
305
- var readProxyTargets = /* @__PURE__ */ new WeakMap();
306
- var identityRecords = /* @__PURE__ */ new WeakMap();
307
- var nextInternId = 0;
308
- var { proxyStateMap: proxyStateMap2 } = unstable_getInternalStates();
309
- function registerSnapshotCopy(copy, target) {
310
- targetRegistry.set(copy, target);
311
- }
312
- function getRegisteredTarget(copy) {
313
- return targetRegistry.get(copy);
314
- }
315
- var registerReadProxyTarget = (readProxy, target) => {
316
- readProxyTargets.set(readProxy, target);
317
- };
318
- var getRegisteredReadProxyTarget = (readProxy) => readProxyTargets.get(readProxy);
319
- function peelIdentityLayer(current) {
320
- const untracked = getUntracked(current);
321
- if (untracked !== null && untracked !== current) return untracked;
322
- const readProxyTarget = getRegisteredReadProxyTarget(current);
323
- if (readProxyTarget !== void 0 && readProxyTarget !== current) return readProxyTarget;
324
- const registeredTarget = targetRegistry.get(current);
325
- if (registeredTarget !== void 0 && registeredTarget !== current) return registeredTarget;
326
- return void 0;
327
- }
328
- function resolveIdentity(value) {
329
- let current = value;
330
- while (isObjectLike(current)) {
331
- const peeled = peelIdentityLayer(current);
332
- if (peeled !== void 0) {
333
- current = peeled;
334
- continue;
335
- }
336
- const entry = proxyStateMap2.get(current);
337
- if (entry !== void 0) {
338
- const target = entry[0];
339
- if (target !== current) {
340
- current = target;
341
- continue;
342
- }
343
- }
344
- break;
345
- }
346
- return current;
347
- }
348
- var recordFor = (key) => {
349
- let record = identityRecords.get(key);
350
- if (record === void 0) {
351
- record = {};
352
- identityRecords.set(key, record);
353
- }
354
- return record;
355
- };
356
- function identify(value) {
357
- const target = resolveIdentity(value);
358
- if (!isObjectLike(target)) return value;
359
- const record = recordFor(target);
360
- if (record.token !== void 0) return record.token;
361
- const token = Object.freeze({});
362
- record.token = token;
363
- return token;
364
- }
365
- var internIdentity = (key) => {
366
- const resolved = resolveIdentity(key);
367
- const record = recordFor(resolved);
368
- if (record.id !== void 0) return record.id;
369
- const id = nextInternId;
370
- nextInternId += 1;
371
- record.id = id;
372
- return id;
373
- };
374
- function isSameIdentity(first, second) {
375
- const resolvedFirst = resolveIdentity(first);
376
- const resolvedSecond = resolveIdentity(second);
377
- return resolvedFirst === resolvedSecond;
378
- }
379
-
380
- // src/peelReadProxy.ts
381
- var { proxyStateMap: proxyStateMap3 } = unstable_getInternalStates();
382
- var isObjectLike2 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
383
- function peelReadProxy(value) {
384
- if (!isObjectLike2(value) || proxyStateMap3.has(value)) return value;
385
- let current = value;
386
- while (isObjectLike2(current)) {
387
- const registeredTarget = getRegisteredReadProxyTarget(current);
388
- if (registeredTarget === void 0) break;
389
- current = registeredTarget;
390
- }
391
- return current;
392
- }
393
-
394
- // src/handle.ts
395
- var occupancies = /* @__PURE__ */ new WeakMap();
396
- var { proxyStateMap: proxyStateMap4 } = unstable_getInternalStates();
397
- var rawTargetOf = (value) => proxyStateMap4.get(value)?.[0] ?? value;
398
- function registerHandle(target, handle) {
399
- let occupants = occupancies.get(target);
400
- if (occupants === void 0) {
401
- occupants = /* @__PURE__ */ new Set();
402
- occupancies.set(target, occupants);
403
- }
404
- for (const reference of occupants) {
405
- if (reference.deref() === handle) return;
406
- }
407
- occupants.add(new WeakRef(handle));
408
- }
409
- var rawOf = (node) => {
410
- const peeled = peelReadProxy(node);
411
- return rawTargetOf(typeof peeled === "object" && peeled !== null ? peeled : node);
412
- };
413
- function handlesOf(node) {
414
- const target = rawOf(node);
415
- const occupants = occupancies.get(target);
416
- if (occupants === void 0) return [];
417
- const handles = new Array();
418
- for (const reference of occupants) {
419
- const handle = reference.deref();
420
- if (handle === void 0) {
421
- occupants.delete(reference);
422
- continue;
423
- }
424
- handles.push(handle);
425
- }
426
- return handles;
427
- }
428
- function handleOf(node) {
429
- const target = rawOf(node);
430
- for (const handle of handlesOf(node)) {
431
- if (rawTargetOf(handle.proxy.root) === target) return handle;
432
- }
433
- return void 0;
434
- }
435
- function requireHandle(state, message) {
436
- const handle = handleOf(state);
437
- if (handle === void 0) throw new Error(message);
438
- return handle;
439
- }
440
-
441
- // src/ops/predicates.ts
442
- var MAX_ARRAY_LENGTH = 4294967295;
443
- var isObjectLike3 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
444
- var isCanonicalArrayIndex = (segment) => Number.isInteger(segment) && typeof segment === "number" && segment >= 0 && segment < MAX_ARRAY_LENGTH;
445
- var isCanonicalArrayIndexString = (key) => {
446
- const index = Number(key);
447
- return Number.isInteger(index) && index >= 0 && index < MAX_ARRAY_LENGTH && String(index) === key;
448
- };
449
-
450
- // src/utils/dataEntries.ts
451
- var walkDataEntries = (value, includeArrayLength = false) => {
452
- const entries = new Array();
453
- for (const key of Object.keys(value)) {
454
- if (key === "__proto__") continue;
455
- const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
456
- if (!descriptor || !("value" in descriptor)) continue;
457
- entries.push({ key, value: descriptor.value, writable: descriptor.writable === true });
458
- }
459
- if (includeArrayLength && Array.isArray(value)) {
460
- const lengthDescriptor = Reflect.getOwnPropertyDescriptor(value, "length");
461
- entries.push({
462
- key: "length",
463
- value: value.length,
464
- writable: lengthDescriptor?.writable === true
465
- });
466
- }
467
- return entries;
468
- };
469
- var segmentFor = (parent, key) => Array.isArray(parent) && isCanonicalArrayIndexString(key) ? Number(key) : key;
470
- var dataEntryValuesOf = (value) => {
471
- const entries = /* @__PURE__ */ new Map();
472
- for (const entry of walkDataEntries(value)) {
473
- entries.set(entry.key, entry.value);
474
- }
475
- return entries;
476
- };
477
- var carriedOwnKeysOf = (value) => Reflect.ownKeys(value).filter((key) => key !== "__proto__");
478
-
479
- // src/valtio/classify.ts
480
- var sourceCache = /* @__PURE__ */ new WeakMap();
481
- var kindCache = /* @__PURE__ */ new WeakMap();
482
- var readSource = (constructor) => {
483
- const cached = sourceCache.get(constructor);
484
- if (cached !== void 0) return cached;
485
- const source = Function.prototype.toString.call(constructor);
486
- sourceCache.set(constructor, source);
487
- return source;
488
- };
489
- var privateNameAccess = /\.\s*#[A-Za-z_$]/;
490
- var privateNameDeclaration = new RegExp(
491
- String.raw`[{;}](?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n|static\b|async\b|get\b|set\b|\*)*` + String.raw`#[A-Za-z_$][\w$]*` + String.raw`(?:[ \t]*(?:\/\*[\s\S]*?\*\/[ \t]*)*[(=;}]|[ \t]*(?:\/\/[^\n]*|\/\*[\s\S]*?\*\/[ \t]*)?(?:\r?\n|$))`,
492
- "m"
493
- );
494
- var hasPrivateName = (source) => privateNameAccess.test(source) || privateNameDeclaration.test(source);
495
- var classifyChain = (initialConstructor) => {
496
- if (typeof initialConstructor !== "function") return "cleanClass";
497
- const cached = kindCache.get(initialConstructor);
498
- if (cached !== void 0) return cached;
499
- let sawNativeSource = false;
500
- let current = initialConstructor;
501
- let kind = "cleanClass";
502
- while (typeof current === "function" && current !== Object && current !== Array && current !== Function.prototype) {
503
- const source = readSource(current);
504
- if (hasPrivateName(source)) {
505
- kind = "privateClass";
506
- break;
507
- }
508
- if (source.includes("[native code]")) sawNativeSource = true;
509
- current = Reflect.getPrototypeOf(current);
510
- }
511
- if (kind !== "privateClass") kind = sawNativeSource ? "nativeClass" : "cleanClass";
512
- kindCache.set(initialConstructor, kind);
513
- return kind;
514
- };
515
- function classifyValue(value) {
516
- const prototype = Object.getPrototypeOf(value);
517
- if (Array.isArray(value))
518
- return prototype === Array.prototype || prototype === null ? "plainArray" : "arraySubclass";
519
- if (prototype === Object.prototype || prototype === null) return "plain";
520
- return classifyChain(value.constructor);
521
- }
522
- function unfrozenAdmissionDecision(value) {
523
- if (typeof value !== "object" || value === null) return { lane: "leaf" };
524
- const kind = classifyValue(value);
525
- if (kind === "plain" || kind === "plainArray" || kind === "cleanClass") return { lane: "tracked" };
526
- return { lane: "dangerous", kind };
527
- }
528
- function admissionDecision(value) {
529
- if (typeof value !== "object" || value === null) return { lane: "leaf" };
530
- if (Object.isFrozen(value)) return { lane: "untracked" };
531
- return unfrozenAdmissionDecision(value);
532
- }
533
- function admissionLane(value) {
534
- return admissionDecision(value).lane;
535
- }
536
- function unfrozenAdmissionLane(value) {
537
- return unfrozenAdmissionDecision(value).lane;
538
- }
539
-
540
- // src/ops/cloneValue.ts
541
- var { proxyStateMap: proxyStateMap5 } = unstable_getInternalStates();
542
- var MissingOwnDescriptorError = class extends Error {
543
- constructor() {
544
- super("opshot: carried own key has no property descriptor");
545
- this.name = "MissingOwnDescriptorError";
546
- }
547
- };
548
- var isInstrumented = (value) => proxyStateMap5.has(value) || getRegisteredTarget(value) !== void 0;
549
- var isPlainArray = (value) => Array.isArray(value);
550
- var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (admissionLane(value) === "tracked" || isInstrumented(value));
551
- var isStructurallyCloneableFrozen = (value) => {
552
- if (!Object.isFrozen(value)) return false;
553
- if (Array.isArray(value)) return true;
554
- const prototype = Object.getPrototypeOf(value);
555
- return prototype === Object.prototype || prototype === null;
556
- };
557
- var isCloneable = (value) => typeof value === "object" && value !== null && (admissionLane(value) === "tracked" || isInstrumented(value) || isStructurallyCloneableFrozen(value));
558
- var cloneValue = (value, memo2, path) => {
559
- if (!isCloneable(value)) return value;
560
- const cached = memo2.get(value);
561
- if (cached !== void 0) return cached;
562
- const array = isPlainArray(value);
563
- const clone = array ? [] : {};
564
- Reflect.setPrototypeOf(clone, Reflect.getPrototypeOf(value));
565
- memo2.set(value, clone);
566
- for (const key of carriedOwnKeysOf(value)) {
567
- const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
568
- if (descriptor === void 0) throw new MissingOwnDescriptorError();
569
- if ("value" in descriptor) {
570
- Object.defineProperty(clone, key, {
571
- ...descriptor,
572
- value: cloneValue(descriptor.value, memo2)
573
- });
574
- } else {
575
- Object.defineProperty(clone, key, descriptor);
576
- }
577
- }
578
- if (Object.isFrozen(value)) Object.freeze(clone);
579
- return clone;
580
- };
581
-
582
- // src/ops/path.ts
583
- var createOperationPath = (segments) => Array.isArray(segments) && Object.isFrozen(segments) ? segments : Object.freeze([...segments]);
584
- var appendOperationPath = (path, segment) => Object.freeze([...path, segment]);
585
- var formatSegment = (segment) => String(segment);
586
- var formatOperationPath = (path) => path.length === 0 ? "/" : `/${path.map(formatSegment).join("/")}`;
587
-
588
- // src/ops/operation.ts
589
- var operationBrand = /* @__PURE__ */ Symbol.for("opshot.operation");
590
- var valueOriginals = /* @__PURE__ */ new WeakMap();
591
- var OperationHalf = class {
592
- constructor(path) {
593
- this.path = createOperationPath(path);
594
- }
595
- };
596
- Object.defineProperty(OperationHalf.prototype, operationBrand, { value: true });
597
- var AssignHalf = class extends OperationHalf {
598
- constructor(path, value, original = value, ids) {
599
- super(path);
600
- this.verb = "assign";
601
- valueOriginals.set(this, original);
602
- this.value = cloneValue(value, /* @__PURE__ */ new WeakMap(), this.path);
603
- if (ids !== void 0) this.ids = ids;
604
- }
605
- };
606
- var DeleteHalf = class extends OperationHalf {
607
- constructor() {
608
- super(...arguments);
609
- this.verb = "delete";
610
- }
611
- };
612
- var LinkHalf = class extends OperationHalf {
613
- constructor(path, ref) {
614
- super(path);
615
- this.verb = "link";
616
- this.ref = ref;
617
- }
618
- };
619
- var stampOf = (operation) => {
620
- const value = Object.getOwnPropertyDescriptor(operation, "stamp")?.value;
621
- return typeof value === "object" && value !== null ? value : void 0;
622
- };
623
- var versionOf = (operation) => {
624
- const value = Reflect.get(operation, "version");
625
- return typeof value === "number" && Number.isInteger(value) ? value : void 0;
626
- };
627
- var stampOperation = (handle, operation) => {
628
- handle.version += 1;
629
- Object.defineProperty(operation, "stamp", { value: handle.stamp, enumerable: false });
630
- Object.defineProperty(operation, "version", { value: handle.version, enumerable: true });
631
- };
632
- var isMutation = (value) => typeof value === "object" && value !== null && operationBrand in value;
633
- var getValueOriginal = (half) => valueOriginals.get(half);
634
- var createAssignMutation = (path, value, original = value, ids) => new AssignHalf(path, value, original, ids);
635
- var createDeleteMutation = (path) => new DeleteHalf(path);
636
- var createLinkMutation = (path, ref) => new LinkHalf(path, ref);
637
-
638
- // src/intern.ts
639
- var { proxyStateMap: proxyStateMap6, proxyCache: proxyCache2 } = unstable_getInternalStates();
640
- var rawTargetOf2 = (value) => proxyStateMap6.get(value)?.[0] ?? value;
641
- var occupancyNodeOf = (node) => {
642
- const peeled = peelReadProxy(node);
643
- const object = typeof peeled === "object" && peeled !== null ? peeled : node;
644
- return rawTargetOf2(getRegisteredTarget(object) ?? object);
645
- };
646
- var liveOfInterned = (raw) => proxyCache2.get(raw) ?? raw;
647
- var departingNodes = /* @__PURE__ */ new WeakMap();
648
- var committedIdOf = (handle, raw) => handle.nodes.get(raw)?.id;
649
- var writeId = (handle, raw, id) => {
650
- const record = handle.nodes.get(raw);
651
- if (record === void 0) handle.nodes.set(raw, { edges: [], id });
652
- else {
653
- if (record.id !== void 0 && record.id !== id) handle.byId.delete(record.id);
654
- record.id = id;
655
- }
656
- handle.byId.set(id, raw);
657
- };
658
- function internNode(handle, node) {
659
- const raw = occupancyNodeOf(node);
660
- const existing = committedIdOf(handle, raw);
661
- if (existing !== void 0) return existing;
662
- const id = handle.nextInternId;
663
- handle.nextInternId += 1;
664
- writeId(handle, raw, id);
665
- return id;
666
- }
667
- var stagedBindIdOf = (capture, raw) => capture.bindIdByNode.get(raw);
668
- var stagedMintIdOf = (capture, raw) => capture.mintIdByNode.get(raw);
669
- var stagedNodeOf = (capture, id) => capture.bindNodeById.get(id) ?? capture.mintNodeById.get(id);
670
- var nextStagedIdOf = (handle, capture) => Math.max(handle.nextInternId, capture.nextStagedId);
671
- var stageMint = (capture, raw, id) => {
672
- capture.mints.push({ node: raw, id });
673
- capture.mintIdByNode.set(raw, id);
674
- capture.mintNodeById.set(id, raw);
675
- if (id + 1 > capture.nextStagedId) capture.nextStagedId = id + 1;
676
- };
677
- var stageBind = (capture, raw, id) => {
678
- capture.binds.push({ node: raw, id });
679
- capture.bindIdByNode.set(raw, id);
680
- capture.bindNodeById.set(id, raw);
681
- if (id + 1 > capture.nextStagedId) capture.nextStagedId = id + 1;
682
- };
683
- var namedRawOf = (handle, id, capture) => {
684
- const staged = capture === void 0 ? void 0 : stagedNodeOf(capture, id);
685
- return staged ?? handle.byId.get(id);
686
- };
687
- function internedIdOf(handle, node, capture) {
688
- const raw = occupancyNodeOf(node);
689
- const bound = capture === void 0 ? void 0 : stagedBindIdOf(capture, raw);
690
- if (bound !== void 0) return bound;
691
- const committed = committedIdOf(handle, raw);
692
- if (committed !== void 0) return committed;
693
- if (capture === void 0) return void 0;
694
- return stagedMintIdOf(capture, raw);
695
- }
696
- function stageVend(handle, capture, node) {
697
- const raw = occupancyNodeOf(node);
698
- const bound = stagedBindIdOf(capture, raw);
699
- if (bound !== void 0) return bound;
700
- const committed = committedIdOf(handle, raw);
701
- if (committed !== void 0) return committed;
702
- const staged = stagedMintIdOf(capture, raw);
703
- if (staged !== void 0) return staged;
704
- const id = nextStagedIdOf(handle, capture);
705
- stageMint(capture, raw, id);
706
- return id;
707
- }
708
- var commitName = (handle, raw, id) => {
709
- writeId(handle, raw, id);
710
- if (id >= handle.nextInternId) handle.nextInternId = id + 1;
711
- };
712
- function commitVends(handle, capture) {
713
- for (const { node, id } of capture.mints) commitName(handle, node, id);
714
- capture.mints.length = 0;
715
- for (const { node, id } of capture.binds) commitName(handle, node, id);
716
- capture.binds.length = 0;
717
- capture.bindIdByNode.clear();
718
- capture.bindNodeById.clear();
719
- capture.mintIdByNode.clear();
720
- capture.mintNodeById.clear();
721
- capture.nextStagedId = 0;
722
- }
723
- function nodeOfInternedId(handle, id, capture) {
724
- const raw = namedRawOf(handle, id, capture);
725
- if (raw === void 0) return void 0;
726
- return liveOfInterned(raw);
727
- }
728
- var walkTracked = (node, visits, chains, resolve, visit) => {
729
- const walk = (current, currentChains, parent, key) => {
730
- const raw = occupancyNodeOf(current);
731
- if (visits.has(raw)) return;
732
- visits.add(raw);
733
- if (admissionLane(current) === "untracked") return;
734
- if (!visit(current, raw, parent, key)) return;
735
- const source = getRegisteredTarget(current) ?? current;
736
- for (const entry of walkDataEntries(source)) {
737
- if (typeof entry.value !== "object" || entry.value === null) continue;
738
- if (currentChains === void 0 || resolve === void 0) {
739
- walk(entry.value, currentChains, current, entry.key);
740
- continue;
741
- }
742
- const childChains = resolve(source, currentChains, segmentFor(source, entry.key), entry);
743
- if (childChains === void 0) continue;
744
- walk(entry.value, childChains, current, entry.key);
745
- }
746
- };
747
- walk(node, chains);
748
- };
749
- function internSubtree(handle, node, chains, resolve, capture) {
750
- walkTracked(node, /* @__PURE__ */ new Set(), chains, resolve, (current) => {
751
- if (capture === void 0) internNode(handle, current);
752
- else stageVend(handle, capture, current);
753
- return true;
754
- });
755
- }
756
- function queueDeparture(handle, node) {
757
- const raw = occupancyNodeOf(node);
758
- let queued = departingNodes.get(handle);
759
- if (queued === void 0) {
760
- queued = /* @__PURE__ */ new Set();
761
- departingNodes.set(handle, queued);
762
- }
763
- queued.add(raw);
764
- }
765
- var parentOfEdge = (parent) => occupancyNodeOf(parent);
766
- var isOccupiedMember = (handle, node) => {
767
- const root = rawTargetOf2(handle.proxy.root);
768
- const raw = occupancyNodeOf(node);
769
- if (raw === root) return true;
770
- const seen = /* @__PURE__ */ new Set();
771
- const walk = (current) => {
772
- if (current === root) return true;
773
- if (seen.has(current)) return false;
774
- seen.add(current);
775
- const edges = handle.nodes.get(current)?.edges;
776
- if (edges === void 0) return false;
777
- for (const edge of edges) {
778
- if (walk(parentOfEdge(edge.parent))) return true;
779
- }
780
- return false;
781
- };
782
- return walk(raw);
783
- };
784
- var walkUnoccupiedCluster = (handle, node, visit) => {
785
- walkTracked(node, /* @__PURE__ */ new Set(), void 0, void 0, (_current, raw) => {
786
- if (isOccupiedMember(handle, raw)) return false;
787
- visit(raw, committedIdOf(handle, raw));
788
- return true;
789
- });
790
- };
791
- var isNamedSlot = (handle, raw, evicted) => handle.nodes.has(raw) || evicted?.has(raw) === true;
792
- var walkSlots = (carried, node, isTracked, visit) => {
793
- const visits = /* @__PURE__ */ new Set();
794
- const walk = (carriedCurrent, current, parent, key) => {
795
- const raw = occupancyNodeOf(current);
796
- const looping = visits.has(raw);
797
- if (!looping) visits.add(raw);
798
- if (admissionLane(current) === "untracked") return;
799
- if (!isTracked(raw)) return;
800
- if (!visit(raw, parent, key) || looping) return;
801
- for (const entry of walkDataEntries(carriedCurrent)) {
802
- if (typeof entry.value !== "object" || entry.value === null) continue;
803
- const child = Reflect.get(current, entry.key);
804
- if (typeof child !== "object" || child === null) continue;
805
- walk(entry.value, child, current, entry.key);
806
- }
807
- };
808
- walk(carried, node);
809
- };
810
- function evictDepartedClusters(handle) {
811
- const evicted = /* @__PURE__ */ new Map();
812
- const queued = departingNodes.get(handle);
813
- if (queued === void 0) return evicted;
814
- const ungrounded = new Array();
815
- for (const node of queued) {
816
- if (!isOccupiedMember(handle, node)) ungrounded.push(node);
817
- }
818
- queued.clear();
819
- const members = new Array();
820
- for (const node of ungrounded) {
821
- walkUnoccupiedCluster(handle, node, (raw, id) => {
822
- members.push(raw);
823
- if (id !== void 0) evicted.set(raw, id);
824
- });
825
- }
826
- for (const raw of members) handle.nodes.delete(raw);
827
- for (const id of evicted.values()) handle.byId.delete(id);
828
- return evicted;
829
- }
830
- function bindVendedIds(handle, node, carried, ids, capture, parent, key) {
831
- let index = 0;
832
- walkSlots(
833
- carried,
834
- node,
835
- (raw) => isNamedSlot(handle, raw),
836
- (raw, walkParent, walkKey) => {
837
- const id = ids[index];
838
- if (id === void 0) return true;
839
- index += 1;
840
- const held = namedRawOf(handle, id, capture);
841
- const slotParent = walkParent ?? parent;
842
- const slotKey = walkKey ?? key;
843
- if (held !== void 0) {
844
- if (occupancyNodeOf(held) !== raw && slotParent !== void 0 && slotKey !== void 0) {
845
- Reflect.set(slotParent, slotKey, liveOfInterned(held));
846
- }
847
- return false;
848
- }
849
- if (capture === void 0) commitName(handle, raw, id);
850
- else stageBind(capture, raw, id);
851
- return true;
852
- }
853
- );
854
- }
855
- function rewindAdmission(handle, node) {
856
- const ids = new Array();
857
- walkUnoccupiedCluster(handle, node, (raw, id) => {
858
- if (id === void 0) return;
859
- ids.push(id);
860
- const record = handle.nodes.get(raw);
861
- if (record !== void 0) record.id = void 0;
862
- handle.byId.delete(id);
863
- });
864
- return ids;
865
- }
866
- function annotateDepartureUndos(handle, ops, evicted) {
867
- if (evicted.size === 0) return;
868
- const claimedMembers = /* @__PURE__ */ new Set();
869
- for (let index = ops.length - 1; index >= 0; index--) {
870
- const operation = ops[index];
871
- if (operation === void 0) continue;
872
- const undo = operation.undo;
873
- if (undo.verb !== "assign") continue;
874
- const original = getValueOriginal(undo) ?? undo.value;
875
- if (typeof original !== "object" || original === null) continue;
876
- const restoredId = evicted.get(occupancyNodeOf(original));
877
- if (restoredId === void 0) continue;
878
- const ids = new Array();
879
- const claimsBefore = claimedMembers.size;
880
- walkSlots(
881
- original,
882
- original,
883
- (raw) => isNamedSlot(handle, raw, evicted),
884
- (raw) => {
885
- const retiredId = evicted.get(raw);
886
- const id = retiredId ?? committedIdOf(handle, raw);
887
- if (id !== void 0) ids.push(id);
888
- if (retiredId === void 0 || claimedMembers.has(raw)) return false;
889
- claimedMembers.add(raw);
890
- return true;
891
- }
892
- );
893
- operation.undo = claimedMembers.size > claimsBefore ? createAssignMutation(undo.path, undo.value, original, ids) : createLinkMutation(undo.path, restoredId);
894
- }
895
- }
896
-
897
- // src/edges.ts
898
- var { proxyStateMap: proxyStateMap7 } = unstable_getInternalStates();
899
- var rawTargetOf3 = (value) => proxyStateMap7.get(value)?.[0] ?? value;
900
- var rawOf2 = (node) => {
901
- const peeled = peelReadProxy(node);
902
- return rawTargetOf3(typeof peeled === "object" && peeled !== null ? peeled : node);
903
- };
904
- var occupancyRootOf = (handle) => rawTargetOf3(handle.proxy.root);
905
- var edgesOf = (handle, node) => handle.nodes.get(node)?.edges;
906
- var pathHasIgnored = (trie, path) => {
907
- if (trie.ignored) return true;
908
- let current = trie;
909
- for (const key of path) {
910
- current = declarationChild(current, key);
911
- if (current === void 0) return false;
912
- if (current.ignored) return true;
913
- }
914
- return false;
915
- };
916
- var pathIsTainted = (trie, path) => {
917
- if (trie.unsafe) return true;
918
- let current = trie;
919
- for (const key of path) {
920
- current = declarationChild(current, key);
921
- if (current === void 0) return false;
922
- if (current.unsafe) return true;
923
- }
924
- return false;
925
- };
926
- var walkGroundedChains = (handle, node, onGround) => {
927
- const root = occupancyRootOf(handle);
928
- const walk = (current, reverseKeys, pathVisited) => {
929
- if (current === root) return onGround([...reverseKeys].reverse());
930
- if (pathVisited.has(current)) return false;
931
- pathVisited.add(current);
932
- const edges = edgesOf(handle, current);
933
- if (edges !== void 0) {
934
- for (const edge of edges) {
935
- if (walk(rawOf2(edge.parent), [...reverseKeys, edge.key], pathVisited)) {
936
- pathVisited.delete(current);
937
- return true;
938
- }
939
- }
940
- }
941
- pathVisited.delete(current);
942
- return false;
943
- };
944
- walk(rawOf2(node), [], /* @__PURE__ */ new Set());
945
- };
946
- function addInEdge(handle, node, parent, key) {
947
- const rawNode = rawOf2(node);
948
- const rawParent = rawOf2(parent);
949
- let record = handle.nodes.get(rawNode);
950
- if (record === void 0) {
951
- record = { edges: [], id: void 0 };
952
- handle.nodes.set(rawNode, record);
953
- }
954
- if (record.edges.some((edge) => rawOf2(edge.parent) === rawParent && edge.key === key)) return;
955
- record.edges.push({ parent: rawParent, key });
956
- registerHandle(rawNode, handle);
957
- }
958
- function hasOtherRoutes(handle, node, parent, key) {
959
- const edges = handle.nodes.get(rawOf2(node))?.edges;
960
- if (edges === void 0) return false;
961
- const rawParent = rawOf2(parent);
962
- return edges.some((edge) => rawOf2(edge.parent) !== rawParent || edge.key !== key);
963
- }
964
- function removeInEdge(handle, node, parent, key) {
965
- const rawNode = rawOf2(node);
966
- const rawParent = rawOf2(parent);
967
- const record = handle.nodes.get(rawNode);
968
- if (record === void 0) return;
969
- const index = record.edges.findIndex((edge) => rawOf2(edge.parent) === rawParent && edge.key === key);
970
- if (index === -1) return;
971
- record.edges.splice(index, 1);
972
- if (rawNode !== occupancyRootOf(handle)) queueDeparture(handle, rawNode);
973
- }
974
- function edgeStatusOf(handle, node) {
975
- const rawNode = rawOf2(node);
976
- const root = occupancyRootOf(handle);
977
- if (rawNode === root) {
978
- return { occupied: true, unsafe: handle.declarations?.unsafe === true };
979
- }
980
- if (handle.declarations === void 0) {
981
- let occupied = false;
982
- walkGroundedChains(handle, rawNode, () => {
983
- occupied = true;
984
- return true;
985
- });
986
- return { occupied, unsafe: false };
987
- }
988
- const declarations = handle.declarations;
989
- const status = { occupied: false, hasClean: false };
990
- walkGroundedChains(handle, rawNode, (pathFromRoot) => {
991
- status.occupied = true;
992
- if (!pathIsTainted(declarations, pathFromRoot)) {
993
- status.hasClean = true;
994
- return true;
995
- }
996
- return false;
997
- });
998
- return { occupied: status.occupied, unsafe: status.occupied && !status.hasClean };
999
- }
1000
- function isIgnoredFrontier(handle, parent, key) {
1001
- const trie = handle.declarations;
1002
- if (trie === void 0) return false;
1003
- let hit = false;
1004
- walkGroundedChains(handle, parent, (pathFromRoot) => {
1005
- if (pathHasIgnored(trie, [...pathFromRoot, key])) {
1006
- hit = true;
1007
- return true;
1008
- }
1009
- return false;
1010
- });
1011
- return hit;
1012
- }
1013
- var uniqueNodeChains = (entries) => {
1014
- const unique = new Array();
1015
- const undefinedFlags = /* @__PURE__ */ new Set();
1016
- const definedFlags = /* @__PURE__ */ new WeakMap();
1017
- for (const entry of entries) {
1018
- const flags = `${entry.tainted ? "1" : "0"}${entry.ignored ? "1" : "0"}`;
1019
- if (entry.residual === void 0) {
1020
- if (undefinedFlags.has(flags)) continue;
1021
- undefinedFlags.add(flags);
1022
- unique.push(entry);
1023
- continue;
1024
- }
1025
- let seen = definedFlags.get(entry.residual);
1026
- if (seen === void 0) {
1027
- seen = /* @__PURE__ */ new Set();
1028
- definedFlags.set(entry.residual, seen);
1029
- }
1030
- if (seen.has(flags)) continue;
1031
- seen.add(flags);
1032
- unique.push(entry);
1033
- }
1034
- return unique;
1035
- };
1036
- var uniqueResiduals = (residuals) => {
1037
- const unique = new Array();
1038
- let sawUndefined = false;
1039
- const seen = /* @__PURE__ */ new Set();
1040
- for (const residual of residuals) {
1041
- if (residual === void 0) {
1042
- if (sawUndefined) continue;
1043
- sawUndefined = true;
1044
- unique.push(void 0);
1045
- continue;
1046
- }
1047
- if (seen.has(residual)) continue;
1048
- seen.add(residual);
1049
- unique.push(residual);
1050
- }
1051
- return unique;
1052
- };
1053
- var chainsAtNode = (handle, node, memo2, computing) => {
1054
- const raw = rawOf2(node);
1055
- const cached = memo2.get(raw);
1056
- if (cached !== void 0) return cached;
1057
- if (computing.has(raw)) return { occupied: false, entries: [], cut: true };
1058
- if (raw === occupancyRootOf(handle)) {
1059
- const trie = handle.declarations;
1060
- const result2 = {
1061
- occupied: true,
1062
- entries: [
1063
- {
1064
- residual: trie,
1065
- tainted: trie?.unsafe === true,
1066
- ignored: trie?.ignored === true
1067
- }
1068
- ],
1069
- cut: false
1070
- };
1071
- memo2.set(raw, result2);
1072
- return result2;
1073
- }
1074
- computing.add(raw);
1075
- const aggregated = new Array();
1076
- let occupied = false;
1077
- let cut = false;
1078
- const edges = edgesOf(handle, raw);
1079
- if (edges !== void 0) {
1080
- for (const edge of edges) {
1081
- const parent = chainsAtNode(handle, edge.parent, memo2, computing);
1082
- if (parent.cut) cut = true;
1083
- if (!parent.occupied) continue;
1084
- occupied = true;
1085
- for (const entry of parent.entries) {
1086
- const child = entry.residual === void 0 ? void 0 : declarationChild(entry.residual, edge.key);
1087
- aggregated.push({
1088
- residual: child,
1089
- tainted: entry.tainted || child?.unsafe === true,
1090
- ignored: entry.ignored || child?.ignored === true
1091
- });
1092
- }
1093
- }
1094
- }
1095
- computing.delete(raw);
1096
- const result = { occupied, entries: uniqueNodeChains(aggregated), cut };
1097
- if (!cut) memo2.set(raw, result);
1098
- return result;
1099
- };
1100
- function descendChains(chains, key) {
1101
- const next = new Array();
1102
- let ignored = false;
1103
- for (const residual of chains) {
1104
- if (residual === void 0) {
1105
- next.push(void 0);
1106
- continue;
1107
- }
1108
- const child = declarationChild(residual, key);
1109
- if (child?.ignored === true) ignored = true;
1110
- if (child?.unsafe === true) continue;
1111
- next.push(child);
1112
- }
1113
- return {
1114
- ignored,
1115
- unsafe: chains.length > 0 && next.length === 0,
1116
- chains: uniqueResiduals(next)
1117
- };
1118
- }
1119
- var childChainsOf = (chains, key) => descendChains(chains, key).chains;
1120
- var isChainsIgnored = (chains) => chains.some((chain) => chain?.ignored === true);
1121
- var isChainsUnsafe = (chains) => chains.length === 0;
1122
- var chainsAtRoot = (declarations) => declarations?.unsafe === true ? [] : [declarations];
1123
- function nodeChainsOf(handle, node) {
1124
- const nodeChains = chainsAtNode(handle, node, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set());
1125
- if (!nodeChains.occupied) return void 0;
1126
- const chains = new Array();
1127
- for (const entry of nodeChains.entries) {
1128
- if (entry.tainted) continue;
1129
- chains.push(entry.residual);
1130
- }
1131
- return uniqueResiduals(chains);
1132
- }
1133
- function slotStatusOf(handle, parent, key) {
1134
- const parentChains = chainsAtNode(handle, parent, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set());
1135
- if (!parentChains.occupied) {
1136
- return { occupied: false, unsafe: false, ignored: false, chains: [] };
1137
- }
1138
- const chains = new Array();
1139
- let ignored = false;
1140
- for (const entry of parentChains.entries) {
1141
- const child = entry.residual === void 0 ? void 0 : declarationChild(entry.residual, key);
1142
- const slotIgnored = entry.ignored || child?.ignored === true;
1143
- const tainted = entry.tainted || child?.unsafe === true;
1144
- if (slotIgnored) ignored = true;
1145
- if (!tainted) chains.push(child);
1146
- }
1147
- return {
1148
- ignored,
1149
- occupied: true,
1150
- unsafe: chains.length === 0,
1151
- chains: uniqueResiduals(chains)
1152
- };
1153
- }
1154
- var isTrackedEdge = (entry) => {
1155
- const value = entry.value;
1156
- const target = isObjectLike3(value) ? getRegisteredTarget(value) ?? value : value;
1157
- return entry.writable && admissionLane(target) === "tracked";
1158
- };
1159
- var graphNodeOf = (value) => rawOf2(getRegisteredTarget(value) ?? value);
1160
- function resolveChildChains(handle, parent, parentChains, key, child) {
1161
- const descended = descendChains(parentChains, key).chains;
1162
- const ignoredResidual = isChainsIgnored(parentChains) || isChainsIgnored(descended);
1163
- if (!isObjectLike3(parent) || !isObjectLike3(child)) {
1164
- if (ignoredResidual) return void 0;
1165
- return { chains: descended, descended, otherRoutes: false };
1166
- }
1167
- const graphParent = graphNodeOf(parent);
1168
- const graphChild = graphNodeOf(child);
1169
- const otherRoutes = hasOtherRoutes(handle, graphChild, graphParent, key);
1170
- const ignored = ignoredResidual || otherRoutes && isIgnoredFrontier(handle, graphParent, key);
1171
- if (ignored) return void 0;
1172
- const chains = otherRoutes ? nodeChainsOf(handle, graphChild) ?? descended : descended;
1173
- return { chains, descended, otherRoutes };
1174
- }
1175
- var seedFrom = (handle, node, chains, visits) => {
1176
- if (isChainsIgnored(chains)) return;
1177
- const raw = rawOf2(node);
1178
- if (visits.has(raw)) return;
1179
- visits.add(raw);
1180
- for (const entry of walkDataEntries(raw)) {
1181
- if (!isTrackedEdge(entry)) continue;
1182
- if (typeof entry.value !== "object" || entry.value === null) continue;
1183
- const key = segmentFor(raw, entry.key);
1184
- const resolved = resolveChildChains(handle, raw, chains, key, entry.value);
1185
- if (resolved === void 0) continue;
1186
- addInEdge(handle, entry.value, raw, key);
1187
- seedFrom(handle, entry.value, resolved.chains, visits);
1188
- }
1189
- };
1190
- function seedInEdges(handle) {
1191
- seedFrom(handle, handle.proxy.root, chainsAtRoot(handle.declarations), /* @__PURE__ */ new Set());
1192
- }
1193
- function seedInEdgesUnder(handle, node, chains) {
1194
- seedFrom(handle, node, chains, /* @__PURE__ */ new Set());
1195
- }
1196
-
1197
- // src/occupancy.ts
1198
- var { proxyStateMap: proxyStateMap8 } = unstable_getInternalStates();
1199
- var rawTargetOf4 = (value) => proxyStateMap8.get(value)?.[0] ?? value;
1200
- var liveOf = (value) => getRegisteredTarget(value) ?? rawTargetOf4(value);
1201
- var createCaptureTables = () => ({
1202
- mints: [],
1203
- binds: [],
1204
- bindIdByNode: /* @__PURE__ */ new Map(),
1205
- bindNodeById: /* @__PURE__ */ new Map(),
1206
- mintIdByNode: /* @__PURE__ */ new Map(),
1207
- mintNodeById: /* @__PURE__ */ new Map(),
1208
- nextStagedId: 0
1209
- });
1210
- var occupancyKeyOf = (key) => typeof key === "number" ? String(key) : key;
1211
- function bindVisitedOccupancy(handle, path, parent, key, child, unsafe = false, ignoredFrontier) {
1212
- if (path.length === 0) return "continue";
1213
- if (ignoredFrontier ?? isIgnoredFrontier(handle, parent, key)) return "skip";
1214
- const parentRaw = liveOf(parent);
1215
- const occupancyKey = occupancyKeyOf(key);
1216
- const admitted = unsafe || !handle.strict;
1217
- if (typeof child === "function") {
1218
- const parentKind = classifyValue(parentRaw);
1219
- if (parentKind === "plain" || parentKind === "plainArray") return "continue";
1220
- if (admitted) return "continue";
1221
- return "skip";
1222
- }
1223
- const stored = Reflect.get(parentRaw, occupancyKey);
1224
- const occupantSource = isObjectLike3(stored) ? stored : child;
1225
- if (typeof occupantSource !== "object" || occupantSource === null) return "continue";
1226
- const childLive = liveOf(occupantSource);
1227
- const descriptor = Reflect.getOwnPropertyDescriptor(parentRaw, occupancyKey);
1228
- if (descriptor !== void 0 && descriptor.writable !== true && admissionDecision(childLive).lane !== "untracked")
1229
- return "skip";
1230
- const decision = admissionDecision(childLive);
1231
- if (decision.lane === "untracked") return "skip";
1232
- if (decision.lane === "dangerous") {
1233
- if (admitted) return "continue";
1234
- return "skip";
1235
- }
1236
- if (!admitted && classifyValue(childLive) === "cleanClass") {
1237
- for (const entry of walkDataEntries(childLive)) {
1238
- if (typeof entry.value !== "function") continue;
1239
- return "skip";
1240
- }
1241
- }
1242
- return "continue";
1243
- }
1244
- function markDirtyPath(dirty, handle, path, parentLive) {
1245
- let current = handle.proxy.root;
1246
- if (isObjectLike3(current)) dirty.nodes.add(rawTargetOf4(current));
1247
- for (const segment of path) {
1248
- if (!isObjectLike3(current)) break;
1249
- current = Reflect.get(current, segment);
1250
- if (isObjectLike3(current)) dirty.nodes.add(rawTargetOf4(current));
1251
- }
1252
- if (parentLive === void 0 || path.length === 0) return;
1253
- const lastSegment = path[path.length - 1];
1254
- if (lastSegment === void 0) return;
1255
- const edge = typeof lastSegment === "number" ? String(lastSegment) : lastSegment;
1256
- const parentRaw = rawTargetOf4(parentLive);
1257
- let edges = dirty.edges.get(parentRaw);
1258
- if (edges === void 0) {
1259
- edges = /* @__PURE__ */ new Set();
1260
- dirty.edges.set(parentRaw, edges);
1261
- }
1262
- edges.add(edge);
1263
- }
1264
- var walkLiveOccupancies = (handle, capture) => {
1265
- const root = handle.proxy.root;
1266
- const visits = /* @__PURE__ */ new Set();
1267
- const rootChains = handle.declarations?.unsafe === true ? [] : [handle.declarations];
1268
- const walk = (node, path, chains) => {
1269
- if (chains.some((residual) => residual?.ignored === true)) return;
1270
- stageVend(handle, capture, node);
1271
- const nodeRaw = rawTargetOf4(node);
1272
- if (visits.has(nodeRaw)) return;
1273
- visits.add(nodeRaw);
1274
- for (const entry of walkDataEntries(node)) {
1275
- const key = segmentFor(node, entry.key);
1276
- const childPath = appendOperationPath(path, key);
1277
- const slot = slotStatusOf(handle, node, key);
1278
- const descended = descendChains(chains, key);
1279
- const ignored = slot.ignored || descended.ignored;
1280
- const unsafe = slot.occupied ? slot.unsafe : descended.unsafe;
1281
- const childChains = slot.occupied ? slot.chains : descended.chains;
1282
- if (ignored) continue;
1283
- const visit = bindVisitedOccupancy(handle, childPath, node, entry.key, entry.value, unsafe);
1284
- if (visit !== "continue") continue;
1285
- if (typeof entry.value === "object" && entry.value !== null) walk(entry.value, childPath, childChains);
1286
- }
1287
- };
1288
- walk(root, createOperationPath([]), rootChains);
1289
- };
1290
- function seedOccupancies(handle) {
1291
- const capture = createCaptureTables();
1292
- walkLiveOccupancies(handle, capture);
1293
- commitVends(handle, capture);
1294
- }
1295
- function syncHandleTables(handle, capture) {
1296
- walkLiveOccupancies(handle, capture);
1297
- }
1298
-
1299
- // src/ops/admission.ts
1300
- var { proxyStateMap: proxyStateMap9 } = unstable_getInternalStates();
1301
- var rawTargetOf5 = (value) => proxyStateMap9.get(value)?.[0] ?? value;
1302
- var MissingDiffParentError = class extends Error {
1303
- constructor() {
1304
- super("opshot: admitStep could not resolve a live parent");
1305
- this.name = "MissingDiffParentError";
1306
- }
1307
- };
1308
- var admitStep = (handle, dirty, path, liveParent, residual) => {
1309
- if (path.length === 0) {
1310
- return { visit: "continue", ignored: isChainsIgnored(residual), liveChild: liveParent, chains: residual };
1311
- }
1312
- const key = path[path.length - 1];
1313
- const liveChild = isObjectLike3(liveParent) && key !== void 0 ? Reflect.get(liveParent, key) : void 0;
1314
- if (handle === void 0) {
1315
- const childChains = key === void 0 ? residual : childChainsOf(residual, key);
1316
- return { visit: "continue", ignored: isChainsIgnored(childChains), liveChild, chains: childChains };
1317
- }
1318
- if (key === void 0) {
1319
- return { visit: "continue", ignored: isChainsIgnored(residual), liveChild: liveParent, chains: residual };
1320
- }
1321
- const resolved = resolveChildChains(handle, liveParent, residual, key, liveChild);
1322
- const ignored = resolved === void 0;
1323
- const chains = resolved?.chains ?? childChainsOf(residual, key);
1324
- if (dirty === void 0) return { visit: "continue", ignored, liveChild, chains };
1325
- if (ignored) return { visit: "skip", ignored, liveChild, chains };
1326
- if (resolved.otherRoutes) {
1327
- if (!isObjectLike3(liveParent) || !isObjectLike3(liveChild)) throw new MissingDiffParentError();
1328
- const slot = slotStatusOf(handle, liveParent, key);
1329
- let unsafe = slot.occupied ? slot.unsafe : isChainsUnsafe(resolved.descended);
1330
- const status = edgeStatusOf(handle, liveChild);
1331
- if (status.occupied) unsafe = status.unsafe;
1332
- return {
1333
- visit: bindVisitedOccupancy(handle, path, liveParent, key, liveChild, unsafe, false),
1334
- ignored,
1335
- liveChild,
1336
- chains
1337
- };
1338
- }
1339
- if (!isObjectLike3(liveParent)) throw new MissingDiffParentError();
1340
- return {
1341
- visit: bindVisitedOccupancy(handle, path, liveParent, key, liveChild, isChainsUnsafe(resolved.descended), false),
1342
- ignored,
1343
- liveChild,
1344
- chains
1345
- };
1346
- };
1347
- var admitDescendants = (handle, path, visits, residual, liveNode, unsafe = false) => {
1348
- if (handle === void 0) return;
1349
- if (!isObjectLike3(liveNode)) return;
1350
- const nodeKey = rawTargetOf5(liveNode);
1351
- if (visits.has(nodeKey)) return;
1352
- visits.add(nodeKey);
1353
- if (isChainsIgnored(residual)) return;
1354
- const nodeUnsafe = unsafe || isChainsUnsafe(residual);
1355
- for (const entry of walkDataEntries(liveNode)) {
1356
- if (typeof entry.value !== "object" || entry.value === null) continue;
1357
- const key = segmentFor(liveNode, entry.key);
1358
- const childPath = appendOperationPath(path, key);
1359
- const descended = descendChains(residual, key);
1360
- let ignored;
1361
- let childChains;
1362
- let childUnsafe;
1363
- let ignoredFrontier;
1364
- if (hasOtherRoutes(handle, entry.value, liveNode, key)) {
1365
- const slot = slotStatusOf(handle, liveNode, key);
1366
- ignored = slot.ignored || descended.ignored;
1367
- childChains = nodeChainsOf(handle, entry.value) ?? descended.chains;
1368
- childUnsafe = slot.occupied ? slot.unsafe : nodeUnsafe || descended.unsafe;
1369
- ignoredFrontier = void 0;
1370
- } else {
1371
- ignored = descended.ignored || isChainsIgnored(descended.chains);
1372
- childChains = descended.chains;
1373
- childUnsafe = nodeUnsafe || descended.unsafe;
1374
- ignoredFrontier = false;
1375
- }
1376
- if (ignored) continue;
1377
- const visit = bindVisitedOccupancy(
1378
- handle,
1379
- childPath,
1380
- liveNode,
1381
- entry.key,
1382
- entry.value,
1383
- childUnsafe,
1384
- ignoredFrontier
1385
- );
1386
- if (visit !== "continue") continue;
1387
- admitDescendants(handle, childPath, visits, childChains, Reflect.get(liveNode, key), childUnsafe);
1388
- }
1389
- };
1390
- var markChangedPath = (handle, dirty, path, liveParent) => {
1391
- if (handle === void 0 || dirty === void 0 || path.length === 0) return;
1392
- if (!isObjectLike3(liveParent)) return;
1393
- markDirtyPath(dirty, handle, path, liveParent);
1394
- };
1395
- var emitsSkippedOccupancy = (value) => isObjectLike3(value) && admissionLane(value) === "untracked";
1396
-
1397
- // src/ops/ancestorPairs.ts
1398
- var MissingAncestorPairError = class extends Error {
1399
- constructor() {
1400
- super("opshot: exitAncestorPair without matching enterAncestorPair");
1401
- this.name = "MissingAncestorPairError";
1402
- }
1403
- };
1404
- var hasAncestorPair = (ancestors, before, after) => ancestors.get(before)?.has(after) ?? false;
1405
- var enterAncestorPair = (ancestors, before, after) => {
1406
- const afterSet = ancestors.get(before) ?? /* @__PURE__ */ new Set();
1407
- afterSet.add(after);
1408
- ancestors.set(before, afterSet);
1409
- };
1410
- var exitAncestorPair = (ancestors, before, after) => {
1411
- const afterSet = ancestors.get(before);
1412
- if (afterSet === void 0) throw new MissingAncestorPairError();
1413
- afterSet.delete(after);
1414
- if (afterSet.size === 0) ancestors.delete(before);
1415
- };
1416
- var walkContainer = (ancestors, before, after, walk) => {
1417
- if (hasAncestorPair(ancestors, before, after)) return;
1418
- enterAncestorPair(ancestors, before, after);
1419
- try {
1420
- walk();
1421
- } finally {
1422
- exitAncestorPair(ancestors, before, after);
1423
- }
1424
- };
1425
-
1426
- // src/ops/internedOccupancy.ts
1427
- var { proxyStateMap: proxyStateMap10 } = unstable_getInternalStates();
1428
- var rawTargetOf6 = (value) => proxyStateMap10.get(value)?.[0] ?? value;
1429
- var liveOf2 = (node) => getRegisteredTarget(node) ?? node;
1430
- var occupancyNodeOf2 = (node) => rawTargetOf6(liveOf2(node));
1431
- var internedOccupied = (handle, node, capture) => internedIdOf(handle, node, capture) !== void 0 && edgeStatusOf(handle, occupancyNodeOf2(node)).occupied;
1432
-
1433
- // src/ops/mintPairs.ts
1434
- var additionPair = (path, after, ids) => ({
1435
- do: createAssignMutation(path, after, after, ids),
1436
- undo: createDeleteMutation(path)
1437
- });
1438
- var removalPair = (path, before) => ({
1439
- do: createDeleteMutation(path),
1440
- undo: createAssignMutation(path, before)
1441
- });
1442
- var linkUndo = (path, before, beforePresent, handle, capture) => {
1443
- if (!beforePresent) return createDeleteMutation(path);
1444
- if (handle !== void 0 && isObjectLike3(before) && internedOccupied(handle, before, capture)) {
1445
- const id = internedIdOf(handle, before, capture);
1446
- if (id !== void 0) return createLinkMutation(path, id);
1447
- }
1448
- return createAssignMutation(path, before);
1449
- };
1450
- var linkOperation = (path, ref, before, beforePresent, handle, capture) => ({
1451
- do: createLinkMutation(path, ref),
1452
- undo: linkUndo(path, before, beforePresent, handle, capture)
1453
- });
1454
- var changePair = (path, before, after, handle, capture, ids) => ({
1455
- do: createAssignMutation(path, after, after, ids),
1456
- undo: linkUndo(path, before, true, handle, capture)
1457
- });
1458
-
1459
- // src/ops/diff.ts
1460
- var IncompatibleObjectRootsError = class extends Error {
1461
- constructor() {
1462
- super("opshot: diffObjects requires compatible supported object roots");
1463
- this.name = "IncompatibleObjectRootsError";
1464
- }
1465
- };
1466
- var commitOperation = (context, pair) => {
1467
- context.ops.push(pair);
1468
- };
1469
- var commitLink = (context, path, ref, before, beforePresent) => {
1470
- commitOperation(context, linkOperation(path, ref, before, beforePresent, context.handle, context.capture));
1471
- };
1472
- var emptyContainerOf = (value) => isPlainArray(value) ? [] : {};
1473
- var namedArrayEntriesOf = (value) => {
1474
- const named = /* @__PURE__ */ new Map();
1475
- for (const key of Object.keys(value)) {
1476
- if (key === "__proto__" || isCanonicalArrayIndexString(key)) continue;
1477
- const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
1478
- if (!descriptor || !("value" in descriptor)) continue;
1479
- named.set(key, descriptor.value);
1480
- }
1481
- return named;
1482
- };
1483
- var mintDecomposedContents = (context, path, after, verdict) => {
1484
- const residual = verdict.chains;
1485
- const liveNode = verdict.liveChild;
1486
- if (isPlainArray(after)) {
1487
- if (after.length > 0)
1488
- commitOperation(
1489
- context,
1490
- changePair(appendOperationPath(path, "length"), 0, after.length, context.handle, context.capture)
1491
- );
1492
- for (let index = 0; index < after.length; index++) {
1493
- if (!Object.hasOwn(after, index)) continue;
1494
- const nextPath = appendOperationPath(path, index);
1495
- const childVerdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1496
- pushAddition(context, nextPath, after[index], childVerdict, liveNode);
1497
- }
1498
- for (const [key, value] of namedArrayEntriesOf(after)) {
1499
- const nextPath = appendOperationPath(path, key);
1500
- const childVerdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1501
- pushAddition(context, nextPath, value, childVerdict, liveNode);
1502
- }
1503
- } else {
1504
- for (const entry of walkDataEntries(after)) {
1505
- const nextPath = appendOperationPath(path, entry.key);
1506
- const childVerdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1507
- pushAddition(context, nextPath, entry.value, childVerdict, liveNode);
1508
- }
1509
- }
1510
- };
1511
- var mintDecomposedAddition = (context, path, after, verdict) => {
1512
- commitOperation(context, {
1513
- do: createAssignMutation(path, emptyContainerOf(after), after),
1514
- undo: createDeleteMutation(path)
1515
- });
1516
- mintDecomposedContents(context, path, after, verdict);
1517
- };
1518
- var mintDecomposedChange = (context, path, before, after, verdict) => {
1519
- commitOperation(context, {
1520
- do: createAssignMutation(path, emptyContainerOf(after), after),
1521
- undo: linkUndo(path, before, true, context.handle, context.capture)
1522
- });
1523
- mintDecomposedContents(context, path, after, verdict);
1524
- };
1525
- var surveyAssignedSubtree = (handle, capture, node, residual, stopAtInternedOccupied) => {
1526
- const visits = /* @__PURE__ */ new Set();
1527
- const pending = new Array();
1528
- const visit = (current, currentResidual) => {
1529
- const raw = occupancyNodeOf2(current);
1530
- if (visits.has(raw)) return false;
1531
- visits.add(raw);
1532
- if (admissionLane(current) === "untracked") return false;
1533
- if (stopAtInternedOccupied) {
1534
- if (current !== node) pending.push(current);
1535
- } else stageVend(handle, capture, current);
1536
- const source = liveOf2(current);
1537
- for (const entry of walkDataEntries(source)) {
1538
- if (typeof entry.value !== "object" || entry.value === null) continue;
1539
- if (!isTrackedEdge(entry)) continue;
1540
- const key = segmentFor(source, entry.key);
1541
- const resolved = resolveChildChains(handle, source, currentResidual, key, entry.value);
1542
- if (resolved === void 0) continue;
1543
- const child = entry.value;
1544
- if (stopAtInternedOccupied && internedOccupied(handle, child, capture)) return true;
1545
- if (visit(child, resolved.chains)) return true;
1546
- }
1547
- return false;
1548
- };
1549
- if (stopAtInternedOccupied) stageVend(handle, capture, node);
1550
- const reachesInternedOccupied = visit(node, residual);
1551
- if (stopAtInternedOccupied && !reachesInternedOccupied) {
1552
- for (const pendingNode of pending) stageVend(handle, capture, pendingNode);
1553
- }
1554
- return { reachesInternedOccupied };
1555
- };
1556
- var internIdsOfSubtree = (handle, node, capture) => {
1557
- const seen = /* @__PURE__ */ new Set();
1558
- const ids = new Array();
1559
- const walk = (current) => {
1560
- const id = internedIdOf(handle, current, capture);
1561
- if (id === void 0 || seen.has(id)) return;
1562
- seen.add(id);
1563
- ids.push(id);
1564
- for (const entry of walkDataEntries(liveOf2(current))) {
1565
- if (typeof entry.value === "object" && entry.value !== null) walk(entry.value);
1566
- }
1567
- };
1568
- walk(node);
1569
- return ids.length === 0 ? void 0 : ids;
1570
- };
1571
- var mintAssignment = (context, path, before, after, beforePresent, verdict) => {
1572
- if (verdict.ignored) return;
1573
- const handle = context.handle;
1574
- if (isObjectLike3(after) && handle !== void 0) {
1575
- const internedId = internedIdOf(handle, after, context.capture);
1576
- if (internedId !== void 0 && internedOccupied(handle, after, context.capture)) {
1577
- const sameOccupant = isObjectLike3(before) && occupancyNodeOf2(before) === occupancyNodeOf2(after);
1578
- const beforeInterned = isObjectLike3(before) && internedIdOf(handle, before, context.capture) !== void 0;
1579
- const uninternedTrackedBefore = isObjectLike3(before) && !beforeInterned && admissionLane(before) !== "untracked";
1580
- if (!sameOccupant && !uninternedTrackedBefore) {
1581
- commitLink(context, path, internedId, before, beforePresent);
1582
- return;
1583
- }
1584
- surveyAssignedSubtree(handle, context.capture, after, verdict.chains, false);
1585
- } else if (admissionLane(after) !== "untracked" && (isPlainObject(after) || isPlainArray(after))) {
1586
- const { reachesInternedOccupied } = surveyAssignedSubtree(
1587
- handle,
1588
- context.capture,
1589
- after,
1590
- verdict.chains,
1591
- true
1592
- );
1593
- if (reachesInternedOccupied) {
1594
- if (!beforePresent) {
1595
- mintDecomposedAddition(context, path, after, verdict);
1596
- return;
1597
- }
1598
- mintDecomposedChange(context, path, before, after, verdict);
1599
- return;
1600
- }
1601
- } else {
1602
- admitDescendants(handle, path, /* @__PURE__ */ new Set(), verdict.chains, verdict.liveChild);
1603
- internSubtree(
1604
- handle,
1605
- after,
1606
- verdict.chains,
1607
- (parent, parentChains, key, entry) => isTrackedEdge(entry) ? resolveChildChains(handle, parent, parentChains, key, entry.value)?.chains : void 0,
1608
- context.capture
1609
- );
1610
- }
1611
- } else if (isObjectLike3(after)) admitDescendants(context.handle, path, /* @__PURE__ */ new Set(), verdict.chains, verdict.liveChild);
1612
- const ids = isObjectLike3(after) && handle !== void 0 ? internIdsOfSubtree(handle, after, context.capture) : void 0;
1613
- if (beforePresent) commitOperation(context, changePair(path, before, after, handle, context.capture, ids));
1614
- else commitOperation(context, additionPair(path, after, ids));
1615
- };
1616
- var pushAddition = (context, path, after, verdict, liveParent) => {
1617
- const { visit, ignored } = verdict;
1618
- if (visit === "skip") {
1619
- if (ignored || !emitsSkippedOccupancy(after)) return;
1620
- } else if (ignored) return;
1621
- markChangedPath(context.handle, context.dirty, path, liveParent);
1622
- mintAssignment(context, path, void 0, after, false, verdict);
1623
- };
1624
- var pushRemoval = (context, path, before, verdict, liveParent) => {
1625
- if (verdict.ignored) return;
1626
- markChangedPath(context.handle, context.dirty, path, liveParent);
1627
- const handle = context.handle;
1628
- if (isObjectLike3(before) && handle !== void 0) {
1629
- const id = internedIdOf(handle, before, context.capture);
1630
- if (id !== void 0 && internedOccupied(handle, before, context.capture)) {
1631
- commitOperation(context, {
1632
- do: createDeleteMutation(path),
1633
- undo: createLinkMutation(path, id)
1634
- });
1635
- return;
1636
- }
1637
- }
1638
- commitOperation(context, removalPair(path, before));
1639
- };
1640
- var pushChange = (context, path, before, after, verdict, liveParent) => {
1641
- markChangedPath(context.handle, context.dirty, path, liveParent);
1642
- mintAssignment(context, path, before, after, true, verdict);
1643
- };
1644
- var sharesStorageIdentity = (before, after) => isObjectLike3(before) && isObjectLike3(after) && isSameIdentity(before, after);
1645
- var diffCollectedProperties = (context, before, after, path, residual, liveNode, beforeEntries, afterEntries) => {
1646
- const keys = /* @__PURE__ */ new Set([...beforeEntries.keys(), ...afterEntries.keys()]);
1647
- for (const key of keys) {
1648
- const nextPath = appendOperationPath(path, key);
1649
- const beforePresent = beforeEntries.has(key);
1650
- const afterPresent = afterEntries.has(key);
1651
- if (beforePresent && afterPresent) {
1652
- diffValue(context, beforeEntries.get(key), afterEntries.get(key), nextPath, residual, liveNode);
1653
- } else if (beforePresent && !Object.hasOwn(after, key)) {
1654
- const verdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1655
- pushRemoval(context, nextPath, beforeEntries.get(key), verdict, liveNode);
1656
- } else if (afterPresent && !Object.hasOwn(before, key)) {
1657
- const verdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1658
- pushAddition(context, nextPath, afterEntries.get(key), verdict, liveNode);
1659
- }
1660
- }
1661
- };
1662
- var diffObjectProperties = (context, before, after, path, residual, liveNode) => {
1663
- diffCollectedProperties(
1664
- context,
1665
- before,
1666
- after,
1667
- path,
1668
- residual,
1669
- liveNode,
1670
- dataEntryValuesOf(before),
1671
- dataEntryValuesOf(after)
1672
- );
1673
- };
1674
- var diffArray = (context, before, after, path, residual, liveNode) => {
1675
- const overlap = Math.min(before.length, after.length);
1676
- for (let index = 0; index < overlap; index++) {
1677
- const beforePresent = Object.hasOwn(before, index);
1678
- const afterPresent = Object.hasOwn(after, index);
1679
- if (!beforePresent && !afterPresent) continue;
1680
- const nextPath = appendOperationPath(path, index);
1681
- if (!beforePresent) {
1682
- const verdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1683
- pushAddition(context, nextPath, after[index], verdict, liveNode);
1684
- } else if (!afterPresent) {
1685
- const verdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1686
- pushRemoval(context, nextPath, before[index], verdict, liveNode);
1687
- } else diffValue(context, before[index], after[index], nextPath, residual, liveNode);
1688
- }
1689
- if (after.length > before.length) {
1690
- const lengthPath = appendOperationPath(path, "length");
1691
- const lengthVerdict = admitStep(context.handle, context.dirty, lengthPath, liveNode, residual);
1692
- pushChange(context, lengthPath, before.length, after.length, lengthVerdict, liveNode);
1693
- for (let index = before.length; index < after.length; index++) {
1694
- if (!Object.hasOwn(after, index)) continue;
1695
- const nextPath = appendOperationPath(path, index);
1696
- const verdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1697
- pushAddition(context, nextPath, after[index], verdict, liveNode);
1698
- }
1699
- } else if (after.length < before.length) {
1700
- for (let index = after.length; index < before.length; index++) {
1701
- if (!Object.hasOwn(before, index)) continue;
1702
- const nextPath = appendOperationPath(path, index);
1703
- const verdict = admitStep(context.handle, context.dirty, nextPath, liveNode, residual);
1704
- pushRemoval(context, nextPath, before[index], verdict, liveNode);
1705
- }
1706
- const lengthPath = appendOperationPath(path, "length");
1707
- const lengthVerdict = admitStep(context.handle, context.dirty, lengthPath, liveNode, residual);
1708
- pushChange(context, lengthPath, before.length, after.length, lengthVerdict, liveNode);
1709
- }
1710
- diffCollectedProperties(
1711
- context,
1712
- before,
1713
- after,
1714
- path,
1715
- residual,
1716
- liveNode,
1717
- namedArrayEntriesOf(before),
1718
- namedArrayEntriesOf(after)
1719
- );
1720
- };
1721
- var diffValue = (context, before, after, path, residual, liveParent) => {
1722
- const replacing = path.length > 0 && isObjectLike3(before) && isObjectLike3(after) && !sharesStorageIdentity(before, after);
1723
- const verdict = admitStep(context.handle, context.dirty, path, liveParent, residual);
1724
- const { visit, ignored, liveChild, chains } = verdict;
1725
- if (visit === "skip" || ignored) {
1726
- if (Object.is(before, after)) return;
1727
- if (isObjectLike3(before) && isObjectLike3(after) && sharesStorageIdentity(before, after)) return;
1728
- if (ignored || !emitsSkippedOccupancy(after)) return;
1729
- pushChange(context, path, before, after, verdict, liveParent);
1730
- return;
1731
- }
1732
- if (Object.is(before, after)) return;
1733
- if (replacing) {
1734
- pushChange(context, path, before, after, verdict, liveParent);
1735
- return;
1736
- }
1737
- if (isPlainArray(before) && isPlainArray(after)) {
1738
- walkContainer(context.ancestors, before, after, () => diffArray(context, before, after, path, chains, liveChild));
1739
- return;
1740
- }
1741
- if (isPlainObject(before) && isPlainObject(after)) {
1742
- walkContainer(
1743
- context.ancestors,
1744
- before,
1745
- after,
1746
- () => diffObjectProperties(context, before, after, path, chains, liveChild)
1747
- );
1748
- return;
1749
- }
1750
- pushChange(context, path, before, after, verdict, liveParent);
1751
- };
1752
- var getRootKind = (value) => {
1753
- if (isPlainArray(value)) return "plainArray";
1754
- if (isPlainObject(value)) return "plainObject";
1755
- return void 0;
1756
- };
1757
- function diffObjects(before, after, handle, dirty, capture) {
1758
- const beforeKind = getRootKind(before);
1759
- const afterKind = getRootKind(after);
1760
- if (beforeKind === void 0 || beforeKind !== afterKind) throw new IncompatibleObjectRootsError();
1761
- const ops = new Array();
1762
- const context = {
1763
- ops,
1764
- ancestors: /* @__PURE__ */ new Map(),
1765
- handle,
1766
- dirty,
1767
- capture: capture ?? createCaptureTables()
1768
- };
1769
- diffValue(
1770
- context,
1771
- before,
1772
- after,
1773
- createOperationPath([]),
1774
- handle === void 0 ? [void 0] : chainsAtRoot(handle.declarations),
1775
- handle?.proxy.root
1776
- );
1777
- return ops;
1778
- }
1779
-
1780
- // src/emit/emitterDeliver.ts
1781
- var collectDeliveries = (handle) => {
1782
- const deliveries = [];
1783
- for (const groupListeners of handle.groups ?? []) {
1784
- for (const byChannel of groupListeners.values()) {
1785
- for (const deliverToListener of byChannel.values()) {
1786
- deliveries.push({ kind: "group", deliver: deliverToListener });
1787
- }
1788
- }
1789
- }
1790
- for (const byChannel of handle.subscribers.values()) {
1791
- for (const deliverToListener of byChannel.values()) {
1792
- deliveries.push({ kind: "own", deliver: deliverToListener });
1793
- }
1794
- }
1795
- return deliveries;
1796
- };
1797
- var runDelivery = (pending, failures) => {
1798
- const handle = handleOf(pending.writeProxy);
1799
- if (handle !== void 0) handle.lastDirty = pending.dirty;
1800
- for (const delivery of pending.deliveries) {
1801
- try {
1802
- if (delivery.kind === "group") {
1803
- delivery.deliver(pending.writeProxy, pending.ops, pending.meta, pending.channelId);
1804
- } else {
1805
- delivery.deliver(pending.ops, pending.meta, pending.channelId);
1806
- }
1807
- } catch (error) {
1808
- failures.push(error);
1809
- }
1810
- }
1811
- };
1812
- var raiseFailures = (failures) => {
1813
- if (failures.length === 0) return;
1814
- if (failures.length > 1) throw new AggregateError(failures, "opshot: listeners failed during delivery");
1815
- throw failures[0];
1816
- };
1817
- var queuedDeliveries = [];
1818
- var deliveryFailures = [];
1819
- var isDraining = false;
1820
- var prepareDelivery = (handle, ops, meta, channelId, dirty) => ({
1821
- writeProxy: handle.proxy.root,
1822
- deliveries: collectDeliveries(handle),
1823
- ops,
1824
- meta,
1825
- channelId,
1826
- dirty
1827
- });
1828
- var enqueueDelivery = (pending) => {
1829
- queuedDeliveries.push(pending);
1830
- };
1831
- var drainDeliveries = () => {
1832
- if (isDraining) return;
1833
- isDraining = true;
1834
- let failures = [];
1835
- try {
1836
- while (queuedDeliveries.length > 0) {
1837
- for (const queued of queuedDeliveries.splice(0, queuedDeliveries.length)) {
1838
- runDelivery(queued, deliveryFailures);
1839
- }
1840
- }
1841
- } finally {
1842
- isDraining = false;
1843
- failures = deliveryFailures.splice(0, deliveryFailures.length);
1844
- }
1845
- raiseFailures(failures);
1846
- };
1847
-
1848
- // src/emit/emitterRegistry.ts
1849
- var { proxyStateMap: proxyStateMap11 } = unstable_getInternalStates();
1850
- var targetOf = (writeProxy) => proxyStateMap11.get(writeProxy)?.[0] ?? writeProxy;
1851
-
1852
- // src/emit/emitter.ts
1853
- function scheduleFlush(handle) {
1854
- if (handle.isFlushScheduled) return;
1855
- handle.isFlushScheduled = true;
1856
- const generation = handle.flushGeneration;
1857
- const run = () => {
1858
- if (generation !== handle.flushGeneration) return;
1859
- handle.isFlushScheduled = false;
1860
- emitWrites(handle);
1861
- };
1862
- void Promise.resolve().then(() => {
1863
- const emitOn = handle.emitOn;
1864
- if (emitOn === void 0) {
1865
- run();
1866
- return;
1867
- }
1868
- emitOn(run);
1869
- });
1870
- }
1871
- function armWatch(handle) {
1872
- handle.disarmWatch = subscribe(
1873
- handle.proxy.root,
1874
- () => {
1875
- handle.hasPendingWrites = true;
1876
- if (handle.isFlushHeld) return;
1877
- scheduleFlush(handle);
1878
- });
1879
- }
1880
- var cloneSnapshotNode = (snap) => {
1881
- const clone = Array.isArray(snap) ? [] : Object.create(Reflect.getPrototypeOf(snap));
1882
- for (const key of carriedOwnKeysOf(snap)) {
1883
- const descriptor = Reflect.getOwnPropertyDescriptor(snap, key);
1884
- if (descriptor !== void 0) Object.defineProperty(clone, key, descriptor);
1885
- }
1886
- if (Array.isArray(snap)) clone.length = snap.length;
1887
- registerSnapshotCopy(clone, getRegisteredTarget(snap) ?? targetOf(snap));
1888
- return clone;
1889
- };
1890
- var reconcileUntracked = (snap, live, seen) => {
1891
- if (seen.has(live)) return snap;
1892
- seen.add(live);
1893
- let result;
1894
- const written = () => {
1895
- result ??= cloneSnapshotNode(snap);
1896
- return result;
1897
- };
1898
- for (const key of carriedOwnKeysOf(live)) {
1899
- const liveValue = Reflect.get(live, key);
1900
- if (typeof liveValue !== "object" || liveValue === null) continue;
1901
- if (admissionLane(liveValue) === "untracked") {
1902
- if (Reflect.get(snap, key) === liveValue) continue;
1903
- const snapChild2 = Reflect.get(snap, key);
1904
- if (typeof snapChild2 !== "object" || snapChild2 === null) continue;
1905
- if (getRegisteredTarget(snapChild2) !== targetOf(liveValue)) continue;
1906
- const descriptor = Reflect.getOwnPropertyDescriptor(live, key);
1907
- if (descriptor === void 0 || descriptor.get !== void 0 || descriptor.set !== void 0) continue;
1908
- Object.defineProperty(written(), key, {
1909
- value: liveValue,
1910
- enumerable: descriptor.enumerable,
1911
- configurable: true
1912
- });
1913
- continue;
1914
- }
1915
- const snapChild = Reflect.get(snap, key);
1916
- if (typeof snapChild !== "object" || snapChild === null) continue;
1917
- const reconciled = reconcileUntracked(snapChild, liveValue, seen);
1918
- if (reconciled === snapChild) continue;
1919
- Object.defineProperty(written(), key, {
1920
- value: reconciled,
1921
- enumerable: true,
1922
- configurable: true
1923
- });
1924
- }
1925
- return result ?? snap;
1926
- };
1927
- var captureDiffOf = (handle, from, capture) => {
1928
- const to = snapshot(handle.proxy.root);
1929
- const dirty = { edges: /* @__PURE__ */ new WeakMap(), nodes: /* @__PURE__ */ new WeakSet() };
1930
- if (from === to) {
1931
- syncHandleTables(handle, capture);
1932
- return { to, ops: [], dirty, capture };
1933
- }
1934
- return {
1935
- to,
1936
- ops: diffObjects(reconcileUntracked(from, handle.proxy.root, /* @__PURE__ */ new WeakSet()), to, handle, dirty, capture),
1937
- dirty,
1938
- capture
1939
- };
1940
- };
1941
- var captureRange = (handle, meta, channelId) => {
1942
- handle.hasPendingWrites = false;
1943
- const from = handle.lastSnapshot;
1944
- const capture = handle.transactionCapture ?? createCaptureTables();
1945
- const committed = captureDiffOf(handle, from, capture);
1946
- const ops = committed.ops;
1947
- commitVends(handle, committed.capture);
1948
- handle.lastSnapshot = committed.to;
1949
- const evicted = evictDepartedClusters(handle);
1950
- if (ops.length > 0) annotateDepartureUndos(handle, ops, evicted);
1951
- if (ops.length > 0 && !handle.replaying) {
1952
- for (const operation of ops) stampOperation(handle, operation);
1953
- }
1954
- return ops.length > 0 ? prepareDelivery(handle, ops, meta, channelId, committed.dirty) : void 0;
1955
- };
1956
- function deliverCapturedRanges(ranges) {
1957
- for (const captured of ranges) {
1958
- if (captured !== void 0) enqueueDelivery(captured);
1959
- }
1960
- drainDeliveries();
1961
- }
1962
- var emitRange = (handle, meta, channelId) => {
1963
- const captured = captureRange(handle, meta, channelId);
1964
- if (captured !== void 0) enqueueDelivery(captured);
1965
- drainDeliveries();
1966
- };
1967
- function captureWrites(handle) {
1968
- return captureRange(handle, void 0, void 0);
1969
- }
1970
- function captureTransactionWrites(handle, meta, channelId) {
1971
- return captureRange(handle, meta, channelId);
1972
- }
1973
- function emitWrites(handle) {
1974
- emitRange(handle, void 0, void 0);
1975
- }
1976
-
1977
- // src/emit/requireObjectSnapshot.ts
1978
- var ObjectRootSnapshotError = class extends Error {
1979
- constructor() {
1980
- super("opshot: state snapshots must have an object root");
1981
- this.name = "ObjectRootSnapshotError";
1982
- }
1983
- };
1984
- var requireObjectSnapshot = (value) => {
1985
- if (value !== null && (typeof value === "object" || typeof value === "function")) return value;
1986
- throw new ObjectRootSnapshotError();
1987
- };
1988
-
1989
- // src/ignore.ts
1990
- var ignoreMarker = /* @__PURE__ */ Symbol("opshot.ignore");
1991
- function ignore(value) {
1992
- return { [ignoreMarker]: value };
1993
- }
1994
-
1995
- // src/isState.ts
1996
- var { proxyStateMap: proxyStateMap12 } = unstable_getInternalStates();
1997
- function isState(value) {
1998
- const resolved = peelReadProxy(value);
1999
- if (typeof resolved !== "object" || resolved === null) return false;
2000
- return proxyStateMap12.has(resolved);
2001
- }
2002
-
2003
- // src/unsafeTrack.ts
2004
- var unsafeMarker = /* @__PURE__ */ Symbol("opshot.unsafe");
2005
- function unsafeTrack(value) {
2006
- return { [unsafeMarker]: value };
2007
- }
2008
-
2009
4
  // src/utils/constructorName.ts
2010
5
  var constructorName = (candidate) => typeof candidate === "function" && candidate.name !== "" ? candidate.name : "Object";
2011
6
 
2012
- // src/valtio/boundaryErrors.ts
7
+ // src/boundaryErrors.ts
2013
8
  var ignoreOption = "ignore(value) to store it by reference, untracked";
2014
9
  var unsafeTrackDataOption = "unsafeTrack(value) to track its data anyway";
2015
- var unsafeTrackPrivateOption = "unsafeTrack(value) tracks public fields while private methods throw on snapshots and undo drops that state";
2016
- var unsafeTrackSlotOption = "unsafeTrack(value) tracks public fields while slot methods throw on snapshots and undo drops that state";
10
+ var unsafeTrackPrivateOption = "unsafeTrack(value) tracks public fields while private methods stay untracked";
11
+ var unsafeTrackSlotOption = "unsafeTrack(value) tracks public fields while slot methods stay untracked";
2017
12
  var unsafeTrackLossyOption = "unsafeTrack(value) to track it lossily";
2018
13
  var locationClause = (path) => path === void 0 || path.length === 0 ? "" : ` at /${path.join("/")}`;
2019
14
  var boundaryError = (className, reason, options, path) => new Error(
@@ -2026,12 +21,7 @@ var slotContainerError = (className, trackedName, path) => boundaryError(
2026
21
  [`use ${trackedName} for a tracked equivalent`, unsafeTrackLossyOption, ignoreOption],
2027
22
  path
2028
23
  );
2029
- var arraySubclassError = (className, path) => boundaryError(
2030
- className,
2031
- "array subclasses lose their prototype in snapshots",
2032
- [unsafeTrackDataOption, ignoreOption],
2033
- path
2034
- );
24
+ var arraySubclassError = (className, path) => boundaryError(className, "array subclasses are not plain arrays", [unsafeTrackDataOption, ignoreOption], path);
2035
25
  var cleanClassError = (className, path) => boundaryError(className, "arrow-method writes won't be tracked", [unsafeTrackDataOption, ignoreOption], path);
2036
26
  var privateClassError = (className, path) => boundaryError(className, "its state is hidden in private fields", [unsafeTrackPrivateOption, ignoreOption], path);
2037
27
  var nativeClassError = (className, path) => boundaryError(className, "its state is hidden in internal slots", [unsafeTrackSlotOption, ignoreOption], path);
@@ -2041,9 +31,6 @@ var nonWritablePropertyError = (value, path) => boundaryError(
2041
31
  ["make the property writable", "ignore(value) to declare the escape"],
2042
32
  path
2043
33
  );
2044
- var snapshotDonationError = (key) => new Error(
2045
- `opshot: cannot assign a snapshot generation at "${String(key)}": a snapshot generation is a read-view, and assigning it creates a dead region. Clone the value, or replay through applyOperations.`
2046
- );
2047
34
  var inheritsFromPrototype = (value, prototype) => {
2048
35
  for (let current = Reflect.getPrototypeOf(value); current !== null; current = Reflect.getPrototypeOf(current))
2049
36
  if (current === prototype) return true;
@@ -2066,1081 +53,646 @@ var rejectionError = (value, kind, path) => {
2066
53
  }
2067
54
  };
2068
55
 
2069
- // src/valtio/snapshotAccessors.ts
2070
- var { proxyStateMap: proxyStateMap13, snapCache: snapCache2 } = unstable_getInternalStates();
2071
- var MissingOwnDescriptorError2 = class extends Error {
2072
- constructor() {
2073
- super("opshot: carried own key has no property descriptor");
2074
- this.name = "MissingOwnDescriptorError";
2075
- }
56
+ // src/classify.ts
57
+ var isDangerousKind = (kind) => kind !== "plain" && kind !== "plainArray" && kind !== "cleanClass";
58
+ var sourceCache = /* @__PURE__ */ new WeakMap();
59
+ var kindCache = /* @__PURE__ */ new WeakMap();
60
+ var readSource = (constructor) => {
61
+ const cached = sourceCache.get(constructor);
62
+ if (cached !== void 0) return cached;
63
+ const source = Function.prototype.toString.call(constructor);
64
+ sourceCache.set(constructor, source);
65
+ return source;
2076
66
  };
2077
- var createSnapshotPreservingAccessors = (target, version) => {
2078
- const cached = snapCache2.get(target);
2079
- if (cached?.[0] === version) {
2080
- const cachedSnapshot = cached[1];
2081
- for (const key of carriedOwnKeysOf(target)) {
2082
- const value = Reflect.get(target, key);
2083
- if (typeof value !== "object" || value === null) continue;
2084
- if (admissionLane(value) !== "untracked") continue;
2085
- if (Reflect.get(cachedSnapshot, key) === value) continue;
2086
- const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
2087
- if (descriptor === void 0 || descriptor.get !== void 0 || descriptor.set !== void 0) continue;
2088
- Object.defineProperty(cachedSnapshot, key, {
2089
- value,
2090
- enumerable: descriptor.enumerable,
2091
- configurable: true
2092
- });
2093
- markToTrack(value, false);
2094
- }
2095
- if (getRegisteredTarget(cachedSnapshot) === void 0) {
2096
- registerSnapshotCopy(cachedSnapshot, target);
2097
- }
2098
- return cachedSnapshot;
2099
- }
2100
- const snap = Array.isArray(target) ? [] : Object.create(Reflect.getPrototypeOf(target));
2101
- registerSnapshotCopy(snap, target);
2102
- markToTrack(snap, true);
2103
- snapCache2.set(target, [version, snap]);
2104
- for (const key of carriedOwnKeysOf(target)) {
2105
- if (Object.getOwnPropertyDescriptor(snap, key)) continue;
2106
- const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
2107
- if (descriptor === void 0) throw new MissingOwnDescriptorError2();
2108
- if (descriptor.get || descriptor.set) {
2109
- Object.defineProperty(snap, key, {
2110
- get: descriptor.get,
2111
- set: descriptor.set,
2112
- enumerable: descriptor.enumerable,
2113
- configurable: true
2114
- });
2115
- continue;
2116
- }
2117
- const value = Reflect.get(target, key);
2118
- const snapshotDescriptor = { value, enumerable: descriptor.enumerable, configurable: true };
2119
- if (typeof value === "object" && value !== null) {
2120
- if (admissionLane(value) === "untracked") {
2121
- markToTrack(value, false);
2122
- } else {
2123
- const childState = proxyStateMap13.get(value);
2124
- if (childState)
2125
- snapshotDescriptor.value = createSnapshotPreservingAccessors(childState[0], childState[1]());
2126
- }
67
+ var privateNameAccess = /\.\s*#[A-Za-z_$]/;
68
+ var privateNameDeclaration = new RegExp(
69
+ String.raw`[{;}](?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n|static\b|async\b|get\b|set\b|\*)*` + String.raw`#[A-Za-z_$][\w$]*` + String.raw`(?:[ \t]*(?:\/\*[\s\S]*?\*\/[ \t]*)*[(=;}]|[ \t]*(?:\/\/[^\n]*|\/\*[\s\S]*?\*\/[ \t]*)?(?:\r?\n|$))`,
70
+ "m"
71
+ );
72
+ var hasPrivateName = (source) => privateNameAccess.test(source) || privateNameDeclaration.test(source);
73
+ var classifyChain = (initialConstructor) => {
74
+ if (typeof initialConstructor !== "function") return "cleanClass";
75
+ const cached = kindCache.get(initialConstructor);
76
+ if (cached !== void 0) return cached;
77
+ let sawNativeSource = false;
78
+ let current = initialConstructor;
79
+ let kind = "cleanClass";
80
+ while (typeof current === "function" && current !== Object && current !== Array && current !== Function.prototype) {
81
+ const source = readSource(current);
82
+ if (hasPrivateName(source)) {
83
+ kind = "privateClass";
84
+ break;
2127
85
  }
2128
- Object.defineProperty(snap, key, snapshotDescriptor);
2129
- }
2130
- if (Array.isArray(target) && snap.length !== target.length) {
2131
- snap.length = target.length;
86
+ if (source.includes("[native code]")) sawNativeSource = true;
87
+ current = Reflect.getPrototypeOf(current);
2132
88
  }
2133
- return snap;
89
+ if (kind !== "privateClass") kind = sawNativeSource ? "nativeClass" : "cleanClass";
90
+ kindCache.set(initialConstructor, kind);
91
+ return kind;
2134
92
  };
93
+ function classifyValue(value) {
94
+ const prototype = Object.getPrototypeOf(value);
95
+ if (Array.isArray(value))
96
+ return prototype === Array.prototype || prototype === null ? "plainArray" : "arraySubclass";
97
+ if (prototype === Object.prototype || prototype === null) return "plain";
98
+ return classifyChain(value.constructor);
99
+ }
2135
100
 
2136
- // src/valtio/boundary.ts
2137
- var { proxyStateMap: proxyStateMap14, proxyCache: proxyCache3 } = unstable_getInternalStates();
2138
- var rawTargetOf7 = (value) => proxyStateMap14.get(value)?.[0] ?? value;
2139
- var handleOwning = (target) => {
2140
- const handles = handlesOf(target);
2141
- const raw = rawTargetOf7(target);
2142
- for (const handle of handles) {
2143
- if (rawTargetOf7(handle.proxy.root) === raw) return handle;
2144
- }
2145
- return handles[0];
2146
- };
2147
- var segmentForProp = (parent, prop) => isPlainArray(parent) && isCanonicalArrayIndexString(prop) ? Number(prop) : prop;
2148
- var setFrameStack = new Array();
2149
- var currentSetParentOf = () => setFrameStack[setFrameStack.length - 1]?.target;
2150
- var currentStatuses = () => setFrameStack[setFrameStack.length - 1]?.statuses;
2151
- var heldStatusesOf = (target, prop) => {
2152
- const key = segmentForProp(target, prop);
2153
- const statuses = new Array();
2154
- for (const handle of handlesOf(target)) {
2155
- const slot = slotStatusOf(handle, target, key);
2156
- if (!slot.occupied) continue;
2157
- statuses.push({ handle, ignored: slot.ignored, unsafe: slot.unsafe, chains: slot.chains });
2158
- }
2159
- return statuses.length === 0 ? void 0 : statuses;
2160
- };
2161
- var inheritedStatusesOf = (target, prop) => {
2162
- const parent = setFrameStack[setFrameStack.length - 1];
2163
- if (parent?.statuses === void 0) return void 0;
2164
- const key = segmentForProp(target, prop);
2165
- return parent.statuses.map((status) => {
2166
- const descended = descendChains(status.chains, key);
2167
- return {
2168
- handle: status.handle,
2169
- ignored: status.ignored || descended.ignored,
2170
- unsafe: status.unsafe || descended.unsafe,
2171
- chains: descended.chains
2172
- };
2173
- });
2174
- };
2175
- var statusesForFrame = (target, prop, initializing) => {
2176
- if (typeof prop !== "string") return void 0;
2177
- if (!initializing) return heldStatusesOf(target, prop);
2178
- return inheritedStatusesOf(target, prop) ?? heldStatusesOf(target, prop);
2179
- };
2180
- var certifyAdmission = (value, path, unsafe = false) => {
2181
- const decision = admissionDecision(value);
2182
- if (decision.lane === "dangerous" && !unsafe) throw rejectionError(value, decision.kind, path);
2183
- return decision.lane;
2184
- };
2185
- var peelSnapshotsAndReadProxies = (value) => {
2186
- let current = value;
2187
- while (typeof current === "object" && current !== null) {
2188
- const untracked = getUntracked(current);
2189
- const next = peelReadProxy(untracked ?? current);
2190
- if (next === current) break;
2191
- current = next;
2192
- }
2193
- return current;
2194
- };
2195
- var walkDataPaths = (value, path, visits, mode, chains, ignored, unsafe) => {
2196
- const node = mode === "admission" ? rawTargetOf7(value) : value;
2197
- if (visits.has(node)) return;
2198
- visits.add(node);
2199
- if (ignored) return;
2200
- for (const entry of walkDataEntries(node)) {
2201
- const childPath = [...path, entry.key];
2202
- const descended = descendChains(chains, segmentForProp(node, entry.key));
2203
- const childIgnored = descended.ignored;
2204
- const childUnsafe = unsafe || descended.unsafe;
2205
- const childChains = descended.chains;
2206
- const child = entry.value;
2207
- if (mode === "admission" && classifyValue(node) === "cleanClass" && !unsafe && typeof child === "function")
2208
- throw rejectionError(node, "cleanClass", childPath);
2209
- if (typeof child !== "object" || child === null) continue;
2210
- if (!entry.writable) {
2211
- if (mode === "admission" && !childIgnored && !childUnsafe && admissionLane(child) !== "untracked")
2212
- throw nonWritablePropertyError(child, childPath);
2213
- continue;
2214
- }
2215
- if (childIgnored) continue;
2216
- let childNode = child;
2217
- if (proxyStateMap14.has(childNode)) {
2218
- if (mode !== "admission") continue;
2219
- childNode = rawTargetOf7(childNode);
2220
- }
2221
- if (mode === "admission") {
2222
- if (childUnsafe) {
2223
- walkDataPaths(childNode, childPath, visits, mode, childChains, childIgnored, childUnsafe);
2224
- continue;
2225
- }
2226
- if (certifyAdmission(childNode, childPath, childUnsafe) === "tracked")
2227
- walkDataPaths(childNode, childPath, visits, mode, childChains, childIgnored, childUnsafe);
2228
- continue;
2229
- }
2230
- if (admissionLane(childNode) === "untracked") continue;
2231
- walkDataPaths(childNode, childPath, visits, mode, childChains, childIgnored, childUnsafe);
2232
- }
2233
- };
2234
- var assertSafeDataPaths = (value, path, visits, mode = "admission", chains = []) => {
2235
- walkDataPaths(
2236
- value,
2237
- path,
2238
- visits,
2239
- mode,
2240
- chains,
2241
- chains.some((residual) => residual?.ignored === true),
2242
- chains.some((residual) => residual?.unsafe === true)
2243
- );
2244
- };
2245
- var certifyCurrentAssignment = (target, prop, resolved) => {
2246
- if (typeof prop !== "string") return;
2247
- const assignments = currentStatuses();
2248
- if (assignments === void 0) return;
2249
- const path = [prop];
2250
- for (const assignment of assignments) {
2251
- if (!assignment.handle.strict || assignment.ignored || assignment.unsafe) continue;
2252
- if (typeof resolved === "function") {
2253
- const parentKind = classifyValue(rawTargetOf7(target));
2254
- if (parentKind !== "plain" && parentKind !== "plainArray")
2255
- throw rejectionError(rawTargetOf7(target), parentKind, path);
2256
- continue;
2257
- }
2258
- const decision = admissionDecision(resolved);
2259
- if (decision.lane === "dangerous") throw rejectionError(resolved, decision.kind, path);
2260
- if (decision.lane === "tracked")
2261
- walkDataPaths(
2262
- resolved,
2263
- path,
2264
- /* @__PURE__ */ new Set(),
2265
- "admission",
2266
- assignment.chains,
2267
- assignment.ignored,
2268
- assignment.unsafe
2269
- );
2270
- }
2271
- };
2272
- var writesThroughAccessor = (target, property) => {
2273
- let holder = target;
2274
- while (holder !== null) {
2275
- const descriptor = Reflect.getOwnPropertyDescriptor(holder, property);
2276
- if (descriptor !== void 0) return !("value" in descriptor);
2277
- holder = Reflect.getPrototypeOf(holder);
2278
- }
2279
- return false;
2280
- };
2281
- var refusesWrite = (target, property, value) => {
2282
- if (Array.isArray(target)) {
2283
- if (property === "length") {
2284
- const coercible = value === null || typeof value !== "object" && typeof value !== "function";
2285
- const newLength = coercible ? Number(value) : Number.NaN;
2286
- if (Number.isInteger(newLength) && newLength >= 0 && newLength < target.length) {
2287
- for (const key of Reflect.ownKeys(target)) {
2288
- if (typeof key !== "string") continue;
2289
- const index = Number(key);
2290
- if (Number.isInteger(index) && index >= newLength && index < 2 ** 32 - 1 && String(index) === key && Reflect.getOwnPropertyDescriptor(target, key)?.configurable !== true)
2291
- return true;
2292
- }
2293
- }
2294
- } else if (typeof property === "string") {
2295
- const index = Number(property);
2296
- if (Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === property && index >= target.length && Reflect.getOwnPropertyDescriptor(target, "length")?.writable === false)
2297
- return true;
2298
- }
2299
- }
2300
- let holder = target;
2301
- while (holder !== null) {
2302
- const descriptor = Reflect.getOwnPropertyDescriptor(holder, property);
2303
- if (descriptor !== void 0) {
2304
- if ("value" in descriptor) {
2305
- if (descriptor.writable !== true) return true;
2306
- return holder !== target && !Object.isExtensible(target);
2307
- }
2308
- return descriptor.set === void 0;
2309
- }
2310
- holder = Reflect.getPrototypeOf(holder);
2311
- }
2312
- return !Object.isExtensible(target);
2313
- };
2314
- function canProxy2(value, parentTarget, unsafe = false) {
2315
- if (typeof value !== "object" || value === null) return false;
2316
- if (admissionLane(value) === "tracked") return true;
2317
- if (unsafe) return true;
2318
- if (proxyStateMap14.has(value)) return true;
2319
- const rootHandle = handleOwning(value);
2320
- if (rootHandle !== void 0 && rawTargetOf7(rootHandle.proxy.root) === rawTargetOf7(value) && (!rootHandle.strict || rootHandle.declarations?.unsafe === true))
2321
- return true;
2322
- if (parentTarget === void 0) return false;
2323
- const handles = handlesOf(parentTarget);
2324
- return handles.length === 1 && handles[0]?.strict === false && admissionLane(value) === "dangerous";
101
+ // src/node.ts
102
+ var byRaw = /* @__PURE__ */ new WeakMap();
103
+ var byProxy = /* @__PURE__ */ new WeakMap();
104
+ var proxyHandler;
105
+ function installProxyHandler(handler2) {
106
+ proxyHandler = handler2;
107
+ }
108
+ function recordOf(value) {
109
+ return byRaw.get(value) ?? byProxy.get(value);
110
+ }
111
+ function rawOf(value) {
112
+ return recordOf(value)?.raw ?? value;
113
+ }
114
+ function proxyOf(raw) {
115
+ const existing = recordOf(raw);
116
+ if (existing !== void 0) return existing.proxy;
117
+ if (proxyHandler === void 0) throw new Error("opshot: proxy handler is not installed");
118
+ const proxy = new Proxy(raw, proxyHandler);
119
+ const record = { raw, proxy, memberships: /* @__PURE__ */ new Map() };
120
+ byRaw.set(raw, record);
121
+ byProxy.set(proxy, record);
122
+ return proxy;
2325
123
  }
2326
- var MissingMutationTrapError = class extends Error {
2327
- constructor() {
2328
- super("opshot: valtio default handler is missing a mutation trap");
2329
- this.name = "MissingMutationTrapError";
2330
- }
2331
- };
2332
- var canProxyCurrentAssignment = (value) => {
2333
- const assignments = currentStatuses();
2334
- if (assignments === void 0) return canProxy2(value, currentSetParentOf());
2335
- const judging = assignments.filter((assignment) => !assignment.ignored);
2336
- if (judging.length === 0) return false;
2337
- return canProxy2(
2338
- value,
2339
- currentSetParentOf(),
2340
- judging.every((assignment) => assignment.unsafe || !assignment.handle.strict)
2341
- );
2342
- };
2343
- var truncatedOccupantsOf = (target, prop, next) => {
2344
- if (!Array.isArray(target) || prop !== "length") return void 0;
2345
- const coercible = next === null || typeof next !== "object" && typeof next !== "function";
2346
- const newLength = coercible ? Number(next) : Number.NaN;
2347
- if (!Number.isInteger(newLength) || newLength < 0 || newLength >= target.length) return void 0;
2348
- const truncated = new Array();
2349
- for (let index = newLength; index < target.length; index++) {
2350
- const occupant = Reflect.get(target, index);
2351
- if (typeof occupant === "object" && occupant !== null) truncated.push({ index, occupant });
2352
- }
2353
- return truncated;
2354
- };
2355
- var commitSetInEdges = (target, prop, previous, next, truncated) => {
2356
- const handles = handlesOf(target);
2357
- if (handles.length === 0) return;
2358
- if (truncated !== void 0) {
2359
- for (const { index, occupant } of truncated) {
2360
- for (const handle of handles) removeInEdge(handle, occupant, target, index);
2361
- }
2362
- return;
2363
- }
2364
- if (typeof prop !== "string") return;
2365
- const key = segmentForProp(target, prop);
2366
- const previousObject = typeof previous === "object" && previous !== null ? previous : void 0;
2367
- const nextObject = typeof next === "object" && next !== null && admissionLane(next) !== "untracked" ? next : void 0;
2368
- for (const handle of handles) {
2369
- if (isIgnoredFrontier(handle, target, key)) {
2370
- if (previousObject !== void 0) removeInEdge(handle, previousObject, target, key);
2371
- continue;
2372
- }
2373
- if (previousObject !== void 0) removeInEdge(handle, previousObject, target, key);
2374
- if (nextObject === void 0) continue;
2375
- const rawNext = rawTargetOf7(nextObject);
2376
- const wasOccupied = rawNext === rawTargetOf7(handle.proxy.root) || (handle.nodes.get(rawNext)?.edges.length ?? 0) > 0;
2377
- addInEdge(handle, nextObject, target, key);
2378
- if (wasOccupied) continue;
2379
- const slot = slotStatusOf(handle, target, key);
2380
- seedInEdgesUnder(handle, nextObject, slot.chains);
124
+ function handlesOf(node) {
125
+ return membershipsOf(node).map(([handle]) => handle);
126
+ }
127
+ function membershipsOf(node) {
128
+ const record = recordOf(rawOf(node));
129
+ if (record === void 0) return [];
130
+ const memberships = new Array();
131
+ for (const [handle, membership] of record.memberships) {
132
+ if (membership.edges > 0) memberships.push([handle, membership]);
2381
133
  }
2382
- };
2383
- var commitDeleteInEdges = (target, prop, previous) => {
2384
- if (typeof prop !== "string") return;
2385
- if (typeof previous !== "object" || previous === null) return;
2386
- const key = segmentForProp(target, prop);
2387
- for (const handle of handlesOf(target)) removeInEdge(handle, previous, target, key);
2388
- };
2389
- var installed = false;
2390
- function installBoundary() {
2391
- if (installed) return;
2392
- installed = true;
2393
- unstable_replaceInternalFunction("canProxy", () => (value) => canProxyCurrentAssignment(value));
2394
- unstable_replaceInternalFunction("createSnapshot", () => createSnapshotPreservingAccessors);
2395
- unstable_replaceInternalFunction(
2396
- "createHandler",
2397
- (createHandler2) => (isInitializing, addPropListener, removePropListener, notifyUpdate) => {
2398
- const handler = createHandler2(isInitializing, addPropListener, removePropListener, notifyUpdate);
2399
- const defaultDelete = handler.deleteProperty;
2400
- const defaultSet = handler.set;
2401
- if (!defaultDelete || !defaultSet) throw new MissingMutationTrapError();
2402
- return {
2403
- ...handler,
2404
- set(target, prop, value, receiver) {
2405
- const assigned = value;
2406
- const resolved = peelSnapshotsAndReadProxies(assigned);
2407
- const truncated = truncatedOccupantsOf(target, prop, resolved);
2408
- const previous = typeof prop === "string" ? Reflect.get(target, prop) : void 0;
2409
- const initializing = isInitializing();
2410
- setFrameStack.push({ target, prop, statuses: statusesForFrame(target, prop, initializing) });
2411
- try {
2412
- if (typeof resolved === "object" && resolved !== null) {
2413
- if (getRegisteredTarget(resolved) !== void 0) throw snapshotDonationError(prop);
2414
- if (refusesWrite(target, prop, resolved)) return false;
2415
- if (!initializing && !writesThroughAccessor(target, prop))
2416
- certifyCurrentAssignment(target, prop, resolved);
2417
- const alreadyTracked = proxyStateMap14.has(resolved) || proxyCache3.has(resolved);
2418
- const instrumented = !alreadyTracked && canProxyCurrentAssignment(resolved) ? proxy(resolved) : resolved;
2419
- const result2 = defaultSet(target, prop, instrumented, receiver);
2420
- if (result2 && !initializing) commitSetInEdges(target, prop, previous, instrumented, truncated);
2421
- return result2;
2422
- }
2423
- if (refusesWrite(target, prop, resolved)) return false;
2424
- if (!initializing && typeof resolved === "function" && !writesThroughAccessor(target, prop))
2425
- certifyCurrentAssignment(target, prop, resolved);
2426
- const result = defaultSet(target, prop, resolved, receiver);
2427
- if (result && !initializing) commitSetInEdges(target, prop, previous, resolved, truncated);
2428
- return result;
2429
- } finally {
2430
- setFrameStack.pop();
2431
- }
2432
- },
2433
- deleteProperty(target, prop) {
2434
- const previous = typeof prop === "string" ? Reflect.get(target, prop) : void 0;
2435
- const result = defaultDelete(target, prop);
2436
- if (result && !isInitializing()) commitDeleteInEdges(target, prop, previous);
2437
- return result;
2438
- },
2439
- defineProperty(target, prop, descriptor) {
2440
- return Reflect.defineProperty(target, prop, descriptor);
2441
- },
2442
- setPrototypeOf(target, proto) {
2443
- return Reflect.setPrototypeOf(target, proto);
2444
- },
2445
- preventExtensions(target) {
2446
- return Reflect.preventExtensions(target);
2447
- }
2448
- };
2449
- }
2450
- );
134
+ return memberships;
2451
135
  }
2452
136
 
2453
- // src/createMutableState.ts
2454
- var isIgnoredWrapper = (value) => typeof value === "object" && value !== null && Object.hasOwn(value, ignoreMarker);
2455
- var isUnsafeWrapper = (value) => typeof value === "object" && value !== null && Object.hasOwn(value, unsafeMarker);
2456
- var consumeMarkerTree = (node, path, walk) => {
2457
- if (Object.isFrozen(node)) return;
2458
- const firstPath = walk.firstOccupancyByNode.get(node);
2459
- if (firstPath !== void 0) {
2460
- const laterOccupancies = walk.laterOccupanciesByNode.get(node);
2461
- if (laterOccupancies === void 0) walk.laterOccupanciesByNode.set(node, [path]);
2462
- else laterOccupancies.push(path);
2463
- return;
2464
- }
2465
- walk.firstOccupancyByNode.set(node, path);
2466
- for (const entry of walkDataEntries(node)) {
2467
- const childPath = appendOperationPath(path, segmentFor(node, entry.key));
2468
- const next = unwrapValue(entry.value, childPath, walk);
2469
- if (!Object.is(next, entry.value) && entry.writable) Reflect.set(node, entry.key, next);
137
+ // src/ignore.ts
138
+ var ignored = /* @__PURE__ */ new WeakSet();
139
+ function ignore(value, on = true) {
140
+ if (value === null || typeof value !== "object" && typeof value !== "function") return value;
141
+ if (on) ignored.add(rawOf(value));
142
+ else ignored.delete(rawOf(value));
143
+ return value;
144
+ }
145
+ var isIgnored = (value) => ignored.has(rawOf(value));
146
+
147
+ // src/unsafeTrack.ts
148
+ var unsafeMarked = /* @__PURE__ */ new WeakSet();
149
+ function unsafeTrack(value, on = true) {
150
+ if (value === null || typeof value !== "object" && typeof value !== "function") return value;
151
+ if (on) unsafeMarked.add(rawOf(value));
152
+ else unsafeMarked.delete(rawOf(value));
153
+ return value;
154
+ }
155
+ var isUnsafeMarked = (value) => unsafeMarked.has(rawOf(value));
156
+
157
+ // src/utils/dataEntries.ts
158
+ var walkDataEntries = (value) => {
159
+ const entries = new Array();
160
+ for (const key of Reflect.ownKeys(value)) {
161
+ if (typeof key !== "string" || key === "__proto__") continue;
162
+ const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
163
+ if (descriptor === void 0 || !descriptor.enumerable || !("value" in descriptor)) continue;
164
+ entries.push({ key, value: descriptor.value, writable: descriptor.writable === true });
2470
165
  }
166
+ return entries;
2471
167
  };
2472
- var unwrapValue = (value, path, walk) => {
2473
- let current = value;
2474
- while (isIgnoredWrapper(current) || isUnsafeWrapper(current)) {
2475
- const node = declarationAtPath(walk.trie, path);
2476
- walk.marked = true;
2477
- if (isIgnoredWrapper(current)) {
2478
- node.ignored = true;
2479
- current = current[ignoreMarker];
2480
- } else {
2481
- node.unsafe = true;
2482
- current = current[unsafeMarker];
168
+
169
+ // src/edges.ts
170
+ var isTrackedEntry = (value, writable) => writable && typeof value === "object" && value !== null && !isIgnored(value) && !Object.isFrozen(value);
171
+ var checkNode = (node, entries, route) => {
172
+ const kind = classifyValue(node);
173
+ if (isDangerousKind(kind)) throw rejectionError(node, kind, route);
174
+ for (const entry of entries) {
175
+ if (typeof entry.value === "function") {
176
+ if (kind === "cleanClass") throw rejectionError(node, "cleanClass", [...route, entry.key]);
177
+ continue;
2483
178
  }
179
+ if (typeof entry.value !== "object" || entry.value === null) continue;
180
+ if (isIgnored(entry.value) || Object.isFrozen(entry.value)) continue;
181
+ if (!entry.writable) throw nonWritablePropertyError(node, [...route, entry.key]);
2484
182
  }
2485
- if (typeof current === "object" && current !== null) consumeMarkerTree(current, path, walk);
2486
- return current;
2487
183
  };
2488
- var trieAtPath = (trie, path) => {
2489
- let current = trie;
2490
- for (const segment of path) {
2491
- current = current.children.get(String(segment));
2492
- if (current === void 0) return void 0;
184
+ var descend = (handle, node, route, checked) => {
185
+ const entries = walkDataEntries(node);
186
+ if (checked) checkNode(node, entries, route);
187
+ for (const entry of entries) {
188
+ if (isTrackedEntry(entry.value, entry.writable))
189
+ attach(handle, node, entry.key, entry.value, [...route, entry.key]);
2493
190
  }
2494
- return current;
2495
191
  };
2496
- var applyCopiedMarkerPaths = (walk) => {
2497
- for (const [node, firstPath] of walk.firstOccupancyByNode) {
2498
- const laterOccupancies = walk.laterOccupanciesByNode.get(node);
2499
- if (laterOccupancies === void 0) continue;
2500
- const source = trieAtPath(walk.trie, firstPath);
2501
- if (source === void 0 || source.children.size === 0) continue;
2502
- for (const laterPath of laterOccupancies) {
2503
- graftDeclarationChildren(source, declarationAtPath(walk.trie, laterPath));
2504
- }
192
+ var flip = (handle, node, route) => {
193
+ const membership = recordOf(node)?.memberships.get(handle);
194
+ if (!membership?.exempt) return;
195
+ membership.exempt = false;
196
+ const entries = walkDataEntries(node);
197
+ checkNode(node, entries, route);
198
+ for (const entry of entries) {
199
+ if (!isTrackedEntry(entry.value, entry.writable)) continue;
200
+ const child = rawOf(entry.value);
201
+ if (recordOf(child)?.memberships.has(handle) === true) flip(handle, child, [...route, entry.key]);
2505
202
  }
2506
203
  };
2507
- function createMutableState(properties, options) {
2508
- installBoundary();
2509
- const trie = createDeclarationTrie();
2510
- let marked = false;
2511
- let root = properties;
2512
- while (isIgnoredWrapper(root) || isUnsafeWrapper(root)) {
2513
- if (isIgnoredWrapper(root)) {
2514
- trie.ignored = true;
2515
- marked = true;
2516
- root = root[ignoreMarker];
2517
- } else {
2518
- trie.unsafe = true;
2519
- marked = true;
2520
- root = root[unsafeMarker];
2521
- }
2522
- }
2523
- if (trie.ignored) return root;
2524
- if (typeof root !== "object" || root === null) return root;
2525
- if (Object.isFrozen(root)) return root;
2526
- if (isState(root)) {
2527
- const peeled = peelReadProxy(root);
2528
- if (typeof peeled === "object" && peeled !== null) return peeled;
204
+ var cascade = (handle, node, keys) => {
205
+ for (const key of keys) {
206
+ const value = Reflect.get(node, key);
207
+ if (typeof value !== "object" || value === null) continue;
208
+ const child = rawOf(value);
209
+ if (recordOf(child)?.memberships.has(handle) === true) detach(handle, child);
2529
210
  }
2530
- const decision = admissionDecision(root);
2531
- const strict = options?.strict !== false;
2532
- if (decision.lane === "leaf") return root;
2533
- const base = Object.create(Reflect.getPrototypeOf(root));
2534
- Object.defineProperties(base, Object.getOwnPropertyDescriptors(root));
2535
- const walk = {
2536
- trie,
2537
- marked,
2538
- firstOccupancyByNode: /* @__PURE__ */ new Map(),
2539
- laterOccupanciesByNode: /* @__PURE__ */ new Map()
2540
- };
2541
- consumeMarkerTree(base, createOperationPath([]), walk);
2542
- applyCopiedMarkerPaths(walk);
2543
- const declarations = walk.marked || hasDeclarations(trie) ? trie : void 0;
2544
- if (decision.lane === "dangerous" && strict && declarations?.unsafe !== true) {
2545
- throw rejectionError(base, decision.kind);
211
+ };
212
+ function attach(handle, parent, key, child, route) {
213
+ const parentMembership = recordOf(parent)?.memberships.get(handle);
214
+ if (parentMembership === void 0) return;
215
+ parentMembership.keys.add(key);
216
+ const rawChild = rawOf(child);
217
+ proxyOf(rawChild);
218
+ const record = recordOf(rawChild);
219
+ if (record === void 0) return;
220
+ const edgeExempt = parentMembership.exempt || isUnsafeMarked(rawChild);
221
+ const membership = record.memberships.get(handle);
222
+ if (membership === void 0) {
223
+ record.memberships.set(handle, { edges: 1, exempt: edgeExempt, keys: /* @__PURE__ */ new Set() });
224
+ descend(handle, rawChild, route, !edgeExempt);
225
+ return;
2546
226
  }
2547
- assertSafeDataPaths(base, [], /* @__PURE__ */ new Set(), strict ? "admission" : "rootsOnly", [declarations]);
2548
- const handle = {
2549
- proxy: { root: base },
2550
- lastSnapshot: base,
2551
- hasPendingWrites: false,
2552
- isFlushScheduled: false,
2553
- isFlushHeld: false,
2554
- flushGeneration: 0,
2555
- subscribers: /* @__PURE__ */ new Map(),
2556
- groups: options?.group !== void 0 ? getGroupChain(options.group) : void 0,
2557
- emitOn: options?.emitOn,
2558
- strict,
2559
- declarations,
2560
- nodes: /* @__PURE__ */ new WeakMap(),
2561
- byId: /* @__PURE__ */ new Map(),
2562
- nextInternId: 1,
2563
- stamp: {},
2564
- version: 0,
2565
- replaying: false
2566
- };
2567
- registerHandle(base, handle);
2568
- handle.nodes.set(base, { edges: [], id: 0 });
2569
- handle.byId.set(0, base);
2570
- const instrumented = proxy({ root: base });
2571
- handle.proxy = instrumented;
2572
- handle.lastSnapshot = requireObjectSnapshot(snapshot(instrumented.root));
2573
- seedInEdges(handle);
2574
- seedOccupancies(handle);
2575
- armWatch(handle);
2576
- return instrumented.root;
227
+ membership.edges += 1;
228
+ if (membership.exempt && !edgeExempt) flip(handle, rawChild, route);
2577
229
  }
2578
-
2579
- // src/createGroup.ts
2580
- var UnknownGroupError = class extends Error {
2581
- constructor() {
2582
- super("opshot: unknown group");
2583
- this.name = "UnknownGroupError";
230
+ function attachRoot(handle, root, exempt) {
231
+ const record = recordOf(root);
232
+ if (record === void 0) return;
233
+ record.memberships.set(handle, { edges: 1, exempt, keys: /* @__PURE__ */ new Set() });
234
+ try {
235
+ descend(handle, root, [], !exempt);
236
+ } catch (error) {
237
+ evict(handle, root);
238
+ throw error;
2584
239
  }
2585
- };
2586
- var groupChainByGroup = /* @__PURE__ */ new WeakMap();
2587
- function isGroup(value) {
2588
- return typeof value === "object" && value !== null && groupChainByGroup.has(value);
2589
- }
2590
- function getGroupListeners(group) {
2591
- const chain = groupChainByGroup.get(group);
2592
- const listeners = chain?.at(-1);
2593
- if (listeners === void 0) throw new UnknownGroupError();
2594
- return listeners;
2595
- }
2596
- function getGroupChain(group) {
2597
- const chain = groupChainByGroup.get(group);
2598
- if (chain === void 0) throw new UnknownGroupError();
2599
- return chain;
2600
240
  }
2601
- function createGroup(parent) {
2602
- if (parent !== void 0 && !isGroup(parent)) {
2603
- throw new Error("opshot: parent is not a group");
2604
- }
2605
- const listeners = /* @__PURE__ */ new Map();
2606
- const group = {
2607
- createMutableState(properties, options) {
2608
- return createMutableState(properties, { ...options, group });
2609
- }
2610
- };
2611
- const chain = parent === void 0 ? [listeners] : [...getGroupChain(parent), listeners];
2612
- groupChainByGroup.set(group, chain);
2613
- return group;
241
+ function detach(handle, child) {
242
+ const rawChild = rawOf(child);
243
+ const record = recordOf(rawChild);
244
+ const membership = record?.memberships.get(handle);
245
+ if (record === void 0 || membership === void 0) return;
246
+ membership.edges -= 1;
247
+ if (membership.edges > 0) return;
248
+ record.memberships.delete(handle);
249
+ cascade(handle, rawChild, membership.keys);
250
+ }
251
+ function evict(handle, node) {
252
+ const rawNode = rawOf(node);
253
+ const record = recordOf(rawNode);
254
+ const membership = record?.memberships.get(handle);
255
+ if (record === void 0 || membership === void 0) return;
256
+ record.memberships.delete(handle);
257
+ cascade(handle, rawNode, membership.keys);
2614
258
  }
2615
259
 
2616
- // src/emit/emitterListeners.ts
2617
- var bindings = /* @__PURE__ */ new WeakMap();
2618
- var dropListenerChannel = (byListener, listener, channelId, unsubscribe) => {
2619
- const channels = byListener.get(listener);
2620
- if (channels?.has(channelId) !== true) {
2621
- bindings.delete(unsubscribe);
2622
- return;
2623
- }
2624
- channels.delete(channelId);
2625
- if (channels.size === 0) byListener.delete(listener);
2626
- bindings.delete(unsubscribe);
2627
- };
2628
- function addStateListener(state, listener, channelId, deliver) {
2629
- const handle = requireHandle(state, "opshot: subscribe requires a state");
2630
- let byChannel = handle.subscribers.get(listener);
2631
- if (byChannel === void 0) {
2632
- byChannel = /* @__PURE__ */ new Map();
2633
- handle.subscribers.set(listener, byChannel);
260
+ // src/handle.ts
261
+ function handleOf(state) {
262
+ const raw = rawOf(state);
263
+ const record = recordOf(raw);
264
+ if (record === void 0) return void 0;
265
+ for (const handle of record.memberships.keys()) {
266
+ if (handle.root === raw) return handle;
2634
267
  }
2635
- byChannel.set(channelId, deliver);
2636
- const unsubscribe = () => {
2637
- const held = bindings.get(unsubscribe);
2638
- if (held === void 0) return;
2639
- dropListenerChannel(held.handle.subscribers, held.listener, held.channelId, unsubscribe);
2640
- };
2641
- bindings.set(unsubscribe, { handle, listener, channelId });
2642
- return unsubscribe;
268
+ return void 0;
2643
269
  }
2644
- function addGroupListener(groupListeners, listener, channelId, deliver) {
2645
- let byChannel = groupListeners.get(listener);
2646
- if (byChannel === void 0) {
2647
- byChannel = /* @__PURE__ */ new Map();
2648
- groupListeners.set(listener, byChannel);
2649
- }
2650
- byChannel.set(channelId, deliver);
2651
- const unsubscribe = () => {
2652
- const held = bindings.get(unsubscribe);
2653
- if (held === void 0) return;
2654
- dropListenerChannel(held.listeners, held.listener, held.channelId, unsubscribe);
2655
- };
2656
- bindings.set(unsubscribe, { listeners: groupListeners, listener, channelId });
2657
- return unsubscribe;
270
+ function requireHandle(state, message) {
271
+ const handle = handleOf(state);
272
+ if (handle === void 0) throw new Error(message);
273
+ return handle;
2658
274
  }
2659
275
 
2660
- // src/emit/resolveWriteProxy.ts
2661
- var { proxyStateMap: proxyStateMap15 } = unstable_getInternalStates();
2662
- var ExpectedStateObjectError = class extends Error {
2663
- constructor() {
2664
- super("opshot: expected a state object");
2665
- this.name = "ExpectedStateObjectError";
2666
- }
2667
- };
2668
- var isObjectLike4 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
2669
- function resolveWriteProxy(state) {
2670
- let current = state;
2671
- while (isObjectLike4(current)) {
2672
- if (proxyStateMap15.has(current)) return current;
2673
- const peeled = peelIdentityLayer(current);
2674
- if (peeled === void 0) break;
2675
- current = peeled;
2676
- }
2677
- if (!isObjectLike4(current) || !proxyStateMap15.has(current)) throw new ExpectedStateObjectError();
2678
- return current;
276
+ // src/batch.ts
277
+ var metaStack = [];
278
+ function currentMeta() {
279
+ return metaStack.length === 0 ? void 0 : metaStack[metaStack.length - 1];
2679
280
  }
2680
-
2681
- // src/transact/nest.ts
2682
- var transactionOpen = false;
2683
- var isTransactionOpen = () => transactionOpen;
2684
- var openTransaction = () => {
2685
- transactionOpen = true;
2686
- };
2687
- var closeTransaction = () => {
2688
- transactionOpen = false;
2689
- };
2690
-
2691
- // src/ops/applyMutations.ts
2692
- var ReplayReattachError = class extends Error {
2693
- constructor(message) {
2694
- super(message);
2695
- this.name = "ReplayReattachError";
2696
- }
2697
- };
2698
- var unresolvedError = (path) => new Error(`opshot: ${formatOperationPath(path)} does not resolve to a supported operation address`);
2699
- var linkError = (path, ref, reason) => new Error(`opshot: link at ${formatOperationPath(path)} with ref ${String(ref)} ${reason}`);
2700
- var isWritableDataDescriptor = (descriptor) => descriptor !== void 0 && "value" in descriptor && descriptor.writable === true;
2701
- var restoreRecordedContent = (attached, recorded, restored, identity) => {
2702
- if (restored.has(recorded)) return;
2703
- restored.add(recorded);
2704
- for (const entry of walkDataEntries(recorded, true)) {
2705
- const key = entry.key;
2706
- const attachedDescriptor = Reflect.getOwnPropertyDescriptor(attached, key);
2707
- if (attachedDescriptor !== void 0 && !isWritableDataDescriptor(attachedDescriptor)) continue;
2708
- const value = entry.value;
2709
- if (identity === "restore" && isObjectLike3(value)) {
2710
- const target = getRegisteredTarget(value);
2711
- if (target !== void 0) {
2712
- const present = attachedDescriptor?.value;
2713
- if (!isObjectLike3(present) || resolveIdentity(present) !== resolveIdentity(target)) {
2714
- Reflect.set(attached, key, target);
2715
- }
2716
- const child = Reflect.get(attached, key);
2717
- if (!isObjectLike3(child)) throw new ReplayReattachError(`opshot: replay could not reattach ${key}`);
2718
- restoreRecordedContent(child, value, restored, identity);
2719
- continue;
2720
- }
2721
- }
2722
- Reflect.set(attached, key, value);
2723
- }
2724
- for (const entry of walkDataEntries(attached)) {
2725
- if (!entry.writable) continue;
2726
- if (Object.hasOwn(recorded, entry.key)) continue;
2727
- Reflect.deleteProperty(attached, entry.key);
2728
- }
2729
- };
2730
- var getValuePayload = (operation, identity) => {
2731
- const original = identity === "restore" ? getValueOriginal(operation) ?? operation.value : operation.value;
2732
- return {
2733
- recorded: original,
2734
- fallback: isObjectLike3(original) ? cloneValue(original, /* @__PURE__ */ new WeakMap(), operation.path) : original
2735
- };
2736
- };
2737
- var restoreValue = (payload, attach, readAttached, identity) => {
2738
- if (identity === "restore" && isObjectLike3(payload.recorded)) {
2739
- const target = getRegisteredTarget(payload.recorded);
2740
- if (target !== void 0) {
2741
- attach(target);
2742
- const attached = readAttached();
2743
- if (!isObjectLike3(attached)) {
2744
- throw new ReplayReattachError("opshot: replay could not read a reattached target");
2745
- }
2746
- restoreRecordedContent(attached, payload.recorded, /* @__PURE__ */ new WeakSet(), identity);
2747
- return;
2748
- }
2749
- }
2750
- attach(payload.fallback);
2751
- };
2752
- var getInheritedDescriptor = (target, key) => {
2753
- let prototype = Reflect.getPrototypeOf(target);
2754
- while (prototype !== null) {
2755
- const descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);
2756
- if (descriptor) return descriptor;
2757
- prototype = Reflect.getPrototypeOf(prototype);
2758
- }
2759
- return void 0;
2760
- };
2761
- var requirePlainSegment = (parent, segment, path) => {
2762
- if (Array.isArray(parent)) {
2763
- if (isCanonicalArrayIndex(segment)) return segment;
2764
- if (typeof segment === "string" && !isCanonicalArrayIndexString(segment)) return segment;
2765
- throw unresolvedError(path);
2766
- }
2767
- if (typeof segment === "string") return segment;
2768
- throw unresolvedError(path);
2769
- };
2770
- var requirePlainProperty = (parent, segment, path) => {
2771
- if (Array.isArray(parent) && segment === "length") return parent.length;
2772
- const key = requirePlainSegment(parent, segment, path);
2773
- const descriptor = Reflect.getOwnPropertyDescriptor(parent, key);
2774
- if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) throw unresolvedError(path);
2775
- return Reflect.get(parent, key);
2776
- };
2777
- var resolveTraversalSegment = (parent, segment, path) => {
2778
- if (!isObjectLike3(parent)) throw unresolvedError(path);
2779
- return requirePlainProperty(parent, segment, path);
2780
- };
2781
- var resolveTerminal = (root, path) => {
2782
- if (path.length === 0) throw unresolvedError(path);
2783
- let parent = root;
2784
- for (let index = 0; index < path.length - 1; index++) parent = resolveTraversalSegment(parent, path[index], path);
2785
- if (!isObjectLike3(parent)) throw unresolvedError(path);
2786
- return { parent, segment: path[path.length - 1] };
2787
- };
2788
- var applyLink = (root, operation, handle) => {
2789
- const path = operation.path;
2790
- const ref = operation.ref;
2791
- if (path.length === 0) throw linkError(path, ref, "does not resolve to a supported operation address");
2792
- const resolved = nodeOfInternedId(handle, ref, handle.transactionCapture);
2793
- if (resolved === void 0) throw linkError(path, ref, "does not resolve");
2794
- const terminal = resolveTerminal(root, path);
2795
- if (Array.isArray(terminal.parent) && terminal.segment === "length") {
2796
- throw linkError(path, ref, "cannot address array length");
2797
- }
2798
- const key = requirePlainSegment(terminal.parent, terminal.segment, path);
2799
- const descriptor = Reflect.getOwnPropertyDescriptor(terminal.parent, key);
2800
- const present = descriptor !== void 0 && descriptor.enumerable && "value" in descriptor;
2801
- if (descriptor !== void 0 && !present) throw unresolvedError(path);
2802
- if (!present) {
2803
- const inheritedDescriptor = getInheritedDescriptor(terminal.parent, key);
2804
- if (inheritedDescriptor && !("value" in inheritedDescriptor)) {
2805
- throw new Error(`opshot: ${formatOperationPath(path)} resolves to an inherited accessor`);
2806
- }
2807
- }
2808
- Reflect.set(terminal.parent, key, resolved);
2809
- };
2810
- var applyPlain = (parent, segment, operation, identity, handle) => {
2811
- const path = operation.path;
2812
- if (Array.isArray(parent) && segment === "length") {
2813
- if (operation.verb !== "assign" || typeof operation.value !== "number" || !Number.isInteger(operation.value) || operation.value < 0 || operation.value > MAX_ARRAY_LENGTH) {
2814
- throw unresolvedError(path);
2815
- }
2816
- Reflect.set(parent, "length", operation.value);
2817
- return;
2818
- }
2819
- const key = requirePlainSegment(parent, segment, path);
2820
- const descriptor = Reflect.getOwnPropertyDescriptor(parent, key);
2821
- const present = descriptor !== void 0 && descriptor.enumerable && "value" in descriptor;
2822
- if (descriptor !== void 0 && !present) throw unresolvedError(path);
2823
- if (operation.verb === "delete") {
2824
- Reflect.deleteProperty(parent, key);
2825
- return;
2826
- }
2827
- if (!present) {
2828
- const inheritedDescriptor = getInheritedDescriptor(parent, key);
2829
- if (inheritedDescriptor && !("value" in inheritedDescriptor)) {
2830
- throw new Error(`opshot: ${formatOperationPath(path)} resolves to an inherited accessor`);
2831
- }
281
+ function batch(callback, meta) {
282
+ metaStack.push(meta);
283
+ try {
284
+ callback();
285
+ } finally {
286
+ metaStack.pop();
2832
287
  }
2833
- const payload = getValuePayload(operation, identity);
2834
- restoreValue(
2835
- payload,
2836
- (value) => Reflect.set(parent, key, value),
2837
- () => Reflect.get(parent, key),
2838
- identity
2839
- );
2840
- const attached = Reflect.get(parent, key);
2841
- if (!isObjectLike3(attached)) return;
2842
- if (operation.ids !== void 0) {
2843
- if (isObjectLike3(payload.recorded)) {
2844
- bindVendedIds(handle, attached, payload.recorded, operation.ids, handle.transactionCapture, parent, key);
288
+ }
289
+
290
+ // src/emit/emitterDeliver.ts
291
+ var runDelivery = (pending, failures) => {
292
+ pending.handle.lastDirty = pending.dirty;
293
+ for (const deliver of pending.deliveries) {
294
+ try {
295
+ deliver(pending.operations);
296
+ } catch (error) {
297
+ failures.push(error);
2845
298
  }
2846
- } else {
2847
- let chains = chainsAtRoot(handle.declarations);
2848
- for (const segment2 of path) chains = descendChains(chains, segment2).chains;
2849
- chains = nodeChainsOf(handle, attached) ?? chains;
2850
- internSubtree(
2851
- handle,
2852
- attached,
2853
- chains,
2854
- (parent2, parentChains, key2, entry) => isTrackedEdge(entry) ? resolveChildChains(handle, parent2, parentChains, key2, entry.value)?.chains : void 0,
2855
- handle.transactionCapture
2856
- );
2857
299
  }
2858
300
  };
2859
- var applyMutation = (root, operation, identity, handle) => {
2860
- if (operation.verb === "link") {
2861
- applyLink(root, operation, handle);
2862
- return;
301
+ var raiseFailures = (failures) => {
302
+ if (failures.length === 0) return;
303
+ if (failures.length > 1) throw new AggregateError(failures, "opshot: listeners failed during delivery");
304
+ throw failures[0];
305
+ };
306
+ var queuedDeliveries = [];
307
+ var deliveryFailures = [];
308
+ var isDraining = false;
309
+ var prepareDelivery = (handle, operations, dirty) => ({
310
+ deliveries: [...handle.subscribers.values()],
311
+ operations,
312
+ handle,
313
+ dirty
314
+ });
315
+ var enqueueDelivery = (pending) => {
316
+ queuedDeliveries.push(pending);
317
+ };
318
+ var drainDeliveries = () => {
319
+ if (isDraining) return;
320
+ isDraining = true;
321
+ let failures = [];
322
+ try {
323
+ while (queuedDeliveries.length > 0) {
324
+ for (const queued of queuedDeliveries.splice(0, queuedDeliveries.length)) {
325
+ runDelivery(queued, deliveryFailures);
326
+ }
327
+ }
328
+ } finally {
329
+ isDraining = false;
330
+ failures = deliveryFailures.splice(0, deliveryFailures.length);
2863
331
  }
2864
- const terminal = resolveTerminal(root, operation.path);
2865
- applyPlain(terminal.parent, terminal.segment, operation, identity, handle);
332
+ raiseFailures(failures);
2866
333
  };
2867
- function applyMutations(root, operations, direction, identity, handle) {
2868
- if (direction === "do") {
2869
- for (const operation of operations) applyMutation(root, operation.do, identity, handle);
334
+
335
+ // src/emit/window.ts
336
+ function recordOperation(handle, raw, pending) {
337
+ let byKey = handle.pendingIndex.get(raw);
338
+ if (byKey === void 0) {
339
+ byKey = /* @__PURE__ */ new Map();
340
+ handle.pendingIndex.set(raw, byKey);
341
+ }
342
+ const index = byKey.get(pending.key);
343
+ const existing = index === void 0 ? void 0 : handle.pending[index];
344
+ if (existing !== void 0 && Object.is(existing.meta, pending.meta)) {
345
+ existing.after = pending.after;
346
+ existing.hasAfter = pending.hasAfter;
2870
347
  return;
2871
348
  }
2872
- const occupantAt = (path) => {
2873
- let current = root;
2874
- for (const segment of path) {
2875
- if (!isObjectLike3(current)) return void 0;
2876
- current = Reflect.get(current, segment);
2877
- }
2878
- return current;
349
+ handle.pending.push(pending);
350
+ byKey.set(pending.key, handle.pending.length - 1);
351
+ if (handle.scheduledFlush !== void 0) return;
352
+ const run = () => {
353
+ if (handle.scheduledFlush !== run) return;
354
+ flushWindow(handle);
2879
355
  };
2880
- const admittedRoots = new Array();
2881
- for (const operation of operations) {
2882
- if (operation.do.verb !== "assign" || !isObjectLike3(operation.do.value)) continue;
2883
- const occupant = occupantAt(operation.undo.path);
2884
- if (isObjectLike3(occupant)) admittedRoots.push(occupant);
2885
- }
2886
- for (let index = operations.length - 1; index >= 0; index--) {
2887
- const operation = operations[index];
2888
- if (operation === void 0) continue;
2889
- applyMutation(root, operation.undo, identity, handle);
356
+ handle.scheduledFlush = run;
357
+ void Promise.resolve().then(() => {
358
+ if (handle.scheduledFlush !== run) return;
359
+ const emitOn = handle.emitOn;
360
+ if (emitOn === void 0) run();
361
+ else emitOn(run);
362
+ });
363
+ }
364
+ function flushWindow(handle) {
365
+ handle.scheduledFlush = void 0;
366
+ const pending = handle.pending.splice(0);
367
+ handle.pendingIndex.clear();
368
+ const operations = new Array();
369
+ for (const item of pending) {
370
+ if (item.hasBefore === item.hasAfter && (!item.hasBefore || Object.is(item.before, item.after))) continue;
371
+ const operation = {
372
+ node: item.node,
373
+ key: item.key,
374
+ meta: item.meta,
375
+ ...item.hasBefore ? { before: item.before } : {},
376
+ ...item.hasAfter ? { after: item.after } : {}
377
+ };
378
+ operations.push(Object.freeze(operation));
2890
379
  }
2891
- const idSet = /* @__PURE__ */ new Set();
2892
- for (const node of admittedRoots) {
2893
- for (const id of rewindAdmission(handle, node)) idSet.add(id);
380
+ if (operations.length === 0) return;
381
+ const edges = /* @__PURE__ */ new Map();
382
+ const nodes = /* @__PURE__ */ new Set();
383
+ for (const operation of operations) {
384
+ const raw = rawOf(operation.node);
385
+ let keys = edges.get(raw);
386
+ if (keys === void 0) {
387
+ keys = /* @__PURE__ */ new Set();
388
+ edges.set(raw, keys);
389
+ }
390
+ keys.add(operation.key);
391
+ nodes.add(raw);
2894
392
  }
2895
- while (idSet.has(handle.nextInternId - 1)) handle.nextInternId -= 1;
393
+ const dirty = { edges, nodes };
394
+ enqueueDelivery(prepareDelivery(handle, operations, dirty));
395
+ drainDeliveries();
2896
396
  }
2897
397
 
2898
- // src/transact/rollback.ts
2899
- var rollbackTransaction = (handle) => {
2900
- const restoreTarget = handle.lastSnapshot;
2901
- const operations = diffObjects(snapshot(handle.proxy.root), restoreTarget, handle, void 0, createCaptureTables());
2902
- if (operations.length > 0) {
2903
- applyMutations(handle.proxy.root, operations, "do", "restore", handle);
398
+ // src/utils/predicates.ts
399
+ var isObjectLike = (value) => value !== null && (typeof value === "object" || typeof value === "function");
400
+
401
+ // src/proxy.ts
402
+ var prototypeFunctionOf = (target, key) => {
403
+ for (let holder = Reflect.getPrototypeOf(target); holder !== null; holder = Reflect.getPrototypeOf(holder)) {
404
+ const descriptor = Reflect.getOwnPropertyDescriptor(holder, key);
405
+ if (descriptor === void 0) continue;
406
+ const method = "value" in descriptor ? descriptor.value : void 0;
407
+ return typeof method === "function" ? method : void 0;
2904
408
  }
2905
- handle.lastSnapshot = restoreTarget;
2906
- handle.hasPendingWrites = false;
409
+ return void 0;
2907
410
  };
2908
-
2909
- // src/transact/transact.ts
2910
- function transact(state, mutate, meta) {
2911
- runTransaction(state, mutate, meta, void 0);
2912
- }
2913
- var attachRollbackCause = (error, rollbackError) => {
2914
- if (!(error instanceof Error) || error.cause !== void 0) return;
2915
- Object.defineProperty(error, "cause", {
2916
- value: rollbackError,
2917
- writable: true,
2918
- enumerable: false,
2919
- configurable: true
2920
- });
411
+ var isRideAlongKey = (target, key) => {
412
+ if (key === "__proto__") return true;
413
+ if (key === "length") return false;
414
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
415
+ return descriptor?.enumerable === false;
2921
416
  };
2922
- var flattenDeliveryFailures = (error) => {
2923
- if (error instanceof AggregateError && error.message === "opshot: listeners failed during delivery") {
2924
- return error.errors;
417
+ var writesThroughAccessor = (target, property) => {
418
+ let holder = target;
419
+ while (holder !== null) {
420
+ const descriptor = Reflect.getOwnPropertyDescriptor(holder, property);
421
+ if (descriptor !== void 0) return !("value" in descriptor);
422
+ holder = Reflect.getPrototypeOf(holder);
2925
423
  }
2926
- return [error];
2927
- };
2928
- var releaseUncaught = (failures) => {
2929
- if (failures.length === 0) return;
2930
- const error = failures.length === 1 ? failures[0] : new AggregateError(failures, "opshot: listeners failed during delivery");
2931
- queueMicrotask(() => {
2932
- throw error;
2933
- });
424
+ return false;
2934
425
  };
2935
- function runTransaction(state, mutate, meta, channelId) {
2936
- if (isTransactionOpen()) {
2937
- throw new Error(
2938
- "opshot: transact cannot be nested; a transaction cannot contain another. Mutate inside the callback rather than transacting, run transactions in sequence, or call applyOperations at top level."
2939
- );
426
+ var proxied = (value) => isObjectLike(value) ? recordOf(value)?.proxy ?? value : value;
427
+ var truncatedOwnEntriesOf = (target, next) => {
428
+ if (!Array.isArray(target)) return [];
429
+ const coercible = next === null || typeof next !== "object" && typeof next !== "function";
430
+ const newLength = coercible ? Number(next) : Number.NaN;
431
+ if (!Number.isInteger(newLength) || newLength < 0 || newLength >= target.length) return [];
432
+ const truncated = new Array();
433
+ for (let index = newLength; index < target.length; index += 1) {
434
+ const key = String(index);
435
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
436
+ if (descriptor === void 0 || !("value" in descriptor)) continue;
437
+ truncated.push({
438
+ key,
439
+ value: descriptor.value,
440
+ writable: descriptor.writable === true
441
+ });
2940
442
  }
2941
- const handle = requireHandle(state, "opshot: transact requires a state");
2942
- handle.flushGeneration += 1;
2943
- handle.isFlushScheduled = false;
2944
- const listenerFailures = new Array();
2945
- const emitCollectingListeners = (emit) => {
2946
- const baseline = handle.lastSnapshot;
2947
- try {
2948
- emit();
2949
- } catch (error) {
2950
- if (handle.lastSnapshot === baseline) throw error;
2951
- listenerFailures.push(...flattenDeliveryFailures(error));
443
+ return truncated;
444
+ };
445
+ var ownDataDescriptor = (target, key) => {
446
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
447
+ if (descriptor === void 0 || !("value" in descriptor)) return { hadPrevious: false, previous: void 0 };
448
+ return { hadPrevious: true, previous: descriptor.value };
449
+ };
450
+ var handler = {
451
+ get(target, key, receiver) {
452
+ const value = Reflect.get(target, key, receiver);
453
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
454
+ const locked = descriptor?.writable === false && descriptor.configurable === false;
455
+ if (locked || !isObjectLike(value)) return value;
456
+ if (typeof value === "function") {
457
+ const method = prototypeFunctionOf(target, key);
458
+ const kind = classifyValue(target);
459
+ if (method !== void 0 && value === method && (kind === "nativeClass" || kind === "privateClass")) {
460
+ const bound = Function.prototype.bind.call(method, target);
461
+ return typeof bound === "function" ? bound : value;
462
+ }
463
+ return value;
2952
464
  }
2953
- };
2954
- const deliverQuietly = (ranges) => {
2955
- try {
2956
- deliverCapturedRanges(ranges);
2957
- } catch (error) {
2958
- listenerFailures.push(...flattenDeliveryFailures(error));
465
+ return recordOf(value)?.proxy ?? value;
466
+ },
467
+ set(target, key, value, receiver) {
468
+ if (typeof key !== "string" || writesThroughAccessor(target, key) || isRideAlongKey(target, key)) {
469
+ return Reflect.set(target, key, value, receiver);
2959
470
  }
2960
- };
2961
- try {
2962
- const starting = captureWrites(handle);
2963
- const previousHeld = handle.isFlushHeld;
2964
- handle.isFlushHeld = true;
2965
- handle.transactionCapture = createCaptureTables();
2966
- openTransaction();
2967
- let completed = false;
2968
- let mutateError;
2969
- try {
2970
- mutate();
2971
- completed = true;
2972
- } catch (error) {
2973
- mutateError = error;
2974
- throw error;
2975
- } finally {
2976
- closeTransaction();
2977
- if (!completed) {
2978
- try {
2979
- rollbackTransaction(handle);
2980
- } catch (rollbackError) {
2981
- attachRollbackCause(mutateError, rollbackError);
471
+ const { hadPrevious, previous } = ownDataDescriptor(target, key);
472
+ const resolved = isObjectLike(value) ? rawOf(value) : value;
473
+ const memberships = membershipsOf(target).map(([handle, membership]) => ({
474
+ handle,
475
+ membership,
476
+ hadKey: membership.keys.has(key)
477
+ }));
478
+ const truncated = key === "length" ? truncatedOwnEntriesOf(target, resolved) : [];
479
+ const previousLength = Array.isArray(target) ? target.length : void 0;
480
+ if (typeof resolved === "function" && memberships.some(({ membership }) => !membership.exempt)) {
481
+ const kind = classifyValue(target);
482
+ if (kind !== "plain" && kind !== "plainArray") throw rejectionError(target, kind, [key]);
483
+ }
484
+ const incoming = resolved !== previous && isTrackedEntry(resolved, true) ? resolved : void 0;
485
+ let rollBack;
486
+ if (incoming !== void 0) {
487
+ const started = new Array();
488
+ rollBack = () => {
489
+ for (const { handle, membership, hadKey } of started) {
490
+ detach(handle, incoming);
491
+ if (!hadKey) membership.keys.delete(key);
492
+ }
493
+ };
494
+ try {
495
+ for (const write of memberships) {
496
+ started.push(write);
497
+ attach(write.handle, target, key, incoming, [key]);
2982
498
  }
2983
- handle.transactionCapture = void 0;
2984
- handle.isFlushHeld = previousHeld;
2985
- deliverQuietly([starting]);
2986
- } else {
2987
- handle.isFlushHeld = previousHeld;
499
+ } catch (error) {
500
+ rollBack();
501
+ throw error;
2988
502
  }
2989
503
  }
2990
- let transaction;
2991
- try {
2992
- transaction = captureTransactionWrites(handle, meta, channelId);
2993
- } catch (error) {
2994
- try {
2995
- rollbackTransaction(handle);
2996
- } catch (rollbackError) {
2997
- attachRollbackCause(error, rollbackError);
504
+ const result = Reflect.set(target, key, resolved, receiver);
505
+ if (!result) {
506
+ rollBack?.();
507
+ return result;
508
+ }
509
+ const meta = currentMeta();
510
+ const node = proxyOf(target);
511
+ for (const { handle, membership, hadKey } of memberships) {
512
+ for (const entry of truncated) {
513
+ if (membership.keys.delete(entry.key) && isObjectLike(entry.value)) detach(handle, entry.value);
514
+ recordOperation(handle, target, {
515
+ node,
516
+ key: entry.key,
517
+ meta,
518
+ before: proxied(entry.value),
519
+ hasBefore: true,
520
+ hasAfter: false
521
+ });
522
+ }
523
+ if (hadKey && previous !== resolved) {
524
+ if (isObjectLike(previous)) detach(handle, previous);
525
+ if (incoming === void 0) membership.keys.delete(key);
526
+ }
527
+ recordOperation(handle, target, {
528
+ node,
529
+ key,
530
+ meta,
531
+ before: proxied(previous),
532
+ after: proxied(resolved),
533
+ hasBefore: hadPrevious,
534
+ hasAfter: true
535
+ });
536
+ if (key !== "length" && Array.isArray(target) && previousLength !== target.length) {
537
+ recordOperation(handle, target, {
538
+ node,
539
+ key: "length",
540
+ meta,
541
+ before: previousLength,
542
+ after: target.length,
543
+ hasBefore: true,
544
+ hasAfter: true
545
+ });
2998
546
  }
2999
- deliverQuietly([starting]);
3000
- throw error;
3001
- } finally {
3002
- handle.transactionCapture = void 0;
3003
547
  }
3004
- deliverQuietly([starting, transaction]);
3005
- emitCollectingListeners(() => {
3006
- emitWrites(handle);
3007
- });
3008
- } finally {
3009
- releaseUncaught(listenerFailures);
548
+ return result;
549
+ },
550
+ deleteProperty(target, key) {
551
+ if (typeof key !== "string" || isRideAlongKey(target, key)) return Reflect.deleteProperty(target, key);
552
+ const { hadPrevious, previous } = ownDataDescriptor(target, key);
553
+ const result = Reflect.deleteProperty(target, key);
554
+ if (!result || !hadPrevious) return result;
555
+ const meta = currentMeta();
556
+ const node = proxyOf(target);
557
+ for (const [handle, membership] of membershipsOf(target)) {
558
+ if (membership.keys.delete(key) && isObjectLike(previous)) detach(handle, previous);
559
+ recordOperation(handle, target, {
560
+ node,
561
+ key,
562
+ meta,
563
+ before: proxied(previous),
564
+ hasBefore: true,
565
+ hasAfter: false
566
+ });
567
+ }
568
+ return result;
569
+ },
570
+ preventExtensions(target) {
571
+ for (const [handle] of membershipsOf(target)) evict(handle, target);
572
+ return Reflect.preventExtensions(target);
573
+ },
574
+ defineProperty(target, key, descriptor) {
575
+ return Reflect.defineProperty(target, key, descriptor);
576
+ },
577
+ setPrototypeOf(target, prototype) {
578
+ return Reflect.setPrototypeOf(target, prototype);
579
+ },
580
+ has(target, key) {
581
+ return Reflect.has(target, key);
582
+ },
583
+ ownKeys(target) {
584
+ return Reflect.ownKeys(target);
585
+ },
586
+ getOwnPropertyDescriptor(target, key) {
587
+ return Reflect.getOwnPropertyDescriptor(target, key);
3010
588
  }
589
+ };
590
+
591
+ // src/createMutableState.ts
592
+ installProxyHandler(handler);
593
+ function createMutableState(properties, options) {
594
+ const incoming = properties;
595
+ if (typeof incoming !== "object" || incoming === null) return properties;
596
+ if (isIgnored(incoming)) return properties;
597
+ if (Object.isFrozen(incoming)) return properties;
598
+ const root = rawOf(incoming);
599
+ if (handleOf(incoming) !== void 0) return proxyOf(incoming);
600
+ const strict = options?.strict !== false;
601
+ const exempt = !strict || isUnsafeMarked(root);
602
+ const handle = {
603
+ root,
604
+ strict,
605
+ emitOn: options?.emitOn,
606
+ subscribers: /* @__PURE__ */ new Map(),
607
+ pending: [],
608
+ pendingIndex: /* @__PURE__ */ new Map()
609
+ };
610
+ const proxy = proxyOf(root);
611
+ attachRoot(handle, root, exempt);
612
+ return proxy;
3011
613
  }
3012
614
 
3013
- // src/ops/applyOperations.ts
3014
- var originError = () => new Error("opshot: applyOperations applies a state's operations only to that state");
3015
- var tapeError = () => new Error("opshot: applyOperations applies only the next or previous operations");
3016
- var isFrozenCopyablePath = (value) => Array.isArray(value) && value.every((segment) => typeof segment === "string" || typeof segment === "number");
3017
- var isNonNegativeInteger = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
3018
- var isWellFormedLinkHalf = (value) => typeof value === "object" && value !== null && "verb" in value && value.verb === "link" && "path" in value && "ref" in value && isFrozenCopyablePath(value.path) && isNonNegativeInteger(value.ref);
3019
- var isWellFormedDeleteHalf = (value) => typeof value === "object" && value !== null && "verb" in value && value.verb === "delete" && "path" in value && isFrozenCopyablePath(value.path);
3020
- var isWellFormedIds = (value) => value === void 0 || Array.isArray(value) && value.every((id) => typeof id === "number" && Number.isInteger(id) && id >= 0);
3021
- var isWellFormedAssignHalf = (value) => typeof value === "object" && value !== null && "verb" in value && value.verb === "assign" && "value" in value && "path" in value && isFrozenCopyablePath(value.path) && (!("ids" in value) || value.ids === void 0 || isWellFormedIds(value.ids));
3022
- var isApplicableHalf = (value) => isMutation(value) || isWellFormedLinkHalf(value) || isWellFormedDeleteHalf(value) || isWellFormedAssignHalf(value);
3023
- var assertApplicable = (operation) => {
3024
- if (isMutation(operation)) {
3025
- throw new Error("opshot: applyOperations applies operation pairs; pass the operation, with a direction");
3026
- }
3027
- if (typeof operation !== "object" || operation === null || !("do" in operation) || !("undo" in operation) || !isApplicableHalf(operation.do) || !isApplicableHalf(operation.undo)) {
3028
- throw new Error("opshot: applyOperations applies well-formed { do, undo } pairs");
3029
- }
615
+ // src/identity.ts
616
+ var readProxyTargets = /* @__PURE__ */ new WeakMap();
617
+ var identityRecords = /* @__PURE__ */ new WeakMap();
618
+ var nextInternId = 0;
619
+ var registerReadProxyTarget = (readProxy, target) => {
620
+ readProxyTargets.set(readProxy, target);
3030
621
  };
3031
- function applyOperations(state, operations, direction, meta) {
3032
- runOperations(state, operations, direction, meta, void 0);
3033
- }
3034
- function runOperations(state, operations, direction, meta, channelId) {
3035
- for (const operation of operations) assertApplicable(operation);
3036
- const appliedDirection = direction;
3037
- if (appliedDirection !== "do" && appliedDirection !== "undo") {
3038
- throw new Error('opshot: applyOperations applies a direction of "do" or "undo"');
3039
- }
3040
- if (isTransactionOpen()) {
3041
- throw new Error(
3042
- "opshot: transact cannot be nested; a transaction cannot contain another. Mutate inside the callback rather than transacting, run transactions in sequence, or call applyOperations at top level."
3043
- );
3044
- }
3045
- const handle = requireHandle(state, "opshot: applyOperations requires a state");
3046
- emitWrites(handle);
3047
- let ownedCount = 0;
3048
- for (const operation of operations) {
3049
- const stamp = stampOf(operation);
3050
- if (stamp !== void 0 && stamp !== handle.stamp) throw originError();
3051
- if (stamp === handle.stamp) ownedCount += 1;
3052
- }
3053
- if (ownedCount > 0 && ownedCount < operations.length) throw originError();
3054
- const owned = operations.length > 0 && ownedCount === operations.length;
3055
- if (owned) {
3056
- let index = 0;
3057
- for (const operation of operations) {
3058
- const expected = direction === "do" ? handle.version + 1 + index : handle.version - (operations.length - 1 - index);
3059
- if (versionOf(operation) !== expected) throw tapeError();
3060
- index += 1;
622
+ var getRegisteredReadProxyTarget = (readProxy) => readProxyTargets.get(readProxy);
623
+ function resolveIdentity(value) {
624
+ let current = value;
625
+ while (isObjectLike(current)) {
626
+ const readTarget = getRegisteredReadProxyTarget(current);
627
+ if (readTarget !== void 0 && readTarget !== current) {
628
+ current = readTarget;
629
+ continue;
3061
630
  }
631
+ const raw = rawOf(current);
632
+ if (raw !== current) {
633
+ current = raw;
634
+ continue;
635
+ }
636
+ break;
3062
637
  }
3063
- handle.replaying = true;
3064
- try {
3065
- runTransaction(
3066
- state,
3067
- () => {
3068
- applyMutations(resolveWriteProxy(state), operations, direction, owned ? "restore" : "construct", handle);
3069
- if (owned) {
3070
- handle.version = direction === "do" ? handle.version + operations.length : handle.version - operations.length;
3071
- }
3072
- },
3073
- meta,
3074
- channelId
3075
- );
3076
- } finally {
3077
- handle.replaying = false;
3078
- }
638
+ return current;
3079
639
  }
3080
-
3081
- // src/subscribe.ts
3082
- function subscribe2(target, listener) {
3083
- if (isGroup(target)) {
3084
- return addGroupListener(
3085
- getGroupListeners(target),
3086
- listener,
3087
- void 0,
3088
- (state, ops, meta) => listener(state, ops, meta)
3089
- );
640
+ var recordFor = (key) => {
641
+ let record = identityRecords.get(key);
642
+ if (record === void 0) {
643
+ record = {};
644
+ identityRecords.set(key, record);
3090
645
  }
3091
- return addStateListener(target, listener, void 0, (ops, meta) => listener(ops, meta));
646
+ return record;
647
+ };
648
+ function identify(value) {
649
+ const target = resolveIdentity(value);
650
+ if (!isObjectLike(target)) return value;
651
+ const record = recordFor(target);
652
+ if (record.token !== void 0) return record.token;
653
+ const token = Object.freeze({});
654
+ record.token = token;
655
+ return token;
3092
656
  }
3093
- function toChannelContext(channelId, defaults, meta, deliveredChannelId) {
3094
- if (deliveredChannelId === channelId) {
3095
- return {
3096
- isTransaction: true,
3097
- meta: { ...defaults, ...typeof meta === "object" && meta !== null ? meta : void 0 }
3098
- };
3099
- }
3100
- return { isTransaction: false, meta };
657
+ var internIdentity = (key) => {
658
+ const resolved = resolveIdentity(key);
659
+ const record = recordFor(resolved);
660
+ if (record.id !== void 0) return record.id;
661
+ const id = nextInternId;
662
+ nextInternId += 1;
663
+ record.id = id;
664
+ return id;
665
+ };
666
+ function isSameIdentity(first, second) {
667
+ const resolvedFirst = resolveIdentity(first);
668
+ const resolvedSecond = resolveIdentity(second);
669
+ return resolvedFirst === resolvedSecond;
3101
670
  }
3102
671
 
3103
- // src/createChannel.ts
3104
- function createChannel(defaults) {
3105
- const channelId = Object.freeze({});
3106
- function transact2(state, mutate, meta) {
3107
- runTransaction(state, mutate, meta, channelId);
3108
- }
3109
- function subscribe3(target, listener) {
3110
- if (isGroup(target)) {
3111
- return addGroupListener(
3112
- getGroupListeners(target),
3113
- listener,
3114
- channelId,
3115
- (state, ops, meta, deliveredChannelId) => {
3116
- listener(
3117
- state,
3118
- ops,
3119
- toChannelContext(channelId, defaults, meta, deliveredChannelId)
3120
- );
3121
- }
3122
- );
3123
- }
3124
- return addStateListener(target, listener, channelId, (ops, meta, deliveredChannelId) => {
3125
- listener(
3126
- ops,
3127
- toChannelContext(channelId, defaults, meta, deliveredChannelId)
3128
- );
3129
- });
3130
- }
3131
- function applyOperations2(state, operations, direction, meta) {
3132
- runOperations(state, operations, direction, meta, channelId);
672
+ // src/peelReadProxy.ts
673
+ function peelReadProxy(value) {
674
+ if (!isObjectLike(value)) return value;
675
+ let current = value;
676
+ while (isObjectLike(current)) {
677
+ const registeredTarget = getRegisteredReadProxyTarget(current);
678
+ if (registeredTarget === void 0) break;
679
+ current = registeredTarget;
3133
680
  }
3134
- return { transact: transact2, subscribe: subscribe3, applyOperations: applyOperations2 };
681
+ return current;
682
+ }
683
+
684
+ // src/isState.ts
685
+ function isState(value) {
686
+ const resolved = peelReadProxy(value);
687
+ if (typeof resolved !== "object" || resolved === null) return false;
688
+ return recordOf(resolved)?.proxy === resolved;
3135
689
  }
3136
690
 
3137
691
  // src/tracked/facadeGuard.ts
3138
692
  var assertMutableFacade = (facade, mutationKey) => {
3139
- const facadeSource = getUntracked(facade);
3140
- const isRegisteredCopy = getRegisteredTarget(facade) !== void 0 || facadeSource !== null && getRegisteredTarget(facadeSource) !== void 0;
3141
693
  const descriptor = Reflect.getOwnPropertyDescriptor(facade, mutationKey);
3142
- if (isRegisteredCopy || descriptor !== void 0 && "writable" in descriptor && !descriptor.writable) {
3143
- throw new Error("opshot: cannot mutate a tracked collection snapshot");
694
+ if (descriptor !== void 0 && "writable" in descriptor && !descriptor.writable) {
695
+ throw new Error("opshot: cannot mutate a non-writable tracked collection");
3144
696
  }
3145
697
  };
3146
698
 
@@ -3185,7 +737,6 @@ var clipTime = (epochMs) => {
3185
737
  };
3186
738
  var TrackedDate = class {
3187
739
  constructor(...args) {
3188
- installBoundary();
3189
740
  this.epochMs = constructDate(args).getTime();
3190
741
  }
3191
742
  readDate() {
@@ -3452,14 +1003,13 @@ var EmptyMapSlotError = class extends Error {
3452
1003
  this.name = "EmptyMapSlotError";
3453
1004
  }
3454
1005
  };
3455
- var isObjectLike5 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
1006
+ var isObjectLike2 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
3456
1007
  var isStoredValue = (stored, incoming) => {
3457
1008
  if (Object.is(stored, incoming)) return true;
3458
- return isObjectLike5(stored) && isObjectLike5(incoming) && isSameIdentity(stored, incoming);
1009
+ return isObjectLike2(stored) && isObjectLike2(incoming) && isSameIdentity(stored, incoming);
3459
1010
  };
3460
1011
  var TrackedMap = class {
3461
1012
  constructor(entries) {
3462
- installBoundary();
3463
1013
  this.slots = [];
3464
1014
  this.index = {};
3465
1015
  this.count = 0;
@@ -3542,7 +1092,6 @@ Object.defineProperty(TrackedMap.prototype, Symbol.toStringTag, {
3542
1092
  // src/tracked/trackedSet.ts
3543
1093
  var TrackedSet = class {
3544
1094
  constructor(values) {
3545
- installBoundary();
3546
1095
  this.slots = [];
3547
1096
  this.index = {};
3548
1097
  this.count = 0;
@@ -3606,36 +1155,42 @@ Object.defineProperty(TrackedSet.prototype, Symbol.toStringTag, {
3606
1155
  writable: false
3607
1156
  });
3608
1157
 
3609
- // src/react/dirtySinceSnapshot.ts
3610
- var parentLiveOf = (root, path) => {
3611
- if (path.length === 0) return void 0;
3612
- let current = root;
3613
- for (const segment of path.slice(0, -1)) {
3614
- if (!isObjectLike3(current)) return void 0;
3615
- current = Reflect.get(current, segment);
3616
- }
3617
- return isObjectLike3(current) ? current : void 0;
3618
- };
3619
- function dirtySinceSnapshot(handle, from) {
3620
- const dirty = { edges: /* @__PURE__ */ new WeakMap(), nodes: /* @__PURE__ */ new WeakSet() };
3621
- for (const operation of diffObjects(from, snapshot(handle.proxy.root))) {
3622
- const path = operation.do.path;
3623
- markDirtyPath(dirty, handle, path, parentLiveOf(handle.proxy.root, path));
3624
- }
3625
- return dirty;
1158
+ // src/emit/emitterListeners.ts
1159
+ var bindings = /* @__PURE__ */ new WeakMap();
1160
+ function addStateListener(state, listener, deliver) {
1161
+ const handle = requireHandle(state, "opshot: subscribe requires a state");
1162
+ handle.subscribers.set(listener, deliver);
1163
+ const unsubscribe = () => {
1164
+ const held = bindings.get(unsubscribe);
1165
+ if (held === void 0) return;
1166
+ held.handle.subscribers.delete(held.listener);
1167
+ bindings.delete(unsubscribe);
1168
+ };
1169
+ bindings.set(unsubscribe, { handle, listener });
1170
+ return unsubscribe;
1171
+ }
1172
+
1173
+ // src/subscribe.ts
1174
+ function subscribe(state, listener) {
1175
+ return addStateListener(state, listener, listener);
1176
+ }
1177
+
1178
+ // src/flush.ts
1179
+ function flush(state) {
1180
+ flushWindow(requireHandle(state, "opshot: flush requires a state"));
3626
1181
  }
3627
1182
 
3628
1183
  // src/react/propWalk.ts
3629
1184
  var stateKeysByContainer = /* @__PURE__ */ new WeakMap();
3630
1185
  var noStateKeys = /* @__PURE__ */ new Set();
3631
1186
  var isReactOwnNode = (value) => "$$typeof" in value || typeof Node !== "undefined" && value instanceof Node;
1187
+ var canRebuild = (container) => !isDangerousKind(classifyValue(container));
3632
1188
  var childRole = (value, writable, mode) => {
3633
1189
  if (typeof value !== "object" || value === null) return "skip";
3634
1190
  if (isReactOwnNode(value)) return "skip";
3635
- if (mode === "nested" && !writable) return "skip";
3636
- if (admissionLane(value) === "untracked") return "skip";
1191
+ if (!isTrackedEntry(value, mode === "entry" || writable)) return "skip";
3637
1192
  if (isState(value)) return "state";
3638
- if (admissionLane(value) === "tracked") return "descend";
1193
+ if (canRebuild(value)) return "descend";
3639
1194
  return "skip";
3640
1195
  };
3641
1196
  var readVerdict = (container, pass) => pass.verdicts.get(container) ?? stateKeysByContainer.get(container) ?? noStateKeys;
@@ -3702,7 +1257,7 @@ function discoverStateKeys(container) {
3702
1257
  const cached = stateKeysByContainer.get(container);
3703
1258
  if (cached !== void 0) return cached;
3704
1259
  if (isReactOwnNode(container)) return noStateKeys;
3705
- if (admissionLane(container) !== "tracked") return noStateKeys;
1260
+ if (Object.isFrozen(container) || !canRebuild(container)) return noStateKeys;
3706
1261
  const pass = createDiscoveryPass();
3707
1262
  visitContainer(container, pass, "nested");
3708
1263
  relaxVerdicts(pass);
@@ -3758,7 +1313,7 @@ function substituteStates(root, wrap) {
3758
1313
  sources: [],
3759
1314
  visitedSources: /* @__PURE__ */ new Set()
3760
1315
  };
3761
- if (isReactOwnNode(root) || unfrozenAdmissionLane(root) !== "tracked") {
1316
+ if (isReactOwnNode(root) || !canRebuild(root)) {
3762
1317
  return { props: root, sources: substitution.sources };
3763
1318
  }
3764
1319
  return { props: substituteContainer(root, substitution, wrap, "entry"), sources: substitution.sources };
@@ -3786,15 +1341,11 @@ var isRendering = () => {
3786
1341
  };
3787
1342
 
3788
1343
  // src/react/readTracker.ts
3789
- var { proxyStateMap: proxyStateMap16 } = unstable_getInternalStates();
3790
1344
  var KEYS_PROPERTY = "k";
3791
1345
  var HAS_KEY_PROPERTY = "h";
3792
1346
  var HAS_OWN_KEY_PROPERTY = "o";
3793
1347
  var ALL_OWN_KEYS_PROPERTY = "w";
3794
- var isObjectLike6 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
3795
- var isLiveProxy = (value) => proxyStateMap16.has(value);
3796
- var getProxyTarget = (writeProxy) => proxyStateMap16.get(writeProxy)?.[0] ?? writeProxy;
3797
- var getProxyVersion = (writeProxy) => getVersion(writeProxy) ?? 0;
1348
+ var isWriteProxy = (value) => recordOf(value)?.proxy === value;
3798
1349
  var getUsage = (affected, target) => {
3799
1350
  let used = affected.get(target);
3800
1351
  if (used === void 0) {
@@ -3803,13 +1354,19 @@ var getUsage = (affected, target) => {
3803
1354
  }
3804
1355
  return used;
3805
1356
  };
3806
- var recordKey = (used, type, key) => {
3807
- let set = used[type];
3808
- if (set === void 0) {
3809
- set = /* @__PURE__ */ new Set();
3810
- used[type] = set;
3811
- }
3812
- set.add(key);
1357
+ var recordIn = (slot, key, value) => {
1358
+ const map = slot ?? /* @__PURE__ */ new Map();
1359
+ if (!map.has(key)) map.set(key, value);
1360
+ return map;
1361
+ };
1362
+ var recordGet = (used, key, value) => {
1363
+ used[KEYS_PROPERTY] = recordIn(used[KEYS_PROPERTY], key, value);
1364
+ };
1365
+ var recordHas = (used, key, value) => {
1366
+ used[HAS_KEY_PROPERTY] = recordIn(used[HAS_KEY_PROPERTY], key, value);
1367
+ };
1368
+ var recordOwn = (used, key, value) => {
1369
+ used[HAS_OWN_KEY_PROPERTY] = recordIn(used[HAS_OWN_KEY_PROPERTY], key, value);
3813
1370
  };
3814
1371
  var getPrototypeMethod = (target, prop) => {
3815
1372
  let prototype = Reflect.getPrototypeOf(target);
@@ -3830,30 +1387,68 @@ var UnregisteredReadTrackerError = class extends Error {
3830
1387
  }
3831
1388
  };
3832
1389
  var trackerPartitions = /* @__PURE__ */ new WeakMap();
1390
+ var partitionsOf = (tracker) => {
1391
+ const partitions = trackerPartitions.get(tracker);
1392
+ if (partitions === void 0) throw new UnregisteredReadTrackerError();
1393
+ return partitions;
1394
+ };
3833
1395
  var recordedKeysOf = (used) => {
3834
- const keySets = new Array();
3835
- if (used[KEYS_PROPERTY] !== void 0) keySets.push(used[KEYS_PROPERTY]);
3836
- if (used[HAS_KEY_PROPERTY] !== void 0) keySets.push(used[HAS_KEY_PROPERTY]);
3837
- if (used[HAS_OWN_KEY_PROPERTY] !== void 0) keySets.push(used[HAS_OWN_KEY_PROPERTY]);
3838
- return keySets;
1396
+ const keyMaps = new Array();
1397
+ if (used[KEYS_PROPERTY] !== void 0) keyMaps.push(used[KEYS_PROPERTY]);
1398
+ if (used[HAS_KEY_PROPERTY] !== void 0) keyMaps.push(used[HAS_KEY_PROPERTY]);
1399
+ if (used[HAS_OWN_KEY_PROPERTY] !== void 0) keyMaps.push(used[HAS_OWN_KEY_PROPERTY]);
1400
+ return keyMaps;
3839
1401
  };
3840
1402
  function readsIntersectDirty(tracker, dirty) {
3841
- const partitions = trackerPartitions.get(tracker);
3842
- if (partitions === void 0) throw new UnregisteredReadTrackerError();
3843
- for (const partition of partitions.values()) {
1403
+ for (const partition of partitionsOf(tracker).values()) {
3844
1404
  for (const [writeProxy, used] of partition.affected) {
3845
- const raw = getProxyTarget(writeProxy);
1405
+ const raw = rawOf(writeProxy);
3846
1406
  const edges = dirty.edges.get(raw);
3847
1407
  for (const keys of recordedKeysOf(used)) {
3848
- for (const key of keys) {
1408
+ for (const key of keys.keys()) {
1409
+ if (typeof key === "symbol") continue;
3849
1410
  if (edges?.has(key) === true) return true;
3850
1411
  }
3851
1412
  }
3852
- if (used[ALL_OWN_KEYS_PROPERTY] === true && dirty.nodes.has(raw)) return true;
1413
+ if (used[ALL_OWN_KEYS_PROPERTY] !== void 0 && dirty.nodes.has(raw)) return true;
3853
1414
  }
3854
1415
  for (const writeProxy of partition.identityReads) {
3855
1416
  if (partition.affected.has(writeProxy)) continue;
3856
- if (dirty.nodes.has(getProxyTarget(writeProxy))) return true;
1417
+ if (dirty.nodes.has(rawOf(writeProxy))) return true;
1418
+ }
1419
+ }
1420
+ return false;
1421
+ }
1422
+ function readsChanged(tracker) {
1423
+ for (const partition of partitionsOf(tracker).values()) {
1424
+ for (const [writeProxy, used] of partition.affected) {
1425
+ const gets = used[KEYS_PROPERTY];
1426
+ if (gets !== void 0) {
1427
+ for (const [key, stored] of gets) {
1428
+ if (!Object.is(Reflect.get(writeProxy, key, writeProxy), stored)) return true;
1429
+ }
1430
+ }
1431
+ const hasKeys = used[HAS_KEY_PROPERTY];
1432
+ if (hasKeys !== void 0) {
1433
+ for (const [key, stored] of hasKeys) {
1434
+ if (!Object.is(Reflect.has(writeProxy, key), stored)) return true;
1435
+ }
1436
+ }
1437
+ const ownKeys = used[HAS_OWN_KEY_PROPERTY];
1438
+ if (ownKeys !== void 0) {
1439
+ for (const [key, stored] of ownKeys) {
1440
+ const present = Reflect.getOwnPropertyDescriptor(writeProxy, key) !== void 0;
1441
+ if (!Object.is(present, stored)) return true;
1442
+ }
1443
+ }
1444
+ const listed = used[ALL_OWN_KEYS_PROPERTY];
1445
+ if (listed !== void 0) {
1446
+ const current = Reflect.ownKeys(writeProxy);
1447
+ if (current.length !== listed.length) return true;
1448
+ for (let index = 0; index < listed.length; index += 1) {
1449
+ if (!Object.is(current[index], listed[index])) return true;
1450
+ }
1451
+ }
3857
1452
  }
3858
1453
  }
3859
1454
  return false;
@@ -3878,13 +1473,13 @@ function createReadTracker() {
3878
1473
  const trackUsage = (partition, writeProxy) => shouldRecord() ? getUsage(partition.affected, writeProxy) : {};
3879
1474
  const recordIdentity = (partition, value) => {
3880
1475
  if (!shouldRecord()) return;
3881
- if (isObjectLike6(value) && isLiveProxy(value)) partition.identityReads.add(value);
1476
+ if (isObjectLike(value) && isWriteProxy(value)) partition.identityReads.add(value);
3882
1477
  };
3883
1478
  const toReadProxy = (writeProxy, partition) => {
3884
- const currentVersion = getProxyVersion(writeProxy);
3885
- const cached = partition.proxyCache.get(writeProxy);
3886
- if (cached?.version === currentVersion) return cached.readProxy;
3887
- const target = getProxyTarget(writeProxy);
1479
+ const raw = rawOf(writeProxy);
1480
+ const cached = partition.proxyCache.get(raw);
1481
+ if (cached !== void 0) return cached;
1482
+ const target = raw;
3888
1483
  const readProxyBox = {};
3889
1484
  const boundMethods = /* @__PURE__ */ new WeakMap();
3890
1485
  const bindMethodToReadProxy = (readProxy2, method) => {
@@ -3894,12 +1489,12 @@ function createReadTracker() {
3894
1489
  boundMethods.set(method, bound);
3895
1490
  return bound;
3896
1491
  };
3897
- const handler = {
1492
+ const handler2 = {
3898
1493
  get(_target, prop) {
3899
1494
  const readProxy2 = readProxyBox.current;
3900
1495
  const value = Reflect.get(writeProxy, prop, readProxy2 ?? writeProxy);
3901
1496
  const used = trackUsage(partition, writeProxy);
3902
- recordKey(used, KEYS_PROPERTY, prop);
1497
+ recordGet(used, prop, value);
3903
1498
  recordIdentity(partition, value);
3904
1499
  if (typeof value === "function") {
3905
1500
  const method = getPrototypeMethod(target, prop);
@@ -3907,25 +1502,28 @@ function createReadTracker() {
3907
1502
  return bindMethodToReadProxy(readProxy2, method);
3908
1503
  }
3909
1504
  }
3910
- if (!isObjectLike6(value)) return value;
1505
+ if (!isObjectLike(value)) return value;
3911
1506
  if (typeof value === "function") return value;
3912
- if (!isLiveProxy(value)) return value;
1507
+ if (!isWriteProxy(value)) return value;
3913
1508
  return toReadProxy(value, partition);
3914
1509
  },
3915
1510
  has(_target, prop) {
3916
1511
  const used = trackUsage(partition, writeProxy);
3917
- recordKey(used, HAS_KEY_PROPERTY, prop);
3918
- return Reflect.has(writeProxy, prop);
1512
+ const result = Reflect.has(writeProxy, prop);
1513
+ recordHas(used, prop, result);
1514
+ return result;
3919
1515
  },
3920
1516
  getOwnPropertyDescriptor(_target, prop) {
3921
1517
  const used = trackUsage(partition, writeProxy);
3922
- recordKey(used, HAS_OWN_KEY_PROPERTY, prop);
3923
- return Reflect.getOwnPropertyDescriptor(writeProxy, prop);
1518
+ const descriptor = Reflect.getOwnPropertyDescriptor(writeProxy, prop);
1519
+ recordOwn(used, prop, descriptor !== void 0);
1520
+ return descriptor;
3924
1521
  },
3925
1522
  ownKeys() {
3926
1523
  const used = trackUsage(partition, writeProxy);
3927
- used[ALL_OWN_KEYS_PROPERTY] = true;
3928
- return Reflect.ownKeys(writeProxy);
1524
+ const keys = Reflect.ownKeys(writeProxy);
1525
+ used[ALL_OWN_KEYS_PROPERTY] ??= keys;
1526
+ return keys;
3929
1527
  },
3930
1528
  set(_target, prop, value) {
3931
1529
  return Reflect.set(writeProxy, prop, value, writeProxy);
@@ -3934,15 +1532,15 @@ function createReadTracker() {
3934
1532
  return Reflect.deleteProperty(writeProxy, prop);
3935
1533
  }
3936
1534
  };
3937
- const readProxy = new Proxy(writeProxy, handler);
1535
+ const readProxy = new Proxy(writeProxy, handler2);
3938
1536
  readProxyBox.current = readProxy;
3939
1537
  registerReadProxyTarget(readProxy, writeProxy);
3940
- partition.proxyCache.set(writeProxy, { readProxy, version: currentVersion });
1538
+ partition.proxyCache.set(raw, readProxy);
3941
1539
  return readProxy;
3942
1540
  };
3943
1541
  const tracker = {
3944
1542
  wrap(writeProxy) {
3945
- if (!isLiveProxy(writeProxy)) {
1543
+ if (!isWriteProxy(writeProxy)) {
3946
1544
  throw new Error("opshot: ReadTracker.wrap requires a write proxy");
3947
1545
  }
3948
1546
  const partition = getPartition(writeProxy);
@@ -3957,6 +1555,7 @@ function createReadTracker() {
3957
1555
  for (const partition of partitions.values()) {
3958
1556
  partition.affected.clear();
3959
1557
  partition.identityReads.clear();
1558
+ partition.proxyCache = /* @__PURE__ */ new WeakMap();
3960
1559
  }
3961
1560
  },
3962
1561
  retain() {
@@ -4010,16 +1609,12 @@ function scope(Component) {
4010
1609
  const Scoped = (props) => {
4011
1610
  const readTrackerRef = useRef(void 0);
4012
1611
  const currentHandlesRef = useRef([]);
4013
- const [gapSnapshots] = useState(() => /* @__PURE__ */ new WeakMap());
4014
1612
  readTrackerRef.current ??= createReadTracker();
4015
1613
  const readTracker = readTrackerRef.current;
4016
1614
  const [, bump] = useReducer((value) => value + 1, 0);
4017
1615
  readTracker.resetReads();
4018
1616
  const { props: renderedProps, sources } = substituteStates(props, (source) => readTracker.wrap(source));
4019
1617
  const uniqueHandles = uniqueHandlesOf(sources);
4020
- for (const handle of uniqueHandles) {
4021
- gapSnapshots.set(handle, snapshot(handle.proxy.root));
4022
- }
4023
1618
  useCommitEffect(() => {
4024
1619
  currentHandlesRef.current = uniqueHandles;
4025
1620
  readTracker.captureReads();
@@ -4031,24 +1626,16 @@ function scope(Component) {
4031
1626
  useEffect(() => {
4032
1627
  let cancelled = false;
4033
1628
  const subscribedHandles = uniqueHandlesOf(sources);
4034
- for (const handle of subscribedHandles) {
4035
- const from = gapSnapshots.get(handle);
4036
- if (from !== void 0 && readsIntersectDirty(readTracker, dirtySinceSnapshot(handle, from))) bump();
4037
- }
4038
1629
  const unsubscribes = subscribedHandles.map(
4039
- (handle) => subscribe2(handle.proxy.root, () => {
1630
+ (handle) => subscribe(proxyOf(handle.root), () => {
4040
1631
  if (cancelled) return;
4041
1632
  const dirty = handle.lastDirty;
4042
1633
  if (dirty !== void 0 && readsIntersectDirty(readTracker, dirty)) bump();
4043
1634
  })
4044
1635
  );
1636
+ if (readsChanged(readTracker)) bump();
4045
1637
  return () => {
4046
1638
  cancelled = true;
4047
- const currentHandles = new Set(currentHandlesRef.current);
4048
- for (const handle of subscribedHandles) {
4049
- if (currentHandles.has(handle)) continue;
4050
- gapSnapshots.set(handle, snapshot(handle.proxy.root));
4051
- }
4052
1639
  for (const unsubscribe of unsubscribes) unsubscribe();
4053
1640
  };
4054
1641
  }, [sourcesKey(sources), readTracker]);
@@ -4058,10 +1645,7 @@ function scope(Component) {
4058
1645
  Scoped.displayName = `scope(${typeof baseName === "string" && baseName !== "" ? baseName : "Component"})`;
4059
1646
  return memo(Scoped, arePropsEqual);
4060
1647
  }
4061
- function useGroup(parent) {
4062
- return useState(() => createGroup(parent))[0];
4063
- }
4064
- var isObjectLike7 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
1648
+ var isObjectLike3 = (value) => value !== null && (typeof value === "object" || typeof value === "function");
4065
1649
  function useMutableState(properties, options) {
4066
1650
  const [{ writeProxy, readTracker }] = useState(() => {
4067
1651
  const initial = typeof properties === "function" ? properties() : properties;
@@ -4072,13 +1656,9 @@ function useMutableState(properties, options) {
4072
1656
  });
4073
1657
  const [, bump] = useReducer((value) => value + 1, 0);
4074
1658
  const currentHandlesRef = useRef([]);
4075
- const [gapSnapshots] = useState(() => /* @__PURE__ */ new WeakMap());
4076
- const uniqueHandles = isObjectLike7(writeProxy) ? handlesOf(writeProxy) : [];
1659
+ const uniqueHandles = isObjectLike3(writeProxy) ? handlesOf(writeProxy) : [];
4077
1660
  readTracker.resetReads();
4078
- const readProxy = isObjectLike7(writeProxy) ? readTracker.wrap(writeProxy) : writeProxy;
4079
- for (const handle of uniqueHandles) {
4080
- gapSnapshots.set(handle, snapshot(handle.proxy.root));
4081
- }
1661
+ const readProxy = isObjectLike3(writeProxy) ? readTracker.wrap(writeProxy) : writeProxy;
4082
1662
  useCommitEffect(() => {
4083
1663
  currentHandlesRef.current = uniqueHandles;
4084
1664
  readTracker.captureReads();
@@ -4089,29 +1669,21 @@ function useMutableState(properties, options) {
4089
1669
  }, [readTracker]);
4090
1670
  useEffect(() => {
4091
1671
  let cancelled = false;
4092
- const subscribedHandles = isObjectLike7(writeProxy) ? handlesOf(writeProxy) : [];
4093
- for (const handle of subscribedHandles) {
4094
- const from = gapSnapshots.get(handle);
4095
- if (from !== void 0 && readsIntersectDirty(readTracker, dirtySinceSnapshot(handle, from))) bump();
4096
- }
1672
+ const subscribedHandles = isObjectLike3(writeProxy) ? handlesOf(writeProxy) : [];
4097
1673
  const unsubscribes = subscribedHandles.map(
4098
- (handle) => subscribe2(handle.proxy.root, () => {
1674
+ (handle) => subscribe(proxyOf(handle.root), () => {
4099
1675
  if (cancelled) return;
4100
1676
  const dirty = handle.lastDirty;
4101
1677
  if (dirty !== void 0 && readsIntersectDirty(readTracker, dirty)) bump();
4102
1678
  })
4103
1679
  );
1680
+ if (readsChanged(readTracker)) bump();
4104
1681
  return () => {
4105
1682
  cancelled = true;
4106
- const currentHandles = new Set(currentHandlesRef.current);
4107
- for (const handle of subscribedHandles) {
4108
- if (currentHandles.has(handle)) continue;
4109
- gapSnapshots.set(handle, snapshot(handle.proxy.root));
4110
- }
4111
1683
  for (const unsubscribe of unsubscribes) unsubscribe();
4112
1684
  };
4113
1685
  }, [writeProxy, readTracker]);
4114
1686
  return readProxy;
4115
1687
  }
4116
1688
 
4117
- export { TrackedDate, TrackedMap, TrackedSet, applyOperations, createChannel, createGroup, createMutableState, diffObjects, identify, ignore, isSameIdentity, isState, scope, subscribe2 as subscribe, transact, unsafeTrack, useGroup, useMutableState };
1689
+ export { TrackedDate, TrackedMap, TrackedSet, batch, createMutableState, flush, identify, ignore, isSameIdentity, isState, scope, subscribe, unsafeTrack, useMutableState };