@solidjs/signals 2.0.0-rc.2 → 2.0.0-rc.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev-shared.js +6505 -0
- package/dist/dev.attribution.js +3484 -0
- package/dist/dev.js +10227 -9508
- package/dist/observe/affects-marks.js +86 -0
- package/dist/observe/affects.js +112 -0
- package/dist/observe/attribution.js +7 -0
- package/dist/observe/boundaries.js +696 -0
- package/dist/observe/core/action.js +182 -0
- package/dist/observe/core/async.js +824 -0
- package/dist/observe/core/attribution-costs.js +66 -0
- package/dist/observe/core/attribution-feedback.js +280 -0
- package/dist/observe/core/attribution-hooks.js +83 -0
- package/dist/observe/core/attribution-queries.js +43 -0
- package/dist/observe/core/attribution.js +3079 -0
- package/dist/observe/core/constants.js +269 -0
- package/dist/observe/core/context.js +63 -0
- package/dist/observe/core/copies.js +10 -0
- package/dist/observe/core/core.js +1707 -0
- package/dist/observe/core/dev.js +394 -0
- package/dist/observe/core/effect.js +193 -0
- package/dist/observe/core/error-hooks.js +71 -0
- package/dist/observe/core/error.js +82 -0
- package/dist/observe/core/external.js +97 -0
- package/dist/observe/core/graph.js +162 -0
- package/dist/observe/core/heap.js +124 -0
- package/dist/observe/core/identities.js +62 -0
- package/dist/observe/core/invariants.js +12 -0
- package/dist/observe/core/lanes.js +972 -0
- package/dist/observe/core/owner.js +371 -0
- package/dist/observe/core/scheduler.js +1157 -0
- package/dist/observe/core/truth.js +47 -0
- package/dist/observe/core/verdict.js +470 -0
- package/dist/observe/deferred.js +186 -0
- package/dist/observe/flatten.js +79 -0
- package/dist/observe/from.js +248 -0
- package/dist/observe/index.js +71 -0
- package/dist/observe/map.js +593 -0
- package/dist/observe/reveal.js +212 -0
- package/dist/observe/signals.js +717 -0
- package/dist/observe/store/affects.js +142 -0
- package/dist/observe/store/edges.js +39 -0
- package/dist/observe/store/hooks.js +16 -0
- package/dist/observe/store/index.js +47 -0
- package/dist/observe/store/optimistic.js +713 -0
- package/dist/observe/store/projection.js +345 -0
- package/dist/observe/store/reconcile.js +281 -0
- package/dist/observe/store/store.js +2127 -0
- package/dist/observe/store/storePath.js +103 -0
- package/dist/observe/store/target.js +46 -0
- package/dist/observe/store/types.js +83 -0
- package/dist/observe/store/utils.js +1063 -0
- package/dist/prod/affects-marks.js +86 -0
- package/dist/prod/affects.js +98 -112
- package/dist/prod/attribution.js +45 -0
- package/dist/prod/boundaries.js +578 -468
- package/dist/prod/core/action.js +92 -59
- package/dist/prod/core/async.js +522 -336
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +168 -44
- package/dist/prod/core/context.js +12 -16
- package/dist/prod/core/copies.js +10 -0
- package/dist/prod/core/core.js +1345 -627
- package/dist/prod/core/dev.js +123 -1
- package/dist/prod/core/effect.js +113 -80
- package/dist/prod/core/error-hooks.js +71 -0
- package/dist/prod/core/error.js +18 -4
- package/dist/prod/core/external.js +6 -7
- package/dist/prod/core/graph.js +119 -72
- package/dist/prod/core/heap.js +85 -109
- package/dist/prod/core/identities.js +62 -0
- package/dist/prod/core/invariants.js +1 -32
- package/dist/prod/core/lanes.js +931 -132
- package/dist/prod/core/owner.js +192 -129
- package/dist/prod/core/scheduler.js +948 -642
- package/dist/prod/core/truth.js +47 -0
- package/dist/prod/core/verdict.js +409 -420
- package/dist/prod/deferred.js +184 -0
- package/dist/prod/flatten.js +77 -0
- package/dist/prod/from.js +248 -0
- package/dist/prod/index.js +40 -16
- package/dist/prod/map.js +481 -211
- package/dist/prod/reveal.js +212 -0
- package/dist/prod/signals.js +401 -84
- package/dist/prod/store/affects.js +142 -0
- package/dist/prod/store/edges.js +39 -0
- package/dist/prod/store/hooks.js +16 -0
- package/dist/prod/store/index.js +27 -18
- package/dist/prod/store/optimistic.js +707 -0
- package/dist/prod/store/projection.js +331 -0
- package/dist/prod/store/reconcile.js +281 -0
- package/dist/prod/store/store.js +1952 -267
- package/dist/prod/store/storePath.js +1 -1
- package/dist/prod/store/target.js +43 -0
- package/dist/prod/store/types.js +83 -0
- package/dist/prod/store/utils.js +997 -138
- package/dist/types/affects-marks.d.ts +14 -0
- package/dist/types/affects.d.ts +12 -30
- package/dist/types/attribution.d.ts +19 -0
- package/dist/types/attribution.prod.d.ts +22 -0
- package/dist/types/boundaries.d.ts +99 -124
- package/dist/types/carved.d.ts +1 -0
- package/dist/types/core/action.d.ts +23 -9
- package/dist/types/core/async.d.ts +34 -6
- package/dist/types/core/attribution-costs.d.ts +35 -0
- package/dist/types/core/attribution-feedback.d.ts +133 -0
- package/dist/types/core/attribution-hooks.d.ts +307 -8
- package/dist/types/core/attribution-queries.d.ts +24 -0
- package/dist/types/core/attribution.d.ts +802 -72
- package/dist/types/core/constants.d.ts +195 -38
- package/dist/types/core/copies.d.ts +54 -0
- package/dist/types/core/core.d.ts +295 -65
- package/dist/types/core/dev.d.ts +509 -22
- package/dist/types/core/effect.d.ts +1 -1
- package/dist/types/core/error-hooks.d.ts +71 -0
- package/dist/types/core/error.d.ts +18 -1
- package/dist/types/core/graph.d.ts +40 -1
- package/dist/types/core/heap.d.ts +5 -5
- package/dist/types/core/identities.d.ts +17 -0
- package/dist/types/core/index.d.ts +11 -7
- package/dist/types/core/invariants.d.ts +1 -26
- package/dist/types/core/lanes.d.ts +74 -43
- package/dist/types/core/owner.d.ts +27 -9
- package/dist/types/core/scheduler.d.ts +353 -102
- package/dist/types/core/truth.d.ts +18 -0
- package/dist/types/core/types.d.ts +97 -71
- package/dist/types/core/verdict.d.ts +35 -0
- package/dist/types/deferred.d.ts +28 -0
- package/dist/types/flatten.d.ts +8 -0
- package/dist/types/from.d.ts +47 -0
- package/dist/types/index.d.ts +33 -7
- package/dist/types/map.d.ts +4 -2
- package/dist/types/reveal.d.ts +19 -0
- package/dist/types/signals.d.ts +196 -45
- package/dist/types/store/affects.d.ts +12 -0
- package/dist/types/store/edges.d.ts +9 -0
- package/dist/types/store/hooks.d.ts +62 -0
- package/dist/types/store/index.d.ts +42 -15
- package/dist/types/store/optimistic.d.ts +24 -45
- package/dist/types/store/projection.d.ts +17 -68
- package/dist/types/store/reconcile.d.ts +3 -46
- package/dist/types/store/store.d.ts +133 -136
- package/dist/types/store/storePath.d.ts +1 -1
- package/dist/types/store/target.d.ts +166 -0
- package/dist/types/store/types.d.ts +105 -0
- package/dist/types/store/utils.d.ts +188 -0
- package/package.json +31 -26
- package/dist/node.cjs +0 -8745
- package/dist/prod/core/optimistic.js +0 -265
- package/dist/prod/store/next/optimistic.js +0 -385
- package/dist/prod/store/next/projection.js +0 -172
- package/dist/prod/store/next/reconcile.js +0 -331
- package/dist/prod/store/next/store.js +0 -1499
- package/dist/prod/store/next/target.js +0 -20
- package/dist/types/core/optimistic.d.ts +0 -6
- package/dist/types/store/next/optimistic.d.ts +0 -20
- package/dist/types/store/next/projection.d.ts +0 -8
- package/dist/types/store/next/reconcile.d.ts +0 -3
- package/dist/types/store/next/store.d.ts +0 -77
- package/dist/types/store/next/target.d.ts +0 -117
- package/dist/types-cjs/affects.d.cts +0 -47
- package/dist/types-cjs/boundaries.d.cts +0 -175
- package/dist/types-cjs/core/action.d.cts +0 -64
- package/dist/types-cjs/core/async.d.cts +0 -21
- package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
- package/dist/types-cjs/core/attribution.d.cts +0 -186
- package/dist/types-cjs/core/constants.d.cts +0 -97
- package/dist/types-cjs/core/context.d.cts +0 -36
- package/dist/types-cjs/core/core.d.cts +0 -163
- package/dist/types-cjs/core/dev.d.cts +0 -81
- package/dist/types-cjs/core/effect.d.cts +0 -30
- package/dist/types-cjs/core/error.d.cts +0 -47
- package/dist/types-cjs/core/external.d.cts +0 -15
- package/dist/types-cjs/core/graph.d.cts +0 -6
- package/dist/types-cjs/core/heap.d.cts +0 -22
- package/dist/types-cjs/core/index.d.cts +0 -13
- package/dist/types-cjs/core/invariants.d.cts +0 -59
- package/dist/types-cjs/core/lanes.d.cts +0 -44
- package/dist/types-cjs/core/optimistic.d.cts +0 -6
- package/dist/types-cjs/core/owner.d.cts +0 -124
- package/dist/types-cjs/core/scheduler.d.cts +0 -180
- package/dist/types-cjs/core/types.d.cts +0 -192
- package/dist/types-cjs/core/verdict.d.cts +0 -2
- package/dist/types-cjs/index.d.cts +0 -10
- package/dist/types-cjs/map.d.cts +0 -69
- package/dist/types-cjs/package.json +0 -3
- package/dist/types-cjs/signals.d.cts +0 -624
- package/dist/types-cjs/store/index.d.cts +0 -19
- package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
- package/dist/types-cjs/store/next/projection.d.cts +0 -8
- package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
- package/dist/types-cjs/store/next/store.d.cts +0 -77
- package/dist/types-cjs/store/next/target.d.cts +0 -117
- package/dist/types-cjs/store/optimistic.d.cts +0 -45
- package/dist/types-cjs/store/projection.d.cts +0 -70
- package/dist/types-cjs/store/reconcile.d.cts +0 -46
- package/dist/types-cjs/store/store.d.cts +0 -138
- package/dist/types-cjs/store/storePath.d.cts +0 -58
- package/dist/types-cjs/store/utils.d.cts +0 -74
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { CONFIG_REDERIVE, STATUS_UNINITIALIZED, CONFIG_LAGS, CONFIG_SLOT_NODE, REACTIVE_RECOMPUTING_DEPS, REACTIVE_DISPOSED, REACTIVE_REASK, CONFIG_HELD, NOT_PENDING } from "./core/constants.js";
|
|
2
|
+
|
|
3
|
+
import { isThenable, handleAsync } from "./core/async.js";
|
|
4
|
+
|
|
5
|
+
import { NotReadyError } from "./core/error.js";
|
|
6
|
+
|
|
7
|
+
import "./core/verdict.js";
|
|
8
|
+
|
|
9
|
+
import { computed } from "./core/core.js";
|
|
10
|
+
|
|
11
|
+
import { cleanup, getOwner } from "./core/owner.js";
|
|
12
|
+
|
|
13
|
+
import "./core/dev.js";
|
|
14
|
+
|
|
15
|
+
import { GlobalQueue, holdNode, txOf, schedule } from "./core/scheduler.js";
|
|
16
|
+
|
|
17
|
+
import "./core/effect.js";
|
|
18
|
+
|
|
19
|
+
import { mark, repoll, unmark } from "./affects-marks.js";
|
|
20
|
+
|
|
21
|
+
import { accessor } from "./signals.js";
|
|
22
|
+
|
|
23
|
+
// `createDeferred` — an async memo that may lag, but never leads (D-40,
|
|
24
|
+
// docs/create-deferred.md).
|
|
25
|
+
// Once the node has a committed value, its own non-final work is invisible
|
|
26
|
+
// to the graph: its readers keep the committed value and hold nothing, its
|
|
27
|
+
// landings are changes of their own, and only the verdict (`isPending`) and
|
|
28
|
+
// the truth readers (`until`, `refresh`'s waiter) see the flight.
|
|
29
|
+
// Built from parts the engine already has, so core pays nothing for it:
|
|
30
|
+
// - **Read side: the loading window** (`_loading`, async.ts). Every pass of
|
|
31
|
+
// a node with a committed value opens the window before it asks, so a
|
|
32
|
+
// flight serves the committed value instead of throwing, and an unready
|
|
33
|
+
// source parks the node instead of pending it. `CONFIG_REDERIVE` makes a
|
|
34
|
+
// source going pending a question for the node's pass (which parks) rather
|
|
35
|
+
// than a status pushed through it to its readers.
|
|
36
|
+
// - **Verdict: a mark** (affects-marks.ts) whose lifetime is the flight —
|
|
37
|
+
// started when a pass asks a new question (a `refresh()` re-ask is quiet, F-9),
|
|
38
|
+
// dropped at the landing, the rejection, a sync answer or the node's death.
|
|
39
|
+
// - **Never leads:** a flight that lands while an input it read is held
|
|
40
|
+
// derived from that hold's world, so it lands into the hold (`holdNode`;
|
|
41
|
+
// `setSignal` stages it there). An input that changed after the pass
|
|
42
|
+
// would have superseded the flight, so a held input at the landing is one
|
|
43
|
+
// the pass read held.
|
|
44
|
+
// - **Truth readers** wait the flight out (`GlobalQueue._lagging`, signals.ts
|
|
45
|
+
// `watch`): `await refresh(d)` delivers the landing, `until` sees only
|
|
46
|
+
// settled values.
|
|
47
|
+
/** Deferred nodes with a flight up. */
|
|
48
|
+
const lagging = new Set;
|
|
49
|
+
|
|
50
|
+
/** The deferred node with a flight up that `c`'s value derives from, if
|
|
51
|
+
* any: `c` itself, or one reached through its current dependencies. */ function lagOf(e, r) {
|
|
52
|
+
if (lagging.has(e)) return e;
|
|
53
|
+
if (r.has(e)) return;
|
|
54
|
+
r.add(e);
|
|
55
|
+
if (e.l & CONFIG_SLOT_NODE) return lagOf(e.O?.fam?.node ?? e, r);
|
|
56
|
+
const t = e.R & REACTIVE_RECOMPUTING_DEPS ? e._ : undefined;
|
|
57
|
+
if (t !== null) for (let o = e.C ?? null; o !== null; o = o.G) {
|
|
58
|
+
const e = lagOf(o.S, r);
|
|
59
|
+
if (e) return e;
|
|
60
|
+
if (o === t) break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates an async memo that may lag, but never leads. Before its first
|
|
68
|
+
* answer it is an ordinary async memo: readers suspend to the nearest
|
|
69
|
+
* `<Loading>`. After it, a refetch holds nothing: readers keep the last
|
|
70
|
+
* committed value until the new one lands, and the rest of the screen moves
|
|
71
|
+
* on without it. `isPending` reports the refetch, on the node and on what
|
|
72
|
+
* derives from it. Use it for independent widgets (dashboards, feeds,
|
|
73
|
+
* search results) where the previous answer with a "refreshing" indicator is
|
|
74
|
+
* better than waiting with everything else.
|
|
75
|
+
*
|
|
76
|
+
* - It never shows a value ahead of a held change: a refetch that read a
|
|
77
|
+
* held value lands with that hold.
|
|
78
|
+
* - A rejected refetch errors like any memo; the stale value never masks it.
|
|
79
|
+
* - `refresh(d)` is a quiet re-ask, and `await refresh(d)` and `until`
|
|
80
|
+
* wait for the landing rather than the stale value.
|
|
81
|
+
* - Combine with `loadingValue` for a node that never suspends at all.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```tsx
|
|
85
|
+
* const rows = createDeferred(() => fetchRows(store.period));
|
|
86
|
+
*
|
|
87
|
+
* <section class={{ stale: isPending(() => rows()) }}>
|
|
88
|
+
* <For each={rows()}>{row => <Row row={row} />}</For>
|
|
89
|
+
* </section>
|
|
90
|
+
* ```
|
|
91
|
+
*/ function createDeferred(e, r) {
|
|
92
|
+
let t;
|
|
93
|
+
/** The flight in force: a promise, a stream, or the error an unready
|
|
94
|
+
* source parked the node with. */ let o = null;
|
|
95
|
+
let n = false;
|
|
96
|
+
let l = false;
|
|
97
|
+
/** The flight `r` is over. An async answer (`held`) arriving while an
|
|
98
|
+
* input is held lands into that hold first. */ const land = (e, r) => {
|
|
99
|
+
if (e === null || o !== e) return;
|
|
100
|
+
o = null;
|
|
101
|
+
lagging.delete(t);
|
|
102
|
+
if (r) for (let e = t.C; e !== null; e = e.G) if (e.S.l & CONFIG_HELD) {
|
|
103
|
+
holdNode(t, txOf(e.S));
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
if (n) {
|
|
107
|
+
n = false;
|
|
108
|
+
unmark(t);
|
|
109
|
+
schedule();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const ask = e => {
|
|
113
|
+
o = e;
|
|
114
|
+
lagging.add(t);
|
|
115
|
+
if (!n && !(t.R & REACTIVE_REASK)) {
|
|
116
|
+
n = true;
|
|
117
|
+
mark(t);
|
|
118
|
+
repoll(t);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
/** Registers the flight and serves the pass's value: the committed one,
|
|
122
|
+
* or over a held landing the landing itself, which a lagging question
|
|
123
|
+
* does not replace (D-40) — restaged as the committed value, the hold's
|
|
124
|
+
* readers would re-derive against the old input. */ const serve = e => {
|
|
125
|
+
const r = handleAsync(t, e);
|
|
126
|
+
return t.l & CONFIG_HELD && t.ue !== NOT_PENDING ? t.ue : r;
|
|
127
|
+
};
|
|
128
|
+
const end = () => t.R & REACTIVE_DISPOSED && land(o);
|
|
129
|
+
return accessor(computed(r => {
|
|
130
|
+
t = getOwner();
|
|
131
|
+
t.l |= CONFIG_REDERIVE;
|
|
132
|
+
cleanup(end);
|
|
133
|
+
// Answered: the node has a real committed answer — not a first load,
|
|
134
|
+
// not a `loadingValue` window still open (both are loading, F-9).
|
|
135
|
+
// Sticky, and read before this wrapper ever opens the window itself.
|
|
136
|
+
const n = l ||= !(t.m & STATUS_UNINITIALIZED) && !t.ce;
|
|
137
|
+
if (n) t.ce = true, t.l |= CONFIG_LAGS;
|
|
138
|
+
try {
|
|
139
|
+
const t = e(r);
|
|
140
|
+
if (n && typeof t === "object" && t !== null) {
|
|
141
|
+
if (isThenable(t)) {
|
|
142
|
+
ask(t);
|
|
143
|
+
const done = () => land(t, true);
|
|
144
|
+
t.then(done, done);
|
|
145
|
+
return serve(t);
|
|
146
|
+
}
|
|
147
|
+
const e = t[Symbol.asyncIterator];
|
|
148
|
+
if (e) {
|
|
149
|
+
// A stream's flight ends at its first yield (or its end).
|
|
150
|
+
const r = e.call(t);
|
|
151
|
+
let o = true;
|
|
152
|
+
const done = () => land(n, true);
|
|
153
|
+
const n = {
|
|
154
|
+
// Registered ahead of the engine's own reaction to the same
|
|
155
|
+
// promise, as for a plain flight: verdict and value in one flush.
|
|
156
|
+
next: e => {
|
|
157
|
+
const t = r.next(e);
|
|
158
|
+
if (o) {
|
|
159
|
+
o = false;
|
|
160
|
+
if (isThenable(t)) t.then(done, done); else done();
|
|
161
|
+
}
|
|
162
|
+
return t;
|
|
163
|
+
},
|
|
164
|
+
return: e => r.return?.(e) ?? Promise.resolve({
|
|
165
|
+
done: true,
|
|
166
|
+
value: e
|
|
167
|
+
})
|
|
168
|
+
};
|
|
169
|
+
ask(n);
|
|
170
|
+
return serve({
|
|
171
|
+
[Symbol.asyncIterator]: () => n
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
land(o);
|
|
176
|
+
return t;
|
|
177
|
+
} catch (e) {
|
|
178
|
+
// The wrapping form: an unready source parks the node in the window,
|
|
179
|
+
// and the wait is its flight until the source's settle re-runs it.
|
|
180
|
+
if (n && e instanceof NotReadyError) ask(e); else land(o);
|
|
181
|
+
throw e;
|
|
182
|
+
}
|
|
183
|
+
}, r));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export { createDeferred };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { NotReadyError } from "./core/error.js";
|
|
2
|
+
|
|
3
|
+
import "./core/verdict.js";
|
|
4
|
+
|
|
5
|
+
import "./core/core.js";
|
|
6
|
+
|
|
7
|
+
import "./core/dev.js";
|
|
8
|
+
|
|
9
|
+
import "./core/scheduler.js";
|
|
10
|
+
|
|
11
|
+
import "./core/effect.js";
|
|
12
|
+
|
|
13
|
+
// CARVE 4: `flatten` lived in boundaries.ts but is the general children
|
|
14
|
+
// resolver the renderers (`web`, `universal`, `solid`'s `children()`) walk
|
|
15
|
+
// through — not a boundary feature. Moved verbatim so the boundary carve
|
|
16
|
+
// measures boundaries alone.
|
|
17
|
+
/**
|
|
18
|
+
* Resolves nested accessors and arrays in a children tree to their rendered
|
|
19
|
+
* values. See the `children()` helper in solid-js for the memoized form.
|
|
20
|
+
*/
|
|
21
|
+
function flatten(r, t) {
|
|
22
|
+
if (typeof r === "function" && !r.length) {
|
|
23
|
+
if (t?.doNotUnwrap) return r;
|
|
24
|
+
do {
|
|
25
|
+
r = r();
|
|
26
|
+
} while (typeof r === "function" && !r.length);
|
|
27
|
+
}
|
|
28
|
+
if (t?.skipNonRendered && (r == null || r === true || r === false || r === "")) return;
|
|
29
|
+
if (Array.isArray(r)) {
|
|
30
|
+
let e = [];
|
|
31
|
+
if (flattenArray(r, e, t)) {
|
|
32
|
+
return () => {
|
|
33
|
+
let r = [];
|
|
34
|
+
flattenArray(e, r, {
|
|
35
|
+
...t,
|
|
36
|
+
doNotUnwrap: false
|
|
37
|
+
});
|
|
38
|
+
return r;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return e;
|
|
42
|
+
}
|
|
43
|
+
return r;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function flattenArray(r, t = [], e) {
|
|
47
|
+
let o = null;
|
|
48
|
+
let f = false;
|
|
49
|
+
for (let n = 0; n < r.length; n++) {
|
|
50
|
+
try {
|
|
51
|
+
let o = r[n];
|
|
52
|
+
if (typeof o === "function" && !o.length) {
|
|
53
|
+
if (e?.doNotUnwrap) {
|
|
54
|
+
t.push(o);
|
|
55
|
+
f = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
do {
|
|
59
|
+
o = o();
|
|
60
|
+
} while (typeof o === "function" && !o.length);
|
|
61
|
+
}
|
|
62
|
+
if (Array.isArray(o)) {
|
|
63
|
+
// OR, don't overwrite: an accessor already pushed under doNotUnwrap
|
|
64
|
+
// still needs the resolving wrapper even when a later sibling
|
|
65
|
+
// fragment contains no functions (#3133).
|
|
66
|
+
f = flattenArray(o, t, e) || f;
|
|
67
|
+
} else if (e?.skipNonRendered && (o == null || o === true || o === false || o === "")) {
|
|
68
|
+
// skip
|
|
69
|
+
} else t.push(o);
|
|
70
|
+
} catch (r) {
|
|
71
|
+
if (!(r instanceof NotReadyError)) throw r;
|
|
72
|
+
o = r;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (o) throw o;
|
|
76
|
+
return f;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { flatten };
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { isThenable, onSupersede } from "./core/async.js";
|
|
2
|
+
|
|
3
|
+
import { CONFIG_CHILDREN_FORBIDDEN } from "./core/constants.js";
|
|
4
|
+
|
|
5
|
+
import { cleanup, getOwner } from "./core/owner.js";
|
|
6
|
+
|
|
7
|
+
// `from` — a push source (callback subscription, Observable, AsyncIterable)
|
|
8
|
+
// as an AsyncIterable a computation can return or `for await` over:
|
|
9
|
+
// const value = createMemo(() => from(source));
|
|
10
|
+
// A subscription keeps the latest value: values that arrive between pulls
|
|
11
|
+
// coalesce. An AsyncIterable streams through unchanged. Either way the source
|
|
12
|
+
// opens when the result is iterated and closes on return(), on supersede (the
|
|
13
|
+
// owning computation re-runs) and on owner disposal, whichever comes first.
|
|
14
|
+
function toSubscribe(e) {
|
|
15
|
+
if (typeof e === "function") return e;
|
|
16
|
+
// TC39 / RxJS interop: `Symbol.observable` (or "@@observable") returns the observable.
|
|
17
|
+
// Read per call, not at module scope, so the module stays side-effect free.
|
|
18
|
+
const n = Symbol.observable;
|
|
19
|
+
const r = (n && e?.[n]) ?? e?.["@@observable"];
|
|
20
|
+
const t = typeof r === "function" ? r.call(e) : e;
|
|
21
|
+
if (t && typeof t.subscribe === "function") return (e, n, r) => t.subscribe({
|
|
22
|
+
next: e,
|
|
23
|
+
error: n,
|
|
24
|
+
complete: r
|
|
25
|
+
});
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const DONE = {
|
|
30
|
+
value: undefined,
|
|
31
|
+
done: true
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Ties an iterator's `finish` to the computation iterating it. Solid reaches
|
|
36
|
+
* an iterator's return() only when the compute returns the iterable directly.
|
|
37
|
+
* Inside an async generator the generator's own return() is queued behind its
|
|
38
|
+
* pending `await`, and owner cleanups wait for the replacing pass to commit,
|
|
39
|
+
* so close on supersede, with owner disposal as the backstop. No owner (an
|
|
40
|
+
* async compute iterating it after its first `await`, or plain iteration):
|
|
41
|
+
* no registration and no diagnostic, so only return() closes it. Scopes that
|
|
42
|
+
* forbid cleanups rely on supersede and return().
|
|
43
|
+
*/ function bindToOwner(e) {
|
|
44
|
+
const n = getOwner();
|
|
45
|
+
if (!n) return;
|
|
46
|
+
onSupersede(e);
|
|
47
|
+
if (!(n.l & CONFIG_CHILDREN_FORBIDDEN)) cleanup(e);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* An AsyncIterable as a stream bound to the iterating computation: every
|
|
52
|
+
* value passes through (no coalescing). `finish` calls the inner return()
|
|
53
|
+
* once and settles pending pulls as done, so a `for await` over it exits as
|
|
54
|
+
* soon as the computation re-runs — even when the inner iterator is an async
|
|
55
|
+
* generator whose own return() the language queues behind its pending
|
|
56
|
+
* `await`.
|
|
57
|
+
*/ function wrapIterable(e) {
|
|
58
|
+
return {
|
|
59
|
+
[Symbol.asyncIterator]() {
|
|
60
|
+
const n = e[Symbol.asyncIterator]();
|
|
61
|
+
let r = false;
|
|
62
|
+
const t = new Set;
|
|
63
|
+
const finish = () => {
|
|
64
|
+
if (r) return DONE;
|
|
65
|
+
r = true;
|
|
66
|
+
for (const e of t) e(DONE);
|
|
67
|
+
t.clear();
|
|
68
|
+
try {
|
|
69
|
+
const e = n.return?.();
|
|
70
|
+
if (isThenable(e)) e.then(undefined, () => {});
|
|
71
|
+
} catch {}
|
|
72
|
+
return DONE;
|
|
73
|
+
};
|
|
74
|
+
bindToOwner(finish);
|
|
75
|
+
return {
|
|
76
|
+
next(...e) {
|
|
77
|
+
if (r) return Promise.resolve(DONE);
|
|
78
|
+
const o = n.next(...e);
|
|
79
|
+
// A bare result (the producer's buffered fast path) passes through.
|
|
80
|
+
if (!isThenable(o)) return o;
|
|
81
|
+
return new Promise((e, n) => {
|
|
82
|
+
t.add(e);
|
|
83
|
+
o.then(n => t.delete(e) && e(n), r => t.delete(e) && n(r));
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
return() {
|
|
87
|
+
return Promise.resolve(finish());
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const toCleanup = e => typeof e === "function" ? e : e && typeof e.unsubscribe === "function" ? () => e.unsubscribe() : () => {};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Converts a callback subscription, an Observable or an AsyncIterable into an
|
|
98
|
+
* AsyncIterable for a Solid computation. A subscription keeps only the latest
|
|
99
|
+
* value, and a value the source emits during `subscribe` is served without a
|
|
100
|
+
* loading frame; an AsyncIterable streams every value through.
|
|
101
|
+
*
|
|
102
|
+
* The source closes on supersede — the owning computation re-running — and
|
|
103
|
+
* on owner disposal. Inside an async generator memo that holds for a
|
|
104
|
+
* `for await` that starts before the first `await`; one that starts after it
|
|
105
|
+
* has no owner to bind to, so its source closes only when the loop ends.
|
|
106
|
+
* Prefer returning `from(...)` from its own memo, with awaited inputs read
|
|
107
|
+
* from upstream memos and transforms done in a downstream memo.
|
|
108
|
+
*
|
|
109
|
+
* Iterate the result with `for await` or return it from a computation: its
|
|
110
|
+
* `next()` returns an already-buffered value as a bare result, not a promise.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* const position = createMemo(() =>
|
|
115
|
+
* from<Position>((next, error) => {
|
|
116
|
+
* const id = navigator.geolocation.watchPosition(next, error);
|
|
117
|
+
* return () => navigator.geolocation.clearWatch(id);
|
|
118
|
+
* })
|
|
119
|
+
* );
|
|
120
|
+
* const ticks = createMemo(() => from(interval$(rate())));
|
|
121
|
+
* ```
|
|
122
|
+
*/ function from(e) {
|
|
123
|
+
const n = toSubscribe(e);
|
|
124
|
+
if (!n) {
|
|
125
|
+
if (e && typeof e[Symbol.asyncIterator] === "function") return wrapIterable(e);
|
|
126
|
+
throw new TypeError("from(): expected a subscribe function, an Observable or an AsyncIterable");
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
[Symbol.asyncIterator]() {
|
|
130
|
+
let e;
|
|
131
|
+
let r = false;
|
|
132
|
+
let t = false;
|
|
133
|
+
let o = false;
|
|
134
|
+
let u;
|
|
135
|
+
let f = null;
|
|
136
|
+
let l = null;
|
|
137
|
+
let s = false;
|
|
138
|
+
const close = () => {
|
|
139
|
+
if (s) return;
|
|
140
|
+
s = true;
|
|
141
|
+
t = true;
|
|
142
|
+
const e = l;
|
|
143
|
+
l = null;
|
|
144
|
+
// A throwing unsubscribe must not escape: at supersede this runs
|
|
145
|
+
// inside flush(), ahead of the replacing pass (the returned-iterator
|
|
146
|
+
// path swallows it the same way).
|
|
147
|
+
try {
|
|
148
|
+
e?.();
|
|
149
|
+
} catch {}
|
|
150
|
+
};
|
|
151
|
+
const settle = () => {
|
|
152
|
+
if (!f) return;
|
|
153
|
+
const n = f;
|
|
154
|
+
if (r) {
|
|
155
|
+
f = null;
|
|
156
|
+
r = false;
|
|
157
|
+
n.resolve({
|
|
158
|
+
value: e,
|
|
159
|
+
done: false
|
|
160
|
+
});
|
|
161
|
+
} else if (o) {
|
|
162
|
+
f = null;
|
|
163
|
+
o = false;
|
|
164
|
+
n.reject(u);
|
|
165
|
+
} else if (t) {
|
|
166
|
+
f = null;
|
|
167
|
+
n.resolve({
|
|
168
|
+
value: undefined,
|
|
169
|
+
done: true
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const i = n(n => {
|
|
174
|
+
if (t) return;
|
|
175
|
+
e = n;
|
|
176
|
+
r = true;
|
|
177
|
+
settle();
|
|
178
|
+
}, e => {
|
|
179
|
+
if (t) return;
|
|
180
|
+
o = true;
|
|
181
|
+
u = e;
|
|
182
|
+
t = true;
|
|
183
|
+
settle();
|
|
184
|
+
close();
|
|
185
|
+
}, () => {
|
|
186
|
+
if (t) return;
|
|
187
|
+
t = true;
|
|
188
|
+
settle();
|
|
189
|
+
close();
|
|
190
|
+
});
|
|
191
|
+
l = toCleanup(i);
|
|
192
|
+
// Completed or errored during subscribe: release what it just returned.
|
|
193
|
+
if (s) {
|
|
194
|
+
const e = l;
|
|
195
|
+
l = null;
|
|
196
|
+
try {
|
|
197
|
+
e();
|
|
198
|
+
} catch {}
|
|
199
|
+
}
|
|
200
|
+
// Idempotent: return(), supersede and disposal may all reach it.
|
|
201
|
+
const finish = () => {
|
|
202
|
+
close();
|
|
203
|
+
r = false;
|
|
204
|
+
if (f) {
|
|
205
|
+
const e = f;
|
|
206
|
+
f = null;
|
|
207
|
+
e.resolve(DONE);
|
|
208
|
+
}
|
|
209
|
+
return DONE;
|
|
210
|
+
};
|
|
211
|
+
bindToOwner(finish);
|
|
212
|
+
return {
|
|
213
|
+
next() {
|
|
214
|
+
// A buffered value is returned as a bare result, not a promise: the
|
|
215
|
+
// iterator consumer lands it in the same pass, so a source that
|
|
216
|
+
// emits during subscribe (BehaviorSubject-style) shows its value
|
|
217
|
+
// with no loading frame. `for await` accepts either form.
|
|
218
|
+
if (r) {
|
|
219
|
+
r = false;
|
|
220
|
+
return {
|
|
221
|
+
value: e,
|
|
222
|
+
done: false
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (o) {
|
|
226
|
+
o = false;
|
|
227
|
+
return Promise.reject(u);
|
|
228
|
+
}
|
|
229
|
+
if (t) return Promise.resolve({
|
|
230
|
+
value: undefined,
|
|
231
|
+
done: true
|
|
232
|
+
});
|
|
233
|
+
return new Promise((e, n) => {
|
|
234
|
+
f = {
|
|
235
|
+
resolve: e,
|
|
236
|
+
reject: n
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
return() {
|
|
241
|
+
return Promise.resolve(finish());
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export { from };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export { ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError } from "./core/error.js";
|
|
2
|
+
|
|
3
|
+
export { isPending, latest } from "./core/verdict.js";
|
|
4
|
+
|
|
5
|
+
export { action } from "./core/action.js";
|
|
6
|
+
|
|
7
|
+
export { clearSnapshots, isEqual, markSnapshotScope, releaseSnapshotScope, runWithOwner, setSnapshotCapture, setWriteHook, untrack } from "./core/core.js";
|
|
8
|
+
|
|
9
|
+
export { enableExternalSource } from "./core/external.js";
|
|
10
|
+
|
|
11
|
+
export { createOwner, createRoot, getNextChildId, getObserver, getOwner, isDisposed, peekNextChildId } from "./core/owner.js";
|
|
12
|
+
|
|
13
|
+
export { setReadWatch, setSignalIdentities, signalName } from "./core/identities.js";
|
|
14
|
+
|
|
15
|
+
export { createContext, getContext, setContext } from "./core/context.js";
|
|
16
|
+
|
|
17
|
+
export { $REFRESH, SUPPORTS_PROXY } from "./core/constants.js";
|
|
18
|
+
|
|
19
|
+
import { OBSERVE as OBSERVE$1 } from "./core/dev.js";
|
|
20
|
+
|
|
21
|
+
export { setConsoleFooter } from "./core/dev.js";
|
|
22
|
+
|
|
23
|
+
export { ROOT_ERROR_HOOK, clock, enforceLoadingBoundary, flush, resetErrorHalt } from "./core/scheduler.js";
|
|
24
|
+
|
|
25
|
+
import "./core/effect.js";
|
|
26
|
+
|
|
27
|
+
export { configureClientErrors } from "./core/error-hooks.js";
|
|
28
|
+
|
|
29
|
+
export { checkForeignOwnerless, runAsSolidCopy } from "./core/copies.js";
|
|
30
|
+
|
|
31
|
+
export { storeName } from "./store/edges.js";
|
|
32
|
+
|
|
33
|
+
export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onFlush, onSettled, refresh, resolve, until } from "./signals.js";
|
|
34
|
+
|
|
35
|
+
export { mapArray, repeat } from "./map.js";
|
|
36
|
+
|
|
37
|
+
export { createStore, deep, reconcile, snapshot } from "./store/index.js";
|
|
38
|
+
|
|
39
|
+
export { affects } from "./affects.js";
|
|
40
|
+
|
|
41
|
+
export { createDeferred } from "./deferred.js";
|
|
42
|
+
|
|
43
|
+
export { from } from "./from.js";
|
|
44
|
+
|
|
45
|
+
export { flatten } from "./flatten.js";
|
|
46
|
+
|
|
47
|
+
export { createErrorBoundary, createLoadingBoundary } from "./boundaries.js";
|
|
48
|
+
|
|
49
|
+
export { createRevealOrder } from "./reveal.js";
|
|
50
|
+
|
|
51
|
+
export { $PROXY, $RECORD, $TARGET, $TRACK, isWrappable, markRaw } from "./store/types.js";
|
|
52
|
+
|
|
53
|
+
export { MergeView, OmitView, SOURCE_MEMO, SOURCE_MERGE, SOURCE_OMIT, SOURCE_PLAIN, SOURCE_PROXY, hasStaticKeys, isStatic, merge, mergeSources, mergeView, omit, omitView, resolvedTable, sourceGet, sourceHas, sourceKeys, sourceOwners, viewOf } from "./store/utils.js";
|
|
54
|
+
|
|
55
|
+
export { createOptimisticStore } from "./store/optimistic.js";
|
|
56
|
+
|
|
57
|
+
export { createProjection } from "./store/projection.js";
|
|
58
|
+
|
|
59
|
+
export { storeHasFamily, storeHasOptimisticFamily, storeIsShallow } from "./store/store.js";
|
|
60
|
+
|
|
61
|
+
export { storePath } from "./store/storePath.js";
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Observe tier (diagnostics channel, attribution hook slot + interaction
|
|
65
|
+
* frame): dev and observe builds. The attribution engine itself is the
|
|
66
|
+
* `@solidjs/signals/attribution` entry.
|
|
67
|
+
*/ const OBSERVE = OBSERVE$1;
|
|
68
|
+
|
|
69
|
+
/** Dev tier (devtools hooks, graph traversal, console reporting): dev builds only. */ const DEV = undefined;
|
|
70
|
+
|
|
71
|
+
export { DEV, OBSERVE };
|