sibujs 4.6.0 → 4.8.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 +1 -1
- package/dist/browser.cjs +62 -8
- package/dist/browser.d.cts +23 -0
- package/dist/browser.d.ts +23 -0
- package/dist/browser.js +6 -5
- package/dist/build.cjs +2388 -1004
- package/dist/build.d.cts +147 -44
- package/dist/build.d.ts +147 -44
- package/dist/build.js +1410 -564
- package/dist/cdn.dev.global.js +14 -12
- package/dist/cdn.full.dev.global.js +15 -13
- package/dist/cdn.full.global.js +14 -12
- package/dist/cdn.global.js +12 -10
- package/dist/chunk-3ACAAQIN.js +224 -0
- package/dist/{chunk-7NCARGJW.js → chunk-44MTL7ED.js} +6 -6
- package/dist/{chunk-BAAG6ZTI.js → chunk-4WMSTZ7J.js} +8 -5
- package/dist/{chunk-H3SRKIYX.js → chunk-62BDYGAG.js} +8 -0
- package/dist/{chunk-DKGBBKOF.js → chunk-C5PEWEGH.js} +20 -5
- package/dist/{chunk-3ISI6ACU.js → chunk-C7AA2CZX.js} +1 -1
- package/dist/{chunk-UZQ6ALFS.js → chunk-CZPRSWSS.js} +1 -1
- package/dist/{chunk-D33YTSX5.js → chunk-DSID757X.js} +5 -4
- package/dist/{chunk-OXUY2A6L.js → chunk-EGUQLBHE.js} +22 -8
- package/dist/{chunk-2INLLLMZ.js → chunk-EXXSN3BW.js} +202 -26
- package/dist/{chunk-HURREPU2.js → chunk-FC6KCJSA.js} +87 -150
- package/dist/{chunk-HYXDKS4N.js → chunk-GSGNX35Q.js} +5 -5
- package/dist/{chunk-7GQCWFOE.js → chunk-J3YQ457H.js} +171 -85
- package/dist/{chunk-ORMZXBKQ.js → chunk-JUTFX2RM.js} +18 -10
- package/dist/{chunk-QE4TTDU3.js → chunk-KJ3UKABJ.js} +12 -11
- package/dist/{chunk-XRRZKZYX.js → chunk-LI4W3U6C.js} +1 -1
- package/dist/{chunk-47M47FOM.js → chunk-O6TRVMJI.js} +58 -6
- package/dist/{chunk-JSXPZCET.js → chunk-Q5J2LVKH.js} +1 -1
- package/dist/{chunk-5MT6SJ3P.js → chunk-QGMSESDD.js} +10 -5
- package/dist/{chunk-AIF3Z2T7.js → chunk-RGLPEBDE.js} +13 -10
- package/dist/{chunk-5Q4R7HCL.js → chunk-TQQUN4WR.js} +11 -2
- package/dist/{chunk-PK6FK2G2.js → chunk-UCNP3HVM.js} +183 -30
- package/dist/{chunk-XC4MEKGA.js → chunk-V3LHZSU5.js} +8 -2
- package/dist/{chunk-VVWPJ543.js → chunk-VWT3VXPL.js} +55 -20
- package/dist/{chunk-SXXVZMKZ.js → chunk-ZVLHNEEL.js} +17 -35
- package/dist/{contracts-DRIuclVT.d.cts → contracts-CLqzJnOV.d.ts} +28 -17
- package/dist/{contracts-DRIuclVT.d.ts → contracts-CTOJXu-x.d.cts} +28 -17
- package/dist/{customElement-MmInOW1U.d.ts → customElement-pYDKUzWl.d.cts} +11 -3
- package/dist/{customElement-MmInOW1U.d.cts → customElement-pYDKUzWl.d.ts} +11 -3
- package/dist/data.cjs +205 -39
- package/dist/data.d.cts +119 -3
- package/dist/data.d.ts +119 -3
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +18 -5
- package/dist/devtools.js +5 -5
- package/dist/ecosystem.cjs +462 -58
- package/dist/ecosystem.d.cts +2 -1
- package/dist/ecosystem.d.ts +2 -1
- package/dist/ecosystem.js +9 -8
- package/dist/extras.cjs +852 -296
- package/dist/extras.d.cts +5 -4
- package/dist/extras.d.ts +5 -4
- package/dist/extras.js +24 -23
- package/dist/index.cjs +721 -176
- package/dist/index.d.cts +220 -169
- package/dist/index.d.ts +220 -169
- package/dist/index.js +16 -12
- package/dist/motion.cjs +12 -4
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +37 -21
- package/dist/patterns.d.cts +2 -1
- package/dist/patterns.d.ts +2 -1
- package/dist/patterns.js +6 -6
- package/dist/performance.cjs +48 -6
- package/dist/performance.d.cts +12 -2
- package/dist/performance.d.ts +12 -2
- package/dist/performance.js +8 -6
- package/dist/plugins.cjs +672 -261
- package/dist/plugins.d.cts +131 -13
- package/dist/plugins.d.ts +131 -13
- package/dist/plugins.js +83 -47
- package/dist/{ssr-XOTUASDO.js → ssr-5OWAH3U2.js} +4 -2
- package/dist/{ssr-Bli9XRW5.d.cts → ssr-C8hgIAw7.d.cts} +6 -0
- package/dist/{ssr-Bli9XRW5.d.ts → ssr-C8hgIAw7.d.ts} +6 -0
- package/dist/ssr.cjs +509 -142
- package/dist/ssr.d.cts +55 -5
- package/dist/ssr.d.ts +55 -5
- package/dist/ssr.js +11 -9
- package/dist/{tagFactory-DFstCLQV.d.cts → tagFactory-8qL9LCIx.d.cts} +58 -19
- package/dist/{tagFactory-DkaNVUNV.d.ts → tagFactory-BL2fymez.d.ts} +58 -19
- package/dist/testing.cjs +17 -4
- package/dist/testing.js +4 -4
- package/dist/types-CJFViL6Q.d.cts +26 -0
- package/dist/types-CJFViL6Q.d.ts +26 -0
- package/dist/ui.cjs +635 -254
- package/dist/ui.d.cts +3 -2
- package/dist/ui.d.ts +3 -2
- package/dist/ui.js +9 -8
- package/dist/widgets.cjs +22 -14
- package/dist/widgets.js +7 -7
- package/package.json +8 -5
package/dist/ssr.cjs
CHANGED
|
@@ -313,8 +313,10 @@ function isSSR() {
|
|
|
313
313
|
function stripControlChars(value) {
|
|
314
314
|
return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
|
|
315
315
|
}
|
|
316
|
+
var ASCII_UPPER = /[A-Z]/;
|
|
317
|
+
var ASCII_UPPER_G = /[A-Z]/g;
|
|
316
318
|
function canonicalAttrName(name) {
|
|
317
|
-
return name.replace(
|
|
319
|
+
return ASCII_UPPER.test(name) ? name.replace(ASCII_UPPER_G, (ch) => String.fromCharCode(ch.charCodeAt(0) + 32)) : name;
|
|
318
320
|
}
|
|
319
321
|
function isEventHandlerAttr(name) {
|
|
320
322
|
if (name.length < 3) return false;
|
|
@@ -327,6 +329,9 @@ function sanitizeUrl(url) {
|
|
|
327
329
|
const probe = stripControlChars(url).trim();
|
|
328
330
|
if (!probe) return "";
|
|
329
331
|
const output2 = url.replace(OUTER_TRIM, "");
|
|
332
|
+
if (probe.length >= 2 && (probe[0] === "\\" || probe[0] === "/") && (probe[1] === "\\" || probe[1] === "/") && (probe[0] === "\\" || probe[1] === "\\")) {
|
|
333
|
+
return "";
|
|
334
|
+
}
|
|
330
335
|
const lower = probe.toLowerCase();
|
|
331
336
|
let schemeEnd = -1;
|
|
332
337
|
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
@@ -343,19 +348,58 @@ function sanitizeUrl(url) {
|
|
|
343
348
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
344
349
|
return output2;
|
|
345
350
|
}
|
|
346
|
-
var SRCSET_DESCRIPTOR = /^\
|
|
351
|
+
var SRCSET_DESCRIPTOR = /^\d+(\.\d+)?[wx]$/;
|
|
352
|
+
function isSrcsetWhitespace(ch) {
|
|
353
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
354
|
+
}
|
|
347
355
|
function sanitizeSrcset(value) {
|
|
348
|
-
const
|
|
356
|
+
const input2 = String(value);
|
|
349
357
|
const out = [];
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
|
|
358
|
+
let i2 = 0;
|
|
359
|
+
const n = input2.length;
|
|
360
|
+
while (i2 < n) {
|
|
361
|
+
while (i2 < n && (isSrcsetWhitespace(input2[i2]) || input2[i2] === ",")) i2++;
|
|
362
|
+
if (i2 >= n) break;
|
|
363
|
+
const urlStart = i2;
|
|
364
|
+
while (i2 < n && !isSrcsetWhitespace(input2[i2])) i2++;
|
|
365
|
+
let url = input2.slice(urlStart, i2);
|
|
366
|
+
const descriptors = [];
|
|
367
|
+
if (url.endsWith(",")) {
|
|
368
|
+
url = url.replace(/,+$/, "");
|
|
369
|
+
} else {
|
|
370
|
+
let current = "";
|
|
371
|
+
let inParens = false;
|
|
372
|
+
while (i2 < n) {
|
|
373
|
+
const ch = input2[i2];
|
|
374
|
+
if (inParens) {
|
|
375
|
+
current += ch;
|
|
376
|
+
if (ch === ")") inParens = false;
|
|
377
|
+
i2++;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (isSrcsetWhitespace(ch)) {
|
|
381
|
+
if (current) descriptors.push(current);
|
|
382
|
+
current = "";
|
|
383
|
+
i2++;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
if (ch === ",") {
|
|
387
|
+
i2++;
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
if (ch === "(") inParens = true;
|
|
391
|
+
current += ch;
|
|
392
|
+
i2++;
|
|
393
|
+
}
|
|
394
|
+
if (current) descriptors.push(current);
|
|
395
|
+
}
|
|
396
|
+
if (url === "") continue;
|
|
397
|
+
if (descriptors.length > 1) continue;
|
|
398
|
+
if (descriptors.length === 1 && !SRCSET_DESCRIPTOR.test(descriptors[0])) continue;
|
|
399
|
+
const safe = sanitizeUrl(url);
|
|
357
400
|
if (!safe) continue;
|
|
358
|
-
|
|
401
|
+
if (safe.startsWith(",") || safe.endsWith(",")) continue;
|
|
402
|
+
out.push(descriptors.length === 1 ? `${safe} ${descriptors[0]}` : safe);
|
|
359
403
|
}
|
|
360
404
|
return out.join(", ");
|
|
361
405
|
}
|
|
@@ -414,8 +458,16 @@ var BLOCKED_CSS_NEEDLES = [
|
|
|
414
458
|
"behavior:",
|
|
415
459
|
"@import",
|
|
416
460
|
"image-set(",
|
|
417
|
-
"filter:progid"
|
|
461
|
+
"filter:progid",
|
|
462
|
+
// CSS Images 4 `image("…")` and CSS Values 5 `src("…")` take a URL as a
|
|
463
|
+
// plain STRING, so they fetch without ever spelling `url(`. Support is thin
|
|
464
|
+
// today, which is exactly when a blocklist should get ahead of it.
|
|
465
|
+
"image(",
|
|
466
|
+
"src("
|
|
418
467
|
];
|
|
468
|
+
var CSS_REASON_MOZ_BINDING = 4;
|
|
469
|
+
var CSS_REASON_BEHAVIOR = 5;
|
|
470
|
+
var CSS_REASON_PROGID = 8;
|
|
419
471
|
function describeElement(el) {
|
|
420
472
|
if (!el) return "an element";
|
|
421
473
|
let out = el.tagName.toLowerCase();
|
|
@@ -439,7 +491,9 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
439
491
|
"behavior: loads and runs a remote HTC script",
|
|
440
492
|
"@import pulls in a remote stylesheet",
|
|
441
493
|
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
442
|
-
"filter:progid activates legacy scriptable filters"
|
|
494
|
+
"filter:progid activates legacy scriptable filters",
|
|
495
|
+
"image() fetches its string argument as a URL, the same exfiltration channel as url()",
|
|
496
|
+
"src() fetches its string argument as a URL, the same exfiltration channel as url()"
|
|
443
497
|
];
|
|
444
498
|
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
445
499
|
const where = describeElement(ctx?.element);
|
|
@@ -454,27 +508,110 @@ function warnDroppedDeclaration(value, reason, ctx) {
|
|
|
454
508
|
return `style declaration "${declaration}" was dropped by the style sanitizer on ${where} \u2014 ${reasons[reason]}. The element renders without it, which usually looks like a missing image rather than an error. Sanctioned alternatives: for a content image use an <img> element (or a <picture>); for decoration, put the rule in a stylesheet and set a class instead \u2014 stylesheet CSS is not sanitized, only inline style attributes are. If this declaration is not yours, it came from untrusted data and the drop just prevented an exfiltration.`;
|
|
455
509
|
});
|
|
456
510
|
}
|
|
511
|
+
function normalizeCssForScan(value) {
|
|
512
|
+
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
513
|
+
return normalized.toLowerCase().replace(/\s+/g, "");
|
|
514
|
+
}
|
|
457
515
|
function blockedCssReason(value) {
|
|
458
516
|
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
459
|
-
const
|
|
460
|
-
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
517
|
+
const lower = normalizeCssForScan(value);
|
|
461
518
|
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
462
519
|
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
463
520
|
}
|
|
464
521
|
return -1;
|
|
465
522
|
}
|
|
466
|
-
function
|
|
467
|
-
const reason =
|
|
523
|
+
function sanitizeCSSDeclaration(property, value, context) {
|
|
524
|
+
const reason = blockedDeclarationReason(property, value);
|
|
468
525
|
if (reason === -1) return value;
|
|
469
|
-
warnDroppedDeclaration(value, reason, context);
|
|
526
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
470
527
|
return "";
|
|
471
528
|
}
|
|
529
|
+
function blockedDeclarationReason(property, value) {
|
|
530
|
+
const reason = blockedCssReason(value);
|
|
531
|
+
if (reason !== -1) return reason;
|
|
532
|
+
const name = canonicalAttrName(property);
|
|
533
|
+
if (name === "behavior") return CSS_REASON_BEHAVIOR;
|
|
534
|
+
if (name === "-moz-binding") return CSS_REASON_MOZ_BINDING;
|
|
535
|
+
if ((name === "filter" || name === "-ms-filter") && normalizeCssForScan(value).includes("progid:")) {
|
|
536
|
+
return CSS_REASON_PROGID;
|
|
537
|
+
}
|
|
538
|
+
return -1;
|
|
539
|
+
}
|
|
540
|
+
function parseStyleDeclarations(css) {
|
|
541
|
+
const chunks = [];
|
|
542
|
+
let buf = "";
|
|
543
|
+
let depth = 0;
|
|
544
|
+
let quote2 = "";
|
|
545
|
+
for (let i2 = 0; i2 < css.length; i2++) {
|
|
546
|
+
const ch = css[i2];
|
|
547
|
+
if (quote2) {
|
|
548
|
+
buf += ch;
|
|
549
|
+
if (ch === "\\" && i2 + 1 < css.length) buf += css[++i2];
|
|
550
|
+
else if (ch === quote2) quote2 = "";
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
if (ch === "\\") {
|
|
554
|
+
buf += ch;
|
|
555
|
+
if (i2 + 1 < css.length) buf += css[++i2];
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
if (ch === "/" && css[i2 + 1] === "*") {
|
|
559
|
+
const end = css.indexOf("*/", i2 + 2);
|
|
560
|
+
if (end === -1) return null;
|
|
561
|
+
i2 = end + 1;
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
if (ch === '"' || ch === "'") quote2 = ch;
|
|
565
|
+
else if (ch === "(" || ch === "[") depth++;
|
|
566
|
+
else if (ch === ")" || ch === "]") {
|
|
567
|
+
if (--depth < 0) return null;
|
|
568
|
+
} else if (ch === "{" || ch === "}") return null;
|
|
569
|
+
else if (ch === ";" && depth === 0) {
|
|
570
|
+
chunks.push(buf);
|
|
571
|
+
buf = "";
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
buf += ch;
|
|
575
|
+
}
|
|
576
|
+
if (quote2 || depth !== 0) return null;
|
|
577
|
+
chunks.push(buf);
|
|
578
|
+
const out = [];
|
|
579
|
+
for (const chunk of chunks) {
|
|
580
|
+
const colon = chunk.indexOf(":");
|
|
581
|
+
if (colon === -1) continue;
|
|
582
|
+
const rawName = chunk.slice(0, colon).trim();
|
|
583
|
+
if (!/^(--[\w-]+|-?[a-zA-Z_][\w-]*)$/.test(rawName)) continue;
|
|
584
|
+
let value = chunk.slice(colon + 1).trim();
|
|
585
|
+
const bang = /!\s*important\s*$/i.exec(value);
|
|
586
|
+
if (bang) value = value.slice(0, bang.index).trim();
|
|
587
|
+
if (value === "") continue;
|
|
588
|
+
const property = rawName.startsWith("--") ? rawName : canonicalAttrName(rawName);
|
|
589
|
+
out.push([property, value, bang !== null]);
|
|
590
|
+
}
|
|
591
|
+
return out;
|
|
592
|
+
}
|
|
593
|
+
function sanitizeStyleDeclarationList(cssText, context) {
|
|
594
|
+
const input2 = String(cssText);
|
|
595
|
+
const declarations = parseStyleDeclarations(input2);
|
|
596
|
+
if (declarations === null) {
|
|
597
|
+
if (blockedCssReason(input2) !== -1) warnDroppedDeclaration(input2, blockedCssReason(input2), context);
|
|
598
|
+
return "";
|
|
599
|
+
}
|
|
600
|
+
const kept = [];
|
|
601
|
+
for (const [property, value, important] of declarations) {
|
|
602
|
+
const reason = blockedDeclarationReason(property, value);
|
|
603
|
+
if (reason !== -1) {
|
|
604
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
kept.push(`${property}: ${value}${important ? " !important" : ""}`);
|
|
608
|
+
}
|
|
609
|
+
return kept.join("; ");
|
|
610
|
+
}
|
|
472
611
|
function sanitizeStyleAttribute(cssText, context) {
|
|
473
612
|
const input2 = String(cssText);
|
|
474
613
|
if (input2.trim() === "") return "";
|
|
475
|
-
if (typeof document === "undefined")
|
|
476
|
-
return sanitizeCSSValue(input2, context) === "" ? "" : input2;
|
|
477
|
-
}
|
|
614
|
+
if (typeof document === "undefined") return sanitizeStyleDeclarationList(input2, context);
|
|
478
615
|
const probe = document.createElement("div");
|
|
479
616
|
try {
|
|
480
617
|
probe.style.cssText = input2;
|
|
@@ -485,8 +622,7 @@ function sanitizeStyleAttribute(cssText, context) {
|
|
|
485
622
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
486
623
|
const property = probe.style[i2];
|
|
487
624
|
const value = probe.style.getPropertyValue(property);
|
|
488
|
-
|
|
489
|
-
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
625
|
+
const reason = blockedDeclarationReason(property, value);
|
|
490
626
|
if (reason !== -1) {
|
|
491
627
|
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
492
628
|
continue;
|
|
@@ -518,6 +654,9 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
518
654
|
function isHtmlContentAttribute(name) {
|
|
519
655
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
520
656
|
}
|
|
657
|
+
function isUrlAttribute(attr) {
|
|
658
|
+
return URL_ATTRIBUTES.has(attr.toLowerCase());
|
|
659
|
+
}
|
|
521
660
|
function isPolicyAttribute(name) {
|
|
522
661
|
const lower = name.toLowerCase();
|
|
523
662
|
return lower === "style" || URL_ATTRIBUTES.has(lower);
|
|
@@ -529,6 +668,11 @@ function sanitizeAttributeString(attr, value, context) {
|
|
|
529
668
|
if (lower === "style") return sanitizeStyleAttribute(value, context);
|
|
530
669
|
return value;
|
|
531
670
|
}
|
|
671
|
+
function resolveAttributeValue(attr, value, context) {
|
|
672
|
+
if (!isPolicyAttribute(attr)) return value;
|
|
673
|
+
const safe = sanitizeAttributeString(attr, value, context);
|
|
674
|
+
return safe === "" ? null : safe;
|
|
675
|
+
}
|
|
532
676
|
|
|
533
677
|
// src/utils/metaRefresh.ts
|
|
534
678
|
function isAsciiWhitespace(ch) {
|
|
@@ -544,40 +688,40 @@ function trimAsciiWhitespace(value) {
|
|
|
544
688
|
var forbidden = (reason) => ({ kind: "forbidden", reason });
|
|
545
689
|
function parseMetaRefreshContent(content) {
|
|
546
690
|
const raw = trimAsciiWhitespace(stripControlChars(content));
|
|
547
|
-
if (raw === "") return forbidden("empty content");
|
|
691
|
+
if (raw === "") return forbidden(DEV ? "empty content" : "");
|
|
548
692
|
let i2 = 0;
|
|
549
693
|
while (i2 < raw.length && raw[i2] >= "0" && raw[i2] <= "9") i2++;
|
|
550
|
-
if (i2 === 0) return forbidden("missing or non-numeric delay");
|
|
694
|
+
if (i2 === 0) return forbidden(DEV ? "missing or non-numeric delay" : "");
|
|
551
695
|
const delay = Number.parseInt(raw.slice(0, i2), 10);
|
|
552
|
-
if (!Number.isFinite(delay)) return forbidden("unparseable delay");
|
|
696
|
+
if (!Number.isFinite(delay)) return forbidden(DEV ? "unparseable delay" : "");
|
|
553
697
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
554
698
|
if (i2 === raw.length) return { kind: "delay-only", delay };
|
|
555
|
-
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden("unexpected text after delay");
|
|
699
|
+
if (raw[i2] !== ";" && raw[i2] !== ",") return forbidden(DEV ? "unexpected text after delay" : "");
|
|
556
700
|
i2++;
|
|
557
701
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
558
702
|
const keyStart = i2;
|
|
559
703
|
while (i2 < raw.length && !isAsciiWhitespace(raw[i2]) && raw[i2] !== "=") i2++;
|
|
560
704
|
const key = raw.slice(keyStart, i2).toLowerCase();
|
|
561
|
-
if (key !== "url") return forbidden(`unsupported refresh key ${JSON.stringify(key)}`);
|
|
705
|
+
if (key !== "url") return forbidden(DEV ? `unsupported refresh key ${JSON.stringify(key)}` : "");
|
|
562
706
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
563
|
-
if (raw[i2] !== "=") return forbidden("missing '=' after url");
|
|
707
|
+
if (raw[i2] !== "=") return forbidden(DEV ? "missing '=' after url" : "");
|
|
564
708
|
i2++;
|
|
565
709
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
566
710
|
let destination;
|
|
567
711
|
const quote2 = raw[i2];
|
|
568
712
|
if (quote2 === '"' || quote2 === "'") {
|
|
569
713
|
const close = raw.indexOf(quote2, i2 + 1);
|
|
570
|
-
if (close === -1) return forbidden("unterminated quoted destination");
|
|
714
|
+
if (close === -1) return forbidden(DEV ? "unterminated quoted destination" : "");
|
|
571
715
|
destination = raw.slice(i2 + 1, close);
|
|
572
716
|
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
573
|
-
if (rest !== "") return forbidden("trailing text after quoted destination");
|
|
717
|
+
if (rest !== "") return forbidden(DEV ? "trailing text after quoted destination" : "");
|
|
574
718
|
} else {
|
|
575
719
|
destination = trimAsciiWhitespace(raw.slice(i2));
|
|
576
|
-
if (/[;,]/.test(destination)) return forbidden("multiple refresh assignments");
|
|
720
|
+
if (/[;,]/.test(destination)) return forbidden(DEV ? "multiple refresh assignments" : "");
|
|
577
721
|
}
|
|
578
|
-
if (destination === "") return forbidden("empty destination");
|
|
722
|
+
if (destination === "") return forbidden(DEV ? "empty destination" : "");
|
|
579
723
|
const sanitizedDestination = sanitizeUrl(destination);
|
|
580
|
-
if (sanitizedDestination === "") return forbidden("destination uses a disallowed protocol");
|
|
724
|
+
if (sanitizedDestination === "") return forbidden(DEV ? "destination uses a disallowed protocol" : "");
|
|
581
725
|
return { kind: "allowed", delay, destination, sanitizedDestination };
|
|
582
726
|
}
|
|
583
727
|
function resolveMetaRefreshPolicy(attributes) {
|
|
@@ -593,7 +737,7 @@ function resolveMetaRefreshPolicy(attributes) {
|
|
|
593
737
|
else if (canonical === "content") content = value;
|
|
594
738
|
}
|
|
595
739
|
if (duplicateName !== void 0) {
|
|
596
|
-
return forbidden(`duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}`);
|
|
740
|
+
return forbidden(DEV ? `duplicate case-insensitive attribute ${JSON.stringify(duplicateName)}` : "");
|
|
597
741
|
}
|
|
598
742
|
if (typeof httpEquiv !== "string") return { kind: "not-refresh" };
|
|
599
743
|
if (trimAsciiWhitespace(stripControlChars(httpEquiv)).toLowerCase() !== "refresh") {
|
|
@@ -619,6 +763,128 @@ function isForbiddenMetaEntry(props) {
|
|
|
619
763
|
return resolveMetaRefreshPolicy(normalized).kind === "forbidden";
|
|
620
764
|
}
|
|
621
765
|
|
|
766
|
+
// src/utils/elementPolicy.ts
|
|
767
|
+
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
768
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
769
|
+
var BLOCKED_ELEMENTS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
770
|
+
function canonicalTagName(tag) {
|
|
771
|
+
return canonicalAttrName(tag);
|
|
772
|
+
}
|
|
773
|
+
function isBlockedElement(tag) {
|
|
774
|
+
return BLOCKED_ELEMENTS.has(canonicalTagName(tag));
|
|
775
|
+
}
|
|
776
|
+
var CODE_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
777
|
+
function isCodeTextElement(tag) {
|
|
778
|
+
return CODE_TEXT_ELEMENTS.has(canonicalTagName(tag));
|
|
779
|
+
}
|
|
780
|
+
var ContextualRefusal = {
|
|
781
|
+
None: 0,
|
|
782
|
+
/** The element would carry a refresh directive the shared policy forbids. */
|
|
783
|
+
MetaRefreshForbidden: 1,
|
|
784
|
+
/** A `<meta>` with a reactive binding may not carry any refresh directive. */
|
|
785
|
+
MetaRefreshReactive: 2,
|
|
786
|
+
/** A runtime value may not choose which program a `<script>` runs. */
|
|
787
|
+
ScriptSource: 3,
|
|
788
|
+
/** An SVG animation may not target a URL, handler or document attribute. */
|
|
789
|
+
AnimationTarget: 4,
|
|
790
|
+
/** A runtime-written `href` may not become an applied stylesheet. */
|
|
791
|
+
StylesheetSource: 5
|
|
792
|
+
};
|
|
793
|
+
var SCRIPT_SOURCE_ATTRIBUTES = /* @__PURE__ */ new Set(["src", "href", "xlink:href", "type", "language"]);
|
|
794
|
+
var SVG_ANIMATION_ELEMENTS = /* @__PURE__ */ new Set(["animate", "set", "animateMotion", "animateTransform", "animateColor"]);
|
|
795
|
+
var reactiveMetaElements = /* @__PURE__ */ new WeakSet();
|
|
796
|
+
function isHtmlNamespace(el) {
|
|
797
|
+
return el.namespaceURI === HTML_NS || el.namespaceURI === null;
|
|
798
|
+
}
|
|
799
|
+
function metaSnapshot(el, canonical, value) {
|
|
800
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
801
|
+
const attrs = el.attributes;
|
|
802
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
803
|
+
const attr = attrs[i2];
|
|
804
|
+
if (attr.name === canonical) continue;
|
|
805
|
+
snapshot.set(attr.name, attr.value);
|
|
806
|
+
}
|
|
807
|
+
if (canonical !== null && value !== null) snapshot.set(canonical, value);
|
|
808
|
+
return snapshot;
|
|
809
|
+
}
|
|
810
|
+
function claimReactiveMeta(el) {
|
|
811
|
+
if (reactiveMetaElements.has(el)) return;
|
|
812
|
+
reactiveMetaElements.add(el);
|
|
813
|
+
if (el.getAttribute("content") === null) return;
|
|
814
|
+
if (resolveMetaRefreshPolicy(metaSnapshot(el, null, null)).kind !== "not-refresh") {
|
|
815
|
+
el.removeAttribute("content");
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
function metaRefusal(el, name, value, origin) {
|
|
819
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
820
|
+
const canonical = canonicalAttrName(name);
|
|
821
|
+
if (canonical !== "http-equiv" && canonical !== "content") return ContextualRefusal.None;
|
|
822
|
+
if (origin === "reactive") claimReactiveMeta(el);
|
|
823
|
+
if (value === null) return ContextualRefusal.None;
|
|
824
|
+
if (canonical === "content" && !el.hasAttribute("http-equiv")) return ContextualRefusal.None;
|
|
825
|
+
const decision = resolveMetaRefreshPolicy(metaSnapshot(el, canonical, value));
|
|
826
|
+
if (decision.kind === "forbidden") return ContextualRefusal.MetaRefreshForbidden;
|
|
827
|
+
if (decision.kind !== "not-refresh" && reactiveMetaElements.has(el)) return ContextualRefusal.MetaRefreshReactive;
|
|
828
|
+
return ContextualRefusal.None;
|
|
829
|
+
}
|
|
830
|
+
function animationRefusal(name, value) {
|
|
831
|
+
if (value === null || canonicalAttrName(name) !== "attributename") return ContextualRefusal.None;
|
|
832
|
+
const target = stripControlChars(value);
|
|
833
|
+
return isUrlAttribute(target) || isEventHandlerAttr(target) || isHtmlContentAttribute(target) ? ContextualRefusal.AnimationTarget : ContextualRefusal.None;
|
|
834
|
+
}
|
|
835
|
+
var runtimeHrefLinks = /* @__PURE__ */ new WeakSet();
|
|
836
|
+
function relHasStylesheet(rel) {
|
|
837
|
+
if (rel === null) return false;
|
|
838
|
+
const lower = canonicalAttrName(rel);
|
|
839
|
+
if (!lower.includes("stylesheet")) return false;
|
|
840
|
+
const tokens = lower.split(/[\t\n\f\r ]+/);
|
|
841
|
+
for (let i2 = 0; i2 < tokens.length; i2++) if (tokens[i2] === "stylesheet") return true;
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
function stylesheetRefusal(el, name, value, origin) {
|
|
845
|
+
if (!isHtmlNamespace(el)) return ContextualRefusal.None;
|
|
846
|
+
const canonical = canonicalAttrName(name);
|
|
847
|
+
if (canonical === "href") {
|
|
848
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
849
|
+
if (relHasStylesheet(el.getAttribute("rel"))) return ContextualRefusal.StylesheetSource;
|
|
850
|
+
runtimeHrefLinks.add(el);
|
|
851
|
+
return ContextualRefusal.None;
|
|
852
|
+
}
|
|
853
|
+
if (canonical === "rel") {
|
|
854
|
+
if (!relHasStylesheet(value)) return ContextualRefusal.None;
|
|
855
|
+
return runtimeHrefLinks.has(el) && el.hasAttribute("href") ? ContextualRefusal.StylesheetSource : ContextualRefusal.None;
|
|
856
|
+
}
|
|
857
|
+
return ContextualRefusal.None;
|
|
858
|
+
}
|
|
859
|
+
function contextualAttributeRefusal(el, name, value, origin) {
|
|
860
|
+
const local = el.localName;
|
|
861
|
+
if (local === "meta") return metaRefusal(el, name, value, origin);
|
|
862
|
+
if (local === "link") return stylesheetRefusal(el, name, value, origin);
|
|
863
|
+
if (local === "script") {
|
|
864
|
+
if (origin === "static" || value === null) return ContextualRefusal.None;
|
|
865
|
+
return SCRIPT_SOURCE_ATTRIBUTES.has(canonicalAttrName(name)) ? ContextualRefusal.ScriptSource : ContextualRefusal.None;
|
|
866
|
+
}
|
|
867
|
+
if (SVG_ANIMATION_ELEMENTS.has(local) && el.namespaceURI === SVG_NS) return animationRefusal(name, value);
|
|
868
|
+
return ContextualRefusal.None;
|
|
869
|
+
}
|
|
870
|
+
function settleAttributeProvenance(el, name, origin) {
|
|
871
|
+
if (el.localName !== "link" || canonicalAttrName(name) !== "href") return;
|
|
872
|
+
if (origin !== "static" && el.hasAttribute("href")) runtimeHrefLinks.add(el);
|
|
873
|
+
else runtimeHrefLinks.delete(el);
|
|
874
|
+
}
|
|
875
|
+
function isForbiddenMetaSnapshot(attributes) {
|
|
876
|
+
return resolveMetaRefreshPolicy(attributes).kind === "forbidden";
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// src/utils/guards.ts
|
|
880
|
+
function readOwnGlobal(key) {
|
|
881
|
+
if (typeof window === "undefined") return void 0;
|
|
882
|
+
if (!Object.hasOwn(window, key)) return void 0;
|
|
883
|
+
const value = window[key];
|
|
884
|
+
if (typeof Node !== "undefined" && value instanceof Node) return void 0;
|
|
885
|
+
return value;
|
|
886
|
+
}
|
|
887
|
+
|
|
622
888
|
// src/utils/headEntry.ts
|
|
623
889
|
var SAFE_HEAD_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
624
890
|
function isEmittableHeadAttrName(name) {
|
|
@@ -629,9 +895,7 @@ function isEmittableHeadAttrName(name) {
|
|
|
629
895
|
return true;
|
|
630
896
|
}
|
|
631
897
|
function sanitizeHeadAttrValue(canonical, value) {
|
|
632
|
-
|
|
633
|
-
const safe = sanitizeAttributeString(canonical, value);
|
|
634
|
-
return safe === "" ? null : safe;
|
|
898
|
+
return resolveAttributeValue(canonical, value);
|
|
635
899
|
}
|
|
636
900
|
function findDuplicateAttributeName(names) {
|
|
637
901
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -688,15 +952,9 @@ function serializeHeadEntry(tag, attrs) {
|
|
|
688
952
|
}
|
|
689
953
|
|
|
690
954
|
// src/platform/ssr.ts
|
|
691
|
-
function isPolicyAttr(lowerName) {
|
|
692
|
-
return isPolicyAttribute(lowerName);
|
|
693
|
-
}
|
|
694
955
|
function isForbiddenSsrAttr(lowerName) {
|
|
695
956
|
return isHtmlContentAttribute(lowerName);
|
|
696
957
|
}
|
|
697
|
-
function sanitizeSsrAttributeValue(lowerName, value) {
|
|
698
|
-
return sanitizeAttributeString(lowerName, value);
|
|
699
|
-
}
|
|
700
958
|
var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
701
959
|
function isSafeAttrName(name) {
|
|
702
960
|
return SAFE_ATTR_NAME.test(name);
|
|
@@ -727,6 +985,64 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
727
985
|
"track",
|
|
728
986
|
"wbr"
|
|
729
987
|
]);
|
|
988
|
+
function findNativeGetter(proto, name) {
|
|
989
|
+
for (let p2 = proto; p2; p2 = Object.getPrototypeOf(p2)) {
|
|
990
|
+
const get = Object.getOwnPropertyDescriptor(p2, name)?.get;
|
|
991
|
+
if (get) return get;
|
|
992
|
+
}
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
var nativeAccessorsByRealm = /* @__PURE__ */ new WeakMap();
|
|
996
|
+
function nativeAccessors() {
|
|
997
|
+
const realm = Element;
|
|
998
|
+
let accessors = nativeAccessorsByRealm.get(realm);
|
|
999
|
+
if (!accessors) {
|
|
1000
|
+
accessors = {
|
|
1001
|
+
attributes: findNativeGetter(Element.prototype, "attributes"),
|
|
1002
|
+
tagName: findNativeGetter(Element.prototype, "tagName"),
|
|
1003
|
+
childNodes: findNativeGetter(Node.prototype, "childNodes"),
|
|
1004
|
+
getAttribute: Element.prototype.getAttribute
|
|
1005
|
+
};
|
|
1006
|
+
nativeAccessorsByRealm.set(realm, accessors);
|
|
1007
|
+
}
|
|
1008
|
+
return accessors;
|
|
1009
|
+
}
|
|
1010
|
+
function attributesOf(el) {
|
|
1011
|
+
const get = nativeAccessors().attributes;
|
|
1012
|
+
return get ? get.call(el) : el.attributes;
|
|
1013
|
+
}
|
|
1014
|
+
function tagNameOf(el) {
|
|
1015
|
+
const get = nativeAccessors().tagName;
|
|
1016
|
+
return get ? get.call(el) : el.tagName;
|
|
1017
|
+
}
|
|
1018
|
+
function childNodesOf(node) {
|
|
1019
|
+
const get = nativeAccessors().childNodes;
|
|
1020
|
+
return get ? get.call(node) : node.childNodes;
|
|
1021
|
+
}
|
|
1022
|
+
function getAttributeOf(el, name) {
|
|
1023
|
+
return nativeAccessors().getAttribute.call(el, name);
|
|
1024
|
+
}
|
|
1025
|
+
function serializeOpenTag(element, tag) {
|
|
1026
|
+
let html2 = `<${tag}`;
|
|
1027
|
+
const meta2 = tag === "meta" ? /* @__PURE__ */ new Map() : null;
|
|
1028
|
+
const attrs = attributesOf(element);
|
|
1029
|
+
for (let i2 = 0; i2 < attrs.length; i2++) {
|
|
1030
|
+
const attr = attrs[i2];
|
|
1031
|
+
const rawName = attr.name;
|
|
1032
|
+
if (!isSafeAttrName(rawName)) continue;
|
|
1033
|
+
if (isEventHandlerAttr(rawName)) continue;
|
|
1034
|
+
if (isForbiddenSsrAttr(rawName)) continue;
|
|
1035
|
+
const value = resolveAttributeValue(rawName.toLowerCase(), attr.value);
|
|
1036
|
+
if (value === null) continue;
|
|
1037
|
+
meta2?.set(rawName, value);
|
|
1038
|
+
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
1039
|
+
}
|
|
1040
|
+
if (meta2 && isForbiddenMetaSnapshot(meta2)) return null;
|
|
1041
|
+
if (!getAttributeOf(element, "data-sibu-hydrate")) {
|
|
1042
|
+
html2 += ` data-sibu-ssr="true"`;
|
|
1043
|
+
}
|
|
1044
|
+
return html2;
|
|
1045
|
+
}
|
|
730
1046
|
function renderToString(element) {
|
|
731
1047
|
if (element instanceof DocumentFragment) {
|
|
732
1048
|
return Array.from(element.childNodes).map((child) => {
|
|
@@ -746,35 +1062,21 @@ function renderToString(element) {
|
|
|
746
1062
|
if (!(element instanceof HTMLElement)) {
|
|
747
1063
|
return escapeHtml(element.textContent || "");
|
|
748
1064
|
}
|
|
749
|
-
const tag = element.
|
|
750
|
-
if (tag
|
|
1065
|
+
const tag = tagNameOf(element).toLowerCase();
|
|
1066
|
+
if (isCodeTextElement(tag)) {
|
|
751
1067
|
return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
752
1068
|
}
|
|
753
1069
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
754
1070
|
return DEV ? "<!--ssr:invalid-tag-->" : "";
|
|
755
1071
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
if (!isSafeAttrName(rawName)) continue;
|
|
760
|
-
if (isEventHandlerAttr(rawName)) continue;
|
|
761
|
-
if (isForbiddenSsrAttr(rawName)) continue;
|
|
762
|
-
const lowerName = rawName.toLowerCase();
|
|
763
|
-
let value = attr.value;
|
|
764
|
-
if (isPolicyAttr(lowerName)) {
|
|
765
|
-
value = sanitizeSsrAttributeValue(lowerName, value);
|
|
766
|
-
if (!value) continue;
|
|
767
|
-
}
|
|
768
|
-
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
769
|
-
}
|
|
770
|
-
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
771
|
-
html2 += ` data-sibu-ssr="true"`;
|
|
772
|
-
}
|
|
1072
|
+
const openTag = serializeOpenTag(element, tag);
|
|
1073
|
+
if (openTag === null) return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
1074
|
+
let html2 = openTag;
|
|
773
1075
|
if (VOID_ELEMENTS.has(tag)) {
|
|
774
1076
|
return `${html2} />`;
|
|
775
1077
|
}
|
|
776
1078
|
html2 += ">";
|
|
777
|
-
for (const child of Array.from(element
|
|
1079
|
+
for (const child of Array.from(childNodesOf(element))) {
|
|
778
1080
|
try {
|
|
779
1081
|
html2 += renderToString(child);
|
|
780
1082
|
} catch (err) {
|
|
@@ -924,12 +1226,8 @@ function buildAttrString(attrs, { allowEventHandlers = false } = {}) {
|
|
|
924
1226
|
if (!isSafeAttrName(rawKey)) continue;
|
|
925
1227
|
if (!allowEventHandlers && isEventHandlerAttr(rawKey)) continue;
|
|
926
1228
|
if (isForbiddenSsrAttr(rawKey)) continue;
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
if (isPolicyAttr(lowerKey)) {
|
|
930
|
-
value = sanitizeSsrAttributeValue(lowerKey, value);
|
|
931
|
-
if (!value) continue;
|
|
932
|
-
}
|
|
1229
|
+
const value = resolveAttributeValue(rawKey.toLowerCase(), String(attrs[rawKey]));
|
|
1230
|
+
if (value === null) continue;
|
|
933
1231
|
out.push(`${rawKey}="${escapeAttr(value)}"`);
|
|
934
1232
|
}
|
|
935
1233
|
return out.join(" ");
|
|
@@ -992,8 +1290,8 @@ async function* renderToStream(element) {
|
|
|
992
1290
|
yield escapeHtml(element.textContent || "");
|
|
993
1291
|
return;
|
|
994
1292
|
}
|
|
995
|
-
const tag = element.
|
|
996
|
-
if (tag
|
|
1293
|
+
const tag = tagNameOf(element).toLowerCase();
|
|
1294
|
+
if (isCodeTextElement(tag)) {
|
|
997
1295
|
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
998
1296
|
return;
|
|
999
1297
|
}
|
|
@@ -1001,29 +1299,17 @@ async function* renderToStream(element) {
|
|
|
1001
1299
|
if (DEV) yield "<!--ssr:invalid-tag-->";
|
|
1002
1300
|
return;
|
|
1003
1301
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
if (isEventHandlerAttr(rawName)) continue;
|
|
1009
|
-
if (isForbiddenSsrAttr(rawName)) continue;
|
|
1010
|
-
const lowerName = rawName.toLowerCase();
|
|
1011
|
-
let value = attr.value;
|
|
1012
|
-
if (isPolicyAttr(lowerName)) {
|
|
1013
|
-
value = sanitizeSsrAttributeValue(lowerName, value);
|
|
1014
|
-
if (!value) continue;
|
|
1015
|
-
}
|
|
1016
|
-
openTag += ` ${rawName}="${escapeAttr(value)}"`;
|
|
1017
|
-
}
|
|
1018
|
-
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
1019
|
-
openTag += ` data-sibu-ssr="true"`;
|
|
1302
|
+
const openTag = serializeOpenTag(element, tag);
|
|
1303
|
+
if (openTag === null) {
|
|
1304
|
+
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
1305
|
+
return;
|
|
1020
1306
|
}
|
|
1021
1307
|
if (VOID_ELEMENTS.has(tag)) {
|
|
1022
1308
|
yield `${openTag} />`;
|
|
1023
1309
|
return;
|
|
1024
1310
|
}
|
|
1025
1311
|
yield `${openTag}>`;
|
|
1026
|
-
for (const child of Array.from(element
|
|
1312
|
+
for (const child of Array.from(childNodesOf(element))) {
|
|
1027
1313
|
try {
|
|
1028
1314
|
yield* renderToStream(child);
|
|
1029
1315
|
} catch (err) {
|
|
@@ -1208,8 +1494,7 @@ function deserializeState(validate) {
|
|
|
1208
1494
|
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
1209
1495
|
);
|
|
1210
1496
|
}
|
|
1211
|
-
const
|
|
1212
|
-
const raw = w[SSR_DATA_ATTR];
|
|
1497
|
+
const raw = readOwnGlobal(SSR_DATA_ATTR);
|
|
1213
1498
|
if (raw === void 0) return void 0;
|
|
1214
1499
|
if (validate && !validate(raw)) return void 0;
|
|
1215
1500
|
return raw;
|
|
@@ -1712,7 +1997,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1712
1997
|
}
|
|
1713
1998
|
|
|
1714
1999
|
// src/reactivity/track.ts
|
|
1715
|
-
var _runtimeVersion = true ? "4.
|
|
2000
|
+
var _runtimeVersion = true ? "4.8.0" : "dev";
|
|
1716
2001
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1717
2002
|
function resolveReactiveApi() {
|
|
1718
2003
|
const g2 = globalThis;
|
|
@@ -1768,6 +2053,14 @@ var getSubscriberCount2 = API.getSubscriberCount;
|
|
|
1768
2053
|
var getSubscriberDeps2 = API.getSubscriberDeps;
|
|
1769
2054
|
var forEachSubscriber2 = API.forEachSubscriber;
|
|
1770
2055
|
|
|
2056
|
+
// src/core/devtoolsHook.ts
|
|
2057
|
+
function emitDevtools(hook, event, payload) {
|
|
2058
|
+
try {
|
|
2059
|
+
hook.emit(event, payload);
|
|
2060
|
+
} catch {
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
|
|
1771
2064
|
// src/core/signals/effect.ts
|
|
1772
2065
|
var _g = globalThis;
|
|
1773
2066
|
var MAX_RERUNS = 100;
|
|
@@ -1883,12 +2176,17 @@ function effect(effectFn, options) {
|
|
|
1883
2176
|
try {
|
|
1884
2177
|
retrack2(ctx.bodyFn, ctx.subscriber);
|
|
1885
2178
|
if (ctx.rerunPending) drainReruns(ctx);
|
|
2179
|
+
} catch (err) {
|
|
2180
|
+
ctx.disposed = true;
|
|
2181
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
2182
|
+
cleanup2(ctx.subscriber);
|
|
2183
|
+
throw err;
|
|
1886
2184
|
} finally {
|
|
1887
2185
|
ctx.running = false;
|
|
1888
2186
|
ctx.rerunPending = false;
|
|
1889
2187
|
}
|
|
1890
2188
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1891
|
-
if (hook) hook
|
|
2189
|
+
if (hook) emitDevtools(hook, "effect:create", { effectFn });
|
|
1892
2190
|
return () => disposeEffect(ctx);
|
|
1893
2191
|
}
|
|
1894
2192
|
|
|
@@ -2256,7 +2554,7 @@ function signal(initial, options) {
|
|
|
2256
2554
|
state2.__v++;
|
|
2257
2555
|
if (DEV) {
|
|
2258
2556
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2259
|
-
if (hook) hook
|
|
2557
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2260
2558
|
}
|
|
2261
2559
|
if (!enqueueBatchedSignal(state2)) {
|
|
2262
2560
|
notifySubscribers2(state2);
|
|
@@ -2270,7 +2568,7 @@ function signal(initial, options) {
|
|
|
2270
2568
|
state2.value = newValue;
|
|
2271
2569
|
state2.__v++;
|
|
2272
2570
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2273
|
-
if (hook) hook
|
|
2571
|
+
if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2274
2572
|
if (!enqueueBatchedSignal(state2)) {
|
|
2275
2573
|
notifySubscribers2(state2);
|
|
2276
2574
|
}
|
|
@@ -2289,7 +2587,7 @@ function signal(initial, options) {
|
|
|
2289
2587
|
}
|
|
2290
2588
|
if (DEV) {
|
|
2291
2589
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2292
|
-
if (hook) hook
|
|
2590
|
+
if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
2293
2591
|
}
|
|
2294
2592
|
return [get, set];
|
|
2295
2593
|
}
|
|
@@ -2510,25 +2808,43 @@ function createMiddlewareChain() {
|
|
|
2510
2808
|
}
|
|
2511
2809
|
|
|
2512
2810
|
// src/utils/setSafeAttribute.ts
|
|
2513
|
-
var
|
|
2514
|
-
var
|
|
2811
|
+
var HTML_NS2 = "http://www.w3.org/1999/xhtml";
|
|
2812
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2515
2813
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
2516
2814
|
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
2517
2815
|
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
2518
2816
|
function isHtmlElement(el) {
|
|
2519
|
-
return el.namespaceURI === null || el.namespaceURI ===
|
|
2817
|
+
return el.namespaceURI === null || el.namespaceURI === HTML_NS2;
|
|
2818
|
+
}
|
|
2819
|
+
function warnContextualRefusal(label2, name, refusal) {
|
|
2820
|
+
devWarnLazy(() => {
|
|
2821
|
+
const reasons = [
|
|
2822
|
+
"",
|
|
2823
|
+
'the element would become a <meta http-equiv="refresh"> directive the shared refresh policy forbids (a destination outside the URL allowlist, or a directive too malformed to read unambiguously)',
|
|
2824
|
+
"a <meta> whose http-equiv or content is reactive may never carry a refresh directive: a browser schedules the navigation as soon as the directive is valid, and nothing can withdraw it when the state changes back",
|
|
2825
|
+
"a runtime value may not choose the program a <script> runs; name the script in static template source, or load it through Head({ script }) as an explicit trust decision",
|
|
2826
|
+
"an SVG animation may not target a URL, event-handler or nested-document attribute; its to / values would be written into that attribute without passing the URL policy",
|
|
2827
|
+
'a runtime-chosen href may not become an applied <link rel="stylesheet">: a well-formed URL is not a trusted stylesheet. Name the stylesheet in static template source, or load a runtime-chosen one through Head({ link }) as an explicit trust decision'
|
|
2828
|
+
];
|
|
2829
|
+
return `${label2}: refusing "${name}" in this element's context \u2014 ${reasons[refusal]}. The write was not performed.`;
|
|
2830
|
+
});
|
|
2520
2831
|
}
|
|
2521
2832
|
function setProp(el, key, val) {
|
|
2522
2833
|
el[key] = val;
|
|
2523
2834
|
}
|
|
2524
2835
|
function namespaceFor(el, name) {
|
|
2525
|
-
if (el.namespaceURI !==
|
|
2836
|
+
if (el.namespaceURI !== SVG_NS2) return null;
|
|
2526
2837
|
const lower = name.toLowerCase();
|
|
2527
2838
|
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
2528
2839
|
if (lower.startsWith("xml:")) return XML_NS;
|
|
2529
2840
|
return null;
|
|
2530
2841
|
}
|
|
2531
2842
|
function setSafeAttribute(el, name, value, options = {}) {
|
|
2843
|
+
const written = commitSafeAttribute(el, name, value, options);
|
|
2844
|
+
if (el.localName === "link") settleAttributeProvenance(el, name, options.reactive ? "reactive" : "runtime");
|
|
2845
|
+
return written;
|
|
2846
|
+
}
|
|
2847
|
+
function commitSafeAttribute(el, name, value, options) {
|
|
2532
2848
|
const ns = namespaceFor(el, name);
|
|
2533
2849
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
2534
2850
|
if (isEventHandlerAttr(name)) {
|
|
@@ -2541,6 +2857,14 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2541
2857
|
else el.removeAttribute(name);
|
|
2542
2858
|
return false;
|
|
2543
2859
|
}
|
|
2860
|
+
const pending = value == null || value === false ? null : value === true ? "" : String(value);
|
|
2861
|
+
const refusal = contextualAttributeRefusal(el, name, pending, options.reactive ? "reactive" : "runtime");
|
|
2862
|
+
if (refusal !== ContextualRefusal.None) {
|
|
2863
|
+
warnContextualRefusal(options.label ?? "setSafeAttribute", name, refusal);
|
|
2864
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
2865
|
+
else el.removeAttribute(name);
|
|
2866
|
+
return false;
|
|
2867
|
+
}
|
|
2544
2868
|
if (value == null) {
|
|
2545
2869
|
if (ns) el.removeAttributeNS(ns, localName);
|
|
2546
2870
|
else el.removeAttribute(name);
|
|
@@ -2584,7 +2908,12 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
2584
2908
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
2585
2909
|
return true;
|
|
2586
2910
|
}
|
|
2587
|
-
const safe =
|
|
2911
|
+
const safe = str === "" ? "" : resolveAttributeValue(name, str, { element: el });
|
|
2912
|
+
if (safe === null) {
|
|
2913
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
2914
|
+
else el.removeAttribute(name);
|
|
2915
|
+
return true;
|
|
2916
|
+
}
|
|
2588
2917
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
2589
2918
|
if (current === safe) return true;
|
|
2590
2919
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -2607,7 +2936,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
2607
2936
|
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
2608
2937
|
return;
|
|
2609
2938
|
}
|
|
2610
|
-
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")
|
|
2939
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")`, reactive: true });
|
|
2611
2940
|
}
|
|
2612
2941
|
return reactiveBinding2(commit, el);
|
|
2613
2942
|
}
|
|
@@ -2781,11 +3110,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2781
3110
|
}
|
|
2782
3111
|
|
|
2783
3112
|
// src/core/rendering/tagFactory.ts
|
|
2784
|
-
var
|
|
2785
|
-
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2786
|
-
function isBlockedTag(tag) {
|
|
2787
|
-
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
2788
|
-
}
|
|
3113
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
2789
3114
|
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
2790
3115
|
"config",
|
|
2791
3116
|
"location",
|
|
@@ -2812,8 +3137,35 @@ function toKebab(prop) {
|
|
|
2812
3137
|
}
|
|
2813
3138
|
function applyStyle(el, style2) {
|
|
2814
3139
|
if (typeof style2 === "function") {
|
|
3140
|
+
const getter = style2;
|
|
3141
|
+
let written = [];
|
|
3142
|
+
let wroteString = false;
|
|
2815
3143
|
const teardown = reactiveBinding2(() => {
|
|
2816
|
-
|
|
3144
|
+
const value = getter();
|
|
3145
|
+
if (value === null || typeof value !== "object") {
|
|
3146
|
+
written = [];
|
|
3147
|
+
wroteString = true;
|
|
3148
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(value), { element: el }));
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
const decl = el.style;
|
|
3152
|
+
if (wroteString) {
|
|
3153
|
+
el.removeAttribute("style");
|
|
3154
|
+
wroteString = false;
|
|
3155
|
+
}
|
|
3156
|
+
const next = [];
|
|
3157
|
+
for (const prop in value) {
|
|
3158
|
+
if (!Object.hasOwn(value, prop)) continue;
|
|
3159
|
+
const val = value[prop];
|
|
3160
|
+
if (val == null) continue;
|
|
3161
|
+
const name = toKebab(prop);
|
|
3162
|
+
next.push(name);
|
|
3163
|
+
decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
3164
|
+
}
|
|
3165
|
+
for (let i2 = 0; i2 < written.length; i2++) {
|
|
3166
|
+
if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
|
|
3167
|
+
}
|
|
3168
|
+
written = next;
|
|
2817
3169
|
}, el);
|
|
2818
3170
|
registerDisposer(el, teardown);
|
|
2819
3171
|
return;
|
|
@@ -2824,16 +3176,17 @@ function applyStyle(el, style2) {
|
|
|
2824
3176
|
}
|
|
2825
3177
|
const htmlEl = el;
|
|
2826
3178
|
for (const prop in style2) {
|
|
3179
|
+
if (!Object.hasOwn(style2, prop)) continue;
|
|
2827
3180
|
const val = style2[prop];
|
|
2828
3181
|
const name = toKebab(prop);
|
|
2829
3182
|
if (typeof val === "function") {
|
|
2830
3183
|
const getter = val;
|
|
2831
3184
|
const teardown = reactiveBinding2(() => {
|
|
2832
|
-
htmlEl.style.setProperty(name,
|
|
3185
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(getter()), { element: el }));
|
|
2833
3186
|
}, el);
|
|
2834
3187
|
registerDisposer(el, teardown);
|
|
2835
3188
|
} else {
|
|
2836
|
-
htmlEl.style.setProperty(name,
|
|
3189
|
+
htmlEl.style.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
|
|
2837
3190
|
}
|
|
2838
3191
|
}
|
|
2839
3192
|
}
|
|
@@ -2844,7 +3197,9 @@ function applyClass(el, cls) {
|
|
|
2844
3197
|
}
|
|
2845
3198
|
if (typeof cls === "function") {
|
|
2846
3199
|
const teardown = reactiveBinding2(() => {
|
|
2847
|
-
|
|
3200
|
+
const value = cls();
|
|
3201
|
+
if (value == null || value === false) el.removeAttribute("class");
|
|
3202
|
+
else el.setAttribute("class", value);
|
|
2848
3203
|
}, el);
|
|
2849
3204
|
registerDisposer(el, teardown);
|
|
2850
3205
|
return;
|
|
@@ -2853,6 +3208,7 @@ function applyClass(el, cls) {
|
|
|
2853
3208
|
let hasReactive = false;
|
|
2854
3209
|
let result = "";
|
|
2855
3210
|
for (const name in obj) {
|
|
3211
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
2856
3212
|
const val = obj[name];
|
|
2857
3213
|
if (typeof val === "function") {
|
|
2858
3214
|
hasReactive = true;
|
|
@@ -2864,6 +3220,7 @@ function applyClass(el, cls) {
|
|
|
2864
3220
|
const update = () => {
|
|
2865
3221
|
let r = "";
|
|
2866
3222
|
for (const name in obj) {
|
|
3223
|
+
if (!Object.hasOwn(obj, name)) continue;
|
|
2867
3224
|
const val = obj[name];
|
|
2868
3225
|
const active = typeof val === "function" ? val() : val;
|
|
2869
3226
|
if (active) r = r ? `${r} ${name}` : name;
|
|
@@ -2926,8 +3283,8 @@ function appendChildren(el, nodes) {
|
|
|
2926
3283
|
}
|
|
2927
3284
|
}
|
|
2928
3285
|
}
|
|
2929
|
-
|
|
2930
|
-
const blocked =
|
|
3286
|
+
function tagFactory(tag, ns) {
|
|
3287
|
+
const blocked = isBlockedElement(tag);
|
|
2931
3288
|
return (first, second) => {
|
|
2932
3289
|
if (blocked) {
|
|
2933
3290
|
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
@@ -2975,7 +3332,9 @@ var tagFactory = (tag, ns) => {
|
|
|
2975
3332
|
const pClass = props.class;
|
|
2976
3333
|
if (pClass != null) applyClass(el, pClass);
|
|
2977
3334
|
const pId = props.id;
|
|
2978
|
-
if (pId
|
|
3335
|
+
if (typeof pId === "function") {
|
|
3336
|
+
registerDisposer(el, bindAttribute(el, "id", pId));
|
|
3337
|
+
} else if (pId != null) {
|
|
2979
3338
|
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
2980
3339
|
devWarn(
|
|
2981
3340
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
@@ -2988,6 +3347,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2988
3347
|
const pOn = props.on;
|
|
2989
3348
|
if (pOn) {
|
|
2990
3349
|
for (const ev in pOn) {
|
|
3350
|
+
if (!Object.hasOwn(pOn, ev)) continue;
|
|
2991
3351
|
const handler = pOn[ev];
|
|
2992
3352
|
if (typeof handler === "function") {
|
|
2993
3353
|
el.addEventListener(ev, handler);
|
|
@@ -3014,6 +3374,7 @@ var tagFactory = (tag, ns) => {
|
|
|
3014
3374
|
continue;
|
|
3015
3375
|
// already handled above / below
|
|
3016
3376
|
default: {
|
|
3377
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
3017
3378
|
const value = props[key];
|
|
3018
3379
|
if (value == null) continue;
|
|
3019
3380
|
if (isEventHandlerAttr(key)) continue;
|
|
@@ -3025,12 +3386,10 @@ var tagFactory = (tag, ns) => {
|
|
|
3025
3386
|
}
|
|
3026
3387
|
}
|
|
3027
3388
|
}
|
|
3028
|
-
if (
|
|
3029
|
-
props.onElement(el);
|
|
3030
|
-
}
|
|
3389
|
+
if (typeof props.onElement === "function") props.onElement(el);
|
|
3031
3390
|
return el;
|
|
3032
3391
|
};
|
|
3033
|
-
}
|
|
3392
|
+
}
|
|
3034
3393
|
|
|
3035
3394
|
// src/core/rendering/html.ts
|
|
3036
3395
|
var html = tagFactory("html");
|
|
@@ -3105,7 +3464,7 @@ var param = tagFactory("param");
|
|
|
3105
3464
|
var picture = tagFactory("picture");
|
|
3106
3465
|
var portal = tagFactory("portal");
|
|
3107
3466
|
var source = tagFactory("source");
|
|
3108
|
-
var svg = tagFactory("svg",
|
|
3467
|
+
var svg = tagFactory("svg", SVG_NS3);
|
|
3109
3468
|
var math = tagFactory("math");
|
|
3110
3469
|
var canvas = tagFactory("canvas");
|
|
3111
3470
|
var noscript = tagFactory("noscript");
|
|
@@ -3146,26 +3505,26 @@ var base = tagFactory("base");
|
|
|
3146
3505
|
var link = tagFactory("link");
|
|
3147
3506
|
var meta = tagFactory("meta");
|
|
3148
3507
|
var style = tagFactory("style");
|
|
3149
|
-
var circle = tagFactory("circle",
|
|
3150
|
-
var ellipse = tagFactory("ellipse",
|
|
3151
|
-
var g = tagFactory("g",
|
|
3152
|
-
var line = tagFactory("line",
|
|
3153
|
-
var path = tagFactory("path",
|
|
3154
|
-
var polygon = tagFactory("polygon",
|
|
3155
|
-
var polyline = tagFactory("polyline",
|
|
3156
|
-
var rect = tagFactory("rect",
|
|
3157
|
-
var text = tagFactory("text",
|
|
3158
|
-
var tspan = tagFactory("tspan",
|
|
3159
|
-
var defs = tagFactory("defs",
|
|
3160
|
-
var clipPath = tagFactory("clipPath",
|
|
3161
|
-
var mask = tagFactory("mask",
|
|
3162
|
-
var pattern = tagFactory("pattern",
|
|
3163
|
-
var linearGradient = tagFactory("linearGradient",
|
|
3164
|
-
var radialGradient = tagFactory("radialGradient",
|
|
3165
|
-
var stop = tagFactory("stop",
|
|
3166
|
-
var use = tagFactory("use",
|
|
3167
|
-
var symbol = tagFactory("symbol",
|
|
3168
|
-
var marker = tagFactory("marker",
|
|
3508
|
+
var circle = tagFactory("circle", SVG_NS3);
|
|
3509
|
+
var ellipse = tagFactory("ellipse", SVG_NS3);
|
|
3510
|
+
var g = tagFactory("g", SVG_NS3);
|
|
3511
|
+
var line = tagFactory("line", SVG_NS3);
|
|
3512
|
+
var path = tagFactory("path", SVG_NS3);
|
|
3513
|
+
var polygon = tagFactory("polygon", SVG_NS3);
|
|
3514
|
+
var polyline = tagFactory("polyline", SVG_NS3);
|
|
3515
|
+
var rect = tagFactory("rect", SVG_NS3);
|
|
3516
|
+
var text = tagFactory("text", SVG_NS3);
|
|
3517
|
+
var tspan = tagFactory("tspan", SVG_NS3);
|
|
3518
|
+
var defs = tagFactory("defs", SVG_NS3);
|
|
3519
|
+
var clipPath = tagFactory("clipPath", SVG_NS3);
|
|
3520
|
+
var mask = tagFactory("mask", SVG_NS3);
|
|
3521
|
+
var pattern = tagFactory("pattern", SVG_NS3);
|
|
3522
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS3);
|
|
3523
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS3);
|
|
3524
|
+
var stop = tagFactory("stop", SVG_NS3);
|
|
3525
|
+
var use = tagFactory("use", SVG_NS3);
|
|
3526
|
+
var symbol = tagFactory("symbol", SVG_NS3);
|
|
3527
|
+
var marker = tagFactory("marker", SVG_NS3);
|
|
3169
3528
|
var center = tagFactory("center");
|
|
3170
3529
|
var font = tagFactory("font");
|
|
3171
3530
|
var marquee = tagFactory("marquee");
|
|
@@ -3446,7 +3805,16 @@ function toError(err) {
|
|
|
3446
3805
|
if (err !== null && typeof err === "object" && "name" in err && "message" in err) return err;
|
|
3447
3806
|
return new Error(String(err));
|
|
3448
3807
|
}
|
|
3808
|
+
function workerSource(fn, api) {
|
|
3809
|
+
if (typeof fn !== "function") {
|
|
3810
|
+
throw new TypeError(
|
|
3811
|
+
`${api}: expected a function, got ${typeof fn}. Worker code must be a function defined in your source \u2014 a string would be evaluated as code.`
|
|
3812
|
+
);
|
|
3813
|
+
}
|
|
3814
|
+
return Function.prototype.toString.call(fn);
|
|
3815
|
+
}
|
|
3449
3816
|
function worker(workerFn2) {
|
|
3817
|
+
const fnBody = workerSource(workerFn2, "worker");
|
|
3450
3818
|
const [result, setResult] = signal(null);
|
|
3451
3819
|
const [error, setError] = signal(null);
|
|
3452
3820
|
const [loading, setLoading] = signal(false);
|
|
@@ -3462,7 +3830,6 @@ function worker(workerFn2) {
|
|
|
3462
3830
|
if (typeof Worker === "undefined") {
|
|
3463
3831
|
throw new Error("Web Workers are not supported in this environment");
|
|
3464
3832
|
}
|
|
3465
|
-
const fnBody = workerFn2.toString();
|
|
3466
3833
|
const blob = new Blob([`self.onmessage = ${fnBody};`], { type: "application/javascript" });
|
|
3467
3834
|
blobUrl = URL.createObjectURL(blob);
|
|
3468
3835
|
worker2 = new Worker(blobUrl);
|
|
@@ -3511,6 +3878,7 @@ function worker(workerFn2) {
|
|
|
3511
3878
|
return { post, result, error, loading, terminate };
|
|
3512
3879
|
}
|
|
3513
3880
|
function workerFn(fn) {
|
|
3881
|
+
const fnStr = workerSource(fn, "workerFn");
|
|
3514
3882
|
const [loading, setLoading] = signal(false);
|
|
3515
3883
|
let worker2 = null;
|
|
3516
3884
|
let blobUrl = null;
|
|
@@ -3525,7 +3893,6 @@ function workerFn(fn) {
|
|
|
3525
3893
|
if (typeof Worker === "undefined") {
|
|
3526
3894
|
throw new Error("Web Workers are not supported in this environment");
|
|
3527
3895
|
}
|
|
3528
|
-
const fnStr = fn.toString();
|
|
3529
3896
|
const blob = new Blob(
|
|
3530
3897
|
[
|
|
3531
3898
|
`self.onmessage = function(e) {
|
|
@@ -3585,6 +3952,7 @@ function workerFn(fn) {
|
|
|
3585
3952
|
return { run, loading, terminate };
|
|
3586
3953
|
}
|
|
3587
3954
|
function createWorkerPool(workerFn2, poolSize) {
|
|
3955
|
+
const fnBody = workerSource(workerFn2, "createWorkerPool");
|
|
3588
3956
|
const size = poolSize || typeof navigator !== "undefined" && navigator.hardwareConcurrency || 4;
|
|
3589
3957
|
const workers = [];
|
|
3590
3958
|
const queues = [];
|
|
@@ -3643,7 +4011,6 @@ function createWorkerPool(workerFn2, poolSize) {
|
|
|
3643
4011
|
if (typeof Worker === "undefined") {
|
|
3644
4012
|
throw new Error("Web Workers are not supported in this environment");
|
|
3645
4013
|
}
|
|
3646
|
-
const fnBody = workerFn2.toString();
|
|
3647
4014
|
const blob = new Blob([`self.onmessage = ${fnBody};`], { type: "application/javascript" });
|
|
3648
4015
|
blobUrl = URL.createObjectURL(blob);
|
|
3649
4016
|
for (let i2 = 0; i2 < size; i2++) {
|