@async/framework 0.10.0 → 0.10.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 +24 -1
- package/browser.js +126 -50
- package/browser.min.js +1 -1
- package/browser.ts +126 -50
- package/browser.umd.js +126 -50
- package/browser.umd.min.js +1 -1
- package/package.json +11 -4
- package/src/cache.js +18 -14
- package/src/lazy-registry.js +16 -2
- package/src/loader.js +7 -0
- package/src/router.js +74 -28
- package/src/server.js +11 -6
package/browser.ts
CHANGED
|
@@ -319,10 +319,20 @@ const __lazyRegistryModule = (() => {
|
|
|
319
319
|
const resolved = resolveDescriptorUrl(type, id, descriptor, registryAssets);
|
|
320
320
|
let modulePromise = moduleCache.get(resolved.moduleUrl);
|
|
321
321
|
if (!modulePromise) {
|
|
322
|
-
modulePromise = Promise.resolve(importModule(resolved.moduleUrl));
|
|
322
|
+
modulePromise = Promise.resolve().then(() => importModule(resolved.moduleUrl));
|
|
323
323
|
moduleCache.set(resolved.moduleUrl, modulePromise);
|
|
324
324
|
}
|
|
325
|
-
|
|
325
|
+
let module;
|
|
326
|
+
try {
|
|
327
|
+
module = await modulePromise;
|
|
328
|
+
} catch (cause) {
|
|
329
|
+
if (moduleCache.get(resolved.moduleUrl) === modulePromise) {
|
|
330
|
+
moduleCache.delete(resolved.moduleUrl);
|
|
331
|
+
}
|
|
332
|
+
throw new Error(`Lazy ${type} "${id}" failed to import ${resolved.moduleUrl}: ${errorMessage(cause)}`, {
|
|
333
|
+
cause
|
|
334
|
+
});
|
|
335
|
+
}
|
|
326
336
|
const value = resolveExport(module, resolved.exportNames, type, id);
|
|
327
337
|
exportCache.set(cacheKey, value);
|
|
328
338
|
return value;
|
|
@@ -482,6 +492,10 @@ const __lazyRegistryModule = (() => {
|
|
|
482
492
|
return /^[A-Za-z][A-Za-z\d+.-]*:/.test(value);
|
|
483
493
|
}
|
|
484
494
|
|
|
495
|
+
function errorMessage(error) {
|
|
496
|
+
return error instanceof Error ? error.message : String(error);
|
|
497
|
+
}
|
|
498
|
+
|
|
485
499
|
function stableStringify(value) {
|
|
486
500
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
487
501
|
return JSON.stringify(value);
|
|
@@ -810,15 +824,7 @@ const __cacheModule = (() => {
|
|
|
810
824
|
|
|
811
825
|
get(key) {
|
|
812
826
|
assertKey(key);
|
|
813
|
-
|
|
814
|
-
if (!entry) {
|
|
815
|
-
return undefined;
|
|
816
|
-
}
|
|
817
|
-
if (entry.expiresAt !== undefined && entry.expiresAt <= now()) {
|
|
818
|
-
entries.delete(key);
|
|
819
|
-
return undefined;
|
|
820
|
-
}
|
|
821
|
-
return entry.value;
|
|
827
|
+
return readEntry(key).value;
|
|
822
828
|
},
|
|
823
829
|
|
|
824
830
|
set(key, value, options = {}) {
|
|
@@ -836,9 +842,9 @@ const __cacheModule = (() => {
|
|
|
836
842
|
if (typeof fn !== "function") {
|
|
837
843
|
throw new TypeError("cache.getOrSet(key, fn) requires a function.");
|
|
838
844
|
}
|
|
839
|
-
const cached =
|
|
840
|
-
if (cached
|
|
841
|
-
return cached;
|
|
845
|
+
const cached = readEntry(key);
|
|
846
|
+
if (cached.found) {
|
|
847
|
+
return cached.value;
|
|
842
848
|
}
|
|
843
849
|
if (pending.has(key)) {
|
|
844
850
|
return pending.get(key);
|
|
@@ -889,8 +895,8 @@ const __cacheModule = (() => {
|
|
|
889
895
|
snapshot() {
|
|
890
896
|
const snapshot = {};
|
|
891
897
|
for (const [key] of entries) {
|
|
892
|
-
const value =
|
|
893
|
-
if (value !== undefined) {
|
|
898
|
+
const { found, value } = readEntry(key);
|
|
899
|
+
if (found && value !== undefined) {
|
|
894
900
|
snapshot[key] = value;
|
|
895
901
|
}
|
|
896
902
|
}
|
|
@@ -930,6 +936,18 @@ const __cacheModule = (() => {
|
|
|
930
936
|
const prefix = key.split(":")[0];
|
|
931
937
|
return definitions.get(prefix);
|
|
932
938
|
}
|
|
939
|
+
|
|
940
|
+
function readEntry(key) {
|
|
941
|
+
const entry = entries.get(key);
|
|
942
|
+
if (!entry) {
|
|
943
|
+
return { found: false, value: undefined };
|
|
944
|
+
}
|
|
945
|
+
if (entry.expiresAt !== undefined && entry.expiresAt <= now()) {
|
|
946
|
+
entries.delete(key);
|
|
947
|
+
return { found: false, value: undefined };
|
|
948
|
+
}
|
|
949
|
+
return { found: true, value: entry.value };
|
|
950
|
+
}
|
|
933
951
|
}
|
|
934
952
|
|
|
935
953
|
function normalizeDefinition(definition) {
|
|
@@ -2449,14 +2467,17 @@ const __serverModule = (() => {
|
|
|
2449
2467
|
return output;
|
|
2450
2468
|
}
|
|
2451
2469
|
|
|
2452
|
-
function assertJsonTransportable(value,
|
|
2470
|
+
function assertJsonTransportable(value, stack = new Set()) {
|
|
2471
|
+
if (typeof value === "bigint") {
|
|
2472
|
+
throw new Error("Server proxy JSON transport does not support BigInt values.");
|
|
2473
|
+
}
|
|
2453
2474
|
if (value == null || typeof value !== "object") {
|
|
2454
2475
|
return;
|
|
2455
2476
|
}
|
|
2456
|
-
if (
|
|
2457
|
-
|
|
2477
|
+
if (stack.has(value)) {
|
|
2478
|
+
throw new Error("Server proxy JSON transport does not support circular values.");
|
|
2458
2479
|
}
|
|
2459
|
-
|
|
2480
|
+
stack.add(value);
|
|
2460
2481
|
|
|
2461
2482
|
const tag = Object.prototype.toString.call(value);
|
|
2462
2483
|
if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
|
|
@@ -2464,13 +2485,15 @@ const __serverModule = (() => {
|
|
|
2464
2485
|
}
|
|
2465
2486
|
if (Array.isArray(value)) {
|
|
2466
2487
|
for (const item of value) {
|
|
2467
|
-
assertJsonTransportable(item,
|
|
2488
|
+
assertJsonTransportable(item, stack);
|
|
2468
2489
|
}
|
|
2490
|
+
stack.delete(value);
|
|
2469
2491
|
return;
|
|
2470
2492
|
}
|
|
2471
2493
|
for (const item of Object.values(value)) {
|
|
2472
|
-
assertJsonTransportable(item,
|
|
2494
|
+
assertJsonTransportable(item, stack);
|
|
2473
2495
|
}
|
|
2496
|
+
stack.delete(value);
|
|
2474
2497
|
}
|
|
2475
2498
|
|
|
2476
2499
|
function joinEndpoint(endpoint, id) {
|
|
@@ -3115,6 +3138,7 @@ const __loaderModule = (() => {
|
|
|
3115
3138
|
return;
|
|
3116
3139
|
}
|
|
3117
3140
|
destroyed = true;
|
|
3141
|
+
markDestroyedScopes(rootNode);
|
|
3118
3142
|
for (const cleanup of [...cleanups]) {
|
|
3119
3143
|
runCleanup(cleanup);
|
|
3120
3144
|
}
|
|
@@ -3565,6 +3589,12 @@ const __loaderModule = (() => {
|
|
|
3565
3589
|
});
|
|
3566
3590
|
}
|
|
3567
3591
|
|
|
3592
|
+
function markDestroyedScopes(scope) {
|
|
3593
|
+
for (const element of elementsIn(scope)) {
|
|
3594
|
+
schedulerInstance.markScopeDestroyed(element);
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
|
|
3568
3598
|
return api;
|
|
3569
3599
|
}
|
|
3570
3600
|
|
|
@@ -3990,7 +4020,7 @@ const __routerModule = (() => {
|
|
|
3990
4020
|
}
|
|
3991
4021
|
const params = {};
|
|
3992
4022
|
candidate.keys.forEach((key, index) => {
|
|
3993
|
-
params[key] =
|
|
4023
|
+
params[key] = safeDecodeURIComponent(match[index + 1] ?? "");
|
|
3994
4024
|
});
|
|
3995
4025
|
return {
|
|
3996
4026
|
pattern: candidate.pattern,
|
|
@@ -4105,11 +4135,11 @@ const __routerModule = (() => {
|
|
|
4105
4135
|
}
|
|
4106
4136
|
bindNavigation();
|
|
4107
4137
|
if (mode === "csr") {
|
|
4108
|
-
|
|
4138
|
+
handleNavigation(api.navigate(currentUrl(), {
|
|
4109
4139
|
replace: true,
|
|
4110
4140
|
initial: true,
|
|
4111
4141
|
source: "client"
|
|
4112
|
-
})
|
|
4142
|
+
}));
|
|
4113
4143
|
return api;
|
|
4114
4144
|
}
|
|
4115
4145
|
updateStateFromLocation();
|
|
@@ -4174,7 +4204,7 @@ const __routerModule = (() => {
|
|
|
4174
4204
|
return;
|
|
4175
4205
|
}
|
|
4176
4206
|
event.preventDefault();
|
|
4177
|
-
api.navigate(anchor.href);
|
|
4207
|
+
handleNavigation(api.navigate(anchor.href));
|
|
4178
4208
|
};
|
|
4179
4209
|
const submit = (event) => {
|
|
4180
4210
|
const form = closest(event.target, "form");
|
|
@@ -4182,9 +4212,9 @@ const __routerModule = (() => {
|
|
|
4182
4212
|
return;
|
|
4183
4213
|
}
|
|
4184
4214
|
event.preventDefault();
|
|
4185
|
-
api.navigate(formActionUrl(form));
|
|
4215
|
+
handleNavigation(api.navigate(formActionUrl(form)));
|
|
4186
4216
|
};
|
|
4187
|
-
const popstate = () => api.navigate(currentUrl(), { history: false });
|
|
4217
|
+
const popstate = () => handleNavigation(api.navigate(currentUrl(), { history: false }));
|
|
4188
4218
|
|
|
4189
4219
|
rootNode.addEventListener?.("click", click);
|
|
4190
4220
|
rootNode.addEventListener?.("submit", submit);
|
|
@@ -4377,6 +4407,19 @@ const __routerModule = (() => {
|
|
|
4377
4407
|
}
|
|
4378
4408
|
}
|
|
4379
4409
|
|
|
4410
|
+
function handleNavigation(promise) {
|
|
4411
|
+
void promise.catch((error) => {
|
|
4412
|
+
if (destroyed) {
|
|
4413
|
+
return;
|
|
4414
|
+
}
|
|
4415
|
+
setRouterState({
|
|
4416
|
+
pending: false,
|
|
4417
|
+
error
|
|
4418
|
+
});
|
|
4419
|
+
dispatchAsyncError(rootNode, error);
|
|
4420
|
+
});
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4380
4423
|
function currentUrl() {
|
|
4381
4424
|
return resolveUrl(documentRef.defaultView?.location?.href ?? "http://localhost/");
|
|
4382
4425
|
}
|
|
@@ -4393,6 +4436,33 @@ const __routerModule = (() => {
|
|
|
4393
4436
|
throw new Error("Router has been destroyed.");
|
|
4394
4437
|
}
|
|
4395
4438
|
}
|
|
4439
|
+
|
|
4440
|
+
function shouldIgnoreLink(event, anchor) {
|
|
4441
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
4442
|
+
return true;
|
|
4443
|
+
}
|
|
4444
|
+
if (anchor.target || anchor.hasAttribute("download")) {
|
|
4445
|
+
return true;
|
|
4446
|
+
}
|
|
4447
|
+
const target = resolveUrl(anchor.href);
|
|
4448
|
+
const current = currentUrl();
|
|
4449
|
+
if (target.origin !== current.origin) {
|
|
4450
|
+
return true;
|
|
4451
|
+
}
|
|
4452
|
+
return isHashOnlyNavigation(target, current, anchor);
|
|
4453
|
+
}
|
|
4454
|
+
|
|
4455
|
+
function shouldIgnoreForm(form) {
|
|
4456
|
+
const method = String(form.method || "get").toLowerCase();
|
|
4457
|
+
return method !== "get" || resolveUrl(form.action).origin !== currentUrl().origin;
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
function formActionUrl(form) {
|
|
4461
|
+
const url = resolveUrl(form.action || form.ownerDocument.defaultView.location.href);
|
|
4462
|
+
const formData = new form.ownerDocument.defaultView.FormData(form);
|
|
4463
|
+
url.search = new URLSearchParams(formData).toString();
|
|
4464
|
+
return url.href;
|
|
4465
|
+
}
|
|
4396
4466
|
}
|
|
4397
4467
|
|
|
4398
4468
|
function normalizeRoute(pattern, definition) {
|
|
@@ -4430,28 +4500,6 @@ const __routerModule = (() => {
|
|
|
4430
4500
|
return { regex: new RegExp(`^${source}$`), keys };
|
|
4431
4501
|
}
|
|
4432
4502
|
|
|
4433
|
-
function shouldIgnoreLink(event, anchor) {
|
|
4434
|
-
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
4435
|
-
return true;
|
|
4436
|
-
}
|
|
4437
|
-
if (anchor.target || anchor.hasAttribute("download")) {
|
|
4438
|
-
return true;
|
|
4439
|
-
}
|
|
4440
|
-
return toUrl(anchor.href).origin !== toUrl(anchor.ownerDocument.defaultView.location.href).origin;
|
|
4441
|
-
}
|
|
4442
|
-
|
|
4443
|
-
function shouldIgnoreForm(form) {
|
|
4444
|
-
const method = String(form.method || "get").toLowerCase();
|
|
4445
|
-
return method !== "get" || toUrl(form.action).origin !== toUrl(form.ownerDocument.defaultView.location.href).origin;
|
|
4446
|
-
}
|
|
4447
|
-
|
|
4448
|
-
function formActionUrl(form) {
|
|
4449
|
-
const url = toUrl(form.action || form.ownerDocument.defaultView.location.href);
|
|
4450
|
-
const formData = new form.ownerDocument.defaultView.FormData(form);
|
|
4451
|
-
url.search = new URLSearchParams(formData).toString();
|
|
4452
|
-
return url.href;
|
|
4453
|
-
}
|
|
4454
|
-
|
|
4455
4503
|
function closest(target, selector) {
|
|
4456
4504
|
return target?.closest?.(selector);
|
|
4457
4505
|
}
|
|
@@ -4467,6 +4515,34 @@ const __routerModule = (() => {
|
|
|
4467
4515
|
return Object.fromEntries(url.searchParams.entries());
|
|
4468
4516
|
}
|
|
4469
4517
|
|
|
4518
|
+
function safeDecodeURIComponent(value) {
|
|
4519
|
+
try {
|
|
4520
|
+
return decodeURIComponent(value);
|
|
4521
|
+
} catch {
|
|
4522
|
+
return value;
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
|
|
4526
|
+
function isHashOnlyNavigation(target, current, anchor) {
|
|
4527
|
+
if (target.origin !== current.origin || target.pathname !== current.pathname || target.search !== current.search) {
|
|
4528
|
+
return false;
|
|
4529
|
+
}
|
|
4530
|
+
return target.hash !== current.hash || anchor.getAttribute?.("href")?.startsWith("#") === true;
|
|
4531
|
+
}
|
|
4532
|
+
|
|
4533
|
+
function dispatchAsyncError(element, error) {
|
|
4534
|
+
const EventCtor = element.ownerDocument?.defaultView?.CustomEvent ?? globalThis.CustomEvent;
|
|
4535
|
+
if (typeof EventCtor !== "function") {
|
|
4536
|
+
return;
|
|
4537
|
+
}
|
|
4538
|
+
element.dispatchEvent?.(
|
|
4539
|
+
new EventCtor("async:error", {
|
|
4540
|
+
bubbles: true,
|
|
4541
|
+
detail: { error }
|
|
4542
|
+
})
|
|
4543
|
+
);
|
|
4544
|
+
}
|
|
4545
|
+
|
|
4470
4546
|
function escapeRegExp(value) {
|
|
4471
4547
|
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4472
4548
|
}
|
package/browser.umd.js
CHANGED
|
@@ -329,10 +329,20 @@
|
|
|
329
329
|
const resolved = resolveDescriptorUrl(type, id, descriptor, registryAssets);
|
|
330
330
|
let modulePromise = moduleCache.get(resolved.moduleUrl);
|
|
331
331
|
if (!modulePromise) {
|
|
332
|
-
modulePromise = Promise.resolve(importModule(resolved.moduleUrl));
|
|
332
|
+
modulePromise = Promise.resolve().then(() => importModule(resolved.moduleUrl));
|
|
333
333
|
moduleCache.set(resolved.moduleUrl, modulePromise);
|
|
334
334
|
}
|
|
335
|
-
|
|
335
|
+
let module;
|
|
336
|
+
try {
|
|
337
|
+
module = await modulePromise;
|
|
338
|
+
} catch (cause) {
|
|
339
|
+
if (moduleCache.get(resolved.moduleUrl) === modulePromise) {
|
|
340
|
+
moduleCache.delete(resolved.moduleUrl);
|
|
341
|
+
}
|
|
342
|
+
throw new Error(`Lazy ${type} "${id}" failed to import ${resolved.moduleUrl}: ${errorMessage(cause)}`, {
|
|
343
|
+
cause
|
|
344
|
+
});
|
|
345
|
+
}
|
|
336
346
|
const value = resolveExport(module, resolved.exportNames, type, id);
|
|
337
347
|
exportCache.set(cacheKey, value);
|
|
338
348
|
return value;
|
|
@@ -492,6 +502,10 @@
|
|
|
492
502
|
return /^[A-Za-z][A-Za-z\d+.-]*:/.test(value);
|
|
493
503
|
}
|
|
494
504
|
|
|
505
|
+
function errorMessage(error) {
|
|
506
|
+
return error instanceof Error ? error.message : String(error);
|
|
507
|
+
}
|
|
508
|
+
|
|
495
509
|
function stableStringify(value) {
|
|
496
510
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
497
511
|
return JSON.stringify(value);
|
|
@@ -820,15 +834,7 @@
|
|
|
820
834
|
|
|
821
835
|
get(key) {
|
|
822
836
|
assertKey(key);
|
|
823
|
-
|
|
824
|
-
if (!entry) {
|
|
825
|
-
return undefined;
|
|
826
|
-
}
|
|
827
|
-
if (entry.expiresAt !== undefined && entry.expiresAt <= now()) {
|
|
828
|
-
entries.delete(key);
|
|
829
|
-
return undefined;
|
|
830
|
-
}
|
|
831
|
-
return entry.value;
|
|
837
|
+
return readEntry(key).value;
|
|
832
838
|
},
|
|
833
839
|
|
|
834
840
|
set(key, value, options = {}) {
|
|
@@ -846,9 +852,9 @@
|
|
|
846
852
|
if (typeof fn !== "function") {
|
|
847
853
|
throw new TypeError("cache.getOrSet(key, fn) requires a function.");
|
|
848
854
|
}
|
|
849
|
-
const cached =
|
|
850
|
-
if (cached
|
|
851
|
-
return cached;
|
|
855
|
+
const cached = readEntry(key);
|
|
856
|
+
if (cached.found) {
|
|
857
|
+
return cached.value;
|
|
852
858
|
}
|
|
853
859
|
if (pending.has(key)) {
|
|
854
860
|
return pending.get(key);
|
|
@@ -899,8 +905,8 @@
|
|
|
899
905
|
snapshot() {
|
|
900
906
|
const snapshot = {};
|
|
901
907
|
for (const [key] of entries) {
|
|
902
|
-
const value =
|
|
903
|
-
if (value !== undefined) {
|
|
908
|
+
const { found, value } = readEntry(key);
|
|
909
|
+
if (found && value !== undefined) {
|
|
904
910
|
snapshot[key] = value;
|
|
905
911
|
}
|
|
906
912
|
}
|
|
@@ -940,6 +946,18 @@
|
|
|
940
946
|
const prefix = key.split(":")[0];
|
|
941
947
|
return definitions.get(prefix);
|
|
942
948
|
}
|
|
949
|
+
|
|
950
|
+
function readEntry(key) {
|
|
951
|
+
const entry = entries.get(key);
|
|
952
|
+
if (!entry) {
|
|
953
|
+
return { found: false, value: undefined };
|
|
954
|
+
}
|
|
955
|
+
if (entry.expiresAt !== undefined && entry.expiresAt <= now()) {
|
|
956
|
+
entries.delete(key);
|
|
957
|
+
return { found: false, value: undefined };
|
|
958
|
+
}
|
|
959
|
+
return { found: true, value: entry.value };
|
|
960
|
+
}
|
|
943
961
|
}
|
|
944
962
|
|
|
945
963
|
function normalizeDefinition(definition) {
|
|
@@ -2459,14 +2477,17 @@
|
|
|
2459
2477
|
return output;
|
|
2460
2478
|
}
|
|
2461
2479
|
|
|
2462
|
-
function assertJsonTransportable(value,
|
|
2480
|
+
function assertJsonTransportable(value, stack = new Set()) {
|
|
2481
|
+
if (typeof value === "bigint") {
|
|
2482
|
+
throw new Error("Server proxy JSON transport does not support BigInt values.");
|
|
2483
|
+
}
|
|
2463
2484
|
if (value == null || typeof value !== "object") {
|
|
2464
2485
|
return;
|
|
2465
2486
|
}
|
|
2466
|
-
if (
|
|
2467
|
-
|
|
2487
|
+
if (stack.has(value)) {
|
|
2488
|
+
throw new Error("Server proxy JSON transport does not support circular values.");
|
|
2468
2489
|
}
|
|
2469
|
-
|
|
2490
|
+
stack.add(value);
|
|
2470
2491
|
|
|
2471
2492
|
const tag = Object.prototype.toString.call(value);
|
|
2472
2493
|
if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
|
|
@@ -2474,13 +2495,15 @@
|
|
|
2474
2495
|
}
|
|
2475
2496
|
if (Array.isArray(value)) {
|
|
2476
2497
|
for (const item of value) {
|
|
2477
|
-
assertJsonTransportable(item,
|
|
2498
|
+
assertJsonTransportable(item, stack);
|
|
2478
2499
|
}
|
|
2500
|
+
stack.delete(value);
|
|
2479
2501
|
return;
|
|
2480
2502
|
}
|
|
2481
2503
|
for (const item of Object.values(value)) {
|
|
2482
|
-
assertJsonTransportable(item,
|
|
2504
|
+
assertJsonTransportable(item, stack);
|
|
2483
2505
|
}
|
|
2506
|
+
stack.delete(value);
|
|
2484
2507
|
}
|
|
2485
2508
|
|
|
2486
2509
|
function joinEndpoint(endpoint, id) {
|
|
@@ -3125,6 +3148,7 @@
|
|
|
3125
3148
|
return;
|
|
3126
3149
|
}
|
|
3127
3150
|
destroyed = true;
|
|
3151
|
+
markDestroyedScopes(rootNode);
|
|
3128
3152
|
for (const cleanup of [...cleanups]) {
|
|
3129
3153
|
runCleanup(cleanup);
|
|
3130
3154
|
}
|
|
@@ -3575,6 +3599,12 @@
|
|
|
3575
3599
|
});
|
|
3576
3600
|
}
|
|
3577
3601
|
|
|
3602
|
+
function markDestroyedScopes(scope) {
|
|
3603
|
+
for (const element of elementsIn(scope)) {
|
|
3604
|
+
schedulerInstance.markScopeDestroyed(element);
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3578
3608
|
return api;
|
|
3579
3609
|
}
|
|
3580
3610
|
|
|
@@ -4000,7 +4030,7 @@
|
|
|
4000
4030
|
}
|
|
4001
4031
|
const params = {};
|
|
4002
4032
|
candidate.keys.forEach((key, index) => {
|
|
4003
|
-
params[key] =
|
|
4033
|
+
params[key] = safeDecodeURIComponent(match[index + 1] ?? "");
|
|
4004
4034
|
});
|
|
4005
4035
|
return {
|
|
4006
4036
|
pattern: candidate.pattern,
|
|
@@ -4115,11 +4145,11 @@
|
|
|
4115
4145
|
}
|
|
4116
4146
|
bindNavigation();
|
|
4117
4147
|
if (mode === "csr") {
|
|
4118
|
-
|
|
4148
|
+
handleNavigation(api.navigate(currentUrl(), {
|
|
4119
4149
|
replace: true,
|
|
4120
4150
|
initial: true,
|
|
4121
4151
|
source: "client"
|
|
4122
|
-
})
|
|
4152
|
+
}));
|
|
4123
4153
|
return api;
|
|
4124
4154
|
}
|
|
4125
4155
|
updateStateFromLocation();
|
|
@@ -4184,7 +4214,7 @@
|
|
|
4184
4214
|
return;
|
|
4185
4215
|
}
|
|
4186
4216
|
event.preventDefault();
|
|
4187
|
-
api.navigate(anchor.href);
|
|
4217
|
+
handleNavigation(api.navigate(anchor.href));
|
|
4188
4218
|
};
|
|
4189
4219
|
const submit = (event) => {
|
|
4190
4220
|
const form = closest(event.target, "form");
|
|
@@ -4192,9 +4222,9 @@
|
|
|
4192
4222
|
return;
|
|
4193
4223
|
}
|
|
4194
4224
|
event.preventDefault();
|
|
4195
|
-
api.navigate(formActionUrl(form));
|
|
4225
|
+
handleNavigation(api.navigate(formActionUrl(form)));
|
|
4196
4226
|
};
|
|
4197
|
-
const popstate = () => api.navigate(currentUrl(), { history: false });
|
|
4227
|
+
const popstate = () => handleNavigation(api.navigate(currentUrl(), { history: false }));
|
|
4198
4228
|
|
|
4199
4229
|
rootNode.addEventListener?.("click", click);
|
|
4200
4230
|
rootNode.addEventListener?.("submit", submit);
|
|
@@ -4387,6 +4417,19 @@
|
|
|
4387
4417
|
}
|
|
4388
4418
|
}
|
|
4389
4419
|
|
|
4420
|
+
function handleNavigation(promise) {
|
|
4421
|
+
void promise.catch((error) => {
|
|
4422
|
+
if (destroyed) {
|
|
4423
|
+
return;
|
|
4424
|
+
}
|
|
4425
|
+
setRouterState({
|
|
4426
|
+
pending: false,
|
|
4427
|
+
error
|
|
4428
|
+
});
|
|
4429
|
+
dispatchAsyncError(rootNode, error);
|
|
4430
|
+
});
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4390
4433
|
function currentUrl() {
|
|
4391
4434
|
return resolveUrl(documentRef.defaultView?.location?.href ?? "http://localhost/");
|
|
4392
4435
|
}
|
|
@@ -4403,6 +4446,33 @@
|
|
|
4403
4446
|
throw new Error("Router has been destroyed.");
|
|
4404
4447
|
}
|
|
4405
4448
|
}
|
|
4449
|
+
|
|
4450
|
+
function shouldIgnoreLink(event, anchor) {
|
|
4451
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
4452
|
+
return true;
|
|
4453
|
+
}
|
|
4454
|
+
if (anchor.target || anchor.hasAttribute("download")) {
|
|
4455
|
+
return true;
|
|
4456
|
+
}
|
|
4457
|
+
const target = resolveUrl(anchor.href);
|
|
4458
|
+
const current = currentUrl();
|
|
4459
|
+
if (target.origin !== current.origin) {
|
|
4460
|
+
return true;
|
|
4461
|
+
}
|
|
4462
|
+
return isHashOnlyNavigation(target, current, anchor);
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
function shouldIgnoreForm(form) {
|
|
4466
|
+
const method = String(form.method || "get").toLowerCase();
|
|
4467
|
+
return method !== "get" || resolveUrl(form.action).origin !== currentUrl().origin;
|
|
4468
|
+
}
|
|
4469
|
+
|
|
4470
|
+
function formActionUrl(form) {
|
|
4471
|
+
const url = resolveUrl(form.action || form.ownerDocument.defaultView.location.href);
|
|
4472
|
+
const formData = new form.ownerDocument.defaultView.FormData(form);
|
|
4473
|
+
url.search = new URLSearchParams(formData).toString();
|
|
4474
|
+
return url.href;
|
|
4475
|
+
}
|
|
4406
4476
|
}
|
|
4407
4477
|
|
|
4408
4478
|
function normalizeRoute(pattern, definition) {
|
|
@@ -4440,28 +4510,6 @@
|
|
|
4440
4510
|
return { regex: new RegExp(`^${source}$`), keys };
|
|
4441
4511
|
}
|
|
4442
4512
|
|
|
4443
|
-
function shouldIgnoreLink(event, anchor) {
|
|
4444
|
-
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
4445
|
-
return true;
|
|
4446
|
-
}
|
|
4447
|
-
if (anchor.target || anchor.hasAttribute("download")) {
|
|
4448
|
-
return true;
|
|
4449
|
-
}
|
|
4450
|
-
return toUrl(anchor.href).origin !== toUrl(anchor.ownerDocument.defaultView.location.href).origin;
|
|
4451
|
-
}
|
|
4452
|
-
|
|
4453
|
-
function shouldIgnoreForm(form) {
|
|
4454
|
-
const method = String(form.method || "get").toLowerCase();
|
|
4455
|
-
return method !== "get" || toUrl(form.action).origin !== toUrl(form.ownerDocument.defaultView.location.href).origin;
|
|
4456
|
-
}
|
|
4457
|
-
|
|
4458
|
-
function formActionUrl(form) {
|
|
4459
|
-
const url = toUrl(form.action || form.ownerDocument.defaultView.location.href);
|
|
4460
|
-
const formData = new form.ownerDocument.defaultView.FormData(form);
|
|
4461
|
-
url.search = new URLSearchParams(formData).toString();
|
|
4462
|
-
return url.href;
|
|
4463
|
-
}
|
|
4464
|
-
|
|
4465
4513
|
function closest(target, selector) {
|
|
4466
4514
|
return target?.closest?.(selector);
|
|
4467
4515
|
}
|
|
@@ -4477,6 +4525,34 @@
|
|
|
4477
4525
|
return Object.fromEntries(url.searchParams.entries());
|
|
4478
4526
|
}
|
|
4479
4527
|
|
|
4528
|
+
function safeDecodeURIComponent(value) {
|
|
4529
|
+
try {
|
|
4530
|
+
return decodeURIComponent(value);
|
|
4531
|
+
} catch {
|
|
4532
|
+
return value;
|
|
4533
|
+
}
|
|
4534
|
+
}
|
|
4535
|
+
|
|
4536
|
+
function isHashOnlyNavigation(target, current, anchor) {
|
|
4537
|
+
if (target.origin !== current.origin || target.pathname !== current.pathname || target.search !== current.search) {
|
|
4538
|
+
return false;
|
|
4539
|
+
}
|
|
4540
|
+
return target.hash !== current.hash || anchor.getAttribute?.("href")?.startsWith("#") === true;
|
|
4541
|
+
}
|
|
4542
|
+
|
|
4543
|
+
function dispatchAsyncError(element, error) {
|
|
4544
|
+
const EventCtor = element.ownerDocument?.defaultView?.CustomEvent ?? globalThis.CustomEvent;
|
|
4545
|
+
if (typeof EventCtor !== "function") {
|
|
4546
|
+
return;
|
|
4547
|
+
}
|
|
4548
|
+
element.dispatchEvent?.(
|
|
4549
|
+
new EventCtor("async:error", {
|
|
4550
|
+
bubbles: true,
|
|
4551
|
+
detail: { error }
|
|
4552
|
+
})
|
|
4553
|
+
);
|
|
4554
|
+
}
|
|
4555
|
+
|
|
4480
4556
|
function escapeRegExp(value) {
|
|
4481
4557
|
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4482
4558
|
}
|