sibujs 3.4.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +118 -15
- package/dist/browser.cjs +410 -101
- package/dist/browser.d.cts +50 -5
- package/dist/browser.d.ts +50 -5
- package/dist/browser.js +8 -6
- package/dist/build.cjs +777 -385
- package/dist/build.js +15 -15
- package/dist/cdn.global.js +11 -7
- package/dist/{chunk-JCO7AHNU.js → chunk-3EKJK5FZ.js} +73 -34
- package/dist/chunk-4MFZMLUU.js +147 -0
- package/dist/chunk-52XFPGSN.js +123 -0
- package/dist/chunk-5INI7D2L.js +194 -0
- package/dist/{chunk-OAVXAFAY.js → chunk-6LG2T7LO.js} +5 -5
- package/dist/{chunk-OOUQUCNN.js → chunk-ACBT6UZS.js} +57 -22
- package/dist/{chunk-F7HW2NI5.js → chunk-AW6HPJ3L.js} +1 -1
- package/dist/chunk-DHDZ7IVN.js +109 -0
- package/dist/{chunk-JNGGM2XE.js → chunk-DQVUBVNX.js} +16 -25
- package/dist/{chunk-AXFWGY32.js → chunk-DR7H6UGM.js} +232 -67
- package/dist/{chunk-WSGLJYFI.js → chunk-E62UADKL.js} +9 -3
- package/dist/{chunk-3Z2NGWQI.js → chunk-ES2GERY2.js} +1 -1
- package/dist/{chunk-S3V6ZXPI.js → chunk-EWEE7NBF.js} +115 -41
- package/dist/{chunk-3DVGCW7O.js → chunk-F64ZPCFE.js} +8 -8
- package/dist/{chunk-APFRCIRI.js → chunk-GCSGGA3Q.js} +295 -198
- package/dist/{chunk-EX77FXTT.js → chunk-HYCCIYNS.js} +228 -51
- package/dist/{chunk-ELXMRSVN.js → chunk-NF3LYCQH.js} +259 -124
- package/dist/chunk-O3QQ3XOL.js +61 -0
- package/dist/{chunk-BUKYCWHX.js → chunk-PBQEW5VW.js} +14 -10
- package/dist/{chunk-H5FI5WDP.js → chunk-RRIDJQ5C.js} +3 -3
- package/dist/{chunk-S3NFJO6L.js → chunk-TIRZCERI.js} +36 -5
- package/dist/{chunk-ODXVQ3CS.js → chunk-VFHIVEPF.js} +309 -188
- package/dist/chunk-VPP2FONR.js +142 -0
- package/dist/{chunk-KZBEVFXZ.js → chunk-W55YHPEP.js} +5 -3
- package/dist/{chunk-FKQG7FTY.js → chunk-WN6WDFCB.js} +4 -4
- package/dist/{chunk-CEBWDD63.js → chunk-WOOMUJFT.js} +228 -86
- package/dist/{chunk-ITWCTZYH.js → chunk-Z2CE42DB.js} +19 -25
- package/dist/{contracts-ey_Qh8ef.d.cts → contracts-Hg6ITAEF.d.cts} +6 -6
- package/dist/{contracts-ey_Qh8ef.d.ts → contracts-Hg6ITAEF.d.ts} +6 -6
- package/dist/{customElement-CPfIrbvg.d.ts → customElement-CKLoO63w.d.cts} +73 -11
- package/dist/{customElement-CPfIrbvg.d.cts → customElement-CKLoO63w.d.ts} +73 -11
- package/dist/data.cjs +483 -205
- package/dist/data.d.cts +139 -7
- package/dist/data.d.ts +139 -7
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +222 -87
- package/dist/devtools.js +8 -8
- package/dist/dispose-4FZ6OFXR.js +19 -0
- package/dist/ecosystem.cjs +419 -175
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +1981 -765
- package/dist/extras.d.cts +7 -7
- package/dist/extras.d.ts +7 -7
- package/dist/extras.js +29 -26
- package/dist/index.cjs +784 -385
- package/dist/index.d.cts +299 -28
- package/dist/index.d.ts +299 -28
- package/dist/index.js +33 -18
- package/dist/motion.cjs +180 -50
- package/dist/motion.d.cts +26 -0
- package/dist/motion.d.ts +26 -0
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +437 -170
- package/dist/patterns.d.cts +60 -13
- package/dist/patterns.d.ts +60 -13
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +333 -148
- package/dist/performance.d.cts +55 -7
- package/dist/performance.d.ts +55 -7
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +1374 -576
- package/dist/plugins.d.cts +227 -9
- package/dist/plugins.d.ts +227 -9
- package/dist/plugins.js +613 -321
- package/dist/{ssr-D62yFwuw.d.cts → ssr-BiPRdZ6n.d.cts} +44 -15
- package/dist/{ssr-D62yFwuw.d.ts → ssr-BiPRdZ6n.d.ts} +44 -15
- package/dist/{ssr-2PPULEK2.js → ssr-JFP5535P.js} +5 -4
- package/dist/ssr.cjs +1104 -443
- package/dist/ssr.d.cts +230 -20
- package/dist/ssr.d.ts +230 -20
- package/dist/ssr.js +15 -12
- package/dist/{startup-0Qv6aosO.d.cts → startup-BMpaiMhP.d.cts} +1 -1
- package/dist/{startup-0Qv6aosO.d.ts → startup-BMpaiMhP.d.ts} +1 -1
- package/dist/testing.cjs +205 -63
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +8 -10
- package/dist/ui.cjs +640 -199
- package/dist/ui.d.cts +2 -2
- package/dist/ui.d.ts +2 -2
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +207 -82
- package/dist/widgets.js +9 -9
- package/package.json +12 -7
- package/dist/chunk-5VGSK6D2.js +0 -80
- package/dist/chunk-COY6PUD2.js +0 -34
- package/dist/chunk-K35BAR4P.js +0 -96
- package/dist/chunk-L3GAGWCC.js +0 -111
- package/dist/chunk-RT3IYFN2.js +0 -38
package/dist/ui.cjs
CHANGED
|
@@ -107,8 +107,104 @@ function devWarn(message) {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// src/core/errors.ts
|
|
111
|
+
var ERROR_STATE_KEY = /* @__PURE__ */ Symbol.for("sibujs.runtime-errors.v1");
|
|
112
|
+
function state() {
|
|
113
|
+
const g = globalThis;
|
|
114
|
+
const existing = g[ERROR_STATE_KEY];
|
|
115
|
+
if (existing) return existing;
|
|
116
|
+
const created = { handler: null, handlerDepth: 0 };
|
|
117
|
+
g[ERROR_STATE_KEY] = created;
|
|
118
|
+
return created;
|
|
119
|
+
}
|
|
120
|
+
function normalizeError(value) {
|
|
121
|
+
if (value instanceof Error) return value;
|
|
122
|
+
const message = typeof value === "string" ? value : `Non-Error value thrown: ${safeStringify(value)}`;
|
|
123
|
+
return new Error(message, { cause: value });
|
|
124
|
+
}
|
|
125
|
+
function safeStringify(value) {
|
|
126
|
+
if (typeof value === "symbol") return value.toString();
|
|
127
|
+
try {
|
|
128
|
+
return typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
|
|
129
|
+
} catch {
|
|
130
|
+
return Object.prototype.toString.call(value);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function describe(context) {
|
|
134
|
+
return context.name ? `${context.phase} "${context.name}"` : context.phase;
|
|
135
|
+
}
|
|
136
|
+
var REACTIVE_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
137
|
+
function untrackedRun(fn) {
|
|
138
|
+
const api = globalThis[REACTIVE_REGISTRY_KEY];
|
|
139
|
+
return api?.untracked ? api.untracked(fn) : fn();
|
|
140
|
+
}
|
|
141
|
+
var PROPAGATE_EVENT = "sibu:error-propagate";
|
|
142
|
+
function claimedByBoundary(error, context) {
|
|
143
|
+
const raw = context.node;
|
|
144
|
+
if (!raw || typeof CustomEvent === "undefined") return false;
|
|
145
|
+
const target = resolveEventTarget(raw);
|
|
146
|
+
if (!target) return false;
|
|
147
|
+
try {
|
|
148
|
+
const event = new CustomEvent(PROPAGATE_EVENT, {
|
|
149
|
+
bubbles: true,
|
|
150
|
+
cancelable: true,
|
|
151
|
+
detail: { error, context }
|
|
152
|
+
});
|
|
153
|
+
return target.dispatchEvent(event) === false;
|
|
154
|
+
} catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function resolveEventTarget(node) {
|
|
159
|
+
const ELEMENT_NODE = 1;
|
|
160
|
+
let current = node;
|
|
161
|
+
while (current) {
|
|
162
|
+
if (current.nodeType === ELEMENT_NODE && typeof current.dispatchEvent === "function") {
|
|
163
|
+
return current;
|
|
164
|
+
}
|
|
165
|
+
current = current.parentNode;
|
|
166
|
+
}
|
|
167
|
+
const self = node;
|
|
168
|
+
return typeof self.dispatchEvent === "function" ? self : null;
|
|
169
|
+
}
|
|
170
|
+
function defaultReport(error, context) {
|
|
171
|
+
if (typeof console === "undefined") return;
|
|
172
|
+
console.error(`[SibuJS] Uncaught error during ${describe(context)}: ${error.message}`, error);
|
|
173
|
+
}
|
|
174
|
+
function reportError(error, context) {
|
|
175
|
+
const err = normalizeError(error);
|
|
176
|
+
untrackedRun(() => {
|
|
177
|
+
if (claimedByBoundary(err, context)) return;
|
|
178
|
+
const s = state();
|
|
179
|
+
const handler = s.handler;
|
|
180
|
+
if (handler && s.handlerDepth === 0) {
|
|
181
|
+
s.handlerDepth++;
|
|
182
|
+
try {
|
|
183
|
+
handler(error instanceof Error ? error : err, context);
|
|
184
|
+
return;
|
|
185
|
+
} catch (handlerError) {
|
|
186
|
+
if (typeof console !== "undefined") {
|
|
187
|
+
const detail = handlerError instanceof Error ? handlerError.message : String(handlerError);
|
|
188
|
+
console.error(`[SibuJS] runtime error handler itself threw: ${detail}`, handlerError);
|
|
189
|
+
}
|
|
190
|
+
} finally {
|
|
191
|
+
s.handlerDepth--;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
defaultReport(err, context);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
110
198
|
// src/core/rendering/dispose.ts
|
|
111
199
|
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
200
|
+
var MAX_DRAIN_TEARDOWNS = 1e4;
|
|
201
|
+
function reportDrainRunaway(label, executed, remaining) {
|
|
202
|
+
if (typeof console === "undefined") return;
|
|
203
|
+
console.error(
|
|
204
|
+
`[SibuJS ${label}] runaway cleanup: stopped after running ${executed} teardowns with ${remaining} still queued. Cleanup production did not stabilize before the teardown safety ceiling was reached \u2014 the remaining work was NOT run.`,
|
|
205
|
+
{ executed, remaining }
|
|
206
|
+
);
|
|
207
|
+
}
|
|
112
208
|
var _isDev2 = isDev();
|
|
113
209
|
var activeBindingCount = 0;
|
|
114
210
|
function registerDisposer(node, teardown) {
|
|
@@ -133,43 +229,49 @@ function dispose(node) {
|
|
|
133
229
|
}
|
|
134
230
|
for (let i = order.length - 1; i >= 0; i--) {
|
|
135
231
|
const current = order[i];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
d();
|
|
144
|
-
} catch (err) {
|
|
145
|
-
if (_isDev2 && typeof console !== "undefined") {
|
|
146
|
-
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
let extraPasses = 0;
|
|
151
|
-
while (extraPasses++ < 8) {
|
|
152
|
-
const added = elementDisposers.get(current);
|
|
153
|
-
if (!added || added.length === 0) break;
|
|
154
|
-
const moreSnapshot = added.slice();
|
|
232
|
+
if (elementDisposers.has(current)) {
|
|
233
|
+
let executed = 0;
|
|
234
|
+
let runaway = false;
|
|
235
|
+
while (!runaway) {
|
|
236
|
+
const pending = elementDisposers.get(current);
|
|
237
|
+
if (!pending || pending.length === 0) break;
|
|
238
|
+
const snapshot = pending.slice();
|
|
155
239
|
elementDisposers.delete(current);
|
|
156
|
-
if (_isDev2) activeBindingCount -=
|
|
157
|
-
for (
|
|
240
|
+
if (_isDev2) activeBindingCount -= snapshot.length;
|
|
241
|
+
for (let i2 = 0; i2 < snapshot.length; i2++) {
|
|
242
|
+
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
243
|
+
const rest = snapshot.slice(i2);
|
|
244
|
+
const added = elementDisposers.get(current);
|
|
245
|
+
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
246
|
+
if (_isDev2) activeBindingCount += rest.length;
|
|
247
|
+
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
248
|
+
runaway = true;
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
executed++;
|
|
158
252
|
try {
|
|
159
|
-
|
|
253
|
+
snapshot[i2]();
|
|
160
254
|
} catch (err) {
|
|
161
|
-
|
|
162
|
-
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
163
|
-
}
|
|
255
|
+
reportError(err, { phase: "cleanup", name: "disposer" });
|
|
164
256
|
}
|
|
165
257
|
}
|
|
166
258
|
}
|
|
167
259
|
}
|
|
168
260
|
}
|
|
169
261
|
}
|
|
262
|
+
function replaceChildrenSafely(parent, ...next) {
|
|
263
|
+
for (let i = 0; i < next.length; i++) {
|
|
264
|
+
const node = next[i];
|
|
265
|
+
node.parentNode?.removeChild(node);
|
|
266
|
+
}
|
|
267
|
+
const current = Array.from(parent.childNodes);
|
|
268
|
+
for (let i = 0; i < current.length; i++) {
|
|
269
|
+
dispose(current[i]);
|
|
270
|
+
}
|
|
271
|
+
parent.replaceChildren(...next);
|
|
272
|
+
}
|
|
170
273
|
|
|
171
274
|
// src/reactivity/track-core.ts
|
|
172
|
-
var _isDev3 = isDev();
|
|
173
275
|
var POOL_MAX = 4096;
|
|
174
276
|
var nodePool = [];
|
|
175
277
|
function createNode() {
|
|
@@ -177,6 +279,7 @@ function createNode() {
|
|
|
177
279
|
sig: null,
|
|
178
280
|
sub: null,
|
|
179
281
|
epoch: 0,
|
|
282
|
+
depVersion: 0,
|
|
180
283
|
sigPrev: null,
|
|
181
284
|
sigNext: null,
|
|
182
285
|
subPrev: null,
|
|
@@ -261,8 +364,27 @@ function safeInvoke(sub) {
|
|
|
261
364
|
try {
|
|
262
365
|
sub();
|
|
263
366
|
} catch (err) {
|
|
264
|
-
|
|
367
|
+
const s = sub;
|
|
368
|
+
reportError(err, { phase: s._errorPhase ?? "effect", name: s.__name, node: s._errorNode });
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function depsChanged(sub) {
|
|
372
|
+
let node = sub.depsHead ?? null;
|
|
373
|
+
if (node === null) return true;
|
|
374
|
+
while (node !== null) {
|
|
375
|
+
const sig = node.sig;
|
|
376
|
+
if (sig === null) return true;
|
|
377
|
+
if (sig._d === true && sig._validate !== void 0) {
|
|
378
|
+
try {
|
|
379
|
+
sig._validate();
|
|
380
|
+
} catch {
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (node.depVersion !== sig.__v) return true;
|
|
385
|
+
node = node.subNext;
|
|
265
386
|
}
|
|
387
|
+
return false;
|
|
266
388
|
}
|
|
267
389
|
var suspendDepth = 0;
|
|
268
390
|
var trackingSuspended = false;
|
|
@@ -344,7 +466,7 @@ function track(effectFn, subscriber) {
|
|
|
344
466
|
const sub = subscriber;
|
|
345
467
|
return sub._dispose ?? (sub._dispose = () => cleanup(subscriber));
|
|
346
468
|
}
|
|
347
|
-
function reactiveBinding(commit) {
|
|
469
|
+
function reactiveBinding(commit, ownerNode) {
|
|
348
470
|
const run = () => {
|
|
349
471
|
const s = subscriber;
|
|
350
472
|
if (s._disposed || s._reentrant) return;
|
|
@@ -360,13 +482,17 @@ function reactiveBinding(commit) {
|
|
|
360
482
|
subscriber.depsTail = null;
|
|
361
483
|
subscriber._epoch = 0;
|
|
362
484
|
subscriber._structDirty = false;
|
|
485
|
+
subscriber._hasComputedDep = false;
|
|
363
486
|
subscriber._runEpoch = 0;
|
|
364
487
|
subscriber._runs = 0;
|
|
365
488
|
subscriber._reentrant = false;
|
|
366
489
|
subscriber._disposed = false;
|
|
490
|
+
subscriber._errorPhase = "binding";
|
|
491
|
+
subscriber._errorNode = ownerNode;
|
|
367
492
|
run();
|
|
368
493
|
return subscriber._dispose ?? (subscriber._dispose = () => {
|
|
369
494
|
subscriber._disposed = true;
|
|
495
|
+
subscriber._errorNode = void 0;
|
|
370
496
|
cleanup(subscriber);
|
|
371
497
|
});
|
|
372
498
|
}
|
|
@@ -378,9 +504,12 @@ function recordDependency(signal2) {
|
|
|
378
504
|
const active = sig.__activeNode ?? null;
|
|
379
505
|
if (active !== null && active.sub === sub) {
|
|
380
506
|
active.epoch = epoch;
|
|
507
|
+
active.depVersion = sig.__v ?? Number.NaN;
|
|
381
508
|
return;
|
|
382
509
|
}
|
|
510
|
+
if (sig._validate !== void 0) sub._hasComputedDep = true;
|
|
383
511
|
const node = allocNode(signal2, sub, epoch);
|
|
512
|
+
node.depVersion = sig.__v ?? Number.NaN;
|
|
384
513
|
node.prevActive = active;
|
|
385
514
|
sig.__activeNode = node;
|
|
386
515
|
linkSub(sub, node);
|
|
@@ -399,9 +528,10 @@ function cleanup(subscriber) {
|
|
|
399
528
|
node = next;
|
|
400
529
|
}
|
|
401
530
|
}
|
|
402
|
-
var maxSubscriberRepeats =
|
|
531
|
+
var maxSubscriberRepeats = 1e3;
|
|
403
532
|
var maxDrainIterations = 1e6;
|
|
404
533
|
var drainEpoch = 0;
|
|
534
|
+
var quarantined = /* @__PURE__ */ new Set();
|
|
405
535
|
function setMaxSubscriberRepeats(n) {
|
|
406
536
|
const prev = maxSubscriberRepeats;
|
|
407
537
|
if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
|
|
@@ -423,19 +553,21 @@ function tickRepeat(sub) {
|
|
|
423
553
|
return s._runs > maxSubscriberRepeats;
|
|
424
554
|
}
|
|
425
555
|
function cycleError(sub) {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
`
|
|
430
|
-
)
|
|
431
|
-
|
|
556
|
+
const name = sub.__name ?? "<unnamed>";
|
|
557
|
+
reportError(
|
|
558
|
+
new Error(
|
|
559
|
+
`subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. This subscriber is quarantined for the rest of this update; other pending work still runs.`
|
|
560
|
+
),
|
|
561
|
+
{ phase: "scheduler", name }
|
|
562
|
+
);
|
|
432
563
|
}
|
|
433
564
|
function absoluteDrainError() {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
`
|
|
437
|
-
)
|
|
438
|
-
|
|
565
|
+
reportError(
|
|
566
|
+
new Error(
|
|
567
|
+
`Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
|
|
568
|
+
),
|
|
569
|
+
{ phase: "scheduler" }
|
|
570
|
+
);
|
|
439
571
|
}
|
|
440
572
|
function drainQueue() {
|
|
441
573
|
let i = 0;
|
|
@@ -445,11 +577,14 @@ function drainQueue() {
|
|
|
445
577
|
break;
|
|
446
578
|
}
|
|
447
579
|
const sub = pendingQueue[i++];
|
|
580
|
+
pendingSet.delete(sub);
|
|
581
|
+
if (quarantined.size > 0 && quarantined.has(sub)) continue;
|
|
582
|
+
if (sub._hasComputedDep === true && !depsChanged(sub)) continue;
|
|
448
583
|
if (tickRepeat(sub)) {
|
|
449
584
|
cycleError(sub);
|
|
450
|
-
|
|
585
|
+
quarantined.add(sub);
|
|
586
|
+
continue;
|
|
451
587
|
}
|
|
452
|
-
pendingSet.delete(sub);
|
|
453
588
|
safeInvoke(sub);
|
|
454
589
|
}
|
|
455
590
|
}
|
|
@@ -464,6 +599,7 @@ function drainNotificationQueue() {
|
|
|
464
599
|
if (notifyDepth === 0) {
|
|
465
600
|
pendingQueue.length = 0;
|
|
466
601
|
pendingSet.clear();
|
|
602
|
+
if (quarantined.size > 0) quarantined.clear();
|
|
467
603
|
}
|
|
468
604
|
}
|
|
469
605
|
}
|
|
@@ -557,6 +693,7 @@ function notifySubscribers(signal2) {
|
|
|
557
693
|
if (notifyDepth === 0) {
|
|
558
694
|
pendingQueue.length = 0;
|
|
559
695
|
pendingSet.clear();
|
|
696
|
+
if (quarantined.size > 0) quarantined.clear();
|
|
560
697
|
}
|
|
561
698
|
}
|
|
562
699
|
}
|
|
@@ -583,14 +720,14 @@ function forEachSubscriber(signal2, visit) {
|
|
|
583
720
|
}
|
|
584
721
|
|
|
585
722
|
// src/reactivity/track.ts
|
|
586
|
-
var
|
|
587
|
-
var _runtimeVersion = true ? "
|
|
723
|
+
var _isDev3 = isDev();
|
|
724
|
+
var _runtimeVersion = true ? "4.0.0" : "dev";
|
|
588
725
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
589
726
|
function resolveReactiveApi() {
|
|
590
727
|
const g = globalThis;
|
|
591
728
|
const existing = g[REGISTRY_KEY];
|
|
592
729
|
if (existing) {
|
|
593
|
-
if (
|
|
730
|
+
if (_isDev3 && !existing.__dupWarned) {
|
|
594
731
|
existing.__dupWarned = true;
|
|
595
732
|
devWarn(
|
|
596
733
|
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
|
|
@@ -675,6 +812,21 @@ function derived(getter, options) {
|
|
|
675
812
|
}, markDirty);
|
|
676
813
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
677
814
|
let evaluating = false;
|
|
815
|
+
const validate = () => {
|
|
816
|
+
if (!cs._d) return;
|
|
817
|
+
const oldValue = cs._v;
|
|
818
|
+
evaluating = true;
|
|
819
|
+
try {
|
|
820
|
+
retrack2(recompute, markDirty);
|
|
821
|
+
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
822
|
+
} finally {
|
|
823
|
+
evaluating = false;
|
|
824
|
+
}
|
|
825
|
+
if (hook && !Object.is(oldValue, cs._v)) {
|
|
826
|
+
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
cs._validate = validate;
|
|
678
830
|
function computedGetter() {
|
|
679
831
|
if (evaluating) {
|
|
680
832
|
throw new Error(
|
|
@@ -682,32 +834,11 @@ function derived(getter, options) {
|
|
|
682
834
|
);
|
|
683
835
|
}
|
|
684
836
|
if (isTrackingSuspended2()) {
|
|
685
|
-
if (cs._d)
|
|
686
|
-
const prev = cs._v;
|
|
687
|
-
evaluating = true;
|
|
688
|
-
try {
|
|
689
|
-
retrack2(recompute, markDirty);
|
|
690
|
-
if (!Object.is(prev, cs._v)) cs.__v++;
|
|
691
|
-
} finally {
|
|
692
|
-
evaluating = false;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
837
|
+
if (cs._d) validate();
|
|
695
838
|
return cs._v;
|
|
696
839
|
}
|
|
840
|
+
if (cs._d) validate();
|
|
697
841
|
recordDependency2(cs);
|
|
698
|
-
if (cs._d) {
|
|
699
|
-
const oldValue = cs._v;
|
|
700
|
-
evaluating = true;
|
|
701
|
-
try {
|
|
702
|
-
retrack2(recompute, markDirty);
|
|
703
|
-
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
704
|
-
} finally {
|
|
705
|
-
evaluating = false;
|
|
706
|
-
}
|
|
707
|
-
if (hook && oldValue !== cs._v) {
|
|
708
|
-
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
842
|
return cs._v;
|
|
712
843
|
}
|
|
713
844
|
if (debugName) {
|
|
@@ -729,20 +860,24 @@ function detectSSRShared() {
|
|
|
729
860
|
const getBuiltin = process.getBuiltinModule;
|
|
730
861
|
if (typeof getBuiltin === "function") {
|
|
731
862
|
mod = getBuiltin("node:async_hooks");
|
|
732
|
-
} else {
|
|
733
|
-
|
|
734
|
-
if (req) mod = req("node:async_hooks");
|
|
863
|
+
} else if (typeof require === "function") {
|
|
864
|
+
mod = require("async_hooks");
|
|
735
865
|
}
|
|
736
866
|
if (mod) detected = new mod.AsyncLocalStorage();
|
|
737
867
|
}
|
|
738
868
|
} catch {
|
|
739
869
|
detected = null;
|
|
740
870
|
}
|
|
741
|
-
return {
|
|
871
|
+
return {
|
|
872
|
+
als: detected,
|
|
873
|
+
fallbackStore: { ssr: false, suspenseIdCounter: 0, locale: void 0 },
|
|
874
|
+
fallbackDepth: 0
|
|
875
|
+
};
|
|
742
876
|
}
|
|
743
877
|
var _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
|
|
744
878
|
var als = _shared.als;
|
|
745
879
|
var fallbackStore = _shared.fallbackStore;
|
|
880
|
+
_shared.fallbackDepth ?? (_shared.fallbackDepth = 0);
|
|
746
881
|
function getSSRStore() {
|
|
747
882
|
if (als) {
|
|
748
883
|
const s = als.getStore();
|
|
@@ -765,7 +900,7 @@ function flushUserCleanups(ctx) {
|
|
|
765
900
|
try {
|
|
766
901
|
list[i]();
|
|
767
902
|
} catch (err) {
|
|
768
|
-
|
|
903
|
+
reportError(err, { phase: "cleanup" });
|
|
769
904
|
}
|
|
770
905
|
}
|
|
771
906
|
}
|
|
@@ -778,11 +913,12 @@ function drainReruns(ctx) {
|
|
|
778
913
|
} while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
|
|
779
914
|
if (ctx.rerunPending) {
|
|
780
915
|
ctx.rerunPending = false;
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
`
|
|
784
|
-
)
|
|
785
|
-
|
|
916
|
+
reportError(
|
|
917
|
+
new Error(
|
|
918
|
+
`effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
919
|
+
),
|
|
920
|
+
{ phase: "effect" }
|
|
921
|
+
);
|
|
786
922
|
}
|
|
787
923
|
}
|
|
788
924
|
function disposeEffect(ctx) {
|
|
@@ -859,6 +995,8 @@ function effect(effectFn, options) {
|
|
|
859
995
|
sub.depsTail = null;
|
|
860
996
|
sub._epoch = 0;
|
|
861
997
|
sub._structDirty = false;
|
|
998
|
+
sub._hasComputedDep = false;
|
|
999
|
+
sub._errorPhase = "effect";
|
|
862
1000
|
sub._runEpoch = 0;
|
|
863
1001
|
sub._runs = 0;
|
|
864
1002
|
ctx.subscriber = sub;
|
|
@@ -927,70 +1065,72 @@ var isBatching = API2.isBatching;
|
|
|
927
1065
|
|
|
928
1066
|
// src/core/signals/signal.ts
|
|
929
1067
|
var _g2 = globalThis;
|
|
930
|
-
var
|
|
1068
|
+
var _isDev4 = isDev();
|
|
931
1069
|
function signal(initial, options) {
|
|
932
|
-
const
|
|
1070
|
+
const state2 = {
|
|
933
1071
|
value: initial,
|
|
934
1072
|
__v: 0,
|
|
935
1073
|
__sc: 0,
|
|
936
1074
|
subsHead: null,
|
|
937
1075
|
subsTail: null,
|
|
938
1076
|
__activeNode: null,
|
|
939
|
-
__name: void 0
|
|
1077
|
+
__name: void 0,
|
|
1078
|
+
_d: false,
|
|
1079
|
+
_validate: void 0
|
|
940
1080
|
};
|
|
941
|
-
const debugName =
|
|
1081
|
+
const debugName = _isDev4 ? options?.name : void 0;
|
|
942
1082
|
const equalsFn = options?.equals;
|
|
943
|
-
if (debugName)
|
|
1083
|
+
if (debugName) state2.__name = debugName;
|
|
944
1084
|
function get() {
|
|
945
|
-
recordDependency2(
|
|
946
|
-
return
|
|
1085
|
+
recordDependency2(state2);
|
|
1086
|
+
return state2.value;
|
|
947
1087
|
}
|
|
948
|
-
get.__signal =
|
|
1088
|
+
get.__signal = state2;
|
|
949
1089
|
if (debugName) get.__name = debugName;
|
|
950
1090
|
let set;
|
|
951
1091
|
if (equalsFn) {
|
|
952
1092
|
set = (next) => {
|
|
953
|
-
const prev =
|
|
1093
|
+
const prev = state2.value;
|
|
954
1094
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
955
1095
|
if (equalsFn(prev, newValue)) return;
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
if (
|
|
1096
|
+
state2.value = newValue;
|
|
1097
|
+
state2.__v++;
|
|
1098
|
+
if (_isDev4) {
|
|
959
1099
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
960
|
-
if (hook) hook.emit("signal:update", { signal:
|
|
1100
|
+
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
961
1101
|
}
|
|
962
|
-
if (!enqueueBatchedSignal(
|
|
963
|
-
notifySubscribers2(
|
|
1102
|
+
if (!enqueueBatchedSignal(state2)) {
|
|
1103
|
+
notifySubscribers2(state2);
|
|
964
1104
|
}
|
|
965
1105
|
};
|
|
966
|
-
} else if (
|
|
1106
|
+
} else if (_isDev4) {
|
|
967
1107
|
set = (next) => {
|
|
968
|
-
const prev =
|
|
1108
|
+
const prev = state2.value;
|
|
969
1109
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
970
1110
|
if (Object.is(newValue, prev)) return;
|
|
971
|
-
|
|
972
|
-
|
|
1111
|
+
state2.value = newValue;
|
|
1112
|
+
state2.__v++;
|
|
973
1113
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
974
|
-
if (hook) hook.emit("signal:update", { signal:
|
|
975
|
-
if (!enqueueBatchedSignal(
|
|
976
|
-
notifySubscribers2(
|
|
1114
|
+
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
1115
|
+
if (!enqueueBatchedSignal(state2)) {
|
|
1116
|
+
notifySubscribers2(state2);
|
|
977
1117
|
}
|
|
978
1118
|
};
|
|
979
1119
|
} else {
|
|
980
1120
|
set = (next) => {
|
|
981
|
-
const prev =
|
|
1121
|
+
const prev = state2.value;
|
|
982
1122
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
983
1123
|
if (Object.is(newValue, prev)) return;
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
if (!enqueueBatchedSignal(
|
|
987
|
-
notifySubscribers2(
|
|
1124
|
+
state2.value = newValue;
|
|
1125
|
+
state2.__v++;
|
|
1126
|
+
if (!enqueueBatchedSignal(state2)) {
|
|
1127
|
+
notifySubscribers2(state2);
|
|
988
1128
|
}
|
|
989
1129
|
};
|
|
990
1130
|
}
|
|
991
|
-
if (
|
|
1131
|
+
if (_isDev4) {
|
|
992
1132
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
993
|
-
if (hook) hook.emit("signal:create", { signal:
|
|
1133
|
+
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
994
1134
|
}
|
|
995
1135
|
return [get, set];
|
|
996
1136
|
}
|
|
@@ -1088,6 +1228,8 @@ function bindField(field, extras) {
|
|
|
1088
1228
|
}
|
|
1089
1229
|
};
|
|
1090
1230
|
return {
|
|
1231
|
+
// The field's own getter, no longer widened to `unknown` — that widening is
|
|
1232
|
+
// what forced every consumer to cast. (TYPE-010)
|
|
1091
1233
|
value: field.value,
|
|
1092
1234
|
on: mergedOn,
|
|
1093
1235
|
onElement,
|
|
@@ -1891,21 +2033,169 @@ function sanitizeCSS(css) {
|
|
|
1891
2033
|
sanitized = sanitized.replace(/behavior\s*:[^;]+;/gi, "/* behavior removed */");
|
|
1892
2034
|
return sanitized;
|
|
1893
2035
|
}
|
|
2036
|
+
function firstCompoundEnd(selector) {
|
|
2037
|
+
let parens = 0;
|
|
2038
|
+
let brackets = 0;
|
|
2039
|
+
let quote = null;
|
|
2040
|
+
for (let i = 0; i < selector.length; i++) {
|
|
2041
|
+
const ch = selector[i];
|
|
2042
|
+
if (quote) {
|
|
2043
|
+
if (ch === "\\") i++;
|
|
2044
|
+
else if (ch === quote) quote = null;
|
|
2045
|
+
continue;
|
|
2046
|
+
}
|
|
2047
|
+
if (ch === '"' || ch === "'") {
|
|
2048
|
+
quote = ch;
|
|
2049
|
+
continue;
|
|
2050
|
+
}
|
|
2051
|
+
if (ch === "\\") {
|
|
2052
|
+
i++;
|
|
2053
|
+
continue;
|
|
2054
|
+
}
|
|
2055
|
+
if (ch === "(") parens++;
|
|
2056
|
+
else if (ch === ")") parens--;
|
|
2057
|
+
else if (ch === "[") brackets++;
|
|
2058
|
+
else if (ch === "]") brackets--;
|
|
2059
|
+
if (parens > 0 || brackets > 0) continue;
|
|
2060
|
+
if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") return i;
|
|
2061
|
+
if (ch === ">" || ch === "+" || ch === "~") return i;
|
|
2062
|
+
if (ch === ":" && selector[i + 1] === ":") return i;
|
|
2063
|
+
}
|
|
2064
|
+
return selector.length;
|
|
2065
|
+
}
|
|
2066
|
+
function scopeSelector(selector, attr) {
|
|
2067
|
+
const end = firstCompoundEnd(selector);
|
|
2068
|
+
const selfForm = `${selector.slice(0, end)}[${attr}]${selector.slice(end)}`;
|
|
2069
|
+
const descendantForm = `[${attr}] ${selector}`;
|
|
2070
|
+
return `${descendantForm}, ${selfForm}`;
|
|
2071
|
+
}
|
|
2072
|
+
function skipNonCode(text, i) {
|
|
2073
|
+
const ch = text[i];
|
|
2074
|
+
if (ch === "\\") return i + 2;
|
|
2075
|
+
if (ch === '"' || ch === "'") {
|
|
2076
|
+
let j = i + 1;
|
|
2077
|
+
while (j < text.length) {
|
|
2078
|
+
if (text[j] === "\\") {
|
|
2079
|
+
j += 2;
|
|
2080
|
+
continue;
|
|
2081
|
+
}
|
|
2082
|
+
if (text[j] === ch) return j + 1;
|
|
2083
|
+
j++;
|
|
2084
|
+
}
|
|
2085
|
+
return text.length;
|
|
2086
|
+
}
|
|
2087
|
+
if (ch === "/" && text[i + 1] === "*") {
|
|
2088
|
+
const end = text.indexOf("*/", i + 2);
|
|
2089
|
+
return end === -1 ? text.length : end + 2;
|
|
2090
|
+
}
|
|
2091
|
+
return -1;
|
|
2092
|
+
}
|
|
2093
|
+
function splitSelectorList(prelude) {
|
|
2094
|
+
const parts = [];
|
|
2095
|
+
let parens = 0;
|
|
2096
|
+
let brackets = 0;
|
|
2097
|
+
let start = 0;
|
|
2098
|
+
for (let i = 0; i < prelude.length; i++) {
|
|
2099
|
+
const skip = skipNonCode(prelude, i);
|
|
2100
|
+
if (skip !== -1) {
|
|
2101
|
+
i = skip - 1;
|
|
2102
|
+
continue;
|
|
2103
|
+
}
|
|
2104
|
+
const ch = prelude[i];
|
|
2105
|
+
if (ch === "(") parens++;
|
|
2106
|
+
else if (ch === ")") parens--;
|
|
2107
|
+
else if (ch === "[") brackets++;
|
|
2108
|
+
else if (ch === "]") brackets--;
|
|
2109
|
+
else if (ch === "," && parens === 0 && brackets === 0) {
|
|
2110
|
+
parts.push(prelude.slice(start, i));
|
|
2111
|
+
start = i + 1;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
parts.push(prelude.slice(start));
|
|
2115
|
+
return parts;
|
|
2116
|
+
}
|
|
2117
|
+
function findBlockEnd(css, openBrace) {
|
|
2118
|
+
let depth = 0;
|
|
2119
|
+
for (let i = openBrace; i < css.length; i++) {
|
|
2120
|
+
const skip = skipNonCode(css, i);
|
|
2121
|
+
if (skip !== -1) {
|
|
2122
|
+
i = skip - 1;
|
|
2123
|
+
continue;
|
|
2124
|
+
}
|
|
2125
|
+
const ch = css[i];
|
|
2126
|
+
if (ch === "{") depth++;
|
|
2127
|
+
else if (ch === "}") {
|
|
2128
|
+
depth--;
|
|
2129
|
+
if (depth === 0) return i;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
return css.length;
|
|
2133
|
+
}
|
|
2134
|
+
var NESTED_AT_RULE = /^@(media|supports|layer|container|scope|document)\b/i;
|
|
2135
|
+
function scopeStylesheet(css, attr) {
|
|
2136
|
+
let out = "";
|
|
2137
|
+
let preludeStart = 0;
|
|
2138
|
+
let parens = 0;
|
|
2139
|
+
let brackets = 0;
|
|
2140
|
+
let i = 0;
|
|
2141
|
+
while (i < css.length) {
|
|
2142
|
+
const skip = skipNonCode(css, i);
|
|
2143
|
+
if (skip !== -1) {
|
|
2144
|
+
i = skip;
|
|
2145
|
+
continue;
|
|
2146
|
+
}
|
|
2147
|
+
const ch = css[i];
|
|
2148
|
+
if (ch === "(") {
|
|
2149
|
+
parens++;
|
|
2150
|
+
i++;
|
|
2151
|
+
continue;
|
|
2152
|
+
}
|
|
2153
|
+
if (ch === ")") {
|
|
2154
|
+
parens--;
|
|
2155
|
+
i++;
|
|
2156
|
+
continue;
|
|
2157
|
+
}
|
|
2158
|
+
if (ch === "[") {
|
|
2159
|
+
brackets++;
|
|
2160
|
+
i++;
|
|
2161
|
+
continue;
|
|
2162
|
+
}
|
|
2163
|
+
if (ch === "]") {
|
|
2164
|
+
brackets--;
|
|
2165
|
+
i++;
|
|
2166
|
+
continue;
|
|
2167
|
+
}
|
|
2168
|
+
if (ch === "{" && parens === 0 && brackets === 0) {
|
|
2169
|
+
const prelude = css.slice(preludeStart, i);
|
|
2170
|
+
const bodyEnd = findBlockEnd(css, i);
|
|
2171
|
+
const body = css.slice(i + 1, bodyEnd);
|
|
2172
|
+
const trimmed = prelude.trim();
|
|
2173
|
+
const lead = prelude.slice(0, prelude.length - prelude.trimStart().length);
|
|
2174
|
+
if (trimmed === "") {
|
|
2175
|
+
out += `${prelude}{${body}}`;
|
|
2176
|
+
} else if (trimmed.startsWith("@")) {
|
|
2177
|
+
out += NESTED_AT_RULE.test(trimmed) ? `${prelude}{${scopeStylesheet(body, attr)}}` : `${prelude}{${body}}`;
|
|
2178
|
+
} else {
|
|
2179
|
+
const scoped = splitSelectorList(trimmed).map((part) => {
|
|
2180
|
+
const selector = part.trim();
|
|
2181
|
+
return selector ? scopeSelector(selector, attr) : part;
|
|
2182
|
+
}).join(", ");
|
|
2183
|
+
out += `${lead}${scoped}{${body}}`;
|
|
2184
|
+
}
|
|
2185
|
+
i = bodyEnd + 1;
|
|
2186
|
+
preludeStart = i;
|
|
2187
|
+
continue;
|
|
2188
|
+
}
|
|
2189
|
+
i++;
|
|
2190
|
+
}
|
|
2191
|
+
out += css.slice(preludeStart);
|
|
2192
|
+
return out;
|
|
2193
|
+
}
|
|
1894
2194
|
function scopedStyle(css) {
|
|
1895
2195
|
const id = `sibu-s${_scope.n++}`;
|
|
1896
2196
|
const attr = `data-${id}`;
|
|
1897
2197
|
const safeCss = sanitizeCSS(css);
|
|
1898
|
-
const scopedCSS = safeCss
|
|
1899
|
-
const trimmed = selector.trim();
|
|
1900
|
-
if (trimmed.startsWith("@") || trimmed.startsWith("from") || trimmed.startsWith("to") || /^\d+%$/.test(trimmed)) {
|
|
1901
|
-
return match;
|
|
1902
|
-
}
|
|
1903
|
-
const pseudoIdx = trimmed.indexOf("::");
|
|
1904
|
-
if (pseudoIdx >= 0) {
|
|
1905
|
-
return `${trimmed.slice(0, pseudoIdx)}[${attr}]${trimmed.slice(pseudoIdx)}${delimiter}`;
|
|
1906
|
-
}
|
|
1907
|
-
return `${trimmed}[${attr}]${delimiter}`;
|
|
1908
|
-
});
|
|
2198
|
+
const scopedCSS = scopeStylesheet(safeCss, attr);
|
|
1909
2199
|
if (typeof document !== "undefined") {
|
|
1910
2200
|
const styleEl = document.createElement("style");
|
|
1911
2201
|
styleEl.setAttribute("data-sibu-scope", id);
|
|
@@ -1921,18 +2211,10 @@ function withScopedStyle(css, component) {
|
|
|
1921
2211
|
style = scopedStyle(css);
|
|
1922
2212
|
}
|
|
1923
2213
|
const el = component(props);
|
|
1924
|
-
|
|
2214
|
+
el.setAttribute(style.attr, "");
|
|
1925
2215
|
return el;
|
|
1926
2216
|
};
|
|
1927
2217
|
}
|
|
1928
|
-
function applyScopeRecursive(element, attr) {
|
|
1929
|
-
element.setAttribute(attr, "");
|
|
1930
|
-
for (const child of Array.from(element.children)) {
|
|
1931
|
-
if (child instanceof HTMLElement) {
|
|
1932
|
-
applyScopeRecursive(child, attr);
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
2218
|
function removeScopedStyle(scopeId) {
|
|
1937
2219
|
const el = document.head.querySelector(`style[data-sibu-scope="${scopeId}"]`);
|
|
1938
2220
|
if (el) el.remove();
|
|
@@ -1948,10 +2230,12 @@ function isEventHandlerAttr(name) {
|
|
|
1948
2230
|
return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
|
|
1949
2231
|
}
|
|
1950
2232
|
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
2233
|
+
var OUTER_TRIM = /^[\x00-\x20\x7f-\x9f]+|[\x00-\x20\x7f-\x9f]+$/g;
|
|
1951
2234
|
function sanitizeUrl(url) {
|
|
1952
|
-
const
|
|
1953
|
-
if (!
|
|
1954
|
-
const
|
|
2235
|
+
const probe = stripControlChars(url).trim();
|
|
2236
|
+
if (!probe) return "";
|
|
2237
|
+
const output = url.replace(OUTER_TRIM, "");
|
|
2238
|
+
const lower = probe.toLowerCase();
|
|
1955
2239
|
let schemeEnd = -1;
|
|
1956
2240
|
for (let i = 0; i < lower.length; i++) {
|
|
1957
2241
|
const ch = lower.charCodeAt(i);
|
|
@@ -1961,12 +2245,13 @@ function sanitizeUrl(url) {
|
|
|
1961
2245
|
}
|
|
1962
2246
|
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
1963
2247
|
}
|
|
1964
|
-
if (schemeEnd === -1) return
|
|
2248
|
+
if (schemeEnd === -1) return output;
|
|
1965
2249
|
const scheme = lower.slice(0, schemeEnd + 1);
|
|
1966
|
-
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return
|
|
2250
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return output;
|
|
1967
2251
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
1968
|
-
return
|
|
2252
|
+
return output;
|
|
1969
2253
|
}
|
|
2254
|
+
var SRCSET_DESCRIPTOR = /^\s+\d+(\.\d+)?[wx]$/;
|
|
1970
2255
|
function sanitizeSrcset(value) {
|
|
1971
2256
|
const parts = value.split(",");
|
|
1972
2257
|
const out = [];
|
|
@@ -1975,12 +2260,91 @@ function sanitizeSrcset(value) {
|
|
|
1975
2260
|
if (!part) continue;
|
|
1976
2261
|
const m = part.match(/^(\S+)(\s+.+)?$/);
|
|
1977
2262
|
if (!m) continue;
|
|
2263
|
+
if (m[2] !== void 0 && !SRCSET_DESCRIPTOR.test(m[2])) continue;
|
|
1978
2264
|
const safe = sanitizeUrl(m[1]);
|
|
1979
2265
|
if (!safe) continue;
|
|
1980
2266
|
out.push(m[2] ? `${safe}${m[2]}` : safe);
|
|
1981
2267
|
}
|
|
1982
2268
|
return out.join(", ");
|
|
1983
2269
|
}
|
|
2270
|
+
var CSS_DANGER_GATE = /[(:@\\]/;
|
|
2271
|
+
function isCssWhitespace(ch) {
|
|
2272
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
2273
|
+
}
|
|
2274
|
+
function isHexDigit(ch) {
|
|
2275
|
+
return ch >= "0" && ch <= "9" || ch >= "a" && ch <= "f" || ch >= "A" && ch <= "F";
|
|
2276
|
+
}
|
|
2277
|
+
function decodeCssEscapes2(value) {
|
|
2278
|
+
let out = "";
|
|
2279
|
+
for (let i = 0; i < value.length; i++) {
|
|
2280
|
+
const ch = value[i];
|
|
2281
|
+
if (ch !== "\\") {
|
|
2282
|
+
out += ch;
|
|
2283
|
+
continue;
|
|
2284
|
+
}
|
|
2285
|
+
if (i + 1 >= value.length) break;
|
|
2286
|
+
const next = value[i + 1];
|
|
2287
|
+
if (next === "\n" || next === "\f") {
|
|
2288
|
+
i += 1;
|
|
2289
|
+
continue;
|
|
2290
|
+
}
|
|
2291
|
+
if (next === "\r") {
|
|
2292
|
+
i += value[i + 2] === "\n" ? 2 : 1;
|
|
2293
|
+
continue;
|
|
2294
|
+
}
|
|
2295
|
+
if (isHexDigit(next)) {
|
|
2296
|
+
let hex = "";
|
|
2297
|
+
let j = i + 1;
|
|
2298
|
+
while (j < value.length && hex.length < 6 && isHexDigit(value[j])) {
|
|
2299
|
+
hex += value[j];
|
|
2300
|
+
j++;
|
|
2301
|
+
}
|
|
2302
|
+
if (j < value.length && isCssWhitespace(value[j])) {
|
|
2303
|
+
j += value[j] === "\r" && value[j + 1] === "\n" ? 2 : 1;
|
|
2304
|
+
}
|
|
2305
|
+
const code = Number.parseInt(hex, 16);
|
|
2306
|
+
const invalid = code === 0 || code > 1114111 || code >= 55296 && code <= 57343;
|
|
2307
|
+
out += invalid ? "\uFFFD" : String.fromCodePoint(code);
|
|
2308
|
+
i = j - 1;
|
|
2309
|
+
continue;
|
|
2310
|
+
}
|
|
2311
|
+
out += next;
|
|
2312
|
+
i += 1;
|
|
2313
|
+
}
|
|
2314
|
+
return out;
|
|
2315
|
+
}
|
|
2316
|
+
function sanitizeCSSValue(value) {
|
|
2317
|
+
if (!CSS_DANGER_GATE.test(value)) return value;
|
|
2318
|
+
const normalized = value.includes("\\") ? decodeCssEscapes2(value) : value;
|
|
2319
|
+
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
2320
|
+
if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("vbscript:") || lower.includes("-moz-binding") || lower.includes("behavior:") || lower.includes("@import") || lower.includes("image-set(") || lower.includes("filter:progid")) {
|
|
2321
|
+
return "";
|
|
2322
|
+
}
|
|
2323
|
+
return value;
|
|
2324
|
+
}
|
|
2325
|
+
function sanitizeStyleAttribute(cssText) {
|
|
2326
|
+
const input = String(cssText);
|
|
2327
|
+
if (input.trim() === "") return "";
|
|
2328
|
+
if (typeof document === "undefined") {
|
|
2329
|
+
return sanitizeCSSValue(input) === "" ? "" : input;
|
|
2330
|
+
}
|
|
2331
|
+
const probe = document.createElement("div");
|
|
2332
|
+
try {
|
|
2333
|
+
probe.style.cssText = input;
|
|
2334
|
+
} catch {
|
|
2335
|
+
return "";
|
|
2336
|
+
}
|
|
2337
|
+
const declarations = [];
|
|
2338
|
+
for (let i = 0; i < probe.style.length; i++) {
|
|
2339
|
+
const property = probe.style[i];
|
|
2340
|
+
const value = probe.style.getPropertyValue(property);
|
|
2341
|
+
if (sanitizeCSSValue(value) === "") continue;
|
|
2342
|
+
if (sanitizeCSSValue(`${property}:${value}`) === "") continue;
|
|
2343
|
+
const priority = probe.style.getPropertyPriority(property);
|
|
2344
|
+
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
2345
|
+
}
|
|
2346
|
+
return declarations.join("; ");
|
|
2347
|
+
}
|
|
1984
2348
|
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
1985
2349
|
"href",
|
|
1986
2350
|
"xlink:href",
|
|
@@ -1993,26 +2357,104 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
1993
2357
|
"background",
|
|
1994
2358
|
"srcset",
|
|
1995
2359
|
"ping",
|
|
1996
|
-
"data"
|
|
2360
|
+
"data",
|
|
2361
|
+
// `<html manifest>` is a URL sink too. It was carried only by the SSR
|
|
2362
|
+
// serializers' private copy of this set; folding that copy into this one would
|
|
2363
|
+
// otherwise have silently dropped its coverage.
|
|
2364
|
+
"manifest"
|
|
1997
2365
|
]);
|
|
2366
|
+
var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
2367
|
+
function isHtmlContentAttribute(name) {
|
|
2368
|
+
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
2369
|
+
}
|
|
1998
2370
|
function sanitizeAttributeString(attr, value) {
|
|
1999
2371
|
const lower = attr.toLowerCase();
|
|
2000
2372
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
2001
2373
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
2374
|
+
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
2002
2375
|
return value;
|
|
2003
2376
|
}
|
|
2004
2377
|
|
|
2005
|
-
// src/
|
|
2006
|
-
var
|
|
2378
|
+
// src/utils/setSafeAttribute.ts
|
|
2379
|
+
var _isDev5 = isDev();
|
|
2380
|
+
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
2381
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2382
|
+
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
2383
|
+
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
2384
|
+
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
2385
|
+
function isHtmlElement(el) {
|
|
2386
|
+
return el.namespaceURI === null || el.namespaceURI === HTML_NS;
|
|
2387
|
+
}
|
|
2007
2388
|
function setProp(el, key, val) {
|
|
2008
2389
|
el[key] = val;
|
|
2009
2390
|
}
|
|
2010
|
-
function
|
|
2011
|
-
if (
|
|
2012
|
-
|
|
2391
|
+
function namespaceFor(el, name) {
|
|
2392
|
+
if (el.namespaceURI !== SVG_NS) return null;
|
|
2393
|
+
const lower = name.toLowerCase();
|
|
2394
|
+
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
2395
|
+
if (lower.startsWith("xml:")) return XML_NS;
|
|
2396
|
+
return null;
|
|
2397
|
+
}
|
|
2398
|
+
function setSafeAttribute(el, name, value, options = {}) {
|
|
2399
|
+
const ns = namespaceFor(el, name);
|
|
2400
|
+
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
2401
|
+
if (isEventHandlerAttr(name)) {
|
|
2402
|
+
if (_isDev5) {
|
|
2013
2403
|
devWarn(
|
|
2014
|
-
|
|
2404
|
+
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
2015
2405
|
);
|
|
2406
|
+
}
|
|
2407
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
2408
|
+
else el.removeAttribute(name);
|
|
2409
|
+
return false;
|
|
2410
|
+
}
|
|
2411
|
+
if (value == null) {
|
|
2412
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
2413
|
+
else el.removeAttribute(name);
|
|
2414
|
+
return true;
|
|
2415
|
+
}
|
|
2416
|
+
if (isHtmlContentAttribute(name)) {
|
|
2417
|
+
if (_isDev5) {
|
|
2418
|
+
devWarn(
|
|
2419
|
+
`${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.`
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
2423
|
+
else el.removeAttribute(name);
|
|
2424
|
+
return false;
|
|
2425
|
+
}
|
|
2426
|
+
const html = isHtmlElement(el);
|
|
2427
|
+
const idlName = html ? name.toLowerCase() : name;
|
|
2428
|
+
if (typeof value === "boolean") {
|
|
2429
|
+
if (html && BOOLEAN_IDL_ATTRS.has(idlName) && idlName in el) {
|
|
2430
|
+
setProp(el, idlName, value);
|
|
2431
|
+
} else if (value) {
|
|
2432
|
+
if (ns) el.setAttributeNS(ns, name, "");
|
|
2433
|
+
else el.setAttribute(name, "");
|
|
2434
|
+
} else if (ns) {
|
|
2435
|
+
el.removeAttributeNS(ns, localName);
|
|
2436
|
+
} else {
|
|
2437
|
+
el.removeAttribute(name);
|
|
2438
|
+
}
|
|
2439
|
+
return true;
|
|
2440
|
+
}
|
|
2441
|
+
const str = String(value);
|
|
2442
|
+
if (options.syncValueProperty !== false && html && (idlName === "value" || idlName === "checked") && idlName in el) {
|
|
2443
|
+
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
2444
|
+
return true;
|
|
2445
|
+
}
|
|
2446
|
+
const safe = sanitizeAttributeString(name, str);
|
|
2447
|
+
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
2448
|
+
if (current === safe) return true;
|
|
2449
|
+
if (ns) el.setAttributeNS(ns, name, safe);
|
|
2450
|
+
else el.setAttribute(name, safe);
|
|
2451
|
+
return true;
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
// src/reactivity/bindAttribute.ts
|
|
2455
|
+
function bindAttribute(el, attr, getter) {
|
|
2456
|
+
if (isEventHandlerAttr(attr)) {
|
|
2457
|
+
setSafeAttribute(el, attr, "", { label: `bindAttribute("${attr}")` });
|
|
2016
2458
|
return () => {
|
|
2017
2459
|
};
|
|
2018
2460
|
}
|
|
@@ -2021,28 +2463,12 @@ function bindAttribute(el, attr, getter) {
|
|
|
2021
2463
|
try {
|
|
2022
2464
|
value = getter();
|
|
2023
2465
|
} catch (err) {
|
|
2024
|
-
|
|
2025
|
-
devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
2026
|
-
return;
|
|
2027
|
-
}
|
|
2028
|
-
if (typeof value === "boolean") {
|
|
2029
|
-
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
2030
|
-
setProp(el, attr, value);
|
|
2031
|
-
} else if (value) {
|
|
2032
|
-
el.setAttribute(attr, "");
|
|
2033
|
-
} else {
|
|
2034
|
-
el.removeAttribute(attr);
|
|
2035
|
-
}
|
|
2466
|
+
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
2036
2467
|
return;
|
|
2037
2468
|
}
|
|
2038
|
-
|
|
2039
|
-
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
2040
|
-
setProp(el, attr, attr === "checked" ? Boolean(value) : str);
|
|
2041
|
-
} else {
|
|
2042
|
-
el.setAttribute(attr, sanitizeAttributeString(attr, str));
|
|
2043
|
-
}
|
|
2469
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")` });
|
|
2044
2470
|
}
|
|
2045
|
-
return reactiveBinding2(commit);
|
|
2471
|
+
return reactiveBinding2(commit, el);
|
|
2046
2472
|
}
|
|
2047
2473
|
|
|
2048
2474
|
// src/ui/reactiveAttr.ts
|
|
@@ -2052,14 +2478,8 @@ function bindAttrs(el, attrs) {
|
|
|
2052
2478
|
if (typeof value === "function") {
|
|
2053
2479
|
const teardown = bindAttribute(el, attr, value);
|
|
2054
2480
|
teardowns.push(teardown);
|
|
2055
|
-
} else if (typeof value === "boolean") {
|
|
2056
|
-
if (value) {
|
|
2057
|
-
el.setAttribute(attr, "");
|
|
2058
|
-
} else {
|
|
2059
|
-
el.removeAttribute(attr);
|
|
2060
|
-
}
|
|
2061
2481
|
} else {
|
|
2062
|
-
el
|
|
2482
|
+
setSafeAttribute(el, attr, value, { label: "bindAttrs" });
|
|
2063
2483
|
}
|
|
2064
2484
|
}
|
|
2065
2485
|
return () => {
|
|
@@ -2070,11 +2490,7 @@ function bindAttrs(el, attrs) {
|
|
|
2070
2490
|
}
|
|
2071
2491
|
function bindBoolAttr(el, attr, getter) {
|
|
2072
2492
|
if (typeof getter !== "function") {
|
|
2073
|
-
|
|
2074
|
-
el.setAttribute(attr, "");
|
|
2075
|
-
} else {
|
|
2076
|
-
el.removeAttribute(attr);
|
|
2077
|
-
}
|
|
2493
|
+
setSafeAttribute(el, attr, getter, { label: "bindBoolAttr" });
|
|
2078
2494
|
return () => {
|
|
2079
2495
|
};
|
|
2080
2496
|
}
|
|
@@ -2086,11 +2502,7 @@ function bindBoolAttr(el, attr, getter) {
|
|
|
2086
2502
|
} catch {
|
|
2087
2503
|
return;
|
|
2088
2504
|
}
|
|
2089
|
-
|
|
2090
|
-
el.setAttribute(attr, "");
|
|
2091
|
-
} else {
|
|
2092
|
-
el.removeAttribute(attr);
|
|
2093
|
-
}
|
|
2505
|
+
setSafeAttribute(el, attr, Boolean(value), { label: "bindBoolAttr" });
|
|
2094
2506
|
}
|
|
2095
2507
|
const teardown = track2(commit);
|
|
2096
2508
|
return teardown;
|
|
@@ -2098,7 +2510,7 @@ function bindBoolAttr(el, attr, getter) {
|
|
|
2098
2510
|
function bindData(el, key, getter) {
|
|
2099
2511
|
const dataAttr = `data-${key}`;
|
|
2100
2512
|
if (typeof getter !== "function") {
|
|
2101
|
-
el
|
|
2513
|
+
setSafeAttribute(el, dataAttr, getter, { label: "bindData" });
|
|
2102
2514
|
return () => {
|
|
2103
2515
|
};
|
|
2104
2516
|
}
|
|
@@ -2238,31 +2650,58 @@ function infiniteScroll(options) {
|
|
|
2238
2650
|
const sentinelRef = { current: null };
|
|
2239
2651
|
let observer = null;
|
|
2240
2652
|
let disposed = false;
|
|
2653
|
+
let generation = 0;
|
|
2654
|
+
function safeHasMore() {
|
|
2655
|
+
try {
|
|
2656
|
+
return hasMore();
|
|
2657
|
+
} catch (err) {
|
|
2658
|
+
reportError(err, { phase: "async", name: "infiniteScroll(hasMore)" });
|
|
2659
|
+
return false;
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
function ownsAttachment(owner) {
|
|
2663
|
+
return !disposed && generation === owner.generation && observer === owner.observer && _current === owner.sentinel;
|
|
2664
|
+
}
|
|
2241
2665
|
function createObserver() {
|
|
2242
2666
|
if (typeof IntersectionObserver === "undefined") return;
|
|
2243
|
-
|
|
2667
|
+
let createdObserver;
|
|
2668
|
+
createdObserver = new IntersectionObserver(
|
|
2244
2669
|
(entries) => {
|
|
2245
2670
|
const entry = entries[0];
|
|
2246
|
-
if (entry?.isIntersecting
|
|
2247
|
-
|
|
2248
|
-
|
|
2671
|
+
if (!entry?.isIntersecting) return;
|
|
2672
|
+
const sentinel = _current;
|
|
2673
|
+
if (!sentinel) return;
|
|
2674
|
+
const owner = { generation, observer: createdObserver, sentinel };
|
|
2675
|
+
if (!ownsAttachment(owner) || loading()) return;
|
|
2676
|
+
const shouldLoad = safeHasMore();
|
|
2677
|
+
if (!shouldLoad || !ownsAttachment(owner)) return;
|
|
2678
|
+
void loadMore(owner);
|
|
2249
2679
|
},
|
|
2250
2680
|
{ threshold }
|
|
2251
2681
|
);
|
|
2682
|
+
observer = createdObserver;
|
|
2252
2683
|
if (sentinelRef.current) {
|
|
2253
|
-
|
|
2684
|
+
createdObserver.observe(sentinelRef.current);
|
|
2254
2685
|
}
|
|
2255
2686
|
}
|
|
2256
|
-
async function loadMore() {
|
|
2257
|
-
setLoading(true);
|
|
2687
|
+
async function loadMore(owner) {
|
|
2258
2688
|
try {
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2689
|
+
setLoading(true);
|
|
2690
|
+
if (!ownsAttachment(owner)) return;
|
|
2691
|
+
try {
|
|
2692
|
+
await onLoadMore();
|
|
2693
|
+
} catch (err) {
|
|
2694
|
+
reportError(err, { phase: "async", name: "infiniteScroll(onLoadMore)" });
|
|
2265
2695
|
}
|
|
2696
|
+
if (!ownsAttachment(owner)) return;
|
|
2697
|
+
setLoading(false);
|
|
2698
|
+
if (!ownsAttachment(owner)) return;
|
|
2699
|
+
const shouldContinue = safeHasMore();
|
|
2700
|
+
if (!shouldContinue || !ownsAttachment(owner)) return;
|
|
2701
|
+
owner.observer.unobserve(owner.sentinel);
|
|
2702
|
+
owner.observer.observe(owner.sentinel);
|
|
2703
|
+
} catch (err) {
|
|
2704
|
+
reportError(err, { phase: "async", name: "infiniteScroll(loadMore)" });
|
|
2266
2705
|
}
|
|
2267
2706
|
}
|
|
2268
2707
|
const originalRef = sentinelRef;
|
|
@@ -2272,7 +2711,10 @@ function infiniteScroll(options) {
|
|
|
2272
2711
|
return _current;
|
|
2273
2712
|
},
|
|
2274
2713
|
set(el) {
|
|
2714
|
+
if (el === _current) return;
|
|
2275
2715
|
_current = el;
|
|
2716
|
+
generation++;
|
|
2717
|
+
setLoading(false);
|
|
2276
2718
|
if (observer) {
|
|
2277
2719
|
observer.disconnect();
|
|
2278
2720
|
observer = null;
|
|
@@ -2285,10 +2727,12 @@ function infiniteScroll(options) {
|
|
|
2285
2727
|
});
|
|
2286
2728
|
function dispose2() {
|
|
2287
2729
|
disposed = true;
|
|
2730
|
+
generation++;
|
|
2288
2731
|
if (observer) {
|
|
2289
2732
|
observer.disconnect();
|
|
2290
2733
|
observer = null;
|
|
2291
2734
|
}
|
|
2735
|
+
setLoading(false);
|
|
2292
2736
|
}
|
|
2293
2737
|
return { sentinelRef: originalRef, loading, dispose: dispose2 };
|
|
2294
2738
|
}
|
|
@@ -2493,6 +2937,7 @@ function scrollLock() {
|
|
|
2493
2937
|
}
|
|
2494
2938
|
|
|
2495
2939
|
// src/platform/customElement.ts
|
|
2940
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2496
2941
|
function defineElement(name, component, options = {}) {
|
|
2497
2942
|
if (customElements.get(name)) return;
|
|
2498
2943
|
const observed = options.observedAttributes || [];
|
|
@@ -2521,11 +2966,8 @@ function defineElement(name, component, options = {}) {
|
|
|
2521
2966
|
}
|
|
2522
2967
|
}
|
|
2523
2968
|
_teardown() {
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
this._rendered = null;
|
|
2527
|
-
}
|
|
2528
|
-
this._root.replaceChildren();
|
|
2969
|
+
this._rendered = null;
|
|
2970
|
+
replaceChildrenSafely(this._root);
|
|
2529
2971
|
}
|
|
2530
2972
|
_render() {
|
|
2531
2973
|
this._teardown();
|
|
@@ -2550,14 +2992,13 @@ function defineElement(name, component, options = {}) {
|
|
|
2550
2992
|
customElements.define(name, SibuElement);
|
|
2551
2993
|
}
|
|
2552
2994
|
function svgElement(tag, props = {}, ...nodes) {
|
|
2553
|
-
const
|
|
2554
|
-
const el = document.createElementNS(SVG_NS, tag);
|
|
2995
|
+
const el = document.createElementNS(SVG_NS2, tag);
|
|
2555
2996
|
for (const [key, value] of Object.entries(props)) {
|
|
2556
2997
|
if (key === "nodes") continue;
|
|
2557
|
-
if (typeof value === "function" && key
|
|
2998
|
+
if (typeof value === "function" && isEventHandlerAttr(key)) {
|
|
2558
2999
|
el.addEventListener(key.slice(2).toLowerCase(), value);
|
|
2559
3000
|
} else if (value != null) {
|
|
2560
|
-
el
|
|
3001
|
+
setSafeAttribute(el, key, value, { label: "svgElement" });
|
|
2561
3002
|
}
|
|
2562
3003
|
}
|
|
2563
3004
|
for (const child of nodes) {
|