react-fine-grained-signals 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1354 @@
1
+ import { createReactiveSystem } from "alien-signals/system";
2
+ //#region src/core/execution-owner.ts
3
+ const UNTRACKED_OWNER = Symbol.for("react-fine-grained-signals.untracked-owner.v2");
4
+ function isGraphExecutionOwner(owner) {
5
+ return typeof owner === "object" && owner !== null && owner.kind === "graph";
6
+ }
7
+ function isRenderExecutionOwner(owner) {
8
+ return typeof owner === "object" && owner !== null && owner.kind === "render";
9
+ }
10
+ const CONTEXT_KEY = Symbol.for("react-fine-grained-signals.shared-execution-owner.v2");
11
+ const globalObject = globalThis;
12
+ const existing = globalObject[CONTEXT_KEY];
13
+ if (existing !== void 0 && existing.version !== 2) throw new Error("Incompatible RFSG shared execution owner");
14
+ const executionContext = existing ?? {
15
+ version: 2,
16
+ owner: void 0,
17
+ frames: []
18
+ };
19
+ executionContext.frames ??= [];
20
+ if (existing === void 0) Object.defineProperty(globalObject, CONTEXT_KEY, {
21
+ value: executionContext,
22
+ enumerable: false,
23
+ configurable: false,
24
+ writable: false
25
+ });
26
+ /** Temporarily changes lexical ownership inside one synchronous call. */
27
+ function withSynchronousExecutionOwner(owner, callback) {
28
+ const previous = executionContext.owner;
29
+ executionContext.owner = owner;
30
+ try {
31
+ return callback();
32
+ } finally {
33
+ executionContext.owner = previous;
34
+ }
35
+ }
36
+ function pushExecutionOwner(owner) {
37
+ const frame = {
38
+ owner,
39
+ active: true
40
+ };
41
+ executionContext.frames.push(frame);
42
+ executionContext.owner = owner;
43
+ let active = true;
44
+ return () => {
45
+ if (!active) return;
46
+ active = false;
47
+ frame.active = false;
48
+ while (executionContext.frames.at(-1)?.active === false) executionContext.frames.pop();
49
+ executionContext.owner = executionContext.frames.at(-1)?.owner;
50
+ };
51
+ }
52
+ //#endregion
53
+ //#region src/core/interop-context.mts
54
+ const READABLE_INTEROP_V1$1 = Symbol.for("react-fine-grained-signals.readable-interop.v1");
55
+ //#endregion
56
+ //#region src/core/foreign-readable-v1.mts
57
+ /** A render owner records another copy's read under its protocol object itself. */
58
+ function isReadableProtocol(value) {
59
+ return typeof value === "object" && value !== null && Reflect.get(value, "version") === 1 && typeof Reflect.get(value, "getRevision") === "function" && typeof Reflect.get(value, "subscribe") === "function";
60
+ }
61
+ function observeRevision(node) {
62
+ return node.renderRevision ??= 0;
63
+ }
64
+ function createForeignReadableAdapter({ runtimeToken, makeNode, mutableFlag, dirtyFlag, getActiveSubscriber, link, propagate, shallowPropagate, flush, isRunning, isBatching, effect, own }) {
65
+ const readableNodes = /* @__PURE__ */ new WeakMap();
66
+ const foreignNodes = /* @__PURE__ */ new WeakMap();
67
+ const localReadable = Symbol("localReadable");
68
+ function getLocalReadableRevision() {
69
+ const readable = this[localReadable];
70
+ const node = readableNodes.get(readable);
71
+ try {
72
+ withSynchronousExecutionOwner(UNTRACKED_OWNER, () => readable.value);
73
+ } catch {}
74
+ return observeRevision(node);
75
+ }
76
+ function subscribeLocalReadable(listener) {
77
+ const readable = this[localReadable];
78
+ const node = readableNodes.get(readable);
79
+ const revision = observeRevision(node);
80
+ let initial = true;
81
+ return {
82
+ unsubscribe: effect(() => {
83
+ try {
84
+ readable.value;
85
+ } catch {}
86
+ if (initial) initial = false;
87
+ else listener(observeRevision(node));
88
+ }),
89
+ revision
90
+ };
91
+ }
92
+ function advance(node, revision) {
93
+ if (revision === node.pendingRevision) return false;
94
+ node.pendingRevision = revision;
95
+ node.flags = mutableFlag | dirtyFlag;
96
+ if (node.subs !== void 0) propagate(node.subs, isRunning());
97
+ return true;
98
+ }
99
+ function observeForeignRevision(node, revision) {
100
+ if (advance(node, revision)) {
101
+ node.revision = revision;
102
+ node.flags = mutableFlag;
103
+ if (node.subs !== void 0) shallowPropagate(node.subs);
104
+ }
105
+ }
106
+ function ensureForeignNode(protocol, observedRevision) {
107
+ let node = foreignNodes.get(protocol);
108
+ if (node === void 0) {
109
+ node = makeNode("external", mutableFlag, {
110
+ protocol,
111
+ revision: observedRevision,
112
+ pendingRevision: observedRevision,
113
+ unsubscribe: void 0
114
+ });
115
+ foreignNodes.set(protocol, node);
116
+ }
117
+ observeForeignRevision(node, observedRevision);
118
+ const subscriber = getActiveSubscriber();
119
+ if (subscriber?.kind === "computed") subscriber.foreignDependent = true;
120
+ if (subscriber !== void 0) link(node, subscriber);
121
+ if (subscriber?.kind === "effect" && activateForeignNode(node)) subscriber.flags |= 128;
122
+ return node;
123
+ }
124
+ function activateForeignNode(node) {
125
+ if (node.unsubscribe === void 0) {
126
+ const subscription = node.protocol.subscribe((revision) => {
127
+ if (revision !== node.revision) advance(node, revision);
128
+ if (!isBatching()) flush();
129
+ });
130
+ node.unsubscribe = subscription.unsubscribe;
131
+ if (advance(node, subscription.revision)) {
132
+ if (!isBatching()) flush();
133
+ return true;
134
+ }
135
+ }
136
+ }
137
+ const graphOwner = {
138
+ version: 2,
139
+ kind: "graph",
140
+ runtimeToken,
141
+ add(protocol, revision) {
142
+ ensureForeignNode(protocol, revision);
143
+ },
144
+ own
145
+ };
146
+ function withGraphOwner(callback) {
147
+ const owner = executionContext.owner;
148
+ if (isGraphExecutionOwner(owner) && owner.runtimeToken === runtimeToken) return callback();
149
+ return withSynchronousExecutionOwner(graphOwner, callback);
150
+ }
151
+ function publishForeignReadable(readable, node, owner) {
152
+ if (owner === UNTRACKED_OWNER || (isGraphExecutionOwner(owner) || isRenderExecutionOwner(owner)) && owner.runtimeToken === runtimeToken) return;
153
+ const protocol = node.readableProtocol;
154
+ if (protocol !== void 0) {
155
+ if (isGraphExecutionOwner(owner) || isRenderExecutionOwner(owner)) owner.add(protocol, observeRevision(node));
156
+ }
157
+ }
158
+ function attachProtocol(readable, node) {
159
+ readableNodes.set(readable, node);
160
+ const protocol = {
161
+ version: 1,
162
+ runtimeToken,
163
+ [localReadable]: readable,
164
+ getRevision: getLocalReadableRevision,
165
+ subscribe: subscribeLocalReadable
166
+ };
167
+ node.readableProtocol = protocol;
168
+ Object.defineProperty(readable, READABLE_INTEROP_V1$1, {
169
+ value: protocol,
170
+ enumerable: false,
171
+ writable: false,
172
+ configurable: false
173
+ });
174
+ }
175
+ function getReadableRevision(readable) {
176
+ const node = readableNodes.get(readable);
177
+ if (node !== void 0) return observeRevision(node);
178
+ const protocolValue = Reflect.get(readable, READABLE_INTEROP_V1$1);
179
+ if (isReadableProtocol(protocolValue)) return protocolValue.getRevision();
180
+ throw new TypeError("Unknown candidate readable");
181
+ }
182
+ return {
183
+ attachProtocol,
184
+ ensureForeignNode,
185
+ activateForeignNode,
186
+ observeForeignRevision,
187
+ getNodeForReadable: (value) => readableNodes.get(value),
188
+ getReadableRevision,
189
+ observeRevision,
190
+ publishForeignReadable,
191
+ graphOwner,
192
+ withGraphOwner
193
+ };
194
+ }
195
+ //#endregion
196
+ //#region src/core/interop.ts
197
+ const READABLE_INTEROP_V1 = Symbol.for("react-fine-grained-signals.readable-interop.v1");
198
+ const SHARED_CONTEXT_V1 = Symbol.for("react-fine-grained-signals.shared-interop-context.v1");
199
+ let cachedContext;
200
+ /** Resolve the tiny same-global context shared by duplicate module copies. */
201
+ function getSharedInteropContext() {
202
+ if (cachedContext !== void 0) return cachedContext;
203
+ const globalObject = globalThis;
204
+ const existing = globalObject[SHARED_CONTEXT_V1];
205
+ if (existing !== void 0) {
206
+ if (existing.version !== 1 || typeof existing.speculativeDepth !== "number") throw new Error("Incompatible react-fine-grained-signals interop context");
207
+ cachedContext = existing;
208
+ return existing;
209
+ }
210
+ const context = {
211
+ version: 1,
212
+ speculativeDepth: 0,
213
+ speculativeDeepReadEpoch: 0
214
+ };
215
+ Object.defineProperty(globalObject, SHARED_CONTEXT_V1, {
216
+ value: context,
217
+ enumerable: false,
218
+ configurable: false,
219
+ writable: false
220
+ });
221
+ cachedContext = context;
222
+ return context;
223
+ }
224
+ function getReadableInterop(readable) {
225
+ const protocol = readable[READABLE_INTEROP_V1];
226
+ if (protocol === void 0 || typeof protocol !== "object" || protocol === null) return;
227
+ const candidate = protocol;
228
+ return candidate.version === 1 && typeof candidate.getRevision === "function" && typeof candidate.subscribe === "function" && typeof candidate.runtimeToken === "object" && candidate.runtimeToken !== null ? candidate : void 0;
229
+ }
230
+ function attachReadableInterop(readable, protocol) {
231
+ Object.defineProperty(readable, READABLE_INTEROP_V1, {
232
+ value: protocol,
233
+ enumerable: false,
234
+ configurable: false,
235
+ writable: false
236
+ });
237
+ }
238
+ function withInteropRenderCollector(collector, callback) {
239
+ const context = getSharedInteropContext();
240
+ const previous = context.renderCollector;
241
+ context.renderCollector = collector;
242
+ try {
243
+ return callback();
244
+ } finally {
245
+ context.renderCollector = previous;
246
+ }
247
+ }
248
+ function withoutInteropRenderCollector(callback) {
249
+ return withInteropRenderCollector(void 0, callback);
250
+ }
251
+ function isInteropSpeculative() {
252
+ return getSharedInteropContext().speculativeDepth > 0;
253
+ }
254
+ /** Marks speculative deep reads whose per-key dependencies were not collected. */
255
+ function markInteropSpeculativeDeepRead() {
256
+ const context = getSharedInteropContext();
257
+ context.speculativeDeepReadEpoch = (context.speculativeDeepReadEpoch ?? 0) + 1;
258
+ }
259
+ //#endregion
260
+ //#region src/core/render-tracking.ts
261
+ let activeRenderCollector;
262
+ /** Returns whether a React render is currently collecting signal reads. */
263
+ function hasActiveRenderCollector() {
264
+ return activeRenderCollector !== void 0;
265
+ }
266
+ /** Replaces the current render collector and returns the previous collector. */
267
+ function setActiveRenderCollector(collector) {
268
+ const previous = activeRenderCollector;
269
+ activeRenderCollector = collector;
270
+ return previous;
271
+ }
272
+ /** Records a dependency and reports whether render collection was active. */
273
+ function trackRenderDependency(dependency, observedVersion) {
274
+ if (activeRenderCollector === void 0) return false;
275
+ activeRenderCollector.add(dependency, observedVersion ?? dependency.getRenderVersion());
276
+ return true;
277
+ }
278
+ /** Runs a callback without adding its reads to the active React render. */
279
+ function untrackedRender(callback) {
280
+ const previous = setActiveRenderCollector();
281
+ try {
282
+ const owner = executionContext.owner;
283
+ const run = () => withoutInteropRenderCollector(callback);
284
+ if (owner !== void 0 && typeof owner !== "symbol" && owner.kind === "graph") return run();
285
+ return withSynchronousExecutionOwner(UNTRACKED_OWNER, run);
286
+ } finally {
287
+ setActiveRenderCollector(previous);
288
+ }
289
+ }
290
+ /**
291
+ * Invokes one subscription listener, keeping its failure from cancelling the
292
+ * listeners queued behind it. Without this, a single throwing subscriber
293
+ * aborts the rest of the notify cycle, so unrelated components silently miss
294
+ * the update that was being delivered. Reported the same way as the other
295
+ * background-callback failures in this codebase (`readBoundSignal` in
296
+ * src/runtime/jsx.ts): `console.error(message, { cause })`.
297
+ */
298
+ function notifyListener(listener) {
299
+ try {
300
+ listener();
301
+ } catch (error) {
302
+ console.error("react-fine-grained-signals: a render-subscription listener threw; continuing with the remaining listeners.", { cause: error });
303
+ }
304
+ }
305
+ //#endregion
306
+ //#region src/core/signal-brand.ts
307
+ /**
308
+ * Package-wide identity marker shared by public signal wrappers and deep proxies.
309
+ *
310
+ * The key names a *generation* of the cross-copy contract; the number stored
311
+ * under it is that generation's minor version. A minor version only ever widens
312
+ * the contract, so anything from the minimum upwards is trusted; a change that
313
+ * an older copy could not honour takes a new key instead.
314
+ *
315
+ * v0.1.x used `react-fine-grained-signals.signal` and trusted every version
316
+ * from 1 upwards. A v0.2 signal is only reactive under the v2 shared execution
317
+ * owner and the ReadableInterop V1 protocol, neither of which a v0.1.x copy
318
+ * knows, so reusing that key with a larger number would have let v0.1.x
319
+ * recognize v0.2 signals (and v0.2 recognize v0.1.x ones) and then silently
320
+ * never update. A separate key makes each generation reject the other's
321
+ * signals outright: JSX and `isSignal` fail loudly instead of going stale.
322
+ */
323
+ const SIGNAL_BRAND = Symbol.for("react-fine-grained-signals.signal.v2");
324
+ //#endregion
325
+ //#region src/core/alien-derived-runtime-core.mts
326
+ const None = 0;
327
+ const Mutable = 1;
328
+ const Watching = 2;
329
+ const RecursedCheck = 4;
330
+ const Dirty = 16;
331
+ const Pending = 32;
332
+ const HasChildEffect = 64;
333
+ function createAlienDerivedRuntime() {
334
+ const runtimeToken = {};
335
+ let renderAdapter;
336
+ let activeRenderAttempt;
337
+ let activeSub;
338
+ let speculativeChildren;
339
+ let cycle = 0;
340
+ let runDepth = 0;
341
+ let batchDepth = 0;
342
+ let flushIndex = 0;
343
+ let queuedLength = 0;
344
+ const queue = [];
345
+ const { link: alienLink, unlink: alienUnlink, propagate, checkDirty, shallowPropagate } = createReactiveSystem({
346
+ update(rawNode) {
347
+ const node = rawNode;
348
+ if (node.kind === "external") {
349
+ const changed = node.revision !== node.pendingRevision;
350
+ node.revision = node.pendingRevision;
351
+ node.flags = Mutable;
352
+ return changed;
353
+ }
354
+ if (node.kind === "computed") return updateComputed(node);
355
+ if (node.kind === "source") return updateSource(node);
356
+ node.flags = Mutable;
357
+ return true;
358
+ },
359
+ notify(rawEffect) {
360
+ let current = rawEffect;
361
+ let insertIndex = queuedLength;
362
+ const firstInsertedIndex = insertIndex;
363
+ do {
364
+ const effect = current;
365
+ queue[insertIndex++] = effect;
366
+ effect.flags &= -3;
367
+ current = effect.subs?.sub;
368
+ if (current === void 0 || !(current.flags & Watching)) break;
369
+ } while (true);
370
+ queuedLength = insertIndex;
371
+ let leftIndex = firstInsertedIndex;
372
+ while (leftIndex < --insertIndex) {
373
+ const left = queue[leftIndex];
374
+ queue[leftIndex++] = queue[insertIndex];
375
+ queue[insertIndex] = left;
376
+ }
377
+ },
378
+ unwatched(rawNode) {
379
+ const node = rawNode;
380
+ if (node.kind === "external") {
381
+ node.unsubscribe?.();
382
+ node.unsubscribe = void 0;
383
+ } else if (node.kind === "computed") {
384
+ if (node.depsTail !== void 0) {
385
+ node.flags = 17;
386
+ disposeDeps(node);
387
+ }
388
+ } else if (node.kind === "effect") disposeEffect(node);
389
+ }
390
+ });
391
+ function linkNode(dependency, subscriber, version) {
392
+ alienLink(dependency, subscriber, version);
393
+ }
394
+ function unlinkNode(linkage, subscriber) {
395
+ return alienUnlink(linkage, subscriber);
396
+ }
397
+ function makeNode(kind, flags, fields = {}) {
398
+ return {
399
+ kind,
400
+ flags,
401
+ deps: void 0,
402
+ depsTail: void 0,
403
+ subs: void 0,
404
+ subsTail: void 0,
405
+ renderRevision: 0,
406
+ ...fields
407
+ };
408
+ }
409
+ const foreignAdapter = createForeignReadableAdapter({
410
+ runtimeToken,
411
+ makeNode,
412
+ mutableFlag: Mutable,
413
+ dirtyFlag: Dirty,
414
+ getActiveSubscriber: () => activeSub,
415
+ link: (node, subscriber) => linkNode(node, subscriber, cycle),
416
+ propagate,
417
+ shallowPropagate,
418
+ flush: () => flush(),
419
+ isRunning: () => !!runDepth,
420
+ isBatching: () => !!batchDepth,
421
+ effect: (callback) => detachedEffect(callback),
422
+ own: adopt
423
+ });
424
+ const renderDependencies = /* @__PURE__ */ new WeakMap();
425
+ const deepSignalNodes = /* @__PURE__ */ new WeakSet();
426
+ const deepWatchedNodes = /* @__PURE__ */ new WeakSet();
427
+ function getRenderDependency(readable, node) {
428
+ if (!renderDependencies.has(readable)) {
429
+ node.getRenderVersion = () => foreignAdapter.observeRevision(node);
430
+ node.subscribeRender = (listener) => {
431
+ let initial = true;
432
+ let version = foreignAdapter.observeRevision(node);
433
+ return detachedEffect(() => {
434
+ try {
435
+ readable.value;
436
+ } catch {}
437
+ const nextVersion = foreignAdapter.observeRevision(node);
438
+ if (initial) initial = false;
439
+ else if (nextVersion !== version) listener();
440
+ version = nextVersion;
441
+ });
442
+ };
443
+ renderDependencies.set(readable, node);
444
+ }
445
+ return renderDependencies.get(readable);
446
+ }
447
+ function readSource(source) {
448
+ if (source.flags & Dirty && updateSource(source)) {
449
+ if (source.subs !== void 0) shallowPropagate(source.subs);
450
+ }
451
+ if (activeSub !== void 0) linkNode(source, activeSub, cycle);
452
+ return source.currentValue;
453
+ }
454
+ function readSourceUntracked(source) {
455
+ if (source.flags & Dirty && updateSource(source)) {
456
+ if (source.subs !== void 0) shallowPropagate(source.subs);
457
+ }
458
+ return source.currentValue;
459
+ }
460
+ function isForeignOwner(owner) {
461
+ return (isGraphExecutionOwner(owner) || isRenderExecutionOwner(owner)) && owner.runtimeToken !== runtimeToken;
462
+ }
463
+ const attachProtocol = foreignAdapter.attachProtocol;
464
+ const ensureForeignNode = foreignAdapter.ensureForeignNode;
465
+ const graphOwner = foreignAdapter.graphOwner;
466
+ function withGraphOwner(callback) {
467
+ const owner = executionContext.owner;
468
+ const previousAttempt = activeRenderAttempt;
469
+ const alreadyOwned = isGraphExecutionOwner(owner) && owner.runtimeToken === runtimeToken;
470
+ if (previousAttempt === void 0 && alreadyOwned) return callback();
471
+ activeRenderAttempt = void 0;
472
+ if (!alreadyOwned) executionContext.owner = graphOwner;
473
+ try {
474
+ return callback();
475
+ } finally {
476
+ if (!alreadyOwned) executionContext.owner = owner;
477
+ activeRenderAttempt = previousAttempt;
478
+ }
479
+ }
480
+ function configureRenderAdapter(adapter) {
481
+ renderAdapter = adapter;
482
+ }
483
+ function withRenderAttempt(attempt, callback) {
484
+ const restore = pushRenderAttempt(attempt);
485
+ try {
486
+ return callback();
487
+ } finally {
488
+ restore();
489
+ }
490
+ }
491
+ function pushRenderAttempt(attempt) {
492
+ const previous = activeRenderAttempt;
493
+ activeRenderAttempt = attempt;
494
+ let active = true;
495
+ return () => {
496
+ if (!active) return;
497
+ active = false;
498
+ if (activeRenderAttempt === attempt) activeRenderAttempt = previous;
499
+ };
500
+ }
501
+ function getActiveRenderAttempt() {
502
+ return activeRenderAttempt;
503
+ }
504
+ const getNodeForReadable = foreignAdapter.getNodeForReadable;
505
+ const getReadableRevision = foreignAdapter.getReadableRevision;
506
+ function isComputedClean(node) {
507
+ if (node.foreignDependent) refreshForeignDependencies(node, /* @__PURE__ */ new Set());
508
+ return node.initialized === true && !(node.flags & 48);
509
+ }
510
+ function getDependencyRevision(dependency) {
511
+ return isReadableProtocol(dependency) ? dependency.getRevision() : getReadableRevision(dependency);
512
+ }
513
+ function promoteComputed(readable, node, entry) {
514
+ if (node.initialized) return true;
515
+ const computed = node;
516
+ const hadForeignDependencies = computed.foreignDependent;
517
+ const dependencies = [];
518
+ const revisions = [];
519
+ for (const [dependency, revision] of entry.dependencies) {
520
+ let protocol = dependency;
521
+ if (!isReadableProtocol(dependency)) {
522
+ if (getReadableRevision(dependency) !== revision) return false;
523
+ const dependencyNode = foreignAdapter.getNodeForReadable(dependency);
524
+ if (dependencyNode !== void 0) {
525
+ if (dependencyNode.kind === "computed" && !isComputedClean(dependencyNode)) return false;
526
+ if (dependencyNode.kind === "source") readSourceUntracked(dependencyNode);
527
+ dependencies.push(dependencyNode);
528
+ revisions.push(revision);
529
+ continue;
530
+ }
531
+ protocol = Reflect.get(dependency, READABLE_INTEROP_V1$1);
532
+ if (!isReadableProtocol(protocol)) return false;
533
+ } else if (dependency.getRevision() !== revision) return false;
534
+ dependencies.push(protocol);
535
+ revisions.push(revision);
536
+ }
537
+ disposeDeps(computed);
538
+ computed.depsTail = void 0;
539
+ const previousSub = activeSub;
540
+ activeSub = computed;
541
+ cycle += 1;
542
+ try {
543
+ for (let index = 0; index < dependencies.length; index += 1) {
544
+ const dependency = dependencies[index];
545
+ if (dependency.kind === void 0) ensureForeignNode(dependency, revisions[index]);
546
+ else linkNode(dependency, computed, cycle);
547
+ }
548
+ } finally {
549
+ activeSub = previousSub;
550
+ }
551
+ recomputeForeignDependencies(computed);
552
+ if (hadForeignDependencies !== computed.foreignDependent) updateForeignDependencyAncestors(computed);
553
+ computed.value = entry.value;
554
+ computed.error = entry.error;
555
+ computed.hasError = entry.hasError;
556
+ computed.initialized = true;
557
+ computed.flags = Mutable;
558
+ computed.renderRevision = computed.renderRevision + 1 | 0;
559
+ return true;
560
+ }
561
+ function hasSubscribers(readable) {
562
+ return foreignAdapter.getNodeForReadable(readable)?.subs !== void 0;
563
+ }
564
+ function hasActiveSubscriber() {
565
+ return activeSub !== void 0;
566
+ }
567
+ function getBatchDepth() {
568
+ return batchDepth;
569
+ }
570
+ function updateSource(source) {
571
+ source.flags = Mutable;
572
+ return !Object.is(source.currentValue, source.currentValue = source.pendingValue);
573
+ }
574
+ function readComputed(computed, track = true) {
575
+ if (computed.foreignDependent) refreshForeignDependencies(computed, /* @__PURE__ */ new Set());
576
+ if (computed.flags & RecursedCheck) throw new Error("Computed cycle detected");
577
+ const flags = computed.flags;
578
+ if (flags & Dirty || flags & Pending && (computed.deps !== void 0 && checkDirty(computed.deps, computed) || (computed.flags = flags & -33, false))) {
579
+ if (updateComputed(computed) && computed.subs !== void 0) shallowPropagate(computed.subs);
580
+ } else if (!flags) updateComputed(computed);
581
+ if (track && activeSub !== void 0) {
582
+ linkNode(computed, activeSub, cycle);
583
+ if (activeSub.kind === "computed" && computed.foreignDependent) activeSub.foreignDependent = true;
584
+ if (activeSub.kind === "effect" && computed.foreignDependent) activateForeignDependencies(computed, /* @__PURE__ */ new Set());
585
+ }
586
+ if (computed.hasError) throw computed.error;
587
+ return computed.value;
588
+ }
589
+ function refreshForeignDependencies(node, visited) {
590
+ if (visited.has(node)) return;
591
+ visited.add(node);
592
+ for (let dependency = node.deps; dependency !== void 0; dependency = dependency.nextDep) {
593
+ const dep = dependency.dep;
594
+ if (dep.kind === "external") foreignAdapter.observeForeignRevision(dep, dep.protocol.getRevision());
595
+ else if (dep.kind === "computed" && dep.foreignDependent) refreshForeignDependencies(dep, visited);
596
+ }
597
+ }
598
+ function activateForeignDependencies(node, visited) {
599
+ if (visited.has(node)) return;
600
+ visited.add(node);
601
+ let dependency = node.deps;
602
+ while (dependency !== void 0) {
603
+ const dep = dependency.dep;
604
+ if (dep.kind === "external") foreignAdapter.activateForeignNode(dep);
605
+ else if (dep.kind === "computed") activateForeignDependencies(dep, visited);
606
+ dependency = dependency.nextDep;
607
+ }
608
+ }
609
+ function updateComputed(computed) {
610
+ if (computed.flags & HasChildEffect) disposeChildEffects(computed);
611
+ computed.depsTail = void 0;
612
+ computed.flags = 5;
613
+ const previous = activeSub;
614
+ activeSub = computed;
615
+ let changed = !computed.initialized;
616
+ const hadError = computed.hasError;
617
+ const hadForeignDependencies = computed.foreignDependent;
618
+ const previousValue = computed.value;
619
+ computed.foreignDependent = false;
620
+ try {
621
+ cycle += 1;
622
+ try {
623
+ computed.value = withGraphOwner(computed.getter);
624
+ computed.error = void 0;
625
+ computed.hasError = false;
626
+ } catch (error) {
627
+ computed.value = void 0;
628
+ computed.error = error;
629
+ computed.hasError = true;
630
+ }
631
+ computed.initialized = true;
632
+ changed = changed || hadError || computed.hasError || !Object.is(previousValue, computed.value);
633
+ if (changed && computed.renderRevision !== void 0) computed.renderRevision = computed.renderRevision + 1 | 0;
634
+ return changed;
635
+ } finally {
636
+ activeSub = previous;
637
+ computed.flags &= -5;
638
+ purgeDeps(computed);
639
+ recomputeForeignDependencies(computed);
640
+ if (hadForeignDependencies !== computed.foreignDependent) updateForeignDependencyAncestors(computed);
641
+ if (computed.foreignDependent && computed.subs !== void 0 && isWatchedByEffect(computed, /* @__PURE__ */ new Set())) activateForeignDependencies(computed, /* @__PURE__ */ new Set());
642
+ }
643
+ }
644
+ function isWatchedByEffect(node, visited) {
645
+ if (visited.has(node)) return false;
646
+ visited.add(node);
647
+ for (let link = node.subs; link !== void 0; link = link.nextSub) {
648
+ const subscriber = link.sub;
649
+ if (subscriber.kind === "effect" ? subscriber.flags !== None : isWatchedByEffect(subscriber, visited)) return true;
650
+ }
651
+ return false;
652
+ }
653
+ function disposeChildEffects(sub) {
654
+ let link = sub.depsTail;
655
+ while (link !== void 0) {
656
+ const previous = link.prevDep;
657
+ if (link.dep.kind === "effect") unlinkNode(link, sub);
658
+ link = previous;
659
+ }
660
+ }
661
+ function recomputeForeignDependencies(computed) {
662
+ let dependency = computed.deps;
663
+ let foreignDependent = false;
664
+ while (dependency !== void 0) {
665
+ const dep = dependency.dep;
666
+ if (dep.kind === "external" || dep.kind === "computed" && dep.foreignDependent) {
667
+ foreignDependent = true;
668
+ break;
669
+ }
670
+ dependency = dependency.nextDep;
671
+ }
672
+ computed.foreignDependent = foreignDependent;
673
+ }
674
+ function updateForeignDependencyAncestors(computed) {
675
+ let link = computed.subs;
676
+ while (link !== void 0) {
677
+ const subscriber = link.sub;
678
+ if (subscriber.kind === "computed") {
679
+ const computedSubscriber = subscriber;
680
+ const wasForeignDependent = computedSubscriber.foreignDependent;
681
+ recomputeForeignDependencies(computedSubscriber);
682
+ if (wasForeignDependent !== computedSubscriber.foreignDependent) updateForeignDependencyAncestors(computedSubscriber);
683
+ }
684
+ link = link.nextSub;
685
+ }
686
+ }
687
+ function runEffect(effect) {
688
+ const flags = effect.flags;
689
+ if (flags & Dirty || flags & Pending && effect.deps !== void 0 && checkDirty(effect.deps, effect)) {
690
+ if (flags & HasChildEffect) disposeChildEffects(effect);
691
+ if (effect.cleanup !== void 0) {
692
+ try {
693
+ runCleanup(effect);
694
+ } catch (error) {
695
+ reportFailure(error);
696
+ }
697
+ if (!effect.flags) return;
698
+ }
699
+ effect.depsTail = void 0;
700
+ effect.flags = 6;
701
+ const previous = activeSub;
702
+ activeSub = effect;
703
+ try {
704
+ cycle += 1;
705
+ runDepth += 1;
706
+ const cleanup = withGraphOwner(effect.fn);
707
+ effect.cleanup = typeof cleanup === "function" ? cleanup : void 0;
708
+ if (!effect.flags && effect.cleanup !== void 0) runCleanup(effect);
709
+ } finally {
710
+ runDepth -= 1;
711
+ activeSub = previous;
712
+ effect.flags &= -5;
713
+ settleDeps(effect);
714
+ }
715
+ } else if (effect.deps !== void 0) effect.flags = Watching | flags & HasChildEffect;
716
+ }
717
+ function settleDeps(effect) {
718
+ if (effect.flags === None) effect.depsTail = void 0;
719
+ purgeDeps(effect);
720
+ }
721
+ function flush() {
722
+ try {
723
+ while (flushIndex < queuedLength) {
724
+ const effect = queue[flushIndex];
725
+ queue[flushIndex++] = void 0;
726
+ try {
727
+ runEffect(effect);
728
+ } catch (error) {
729
+ reportFailure(error);
730
+ }
731
+ }
732
+ } finally {
733
+ while (flushIndex < queuedLength) {
734
+ const effect = queue[flushIndex];
735
+ queue[flushIndex++] = void 0;
736
+ effect.flags |= 10;
737
+ }
738
+ flushIndex = 0;
739
+ queuedLength = 0;
740
+ }
741
+ }
742
+ function reportFailure(error) {
743
+ try {
744
+ console.error("react-fine-grained-signals: an effect() callback threw; the error is contained and reported here so this flush can finish.", { cause: error });
745
+ } catch {}
746
+ try {
747
+ const report = globalThis.reportError;
748
+ if (typeof report === "function") report.call(globalThis, error);
749
+ } catch {}
750
+ }
751
+ function disposeDeps(sub) {
752
+ let depLink = sub.depsTail;
753
+ while (depLink !== void 0) {
754
+ const previous = depLink.prevDep;
755
+ unlinkNode(depLink, sub);
756
+ depLink = previous;
757
+ }
758
+ }
759
+ function purgeDeps(sub) {
760
+ const tail = sub.depsTail;
761
+ let depLink = tail === void 0 ? sub.deps : tail.nextDep;
762
+ while (depLink !== void 0) depLink = unlinkNode(depLink, sub);
763
+ }
764
+ function runCleanup(effect) {
765
+ const cleanup = effect.cleanup;
766
+ effect.cleanup = void 0;
767
+ const previous = activeSub;
768
+ activeSub = void 0;
769
+ try {
770
+ return withSynchronousExecutionOwner(UNTRACKED_OWNER, cleanup);
771
+ } finally {
772
+ activeSub = previous;
773
+ }
774
+ }
775
+ function disposeEffect(effect) {
776
+ effect.flags = None;
777
+ disposeDeps(effect);
778
+ const ownerLink = effect.subs;
779
+ if (ownerLink !== void 0) unlinkNode(ownerLink, ownerLink.sub);
780
+ if (effect.cleanup !== void 0) try {
781
+ runCleanup(effect);
782
+ } catch (error) {
783
+ reportFailure(error);
784
+ }
785
+ }
786
+ function detachedEffect(fn) {
787
+ return effect(fn, true);
788
+ }
789
+ function effect(fn, detached) {
790
+ const node = makeNode("effect", 6, {
791
+ fn,
792
+ cleanup: void 0
793
+ });
794
+ const dispose = () => disposeEffect(node);
795
+ const previous = activeSub;
796
+ if (!detached) {
797
+ const owner = executionContext.owner;
798
+ if (previous === void 0 && speculativeChildren === void 0 && (isGraphExecutionOwner(owner) || isRenderExecutionOwner(owner)) && owner.runtimeToken !== runtimeToken) owner.own?.(dispose);
799
+ else adopt(dispose, node);
800
+ }
801
+ try {
802
+ activeSub = node;
803
+ runDepth += 1;
804
+ try {
805
+ const cleanup = withGraphOwner(fn);
806
+ node.cleanup = typeof cleanup === "function" ? cleanup : void 0;
807
+ } catch (error) {
808
+ node.cleanup = void 0;
809
+ reportFailure(error);
810
+ } finally {
811
+ runDepth -= 1;
812
+ activeSub = previous;
813
+ node.flags &= -5;
814
+ purgeDeps(node);
815
+ }
816
+ } catch (error) {
817
+ reportFailure(error);
818
+ }
819
+ if (!runDepth && !batchDepth) {
820
+ if (node.flags & 128) runEffect(node);
821
+ if (queuedLength) flush();
822
+ }
823
+ return dispose;
824
+ }
825
+ function adopt(disposeChild, child = makeNode("effect", Watching, { cleanup: disposeChild })) {
826
+ if (activeSub !== void 0) {
827
+ linkNode(child, activeSub, 0);
828
+ activeSub.flags |= HasChildEffect;
829
+ } else speculativeChildren?.push(disposeChild);
830
+ }
831
+ function evaluateSpeculatively(computed, entry) {
832
+ const previousSub = activeSub;
833
+ const previousChildren = speculativeChildren;
834
+ const children = [];
835
+ const getter = computed.getter;
836
+ activeSub = void 0;
837
+ speculativeChildren = children;
838
+ try {
839
+ entry.value = getter();
840
+ } catch (error) {
841
+ entry.error = error;
842
+ entry.hasError = true;
843
+ } finally {
844
+ activeSub = previousSub;
845
+ speculativeChildren = previousChildren;
846
+ for (const disposeChild of children) disposeChild();
847
+ }
848
+ return children.length > 0;
849
+ }
850
+ function batch(fn) {
851
+ batchDepth += 1;
852
+ try {
853
+ return fn();
854
+ } finally {
855
+ batchDepth -= 1;
856
+ if (!batchDepth) flush();
857
+ }
858
+ }
859
+ function untracked(fn) {
860
+ const previous = activeSub;
861
+ const previousAttempt = activeRenderAttempt;
862
+ activeSub = void 0;
863
+ activeRenderAttempt = void 0;
864
+ try {
865
+ return withSynchronousExecutionOwner(UNTRACKED_OWNER, fn);
866
+ } finally {
867
+ activeRenderAttempt = previousAttempt;
868
+ activeSub = previous;
869
+ }
870
+ }
871
+ const brandDescriptor = () => ({
872
+ value: 1,
873
+ enumerable: false,
874
+ writable: false,
875
+ configurable: false
876
+ });
877
+ function registerHelperBrand(value) {
878
+ Object.defineProperty(value, SIGNAL_BRAND, brandDescriptor());
879
+ }
880
+ function inlineWrite(node, value) {
881
+ if (!Object.is(node.pendingValue, node.pendingValue = value)) {
882
+ if (node.renderRevision !== void 0) node.renderRevision = node.renderRevision + 1 | 0;
883
+ node.flags = 17;
884
+ const subscribers = node.subs;
885
+ if (subscribers !== void 0) {
886
+ propagate(subscribers, !!runDepth);
887
+ if (!batchDepth) flush();
888
+ }
889
+ }
890
+ }
891
+ function inlineDeepSignalWrite(node, value) {
892
+ deepWatchedNodes.delete(node);
893
+ inlineWrite(node, value);
894
+ }
895
+ class HelperBrandSignal {
896
+ #node;
897
+ constructor(node, branded = true) {
898
+ this.#node = node;
899
+ if (branded) registerHelperBrand(this);
900
+ attachProtocol(this, node);
901
+ }
902
+ get value() {
903
+ const node = this.#node;
904
+ const currentOwner = executionContext.owner;
905
+ if (currentOwner === void 0) {
906
+ const value = readSource(node);
907
+ if (activeRenderCollector !== void 0) trackRenderDependency(getRenderDependency(this, node));
908
+ return value;
909
+ }
910
+ if (currentOwner === graphOwner) return readSource(node);
911
+ const attempt = activeRenderAttempt;
912
+ if (attempt !== void 0 && isRenderExecutionOwner(currentOwner) && currentOwner.runtimeToken === runtimeToken && renderAdapter !== void 0) {
913
+ foreignAdapter.observeRevision(node);
914
+ return renderAdapter.readSource(this, node, attempt);
915
+ }
916
+ if (currentOwner === UNTRACKED_OWNER) return readSourceUntracked(node);
917
+ if (isForeignOwner(currentOwner)) {
918
+ const value = readSourceUntracked(node);
919
+ foreignAdapter.publishForeignReadable(this, node, currentOwner);
920
+ return value;
921
+ }
922
+ return readSource(node);
923
+ }
924
+ set value(value) {
925
+ inlineWrite(this.#node, value);
926
+ }
927
+ peek() {
928
+ return this.#node.pendingValue;
929
+ }
930
+ }
931
+ /** Internal DeepSignal root and per-property version sources have a distinct
932
+ * write entry point because their liveness markers must be cleared before any
933
+ * write, including an Object.is-equal write. Ordinary branded signals never
934
+ * pay that bookkeeping cost. */
935
+ class DeepSignalRuntimeSource {
936
+ #node;
937
+ constructor(node) {
938
+ this.#node = node;
939
+ attachProtocol(this, node);
940
+ }
941
+ get value() {
942
+ const node = this.#node;
943
+ const currentOwner = executionContext.owner;
944
+ if (currentOwner === void 0) {
945
+ const value = readSource(node);
946
+ if (activeRenderCollector !== void 0) trackRenderDependency(getRenderDependency(this, node));
947
+ return value;
948
+ }
949
+ if (currentOwner === graphOwner) return readSource(node);
950
+ const attempt = activeRenderAttempt;
951
+ if (attempt !== void 0 && isRenderExecutionOwner(currentOwner) && currentOwner.runtimeToken === runtimeToken && renderAdapter !== void 0) {
952
+ foreignAdapter.observeRevision(node);
953
+ return renderAdapter.readSource(this, node, attempt);
954
+ }
955
+ if (currentOwner === UNTRACKED_OWNER) return readSourceUntracked(node);
956
+ if (isForeignOwner(currentOwner)) {
957
+ const value = readSourceUntracked(node);
958
+ foreignAdapter.publishForeignReadable(this, node, currentOwner);
959
+ return value;
960
+ }
961
+ return readSource(node);
962
+ }
963
+ set value(value) {
964
+ inlineDeepSignalWrite(this.#node, value);
965
+ }
966
+ peek() {
967
+ return this.#node.pendingValue;
968
+ }
969
+ }
970
+ function createBrandedSignal(makeReadable, initialValue) {
971
+ return new makeReadable(makeNode("source", Mutable, {
972
+ currentValue: initialValue,
973
+ pendingValue: initialValue
974
+ }));
975
+ }
976
+ const signalClassBrandHelper = (initialValue) => createBrandedSignal(HelperBrandSignal, initialValue);
977
+ class HelperBrandComputed {
978
+ #node;
979
+ constructor(node, branded = true) {
980
+ this.#node = node;
981
+ if (branded) registerHelperBrand(this);
982
+ attachProtocol(this, node);
983
+ }
984
+ get value() {
985
+ const node = this.#node;
986
+ const currentOwner = executionContext.owner;
987
+ if (currentOwner === graphOwner) return readComputed(node);
988
+ const attempt = activeRenderAttempt;
989
+ if (attempt !== void 0 && isRenderExecutionOwner(currentOwner) && currentOwner.runtimeToken === runtimeToken && renderAdapter !== void 0) {
990
+ foreignAdapter.observeRevision(node);
991
+ return renderAdapter.readComputed(this, node, attempt);
992
+ }
993
+ const owner = currentOwner;
994
+ const foreign = owner !== void 0 && isForeignOwner(owner);
995
+ try {
996
+ return readComputed(node, owner !== UNTRACKED_OWNER && !foreign);
997
+ } finally {
998
+ if (owner === void 0) {
999
+ if (activeRenderCollector !== void 0) trackRenderDependency(getRenderDependency(this, node));
1000
+ } else if (foreign) foreignAdapter.publishForeignReadable(this, node, owner);
1001
+ }
1002
+ }
1003
+ peek() {
1004
+ return untracked(() => readComputed(this.#node));
1005
+ }
1006
+ }
1007
+ function createBrandedComputed(makeReadable, getter) {
1008
+ return new makeReadable(makeNode("computed", None, {
1009
+ getter,
1010
+ value: void 0,
1011
+ error: void 0,
1012
+ hasError: false,
1013
+ initialized: false
1014
+ }));
1015
+ }
1016
+ const computedClassBrandHelper = (getter) => createBrandedComputed(HelperBrandComputed, getter);
1017
+ function hasBrandAndPeek(value) {
1018
+ if (typeof value !== "object" || value === null) return false;
1019
+ const version = Reflect.get(value, SIGNAL_BRAND);
1020
+ return typeof version === "number" && version >= 1 && typeof Reflect.get(value, "peek") === "function";
1021
+ }
1022
+ const isSignalBrandHelper = hasBrandAndPeek;
1023
+ function createDeepSignal(initialValue) {
1024
+ const node = makeNode("source", Mutable, {
1025
+ currentValue: initialValue,
1026
+ pendingValue: initialValue
1027
+ });
1028
+ const readable = new DeepSignalRuntimeSource(node);
1029
+ deepSignalNodes.add(node);
1030
+ return readable;
1031
+ }
1032
+ function createDeepSignalVersion(initialValue) {
1033
+ const node = makeNode("source", Mutable, {
1034
+ currentValue: initialValue,
1035
+ pendingValue: initialValue
1036
+ });
1037
+ const readable = new DeepSignalRuntimeSource(node);
1038
+ deepSignalNodes.add(node);
1039
+ return readable;
1040
+ }
1041
+ function markDeepSignalWatched(readable) {
1042
+ const node = foreignAdapter.getNodeForReadable(readable);
1043
+ if (node !== void 0) deepWatchedNodes.add(node);
1044
+ }
1045
+ function hasDeepSignalSubscribers(readable) {
1046
+ const node = foreignAdapter.getNodeForReadable(readable);
1047
+ return node !== void 0 && (deepWatchedNodes.has(node) || deepSignalNodes.has(node) && hasSubscribers(readable));
1048
+ }
1049
+ function getRenderVersion(readable) {
1050
+ return foreignAdapter.getReadableRevision(readable);
1051
+ }
1052
+ function subscribeReadables(readables, notify) {
1053
+ let initial = true;
1054
+ return detachedEffect(() => {
1055
+ for (const readable of readables) try {
1056
+ readable.value;
1057
+ } catch {}
1058
+ if (initial) initial = false;
1059
+ else notify();
1060
+ });
1061
+ }
1062
+ return {
1063
+ runtimeToken,
1064
+ graphOwner,
1065
+ configureRenderAdapter,
1066
+ withRenderAttempt,
1067
+ pushRenderAttempt,
1068
+ getActiveRenderAttempt,
1069
+ getNodeForReadable,
1070
+ getReadableRevision,
1071
+ getDependencyRevision,
1072
+ isComputedClean,
1073
+ promoteComputed,
1074
+ evaluateSpeculatively,
1075
+ adopt,
1076
+ hasSubscribers,
1077
+ hasActiveSubscriber,
1078
+ getBatchDepth,
1079
+ signal: signalClassBrandHelper,
1080
+ computed: computedClassBrandHelper,
1081
+ effect,
1082
+ detachedEffect,
1083
+ batch,
1084
+ untracked,
1085
+ SIGNAL_BRAND,
1086
+ isSignal: isSignalBrandHelper,
1087
+ createDeepSignal,
1088
+ createDeepSignalVersion,
1089
+ markDeepSignalWatched,
1090
+ hasDeepSignalSubscribers,
1091
+ getRenderVersion,
1092
+ subscribeReadables
1093
+ };
1094
+ }
1095
+ //#endregion
1096
+ //#region src/core/render-runtime.mts
1097
+ function createAlienDerivedRenderAdapter(core) {
1098
+ let activeSpeculativeComputed;
1099
+ const readablesByNode = /* @__PURE__ */ new WeakMap();
1100
+ const collectorFrames = [];
1101
+ let baseRenderCollector;
1102
+ function addDependency(attempt, dependency, revision) {
1103
+ const node = core.getNodeForReadable(dependency);
1104
+ if (node !== void 0) readablesByNode.set(node, dependency);
1105
+ if (activeSpeculativeComputed !== void 0) activeSpeculativeComputed.dependencies.set(dependency, revision);
1106
+ else attempt.add(dependency, revision);
1107
+ }
1108
+ function readSource(readable, node, attempt) {
1109
+ addDependency(attempt, readable, node.renderRevision);
1110
+ return node.pendingValue;
1111
+ }
1112
+ function readComputed(readable, node, attempt) {
1113
+ if (activeSpeculativeComputed !== void 0) {
1114
+ const restoreAttempt = core.pushRenderAttempt(void 0);
1115
+ try {
1116
+ return readable.value;
1117
+ } finally {
1118
+ addDependency(attempt, readable, node.renderRevision);
1119
+ restoreAttempt();
1120
+ }
1121
+ }
1122
+ addDependency(attempt, readable, node.renderRevision);
1123
+ const cache = attempt.computedCache;
1124
+ let entry = cache.get(node);
1125
+ if (entry !== void 0 && isEntryCurrent(entry)) {
1126
+ if (entry.hasError) throw entry.error;
1127
+ return entry.value;
1128
+ }
1129
+ if (core.isComputedClean(node)) {
1130
+ if (node.hasError) throw node.error;
1131
+ return node.value;
1132
+ }
1133
+ entry = {
1134
+ dependencies: /* @__PURE__ */ new Map(),
1135
+ value: void 0,
1136
+ error: void 0,
1137
+ hasError: false,
1138
+ canPromote: false
1139
+ };
1140
+ cache.set(node, entry);
1141
+ const previous = activeSpeculativeComputed;
1142
+ activeSpeculativeComputed = entry;
1143
+ const deepReadEpoch = attempt.speculativeDeepReadEpoch;
1144
+ let createdEffects = false;
1145
+ try {
1146
+ createdEffects = core.evaluateSpeculatively(node, entry);
1147
+ } finally {
1148
+ activeSpeculativeComputed = previous;
1149
+ entry.canPromote = !createdEffects && deepReadEpoch === attempt.speculativeDeepReadEpoch;
1150
+ }
1151
+ if (entry.hasError) throw entry.error;
1152
+ return entry.value;
1153
+ }
1154
+ function isEntryCurrent(entry) {
1155
+ for (const [dependency, revision] of entry.dependencies) {
1156
+ const node = core.getNodeForReadable(dependency);
1157
+ if (node === void 0) {
1158
+ if (core.getDependencyRevision(dependency) !== revision) return false;
1159
+ } else if (node.renderRevision !== revision || node.kind === "computed" && !core.isComputedClean(node)) return false;
1160
+ }
1161
+ return true;
1162
+ }
1163
+ core.configureRenderAdapter({
1164
+ readSource,
1165
+ readComputed
1166
+ });
1167
+ function createRenderAttempt() {
1168
+ return {
1169
+ dependencies: /* @__PURE__ */ new Map(),
1170
+ computedCache: /* @__PURE__ */ new Map(),
1171
+ speculativeDeepReadEpoch: 0,
1172
+ add(dependency, revision) {
1173
+ if (!this.dependencies.has(dependency)) this.dependencies.set(dependency, revision);
1174
+ },
1175
+ markSpeculativeDeepRead() {
1176
+ this.speculativeDeepReadEpoch += 1;
1177
+ }
1178
+ };
1179
+ }
1180
+ function createRenderOwner(attempt, scopePolicy = "managed") {
1181
+ return {
1182
+ version: 2,
1183
+ kind: "render",
1184
+ scopePolicy,
1185
+ runtimeToken: core.runtimeToken,
1186
+ add(protocol, revision) {
1187
+ addDependency(attempt, protocol, revision);
1188
+ },
1189
+ isSpeculative() {
1190
+ return activeSpeculativeComputed !== void 0;
1191
+ },
1192
+ markSpeculativeDeepRead() {
1193
+ attempt.markSpeculativeDeepRead();
1194
+ },
1195
+ own: core.adopt
1196
+ };
1197
+ }
1198
+ function pushRenderScope(attempt, scopePolicy = "managed") {
1199
+ const parent = executionContext.owner;
1200
+ if (isRenderExecutionOwner(parent) && !(parent.scopePolicy === "managed" && scopePolicy === "managed")) parent.closeScope?.();
1201
+ const restoreAttempt = core.pushRenderAttempt(attempt);
1202
+ const owner = createRenderOwner(attempt, scopePolicy);
1203
+ const restoreOwner = pushExecutionOwner(owner);
1204
+ const collector = { add(dependency, revision) {
1205
+ addDependency(attempt, dependency, revision);
1206
+ } };
1207
+ if (collectorFrames.length === 0) baseRenderCollector = activeRenderCollector;
1208
+ const frame = {
1209
+ collector,
1210
+ active: true
1211
+ };
1212
+ collectorFrames.push(frame);
1213
+ setActiveRenderCollector(collector);
1214
+ let active = true;
1215
+ const restoreScope = () => {
1216
+ if (!active) return;
1217
+ active = false;
1218
+ frame.active = false;
1219
+ while (collectorFrames.at(-1)?.active === false) collectorFrames.pop();
1220
+ setActiveRenderCollector(collectorFrames.at(-1)?.collector ?? baseRenderCollector);
1221
+ if (collectorFrames.length === 0) baseRenderCollector = void 0;
1222
+ restoreAttempt();
1223
+ restoreOwner();
1224
+ };
1225
+ owner.closeScope = restoreScope;
1226
+ return restoreScope;
1227
+ }
1228
+ function withRenderScope(attempt, callback, scopePolicy = "managed") {
1229
+ const restore = pushRenderScope(attempt, scopePolicy);
1230
+ try {
1231
+ return callback();
1232
+ } finally {
1233
+ restore();
1234
+ }
1235
+ }
1236
+ function promoteRenderAttempt(attempt) {
1237
+ for (const [node, entry] of attempt.computedCache) {
1238
+ if (!entry.canPromote) continue;
1239
+ const readable = readablesByNode.get(node);
1240
+ if (readable === void 0 || !core.promoteComputed(readable, node, entry)) return false;
1241
+ }
1242
+ return true;
1243
+ }
1244
+ function settleRenderAttempt(attempt) {
1245
+ let stable = true;
1246
+ for (const [dependency, revision] of attempt.dependencies) {
1247
+ const currentRevision = getRenderVersion(dependency);
1248
+ if (currentRevision === revision) continue;
1249
+ const node = core.getNodeForReadable(dependency);
1250
+ const entry = node === void 0 ? void 0 : attempt.computedCache.get(node);
1251
+ if (node === void 0 || entry === void 0 || node.initialized !== true || entry.hasError !== node.hasError || !entry.hasError && !Object.is(entry.value, node.value)) {
1252
+ stable = false;
1253
+ continue;
1254
+ }
1255
+ attempt.dependencies.set(dependency, currentRevision);
1256
+ }
1257
+ return stable;
1258
+ }
1259
+ function getRenderVersion(readable) {
1260
+ if (isReadableProtocol(readable) || core.getNodeForReadable(readable) !== void 0 || Reflect.get(readable, READABLE_INTEROP_V1$1) !== void 0) return core.getDependencyRevision(readable);
1261
+ const getVersion = Reflect.get(readable, "getRenderVersion");
1262
+ if (typeof getVersion === "function") return getVersion.call(readable);
1263
+ throw new TypeError("Unknown render dependency");
1264
+ }
1265
+ function hasActiveRenderOwner() {
1266
+ return isRenderExecutionOwner(executionContext.owner);
1267
+ }
1268
+ function isSpeculative() {
1269
+ const owner = executionContext.owner;
1270
+ if (isGraphExecutionOwner(owner) || owner === UNTRACKED_OWNER) return false;
1271
+ return isRenderExecutionOwner(owner) && (owner.isSpeculative?.() === true || activeSpeculativeComputed !== void 0);
1272
+ }
1273
+ function markSpeculativeDeepRead() {
1274
+ const attempt = core.getActiveRenderAttempt();
1275
+ if (attempt !== void 0) attempt.markSpeculativeDeepRead();
1276
+ else if (isRenderExecutionOwner(executionContext.owner)) executionContext.owner.markSpeculativeDeepRead?.();
1277
+ }
1278
+ function subscribeReadables(readables, notify) {
1279
+ let initial = true;
1280
+ return core.detachedEffect(() => {
1281
+ for (const readable of readables) try {
1282
+ readable.value;
1283
+ } catch {}
1284
+ if (initial) initial = false;
1285
+ else notify();
1286
+ });
1287
+ }
1288
+ function captureRenderSnapshot(readable) {
1289
+ const attempt = createRenderAttempt();
1290
+ let value;
1291
+ withRenderScope(attempt, () => {
1292
+ value = readable.value;
1293
+ });
1294
+ return {
1295
+ value,
1296
+ dependencies: attempt.dependencies,
1297
+ attempt
1298
+ };
1299
+ }
1300
+ function getExecutionOwner() {
1301
+ return executionContext.owner;
1302
+ }
1303
+ return {
1304
+ createRenderAttempt,
1305
+ createRenderOwner,
1306
+ pushRenderScope,
1307
+ withRenderScope,
1308
+ promoteRenderAttempt,
1309
+ settleRenderAttempt,
1310
+ getRenderVersion,
1311
+ hasActiveRenderOwner,
1312
+ isSpeculative,
1313
+ markSpeculativeDeepRead,
1314
+ subscribeReadables,
1315
+ captureRenderSnapshot,
1316
+ getExecutionOwner
1317
+ };
1318
+ }
1319
+ //#endregion
1320
+ //#region src/core/reactive-runtime.ts
1321
+ /** Builds one Alien-derived graph and its separate owner/render adapters. */
1322
+ function createReactiveRuntime() {
1323
+ const graph = createAlienDerivedRuntime();
1324
+ const render = createAlienDerivedRenderAdapter(graph);
1325
+ return {
1326
+ runtimeToken: graph.runtimeToken,
1327
+ graphOwner: graph.graphOwner,
1328
+ getNodeForReadable: graph.getNodeForReadable,
1329
+ renderAdapter: render,
1330
+ signal: graph.signal,
1331
+ computed: graph.computed,
1332
+ effect: graph.effect,
1333
+ detachedEffect: graph.detachedEffect,
1334
+ batch: graph.batch,
1335
+ untracked: graph.untracked,
1336
+ hasSubscribers: graph.hasSubscribers,
1337
+ hasActiveSubscriber: graph.hasActiveSubscriber,
1338
+ getBatchDepth: graph.getBatchDepth,
1339
+ createDeepSignal: graph.createDeepSignal,
1340
+ createDeepSignalVersion: graph.createDeepSignalVersion,
1341
+ markDeepSignalWatched: graph.markDeepSignalWatched,
1342
+ hasDeepSignalSubscribers: graph.hasDeepSignalSubscribers,
1343
+ isSpeculative: render.isSpeculative,
1344
+ markSpeculativeDeepRead: render.markSpeculativeDeepRead
1345
+ };
1346
+ }
1347
+ //#endregion
1348
+ //#region src/core/core-runtime.ts
1349
+ /** The single graph used by this package's public signal APIs. */
1350
+ const coreRuntime = createReactiveRuntime();
1351
+ //#endregion
1352
+ export { untrackedRender as a, getSharedInteropContext as c, UNTRACKED_OWNER as d, executionContext as f, notifyListener as i, isInteropSpeculative as l, SIGNAL_BRAND as n, attachReadableInterop as o, hasActiveRenderCollector as r, getReadableInterop as s, coreRuntime as t, markInteropSpeculativeDeepRead as u };
1353
+
1354
+ //# sourceMappingURL=core-runtime-2jSE9Tz5.js.map