sibujs 1.4.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/README.md +105 -119
- package/dist/browser.cjs +288 -80
- package/dist/browser.d.cts +19 -9
- package/dist/browser.d.ts +19 -9
- package/dist/browser.js +6 -6
- package/dist/build.cjs +1019 -313
- package/dist/build.d.cts +1 -1
- package/dist/build.d.ts +1 -1
- 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-ZWKZCBO6.js → chunk-3LR7GLWQ.js} +154 -33
- package/dist/{chunk-3AIRKM3B.js → chunk-3NSGB5JN.js} +115 -34
- package/dist/{chunk-3ARAQO7B.js → chunk-52YJLLRO.js} +29 -6
- package/dist/chunk-54EDRCEF.js +93 -0
- 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-WR5D4EGH.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-JAKHTMQU.js → chunk-JA6667UN.js} +206 -46
- package/dist/{chunk-77L6NL3X.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-F3FA4F32.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-TSOKIX5Z.js → chunk-MIUAXB7K.js} +126 -74
- package/dist/{chunk-QWZG56ET.js → chunk-ND2664SF.js} +558 -190
- package/dist/{chunk-JCI5M6U6.js → chunk-O2MNQFLP.js} +261 -79
- package/dist/{chunk-EWFVA3TJ.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-ZD6OAMTH.js → chunk-VLPPXTYG.js} +90 -35
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- package/dist/{contracts-xo5ckdRP.d.cts → contracts-ey_Qh8ef.d.cts} +7 -8
- package/dist/{contracts-xo5ckdRP.d.ts → contracts-ey_Qh8ef.d.ts} +7 -8
- package/dist/{customElement-D2DJp_xn.d.cts → customElement-CPfIrbvg.d.cts} +18 -9
- package/dist/{customElement-D2DJp_xn.d.ts → customElement-CPfIrbvg.d.ts} +18 -9
- package/dist/data.cjs +452 -100
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +535 -247
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +34 -30
- package/dist/ecosystem.cjs +499 -143
- package/dist/ecosystem.d.cts +13 -11
- package/dist/ecosystem.d.ts +13 -11
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3639 -1629
- package/dist/extras.d.cts +11 -11
- package/dist/extras.d.ts +11 -11
- package/dist/extras.js +58 -45
- package/dist/index.cjs +1023 -313
- package/dist/index.d.cts +128 -55
- package/dist/index.d.ts +128 -55
- 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 +90 -36
- package/dist/motion.d.cts +1 -1
- package/dist/motion.d.ts +1 -1
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +414 -81
- package/dist/patterns.d.cts +53 -20
- package/dist/patterns.d.ts +53 -20
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +364 -108
- package/dist/performance.d.cts +29 -17
- package/dist/performance.d.ts +29 -17
- package/dist/performance.js +13 -6
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +652 -271
- package/dist/plugins.d.cts +13 -6
- package/dist/plugins.d.ts +13 -6
- package/dist/plugins.js +116 -50
- 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 +648 -219
- package/dist/ssr.d.cts +27 -7
- package/dist/ssr.d.ts +27 -7
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.cts → 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 +576 -168
- package/dist/ui.d.cts +13 -16
- package/dist/ui.d.ts +13 -16
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +1001 -93
- 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-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- 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-BGN5ZMP4.js +0 -26
- 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-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-HGMJFBC7.js +0 -654
- 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-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-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NHUC2QWH.js +0 -282
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.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-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TNQWPPE6.js +0 -37
- 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-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- 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/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/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- 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
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
div,
|
|
3
3
|
span
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-R73P76YZ.js";
|
|
5
5
|
import {
|
|
6
6
|
sanitizeUrl
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UCS6AMJ7.js";
|
|
8
8
|
import {
|
|
9
9
|
effect
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HB24TBAF.js";
|
|
11
11
|
import {
|
|
12
12
|
batch,
|
|
13
13
|
signal
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-CC65Y57T.js";
|
|
15
15
|
|
|
16
16
|
// src/platform/head.ts
|
|
17
17
|
var HEAD_URL_ATTRS = /* @__PURE__ */ new Set(["href", "src"]);
|
|
@@ -148,24 +148,37 @@ function worker(workerFn2) {
|
|
|
148
148
|
const [error, setError] = signal(null);
|
|
149
149
|
const [loading, setLoading] = signal(false);
|
|
150
150
|
let worker2 = null;
|
|
151
|
+
let blobUrl = null;
|
|
152
|
+
const revokeBlobUrl = () => {
|
|
153
|
+
if (blobUrl) {
|
|
154
|
+
URL.revokeObjectURL(blobUrl);
|
|
155
|
+
blobUrl = null;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
151
158
|
try {
|
|
152
159
|
if (typeof Worker === "undefined") {
|
|
153
160
|
throw new Error("Web Workers are not supported in this environment");
|
|
154
161
|
}
|
|
155
162
|
const fnBody = workerFn2.toString();
|
|
156
163
|
const blob = new Blob([`self.onmessage = ${fnBody};`], { type: "application/javascript" });
|
|
157
|
-
|
|
158
|
-
worker2 = new Worker(
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
blobUrl = URL.createObjectURL(blob);
|
|
165
|
+
worker2 = new Worker(blobUrl);
|
|
166
|
+
worker2.addEventListener("message", (e) => {
|
|
167
|
+
revokeBlobUrl();
|
|
161
168
|
setResult(e.data);
|
|
162
169
|
setLoading(false);
|
|
163
|
-
};
|
|
164
|
-
worker2.
|
|
170
|
+
});
|
|
171
|
+
worker2.addEventListener("error", (e) => {
|
|
172
|
+
revokeBlobUrl();
|
|
165
173
|
setError(new Error(e.message || "Worker error"));
|
|
166
174
|
setLoading(false);
|
|
167
|
-
|
|
175
|
+
if (worker2) {
|
|
176
|
+
worker2.terminate();
|
|
177
|
+
worker2 = null;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
168
180
|
} catch (err) {
|
|
181
|
+
revokeBlobUrl();
|
|
169
182
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
170
183
|
}
|
|
171
184
|
function post(data) {
|
|
@@ -179,6 +192,7 @@ function worker(workerFn2) {
|
|
|
179
192
|
if (!worker2) return;
|
|
180
193
|
worker2.terminate();
|
|
181
194
|
worker2 = null;
|
|
195
|
+
revokeBlobUrl();
|
|
182
196
|
setLoading(false);
|
|
183
197
|
}
|
|
184
198
|
return { post, result, error, loading, terminate };
|
|
@@ -186,6 +200,14 @@ function worker(workerFn2) {
|
|
|
186
200
|
function workerFn(fn) {
|
|
187
201
|
const [loading, setLoading] = signal(false);
|
|
188
202
|
let worker2 = null;
|
|
203
|
+
let blobUrl = null;
|
|
204
|
+
const revokeBlobUrl = () => {
|
|
205
|
+
if (blobUrl) {
|
|
206
|
+
URL.revokeObjectURL(blobUrl);
|
|
207
|
+
blobUrl = null;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const queue = [];
|
|
189
211
|
try {
|
|
190
212
|
if (typeof Worker === "undefined") {
|
|
191
213
|
throw new Error("Web Workers are not supported in this environment");
|
|
@@ -201,10 +223,26 @@ function workerFn(fn) {
|
|
|
201
223
|
],
|
|
202
224
|
{ type: "application/javascript" }
|
|
203
225
|
);
|
|
204
|
-
|
|
205
|
-
worker2 = new Worker(
|
|
206
|
-
|
|
226
|
+
blobUrl = URL.createObjectURL(blob);
|
|
227
|
+
worker2 = new Worker(blobUrl);
|
|
228
|
+
worker2.addEventListener("message", (e) => {
|
|
229
|
+
revokeBlobUrl();
|
|
230
|
+
const head = queue.shift();
|
|
231
|
+
if (queue.length === 0) setLoading(false);
|
|
232
|
+
if (head) head.resolve(e.data);
|
|
233
|
+
});
|
|
234
|
+
worker2.addEventListener("error", (e) => {
|
|
235
|
+
revokeBlobUrl();
|
|
236
|
+
const err = new Error(e.message || "Worker error");
|
|
237
|
+
while (queue.length > 0) queue.shift().reject(err);
|
|
238
|
+
setLoading(false);
|
|
239
|
+
if (worker2) {
|
|
240
|
+
worker2.terminate();
|
|
241
|
+
worker2 = null;
|
|
242
|
+
}
|
|
243
|
+
});
|
|
207
244
|
} catch {
|
|
245
|
+
revokeBlobUrl();
|
|
208
246
|
}
|
|
209
247
|
function run(...args) {
|
|
210
248
|
return new Promise((resolve, reject) => {
|
|
@@ -213,14 +251,7 @@ function workerFn(fn) {
|
|
|
213
251
|
return;
|
|
214
252
|
}
|
|
215
253
|
setLoading(true);
|
|
216
|
-
|
|
217
|
-
setLoading(false);
|
|
218
|
-
resolve(e.data);
|
|
219
|
-
};
|
|
220
|
-
worker2.onerror = (e) => {
|
|
221
|
-
setLoading(false);
|
|
222
|
-
reject(new Error(e.message || "Worker error"));
|
|
223
|
-
};
|
|
254
|
+
queue.push({ resolve, reject });
|
|
224
255
|
worker2.postMessage(args);
|
|
225
256
|
});
|
|
226
257
|
}
|
|
@@ -228,6 +259,9 @@ function workerFn(fn) {
|
|
|
228
259
|
if (!worker2) return;
|
|
229
260
|
worker2.terminate();
|
|
230
261
|
worker2 = null;
|
|
262
|
+
const err = new Error("Worker terminated");
|
|
263
|
+
while (queue.length > 0) queue.shift().reject(err);
|
|
264
|
+
revokeBlobUrl();
|
|
231
265
|
setLoading(false);
|
|
232
266
|
}
|
|
233
267
|
return { run, loading, terminate };
|
|
@@ -235,20 +269,63 @@ function workerFn(fn) {
|
|
|
235
269
|
function createWorkerPool(workerFn2, poolSize) {
|
|
236
270
|
const size = poolSize || typeof navigator !== "undefined" && navigator.hardwareConcurrency || 4;
|
|
237
271
|
const workers = [];
|
|
272
|
+
const queues = [];
|
|
273
|
+
const inflight = [];
|
|
238
274
|
let currentIndex = 0;
|
|
239
275
|
let alive = true;
|
|
276
|
+
let blobUrl = null;
|
|
277
|
+
let firedOnce = false;
|
|
278
|
+
const revokeBlobUrl = () => {
|
|
279
|
+
if (blobUrl) {
|
|
280
|
+
URL.revokeObjectURL(blobUrl);
|
|
281
|
+
blobUrl = null;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
function dispatchNext(idx) {
|
|
285
|
+
if (!alive || inflight[idx] || queues[idx].length === 0) return;
|
|
286
|
+
const w = workers[idx];
|
|
287
|
+
const slot = queues[idx].shift();
|
|
288
|
+
const onMsg = (e) => {
|
|
289
|
+
if (!firedOnce) {
|
|
290
|
+
firedOnce = true;
|
|
291
|
+
revokeBlobUrl();
|
|
292
|
+
}
|
|
293
|
+
w.removeEventListener("message", onMsg);
|
|
294
|
+
w.removeEventListener("error", onErr);
|
|
295
|
+
inflight[idx] = null;
|
|
296
|
+
slot.resolve(e.data);
|
|
297
|
+
dispatchNext(idx);
|
|
298
|
+
};
|
|
299
|
+
const onErr = (e) => {
|
|
300
|
+
if (!firedOnce) {
|
|
301
|
+
firedOnce = true;
|
|
302
|
+
revokeBlobUrl();
|
|
303
|
+
}
|
|
304
|
+
w.removeEventListener("message", onMsg);
|
|
305
|
+
w.removeEventListener("error", onErr);
|
|
306
|
+
inflight[idx] = null;
|
|
307
|
+
slot.reject(new Error(e.message || "Worker error"));
|
|
308
|
+
dispatchNext(idx);
|
|
309
|
+
};
|
|
310
|
+
inflight[idx] = { ...slot, onMsg, onErr };
|
|
311
|
+
w.addEventListener("message", onMsg);
|
|
312
|
+
w.addEventListener("error", onErr);
|
|
313
|
+
w.postMessage(slot.data);
|
|
314
|
+
}
|
|
240
315
|
try {
|
|
241
316
|
if (typeof Worker === "undefined") {
|
|
242
317
|
throw new Error("Web Workers are not supported in this environment");
|
|
243
318
|
}
|
|
244
319
|
const fnBody = workerFn2.toString();
|
|
245
320
|
const blob = new Blob([`self.onmessage = ${fnBody};`], { type: "application/javascript" });
|
|
246
|
-
|
|
321
|
+
blobUrl = URL.createObjectURL(blob);
|
|
247
322
|
for (let i = 0; i < size; i++) {
|
|
248
|
-
workers.push(new Worker(
|
|
323
|
+
workers.push(new Worker(blobUrl));
|
|
324
|
+
queues.push([]);
|
|
325
|
+
inflight.push(null);
|
|
249
326
|
}
|
|
250
|
-
URL.revokeObjectURL(url);
|
|
251
327
|
} catch {
|
|
328
|
+
revokeBlobUrl();
|
|
252
329
|
}
|
|
253
330
|
function execute(data) {
|
|
254
331
|
return new Promise((resolve, reject) => {
|
|
@@ -256,23 +333,25 @@ function createWorkerPool(workerFn2, poolSize) {
|
|
|
256
333
|
reject(new Error("Worker pool is not available"));
|
|
257
334
|
return;
|
|
258
335
|
}
|
|
259
|
-
const
|
|
336
|
+
const idx = currentIndex % workers.length;
|
|
260
337
|
currentIndex++;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
};
|
|
264
|
-
worker2.onerror = (e) => {
|
|
265
|
-
reject(new Error(e.message || "Worker error"));
|
|
266
|
-
};
|
|
267
|
-
worker2.postMessage(data);
|
|
338
|
+
queues[idx].push({ data, resolve, reject });
|
|
339
|
+
dispatchNext(idx);
|
|
268
340
|
});
|
|
269
341
|
}
|
|
270
342
|
function terminate() {
|
|
271
343
|
alive = false;
|
|
272
|
-
for (const w of workers)
|
|
273
|
-
|
|
344
|
+
for (const w of workers) w.terminate();
|
|
345
|
+
const err = new Error("Worker pool terminated");
|
|
346
|
+
for (let i = 0; i < queues.length; i++) {
|
|
347
|
+
const inf = inflight[i];
|
|
348
|
+
if (inf) inf.reject(err);
|
|
349
|
+
for (const s of queues[i]) s.reject(err);
|
|
350
|
+
queues[i] = [];
|
|
351
|
+
inflight[i] = null;
|
|
274
352
|
}
|
|
275
353
|
workers.length = 0;
|
|
354
|
+
revokeBlobUrl();
|
|
276
355
|
}
|
|
277
356
|
return { execute, terminate };
|
|
278
357
|
}
|
|
@@ -308,7 +387,28 @@ function wasm(source, config = {}) {
|
|
|
308
387
|
};
|
|
309
388
|
}
|
|
310
389
|
async function loadWasmModule(source, imports, cacheKey) {
|
|
311
|
-
const
|
|
390
|
+
const isOptionsBag = !!(imports && ("allowedOrigins" in imports || "unsafelyAllowAnyOrigin" in imports));
|
|
391
|
+
const opts = isOptionsBag ? imports : { imports, cacheKey };
|
|
392
|
+
const wasmImports = opts.imports;
|
|
393
|
+
const key = opts.cacheKey || (typeof source === "string" ? source : void 0);
|
|
394
|
+
if (typeof source === "string") {
|
|
395
|
+
const allowed = opts.allowedOrigins ?? [];
|
|
396
|
+
if (allowed.length > 0) {
|
|
397
|
+
let parsed;
|
|
398
|
+
try {
|
|
399
|
+
parsed = new URL(source, typeof location !== "undefined" ? location.href : void 0);
|
|
400
|
+
} catch {
|
|
401
|
+
throw new Error(`loadWasmModule: invalid URL "${source}"`);
|
|
402
|
+
}
|
|
403
|
+
if (!allowed.includes(parsed.origin)) {
|
|
404
|
+
throw new Error(`loadWasmModule: origin "${parsed.origin}" is not in the allowlist`);
|
|
405
|
+
}
|
|
406
|
+
} else if (!opts.unsafelyAllowAnyOrigin) {
|
|
407
|
+
throw new Error(
|
|
408
|
+
`loadWasmModule: refused to fetch "${source}" with no allowedOrigins. Pass { allowedOrigins: [...] } to restrict the origin, or { unsafelyAllowAnyOrigin: true } to opt in (CWE-829).`
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
312
412
|
if (key) {
|
|
313
413
|
const cachedInstance = instanceCache.get(key);
|
|
314
414
|
if (cachedInstance) {
|
|
@@ -324,7 +424,7 @@ async function loadWasmModule(source, imports, cacheKey) {
|
|
|
324
424
|
if (typeof source === "string") {
|
|
325
425
|
if (typeof WebAssembly.instantiateStreaming === "function") {
|
|
326
426
|
const response2 = fetch(source);
|
|
327
|
-
const result = await WebAssembly.instantiateStreaming(response2,
|
|
427
|
+
const result = await WebAssembly.instantiateStreaming(response2, wasmImports || {});
|
|
328
428
|
if (key) {
|
|
329
429
|
moduleCache.set(key, result.module);
|
|
330
430
|
instanceCache.set(key, result.instance);
|
|
@@ -341,12 +441,28 @@ async function loadWasmModule(source, imports, cacheKey) {
|
|
|
341
441
|
module = await WebAssembly.compile(bytes);
|
|
342
442
|
if (key) moduleCache.set(key, module);
|
|
343
443
|
}
|
|
344
|
-
const instance = await WebAssembly.instantiate(module,
|
|
444
|
+
const instance = await WebAssembly.instantiate(module, wasmImports || {});
|
|
345
445
|
if (key) instanceCache.set(key, instance);
|
|
346
446
|
return instance;
|
|
347
447
|
}
|
|
348
|
-
async function preloadWasm(url) {
|
|
448
|
+
async function preloadWasm(url, options = {}) {
|
|
349
449
|
if (moduleCache.has(url)) return;
|
|
450
|
+
const allowed = options.allowedOrigins ?? [];
|
|
451
|
+
if (allowed.length > 0) {
|
|
452
|
+
let parsed;
|
|
453
|
+
try {
|
|
454
|
+
parsed = new URL(url, typeof location !== "undefined" ? location.href : void 0);
|
|
455
|
+
} catch {
|
|
456
|
+
throw new Error(`preloadWasm: invalid URL "${url}"`);
|
|
457
|
+
}
|
|
458
|
+
if (!allowed.includes(parsed.origin)) {
|
|
459
|
+
throw new Error(`preloadWasm: origin "${parsed.origin}" is not in the allowlist`);
|
|
460
|
+
}
|
|
461
|
+
} else if (!options.unsafelyAllowAnyOrigin) {
|
|
462
|
+
throw new Error(
|
|
463
|
+
`preloadWasm: refused to fetch "${url}" with no allowedOrigins. Pass { allowedOrigins: [...] } or { unsafelyAllowAnyOrigin: true } (CWE-829).`
|
|
464
|
+
);
|
|
465
|
+
}
|
|
350
466
|
let module;
|
|
351
467
|
if (typeof WebAssembly.compileStreaming === "function") {
|
|
352
468
|
module = await WebAssembly.compileStreaming(fetch(url));
|
|
@@ -415,31 +531,38 @@ function createMicroApp(config) {
|
|
|
415
531
|
}
|
|
416
532
|
let mounted = false;
|
|
417
533
|
function mount(component) {
|
|
418
|
-
|
|
419
|
-
root.innerHTML = "";
|
|
420
|
-
} else {
|
|
421
|
-
while (root.firstChild) {
|
|
422
|
-
root.removeChild(root.firstChild);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
534
|
+
root.replaceChildren();
|
|
425
535
|
const el = component();
|
|
426
536
|
root.appendChild(el);
|
|
427
537
|
mounted = true;
|
|
428
538
|
}
|
|
429
539
|
function unmount() {
|
|
430
540
|
if (!mounted) return;
|
|
431
|
-
|
|
432
|
-
root.innerHTML = "";
|
|
433
|
-
} else {
|
|
434
|
-
while (root.firstChild) {
|
|
435
|
-
root.removeChild(root.firstChild);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
541
|
+
root.replaceChildren();
|
|
438
542
|
mounted = false;
|
|
439
543
|
}
|
|
440
544
|
return { mount, unmount, element: host };
|
|
441
545
|
}
|
|
442
|
-
function loadRemoteModule(url) {
|
|
546
|
+
function loadRemoteModule(url, optionsOrAllowedOrigins = []) {
|
|
547
|
+
const opts = Array.isArray(optionsOrAllowedOrigins) ? { allowedOrigins: optionsOrAllowedOrigins } : optionsOrAllowedOrigins;
|
|
548
|
+
const allowedOrigins = opts.allowedOrigins ?? [];
|
|
549
|
+
if (allowedOrigins.length > 0) {
|
|
550
|
+
let parsed;
|
|
551
|
+
try {
|
|
552
|
+
parsed = new URL(url, typeof location !== "undefined" ? location.href : void 0);
|
|
553
|
+
} catch {
|
|
554
|
+
return Promise.reject(new Error(`loadRemoteModule: invalid URL "${url}"`));
|
|
555
|
+
}
|
|
556
|
+
if (!allowedOrigins.includes(parsed.origin)) {
|
|
557
|
+
return Promise.reject(new Error(`loadRemoteModule: origin "${parsed.origin}" is not in the allowlist`));
|
|
558
|
+
}
|
|
559
|
+
} else if (!opts.unsafelyAllowAnyOrigin) {
|
|
560
|
+
return Promise.reject(
|
|
561
|
+
new Error(
|
|
562
|
+
`loadRemoteModule: refused to import "${url}" with no allowedOrigins. Pass { allowedOrigins: [...] } to restrict the origin, or { unsafelyAllowAnyOrigin: true } to opt in to unrestricted imports (CWE-829).`
|
|
563
|
+
)
|
|
564
|
+
);
|
|
565
|
+
}
|
|
443
566
|
const cached = moduleCache2.get(url);
|
|
444
567
|
if (cached) return cached;
|
|
445
568
|
const promise = import(
|
|
@@ -529,21 +652,49 @@ function serviceWorker(scriptUrl, options) {
|
|
|
529
652
|
const [isReady, setIsReady] = signal(false);
|
|
530
653
|
const [isUpdateAvailable, setIsUpdateAvailable] = signal(false);
|
|
531
654
|
const [error, setError] = signal(null);
|
|
655
|
+
let disposed = false;
|
|
656
|
+
let updateFoundHandler = null;
|
|
657
|
+
let stateChangeHandler = null;
|
|
658
|
+
let trackedWorker = null;
|
|
659
|
+
let trackedReg = null;
|
|
660
|
+
function detachListeners() {
|
|
661
|
+
if (trackedReg && updateFoundHandler) {
|
|
662
|
+
trackedReg.removeEventListener("updatefound", updateFoundHandler);
|
|
663
|
+
}
|
|
664
|
+
if (trackedWorker && stateChangeHandler) {
|
|
665
|
+
trackedWorker.removeEventListener("statechange", stateChangeHandler);
|
|
666
|
+
}
|
|
667
|
+
updateFoundHandler = null;
|
|
668
|
+
stateChangeHandler = null;
|
|
669
|
+
trackedWorker = null;
|
|
670
|
+
trackedReg = null;
|
|
671
|
+
}
|
|
532
672
|
if ("serviceWorker" in navigator) {
|
|
533
673
|
navigator.serviceWorker.register(scriptUrl, options).then((reg) => {
|
|
674
|
+
if (disposed) return;
|
|
534
675
|
setRegistration(reg);
|
|
535
676
|
setIsReady(true);
|
|
536
|
-
|
|
677
|
+
trackedReg = reg;
|
|
678
|
+
updateFoundHandler = () => {
|
|
679
|
+
if (disposed) return;
|
|
537
680
|
const newWorker = reg.installing;
|
|
538
681
|
if (newWorker) {
|
|
539
|
-
|
|
682
|
+
if (trackedWorker && stateChangeHandler) {
|
|
683
|
+
trackedWorker.removeEventListener("statechange", stateChangeHandler);
|
|
684
|
+
}
|
|
685
|
+
trackedWorker = newWorker;
|
|
686
|
+
stateChangeHandler = () => {
|
|
687
|
+
if (disposed) return;
|
|
540
688
|
if (newWorker.state === "installed" && navigator.serviceWorker.controller) {
|
|
541
689
|
setIsUpdateAvailable(true);
|
|
542
690
|
}
|
|
543
|
-
}
|
|
691
|
+
};
|
|
692
|
+
newWorker.addEventListener("statechange", stateChangeHandler);
|
|
544
693
|
}
|
|
545
|
-
}
|
|
694
|
+
};
|
|
695
|
+
reg.addEventListener("updatefound", updateFoundHandler);
|
|
546
696
|
}).catch((err) => {
|
|
697
|
+
if (disposed) return;
|
|
547
698
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
548
699
|
});
|
|
549
700
|
}
|
|
@@ -554,6 +705,8 @@ function serviceWorker(scriptUrl, options) {
|
|
|
554
705
|
}
|
|
555
706
|
}
|
|
556
707
|
async function unregister() {
|
|
708
|
+
disposed = true;
|
|
709
|
+
detachListeners();
|
|
557
710
|
const reg = registration();
|
|
558
711
|
if (reg) {
|
|
559
712
|
const result = await reg.unregister();
|
|
@@ -592,24 +745,42 @@ function createISR(options) {
|
|
|
592
745
|
const { revalidateAfter, fetcher, initialData } = options;
|
|
593
746
|
const [data, setData] = signal(initialData);
|
|
594
747
|
const [timestamp, setTimestamp] = signal(initialData !== void 0 ? Date.now() : 0);
|
|
748
|
+
const controller = new AbortController();
|
|
749
|
+
let inFlight = false;
|
|
750
|
+
let disposed = false;
|
|
595
751
|
const isStale = () => {
|
|
596
752
|
const ts = timestamp();
|
|
597
753
|
if (ts === 0) return true;
|
|
598
754
|
return Date.now() - ts >= revalidateAfter;
|
|
599
755
|
};
|
|
600
756
|
const revalidate = async () => {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
757
|
+
if (disposed || inFlight) return;
|
|
758
|
+
if (controller.signal.aborted) return;
|
|
759
|
+
inFlight = true;
|
|
760
|
+
try {
|
|
761
|
+
const result = await fetcher({ signal: controller.signal });
|
|
762
|
+
if (disposed || controller.signal.aborted) return;
|
|
763
|
+
setData(result);
|
|
764
|
+
setTimestamp(Date.now());
|
|
765
|
+
} finally {
|
|
766
|
+
inFlight = false;
|
|
767
|
+
}
|
|
604
768
|
};
|
|
605
769
|
if (initialData === void 0) {
|
|
606
|
-
revalidate()
|
|
770
|
+
revalidate().catch((err) => {
|
|
771
|
+
if (typeof console !== "undefined") console.warn("[SibuJS ISR] initial fetch failed", err);
|
|
772
|
+
});
|
|
607
773
|
}
|
|
608
774
|
const intervalId = setInterval(() => {
|
|
609
|
-
revalidate()
|
|
775
|
+
revalidate().catch((err) => {
|
|
776
|
+
if (typeof console !== "undefined") console.warn("[SibuJS ISR] revalidate failed", err);
|
|
777
|
+
});
|
|
610
778
|
}, revalidateAfter);
|
|
611
779
|
const dispose = () => {
|
|
780
|
+
if (disposed) return;
|
|
781
|
+
disposed = true;
|
|
612
782
|
clearInterval(intervalId);
|
|
783
|
+
controller.abort();
|
|
613
784
|
};
|
|
614
785
|
return { data, isStale, revalidate, dispose };
|
|
615
786
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// src/utils/sanitize.ts
|
|
2
|
+
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
3
|
+
function sanitizeUrl(url) {
|
|
4
|
+
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
5
|
+
if (!trimmed) return "";
|
|
6
|
+
const lower = trimmed.toLowerCase();
|
|
7
|
+
let schemeEnd = -1;
|
|
8
|
+
for (let i = 0; i < lower.length; i++) {
|
|
9
|
+
const ch = lower.charCodeAt(i);
|
|
10
|
+
if (ch === 58) {
|
|
11
|
+
schemeEnd = i;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
15
|
+
}
|
|
16
|
+
if (schemeEnd === -1) return trimmed;
|
|
17
|
+
const scheme = lower.slice(0, schemeEnd + 1);
|
|
18
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
|
|
19
|
+
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
20
|
+
return trimmed;
|
|
21
|
+
}
|
|
22
|
+
function sanitizeSrcset(value) {
|
|
23
|
+
const parts = value.split(",");
|
|
24
|
+
const out = [];
|
|
25
|
+
for (let i = 0; i < parts.length; i++) {
|
|
26
|
+
const part = parts[i].trim();
|
|
27
|
+
if (!part) continue;
|
|
28
|
+
const m = part.match(/^(\S+)(\s+.+)?$/);
|
|
29
|
+
if (!m) continue;
|
|
30
|
+
const safe = sanitizeUrl(m[1]);
|
|
31
|
+
if (!safe) continue;
|
|
32
|
+
out.push(m[2] ? `${safe}${m[2]}` : safe);
|
|
33
|
+
}
|
|
34
|
+
return out.join(", ");
|
|
35
|
+
}
|
|
36
|
+
function sanitizeCSSValue(value) {
|
|
37
|
+
const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
|
|
38
|
+
const code = Number.parseInt(hex, 16);
|
|
39
|
+
if (!Number.isFinite(code) || code < 0 || code > 1114111) return "";
|
|
40
|
+
try {
|
|
41
|
+
return String.fromCodePoint(code);
|
|
42
|
+
} catch {
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const lower = decoded.toLowerCase().replace(/\s+/g, "");
|
|
47
|
+
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")) {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
function stripHtml(html) {
|
|
53
|
+
return String(html).replace(/<[^>]*>/g, "");
|
|
54
|
+
}
|
|
55
|
+
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
56
|
+
"href",
|
|
57
|
+
"xlink:href",
|
|
58
|
+
"src",
|
|
59
|
+
"action",
|
|
60
|
+
"formaction",
|
|
61
|
+
"formtarget",
|
|
62
|
+
"cite",
|
|
63
|
+
"poster",
|
|
64
|
+
"background",
|
|
65
|
+
"srcset",
|
|
66
|
+
"ping",
|
|
67
|
+
"data"
|
|
68
|
+
]);
|
|
69
|
+
function isUrlAttribute(attr) {
|
|
70
|
+
return URL_ATTRIBUTES.has(attr);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
sanitizeUrl,
|
|
75
|
+
sanitizeSrcset,
|
|
76
|
+
sanitizeCSSValue,
|
|
77
|
+
stripHtml,
|
|
78
|
+
isUrlAttribute
|
|
79
|
+
};
|