@async/framework 0.10.1 → 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 +16 -0
- 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 +1 -1
- 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/src/router.js
CHANGED
|
@@ -61,7 +61,7 @@ export function createRouteRegistry(initialMap = {}, options = {}) {
|
|
|
61
61
|
}
|
|
62
62
|
const params = {};
|
|
63
63
|
candidate.keys.forEach((key, index) => {
|
|
64
|
-
params[key] =
|
|
64
|
+
params[key] = safeDecodeURIComponent(match[index + 1] ?? "");
|
|
65
65
|
});
|
|
66
66
|
return {
|
|
67
67
|
pattern: candidate.pattern,
|
|
@@ -176,11 +176,11 @@ export function createRouter({
|
|
|
176
176
|
}
|
|
177
177
|
bindNavigation();
|
|
178
178
|
if (mode === "csr") {
|
|
179
|
-
|
|
179
|
+
handleNavigation(api.navigate(currentUrl(), {
|
|
180
180
|
replace: true,
|
|
181
181
|
initial: true,
|
|
182
182
|
source: "client"
|
|
183
|
-
})
|
|
183
|
+
}));
|
|
184
184
|
return api;
|
|
185
185
|
}
|
|
186
186
|
updateStateFromLocation();
|
|
@@ -245,7 +245,7 @@ export function createRouter({
|
|
|
245
245
|
return;
|
|
246
246
|
}
|
|
247
247
|
event.preventDefault();
|
|
248
|
-
api.navigate(anchor.href);
|
|
248
|
+
handleNavigation(api.navigate(anchor.href));
|
|
249
249
|
};
|
|
250
250
|
const submit = (event) => {
|
|
251
251
|
const form = closest(event.target, "form");
|
|
@@ -253,9 +253,9 @@ export function createRouter({
|
|
|
253
253
|
return;
|
|
254
254
|
}
|
|
255
255
|
event.preventDefault();
|
|
256
|
-
api.navigate(formActionUrl(form));
|
|
256
|
+
handleNavigation(api.navigate(formActionUrl(form)));
|
|
257
257
|
};
|
|
258
|
-
const popstate = () => api.navigate(currentUrl(), { history: false });
|
|
258
|
+
const popstate = () => handleNavigation(api.navigate(currentUrl(), { history: false }));
|
|
259
259
|
|
|
260
260
|
rootNode.addEventListener?.("click", click);
|
|
261
261
|
rootNode.addEventListener?.("submit", submit);
|
|
@@ -448,6 +448,19 @@ export function createRouter({
|
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
450
|
|
|
451
|
+
function handleNavigation(promise) {
|
|
452
|
+
void promise.catch((error) => {
|
|
453
|
+
if (destroyed) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
setRouterState({
|
|
457
|
+
pending: false,
|
|
458
|
+
error
|
|
459
|
+
});
|
|
460
|
+
dispatchAsyncError(rootNode, error);
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
451
464
|
function currentUrl() {
|
|
452
465
|
return resolveUrl(documentRef.defaultView?.location?.href ?? "http://localhost/");
|
|
453
466
|
}
|
|
@@ -464,6 +477,33 @@ export function createRouter({
|
|
|
464
477
|
throw new Error("Router has been destroyed.");
|
|
465
478
|
}
|
|
466
479
|
}
|
|
480
|
+
|
|
481
|
+
function shouldIgnoreLink(event, anchor) {
|
|
482
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
if (anchor.target || anchor.hasAttribute("download")) {
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
const target = resolveUrl(anchor.href);
|
|
489
|
+
const current = currentUrl();
|
|
490
|
+
if (target.origin !== current.origin) {
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
return isHashOnlyNavigation(target, current, anchor);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function shouldIgnoreForm(form) {
|
|
497
|
+
const method = String(form.method || "get").toLowerCase();
|
|
498
|
+
return method !== "get" || resolveUrl(form.action).origin !== currentUrl().origin;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function formActionUrl(form) {
|
|
502
|
+
const url = resolveUrl(form.action || form.ownerDocument.defaultView.location.href);
|
|
503
|
+
const formData = new form.ownerDocument.defaultView.FormData(form);
|
|
504
|
+
url.search = new URLSearchParams(formData).toString();
|
|
505
|
+
return url.href;
|
|
506
|
+
}
|
|
467
507
|
}
|
|
468
508
|
|
|
469
509
|
function normalizeRoute(pattern, definition) {
|
|
@@ -501,28 +541,6 @@ function compilePattern(pattern) {
|
|
|
501
541
|
return { regex: new RegExp(`^${source}$`), keys };
|
|
502
542
|
}
|
|
503
543
|
|
|
504
|
-
function shouldIgnoreLink(event, anchor) {
|
|
505
|
-
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
506
|
-
return true;
|
|
507
|
-
}
|
|
508
|
-
if (anchor.target || anchor.hasAttribute("download")) {
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
return toUrl(anchor.href).origin !== toUrl(anchor.ownerDocument.defaultView.location.href).origin;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
function shouldIgnoreForm(form) {
|
|
515
|
-
const method = String(form.method || "get").toLowerCase();
|
|
516
|
-
return method !== "get" || toUrl(form.action).origin !== toUrl(form.ownerDocument.defaultView.location.href).origin;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
function formActionUrl(form) {
|
|
520
|
-
const url = toUrl(form.action || form.ownerDocument.defaultView.location.href);
|
|
521
|
-
const formData = new form.ownerDocument.defaultView.FormData(form);
|
|
522
|
-
url.search = new URLSearchParams(formData).toString();
|
|
523
|
-
return url.href;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
544
|
function closest(target, selector) {
|
|
527
545
|
return target?.closest?.(selector);
|
|
528
546
|
}
|
|
@@ -538,6 +556,34 @@ function queryObject(url) {
|
|
|
538
556
|
return Object.fromEntries(url.searchParams.entries());
|
|
539
557
|
}
|
|
540
558
|
|
|
559
|
+
function safeDecodeURIComponent(value) {
|
|
560
|
+
try {
|
|
561
|
+
return decodeURIComponent(value);
|
|
562
|
+
} catch {
|
|
563
|
+
return value;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function isHashOnlyNavigation(target, current, anchor) {
|
|
568
|
+
if (target.origin !== current.origin || target.pathname !== current.pathname || target.search !== current.search) {
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
return target.hash !== current.hash || anchor.getAttribute?.("href")?.startsWith("#") === true;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function dispatchAsyncError(element, error) {
|
|
575
|
+
const EventCtor = element.ownerDocument?.defaultView?.CustomEvent ?? globalThis.CustomEvent;
|
|
576
|
+
if (typeof EventCtor !== "function") {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
element.dispatchEvent?.(
|
|
580
|
+
new EventCtor("async:error", {
|
|
581
|
+
bubbles: true,
|
|
582
|
+
detail: { error }
|
|
583
|
+
})
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
|
|
541
587
|
function escapeRegExp(value) {
|
|
542
588
|
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
543
589
|
}
|
package/src/server.js
CHANGED
|
@@ -305,14 +305,17 @@ function formDataToObject(formData) {
|
|
|
305
305
|
return output;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
function assertJsonTransportable(value,
|
|
308
|
+
function assertJsonTransportable(value, stack = new Set()) {
|
|
309
|
+
if (typeof value === "bigint") {
|
|
310
|
+
throw new Error("Server proxy JSON transport does not support BigInt values.");
|
|
311
|
+
}
|
|
309
312
|
if (value == null || typeof value !== "object") {
|
|
310
313
|
return;
|
|
311
314
|
}
|
|
312
|
-
if (
|
|
313
|
-
|
|
315
|
+
if (stack.has(value)) {
|
|
316
|
+
throw new Error("Server proxy JSON transport does not support circular values.");
|
|
314
317
|
}
|
|
315
|
-
|
|
318
|
+
stack.add(value);
|
|
316
319
|
|
|
317
320
|
const tag = Object.prototype.toString.call(value);
|
|
318
321
|
if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
|
|
@@ -320,13 +323,15 @@ function assertJsonTransportable(value, seen = new Set()) {
|
|
|
320
323
|
}
|
|
321
324
|
if (Array.isArray(value)) {
|
|
322
325
|
for (const item of value) {
|
|
323
|
-
assertJsonTransportable(item,
|
|
326
|
+
assertJsonTransportable(item, stack);
|
|
324
327
|
}
|
|
328
|
+
stack.delete(value);
|
|
325
329
|
return;
|
|
326
330
|
}
|
|
327
331
|
for (const item of Object.values(value)) {
|
|
328
|
-
assertJsonTransportable(item,
|
|
332
|
+
assertJsonTransportable(item, stack);
|
|
329
333
|
}
|
|
334
|
+
stack.delete(value);
|
|
330
335
|
}
|
|
331
336
|
|
|
332
337
|
function joinEndpoint(endpoint, id) {
|