sibujs 1.5.0 → 2.0.0
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/browser.cjs +238 -69
- package/dist/browser.d.cts +5 -0
- package/dist/browser.d.ts +5 -0
- package/dist/browser.js +6 -6
- package/dist/build.cjs +916 -292
- package/dist/build.js +15 -13
- package/dist/cdn.global.js +17 -16
- package/dist/chunk-2RA7SHDA.js +65 -0
- package/dist/chunk-2UPRY23K.js +80 -0
- package/dist/chunk-3JHCYHWN.js +125 -0
- package/dist/{chunk-VAPYJN4X.js → chunk-3LR7GLWQ.js} +93 -23
- package/dist/{chunk-RJ46C3CS.js → chunk-3NSGB5JN.js} +71 -20
- package/dist/{chunk-XUEEGU5O.js → chunk-52YJLLRO.js} +16 -4
- package/dist/{chunk-XHK6BDAJ.js → chunk-54EDRCEF.js} +25 -8
- package/dist/chunk-7JDB7I65.js +1327 -0
- package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
- package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
- package/dist/{chunk-BGN5ZMP4.js → chunk-GTBNNBJ6.js} +14 -2
- package/dist/chunk-HB24TBAF.js +121 -0
- package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
- package/dist/{chunk-BGTHZHJ5.js → chunk-JA6667UN.js} +188 -44
- package/dist/{chunk-7GRNSCFT.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-SFKNRVCU.js → chunk-KLRMB5ZS.js} +135 -79
- package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
- package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
- package/dist/{chunk-BMPL52BF.js → chunk-MIUAXB7K.js} +118 -66
- package/dist/{chunk-JCDUJN2F.js → chunk-ND2664SF.js} +486 -153
- package/dist/{chunk-VQDZK23A.js → chunk-O2MNQFLP.js} +181 -66
- package/dist/{chunk-NHUC2QWH.js → chunk-R73P76YZ.js} +1 -1
- package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
- package/dist/chunk-UCS6AMJ7.js +79 -0
- package/dist/{chunk-K4G4ZQNR.js → chunk-VLPPXTYG.js} +84 -38
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- package/dist/{customElement-BL3Uo8dL.d.cts → customElement-CPfIrbvg.d.cts} +14 -10
- package/dist/{customElement-BL3Uo8dL.d.ts → customElement-CPfIrbvg.d.ts} +14 -10
- package/dist/data.cjs +410 -99
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +513 -223
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +12 -6
- package/dist/ecosystem.cjs +475 -144
- package/dist/ecosystem.d.cts +9 -7
- package/dist/ecosystem.d.ts +9 -7
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3355 -1541
- package/dist/extras.d.cts +9 -9
- package/dist/extras.d.ts +9 -9
- package/dist/extras.js +58 -45
- package/dist/index.cjs +920 -292
- package/dist/index.d.cts +71 -8
- package/dist/index.d.ts +71 -8
- package/dist/index.js +28 -16
- package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
- package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
- package/dist/motion.cjs +77 -34
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +335 -69
- package/dist/patterns.d.cts +11 -12
- package/dist/patterns.d.ts +11 -12
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +279 -108
- package/dist/performance.d.cts +23 -16
- package/dist/performance.d.ts +23 -16
- package/dist/performance.js +13 -8
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +635 -260
- package/dist/plugins.d.cts +10 -3
- package/dist/plugins.d.ts +10 -3
- package/dist/plugins.js +106 -38
- package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
- package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
- package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
- package/dist/ssr.cjs +642 -222
- package/dist/ssr.d.cts +26 -6
- package/dist/ssr.d.ts +26 -6
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.ts} +9 -1
- package/dist/testing.cjs +252 -63
- package/dist/testing.d.cts +17 -4
- package/dist/testing.d.ts +17 -4
- package/dist/testing.js +100 -44
- package/dist/ui.cjs +463 -137
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +977 -94
- package/dist/widgets.d.cts +104 -2
- package/dist/widgets.d.ts +104 -2
- package/dist/widgets.js +9 -7
- package/package.json +8 -2
- package/dist/chunk-32DY64NT.js +0 -282
- package/dist/chunk-3AIRKM3B.js +0 -1263
- package/dist/chunk-3ARAQO7B.js +0 -398
- package/dist/chunk-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-5ZYQ6KDD.js +0 -154
- package/dist/chunk-6BMPXPUW.js +0 -26
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- package/dist/chunk-77L6NL3X.js +0 -1097
- package/dist/chunk-7BF6TK55.js +0 -1097
- package/dist/chunk-7TQKR4PP.js +0 -294
- package/dist/chunk-7V26P53V.js +0 -712
- package/dist/chunk-AZ3ISID5.js +0 -298
- package/dist/chunk-B7SWRFUT.js +0 -332
- package/dist/chunk-BTU3TJDS.js +0 -365
- package/dist/chunk-BW3WT46K.js +0 -937
- package/dist/chunk-C6KFWOFV.js +0 -616
- package/dist/chunk-CHF5OHIA.js +0 -61
- package/dist/chunk-CHJ27IGK.js +0 -26
- package/dist/chunk-CMBFNA7L.js +0 -27
- package/dist/chunk-DAHRH4ON.js +0 -331
- package/dist/chunk-DKOHBI74.js +0 -924
- package/dist/chunk-DTCOOBMX.js +0 -725
- package/dist/chunk-EBGIRKQY.js +0 -616
- package/dist/chunk-EUZND3CB.js +0 -27
- package/dist/chunk-EVCZO745.js +0 -365
- package/dist/chunk-EWFVA3TJ.js +0 -282
- package/dist/chunk-F3FA4F32.js +0 -292
- package/dist/chunk-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-GJPXRJ45.js +0 -37
- package/dist/chunk-HGMJFBC7.js +0 -654
- package/dist/chunk-JAKHTMQU.js +0 -1000
- package/dist/chunk-JCI5M6U6.js +0 -956
- package/dist/chunk-K5ZUMYVS.js +0 -89
- package/dist/chunk-KQPDEVVS.js +0 -398
- package/dist/chunk-L6JRBDNS.js +0 -60
- package/dist/chunk-LA6KQEDU.js +0 -712
- package/dist/chunk-MB6QFH3I.js +0 -2776
- package/dist/chunk-MDVXJWFN.js +0 -304
- package/dist/chunk-MEZVEBPN.js +0 -2008
- package/dist/chunk-MK4ERFYL.js +0 -2249
- package/dist/chunk-MLKGABMK.js +0 -9
- package/dist/chunk-MQ5GOYPH.js +0 -2249
- package/dist/chunk-MYRV7VDM.js +0 -742
- package/dist/chunk-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-NZIIMDWI.js +0 -84
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P3XWXJZU.js +0 -282
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.js +0 -616
- package/dist/chunk-PDZQY43A.js +0 -616
- package/dist/chunk-PTQJDMRT.js +0 -146
- package/dist/chunk-PZEGYCF5.js +0 -61
- package/dist/chunk-QBMDLBU2.js +0 -975
- package/dist/chunk-QWZG56ET.js +0 -2744
- package/dist/chunk-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TDGZL5CU.js +0 -365
- package/dist/chunk-TNQWPPE6.js +0 -37
- package/dist/chunk-TSOKIX5Z.js +0 -654
- package/dist/chunk-UHNL42EF.js +0 -2730
- package/dist/chunk-UNXCEF6S.js +0 -21
- package/dist/chunk-V2XTI523.js +0 -347
- package/dist/chunk-VAU366PN.js +0 -2241
- package/dist/chunk-VMVDTCXB.js +0 -712
- package/dist/chunk-VQNQZCWJ.js +0 -61
- package/dist/chunk-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- package/dist/chunk-WR5D4EGH.js +0 -26
- package/dist/chunk-WUHJISPP.js +0 -298
- package/dist/chunk-XYU6TZOW.js +0 -182
- package/dist/chunk-Y6GP4QGG.js +0 -276
- package/dist/chunk-YECR7UIA.js +0 -347
- package/dist/chunk-YUTWTI4B.js +0 -654
- package/dist/chunk-Z65KYU7I.js +0 -26
- package/dist/chunk-Z6POF5YC.js +0 -975
- package/dist/chunk-ZBJP6WFL.js +0 -482
- package/dist/chunk-ZD6OAMTH.js +0 -277
- package/dist/chunk-ZWKZCBO6.js +0 -317
- package/dist/contracts-DDrwxvJ-.d.cts +0 -245
- package/dist/contracts-DDrwxvJ-.d.ts +0 -245
- package/dist/contracts-DOrhwbke.d.cts +0 -245
- package/dist/contracts-DOrhwbke.d.ts +0 -245
- package/dist/contracts-xo5ckdRP.d.cts +0 -240
- package/dist/contracts-xo5ckdRP.d.ts +0 -240
- package/dist/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- package/dist/customElement-D2DJp_xn.d.cts +0 -313
- package/dist/customElement-D2DJp_xn.d.ts +0 -313
- package/dist/customElement-yz8uyk-0.d.cts +0 -308
- package/dist/customElement-yz8uyk-0.d.ts +0 -308
- package/dist/introspect-Cb0zgpi2.d.cts +0 -477
- package/dist/introspect-Y2xNXGSf.d.ts +0 -477
- package/dist/plugin-Bek4RhJY.d.cts +0 -43
- package/dist/plugin-Bek4RhJY.d.ts +0 -43
- package/dist/ssr-3RXHP5ES.js +0 -38
- package/dist/ssr-6GIMY5MX.js +0 -38
- package/dist/ssr-BA6sxxUd.d.cts +0 -135
- package/dist/ssr-BA6sxxUd.d.ts +0 -135
- package/dist/ssr-WKUPVSSK.js +0 -36
- package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
- package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
package/dist/plugins.cjs
CHANGED
|
@@ -26,12 +26,12 @@ function isDev() {
|
|
|
26
26
|
}
|
|
27
27
|
function devAssert(condition, message) {
|
|
28
28
|
if (_isDev && !condition) {
|
|
29
|
-
throw new Error(`[
|
|
29
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
function devWarn(message) {
|
|
33
33
|
if (_isDev) {
|
|
34
|
-
console.warn(`[
|
|
34
|
+
console.warn(`[SibuJS] ${message}`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
var _isDev;
|
|
@@ -47,14 +47,47 @@ function sanitizeUrl(url) {
|
|
|
47
47
|
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
48
48
|
if (!trimmed) return "";
|
|
49
49
|
const lower = trimmed.toLowerCase();
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
let schemeEnd = -1;
|
|
51
|
+
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
52
|
+
const ch = lower.charCodeAt(i2);
|
|
53
|
+
if (ch === 58) {
|
|
54
|
+
schemeEnd = i2;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
52
58
|
}
|
|
59
|
+
if (schemeEnd === -1) return trimmed;
|
|
60
|
+
const scheme = lower.slice(0, schemeEnd + 1);
|
|
61
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
|
|
62
|
+
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
53
63
|
return trimmed;
|
|
54
64
|
}
|
|
65
|
+
function sanitizeSrcset(value) {
|
|
66
|
+
const parts = value.split(",");
|
|
67
|
+
const out = [];
|
|
68
|
+
for (let i2 = 0; i2 < parts.length; i2++) {
|
|
69
|
+
const part = parts[i2].trim();
|
|
70
|
+
if (!part) continue;
|
|
71
|
+
const m = part.match(/^(\S+)(\s+.+)?$/);
|
|
72
|
+
if (!m) continue;
|
|
73
|
+
const safe = sanitizeUrl(m[1]);
|
|
74
|
+
if (!safe) continue;
|
|
75
|
+
out.push(m[2] ? `${safe}${m[2]}` : safe);
|
|
76
|
+
}
|
|
77
|
+
return out.join(", ");
|
|
78
|
+
}
|
|
55
79
|
function sanitizeCSSValue(value) {
|
|
56
|
-
const
|
|
57
|
-
|
|
80
|
+
const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
|
|
81
|
+
const code2 = Number.parseInt(hex, 16);
|
|
82
|
+
if (!Number.isFinite(code2) || code2 < 0 || code2 > 1114111) return "";
|
|
83
|
+
try {
|
|
84
|
+
return String.fromCodePoint(code2);
|
|
85
|
+
} catch {
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const lower = decoded.toLowerCase().replace(/\s+/g, "");
|
|
90
|
+
if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("vbscript:") || lower.includes("-moz-binding") || lower.includes("behavior:") || lower.includes("@import") || lower.includes("image-set(") || lower.includes("filter:progid")) {
|
|
58
91
|
return "";
|
|
59
92
|
}
|
|
60
93
|
return value;
|
|
@@ -62,11 +95,56 @@ function sanitizeCSSValue(value) {
|
|
|
62
95
|
function isUrlAttribute(attr) {
|
|
63
96
|
return URL_ATTRIBUTES.has(attr);
|
|
64
97
|
}
|
|
65
|
-
var URL_ATTRIBUTES;
|
|
98
|
+
var SAFE_URL_PROTOCOLS, URL_ATTRIBUTES;
|
|
66
99
|
var init_sanitize = __esm({
|
|
67
100
|
"src/utils/sanitize.ts"() {
|
|
68
101
|
"use strict";
|
|
69
|
-
|
|
102
|
+
SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
103
|
+
URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
104
|
+
"href",
|
|
105
|
+
"xlink:href",
|
|
106
|
+
"src",
|
|
107
|
+
"action",
|
|
108
|
+
"formaction",
|
|
109
|
+
"formtarget",
|
|
110
|
+
"cite",
|
|
111
|
+
"poster",
|
|
112
|
+
"background",
|
|
113
|
+
"srcset",
|
|
114
|
+
"ping",
|
|
115
|
+
"data"
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// src/core/ssr-context.ts
|
|
121
|
+
function getSSRStore() {
|
|
122
|
+
if (als) {
|
|
123
|
+
const s2 = als.getStore();
|
|
124
|
+
if (s2) return s2;
|
|
125
|
+
}
|
|
126
|
+
return fallbackStore;
|
|
127
|
+
}
|
|
128
|
+
function isSSR() {
|
|
129
|
+
return getSSRStore().ssr;
|
|
130
|
+
}
|
|
131
|
+
var als, fallbackStore;
|
|
132
|
+
var init_ssr_context = __esm({
|
|
133
|
+
"src/core/ssr-context.ts"() {
|
|
134
|
+
"use strict";
|
|
135
|
+
als = null;
|
|
136
|
+
try {
|
|
137
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
138
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
139
|
+
if (req) {
|
|
140
|
+
const mod = req("node:async_hooks");
|
|
141
|
+
als = new mod.AsyncLocalStorage();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
als = null;
|
|
146
|
+
}
|
|
147
|
+
fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
70
148
|
}
|
|
71
149
|
});
|
|
72
150
|
|
|
@@ -100,7 +178,7 @@ function isEventHandlerAttr2(name) {
|
|
|
100
178
|
return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
|
|
101
179
|
}
|
|
102
180
|
function ssrErrorComment(err) {
|
|
103
|
-
if (
|
|
181
|
+
if (_isDev8) {
|
|
104
182
|
const msg = escapeHtml(err instanceof Error ? err.message : String(err));
|
|
105
183
|
return `<!--SSR error: ${safeCommentText(msg)}-->`;
|
|
106
184
|
}
|
|
@@ -130,10 +208,10 @@ function renderToString(element) {
|
|
|
130
208
|
}
|
|
131
209
|
const tag = element.tagName.toLowerCase();
|
|
132
210
|
if (tag === "script" || tag === "style") {
|
|
133
|
-
return
|
|
211
|
+
return _isDev8 ? `<!--ssr:${tag}-stripped-->` : "";
|
|
134
212
|
}
|
|
135
213
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
136
|
-
return
|
|
214
|
+
return _isDev8 ? "<!--ssr:invalid-tag-->" : "";
|
|
137
215
|
}
|
|
138
216
|
let html2 = `<${tag}`;
|
|
139
217
|
for (const attr of Array.from(element.attributes)) {
|
|
@@ -174,9 +252,9 @@ function hydrate(component, container, options = {}) {
|
|
|
174
252
|
const first = mismatches[0];
|
|
175
253
|
if (options.onMismatch) {
|
|
176
254
|
options.onMismatch(first);
|
|
177
|
-
} else if (
|
|
255
|
+
} else if (_isDev8) {
|
|
178
256
|
console.warn(
|
|
179
|
-
`[
|
|
257
|
+
`[SibuJS hydration] ${first.message}
|
|
180
258
|
at ${first.path}
|
|
181
259
|
server: ${first.serverValue}
|
|
182
260
|
client: ${first.clientValue}`
|
|
@@ -184,17 +262,9 @@ function hydrate(component, container, options = {}) {
|
|
|
184
262
|
}
|
|
185
263
|
}
|
|
186
264
|
}
|
|
187
|
-
|
|
265
|
+
container.replaceChildren(clientTree);
|
|
188
266
|
container.setAttribute("data-sibu-hydrated", "true");
|
|
189
267
|
}
|
|
190
|
-
function hydrateNode(serverNode, clientNode) {
|
|
191
|
-
if (!serverNode) return;
|
|
192
|
-
const serverChildren = Array.from(serverNode.children);
|
|
193
|
-
const clientChildren = Array.from(clientNode.children);
|
|
194
|
-
for (let i2 = 0; i2 < Math.min(serverChildren.length, clientChildren.length); i2++) {
|
|
195
|
-
hydrateNode(serverChildren[i2], clientChildren[i2]);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
268
|
function collectMismatches(serverNode, clientNode, path2, out, max = 5) {
|
|
199
269
|
if (out.length >= max) return;
|
|
200
270
|
const nodePath = path2 || clientNode?.tagName?.toLowerCase() || "(root)";
|
|
@@ -372,11 +442,11 @@ async function* renderToStream(element) {
|
|
|
372
442
|
}
|
|
373
443
|
const tag = element.tagName.toLowerCase();
|
|
374
444
|
if (tag === "script" || tag === "style") {
|
|
375
|
-
if (
|
|
445
|
+
if (_isDev8) yield `<!--ssr:${tag}-stripped-->`;
|
|
376
446
|
return;
|
|
377
447
|
}
|
|
378
448
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
379
|
-
if (
|
|
449
|
+
if (_isDev8) yield "<!--ssr:invalid-tag-->";
|
|
380
450
|
return;
|
|
381
451
|
}
|
|
382
452
|
let openTag = `<${tag}`;
|
|
@@ -424,12 +494,15 @@ function renderToReadableStream(element) {
|
|
|
424
494
|
controller.enqueue(value);
|
|
425
495
|
}
|
|
426
496
|
},
|
|
427
|
-
cancel() {
|
|
428
|
-
generator.return(void 0);
|
|
497
|
+
async cancel() {
|
|
498
|
+
await generator.return(void 0);
|
|
429
499
|
}
|
|
430
500
|
});
|
|
431
501
|
}
|
|
432
502
|
function island(id, component) {
|
|
503
|
+
if (!SAFE_ID.test(id)) {
|
|
504
|
+
throw new Error(`[SibuJS SSR] island: id must match [A-Za-z0-9_-]+ (got: ${JSON.stringify(id.slice(0, 32))})`);
|
|
505
|
+
}
|
|
433
506
|
const el = component();
|
|
434
507
|
el.setAttribute("data-sibu-island", id);
|
|
435
508
|
return el;
|
|
@@ -442,8 +515,9 @@ function hydrateIslands(container, islands) {
|
|
|
442
515
|
const factory = islands[id];
|
|
443
516
|
if (typeof factory !== "function") continue;
|
|
444
517
|
const clientTree = factory();
|
|
445
|
-
|
|
446
|
-
|
|
518
|
+
clientTree.setAttribute("data-sibu-island", id);
|
|
519
|
+
clientTree.setAttribute("data-sibu-hydrated", "true");
|
|
520
|
+
marker2.replaceWith(clientTree);
|
|
447
521
|
}
|
|
448
522
|
container.setAttribute("data-sibu-hydrated", "partial");
|
|
449
523
|
}
|
|
@@ -460,8 +534,9 @@ function hydrateProgressively(container, islands, options) {
|
|
|
460
534
|
for (const entry of entries) {
|
|
461
535
|
if (entry.isIntersecting) {
|
|
462
536
|
const clientTree = factory();
|
|
463
|
-
|
|
464
|
-
|
|
537
|
+
clientTree.setAttribute("data-sibu-island", id);
|
|
538
|
+
clientTree.setAttribute("data-sibu-hydrated", "true");
|
|
539
|
+
marker2.replaceWith(clientTree);
|
|
465
540
|
observer.disconnect();
|
|
466
541
|
break;
|
|
467
542
|
}
|
|
@@ -478,18 +553,36 @@ function hydrateProgressively(container, islands, options) {
|
|
|
478
553
|
};
|
|
479
554
|
}
|
|
480
555
|
function resetSSRState() {
|
|
481
|
-
suspenseIdCounter = 0;
|
|
556
|
+
getSSRStore().suspenseIdCounter = 0;
|
|
557
|
+
}
|
|
558
|
+
function noop() {
|
|
482
559
|
}
|
|
483
560
|
function ssrSuspense(props) {
|
|
484
|
-
const
|
|
561
|
+
const store = getSSRStore();
|
|
562
|
+
const id = `sibu-sus-${store.suspenseIdCounter++}`;
|
|
563
|
+
const timeoutMs = props.timeoutMs ?? 3e4;
|
|
485
564
|
const fallbackEl = props.fallback();
|
|
486
565
|
const wrapper = document.createElement("div");
|
|
487
566
|
wrapper.setAttribute("data-sibu-suspense-id", id);
|
|
488
567
|
wrapper.appendChild(fallbackEl);
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
568
|
+
const fallbackHtml = renderToString(fallbackEl);
|
|
569
|
+
let timer;
|
|
570
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
571
|
+
timer = setTimeout(() => reject(new Error(`[SibuJS SSR] ssrSuspense timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
572
|
+
});
|
|
573
|
+
const raced = Promise.race([props.content(), timeoutPromise]);
|
|
574
|
+
const promise = raced.then(
|
|
575
|
+
(resolvedEl) => {
|
|
576
|
+
if (timer) clearTimeout(timer);
|
|
577
|
+
return { id, html: renderToString(resolvedEl) };
|
|
578
|
+
},
|
|
579
|
+
(err) => {
|
|
580
|
+
if (timer) clearTimeout(timer);
|
|
581
|
+
if (_isDev8) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
|
|
582
|
+
return { id, html: fallbackHtml };
|
|
583
|
+
}
|
|
584
|
+
);
|
|
585
|
+
promise.catch(noop);
|
|
493
586
|
return { element: wrapper, promise };
|
|
494
587
|
}
|
|
495
588
|
function suspenseSwapScript(id, nonce) {
|
|
@@ -515,14 +608,26 @@ async function* renderToSuspenseStream(element, pendingBoundaries = [], options)
|
|
|
515
608
|
function escapeScriptJson(json) {
|
|
516
609
|
return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
517
610
|
}
|
|
518
|
-
function serializeState(state, nonce) {
|
|
519
|
-
const
|
|
611
|
+
function serializeState(state, nonce, options) {
|
|
612
|
+
const rawJson = JSON.stringify(state);
|
|
613
|
+
const maxBytes = options?.maxBytes ?? DEFAULT_MAX_SSR_BYTES;
|
|
614
|
+
const byteLen = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(rawJson).byteLength : Buffer.byteLength(rawJson, "utf8");
|
|
615
|
+
if (byteLen > maxBytes) {
|
|
616
|
+
throw new Error(`[SibuJS SSR] serializeState: payload (${byteLen} bytes) exceeds maxBytes (${maxBytes})`);
|
|
617
|
+
}
|
|
618
|
+
const json = escapeScriptJson(rawJson);
|
|
520
619
|
const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
521
620
|
return `<script${nonceAttr}>window.${SSR_DATA_ATTR}=${json}</script>`;
|
|
522
621
|
}
|
|
523
622
|
function deserializeState(validate) {
|
|
524
623
|
if (typeof window === "undefined") return void 0;
|
|
525
|
-
|
|
624
|
+
if (_isDev8 && !validate) {
|
|
625
|
+
console.warn(
|
|
626
|
+
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
const w = window;
|
|
630
|
+
const raw = w[SSR_DATA_ATTR];
|
|
526
631
|
if (raw === void 0) return void 0;
|
|
527
632
|
if (validate && !validate(raw)) return void 0;
|
|
528
633
|
return raw;
|
|
@@ -533,13 +638,14 @@ function escapeHtml(str) {
|
|
|
533
638
|
function escapeAttr(str) {
|
|
534
639
|
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
535
640
|
}
|
|
536
|
-
var
|
|
641
|
+
var _isDev8, SAFE_ATTR_NAME, URL_ATTRS, VOID_ELEMENTS, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
|
|
537
642
|
var init_ssr = __esm({
|
|
538
643
|
"src/platform/ssr.ts"() {
|
|
539
644
|
"use strict";
|
|
540
645
|
init_dev();
|
|
646
|
+
init_ssr_context();
|
|
541
647
|
init_sanitize();
|
|
542
|
-
|
|
648
|
+
_isDev8 = isDev();
|
|
543
649
|
SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
544
650
|
URL_ATTRS = /* @__PURE__ */ new Set([
|
|
545
651
|
"href",
|
|
@@ -571,9 +677,10 @@ var init_ssr = __esm({
|
|
|
571
677
|
"track",
|
|
572
678
|
"wbr"
|
|
573
679
|
]);
|
|
574
|
-
|
|
680
|
+
SAFE_ID = /^[A-Za-z0-9_-]+$/;
|
|
575
681
|
SAFE_SUSPENSE_ID = /^[A-Za-z0-9_-]+$/;
|
|
576
682
|
SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
|
|
683
|
+
DEFAULT_MAX_SSR_BYTES = 1024 * 1024;
|
|
577
684
|
}
|
|
578
685
|
});
|
|
579
686
|
|
|
@@ -588,6 +695,7 @@ __export(plugins_exports, {
|
|
|
588
695
|
Suspense: () => Suspense,
|
|
589
696
|
Trans: () => Trans,
|
|
590
697
|
VERSION: () => VERSION,
|
|
698
|
+
__removeRouterPagehideHandler: () => __removeRouterPagehideHandler,
|
|
591
699
|
addRoute: () => addRoute,
|
|
592
700
|
afterEach: () => afterEach,
|
|
593
701
|
back: () => back,
|
|
@@ -603,6 +711,7 @@ __export(plugins_exports, {
|
|
|
603
711
|
createMigrationRunner: () => createMigrationRunner,
|
|
604
712
|
createModuleRegistry: () => createModuleRegistry,
|
|
605
713
|
createPlugin: () => createPlugin,
|
|
714
|
+
createPluginRegistry: () => createPluginRegistry,
|
|
606
715
|
createRouter: () => createRouter,
|
|
607
716
|
createSSRCache: () => createSSRCache,
|
|
608
717
|
createSSRRouter: () => createSSRRouter,
|
|
@@ -645,6 +754,7 @@ __export(plugins_exports, {
|
|
|
645
754
|
routerState: () => routerState,
|
|
646
755
|
satisfies: () => satisfies,
|
|
647
756
|
serializeRouteState: () => serializeRouteState,
|
|
757
|
+
setDefaultPluginRegistry: () => setDefaultPluginRegistry,
|
|
648
758
|
setLocale: () => setLocale,
|
|
649
759
|
setRouteTransition: () => setRouteTransition,
|
|
650
760
|
setRoutes: () => setRoutes,
|
|
@@ -655,6 +765,9 @@ __export(plugins_exports, {
|
|
|
655
765
|
});
|
|
656
766
|
module.exports = __toCommonJS(plugins_exports);
|
|
657
767
|
|
|
768
|
+
// src/core/rendering/tagFactory.ts
|
|
769
|
+
init_dev();
|
|
770
|
+
|
|
658
771
|
// src/reactivity/bindAttribute.ts
|
|
659
772
|
init_dev();
|
|
660
773
|
init_sanitize();
|
|
@@ -666,11 +779,11 @@ var subscriberStack = new Array(32);
|
|
|
666
779
|
var stackCapacity = 32;
|
|
667
780
|
var stackTop = -1;
|
|
668
781
|
var currentSubscriber = null;
|
|
669
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
670
782
|
var SUBS = "__s";
|
|
671
783
|
var notifyDepth = 0;
|
|
672
784
|
var pendingQueue = [];
|
|
673
785
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
786
|
+
var propagateStack = [];
|
|
674
787
|
function safeInvoke(sub2) {
|
|
675
788
|
try {
|
|
676
789
|
sub2();
|
|
@@ -716,7 +829,6 @@ function recordDependency(signal2) {
|
|
|
716
829
|
let subs = signal2[SUBS];
|
|
717
830
|
if (!subs) {
|
|
718
831
|
subs = /* @__PURE__ */ new Set();
|
|
719
|
-
signalSubscribers.set(signal2, subs);
|
|
720
832
|
signal2[SUBS] = subs;
|
|
721
833
|
}
|
|
722
834
|
subs.add(currentSubscriber);
|
|
@@ -726,42 +838,46 @@ function recordDependency(signal2) {
|
|
|
726
838
|
signal2.__f = void 0;
|
|
727
839
|
}
|
|
728
840
|
}
|
|
841
|
+
var maxDrainIterations = 1e5;
|
|
729
842
|
function propagateDirty(sub2) {
|
|
730
843
|
sub2();
|
|
731
|
-
|
|
732
|
-
|
|
844
|
+
const rootSig = sub2._sig;
|
|
845
|
+
if (!rootSig) return;
|
|
846
|
+
const stack = propagateStack;
|
|
847
|
+
const baseLen = stack.length;
|
|
848
|
+
stack.push(rootSig);
|
|
849
|
+
while (stack.length > baseLen) {
|
|
850
|
+
const sig = stack.pop();
|
|
733
851
|
const first = sig.__f;
|
|
734
852
|
if (first) {
|
|
735
853
|
if (first._c) {
|
|
736
854
|
const nSig = first._sig;
|
|
737
|
-
nSig._d
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
if (!pendingSet.has(first)) {
|
|
855
|
+
if (!nSig._d) {
|
|
856
|
+
nSig._d = true;
|
|
857
|
+
stack.push(nSig);
|
|
858
|
+
}
|
|
859
|
+
} else if (!pendingSet.has(first)) {
|
|
742
860
|
pendingSet.add(first);
|
|
743
861
|
pendingQueue.push(first);
|
|
744
862
|
}
|
|
745
|
-
|
|
863
|
+
continue;
|
|
746
864
|
}
|
|
747
865
|
const subs = sig[SUBS];
|
|
748
|
-
if (!subs)
|
|
749
|
-
let nextSig;
|
|
866
|
+
if (!subs) continue;
|
|
750
867
|
for (const s2 of subs) {
|
|
751
868
|
if (s2._c) {
|
|
752
|
-
s2();
|
|
753
869
|
const nSig = s2._sig;
|
|
754
|
-
if (nSig && !
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
870
|
+
if (nSig && !nSig._d) {
|
|
871
|
+
nSig._d = true;
|
|
872
|
+
stack.push(nSig);
|
|
873
|
+
} else if (!nSig) {
|
|
874
|
+
s2();
|
|
758
875
|
}
|
|
759
876
|
} else if (!pendingSet.has(s2)) {
|
|
760
877
|
pendingSet.add(s2);
|
|
761
878
|
pendingQueue.push(s2);
|
|
762
879
|
}
|
|
763
880
|
}
|
|
764
|
-
sig = nextSig;
|
|
765
881
|
}
|
|
766
882
|
}
|
|
767
883
|
function notifySubscribers(signal2) {
|
|
@@ -785,13 +901,23 @@ function notifySubscribers(signal2) {
|
|
|
785
901
|
}
|
|
786
902
|
let i2 = 0;
|
|
787
903
|
while (i2 < pendingQueue.length) {
|
|
904
|
+
if (i2 >= maxDrainIterations) {
|
|
905
|
+
if (typeof console !== "undefined") {
|
|
906
|
+
console.error(
|
|
907
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
break;
|
|
911
|
+
}
|
|
788
912
|
safeInvoke(pendingQueue[i2]);
|
|
789
913
|
i2++;
|
|
790
914
|
}
|
|
791
915
|
} finally {
|
|
792
|
-
pendingQueue.length = 0;
|
|
793
|
-
pendingSet.clear();
|
|
794
916
|
notifyDepth--;
|
|
917
|
+
if (notifyDepth === 0) {
|
|
918
|
+
pendingQueue.length = 0;
|
|
919
|
+
pendingSet.clear();
|
|
920
|
+
}
|
|
795
921
|
}
|
|
796
922
|
return;
|
|
797
923
|
}
|
|
@@ -811,30 +937,48 @@ function notifySubscribers(signal2) {
|
|
|
811
937
|
notifyDepth++;
|
|
812
938
|
try {
|
|
813
939
|
let directCount = 0;
|
|
940
|
+
let hasComputedSub = false;
|
|
814
941
|
for (const sub2 of subs) {
|
|
942
|
+
if (sub2._c) hasComputedSub = true;
|
|
815
943
|
pendingQueue[directCount++] = sub2;
|
|
816
944
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
945
|
+
if (!hasComputedSub) {
|
|
946
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
947
|
+
safeInvoke(pendingQueue[i3]);
|
|
820
948
|
}
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
949
|
+
} else {
|
|
950
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
951
|
+
if (pendingQueue[i3]._c) {
|
|
952
|
+
propagateDirty(pendingQueue[i3]);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
956
|
+
const sub2 = pendingQueue[i3];
|
|
957
|
+
if (!sub2._c && !pendingSet.has(sub2)) {
|
|
958
|
+
pendingSet.add(sub2);
|
|
959
|
+
safeInvoke(sub2);
|
|
826
960
|
}
|
|
827
961
|
}
|
|
828
962
|
}
|
|
829
963
|
let i2 = directCount;
|
|
830
964
|
while (i2 < pendingQueue.length) {
|
|
965
|
+
if (i2 - directCount >= maxDrainIterations) {
|
|
966
|
+
if (typeof console !== "undefined") {
|
|
967
|
+
console.error(
|
|
968
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
831
973
|
safeInvoke(pendingQueue[i2]);
|
|
832
974
|
i2++;
|
|
833
975
|
}
|
|
834
976
|
} finally {
|
|
835
|
-
pendingQueue.length = 0;
|
|
836
|
-
pendingSet.clear();
|
|
837
977
|
notifyDepth--;
|
|
978
|
+
if (notifyDepth === 0) {
|
|
979
|
+
pendingQueue.length = 0;
|
|
980
|
+
pendingSet.clear();
|
|
981
|
+
}
|
|
838
982
|
}
|
|
839
983
|
}
|
|
840
984
|
function cleanup(subscriber) {
|
|
@@ -845,7 +989,9 @@ function cleanup(subscriber) {
|
|
|
845
989
|
if (subs) {
|
|
846
990
|
subs.delete(subscriber);
|
|
847
991
|
if (singleDep.__f === subscriber) {
|
|
848
|
-
singleDep.__f = void 0;
|
|
992
|
+
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
993
|
+
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
994
|
+
singleDep.__f = subs.values().next().value;
|
|
849
995
|
}
|
|
850
996
|
}
|
|
851
997
|
sub2._dep = void 0;
|
|
@@ -858,7 +1004,9 @@ function cleanup(subscriber) {
|
|
|
858
1004
|
if (subs) {
|
|
859
1005
|
subs.delete(subscriber);
|
|
860
1006
|
if (signal2.__f === subscriber) {
|
|
861
|
-
signal2.__f = void 0;
|
|
1007
|
+
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
1008
|
+
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
1009
|
+
signal2.__f = subs.values().next().value;
|
|
862
1010
|
}
|
|
863
1011
|
}
|
|
864
1012
|
}
|
|
@@ -867,6 +1015,9 @@ function cleanup(subscriber) {
|
|
|
867
1015
|
|
|
868
1016
|
// src/reactivity/bindAttribute.ts
|
|
869
1017
|
var _isDev3 = isDev();
|
|
1018
|
+
function setProp(el, key, val) {
|
|
1019
|
+
el[key] = val;
|
|
1020
|
+
}
|
|
870
1021
|
function isEventHandlerAttr(name) {
|
|
871
1022
|
if (name.length < 3) return false;
|
|
872
1023
|
const lower = name.toLowerCase();
|
|
@@ -892,7 +1043,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
892
1043
|
}
|
|
893
1044
|
if (typeof value === "boolean") {
|
|
894
1045
|
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
895
|
-
el
|
|
1046
|
+
setProp(el, attr, value);
|
|
896
1047
|
} else if (value) {
|
|
897
1048
|
el.setAttribute(attr, "");
|
|
898
1049
|
} else {
|
|
@@ -902,7 +1053,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
902
1053
|
}
|
|
903
1054
|
const str = String(value);
|
|
904
1055
|
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
905
|
-
el
|
|
1056
|
+
setProp(el, attr, attr === "checked" ? Boolean(value) : str);
|
|
906
1057
|
} else {
|
|
907
1058
|
el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
|
|
908
1059
|
}
|
|
@@ -940,24 +1091,29 @@ function bindChildNode(placeholder, getter) {
|
|
|
940
1091
|
let newNodes;
|
|
941
1092
|
if (Array.isArray(result)) {
|
|
942
1093
|
newNodes = [];
|
|
1094
|
+
const seen = /* @__PURE__ */ new Set();
|
|
943
1095
|
for (let i2 = 0; i2 < result.length; i2++) {
|
|
944
1096
|
const item = result[i2];
|
|
945
1097
|
if (item == null || typeof item === "boolean") continue;
|
|
946
|
-
|
|
1098
|
+
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
1099
|
+
if (seen.has(node)) {
|
|
1100
|
+
if (_isDev4)
|
|
1101
|
+
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
1102
|
+
continue;
|
|
1103
|
+
}
|
|
1104
|
+
seen.add(node);
|
|
1105
|
+
newNodes.push(node);
|
|
947
1106
|
}
|
|
948
1107
|
} else {
|
|
949
1108
|
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
950
1109
|
newNodes = [node];
|
|
951
1110
|
}
|
|
952
|
-
|
|
953
|
-
if (
|
|
1111
|
+
let reused;
|
|
1112
|
+
if (lastNodes.length > 0 && newNodes.length > 0) {
|
|
1113
|
+
const lastSet = new Set(lastNodes);
|
|
1114
|
+
reused = /* @__PURE__ */ new Set();
|
|
954
1115
|
for (let i2 = 0; i2 < newNodes.length; i2++) {
|
|
955
|
-
|
|
956
|
-
if (newNodes[i2] === lastNodes[j]) {
|
|
957
|
-
reused.add(newNodes[i2]);
|
|
958
|
-
break;
|
|
959
|
-
}
|
|
960
|
-
}
|
|
1116
|
+
if (lastSet.has(newNodes[i2])) reused.add(newNodes[i2]);
|
|
961
1117
|
}
|
|
962
1118
|
}
|
|
963
1119
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
@@ -1004,7 +1160,7 @@ function dispose(node) {
|
|
|
1004
1160
|
while (stack.length > 0) {
|
|
1005
1161
|
const current = stack.pop();
|
|
1006
1162
|
order.push(current);
|
|
1007
|
-
const children = current.childNodes;
|
|
1163
|
+
const children = Array.from(current.childNodes);
|
|
1008
1164
|
for (let i2 = 0; i2 < children.length; i2++) {
|
|
1009
1165
|
stack.push(children[i2]);
|
|
1010
1166
|
}
|
|
@@ -1013,8 +1169,10 @@ function dispose(node) {
|
|
|
1013
1169
|
const current = order[i2];
|
|
1014
1170
|
const disposers = elementDisposers.get(current);
|
|
1015
1171
|
if (disposers) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1172
|
+
const snapshot = disposers.slice();
|
|
1173
|
+
elementDisposers.delete(current);
|
|
1174
|
+
if (_isDev5) activeBindingCount -= snapshot.length;
|
|
1175
|
+
for (const d of snapshot) {
|
|
1018
1176
|
try {
|
|
1019
1177
|
d();
|
|
1020
1178
|
} catch (err) {
|
|
@@ -1023,13 +1181,53 @@ function dispose(node) {
|
|
|
1023
1181
|
}
|
|
1024
1182
|
}
|
|
1025
1183
|
}
|
|
1026
|
-
|
|
1184
|
+
let extraPasses = 0;
|
|
1185
|
+
while (extraPasses++ < 8) {
|
|
1186
|
+
const added = elementDisposers.get(current);
|
|
1187
|
+
if (!added || added.length === 0) break;
|
|
1188
|
+
const moreSnapshot = added.slice();
|
|
1189
|
+
elementDisposers.delete(current);
|
|
1190
|
+
if (_isDev5) activeBindingCount -= moreSnapshot.length;
|
|
1191
|
+
for (const d of moreSnapshot) {
|
|
1192
|
+
try {
|
|
1193
|
+
d();
|
|
1194
|
+
} catch (err) {
|
|
1195
|
+
if (_isDev5 && typeof console !== "undefined") {
|
|
1196
|
+
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1027
1201
|
}
|
|
1028
1202
|
}
|
|
1029
1203
|
}
|
|
1030
1204
|
|
|
1031
1205
|
// src/core/rendering/tagFactory.ts
|
|
1032
1206
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1207
|
+
var _isDev6 = isDev();
|
|
1208
|
+
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
1209
|
+
function validateTagName(tag) {
|
|
1210
|
+
const lower = tag.toLowerCase();
|
|
1211
|
+
if (BLOCKED_TAGS.has(lower)) {
|
|
1212
|
+
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
1216
|
+
"config",
|
|
1217
|
+
"location",
|
|
1218
|
+
"history",
|
|
1219
|
+
"document",
|
|
1220
|
+
"window",
|
|
1221
|
+
"navigator",
|
|
1222
|
+
"name",
|
|
1223
|
+
"top",
|
|
1224
|
+
"parent",
|
|
1225
|
+
"self",
|
|
1226
|
+
"frames"
|
|
1227
|
+
]);
|
|
1228
|
+
function setProp2(el, key, val) {
|
|
1229
|
+
el[key] = val;
|
|
1230
|
+
}
|
|
1033
1231
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
1034
1232
|
function toKebab(prop) {
|
|
1035
1233
|
let cached = kebabCache.get(prop);
|
|
@@ -1154,79 +1352,103 @@ function appendChildren(el, nodes) {
|
|
|
1154
1352
|
}
|
|
1155
1353
|
}
|
|
1156
1354
|
}
|
|
1157
|
-
var tagFactory = (tag, ns) =>
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
if (
|
|
1162
|
-
|
|
1163
|
-
|
|
1355
|
+
var tagFactory = (tag, ns) => {
|
|
1356
|
+
return (first, second) => {
|
|
1357
|
+
validateTagName(tag);
|
|
1358
|
+
const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
1359
|
+
if (first === void 0) return el;
|
|
1360
|
+
if (typeof first === "string") {
|
|
1361
|
+
if (second !== void 0) {
|
|
1362
|
+
el.setAttribute("class", first);
|
|
1363
|
+
appendChildren(el, second);
|
|
1364
|
+
return el;
|
|
1365
|
+
}
|
|
1366
|
+
el.textContent = first;
|
|
1164
1367
|
return el;
|
|
1165
1368
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1369
|
+
if (typeof first === "number") {
|
|
1370
|
+
el.textContent = String(first);
|
|
1371
|
+
return el;
|
|
1372
|
+
}
|
|
1373
|
+
if (Array.isArray(first) || first instanceof Node || typeof first === "function") {
|
|
1374
|
+
appendChildren(el, first);
|
|
1375
|
+
return el;
|
|
1376
|
+
}
|
|
1377
|
+
const props = first;
|
|
1378
|
+
const pClass = props.class;
|
|
1379
|
+
if (pClass != null) applyClass(el, pClass);
|
|
1380
|
+
const pId = props.id;
|
|
1381
|
+
if (pId != null) {
|
|
1382
|
+
if (_isDev6 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
1383
|
+
devWarn(
|
|
1384
|
+
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
el.id = pId;
|
|
1388
|
+
}
|
|
1389
|
+
const pNodes = second !== void 0 ? second : props.nodes;
|
|
1390
|
+
if (pNodes != null) appendChildren(el, pNodes);
|
|
1391
|
+
const pOn = props.on;
|
|
1392
|
+
if (pOn) {
|
|
1393
|
+
for (const ev in pOn) {
|
|
1394
|
+
const handler = pOn[ev];
|
|
1395
|
+
if (typeof handler === "function") {
|
|
1396
|
+
el.addEventListener(ev, handler);
|
|
1397
|
+
} else if (_isDev6) {
|
|
1398
|
+
devWarn(
|
|
1399
|
+
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
const pStyle = props.style;
|
|
1405
|
+
if (pStyle != null) applyStyle(el, pStyle);
|
|
1406
|
+
const pRef = props.ref;
|
|
1407
|
+
if (pRef) pRef.current = el;
|
|
1408
|
+
for (const key in props) {
|
|
1409
|
+
switch (key) {
|
|
1410
|
+
case "class":
|
|
1411
|
+
case "id":
|
|
1412
|
+
case "nodes":
|
|
1413
|
+
case "on":
|
|
1414
|
+
case "style":
|
|
1415
|
+
case "ref":
|
|
1416
|
+
case "onElement":
|
|
1417
|
+
continue;
|
|
1418
|
+
// already handled above / below
|
|
1419
|
+
default: {
|
|
1420
|
+
const value = props[key];
|
|
1421
|
+
if (value == null) continue;
|
|
1422
|
+
const lkey = key.toLowerCase();
|
|
1423
|
+
if (lkey[0] === "o" && lkey[1] === "n") continue;
|
|
1424
|
+
if (typeof value === "function") {
|
|
1425
|
+
registerDisposer(el, bindAttribute(el, key, value));
|
|
1426
|
+
} else if (typeof value === "boolean") {
|
|
1427
|
+
if (key in el && (key === "checked" || key === "disabled" || key === "selected")) {
|
|
1428
|
+
setProp2(el, key, value);
|
|
1429
|
+
} else if (value) {
|
|
1430
|
+
el.setAttribute(key, "");
|
|
1431
|
+
} else {
|
|
1432
|
+
el.removeAttribute(key);
|
|
1433
|
+
}
|
|
1216
1434
|
} else {
|
|
1217
|
-
|
|
1435
|
+
const str = String(value);
|
|
1436
|
+
if (lkey === "srcset") {
|
|
1437
|
+
el.setAttribute(key, sanitizeSrcset(str));
|
|
1438
|
+
} else if (isUrlAttribute(lkey)) {
|
|
1439
|
+
el.setAttribute(key, sanitizeUrl(str));
|
|
1440
|
+
} else {
|
|
1441
|
+
el.setAttribute(key, str);
|
|
1442
|
+
}
|
|
1218
1443
|
}
|
|
1219
|
-
} else {
|
|
1220
|
-
const str = String(value);
|
|
1221
|
-
el.setAttribute(key, isUrlAttribute(key) ? sanitizeUrl(str) : str);
|
|
1222
1444
|
}
|
|
1223
1445
|
}
|
|
1224
1446
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1447
|
+
if (props.onElement && typeof props.onElement === "function") {
|
|
1448
|
+
props.onElement(el);
|
|
1449
|
+
}
|
|
1450
|
+
return el;
|
|
1451
|
+
};
|
|
1230
1452
|
};
|
|
1231
1453
|
|
|
1232
1454
|
// src/core/rendering/html.ts
|
|
@@ -1379,10 +1601,10 @@ function enqueueBatchedSignal(signal2) {
|
|
|
1379
1601
|
// src/core/signals/signal.ts
|
|
1380
1602
|
init_dev();
|
|
1381
1603
|
var _g = globalThis;
|
|
1382
|
-
var
|
|
1604
|
+
var _isDev7 = isDev();
|
|
1383
1605
|
function signal(initial, options) {
|
|
1384
1606
|
const state = { value: initial };
|
|
1385
|
-
const debugName =
|
|
1607
|
+
const debugName = _isDev7 ? options?.name : void 0;
|
|
1386
1608
|
const equalsFn = options?.equals;
|
|
1387
1609
|
if (debugName) {
|
|
1388
1610
|
state.__name = debugName;
|
|
@@ -1396,7 +1618,7 @@ function signal(initial, options) {
|
|
|
1396
1618
|
function set(next) {
|
|
1397
1619
|
const newValue = typeof next === "function" ? next(state.value) : next;
|
|
1398
1620
|
if (equalsFn ? equalsFn(state.value, newValue) : Object.is(newValue, state.value)) return;
|
|
1399
|
-
if (
|
|
1621
|
+
if (_isDev7) {
|
|
1400
1622
|
const oldValue = state.value;
|
|
1401
1623
|
state.value = newValue;
|
|
1402
1624
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
@@ -1408,7 +1630,7 @@ function signal(initial, options) {
|
|
|
1408
1630
|
notifySubscribers(state);
|
|
1409
1631
|
}
|
|
1410
1632
|
}
|
|
1411
|
-
if (
|
|
1633
|
+
if (_isDev7) {
|
|
1412
1634
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1413
1635
|
if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
|
|
1414
1636
|
}
|
|
@@ -1445,40 +1667,93 @@ function getAvailableLocales() {
|
|
|
1445
1667
|
|
|
1446
1668
|
// src/core/signals/effect.ts
|
|
1447
1669
|
init_dev();
|
|
1448
|
-
|
|
1449
|
-
// src/core/ssr-context.ts
|
|
1450
|
-
var ssrMode = false;
|
|
1451
|
-
function isSSR() {
|
|
1452
|
-
return ssrMode;
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
// src/core/signals/effect.ts
|
|
1670
|
+
init_ssr_context();
|
|
1456
1671
|
var _g2 = globalThis;
|
|
1457
1672
|
function effect(effectFn, options) {
|
|
1458
1673
|
devAssert(typeof effectFn === "function", "effect: argument must be a function.");
|
|
1459
1674
|
if (isSSR()) return () => {
|
|
1460
1675
|
};
|
|
1461
1676
|
const onError = options?.onError;
|
|
1677
|
+
let userCleanups = [];
|
|
1678
|
+
const onCleanup = (fn) => {
|
|
1679
|
+
userCleanups.push(fn);
|
|
1680
|
+
};
|
|
1681
|
+
const runUserCleanups = () => {
|
|
1682
|
+
if (userCleanups.length === 0) return;
|
|
1683
|
+
const list = userCleanups;
|
|
1684
|
+
userCleanups = [];
|
|
1685
|
+
for (let i2 = list.length - 1; i2 >= 0; i2--) {
|
|
1686
|
+
try {
|
|
1687
|
+
list[i2]();
|
|
1688
|
+
} catch (err) {
|
|
1689
|
+
if (typeof console !== "undefined") {
|
|
1690
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
};
|
|
1695
|
+
const invokeBody = () => effectFn(onCleanup);
|
|
1462
1696
|
const wrappedFn = onError ? () => {
|
|
1463
1697
|
try {
|
|
1464
|
-
|
|
1698
|
+
invokeBody();
|
|
1465
1699
|
} catch (err) {
|
|
1466
1700
|
onError(err);
|
|
1467
1701
|
}
|
|
1468
|
-
} :
|
|
1702
|
+
} : invokeBody;
|
|
1469
1703
|
let cleanupHandle = () => {
|
|
1470
1704
|
};
|
|
1705
|
+
let running = false;
|
|
1471
1706
|
const subscriber = () => {
|
|
1472
|
-
|
|
1473
|
-
|
|
1707
|
+
if (running) {
|
|
1708
|
+
if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
1709
|
+
console.warn(
|
|
1710
|
+
"[SibuJS] effect re-entered itself while running \u2014 the triggering update will be ignored. Wrap mutual writes in `batch()` or split the effect to avoid this."
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
running = true;
|
|
1716
|
+
try {
|
|
1717
|
+
runUserCleanups();
|
|
1718
|
+
cleanupHandle();
|
|
1719
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
1720
|
+
} finally {
|
|
1721
|
+
running = false;
|
|
1722
|
+
}
|
|
1474
1723
|
};
|
|
1475
|
-
|
|
1724
|
+
running = true;
|
|
1725
|
+
try {
|
|
1726
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
1727
|
+
} finally {
|
|
1728
|
+
running = false;
|
|
1729
|
+
}
|
|
1476
1730
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1477
1731
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
1732
|
+
let disposed = false;
|
|
1478
1733
|
return () => {
|
|
1734
|
+
if (disposed) return;
|
|
1735
|
+
disposed = true;
|
|
1479
1736
|
const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1480
|
-
if (h)
|
|
1481
|
-
|
|
1737
|
+
if (h) {
|
|
1738
|
+
try {
|
|
1739
|
+
h.emit("effect:destroy", { effectFn });
|
|
1740
|
+
} catch {
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
try {
|
|
1744
|
+
runUserCleanups();
|
|
1745
|
+
} catch (err) {
|
|
1746
|
+
if (typeof console !== "undefined") {
|
|
1747
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
try {
|
|
1751
|
+
cleanupHandle();
|
|
1752
|
+
} catch (err) {
|
|
1753
|
+
if (typeof console !== "undefined") {
|
|
1754
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1482
1757
|
};
|
|
1483
1758
|
}
|
|
1484
1759
|
|
|
@@ -1849,9 +2124,11 @@ var ComponentLoader = class {
|
|
|
1849
2124
|
}
|
|
1850
2125
|
return component;
|
|
1851
2126
|
} catch (error) {
|
|
1852
|
-
|
|
2127
|
+
const wrapped = new Error(
|
|
1853
2128
|
`Failed to load component for route "${routePath}": ${error instanceof Error ? error.message : String(error)}`
|
|
1854
2129
|
);
|
|
2130
|
+
wrapped.cause = error;
|
|
2131
|
+
throw wrapped;
|
|
1855
2132
|
}
|
|
1856
2133
|
}
|
|
1857
2134
|
isAsyncComponent(comp) {
|
|
@@ -2037,10 +2314,13 @@ var _SibuRouter = class _SibuRouter {
|
|
|
2037
2314
|
}
|
|
2038
2315
|
if ("redirect" in route2) {
|
|
2039
2316
|
const redirectPath = typeof route2.redirect === "function" ? route2.redirect(to) : route2.redirect;
|
|
2040
|
-
if (typeof redirectPath === "string" && /^https
|
|
2041
|
-
console
|
|
2042
|
-
|
|
2043
|
-
|
|
2317
|
+
if (typeof redirectPath === "string" && /^(https?:)?\/\//i.test(redirectPath)) {
|
|
2318
|
+
if (typeof console !== "undefined") {
|
|
2319
|
+
console.error(
|
|
2320
|
+
`[SibuJS Router] Refusing absolute/protocol-relative redirect "${redirectPath}" \u2014 open-redirect risk.`
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2323
|
+
throw new NavigationFailureError("aborted", from, to);
|
|
2044
2324
|
}
|
|
2045
2325
|
if (typeof redirectPath === "string" && !isSafeNavigationTarget(redirectPath)) {
|
|
2046
2326
|
throw new NavigationFailureError("aborted", from, to);
|
|
@@ -2243,6 +2523,7 @@ function createRouter(routesOrOptions, options = {}) {
|
|
|
2243
2523
|
routes = [];
|
|
2244
2524
|
}
|
|
2245
2525
|
globalRouter = new SibuRouter(routes, options);
|
|
2526
|
+
ensureRouterPagehide();
|
|
2246
2527
|
return globalRouter;
|
|
2247
2528
|
}
|
|
2248
2529
|
function setRoutes(routes) {
|
|
@@ -2316,7 +2597,9 @@ function Route() {
|
|
|
2316
2597
|
let currentTopRoute = null;
|
|
2317
2598
|
const cleanupNodes = () => {
|
|
2318
2599
|
[currentNode, loadingNode, errorNode].forEach((node) => {
|
|
2319
|
-
if (node
|
|
2600
|
+
if (!node) return;
|
|
2601
|
+
dispose(node);
|
|
2602
|
+
if (node.parentNode) {
|
|
2320
2603
|
node.parentNode.removeChild(node);
|
|
2321
2604
|
}
|
|
2322
2605
|
});
|
|
@@ -2347,13 +2630,24 @@ function Route() {
|
|
|
2347
2630
|
loadingNode = null;
|
|
2348
2631
|
}
|
|
2349
2632
|
};
|
|
2350
|
-
const showError = (error) => {
|
|
2633
|
+
const showError = (error, routeDef) => {
|
|
2351
2634
|
if (!anchor.parentNode) return;
|
|
2352
2635
|
cleanupNodes();
|
|
2353
2636
|
errorNode = document.createElement("div");
|
|
2354
2637
|
errorNode.className = "route-error";
|
|
2355
2638
|
errorNode.setAttribute("role", "alert");
|
|
2356
2639
|
errorNode.setAttribute("aria-live", "assertive");
|
|
2640
|
+
if (routeDef && "component" in routeDef) {
|
|
2641
|
+
const src = routeDef.component.toString();
|
|
2642
|
+
const importMatch = src.match(/import\(["']([^"']+)["']\)/);
|
|
2643
|
+
if (importMatch) {
|
|
2644
|
+
errorNode.setAttribute("data-component-source", importMatch[1]);
|
|
2645
|
+
}
|
|
2646
|
+
if (routeDef.component.name) {
|
|
2647
|
+
errorNode.setAttribute("data-component-name", routeDef.component.name);
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
errorNode.__routeError = error;
|
|
2357
2651
|
const title2 = document.createElement("h3");
|
|
2358
2652
|
title2.textContent = "Route Error";
|
|
2359
2653
|
title2.className = "route-error-title";
|
|
@@ -2364,12 +2658,14 @@ function Route() {
|
|
|
2364
2658
|
retryButton.textContent = "Retry";
|
|
2365
2659
|
retryButton.className = "route-error-retry";
|
|
2366
2660
|
retryButton.type = "button";
|
|
2367
|
-
|
|
2661
|
+
const onRetryClick = () => {
|
|
2368
2662
|
if (globalRouter) {
|
|
2369
2663
|
globalRouter.clearErrorCache();
|
|
2370
2664
|
update();
|
|
2371
2665
|
}
|
|
2372
|
-
}
|
|
2666
|
+
};
|
|
2667
|
+
retryButton.addEventListener("click", onRetryClick);
|
|
2668
|
+
registerDisposer(retryButton, () => retryButton.removeEventListener("click", onRetryClick));
|
|
2373
2669
|
errorNode.appendChild(title2);
|
|
2374
2670
|
errorNode.appendChild(message);
|
|
2375
2671
|
errorNode.appendChild(retryButton);
|
|
@@ -2401,7 +2697,11 @@ function Route() {
|
|
|
2401
2697
|
currentTopRoute = routeDef;
|
|
2402
2698
|
if ("redirect" in routeDef) {
|
|
2403
2699
|
const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
|
|
2404
|
-
queueMicrotask(() =>
|
|
2700
|
+
queueMicrotask(() => {
|
|
2701
|
+
globalRouter?.navigate(redirectPath).catch((err) => {
|
|
2702
|
+
if (typeof console !== "undefined") console.error("[router] redirect failed:", err);
|
|
2703
|
+
});
|
|
2704
|
+
});
|
|
2405
2705
|
return;
|
|
2406
2706
|
}
|
|
2407
2707
|
if ("component" in routeDef) {
|
|
@@ -2420,7 +2720,7 @@ function Route() {
|
|
|
2420
2720
|
} catch (error) {
|
|
2421
2721
|
hideLoading();
|
|
2422
2722
|
console.error("[Route] Component error:", error);
|
|
2423
|
-
showError(error instanceof Error ? error : new Error(String(error)));
|
|
2723
|
+
showError(error instanceof Error ? error : new Error(String(error)), routeDef);
|
|
2424
2724
|
}
|
|
2425
2725
|
}
|
|
2426
2726
|
} catch (error) {
|
|
@@ -2440,13 +2740,16 @@ function Route() {
|
|
|
2440
2740
|
await originalUpdate();
|
|
2441
2741
|
routeInitialized = true;
|
|
2442
2742
|
};
|
|
2443
|
-
track(wrappedUpdate);
|
|
2743
|
+
const routeTeardown = track(wrappedUpdate);
|
|
2444
2744
|
if (!routeInitialized) {
|
|
2445
2745
|
queueMicrotask(() => {
|
|
2446
2746
|
if (!routeInitialized && anchor.parentNode) wrappedUpdate();
|
|
2447
2747
|
});
|
|
2448
2748
|
}
|
|
2449
|
-
routeCleanups.push(
|
|
2749
|
+
routeCleanups.push(() => {
|
|
2750
|
+
routeTeardown();
|
|
2751
|
+
cleanupNodes();
|
|
2752
|
+
});
|
|
2450
2753
|
return anchor;
|
|
2451
2754
|
}
|
|
2452
2755
|
function KeepAliveRoute(options) {
|
|
@@ -2475,7 +2778,11 @@ function KeepAliveRoute(options) {
|
|
|
2475
2778
|
const { route: routeDef } = match;
|
|
2476
2779
|
if ("redirect" in routeDef) {
|
|
2477
2780
|
const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
|
|
2478
|
-
queueMicrotask(() =>
|
|
2781
|
+
queueMicrotask(() => {
|
|
2782
|
+
globalRouter?.navigate(redirectPath).catch((err) => {
|
|
2783
|
+
if (typeof console !== "undefined") console.error("[router] redirect failed:", err);
|
|
2784
|
+
});
|
|
2785
|
+
});
|
|
2479
2786
|
return;
|
|
2480
2787
|
}
|
|
2481
2788
|
if (!("component" in routeDef)) return;
|
|
@@ -2545,13 +2852,14 @@ function KeepAliveRoute(options) {
|
|
|
2545
2852
|
await update();
|
|
2546
2853
|
initialized = true;
|
|
2547
2854
|
};
|
|
2548
|
-
track(wrappedUpdate);
|
|
2855
|
+
const kaTeardown = track(wrappedUpdate);
|
|
2549
2856
|
if (!initialized) {
|
|
2550
2857
|
queueMicrotask(() => {
|
|
2551
2858
|
if (!initialized && anchor.parentNode) wrappedUpdate();
|
|
2552
2859
|
});
|
|
2553
2860
|
}
|
|
2554
2861
|
routeCleanups.push(() => {
|
|
2862
|
+
kaTeardown();
|
|
2555
2863
|
for (const node of cache.values()) {
|
|
2556
2864
|
dispose(node);
|
|
2557
2865
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
@@ -2618,12 +2926,18 @@ function RouterLink(props) {
|
|
|
2618
2926
|
}
|
|
2619
2927
|
});
|
|
2620
2928
|
}
|
|
2621
|
-
|
|
2929
|
+
const onLinkClick = (e) => {
|
|
2622
2930
|
if (target || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) {
|
|
2623
2931
|
return;
|
|
2624
2932
|
}
|
|
2625
2933
|
e.preventDefault();
|
|
2626
|
-
globalRouter?.navigate(to, { replace: replace2 })
|
|
2934
|
+
globalRouter?.navigate(to, { replace: replace2 }).catch((err) => {
|
|
2935
|
+
if (typeof console !== "undefined") console.error("[router] link navigate failed:", err);
|
|
2936
|
+
});
|
|
2937
|
+
};
|
|
2938
|
+
link2.addEventListener("click", onLinkClick);
|
|
2939
|
+
registerDisposer(link2, () => {
|
|
2940
|
+
link2.removeEventListener("click", onLinkClick);
|
|
2627
2941
|
});
|
|
2628
2942
|
return link2;
|
|
2629
2943
|
}
|
|
@@ -2734,10 +3048,21 @@ function destroyRouter() {
|
|
|
2734
3048
|
globalRouter = null;
|
|
2735
3049
|
}
|
|
2736
3050
|
}
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
3051
|
+
var _routerPagehideHandler = null;
|
|
3052
|
+
function ensureRouterPagehide() {
|
|
3053
|
+
if (_routerPagehideHandler || typeof window === "undefined") return;
|
|
3054
|
+
_routerPagehideHandler = (event) => {
|
|
3055
|
+
if (event.persisted === false) {
|
|
3056
|
+
destroyRouter();
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
window.addEventListener("pagehide", _routerPagehideHandler);
|
|
3060
|
+
}
|
|
3061
|
+
function __removeRouterPagehideHandler() {
|
|
3062
|
+
if (_routerPagehideHandler && typeof window !== "undefined") {
|
|
3063
|
+
window.removeEventListener("pagehide", _routerPagehideHandler);
|
|
3064
|
+
_routerPagehideHandler = null;
|
|
3065
|
+
}
|
|
2741
3066
|
}
|
|
2742
3067
|
function Outlet() {
|
|
2743
3068
|
const anchor = document.createComment("route-outlet-nested");
|
|
@@ -2763,12 +3088,20 @@ function Outlet() {
|
|
|
2763
3088
|
console.error("[Outlet] Failed to render child route:", error);
|
|
2764
3089
|
}
|
|
2765
3090
|
};
|
|
2766
|
-
track(update);
|
|
3091
|
+
const outletTeardown = track(update);
|
|
2767
3092
|
if (!anchor.parentNode) {
|
|
2768
3093
|
queueMicrotask(() => {
|
|
2769
3094
|
if (anchor.parentNode) update();
|
|
2770
3095
|
});
|
|
2771
3096
|
}
|
|
3097
|
+
routeCleanups.push(() => {
|
|
3098
|
+
outletTeardown();
|
|
3099
|
+
if (currentNode) {
|
|
3100
|
+
dispose(currentNode);
|
|
3101
|
+
if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
|
|
3102
|
+
currentNode = null;
|
|
3103
|
+
}
|
|
3104
|
+
});
|
|
2772
3105
|
return anchor;
|
|
2773
3106
|
}
|
|
2774
3107
|
function addRoute(route2, parentPath) {
|
|
@@ -3086,6 +3419,10 @@ function hydrateRouter(routes, options) {
|
|
|
3086
3419
|
if (resolved.component) {
|
|
3087
3420
|
hydrate2(resolved.component, container);
|
|
3088
3421
|
}
|
|
3422
|
+
}).catch((err) => {
|
|
3423
|
+
if (typeof console !== "undefined") {
|
|
3424
|
+
console.error("[SibuJS routerSSR] failed to load hydrate:", err);
|
|
3425
|
+
}
|
|
3089
3426
|
});
|
|
3090
3427
|
}
|
|
3091
3428
|
}
|
|
@@ -3159,83 +3496,117 @@ function escapeAttrLocal(str) {
|
|
|
3159
3496
|
}
|
|
3160
3497
|
|
|
3161
3498
|
// src/plugins/plugin.ts
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
init: [],
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3499
|
+
function createPluginRegistry() {
|
|
3500
|
+
const installedPlugins = /* @__PURE__ */ new Set();
|
|
3501
|
+
const hooks = { init: [], mount: [], unmount: [], error: [] };
|
|
3502
|
+
const provided = /* @__PURE__ */ new Map();
|
|
3503
|
+
const registry = {
|
|
3504
|
+
installedPlugins,
|
|
3505
|
+
hooks,
|
|
3506
|
+
provided,
|
|
3507
|
+
plugin(p2, options) {
|
|
3508
|
+
if (installedPlugins.has(p2.name)) {
|
|
3509
|
+
console.warn(`[Plugin] "${p2.name}" is already installed.`);
|
|
3510
|
+
return;
|
|
3511
|
+
}
|
|
3512
|
+
const ctx = {
|
|
3513
|
+
onInit: (cb) => hooks.init.push(cb),
|
|
3514
|
+
onMount: (cb) => hooks.mount.push(cb),
|
|
3515
|
+
onUnmount: (cb) => hooks.unmount.push(cb),
|
|
3516
|
+
onError: (cb) => hooks.error.push(cb),
|
|
3517
|
+
provide: (key, value) => provided.set(key, value)
|
|
3518
|
+
};
|
|
3519
|
+
const initHooksBefore = hooks.init.length;
|
|
3520
|
+
p2.install(ctx, options);
|
|
3521
|
+
installedPlugins.add(p2.name);
|
|
3522
|
+
const justAdded = hooks.init.slice(initHooksBefore);
|
|
3523
|
+
for (const cb of justAdded) {
|
|
3524
|
+
try {
|
|
3525
|
+
cb();
|
|
3526
|
+
} catch (e) {
|
|
3527
|
+
console.error(`[Plugin] "${p2.name}" init error:`, e);
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
},
|
|
3531
|
+
inject(key, defaultValue) {
|
|
3532
|
+
if (provided.has(key)) return provided.get(key);
|
|
3533
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
3534
|
+
throw new Error(`[Plugin] No provider found for key "${key}"`);
|
|
3535
|
+
},
|
|
3536
|
+
triggerMount(element) {
|
|
3537
|
+
const snapshot = hooks.mount.slice();
|
|
3538
|
+
for (const hook of snapshot) {
|
|
3539
|
+
try {
|
|
3540
|
+
hook(element);
|
|
3541
|
+
} catch (e) {
|
|
3542
|
+
console.error("[Plugin] Mount hook error:", e);
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
},
|
|
3546
|
+
triggerUnmount(element) {
|
|
3547
|
+
const snapshot = hooks.unmount.slice();
|
|
3548
|
+
for (const hook of snapshot) {
|
|
3549
|
+
try {
|
|
3550
|
+
hook(element);
|
|
3551
|
+
} catch (e) {
|
|
3552
|
+
console.error("[Plugin] Unmount hook error:", e);
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
},
|
|
3556
|
+
triggerError(error) {
|
|
3557
|
+
const snapshot = hooks.error.slice();
|
|
3558
|
+
for (const hook of snapshot) {
|
|
3559
|
+
try {
|
|
3560
|
+
hook(error);
|
|
3561
|
+
} catch (e) {
|
|
3562
|
+
console.error("[Plugin] Error hook error:", e);
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
},
|
|
3566
|
+
reset() {
|
|
3567
|
+
installedPlugins.clear();
|
|
3568
|
+
hooks.init.length = 0;
|
|
3569
|
+
hooks.mount.length = 0;
|
|
3570
|
+
hooks.unmount.length = 0;
|
|
3571
|
+
hooks.error.length = 0;
|
|
3572
|
+
provided.clear();
|
|
3573
|
+
}
|
|
3574
|
+
};
|
|
3575
|
+
return registry;
|
|
3576
|
+
}
|
|
3577
|
+
var defaultRegistry = createPluginRegistry();
|
|
3578
|
+
var defaultRegistryTouched = false;
|
|
3170
3579
|
function createPlugin(name, install) {
|
|
3171
3580
|
return { name, install };
|
|
3172
3581
|
}
|
|
3173
3582
|
function plugin(plugin2, options) {
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
return;
|
|
3177
|
-
}
|
|
3178
|
-
const ctx = {
|
|
3179
|
-
onInit: (cb) => hooks.init.push(cb),
|
|
3180
|
-
onMount: (cb) => hooks.mount.push(cb),
|
|
3181
|
-
onUnmount: (cb) => hooks.unmount.push(cb),
|
|
3182
|
-
onError: (cb) => hooks.error.push(cb),
|
|
3183
|
-
provide: (key, value) => provided.set(key, value)
|
|
3184
|
-
};
|
|
3185
|
-
const initHooksBefore = hooks.init.length;
|
|
3186
|
-
plugin2.install(ctx, options);
|
|
3187
|
-
installedPlugins.add(plugin2.name);
|
|
3188
|
-
for (let i2 = initHooksBefore; i2 < hooks.init.length; i2++) {
|
|
3189
|
-
try {
|
|
3190
|
-
hooks.init[i2]();
|
|
3191
|
-
} catch (e) {
|
|
3192
|
-
console.error(`[Plugin] "${plugin2.name}" init error:`, e);
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3583
|
+
defaultRegistryTouched = true;
|
|
3584
|
+
defaultRegistry.plugin(plugin2, options);
|
|
3195
3585
|
}
|
|
3196
3586
|
function inject(key, defaultValue) {
|
|
3197
|
-
|
|
3198
|
-
return provided.get(key);
|
|
3199
|
-
}
|
|
3200
|
-
if (defaultValue !== void 0) {
|
|
3201
|
-
return defaultValue;
|
|
3202
|
-
}
|
|
3203
|
-
throw new Error(`[Plugin] No provider found for key "${key}"`);
|
|
3587
|
+
return defaultRegistry.inject(key, defaultValue);
|
|
3204
3588
|
}
|
|
3205
3589
|
function triggerPluginMount(element) {
|
|
3206
|
-
|
|
3207
|
-
try {
|
|
3208
|
-
hook(element);
|
|
3209
|
-
} catch (e) {
|
|
3210
|
-
console.error("[Plugin] Mount hook error:", e);
|
|
3211
|
-
}
|
|
3212
|
-
}
|
|
3590
|
+
defaultRegistry.triggerMount(element);
|
|
3213
3591
|
}
|
|
3214
3592
|
function triggerPluginUnmount(element) {
|
|
3215
|
-
|
|
3216
|
-
try {
|
|
3217
|
-
hook(element);
|
|
3218
|
-
} catch (e) {
|
|
3219
|
-
console.error("[Plugin] Unmount hook error:", e);
|
|
3220
|
-
}
|
|
3221
|
-
}
|
|
3593
|
+
defaultRegistry.triggerUnmount(element);
|
|
3222
3594
|
}
|
|
3223
3595
|
function triggerPluginError(error) {
|
|
3224
|
-
|
|
3225
|
-
try {
|
|
3226
|
-
hook(error);
|
|
3227
|
-
} catch (e) {
|
|
3228
|
-
console.error("[Plugin] Error hook error:", e);
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3596
|
+
defaultRegistry.triggerError(error);
|
|
3231
3597
|
}
|
|
3232
3598
|
function resetPlugins() {
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3599
|
+
defaultRegistry.reset();
|
|
3600
|
+
defaultRegistryTouched = false;
|
|
3601
|
+
}
|
|
3602
|
+
function setDefaultPluginRegistry(registry) {
|
|
3603
|
+
if (defaultRegistryTouched && defaultRegistry.installedPlugins.size > 0) {
|
|
3604
|
+
console.warn(
|
|
3605
|
+
"[Plugin] Replacing default plugin registry while plugins are already installed on the singleton. This may indicate mixed singleton/registry usage."
|
|
3606
|
+
);
|
|
3607
|
+
}
|
|
3608
|
+
defaultRegistry = registry;
|
|
3609
|
+
defaultRegistryTouched = true;
|
|
3239
3610
|
}
|
|
3240
3611
|
|
|
3241
3612
|
// src/plugins/modular.ts
|
|
@@ -3713,7 +4084,8 @@ init_ssr();
|
|
|
3713
4084
|
function preloadCritical(resources) {
|
|
3714
4085
|
if (typeof document === "undefined") return;
|
|
3715
4086
|
for (const resource of resources) {
|
|
3716
|
-
const
|
|
4087
|
+
const safeHref = typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(resource.href) : resource.href.replace(/["\\]/g, "\\$&");
|
|
4088
|
+
const existing = document.querySelector(`link[rel="preload"][href="${safeHref}"]`);
|
|
3717
4089
|
if (existing) continue;
|
|
3718
4090
|
const link2 = document.createElement("link");
|
|
3719
4091
|
link2.rel = "preload";
|
|
@@ -3948,6 +4320,7 @@ function createBootSequence() {
|
|
|
3948
4320
|
Suspense,
|
|
3949
4321
|
Trans,
|
|
3950
4322
|
VERSION,
|
|
4323
|
+
__removeRouterPagehideHandler,
|
|
3951
4324
|
addRoute,
|
|
3952
4325
|
afterEach,
|
|
3953
4326
|
back,
|
|
@@ -3963,6 +4336,7 @@ function createBootSequence() {
|
|
|
3963
4336
|
createMigrationRunner,
|
|
3964
4337
|
createModuleRegistry,
|
|
3965
4338
|
createPlugin,
|
|
4339
|
+
createPluginRegistry,
|
|
3966
4340
|
createRouter,
|
|
3967
4341
|
createSSRCache,
|
|
3968
4342
|
createSSRRouter,
|
|
@@ -4005,6 +4379,7 @@ function createBootSequence() {
|
|
|
4005
4379
|
routerState,
|
|
4006
4380
|
satisfies,
|
|
4007
4381
|
serializeRouteState,
|
|
4382
|
+
setDefaultPluginRegistry,
|
|
4008
4383
|
setLocale,
|
|
4009
4384
|
setRouteTransition,
|
|
4010
4385
|
setRoutes,
|