sibujs 4.1.0 → 4.2.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 +24 -0
- package/dist/browser.cjs +13 -21
- package/dist/browser.js +6 -6
- package/dist/build.cjs +278 -104
- package/dist/build.js +15 -15
- package/dist/cdn.dev.global.js +398 -0
- package/dist/cdn.global.js +10 -10
- package/dist/{chunk-DCDS2PQ6.js → chunk-2LOYNGBY.js} +2 -2
- package/dist/{chunk-VPP2FONR.js → chunk-2WLZ6757.js} +17 -10
- package/dist/{chunk-IM7N5WR4.js → chunk-3VTSPNC5.js} +2 -2
- package/dist/{chunk-TIRZCERI.js → chunk-5DXA2J44.js} +1 -1
- package/dist/{chunk-I3VI34DP.js → chunk-6ZGI3RBE.js} +149 -33
- package/dist/{chunk-D3SZ4LVS.js → chunk-7ALC7KGE.js} +5 -6
- package/dist/{chunk-PFTDGEPZ.js → chunk-7VEC3UD2.js} +3 -3
- package/dist/{chunk-KSOEJGFO.js → chunk-BMYYZWHX.js} +3 -3
- package/dist/{chunk-LOFZHP6V.js → chunk-BNKV4REK.js} +7 -8
- package/dist/{chunk-5GJ5RTHA.js → chunk-FOWBJZDL.js} +7 -8
- package/dist/{chunk-FB7KQXZI.js → chunk-GDUNQCCW.js} +4 -4
- package/dist/{chunk-UFSQEO7P.js → chunk-HECVW343.js} +7 -8
- package/dist/{chunk-SHDVWATN.js → chunk-HJEPKZ2O.js} +7 -8
- package/dist/{chunk-ANGSYNPX.js → chunk-HZEBO22J.js} +57 -37
- package/dist/{chunk-5INI7D2L.js → chunk-IXKSNWV5.js} +74 -11
- package/dist/{chunk-DAKLOMKS.js → chunk-KE4KWRDY.js} +3 -3
- package/dist/{chunk-AW6HPJ3L.js → chunk-KKLW7YWL.js} +1 -1
- package/dist/{chunk-BMSN6NWQ.js → chunk-NEYWS4EX.js} +6 -6
- package/dist/{chunk-HYCCIYNS.js → chunk-NIOYEGBQ.js} +13 -14
- package/dist/{chunk-4U7KD3RY.js → chunk-OUWAIXIK.js} +3 -3
- package/dist/{chunk-MRAMKDHQ.js → chunk-P3DHXBR6.js} +1 -1
- package/dist/{chunk-FMHIQNMP.js → chunk-QCFLDD7C.js} +5 -5
- package/dist/{chunk-DHDZ7IVN.js → chunk-QKRPLZ2V.js} +7 -8
- package/dist/{chunk-4RH6D7GR.js → chunk-QL4UREZO.js} +6 -6
- package/dist/{chunk-XIHMS2Y6.js → chunk-SF3TB4K6.js} +8 -8
- package/dist/{chunk-XSZRJW76.js → chunk-XZ2N525U.js} +6 -6
- package/dist/{customElement-CKLoO63w.d.ts → customElement-CNZxEB9G.d.cts} +77 -0
- package/dist/{customElement-CKLoO63w.d.cts → customElement-CNZxEB9G.d.ts} +77 -0
- package/dist/data.cjs +15 -24
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +18 -22
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +8 -8
- package/dist/{dispose-4FZ6OFXR.js → dispose-46BOMMQJ.js} +2 -2
- package/dist/ecosystem.cjs +222 -67
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +243 -86
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +25 -25
- package/dist/index.cjs +272 -98
- package/dist/index.d.cts +154 -33
- package/dist/index.d.ts +154 -33
- package/dist/index.js +15 -15
- package/dist/{introspect-RjLfIFpL.d.cts → introspect-D5xF-0Es.d.cts} +7 -0
- package/dist/{introspect-DOZfmC-4.d.ts → introspect-rSBIxEQi.d.ts} +7 -0
- package/dist/motion.cjs +13 -22
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +16 -24
- package/dist/patterns.d.cts +8 -0
- package/dist/patterns.d.ts +8 -0
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +16 -27
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +260 -86
- package/dist/plugins.d.cts +92 -0
- package/dist/plugins.d.ts +92 -0
- package/dist/plugins.js +18 -17
- package/dist/{ssr-JFP5535P.js → ssr-Y7XOEPEN.js} +5 -5
- package/dist/ssr.cjs +233 -79
- package/dist/ssr.js +12 -12
- package/dist/testing.cjs +11 -19
- package/dist/testing.js +5 -5
- package/dist/ui.cjs +98 -43
- package/dist/ui.d.cts +7 -1
- package/dist/ui.d.ts +7 -1
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +13 -21
- package/dist/widgets.d.cts +8 -0
- package/dist/widgets.d.ts +8 -0
- package/dist/widgets.js +9 -9
- package/package.json +5 -2
package/dist/extras.cjs
CHANGED
|
@@ -318,23 +318,28 @@ __export(extras_exports, {
|
|
|
318
318
|
module.exports = __toCommonJS(extras_exports);
|
|
319
319
|
|
|
320
320
|
// src/core/dev.ts
|
|
321
|
+
var DEV = typeof __SIBU_DEV__ !== "undefined" ? !!__SIBU_DEV__ : typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
322
|
+
// safe default: off in browser, on in test/dev Node
|
|
323
|
+
typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
324
|
+
);
|
|
321
325
|
function isDev() {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
// this branch is unreachable here.
|
|
326
|
-
/* v8 ignore next 2 */
|
|
327
|
-
typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
328
|
-
);
|
|
326
|
+
if (typeof globalThis.__SIBU_DEV__ !== "undefined") return !!globalThis.__SIBU_DEV__;
|
|
327
|
+
if (typeof __SIBU_DEV__ !== "undefined") return !!__SIBU_DEV__;
|
|
328
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
329
329
|
}
|
|
330
|
-
var _isDev = isDev();
|
|
331
330
|
function devAssert(condition, message) {
|
|
332
|
-
if (
|
|
331
|
+
if ((typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) && !condition) {
|
|
333
332
|
throw new Error(`[SibuJS] ${message}`);
|
|
334
333
|
}
|
|
335
334
|
}
|
|
335
|
+
function devWarnLazy(build) {
|
|
336
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
337
|
+
const message = build();
|
|
338
|
+
if (message) console.warn(`[SibuJS] ${message}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
336
341
|
function devWarn(message) {
|
|
337
|
-
if (
|
|
342
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
338
343
|
console.warn(`[SibuJS] ${message}`);
|
|
339
344
|
}
|
|
340
345
|
}
|
|
@@ -883,17 +888,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
883
888
|
}
|
|
884
889
|
|
|
885
890
|
// src/reactivity/track.ts
|
|
886
|
-
var
|
|
887
|
-
var _runtimeVersion = true ? "4.1.0" : "dev";
|
|
891
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
888
892
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
889
893
|
function resolveReactiveApi() {
|
|
890
894
|
const g2 = globalThis;
|
|
891
895
|
const existing = g2[REGISTRY_KEY];
|
|
892
896
|
if (existing) {
|
|
893
|
-
if (
|
|
897
|
+
if (DEV && !existing.__dupWarned) {
|
|
894
898
|
existing.__dupWarned = true;
|
|
895
899
|
devWarn(
|
|
896
|
-
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity
|
|
900
|
+
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity is NOT broken and no bundler configuration is required: every copy routes through the first one via a global registry, so signal writes still reach subscribers registered by any copy. This is only a SIZE issue \u2014 the duplicate copy's bytes are downloaded and parsed for nothing. If you want them back, de-duplicate sibujs in your bundler (Vite: resolve.dedupe: ['sibujs']). Mismatched VERSIONS above are worth fixing regardless, since only the first one loaded is used.`
|
|
897
901
|
);
|
|
898
902
|
}
|
|
899
903
|
return existing;
|
|
@@ -1239,7 +1243,6 @@ var isBatching = API2.isBatching;
|
|
|
1239
1243
|
|
|
1240
1244
|
// src/core/signals/signal.ts
|
|
1241
1245
|
var _g2 = globalThis;
|
|
1242
|
-
var _isDev3 = isDev();
|
|
1243
1246
|
function signal(initial, options) {
|
|
1244
1247
|
const state2 = {
|
|
1245
1248
|
value: initial,
|
|
@@ -1252,7 +1255,7 @@ function signal(initial, options) {
|
|
|
1252
1255
|
_d: false,
|
|
1253
1256
|
_validate: void 0
|
|
1254
1257
|
};
|
|
1255
|
-
const debugName =
|
|
1258
|
+
const debugName = DEV ? options?.name : void 0;
|
|
1256
1259
|
const equalsFn = options?.equals;
|
|
1257
1260
|
if (debugName) state2.__name = debugName;
|
|
1258
1261
|
function get() {
|
|
@@ -1269,7 +1272,7 @@ function signal(initial, options) {
|
|
|
1269
1272
|
if (equalsFn(prev, newValue)) return;
|
|
1270
1273
|
state2.value = newValue;
|
|
1271
1274
|
state2.__v++;
|
|
1272
|
-
if (
|
|
1275
|
+
if (DEV) {
|
|
1273
1276
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1274
1277
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
1275
1278
|
}
|
|
@@ -1277,7 +1280,7 @@ function signal(initial, options) {
|
|
|
1277
1280
|
notifySubscribers2(state2);
|
|
1278
1281
|
}
|
|
1279
1282
|
};
|
|
1280
|
-
} else if (
|
|
1283
|
+
} else if (DEV) {
|
|
1281
1284
|
set = (next) => {
|
|
1282
1285
|
const prev = state2.value;
|
|
1283
1286
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -1302,7 +1305,7 @@ function signal(initial, options) {
|
|
|
1302
1305
|
}
|
|
1303
1306
|
};
|
|
1304
1307
|
}
|
|
1305
|
-
if (
|
|
1308
|
+
if (DEV) {
|
|
1306
1309
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
1307
1310
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
1308
1311
|
}
|
|
@@ -2439,11 +2442,10 @@ function syncAdapter(config) {
|
|
|
2439
2442
|
}
|
|
2440
2443
|
|
|
2441
2444
|
// src/core/rendering/context.ts
|
|
2442
|
-
var _isDev4 = isDev();
|
|
2443
2445
|
function context(defaultValue) {
|
|
2444
2446
|
const [getValue, setValue] = signal(defaultValue);
|
|
2445
2447
|
const warnIfSSR = (method) => {
|
|
2446
|
-
if (!
|
|
2448
|
+
if (!DEV || !isSSR()) return;
|
|
2447
2449
|
devWarn(
|
|
2448
2450
|
`context.${method}() called during SSR. SibuJS context() is application-global \u2014 it is NOT isolated per request, so a concurrent request can observe this value. Do not use context() for request-specific SSR data; pass it explicitly or use request-scoped storage instead.`
|
|
2449
2451
|
);
|
|
@@ -2471,7 +2473,7 @@ function context(defaultValue) {
|
|
|
2471
2473
|
setValue(value);
|
|
2472
2474
|
try {
|
|
2473
2475
|
const result = fn();
|
|
2474
|
-
if (
|
|
2476
|
+
if (DEV && result !== null && typeof result?.then === "function") {
|
|
2475
2477
|
devWarn(
|
|
2476
2478
|
"context.withContext() received an async callback. Scoping is synchronous only \u2014 the previous value is restored as soon as the callback returns its promise, so anything after an `await` runs outside the scope."
|
|
2477
2479
|
);
|
|
@@ -2724,20 +2726,75 @@ function decodeCssEscapes(value) {
|
|
|
2724
2726
|
}
|
|
2725
2727
|
return out;
|
|
2726
2728
|
}
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
+
var BLOCKED_CSS_NEEDLES = [
|
|
2730
|
+
"url(",
|
|
2731
|
+
"expression(",
|
|
2732
|
+
"javascript:",
|
|
2733
|
+
"vbscript:",
|
|
2734
|
+
"-moz-binding",
|
|
2735
|
+
"behavior:",
|
|
2736
|
+
"@import",
|
|
2737
|
+
"image-set(",
|
|
2738
|
+
"filter:progid"
|
|
2739
|
+
];
|
|
2740
|
+
function describeElement(el) {
|
|
2741
|
+
if (!el) return "an element";
|
|
2742
|
+
let out = el.tagName.toLowerCase();
|
|
2743
|
+
const id = el.getAttribute("id");
|
|
2744
|
+
if (id) out += `#${id}`;
|
|
2745
|
+
const cls = el.getAttribute("class");
|
|
2746
|
+
if (cls) out += `.${cls.trim().split(/\s+/).slice(0, 3).join(".")}`;
|
|
2747
|
+
return `<${out}>`;
|
|
2748
|
+
}
|
|
2749
|
+
var warnedDeclarations = /* @__PURE__ */ new Set();
|
|
2750
|
+
var MAX_WARNED_DECLARATIONS = 100;
|
|
2751
|
+
var declarationCapAnnounced = false;
|
|
2752
|
+
function warnDroppedDeclaration(value, reason, ctx) {
|
|
2753
|
+
devWarnLazy(() => {
|
|
2754
|
+
const reasons = [
|
|
2755
|
+
"url() in an inline style is an exfiltration channel: the browser fetches it immediately and the URL's path or query can carry page data off-origin",
|
|
2756
|
+
"expression() executes arbitrary script in legacy engines",
|
|
2757
|
+
"the javascript: scheme executes script",
|
|
2758
|
+
"the vbscript: scheme executes script",
|
|
2759
|
+
"-moz-binding loads and runs remote XBL",
|
|
2760
|
+
"behavior: loads and runs a remote HTC script",
|
|
2761
|
+
"@import pulls in a remote stylesheet",
|
|
2762
|
+
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
2763
|
+
"filter:progid activates legacy scriptable filters"
|
|
2764
|
+
];
|
|
2765
|
+
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
2766
|
+
const where = describeElement(ctx?.element);
|
|
2767
|
+
const key = `${where}|${declaration}`;
|
|
2768
|
+
if (warnedDeclarations.has(key)) return "";
|
|
2769
|
+
if (warnedDeclarations.size >= MAX_WARNED_DECLARATIONS) {
|
|
2770
|
+
if (declarationCapAnnounced) return "";
|
|
2771
|
+
declarationCapAnnounced = true;
|
|
2772
|
+
return `${MAX_WARNED_DECLARATIONS} distinct dropped style declarations have been reported; suppressing further ones for the rest of this session so they cannot flood the console. The declarations are still dropped \u2014 only the reporting stops. Fix the reported ones and reload to see any that remain.`;
|
|
2773
|
+
}
|
|
2774
|
+
warnedDeclarations.add(key);
|
|
2775
|
+
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.`;
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
function blockedCssReason(value) {
|
|
2779
|
+
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
2729
2780
|
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
2730
2781
|
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
2731
|
-
|
|
2732
|
-
return
|
|
2782
|
+
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
2783
|
+
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
2733
2784
|
}
|
|
2734
|
-
return
|
|
2785
|
+
return -1;
|
|
2735
2786
|
}
|
|
2736
|
-
function
|
|
2787
|
+
function sanitizeCSSValue(value, context2) {
|
|
2788
|
+
const reason = blockedCssReason(value);
|
|
2789
|
+
if (reason === -1) return value;
|
|
2790
|
+
warnDroppedDeclaration(value, reason, context2);
|
|
2791
|
+
return "";
|
|
2792
|
+
}
|
|
2793
|
+
function sanitizeStyleAttribute(cssText, context2) {
|
|
2737
2794
|
const input2 = String(cssText);
|
|
2738
2795
|
if (input2.trim() === "") return "";
|
|
2739
2796
|
if (typeof document === "undefined") {
|
|
2740
|
-
return sanitizeCSSValue(input2) === "" ? "" : input2;
|
|
2797
|
+
return sanitizeCSSValue(input2, context2) === "" ? "" : input2;
|
|
2741
2798
|
}
|
|
2742
2799
|
const probe = document.createElement("div");
|
|
2743
2800
|
try {
|
|
@@ -2749,8 +2806,12 @@ function sanitizeStyleAttribute(cssText) {
|
|
|
2749
2806
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
2750
2807
|
const property = probe.style[i2];
|
|
2751
2808
|
const value = probe.style.getPropertyValue(property);
|
|
2752
|
-
|
|
2753
|
-
if (
|
|
2809
|
+
let reason = blockedCssReason(value);
|
|
2810
|
+
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
2811
|
+
if (reason !== -1) {
|
|
2812
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
2813
|
+
continue;
|
|
2814
|
+
}
|
|
2754
2815
|
const priority = probe.style.getPropertyPriority(property);
|
|
2755
2816
|
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
2756
2817
|
}
|
|
@@ -2798,11 +2859,11 @@ function isPolicyAttribute(name) {
|
|
|
2798
2859
|
const lower = name.toLowerCase();
|
|
2799
2860
|
return lower === "style" || URL_ATTRIBUTES.has(lower);
|
|
2800
2861
|
}
|
|
2801
|
-
function sanitizeAttributeString(attr, value) {
|
|
2862
|
+
function sanitizeAttributeString(attr, value, context2) {
|
|
2802
2863
|
const lower = attr.toLowerCase();
|
|
2803
2864
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
2804
2865
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
2805
|
-
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
2866
|
+
if (lower === "style") return sanitizeStyleAttribute(value, context2);
|
|
2806
2867
|
return value;
|
|
2807
2868
|
}
|
|
2808
2869
|
|
|
@@ -5118,7 +5179,6 @@ function reportDrainRunaway(label2, executed, remaining) {
|
|
|
5118
5179
|
{ executed, remaining }
|
|
5119
5180
|
);
|
|
5120
5181
|
}
|
|
5121
|
-
var _isDev5 = isDev();
|
|
5122
5182
|
var activeBindingCount = 0;
|
|
5123
5183
|
function registerDisposer(node, teardown) {
|
|
5124
5184
|
let disposers = elementDisposers.get(node);
|
|
@@ -5127,7 +5187,7 @@ function registerDisposer(node, teardown) {
|
|
|
5127
5187
|
elementDisposers.set(node, disposers);
|
|
5128
5188
|
}
|
|
5129
5189
|
disposers.push(teardown);
|
|
5130
|
-
if (
|
|
5190
|
+
if (DEV) activeBindingCount++;
|
|
5131
5191
|
}
|
|
5132
5192
|
function dispose(node) {
|
|
5133
5193
|
const stack = [node];
|
|
@@ -5150,13 +5210,13 @@ function dispose(node) {
|
|
|
5150
5210
|
if (!pending || pending.length === 0) break;
|
|
5151
5211
|
const snapshot = pending.slice();
|
|
5152
5212
|
elementDisposers.delete(current);
|
|
5153
|
-
if (
|
|
5213
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
5154
5214
|
for (let i3 = 0; i3 < snapshot.length; i3++) {
|
|
5155
5215
|
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
5156
5216
|
const rest = snapshot.slice(i3);
|
|
5157
5217
|
const added = elementDisposers.get(current);
|
|
5158
5218
|
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
5159
|
-
if (
|
|
5219
|
+
if (DEV) activeBindingCount += rest.length;
|
|
5160
5220
|
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
5161
5221
|
runaway = true;
|
|
5162
5222
|
break;
|
|
@@ -6273,16 +6333,16 @@ function sanitizeCSS(css) {
|
|
|
6273
6333
|
function firstCompoundEnd(selector) {
|
|
6274
6334
|
let parens = 0;
|
|
6275
6335
|
let brackets = 0;
|
|
6276
|
-
let
|
|
6336
|
+
let quote2 = null;
|
|
6277
6337
|
for (let i2 = 0; i2 < selector.length; i2++) {
|
|
6278
6338
|
const ch = selector[i2];
|
|
6279
|
-
if (
|
|
6339
|
+
if (quote2) {
|
|
6280
6340
|
if (ch === "\\") i2++;
|
|
6281
|
-
else if (ch ===
|
|
6341
|
+
else if (ch === quote2) quote2 = null;
|
|
6282
6342
|
continue;
|
|
6283
6343
|
}
|
|
6284
6344
|
if (ch === '"' || ch === "'") {
|
|
6285
|
-
|
|
6345
|
+
quote2 = ch;
|
|
6286
6346
|
continue;
|
|
6287
6347
|
}
|
|
6288
6348
|
if (ch === "\\") {
|
|
@@ -6458,7 +6518,6 @@ function removeScopedStyle(scopeId) {
|
|
|
6458
6518
|
}
|
|
6459
6519
|
|
|
6460
6520
|
// src/utils/setSafeAttribute.ts
|
|
6461
|
-
var _isDev6 = isDev();
|
|
6462
6521
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
6463
6522
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
6464
6523
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -6481,7 +6540,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
6481
6540
|
const ns = namespaceFor(el, name);
|
|
6482
6541
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
6483
6542
|
if (isEventHandlerAttr(name)) {
|
|
6484
|
-
if (
|
|
6543
|
+
if (DEV) {
|
|
6485
6544
|
devWarn(
|
|
6486
6545
|
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
6487
6546
|
);
|
|
@@ -6496,7 +6555,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
6496
6555
|
return true;
|
|
6497
6556
|
}
|
|
6498
6557
|
if (isHtmlContentAttribute(name)) {
|
|
6499
|
-
if (
|
|
6558
|
+
if (DEV) {
|
|
6500
6559
|
devWarn(
|
|
6501
6560
|
`${options.label ?? "setSafeAttribute"}: refusing to set "${name}". The browser parses this attribute as a nested HTML document, so a generic string value cannot be made safe \u2014 attribute escaping is undone before the parse. Build the frame's content another way.`
|
|
6502
6561
|
);
|
|
@@ -6525,7 +6584,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
6525
6584
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
6526
6585
|
return true;
|
|
6527
6586
|
}
|
|
6528
|
-
const safe = sanitizeAttributeString(name, str);
|
|
6587
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
6529
6588
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
6530
6589
|
if (current === safe) return true;
|
|
6531
6590
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -7097,7 +7156,6 @@ function uniqueId(suffix) {
|
|
|
7097
7156
|
}
|
|
7098
7157
|
|
|
7099
7158
|
// src/performance/domRecycler.ts
|
|
7100
|
-
var _isDev7 = isDev();
|
|
7101
7159
|
var DOMPool = class {
|
|
7102
7160
|
constructor(maxSize = 50) {
|
|
7103
7161
|
this.pools = /* @__PURE__ */ new Map();
|
|
@@ -7124,7 +7182,7 @@ var DOMPool = class {
|
|
|
7124
7182
|
* is almost certainly a bug.
|
|
7125
7183
|
*/
|
|
7126
7184
|
release(element) {
|
|
7127
|
-
if (
|
|
7185
|
+
if (DEV && element.isConnected) {
|
|
7128
7186
|
devWarn(
|
|
7129
7187
|
"DOMPool.release() called on a still-connected element. Detach it from the DOM first (remove() / dispose())."
|
|
7130
7188
|
);
|
|
@@ -7269,9 +7327,9 @@ function parseMetaRefreshContent(content) {
|
|
|
7269
7327
|
i2++;
|
|
7270
7328
|
while (i2 < raw.length && isAsciiWhitespace(raw[i2])) i2++;
|
|
7271
7329
|
let destination;
|
|
7272
|
-
const
|
|
7273
|
-
if (
|
|
7274
|
-
const close = raw.indexOf(
|
|
7330
|
+
const quote2 = raw[i2];
|
|
7331
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
7332
|
+
const close = raw.indexOf(quote2, i2 + 1);
|
|
7275
7333
|
if (close === -1) return forbidden("unterminated quoted destination");
|
|
7276
7334
|
destination = raw.slice(i2 + 1, close);
|
|
7277
7335
|
const rest = trimAsciiWhitespace(raw.slice(close + 1));
|
|
@@ -7402,13 +7460,12 @@ function isForbiddenSsrAttr(lowerName) {
|
|
|
7402
7460
|
function sanitizeSsrAttributeValue(lowerName, value) {
|
|
7403
7461
|
return sanitizeAttributeString(lowerName, value);
|
|
7404
7462
|
}
|
|
7405
|
-
var _isDev8 = isDev();
|
|
7406
7463
|
var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
7407
7464
|
function isSafeAttrName(name) {
|
|
7408
7465
|
return SAFE_ATTR_NAME.test(name);
|
|
7409
7466
|
}
|
|
7410
7467
|
function ssrErrorComment(err) {
|
|
7411
|
-
if (
|
|
7468
|
+
if (DEV) {
|
|
7412
7469
|
const msg = escapeHtml(err instanceof Error ? err.message : String(err));
|
|
7413
7470
|
return `<!--SSR error: ${safeCommentText(msg)}-->`;
|
|
7414
7471
|
}
|
|
@@ -7454,10 +7511,10 @@ function renderToString(element) {
|
|
|
7454
7511
|
}
|
|
7455
7512
|
const tag = element.tagName.toLowerCase();
|
|
7456
7513
|
if (tag === "script" || tag === "style") {
|
|
7457
|
-
return
|
|
7514
|
+
return DEV ? `<!--ssr:${tag}-stripped-->` : "";
|
|
7458
7515
|
}
|
|
7459
7516
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
7460
|
-
return
|
|
7517
|
+
return DEV ? "<!--ssr:invalid-tag-->" : "";
|
|
7461
7518
|
}
|
|
7462
7519
|
let html2 = `<${tag}`;
|
|
7463
7520
|
for (const attr of Array.from(element.attributes)) {
|
|
@@ -7499,7 +7556,7 @@ function hydrate(component, container, options = {}) {
|
|
|
7499
7556
|
const first = mismatches[0];
|
|
7500
7557
|
if (options.onMismatch) {
|
|
7501
7558
|
options.onMismatch(first);
|
|
7502
|
-
} else if (
|
|
7559
|
+
} else if (DEV) {
|
|
7503
7560
|
console.warn(
|
|
7504
7561
|
`[SibuJS hydration] ${first.message}
|
|
7505
7562
|
at ${first.path}
|
|
@@ -7700,11 +7757,11 @@ async function* renderToStream(element) {
|
|
|
7700
7757
|
}
|
|
7701
7758
|
const tag = element.tagName.toLowerCase();
|
|
7702
7759
|
if (tag === "script" || tag === "style") {
|
|
7703
|
-
if (
|
|
7760
|
+
if (DEV) yield `<!--ssr:${tag}-stripped-->`;
|
|
7704
7761
|
return;
|
|
7705
7762
|
}
|
|
7706
7763
|
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
7707
|
-
if (
|
|
7764
|
+
if (DEV) yield "<!--ssr:invalid-tag-->";
|
|
7708
7765
|
return;
|
|
7709
7766
|
}
|
|
7710
7767
|
let openTag = `<${tag}`;
|
|
@@ -7847,7 +7904,7 @@ function ssrSuspense(props) {
|
|
|
7847
7904
|
},
|
|
7848
7905
|
(err) => {
|
|
7849
7906
|
if (timer) clearTimeout(timer);
|
|
7850
|
-
if (
|
|
7907
|
+
if (DEV) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
|
|
7851
7908
|
return { id, html: fallbackHtml };
|
|
7852
7909
|
}
|
|
7853
7910
|
);
|
|
@@ -7893,7 +7950,7 @@ function serializeState(state2, nonce, options) {
|
|
|
7893
7950
|
}
|
|
7894
7951
|
function deserializeState(validate) {
|
|
7895
7952
|
if (typeof window === "undefined") return void 0;
|
|
7896
|
-
if (
|
|
7953
|
+
if (DEV && !validate) {
|
|
7897
7954
|
console.warn(
|
|
7898
7955
|
"[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
|
|
7899
7956
|
);
|
|
@@ -8913,8 +8970,101 @@ function isWasmCached(key) {
|
|
|
8913
8970
|
return moduleCache.has(key);
|
|
8914
8971
|
}
|
|
8915
8972
|
|
|
8973
|
+
// src/core/rendering/focusPreservation.ts
|
|
8974
|
+
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
8975
|
+
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
8976
|
+
function selectionOf(el) {
|
|
8977
|
+
const tag = el.tagName;
|
|
8978
|
+
const selectable = tag === "TEXTAREA" || tag === "INPUT" && SELECTABLE_TYPES.has(el.type.toLowerCase());
|
|
8979
|
+
if (!selectable) return { start: null, end: null, direction: null };
|
|
8980
|
+
const field = el;
|
|
8981
|
+
return { start: field.selectionStart, end: field.selectionEnd, direction: field.selectionDirection };
|
|
8982
|
+
}
|
|
8983
|
+
function captureFocusWithin(nodes) {
|
|
8984
|
+
if (nodes.length === 0 || typeof document === "undefined") return null;
|
|
8985
|
+
const active = document.activeElement;
|
|
8986
|
+
if (!active || active === document.body) return null;
|
|
8987
|
+
let inside = false;
|
|
8988
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
8989
|
+
const n = nodes[i2];
|
|
8990
|
+
if (n === active || n.nodeType === 1 && n.contains(active)) {
|
|
8991
|
+
inside = true;
|
|
8992
|
+
break;
|
|
8993
|
+
}
|
|
8994
|
+
}
|
|
8995
|
+
if (!inside) return null;
|
|
8996
|
+
let attr = null;
|
|
8997
|
+
let value = null;
|
|
8998
|
+
for (let i2 = 0; i2 < IDENTITY_ATTRS.length; i2++) {
|
|
8999
|
+
const candidate = active.getAttribute(IDENTITY_ATTRS[i2]);
|
|
9000
|
+
if (candidate) {
|
|
9001
|
+
attr = IDENTITY_ATTRS[i2];
|
|
9002
|
+
value = candidate;
|
|
9003
|
+
break;
|
|
9004
|
+
}
|
|
9005
|
+
}
|
|
9006
|
+
return { el: active, attr, value, tag: active.tagName, ...selectionOf(active) };
|
|
9007
|
+
}
|
|
9008
|
+
function quote(value) {
|
|
9009
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
9010
|
+
}
|
|
9011
|
+
function findUniqueByIdentity(nodes, selector) {
|
|
9012
|
+
let el = null;
|
|
9013
|
+
let count = 0;
|
|
9014
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
9015
|
+
const n = nodes[i2];
|
|
9016
|
+
if (n.nodeType !== 1) continue;
|
|
9017
|
+
const root = n;
|
|
9018
|
+
if (root.matches(selector)) {
|
|
9019
|
+
count++;
|
|
9020
|
+
el ?? (el = root);
|
|
9021
|
+
}
|
|
9022
|
+
const inner = root.querySelectorAll(selector);
|
|
9023
|
+
for (let j = 0; j < inner.length; j++) {
|
|
9024
|
+
count++;
|
|
9025
|
+
el ?? (el = inner[j]);
|
|
9026
|
+
}
|
|
9027
|
+
if (count > 1) return { el: null, count };
|
|
9028
|
+
}
|
|
9029
|
+
return count === 1 ? { el, count } : { el: null, count };
|
|
9030
|
+
}
|
|
9031
|
+
function refocus(el, snapshot) {
|
|
9032
|
+
el.focus();
|
|
9033
|
+
if (snapshot.start !== null && typeof el.setSelectionRange === "function") {
|
|
9034
|
+
const field = el;
|
|
9035
|
+
const max2 = field.value.length;
|
|
9036
|
+
const start = Math.min(snapshot.start, max2);
|
|
9037
|
+
const end = Math.min(snapshot.end ?? start, max2);
|
|
9038
|
+
field.setSelectionRange(start, end, snapshot.direction ?? "none");
|
|
9039
|
+
}
|
|
9040
|
+
}
|
|
9041
|
+
function restoreFocusWithin(snapshot, nodes, where) {
|
|
9042
|
+
if (!snapshot) return;
|
|
9043
|
+
if (typeof document === "undefined") return;
|
|
9044
|
+
const active = document.activeElement;
|
|
9045
|
+
if (active === snapshot.el) return;
|
|
9046
|
+
if (active && active !== document.body && active !== document.documentElement) return;
|
|
9047
|
+
if (snapshot.el.isConnected) {
|
|
9048
|
+
refocus(snapshot.el, snapshot);
|
|
9049
|
+
return;
|
|
9050
|
+
}
|
|
9051
|
+
let ambiguous = false;
|
|
9052
|
+
if (snapshot.attr && snapshot.value) {
|
|
9053
|
+
const { el: replacement, count } = findUniqueByIdentity(nodes, `[${snapshot.attr}=${quote(snapshot.value)}]`);
|
|
9054
|
+
if (replacement && replacement.tagName === snapshot.tag) {
|
|
9055
|
+
refocus(replacement, snapshot);
|
|
9056
|
+
return;
|
|
9057
|
+
}
|
|
9058
|
+
ambiguous = count > 1;
|
|
9059
|
+
}
|
|
9060
|
+
devWarnLazy(() => {
|
|
9061
|
+
const id = snapshot.attr ? ` (${snapshot.attr}="${snapshot.value}")` : "";
|
|
9062
|
+
const why = ambiguous ? `several elements in the rebuilt subtree share ${snapshot.attr}="${snapshot.value}", so there is no way to tell which one the user was in \u2014 a shared name (a radio group) identifies a GROUP, not a control. Add a unique id or data-focus-key to each` : "no element in the rebuilt subtree carries the same identity. Give it a stable id, name, or data-focus-key that the rebuild reproduces";
|
|
9063
|
+
return `${where}: a reactive rebuild discarded the focused element <${snapshot.tag.toLowerCase()}>${id} and could not re-establish it, so focus fell back to <body>. An in-progress edit ends here, and an in-progress IME composition is lost outright \u2014 a composition belongs to the DOM node, so it cannot survive the node being destroyed. ${why}, or stop the rebuild from happening: key the subtree with match(() => shapeKey(), { \u2026 }) so it is re-created only when the shape actually changes, and drive the rest with reactive attributes and text children, which mutate nodes in place instead of replacing them.`;
|
|
9064
|
+
});
|
|
9065
|
+
}
|
|
9066
|
+
|
|
8916
9067
|
// src/reactivity/bindChildNode.ts
|
|
8917
|
-
var _isDev9 = isDev();
|
|
8918
9068
|
function bindChildNode(placeholder, getter) {
|
|
8919
9069
|
let lastNodes = [];
|
|
8920
9070
|
function commit() {
|
|
@@ -8925,6 +9075,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
8925
9075
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
8926
9076
|
return;
|
|
8927
9077
|
}
|
|
9078
|
+
const focused = captureFocusWithin(lastNodes);
|
|
8928
9079
|
if (result == null || typeof result === "boolean") {
|
|
8929
9080
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
8930
9081
|
const node = lastNodes[i2];
|
|
@@ -8932,6 +9083,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
8932
9083
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
8933
9084
|
}
|
|
8934
9085
|
lastNodes.length = 0;
|
|
9086
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
8935
9087
|
return;
|
|
8936
9088
|
}
|
|
8937
9089
|
const parent = placeholder.parentNode;
|
|
@@ -8948,8 +9100,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
8948
9100
|
if (item == null || typeof item === "boolean") continue;
|
|
8949
9101
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
8950
9102
|
if (seen.has(node)) {
|
|
8951
|
-
if (
|
|
8952
|
-
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
9103
|
+
if (DEV) devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
8953
9104
|
continue;
|
|
8954
9105
|
}
|
|
8955
9106
|
seen.add(node);
|
|
@@ -8982,13 +9133,13 @@ function bindChildNode(placeholder, getter) {
|
|
|
8982
9133
|
prev = node;
|
|
8983
9134
|
}
|
|
8984
9135
|
lastNodes = newNodes;
|
|
9136
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
8985
9137
|
}
|
|
8986
9138
|
return reactiveBinding2(commit, placeholder);
|
|
8987
9139
|
}
|
|
8988
9140
|
|
|
8989
9141
|
// src/core/rendering/tagFactory.ts
|
|
8990
9142
|
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
8991
|
-
var _isDev10 = isDev();
|
|
8992
9143
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
8993
9144
|
function isBlockedTag(tag) {
|
|
8994
9145
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -9006,18 +9157,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
9006
9157
|
"self",
|
|
9007
9158
|
"frames"
|
|
9008
9159
|
]);
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
const tokens = t.split(/\s+/);
|
|
9013
|
-
let sawClassish = false;
|
|
9014
|
-
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
9015
|
-
const tok = tokens[i2];
|
|
9016
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
9017
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
9018
|
-
}
|
|
9019
|
-
return sawClassish;
|
|
9020
|
-
}
|
|
9160
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
9161
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
9162
|
+
var loneStringCapAnnounced = false;
|
|
9021
9163
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
9022
9164
|
function toKebab(prop) {
|
|
9023
9165
|
let cached = kebabCache.get(prop);
|
|
@@ -9029,13 +9171,13 @@ function toKebab(prop) {
|
|
|
9029
9171
|
function applyStyle(el, style2) {
|
|
9030
9172
|
if (typeof style2 === "function") {
|
|
9031
9173
|
const teardown = reactiveBinding2(() => {
|
|
9032
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
9174
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
|
|
9033
9175
|
}, el);
|
|
9034
9176
|
registerDisposer(el, teardown);
|
|
9035
9177
|
return;
|
|
9036
9178
|
}
|
|
9037
9179
|
if (typeof style2 === "string") {
|
|
9038
|
-
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
9180
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2, { element: el }));
|
|
9039
9181
|
return;
|
|
9040
9182
|
}
|
|
9041
9183
|
const htmlEl = el;
|
|
@@ -9045,11 +9187,11 @@ function applyStyle(el, style2) {
|
|
|
9045
9187
|
if (typeof val === "function") {
|
|
9046
9188
|
const getter = val;
|
|
9047
9189
|
const teardown = reactiveBinding2(() => {
|
|
9048
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
9190
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
9049
9191
|
}, el);
|
|
9050
9192
|
registerDisposer(el, teardown);
|
|
9051
9193
|
} else {
|
|
9052
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
9194
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
9053
9195
|
}
|
|
9054
9196
|
}
|
|
9055
9197
|
}
|
|
@@ -9156,11 +9298,26 @@ var tagFactory = (tag, ns) => {
|
|
|
9156
9298
|
appendChildren(el, second);
|
|
9157
9299
|
return el;
|
|
9158
9300
|
}
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9301
|
+
devWarnLazy(() => {
|
|
9302
|
+
const tokens = first.trim().split(/\s+/);
|
|
9303
|
+
if (tokens.length < 2) return "";
|
|
9304
|
+
let utilityTokens = 0;
|
|
9305
|
+
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
9306
|
+
const tok = tokens[i2];
|
|
9307
|
+
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return "";
|
|
9308
|
+
if (/[-:/0-9]/.test(tok)) utilityTokens++;
|
|
9309
|
+
}
|
|
9310
|
+
if (utilityTokens < 2) return "";
|
|
9311
|
+
const key = `${tag}|${first}`;
|
|
9312
|
+
if (warnedLoneStrings.has(key)) return "";
|
|
9313
|
+
if (warnedLoneStrings.size >= MAX_WARNED_LONE_STRINGS) {
|
|
9314
|
+
if (loneStringCapAnnounced) return "";
|
|
9315
|
+
loneStringCapAnnounced = true;
|
|
9316
|
+
return `tagFactory: ${MAX_WARNED_LONE_STRINGS} distinct lone-string class warnings have been reported; suppressing further ones for the rest of this session so they cannot flood the console. Fix the reported ones and reload to see any that remain.`;
|
|
9317
|
+
}
|
|
9318
|
+
warnedLoneStrings.add(key);
|
|
9319
|
+
return `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`;
|
|
9320
|
+
});
|
|
9164
9321
|
el.textContent = first;
|
|
9165
9322
|
return el;
|
|
9166
9323
|
}
|
|
@@ -9177,7 +9334,7 @@ var tagFactory = (tag, ns) => {
|
|
|
9177
9334
|
if (pClass != null) applyClass(el, pClass);
|
|
9178
9335
|
const pId = props.id;
|
|
9179
9336
|
if (pId != null) {
|
|
9180
|
-
if (
|
|
9337
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
9181
9338
|
devWarn(
|
|
9182
9339
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
9183
9340
|
);
|
|
@@ -9192,7 +9349,7 @@ var tagFactory = (tag, ns) => {
|
|
|
9192
9349
|
const handler = pOn[ev];
|
|
9193
9350
|
if (typeof handler === "function") {
|
|
9194
9351
|
el.addEventListener(ev, handler);
|
|
9195
|
-
} else if (
|
|
9352
|
+
} else if (DEV) {
|
|
9196
9353
|
devWarn(
|
|
9197
9354
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
9198
9355
|
);
|