@fluixi/reactive 1.0.0-alpha.83 → 1.0.0-alpha.84
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/cdn/reactive.cjs +2673 -1
- package/dist/cdn/reactive.global.js +2 -1
- package/dist/cdn/reactive.mjs +2657 -1
- package/dist/cdn/signal.cjs +299 -1
- package/dist/cdn/signal.d.ts +1 -1
- package/dist/cdn/signal.global.js +2 -1
- package/dist/cdn/signal.js +1 -1
- package/dist/cdn/signal.mjs +276 -1
- package/dist/index.cjs +2673 -1
- package/dist/index.mjs +2657 -1
- package/dist/lib/index.cjs +2674 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/index.mjs +2659 -1
- package/dist/lib/observable/index.cjs +386 -1
- package/dist/lib/observable/index.mjs +364 -1
- package/dist/lib/observable/observable.cjs +384 -1
- package/dist/lib/observable/observable.d.ts +0 -137
- package/dist/lib/observable/observable.d.ts.map +1 -1
- package/dist/lib/observable/observable.js +0 -71
- package/dist/lib/observable/observable.mjs +361 -1
- package/dist/lib/observable/subscription.cjs +180 -1
- package/dist/lib/observable/subscription.d.ts +0 -12
- package/dist/lib/observable/subscription.d.ts.map +1 -1
- package/dist/lib/observable/subscription.js +0 -12
- package/dist/lib/observable/subscription.mjs +157 -1
- package/dist/lib/observable/types.cjs +18 -1
- package/dist/lib/observable/types.d.ts.map +1 -1
- package/dist/lib/predicates.cjs +44 -1
- package/dist/lib/predicates.d.ts +2 -2
- package/dist/lib/predicates.js +2 -2
- package/dist/lib/predicates.mjs +23 -1
- package/dist/lib/signal/api.cjs +571 -1
- package/dist/lib/signal/api.d.ts +211 -1
- package/dist/lib/signal/api.d.ts.map +1 -1
- package/dist/lib/signal/api.js +207 -12
- package/dist/lib/signal/api.mjs +548 -1
- package/dist/lib/signal/cached-resource.cjs +672 -1
- package/dist/lib/signal/cached-resource.d.ts +28 -16
- package/dist/lib/signal/cached-resource.d.ts.map +1 -1
- package/dist/lib/signal/cached-resource.js +35 -29
- package/dist/lib/signal/cached-resource.mjs +650 -1
- package/dist/lib/signal/graph/children.cjs +325 -1
- package/dist/lib/signal/graph/children.js +1 -1
- package/dist/lib/signal/graph/children.mjs +302 -1
- package/dist/lib/signal/graph/compat.cjs +578 -1
- package/dist/lib/signal/graph/compat.d.ts +13 -13
- package/dist/lib/signal/graph/compat.d.ts.map +1 -1
- package/dist/lib/signal/graph/compat.js +33 -31
- package/dist/lib/signal/graph/compat.mjs +556 -1
- package/dist/lib/signal/graph/core.cjs +295 -1
- package/dist/lib/signal/graph/core.d.ts +28 -24
- package/dist/lib/signal/graph/core.d.ts.map +1 -1
- package/dist/lib/signal/graph/core.js +38 -31
- package/dist/lib/signal/graph/core.mjs +273 -1
- package/dist/lib/signal/graph/debounced.cjs +668 -1
- package/dist/lib/signal/graph/debounced.d.ts +5 -5
- package/dist/lib/signal/graph/debounced.d.ts.map +1 -1
- package/dist/lib/signal/graph/debounced.js +5 -5
- package/dist/lib/signal/graph/debounced.mjs +645 -1
- package/dist/lib/signal/graph/derived.cjs +496 -1
- package/dist/lib/signal/graph/derived.d.ts +1 -1
- package/dist/lib/signal/graph/derived.js +1 -1
- package/dist/lib/signal/graph/derived.mjs +473 -1
- package/dist/lib/signal/graph/detect.cjs +66 -1
- package/dist/lib/signal/graph/detect.mjs +45 -1
- package/dist/lib/signal/graph/error-boundary.cjs +301 -1
- package/dist/lib/signal/graph/error-boundary.js +3 -3
- package/dist/lib/signal/graph/error-boundary.mjs +278 -1
- package/dist/lib/signal/graph/index.cjs +305 -1
- package/dist/lib/signal/graph/index.d.ts +7 -6
- package/dist/lib/signal/graph/index.d.ts.map +1 -1
- package/dist/lib/signal/graph/index.js +7 -6
- package/dist/lib/signal/graph/index.mjs +283 -1
- package/dist/lib/signal/graph/observe.cjs +163 -1
- package/dist/lib/signal/graph/observe.d.ts +8 -8
- package/dist/lib/signal/graph/observe.js +5 -5
- package/dist/lib/signal/graph/observe.mjs +140 -1
- package/dist/lib/signal/graph/resource.cjs +620 -1
- package/dist/lib/signal/graph/resource.d.ts +1 -1
- package/dist/lib/signal/graph/resource.js +7 -8
- package/dist/lib/signal/graph/resource.mjs +597 -1
- package/dist/lib/signal/graph/runtime.cjs +501 -1
- package/dist/lib/signal/graph/runtime.d.ts +7 -7
- package/dist/lib/signal/graph/runtime.d.ts.map +1 -1
- package/dist/lib/signal/graph/runtime.js +34 -30
- package/dist/lib/signal/graph/runtime.mjs +478 -1
- package/dist/lib/signal/graph/signal-next.cjs +1208 -1
- package/dist/lib/signal/graph/signal-next.d.ts +5 -5
- package/dist/lib/signal/graph/signal-next.d.ts.map +1 -1
- package/dist/lib/signal/graph/signal-next.js +14 -12
- package/dist/lib/signal/graph/signal-next.mjs +1186 -1
- package/dist/lib/signal/graph/ssr-hooks.cjs +60 -1
- package/dist/lib/signal/graph/ssr-hooks.d.ts +6 -7
- package/dist/lib/signal/graph/ssr-hooks.d.ts.map +1 -1
- package/dist/lib/signal/graph/ssr-hooks.js +6 -7
- package/dist/lib/signal/graph/ssr-hooks.mjs +39 -1
- package/dist/lib/signal/graph/state.cjs +72 -1
- package/dist/lib/signal/graph/state.d.ts +41 -10
- package/dist/lib/signal/graph/state.d.ts.map +1 -1
- package/dist/lib/signal/graph/state.js +83 -22
- package/dist/lib/signal/graph/state.mjs +49 -1
- package/dist/lib/signal/graph/suspense.cjs +301 -1
- package/dist/lib/signal/graph/suspense.js +4 -4
- package/dist/lib/signal/graph/suspense.mjs +278 -1
- package/dist/lib/signal/index-legacy.cjs +2540 -1
- package/dist/lib/signal/index-legacy.d.ts +1 -1
- package/dist/lib/signal/index-legacy.js +1 -1
- package/dist/lib/signal/index-legacy.mjs +2518 -1
- package/dist/lib/signal/index.cjs +1275 -1
- package/dist/lib/signal/index.d.ts +3 -2
- package/dist/lib/signal/index.d.ts.map +1 -1
- package/dist/lib/signal/index.js +7 -4
- package/dist/lib/signal/index.mjs +1253 -1
- package/dist/lib/signal/list.cjs +549 -1
- package/dist/lib/signal/list.d.ts +5 -5
- package/dist/lib/signal/list.js +5 -5
- package/dist/lib/signal/list.mjs +526 -1
- package/dist/lib/signal/resource-api.cjs +626 -1
- package/dist/lib/signal/resource-api.d.ts +5 -5
- package/dist/lib/signal/resource-api.js +5 -5
- package/dist/lib/signal/resource-api.mjs +603 -1
- package/dist/lib/signal/signal.cjs +2023 -1
- package/dist/lib/signal/signal.d.ts +4 -4
- package/dist/lib/signal/signal.d.ts.map +1 -1
- package/dist/lib/signal/signal.js +22 -23
- package/dist/lib/signal/signal.mjs +2000 -1
- package/dist/lib/signal/types.cjs +38 -1
- package/dist/lib/signal/types.d.ts.map +1 -1
- package/dist/lib/signal/types.js +2 -2
- package/dist/lib/signal/types.mjs +17 -1
- package/dist/lib/signal/utilities.cjs +1012 -1
- package/dist/lib/signal/utilities.d.ts +0 -108
- package/dist/lib/signal/utilities.d.ts.map +1 -1
- package/dist/lib/signal/utilities.js +0 -158
- package/dist/lib/signal/utilities.mjs +990 -1
- package/dist/lib/store/api.cjs +612 -1
- package/dist/lib/store/api.d.ts +33 -0
- package/dist/lib/store/api.d.ts.map +1 -1
- package/dist/lib/store/api.js +41 -8
- package/dist/lib/store/api.mjs +596 -1
- package/dist/lib/store/index.cjs +691 -1
- package/dist/lib/store/index.js +1 -1
- package/dist/lib/store/index.mjs +676 -1
- package/dist/lib/store/setter.types.cjs +18 -1
- package/dist/lib/store/setter.types.d.ts +43 -3
- package/dist/lib/store/setter.types.d.ts.map +1 -1
- package/dist/lib/store/store.cjs +658 -1
- package/dist/lib/store/store.d.ts +72 -0
- package/dist/lib/store/store.d.ts.map +1 -1
- package/dist/lib/store/store.js +148 -5
- package/dist/lib/store/store.mjs +644 -1
- package/dist/lib/store/types.cjs +18 -1
- package/dist/lib/store/types.d.ts +1 -1
- package/dist/lib/store/types.d.ts.map +1 -1
- package/dist/lib/store/utils.cjs +43 -1
- package/dist/lib/store/utils.d.ts +1 -1
- package/dist/lib/store/utils.js +1 -1
- package/dist/lib/store/utils.mjs +22 -1
- package/dist/lib/subject.cjs +450 -1
- package/dist/lib/subject.js +3 -91
- package/dist/lib/subject.mjs +427 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/version.generated.cjs +27 -1
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +2 -2
- package/dist/version.generated.mjs +7 -1
- package/package.json +5 -4
|
@@ -1 +1,301 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/lib/signal/graph/suspense.ts
|
|
21
|
+
var suspense_exports = {};
|
|
22
|
+
__export(suspense_exports, {
|
|
23
|
+
SuspenseContext: () => SuspenseContext,
|
|
24
|
+
createSuspenseBoundary: () => createSuspenseBoundary,
|
|
25
|
+
provideSuspense: () => provideSuspense
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(suspense_exports);
|
|
28
|
+
|
|
29
|
+
// src/version.generated.ts
|
|
30
|
+
var VERSION = "1.0.0-alpha.84";
|
|
31
|
+
|
|
32
|
+
// src/lib/signal/graph/state.ts
|
|
33
|
+
var MAJOR = VERSION.split(".")[0];
|
|
34
|
+
var KEY = `__fluixi_signal_state_v${MAJOR}__`;
|
|
35
|
+
var VERSIONS_KEY = `__fluixi_signal_builds_v${MAJOR}__`;
|
|
36
|
+
var defaultSchedule = (run) => {
|
|
37
|
+
if (typeof queueMicrotask === "function") queueMicrotask(run);
|
|
38
|
+
else void Promise.resolve().then(run);
|
|
39
|
+
};
|
|
40
|
+
function defaults() {
|
|
41
|
+
return {
|
|
42
|
+
consumer: null,
|
|
43
|
+
untracked: false,
|
|
44
|
+
owner: null,
|
|
45
|
+
queue: [],
|
|
46
|
+
scheduled: false,
|
|
47
|
+
flushing: false,
|
|
48
|
+
batchDepth: 0,
|
|
49
|
+
hostSchedule: defaultSchedule,
|
|
50
|
+
onSuspend: null,
|
|
51
|
+
onError: null,
|
|
52
|
+
observer: null
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
var realm = globalThis;
|
|
56
|
+
function backfillState(existing) {
|
|
57
|
+
const fresh = defaults();
|
|
58
|
+
const target = existing;
|
|
59
|
+
for (const field of Object.keys(fresh)) {
|
|
60
|
+
if (!(field in existing)) target[field] = fresh[field];
|
|
61
|
+
}
|
|
62
|
+
return existing;
|
|
63
|
+
}
|
|
64
|
+
function claim() {
|
|
65
|
+
const existing = realm[KEY];
|
|
66
|
+
return existing ? backfillState(existing) : realm[KEY] = defaults();
|
|
67
|
+
}
|
|
68
|
+
var G = claim();
|
|
69
|
+
(realm[VERSIONS_KEY] ??= []).push(VERSION);
|
|
70
|
+
|
|
71
|
+
// src/lib/signal/graph/observe.ts
|
|
72
|
+
function observeReactiveNodes(next) {
|
|
73
|
+
G.observer = next;
|
|
74
|
+
return () => {
|
|
75
|
+
if (G.observer === next) G.observer = null;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
var running = [];
|
|
79
|
+
var origin;
|
|
80
|
+
function reportReactiveNode(report) {
|
|
81
|
+
const observer = G.observer;
|
|
82
|
+
if (observer) {
|
|
83
|
+
observer.created(
|
|
84
|
+
report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function reportReactiveWrite(node, by) {
|
|
89
|
+
G.observer?.wrote?.(node, by);
|
|
90
|
+
}
|
|
91
|
+
function reportReactiveContextCreated(id) {
|
|
92
|
+
G.observer?.contextCreated?.(id);
|
|
93
|
+
}
|
|
94
|
+
function reportReactiveContext(id, kind, value) {
|
|
95
|
+
const observer = G.observer;
|
|
96
|
+
if (!observer?.context || !running.length) return;
|
|
97
|
+
observer.context(running[running.length - 1], id, kind, value);
|
|
98
|
+
}
|
|
99
|
+
function reportReactiveDispose(node) {
|
|
100
|
+
G.observer?.disposed?.(node);
|
|
101
|
+
}
|
|
102
|
+
var HOOK = "__FLUIXI_DEVTOOLS_HOOK__";
|
|
103
|
+
var hook = globalThis[HOOK];
|
|
104
|
+
if (typeof hook?.inject === "function") {
|
|
105
|
+
try {
|
|
106
|
+
hook.inject({ observeReactiveNodes, version: VERSION });
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function isObserved() {
|
|
111
|
+
return G.observer != null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/lib/signal/graph/core.ts
|
|
115
|
+
var DIRTY = 2;
|
|
116
|
+
var Source = class {
|
|
117
|
+
constructor() {
|
|
118
|
+
/** Computeds, and watched leaves, that read this node. */
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
120
|
+
this.observers = null;
|
|
121
|
+
/** Watchers eagerly observing this node, which is how `runtime.ts` schedules effects. */
|
|
122
|
+
this.watchers = null;
|
|
123
|
+
/** Bumped whenever this node's value actually changes (equality-gated). */
|
|
124
|
+
this.version = 0;
|
|
125
|
+
}
|
|
126
|
+
/** Settle this node so a reader sees a current value/version. Overridden by Computed. */
|
|
127
|
+
updateIfNecessary() {
|
|
128
|
+
}
|
|
129
|
+
/** Link the current consumer (if any) as an observer of this node. */
|
|
130
|
+
track() {
|
|
131
|
+
if (G.untracked) return;
|
|
132
|
+
const consumer = G.consumer;
|
|
133
|
+
if (!consumer) return;
|
|
134
|
+
(this.observers ??= /* @__PURE__ */ new Set()).add(consumer);
|
|
135
|
+
(consumer.sources ??= /* @__PURE__ */ new Set()).add(this);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
var State = class extends Source {
|
|
139
|
+
constructor(value, options) {
|
|
140
|
+
super();
|
|
141
|
+
this._value = value;
|
|
142
|
+
this._equals = options?.equals === false ? () => false : options?.equals ?? Object.is;
|
|
143
|
+
}
|
|
144
|
+
get() {
|
|
145
|
+
this.track();
|
|
146
|
+
return this._value;
|
|
147
|
+
}
|
|
148
|
+
set(next) {
|
|
149
|
+
if (this._equals(this._value, next)) return;
|
|
150
|
+
this._value = next;
|
|
151
|
+
this.version++;
|
|
152
|
+
reportReactiveWrite(this, G.consumer);
|
|
153
|
+
if (this.observers) for (const o of [...this.observers]) o.markDirty(DIRTY);
|
|
154
|
+
notifyWatchers(this);
|
|
155
|
+
}
|
|
156
|
+
/** Read without subscribing (peek). */
|
|
157
|
+
peek() {
|
|
158
|
+
return this._value;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
function notifyWatchers(node) {
|
|
162
|
+
if (!node.watchers) return;
|
|
163
|
+
for (const w of [...node.watchers]) w._notify(node);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/lib/signal/graph/runtime.ts
|
|
167
|
+
function makeOwner(parent) {
|
|
168
|
+
return { cleanups: null, owned: null, parent, contexts: null };
|
|
169
|
+
}
|
|
170
|
+
function createContext(defaultValue, name) {
|
|
171
|
+
const id = Symbol(name ?? "context");
|
|
172
|
+
reportReactiveContextCreated(id);
|
|
173
|
+
const Provider = (props) => {
|
|
174
|
+
reportReactiveContext(id, "provide", props.value);
|
|
175
|
+
const parent = G.owner;
|
|
176
|
+
const owner = makeOwner(parent);
|
|
177
|
+
(owner.contexts = /* @__PURE__ */ new Map()).set(id, props.value);
|
|
178
|
+
if (parent) (parent.owned ??= []).push(owner);
|
|
179
|
+
G.owner = owner;
|
|
180
|
+
try {
|
|
181
|
+
return props.children;
|
|
182
|
+
} finally {
|
|
183
|
+
G.owner = parent;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
return { id, defaultValue, Provider };
|
|
187
|
+
}
|
|
188
|
+
function readContextFrom(owner, context) {
|
|
189
|
+
let o = owner;
|
|
190
|
+
while (o) {
|
|
191
|
+
if (o.contexts && o.contexts.has(context.id)) return o.contexts.get(context.id);
|
|
192
|
+
o = o.parent;
|
|
193
|
+
}
|
|
194
|
+
return context.defaultValue;
|
|
195
|
+
}
|
|
196
|
+
function provide(context, value, fn) {
|
|
197
|
+
const owner = makeOwner(G.owner);
|
|
198
|
+
(owner.contexts = /* @__PURE__ */ new Map()).set(context.id, value);
|
|
199
|
+
if (G.owner) (G.owner.owned ??= []).push(owner);
|
|
200
|
+
const prev = G.owner;
|
|
201
|
+
G.owner = owner;
|
|
202
|
+
try {
|
|
203
|
+
return fn();
|
|
204
|
+
} finally {
|
|
205
|
+
G.owner = prev;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function setSuspendHandler(fn) {
|
|
209
|
+
G.onSuspend = fn;
|
|
210
|
+
}
|
|
211
|
+
function onCleanup(fn) {
|
|
212
|
+
if (!G.owner) return;
|
|
213
|
+
if (G.owner.disposed) {
|
|
214
|
+
fn();
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
(G.owner.cleanups ??= []).push(fn);
|
|
218
|
+
}
|
|
219
|
+
function setScheduler(fn) {
|
|
220
|
+
G.hostSchedule = fn ?? ((run) => void Promise.resolve().then(run));
|
|
221
|
+
}
|
|
222
|
+
function flushSync() {
|
|
223
|
+
G.scheduled = false;
|
|
224
|
+
if (G.flushing) return;
|
|
225
|
+
G.flushing = true;
|
|
226
|
+
let guard = 0;
|
|
227
|
+
try {
|
|
228
|
+
while (G.queue.length) {
|
|
229
|
+
if (++guard > 1e5) throw new Error("[fluixi] effect flush did not settle (cycle?)");
|
|
230
|
+
const batchOf = G.queue;
|
|
231
|
+
G.queue = [];
|
|
232
|
+
for (const e of batchOf) {
|
|
233
|
+
e.queued = false;
|
|
234
|
+
if (!e.disposed) e.run();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} finally {
|
|
238
|
+
G.flushing = false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function afterWrite() {
|
|
242
|
+
if (G.batchDepth === 0) flushSync();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/lib/signal/graph/compat.ts
|
|
246
|
+
setScheduler(() => {
|
|
247
|
+
});
|
|
248
|
+
var $SIGNAL = /* @__PURE__ */ Symbol.for("signal");
|
|
249
|
+
var $NODE = /* @__PURE__ */ Symbol.for("signal-node");
|
|
250
|
+
function createSignal(value, options) {
|
|
251
|
+
const state = new State(value, { equals: options?.equals });
|
|
252
|
+
const read = (() => state.get());
|
|
253
|
+
const write = ((next) => {
|
|
254
|
+
const v = typeof next === "function" ? next(state.peek()) : next;
|
|
255
|
+
state.set(v);
|
|
256
|
+
afterWrite();
|
|
257
|
+
return v;
|
|
258
|
+
});
|
|
259
|
+
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
260
|
+
Object.defineProperty(read, $NODE, {
|
|
261
|
+
value: {
|
|
262
|
+
get value() {
|
|
263
|
+
return state.peek();
|
|
264
|
+
},
|
|
265
|
+
get version() {
|
|
266
|
+
return state.version;
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
enumerable: false
|
|
270
|
+
});
|
|
271
|
+
reportReactiveNode({
|
|
272
|
+
kind: "signal",
|
|
273
|
+
node: state,
|
|
274
|
+
handle: read,
|
|
275
|
+
name: options?.name,
|
|
276
|
+
set: write
|
|
277
|
+
});
|
|
278
|
+
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
279
|
+
return [read, write];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/lib/signal/graph/suspense.ts
|
|
283
|
+
var SuspenseContext = createContext();
|
|
284
|
+
setSuspendHandler((promise, owner) => {
|
|
285
|
+
const boundary = readContextFrom(owner, SuspenseContext);
|
|
286
|
+
if (!boundary) return;
|
|
287
|
+
boundary.increment();
|
|
288
|
+
promise.finally(() => boundary.decrement());
|
|
289
|
+
});
|
|
290
|
+
function createSuspenseBoundary() {
|
|
291
|
+
const [pending, setPending] = createSignal(0);
|
|
292
|
+
let count = 0;
|
|
293
|
+
return {
|
|
294
|
+
increment: () => setPending(count += 1),
|
|
295
|
+
decrement: () => setPending(count -= 1),
|
|
296
|
+
inFallback: () => pending() > 0
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function provideSuspense(boundary, fn) {
|
|
300
|
+
return provide(SuspenseContext, boundary, fn);
|
|
301
|
+
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Suspense ported onto the TC39 core (additive; legacy signal.ts untouched).
|
|
3
3
|
*
|
|
4
4
|
* A Suspense boundary is just a context carrying a pending counter. A suspended read
|
|
5
|
-
* (createResource while pending throws its promise) bubbles to the
|
|
6
|
-
* which calls the injected suspend handler registered here
|
|
5
|
+
* (createResource while pending throws its promise) bubbles to the runtime effect's run(),
|
|
6
|
+
* which calls the injected suspend handler registered here, it finds the nearest
|
|
7
7
|
* boundary (via the effect's owner chain) and increments it; the promise settling
|
|
8
8
|
* decrements it. The effect itself re-runs through normal reactivity once the
|
|
9
9
|
* resource's state signal changes, so the resolved content replaces the fallback.
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
import { createContext, provide, readContextFrom, setSuspendHandler, } from './runtime.js';
|
|
12
12
|
import { createSignal } from './compat.js';
|
|
13
13
|
const SuspenseContext = createContext();
|
|
14
|
-
// Wire the
|
|
14
|
+
// Wire the runtime effect's suspend path to the nearest boundary. Registered once.
|
|
15
15
|
setSuspendHandler((promise, owner) => {
|
|
16
16
|
const boundary = readContextFrom(owner, SuspenseContext);
|
|
17
17
|
if (!boundary)
|
|
18
|
-
return; // no boundary above
|
|
18
|
+
return; // no boundary above -> let it stay pending (no crash)
|
|
19
19
|
boundary.increment();
|
|
20
20
|
promise.finally(() => boundary.decrement());
|
|
21
21
|
});
|
|
@@ -1 +1,278 @@
|
|
|
1
|
-
|
|
1
|
+
// src/version.generated.ts
|
|
2
|
+
var VERSION = "1.0.0-alpha.84";
|
|
3
|
+
|
|
4
|
+
// src/lib/signal/graph/state.ts
|
|
5
|
+
var MAJOR = VERSION.split(".")[0];
|
|
6
|
+
var KEY = `__fluixi_signal_state_v${MAJOR}__`;
|
|
7
|
+
var VERSIONS_KEY = `__fluixi_signal_builds_v${MAJOR}__`;
|
|
8
|
+
var defaultSchedule = (run) => {
|
|
9
|
+
if (typeof queueMicrotask === "function") queueMicrotask(run);
|
|
10
|
+
else void Promise.resolve().then(run);
|
|
11
|
+
};
|
|
12
|
+
function defaults() {
|
|
13
|
+
return {
|
|
14
|
+
consumer: null,
|
|
15
|
+
untracked: false,
|
|
16
|
+
owner: null,
|
|
17
|
+
queue: [],
|
|
18
|
+
scheduled: false,
|
|
19
|
+
flushing: false,
|
|
20
|
+
batchDepth: 0,
|
|
21
|
+
hostSchedule: defaultSchedule,
|
|
22
|
+
onSuspend: null,
|
|
23
|
+
onError: null,
|
|
24
|
+
observer: null
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
var realm = globalThis;
|
|
28
|
+
function backfillState(existing) {
|
|
29
|
+
const fresh = defaults();
|
|
30
|
+
const target = existing;
|
|
31
|
+
for (const field of Object.keys(fresh)) {
|
|
32
|
+
if (!(field in existing)) target[field] = fresh[field];
|
|
33
|
+
}
|
|
34
|
+
return existing;
|
|
35
|
+
}
|
|
36
|
+
function claim() {
|
|
37
|
+
const existing = realm[KEY];
|
|
38
|
+
return existing ? backfillState(existing) : realm[KEY] = defaults();
|
|
39
|
+
}
|
|
40
|
+
var G = claim();
|
|
41
|
+
(realm[VERSIONS_KEY] ??= []).push(VERSION);
|
|
42
|
+
|
|
43
|
+
// src/lib/signal/graph/observe.ts
|
|
44
|
+
function observeReactiveNodes(next) {
|
|
45
|
+
G.observer = next;
|
|
46
|
+
return () => {
|
|
47
|
+
if (G.observer === next) G.observer = null;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var running = [];
|
|
51
|
+
var origin;
|
|
52
|
+
function reportReactiveNode(report) {
|
|
53
|
+
const observer = G.observer;
|
|
54
|
+
if (observer) {
|
|
55
|
+
observer.created(
|
|
56
|
+
report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function reportReactiveWrite(node, by) {
|
|
61
|
+
G.observer?.wrote?.(node, by);
|
|
62
|
+
}
|
|
63
|
+
function reportReactiveContextCreated(id) {
|
|
64
|
+
G.observer?.contextCreated?.(id);
|
|
65
|
+
}
|
|
66
|
+
function reportReactiveContext(id, kind, value) {
|
|
67
|
+
const observer = G.observer;
|
|
68
|
+
if (!observer?.context || !running.length) return;
|
|
69
|
+
observer.context(running[running.length - 1], id, kind, value);
|
|
70
|
+
}
|
|
71
|
+
function reportReactiveDispose(node) {
|
|
72
|
+
G.observer?.disposed?.(node);
|
|
73
|
+
}
|
|
74
|
+
var HOOK = "__FLUIXI_DEVTOOLS_HOOK__";
|
|
75
|
+
var hook = globalThis[HOOK];
|
|
76
|
+
if (typeof hook?.inject === "function") {
|
|
77
|
+
try {
|
|
78
|
+
hook.inject({ observeReactiveNodes, version: VERSION });
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function isObserved() {
|
|
83
|
+
return G.observer != null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/lib/signal/graph/core.ts
|
|
87
|
+
var DIRTY = 2;
|
|
88
|
+
var Source = class {
|
|
89
|
+
constructor() {
|
|
90
|
+
/** Computeds, and watched leaves, that read this node. */
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
+
this.observers = null;
|
|
93
|
+
/** Watchers eagerly observing this node, which is how `runtime.ts` schedules effects. */
|
|
94
|
+
this.watchers = null;
|
|
95
|
+
/** Bumped whenever this node's value actually changes (equality-gated). */
|
|
96
|
+
this.version = 0;
|
|
97
|
+
}
|
|
98
|
+
/** Settle this node so a reader sees a current value/version. Overridden by Computed. */
|
|
99
|
+
updateIfNecessary() {
|
|
100
|
+
}
|
|
101
|
+
/** Link the current consumer (if any) as an observer of this node. */
|
|
102
|
+
track() {
|
|
103
|
+
if (G.untracked) return;
|
|
104
|
+
const consumer = G.consumer;
|
|
105
|
+
if (!consumer) return;
|
|
106
|
+
(this.observers ??= /* @__PURE__ */ new Set()).add(consumer);
|
|
107
|
+
(consumer.sources ??= /* @__PURE__ */ new Set()).add(this);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
var State = class extends Source {
|
|
111
|
+
constructor(value, options) {
|
|
112
|
+
super();
|
|
113
|
+
this._value = value;
|
|
114
|
+
this._equals = options?.equals === false ? () => false : options?.equals ?? Object.is;
|
|
115
|
+
}
|
|
116
|
+
get() {
|
|
117
|
+
this.track();
|
|
118
|
+
return this._value;
|
|
119
|
+
}
|
|
120
|
+
set(next) {
|
|
121
|
+
if (this._equals(this._value, next)) return;
|
|
122
|
+
this._value = next;
|
|
123
|
+
this.version++;
|
|
124
|
+
reportReactiveWrite(this, G.consumer);
|
|
125
|
+
if (this.observers) for (const o of [...this.observers]) o.markDirty(DIRTY);
|
|
126
|
+
notifyWatchers(this);
|
|
127
|
+
}
|
|
128
|
+
/** Read without subscribing (peek). */
|
|
129
|
+
peek() {
|
|
130
|
+
return this._value;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
function notifyWatchers(node) {
|
|
134
|
+
if (!node.watchers) return;
|
|
135
|
+
for (const w of [...node.watchers]) w._notify(node);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/lib/signal/graph/runtime.ts
|
|
139
|
+
function makeOwner(parent) {
|
|
140
|
+
return { cleanups: null, owned: null, parent, contexts: null };
|
|
141
|
+
}
|
|
142
|
+
function createContext(defaultValue, name) {
|
|
143
|
+
const id = Symbol(name ?? "context");
|
|
144
|
+
reportReactiveContextCreated(id);
|
|
145
|
+
const Provider = (props) => {
|
|
146
|
+
reportReactiveContext(id, "provide", props.value);
|
|
147
|
+
const parent = G.owner;
|
|
148
|
+
const owner = makeOwner(parent);
|
|
149
|
+
(owner.contexts = /* @__PURE__ */ new Map()).set(id, props.value);
|
|
150
|
+
if (parent) (parent.owned ??= []).push(owner);
|
|
151
|
+
G.owner = owner;
|
|
152
|
+
try {
|
|
153
|
+
return props.children;
|
|
154
|
+
} finally {
|
|
155
|
+
G.owner = parent;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
return { id, defaultValue, Provider };
|
|
159
|
+
}
|
|
160
|
+
function readContextFrom(owner, context) {
|
|
161
|
+
let o = owner;
|
|
162
|
+
while (o) {
|
|
163
|
+
if (o.contexts && o.contexts.has(context.id)) return o.contexts.get(context.id);
|
|
164
|
+
o = o.parent;
|
|
165
|
+
}
|
|
166
|
+
return context.defaultValue;
|
|
167
|
+
}
|
|
168
|
+
function provide(context, value, fn) {
|
|
169
|
+
const owner = makeOwner(G.owner);
|
|
170
|
+
(owner.contexts = /* @__PURE__ */ new Map()).set(context.id, value);
|
|
171
|
+
if (G.owner) (G.owner.owned ??= []).push(owner);
|
|
172
|
+
const prev = G.owner;
|
|
173
|
+
G.owner = owner;
|
|
174
|
+
try {
|
|
175
|
+
return fn();
|
|
176
|
+
} finally {
|
|
177
|
+
G.owner = prev;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function setSuspendHandler(fn) {
|
|
181
|
+
G.onSuspend = fn;
|
|
182
|
+
}
|
|
183
|
+
function onCleanup(fn) {
|
|
184
|
+
if (!G.owner) return;
|
|
185
|
+
if (G.owner.disposed) {
|
|
186
|
+
fn();
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
(G.owner.cleanups ??= []).push(fn);
|
|
190
|
+
}
|
|
191
|
+
function setScheduler(fn) {
|
|
192
|
+
G.hostSchedule = fn ?? ((run) => void Promise.resolve().then(run));
|
|
193
|
+
}
|
|
194
|
+
function flushSync() {
|
|
195
|
+
G.scheduled = false;
|
|
196
|
+
if (G.flushing) return;
|
|
197
|
+
G.flushing = true;
|
|
198
|
+
let guard = 0;
|
|
199
|
+
try {
|
|
200
|
+
while (G.queue.length) {
|
|
201
|
+
if (++guard > 1e5) throw new Error("[fluixi] effect flush did not settle (cycle?)");
|
|
202
|
+
const batchOf = G.queue;
|
|
203
|
+
G.queue = [];
|
|
204
|
+
for (const e of batchOf) {
|
|
205
|
+
e.queued = false;
|
|
206
|
+
if (!e.disposed) e.run();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} finally {
|
|
210
|
+
G.flushing = false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function afterWrite() {
|
|
214
|
+
if (G.batchDepth === 0) flushSync();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/lib/signal/graph/compat.ts
|
|
218
|
+
setScheduler(() => {
|
|
219
|
+
});
|
|
220
|
+
var $SIGNAL = /* @__PURE__ */ Symbol.for("signal");
|
|
221
|
+
var $NODE = /* @__PURE__ */ Symbol.for("signal-node");
|
|
222
|
+
function createSignal(value, options) {
|
|
223
|
+
const state = new State(value, { equals: options?.equals });
|
|
224
|
+
const read = (() => state.get());
|
|
225
|
+
const write = ((next) => {
|
|
226
|
+
const v = typeof next === "function" ? next(state.peek()) : next;
|
|
227
|
+
state.set(v);
|
|
228
|
+
afterWrite();
|
|
229
|
+
return v;
|
|
230
|
+
});
|
|
231
|
+
Object.defineProperty(read, $SIGNAL, { value: true, enumerable: true });
|
|
232
|
+
Object.defineProperty(read, $NODE, {
|
|
233
|
+
value: {
|
|
234
|
+
get value() {
|
|
235
|
+
return state.peek();
|
|
236
|
+
},
|
|
237
|
+
get version() {
|
|
238
|
+
return state.version;
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
enumerable: false
|
|
242
|
+
});
|
|
243
|
+
reportReactiveNode({
|
|
244
|
+
kind: "signal",
|
|
245
|
+
node: state,
|
|
246
|
+
handle: read,
|
|
247
|
+
name: options?.name,
|
|
248
|
+
set: write
|
|
249
|
+
});
|
|
250
|
+
if (isObserved()) onCleanup(() => reportReactiveDispose(state));
|
|
251
|
+
return [read, write];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// src/lib/signal/graph/suspense.ts
|
|
255
|
+
var SuspenseContext = createContext();
|
|
256
|
+
setSuspendHandler((promise, owner) => {
|
|
257
|
+
const boundary = readContextFrom(owner, SuspenseContext);
|
|
258
|
+
if (!boundary) return;
|
|
259
|
+
boundary.increment();
|
|
260
|
+
promise.finally(() => boundary.decrement());
|
|
261
|
+
});
|
|
262
|
+
function createSuspenseBoundary() {
|
|
263
|
+
const [pending, setPending] = createSignal(0);
|
|
264
|
+
let count = 0;
|
|
265
|
+
return {
|
|
266
|
+
increment: () => setPending(count += 1),
|
|
267
|
+
decrement: () => setPending(count -= 1),
|
|
268
|
+
inFallback: () => pending() > 0
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function provideSuspense(boundary, fn) {
|
|
272
|
+
return provide(SuspenseContext, boundary, fn);
|
|
273
|
+
}
|
|
274
|
+
export {
|
|
275
|
+
SuspenseContext,
|
|
276
|
+
createSuspenseBoundary,
|
|
277
|
+
provideSuspense
|
|
278
|
+
};
|