solid-js 2.0.0-experimental.14 → 2.0.0-experimental.15
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.cjs +429 -41
- package/dist/dev.js +427 -27
- package/dist/server.cjs +335 -43
- package/dist/server.js +336 -45
- package/dist/solid.cjs +415 -40
- package/dist/solid.js +413 -26
- package/package.json +2 -2
- package/types/client/component.d.ts +1 -1
- package/types/client/hydration.d.ts +34 -2
- package/types/server/component.d.ts +6 -2
- package/types/server/index.d.ts +2 -2
- package/types/server/shared.d.ts +22 -1
- package/types/server/signals.d.ts +8 -2
package/dist/solid.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, getOwner,
|
|
2
|
-
export { $PROXY, $TRACK, NotReadyError, action, createEffect,
|
|
1
|
+
import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, createLoadBoundary, getOwner, onCleanup, isDisposed, runWithOwner, createOptimistic as createOptimistic$1, createOptimisticStore as createOptimisticStore$1, createProjection as createProjection$1, createSignal as createSignal$1, createStore as createStore$1, setSnapshotCapture, releaseSnapshotScope, getNextChildId, createErrorBoundary as createErrorBoundary$1, markSnapshotScope, flush, clearSnapshots, peekNextChildId, untrack, mapArray, repeat } from '@solidjs/signals';
|
|
2
|
+
export { $PROXY, $TRACK, NotReadyError, action, createEffect, createReaction, createRenderEffect, createRoot, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isPending, isRefreshing, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, untrack } from '@solidjs/signals';
|
|
3
3
|
|
|
4
4
|
const $DEVCOMP = Symbol(0);
|
|
5
5
|
function createContext(defaultValue, options) {
|
|
@@ -37,8 +37,44 @@ const sharedConfig = {
|
|
|
37
37
|
return getNextChildId(o);
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
+
let _hydrationEndCallbacks = null;
|
|
41
|
+
let _pendingBoundaries = 0;
|
|
42
|
+
let _hydrationDone = false;
|
|
43
|
+
let _snapshotRootOwner = null;
|
|
44
|
+
function markTopLevelSnapshotScope() {
|
|
45
|
+
if (_snapshotRootOwner) return;
|
|
46
|
+
let owner = getOwner();
|
|
47
|
+
if (!owner) return;
|
|
48
|
+
while (owner._parent) owner = owner._parent;
|
|
49
|
+
markSnapshotScope(owner);
|
|
50
|
+
_snapshotRootOwner = owner;
|
|
51
|
+
}
|
|
52
|
+
function drainHydrationCallbacks() {
|
|
53
|
+
if (_hydrationDone) return;
|
|
54
|
+
_hydrationDone = true;
|
|
55
|
+
_doneValue = true;
|
|
56
|
+
clearSnapshots();
|
|
57
|
+
setSnapshotCapture(false);
|
|
58
|
+
flush();
|
|
59
|
+
const cbs = _hydrationEndCallbacks;
|
|
60
|
+
_hydrationEndCallbacks = null;
|
|
61
|
+
if (cbs) for (const cb of cbs) cb();
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
if (globalThis._$HY) globalThis._$HY.done = true;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function checkHydrationComplete() {
|
|
67
|
+
if (_pendingBoundaries === 0) drainHydrationCallbacks();
|
|
68
|
+
}
|
|
69
|
+
let _hydratingValue = false;
|
|
70
|
+
let _doneValue = false;
|
|
40
71
|
let _createMemo;
|
|
41
72
|
let _createSignal;
|
|
73
|
+
let _createErrorBoundary;
|
|
74
|
+
let _createOptimistic;
|
|
75
|
+
let _createProjection;
|
|
76
|
+
let _createStore;
|
|
77
|
+
let _createOptimisticStore;
|
|
42
78
|
class MockPromise {
|
|
43
79
|
static all() {
|
|
44
80
|
return new MockPromise();
|
|
@@ -74,14 +110,110 @@ function subFetch(fn, prev) {
|
|
|
74
110
|
try {
|
|
75
111
|
window.fetch = () => new MockPromise();
|
|
76
112
|
Promise = MockPromise;
|
|
77
|
-
|
|
113
|
+
const result = fn(prev);
|
|
114
|
+
if (result && typeof result[Symbol.asyncIterator] === "function") {
|
|
115
|
+
result[Symbol.asyncIterator]().next();
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
78
118
|
} finally {
|
|
79
119
|
window.fetch = ogFetch;
|
|
80
120
|
Promise = ogPromise;
|
|
81
121
|
}
|
|
82
122
|
}
|
|
123
|
+
function consumeFirstSync(ai) {
|
|
124
|
+
const iter = ai[Symbol.asyncIterator]();
|
|
125
|
+
const r = iter.next();
|
|
126
|
+
const value = !(r instanceof Promise) && !r.done ? r.value : undefined;
|
|
127
|
+
return [value, iter];
|
|
128
|
+
}
|
|
129
|
+
function applyPatches(target, patches) {
|
|
130
|
+
for (const patch of patches) {
|
|
131
|
+
const path = patch[0];
|
|
132
|
+
let current = target;
|
|
133
|
+
for (let i = 0; i < path.length - 1; i++) current = current[path[i]];
|
|
134
|
+
const key = path[path.length - 1];
|
|
135
|
+
if (patch.length === 1) {
|
|
136
|
+
Array.isArray(current) ? current.splice(key, 1) : delete current[key];
|
|
137
|
+
} else if (patch.length === 3) {
|
|
138
|
+
current.splice(key, 0, patch[1]);
|
|
139
|
+
} else {
|
|
140
|
+
current[key] = patch[1];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function scheduleIteratorConsumption(iter, apply) {
|
|
145
|
+
const consume = () => {
|
|
146
|
+
while (true) {
|
|
147
|
+
const n = iter.next();
|
|
148
|
+
if (n instanceof Promise) {
|
|
149
|
+
n.then(r => {
|
|
150
|
+
if (r.done) return;
|
|
151
|
+
apply(r.value);
|
|
152
|
+
consume();
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (n.done) break;
|
|
157
|
+
apply(n.value);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
consume();
|
|
161
|
+
}
|
|
162
|
+
function isAsyncIterable(v) {
|
|
163
|
+
return v != null && typeof v[Symbol.asyncIterator] === "function";
|
|
164
|
+
}
|
|
165
|
+
function hydrateSignalFromAsyncIterable(coreFn, compute, value, options) {
|
|
166
|
+
const parent = getOwner();
|
|
167
|
+
const expectedId = peekNextChildId(parent);
|
|
168
|
+
if (!sharedConfig.has(expectedId)) return null;
|
|
169
|
+
const initP = sharedConfig.load(expectedId);
|
|
170
|
+
if (!isAsyncIterable(initP)) return null;
|
|
171
|
+
const [firstValue, iter] = consumeFirstSync(initP);
|
|
172
|
+
const [get, set] = createSignal$1(firstValue);
|
|
173
|
+
const result = coreFn(() => get(), firstValue, options);
|
|
174
|
+
scheduleIteratorConsumption(iter, v => {
|
|
175
|
+
set(() => v);
|
|
176
|
+
flush();
|
|
177
|
+
});
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) {
|
|
181
|
+
const parent = getOwner();
|
|
182
|
+
const expectedId = peekNextChildId(parent);
|
|
183
|
+
if (!sharedConfig.has(expectedId)) return null;
|
|
184
|
+
const initP = sharedConfig.load(expectedId);
|
|
185
|
+
if (!isAsyncIterable(initP)) return null;
|
|
186
|
+
const [firstState, iter] = consumeFirstSync(initP);
|
|
187
|
+
const [store, setStore] = coreFn(() => {}, firstState ?? initialValue, options);
|
|
188
|
+
scheduleIteratorConsumption(iter, patches => {
|
|
189
|
+
setStore(d => {
|
|
190
|
+
applyPatches(d, patches);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
return [store, setStore];
|
|
194
|
+
}
|
|
83
195
|
function hydratedCreateMemo(compute, value, options) {
|
|
84
196
|
if (!sharedConfig.hydrating) return createMemo$1(compute, value, options);
|
|
197
|
+
markTopLevelSnapshotScope();
|
|
198
|
+
const ssrSource = options?.ssrSource;
|
|
199
|
+
if (ssrSource === "client") {
|
|
200
|
+
const [hydrated, setHydrated] = createSignal$1(false);
|
|
201
|
+
const memo = createMemo$1(prev => {
|
|
202
|
+
if (!hydrated()) return prev ?? value;
|
|
203
|
+
return compute(prev);
|
|
204
|
+
}, value, options);
|
|
205
|
+
setHydrated(true);
|
|
206
|
+
return memo;
|
|
207
|
+
}
|
|
208
|
+
if (ssrSource === "initial") {
|
|
209
|
+
return createMemo$1(prev => {
|
|
210
|
+
if (!sharedConfig.hydrating) return compute(prev);
|
|
211
|
+
subFetch(compute, prev);
|
|
212
|
+
return prev ?? value;
|
|
213
|
+
}, value, options);
|
|
214
|
+
}
|
|
215
|
+
const aiResult = hydrateSignalFromAsyncIterable(createMemo$1, compute, value, options);
|
|
216
|
+
if (aiResult !== null) return aiResult;
|
|
85
217
|
return createMemo$1(prev => {
|
|
86
218
|
const o = getOwner();
|
|
87
219
|
if (!sharedConfig.hydrating) return compute(prev);
|
|
@@ -93,6 +225,26 @@ function hydratedCreateMemo(compute, value, options) {
|
|
|
93
225
|
}
|
|
94
226
|
function hydratedCreateSignal(fn, second, third) {
|
|
95
227
|
if (typeof fn !== "function" || !sharedConfig.hydrating) return createSignal$1(fn, second, third);
|
|
228
|
+
markTopLevelSnapshotScope();
|
|
229
|
+
const ssrSource = third?.ssrSource;
|
|
230
|
+
if (ssrSource === "client") {
|
|
231
|
+
const [hydrated, setHydrated] = createSignal$1(false);
|
|
232
|
+
const sig = createSignal$1(prev => {
|
|
233
|
+
if (!hydrated()) return prev ?? second;
|
|
234
|
+
return fn(prev);
|
|
235
|
+
}, second, third);
|
|
236
|
+
setHydrated(true);
|
|
237
|
+
return sig;
|
|
238
|
+
}
|
|
239
|
+
if (ssrSource === "initial") {
|
|
240
|
+
return createSignal$1(prev => {
|
|
241
|
+
if (!sharedConfig.hydrating) return fn(prev);
|
|
242
|
+
subFetch(fn, prev);
|
|
243
|
+
return prev ?? second;
|
|
244
|
+
}, second, third);
|
|
245
|
+
}
|
|
246
|
+
const aiResult = hydrateSignalFromAsyncIterable(createSignal$1, fn, second, third);
|
|
247
|
+
if (aiResult !== null) return aiResult;
|
|
96
248
|
return createSignal$1(prev => {
|
|
97
249
|
if (!sharedConfig.hydrating) return fn(prev);
|
|
98
250
|
const o = getOwner();
|
|
@@ -102,17 +254,215 @@ function hydratedCreateSignal(fn, second, third) {
|
|
|
102
254
|
return init != null ? (subFetch(fn, prev), init) : fn(prev);
|
|
103
255
|
}, second, third);
|
|
104
256
|
}
|
|
257
|
+
function hydratedCreateErrorBoundary(fn, fallback) {
|
|
258
|
+
if (!sharedConfig.hydrating) return createErrorBoundary$1(fn, fallback);
|
|
259
|
+
markTopLevelSnapshotScope();
|
|
260
|
+
const parent = getOwner();
|
|
261
|
+
const expectedId = peekNextChildId(parent);
|
|
262
|
+
if (sharedConfig.has(expectedId)) {
|
|
263
|
+
const err = sharedConfig.load(expectedId);
|
|
264
|
+
if (err !== undefined) {
|
|
265
|
+
let hydrated = true;
|
|
266
|
+
return createErrorBoundary$1(() => {
|
|
267
|
+
if (hydrated) {
|
|
268
|
+
hydrated = false;
|
|
269
|
+
throw err;
|
|
270
|
+
}
|
|
271
|
+
return fn();
|
|
272
|
+
}, fallback);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return createErrorBoundary$1(fn, fallback);
|
|
276
|
+
}
|
|
277
|
+
function hydratedCreateOptimistic(fn, second, third) {
|
|
278
|
+
if (typeof fn !== "function" || !sharedConfig.hydrating) return createOptimistic$1(fn, second, third);
|
|
279
|
+
markTopLevelSnapshotScope();
|
|
280
|
+
const ssrSource = third?.ssrSource;
|
|
281
|
+
if (ssrSource === "client") {
|
|
282
|
+
const [hydrated, setHydrated] = createSignal$1(false);
|
|
283
|
+
const sig = createOptimistic$1(prev => {
|
|
284
|
+
if (!hydrated()) return prev ?? second;
|
|
285
|
+
return fn(prev);
|
|
286
|
+
}, second, third);
|
|
287
|
+
setHydrated(true);
|
|
288
|
+
return sig;
|
|
289
|
+
}
|
|
290
|
+
if (ssrSource === "initial") {
|
|
291
|
+
return createOptimistic$1(prev => {
|
|
292
|
+
if (!sharedConfig.hydrating) return fn(prev);
|
|
293
|
+
subFetch(fn, prev);
|
|
294
|
+
return prev ?? second;
|
|
295
|
+
}, second, third);
|
|
296
|
+
}
|
|
297
|
+
const aiResult = hydrateSignalFromAsyncIterable(createOptimistic$1, fn, second, third);
|
|
298
|
+
if (aiResult !== null) return aiResult;
|
|
299
|
+
return createOptimistic$1(prev => {
|
|
300
|
+
const o = getOwner();
|
|
301
|
+
if (!sharedConfig.hydrating) return fn(prev);
|
|
302
|
+
let initP;
|
|
303
|
+
if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id);
|
|
304
|
+
const init = initP?.v ?? initP;
|
|
305
|
+
return init != null ? (subFetch(fn, prev), init) : fn(prev);
|
|
306
|
+
}, second, third);
|
|
307
|
+
}
|
|
308
|
+
function wrapStoreFn(fn, ssrSource) {
|
|
309
|
+
if (ssrSource === "initial") {
|
|
310
|
+
return draft => {
|
|
311
|
+
if (!sharedConfig.hydrating) return fn(draft);
|
|
312
|
+
subFetch(fn, draft);
|
|
313
|
+
return undefined;
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return draft => {
|
|
317
|
+
const o = getOwner();
|
|
318
|
+
if (!sharedConfig.hydrating) return fn(draft);
|
|
319
|
+
let initP;
|
|
320
|
+
if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id);
|
|
321
|
+
const init = initP?.v ?? initP;
|
|
322
|
+
return init != null ? (subFetch(fn, draft), init) : fn(draft);
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function hydratedCreateStore(first, second, third) {
|
|
326
|
+
if (typeof first !== "function" || !sharedConfig.hydrating) return createStore$1(first, second, third);
|
|
327
|
+
markTopLevelSnapshotScope();
|
|
328
|
+
const ssrSource = third?.ssrSource;
|
|
329
|
+
if (ssrSource === "client" || ssrSource === "initial") {
|
|
330
|
+
return createStore$1(second ?? {}, undefined, third);
|
|
331
|
+
}
|
|
332
|
+
const aiResult = hydrateStoreFromAsyncIterable(createStore$1, second ?? {}, third);
|
|
333
|
+
if (aiResult !== null) return aiResult;
|
|
334
|
+
return createStore$1(wrapStoreFn(first, ssrSource), second, third);
|
|
335
|
+
}
|
|
336
|
+
function hydratedCreateOptimisticStore(first, second, third) {
|
|
337
|
+
if (typeof first !== "function" || !sharedConfig.hydrating) return createOptimisticStore$1(first, second, third);
|
|
338
|
+
markTopLevelSnapshotScope();
|
|
339
|
+
const ssrSource = third?.ssrSource;
|
|
340
|
+
if (ssrSource === "client" || ssrSource === "initial") {
|
|
341
|
+
return createOptimisticStore$1(second ?? {}, undefined, third);
|
|
342
|
+
}
|
|
343
|
+
const aiResult = hydrateStoreFromAsyncIterable(createOptimisticStore$1, second ?? {}, third);
|
|
344
|
+
if (aiResult !== null) return aiResult;
|
|
345
|
+
return createOptimisticStore$1(wrapStoreFn(first, ssrSource), second, third);
|
|
346
|
+
}
|
|
347
|
+
function hydratedCreateProjection(fn, initialValue, options) {
|
|
348
|
+
if (!sharedConfig.hydrating) return createProjection$1(fn, initialValue, options);
|
|
349
|
+
markTopLevelSnapshotScope();
|
|
350
|
+
const ssrSource = options?.ssrSource;
|
|
351
|
+
if (ssrSource === "client" || ssrSource === "initial") {
|
|
352
|
+
return createProjection$1(draft => draft, initialValue, options);
|
|
353
|
+
}
|
|
354
|
+
const aiResult = hydrateStoreFromAsyncIterable(createStore$1, initialValue, options);
|
|
355
|
+
if (aiResult !== null) return aiResult[0];
|
|
356
|
+
return createProjection$1(wrapStoreFn(fn, ssrSource), initialValue, options);
|
|
357
|
+
}
|
|
105
358
|
function enableHydration() {
|
|
106
359
|
_createMemo = hydratedCreateMemo;
|
|
107
360
|
_createSignal = hydratedCreateSignal;
|
|
361
|
+
_createErrorBoundary = hydratedCreateErrorBoundary;
|
|
362
|
+
_createOptimistic = hydratedCreateOptimistic;
|
|
363
|
+
_createProjection = hydratedCreateProjection;
|
|
364
|
+
_createStore = hydratedCreateStore;
|
|
365
|
+
_createOptimisticStore = hydratedCreateOptimisticStore;
|
|
366
|
+
_hydratingValue = sharedConfig.hydrating;
|
|
367
|
+
_doneValue = sharedConfig.done;
|
|
368
|
+
Object.defineProperty(sharedConfig, "hydrating", {
|
|
369
|
+
get() {
|
|
370
|
+
return _hydratingValue;
|
|
371
|
+
},
|
|
372
|
+
set(v) {
|
|
373
|
+
const was = _hydratingValue;
|
|
374
|
+
_hydratingValue = v;
|
|
375
|
+
if (!was && v) {
|
|
376
|
+
_hydrationDone = false;
|
|
377
|
+
_doneValue = false;
|
|
378
|
+
_pendingBoundaries = 0;
|
|
379
|
+
setSnapshotCapture(true);
|
|
380
|
+
_snapshotRootOwner = null;
|
|
381
|
+
} else if (was && !v) {
|
|
382
|
+
if (_snapshotRootOwner) {
|
|
383
|
+
releaseSnapshotScope(_snapshotRootOwner);
|
|
384
|
+
_snapshotRootOwner = null;
|
|
385
|
+
}
|
|
386
|
+
checkHydrationComplete();
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
configurable: true,
|
|
390
|
+
enumerable: true
|
|
391
|
+
});
|
|
392
|
+
Object.defineProperty(sharedConfig, "done", {
|
|
393
|
+
get() {
|
|
394
|
+
return _doneValue;
|
|
395
|
+
},
|
|
396
|
+
set(v) {
|
|
397
|
+
_doneValue = v;
|
|
398
|
+
if (v) drainHydrationCallbacks();
|
|
399
|
+
},
|
|
400
|
+
configurable: true,
|
|
401
|
+
enumerable: true
|
|
402
|
+
});
|
|
108
403
|
}
|
|
109
404
|
const createMemo = (...args) => (_createMemo || createMemo$1)(...args);
|
|
110
405
|
const createSignal = (...args) => (_createSignal || createSignal$1)(...args);
|
|
406
|
+
const createErrorBoundary = (...args) => (_createErrorBoundary || createErrorBoundary$1)(...args);
|
|
407
|
+
const createOptimistic = (...args) => (_createOptimistic || createOptimistic$1)(...args);
|
|
408
|
+
const createProjection = (...args) => (_createProjection || createProjection$1)(...args);
|
|
409
|
+
const createStore = (...args) => (_createStore || createStore$1)(...args);
|
|
410
|
+
const createOptimisticStore = (...args) => (_createOptimisticStore || createOptimisticStore$1)(...args);
|
|
411
|
+
function loadModuleAssets(mapping) {
|
|
412
|
+
const hy = globalThis._$HY;
|
|
413
|
+
if (!hy) return;
|
|
414
|
+
if (!hy.modules) hy.modules = {};
|
|
415
|
+
if (!hy.loading) hy.loading = {};
|
|
416
|
+
const pending = [];
|
|
417
|
+
for (const moduleUrl in mapping) {
|
|
418
|
+
if (hy.modules[moduleUrl]) continue;
|
|
419
|
+
const entryUrl = mapping[moduleUrl];
|
|
420
|
+
if (!hy.loading[moduleUrl]) {
|
|
421
|
+
hy.loading[moduleUrl] = import(entryUrl).then(mod => {
|
|
422
|
+
hy.modules[moduleUrl] = mod;
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
pending.push(hy.loading[moduleUrl]);
|
|
426
|
+
}
|
|
427
|
+
return pending.length ? Promise.all(pending).then(() => {}) : undefined;
|
|
428
|
+
}
|
|
429
|
+
function createBoundaryTrigger() {
|
|
430
|
+
setSnapshotCapture(false);
|
|
431
|
+
const [s, set] = createSignal$1(undefined, {
|
|
432
|
+
equals: false
|
|
433
|
+
});
|
|
434
|
+
s();
|
|
435
|
+
setSnapshotCapture(true);
|
|
436
|
+
return set;
|
|
437
|
+
}
|
|
438
|
+
function resumeBoundaryHydration(o, id, set) {
|
|
439
|
+
_pendingBoundaries--;
|
|
440
|
+
if (isDisposed(o)) {
|
|
441
|
+
checkHydrationComplete();
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
sharedConfig.gather(id);
|
|
445
|
+
_hydratingValue = true;
|
|
446
|
+
markSnapshotScope(o);
|
|
447
|
+
_snapshotRootOwner = o;
|
|
448
|
+
set();
|
|
449
|
+
flush();
|
|
450
|
+
_snapshotRootOwner = null;
|
|
451
|
+
_hydratingValue = false;
|
|
452
|
+
releaseSnapshotScope(o);
|
|
453
|
+
flush();
|
|
454
|
+
checkHydrationComplete();
|
|
455
|
+
}
|
|
111
456
|
function Loading(props) {
|
|
112
457
|
if (!sharedConfig.hydrating) return createLoadBoundary(() => props.children, () => props.fallback);
|
|
113
458
|
return createMemo$1(() => {
|
|
114
459
|
const o = getOwner();
|
|
115
460
|
const id = o.id;
|
|
461
|
+
let assetPromise;
|
|
462
|
+
if (sharedConfig.hydrating && sharedConfig.has(id + "_assets")) {
|
|
463
|
+
const mapping = sharedConfig.load(id + "_assets");
|
|
464
|
+
if (mapping && typeof mapping === "object") assetPromise = loadModuleAssets(mapping);
|
|
465
|
+
}
|
|
116
466
|
if (sharedConfig.hydrating && sharedConfig.has(id)) {
|
|
117
467
|
let ref = sharedConfig.load(id);
|
|
118
468
|
let p;
|
|
@@ -120,24 +470,38 @@ function Loading(props) {
|
|
|
120
470
|
if (typeof ref !== "object" || ref.s !== 1) p = ref;else sharedConfig.gather(id);
|
|
121
471
|
}
|
|
122
472
|
if (p) {
|
|
123
|
-
|
|
124
|
-
|
|
473
|
+
_pendingBoundaries++;
|
|
474
|
+
onCleanup(() => {
|
|
475
|
+
if (!isDisposed(o)) return;
|
|
476
|
+
sharedConfig.cleanupFragment?.(id);
|
|
125
477
|
});
|
|
126
|
-
|
|
478
|
+
const set = createBoundaryTrigger();
|
|
127
479
|
if (p !== "$$f") {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
480
|
+
const waitFor = assetPromise ? Promise.all([p, assetPromise]) : p;
|
|
481
|
+
waitFor.then(() => resumeBoundaryHydration(o, id, set), err => {
|
|
482
|
+
_pendingBoundaries--;
|
|
483
|
+
checkHydrationComplete();
|
|
484
|
+
runWithOwner(o, () => {
|
|
485
|
+
throw err;
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
} else {
|
|
489
|
+
const afterAssets = () => {
|
|
490
|
+
_pendingBoundaries--;
|
|
131
491
|
set();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}));
|
|
137
|
-
} else queueMicrotask(set);
|
|
492
|
+
checkHydrationComplete();
|
|
493
|
+
};
|
|
494
|
+
if (assetPromise) assetPromise.then(() => queueMicrotask(afterAssets));else queueMicrotask(afterAssets);
|
|
495
|
+
}
|
|
138
496
|
return props.fallback;
|
|
139
497
|
}
|
|
140
498
|
}
|
|
499
|
+
if (assetPromise) {
|
|
500
|
+
_pendingBoundaries++;
|
|
501
|
+
const set = createBoundaryTrigger();
|
|
502
|
+
assetPromise.then(() => resumeBoundaryHydration(o, id, set));
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
141
505
|
return createLoadBoundary(() => props.children, () => props.fallback);
|
|
142
506
|
});
|
|
143
507
|
}
|
|
@@ -145,11 +509,24 @@ function Loading(props) {
|
|
|
145
509
|
function createComponent(Comp, props) {
|
|
146
510
|
return untrack(() => Comp(props || {}));
|
|
147
511
|
}
|
|
148
|
-
function lazy(fn) {
|
|
512
|
+
function lazy(fn, moduleUrl) {
|
|
149
513
|
let comp;
|
|
150
514
|
let p;
|
|
151
515
|
const wrap = props => {
|
|
152
|
-
|
|
516
|
+
if (sharedConfig.hydrating && moduleUrl) {
|
|
517
|
+
const cached = globalThis._$HY?.modules?.[moduleUrl];
|
|
518
|
+
if (!cached) {
|
|
519
|
+
throw new Error(`lazy() module "${moduleUrl}" was not preloaded before hydration. ` + "Ensure it is inside a Loading boundary.");
|
|
520
|
+
}
|
|
521
|
+
comp = () => cached.default;
|
|
522
|
+
}
|
|
523
|
+
if (!comp) {
|
|
524
|
+
p || (p = fn());
|
|
525
|
+
p.then(mod => {
|
|
526
|
+
comp = () => mod.default;
|
|
527
|
+
});
|
|
528
|
+
comp = createMemo$1(() => p.then(mod => mod.default));
|
|
529
|
+
}
|
|
153
530
|
let Comp;
|
|
154
531
|
return createMemo$1(() => (Comp = comp()) ? untrack(() => {
|
|
155
532
|
return Comp(props);
|
|
@@ -191,10 +568,15 @@ function Show(props) {
|
|
|
191
568
|
if (c) {
|
|
192
569
|
const child = props.children;
|
|
193
570
|
const fn = typeof child === "function" && child.length > 0;
|
|
194
|
-
return fn ? untrack(() =>
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
571
|
+
return fn ? untrack(() => {
|
|
572
|
+
try {
|
|
573
|
+
return child(() => {
|
|
574
|
+
if (!untrack(condition)) throw narrowedError("Show");
|
|
575
|
+
return conditionValue();
|
|
576
|
+
});
|
|
577
|
+
} finally {
|
|
578
|
+
}
|
|
579
|
+
}) : child;
|
|
198
580
|
}
|
|
199
581
|
return props.fallback;
|
|
200
582
|
}, undefined, undefined);
|
|
@@ -222,10 +604,15 @@ function Switch(props) {
|
|
|
222
604
|
const [index, conditionValue, mp] = sel;
|
|
223
605
|
const child = mp.children;
|
|
224
606
|
const fn = typeof child === "function" && child.length > 0;
|
|
225
|
-
return fn ? untrack(() =>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
607
|
+
return fn ? untrack(() => {
|
|
608
|
+
try {
|
|
609
|
+
return child(() => {
|
|
610
|
+
if (untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match");
|
|
611
|
+
return conditionValue();
|
|
612
|
+
});
|
|
613
|
+
} finally {
|
|
614
|
+
}
|
|
615
|
+
}) : child;
|
|
229
616
|
}, undefined, undefined);
|
|
230
617
|
}
|
|
231
618
|
function Match(props) {
|
|
@@ -242,4 +629,4 @@ function ssrHandleError() {}
|
|
|
242
629
|
function ssrRunInScope() {}
|
|
243
630
|
const DEV = undefined;
|
|
244
631
|
|
|
245
|
-
export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, children, createComponent, createContext, createMemo, createSignal, createUniqueId, enableHydration, lazy, sharedConfig, ssrHandleError, ssrRunInScope, useContext };
|
|
632
|
+
export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, children, createComponent, createContext, createMemo, createOptimistic, createOptimisticStore, createProjection, createSignal, createStore, createUniqueId, enableHydration, lazy, sharedConfig, ssrHandleError, ssrRunInScope, useContext };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solid-js",
|
|
3
3
|
"description": "A declarative JavaScript library for building user interfaces.",
|
|
4
|
-
"version": "2.0.0-experimental.
|
|
4
|
+
"version": "2.0.0-experimental.15",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://solidjs.com",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"performance"
|
|
80
80
|
],
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@solidjs/signals": "^0.10.
|
|
82
|
+
"@solidjs/signals": "^0.10.8",
|
|
83
83
|
"csstype": "^3.1.0",
|
|
84
84
|
"seroval": "~1.5.0",
|
|
85
85
|
"seroval-plugins": "~1.5.0"
|
|
@@ -66,7 +66,7 @@ export type Ref<T> = T | ((val: T) => void);
|
|
|
66
66
|
export declare function createComponent<T extends Record<string, any>>(Comp: Component<T>, props: T): JSX.Element;
|
|
67
67
|
export declare function lazy<T extends Component<any>>(fn: () => Promise<{
|
|
68
68
|
default: T;
|
|
69
|
-
}
|
|
69
|
+
}>, moduleUrl?: string): T & {
|
|
70
70
|
preload: () => Promise<{
|
|
71
71
|
default: T;
|
|
72
72
|
}>;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
import { createMemo as coreMemo, createSignal as coreSignal } from "@solidjs/signals";
|
|
1
|
+
import { createErrorBoundary as coreErrorBoundary, createMemo as coreMemo, createSignal as coreSignal, createOptimistic as coreOptimistic, type ProjectionOptions, type Store, type StoreSetter } from "@solidjs/signals";
|
|
2
2
|
import { JSX } from "../jsx.js";
|
|
3
|
-
|
|
3
|
+
declare module "@solidjs/signals" {
|
|
4
|
+
interface MemoOptions<T> {
|
|
5
|
+
deferStream?: boolean;
|
|
6
|
+
ssrSource?: "server" | "hybrid" | "initial" | "client";
|
|
7
|
+
}
|
|
8
|
+
interface SignalOptions<T> {
|
|
9
|
+
deferStream?: boolean;
|
|
10
|
+
ssrSource?: "server" | "hybrid" | "initial" | "client";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export type HydrationProjectionOptions = ProjectionOptions & {
|
|
14
|
+
ssrSource?: "server" | "hybrid" | "initial" | "client";
|
|
15
|
+
};
|
|
4
16
|
export type HydrationContext = {};
|
|
5
17
|
type SharedConfig = {
|
|
6
18
|
hydrating: boolean;
|
|
@@ -10,14 +22,33 @@ type SharedConfig = {
|
|
|
10
22
|
load?: (id: string) => Promise<any> | any;
|
|
11
23
|
has?: (id: string) => boolean;
|
|
12
24
|
gather?: (key: string) => void;
|
|
25
|
+
cleanupFragment?: (id: string) => void;
|
|
13
26
|
registry?: Map<string, Element>;
|
|
14
27
|
done: boolean;
|
|
15
28
|
getNextContextId(): string;
|
|
16
29
|
};
|
|
17
30
|
export declare const sharedConfig: SharedConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Registers a callback to run once when all hydration completes
|
|
33
|
+
* (all boundaries hydrated or cancelled). If hydration is already
|
|
34
|
+
* complete (or not hydrating), fires via queueMicrotask.
|
|
35
|
+
*/
|
|
36
|
+
export declare function onHydrationEnd(callback: () => void): void;
|
|
18
37
|
export declare function enableHydration(): void;
|
|
19
38
|
export declare const createMemo: typeof coreMemo;
|
|
20
39
|
export declare const createSignal: typeof coreSignal;
|
|
40
|
+
export declare const createErrorBoundary: typeof coreErrorBoundary;
|
|
41
|
+
export declare const createOptimistic: typeof coreOptimistic;
|
|
42
|
+
export declare const createProjection: <T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, initialValue?: T, options?: HydrationProjectionOptions) => Store<T>;
|
|
43
|
+
type NoFn<T> = T extends Function ? never : T;
|
|
44
|
+
export declare const createStore: {
|
|
45
|
+
<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): [get: Store<T>, set: StoreSetter<T>];
|
|
46
|
+
<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store?: NoFn<T> | Store<NoFn<T>>, options?: HydrationProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
|
|
47
|
+
};
|
|
48
|
+
export declare const createOptimisticStore: {
|
|
49
|
+
<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): [get: Store<T>, set: StoreSetter<T>];
|
|
50
|
+
<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store?: NoFn<T> | Store<NoFn<T>>, options?: HydrationProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
|
|
51
|
+
};
|
|
21
52
|
/**
|
|
22
53
|
* Tracks all resources inside a component and renders a fallback until they are all resolved
|
|
23
54
|
* ```typescript
|
|
@@ -33,3 +64,4 @@ export declare function Loading(props: {
|
|
|
33
64
|
fallback?: JSX.Element;
|
|
34
65
|
children: JSX.Element;
|
|
35
66
|
}): JSX.Element;
|
|
67
|
+
export {};
|
|
@@ -50,11 +50,15 @@ export type Ref<T> = T | ((val: T) => void);
|
|
|
50
50
|
export declare function createComponent<T extends Record<string, any>>(Comp: Component<T>, props: T): JSX.Element;
|
|
51
51
|
/**
|
|
52
52
|
* Lazy load a function component asynchronously.
|
|
53
|
-
* On server,
|
|
53
|
+
* On server, returns a createMemo that throws NotReadyError until the module resolves,
|
|
54
|
+
* allowing resolveSSRNode to capture it as a fine-grained hole. The memo naturally
|
|
55
|
+
* scopes the owner so hydration IDs align with the client's createMemo in lazy().
|
|
56
|
+
* Requires `moduleUrl` for SSR — the bundler plugin injects the module specifier
|
|
57
|
+
* so the server can look up client chunk URLs from the asset manifest.
|
|
54
58
|
*/
|
|
55
59
|
export declare function lazy<T extends Component<any>>(fn: () => Promise<{
|
|
56
60
|
default: T;
|
|
57
|
-
}
|
|
61
|
+
}>, moduleUrl?: string): T & {
|
|
58
62
|
preload: () => Promise<{
|
|
59
63
|
default: T;
|
|
60
64
|
}>;
|
package/types/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { $PROXY, $TRACK, action, createEffect, createMemo, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isRefreshing, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, NotReadyError, runWithOwner, snapshot, untrack } from "./signals.js";
|
|
2
|
-
export type { Accessor, ComputeFunction, EffectFunction, EffectOptions, Merge, NoInfer, NotWrappable, Omit, Owner, Signal, SignalOptions, Setter, Store, SolidStore, StoreNode, StoreSetter } from "./signals.js";
|
|
1
|
+
export { $PROXY, $TRACK, action, createEffect, createMemo, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isRefreshing, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, NotReadyError, runWithOwner, snapshot, createDeepProxy, untrack } from "./signals.js";
|
|
2
|
+
export type { Accessor, ComputeFunction, EffectFunction, EffectOptions, Merge, NoInfer, NotWrappable, Omit, Owner, Signal, SignalOptions, Setter, Store, SolidStore, StoreNode, StoreSetter, PatchOp } from "./signals.js";
|
|
3
3
|
export { $DEVCOMP, children, createContext, useContext, ssrRunInScope } from "./core.js";
|
|
4
4
|
export type { ChildrenReturn, Context, ContextProviderComponent, ResolvedChildren, ResolvedJSXElement } from "./core.js";
|
|
5
5
|
export * from "./component.js";
|
package/types/server/shared.d.ts
CHANGED
|
@@ -6,13 +6,34 @@ type SSRTemplateObject = {
|
|
|
6
6
|
export type HydrationContext = {
|
|
7
7
|
id: string;
|
|
8
8
|
count: number;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Serialize a value for client hydration.
|
|
11
|
+
* In renderToStream (async: true), accepts promises and async iterables.
|
|
12
|
+
* In renderToString (async: false), only synchronous values are allowed —
|
|
13
|
+
* passing async values will throw.
|
|
14
|
+
*/
|
|
15
|
+
serialize: (id: string, v: any, deferStream?: boolean) => void;
|
|
10
16
|
resolve(value: any): SSRTemplateObject;
|
|
11
17
|
ssr(template: string[], ...values: any[]): SSRTemplateObject;
|
|
12
18
|
escape(value: any): string;
|
|
13
19
|
replace: (id: string, replacement: () => any) => void;
|
|
14
20
|
block: (p: Promise<any>) => void;
|
|
15
21
|
registerFragment: (v: string) => (v?: string, err?: any) => boolean;
|
|
22
|
+
/** Register a client-side asset URL discovered during SSR (e.g. from lazy()). */
|
|
23
|
+
registerAsset?: (type: "module" | "style", url: string) => void;
|
|
24
|
+
/** Register a moduleUrl-to-entryUrl mapping for the current boundary. */
|
|
25
|
+
registerModule?: (moduleUrl: string, entryUrl: string) => void;
|
|
26
|
+
/** Resolve a module's JS and CSS assets from the asset manifest. Set by dom-expressions. */
|
|
27
|
+
resolveAssets?: (moduleUrl: string) => {
|
|
28
|
+
js: string[];
|
|
29
|
+
css: string[];
|
|
30
|
+
} | null;
|
|
31
|
+
/** Retrieve the moduleUrl-to-entryUrl map for a boundary. */
|
|
32
|
+
getBoundaryModules?: (id: string) => Record<string, string> | null;
|
|
33
|
+
/** @internal Tracks which Loading boundary is currently rendering. Set by dom-expressions via applyAssetTracking(). */
|
|
34
|
+
_currentBoundaryId?: string | null;
|
|
35
|
+
assets: any[];
|
|
36
|
+
/** True only in renderToStream — enables async data serialization and streaming. */
|
|
16
37
|
async?: boolean;
|
|
17
38
|
noHydrate: boolean;
|
|
18
39
|
};
|