@async/framework 0.11.1 → 0.11.2
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/CHANGELOG.md +16 -0
- package/browser.js +184 -28
- package/browser.min.js +1 -1
- package/browser.ts +184 -28
- package/browser.umd.js +184 -28
- package/browser.umd.min.js +1 -1
- package/framework.ts +184 -28
- package/package.json +4 -3
- package/server.js +184 -28
package/browser.ts
CHANGED
|
@@ -186,6 +186,24 @@ const __asyncSignalModule = (() => {
|
|
|
186
186
|
};
|
|
187
187
|
},
|
|
188
188
|
|
|
189
|
+
_restore(snapshot = {}) {
|
|
190
|
+
if (!isAsyncSignalSnapshot(snapshot)) {
|
|
191
|
+
return state.set(snapshot);
|
|
192
|
+
}
|
|
193
|
+
if (activeAbort && !activeAbort.aborted) {
|
|
194
|
+
activeAbort.cancel(new Error(`Async signal "${registeredId}" restored from snapshot.`));
|
|
195
|
+
}
|
|
196
|
+
value = snapshot.value;
|
|
197
|
+
loading = Boolean(snapshot.loading);
|
|
198
|
+
error = snapshot.error ?? null;
|
|
199
|
+
status = typeof snapshot.status === "string" ? snapshot.status : inferStatus({ value, loading, error });
|
|
200
|
+
if (Number.isFinite(snapshot.version)) {
|
|
201
|
+
version = snapshot.version;
|
|
202
|
+
}
|
|
203
|
+
notify();
|
|
204
|
+
return state;
|
|
205
|
+
},
|
|
206
|
+
|
|
189
207
|
_bindRegistry(nextRegistry, nextId) {
|
|
190
208
|
registry = nextRegistry;
|
|
191
209
|
registeredId = nextId;
|
|
@@ -271,6 +289,27 @@ const __asyncSignalModule = (() => {
|
|
|
271
289
|
return Boolean(value?.[asyncSignalKind]);
|
|
272
290
|
}
|
|
273
291
|
|
|
292
|
+
function isAsyncSignalSnapshot(value) {
|
|
293
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
return Object.hasOwn(value, "value")
|
|
297
|
+
&& (Object.hasOwn(value, "loading")
|
|
298
|
+
|| Object.hasOwn(value, "error")
|
|
299
|
+
|| Object.hasOwn(value, "status")
|
|
300
|
+
|| Object.hasOwn(value, "version"));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function inferStatus({ value, loading, error }) {
|
|
304
|
+
if (loading) {
|
|
305
|
+
return "loading";
|
|
306
|
+
}
|
|
307
|
+
if (error) {
|
|
308
|
+
return "error";
|
|
309
|
+
}
|
|
310
|
+
return value === undefined ? "idle" : "ready";
|
|
311
|
+
}
|
|
312
|
+
|
|
274
313
|
function attachCancel(signal, controller) {
|
|
275
314
|
Object.defineProperty(signal, "cancel", {
|
|
276
315
|
configurable: true,
|
|
@@ -1909,12 +1948,16 @@ const __componentModule = (() => {
|
|
|
1909
1948
|
});
|
|
1910
1949
|
|
|
1911
1950
|
const output = Component.call(context, props);
|
|
1951
|
+
if (output && typeof output.then === "function") {
|
|
1952
|
+
throw new TypeError(`Component "${componentName(Component)}" returned a Promise. Async components are not supported by synchronous renderComponent(). Use an async partial or handler instead.`);
|
|
1953
|
+
}
|
|
1912
1954
|
const html = renderScopedTemplate(output);
|
|
1913
1955
|
|
|
1914
1956
|
return {
|
|
1915
1957
|
html,
|
|
1916
1958
|
attach(target) {
|
|
1917
|
-
for (
|
|
1959
|
+
for (let index = 0; index < attachHooks.length; index += 1) {
|
|
1960
|
+
const hook = attachHooks[index];
|
|
1918
1961
|
runtime.scheduler?.enqueue("lifecycle", () => {
|
|
1919
1962
|
const cleanup = hook(target);
|
|
1920
1963
|
if (typeof cleanup === "function") {
|
|
@@ -1922,7 +1965,7 @@ const __componentModule = (() => {
|
|
|
1922
1965
|
}
|
|
1923
1966
|
}, {
|
|
1924
1967
|
scope,
|
|
1925
|
-
key: `attach:${
|
|
1968
|
+
key: `attach:${index}`
|
|
1926
1969
|
}) ?? runAttachHook(hook, target);
|
|
1927
1970
|
}
|
|
1928
1971
|
},
|
|
@@ -1930,8 +1973,12 @@ const __componentModule = (() => {
|
|
|
1930
1973
|
this.attach(target);
|
|
1931
1974
|
},
|
|
1932
1975
|
visible(target, observeVisible) {
|
|
1933
|
-
|
|
1934
|
-
|
|
1976
|
+
if (visibleHooks.length === 0) {
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
const cleanup = observeVisible(target, () => {
|
|
1980
|
+
for (let index = 0; index < visibleHooks.length; index += 1) {
|
|
1981
|
+
const hook = visibleHooks[index];
|
|
1935
1982
|
runtime.scheduler?.enqueue("lifecycle", () => {
|
|
1936
1983
|
const hookCleanup = hook(target);
|
|
1937
1984
|
if (typeof hookCleanup === "function") {
|
|
@@ -1939,12 +1986,12 @@ const __componentModule = (() => {
|
|
|
1939
1986
|
}
|
|
1940
1987
|
}, {
|
|
1941
1988
|
scope,
|
|
1942
|
-
key: `visible:${
|
|
1989
|
+
key: `visible:${index}`
|
|
1943
1990
|
}) ?? runVisibleHook(hook, target);
|
|
1944
|
-
});
|
|
1945
|
-
if (typeof cleanup === "function") {
|
|
1946
|
-
cleanups.push(cleanup);
|
|
1947
1991
|
}
|
|
1992
|
+
});
|
|
1993
|
+
if (typeof cleanup === "function") {
|
|
1994
|
+
cleanups.push(cleanup);
|
|
1948
1995
|
}
|
|
1949
1996
|
},
|
|
1950
1997
|
cleanup() {
|
|
@@ -2200,11 +2247,12 @@ const __serverModule = (() => {
|
|
|
2200
2247
|
signal: context.abort
|
|
2201
2248
|
});
|
|
2202
2249
|
|
|
2250
|
+
assertTransportResponse(id, response);
|
|
2203
2251
|
if (!response.ok) {
|
|
2204
2252
|
throw new Error(`Server function "${id}" failed with ${response.status}.`);
|
|
2205
2253
|
}
|
|
2206
2254
|
|
|
2207
|
-
const result = await readServerResponse(response);
|
|
2255
|
+
const result = await readServerResponse(id, response);
|
|
2208
2256
|
await applyServerResult(result, runContext);
|
|
2209
2257
|
return markAppliedServerValue(unwrapServerResult(result));
|
|
2210
2258
|
}
|
|
@@ -2245,6 +2293,11 @@ const __serverModule = (() => {
|
|
|
2245
2293
|
return result;
|
|
2246
2294
|
}
|
|
2247
2295
|
|
|
2296
|
+
if (result.error) {
|
|
2297
|
+
markAppliedServerResult(result);
|
|
2298
|
+
throw toError(result.error);
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2248
2301
|
if (result.signals && context.signals) {
|
|
2249
2302
|
for (const [path, value] of Object.entries(result.signals)) {
|
|
2250
2303
|
context.signals.set?.(path, value);
|
|
@@ -2263,15 +2316,7 @@ const __serverModule = (() => {
|
|
|
2263
2316
|
await context.router?.navigate?.(result.redirect);
|
|
2264
2317
|
}
|
|
2265
2318
|
|
|
2266
|
-
|
|
2267
|
-
throw toError(result.error);
|
|
2268
|
-
}
|
|
2269
|
-
|
|
2270
|
-
Object.defineProperty(result, appliedServerResult, {
|
|
2271
|
-
configurable: true,
|
|
2272
|
-
enumerable: false,
|
|
2273
|
-
value: true
|
|
2274
|
-
});
|
|
2319
|
+
markAppliedServerResult(result);
|
|
2275
2320
|
|
|
2276
2321
|
return result;
|
|
2277
2322
|
}
|
|
@@ -2290,6 +2335,15 @@ const __serverModule = (() => {
|
|
|
2290
2335
|
return value;
|
|
2291
2336
|
}
|
|
2292
2337
|
|
|
2338
|
+
function markAppliedServerResult(result) {
|
|
2339
|
+
Object.defineProperty(result, appliedServerResult, {
|
|
2340
|
+
configurable: true,
|
|
2341
|
+
enumerable: false,
|
|
2342
|
+
value: true
|
|
2343
|
+
});
|
|
2344
|
+
return result;
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2293
2347
|
function defaultInput(context = {}) {
|
|
2294
2348
|
const form = findForm(context);
|
|
2295
2349
|
if (form) {
|
|
@@ -2367,10 +2421,37 @@ const __serverModule = (() => {
|
|
|
2367
2421
|
return namespace([]);
|
|
2368
2422
|
}
|
|
2369
2423
|
|
|
2370
|
-
|
|
2424
|
+
function assertTransportResponse(id, response) {
|
|
2425
|
+
if (!response || typeof response !== "object") {
|
|
2426
|
+
throw new Error(`Server function "${id}" transport returned an invalid response: expected a fetch Response-like object.`);
|
|
2427
|
+
}
|
|
2428
|
+
if (typeof response.ok !== "boolean") {
|
|
2429
|
+
throw new Error(`Server function "${id}" transport returned an invalid response: missing boolean ok.`);
|
|
2430
|
+
}
|
|
2431
|
+
if (!response.headers || typeof response.headers.get !== "function") {
|
|
2432
|
+
throw new Error(`Server function "${id}" transport returned an invalid response: missing headers.get(name).`);
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
async function readServerResponse(id, response) {
|
|
2437
|
+
if (response.status === 204) {
|
|
2438
|
+
return { value: undefined };
|
|
2439
|
+
}
|
|
2371
2440
|
const type = response.headers.get("content-type") ?? "";
|
|
2372
2441
|
if (type.includes("application/json")) {
|
|
2373
|
-
|
|
2442
|
+
if (typeof response.json !== "function") {
|
|
2443
|
+
throw new Error(`Server function "${id}" transport returned an invalid response: missing json().`);
|
|
2444
|
+
}
|
|
2445
|
+
try {
|
|
2446
|
+
return await response.json();
|
|
2447
|
+
} catch (cause) {
|
|
2448
|
+
throw new Error(`Server function "${id}" returned invalid JSON: ${errorMessage(cause)}`, {
|
|
2449
|
+
cause
|
|
2450
|
+
});
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
if (typeof response.text !== "function") {
|
|
2454
|
+
throw new Error(`Server function "${id}" transport returned an invalid response: missing text().`);
|
|
2374
2455
|
}
|
|
2375
2456
|
return { value: await response.text() };
|
|
2376
2457
|
}
|
|
@@ -2483,6 +2564,9 @@ const __serverModule = (() => {
|
|
|
2483
2564
|
if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
|
|
2484
2565
|
throw new Error("Server proxy JSON transport does not support File, Blob, or FormData values yet.");
|
|
2485
2566
|
}
|
|
2567
|
+
if (isUnsupportedJsonTransportObject(value, tag)) {
|
|
2568
|
+
throw new Error("Server proxy JSON transport does not support URLSearchParams, Headers, Request, Response, ReadableStream, ArrayBuffer, or typed array values yet.");
|
|
2569
|
+
}
|
|
2486
2570
|
if (Array.isArray(value)) {
|
|
2487
2571
|
for (const item of value) {
|
|
2488
2572
|
assertJsonTransportable(item, stack);
|
|
@@ -2496,6 +2580,16 @@ const __serverModule = (() => {
|
|
|
2496
2580
|
stack.delete(value);
|
|
2497
2581
|
}
|
|
2498
2582
|
|
|
2583
|
+
function isUnsupportedJsonTransportObject(value, tag = Object.prototype.toString.call(value)) {
|
|
2584
|
+
return tag === "[object URLSearchParams]"
|
|
2585
|
+
|| tag === "[object Headers]"
|
|
2586
|
+
|| tag === "[object Request]"
|
|
2587
|
+
|| tag === "[object Response]"
|
|
2588
|
+
|| tag === "[object ReadableStream]"
|
|
2589
|
+
|| tag === "[object ArrayBuffer]"
|
|
2590
|
+
|| ArrayBuffer.isView(value);
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2499
2593
|
function joinEndpoint(endpoint, id) {
|
|
2500
2594
|
return `${String(endpoint).replace(/\/$/, "")}/${encodeURIComponent(id)}`;
|
|
2501
2595
|
}
|
|
@@ -2517,6 +2611,10 @@ const __serverModule = (() => {
|
|
|
2517
2611
|
return new Error(String(value));
|
|
2518
2612
|
}
|
|
2519
2613
|
|
|
2614
|
+
function errorMessage(error) {
|
|
2615
|
+
return error instanceof Error ? error.message : String(error);
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2520
2618
|
function assertServerId(id) {
|
|
2521
2619
|
if (typeof id !== "string" || id.length === 0) {
|
|
2522
2620
|
throw new TypeError("Server function id must be a non-empty string.");
|
|
@@ -2749,7 +2847,8 @@ const __schedulerModule = (() => {
|
|
|
2749
2847
|
const phases = [...(options.phases ?? defaultPhases)];
|
|
2750
2848
|
const queues = new Map(phases.map((phase) => [phase, []]));
|
|
2751
2849
|
const keyedJobs = new Map();
|
|
2752
|
-
const
|
|
2850
|
+
const destroyedObjectScopes = new WeakSet();
|
|
2851
|
+
const destroyedPrimitiveScopes = new Set();
|
|
2753
2852
|
const objectScopeIds = new WeakMap();
|
|
2754
2853
|
const onError = typeof options.onError === "function" ? options.onError : undefined;
|
|
2755
2854
|
const maxDepth = options.maxDepth ?? 100;
|
|
@@ -2797,7 +2896,7 @@ const __schedulerModule = (() => {
|
|
|
2797
2896
|
throw new TypeError("scheduler.enqueue(phase, fn) requires a function.");
|
|
2798
2897
|
}
|
|
2799
2898
|
const scope = options.scope;
|
|
2800
|
-
if (
|
|
2899
|
+
if (isScopeDestroyed(scope)) {
|
|
2801
2900
|
return noop;
|
|
2802
2901
|
}
|
|
2803
2902
|
|
|
@@ -2901,14 +3000,29 @@ const __schedulerModule = (() => {
|
|
|
2901
3000
|
|
|
2902
3001
|
markScopeDestroyed(scope) {
|
|
2903
3002
|
if (scope !== undefined) {
|
|
2904
|
-
|
|
3003
|
+
if (isObjectScope(scope)) {
|
|
3004
|
+
destroyedObjectScopes.add(scope);
|
|
3005
|
+
} else {
|
|
3006
|
+
destroyedPrimitiveScopes.add(scope);
|
|
3007
|
+
}
|
|
2905
3008
|
api.cancelScope(scope);
|
|
2906
3009
|
}
|
|
2907
3010
|
return api;
|
|
2908
3011
|
},
|
|
2909
3012
|
|
|
3013
|
+
reviveScope(scope) {
|
|
3014
|
+
if (scope !== undefined) {
|
|
3015
|
+
if (isObjectScope(scope)) {
|
|
3016
|
+
destroyedObjectScopes.delete(scope);
|
|
3017
|
+
} else {
|
|
3018
|
+
destroyedPrimitiveScopes.delete(scope);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
return api;
|
|
3022
|
+
},
|
|
3023
|
+
|
|
2910
3024
|
isScopeDestroyed(scope) {
|
|
2911
|
-
return
|
|
3025
|
+
return isScopeDestroyed(scope);
|
|
2912
3026
|
},
|
|
2913
3027
|
|
|
2914
3028
|
inspect() {
|
|
@@ -2920,7 +3034,7 @@ const __schedulerModule = (() => {
|
|
|
2920
3034
|
strategy,
|
|
2921
3035
|
phases: [...phases],
|
|
2922
3036
|
pending: counts,
|
|
2923
|
-
scopesDestroyed:
|
|
3037
|
+
scopesDestroyed: destroyedPrimitiveScopes.size,
|
|
2924
3038
|
flushing,
|
|
2925
3039
|
scheduled
|
|
2926
3040
|
};
|
|
@@ -2935,7 +3049,7 @@ const __schedulerModule = (() => {
|
|
|
2935
3049
|
queue.length = 0;
|
|
2936
3050
|
}
|
|
2937
3051
|
keyedJobs.clear();
|
|
2938
|
-
|
|
3052
|
+
destroyedPrimitiveScopes.clear();
|
|
2939
3053
|
}
|
|
2940
3054
|
};
|
|
2941
3055
|
|
|
@@ -2975,7 +3089,7 @@ const __schedulerModule = (() => {
|
|
|
2975
3089
|
if (job.key) {
|
|
2976
3090
|
keyedJobs.delete(job.key);
|
|
2977
3091
|
}
|
|
2978
|
-
if (job.canceled || (job.scope
|
|
3092
|
+
if (job.canceled || isScopeDestroyed(job.scope)) {
|
|
2979
3093
|
continue;
|
|
2980
3094
|
}
|
|
2981
3095
|
try {
|
|
@@ -3032,6 +3146,20 @@ const __schedulerModule = (() => {
|
|
|
3032
3146
|
}
|
|
3033
3147
|
return String(scope);
|
|
3034
3148
|
}
|
|
3149
|
+
|
|
3150
|
+
function isScopeDestroyed(scope) {
|
|
3151
|
+
if (scope === undefined) {
|
|
3152
|
+
return false;
|
|
3153
|
+
}
|
|
3154
|
+
if (isObjectScope(scope)) {
|
|
3155
|
+
return destroyedObjectScopes.has(scope);
|
|
3156
|
+
}
|
|
3157
|
+
return destroyedPrimitiveScopes.has(scope);
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
function isObjectScope(scope) {
|
|
3162
|
+
return (typeof scope === "object" && scope !== null) || typeof scope === "function";
|
|
3035
3163
|
}
|
|
3036
3164
|
|
|
3037
3165
|
function scheduleMicrotask(fn) {
|
|
@@ -3092,6 +3220,7 @@ const __loaderModule = (() => {
|
|
|
3092
3220
|
|
|
3093
3221
|
scan(rootOrFragment = rootNode) {
|
|
3094
3222
|
assertActive();
|
|
3223
|
+
reviveScopes(rootOrFragment);
|
|
3095
3224
|
bindSignalAttributes(rootOrFragment);
|
|
3096
3225
|
bindClassAttributes(rootOrFragment);
|
|
3097
3226
|
bindEventAttributes(rootOrFragment);
|
|
@@ -3595,6 +3724,12 @@ const __loaderModule = (() => {
|
|
|
3595
3724
|
}
|
|
3596
3725
|
}
|
|
3597
3726
|
|
|
3727
|
+
function reviveScopes(scope) {
|
|
3728
|
+
for (const element of elementsIn(scope)) {
|
|
3729
|
+
schedulerInstance.reviveScope?.(element);
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3598
3733
|
return api;
|
|
3599
3734
|
}
|
|
3600
3735
|
|
|
@@ -4158,7 +4293,10 @@ const __routerModule = (() => {
|
|
|
4158
4293
|
}
|
|
4159
4294
|
const matched = api.match(url);
|
|
4160
4295
|
if (matched?.route?.partial && partials?.resolve?.(matched.route.partial)) {
|
|
4161
|
-
return partials.render(matched.route.partial, matched.params,
|
|
4296
|
+
return partials.render(matched.route.partial, matched.params, {
|
|
4297
|
+
...contextFor(matched),
|
|
4298
|
+
prefetch: true
|
|
4299
|
+
});
|
|
4162
4300
|
}
|
|
4163
4301
|
return Promise.resolve(null);
|
|
4164
4302
|
},
|
|
@@ -5194,6 +5332,13 @@ const __appModule = (() => {
|
|
|
5194
5332
|
function setOrRegisterSignal(signals, path, value) {
|
|
5195
5333
|
const id = String(path).split(".")[0];
|
|
5196
5334
|
if (signals.has?.(id)) {
|
|
5335
|
+
if (path === id) {
|
|
5336
|
+
const entry = signals._entry?.(id);
|
|
5337
|
+
if (typeof entry?._restore === "function" && isAsyncSignalSnapshot(value)) {
|
|
5338
|
+
entry._restore(value);
|
|
5339
|
+
return;
|
|
5340
|
+
}
|
|
5341
|
+
}
|
|
5197
5342
|
signals.set(path, value);
|
|
5198
5343
|
return;
|
|
5199
5344
|
}
|
|
@@ -5203,6 +5348,17 @@ const __appModule = (() => {
|
|
|
5203
5348
|
}
|
|
5204
5349
|
}
|
|
5205
5350
|
|
|
5351
|
+
function isAsyncSignalSnapshot(value) {
|
|
5352
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5353
|
+
return false;
|
|
5354
|
+
}
|
|
5355
|
+
return Object.hasOwn(value, "value")
|
|
5356
|
+
&& (Object.hasOwn(value, "loading")
|
|
5357
|
+
|| Object.hasOwn(value, "error")
|
|
5358
|
+
|| Object.hasOwn(value, "status")
|
|
5359
|
+
|| Object.hasOwn(value, "version"));
|
|
5360
|
+
}
|
|
5361
|
+
|
|
5206
5362
|
function attachServerCache(server, cache) {
|
|
5207
5363
|
try {
|
|
5208
5364
|
server.cache = cache;
|