@webjsdev/core 0.7.50 → 0.7.51
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/webjs-core-browser.js +5 -5
- package/dist/webjs-core-browser.js.map +3 -3
- package/dist/webjs-core-testing.js +20 -20
- package/dist/webjs-core-testing.js.map +3 -3
- package/dist/webjs-core.js +7 -7
- package/dist/webjs-core.js.map +3 -3
- package/index-browser.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/component/lifecycle.js +1481 -0
- package/src/component/reactive.js +171 -0
- package/src/component/server-element.js +248 -0
- package/src/component.js +2 -1896
- package/src/render-client/parts.js +2007 -0
- package/src/render-client/reconciler.js +388 -0
- package/src/render-client/template-compiler.js +525 -0
- package/src/render-client.js +1 -2938
- package/src/render-server/attrs.js +160 -0
- package/src/render-server/dsd.js +445 -0
- package/src/render-server/html-scan.js +402 -0
- package/src/render-server/slots.js +213 -0
- package/src/render-server/stream.js +163 -0
- package/src/render-server/template-renderer.js +923 -0
- package/src/render-server/text.js +163 -0
- package/src/render-server.js +6 -2405
- package/src/router-client/anchors.js +44 -0
- package/src/router-client/boundaries.js +221 -0
- package/src/router-client/constants.js +187 -0
- package/src/router-client/diagnostics.js +377 -0
- package/src/router-client/dom-differ.js +709 -0
- package/src/router-client/dom-parse.js +150 -0
- package/src/router-client/events.js +139 -0
- package/src/router-client/fetch-apply.js +387 -0
- package/src/router-client/form-encoder.js +135 -0
- package/src/router-client/frames.js +329 -0
- package/src/router-client/head-merge.js +344 -0
- package/src/router-client/nav-error.js +105 -0
- package/src/router-client/navigator.js +781 -0
- package/src/router-client/prefetch.js +824 -0
- package/src/router-client/scroll.js +259 -0
- package/src/router-client/snapshot-cache.js +97 -0
- package/src/router-client/state.js +92 -0
- package/src/router-client/stream.js +206 -0
- package/src/router-client/swap.js +451 -0
- package/src/router-client/upgrade.js +261 -0
- package/src/router-client/view-transition.js +223 -0
- package/src/router-client.d.ts +10 -1
- package/src/router-client.js +75 -5345
- package/src/slot/assignment.js +304 -0
- package/src/slot/interception.js +558 -0
- package/src/slot/polyfills.js +365 -0
- package/src/slot/project.js +432 -0
- package/src/slot/sensors.js +303 -0
- package/src/slot/state.js +245 -0
- package/src/slot/symbols.js +85 -0
- package/src/slot.js +7 -2199
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client router: nav-error.
|
|
3
|
+
*
|
|
4
|
+
* Moved verbatim out of the pre-split `router-client.js`; that barrel holds
|
|
5
|
+
* the router's full contract and the public entry points.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { collectBoundaries } from './boundaries.js';
|
|
10
|
+
import { reportFallback } from './diagnostics.js';
|
|
11
|
+
import { hardNavigate } from './state.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Render the minimal default in-place error surface into the deepest
|
|
15
|
+
* shared layout children slot, so the SPA shell (outer chrome, nav,
|
|
16
|
+
* scroll, focus, client state) survives a failed navigation instead of
|
|
17
|
+
* being destroyed by a full reload. Returns true when it rendered into a
|
|
18
|
+
* slot, false when no shared layout marker exists (a cross-document nav).
|
|
19
|
+
* On a false return the caller may fall back to a hard load as a last
|
|
20
|
+
* resort.
|
|
21
|
+
*
|
|
22
|
+
* @param {number | null} status HTTP status of the failed response, or null for a transport/parse failure.
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
function renderInPlaceNavError(status) {
|
|
26
|
+
if (typeof document === 'undefined' || !document.body) return false;
|
|
27
|
+
const here = collectBoundaries(document.body);
|
|
28
|
+
if (!here) return false; // poisoned live tree: let the caller hard-load
|
|
29
|
+
// The deepest boundary is the same swap target a normal partial swap writes
|
|
30
|
+
// to (longest path wins), so the outer chrome / nav are preserved.
|
|
31
|
+
/** @type {{ start: Comment, end: Comment } | undefined} */
|
|
32
|
+
let deepest;
|
|
33
|
+
let deepestPathLen = -1;
|
|
34
|
+
for (const [path, slot] of here) {
|
|
35
|
+
if (path.length > deepestPathLen) { deepestPathLen = path.length; deepest = slot; }
|
|
36
|
+
}
|
|
37
|
+
if (!deepest) return false;
|
|
38
|
+
const liveParent = deepest.start.parentNode;
|
|
39
|
+
if (!liveParent || deepest.start.parentNode !== deepest.end.parentNode) return false;
|
|
40
|
+
|
|
41
|
+
const alert = document.createElement('div');
|
|
42
|
+
alert.setAttribute('role', 'alert');
|
|
43
|
+
alert.setAttribute('data-webjs-nav-error', '');
|
|
44
|
+
const msg = status
|
|
45
|
+
? `This page could not be loaded. (status ${status})`
|
|
46
|
+
: 'This page could not be loaded.';
|
|
47
|
+
alert.textContent = msg;
|
|
48
|
+
|
|
49
|
+
// Replace the slot contents with the alert.
|
|
50
|
+
const range = document.createRange();
|
|
51
|
+
range.setStartAfter(deepest.start);
|
|
52
|
+
range.setEndBefore(deepest.end);
|
|
53
|
+
range.deleteContents();
|
|
54
|
+
liveParent.insertBefore(alert, deepest.end);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Shared fallback for a non-HTML error response or a transport/parse
|
|
60
|
+
* failure during a client navigation. Dispatches a cancelable
|
|
61
|
+
* `webjs:navigation-error` event on `document` (matching the
|
|
62
|
+
* `webjs:frame-missing` / `webjs:prefetch` dispatch convention) so the
|
|
63
|
+
* app can recover in place. If the app calls `preventDefault()`, the
|
|
64
|
+
* router does NOTHING further and leaves the current page exactly as it
|
|
65
|
+
* is. Otherwise it renders a minimal in-place `role="alert"` surface into
|
|
66
|
+
* the deepest layout children slot (the SPA shell survives), and only
|
|
67
|
+
* hard-navigates as a last resort when no in-place target exists.
|
|
68
|
+
*
|
|
69
|
+
* Never call this for an AbortError: a superseding nav is a normal
|
|
70
|
+
* supersede, not an error, and must not surface a navigation-error.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} href The URL that failed to navigate to.
|
|
73
|
+
* @param {number | null} status HTTP status when a response arrived, else null.
|
|
74
|
+
* @param {Error | null} error The Error for a transport/parse failure, else null.
|
|
75
|
+
*/
|
|
76
|
+
export function handleNavigationError(href, status, error) {
|
|
77
|
+
const evt = new CustomEvent('webjs:navigation-error', {
|
|
78
|
+
bubbles: true,
|
|
79
|
+
cancelable: true,
|
|
80
|
+
detail: { url: href, status: status == null ? null : status, error: error || null },
|
|
81
|
+
});
|
|
82
|
+
// Guard the dispatch: a throwing app listener must not wedge the nav engine.
|
|
83
|
+
if (typeof document !== 'undefined') {
|
|
84
|
+
try { document.dispatchEvent(evt); } catch { /* a buggy listener cannot break recovery */ }
|
|
85
|
+
}
|
|
86
|
+
// The app owns recovery: leave the page untouched (shell, scroll, focus,
|
|
87
|
+
// client state all preserved). No reload, no render.
|
|
88
|
+
if (evt.defaultPrevented) return;
|
|
89
|
+
// Default: render a minimal in-place error surface so the SPA is not
|
|
90
|
+
// destroyed and the user is not sent to a second failing round-trip.
|
|
91
|
+
if (renderInPlaceNavError(status)) return;
|
|
92
|
+
// Last resort only: no shared layout marker to render into (a genuine
|
|
93
|
+
// cross-document nav). Fall back to a hard load so an unrecoverable case
|
|
94
|
+
// is not a silent dead-end. This is the exception, reached only after
|
|
95
|
+
// the event was not cancelled AND no in-place target exists.
|
|
96
|
+
//
|
|
97
|
+
// Report it like every other degradation (#1114): this IS a click turning
|
|
98
|
+
// into a document load, so an app watching `webjs:navigation-fallback` to
|
|
99
|
+
// count full loads must see it. The preceding `webjs:navigation-error`
|
|
100
|
+
// carries no `cause` / `willReload`, so it is not a substitute.
|
|
101
|
+
if (typeof location !== 'undefined') {
|
|
102
|
+
reportFallback('navigation-error-unrecoverable', href);
|
|
103
|
+
hardNavigate(href);
|
|
104
|
+
}
|
|
105
|
+
}
|