@estjs/signals 0.0.15-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1947 @@
1
+ 'use strict';
2
+
3
+ var shared = require('@estjs/shared');
4
+
5
+ /**
6
+ * @estjs/signals v0.0.15-beta.1
7
+ * (c) 2023-Present jiangxd <jiangxd2016@gmail.com>
8
+ * @license MIT
9
+ **/
10
+ var __defProp = Object.defineProperty;
11
+ var __defProps = Object.defineProperties;
12
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
13
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
14
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
15
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
16
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
+ var __spreadValues = (a, b) => {
18
+ for (var prop in b || (b = {}))
19
+ if (__hasOwnProp.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ if (__getOwnPropSymbols)
22
+ for (var prop of __getOwnPropSymbols(b)) {
23
+ if (__propIsEnum.call(b, prop))
24
+ __defNormalProp(a, prop, b[prop]);
25
+ }
26
+ return a;
27
+ };
28
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
29
+
30
+ // src/constants.ts
31
+ var TriggerOpTypes = {
32
+ SET: "SET",
33
+ ADD: "ADD",
34
+ DELETE: "DELETE",
35
+ CLEAR: "CLEAR"
36
+ };
37
+ var SIGNAL_KEY = Symbol("Signal_Key" );
38
+ var ARRAY_KEY = Symbol("Array_Key" );
39
+ var COLLECTION_KEY = Symbol("Collection_Key" );
40
+ var WEAK_COLLECTION_KEY = Symbol("WeakCollection_Key" );
41
+ var ARRAY_ITERATE_KEY = Symbol("Array_Iterate_Key" );
42
+
43
+ // src/propagation.ts
44
+ function propagate(link) {
45
+ let next = link.nextSubLink;
46
+ let stack;
47
+ top: do {
48
+ const sub = link.subNode;
49
+ const queueBit = sub.flag & 64 /* QUEUED */;
50
+ const watcherBit = sub.flag & 2 /* WATCHING */;
51
+ let flags = sub.flag & -65 /* QUEUED */;
52
+ if (!(flags & (16 /* DIRTY */ | 32 /* PENDING */ | 8 /* RECURSED */ | 4 /* RECURSED_CHECK */))) {
53
+ sub.flag = queueBit | watcherBit | flags | 32 /* PENDING */;
54
+ } else if (flags & (16 /* DIRTY */ | 32 /* PENDING */)) ; else if (!(flags & (8 /* RECURSED */ | 4 /* RECURSED_CHECK */))) {
55
+ flags = 0 /* NONE */;
56
+ sub.flag = queueBit | watcherBit;
57
+ } else if (!(flags & 4 /* RECURSED_CHECK */)) {
58
+ sub.flag = queueBit | watcherBit | (flags & -9 /* RECURSED */ | 32 /* PENDING */);
59
+ } else if (!(flags & (16 /* DIRTY */ | 32 /* PENDING */)) && isValidLink(link, sub)) {
60
+ sub.flag = queueBit | watcherBit | (flags | 8 /* RECURSED */ | 32 /* PENDING */);
61
+ flags &= 1 /* MUTABLE */;
62
+ } else {
63
+ flags = 0 /* NONE */;
64
+ sub.flag = queueBit | watcherBit;
65
+ }
66
+ if (sub.flag & 2 /* WATCHING */) {
67
+ enqueueEffect(sub);
68
+ }
69
+ if (flags & 1 /* MUTABLE */) {
70
+ const subSubs = sub.subLink;
71
+ if (subSubs) {
72
+ const nextSub = (link = subSubs).nextSubLink;
73
+ if (nextSub) {
74
+ stack = { value: next, prev: stack };
75
+ next = nextSub;
76
+ }
77
+ continue;
78
+ }
79
+ }
80
+ if (next) {
81
+ link = next;
82
+ next = link.nextSubLink;
83
+ continue;
84
+ }
85
+ while (stack) {
86
+ link = stack.value;
87
+ stack = stack.prev;
88
+ if (link) {
89
+ next = link.nextSubLink;
90
+ continue top;
91
+ }
92
+ }
93
+ break;
94
+ } while (true);
95
+ }
96
+ function shallowPropagate(link) {
97
+ while (link) {
98
+ const sub = link.subNode;
99
+ const queueBit = sub.flag & 64 /* QUEUED */;
100
+ const flags = sub.flag & -65 /* QUEUED */;
101
+ if (!(flags & 16 /* DIRTY */) && flags & (1 /* MUTABLE */ | 32 /* PENDING */)) {
102
+ const newFlags = queueBit | flags & -33 /* PENDING */ | 16 /* DIRTY */;
103
+ sub.flag = newFlags;
104
+ if (newFlags & 2 /* WATCHING */) {
105
+ enqueueEffect(sub);
106
+ }
107
+ if (flags & 1 /* MUTABLE */ && sub.subLink) {
108
+ shallowPropagate(sub.subLink);
109
+ }
110
+ }
111
+ link = link.nextSubLink;
112
+ }
113
+ }
114
+ function enqueueEffect(effect2) {
115
+ if (!effect2.active) {
116
+ return;
117
+ }
118
+ effect2.notify();
119
+ }
120
+
121
+ // src/link.ts
122
+ var currentLinkVersion = 0;
123
+ var activeSub;
124
+ var isUntracking = false;
125
+ function linkReactiveNode(depNode, subNode) {
126
+ if (isUntracking) {
127
+ return void 0;
128
+ }
129
+ const prevDep = subNode.depLinkTail;
130
+ if (prevDep && prevDep.depNode === depNode) {
131
+ return prevDep;
132
+ }
133
+ const nextDep = prevDep ? prevDep.nextDepLink : subNode.depLink;
134
+ if (nextDep && nextDep.depNode === depNode) {
135
+ nextDep.version = currentLinkVersion;
136
+ subNode.depLinkTail = nextDep;
137
+ return nextDep;
138
+ }
139
+ const prevSub = depNode.subLinkTail;
140
+ if (prevSub && prevSub.version === currentLinkVersion && prevSub.subNode === subNode) {
141
+ subNode.depLinkTail = prevSub;
142
+ return prevSub;
143
+ }
144
+ const newLink = {
145
+ version: currentLinkVersion,
146
+ depNode,
147
+ subNode,
148
+ // Subscriber chain pointers (horizontal)
149
+ prevSubLink: prevSub,
150
+ nextSubLink: void 0,
151
+ // Dependency chain pointers (vertical)
152
+ prevDepLink: prevDep,
153
+ nextDepLink: nextDep
154
+ };
155
+ if (nextDep) {
156
+ nextDep.prevDepLink = newLink;
157
+ }
158
+ if (prevDep) {
159
+ prevDep.nextDepLink = newLink;
160
+ } else {
161
+ subNode.depLink = newLink;
162
+ }
163
+ if (prevSub) {
164
+ prevSub.nextSubLink = newLink;
165
+ } else {
166
+ depNode.subLink = newLink;
167
+ }
168
+ depNode.subLinkTail = newLink;
169
+ subNode.depLinkTail = newLink;
170
+ {
171
+ if (subNode.onTrack && shared.isFunction(subNode == null ? void 0 : subNode.onTrack)) {
172
+ subNode.onTrack({
173
+ effect: subNode,
174
+ target: depNode,
175
+ type: "get",
176
+ key: void 0
177
+ });
178
+ }
179
+ }
180
+ return newLink;
181
+ }
182
+ function unlinkReactiveNode(linkNode, subNode = linkNode.subNode) {
183
+ const depNode = linkNode.depNode;
184
+ const prevSub = linkNode.prevSubLink;
185
+ const nextSub = linkNode.nextSubLink;
186
+ const prevDep = linkNode.prevDepLink;
187
+ const nextDep = linkNode.nextDepLink;
188
+ if (nextDep) {
189
+ nextDep.prevDepLink = prevDep;
190
+ } else {
191
+ subNode.depLinkTail = prevDep;
192
+ }
193
+ if (prevDep) {
194
+ prevDep.nextDepLink = nextDep;
195
+ } else {
196
+ subNode.depLink = nextDep;
197
+ }
198
+ if (nextSub) {
199
+ nextSub.prevSubLink = prevSub;
200
+ } else {
201
+ depNode.subLinkTail = prevSub;
202
+ }
203
+ if (prevSub) {
204
+ prevSub.nextSubLink = nextSub;
205
+ } else {
206
+ depNode.subLink = nextSub;
207
+ if (nextSub === void 0) {
208
+ let toRemove = depNode.depLink;
209
+ while (toRemove) {
210
+ toRemove = unlinkReactiveNode(toRemove, depNode);
211
+ }
212
+ depNode.depLinkTail = void 0;
213
+ depNode.flag |= 16 /* DIRTY */;
214
+ {
215
+ if (depNode.depLink) {
216
+ shared.error(
217
+ "[Link] Cascading cleanup failed: depNode still has dependency links. This indicates a bug in the unlinking logic."
218
+ );
219
+ }
220
+ }
221
+ }
222
+ }
223
+ linkNode.depNode = void 0;
224
+ linkNode.subNode = void 0;
225
+ linkNode.prevSubLink = void 0;
226
+ linkNode.nextSubLink = void 0;
227
+ linkNode.prevDepLink = void 0;
228
+ linkNode.nextDepLink = void 0;
229
+ return nextDep;
230
+ }
231
+ function checkDirty(link, sub) {
232
+ const stack = [{ link, owner: sub }];
233
+ const pendingNodes = [];
234
+ while (stack.length > 0) {
235
+ const frame = stack.pop();
236
+ let current = frame.link;
237
+ const owner = frame.owner;
238
+ while (current) {
239
+ const dep = current.depNode;
240
+ const depFlags = dep.flag;
241
+ if (owner.flag & 16 /* DIRTY */) {
242
+ return true;
243
+ }
244
+ if ((depFlags & (1 /* MUTABLE */ | 16 /* DIRTY */)) === (1 /* MUTABLE */ | 16 /* DIRTY */)) {
245
+ const subs = dep.subLink;
246
+ if (subs && subs.nextSubLink) {
247
+ shallowPropagate2(subs);
248
+ }
249
+ for (const node of pendingNodes) {
250
+ if (node.flag & 32 /* PENDING */) {
251
+ node.flag = node.flag & -33 /* PENDING */ | 16 /* DIRTY */;
252
+ }
253
+ }
254
+ return true;
255
+ }
256
+ if ((depFlags & (1 /* MUTABLE */ | 32 /* PENDING */)) === (1 /* MUTABLE */ | 32 /* PENDING */)) {
257
+ if (dep.depLink) {
258
+ pendingNodes.push(dep);
259
+ stack.push({ link: dep.depLink, owner: dep });
260
+ } else {
261
+ dep.flag &= -33 /* PENDING */;
262
+ }
263
+ } else if (depFlags & 32 /* PENDING */) {
264
+ dep.flag &= -33 /* PENDING */;
265
+ }
266
+ current = current.nextDepLink;
267
+ }
268
+ }
269
+ for (const node of pendingNodes) {
270
+ node.flag &= -33 /* PENDING */;
271
+ }
272
+ if (sub.flag & 32 /* PENDING */) {
273
+ sub.flag &= -33 /* PENDING */;
274
+ }
275
+ return false;
276
+ }
277
+ function shallowPropagate2(link) {
278
+ while (link) {
279
+ const sub = link.subNode;
280
+ const queueBit = sub.flag & 64 /* QUEUED */;
281
+ const flags = sub.flag & -65 /* QUEUED */;
282
+ if ((flags & (32 /* PENDING */ | 16 /* DIRTY */)) === 32 /* PENDING */) {
283
+ sub.flag = queueBit | flags | 16 /* DIRTY */;
284
+ }
285
+ link = link.nextSubLink;
286
+ }
287
+ }
288
+ function setActiveSub(sub) {
289
+ const prev = activeSub;
290
+ activeSub = sub;
291
+ return prev;
292
+ }
293
+ function startTracking(sub) {
294
+ currentLinkVersion++;
295
+ sub.depLinkTail = void 0;
296
+ sub.flag = sub.flag & -57 | 4 /* RECURSED_CHECK */;
297
+ return setActiveSub(sub);
298
+ }
299
+ function endTracking(sub, prevSub) {
300
+ activeSub = prevSub;
301
+ const depsTail = sub.depLinkTail;
302
+ let toRemove = depsTail ? depsTail.nextDepLink : sub.depLink;
303
+ while (toRemove) {
304
+ toRemove = unlinkReactiveNode(toRemove, sub);
305
+ }
306
+ sub.flag &= -5 /* RECURSED_CHECK */;
307
+ }
308
+ function untrack(fn) {
309
+ const prevSub = setActiveSub(void 0);
310
+ const prevUntracking = isUntracking;
311
+ isUntracking = true;
312
+ try {
313
+ return fn();
314
+ } finally {
315
+ isUntracking = prevUntracking;
316
+ setActiveSub(prevSub);
317
+ }
318
+ }
319
+ function isValidLink(checkLink, sub) {
320
+ let link = sub.depLinkTail;
321
+ while (link) {
322
+ if (link === checkLink) {
323
+ return true;
324
+ }
325
+ link = link.prevDepLink;
326
+ }
327
+ return false;
328
+ }
329
+ var targetMap = /* @__PURE__ */ new WeakMap();
330
+ function track(target, key) {
331
+ if (!activeSub || isUntracking) {
332
+ return;
333
+ }
334
+ let depsMap = targetMap.get(target);
335
+ if (!depsMap) {
336
+ depsMap = /* @__PURE__ */ new Map();
337
+ targetMap.set(target, depsMap);
338
+ }
339
+ let dep = depsMap.get(key);
340
+ if (!dep) {
341
+ dep = /* @__PURE__ */ new Set();
342
+ depsMap.set(key, dep);
343
+ }
344
+ if (!dep.has(activeSub)) {
345
+ dep.add(activeSub);
346
+ if (shared.isFunction(activeSub.onTrack)) {
347
+ activeSub.onTrack({
348
+ effect: activeSub,
349
+ target,
350
+ type: "get",
351
+ key
352
+ });
353
+ }
354
+ }
355
+ }
356
+ function trigger(target, type, key, newValue) {
357
+ const depsMap = targetMap.get(target);
358
+ if (!depsMap) {
359
+ return;
360
+ }
361
+ const effects = /* @__PURE__ */ new Set();
362
+ if (key !== void 0) {
363
+ if (Array.isArray(key)) {
364
+ key.forEach((k) => {
365
+ const dep = depsMap.get(k);
366
+ if (dep) {
367
+ dep.forEach((effect2) => effects.add(effect2));
368
+ }
369
+ });
370
+ } else {
371
+ const dep = depsMap.get(key);
372
+ if (dep) {
373
+ dep.forEach((effect2) => effects.add(effect2));
374
+ }
375
+ }
376
+ }
377
+ if (type === "ADD" || type === "DELETE" || type === "CLEAR") {
378
+ const ITERATE_KEY2 = Symbol("iterate");
379
+ const ARRAY_ITERATE_KEY2 = Symbol("arrayIterate");
380
+ const iterationKey = Array.isArray(target) ? ARRAY_ITERATE_KEY2 : ITERATE_KEY2;
381
+ const iterationDep = depsMap.get(iterationKey);
382
+ if (iterationDep) {
383
+ iterationDep.forEach((effect2) => effects.add(effect2));
384
+ }
385
+ }
386
+ effects.forEach((effect2) => {
387
+ var _a5;
388
+ if (shared.isFunction(effect2.onTrigger)) {
389
+ effect2.onTrigger({
390
+ effect: effect2,
391
+ target,
392
+ type,
393
+ key,
394
+ newValue
395
+ });
396
+ }
397
+ if (effect2.flag & 2 /* WATCHING */) {
398
+ (_a5 = effect2.notify) == null ? void 0 : _a5.call(effect2);
399
+ } else if (effect2.flag & 1 /* MUTABLE */) {
400
+ effect2.flag |= 16 /* DIRTY */;
401
+ if (effect2.subLink) {
402
+ propagate(effect2.subLink);
403
+ }
404
+ }
405
+ });
406
+ }
407
+ var reactiveCaches = /* @__PURE__ */ new WeakMap();
408
+ function toRaw(value) {
409
+ if (!value || !shared.isObject(value)) {
410
+ return value;
411
+ }
412
+ const raw = value["_RAW" /* RAW */];
413
+ if (raw) {
414
+ return toRaw(raw);
415
+ }
416
+ if (isSignal(value)) {
417
+ return toRaw(value.peek());
418
+ }
419
+ return value;
420
+ }
421
+ var arrayInstrumentations = createArrayInstrumentations();
422
+ function createArrayInstrumentations() {
423
+ const instrumentations = {};
424
+ ["includes", "indexOf", "lastIndexOf"].forEach((key) => {
425
+ instrumentations[key] = function(...args) {
426
+ const arr = toRaw(this);
427
+ track(arr, ARRAY_ITERATE_KEY);
428
+ let res = arr[key](...args);
429
+ if ((res === -1 || res === false) && args.length > 0) {
430
+ const rawArgs = args.map((arg) => toRaw(arg));
431
+ res = arr[key](...rawArgs);
432
+ }
433
+ return res;
434
+ };
435
+ });
436
+ ["find", "findIndex", "findLast", "findLastIndex"].forEach((key) => {
437
+ instrumentations[key] = function(...args) {
438
+ const arr = toRaw(this);
439
+ const isShallowMode = isShallow(this);
440
+ track(arr, ARRAY_ITERATE_KEY);
441
+ const res = arr[key](...args);
442
+ if ((key === "find" || key === "findLast") && shared.isObject(res) && !isShallowMode) {
443
+ return reactiveImpl(res);
444
+ }
445
+ return res;
446
+ };
447
+ });
448
+ ["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "fill", "copyWithin"].forEach(
449
+ (key) => {
450
+ instrumentations[key] = function(...args) {
451
+ const arr = toRaw(this);
452
+ const res = Array.prototype[key].apply(arr, args);
453
+ trigger(arr, TriggerOpTypes.SET, ARRAY_KEY);
454
+ trigger(arr, TriggerOpTypes.SET, ARRAY_ITERATE_KEY);
455
+ return res;
456
+ };
457
+ }
458
+ );
459
+ ["toReversed", "toSorted", "toSpliced"].forEach((key) => {
460
+ instrumentations[key] = function(...args) {
461
+ const arr = toRaw(this);
462
+ const isShallowMode = isShallow(this);
463
+ track(arr, ARRAY_ITERATE_KEY);
464
+ if (key === "toSpliced") {
465
+ for (let i = 0, l = arr.length; i < l; i++) {
466
+ track(arr, `${i}`);
467
+ }
468
+ }
469
+ const res = Array.prototype[key].apply(arr, args);
470
+ if (!Array.isArray(res)) {
471
+ return res;
472
+ }
473
+ return res.map((item) => shared.isObject(item) ? reactiveImpl(item, isShallowMode) : item);
474
+ };
475
+ });
476
+ ["concat", "slice", "filter", "map", "flatMap", "flat"].forEach((key) => {
477
+ instrumentations[key] = function(...args) {
478
+ const arr = toRaw(this);
479
+ track(arr, ARRAY_ITERATE_KEY);
480
+ const res = Array.prototype[key].apply(arr, args);
481
+ return res;
482
+ };
483
+ });
484
+ ["join", "toString", "toLocaleString"].forEach((key) => {
485
+ instrumentations[key] = function(...args) {
486
+ const arr = toRaw(this);
487
+ track(arr, ARRAY_ITERATE_KEY);
488
+ return Array.prototype[key].apply(arr, args);
489
+ };
490
+ });
491
+ ["values", "keys", "entries", Symbol.iterator].forEach((key) => {
492
+ instrumentations[key] = function() {
493
+ const arr = toRaw(this);
494
+ const isShallowMode = isShallow(this);
495
+ track(arr, ARRAY_KEY);
496
+ const rawIterator = key === Symbol.iterator ? arr[Symbol.iterator]() : arr[key]();
497
+ return {
498
+ next() {
499
+ const { value, done } = rawIterator.next();
500
+ if (done) {
501
+ return { value, done };
502
+ }
503
+ if (Array.isArray(value)) {
504
+ return {
505
+ value: value.map((v) => shared.isObject(v) ? reactiveImpl(v, isShallowMode) : v),
506
+ done
507
+ };
508
+ }
509
+ return {
510
+ value: shared.isObject(value) ? reactiveImpl(value, isShallowMode) : value,
511
+ done
512
+ };
513
+ },
514
+ [Symbol.iterator]() {
515
+ return this;
516
+ }
517
+ };
518
+ };
519
+ });
520
+ return instrumentations;
521
+ }
522
+ var arrayHandlers = (shallow) => ({
523
+ get: (target, key, receiver) => {
524
+ if (key === "_RAW" /* RAW */) {
525
+ return target;
526
+ }
527
+ if (key === "_IS_REACTIVE" /* IS_REACTIVE */) {
528
+ return true;
529
+ }
530
+ if (key === "_IS_SHALLOW" /* IS_SHALLOW */) {
531
+ return shallow;
532
+ }
533
+ if (shared.hasOwn(arrayInstrumentations, key)) {
534
+ return arrayInstrumentations[key];
535
+ }
536
+ const value = Reflect.get(target, key, receiver);
537
+ if (shared.isStringNumber(key)) {
538
+ track(target, key);
539
+ }
540
+ track(target, ARRAY_KEY);
541
+ if (shared.isObject(value) && !shallow) {
542
+ return reactiveImpl(value);
543
+ }
544
+ return value;
545
+ },
546
+ set: (target, key, value, receiver) => {
547
+ const oldValue = Reflect.get(target, key, receiver);
548
+ const result = Reflect.set(target, key, value, receiver);
549
+ if (shared.hasChanged(value, oldValue)) {
550
+ if (shared.isStringNumber(key)) {
551
+ trigger(target, TriggerOpTypes.SET, [key, ARRAY_ITERATE_KEY, ARRAY_KEY]);
552
+ } else {
553
+ trigger(target, TriggerOpTypes.SET, key);
554
+ }
555
+ }
556
+ return result;
557
+ }
558
+ });
559
+ var shallowArrayHandlers = arrayHandlers(true);
560
+ var deepArrayHandlers = arrayHandlers(false);
561
+ var collectionHandlers = {
562
+ get(target, key) {
563
+ if (key === "_IS_REACTIVE" /* IS_REACTIVE */) {
564
+ return true;
565
+ }
566
+ if (key === "_RAW" /* RAW */) {
567
+ return target;
568
+ }
569
+ return Reflect.get(
570
+ shared.hasOwn(collectionInstrumentations, key) ? collectionInstrumentations : target,
571
+ key,
572
+ target
573
+ );
574
+ }
575
+ };
576
+ var weakCollectionHandlers = {
577
+ get(target, key) {
578
+ if (key === "_IS_REACTIVE" /* IS_REACTIVE */) {
579
+ return true;
580
+ }
581
+ if (key === "_RAW" /* RAW */) {
582
+ return target;
583
+ }
584
+ return Reflect.get(
585
+ shared.hasOwn(weakInstrumentations, key) && key in target ? weakInstrumentations : target,
586
+ key,
587
+ target
588
+ );
589
+ }
590
+ };
591
+ var collectionInstrumentations = {
592
+ get(key) {
593
+ const target = toRaw(this);
594
+ track(target, COLLECTION_KEY);
595
+ const value = target.get(key);
596
+ if (shared.isObject(value) && !isShallow(this)) {
597
+ return reactiveImpl(value);
598
+ }
599
+ return value;
600
+ },
601
+ set(key, value) {
602
+ const target = toRaw(this);
603
+ const hadKey = target.has(key);
604
+ const oldValue = target.get(key);
605
+ const rawValue = toRaw(value);
606
+ target.set(key, rawValue);
607
+ if (!hadKey || shared.hasChanged(oldValue, rawValue)) {
608
+ trigger(target, TriggerOpTypes.SET, COLLECTION_KEY);
609
+ }
610
+ return this;
611
+ },
612
+ add(value) {
613
+ const target = toRaw(this);
614
+ const rawValue = toRaw(value);
615
+ const hadValue = target.has(rawValue);
616
+ target.add(rawValue);
617
+ if (!hadValue) {
618
+ trigger(target, TriggerOpTypes.ADD, COLLECTION_KEY);
619
+ } else {
620
+ trigger(target, TriggerOpTypes.SET, COLLECTION_KEY);
621
+ }
622
+ return this;
623
+ },
624
+ has(key) {
625
+ const target = toRaw(this);
626
+ track(target, COLLECTION_KEY);
627
+ const hasKey = target.has(key);
628
+ if (!hasKey && shared.isObject(key)) {
629
+ return target.has(toRaw(key));
630
+ }
631
+ return hasKey;
632
+ },
633
+ delete(key) {
634
+ const target = toRaw(this);
635
+ const hadKey = target.has(key);
636
+ let result = target.delete(key);
637
+ if (!result && shared.isObject(key)) {
638
+ result = target.delete(toRaw(key));
639
+ }
640
+ if (hadKey || result) {
641
+ trigger(target, TriggerOpTypes.DELETE, COLLECTION_KEY);
642
+ }
643
+ return result;
644
+ },
645
+ clear() {
646
+ const target = toRaw(this);
647
+ const hadItems = target.size > 0;
648
+ const result = target.clear();
649
+ if (hadItems) {
650
+ trigger(target, TriggerOpTypes.CLEAR, COLLECTION_KEY);
651
+ }
652
+ return result;
653
+ },
654
+ forEach(callback, thisArg) {
655
+ const target = toRaw(this);
656
+ const isShallowMode = isShallow(this);
657
+ track(target, COLLECTION_KEY);
658
+ target.forEach((value, key) => {
659
+ const wrappedValue = isShallowMode || !shared.isObject(value) ? value : reactiveImpl(value);
660
+ const wrappedKey = isShallowMode || !shared.isObject(key) ? key : reactiveImpl(key);
661
+ callback.call(thisArg, wrappedValue, wrappedKey, this);
662
+ });
663
+ },
664
+ [Symbol.iterator]() {
665
+ const target = toRaw(this);
666
+ const isShallowMode = isShallow(this);
667
+ track(target, COLLECTION_KEY);
668
+ const rawIterator = target[Symbol.iterator]();
669
+ return {
670
+ next() {
671
+ const { value, done } = rawIterator.next();
672
+ if (done) {
673
+ return { value, done };
674
+ }
675
+ if (isShallowMode) {
676
+ return { value, done };
677
+ }
678
+ if (Array.isArray(value)) {
679
+ return {
680
+ value: value.map((v) => shared.isObject(v) ? reactiveImpl(v) : v),
681
+ done
682
+ };
683
+ }
684
+ return {
685
+ value: shared.isObject(value) ? reactiveImpl(value) : value,
686
+ done
687
+ };
688
+ },
689
+ [Symbol.iterator]() {
690
+ return this;
691
+ }
692
+ };
693
+ },
694
+ get size() {
695
+ const target = toRaw(this);
696
+ track(target, COLLECTION_KEY);
697
+ return target.size;
698
+ },
699
+ keys() {
700
+ const target = toRaw(this);
701
+ const isShallowMode = isShallow(this);
702
+ track(target, COLLECTION_KEY);
703
+ const rawIterator = target.keys();
704
+ return {
705
+ next() {
706
+ const { value, done } = rawIterator.next();
707
+ if (done) {
708
+ return { value, done };
709
+ }
710
+ return {
711
+ value: isShallowMode || !shared.isObject(value) ? value : reactiveImpl(value),
712
+ done
713
+ };
714
+ },
715
+ [Symbol.iterator]() {
716
+ return this;
717
+ }
718
+ };
719
+ },
720
+ values() {
721
+ const target = toRaw(this);
722
+ const isShallowMode = isShallow(this);
723
+ track(target, COLLECTION_KEY);
724
+ const rawIterator = target.values();
725
+ return {
726
+ next() {
727
+ const { value, done } = rawIterator.next();
728
+ if (done) {
729
+ return { value, done };
730
+ }
731
+ return {
732
+ value: isShallowMode || !shared.isObject(value) ? value : reactiveImpl(value),
733
+ done
734
+ };
735
+ },
736
+ [Symbol.iterator]() {
737
+ return this;
738
+ }
739
+ };
740
+ },
741
+ entries() {
742
+ const target = toRaw(this);
743
+ const isShallowMode = isShallow(this);
744
+ track(target, COLLECTION_KEY);
745
+ const rawIterator = target.entries();
746
+ return {
747
+ next() {
748
+ const { value, done } = rawIterator.next();
749
+ if (done) {
750
+ return { value, done };
751
+ }
752
+ if (isShallowMode) {
753
+ return { value, done };
754
+ }
755
+ return {
756
+ value: value.map((v) => shared.isObject(v) ? reactiveImpl(v) : v),
757
+ done
758
+ };
759
+ },
760
+ [Symbol.iterator]() {
761
+ return this;
762
+ }
763
+ };
764
+ }
765
+ };
766
+ var weakInstrumentations = {
767
+ get(key) {
768
+ const target = toRaw(this);
769
+ track(target, WEAK_COLLECTION_KEY);
770
+ let value = target.get(key);
771
+ if (value === void 0 && isReactive(key)) {
772
+ value = target.get(toRaw(key));
773
+ }
774
+ if (shared.isObject(value) && !isShallow(this)) {
775
+ return reactiveImpl(value);
776
+ }
777
+ return value;
778
+ },
779
+ set(key, value) {
780
+ const target = toRaw(this);
781
+ const rawKey = toRaw(key);
782
+ const hadKey = target.has(rawKey);
783
+ const oldValue = target.get(rawKey);
784
+ const rawValue = toRaw(value);
785
+ target.set(rawKey, rawValue);
786
+ if (!hadKey || shared.hasChanged(oldValue, rawValue)) {
787
+ trigger(target, TriggerOpTypes.SET, WEAK_COLLECTION_KEY);
788
+ }
789
+ return this;
790
+ },
791
+ add(value) {
792
+ const target = toRaw(this);
793
+ const rawValue = toRaw(value);
794
+ const hadValue = target.has(rawValue);
795
+ target.add(rawValue);
796
+ if (!hadValue) {
797
+ trigger(target, TriggerOpTypes.ADD, WEAK_COLLECTION_KEY);
798
+ }
799
+ return this;
800
+ },
801
+ has(key) {
802
+ const target = toRaw(this);
803
+ track(target, WEAK_COLLECTION_KEY);
804
+ let hasKey = target.has(key);
805
+ if (!hasKey && isReactive(key)) {
806
+ hasKey = target.has(toRaw(key));
807
+ }
808
+ return hasKey;
809
+ },
810
+ delete(key) {
811
+ const target = toRaw(this);
812
+ const rawKey = toRaw(key);
813
+ const hadKey = target.has(rawKey);
814
+ const result = target.delete(rawKey);
815
+ if (hadKey || result) {
816
+ trigger(target, TriggerOpTypes.DELETE, WEAK_COLLECTION_KEY);
817
+ }
818
+ return result;
819
+ }
820
+ };
821
+ var objectHandlers = (shallow) => ({
822
+ get(target, key, receiver) {
823
+ if (key === "_RAW" /* RAW */) {
824
+ return target;
825
+ }
826
+ if (key === "_IS_REACTIVE" /* IS_REACTIVE */) {
827
+ return true;
828
+ }
829
+ if (key === "_IS_SHALLOW" /* IS_SHALLOW */) {
830
+ return shallow;
831
+ }
832
+ const value = Reflect.get(target, key, receiver);
833
+ const valueUnwrapped = isSignal(value) ? value.value : value;
834
+ track(target, key);
835
+ if (shared.isObject(valueUnwrapped) && !shallow) {
836
+ return reactiveImpl(valueUnwrapped);
837
+ }
838
+ return valueUnwrapped;
839
+ },
840
+ set: (target, key, value, receiver) => {
841
+ const oldValue = Reflect.get(target, key, receiver);
842
+ const result = Reflect.set(target, key, toRaw(value), receiver);
843
+ if (shared.hasChanged(value, oldValue)) {
844
+ trigger(target, TriggerOpTypes.SET, key, value);
845
+ }
846
+ return result;
847
+ },
848
+ deleteProperty: (target, key) => {
849
+ const hadKey = shared.hasOwn(target, key);
850
+ const result = Reflect.deleteProperty(target, key);
851
+ if (hadKey && result) {
852
+ trigger(target, TriggerOpTypes.DELETE, key, void 0);
853
+ }
854
+ return result;
855
+ }
856
+ });
857
+ function reactiveImpl(target, shallow = false) {
858
+ if (!shared.isObject(target)) {
859
+ return target;
860
+ }
861
+ if (isReactive(target)) {
862
+ return target;
863
+ }
864
+ const existingProxy = reactiveCaches.get(target);
865
+ if (existingProxy) {
866
+ return existingProxy;
867
+ }
868
+ let handler;
869
+ if (shared.isArray(target)) {
870
+ handler = shallow ? shallowArrayHandlers : deepArrayHandlers;
871
+ } else if (shared.isSet(target) || shared.isMap(target)) {
872
+ handler = collectionHandlers;
873
+ } else if (shared.isWeakMap(target) || shared.isWeakSet(target)) {
874
+ handler = weakCollectionHandlers;
875
+ } else {
876
+ handler = objectHandlers(shallow);
877
+ }
878
+ const proxy = new Proxy(target, handler);
879
+ reactiveCaches.set(target, proxy);
880
+ return proxy;
881
+ }
882
+ function isReactive(target) {
883
+ return !!(target && target["_IS_REACTIVE" /* IS_REACTIVE */]);
884
+ }
885
+ function reactive(target) {
886
+ if (isReactive(target)) {
887
+ {
888
+ shared.warn(
889
+ "[Reactive] Target is already reactive. Returning existing reactive proxy to avoid double wrapping."
890
+ );
891
+ }
892
+ return target;
893
+ }
894
+ if (isSignal(target)) {
895
+ {
896
+ shared.warn(
897
+ "[Reactive] Creating a reactive proxy from a signal is not recommended. Use the signal directly or access its value property."
898
+ );
899
+ }
900
+ return target;
901
+ }
902
+ return reactiveImpl(target);
903
+ }
904
+ function shallowReactive(target) {
905
+ if (isReactive(target)) {
906
+ {
907
+ if (isShallow(target)) {
908
+ shared.warn(
909
+ "[ShallowReactive] Target is already a shallow reactive proxy. Returning existing proxy to avoid double wrapping."
910
+ );
911
+ } else {
912
+ shared.warn(
913
+ "[ShallowReactive] Target is already a deep reactive proxy. Cannot convert deep reactive to shallow reactive. Returning existing proxy."
914
+ );
915
+ }
916
+ }
917
+ return target;
918
+ }
919
+ if (isSignal(target)) {
920
+ {
921
+ shared.warn(
922
+ "[ShallowReactive] Creating a reactive proxy from a signal is not recommended. Use the signal directly or access its value property."
923
+ );
924
+ }
925
+ return target;
926
+ }
927
+ return reactiveImpl(target, true);
928
+ }
929
+ function isShallow(value) {
930
+ return !!(value && value["_IS_SHALLOW" /* IS_SHALLOW */]);
931
+ }
932
+ var toReactive = (value) => shared.isObject(value) ? reactive(value) : value;
933
+
934
+ // src/signal.ts
935
+ var _a;
936
+ _a = "_IS_SIGNAL" /* IS_SIGNAL */;
937
+ var SignalImpl = class {
938
+ // Mark as Signal
939
+ /**
940
+ * Create a new Signal with the given initial value.
941
+ *
942
+ * @param value - Initial value
943
+ * @param shallow - Whether only the top level should be reactive
944
+ */
945
+ constructor(value, shallow = false) {
946
+ this.flag = 1 /* MUTABLE */;
947
+ // Mark whether it's shallow reactive
948
+ // @ts-ignore
949
+ this[_a] = true;
950
+ this._oldValue = this._rawValue = value;
951
+ if (shallow) {
952
+ this._value = shared.isObject(value) ? shallowReactive(value) : value;
953
+ } else {
954
+ this._value = shared.isObject(value) ? reactive(value) : value;
955
+ }
956
+ this["_IS_SHALLOW" /* IS_SHALLOW */] = shallow;
957
+ }
958
+ // dep getter, returns itself for dependency collection
959
+ get dep() {
960
+ return this;
961
+ }
962
+ get value() {
963
+ const sub = activeSub;
964
+ if (sub) {
965
+ linkReactiveNode(this, sub);
966
+ }
967
+ if (this.flag & 16 /* DIRTY */ && this.shouldUpdate()) {
968
+ const subs = this.subLink;
969
+ if (subs) {
970
+ shallowPropagate2(subs);
971
+ }
972
+ }
973
+ return this._value;
974
+ }
975
+ // value setter, triggers update when value changes
976
+ set value(value) {
977
+ if (isSignal(value)) {
978
+ {
979
+ shared.warn(
980
+ "Setting a signal value to another signal is not recommended. The value will be unwrapped automatically."
981
+ );
982
+ }
983
+ value = value.peek();
984
+ }
985
+ value = toRaw(value);
986
+ if (!shared.hasChanged(this._rawValue, value)) {
987
+ return;
988
+ }
989
+ this.flag |= 16 /* DIRTY */;
990
+ this._rawValue = value;
991
+ const shallow = this["_IS_SHALLOW" /* IS_SHALLOW */];
992
+ if (shallow) {
993
+ this._value = shared.isObject(value) ? shallowReactive(value) : value;
994
+ } else {
995
+ this._value = shared.isObject(value) ? reactive(value) : value;
996
+ }
997
+ const subs = this.subLink;
998
+ if (subs) {
999
+ propagate(subs);
1000
+ }
1001
+ }
1002
+ // Check if the value should be update
1003
+ shouldUpdate() {
1004
+ this.flag &= -17 /* DIRTY */;
1005
+ return shared.hasChanged(this._oldValue, this._oldValue = this._rawValue);
1006
+ }
1007
+ // Get current value without triggering dependency tracking
1008
+ peek() {
1009
+ return this._value;
1010
+ }
1011
+ // set method is an alias for the value setter
1012
+ set(value) {
1013
+ this.value = value;
1014
+ }
1015
+ // Update value using an updater function
1016
+ update(updater) {
1017
+ const nextValue = updater(this.peek());
1018
+ if (isSignal(nextValue)) {
1019
+ {
1020
+ shared.warn(
1021
+ "Returning a signal from an update function is not recommended. The value will be unwrapped."
1022
+ );
1023
+ }
1024
+ this.value = nextValue.peek();
1025
+ } else {
1026
+ this.value = nextValue;
1027
+ }
1028
+ }
1029
+ };
1030
+ function signal(value) {
1031
+ if (isSignal(value)) {
1032
+ {
1033
+ shared.warn(
1034
+ "Creating a signal with another signal is not recommended. The value will be unwrapped."
1035
+ );
1036
+ }
1037
+ return value;
1038
+ }
1039
+ return new SignalImpl(value);
1040
+ }
1041
+ function shallowSignal(value) {
1042
+ if (isSignal(value)) {
1043
+ {
1044
+ shared.warn(
1045
+ "Creating a shallow signal with another signal is not recommended. The value will be unwrapped."
1046
+ );
1047
+ }
1048
+ value = value.peek();
1049
+ }
1050
+ return new SignalImpl(value, true);
1051
+ }
1052
+ function isSignal(value) {
1053
+ return !!value && !!value["_IS_SIGNAL" /* IS_SIGNAL */];
1054
+ }
1055
+ var queue = /* @__PURE__ */ new Set();
1056
+ var activePreFlushCbs = /* @__PURE__ */ new Set();
1057
+ var p = Promise.resolve();
1058
+ var isFlushPending = false;
1059
+ function nextTick(fn) {
1060
+ if (fn) {
1061
+ return new Promise((resolve, reject) => {
1062
+ queueMicrotask(() => {
1063
+ try {
1064
+ fn();
1065
+ resolve();
1066
+ } catch (error6) {
1067
+ reject(error6);
1068
+ }
1069
+ });
1070
+ });
1071
+ }
1072
+ return p;
1073
+ }
1074
+ function queueJob(job) {
1075
+ queue.add(job);
1076
+ queueFlush();
1077
+ }
1078
+ function queueFlush() {
1079
+ if (!isFlushPending) {
1080
+ isFlushPending = true;
1081
+ nextTick(flushJobs);
1082
+ }
1083
+ }
1084
+ function queuePreFlushCb(cb) {
1085
+ activePreFlushCbs.add(cb);
1086
+ queueFlush();
1087
+ }
1088
+ function flushJobs() {
1089
+ isFlushPending = false;
1090
+ flushPreFlushCbs();
1091
+ while (queue.size > 0) {
1092
+ const jobs = Array.from(queue);
1093
+ queue.clear();
1094
+ for (const job of jobs) {
1095
+ try {
1096
+ job();
1097
+ } catch (_error) {
1098
+ {
1099
+ shared.error("Error executing queued job:", _error);
1100
+ }
1101
+ }
1102
+ }
1103
+ }
1104
+ }
1105
+ function flushPreFlushCbs() {
1106
+ const callbacks = Array.from(activePreFlushCbs);
1107
+ activePreFlushCbs.clear();
1108
+ for (const callback of callbacks) {
1109
+ try {
1110
+ callback();
1111
+ } catch (_error) {
1112
+ {
1113
+ shared.error("Error executing pre-flush callback:", _error);
1114
+ }
1115
+ }
1116
+ }
1117
+ }
1118
+ function createScheduler(effect2, flush) {
1119
+ switch (flush) {
1120
+ case "sync":
1121
+ return () => effect2();
1122
+ case "pre":
1123
+ return () => queuePreFlushCb(effect2);
1124
+ case "post":
1125
+ return () => queueJob(effect2);
1126
+ default:
1127
+ {
1128
+ shared.warn(`Invalid flush timing: ${flush}. Defaulting to 'post'.`);
1129
+ }
1130
+ return () => queueJob(effect2);
1131
+ }
1132
+ }
1133
+
1134
+ // src/batch.ts
1135
+ var batchDepth = 0;
1136
+ function batch(fn) {
1137
+ startBatch();
1138
+ try {
1139
+ return fn();
1140
+ } finally {
1141
+ endBatch();
1142
+ }
1143
+ }
1144
+ function startBatch() {
1145
+ batchDepth++;
1146
+ }
1147
+ function endBatch() {
1148
+ if (batchDepth === 0) {
1149
+ shared.warn(
1150
+ "[Batch] endBatch() called without matching startBatch(). This may indicate unbalanced batch calls in your code."
1151
+ );
1152
+ return;
1153
+ }
1154
+ if (--batchDepth === 0) {
1155
+ flushJobs();
1156
+ if (batchDepth !== 0) {
1157
+ shared.error(
1158
+ `[Batch] Batch depth is not zero after endBatch(). Current depth: ${batchDepth}. This indicates a bug in batch management.`
1159
+ );
1160
+ }
1161
+ }
1162
+ }
1163
+ function isBatching() {
1164
+ return batchDepth > 0;
1165
+ }
1166
+ function getBatchDepth() {
1167
+ return batchDepth;
1168
+ }
1169
+
1170
+ // src/effect.ts
1171
+ var _a2;
1172
+ _a2 = "_IS_EFFECT" /* IS_EFFECT */;
1173
+ var EffectImpl = class {
1174
+ /**
1175
+ * Create an Effect instance
1176
+ *
1177
+ * @param fn - The effect function
1178
+ * @param options - Configuration options
1179
+ */
1180
+ constructor(fn, options) {
1181
+ this.flag = 2 /* WATCHING */ | 16 /* DIRTY */;
1182
+ // @ts-ignore
1183
+ this[_a2] = true;
1184
+ // ===== State management =====
1185
+ this._active = true;
1186
+ this.fn = fn;
1187
+ if (options) {
1188
+ this.scheduler = options.flush || options.scheduler;
1189
+ this.onStop = options.onStop;
1190
+ this.onTrack = options.onTrack;
1191
+ this.onTrigger = options.onTrigger;
1192
+ }
1193
+ }
1194
+ /**
1195
+ * Check if the Effect is active
1196
+ */
1197
+ get active() {
1198
+ return this._active;
1199
+ }
1200
+ /**
1201
+ * Check if the Effect is dirty (needs re-execution)
1202
+
1203
+ */
1204
+ get dirty() {
1205
+ const flags = this.flag;
1206
+ if (flags & 16 /* DIRTY */) {
1207
+ return true;
1208
+ }
1209
+ if (flags & 32 /* PENDING */) {
1210
+ if (this.depLink && checkDirty(this.depLink, this)) {
1211
+ this.flag = flags & -33 /* PENDING */ | 16 /* DIRTY */;
1212
+ return true;
1213
+ }
1214
+ this.flag = flags & -33 /* PENDING */;
1215
+ }
1216
+ return false;
1217
+ }
1218
+ /**
1219
+ * Pause Effect execution
1220
+ *
1221
+ * When an effect is paused:
1222
+ * - It stops responding to dependency changes
1223
+ * - Notifications are ignored (see notify method)
1224
+ * - DIRTY and PENDING flags are still set when dependencies change
1225
+ * - The effect remains active and maintains its dependency links
1226
+ *
1227
+ * Use cases:
1228
+ * - Temporarily disable effects during bulk updates
1229
+ * - Prevent effects from running during initialization
1230
+ * - Control when side effects should execute
1231
+ *
1232
+ * @example
1233
+ * ```typescript
1234
+ * const count = signal(0);
1235
+ * const runner = effect(() => console.log(count.value));
1236
+ *
1237
+ * runner.effect.pause();
1238
+ * count.value = 1; // Effect won't run
1239
+ * count.value = 2; // Effect won't run
1240
+ * runner.effect.resume(); // Effect runs once with latest value
1241
+ * ```
1242
+ */
1243
+ pause() {
1244
+ this.flag |= 256 /* PAUSED */;
1245
+ }
1246
+ /**
1247
+ * Resume Effect execution
1248
+ *
1249
+ * When an effect is resumed:
1250
+ * - The PAUSED flag is cleared
1251
+ * - If dependencies changed during pause (DIRTY or PENDING flags set),
1252
+ * the effect executes immediately via notify()
1253
+ * - If no changes occurred, the effect simply becomes active again
1254
+ *
1255
+ * State management:
1256
+ * - Clears PAUSED flag atomically
1257
+ * - Checks for accumulated DIRTY/PENDING flags
1258
+ * - Triggers execution if needed
1259
+ *
1260
+ * @example
1261
+ * ```typescript
1262
+ * const count = signal(0);
1263
+ * const runner = effect(() => console.log(count.value));
1264
+ *
1265
+ * runner.effect.pause();
1266
+ * count.value = 1; // Queued
1267
+ * count.value = 2; // Queued
1268
+ * runner.effect.resume(); // Executes once with count.value = 2
1269
+ * ```
1270
+ */
1271
+ resume() {
1272
+ const flags = this.flag;
1273
+ const nextFlags = flags & -257 /* PAUSED */;
1274
+ this.flag = nextFlags;
1275
+ const wasDirty = (nextFlags & 16 /* DIRTY */) !== 0;
1276
+ const wasPending = (nextFlags & 32 /* PENDING */) !== 0;
1277
+ if (wasDirty || wasPending) {
1278
+ this.notify();
1279
+ }
1280
+ }
1281
+ /**
1282
+ * Execute the Effect function
1283
+ *
1284
+ * Core execution flow:
1285
+ * 1. Check if active
1286
+ * 2. Clear dirty flag
1287
+ * 3. Start tracking dependencies
1288
+ * 4. Execute user function
1289
+ * 5. End tracking, clean up stale dependencies
1290
+
1291
+ * @returns The return value of the effect function
1292
+ */
1293
+ run() {
1294
+ if (!this._active) {
1295
+ return this.fn();
1296
+ }
1297
+ const flags = this.flag;
1298
+ this.flag = flags & -17 /* DIRTY */ | 1024 /* STOP */;
1299
+ const prevSub = startTracking(this);
1300
+ try {
1301
+ return this.fn();
1302
+ } catch (error6) {
1303
+ this.flag |= 16 /* DIRTY */;
1304
+ throw error6;
1305
+ } finally {
1306
+ this.flag &= -1025 /* STOP */;
1307
+ endTracking(this, prevSub);
1308
+ }
1309
+ }
1310
+ /**
1311
+ * Get or create the job function for this effect
1312
+ */
1313
+ getJob() {
1314
+ if (!this._job) {
1315
+ this._job = () => this.run();
1316
+ }
1317
+ return this._job;
1318
+ }
1319
+ /**
1320
+ * Notify that the Effect needs to execute
1321
+ *
1322
+ * Called by dependent reactive values.
1323
+ * Decides whether to execute immediately or defer based on scheduling strategy.
1324
+ */
1325
+ notify() {
1326
+ const flags = this.flag;
1327
+ if (!this._active || flags & (256 /* PAUSED */ | 1024 /* STOP */ | 16 /* DIRTY */)) {
1328
+ return;
1329
+ }
1330
+ this.flag = flags | 16 /* DIRTY */;
1331
+ if (this.onTrigger) {
1332
+ this.onTrigger({
1333
+ effect: this,
1334
+ target: {},
1335
+ type: "set"
1336
+ });
1337
+ }
1338
+ if (this.scheduler) {
1339
+ if (shared.isFunction(this.scheduler)) {
1340
+ this.scheduler(this);
1341
+ } else {
1342
+ const schedulerFn = createScheduler(() => this.run(), this.scheduler);
1343
+ schedulerFn();
1344
+ }
1345
+ } else if (isBatching()) {
1346
+ queueJob(this.getJob());
1347
+ } else {
1348
+ this.run();
1349
+ }
1350
+ }
1351
+ /**
1352
+ * Stop the Effect
1353
+ *
1354
+ * After stopping:
1355
+ * - No longer responds to dependency changes
1356
+ * - Disconnects all dependency links
1357
+ * - Clears cached job function
1358
+ * - Calls onStop callback
1359
+ * - Verifies complete cleanup in development mode
1360
+ */
1361
+ stop() {
1362
+ if (!this._active) {
1363
+ {
1364
+ shared.warn("[Effect] Attempting to stop an already stopped effect.");
1365
+ }
1366
+ return;
1367
+ }
1368
+ this._active = false;
1369
+ let dep = this.depLink;
1370
+ while (dep) {
1371
+ dep = unlinkReactiveNode(dep, this);
1372
+ }
1373
+ let sub = this.subLink;
1374
+ while (sub) {
1375
+ sub = unlinkReactiveNode(sub);
1376
+ }
1377
+ this._job = void 0;
1378
+ this.depLinkTail = void 0;
1379
+ this.subLinkTail = void 0;
1380
+ {
1381
+ if (this.depLink) {
1382
+ shared.error(
1383
+ "[Effect] Cleanup verification failed: depLink not cleared. This indicates a memory leak in the dependency tracking system."
1384
+ );
1385
+ }
1386
+ if (this.subLink) {
1387
+ shared.error(
1388
+ "[Effect] Cleanup verification failed: subLink not cleared. This indicates a memory leak in the subscription system."
1389
+ );
1390
+ }
1391
+ }
1392
+ if (this.onStop) {
1393
+ this.onStop();
1394
+ }
1395
+ }
1396
+ };
1397
+ function effect(fn, options) {
1398
+ const effectInstance = new EffectImpl(fn, options);
1399
+ try {
1400
+ effectInstance.run();
1401
+ } catch (_error) {
1402
+ effectInstance.stop();
1403
+ {
1404
+ shared.error(
1405
+ "[Effect] Effect failed during initial execution and has been stopped. Fix the error in your effect function.",
1406
+ _error
1407
+ );
1408
+ }
1409
+ throw _error;
1410
+ }
1411
+ const runner = () => effectInstance.run();
1412
+ runner.effect = effectInstance;
1413
+ runner.stop = () => effectInstance.stop();
1414
+ return runner;
1415
+ }
1416
+ function stop(runner) {
1417
+ runner.effect.stop();
1418
+ }
1419
+ function isEffect(value) {
1420
+ return !!(value && value["_IS_EFFECT" /* IS_EFFECT */]);
1421
+ }
1422
+ function memoEffect(fn, initialState, options) {
1423
+ let currentState = initialState;
1424
+ const effectFn = () => {
1425
+ const result = fn(currentState);
1426
+ currentState = result;
1427
+ };
1428
+ return effect(effectFn, options);
1429
+ }
1430
+ var NO_VALUE = Symbol("computed-no-value");
1431
+ var _a3;
1432
+ _a3 = "_IS_COMPUTED" /* IS_COMPUTED */;
1433
+ var ComputedImpl = class {
1434
+ /**
1435
+ * Create a Computed instance
1436
+ *
1437
+ * @param getter - The computation function
1438
+ * @param setter - Optional setter function
1439
+ * @param onTrack - Optional debug callback for dependency tracking
1440
+ * @param onTrigger - Optional debug callback for triggers
1441
+ */
1442
+ constructor(getter, setter, onTrack, onTrigger) {
1443
+ this.flag = 1 /* MUTABLE */ | 16 /* DIRTY */;
1444
+ //@ts-ignore
1445
+ this[_a3] = true;
1446
+ // ===== Cache =====
1447
+ // Use symbol sentinel to distinguish "no value" from undefined/null values
1448
+ this._value = NO_VALUE;
1449
+ this.getter = getter;
1450
+ this.setter = setter;
1451
+ this.onTrack = onTrack;
1452
+ this.onTrigger = onTrigger;
1453
+ this.flag |= 16 /* DIRTY */;
1454
+ }
1455
+ get value() {
1456
+ if (activeSub) {
1457
+ linkReactiveNode(this, activeSub);
1458
+ }
1459
+ const flags = this.flag;
1460
+ const hasValue = this._value !== NO_VALUE;
1461
+ if (hasValue && !(flags & (16 /* DIRTY */ | 32 /* PENDING */))) {
1462
+ return this._value;
1463
+ }
1464
+ if (!hasValue || flags & 16 /* DIRTY */) {
1465
+ this.recompute();
1466
+ return this._value;
1467
+ }
1468
+ if (flags & 32 /* PENDING */) {
1469
+ if (this.depLink && checkDirty(this.depLink, this)) {
1470
+ this.recompute();
1471
+ } else {
1472
+ this.flag = flags & -33 /* PENDING */;
1473
+ }
1474
+ }
1475
+ return this._value;
1476
+ }
1477
+ /**
1478
+ * Set value (only effective when setter is provided)
1479
+ *
1480
+ * @param newValue - The new value
1481
+ */
1482
+ set value(newValue) {
1483
+ if (this.setter) {
1484
+ this.setter(newValue);
1485
+ } else {
1486
+ shared.warn(
1487
+ "[Computed] Cannot set readonly computed value. Provide a setter in the computed options to make it writable.\nExample: computed({ get: () => value, set: (v) => { ... } })"
1488
+ );
1489
+ }
1490
+ }
1491
+ /**
1492
+ * Read value without tracking dependencies
1493
+ *
1494
+ * @returns Current value
1495
+ */
1496
+ peek() {
1497
+ if (this._value === NO_VALUE) {
1498
+ this.recompute();
1499
+ }
1500
+ return this._value;
1501
+ }
1502
+ /**
1503
+ * Recompute the value
1504
+ *
1505
+ * computation logic:
1506
+ * 1. Start tracking dependencies
1507
+ * 2. Execute getter function
1508
+ * 3. Check if value changed using optimized comparison
1509
+ * 4. If changed, update cache and notify subscribers
1510
+ * 5. End tracking, clean up stale dependencies
1511
+ * @private
1512
+ */
1513
+ recompute() {
1514
+ const oldValue = this._value;
1515
+ const hadValue = oldValue !== NO_VALUE;
1516
+ const prevSub = startTracking(this);
1517
+ try {
1518
+ const newValue = this.getter();
1519
+ const flags = this.flag;
1520
+ const clearMask = ~(16 /* DIRTY */ | 32 /* PENDING */);
1521
+ const valueChanged = !hadValue || shared.hasChanged(oldValue, newValue);
1522
+ if (valueChanged) {
1523
+ this._value = newValue;
1524
+ this.flag = flags & clearMask;
1525
+ if (this.onTrigger) {
1526
+ this.onTrigger({
1527
+ effect: this,
1528
+ target: this,
1529
+ type: "set",
1530
+ key: "value",
1531
+ newValue
1532
+ });
1533
+ }
1534
+ if (this.subLink) {
1535
+ shallowPropagate(this.subLink);
1536
+ }
1537
+ } else {
1538
+ this.flag = flags & clearMask;
1539
+ }
1540
+ } catch (_error) {
1541
+ this.flag &= -49;
1542
+ {
1543
+ shared.error(
1544
+ "[Computed] Error occurred while computing value. Check your getter function for errors.",
1545
+ _error
1546
+ );
1547
+ }
1548
+ throw _error;
1549
+ } finally {
1550
+ endTracking(this, prevSub);
1551
+ }
1552
+ }
1553
+ /**
1554
+ * Check if update is needed
1555
+ *
1556
+ * Internal use, called by reactive system.
1557
+ *
1558
+ * @returns true if value changed
1559
+ */
1560
+ shouldUpdate() {
1561
+ const hadValue = this._value !== NO_VALUE;
1562
+ const oldValue = this._value;
1563
+ this.recompute();
1564
+ if (!hadValue) {
1565
+ return true;
1566
+ }
1567
+ return shared.hasChanged(this._value, oldValue);
1568
+ }
1569
+ };
1570
+ function computed(getterOrOptions) {
1571
+ if (isComputed(getterOrOptions)) {
1572
+ {
1573
+ shared.warn(
1574
+ "[Computed] Creating a computed from another computed is not recommended. The existing computed will be returned to avoid unnecessary wrapping."
1575
+ );
1576
+ }
1577
+ return getterOrOptions;
1578
+ }
1579
+ if (!getterOrOptions) {
1580
+ throw new Error(
1581
+ "[Computed] Invalid argument: computed() requires a getter function or options object."
1582
+ );
1583
+ }
1584
+ if (shared.isFunction(getterOrOptions)) {
1585
+ return new ComputedImpl(getterOrOptions);
1586
+ }
1587
+ if (shared.isPlainObject(getterOrOptions)) {
1588
+ const { get, set, onTrack, onTrigger } = getterOrOptions;
1589
+ if (!get) {
1590
+ throw new Error(
1591
+ "[Computed] Invalid options: getter function is required.\nUsage: computed({ get: () => value, set: (v) => { ... } })"
1592
+ );
1593
+ }
1594
+ if (!shared.isFunction(get)) {
1595
+ throw new TypeError(
1596
+ `[Computed] Invalid options: getter must be a function.
1597
+ Received: ${typeof get}`
1598
+ );
1599
+ }
1600
+ return new ComputedImpl(get, set, onTrack, onTrigger);
1601
+ }
1602
+ throw new Error(
1603
+ `[Computed] Invalid argument: expected a function or options object.
1604
+ Received: ${typeof getterOrOptions}`
1605
+ );
1606
+ }
1607
+ function isComputed(value) {
1608
+ return !!value && !!value["_IS_COMPUTED" /* IS_COMPUTED */];
1609
+ }
1610
+ function createOptionsStore(options) {
1611
+ if (!options.state) {
1612
+ shared.warn("Store state is required");
1613
+ throw new Error("Store state is required");
1614
+ }
1615
+ const { state, getters, actions } = options;
1616
+ const initState = __spreadValues({}, state);
1617
+ const reactiveState = reactive(state);
1618
+ const subscriptions = /* @__PURE__ */ new Set();
1619
+ const actionCallbacks = /* @__PURE__ */ new Set();
1620
+ const defaultActions = {
1621
+ patch$(payload) {
1622
+ if (!payload) {
1623
+ shared.warn("Patch payload is required");
1624
+ return;
1625
+ }
1626
+ batch(() => {
1627
+ Object.assign(reactiveState, payload);
1628
+ });
1629
+ subscriptions.forEach((callback) => callback(reactiveState));
1630
+ actionCallbacks.forEach((callback) => callback(reactiveState));
1631
+ },
1632
+ subscribe$(callback) {
1633
+ if (!callback) {
1634
+ shared.warn("Subscribe callback is required");
1635
+ return;
1636
+ }
1637
+ subscriptions.add(callback);
1638
+ },
1639
+ unsubscribe$(callback) {
1640
+ subscriptions.delete(callback);
1641
+ },
1642
+ onAction$(callback) {
1643
+ if (!callback) {
1644
+ shared.warn("Action callback is required");
1645
+ return;
1646
+ }
1647
+ actionCallbacks.add(callback);
1648
+ },
1649
+ reset$() {
1650
+ batch(() => {
1651
+ Object.assign(reactiveState, initState);
1652
+ });
1653
+ subscriptions.forEach((callback) => callback(reactiveState));
1654
+ actionCallbacks.forEach((callback) => callback(reactiveState));
1655
+ }
1656
+ };
1657
+ const store = __spreadValues(__spreadProps(__spreadValues({}, reactiveState), {
1658
+ state: reactiveState
1659
+ }), defaultActions);
1660
+ if (getters) {
1661
+ for (const key in getters) {
1662
+ const getter = getters[key];
1663
+ if (getter) {
1664
+ Object.defineProperty(store, key, {
1665
+ get() {
1666
+ return computed(() => getter.call(store, reactiveState)).value;
1667
+ },
1668
+ enumerable: true,
1669
+ configurable: true
1670
+ });
1671
+ }
1672
+ }
1673
+ }
1674
+ if (actions) {
1675
+ for (const key in actions) {
1676
+ const action = actions[key];
1677
+ if (action) {
1678
+ store[key] = (...args) => {
1679
+ const result = action.apply(reactiveState, args);
1680
+ actionCallbacks.forEach((callback) => callback(reactiveState));
1681
+ return result;
1682
+ };
1683
+ }
1684
+ }
1685
+ }
1686
+ return store;
1687
+ }
1688
+ function createClassStore(StoreClass) {
1689
+ const instance = new StoreClass();
1690
+ const state = /* @__PURE__ */ Object.create(null);
1691
+ const getters = {};
1692
+ const actions = {};
1693
+ Object.getOwnPropertyNames(instance).forEach((key) => {
1694
+ state[key] = instance[key];
1695
+ });
1696
+ Object.getOwnPropertyNames(StoreClass.prototype).forEach((key) => {
1697
+ const descriptor = Object.getOwnPropertyDescriptor(StoreClass.prototype, key);
1698
+ if (descriptor) {
1699
+ if (typeof descriptor.get === "function") {
1700
+ getters[key] = function() {
1701
+ return descriptor.get.call(this);
1702
+ };
1703
+ } else if (typeof descriptor.value === "function" && key !== "constructor") {
1704
+ actions[key] = function(...args) {
1705
+ return descriptor.value.apply(this, args);
1706
+ };
1707
+ }
1708
+ }
1709
+ });
1710
+ return {
1711
+ state,
1712
+ getters,
1713
+ actions
1714
+ };
1715
+ }
1716
+ function createStore(storeDefinition) {
1717
+ if (!storeDefinition) {
1718
+ shared.warn("Store definition is required");
1719
+ throw new Error("Store definition is required");
1720
+ }
1721
+ return () => {
1722
+ let options;
1723
+ if (typeof storeDefinition === "function") {
1724
+ options = createClassStore(storeDefinition);
1725
+ } else {
1726
+ options = storeDefinition;
1727
+ }
1728
+ const store = createOptionsStore(options);
1729
+ if (typeof storeDefinition === "function") {
1730
+ Object.keys(options.actions || {}).forEach((key) => {
1731
+ store[key] = options.actions[key].bind(store);
1732
+ });
1733
+ }
1734
+ return store;
1735
+ };
1736
+ }
1737
+ var _a4, _b;
1738
+ var RefImpl = class extends (_b = SignalImpl, _a4 = "_IS_REF" /* IS_REF */, _b) {
1739
+ /**
1740
+ * Creates a new ref with the given initial value.
1741
+ *
1742
+ * @param value - The initial value
1743
+ */
1744
+ constructor(value) {
1745
+ super(value, true);
1746
+ // @ts-ignore
1747
+ this[_a4] = true;
1748
+ }
1749
+ get value() {
1750
+ track(this, SIGNAL_KEY);
1751
+ return this._value;
1752
+ }
1753
+ set value(newValue) {
1754
+ if (isSignal(newValue)) {
1755
+ newValue = newValue.value;
1756
+ }
1757
+ if (isRef(newValue)) {
1758
+ newValue = newValue.value;
1759
+ }
1760
+ if (shared.hasChanged(this._value, newValue)) {
1761
+ this._value = newValue;
1762
+ if (this.subLink) {
1763
+ shallowPropagate2(this.subLink);
1764
+ }
1765
+ trigger(this, "SET", SIGNAL_KEY);
1766
+ }
1767
+ }
1768
+ };
1769
+ function ref(value = void 0) {
1770
+ if (isRef(value)) {
1771
+ {
1772
+ shared.info("Creating a ref with another ref is not recommended. The value will be unwrapped.");
1773
+ }
1774
+ return value;
1775
+ }
1776
+ if (isSignal(value)) {
1777
+ {
1778
+ shared.info("Creating a ref with a signal is not recommended. The value will be unwrapped.");
1779
+ }
1780
+ return new RefImpl(value.peek());
1781
+ }
1782
+ return new RefImpl(value);
1783
+ }
1784
+ function isRef(value) {
1785
+ return !!value && !!value["_IS_REF" /* IS_REF */];
1786
+ }
1787
+ var INITIAL_WATCHER_VALUE = {};
1788
+ var cleanupMap = /* @__PURE__ */ new WeakMap();
1789
+ function traverse(value, seen = /* @__PURE__ */ new Set()) {
1790
+ if (!shared.isObject(value) || seen.has(value)) {
1791
+ return value;
1792
+ }
1793
+ seen.add(value);
1794
+ if (isSignal(value) || isComputed(value)) {
1795
+ return traverse(value.value, seen);
1796
+ }
1797
+ if (Array.isArray(value)) {
1798
+ for (const element of value) {
1799
+ traverse(element, seen);
1800
+ }
1801
+ } else if (shared.isMap(value)) {
1802
+ value.forEach((v) => {
1803
+ traverse(v, seen);
1804
+ });
1805
+ value.keys();
1806
+ value.values();
1807
+ } else if (shared.isSet(value)) {
1808
+ value.forEach((v) => {
1809
+ traverse(v, seen);
1810
+ });
1811
+ value.values();
1812
+ } else {
1813
+ Object.keys(value).forEach((key) => {
1814
+ traverse(value[key], seen);
1815
+ });
1816
+ }
1817
+ return value;
1818
+ }
1819
+ function cloneValue(value) {
1820
+ if (!shared.isObject(value)) {
1821
+ return value;
1822
+ }
1823
+ if (Array.isArray(value)) {
1824
+ return value.map((item) => cloneValue(item));
1825
+ }
1826
+ if (shared.isMap(value)) {
1827
+ const cloned2 = /* @__PURE__ */ new Map();
1828
+ value.forEach((v, k) => {
1829
+ cloned2.set(k, cloneValue(v));
1830
+ });
1831
+ return cloned2;
1832
+ }
1833
+ if (shared.isSet(value)) {
1834
+ const cloned2 = /* @__PURE__ */ new Set();
1835
+ value.forEach((v) => {
1836
+ cloned2.add(cloneValue(v));
1837
+ });
1838
+ return cloned2;
1839
+ }
1840
+ const cloned = {};
1841
+ for (const key of Object.keys(value)) {
1842
+ cloned[key] = cloneValue(value[key]);
1843
+ }
1844
+ return cloned;
1845
+ }
1846
+ function resolveSource(source) {
1847
+ if (Array.isArray(source)) {
1848
+ return () => source.map((s) => {
1849
+ if (isSignal(s) || isComputed(s)) {
1850
+ return s.value;
1851
+ }
1852
+ if (isReactive(s)) {
1853
+ return traverse(s);
1854
+ }
1855
+ if (shared.isFunction(s)) {
1856
+ return s();
1857
+ }
1858
+ return s;
1859
+ });
1860
+ }
1861
+ if (shared.isFunction(source)) {
1862
+ return source;
1863
+ }
1864
+ if (isSignal(source)) {
1865
+ return () => source.value;
1866
+ }
1867
+ if (shared.isObject(source) && "value" in source) {
1868
+ return () => source.value;
1869
+ }
1870
+ if (isReactive(source)) {
1871
+ return () => traverse(source);
1872
+ }
1873
+ return () => source;
1874
+ }
1875
+ function watch(source, callback, options = {}) {
1876
+ const { immediate = false, deep = false } = options;
1877
+ let oldValue = INITIAL_WATCHER_VALUE;
1878
+ const getter = resolveSource(source);
1879
+ const job = () => {
1880
+ const currentEffect = runner.effect;
1881
+ if (!currentEffect.run) {
1882
+ return;
1883
+ }
1884
+ const newValue = currentEffect.run();
1885
+ if (shared.hasChanged(newValue, oldValue)) {
1886
+ callback(newValue, oldValue === INITIAL_WATCHER_VALUE ? void 0 : oldValue);
1887
+ oldValue = cloneValue(newValue);
1888
+ }
1889
+ };
1890
+ const runner = effect(
1891
+ () => {
1892
+ const value = getter();
1893
+ if (deep) {
1894
+ traverse(value);
1895
+ }
1896
+ return value;
1897
+ },
1898
+ {
1899
+ // Use scheduler to queue job, implementing async and debouncing.
1900
+ scheduler: () => queueJob(job)
1901
+ }
1902
+ );
1903
+ if (immediate) {
1904
+ job();
1905
+ } else {
1906
+ oldValue = cloneValue(runner.effect.run());
1907
+ }
1908
+ return () => {
1909
+ runner.stop();
1910
+ const cleanups = cleanupMap.get(runner.effect);
1911
+ if (cleanups) {
1912
+ cleanups.forEach((fn) => fn());
1913
+ cleanupMap.delete(runner.effect);
1914
+ }
1915
+ };
1916
+ }
1917
+
1918
+ exports.TriggerOpTypes = TriggerOpTypes;
1919
+ exports.batch = batch;
1920
+ exports.computed = computed;
1921
+ exports.createStore = createStore;
1922
+ exports.effect = effect;
1923
+ exports.endBatch = endBatch;
1924
+ exports.getBatchDepth = getBatchDepth;
1925
+ exports.isBatching = isBatching;
1926
+ exports.isComputed = isComputed;
1927
+ exports.isEffect = isEffect;
1928
+ exports.isReactive = isReactive;
1929
+ exports.isRef = isRef;
1930
+ exports.isShallow = isShallow;
1931
+ exports.isSignal = isSignal;
1932
+ exports.memoEffect = memoEffect;
1933
+ exports.nextTick = nextTick;
1934
+ exports.queueJob = queueJob;
1935
+ exports.queuePreFlushCb = queuePreFlushCb;
1936
+ exports.reactive = reactive;
1937
+ exports.ref = ref;
1938
+ exports.shallowReactive = shallowReactive;
1939
+ exports.shallowSignal = shallowSignal;
1940
+ exports.signal = signal;
1941
+ exports.startBatch = startBatch;
1942
+ exports.stop = stop;
1943
+ exports.toRaw = toRaw;
1944
+ exports.toReactive = toReactive;
1945
+ exports.trigger = trigger;
1946
+ exports.untrack = untrack;
1947
+ exports.watch = watch;