@askrjs/askr 0.0.3 → 0.0.4
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 +8 -5
- package/dist/chunk-64C7W2AE.js +43 -0
- package/dist/chunk-64C7W2AE.js.map +1 -0
- package/dist/chunk-6FLMH4EL.js +124 -0
- package/dist/chunk-6FLMH4EL.js.map +1 -0
- package/dist/{chunk-JHOGWTAW.js → chunk-FJUXFA72.js} +2 -2
- package/dist/chunk-FJUXFA72.js.map +1 -0
- package/dist/{chunk-H3NSVHA7.js → chunk-VRAEBIJ3.js} +7 -5
- package/dist/chunk-VRAEBIJ3.js.map +1 -0
- package/dist/chunk-WTFWRSHB.js +98 -0
- package/dist/chunk-WTFWRSHB.js.map +1 -0
- package/dist/chunk-XHKZGJE3.js +2907 -0
- package/dist/chunk-XHKZGJE3.js.map +1 -0
- package/dist/chunk-Z5ZSTLYF.js +420 -0
- package/dist/chunk-Z5ZSTLYF.js.map +1 -0
- package/dist/fx/index.cjs +1193 -0
- package/dist/fx/index.cjs.map +1 -0
- package/dist/fx/index.d.cts +186 -0
- package/dist/fx/index.d.ts +186 -0
- package/dist/fx/index.js +418 -0
- package/dist/fx/index.js.map +1 -0
- package/dist/index.cjs +1369 -2525
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -407
- package/dist/index.d.ts +74 -407
- package/dist/index.js +63 -803
- package/dist/index.js.map +1 -1
- package/dist/jsx/jsx-dev-runtime.cjs +1 -1
- package/dist/jsx/jsx-dev-runtime.cjs.map +1 -1
- package/dist/jsx/jsx-dev-runtime.d.cts +3 -2
- package/dist/jsx/jsx-dev-runtime.d.ts +3 -2
- package/dist/jsx/jsx-dev-runtime.js +1 -1
- package/dist/jsx/jsx-runtime.d.cts +2 -1
- package/dist/jsx/jsx-runtime.d.ts +2 -1
- package/dist/jsx/jsx-runtime.js +1 -1
- package/dist/{types-DLTViI21.d.cts → jsx-AzPM8gMS.d.cts} +6 -21
- package/dist/{types-DLTViI21.d.ts → jsx-AzPM8gMS.d.ts} +6 -21
- package/dist/{navigate-CZEUXFPM.js → navigate-LUVYHYZZ.js} +5 -4
- package/dist/resources/index.cjs +1200 -0
- package/dist/resources/index.cjs.map +1 -0
- package/dist/resources/index.d.cts +21 -0
- package/dist/resources/index.d.ts +21 -0
- package/dist/resources/index.js +278 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/{route-USEXGOBT.js → route-BCND6MPK.js} +4 -3
- package/dist/{chunk-2ONGHQ7Z.js → router/index.cjs} +775 -643
- package/dist/router/index.cjs.map +1 -0
- package/dist/router/index.d.cts +64 -0
- package/dist/router/index.d.ts +64 -0
- package/dist/router/index.js +49 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router-DaGtH1Sq.d.cts +36 -0
- package/dist/router-DaGtH1Sq.d.ts +36 -0
- package/dist/ssr/index.cjs +4059 -0
- package/dist/ssr/index.cjs.map +1 -0
- package/dist/ssr/index.d.cts +123 -0
- package/dist/ssr/index.d.ts +123 -0
- package/dist/{chunk-OFW6DFBM.js → ssr/index.js} +202 -252
- package/dist/ssr/index.js.map +1 -0
- package/dist/types-CZ5sWur5.d.cts +23 -0
- package/dist/types-CZHOAiC1.d.ts +23 -0
- package/package.json +19 -6
- package/src/jsx/types.ts +4 -17
- package/dist/chunk-2ONGHQ7Z.js.map +0 -1
- package/dist/chunk-H3NSVHA7.js.map +0 -1
- package/dist/chunk-JHOGWTAW.js.map +0 -1
- package/dist/chunk-OFW6DFBM.js.map +0 -1
- package/dist/ssr-QJ5NTQR6.js +0 -28
- package/dist/ssr-QJ5NTQR6.js.map +0 -1
- /package/dist/{navigate-CZEUXFPM.js.map → navigate-LUVYHYZZ.js.map} +0 -0
- /package/dist/{route-USEXGOBT.js.map → route-BCND6MPK.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -85,36 +85,11 @@ function isBulkCommitActive() {
|
|
|
85
85
|
function isSchedulerExecuting() {
|
|
86
86
|
return globalScheduler.isExecuting();
|
|
87
87
|
}
|
|
88
|
-
function scheduleEventHandler(handler) {
|
|
89
|
-
return (event) => {
|
|
90
|
-
globalScheduler.setInHandler(true);
|
|
91
|
-
try {
|
|
92
|
-
handler.call(null, event);
|
|
93
|
-
} catch (error) {
|
|
94
|
-
logger.error("[Askr] Event handler error:", error);
|
|
95
|
-
} finally {
|
|
96
|
-
globalScheduler.setInHandler(false);
|
|
97
|
-
const state2 = globalScheduler.getState();
|
|
98
|
-
if ((state2.queueLength ?? 0) > 0 && !state2.running) {
|
|
99
|
-
queueMicrotask(() => {
|
|
100
|
-
try {
|
|
101
|
-
if (!globalScheduler.isExecuting()) globalScheduler.flush();
|
|
102
|
-
} catch (err) {
|
|
103
|
-
setTimeout(() => {
|
|
104
|
-
throw err;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
88
|
var MAX_FLUSH_DEPTH, Scheduler, globalScheduler;
|
|
113
89
|
var init_scheduler = __esm({
|
|
114
90
|
"src/runtime/scheduler.ts"() {
|
|
115
91
|
"use strict";
|
|
116
92
|
init_invariant();
|
|
117
|
-
init_logger();
|
|
118
93
|
MAX_FLUSH_DEPTH = 50;
|
|
119
94
|
Scheduler = class {
|
|
120
95
|
constructor() {
|
|
@@ -136,9 +111,9 @@ var init_scheduler = __esm({
|
|
|
136
111
|
// Keep a lightweight taskCount for compatibility/diagnostics
|
|
137
112
|
this.taskCount = 0;
|
|
138
113
|
}
|
|
139
|
-
enqueue(
|
|
114
|
+
enqueue(task) {
|
|
140
115
|
assertSchedulingPrecondition(
|
|
141
|
-
typeof
|
|
116
|
+
typeof task === "function",
|
|
142
117
|
"enqueue() requires a function"
|
|
143
118
|
);
|
|
144
119
|
if (isBulkCommitActive() && !this.allowSyncProgress) {
|
|
@@ -149,7 +124,7 @@ var init_scheduler = __esm({
|
|
|
149
124
|
}
|
|
150
125
|
return;
|
|
151
126
|
}
|
|
152
|
-
this.q.push(
|
|
127
|
+
this.q.push(task);
|
|
153
128
|
this.taskCount++;
|
|
154
129
|
if (!this.running && !this.kickScheduled && !this.inHandler && !isBulkCommitActive()) {
|
|
155
130
|
this.kickScheduled = true;
|
|
@@ -190,10 +165,10 @@ var init_scheduler = __esm({
|
|
|
190
165
|
`[Scheduler] exceeded MAX_FLUSH_DEPTH (${MAX_FLUSH_DEPTH}). Likely infinite update loop.`
|
|
191
166
|
);
|
|
192
167
|
}
|
|
193
|
-
const
|
|
168
|
+
const task = this.q[this.head++];
|
|
194
169
|
try {
|
|
195
170
|
this.executionDepth++;
|
|
196
|
-
|
|
171
|
+
task();
|
|
197
172
|
this.executionDepth--;
|
|
198
173
|
} catch (err) {
|
|
199
174
|
if (this.executionDepth > 0) this.executionDepth = 0;
|
|
@@ -211,14 +186,10 @@ var init_scheduler = __esm({
|
|
|
211
186
|
this.head = 0;
|
|
212
187
|
} else if (this.head > 0) {
|
|
213
188
|
const remaining = this.q.length - this.head;
|
|
214
|
-
|
|
215
|
-
this.q = this.q
|
|
216
|
-
} else {
|
|
217
|
-
for (let i = 0; i < remaining; i++) {
|
|
218
|
-
this.q[i] = this.q[this.head + i];
|
|
219
|
-
}
|
|
220
|
-
this.q.length = remaining;
|
|
189
|
+
for (let i = 0; i < remaining; i++) {
|
|
190
|
+
this.q[i] = this.q[this.head + i];
|
|
221
191
|
}
|
|
192
|
+
this.q.length = remaining;
|
|
222
193
|
this.head = 0;
|
|
223
194
|
}
|
|
224
195
|
this.flushVersion++;
|
|
@@ -373,123 +344,15 @@ function withContext(frame, fn) {
|
|
|
373
344
|
currentContextFrame = oldFrame;
|
|
374
345
|
}
|
|
375
346
|
}
|
|
376
|
-
function withAsyncResourceContext(frame, fn) {
|
|
377
|
-
const oldFrame = currentAsyncResourceFrame;
|
|
378
|
-
currentAsyncResourceFrame = frame;
|
|
379
|
-
try {
|
|
380
|
-
return fn();
|
|
381
|
-
} finally {
|
|
382
|
-
currentAsyncResourceFrame = oldFrame;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
function defineContext(defaultValue) {
|
|
386
|
-
const key = /* @__PURE__ */ Symbol("AskrContext");
|
|
387
|
-
return {
|
|
388
|
-
key,
|
|
389
|
-
defaultValue,
|
|
390
|
-
Scope: (props) => {
|
|
391
|
-
const value = props.value;
|
|
392
|
-
return {
|
|
393
|
-
type: ContextScopeComponent,
|
|
394
|
-
props: { key, value, children: props.children }
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
function readContext(context) {
|
|
400
|
-
const frame = currentContextFrame || currentAsyncResourceFrame;
|
|
401
|
-
if (!frame) {
|
|
402
|
-
throw new Error(
|
|
403
|
-
"readContext() can only be called during component render or async resource execution. Ensure you are calling this from inside your component or resource function."
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
let current2 = frame;
|
|
407
|
-
while (current2) {
|
|
408
|
-
const values = current2.values;
|
|
409
|
-
if (values && values.has(context.key)) {
|
|
410
|
-
return values.get(context.key);
|
|
411
|
-
}
|
|
412
|
-
current2 = current2.parent;
|
|
413
|
-
}
|
|
414
|
-
return context.defaultValue;
|
|
415
|
-
}
|
|
416
|
-
function ContextScopeComponent(props) {
|
|
417
|
-
const key = props["key"];
|
|
418
|
-
const value = props["value"];
|
|
419
|
-
const children = props["children"];
|
|
420
|
-
const instance = getCurrentComponentInstance();
|
|
421
|
-
const parentFrame = (() => {
|
|
422
|
-
if (currentContextFrame) return currentContextFrame;
|
|
423
|
-
if (instance && instance.ownerFrame) return instance.ownerFrame;
|
|
424
|
-
return null;
|
|
425
|
-
})();
|
|
426
|
-
const newFrame = {
|
|
427
|
-
parent: parentFrame,
|
|
428
|
-
values: /* @__PURE__ */ new Map([[key, value]])
|
|
429
|
-
};
|
|
430
|
-
function createFunctionChildInvoker(fn, frame, owner) {
|
|
431
|
-
return {
|
|
432
|
-
type: ContextFunctionChildInvoker,
|
|
433
|
-
props: { fn, __frame: frame, __owner: owner }
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
if (Array.isArray(children)) {
|
|
437
|
-
return children.map((child) => {
|
|
438
|
-
if (typeof child === "function") {
|
|
439
|
-
return createFunctionChildInvoker(
|
|
440
|
-
child,
|
|
441
|
-
newFrame,
|
|
442
|
-
getCurrentComponentInstance()
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
return markWithFrame(child, newFrame);
|
|
446
|
-
});
|
|
447
|
-
} else if (typeof children === "function") {
|
|
448
|
-
return createFunctionChildInvoker(
|
|
449
|
-
children,
|
|
450
|
-
newFrame,
|
|
451
|
-
getCurrentComponentInstance()
|
|
452
|
-
);
|
|
453
|
-
} else if (children) {
|
|
454
|
-
return markWithFrame(children, newFrame);
|
|
455
|
-
}
|
|
456
|
-
return null;
|
|
457
|
-
}
|
|
458
|
-
function markWithFrame(node, frame) {
|
|
459
|
-
if (typeof node === "object" && node !== null) {
|
|
460
|
-
const obj = node;
|
|
461
|
-
obj[CONTEXT_FRAME_SYMBOL] = frame;
|
|
462
|
-
const children = obj.children;
|
|
463
|
-
if (Array.isArray(children)) {
|
|
464
|
-
for (let i = 0; i < children.length; i++) {
|
|
465
|
-
const child = children[i];
|
|
466
|
-
if (child) {
|
|
467
|
-
children[i] = markWithFrame(child, frame);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
} else if (children) {
|
|
471
|
-
obj.children = markWithFrame(children, frame);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
return node;
|
|
475
|
-
}
|
|
476
|
-
function ContextFunctionChildInvoker(props) {
|
|
477
|
-
const { fn, __frame } = props;
|
|
478
|
-
const res = withContext(__frame, () => fn());
|
|
479
|
-
if (res) return markWithFrame(res, __frame);
|
|
480
|
-
return null;
|
|
481
|
-
}
|
|
482
347
|
function getCurrentContextFrame() {
|
|
483
348
|
return currentContextFrame;
|
|
484
349
|
}
|
|
485
|
-
var CONTEXT_FRAME_SYMBOL, currentContextFrame
|
|
350
|
+
var CONTEXT_FRAME_SYMBOL, currentContextFrame;
|
|
486
351
|
var init_context = __esm({
|
|
487
352
|
"src/runtime/context.ts"() {
|
|
488
353
|
"use strict";
|
|
489
|
-
init_component();
|
|
490
354
|
CONTEXT_FRAME_SYMBOL = /* @__PURE__ */ Symbol("__tempoContextFrame__");
|
|
491
355
|
currentContextFrame = null;
|
|
492
|
-
currentAsyncResourceFrame = null;
|
|
493
356
|
}
|
|
494
357
|
});
|
|
495
358
|
|
|
@@ -555,172 +418,6 @@ var init_diag = __esm({
|
|
|
555
418
|
}
|
|
556
419
|
});
|
|
557
420
|
|
|
558
|
-
// src/runtime/dev-namespace.ts
|
|
559
|
-
function getDevNamespace() {
|
|
560
|
-
if (process.env.NODE_ENV === "production") return {};
|
|
561
|
-
try {
|
|
562
|
-
const g = globalThis;
|
|
563
|
-
if (!g.__ASKR__) g.__ASKR__ = {};
|
|
564
|
-
return g.__ASKR__;
|
|
565
|
-
} catch {
|
|
566
|
-
return {};
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
function setDevValue(key, value) {
|
|
570
|
-
if (process.env.NODE_ENV === "production") return;
|
|
571
|
-
try {
|
|
572
|
-
getDevNamespace()[key] = value;
|
|
573
|
-
} catch {
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
function getDevValue(key) {
|
|
577
|
-
if (process.env.NODE_ENV === "production") return void 0;
|
|
578
|
-
try {
|
|
579
|
-
return getDevNamespace()[key];
|
|
580
|
-
} catch {
|
|
581
|
-
return void 0;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
var init_dev_namespace = __esm({
|
|
585
|
-
"src/runtime/dev-namespace.ts"() {
|
|
586
|
-
"use strict";
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
// src/runtime/fastlane-shared.ts
|
|
591
|
-
function enterBulkCommit() {
|
|
592
|
-
_bulkCommitActive = true;
|
|
593
|
-
_appliedParents = /* @__PURE__ */ new WeakSet();
|
|
594
|
-
try {
|
|
595
|
-
const cleared = globalScheduler.clearPendingSyncTasks?.() ?? 0;
|
|
596
|
-
setDevValue("__ASKR_FASTLANE_CLEARED_TASKS", cleared);
|
|
597
|
-
} catch (err) {
|
|
598
|
-
if (process.env.NODE_ENV !== "production") throw err;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
function exitBulkCommit() {
|
|
602
|
-
_bulkCommitActive = false;
|
|
603
|
-
_appliedParents = null;
|
|
604
|
-
}
|
|
605
|
-
function isBulkCommitActive2() {
|
|
606
|
-
return _bulkCommitActive;
|
|
607
|
-
}
|
|
608
|
-
function markFastPathApplied(parent) {
|
|
609
|
-
if (!_appliedParents) return;
|
|
610
|
-
try {
|
|
611
|
-
_appliedParents.add(parent);
|
|
612
|
-
} catch (e) {
|
|
613
|
-
void e;
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
function isFastPathApplied(parent) {
|
|
617
|
-
return !!(_appliedParents && _appliedParents.has(parent));
|
|
618
|
-
}
|
|
619
|
-
var _bulkCommitActive, _appliedParents;
|
|
620
|
-
var init_fastlane_shared = __esm({
|
|
621
|
-
"src/runtime/fastlane-shared.ts"() {
|
|
622
|
-
"use strict";
|
|
623
|
-
init_scheduler();
|
|
624
|
-
init_dev_namespace();
|
|
625
|
-
_bulkCommitActive = false;
|
|
626
|
-
_appliedParents = null;
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
// src/renderer/types.ts
|
|
631
|
-
function _isDOMElement(node) {
|
|
632
|
-
return typeof node === "object" && node !== null && "type" in node;
|
|
633
|
-
}
|
|
634
|
-
var init_types = __esm({
|
|
635
|
-
"src/renderer/types.ts"() {
|
|
636
|
-
"use strict";
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
// src/renderer/cleanup.ts
|
|
641
|
-
function cleanupSingleInstance(node, errors, strict) {
|
|
642
|
-
const inst = node.__ASKR_INSTANCE;
|
|
643
|
-
if (!inst) return;
|
|
644
|
-
try {
|
|
645
|
-
cleanupComponent(inst);
|
|
646
|
-
} catch (err) {
|
|
647
|
-
if (strict) errors.push(err);
|
|
648
|
-
else logger.warn("[Askr] cleanupComponent failed:", err);
|
|
649
|
-
}
|
|
650
|
-
try {
|
|
651
|
-
delete node.__ASKR_INSTANCE;
|
|
652
|
-
} catch (e) {
|
|
653
|
-
if (strict) errors.push(e);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
function cleanupInstanceIfPresent(node, opts) {
|
|
657
|
-
if (!node || !(node instanceof Element)) return;
|
|
658
|
-
const errors = [];
|
|
659
|
-
const strict = opts?.strict ?? false;
|
|
660
|
-
try {
|
|
661
|
-
cleanupSingleInstance(node, errors, strict);
|
|
662
|
-
} catch (err) {
|
|
663
|
-
if (strict) errors.push(err);
|
|
664
|
-
else logger.warn("[Askr] cleanupInstanceIfPresent failed:", err);
|
|
665
|
-
}
|
|
666
|
-
try {
|
|
667
|
-
const descendants = node.querySelectorAll("*");
|
|
668
|
-
for (const d of Array.from(descendants)) {
|
|
669
|
-
try {
|
|
670
|
-
cleanupSingleInstance(d, errors, strict);
|
|
671
|
-
} catch (err) {
|
|
672
|
-
if (strict) errors.push(err);
|
|
673
|
-
else
|
|
674
|
-
logger.warn(
|
|
675
|
-
"[Askr] cleanupInstanceIfPresent descendant cleanup failed:",
|
|
676
|
-
err
|
|
677
|
-
);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
} catch (err) {
|
|
681
|
-
if (strict) errors.push(err);
|
|
682
|
-
else
|
|
683
|
-
logger.warn(
|
|
684
|
-
"[Askr] cleanupInstanceIfPresent descendant query failed:",
|
|
685
|
-
err
|
|
686
|
-
);
|
|
687
|
-
}
|
|
688
|
-
if (errors.length > 0) {
|
|
689
|
-
throw new AggregateError(errors, "cleanupInstanceIfPresent failed");
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
function cleanupInstancesUnder(node, opts) {
|
|
693
|
-
cleanupInstanceIfPresent(node, opts);
|
|
694
|
-
}
|
|
695
|
-
function removeElementListeners(element) {
|
|
696
|
-
const map = elementListeners.get(element);
|
|
697
|
-
if (map) {
|
|
698
|
-
for (const [eventName, entry] of map) {
|
|
699
|
-
if (entry.options !== void 0)
|
|
700
|
-
element.removeEventListener(eventName, entry.handler, entry.options);
|
|
701
|
-
else element.removeEventListener(eventName, entry.handler);
|
|
702
|
-
}
|
|
703
|
-
elementListeners.delete(element);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
function removeAllListeners(root) {
|
|
707
|
-
if (!root) return;
|
|
708
|
-
removeElementListeners(root);
|
|
709
|
-
const children = root.querySelectorAll("*");
|
|
710
|
-
for (let i = 0; i < children.length; i++) {
|
|
711
|
-
removeElementListeners(children[i]);
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
var elementListeners;
|
|
715
|
-
var init_cleanup = __esm({
|
|
716
|
-
"src/renderer/cleanup.ts"() {
|
|
717
|
-
"use strict";
|
|
718
|
-
init_component();
|
|
719
|
-
init_logger();
|
|
720
|
-
elementListeners = /* @__PURE__ */ new WeakMap();
|
|
721
|
-
}
|
|
722
|
-
});
|
|
723
|
-
|
|
724
421
|
// src/renderer/utils.ts
|
|
725
422
|
function parseEventName(propName) {
|
|
726
423
|
if (!propName.startsWith("on") || propName.length <= 2) return null;
|
|
@@ -809,8 +506,7 @@ function extractKey(vnode) {
|
|
|
809
506
|
}
|
|
810
507
|
function buildKeyMapFromChildren(parent) {
|
|
811
508
|
const map = /* @__PURE__ */ new Map();
|
|
812
|
-
|
|
813
|
-
for (const ch of children) {
|
|
509
|
+
for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {
|
|
814
510
|
const k = ch.getAttribute("data-key");
|
|
815
511
|
if (k !== null) {
|
|
816
512
|
map.set(k, ch);
|
|
@@ -985,269 +681,668 @@ var init_keyed = __esm({
|
|
|
985
681
|
}
|
|
986
682
|
});
|
|
987
683
|
|
|
988
|
-
// src/jsx
|
|
684
|
+
// src/common/jsx.ts
|
|
989
685
|
var ELEMENT_TYPE, Fragment;
|
|
990
|
-
var
|
|
991
|
-
"src/jsx
|
|
686
|
+
var init_jsx = __esm({
|
|
687
|
+
"src/common/jsx.ts"() {
|
|
992
688
|
"use strict";
|
|
993
689
|
ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("askr.element");
|
|
994
690
|
Fragment = /* @__PURE__ */ Symbol.for("askr.fragment");
|
|
995
691
|
}
|
|
996
692
|
});
|
|
997
693
|
|
|
998
|
-
// src/
|
|
999
|
-
function
|
|
1000
|
-
return {
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
}
|
|
694
|
+
// src/runtime/dev-namespace.ts
|
|
695
|
+
function getDevNamespace() {
|
|
696
|
+
if (process.env.NODE_ENV === "production") return {};
|
|
697
|
+
try {
|
|
698
|
+
const g = globalThis;
|
|
699
|
+
if (!g.__ASKR__) g.__ASKR__ = {};
|
|
700
|
+
return g.__ASKR__;
|
|
701
|
+
} catch {
|
|
702
|
+
return {};
|
|
703
|
+
}
|
|
1006
704
|
}
|
|
1007
|
-
function
|
|
1008
|
-
|
|
705
|
+
function setDevValue(key, value) {
|
|
706
|
+
if (process.env.NODE_ENV === "production") return;
|
|
707
|
+
try {
|
|
708
|
+
getDevNamespace()[key] = value;
|
|
709
|
+
} catch {
|
|
710
|
+
}
|
|
1009
711
|
}
|
|
1010
|
-
function
|
|
1011
|
-
|
|
712
|
+
function getDevValue(key) {
|
|
713
|
+
if (process.env.NODE_ENV === "production") return void 0;
|
|
714
|
+
try {
|
|
715
|
+
return getDevNamespace()[key];
|
|
716
|
+
} catch {
|
|
717
|
+
return void 0;
|
|
718
|
+
}
|
|
1012
719
|
}
|
|
1013
|
-
var
|
|
1014
|
-
|
|
1015
|
-
"src/jsx/jsx-runtime.ts"() {
|
|
720
|
+
var init_dev_namespace = __esm({
|
|
721
|
+
"src/runtime/dev-namespace.ts"() {
|
|
1016
722
|
"use strict";
|
|
1017
|
-
init_types2();
|
|
1018
|
-
ELEMENT_TYPE2 = /* @__PURE__ */ Symbol.for("askr.element");
|
|
1019
|
-
Fragment2 = /* @__PURE__ */ Symbol.for("askr.fragment");
|
|
1020
723
|
}
|
|
1021
724
|
});
|
|
1022
725
|
|
|
1023
|
-
// src/
|
|
1024
|
-
function
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
726
|
+
// src/runtime/fastlane.ts
|
|
727
|
+
function enterBulkCommit() {
|
|
728
|
+
_bulkCommitActive = true;
|
|
729
|
+
_appliedParents = /* @__PURE__ */ new WeakSet();
|
|
730
|
+
try {
|
|
731
|
+
const cleared = globalScheduler.clearPendingSyncTasks?.() ?? 0;
|
|
732
|
+
setDevValue("__ASKR_FASTLANE_CLEARED_TASKS", cleared);
|
|
733
|
+
} catch (err) {
|
|
734
|
+
if (process.env.NODE_ENV !== "production") throw err;
|
|
1031
735
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
736
|
+
}
|
|
737
|
+
function exitBulkCommit() {
|
|
738
|
+
_bulkCommitActive = false;
|
|
739
|
+
_appliedParents = null;
|
|
740
|
+
}
|
|
741
|
+
function isBulkCommitActive2() {
|
|
742
|
+
return _bulkCommitActive;
|
|
743
|
+
}
|
|
744
|
+
function markFastPathApplied(parent) {
|
|
745
|
+
if (!_appliedParents) return;
|
|
746
|
+
try {
|
|
747
|
+
_appliedParents.add(parent);
|
|
748
|
+
} catch (e) {
|
|
749
|
+
void e;
|
|
1034
750
|
}
|
|
1035
|
-
elementListeners.get(el).set(eventName, {
|
|
1036
|
-
handler: wrappedHandler,
|
|
1037
|
-
original: handler,
|
|
1038
|
-
options
|
|
1039
|
-
});
|
|
1040
751
|
}
|
|
1041
|
-
function
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
752
|
+
function isFastPathApplied(parent) {
|
|
753
|
+
return !!(_appliedParents && _appliedParents.has(parent));
|
|
754
|
+
}
|
|
755
|
+
function finalizeReadSubscriptions(instance) {
|
|
756
|
+
const newSet = instance._pendingReadStates ?? /* @__PURE__ */ new Set();
|
|
757
|
+
const oldSet = instance._lastReadStates ?? /* @__PURE__ */ new Set();
|
|
758
|
+
const token = instance._currentRenderToken;
|
|
759
|
+
if (token === void 0) return;
|
|
760
|
+
for (const s of oldSet) {
|
|
761
|
+
if (!newSet.has(s)) {
|
|
762
|
+
const readers = s._readers;
|
|
763
|
+
if (readers) readers.delete(instance);
|
|
1050
764
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
765
|
+
}
|
|
766
|
+
instance.lastRenderToken = token;
|
|
767
|
+
for (const s of newSet) {
|
|
768
|
+
let readers = s._readers;
|
|
769
|
+
if (!readers) {
|
|
770
|
+
readers = /* @__PURE__ */ new Map();
|
|
771
|
+
s._readers = readers;
|
|
1057
772
|
}
|
|
773
|
+
readers.set(instance, instance.lastRenderToken ?? 0);
|
|
1058
774
|
}
|
|
775
|
+
instance._lastReadStates = newSet;
|
|
776
|
+
instance._pendingReadStates = /* @__PURE__ */ new Set();
|
|
777
|
+
instance._currentRenderToken = void 0;
|
|
1059
778
|
}
|
|
1060
|
-
function
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
el.setAttribute("checked", String(Boolean(value)));
|
|
779
|
+
function unwrapFragmentForFastPath(vnode) {
|
|
780
|
+
if (!vnode || typeof vnode !== "object" || !("type" in vnode)) return vnode;
|
|
781
|
+
const v = vnode;
|
|
782
|
+
if (typeof v.type === "symbol" && (v.type === Fragment || String(v.type) === "Symbol(askr.fragment)")) {
|
|
783
|
+
const children = v.children || v.props?.children;
|
|
784
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
785
|
+
for (const child of children) {
|
|
786
|
+
if (child && typeof child === "object" && "type" in child) {
|
|
787
|
+
const c = child;
|
|
788
|
+
if (typeof c.type === "string") {
|
|
789
|
+
return child;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
1075
793
|
}
|
|
1076
794
|
}
|
|
795
|
+
return vnode;
|
|
1077
796
|
}
|
|
1078
|
-
function
|
|
1079
|
-
const
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
797
|
+
function classifyUpdate(instance, result) {
|
|
798
|
+
const unwrappedResult = unwrapFragmentForFastPath(result);
|
|
799
|
+
if (!unwrappedResult || typeof unwrappedResult !== "object" || !("type" in unwrappedResult))
|
|
800
|
+
return { useFastPath: false, reason: "not-vnode" };
|
|
801
|
+
const vnode = unwrappedResult;
|
|
802
|
+
if (vnode == null || typeof vnode.type !== "string")
|
|
803
|
+
return { useFastPath: false, reason: "not-intrinsic" };
|
|
804
|
+
const parent = instance.target;
|
|
805
|
+
if (!parent) return { useFastPath: false, reason: "no-root" };
|
|
806
|
+
const firstChild = parent.children[0];
|
|
807
|
+
if (!firstChild) return { useFastPath: false, reason: "no-first-child" };
|
|
808
|
+
if (firstChild.tagName.toLowerCase() !== String(vnode.type).toLowerCase())
|
|
809
|
+
return { useFastPath: false, reason: "root-tag-mismatch" };
|
|
810
|
+
const children = vnode.children || vnode.props?.children;
|
|
811
|
+
if (!Array.isArray(children))
|
|
812
|
+
return { useFastPath: false, reason: "no-children-array" };
|
|
813
|
+
for (const c of children) {
|
|
814
|
+
if (typeof c === "object" && c !== null && "type" in c && typeof c.type === "function") {
|
|
815
|
+
return { useFastPath: false, reason: "component-child-present" };
|
|
816
|
+
}
|
|
1082
817
|
}
|
|
818
|
+
if (instance.mountOperations.length > 0)
|
|
819
|
+
return { useFastPath: false, reason: "pending-mounts" };
|
|
820
|
+
try {
|
|
821
|
+
populateKeyMapForElement(firstChild);
|
|
822
|
+
} catch {
|
|
823
|
+
}
|
|
824
|
+
const oldKeyMap = getKeyMapForElement(firstChild);
|
|
825
|
+
const decision = isKeyedReorderFastPathEligible(
|
|
826
|
+
firstChild,
|
|
827
|
+
children,
|
|
828
|
+
oldKeyMap
|
|
829
|
+
);
|
|
830
|
+
if (!decision.useFastPath || decision.totalKeyed < 128)
|
|
831
|
+
return { ...decision, useFastPath: false, reason: "renderer-declined" };
|
|
832
|
+
return { ...decision, useFastPath: true };
|
|
1083
833
|
}
|
|
1084
|
-
function
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
834
|
+
function commitReorderOnly(instance, result) {
|
|
835
|
+
const evaluate2 = globalThis.__ASKR_RENDERER?.evaluate;
|
|
836
|
+
if (typeof evaluate2 !== "function") {
|
|
837
|
+
logger.warn(
|
|
838
|
+
"[Tempo][FASTPATH][DEV] renderer.evaluate not available; declining fast-lane"
|
|
839
|
+
);
|
|
840
|
+
return false;
|
|
841
|
+
}
|
|
842
|
+
const schedBefore = process.env.NODE_ENV !== "production" ? globalScheduler.getState() : null;
|
|
843
|
+
enterBulkCommit();
|
|
844
|
+
try {
|
|
845
|
+
globalScheduler.runWithSyncProgress(() => {
|
|
846
|
+
evaluate2(result, instance.target);
|
|
847
|
+
try {
|
|
848
|
+
finalizeReadSubscriptions(instance);
|
|
849
|
+
} catch (e) {
|
|
850
|
+
if (process.env.NODE_ENV !== "production") throw e;
|
|
1095
851
|
}
|
|
852
|
+
});
|
|
853
|
+
const clearedAfter = globalScheduler.clearPendingSyncTasks?.() ?? 0;
|
|
854
|
+
setDevValue("__FASTLANE_CLEARED_AFTER", clearedAfter);
|
|
855
|
+
if (process.env.NODE_ENV !== "production") {
|
|
856
|
+
validateFastLaneInvariants(instance, schedBefore);
|
|
1096
857
|
}
|
|
858
|
+
return true;
|
|
859
|
+
} finally {
|
|
860
|
+
exitBulkCommit();
|
|
1097
861
|
}
|
|
1098
|
-
if (
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
logger.warn(
|
|
1103
|
-
`Missing keys on dynamic lists in ${name}. Each child in a list should have a unique "key" prop.`
|
|
1104
|
-
);
|
|
1105
|
-
} catch {
|
|
1106
|
-
logger.warn(
|
|
1107
|
-
'Missing keys on dynamic lists. Each child in a list should have a unique "key" prop.'
|
|
862
|
+
if (process.env.NODE_ENV !== "production") {
|
|
863
|
+
if (isBulkCommitActive2()) {
|
|
864
|
+
throw new Error(
|
|
865
|
+
"Fast-lane invariant violated: bulk commit flag still set after commit"
|
|
1108
866
|
);
|
|
1109
867
|
}
|
|
1110
868
|
}
|
|
1111
869
|
}
|
|
1112
|
-
function
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
870
|
+
function validateFastLaneInvariants(instance, schedBefore) {
|
|
871
|
+
const commitCount = getDevValue("__LAST_FASTPATH_COMMIT_COUNT") ?? 0;
|
|
872
|
+
const invariants = {
|
|
873
|
+
commitCount,
|
|
874
|
+
mountOps: instance.mountOperations.length,
|
|
875
|
+
cleanupFns: instance.cleanupFns.length
|
|
876
|
+
};
|
|
877
|
+
setDevValue("__LAST_FASTLANE_INVARIANTS", invariants);
|
|
878
|
+
if (commitCount !== 1) {
|
|
879
|
+
console.error(
|
|
880
|
+
"[FASTLANE][INV] commitCount",
|
|
881
|
+
commitCount,
|
|
882
|
+
"diag",
|
|
883
|
+
globalThis.__ASKR_DIAG
|
|
884
|
+
);
|
|
885
|
+
throw new Error(
|
|
886
|
+
"Fast-lane invariant violated: expected exactly one DOM commit during reorder-only commit"
|
|
887
|
+
);
|
|
1121
888
|
}
|
|
1122
|
-
if (
|
|
1123
|
-
|
|
889
|
+
if (invariants.mountOps > 0) {
|
|
890
|
+
throw new Error(
|
|
891
|
+
"Fast-lane invariant violated: mount operations were registered during bulk commit"
|
|
892
|
+
);
|
|
1124
893
|
}
|
|
1125
|
-
if (
|
|
1126
|
-
|
|
894
|
+
if (invariants.cleanupFns > 0) {
|
|
895
|
+
throw new Error(
|
|
896
|
+
"Fast-lane invariant violated: cleanup functions were added during bulk commit"
|
|
897
|
+
);
|
|
1127
898
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
899
|
+
const schedAfter = globalScheduler.getState();
|
|
900
|
+
if (schedBefore && schedAfter && schedAfter.taskCount > schedBefore.taskCount) {
|
|
901
|
+
console.error(
|
|
902
|
+
"[FASTLANE] schedBefore, schedAfter",
|
|
903
|
+
schedBefore,
|
|
904
|
+
schedAfter
|
|
905
|
+
);
|
|
906
|
+
console.error("[FASTLANE] enqueue logs", getDevValue("__ENQUEUE_LOGS"));
|
|
907
|
+
throw new Error(
|
|
908
|
+
"Fast-lane invariant violated: scheduler enqueued leftover work during bulk commit"
|
|
909
|
+
);
|
|
1130
910
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
911
|
+
let finalState = globalScheduler.getState();
|
|
912
|
+
const executing = globalScheduler.isExecuting();
|
|
913
|
+
let outstandingAfter = Math.max(
|
|
914
|
+
0,
|
|
915
|
+
finalState.taskCount - (executing ? 1 : 0)
|
|
916
|
+
);
|
|
917
|
+
if (outstandingAfter !== 0) {
|
|
918
|
+
let attempts = 0;
|
|
919
|
+
while (attempts < 5) {
|
|
920
|
+
const cleared = globalScheduler.clearPendingSyncTasks?.() ?? 0;
|
|
921
|
+
if (cleared === 0) break;
|
|
922
|
+
attempts++;
|
|
1136
923
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
if (
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
924
|
+
finalState = globalScheduler.getState();
|
|
925
|
+
outstandingAfter = Math.max(
|
|
926
|
+
0,
|
|
927
|
+
finalState.taskCount - (globalScheduler.isExecuting() ? 1 : 0)
|
|
928
|
+
);
|
|
929
|
+
if (outstandingAfter !== 0) {
|
|
930
|
+
console.error(
|
|
931
|
+
"[FASTLANE] Post-commit enqueue logs:",
|
|
932
|
+
getDevValue("__ENQUEUE_LOGS")
|
|
933
|
+
);
|
|
934
|
+
console.error(
|
|
935
|
+
"[FASTLANE] Cleared counts:",
|
|
936
|
+
getDevValue("__FASTLANE_CLEARED_TASKS"),
|
|
937
|
+
getDevValue("__FASTLANE_CLEARED_AFTER")
|
|
938
|
+
);
|
|
939
|
+
throw new Error(
|
|
940
|
+
`Fast-lane invariant violated: scheduler has ${finalState.taskCount} pending task(s) after commit`
|
|
941
|
+
);
|
|
1150
942
|
}
|
|
1151
943
|
}
|
|
1152
|
-
return null;
|
|
1153
944
|
}
|
|
1154
|
-
function
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
945
|
+
function tryRuntimeFastLaneSync(instance, result) {
|
|
946
|
+
const cls = classifyUpdate(instance, result);
|
|
947
|
+
if (!cls.useFastPath) {
|
|
948
|
+
setDevValue("__LAST_FASTPATH_STATS", void 0);
|
|
949
|
+
setDevValue("__LAST_FASTPATH_COMMIT_COUNT", 0);
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
952
|
+
try {
|
|
953
|
+
return commitReorderOnly(instance, result);
|
|
954
|
+
} catch (err) {
|
|
955
|
+
if (process.env.NODE_ENV !== "production") throw err;
|
|
956
|
+
return false;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
var _bulkCommitActive, _appliedParents;
|
|
960
|
+
var init_fastlane = __esm({
|
|
961
|
+
"src/runtime/fastlane.ts"() {
|
|
962
|
+
"use strict";
|
|
963
|
+
init_scheduler();
|
|
964
|
+
init_logger();
|
|
965
|
+
init_keyed();
|
|
966
|
+
init_jsx();
|
|
967
|
+
init_dev_namespace();
|
|
968
|
+
_bulkCommitActive = false;
|
|
969
|
+
_appliedParents = null;
|
|
970
|
+
if (typeof globalThis !== "undefined") {
|
|
971
|
+
globalThis.__ASKR_FASTLANE = {
|
|
972
|
+
isBulkCommitActive: isBulkCommitActive2,
|
|
973
|
+
enterBulkCommit,
|
|
974
|
+
exitBulkCommit,
|
|
975
|
+
tryRuntimeFastLaneSync,
|
|
976
|
+
markFastPathApplied,
|
|
977
|
+
isFastPathApplied
|
|
978
|
+
};
|
|
1169
979
|
}
|
|
1170
980
|
}
|
|
1171
|
-
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
// src/common/vnode.ts
|
|
984
|
+
function _isDOMElement(node) {
|
|
985
|
+
return typeof node === "object" && node !== null && "type" in node;
|
|
1172
986
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
const componentFn = type;
|
|
1177
|
-
const isAsync = componentFn.constructor.name === "AsyncFunction";
|
|
1178
|
-
if (isAsync) {
|
|
1179
|
-
throw new Error(
|
|
1180
|
-
"Async components are not supported. Use resource() for async work."
|
|
1181
|
-
);
|
|
987
|
+
var init_vnode = __esm({
|
|
988
|
+
"src/common/vnode.ts"() {
|
|
989
|
+
"use strict";
|
|
1182
990
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
);
|
|
1191
|
-
node.__instance = childInstance;
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
// src/renderer/types.ts
|
|
994
|
+
var init_types = __esm({
|
|
995
|
+
"src/renderer/types.ts"() {
|
|
996
|
+
"use strict";
|
|
997
|
+
init_vnode();
|
|
1192
998
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
// src/renderer/cleanup.ts
|
|
1002
|
+
function cleanupSingleInstance(node, errors, strict) {
|
|
1003
|
+
const inst = node.__ASKR_INSTANCE;
|
|
1004
|
+
if (!inst) return;
|
|
1005
|
+
try {
|
|
1006
|
+
cleanupComponent(inst);
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
if (strict) errors.push(err);
|
|
1009
|
+
else logger.warn("[Askr] cleanupComponent failed:", err);
|
|
1195
1010
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
if (result instanceof Promise) {
|
|
1201
|
-
throw new Error(
|
|
1202
|
-
"Async components are not supported. Components must return synchronously."
|
|
1203
|
-
);
|
|
1011
|
+
try {
|
|
1012
|
+
delete node.__ASKR_INSTANCE;
|
|
1013
|
+
} catch (e) {
|
|
1014
|
+
if (strict) errors.push(e);
|
|
1204
1015
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1016
|
+
}
|
|
1017
|
+
function forEachDescendantElement(root, visit) {
|
|
1018
|
+
try {
|
|
1019
|
+
const doc = root.ownerDocument;
|
|
1020
|
+
const createTreeWalker = doc?.createTreeWalker;
|
|
1021
|
+
if (typeof createTreeWalker === "function") {
|
|
1022
|
+
const walker = createTreeWalker.call(doc, root, 1);
|
|
1023
|
+
let n = walker.firstChild();
|
|
1024
|
+
while (n) {
|
|
1025
|
+
visit(n);
|
|
1026
|
+
n = walker.nextNode();
|
|
1027
|
+
}
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
} catch {
|
|
1209
1031
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
childInstance.mounted = true;
|
|
1214
|
-
childInstance.notifyUpdate = childInstance._enqueueRun;
|
|
1215
|
-
return placeholder;
|
|
1032
|
+
const descendants = root.querySelectorAll("*");
|
|
1033
|
+
for (let i = 0; i < descendants.length; i++) {
|
|
1034
|
+
visit(descendants[i]);
|
|
1216
1035
|
}
|
|
1217
|
-
const host = document.createElement("div");
|
|
1218
|
-
host.appendChild(dom);
|
|
1219
|
-
mountInstanceInline(childInstance, host);
|
|
1220
|
-
return host;
|
|
1221
1036
|
}
|
|
1222
|
-
function
|
|
1223
|
-
|
|
1224
|
-
const
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1037
|
+
function cleanupInstanceIfPresent(node, opts) {
|
|
1038
|
+
if (!node || !(node instanceof Element)) return;
|
|
1039
|
+
const strict = opts?.strict ?? false;
|
|
1040
|
+
const errors = strict ? [] : null;
|
|
1041
|
+
try {
|
|
1042
|
+
cleanupSingleInstance(node, errors, strict);
|
|
1043
|
+
} catch (err) {
|
|
1044
|
+
if (strict) errors.push(err);
|
|
1045
|
+
else logger.warn("[Askr] cleanupInstanceIfPresent failed:", err);
|
|
1046
|
+
}
|
|
1047
|
+
try {
|
|
1048
|
+
forEachDescendantElement(node, (d) => {
|
|
1049
|
+
try {
|
|
1050
|
+
cleanupSingleInstance(d, errors, strict);
|
|
1051
|
+
} catch (err) {
|
|
1052
|
+
if (strict) errors.push(err);
|
|
1053
|
+
else
|
|
1054
|
+
logger.warn(
|
|
1055
|
+
"[Askr] cleanupInstanceIfPresent descendant cleanup failed:",
|
|
1056
|
+
err
|
|
1057
|
+
);
|
|
1230
1058
|
}
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1059
|
+
});
|
|
1060
|
+
} catch (err) {
|
|
1061
|
+
if (strict) errors.push(err);
|
|
1062
|
+
else
|
|
1063
|
+
logger.warn(
|
|
1064
|
+
"[Askr] cleanupInstanceIfPresent descendant query failed:",
|
|
1065
|
+
err
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
if (errors && errors.length > 0) {
|
|
1069
|
+
throw new AggregateError(errors, "cleanupInstanceIfPresent failed");
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
function cleanupInstancesUnder(node, opts) {
|
|
1073
|
+
cleanupInstanceIfPresent(node, opts);
|
|
1074
|
+
}
|
|
1075
|
+
function removeElementListeners(element) {
|
|
1076
|
+
const map = elementListeners.get(element);
|
|
1077
|
+
if (map) {
|
|
1078
|
+
for (const [eventName, entry] of map) {
|
|
1079
|
+
if (entry.options !== void 0)
|
|
1080
|
+
element.removeEventListener(eventName, entry.handler, entry.options);
|
|
1081
|
+
else element.removeEventListener(eventName, entry.handler);
|
|
1234
1082
|
}
|
|
1083
|
+
elementListeners.delete(element);
|
|
1235
1084
|
}
|
|
1236
|
-
return fragment;
|
|
1237
1085
|
}
|
|
1238
|
-
function
|
|
1239
|
-
if (!
|
|
1240
|
-
|
|
1086
|
+
function removeAllListeners(root) {
|
|
1087
|
+
if (!root) return;
|
|
1088
|
+
removeElementListeners(root);
|
|
1089
|
+
forEachDescendantElement(root, removeElementListeners);
|
|
1090
|
+
}
|
|
1091
|
+
var elementListeners;
|
|
1092
|
+
var init_cleanup = __esm({
|
|
1093
|
+
"src/renderer/cleanup.ts"() {
|
|
1094
|
+
"use strict";
|
|
1095
|
+
init_component();
|
|
1096
|
+
init_logger();
|
|
1097
|
+
elementListeners = /* @__PURE__ */ new WeakMap();
|
|
1241
1098
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
// src/jsx/types.ts
|
|
1102
|
+
var init_types2 = __esm({
|
|
1103
|
+
"src/jsx/types.ts"() {
|
|
1104
|
+
"use strict";
|
|
1105
|
+
init_jsx();
|
|
1106
|
+
}
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
// src/jsx/jsx-runtime.ts
|
|
1110
|
+
var Fragment2;
|
|
1111
|
+
var init_jsx_runtime = __esm({
|
|
1112
|
+
"src/jsx/jsx-runtime.ts"() {
|
|
1113
|
+
"use strict";
|
|
1114
|
+
init_types2();
|
|
1115
|
+
Fragment2 = /* @__PURE__ */ Symbol.for("askr.fragment");
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
// src/renderer/dom.ts
|
|
1120
|
+
function addTrackedListener(el, eventName, handler) {
|
|
1121
|
+
const wrappedHandler = createWrappedHandler(handler, true);
|
|
1122
|
+
const options = getPassiveOptions(eventName);
|
|
1123
|
+
if (options !== void 0) {
|
|
1124
|
+
el.addEventListener(eventName, wrappedHandler, options);
|
|
1125
|
+
} else {
|
|
1126
|
+
el.addEventListener(eventName, wrappedHandler);
|
|
1127
|
+
}
|
|
1128
|
+
if (!elementListeners.has(el)) {
|
|
1129
|
+
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
1130
|
+
}
|
|
1131
|
+
elementListeners.get(el).set(eventName, {
|
|
1132
|
+
handler: wrappedHandler,
|
|
1133
|
+
original: handler,
|
|
1134
|
+
options
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
function applyPropsToElement(el, props, tagName) {
|
|
1246
1138
|
for (const key in props) {
|
|
1247
1139
|
const value = props[key];
|
|
1248
1140
|
if (isSkippedProp(key)) continue;
|
|
1141
|
+
if (value === void 0 || value === null || value === false) continue;
|
|
1249
1142
|
const eventName = parseEventName(key);
|
|
1250
|
-
if (
|
|
1143
|
+
if (eventName) {
|
|
1144
|
+
addTrackedListener(el, eventName, value);
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
if (key === "class" || key === "className") {
|
|
1148
|
+
el.className = String(value);
|
|
1149
|
+
} else if (key === "value" || key === "checked") {
|
|
1150
|
+
applyFormControlProp(el, key, value, tagName);
|
|
1151
|
+
} else {
|
|
1152
|
+
el.setAttribute(key, String(value));
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
function applyFormControlProp(el, key, value, tagName) {
|
|
1157
|
+
if (key === "value") {
|
|
1158
|
+
if (tagNamesEqualIgnoreCase(tagName, "input") || tagNamesEqualIgnoreCase(tagName, "textarea") || tagNamesEqualIgnoreCase(tagName, "select")) {
|
|
1159
|
+
el.value = String(value);
|
|
1160
|
+
el.setAttribute("value", String(value));
|
|
1161
|
+
} else {
|
|
1162
|
+
el.setAttribute("value", String(value));
|
|
1163
|
+
}
|
|
1164
|
+
} else if (key === "checked") {
|
|
1165
|
+
if (tagNamesEqualIgnoreCase(tagName, "input")) {
|
|
1166
|
+
el.checked = Boolean(value);
|
|
1167
|
+
el.setAttribute("checked", String(Boolean(value)));
|
|
1168
|
+
} else {
|
|
1169
|
+
el.setAttribute("checked", String(Boolean(value)));
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
function materializeKey(el, vnode, props) {
|
|
1174
|
+
const vnodeKey = vnode.key ?? props?.key;
|
|
1175
|
+
if (vnodeKey !== void 0) {
|
|
1176
|
+
el.setAttribute("data-key", String(vnodeKey));
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
function warnMissingKeys(children) {
|
|
1180
|
+
if (process.env.NODE_ENV === "production") return;
|
|
1181
|
+
let hasElements = false;
|
|
1182
|
+
let hasKeys = false;
|
|
1183
|
+
for (const item of children) {
|
|
1184
|
+
if (typeof item === "object" && item !== null && "type" in item) {
|
|
1185
|
+
hasElements = true;
|
|
1186
|
+
const rawKey = item.key ?? item.props?.key;
|
|
1187
|
+
if (rawKey !== void 0) {
|
|
1188
|
+
hasKeys = true;
|
|
1189
|
+
break;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (hasElements && !hasKeys) {
|
|
1194
|
+
try {
|
|
1195
|
+
const inst = getCurrentInstance();
|
|
1196
|
+
const name = inst?.fn?.name || "<anonymous>";
|
|
1197
|
+
logger.warn(
|
|
1198
|
+
`Missing keys on dynamic lists in ${name}. Each child in a list should have a unique "key" prop.`
|
|
1199
|
+
);
|
|
1200
|
+
} catch {
|
|
1201
|
+
logger.warn(
|
|
1202
|
+
'Missing keys on dynamic lists. Each child in a list should have a unique "key" prop.'
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
function createDOMNode(node) {
|
|
1208
|
+
if (!IS_DOM_AVAILABLE) {
|
|
1209
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1210
|
+
try {
|
|
1211
|
+
logger.warn("[Askr] createDOMNode called in non-DOM environment");
|
|
1212
|
+
} catch {
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
if (typeof node === "string") {
|
|
1218
|
+
return document.createTextNode(node);
|
|
1219
|
+
}
|
|
1220
|
+
if (typeof node === "number") {
|
|
1221
|
+
return document.createTextNode(String(node));
|
|
1222
|
+
}
|
|
1223
|
+
if (!node) {
|
|
1224
|
+
return null;
|
|
1225
|
+
}
|
|
1226
|
+
if (Array.isArray(node)) {
|
|
1227
|
+
const fragment = document.createDocumentFragment();
|
|
1228
|
+
for (const child of node) {
|
|
1229
|
+
const dom = createDOMNode(child);
|
|
1230
|
+
if (dom) fragment.appendChild(dom);
|
|
1231
|
+
}
|
|
1232
|
+
return fragment;
|
|
1233
|
+
}
|
|
1234
|
+
if (typeof node === "object" && node !== null && "type" in node) {
|
|
1235
|
+
const type = node.type;
|
|
1236
|
+
const props = node.props || {};
|
|
1237
|
+
if (typeof type === "string") {
|
|
1238
|
+
return createIntrinsicElement(node, type, props);
|
|
1239
|
+
}
|
|
1240
|
+
if (typeof type === "function") {
|
|
1241
|
+
return createComponentElement(node, type, props);
|
|
1242
|
+
}
|
|
1243
|
+
if (typeof type === "symbol" && (type === Fragment2 || String(type) === "Symbol(Fragment)")) {
|
|
1244
|
+
return createFragmentElement(node, props);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
return null;
|
|
1248
|
+
}
|
|
1249
|
+
function createIntrinsicElement(node, type, props) {
|
|
1250
|
+
const el = document.createElement(type);
|
|
1251
|
+
materializeKey(el, node, props);
|
|
1252
|
+
applyPropsToElement(el, props, type);
|
|
1253
|
+
const children = props.children || node.children;
|
|
1254
|
+
if (children) {
|
|
1255
|
+
if (Array.isArray(children)) {
|
|
1256
|
+
warnMissingKeys(children);
|
|
1257
|
+
for (const child of children) {
|
|
1258
|
+
const dom = createDOMNode(child);
|
|
1259
|
+
if (dom) el.appendChild(dom);
|
|
1260
|
+
}
|
|
1261
|
+
} else {
|
|
1262
|
+
const dom = createDOMNode(children);
|
|
1263
|
+
if (dom) el.appendChild(dom);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
return el;
|
|
1267
|
+
}
|
|
1268
|
+
function createComponentElement(node, type, props) {
|
|
1269
|
+
const frame = node[CONTEXT_FRAME_SYMBOL];
|
|
1270
|
+
const snapshot = frame || getCurrentContextFrame();
|
|
1271
|
+
const componentFn = type;
|
|
1272
|
+
const isAsync = componentFn.constructor.name === "AsyncFunction";
|
|
1273
|
+
if (isAsync) {
|
|
1274
|
+
throw new Error(
|
|
1275
|
+
"Async components are not supported. Use resource() for async work."
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
let childInstance = node.__instance;
|
|
1279
|
+
if (!childInstance) {
|
|
1280
|
+
childInstance = createComponentInstance(
|
|
1281
|
+
`comp-${Math.random().toString(36).slice(2, 7)}`,
|
|
1282
|
+
componentFn,
|
|
1283
|
+
props || {},
|
|
1284
|
+
null
|
|
1285
|
+
);
|
|
1286
|
+
node.__instance = childInstance;
|
|
1287
|
+
}
|
|
1288
|
+
if (snapshot) {
|
|
1289
|
+
childInstance.ownerFrame = snapshot;
|
|
1290
|
+
}
|
|
1291
|
+
const result = withContext(
|
|
1292
|
+
snapshot,
|
|
1293
|
+
() => renderComponentInline(childInstance)
|
|
1294
|
+
);
|
|
1295
|
+
if (result instanceof Promise) {
|
|
1296
|
+
throw new Error(
|
|
1297
|
+
"Async components are not supported. Components must return synchronously."
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
const dom = withContext(snapshot, () => createDOMNode(result));
|
|
1301
|
+
if (dom instanceof Element) {
|
|
1302
|
+
mountInstanceInline(childInstance, dom);
|
|
1303
|
+
return dom;
|
|
1304
|
+
}
|
|
1305
|
+
if (!dom) {
|
|
1306
|
+
const placeholder = document.createComment("");
|
|
1307
|
+
childInstance._placeholder = placeholder;
|
|
1308
|
+
childInstance.mounted = true;
|
|
1309
|
+
childInstance.notifyUpdate = childInstance._enqueueRun;
|
|
1310
|
+
return placeholder;
|
|
1311
|
+
}
|
|
1312
|
+
const host = document.createElement("div");
|
|
1313
|
+
host.appendChild(dom);
|
|
1314
|
+
mountInstanceInline(childInstance, host);
|
|
1315
|
+
return host;
|
|
1316
|
+
}
|
|
1317
|
+
function createFragmentElement(node, props) {
|
|
1318
|
+
const fragment = document.createDocumentFragment();
|
|
1319
|
+
const children = props.children || node.children;
|
|
1320
|
+
if (children) {
|
|
1321
|
+
if (Array.isArray(children)) {
|
|
1322
|
+
for (const child of children) {
|
|
1323
|
+
const dom = createDOMNode(child);
|
|
1324
|
+
if (dom) fragment.appendChild(dom);
|
|
1325
|
+
}
|
|
1326
|
+
} else {
|
|
1327
|
+
const dom = createDOMNode(children);
|
|
1328
|
+
if (dom) fragment.appendChild(dom);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
return fragment;
|
|
1332
|
+
}
|
|
1333
|
+
function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
1334
|
+
if (!_isDOMElement(vnode)) {
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
const props = vnode.props || {};
|
|
1338
|
+
materializeKey(el, vnode, props);
|
|
1339
|
+
const existingListeners = elementListeners.get(el);
|
|
1340
|
+
let desiredEventNames = null;
|
|
1341
|
+
for (const key in props) {
|
|
1342
|
+
const value = props[key];
|
|
1343
|
+
if (isSkippedProp(key)) continue;
|
|
1344
|
+
const eventName = parseEventName(key);
|
|
1345
|
+
if (value === void 0 || value === null || value === false) {
|
|
1251
1346
|
if (key === "class" || key === "className") {
|
|
1252
1347
|
el.className = "";
|
|
1253
1348
|
} else if (eventName && existingListeners?.has(eventName)) {
|
|
@@ -1268,13 +1363,19 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
1268
1363
|
} else if (key === "value" || key === "checked") {
|
|
1269
1364
|
el[key] = value;
|
|
1270
1365
|
} else if (eventName) {
|
|
1271
|
-
|
|
1366
|
+
if (existingListeners && existingListeners.size > 0) {
|
|
1367
|
+
(desiredEventNames ??= /* @__PURE__ */ new Set()).add(eventName);
|
|
1368
|
+
}
|
|
1272
1369
|
const existing = existingListeners?.get(eventName);
|
|
1273
1370
|
if (existing && existing.original === value) {
|
|
1274
1371
|
continue;
|
|
1275
1372
|
}
|
|
1276
1373
|
if (existing) {
|
|
1277
|
-
|
|
1374
|
+
if (existing.options !== void 0) {
|
|
1375
|
+
el.removeEventListener(eventName, existing.handler, existing.options);
|
|
1376
|
+
} else {
|
|
1377
|
+
el.removeEventListener(eventName, existing.handler);
|
|
1378
|
+
}
|
|
1278
1379
|
}
|
|
1279
1380
|
const wrappedHandler = createWrappedHandler(
|
|
1280
1381
|
value,
|
|
@@ -1298,15 +1399,29 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
1298
1399
|
el.setAttribute(key, String(value));
|
|
1299
1400
|
}
|
|
1300
1401
|
}
|
|
1301
|
-
if (existingListeners) {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1402
|
+
if (existingListeners && existingListeners.size > 0) {
|
|
1403
|
+
if (desiredEventNames === null) {
|
|
1404
|
+
for (const [eventName, entry] of existingListeners) {
|
|
1405
|
+
if (entry.options !== void 0) {
|
|
1406
|
+
el.removeEventListener(eventName, entry.handler, entry.options);
|
|
1407
|
+
} else {
|
|
1408
|
+
el.removeEventListener(eventName, entry.handler);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
elementListeners.delete(el);
|
|
1412
|
+
} else {
|
|
1413
|
+
for (const [eventName, entry] of existingListeners) {
|
|
1414
|
+
if (!desiredEventNames.has(eventName)) {
|
|
1415
|
+
if (entry.options !== void 0) {
|
|
1416
|
+
el.removeEventListener(eventName, entry.handler, entry.options);
|
|
1417
|
+
} else {
|
|
1418
|
+
el.removeEventListener(eventName, entry.handler);
|
|
1419
|
+
}
|
|
1420
|
+
existingListeners.delete(eventName);
|
|
1421
|
+
}
|
|
1307
1422
|
}
|
|
1423
|
+
if (existingListeners.size === 0) elementListeners.delete(el);
|
|
1308
1424
|
}
|
|
1309
|
-
if (existingListeners.size === 0) elementListeners.delete(el);
|
|
1310
1425
|
}
|
|
1311
1426
|
if (updateChildren) {
|
|
1312
1427
|
const children = vnode.children || props.children;
|
|
@@ -1349,47 +1464,47 @@ function updateUnkeyedChildren(parent, newChildren) {
|
|
|
1349
1464
|
}
|
|
1350
1465
|
const max = Math.max(existing.length, newChildren.length);
|
|
1351
1466
|
for (let i = 0; i < max; i++) {
|
|
1352
|
-
const
|
|
1467
|
+
const current = existing[i];
|
|
1353
1468
|
const next = newChildren[i];
|
|
1354
|
-
if (next === void 0 &&
|
|
1355
|
-
cleanupInstanceIfPresent(
|
|
1356
|
-
|
|
1469
|
+
if (next === void 0 && current) {
|
|
1470
|
+
cleanupInstanceIfPresent(current);
|
|
1471
|
+
current.remove();
|
|
1357
1472
|
continue;
|
|
1358
1473
|
}
|
|
1359
|
-
if (!
|
|
1474
|
+
if (!current && next !== void 0) {
|
|
1360
1475
|
const dom = createDOMNode(next);
|
|
1361
1476
|
if (dom) parent.appendChild(dom);
|
|
1362
1477
|
continue;
|
|
1363
1478
|
}
|
|
1364
|
-
if (!
|
|
1479
|
+
if (!current || next === void 0) continue;
|
|
1365
1480
|
if (typeof next === "string" || typeof next === "number") {
|
|
1366
|
-
|
|
1481
|
+
current.textContent = String(next);
|
|
1367
1482
|
} else if (_isDOMElement(next)) {
|
|
1368
1483
|
if (typeof next.type === "string") {
|
|
1369
|
-
if (
|
|
1370
|
-
updateElementFromVnode(
|
|
1484
|
+
if (tagsEqualIgnoreCase(current.tagName, next.type)) {
|
|
1485
|
+
updateElementFromVnode(current, next);
|
|
1371
1486
|
} else {
|
|
1372
1487
|
const dom = createDOMNode(next);
|
|
1373
1488
|
if (dom) {
|
|
1374
|
-
if (
|
|
1375
|
-
cleanupInstanceIfPresent(
|
|
1376
|
-
parent.replaceChild(dom,
|
|
1489
|
+
if (current instanceof Element) removeAllListeners(current);
|
|
1490
|
+
cleanupInstanceIfPresent(current);
|
|
1491
|
+
parent.replaceChild(dom, current);
|
|
1377
1492
|
}
|
|
1378
1493
|
}
|
|
1379
1494
|
} else {
|
|
1380
1495
|
const dom = createDOMNode(next);
|
|
1381
1496
|
if (dom) {
|
|
1382
|
-
if (
|
|
1383
|
-
cleanupInstanceIfPresent(
|
|
1384
|
-
parent.replaceChild(dom,
|
|
1497
|
+
if (current instanceof Element) removeAllListeners(current);
|
|
1498
|
+
cleanupInstanceIfPresent(current);
|
|
1499
|
+
parent.replaceChild(dom, current);
|
|
1385
1500
|
}
|
|
1386
1501
|
}
|
|
1387
1502
|
} else {
|
|
1388
1503
|
const dom = createDOMNode(next);
|
|
1389
1504
|
if (dom) {
|
|
1390
|
-
if (
|
|
1391
|
-
cleanupInstanceIfPresent(
|
|
1392
|
-
parent.replaceChild(dom,
|
|
1505
|
+
if (current instanceof Element) removeAllListeners(current);
|
|
1506
|
+
cleanupInstanceIfPresent(current);
|
|
1507
|
+
parent.replaceChild(dom, current);
|
|
1393
1508
|
}
|
|
1394
1509
|
}
|
|
1395
1510
|
}
|
|
@@ -1399,31 +1514,38 @@ function performBulkPositionalKeyedTextUpdate(parent, keyedVnodes) {
|
|
|
1399
1514
|
let reused = 0;
|
|
1400
1515
|
let updatedKeys = 0;
|
|
1401
1516
|
const t0 = now();
|
|
1517
|
+
const debugFastPath = process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true";
|
|
1402
1518
|
for (let i = 0; i < total; i++) {
|
|
1403
1519
|
const { key, vnode } = keyedVnodes[i];
|
|
1404
1520
|
const ch = parent.children[i];
|
|
1405
1521
|
if (ch && _isDOMElement(vnode) && typeof vnode.type === "string") {
|
|
1406
1522
|
const vnodeType = vnode.type;
|
|
1407
|
-
if (ch.tagName
|
|
1523
|
+
if (tagsEqualIgnoreCase(ch.tagName, vnodeType)) {
|
|
1408
1524
|
const children = vnode.children || vnode.props?.children;
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1525
|
+
if (debugFastPath) {
|
|
1526
|
+
logFastPathDebug("positional idx", i, {
|
|
1527
|
+
chTag: ch.tagName,
|
|
1528
|
+
vnodeType,
|
|
1529
|
+
chChildNodes: ch.childNodes.length,
|
|
1530
|
+
childrenType: Array.isArray(children) ? "array" : typeof children
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
updateTextContent(ch, children, vnode);
|
|
1416
1534
|
setDataKey(ch, key, () => updatedKeys++);
|
|
1417
1535
|
reused++;
|
|
1418
1536
|
continue;
|
|
1419
1537
|
} else {
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1538
|
+
if (debugFastPath) {
|
|
1539
|
+
logFastPathDebug("positional tag mismatch", i, {
|
|
1540
|
+
chTag: ch.tagName,
|
|
1541
|
+
vnodeType
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1424
1544
|
}
|
|
1425
1545
|
} else {
|
|
1426
|
-
|
|
1546
|
+
if (debugFastPath) {
|
|
1547
|
+
logFastPathDebug("positional missing or invalid", i, { ch: !!ch });
|
|
1548
|
+
}
|
|
1427
1549
|
}
|
|
1428
1550
|
replaceNodeAtPosition(parent, i, vnode);
|
|
1429
1551
|
}
|
|
@@ -1433,14 +1555,46 @@ function performBulkPositionalKeyedTextUpdate(parent, keyedVnodes) {
|
|
|
1433
1555
|
recordFastPathStats(stats, "bulkKeyedPositionalHits");
|
|
1434
1556
|
return stats;
|
|
1435
1557
|
}
|
|
1436
|
-
function updateTextContent(el, children) {
|
|
1558
|
+
function updateTextContent(el, children, vnode) {
|
|
1437
1559
|
if (typeof children === "string" || typeof children === "number") {
|
|
1438
1560
|
setTextNodeData(el, String(children));
|
|
1439
1561
|
} else if (Array.isArray(children) && children.length === 1 && (typeof children[0] === "string" || typeof children[0] === "number")) {
|
|
1440
1562
|
setTextNodeData(el, String(children[0]));
|
|
1441
1563
|
} else {
|
|
1442
|
-
|
|
1564
|
+
if (!tryUpdateTwoChildTextPattern(el, vnode)) {
|
|
1565
|
+
updateElementFromVnode(el, vnode);
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
function tryUpdateTwoChildTextPattern(parentEl, vnode) {
|
|
1570
|
+
const vnodeChildren = vnode.children || vnode.props?.children;
|
|
1571
|
+
if (!Array.isArray(vnodeChildren) || vnodeChildren.length !== 2) return false;
|
|
1572
|
+
const c0 = vnodeChildren[0];
|
|
1573
|
+
const c1 = vnodeChildren[1];
|
|
1574
|
+
if (!_isDOMElement(c0) || !_isDOMElement(c1)) return false;
|
|
1575
|
+
if (typeof c0.type !== "string" || typeof c1.type !== "string") return false;
|
|
1576
|
+
const el0 = parentEl.children[0];
|
|
1577
|
+
const el1 = parentEl.children[1];
|
|
1578
|
+
if (!el0 || !el1) return false;
|
|
1579
|
+
if (!tagsEqualIgnoreCase(el0.tagName, c0.type)) return false;
|
|
1580
|
+
if (!tagsEqualIgnoreCase(el1.tagName, c1.type)) return false;
|
|
1581
|
+
const t0 = c0.children || c0.props?.children;
|
|
1582
|
+
const t1 = c1.children || c1.props?.children;
|
|
1583
|
+
if (typeof t0 === "string" || typeof t0 === "number") {
|
|
1584
|
+
setTextNodeData(el0, String(t0));
|
|
1585
|
+
} else if (Array.isArray(t0) && t0.length === 1 && (typeof t0[0] === "string" || typeof t0[0] === "number")) {
|
|
1586
|
+
setTextNodeData(el0, String(t0[0]));
|
|
1587
|
+
} else {
|
|
1588
|
+
return false;
|
|
1589
|
+
}
|
|
1590
|
+
if (typeof t1 === "string" || typeof t1 === "number") {
|
|
1591
|
+
setTextNodeData(el1, String(t1));
|
|
1592
|
+
} else if (Array.isArray(t1) && t1.length === 1 && (typeof t1[0] === "string" || typeof t1[0] === "number")) {
|
|
1593
|
+
setTextNodeData(el1, String(t1[0]));
|
|
1594
|
+
} else {
|
|
1595
|
+
return false;
|
|
1443
1596
|
}
|
|
1597
|
+
return true;
|
|
1444
1598
|
}
|
|
1445
1599
|
function setTextNodeData(el, text) {
|
|
1446
1600
|
if (el.childNodes.length === 1 && el.firstChild?.nodeType === 3) {
|
|
@@ -1451,11 +1605,56 @@ function setTextNodeData(el, text) {
|
|
|
1451
1605
|
}
|
|
1452
1606
|
function setDataKey(el, key, onSet) {
|
|
1453
1607
|
try {
|
|
1454
|
-
|
|
1608
|
+
const next = String(key);
|
|
1609
|
+
if (el.getAttribute("data-key") === next) return;
|
|
1610
|
+
el.setAttribute("data-key", next);
|
|
1455
1611
|
onSet();
|
|
1456
1612
|
} catch {
|
|
1457
1613
|
}
|
|
1458
1614
|
}
|
|
1615
|
+
function upperCommonTagName(tag) {
|
|
1616
|
+
switch (tag) {
|
|
1617
|
+
case "div":
|
|
1618
|
+
return "DIV";
|
|
1619
|
+
case "span":
|
|
1620
|
+
return "SPAN";
|
|
1621
|
+
case "p":
|
|
1622
|
+
return "P";
|
|
1623
|
+
case "a":
|
|
1624
|
+
return "A";
|
|
1625
|
+
case "button":
|
|
1626
|
+
return "BUTTON";
|
|
1627
|
+
case "input":
|
|
1628
|
+
return "INPUT";
|
|
1629
|
+
case "ul":
|
|
1630
|
+
return "UL";
|
|
1631
|
+
case "ol":
|
|
1632
|
+
return "OL";
|
|
1633
|
+
case "li":
|
|
1634
|
+
return "LI";
|
|
1635
|
+
default:
|
|
1636
|
+
return null;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
function tagNamesEqualIgnoreCase(a, b) {
|
|
1640
|
+
if (a === b) return true;
|
|
1641
|
+
const len = a.length;
|
|
1642
|
+
if (len !== b.length) return false;
|
|
1643
|
+
for (let i = 0; i < len; i++) {
|
|
1644
|
+
const ac = a.charCodeAt(i);
|
|
1645
|
+
const bc = b.charCodeAt(i);
|
|
1646
|
+
if (ac === bc) continue;
|
|
1647
|
+
const an = ac >= 65 && ac <= 90 ? ac + 32 : ac;
|
|
1648
|
+
const bn = bc >= 65 && bc <= 90 ? bc + 32 : bc;
|
|
1649
|
+
if (an !== bn) return false;
|
|
1650
|
+
}
|
|
1651
|
+
return true;
|
|
1652
|
+
}
|
|
1653
|
+
function tagsEqualIgnoreCase(elementTagName, vnodeType) {
|
|
1654
|
+
const upperCommon = upperCommonTagName(vnodeType);
|
|
1655
|
+
if (upperCommon !== null && elementTagName === upperCommon) return true;
|
|
1656
|
+
return tagNamesEqualIgnoreCase(elementTagName, vnodeType);
|
|
1657
|
+
}
|
|
1459
1658
|
function replaceNodeAtPosition(parent, index, vnode) {
|
|
1460
1659
|
const dom = createDOMNode(vnode);
|
|
1461
1660
|
if (dom) {
|
|
@@ -1470,7 +1669,8 @@ function replaceNodeAtPosition(parent, index, vnode) {
|
|
|
1470
1669
|
}
|
|
1471
1670
|
function updateKeyedElementsMap(parent, keyedVnodes) {
|
|
1472
1671
|
try {
|
|
1473
|
-
const
|
|
1672
|
+
const existing = keyedElements.get(parent);
|
|
1673
|
+
const newKeyMap = existing ? (existing.clear(), existing) : /* @__PURE__ */ new Map();
|
|
1474
1674
|
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
1475
1675
|
const k = keyedVnodes[i].key;
|
|
1476
1676
|
const ch = parent.children[i];
|
|
@@ -1492,7 +1692,6 @@ function performBulkTextReplace(parent, newChildren) {
|
|
|
1492
1692
|
else if (result === "created") created++;
|
|
1493
1693
|
}
|
|
1494
1694
|
const tBuild = now() - t0;
|
|
1495
|
-
cleanupRemovedNodes(parent, finalNodes);
|
|
1496
1695
|
const tCommit = commitBulkReplace(parent, finalNodes);
|
|
1497
1696
|
keyedElements.delete(parent);
|
|
1498
1697
|
const stats = {
|
|
@@ -1527,7 +1726,7 @@ function processElementVnode(vnode, existingNode, finalNodes) {
|
|
|
1527
1726
|
const vnodeObj = vnode;
|
|
1528
1727
|
if (typeof vnodeObj.type === "string") {
|
|
1529
1728
|
const tag = vnodeObj.type;
|
|
1530
|
-
if (existingNode && existingNode.nodeType === 1 && existingNode.tagName
|
|
1729
|
+
if (existingNode && existingNode.nodeType === 1 && tagsEqualIgnoreCase(existingNode.tagName, tag)) {
|
|
1531
1730
|
updateElementFromVnode(existingNode, vnode);
|
|
1532
1731
|
finalNodes.push(existingNode);
|
|
1533
1732
|
return "reused";
|
|
@@ -1540,24 +1739,21 @@ function processElementVnode(vnode, existingNode, finalNodes) {
|
|
|
1540
1739
|
}
|
|
1541
1740
|
return "skipped";
|
|
1542
1741
|
}
|
|
1543
|
-
function cleanupRemovedNodes(parent, keepNodes) {
|
|
1544
|
-
try {
|
|
1545
|
-
const toRemove = Array.from(parent.childNodes).filter(
|
|
1546
|
-
(n) => !keepNodes.includes(n)
|
|
1547
|
-
);
|
|
1548
|
-
for (const n of toRemove) {
|
|
1549
|
-
if (n instanceof Element) removeAllListeners(n);
|
|
1550
|
-
cleanupInstanceIfPresent(n);
|
|
1551
|
-
}
|
|
1552
|
-
} catch {
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
1742
|
function commitBulkReplace(parent, nodes) {
|
|
1556
1743
|
const fragStart = Date.now();
|
|
1557
1744
|
const fragment = document.createDocumentFragment();
|
|
1558
1745
|
for (let i = 0; i < nodes.length; i++) {
|
|
1559
1746
|
fragment.appendChild(nodes[i]);
|
|
1560
1747
|
}
|
|
1748
|
+
try {
|
|
1749
|
+
for (let n = parent.firstChild; n; ) {
|
|
1750
|
+
const next = n.nextSibling;
|
|
1751
|
+
if (n instanceof Element) removeAllListeners(n);
|
|
1752
|
+
cleanupInstanceIfPresent(n);
|
|
1753
|
+
n = next;
|
|
1754
|
+
}
|
|
1755
|
+
} catch {
|
|
1756
|
+
}
|
|
1561
1757
|
recordDOMReplace("bulk-text-replace");
|
|
1562
1758
|
parent.replaceChildren(fragment);
|
|
1563
1759
|
return Date.now() - fragStart;
|
|
@@ -1687,9 +1883,7 @@ function applyRendererFastPath(parent, keyedVnodes, oldKeyMap, unkeyedVnodes) {
|
|
|
1687
1883
|
} else {
|
|
1688
1884
|
localOldKeyMap = /* @__PURE__ */ new Map();
|
|
1689
1885
|
try {
|
|
1690
|
-
|
|
1691
|
-
for (let i = 0; i < parentChildren.length; i++) {
|
|
1692
|
-
const ch = parentChildren[i];
|
|
1886
|
+
for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {
|
|
1693
1887
|
const k = ch.getAttribute("data-key");
|
|
1694
1888
|
if (k !== null) {
|
|
1695
1889
|
localOldKeyMap.set(k, ch);
|
|
@@ -1753,11 +1947,11 @@ function applyRendererFastPath(parent, keyedVnodes, oldKeyMap, unkeyedVnodes) {
|
|
|
1753
1947
|
fragmentAppendCount++;
|
|
1754
1948
|
}
|
|
1755
1949
|
try {
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
for (const n of toRemove) {
|
|
1950
|
+
for (let n = parent.firstChild; n; ) {
|
|
1951
|
+
const next = n.nextSibling;
|
|
1759
1952
|
if (n instanceof Element) removeAllListeners(n);
|
|
1760
1953
|
cleanupInstanceIfPresent(n);
|
|
1954
|
+
n = next;
|
|
1761
1955
|
}
|
|
1762
1956
|
} catch (e) {
|
|
1763
1957
|
void e;
|
|
@@ -1833,14 +2027,26 @@ var init_fastpath = __esm({
|
|
|
1833
2027
|
init_cleanup();
|
|
1834
2028
|
init_diag();
|
|
1835
2029
|
init_scheduler();
|
|
1836
|
-
|
|
2030
|
+
init_fastlane();
|
|
1837
2031
|
}
|
|
1838
2032
|
});
|
|
1839
2033
|
|
|
1840
2034
|
// src/renderer/reconcile.ts
|
|
1841
|
-
function
|
|
1842
|
-
|
|
1843
|
-
|
|
2035
|
+
function tagNamesEqualIgnoreCase2(a, b) {
|
|
2036
|
+
if (a === b) return true;
|
|
2037
|
+
if (a.length !== b.length) return false;
|
|
2038
|
+
for (let i = 0; i < a.length; i++) {
|
|
2039
|
+
const ca = a.charCodeAt(i);
|
|
2040
|
+
const cb = b.charCodeAt(i);
|
|
2041
|
+
if (ca === cb) continue;
|
|
2042
|
+
const fa = ca >= 65 && ca <= 90 ? ca + 32 : ca;
|
|
2043
|
+
const fb = cb >= 65 && cb <= 90 ? cb + 32 : cb;
|
|
2044
|
+
if (fa !== fb) return false;
|
|
2045
|
+
}
|
|
2046
|
+
return true;
|
|
2047
|
+
}
|
|
2048
|
+
function reconcileKeyedChildren(parent, newChildren, oldKeyMap) {
|
|
2049
|
+
const { keyedVnodes, unkeyedVnodes } = partitionChildren(newChildren);
|
|
1844
2050
|
const fastPathResult = tryFastPaths(
|
|
1845
2051
|
parent,
|
|
1846
2052
|
newChildren,
|
|
@@ -1851,20 +2057,6 @@ function reconcileKeyedChildren(parent, newChildren, oldKeyMap) {
|
|
|
1851
2057
|
if (fastPathResult) return fastPathResult;
|
|
1852
2058
|
return performFullReconciliation(parent, newChildren, keyedVnodes, oldKeyMap);
|
|
1853
2059
|
}
|
|
1854
|
-
function logReconcileDebug(newChildren) {
|
|
1855
|
-
if (process.env.NODE_ENV !== "production") {
|
|
1856
|
-
try {
|
|
1857
|
-
logger.warn(
|
|
1858
|
-
"[Askr][RECONCILE] reconcileKeyedChildren newChildren sample",
|
|
1859
|
-
{
|
|
1860
|
-
sample: newChildren && newChildren.length && newChildren[0] || null,
|
|
1861
|
-
len: newChildren.length
|
|
1862
|
-
}
|
|
1863
|
-
);
|
|
1864
|
-
} catch {
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
2060
|
function partitionChildren(newChildren) {
|
|
1869
2061
|
const keyedVnodes = [];
|
|
1870
2062
|
const unkeyedVnodes = [];
|
|
@@ -1922,7 +2114,6 @@ function tryPositionalBulkUpdate(parent, keyedVnodes) {
|
|
|
1922
2114
|
const total = keyedVnodes.length;
|
|
1923
2115
|
if (total < 10) return null;
|
|
1924
2116
|
const matchCount = countPositionalMatches(parent, keyedVnodes);
|
|
1925
|
-
logPositionalCheck(total, matchCount, parent.children.length);
|
|
1926
2117
|
if (matchCount / total < 0.9) return null;
|
|
1927
2118
|
if (hasPositionalPropChanges(parent, keyedVnodes)) return null;
|
|
1928
2119
|
try {
|
|
@@ -1943,7 +2134,7 @@ function countPositionalMatches(parent, keyedVnodes) {
|
|
|
1943
2134
|
continue;
|
|
1944
2135
|
const el = parent.children[i];
|
|
1945
2136
|
if (!el) continue;
|
|
1946
|
-
if (el.tagName
|
|
2137
|
+
if (tagNamesEqualIgnoreCase2(el.tagName, vnode.type)) {
|
|
1947
2138
|
matchCount++;
|
|
1948
2139
|
}
|
|
1949
2140
|
}
|
|
@@ -1951,18 +2142,6 @@ function countPositionalMatches(parent, keyedVnodes) {
|
|
|
1951
2142
|
}
|
|
1952
2143
|
return matchCount;
|
|
1953
2144
|
}
|
|
1954
|
-
function logPositionalCheck(total, matchCount, parentChildren) {
|
|
1955
|
-
if (process.env.NODE_ENV !== "production") {
|
|
1956
|
-
try {
|
|
1957
|
-
logger.warn("[Askr][FASTPATH] positional check", {
|
|
1958
|
-
total,
|
|
1959
|
-
matchCount,
|
|
1960
|
-
parentChildren
|
|
1961
|
-
});
|
|
1962
|
-
} catch {
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
2145
|
function hasPositionalPropChanges(parent, keyedVnodes) {
|
|
1967
2146
|
try {
|
|
1968
2147
|
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
@@ -1981,9 +2160,7 @@ function hasPositionalPropChanges(parent, keyedVnodes) {
|
|
|
1981
2160
|
function rebuildKeyedMap(parent) {
|
|
1982
2161
|
try {
|
|
1983
2162
|
const map = /* @__PURE__ */ new Map();
|
|
1984
|
-
|
|
1985
|
-
for (let i = 0; i < children.length; i++) {
|
|
1986
|
-
const el = children[i];
|
|
2163
|
+
for (let el = parent.firstElementChild; el; el = el.nextElementSibling) {
|
|
1987
2164
|
const k = el.getAttribute("data-key");
|
|
1988
2165
|
if (k !== null) {
|
|
1989
2166
|
map.set(k, el);
|
|
@@ -2044,18 +2221,19 @@ function createOldElResolver(parent, oldKeyMap, usedOldEls) {
|
|
|
2044
2221
|
}
|
|
2045
2222
|
function scanForElementByKey(parent, k, keyStr, usedOldEls) {
|
|
2046
2223
|
try {
|
|
2047
|
-
|
|
2048
|
-
for (const ch of children) {
|
|
2224
|
+
for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {
|
|
2049
2225
|
if (usedOldEls.has(ch)) continue;
|
|
2050
2226
|
const attr = ch.getAttribute("data-key");
|
|
2051
2227
|
if (attr === keyStr) {
|
|
2052
2228
|
usedOldEls.add(ch);
|
|
2053
2229
|
return ch;
|
|
2054
2230
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2231
|
+
if (attr !== null) {
|
|
2232
|
+
const numAttr = Number(attr);
|
|
2233
|
+
if (!Number.isNaN(numAttr) && numAttr === k) {
|
|
2234
|
+
usedOldEls.add(ch);
|
|
2235
|
+
return ch;
|
|
2236
|
+
}
|
|
2059
2237
|
}
|
|
2060
2238
|
}
|
|
2061
2239
|
} catch {
|
|
@@ -2072,9 +2250,17 @@ function reconcileSingleChild(child, index, parent, resolveOldElOnce, usedOldEls
|
|
|
2072
2250
|
function reconcileKeyedChild(child, key, parent, resolveOldElOnce, newKeyMap) {
|
|
2073
2251
|
const el = resolveOldElOnce(key);
|
|
2074
2252
|
if (el && el.parentElement === parent) {
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2253
|
+
try {
|
|
2254
|
+
const childObj = child;
|
|
2255
|
+
if (childObj && typeof childObj === "object" && typeof childObj.type === "string") {
|
|
2256
|
+
if (tagNamesEqualIgnoreCase2(el.tagName, childObj.type)) {
|
|
2257
|
+
updateElementFromVnode(el, child);
|
|
2258
|
+
newKeyMap.set(key, el);
|
|
2259
|
+
return el;
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
} catch {
|
|
2263
|
+
}
|
|
2078
2264
|
}
|
|
2079
2265
|
const dom = createDOMNode(child);
|
|
2080
2266
|
if (dom) {
|
|
@@ -2111,13 +2297,16 @@ function canReuseElement(existing, child) {
|
|
|
2111
2297
|
if (typeof child !== "object" || child === null || !("type" in child))
|
|
2112
2298
|
return false;
|
|
2113
2299
|
const childObj = child;
|
|
2114
|
-
const
|
|
2115
|
-
|
|
2300
|
+
const existingKey = existing.getAttribute("data-key");
|
|
2301
|
+
const hasNoKey = existingKey === null || existingKey === void 0;
|
|
2302
|
+
return hasNoKey && typeof childObj.type === "string" && tagNamesEqualIgnoreCase2(existing.tagName, childObj.type);
|
|
2116
2303
|
}
|
|
2117
2304
|
function findAvailableUnkeyedElement(parent, usedOldEls) {
|
|
2118
|
-
|
|
2119
|
-
(
|
|
2120
|
-
|
|
2305
|
+
for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {
|
|
2306
|
+
if (usedOldEls.has(ch)) continue;
|
|
2307
|
+
if (ch.getAttribute("data-key") === null) return ch;
|
|
2308
|
+
}
|
|
2309
|
+
return void 0;
|
|
2121
2310
|
}
|
|
2122
2311
|
function tryReuseElement(avail, child, usedOldEls) {
|
|
2123
2312
|
if (typeof child === "string" || typeof child === "number") {
|
|
@@ -2127,7 +2316,7 @@ function tryReuseElement(avail, child, usedOldEls) {
|
|
|
2127
2316
|
}
|
|
2128
2317
|
if (typeof child === "object" && child !== null && "type" in child) {
|
|
2129
2318
|
const childObj = child;
|
|
2130
|
-
if (typeof childObj.type === "string" && avail.tagName
|
|
2319
|
+
if (typeof childObj.type === "string" && tagNamesEqualIgnoreCase2(avail.tagName, childObj.type)) {
|
|
2131
2320
|
updateElementFromVnode(avail, child);
|
|
2132
2321
|
usedOldEls.add(avail);
|
|
2133
2322
|
return avail;
|
|
@@ -2141,10 +2330,11 @@ function commitReconciliation(parent, finalNodes) {
|
|
|
2141
2330
|
fragment.appendChild(finalNodes[i]);
|
|
2142
2331
|
}
|
|
2143
2332
|
try {
|
|
2144
|
-
|
|
2145
|
-
|
|
2333
|
+
for (let n = parent.firstChild; n; ) {
|
|
2334
|
+
const next = n.nextSibling;
|
|
2146
2335
|
if (n instanceof Element) removeAllListeners(n);
|
|
2147
2336
|
cleanupInstanceIfPresent(n);
|
|
2337
|
+
n = next;
|
|
2148
2338
|
}
|
|
2149
2339
|
} catch {
|
|
2150
2340
|
}
|
|
@@ -2157,14 +2347,26 @@ var init_reconcile = __esm({
|
|
|
2157
2347
|
init_dom();
|
|
2158
2348
|
init_keyed();
|
|
2159
2349
|
init_cleanup();
|
|
2160
|
-
|
|
2350
|
+
init_fastlane();
|
|
2161
2351
|
init_fastpath();
|
|
2162
|
-
init_logger();
|
|
2163
2352
|
init_utils();
|
|
2164
2353
|
}
|
|
2165
2354
|
});
|
|
2166
2355
|
|
|
2167
2356
|
// src/renderer/evaluate.ts
|
|
2357
|
+
function tagNamesEqualIgnoreCase3(a, b) {
|
|
2358
|
+
if (a === b) return true;
|
|
2359
|
+
if (a.length !== b.length) return false;
|
|
2360
|
+
for (let i = 0; i < a.length; i++) {
|
|
2361
|
+
const ca = a.charCodeAt(i);
|
|
2362
|
+
const cb = b.charCodeAt(i);
|
|
2363
|
+
if (ca === cb) continue;
|
|
2364
|
+
const fa = ca >= 65 && ca <= 90 ? ca + 32 : ca;
|
|
2365
|
+
const fb = cb >= 65 && cb <= 90 ? cb + 32 : cb;
|
|
2366
|
+
if (fa !== fb) return false;
|
|
2367
|
+
}
|
|
2368
|
+
return true;
|
|
2369
|
+
}
|
|
2168
2370
|
function checkSimpleText(vnodeChildren) {
|
|
2169
2371
|
if (!Array.isArray(vnodeChildren)) {
|
|
2170
2372
|
if (typeof vnodeChildren === "string" || typeof vnodeChildren === "number") {
|
|
@@ -2187,8 +2389,7 @@ function tryUpdateTextInPlace(element, text) {
|
|
|
2187
2389
|
}
|
|
2188
2390
|
function buildKeyMapFromDOM(parent) {
|
|
2189
2391
|
const keyMap = /* @__PURE__ */ new Map();
|
|
2190
|
-
|
|
2191
|
-
for (const child of children) {
|
|
2392
|
+
for (let child = parent.firstElementChild; child; child = child.nextElementSibling) {
|
|
2192
2393
|
const k = child.getAttribute("data-key");
|
|
2193
2394
|
if (k !== null) {
|
|
2194
2395
|
keyMap.set(k, child);
|
|
@@ -2209,9 +2410,10 @@ function getOrBuildKeyMap(parent) {
|
|
|
2209
2410
|
return keyMap.size > 0 ? keyMap : void 0;
|
|
2210
2411
|
}
|
|
2211
2412
|
function hasKeyedChildren(children) {
|
|
2212
|
-
|
|
2213
|
-
(
|
|
2214
|
-
|
|
2413
|
+
for (let i = 0; i < children.length; i++) {
|
|
2414
|
+
if (extractKey(children[i]) !== void 0) return true;
|
|
2415
|
+
}
|
|
2416
|
+
return false;
|
|
2215
2417
|
}
|
|
2216
2418
|
function trackBulkTextStats(stats) {
|
|
2217
2419
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -2328,12 +2530,16 @@ function smartUpdateElement(element, vnode) {
|
|
|
2328
2530
|
updateElementFromVnode(element, vnode, false);
|
|
2329
2531
|
}
|
|
2330
2532
|
function processFragmentChildren(target, childArray) {
|
|
2331
|
-
|
|
2533
|
+
let existingNode = target.firstElementChild;
|
|
2332
2534
|
for (let i = 0; i < childArray.length; i++) {
|
|
2333
2535
|
const childVnode = childArray[i];
|
|
2334
|
-
const
|
|
2335
|
-
if (existingNode && _isDOMElement(childVnode) && typeof childVnode.type === "string" &&
|
|
2536
|
+
const nextExisting = existingNode ? existingNode.nextElementSibling : null;
|
|
2537
|
+
if (existingNode && _isDOMElement(childVnode) && typeof childVnode.type === "string" && tagNamesEqualIgnoreCase3(
|
|
2538
|
+
existingNode.tagName,
|
|
2539
|
+
childVnode.type
|
|
2540
|
+
)) {
|
|
2336
2541
|
smartUpdateElement(existingNode, childVnode);
|
|
2542
|
+
existingNode = nextExisting;
|
|
2337
2543
|
continue;
|
|
2338
2544
|
}
|
|
2339
2545
|
const newDom = createDOMNode(childVnode);
|
|
@@ -2344,39 +2550,29 @@ function processFragmentChildren(target, childArray) {
|
|
|
2344
2550
|
target.appendChild(newDom);
|
|
2345
2551
|
}
|
|
2346
2552
|
}
|
|
2553
|
+
existingNode = nextExisting;
|
|
2347
2554
|
}
|
|
2348
|
-
while (
|
|
2349
|
-
|
|
2555
|
+
while (existingNode) {
|
|
2556
|
+
const next = existingNode.nextElementSibling;
|
|
2557
|
+
target.removeChild(existingNode);
|
|
2558
|
+
existingNode = next;
|
|
2350
2559
|
}
|
|
2351
2560
|
}
|
|
2352
|
-
function createWrappedEventHandler(handler) {
|
|
2353
|
-
return (event) => {
|
|
2354
|
-
globalScheduler.setInHandler(true);
|
|
2355
|
-
try {
|
|
2356
|
-
handler(event);
|
|
2357
|
-
} catch (error) {
|
|
2358
|
-
logger.error("[Askr] Event handler error:", error);
|
|
2359
|
-
} finally {
|
|
2360
|
-
globalScheduler.setInHandler(false);
|
|
2361
|
-
}
|
|
2362
|
-
};
|
|
2363
|
-
}
|
|
2364
2561
|
function applyPropsToElement2(el, props) {
|
|
2365
2562
|
for (const [key, value] of Object.entries(props)) {
|
|
2366
2563
|
if (key === "children" || key === "key") continue;
|
|
2367
2564
|
if (value === void 0 || value === null || value === false) continue;
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
const wrappedHandler =
|
|
2371
|
-
|
|
2372
|
-
|
|
2565
|
+
const eventName = parseEventName(key);
|
|
2566
|
+
if (eventName) {
|
|
2567
|
+
const wrappedHandler = createWrappedHandler(
|
|
2568
|
+
value,
|
|
2569
|
+
false
|
|
2570
|
+
);
|
|
2571
|
+
const options = getPassiveOptions(eventName);
|
|
2572
|
+
if (options !== void 0)
|
|
2373
2573
|
el.addEventListener(eventName, wrappedHandler, options);
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
}
|
|
2377
|
-
if (!elementListeners.has(el)) {
|
|
2378
|
-
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
2379
|
-
}
|
|
2574
|
+
else el.addEventListener(eventName, wrappedHandler);
|
|
2575
|
+
if (!elementListeners.has(el)) elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
2380
2576
|
elementListeners.get(el).set(eventName, {
|
|
2381
2577
|
handler: wrappedHandler,
|
|
2382
2578
|
original: value,
|
|
@@ -2426,11 +2622,11 @@ function evaluate(node, target, context) {
|
|
|
2426
2622
|
}
|
|
2427
2623
|
if (context && domRanges.has(context)) {
|
|
2428
2624
|
const range = domRanges.get(context);
|
|
2429
|
-
let
|
|
2430
|
-
while (
|
|
2431
|
-
const next =
|
|
2432
|
-
|
|
2433
|
-
|
|
2625
|
+
let current = range.start.nextSibling;
|
|
2626
|
+
while (current && current !== range.end) {
|
|
2627
|
+
const next = current.nextSibling;
|
|
2628
|
+
current.remove();
|
|
2629
|
+
current = next;
|
|
2434
2630
|
}
|
|
2435
2631
|
const dom = createDOMNode(node);
|
|
2436
2632
|
if (dom) {
|
|
@@ -2458,7 +2654,7 @@ function evaluate(node, target, context) {
|
|
|
2458
2654
|
}
|
|
2459
2655
|
}
|
|
2460
2656
|
const firstChild = target.children[0];
|
|
2461
|
-
if (firstChild && _isDOMElement(vnode) && typeof vnode.type === "string" && firstChild.tagName
|
|
2657
|
+
if (firstChild && _isDOMElement(vnode) && typeof vnode.type === "string" && tagNamesEqualIgnoreCase3(firstChild.tagName, vnode.type)) {
|
|
2462
2658
|
smartUpdateElement(firstChild, vnode);
|
|
2463
2659
|
} else {
|
|
2464
2660
|
target.textContent = "";
|
|
@@ -2476,7 +2672,6 @@ var domRanges;
|
|
|
2476
2672
|
var init_evaluate = __esm({
|
|
2477
2673
|
"src/renderer/evaluate.ts"() {
|
|
2478
2674
|
"use strict";
|
|
2479
|
-
init_scheduler();
|
|
2480
2675
|
init_logger();
|
|
2481
2676
|
init_cleanup();
|
|
2482
2677
|
init_keyed();
|
|
@@ -2484,7 +2679,8 @@ var init_evaluate = __esm({
|
|
|
2484
2679
|
init_types();
|
|
2485
2680
|
init_dom();
|
|
2486
2681
|
init_diag();
|
|
2487
|
-
|
|
2682
|
+
init_jsx();
|
|
2683
|
+
init_utils();
|
|
2488
2684
|
domRanges = /* @__PURE__ */ new WeakMap();
|
|
2489
2685
|
}
|
|
2490
2686
|
});
|
|
@@ -2564,23 +2760,6 @@ function createComponentInstance(id, fn, props, target) {
|
|
|
2564
2760
|
function getCurrentComponentInstance() {
|
|
2565
2761
|
return currentInstance;
|
|
2566
2762
|
}
|
|
2567
|
-
function setCurrentComponentInstance(instance) {
|
|
2568
|
-
currentInstance = instance;
|
|
2569
|
-
}
|
|
2570
|
-
function registerMountOperation(operation) {
|
|
2571
|
-
const instance = getCurrentComponentInstance();
|
|
2572
|
-
if (instance) {
|
|
2573
|
-
if (isBulkCommitActive2()) {
|
|
2574
|
-
if (process.env.NODE_ENV !== "production") {
|
|
2575
|
-
throw new Error(
|
|
2576
|
-
"registerMountOperation called during bulk commit fast-lane"
|
|
2577
|
-
);
|
|
2578
|
-
}
|
|
2579
|
-
return;
|
|
2580
|
-
}
|
|
2581
|
-
instance.mountOperations.push(operation);
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
2763
|
function executeMountOperations(instance) {
|
|
2585
2764
|
if (!instance.isRoot) return;
|
|
2586
2765
|
for (const operation of instance.mountOperations) {
|
|
@@ -2633,7 +2812,7 @@ function runComponent(instance) {
|
|
|
2633
2812
|
globalScheduler.enqueue(() => {
|
|
2634
2813
|
if (!instance.target && instance._placeholder) {
|
|
2635
2814
|
if (result === null || result === void 0) {
|
|
2636
|
-
|
|
2815
|
+
finalizeReadSubscriptions2(instance);
|
|
2637
2816
|
return;
|
|
2638
2817
|
}
|
|
2639
2818
|
const placeholder = instance._placeholder;
|
|
@@ -2653,7 +2832,7 @@ function runComponent(instance) {
|
|
|
2653
2832
|
instance.target = host;
|
|
2654
2833
|
instance._placeholder = void 0;
|
|
2655
2834
|
host.__ASKR_INSTANCE = instance;
|
|
2656
|
-
|
|
2835
|
+
finalizeReadSubscriptions2(instance);
|
|
2657
2836
|
} finally {
|
|
2658
2837
|
currentInstance = oldInstance;
|
|
2659
2838
|
}
|
|
@@ -2698,7 +2877,7 @@ function runComponent(instance) {
|
|
|
2698
2877
|
} finally {
|
|
2699
2878
|
currentInstance = oldInstance;
|
|
2700
2879
|
}
|
|
2701
|
-
|
|
2880
|
+
finalizeReadSubscriptions2(instance);
|
|
2702
2881
|
instance.mounted = true;
|
|
2703
2882
|
if (wasFirstMount && instance.mountOperations.length > 0) {
|
|
2704
2883
|
executeMountOperations(instance);
|
|
@@ -2750,7 +2929,7 @@ function renderComponentInline(instance) {
|
|
|
2750
2929
|
try {
|
|
2751
2930
|
const result = executeComponentSync(instance);
|
|
2752
2931
|
if (!hadToken) {
|
|
2753
|
-
|
|
2932
|
+
finalizeReadSubscriptions2(instance);
|
|
2754
2933
|
}
|
|
2755
2934
|
return result;
|
|
2756
2935
|
} finally {
|
|
@@ -2818,15 +2997,7 @@ function executeComponent(instance) {
|
|
|
2818
2997
|
function getCurrentInstance() {
|
|
2819
2998
|
return currentInstance;
|
|
2820
2999
|
}
|
|
2821
|
-
function
|
|
2822
|
-
if (!currentInstance) {
|
|
2823
|
-
throw new Error(
|
|
2824
|
-
"getSignal() can only be called during component render execution. Ensure you are calling this from inside your component function."
|
|
2825
|
-
);
|
|
2826
|
-
}
|
|
2827
|
-
return currentInstance.abortController.signal;
|
|
2828
|
-
}
|
|
2829
|
-
function finalizeReadSubscriptions(instance) {
|
|
3000
|
+
function finalizeReadSubscriptions2(instance) {
|
|
2830
3001
|
const newSet = instance._pendingReadStates ?? /* @__PURE__ */ new Set();
|
|
2831
3002
|
const oldSet = instance._lastReadStates ?? /* @__PURE__ */ new Set();
|
|
2832
3003
|
const token = instance._currentRenderToken;
|
|
@@ -2897,7 +3068,7 @@ var init_component = __esm({
|
|
|
2897
3068
|
init_context();
|
|
2898
3069
|
init_logger();
|
|
2899
3070
|
init_diag();
|
|
2900
|
-
|
|
3071
|
+
init_fastlane();
|
|
2901
3072
|
init_renderer();
|
|
2902
3073
|
currentInstance = null;
|
|
2903
3074
|
stateIndex = 0;
|
|
@@ -2905,97 +3076,6 @@ var init_component = __esm({
|
|
|
2905
3076
|
}
|
|
2906
3077
|
});
|
|
2907
3078
|
|
|
2908
|
-
// src/ssr/errors.ts
|
|
2909
|
-
var SSRDataMissingError;
|
|
2910
|
-
var init_errors = __esm({
|
|
2911
|
-
"src/ssr/errors.ts"() {
|
|
2912
|
-
"use strict";
|
|
2913
|
-
SSRDataMissingError = class _SSRDataMissingError extends Error {
|
|
2914
|
-
constructor(message = "Server-side rendering requires all data to be available synchronously. This component attempted to use async data during SSR.") {
|
|
2915
|
-
super(message);
|
|
2916
|
-
this.code = "SSR_DATA_MISSING";
|
|
2917
|
-
this.name = "SSRDataMissingError";
|
|
2918
|
-
Object.setPrototypeOf(this, _SSRDataMissingError.prototype);
|
|
2919
|
-
}
|
|
2920
|
-
};
|
|
2921
|
-
}
|
|
2922
|
-
});
|
|
2923
|
-
|
|
2924
|
-
// src/ssr/context.ts
|
|
2925
|
-
function withSSRContext(ctx, fn) {
|
|
2926
|
-
const prev = current;
|
|
2927
|
-
current = ctx;
|
|
2928
|
-
try {
|
|
2929
|
-
return fn();
|
|
2930
|
-
} finally {
|
|
2931
|
-
current = prev;
|
|
2932
|
-
}
|
|
2933
|
-
}
|
|
2934
|
-
function createRenderContext(seed = 12345) {
|
|
2935
|
-
return { seed };
|
|
2936
|
-
}
|
|
2937
|
-
function getCurrentSSRContext() {
|
|
2938
|
-
return currentSSRContext;
|
|
2939
|
-
}
|
|
2940
|
-
function runWithSSRContext(ctx, fn) {
|
|
2941
|
-
const prev = currentSSRContext;
|
|
2942
|
-
currentSSRContext = ctx;
|
|
2943
|
-
try {
|
|
2944
|
-
return fn();
|
|
2945
|
-
} finally {
|
|
2946
|
-
currentSSRContext = prev;
|
|
2947
|
-
}
|
|
2948
|
-
}
|
|
2949
|
-
function throwSSRDataMissing() {
|
|
2950
|
-
throw new SSRDataMissingError();
|
|
2951
|
-
}
|
|
2952
|
-
var current, currentSSRContext;
|
|
2953
|
-
var init_context2 = __esm({
|
|
2954
|
-
"src/ssr/context.ts"() {
|
|
2955
|
-
"use strict";
|
|
2956
|
-
init_errors();
|
|
2957
|
-
current = null;
|
|
2958
|
-
currentSSRContext = null;
|
|
2959
|
-
}
|
|
2960
|
-
});
|
|
2961
|
-
|
|
2962
|
-
// src/ssr/render-keys.ts
|
|
2963
|
-
function getCurrentRenderData() {
|
|
2964
|
-
return currentRenderData;
|
|
2965
|
-
}
|
|
2966
|
-
function resetKeyCounter() {
|
|
2967
|
-
keyCounter = 0;
|
|
2968
|
-
}
|
|
2969
|
-
function getNextKey() {
|
|
2970
|
-
return `r:${keyCounter++}`;
|
|
2971
|
-
}
|
|
2972
|
-
function startRenderPhase(data) {
|
|
2973
|
-
currentRenderData = data ?? null;
|
|
2974
|
-
resetKeyCounter();
|
|
2975
|
-
}
|
|
2976
|
-
function stopRenderPhase() {
|
|
2977
|
-
currentRenderData = null;
|
|
2978
|
-
resetKeyCounter();
|
|
2979
|
-
}
|
|
2980
|
-
async function resolvePlan(_plan) {
|
|
2981
|
-
throw new Error(
|
|
2982
|
-
`${PREPASS_REMOVED_MSG}; async resource plans are not supported`
|
|
2983
|
-
);
|
|
2984
|
-
}
|
|
2985
|
-
function collectResources(_opts) {
|
|
2986
|
-
throw new Error(`${PREPASS_REMOVED_MSG}; collectResources is disabled`);
|
|
2987
|
-
}
|
|
2988
|
-
var keyCounter, currentRenderData, PREPASS_REMOVED_MSG, resolveResources;
|
|
2989
|
-
var init_render_keys = __esm({
|
|
2990
|
-
"src/ssr/render-keys.ts"() {
|
|
2991
|
-
"use strict";
|
|
2992
|
-
keyCounter = 0;
|
|
2993
|
-
currentRenderData = null;
|
|
2994
|
-
PREPASS_REMOVED_MSG = "SSR collection/prepass is removed: SSR is strictly synchronous";
|
|
2995
|
-
resolveResources = resolvePlan;
|
|
2996
|
-
}
|
|
2997
|
-
});
|
|
2998
|
-
|
|
2999
3079
|
// src/router/match.ts
|
|
3000
3080
|
function match(path, pattern) {
|
|
3001
3081
|
const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
@@ -3034,6 +3114,29 @@ var init_match = __esm({
|
|
|
3034
3114
|
}
|
|
3035
3115
|
});
|
|
3036
3116
|
|
|
3117
|
+
// src/runtime/execution-model.ts
|
|
3118
|
+
function getExecutionModel() {
|
|
3119
|
+
const g = globalThis;
|
|
3120
|
+
return g[EXECUTION_MODEL_KEY];
|
|
3121
|
+
}
|
|
3122
|
+
function assertExecutionModel(model) {
|
|
3123
|
+
const g = globalThis;
|
|
3124
|
+
const cur = g[EXECUTION_MODEL_KEY];
|
|
3125
|
+
if (cur && cur !== model) {
|
|
3126
|
+
throw new Error(
|
|
3127
|
+
`[Askr] mixing execution models is not allowed (current: ${cur}, attempted: ${model}). Choose exactly one: createSPA, createSSR, or createIslands.`
|
|
3128
|
+
);
|
|
3129
|
+
}
|
|
3130
|
+
if (!cur) g[EXECUTION_MODEL_KEY] = model;
|
|
3131
|
+
}
|
|
3132
|
+
var EXECUTION_MODEL_KEY;
|
|
3133
|
+
var init_execution_model = __esm({
|
|
3134
|
+
"src/runtime/execution-model.ts"() {
|
|
3135
|
+
"use strict";
|
|
3136
|
+
EXECUTION_MODEL_KEY = /* @__PURE__ */ Symbol.for("__ASKR_EXECUTION_MODEL__");
|
|
3137
|
+
}
|
|
3138
|
+
});
|
|
3139
|
+
|
|
3037
3140
|
// src/router/route.ts
|
|
3038
3141
|
var route_exports = {};
|
|
3039
3142
|
__export(route_exports, {
|
|
@@ -3050,6 +3153,13 @@ __export(route_exports, {
|
|
|
3050
3153
|
setServerLocation: () => setServerLocation,
|
|
3051
3154
|
unloadNamespace: () => unloadNamespace
|
|
3052
3155
|
});
|
|
3156
|
+
function setHasRoutes(value) {
|
|
3157
|
+
try {
|
|
3158
|
+
const g = globalThis;
|
|
3159
|
+
g[HAS_ROUTES_KEY] = value;
|
|
3160
|
+
} catch {
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3053
3163
|
function getDepth(path) {
|
|
3054
3164
|
const normalized = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
3055
3165
|
return normalized === "/" ? 0 : normalized.split("/").filter(Boolean).length;
|
|
@@ -3168,6 +3278,11 @@ function _unlockRouteRegistrationForTests() {
|
|
|
3168
3278
|
registrationLocked = false;
|
|
3169
3279
|
}
|
|
3170
3280
|
function route(path, handler, namespace) {
|
|
3281
|
+
if (getExecutionModel() === "islands") {
|
|
3282
|
+
throw new Error(
|
|
3283
|
+
"Routes are not supported with islands. Use createSPA (client) or createSSR (server) instead."
|
|
3284
|
+
);
|
|
3285
|
+
}
|
|
3171
3286
|
if (typeof path === "undefined") {
|
|
3172
3287
|
const instance = getCurrentComponentInstance();
|
|
3173
3288
|
if (!instance) {
|
|
@@ -3210,7 +3325,7 @@ function route(path, handler, namespace) {
|
|
|
3210
3325
|
}
|
|
3211
3326
|
if (registrationLocked) {
|
|
3212
3327
|
throw new Error(
|
|
3213
|
-
"Route registration is locked after app startup. Register routes at module load time before calling
|
|
3328
|
+
"Route registration is locked after app startup. Register routes at module load time before calling createSPA or createSSR."
|
|
3214
3329
|
);
|
|
3215
3330
|
}
|
|
3216
3331
|
if (typeof handler !== "function") {
|
|
@@ -3220,6 +3335,7 @@ function route(path, handler, namespace) {
|
|
|
3220
3335
|
}
|
|
3221
3336
|
const routeObj = { path, handler, namespace };
|
|
3222
3337
|
routes.push(routeObj);
|
|
3338
|
+
setHasRoutes(true);
|
|
3223
3339
|
const depth = getDepth(path);
|
|
3224
3340
|
let depthRoutes = routesByDepth.get(depth);
|
|
3225
3341
|
if (!depthRoutes) {
|
|
@@ -3243,1373 +3359,303 @@ function unloadNamespace(namespace) {
|
|
|
3243
3359
|
if (routes[i].namespace === namespace) {
|
|
3244
3360
|
const removed = routes[i];
|
|
3245
3361
|
routes.splice(i, 1);
|
|
3246
|
-
const depth = getDepth(removed.path);
|
|
3247
|
-
const depthRoutes = routesByDepth.get(depth);
|
|
3248
|
-
if (depthRoutes) {
|
|
3249
|
-
const idx = depthRoutes.indexOf(removed);
|
|
3250
|
-
if (idx >= 0) {
|
|
3251
|
-
depthRoutes.splice(idx, 1);
|
|
3252
|
-
}
|
|
3253
|
-
}
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
namespaces.delete(namespace);
|
|
3257
|
-
return before - routes.length;
|
|
3258
|
-
}
|
|
3259
|
-
function clearRoutes() {
|
|
3260
|
-
routes.length = 0;
|
|
3261
|
-
namespaces.clear();
|
|
3262
|
-
routesByDepth.clear();
|
|
3263
|
-
}
|
|
3264
|
-
function normalizeHandler(handler) {
|
|
3265
|
-
if (handler == null) return void 0;
|
|
3266
|
-
if (typeof handler === "function") {
|
|
3267
|
-
return (params, ctx) => {
|
|
3268
|
-
try {
|
|
3269
|
-
return handler(params, ctx);
|
|
3270
|
-
} catch {
|
|
3271
|
-
return handler(params);
|
|
3272
|
-
}
|
|
3273
|
-
};
|
|
3274
|
-
}
|
|
3275
|
-
return void 0;
|
|
3276
|
-
}
|
|
3277
|
-
function registerRoute(path, handler, ...children) {
|
|
3278
|
-
const isRelative = !path.startsWith("/");
|
|
3279
|
-
const descriptor = {
|
|
3280
|
-
path,
|
|
3281
|
-
handler,
|
|
3282
|
-
children: children.filter(Boolean),
|
|
3283
|
-
_isDescriptor: true
|
|
3284
|
-
};
|
|
3285
|
-
if (!isRelative) {
|
|
3286
|
-
const normalized = normalizeHandler(handler);
|
|
3287
|
-
if (handler != null && !normalized) {
|
|
3288
|
-
throw new Error(
|
|
3289
|
-
"registerRoute(path, handler) requires a function handler. Passing JSX elements or VNodes directly is not supported."
|
|
3290
|
-
);
|
|
3291
|
-
}
|
|
3292
|
-
if (normalized) route(path, normalized);
|
|
3293
|
-
for (const child of descriptor.children || []) {
|
|
3294
|
-
const base = path === "/" ? "" : path.replace(/\/$/, "");
|
|
3295
|
-
const childPath = `${base}/${child.path.replace(/^\//, "")}`.replace(
|
|
3296
|
-
/\/\//g,
|
|
3297
|
-
"/"
|
|
3298
|
-
);
|
|
3299
|
-
if (child.handler) {
|
|
3300
|
-
const childNormalized = normalizeHandler(child.handler);
|
|
3301
|
-
if (!childNormalized) {
|
|
3302
|
-
throw new Error(
|
|
3303
|
-
"registerRoute child handler must be a function. Passing JSX elements directly is not supported."
|
|
3304
|
-
);
|
|
3305
|
-
}
|
|
3306
|
-
if (childNormalized) route(childPath, childNormalized);
|
|
3307
|
-
}
|
|
3308
|
-
if (child.children && child.children.length) {
|
|
3309
|
-
registerRoute(
|
|
3310
|
-
childPath,
|
|
3311
|
-
null,
|
|
3312
|
-
...child.children
|
|
3313
|
-
);
|
|
3314
|
-
}
|
|
3315
|
-
}
|
|
3316
|
-
return descriptor;
|
|
3317
|
-
}
|
|
3318
|
-
return descriptor;
|
|
3319
|
-
}
|
|
3320
|
-
function getLoadedNamespaces() {
|
|
3321
|
-
return Array.from(namespaces);
|
|
3322
|
-
}
|
|
3323
|
-
function resolveRoute(pathname) {
|
|
3324
|
-
const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
|
|
3325
|
-
const depth = normalized === "/" ? 0 : normalized.split("/").filter(Boolean).length;
|
|
3326
|
-
const candidates = [];
|
|
3327
|
-
const depthRoutes = routesByDepth.get(depth);
|
|
3328
|
-
if (depthRoutes) {
|
|
3329
|
-
for (const r of depthRoutes) {
|
|
3330
|
-
const result = match(pathname, r.path);
|
|
3331
|
-
if (result.matched) {
|
|
3332
|
-
candidates.push({
|
|
3333
|
-
route: r,
|
|
3334
|
-
specificity: getSpecificity(r.path),
|
|
3335
|
-
params: result.params
|
|
3336
|
-
});
|
|
3337
|
-
}
|
|
3338
|
-
}
|
|
3339
|
-
}
|
|
3340
|
-
for (const r of routes) {
|
|
3341
|
-
if (depthRoutes?.includes(r)) continue;
|
|
3342
|
-
const result = match(pathname, r.path);
|
|
3343
|
-
if (result.matched) {
|
|
3344
|
-
candidates.push({
|
|
3345
|
-
route: r,
|
|
3346
|
-
specificity: getSpecificity(r.path),
|
|
3347
|
-
params: result.params
|
|
3348
|
-
});
|
|
3349
|
-
}
|
|
3350
|
-
}
|
|
3351
|
-
candidates.sort((a, b) => b.specificity - a.specificity);
|
|
3352
|
-
if (candidates.length > 0) {
|
|
3353
|
-
const best = candidates[0];
|
|
3354
|
-
return { handler: best.route.handler, params: best.params };
|
|
3355
|
-
}
|
|
3356
|
-
return null;
|
|
3357
|
-
}
|
|
3358
|
-
var routes, namespaces, routesByDepth, serverLocation, registrationLocked;
|
|
3359
|
-
var init_route = __esm({
|
|
3360
|
-
"src/router/route.ts"() {
|
|
3361
|
-
"use strict";
|
|
3362
|
-
init_match();
|
|
3363
|
-
init_component();
|
|
3364
|
-
routes = [];
|
|
3365
|
-
namespaces = /* @__PURE__ */ new Set();
|
|
3366
|
-
routesByDepth = /* @__PURE__ */ new Map();
|
|
3367
|
-
serverLocation = null;
|
|
3368
|
-
registrationLocked = false;
|
|
3369
|
-
}
|
|
3370
|
-
});
|
|
3371
|
-
|
|
3372
|
-
// src/router/navigate.ts
|
|
3373
|
-
var navigate_exports = {};
|
|
3374
|
-
__export(navigate_exports, {
|
|
3375
|
-
cleanupNavigation: () => cleanupNavigation,
|
|
3376
|
-
initializeNavigation: () => initializeNavigation,
|
|
3377
|
-
navigate: () => navigate,
|
|
3378
|
-
registerAppInstance: () => registerAppInstance
|
|
3379
|
-
});
|
|
3380
|
-
function registerAppInstance(instance, _path) {
|
|
3381
|
-
currentInstance2 = instance;
|
|
3382
|
-
if (process.env.NODE_ENV === "production") {
|
|
3383
|
-
lockRouteRegistration();
|
|
3384
|
-
}
|
|
3385
|
-
}
|
|
3386
|
-
function navigate(path) {
|
|
3387
|
-
if (typeof window === "undefined") {
|
|
3388
|
-
return;
|
|
3389
|
-
}
|
|
3390
|
-
const resolved = resolveRoute(path);
|
|
3391
|
-
if (!resolved) {
|
|
3392
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3393
|
-
logger.warn(`No route found for path: ${path}`);
|
|
3394
|
-
}
|
|
3395
|
-
return;
|
|
3396
|
-
}
|
|
3397
|
-
window.history.pushState({ path }, "", path);
|
|
3398
|
-
if (currentInstance2) {
|
|
3399
|
-
cleanupComponent(currentInstance2);
|
|
3400
|
-
currentInstance2.fn = resolved.handler;
|
|
3401
|
-
currentInstance2.props = resolved.params;
|
|
3402
|
-
currentInstance2.stateValues = [];
|
|
3403
|
-
currentInstance2.expectedStateIndices = [];
|
|
3404
|
-
currentInstance2.firstRenderComplete = false;
|
|
3405
|
-
currentInstance2.stateIndexCheck = -1;
|
|
3406
|
-
currentInstance2.evaluationGeneration++;
|
|
3407
|
-
currentInstance2.notifyUpdate = null;
|
|
3408
|
-
currentInstance2.abortController = new AbortController();
|
|
3409
|
-
mountComponent(currentInstance2);
|
|
3410
|
-
}
|
|
3411
|
-
}
|
|
3412
|
-
function handlePopState(_event) {
|
|
3413
|
-
const path = window.location.pathname;
|
|
3414
|
-
if (!currentInstance2) {
|
|
3415
|
-
return;
|
|
3416
|
-
}
|
|
3417
|
-
const resolved = resolveRoute(path);
|
|
3418
|
-
if (resolved) {
|
|
3419
|
-
cleanupComponent(currentInstance2);
|
|
3420
|
-
currentInstance2.fn = resolved.handler;
|
|
3421
|
-
currentInstance2.props = resolved.params;
|
|
3422
|
-
currentInstance2.stateValues = [];
|
|
3423
|
-
currentInstance2.expectedStateIndices = [];
|
|
3424
|
-
currentInstance2.firstRenderComplete = false;
|
|
3425
|
-
currentInstance2.stateIndexCheck = -1;
|
|
3426
|
-
currentInstance2.evaluationGeneration++;
|
|
3427
|
-
currentInstance2.notifyUpdate = null;
|
|
3428
|
-
currentInstance2.abortController = new AbortController();
|
|
3429
|
-
mountComponent(currentInstance2);
|
|
3430
|
-
}
|
|
3431
|
-
}
|
|
3432
|
-
function initializeNavigation() {
|
|
3433
|
-
if (typeof window !== "undefined") {
|
|
3434
|
-
window.addEventListener("popstate", handlePopState);
|
|
3435
|
-
}
|
|
3436
|
-
}
|
|
3437
|
-
function cleanupNavigation() {
|
|
3438
|
-
if (typeof window !== "undefined") {
|
|
3439
|
-
window.removeEventListener("popstate", handlePopState);
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
3442
|
-
var currentInstance2;
|
|
3443
|
-
var init_navigate = __esm({
|
|
3444
|
-
"src/router/navigate.ts"() {
|
|
3445
|
-
"use strict";
|
|
3446
|
-
init_route();
|
|
3447
|
-
init_component();
|
|
3448
|
-
init_logger();
|
|
3449
|
-
currentInstance2 = null;
|
|
3450
|
-
}
|
|
3451
|
-
});
|
|
3452
|
-
|
|
3453
|
-
// src/jsx/utils.ts
|
|
3454
|
-
function isElement(value) {
|
|
3455
|
-
return typeof value === "object" && value !== null && value.$$typeof === ELEMENT_TYPE;
|
|
3456
|
-
}
|
|
3457
|
-
function cloneElement(element, props) {
|
|
3458
|
-
return {
|
|
3459
|
-
...element,
|
|
3460
|
-
props: { ...element.props, ...props }
|
|
3461
|
-
};
|
|
3462
|
-
}
|
|
3463
|
-
var init_utils2 = __esm({
|
|
3464
|
-
"src/jsx/utils.ts"() {
|
|
3465
|
-
"use strict";
|
|
3466
|
-
init_types2();
|
|
3467
|
-
}
|
|
3468
|
-
});
|
|
3469
|
-
|
|
3470
|
-
// src/jsx/index.ts
|
|
3471
|
-
var init_jsx = __esm({
|
|
3472
|
-
"src/jsx/index.ts"() {
|
|
3473
|
-
"use strict";
|
|
3474
|
-
init_types2();
|
|
3475
|
-
init_utils2();
|
|
3476
|
-
}
|
|
3477
|
-
});
|
|
3478
|
-
|
|
3479
|
-
// src/foundations/portal.tsx
|
|
3480
|
-
function definePortal() {
|
|
3481
|
-
if (typeof createPortalSlot !== "function") {
|
|
3482
|
-
let HostFallback2 = function() {
|
|
3483
|
-
hosts = hosts.filter((h) => h.mounted !== false);
|
|
3484
|
-
const inst = getCurrentComponentInstance();
|
|
3485
|
-
if (inst && !hosts.includes(inst)) hosts.push(inst);
|
|
3486
|
-
const owner = hosts.find((h) => h.mounted === true) || null;
|
|
3487
|
-
const mountedHosts = hosts.filter((h) => h.mounted === true);
|
|
3488
|
-
if (mountedHosts.length > 1) {
|
|
3489
|
-
logger.warn(
|
|
3490
|
-
"[Portal] multiple hosts are mounted for same portal; first mounted host will be owner"
|
|
3491
|
-
);
|
|
3492
|
-
}
|
|
3493
|
-
if (inst && owner && owner !== inst) {
|
|
3494
|
-
logger.debug(
|
|
3495
|
-
"[Portal] non-owner reader detected; only owner renders portal content"
|
|
3496
|
-
);
|
|
3497
|
-
}
|
|
3498
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3499
|
-
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3500
|
-
ns.__PORTAL_READS = (ns.__PORTAL_READS || 0) + 1;
|
|
3501
|
-
}
|
|
3502
|
-
if (process.env.NODE_ENV !== "production" && inst && owner && inst === owner) {
|
|
3503
|
-
logger.debug("[Portal] owner read ->", inst.id, "pending=", pending);
|
|
3504
|
-
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3505
|
-
ns.__PORTAL_HOST_ATTACHED = !!(inst && inst.target);
|
|
3506
|
-
ns.__PORTAL_HOST_ID = inst ? inst.id : void 0;
|
|
3507
|
-
}
|
|
3508
|
-
return inst === owner ? pending : void 0;
|
|
3509
|
-
};
|
|
3510
|
-
var HostFallback = HostFallback2;
|
|
3511
|
-
let hosts = [];
|
|
3512
|
-
let pending;
|
|
3513
|
-
HostFallback2.render = function RenderFallback(props) {
|
|
3514
|
-
hosts = hosts.filter((h) => h.mounted !== false);
|
|
3515
|
-
const owner = hosts.find((h) => h.mounted === true) || null;
|
|
3516
|
-
if (!owner) {
|
|
3517
|
-
logger.debug(
|
|
3518
|
-
"[Portal] fallback.write dropped -> no owner or not mounted",
|
|
3519
|
-
props?.children
|
|
3520
|
-
);
|
|
3521
|
-
return null;
|
|
3522
|
-
}
|
|
3523
|
-
pending = props.children;
|
|
3524
|
-
logger.debug("[Portal] fallback.write ->", pending, "owner=", owner.id);
|
|
3525
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3526
|
-
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3527
|
-
ns.__PORTAL_WRITES = (ns.__PORTAL_WRITES || 0) + 1;
|
|
3528
|
-
}
|
|
3529
|
-
if (owner && owner.notifyUpdate) {
|
|
3530
|
-
if (process.env.NODE_ENV !== "production")
|
|
3531
|
-
logger.debug(
|
|
3532
|
-
"[Portal] fallback.write notify ->",
|
|
3533
|
-
owner.id,
|
|
3534
|
-
!!owner.notifyUpdate
|
|
3535
|
-
);
|
|
3536
|
-
owner.notifyUpdate();
|
|
3537
|
-
}
|
|
3538
|
-
return null;
|
|
3539
|
-
};
|
|
3540
|
-
return HostFallback2;
|
|
3541
|
-
}
|
|
3542
|
-
const slot = createPortalSlot();
|
|
3543
|
-
function PortalHost() {
|
|
3544
|
-
return slot.read();
|
|
3545
|
-
}
|
|
3546
|
-
PortalHost.render = function PortalRender(props) {
|
|
3547
|
-
logger.debug("[Portal] write ->", props?.children);
|
|
3548
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3549
|
-
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3550
|
-
ns.__PORTAL_WRITES = (ns.__PORTAL_WRITES || 0) + 1;
|
|
3551
|
-
}
|
|
3552
|
-
slot.write(props.children);
|
|
3553
|
-
return null;
|
|
3554
|
-
};
|
|
3555
|
-
return PortalHost;
|
|
3556
|
-
}
|
|
3557
|
-
function _resetDefaultPortal() {
|
|
3558
|
-
_defaultPortal = void 0;
|
|
3559
|
-
_defaultPortalIsFallback = false;
|
|
3560
|
-
}
|
|
3561
|
-
function ensureDefaultPortal() {
|
|
3562
|
-
logger.debug(
|
|
3563
|
-
"[DefaultPortal] ensureDefaultPortal _defaultPortalIsFallback=",
|
|
3564
|
-
_defaultPortalIsFallback,
|
|
3565
|
-
"createPortalSlot=",
|
|
3566
|
-
typeof createPortalSlot === "function"
|
|
3567
|
-
);
|
|
3568
|
-
if (!_defaultPortal) {
|
|
3569
|
-
if (typeof createPortalSlot === "function") {
|
|
3570
|
-
_defaultPortal = definePortal();
|
|
3571
|
-
_defaultPortalIsFallback = false;
|
|
3572
|
-
logger.debug("[DefaultPortal] created real portal");
|
|
3573
|
-
} else {
|
|
3574
|
-
_defaultPortal = definePortal();
|
|
3575
|
-
_defaultPortalIsFallback = true;
|
|
3576
|
-
logger.debug("[DefaultPortal] created fallback portal");
|
|
3577
|
-
}
|
|
3578
|
-
return _defaultPortal;
|
|
3579
|
-
}
|
|
3580
|
-
if (_defaultPortalIsFallback && typeof createPortalSlot === "function") {
|
|
3581
|
-
const real = definePortal();
|
|
3582
|
-
_defaultPortal = real;
|
|
3583
|
-
_defaultPortalIsFallback = false;
|
|
3584
|
-
}
|
|
3585
|
-
if (!_defaultPortalIsFallback && typeof createPortalSlot !== "function") {
|
|
3586
|
-
const fallback = definePortal();
|
|
3587
|
-
_defaultPortal = fallback;
|
|
3588
|
-
_defaultPortalIsFallback = true;
|
|
3589
|
-
logger.debug("[DefaultPortal] reverted to fallback portal");
|
|
3590
|
-
}
|
|
3591
|
-
return _defaultPortal;
|
|
3592
|
-
}
|
|
3593
|
-
var _defaultPortal, _defaultPortalIsFallback, DefaultPortal;
|
|
3594
|
-
var init_portal = __esm({
|
|
3595
|
-
"src/foundations/portal.tsx"() {
|
|
3596
|
-
"use strict";
|
|
3597
|
-
init_component();
|
|
3598
|
-
init_logger();
|
|
3599
|
-
_defaultPortalIsFallback = false;
|
|
3600
|
-
DefaultPortal = (() => {
|
|
3601
|
-
function Host() {
|
|
3602
|
-
const v = ensureDefaultPortal()();
|
|
3603
|
-
return v === void 0 ? null : v;
|
|
3604
|
-
}
|
|
3605
|
-
Host.render = function Render(props) {
|
|
3606
|
-
ensureDefaultPortal().render(props);
|
|
3607
|
-
return null;
|
|
3608
|
-
};
|
|
3609
|
-
return Host;
|
|
3610
|
-
})();
|
|
3611
|
-
}
|
|
3612
|
-
});
|
|
3613
|
-
|
|
3614
|
-
// src/ssr/escape.ts
|
|
3615
|
-
function escapeText(text) {
|
|
3616
|
-
const useCache = text.length <= 64;
|
|
3617
|
-
if (useCache) {
|
|
3618
|
-
const cached = escapeCache.get(text);
|
|
3619
|
-
if (cached !== void 0) return cached;
|
|
3620
|
-
}
|
|
3621
|
-
const str = String(text);
|
|
3622
|
-
if (!str.includes("&") && !str.includes("<") && !str.includes(">")) {
|
|
3623
|
-
if (useCache && escapeCache.size < MAX_CACHE_SIZE) {
|
|
3624
|
-
escapeCache.set(text, str);
|
|
3625
|
-
}
|
|
3626
|
-
return str;
|
|
3627
|
-
}
|
|
3628
|
-
const result = str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3629
|
-
if (useCache && escapeCache.size < MAX_CACHE_SIZE) {
|
|
3630
|
-
escapeCache.set(text, result);
|
|
3631
|
-
}
|
|
3632
|
-
return result;
|
|
3633
|
-
}
|
|
3634
|
-
function escapeAttr(value) {
|
|
3635
|
-
const str = String(value);
|
|
3636
|
-
if (!str.includes("&") && !str.includes('"') && !str.includes("'") && !str.includes("<") && !str.includes(">")) {
|
|
3637
|
-
return str;
|
|
3638
|
-
}
|
|
3639
|
-
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
3640
|
-
}
|
|
3641
|
-
function escapeCssValue(value) {
|
|
3642
|
-
const str = String(value);
|
|
3643
|
-
if (/(?:url|expression|javascript)\s*\(/i.test(str)) {
|
|
3644
|
-
return "";
|
|
3645
|
-
}
|
|
3646
|
-
return str.replace(/[{}<>\\]/g, "");
|
|
3647
|
-
}
|
|
3648
|
-
function styleObjToCss(value) {
|
|
3649
|
-
if (!value || typeof value !== "object") return null;
|
|
3650
|
-
const entries = Object.entries(value);
|
|
3651
|
-
if (entries.length === 0) return "";
|
|
3652
|
-
let out = "";
|
|
3653
|
-
for (const [k, v] of entries) {
|
|
3654
|
-
if (v === null || v === void 0 || v === false) continue;
|
|
3655
|
-
const prop = k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
3656
|
-
const safeValue = escapeCssValue(String(v));
|
|
3657
|
-
if (safeValue) {
|
|
3658
|
-
out += `${prop}:${safeValue};`;
|
|
3659
|
-
}
|
|
3660
|
-
}
|
|
3661
|
-
return out;
|
|
3662
|
-
}
|
|
3663
|
-
var VOID_ELEMENTS, escapeCache, MAX_CACHE_SIZE;
|
|
3664
|
-
var init_escape = __esm({
|
|
3665
|
-
"src/ssr/escape.ts"() {
|
|
3666
|
-
"use strict";
|
|
3667
|
-
VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
3668
|
-
"area",
|
|
3669
|
-
"base",
|
|
3670
|
-
"br",
|
|
3671
|
-
"col",
|
|
3672
|
-
"embed",
|
|
3673
|
-
"hr",
|
|
3674
|
-
"img",
|
|
3675
|
-
"input",
|
|
3676
|
-
"link",
|
|
3677
|
-
"meta",
|
|
3678
|
-
"param",
|
|
3679
|
-
"source",
|
|
3680
|
-
"track",
|
|
3681
|
-
"wbr"
|
|
3682
|
-
]);
|
|
3683
|
-
escapeCache = /* @__PURE__ */ new Map();
|
|
3684
|
-
MAX_CACHE_SIZE = 256;
|
|
3685
|
-
}
|
|
3686
|
-
});
|
|
3687
|
-
|
|
3688
|
-
// src/ssr/attrs.ts
|
|
3689
|
-
function renderAttrs(props, opts) {
|
|
3690
|
-
if (!props || typeof props !== "object") {
|
|
3691
|
-
return opts?.returnDangerousHtml ? { attrs: "" } : "";
|
|
3692
|
-
}
|
|
3693
|
-
let result = "";
|
|
3694
|
-
let dangerousHtml;
|
|
3695
|
-
for (const [key, value] of Object.entries(props)) {
|
|
3696
|
-
if (key === "children") continue;
|
|
3697
|
-
if (key === "dangerouslySetInnerHTML") {
|
|
3698
|
-
if (value && typeof value === "object" && "__html" in value) {
|
|
3699
|
-
dangerousHtml = String(value.__html);
|
|
3700
|
-
}
|
|
3701
|
-
continue;
|
|
3702
|
-
}
|
|
3703
|
-
if (key.length >= 3 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z") {
|
|
3704
|
-
continue;
|
|
3705
|
-
}
|
|
3706
|
-
if (key.startsWith("_")) continue;
|
|
3707
|
-
const attrName = key === "class" || key === "className" ? "class" : key;
|
|
3708
|
-
if (attrName === "style") {
|
|
3709
|
-
const css = typeof value === "string" ? value : styleObjToCss(value);
|
|
3710
|
-
if (css === null || css === "") continue;
|
|
3711
|
-
result += ` style="${escapeAttr(css)}"`;
|
|
3712
|
-
continue;
|
|
3713
|
-
}
|
|
3714
|
-
if (value === true) {
|
|
3715
|
-
result += ` ${attrName}`;
|
|
3716
|
-
} else if (value === false || value === null || value === void 0) {
|
|
3717
|
-
continue;
|
|
3718
|
-
} else {
|
|
3719
|
-
result += ` ${attrName}="${escapeAttr(String(value))}"`;
|
|
3720
|
-
}
|
|
3721
|
-
}
|
|
3722
|
-
if (opts?.returnDangerousHtml) {
|
|
3723
|
-
return { attrs: result, dangerousHtml };
|
|
3724
|
-
}
|
|
3725
|
-
return result;
|
|
3726
|
-
}
|
|
3727
|
-
var init_attrs = __esm({
|
|
3728
|
-
"src/ssr/attrs.ts"() {
|
|
3729
|
-
"use strict";
|
|
3730
|
-
init_escape();
|
|
3731
|
-
}
|
|
3732
|
-
});
|
|
3733
|
-
|
|
3734
|
-
// src/ssr/sink.ts
|
|
3735
|
-
var StringSink, StreamSink;
|
|
3736
|
-
var init_sink = __esm({
|
|
3737
|
-
"src/ssr/sink.ts"() {
|
|
3738
|
-
"use strict";
|
|
3739
|
-
StringSink = class {
|
|
3740
|
-
constructor() {
|
|
3741
|
-
this.chunks = [];
|
|
3742
|
-
}
|
|
3743
|
-
write(html) {
|
|
3744
|
-
if (html) this.chunks.push(html);
|
|
3745
|
-
}
|
|
3746
|
-
end() {
|
|
3747
|
-
}
|
|
3748
|
-
toString() {
|
|
3749
|
-
return this.chunks.join("");
|
|
3750
|
-
}
|
|
3751
|
-
};
|
|
3752
|
-
StreamSink = class {
|
|
3753
|
-
constructor(onChunk, onComplete) {
|
|
3754
|
-
this.onChunk = onChunk;
|
|
3755
|
-
this.onComplete = onComplete;
|
|
3756
|
-
}
|
|
3757
|
-
write(html) {
|
|
3758
|
-
if (html) this.onChunk(html);
|
|
3759
|
-
}
|
|
3760
|
-
end() {
|
|
3761
|
-
this.onComplete();
|
|
3762
|
-
}
|
|
3763
|
-
};
|
|
3764
|
-
}
|
|
3765
|
-
});
|
|
3766
|
-
|
|
3767
|
-
// src/ssr/stream-render.ts
|
|
3768
|
-
function isVNodeLike(x) {
|
|
3769
|
-
return !!x && typeof x === "object" && "type" in x;
|
|
3770
|
-
}
|
|
3771
|
-
function normalizeChildren(node) {
|
|
3772
|
-
const n = node;
|
|
3773
|
-
const direct = Array.isArray(n?.children) ? n?.children : null;
|
|
3774
|
-
const fromProps = n?.props?.children;
|
|
3775
|
-
const raw = direct ?? fromProps;
|
|
3776
|
-
if (raw === null || raw === void 0 || raw === false) return [];
|
|
3777
|
-
if (Array.isArray(raw)) return raw;
|
|
3778
|
-
return [raw];
|
|
3779
|
-
}
|
|
3780
|
-
function renderChildrenToSink(children, sink, ctx) {
|
|
3781
|
-
for (const c of children)
|
|
3782
|
-
renderNodeToSink(
|
|
3783
|
-
c,
|
|
3784
|
-
sink,
|
|
3785
|
-
ctx
|
|
3786
|
-
);
|
|
3787
|
-
}
|
|
3788
|
-
function isPromiseLike(x) {
|
|
3789
|
-
if (!x || typeof x !== "object") return false;
|
|
3790
|
-
const then = x.then;
|
|
3791
|
-
return typeof then === "function";
|
|
3792
|
-
}
|
|
3793
|
-
function executeComponent2(type, props, ctx) {
|
|
3794
|
-
const res = type(props ?? {}, { signal: ctx.signal });
|
|
3795
|
-
if (isPromiseLike(res)) {
|
|
3796
|
-
throwSSRDataMissing();
|
|
3797
|
-
}
|
|
3798
|
-
return res;
|
|
3799
|
-
}
|
|
3800
|
-
function renderNodeToSink(node, sink, ctx) {
|
|
3801
|
-
if (node === null || node === void 0) return;
|
|
3802
|
-
if (typeof node === "string") {
|
|
3803
|
-
sink.write(escapeText(node));
|
|
3804
|
-
return;
|
|
3805
|
-
}
|
|
3806
|
-
if (typeof node === "number") {
|
|
3807
|
-
sink.write(escapeText(String(node)));
|
|
3808
|
-
return;
|
|
3809
|
-
}
|
|
3810
|
-
if (!isVNodeLike(node)) return;
|
|
3811
|
-
const { type, props } = node;
|
|
3812
|
-
if (typeof type === "symbol" && (type === Fragment || String(type) === "Symbol(Fragment)")) {
|
|
3813
|
-
const children = normalizeChildren(node);
|
|
3814
|
-
renderChildrenToSink(children, sink, ctx);
|
|
3815
|
-
return;
|
|
3816
|
-
}
|
|
3817
|
-
if (typeof type === "function") {
|
|
3818
|
-
const out = withSSRContext(
|
|
3819
|
-
ctx,
|
|
3820
|
-
() => executeComponent2(type, props, ctx)
|
|
3821
|
-
);
|
|
3822
|
-
renderNodeToSink(
|
|
3823
|
-
out,
|
|
3824
|
-
sink,
|
|
3825
|
-
ctx
|
|
3826
|
-
);
|
|
3827
|
-
return;
|
|
3828
|
-
}
|
|
3829
|
-
const tag = String(type);
|
|
3830
|
-
const { attrs, dangerousHtml } = renderAttrs(props, {
|
|
3831
|
-
returnDangerousHtml: true
|
|
3832
|
-
});
|
|
3833
|
-
if (VOID_ELEMENTS.has(tag)) {
|
|
3834
|
-
sink.write(`<${tag}${attrs} />`);
|
|
3835
|
-
return;
|
|
3836
|
-
}
|
|
3837
|
-
sink.write(`<${tag}${attrs}>`);
|
|
3838
|
-
if (dangerousHtml !== void 0) {
|
|
3839
|
-
sink.write(dangerousHtml);
|
|
3840
|
-
} else {
|
|
3841
|
-
const children = normalizeChildren(node);
|
|
3842
|
-
renderChildrenToSink(children, sink, ctx);
|
|
3843
|
-
}
|
|
3844
|
-
sink.write(`</${tag}>`);
|
|
3845
|
-
}
|
|
3846
|
-
var init_stream_render = __esm({
|
|
3847
|
-
"src/ssr/stream-render.ts"() {
|
|
3848
|
-
"use strict";
|
|
3849
|
-
init_jsx();
|
|
3850
|
-
init_context2();
|
|
3851
|
-
init_escape();
|
|
3852
|
-
init_attrs();
|
|
3853
|
-
}
|
|
3854
|
-
});
|
|
3855
|
-
|
|
3856
|
-
// src/ssr/index.ts
|
|
3857
|
-
var ssr_exports = {};
|
|
3858
|
-
__export(ssr_exports, {
|
|
3859
|
-
SSRDataMissingError: () => SSRDataMissingError,
|
|
3860
|
-
collectResources: () => collectResources,
|
|
3861
|
-
popSSRStrictPurityGuard: () => popSSRStrictPurityGuard,
|
|
3862
|
-
pushSSRStrictPurityGuard: () => pushSSRStrictPurityGuard,
|
|
3863
|
-
renderToStream: () => renderToStream,
|
|
3864
|
-
renderToString: () => renderToString,
|
|
3865
|
-
renderToStringSync: () => renderToStringSync,
|
|
3866
|
-
renderToStringSyncForUrl: () => renderToStringSyncForUrl,
|
|
3867
|
-
resolvePlan: () => resolvePlan,
|
|
3868
|
-
resolveResources: () => resolveResources
|
|
3869
|
-
});
|
|
3870
|
-
function pushSSRStrictPurityGuard() {
|
|
3871
|
-
if (process.env.NODE_ENV === "production") return;
|
|
3872
|
-
__ssrGuardStack.push({
|
|
3873
|
-
random: Reflect.get(Math, "random"),
|
|
3874
|
-
now: Reflect.get(Date, "now")
|
|
3875
|
-
});
|
|
3876
|
-
Reflect.set(Math, "random", () => {
|
|
3877
|
-
throw new Error(
|
|
3878
|
-
"SSR Strict Purity: Math.random is not allowed during synchronous SSR. Use the provided `ssr` context RNG instead."
|
|
3879
|
-
);
|
|
3880
|
-
});
|
|
3881
|
-
Reflect.set(Date, "now", () => {
|
|
3882
|
-
throw new Error(
|
|
3883
|
-
"SSR Strict Purity: Date.now is not allowed during synchronous SSR. Pass timestamps explicitly or use deterministic helpers."
|
|
3884
|
-
);
|
|
3885
|
-
});
|
|
3886
|
-
}
|
|
3887
|
-
function popSSRStrictPurityGuard() {
|
|
3888
|
-
if (process.env.NODE_ENV === "production") return;
|
|
3889
|
-
const prev = __ssrGuardStack.pop();
|
|
3890
|
-
if (prev) {
|
|
3891
|
-
Reflect.set(Math, "random", prev.random);
|
|
3892
|
-
Reflect.set(Date, "now", prev.now);
|
|
3893
|
-
}
|
|
3894
|
-
}
|
|
3895
|
-
function renderChildSync(child, ctx) {
|
|
3896
|
-
if (typeof child === "string") return escapeText(child);
|
|
3897
|
-
if (typeof child === "number") return escapeText(String(child));
|
|
3898
|
-
if (child === null || child === void 0 || child === false) return "";
|
|
3899
|
-
if (typeof child === "object" && child !== null && "type" in child) {
|
|
3900
|
-
return renderNodeSync(child, ctx);
|
|
3901
|
-
}
|
|
3902
|
-
return "";
|
|
3903
|
-
}
|
|
3904
|
-
function renderChildrenSync(children, ctx) {
|
|
3905
|
-
if (!children || !Array.isArray(children) || children.length === 0) return "";
|
|
3906
|
-
let result = "";
|
|
3907
|
-
for (const child of children) result += renderChildSync(child, ctx);
|
|
3908
|
-
return result;
|
|
3909
|
-
}
|
|
3910
|
-
function renderNodeSync(node, ctx) {
|
|
3911
|
-
const { type, props } = node;
|
|
3912
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3913
|
-
try {
|
|
3914
|
-
logger.warn("[SSR] renderNodeSync type:", typeof type, type);
|
|
3915
|
-
} catch {
|
|
3916
|
-
}
|
|
3917
|
-
}
|
|
3918
|
-
if (typeof type === "function") {
|
|
3919
|
-
const result = executeComponentSync2(type, props, ctx);
|
|
3920
|
-
if (result instanceof Promise) {
|
|
3921
|
-
throwSSRDataMissing();
|
|
3922
|
-
}
|
|
3923
|
-
return renderNodeSync(result, ctx);
|
|
3924
|
-
}
|
|
3925
|
-
if (typeof type === "symbol") {
|
|
3926
|
-
if (type === Fragment) {
|
|
3927
|
-
const childrenArr = Array.isArray(node.children) ? node.children : Array.isArray(props?.children) ? props?.children : void 0;
|
|
3928
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3929
|
-
try {
|
|
3930
|
-
logger.warn("[SSR] fragment children length:", childrenArr?.length);
|
|
3931
|
-
} catch {
|
|
3932
|
-
}
|
|
3933
|
-
}
|
|
3934
|
-
return renderChildrenSync(childrenArr, ctx);
|
|
3935
|
-
}
|
|
3936
|
-
throw new Error(
|
|
3937
|
-
`renderNodeSync: unsupported VNode symbol type: ${String(type)}`
|
|
3938
|
-
);
|
|
3939
|
-
}
|
|
3940
|
-
const typeStr = type;
|
|
3941
|
-
if (VOID_ELEMENTS.has(typeStr)) {
|
|
3942
|
-
const attrs2 = renderAttrs(props);
|
|
3943
|
-
return `<${typeStr}${attrs2} />`;
|
|
3944
|
-
}
|
|
3945
|
-
const { attrs, dangerousHtml } = renderAttrs(props, {
|
|
3946
|
-
returnDangerousHtml: true
|
|
3947
|
-
});
|
|
3948
|
-
if (dangerousHtml !== void 0) {
|
|
3949
|
-
return `<${typeStr}${attrs}>${dangerousHtml}</${typeStr}>`;
|
|
3950
|
-
}
|
|
3951
|
-
const children = node.children;
|
|
3952
|
-
const childrenHtml = renderChildrenSync(children, ctx);
|
|
3953
|
-
return `<${typeStr}${attrs}>${childrenHtml}</${typeStr}>`;
|
|
3954
|
-
}
|
|
3955
|
-
function executeComponentSync2(component, props, ctx) {
|
|
3956
|
-
try {
|
|
3957
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3958
|
-
pushSSRStrictPurityGuard();
|
|
3959
|
-
}
|
|
3960
|
-
const prev = getCurrentComponentInstance();
|
|
3961
|
-
const temp = createComponentInstance(
|
|
3962
|
-
"ssr-temp",
|
|
3963
|
-
component,
|
|
3964
|
-
props || {},
|
|
3965
|
-
null
|
|
3966
|
-
);
|
|
3967
|
-
temp.ssr = true;
|
|
3968
|
-
setCurrentComponentInstance(temp);
|
|
3969
|
-
try {
|
|
3970
|
-
return runWithSSRContext(ctx, () => {
|
|
3971
|
-
const result = component(props || {}, { ssr: ctx });
|
|
3972
|
-
if (result instanceof Promise) {
|
|
3973
|
-
throwSSRDataMissing();
|
|
3974
|
-
}
|
|
3975
|
-
if (typeof result === "string" || typeof result === "number" || typeof result === "boolean" || result === null || result === void 0) {
|
|
3976
|
-
const inner = result === null || result === void 0 || result === false ? "" : String(result);
|
|
3977
|
-
return {
|
|
3978
|
-
$$typeof: ELEMENT_TYPE,
|
|
3979
|
-
type: Fragment,
|
|
3980
|
-
props: { children: inner ? [inner] : [] }
|
|
3981
|
-
};
|
|
3982
|
-
}
|
|
3983
|
-
return result;
|
|
3984
|
-
});
|
|
3985
|
-
} finally {
|
|
3986
|
-
setCurrentComponentInstance(prev);
|
|
3987
|
-
}
|
|
3988
|
-
} finally {
|
|
3989
|
-
if (process.env.NODE_ENV !== "production") popSSRStrictPurityGuard();
|
|
3990
|
-
}
|
|
3991
|
-
}
|
|
3992
|
-
function renderToStringSync(component, props, options) {
|
|
3993
|
-
const seed = options?.seed ?? 12345;
|
|
3994
|
-
const ctx = createRenderContext(seed);
|
|
3995
|
-
startRenderPhase(options?.data ?? null);
|
|
3996
|
-
try {
|
|
3997
|
-
const wrapped = (p, c) => {
|
|
3998
|
-
const out = component(p ?? {}, c);
|
|
3999
|
-
const portalVNode = {
|
|
4000
|
-
$$typeof: ELEMENT_TYPE,
|
|
4001
|
-
type: DefaultPortal,
|
|
4002
|
-
props: {},
|
|
4003
|
-
key: "__default_portal"
|
|
4004
|
-
};
|
|
4005
|
-
if (out == null) {
|
|
4006
|
-
return {
|
|
4007
|
-
$$typeof: ELEMENT_TYPE,
|
|
4008
|
-
type: Fragment,
|
|
4009
|
-
props: { children: [portalVNode] }
|
|
4010
|
-
};
|
|
4011
|
-
}
|
|
4012
|
-
return {
|
|
4013
|
-
$$typeof: ELEMENT_TYPE,
|
|
4014
|
-
type: Fragment,
|
|
4015
|
-
props: { children: [out, portalVNode] }
|
|
4016
|
-
};
|
|
4017
|
-
};
|
|
4018
|
-
const node = executeComponentSync2(wrapped, props || {}, ctx);
|
|
4019
|
-
if (!node) {
|
|
4020
|
-
throw new Error("renderToStringSync: wrapped component returned empty");
|
|
4021
|
-
}
|
|
4022
|
-
return renderNodeSync(node, ctx);
|
|
4023
|
-
} finally {
|
|
4024
|
-
stopRenderPhase();
|
|
4025
|
-
}
|
|
4026
|
-
}
|
|
4027
|
-
function renderToStringSyncForUrl(opts) {
|
|
4028
|
-
const { url, routes: routes2, options } = opts;
|
|
4029
|
-
const {
|
|
4030
|
-
clearRoutes: clearRoutes2,
|
|
4031
|
-
route: route2,
|
|
4032
|
-
setServerLocation: setServerLocation2,
|
|
4033
|
-
lockRouteRegistration: lockRouteRegistration2,
|
|
4034
|
-
resolveRoute: resolveRoute2
|
|
4035
|
-
} = route_exports;
|
|
4036
|
-
clearRoutes2();
|
|
4037
|
-
for (const r of routes2) {
|
|
4038
|
-
route2(r.path, r.handler, r.namespace);
|
|
4039
|
-
}
|
|
4040
|
-
setServerLocation2(url);
|
|
4041
|
-
if (process.env.NODE_ENV === "production") lockRouteRegistration2();
|
|
4042
|
-
const resolved = resolveRoute2(url);
|
|
4043
|
-
if (!resolved)
|
|
4044
|
-
throw new Error(`renderToStringSync: no route found for url: ${url}`);
|
|
4045
|
-
const seed = options?.seed ?? 12345;
|
|
4046
|
-
const ctx = createRenderContext(seed);
|
|
4047
|
-
startRenderPhase(options?.data ?? null);
|
|
4048
|
-
try {
|
|
4049
|
-
const wrapped = (p, c) => {
|
|
4050
|
-
const out = resolved.handler(p ?? {}, c);
|
|
4051
|
-
const portalVNode = {
|
|
4052
|
-
$$typeof: ELEMENT_TYPE,
|
|
4053
|
-
type: DefaultPortal,
|
|
4054
|
-
props: {},
|
|
4055
|
-
key: "__default_portal"
|
|
4056
|
-
};
|
|
4057
|
-
if (out == null) {
|
|
4058
|
-
return {
|
|
4059
|
-
$$typeof: ELEMENT_TYPE,
|
|
4060
|
-
type: Fragment,
|
|
4061
|
-
props: { children: [portalVNode] }
|
|
4062
|
-
};
|
|
4063
|
-
}
|
|
4064
|
-
return {
|
|
4065
|
-
$$typeof: ELEMENT_TYPE,
|
|
4066
|
-
type: Fragment,
|
|
4067
|
-
props: { children: [out, portalVNode] }
|
|
4068
|
-
};
|
|
4069
|
-
};
|
|
4070
|
-
const node = executeComponentSync2(wrapped, resolved.params || {}, ctx);
|
|
4071
|
-
return renderNodeSync(node, ctx);
|
|
4072
|
-
} finally {
|
|
4073
|
-
stopRenderPhase();
|
|
4074
|
-
}
|
|
4075
|
-
}
|
|
4076
|
-
function renderToString(arg) {
|
|
4077
|
-
if (typeof arg === "function") {
|
|
4078
|
-
return renderToStringSync(
|
|
4079
|
-
arg
|
|
4080
|
-
);
|
|
4081
|
-
}
|
|
4082
|
-
const opts = arg;
|
|
4083
|
-
const sink = new StringSink();
|
|
4084
|
-
renderToSinkInternal({ ...opts, sink });
|
|
4085
|
-
sink.end();
|
|
4086
|
-
return sink.toString();
|
|
4087
|
-
}
|
|
4088
|
-
function renderToStream(opts) {
|
|
4089
|
-
const sink = new StreamSink(opts.onChunk, opts.onComplete);
|
|
4090
|
-
renderToSinkInternal({ ...opts, sink });
|
|
4091
|
-
sink.end();
|
|
4092
|
-
}
|
|
4093
|
-
function renderToSinkInternal(opts) {
|
|
4094
|
-
const { url, routes: routes2, seed = 12345, data, sink } = opts;
|
|
4095
|
-
const {
|
|
4096
|
-
clearRoutes: clearRoutes2,
|
|
4097
|
-
route: route2,
|
|
4098
|
-
setServerLocation: setServerLocation2,
|
|
4099
|
-
lockRouteRegistration: lockRouteRegistration2,
|
|
4100
|
-
resolveRoute: resolveRoute2
|
|
4101
|
-
} = route_exports;
|
|
4102
|
-
clearRoutes2();
|
|
4103
|
-
for (const r of routes2) route2(r.path, r.handler, r.namespace);
|
|
4104
|
-
setServerLocation2(url);
|
|
4105
|
-
if (process.env.NODE_ENV === "production") lockRouteRegistration2();
|
|
4106
|
-
const resolved = resolveRoute2(url);
|
|
4107
|
-
if (!resolved) throw new Error(`SSR: no route found for url: ${url}`);
|
|
4108
|
-
const ctx = {
|
|
4109
|
-
url,
|
|
4110
|
-
seed,
|
|
4111
|
-
data,
|
|
4112
|
-
params: resolved.params,
|
|
4113
|
-
signal: void 0
|
|
4114
|
-
};
|
|
4115
|
-
const node = resolved.handler(resolved.params);
|
|
4116
|
-
startRenderPhase(data || null);
|
|
4117
|
-
try {
|
|
4118
|
-
renderNodeToSink(node, sink, ctx);
|
|
4119
|
-
} finally {
|
|
4120
|
-
stopRenderPhase();
|
|
4121
|
-
}
|
|
4122
|
-
}
|
|
4123
|
-
var __ssrGuardStack;
|
|
4124
|
-
var init_ssr = __esm({
|
|
4125
|
-
"src/ssr/index.ts"() {
|
|
4126
|
-
"use strict";
|
|
4127
|
-
init_route();
|
|
4128
|
-
init_jsx();
|
|
4129
|
-
init_portal();
|
|
4130
|
-
init_context2();
|
|
4131
|
-
init_component();
|
|
4132
|
-
init_escape();
|
|
4133
|
-
init_attrs();
|
|
4134
|
-
init_logger();
|
|
4135
|
-
init_context2();
|
|
4136
|
-
init_sink();
|
|
4137
|
-
init_stream_render();
|
|
4138
|
-
init_render_keys();
|
|
4139
|
-
__ssrGuardStack = [];
|
|
4140
|
-
}
|
|
4141
|
-
});
|
|
4142
|
-
|
|
4143
|
-
// src/index.ts
|
|
4144
|
-
var index_exports = {};
|
|
4145
|
-
__export(index_exports, {
|
|
4146
|
-
DefaultPortal: () => DefaultPortal,
|
|
4147
|
-
Fragment: () => Fragment2,
|
|
4148
|
-
Link: () => Link,
|
|
4149
|
-
Slot: () => Slot,
|
|
4150
|
-
_resetDefaultPortal: () => _resetDefaultPortal,
|
|
4151
|
-
cleanupApp: () => cleanupApp,
|
|
4152
|
-
clearRoutes: () => clearRoutes,
|
|
4153
|
-
collectResources: () => collectResources,
|
|
4154
|
-
createIsland: () => createIsland,
|
|
4155
|
-
createSPA: () => createSPA,
|
|
4156
|
-
defineContext: () => defineContext,
|
|
4157
|
-
definePortal: () => definePortal,
|
|
4158
|
-
derive: () => derive,
|
|
4159
|
-
getLoadedNamespaces: () => getLoadedNamespaces,
|
|
4160
|
-
getNamespaceRoutes: () => getNamespaceRoutes,
|
|
4161
|
-
getRoutes: () => getRoutes,
|
|
4162
|
-
getSignal: () => getSignal,
|
|
4163
|
-
hasApp: () => hasApp,
|
|
4164
|
-
hydrateSPA: () => hydrateSPA,
|
|
4165
|
-
jsx: () => jsx,
|
|
4166
|
-
jsxs: () => jsxs,
|
|
4167
|
-
layout: () => layout,
|
|
4168
|
-
navigate: () => navigate,
|
|
4169
|
-
readContext: () => readContext,
|
|
4170
|
-
renderToStream: () => renderToStream,
|
|
4171
|
-
renderToString: () => renderToString,
|
|
4172
|
-
renderToStringSync: () => renderToStringSync,
|
|
4173
|
-
renderToStringSyncForUrl: () => renderToStringSyncForUrl,
|
|
4174
|
-
resolveResources: () => resolveResources,
|
|
4175
|
-
resource: () => resource,
|
|
4176
|
-
route: () => route,
|
|
4177
|
-
scheduleEventHandler: () => scheduleEventHandler,
|
|
4178
|
-
setServerLocation: () => setServerLocation,
|
|
4179
|
-
state: () => state,
|
|
4180
|
-
task: () => task,
|
|
4181
|
-
unloadNamespace: () => unloadNamespace
|
|
4182
|
-
});
|
|
4183
|
-
module.exports = __toCommonJS(index_exports);
|
|
4184
|
-
|
|
4185
|
-
// src/runtime/state.ts
|
|
4186
|
-
init_scheduler();
|
|
4187
|
-
init_component();
|
|
4188
|
-
init_invariant();
|
|
4189
|
-
init_fastlane_shared();
|
|
4190
|
-
function state(initialValue) {
|
|
4191
|
-
const instance = getCurrentInstance();
|
|
4192
|
-
if (!instance) {
|
|
4193
|
-
throw new Error(
|
|
4194
|
-
"state() can only be called during component render execution. Move state() calls to the top level of your component function."
|
|
4195
|
-
);
|
|
4196
|
-
}
|
|
4197
|
-
const index = getNextStateIndex();
|
|
4198
|
-
const stateValues = instance.stateValues;
|
|
4199
|
-
if (index < instance.stateIndexCheck) {
|
|
4200
|
-
throw new Error(
|
|
4201
|
-
`State index violation: state() call at index ${index}, but previously saw index ${instance.stateIndexCheck}. This happens when state() is called conditionally (inside if/for/etc). Move all state() calls to the top level of your component function, before any conditionals.`
|
|
4202
|
-
);
|
|
4203
|
-
}
|
|
4204
|
-
invariant(
|
|
4205
|
-
index >= instance.stateIndexCheck,
|
|
4206
|
-
"[State] State indices must increase monotonically"
|
|
4207
|
-
);
|
|
4208
|
-
instance.stateIndexCheck = index;
|
|
4209
|
-
if (instance.firstRenderComplete) {
|
|
4210
|
-
if (!instance.expectedStateIndices.includes(index)) {
|
|
4211
|
-
throw new Error(
|
|
4212
|
-
`Hook order violation: state() called at index ${index}, but this index was not in the first render's sequence [${instance.expectedStateIndices.join(", ")}]. This usually means state() is inside a conditional or loop. Move all state() calls to the top level of your component function.`
|
|
4213
|
-
);
|
|
4214
|
-
}
|
|
4215
|
-
} else {
|
|
4216
|
-
instance.expectedStateIndices.push(index);
|
|
4217
|
-
}
|
|
4218
|
-
if (stateValues[index]) {
|
|
4219
|
-
const existing = stateValues[index];
|
|
4220
|
-
if (existing._owner !== instance) {
|
|
4221
|
-
throw new Error(
|
|
4222
|
-
`State ownership violation: state() called at index ${index} is owned by a different component instance. State ownership is positional and immutable.`
|
|
4223
|
-
);
|
|
4224
|
-
}
|
|
4225
|
-
return existing;
|
|
4226
|
-
}
|
|
4227
|
-
const cell = createStateCell(initialValue, instance);
|
|
4228
|
-
stateValues[index] = cell;
|
|
4229
|
-
return cell;
|
|
4230
|
-
}
|
|
4231
|
-
function createStateCell(initialValue, instance) {
|
|
4232
|
-
let value = initialValue;
|
|
4233
|
-
const readers = /* @__PURE__ */ new Map();
|
|
4234
|
-
function read() {
|
|
4235
|
-
read._hasBeenRead = true;
|
|
4236
|
-
const inst = getCurrentInstance();
|
|
4237
|
-
if (inst && inst._currentRenderToken !== void 0) {
|
|
4238
|
-
if (!inst._pendingReadStates) inst._pendingReadStates = /* @__PURE__ */ new Set();
|
|
4239
|
-
inst._pendingReadStates.add(read);
|
|
4240
|
-
}
|
|
4241
|
-
return value;
|
|
4242
|
-
}
|
|
4243
|
-
read._readers = readers;
|
|
4244
|
-
read._owner = instance;
|
|
4245
|
-
read.set = (newValueOrUpdater) => {
|
|
4246
|
-
const currentInst = getCurrentInstance();
|
|
4247
|
-
if (currentInst !== null && process.env.NODE_ENV !== "production") {
|
|
4248
|
-
throw new Error(
|
|
4249
|
-
`[Askr] state.set() cannot be called during component render. State mutations during render break the actor model and cause infinite loops. Move state updates to event handlers or use conditional rendering instead.`
|
|
4250
|
-
);
|
|
4251
|
-
}
|
|
4252
|
-
if (currentInst !== null && process.env.NODE_ENV === "production") {
|
|
4253
|
-
if (typeof console !== "undefined" && console.warn) {
|
|
4254
|
-
console.warn(
|
|
4255
|
-
"[Askr] state.set() called during render - update skipped. Move state updates to event handlers."
|
|
4256
|
-
);
|
|
4257
|
-
}
|
|
4258
|
-
return;
|
|
4259
|
-
}
|
|
4260
|
-
let newValue;
|
|
4261
|
-
if (typeof newValueOrUpdater === "function") {
|
|
4262
|
-
const updater = newValueOrUpdater;
|
|
4263
|
-
newValue = updater(value);
|
|
4264
|
-
} else {
|
|
4265
|
-
newValue = newValueOrUpdater;
|
|
4266
|
-
}
|
|
4267
|
-
if (Object.is(value, newValue)) return;
|
|
4268
|
-
if (isBulkCommitActive2()) {
|
|
4269
|
-
value = newValue;
|
|
4270
|
-
return;
|
|
4271
|
-
}
|
|
4272
|
-
value = newValue;
|
|
4273
|
-
const readersMap = read._readers;
|
|
4274
|
-
if (readersMap) {
|
|
4275
|
-
for (const [subInst, token] of readersMap) {
|
|
4276
|
-
if (subInst.lastRenderToken !== token) continue;
|
|
4277
|
-
if (!subInst.hasPendingUpdate) {
|
|
4278
|
-
subInst.hasPendingUpdate = true;
|
|
4279
|
-
const subTask = subInst._pendingFlushTask;
|
|
4280
|
-
if (subTask) globalScheduler.enqueue(subTask);
|
|
4281
|
-
else
|
|
4282
|
-
globalScheduler.enqueue(() => {
|
|
4283
|
-
subInst.hasPendingUpdate = false;
|
|
4284
|
-
subInst.notifyUpdate?.();
|
|
4285
|
-
});
|
|
4286
|
-
}
|
|
4287
|
-
}
|
|
4288
|
-
}
|
|
4289
|
-
const readersMapForOwner = readersMap;
|
|
4290
|
-
const ownerRecordedToken = readersMapForOwner?.get(instance);
|
|
4291
|
-
const ownerShouldEnqueue = (
|
|
4292
|
-
// Normal case: owner read this state in last committed render
|
|
4293
|
-
ownerRecordedToken !== void 0 && instance.lastRenderToken === ownerRecordedToken
|
|
4294
|
-
);
|
|
4295
|
-
if (ownerShouldEnqueue && !instance.hasPendingUpdate) {
|
|
4296
|
-
instance.hasPendingUpdate = true;
|
|
4297
|
-
const task2 = instance._pendingFlushTask;
|
|
4298
|
-
if (task2) globalScheduler.enqueue(task2);
|
|
4299
|
-
else
|
|
4300
|
-
globalScheduler.enqueue(() => {
|
|
4301
|
-
instance.hasPendingUpdate = false;
|
|
4302
|
-
instance.notifyUpdate?.();
|
|
4303
|
-
});
|
|
3362
|
+
const depth = getDepth(removed.path);
|
|
3363
|
+
const depthRoutes = routesByDepth.get(depth);
|
|
3364
|
+
if (depthRoutes) {
|
|
3365
|
+
const idx = depthRoutes.indexOf(removed);
|
|
3366
|
+
if (idx >= 0) {
|
|
3367
|
+
depthRoutes.splice(idx, 1);
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
4304
3370
|
}
|
|
4305
|
-
}
|
|
4306
|
-
|
|
3371
|
+
}
|
|
3372
|
+
namespaces.delete(namespace);
|
|
3373
|
+
return before - routes.length;
|
|
4307
3374
|
}
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
this.value = null;
|
|
4325
|
-
this.pending = true;
|
|
4326
|
-
this.error = null;
|
|
4327
|
-
this.generation = 0;
|
|
4328
|
-
this.controller = null;
|
|
4329
|
-
this.deps = null;
|
|
4330
|
-
this.resourceFrame = null;
|
|
4331
|
-
this.subscribers = /* @__PURE__ */ new Set();
|
|
4332
|
-
this.fn = fn;
|
|
4333
|
-
this.deps = deps ? deps.slice() : null;
|
|
4334
|
-
this.resourceFrame = resourceFrame;
|
|
4335
|
-
this.snapshot = {
|
|
4336
|
-
value: null,
|
|
4337
|
-
pending: true,
|
|
4338
|
-
error: null,
|
|
4339
|
-
refresh: () => this.refresh()
|
|
3375
|
+
function clearRoutes() {
|
|
3376
|
+
routes.length = 0;
|
|
3377
|
+
namespaces.clear();
|
|
3378
|
+
routesByDepth.clear();
|
|
3379
|
+
registrationLocked = false;
|
|
3380
|
+
setHasRoutes(false);
|
|
3381
|
+
}
|
|
3382
|
+
function normalizeHandler(handler) {
|
|
3383
|
+
if (handler == null) return void 0;
|
|
3384
|
+
if (typeof handler === "function") {
|
|
3385
|
+
return (params, ctx) => {
|
|
3386
|
+
try {
|
|
3387
|
+
return handler(params, ctx);
|
|
3388
|
+
} catch {
|
|
3389
|
+
return handler(params);
|
|
3390
|
+
}
|
|
4340
3391
|
};
|
|
4341
3392
|
}
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
}
|
|
4352
|
-
|
|
4353
|
-
const
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
this.pending = true;
|
|
4358
|
-
this.error = null;
|
|
4359
|
-
if (notify) this.notifySubscribers();
|
|
4360
|
-
let result;
|
|
4361
|
-
try {
|
|
4362
|
-
result = withAsyncResourceContext(
|
|
4363
|
-
this.resourceFrame,
|
|
4364
|
-
() => this.fn({ signal: controller.signal })
|
|
3393
|
+
return void 0;
|
|
3394
|
+
}
|
|
3395
|
+
function registerRoute(path, handler, ...children) {
|
|
3396
|
+
const isRelative = !path.startsWith("/");
|
|
3397
|
+
const descriptor = {
|
|
3398
|
+
path,
|
|
3399
|
+
handler,
|
|
3400
|
+
children: children.filter(Boolean),
|
|
3401
|
+
_isDescriptor: true
|
|
3402
|
+
};
|
|
3403
|
+
if (!isRelative) {
|
|
3404
|
+
const normalized = normalizeHandler(handler);
|
|
3405
|
+
if (handler != null && !normalized) {
|
|
3406
|
+
throw new Error(
|
|
3407
|
+
"registerRoute(path, handler) requires a function handler. Passing JSX elements or VNodes directly is not supported."
|
|
4365
3408
|
);
|
|
4366
|
-
} catch (err) {
|
|
4367
|
-
this.pending = false;
|
|
4368
|
-
this.error = err;
|
|
4369
|
-
if (notify) this.notifySubscribers();
|
|
4370
|
-
return;
|
|
4371
|
-
}
|
|
4372
|
-
if (!(result instanceof Promise)) {
|
|
4373
|
-
this.value = result;
|
|
4374
|
-
this.pending = false;
|
|
4375
|
-
this.error = null;
|
|
4376
|
-
if (notify) this.notifySubscribers();
|
|
4377
|
-
return;
|
|
4378
3409
|
}
|
|
4379
|
-
if (
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
this.pending = false;
|
|
4392
|
-
this.error = err;
|
|
4393
|
-
try {
|
|
4394
|
-
if (this.ownerName) {
|
|
4395
|
-
logger.error(
|
|
4396
|
-
`[Askr] Async resource error in ${this.ownerName}:`,
|
|
4397
|
-
err
|
|
3410
|
+
if (normalized) route(path, normalized);
|
|
3411
|
+
for (const child of descriptor.children || []) {
|
|
3412
|
+
const base = path === "/" ? "" : path.replace(/\/$/, "");
|
|
3413
|
+
const childPath = `${base}/${child.path.replace(/^\//, "")}`.replace(
|
|
3414
|
+
/\/\//g,
|
|
3415
|
+
"/"
|
|
3416
|
+
);
|
|
3417
|
+
if (child.handler) {
|
|
3418
|
+
const childNormalized = normalizeHandler(child.handler);
|
|
3419
|
+
if (!childNormalized) {
|
|
3420
|
+
throw new Error(
|
|
3421
|
+
"registerRoute child handler must be a function. Passing JSX elements directly is not supported."
|
|
4398
3422
|
);
|
|
4399
|
-
} else {
|
|
4400
|
-
logger.error("[Askr] Async resource error:", err);
|
|
4401
3423
|
}
|
|
4402
|
-
|
|
3424
|
+
if (childNormalized) route(childPath, childNormalized);
|
|
4403
3425
|
}
|
|
4404
|
-
|
|
4405
|
-
|
|
3426
|
+
if (child.children && child.children.length) {
|
|
3427
|
+
registerRoute(
|
|
3428
|
+
childPath,
|
|
3429
|
+
null,
|
|
3430
|
+
...child.children
|
|
3431
|
+
);
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
return descriptor;
|
|
3435
|
+
}
|
|
3436
|
+
return descriptor;
|
|
3437
|
+
}
|
|
3438
|
+
function getLoadedNamespaces() {
|
|
3439
|
+
return Array.from(namespaces);
|
|
3440
|
+
}
|
|
3441
|
+
function resolveRoute(pathname) {
|
|
3442
|
+
const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
|
|
3443
|
+
const depth = normalized === "/" ? 0 : normalized.split("/").filter(Boolean).length;
|
|
3444
|
+
const candidates = [];
|
|
3445
|
+
const depthRoutes = routesByDepth.get(depth);
|
|
3446
|
+
if (depthRoutes) {
|
|
3447
|
+
for (const r of depthRoutes) {
|
|
3448
|
+
const result = match(pathname, r.path);
|
|
3449
|
+
if (result.matched) {
|
|
3450
|
+
candidates.push({
|
|
3451
|
+
route: r,
|
|
3452
|
+
specificity: getSpecificity(r.path),
|
|
3453
|
+
params: result.params
|
|
3454
|
+
});
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
4406
3457
|
}
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
3458
|
+
for (const r of routes) {
|
|
3459
|
+
if (depthRoutes?.includes(r)) continue;
|
|
3460
|
+
const result = match(pathname, r.path);
|
|
3461
|
+
if (result.matched) {
|
|
3462
|
+
candidates.push({
|
|
3463
|
+
route: r,
|
|
3464
|
+
specificity: getSpecificity(r.path),
|
|
3465
|
+
params: result.params
|
|
3466
|
+
});
|
|
3467
|
+
}
|
|
4411
3468
|
}
|
|
4412
|
-
|
|
4413
|
-
|
|
3469
|
+
candidates.sort((a, b) => b.specificity - a.specificity);
|
|
3470
|
+
if (candidates.length > 0) {
|
|
3471
|
+
const best = candidates[0];
|
|
3472
|
+
return { handler: best.route.handler, params: best.params };
|
|
4414
3473
|
}
|
|
4415
|
-
|
|
3474
|
+
return null;
|
|
3475
|
+
}
|
|
3476
|
+
var routes, namespaces, HAS_ROUTES_KEY, routesByDepth, serverLocation, registrationLocked;
|
|
3477
|
+
var init_route = __esm({
|
|
3478
|
+
"src/router/route.ts"() {
|
|
3479
|
+
"use strict";
|
|
3480
|
+
init_match();
|
|
3481
|
+
init_component();
|
|
3482
|
+
init_execution_model();
|
|
3483
|
+
routes = [];
|
|
3484
|
+
namespaces = /* @__PURE__ */ new Set();
|
|
3485
|
+
HAS_ROUTES_KEY = /* @__PURE__ */ Symbol.for("__ASKR_HAS_ROUTES__");
|
|
3486
|
+
setHasRoutes(false);
|
|
3487
|
+
routesByDepth = /* @__PURE__ */ new Map();
|
|
3488
|
+
serverLocation = null;
|
|
3489
|
+
registrationLocked = false;
|
|
3490
|
+
}
|
|
3491
|
+
});
|
|
4416
3492
|
|
|
4417
|
-
// src/
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
3493
|
+
// src/router/navigate.ts
|
|
3494
|
+
function registerAppInstance(instance, _path) {
|
|
3495
|
+
currentInstance2 = instance;
|
|
3496
|
+
if (process.env.NODE_ENV === "production") {
|
|
3497
|
+
lockRouteRegistration();
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
function handlePopState(_event) {
|
|
3501
|
+
const path = window.location.pathname;
|
|
3502
|
+
if (!currentInstance2) {
|
|
3503
|
+
return;
|
|
3504
|
+
}
|
|
3505
|
+
const resolved = resolveRoute(path);
|
|
3506
|
+
if (resolved) {
|
|
3507
|
+
cleanupComponent(currentInstance2);
|
|
3508
|
+
currentInstance2.fn = resolved.handler;
|
|
3509
|
+
currentInstance2.props = resolved.params;
|
|
3510
|
+
currentInstance2.stateValues = [];
|
|
3511
|
+
currentInstance2.expectedStateIndices = [];
|
|
3512
|
+
currentInstance2.firstRenderComplete = false;
|
|
3513
|
+
currentInstance2.stateIndexCheck = -1;
|
|
3514
|
+
currentInstance2.evaluationGeneration++;
|
|
3515
|
+
currentInstance2.notifyUpdate = null;
|
|
3516
|
+
currentInstance2.abortController = new AbortController();
|
|
3517
|
+
mountComponent(currentInstance2);
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
function initializeNavigation() {
|
|
3521
|
+
if (typeof window !== "undefined") {
|
|
3522
|
+
window.addEventListener("popstate", handlePopState);
|
|
4424
3523
|
}
|
|
4425
|
-
return cache;
|
|
4426
3524
|
}
|
|
3525
|
+
var currentInstance2;
|
|
3526
|
+
var init_navigate = __esm({
|
|
3527
|
+
"src/router/navigate.ts"() {
|
|
3528
|
+
"use strict";
|
|
3529
|
+
init_route();
|
|
3530
|
+
init_component();
|
|
3531
|
+
currentInstance2 = null;
|
|
3532
|
+
}
|
|
3533
|
+
});
|
|
4427
3534
|
|
|
4428
|
-
// src/
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
const inst = instance;
|
|
4434
|
-
if (!instance) {
|
|
4435
|
-
const renderData2 = getCurrentRenderData();
|
|
4436
|
-
if (renderData2) {
|
|
4437
|
-
const key = getNextKey();
|
|
4438
|
-
if (!(key in renderData2)) {
|
|
4439
|
-
throwSSRDataMissing();
|
|
4440
|
-
}
|
|
4441
|
-
const val = renderData2[key];
|
|
4442
|
-
return {
|
|
4443
|
-
value: val,
|
|
4444
|
-
pending: false,
|
|
4445
|
-
error: null,
|
|
4446
|
-
refresh: () => {
|
|
4447
|
-
}
|
|
4448
|
-
};
|
|
4449
|
-
}
|
|
4450
|
-
const ssrCtx = getCurrentSSRContext();
|
|
4451
|
-
if (ssrCtx) {
|
|
4452
|
-
throwSSRDataMissing();
|
|
4453
|
-
}
|
|
4454
|
-
return {
|
|
4455
|
-
value: null,
|
|
4456
|
-
pending: true,
|
|
4457
|
-
error: null,
|
|
4458
|
-
refresh: () => {
|
|
4459
|
-
}
|
|
4460
|
-
};
|
|
3535
|
+
// src/jsx/index.ts
|
|
3536
|
+
var init_jsx2 = __esm({
|
|
3537
|
+
"src/jsx/index.ts"() {
|
|
3538
|
+
"use strict";
|
|
3539
|
+
init_types2();
|
|
4461
3540
|
}
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
snapshot: {
|
|
4472
|
-
value: val,
|
|
4473
|
-
pending: false,
|
|
4474
|
-
error: null,
|
|
4475
|
-
refresh: () => {
|
|
4476
|
-
}
|
|
4477
|
-
}
|
|
4478
|
-
});
|
|
4479
|
-
const h2 = holder2();
|
|
4480
|
-
h2.snapshot.value = val;
|
|
4481
|
-
h2.snapshot.pending = false;
|
|
4482
|
-
h2.snapshot.error = null;
|
|
4483
|
-
holder2.set(h2);
|
|
4484
|
-
return h2.snapshot;
|
|
4485
|
-
}
|
|
4486
|
-
const holder = state({
|
|
4487
|
-
cell: void 0,
|
|
4488
|
-
snapshot: {
|
|
4489
|
-
value: null,
|
|
4490
|
-
pending: true,
|
|
4491
|
-
error: null,
|
|
4492
|
-
refresh: () => {
|
|
3541
|
+
});
|
|
3542
|
+
|
|
3543
|
+
// src/foundations/portal.tsx
|
|
3544
|
+
function definePortal() {
|
|
3545
|
+
if (typeof createPortalSlot !== "function") {
|
|
3546
|
+
let HostFallback2 = function() {
|
|
3547
|
+
if (owner && owner.mounted === false) {
|
|
3548
|
+
owner = null;
|
|
3549
|
+
pending = void 0;
|
|
4493
3550
|
}
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
const cell2 = new ResourceCell(fn, deps, frame);
|
|
4500
|
-
cell2.ownerName = inst.fn?.name || "<anonymous>";
|
|
4501
|
-
h.cell = cell2;
|
|
4502
|
-
h.snapshot = cell2.snapshot;
|
|
4503
|
-
const unsubscribe = cell2.subscribe(() => {
|
|
4504
|
-
const cur = holder();
|
|
4505
|
-
cur.snapshot.value = cell2.snapshot.value;
|
|
4506
|
-
cur.snapshot.pending = cell2.snapshot.pending;
|
|
4507
|
-
cur.snapshot.error = cell2.snapshot.error;
|
|
4508
|
-
holder.set(cur);
|
|
4509
|
-
try {
|
|
4510
|
-
inst._enqueueRun?.();
|
|
4511
|
-
} catch {
|
|
3551
|
+
const inst = getCurrentComponentInstance();
|
|
3552
|
+
if (!owner && inst) owner = inst;
|
|
3553
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3554
|
+
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3555
|
+
ns.__PORTAL_READS = (ns.__PORTAL_READS || 0) + 1;
|
|
4512
3556
|
}
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
cell2.start(inst.ssr ?? false, false);
|
|
4520
|
-
if (!cell2.pending) {
|
|
4521
|
-
const cur = holder();
|
|
4522
|
-
cur.snapshot.value = cell2.value;
|
|
4523
|
-
cur.snapshot.pending = cell2.pending;
|
|
4524
|
-
cur.snapshot.error = cell2.error;
|
|
3557
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3558
|
+
if (inst && owner && inst !== owner && inst.mounted === true) {
|
|
3559
|
+
logger.warn(
|
|
3560
|
+
"[Portal] multiple mounted hosts detected; first mounted host is owner"
|
|
3561
|
+
);
|
|
3562
|
+
}
|
|
4525
3563
|
}
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
const cell = h.cell;
|
|
4537
|
-
const depsChanged = !cell.deps || cell.deps.length !== deps.length || cell.deps.some((d, i) => d !== deps[i]);
|
|
4538
|
-
if (depsChanged) {
|
|
4539
|
-
cell.deps = deps.slice();
|
|
4540
|
-
cell.generation++;
|
|
4541
|
-
cell.pending = true;
|
|
4542
|
-
cell.error = null;
|
|
4543
|
-
try {
|
|
4544
|
-
cell.start(inst.ssr ?? false, false);
|
|
4545
|
-
if (!cell.pending) {
|
|
4546
|
-
const cur = holder();
|
|
4547
|
-
cur.snapshot.value = cell.value;
|
|
4548
|
-
cur.snapshot.pending = cell.pending;
|
|
4549
|
-
cur.snapshot.error = cell.error;
|
|
3564
|
+
return inst && owner && inst === owner ? pending : void 0;
|
|
3565
|
+
};
|
|
3566
|
+
var HostFallback = HostFallback2;
|
|
3567
|
+
let owner = null;
|
|
3568
|
+
let pending;
|
|
3569
|
+
HostFallback2.render = function RenderFallback(props) {
|
|
3570
|
+
if (!owner || owner.mounted !== true) return null;
|
|
3571
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3572
|
+
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3573
|
+
ns.__PORTAL_WRITES = (ns.__PORTAL_WRITES || 0) + 1;
|
|
4550
3574
|
}
|
|
4551
|
-
|
|
4552
|
-
if (
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
3575
|
+
pending = props.children;
|
|
3576
|
+
if (owner.notifyUpdate) owner.notifyUpdate();
|
|
3577
|
+
return null;
|
|
3578
|
+
};
|
|
3579
|
+
return HostFallback2;
|
|
3580
|
+
}
|
|
3581
|
+
const slot = createPortalSlot();
|
|
3582
|
+
function PortalHost() {
|
|
3583
|
+
return slot.read();
|
|
4560
3584
|
}
|
|
4561
|
-
|
|
3585
|
+
PortalHost.render = function PortalRender(props) {
|
|
3586
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3587
|
+
const ns = globalThis.__ASKR__ || (globalThis.__ASKR__ = {});
|
|
3588
|
+
ns.__PORTAL_WRITES = (ns.__PORTAL_WRITES || 0) + 1;
|
|
3589
|
+
}
|
|
3590
|
+
slot.write(props.children);
|
|
3591
|
+
return null;
|
|
3592
|
+
};
|
|
3593
|
+
return PortalHost;
|
|
4562
3594
|
}
|
|
4563
|
-
function
|
|
4564
|
-
if (
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
3595
|
+
function ensureDefaultPortal() {
|
|
3596
|
+
if (!_defaultPortal) {
|
|
3597
|
+
if (typeof createPortalSlot === "function") {
|
|
3598
|
+
_defaultPortal = definePortal();
|
|
3599
|
+
_defaultPortalIsFallback = false;
|
|
3600
|
+
} else {
|
|
3601
|
+
_defaultPortal = definePortal();
|
|
3602
|
+
_defaultPortalIsFallback = true;
|
|
4570
3603
|
}
|
|
4571
|
-
|
|
4572
|
-
if (cache2.has(value2)) return cache2.get(value2);
|
|
4573
|
-
cache2.set(value2, value2);
|
|
4574
|
-
return value2;
|
|
4575
|
-
}
|
|
4576
|
-
let value;
|
|
4577
|
-
if (typeof source === "function" && !("value" in source)) {
|
|
4578
|
-
value = source();
|
|
4579
|
-
} else {
|
|
4580
|
-
value = source?.value ?? source;
|
|
3604
|
+
return _defaultPortal;
|
|
4581
3605
|
}
|
|
4582
|
-
if (
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
3606
|
+
if (_defaultPortalIsFallback && typeof createPortalSlot === "function") {
|
|
3607
|
+
const real = definePortal();
|
|
3608
|
+
_defaultPortal = real;
|
|
3609
|
+
_defaultPortalIsFallback = false;
|
|
4586
3610
|
}
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
3611
|
+
if (!_defaultPortalIsFallback && typeof createPortalSlot !== "function") {
|
|
3612
|
+
const fallback = definePortal();
|
|
3613
|
+
_defaultPortal = fallback;
|
|
3614
|
+
_defaultPortalIsFallback = true;
|
|
4590
3615
|
}
|
|
4591
|
-
|
|
4592
|
-
cache.set(value, result);
|
|
4593
|
-
return result;
|
|
4594
|
-
}
|
|
4595
|
-
function task(fn) {
|
|
4596
|
-
const ownerIsRoot = getCurrentComponentInstance()?.isRoot ?? false;
|
|
4597
|
-
registerMountOperation(async () => {
|
|
4598
|
-
if (!ownerIsRoot) {
|
|
4599
|
-
throw new Error("[Askr] task() may only be used in root components");
|
|
4600
|
-
}
|
|
4601
|
-
return await fn();
|
|
4602
|
-
});
|
|
3616
|
+
return _defaultPortal;
|
|
4603
3617
|
}
|
|
3618
|
+
var _defaultPortal, _defaultPortalIsFallback, DefaultPortal;
|
|
3619
|
+
var init_portal = __esm({
|
|
3620
|
+
"src/foundations/portal.tsx"() {
|
|
3621
|
+
"use strict";
|
|
3622
|
+
init_component();
|
|
3623
|
+
init_logger();
|
|
3624
|
+
_defaultPortalIsFallback = false;
|
|
3625
|
+
DefaultPortal = (() => {
|
|
3626
|
+
function Host() {
|
|
3627
|
+
const v = ensureDefaultPortal()();
|
|
3628
|
+
return v === void 0 ? null : v;
|
|
3629
|
+
}
|
|
3630
|
+
Host.render = function Render(props) {
|
|
3631
|
+
ensureDefaultPortal().render(props);
|
|
3632
|
+
return null;
|
|
3633
|
+
};
|
|
3634
|
+
return Host;
|
|
3635
|
+
})();
|
|
3636
|
+
}
|
|
3637
|
+
});
|
|
3638
|
+
|
|
3639
|
+
// src/index.ts
|
|
3640
|
+
var index_exports = {};
|
|
3641
|
+
__export(index_exports, {
|
|
3642
|
+
createIsland: () => createIsland,
|
|
3643
|
+
createSPA: () => createSPA,
|
|
3644
|
+
derive: () => derive,
|
|
3645
|
+
state: () => state
|
|
3646
|
+
});
|
|
3647
|
+
module.exports = __toCommonJS(index_exports);
|
|
4604
3648
|
|
|
4605
3649
|
// src/boot/index.ts
|
|
4606
3650
|
init_component();
|
|
4607
3651
|
init_scheduler();
|
|
4608
3652
|
init_logger();
|
|
4609
3653
|
init_navigate();
|
|
4610
|
-
|
|
3654
|
+
init_execution_model();
|
|
3655
|
+
init_jsx2();
|
|
4611
3656
|
init_portal();
|
|
4612
3657
|
init_renderer();
|
|
3658
|
+
var HAS_ROUTES_KEY2 = /* @__PURE__ */ Symbol.for("__ASKR_HAS_ROUTES__");
|
|
4613
3659
|
var componentIdCounter = 0;
|
|
4614
3660
|
var instancesByRoot = /* @__PURE__ */ new WeakMap();
|
|
4615
3661
|
var CLEANUP_SYMBOL = /* @__PURE__ */ Symbol.for("__tempoCleanup__");
|
|
@@ -4749,6 +3795,7 @@ function mountOrUpdate(rootElement, componentFn, options) {
|
|
|
4749
3795
|
globalScheduler.flush();
|
|
4750
3796
|
}
|
|
4751
3797
|
function createIsland(config) {
|
|
3798
|
+
assertExecutionModel("islands");
|
|
4752
3799
|
if (!config || typeof config !== "object") {
|
|
4753
3800
|
throw new Error("createIsland requires a config object");
|
|
4754
3801
|
}
|
|
@@ -4759,433 +3806,230 @@ function createIsland(config) {
|
|
|
4759
3806
|
if (!rootElement) throw new Error(`Root element not found: ${config.root}`);
|
|
4760
3807
|
if ("routes" in config) {
|
|
4761
3808
|
throw new Error(
|
|
4762
|
-
"createIsland does not accept routes; use createSPA for routed apps"
|
|
4763
|
-
);
|
|
4764
|
-
}
|
|
4765
|
-
mountOrUpdate(rootElement, config.component, {
|
|
4766
|
-
cleanupStrict: config.cleanupStrict
|
|
4767
|
-
});
|
|
4768
|
-
}
|
|
4769
|
-
async function createSPA(config) {
|
|
4770
|
-
if (!config || typeof config !== "object") {
|
|
4771
|
-
throw new Error("createSPA requires a config object");
|
|
4772
|
-
}
|
|
4773
|
-
if (!Array.isArray(config.routes) || config.routes.length === 0) {
|
|
4774
|
-
throw new Error(
|
|
4775
|
-
"createSPA requires a route table. If you are enhancing existing HTML, use createIsland instead."
|
|
4776
|
-
);
|
|
4777
|
-
}
|
|
4778
|
-
const rootElement = typeof config.root === "string" ? document.getElementById(config.root) : config.root;
|
|
4779
|
-
if (!rootElement) throw new Error(`Root element not found: ${config.root}`);
|
|
4780
|
-
const { clearRoutes: clearRoutes2, route: route2, lockRouteRegistration: lockRouteRegistration2, resolveRoute: resolveRoute2 } = await Promise.resolve().then(() => (init_route(), route_exports));
|
|
4781
|
-
clearRoutes2();
|
|
4782
|
-
for (const r of config.routes) {
|
|
4783
|
-
route2(r.path, r.handler, r.namespace);
|
|
4784
|
-
}
|
|
4785
|
-
if (process.env.NODE_ENV === "production") lockRouteRegistration2();
|
|
4786
|
-
const path = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
4787
|
-
const resolved = resolveRoute2(path);
|
|
4788
|
-
if (!resolved) {
|
|
4789
|
-
if (process.env.NODE_ENV !== "production") {
|
|
4790
|
-
logger.warn(
|
|
4791
|
-
`createSPA: no route found for current path (${path}). Mounting empty placeholder; navigation will activate routes when requested.`
|
|
4792
|
-
);
|
|
4793
|
-
}
|
|
4794
|
-
mountOrUpdate(rootElement, () => ({ type: "div", children: [] }), {
|
|
4795
|
-
cleanupStrict: false
|
|
4796
|
-
});
|
|
4797
|
-
const instance2 = instancesByRoot.get(rootElement);
|
|
4798
|
-
if (!instance2) throw new Error("Internal error: app instance missing");
|
|
4799
|
-
registerAppInstance(instance2, path);
|
|
4800
|
-
initializeNavigation();
|
|
4801
|
-
return;
|
|
4802
|
-
}
|
|
4803
|
-
mountOrUpdate(rootElement, resolved.handler, {
|
|
4804
|
-
cleanupStrict: false
|
|
4805
|
-
});
|
|
4806
|
-
const instance = instancesByRoot.get(rootElement);
|
|
4807
|
-
if (!instance) throw new Error("Internal error: app instance missing");
|
|
4808
|
-
registerAppInstance(instance, path);
|
|
4809
|
-
initializeNavigation();
|
|
4810
|
-
}
|
|
4811
|
-
async function hydrateSPA(config) {
|
|
4812
|
-
if (!config || typeof config !== "object") {
|
|
4813
|
-
throw new Error("hydrateSPA requires a config object");
|
|
4814
|
-
}
|
|
4815
|
-
if (!Array.isArray(config.routes) || config.routes.length === 0) {
|
|
4816
|
-
throw new Error(
|
|
4817
|
-
"hydrateSPA requires a route table. If you are enhancing existing HTML, use createIsland instead."
|
|
4818
|
-
);
|
|
4819
|
-
}
|
|
4820
|
-
const rootElement = typeof config.root === "string" ? document.getElementById(config.root) : config.root;
|
|
4821
|
-
if (!rootElement) throw new Error(`Root element not found: ${config.root}`);
|
|
4822
|
-
const serverHTML = rootElement.innerHTML;
|
|
4823
|
-
const {
|
|
4824
|
-
clearRoutes: clearRoutes2,
|
|
4825
|
-
route: route2,
|
|
4826
|
-
setServerLocation: setServerLocation2,
|
|
4827
|
-
lockRouteRegistration: lockRouteRegistration2,
|
|
4828
|
-
resolveRoute: resolveRoute2
|
|
4829
|
-
} = await Promise.resolve().then(() => (init_route(), route_exports));
|
|
4830
|
-
clearRoutes2();
|
|
4831
|
-
for (const r of config.routes) {
|
|
4832
|
-
route2(r.path, r.handler, r.namespace);
|
|
4833
|
-
}
|
|
4834
|
-
const path = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
4835
|
-
setServerLocation2(path);
|
|
4836
|
-
if (process.env.NODE_ENV === "production") lockRouteRegistration2();
|
|
4837
|
-
const resolved = resolveRoute2(path);
|
|
4838
|
-
if (!resolved) {
|
|
4839
|
-
throw new Error(`hydrateSPA: no route found for current path (${path}).`);
|
|
4840
|
-
}
|
|
4841
|
-
const { renderToStringSync: renderToStringSync2 } = await Promise.resolve().then(() => (init_ssr(), ssr_exports));
|
|
4842
|
-
const expectedHTML = renderToStringSync2(() => {
|
|
4843
|
-
const out = resolved.handler(resolved.params);
|
|
4844
|
-
return out ?? {
|
|
4845
|
-
type: "div",
|
|
4846
|
-
children: []
|
|
4847
|
-
};
|
|
4848
|
-
});
|
|
4849
|
-
const serverContainer = document.createElement("div");
|
|
4850
|
-
serverContainer.innerHTML = serverHTML;
|
|
4851
|
-
const expectedContainer = document.createElement("div");
|
|
4852
|
-
expectedContainer.innerHTML = expectedHTML;
|
|
4853
|
-
if (!serverContainer.isEqualNode(expectedContainer)) {
|
|
4854
|
-
throw new Error(
|
|
4855
|
-
"[Askr] Hydration mismatch detected. Server HTML does not match expected server-render output."
|
|
4856
|
-
);
|
|
4857
|
-
}
|
|
4858
|
-
mountOrUpdate(rootElement, resolved.handler, {
|
|
4859
|
-
cleanupStrict: false
|
|
4860
|
-
});
|
|
4861
|
-
const { registerAppInstance: registerAppInstance2, initializeNavigation: initializeNavigation2 } = await Promise.resolve().then(() => (init_navigate(), navigate_exports));
|
|
4862
|
-
const instance = instancesByRoot.get(rootElement);
|
|
4863
|
-
if (!instance) throw new Error("Internal error: app instance missing");
|
|
4864
|
-
registerAppInstance2(instance, path);
|
|
4865
|
-
initializeNavigation2();
|
|
4866
|
-
}
|
|
4867
|
-
function cleanupApp(root) {
|
|
4868
|
-
const rootElement = typeof root === "string" ? document.getElementById(root) : root;
|
|
4869
|
-
if (!rootElement) return;
|
|
4870
|
-
const cleanupFn = rootElement[CLEANUP_SYMBOL];
|
|
4871
|
-
if (typeof cleanupFn === "function") {
|
|
4872
|
-
cleanupFn();
|
|
4873
|
-
}
|
|
4874
|
-
instancesByRoot.delete(rootElement);
|
|
4875
|
-
}
|
|
4876
|
-
function hasApp(root) {
|
|
4877
|
-
const rootElement = typeof root === "string" ? document.getElementById(root) : root;
|
|
4878
|
-
if (!rootElement) return false;
|
|
4879
|
-
return instancesByRoot.has(rootElement);
|
|
4880
|
-
}
|
|
4881
|
-
|
|
4882
|
-
// src/index.ts
|
|
4883
|
-
init_route();
|
|
4884
|
-
init_route();
|
|
4885
|
-
init_navigate();
|
|
4886
|
-
|
|
4887
|
-
// src/components/Link.tsx
|
|
4888
|
-
init_navigate();
|
|
4889
|
-
function Link({ href, children }) {
|
|
4890
|
-
return {
|
|
4891
|
-
type: "a",
|
|
4892
|
-
props: {
|
|
4893
|
-
href,
|
|
4894
|
-
children,
|
|
4895
|
-
onClick: (e) => {
|
|
4896
|
-
const event = e;
|
|
4897
|
-
const button = event.button ?? 0;
|
|
4898
|
-
if (button !== 0 || // not left-click
|
|
4899
|
-
event.ctrlKey || // Ctrl/Cmd+click
|
|
4900
|
-
event.metaKey || // Cmd on Mac
|
|
4901
|
-
event.shiftKey || // Shift+click
|
|
4902
|
-
event.altKey) {
|
|
4903
|
-
return;
|
|
4904
|
-
}
|
|
4905
|
-
event.preventDefault();
|
|
4906
|
-
navigate(href);
|
|
4907
|
-
}
|
|
4908
|
-
}
|
|
4909
|
-
};
|
|
4910
|
-
}
|
|
4911
|
-
|
|
4912
|
-
// src/foundations/layout.tsx
|
|
4913
|
-
function layout(Layout) {
|
|
4914
|
-
return (children, props) => Layout({ ...props, children });
|
|
4915
|
-
}
|
|
4916
|
-
|
|
4917
|
-
// src/foundations/slot.tsx
|
|
4918
|
-
init_logger();
|
|
4919
|
-
init_jsx();
|
|
4920
|
-
function Slot(props) {
|
|
4921
|
-
if (props.asChild) {
|
|
4922
|
-
const { children, ...rest } = props;
|
|
4923
|
-
if (isElement(children)) {
|
|
4924
|
-
return cloneElement(children, rest);
|
|
4925
|
-
}
|
|
4926
|
-
logger.warn("<Slot asChild> expects a single JSX element child.");
|
|
4927
|
-
return null;
|
|
4928
|
-
}
|
|
4929
|
-
return {
|
|
4930
|
-
$$typeof: ELEMENT_TYPE,
|
|
4931
|
-
type: Fragment,
|
|
4932
|
-
props: { children: props.children }
|
|
4933
|
-
};
|
|
4934
|
-
}
|
|
4935
|
-
|
|
4936
|
-
// src/index.ts
|
|
4937
|
-
init_portal();
|
|
4938
|
-
init_ssr();
|
|
4939
|
-
init_jsx_runtime();
|
|
4940
|
-
init_route();
|
|
4941
|
-
init_navigate();
|
|
4942
|
-
|
|
4943
|
-
// src/runtime/fastlane.ts
|
|
4944
|
-
init_scheduler();
|
|
4945
|
-
init_logger();
|
|
4946
|
-
init_component();
|
|
4947
|
-
init_renderer();
|
|
4948
|
-
init_fastlane_shared();
|
|
4949
|
-
init_types2();
|
|
4950
|
-
init_dev_namespace();
|
|
4951
|
-
function unwrapFragmentForFastPath(vnode) {
|
|
4952
|
-
if (!vnode || typeof vnode !== "object" || !("type" in vnode)) return vnode;
|
|
4953
|
-
const v = vnode;
|
|
4954
|
-
if (typeof v.type === "symbol" && (v.type === Fragment || String(v.type) === "Symbol(askr.fragment)")) {
|
|
4955
|
-
const children = v.children || v.props?.children;
|
|
4956
|
-
if (Array.isArray(children) && children.length > 0) {
|
|
4957
|
-
for (const child of children) {
|
|
4958
|
-
if (child && typeof child === "object" && "type" in child) {
|
|
4959
|
-
const c = child;
|
|
4960
|
-
if (typeof c.type === "string") {
|
|
4961
|
-
return child;
|
|
4962
|
-
}
|
|
4963
|
-
}
|
|
4964
|
-
}
|
|
4965
|
-
}
|
|
4966
|
-
}
|
|
4967
|
-
return vnode;
|
|
4968
|
-
}
|
|
4969
|
-
function classifyUpdate(instance, result) {
|
|
4970
|
-
const unwrappedResult = unwrapFragmentForFastPath(result);
|
|
4971
|
-
if (!unwrappedResult || typeof unwrappedResult !== "object" || !("type" in unwrappedResult))
|
|
4972
|
-
return { useFastPath: false, reason: "not-vnode" };
|
|
4973
|
-
const vnode = unwrappedResult;
|
|
4974
|
-
if (vnode == null || typeof vnode.type !== "string")
|
|
4975
|
-
return { useFastPath: false, reason: "not-intrinsic" };
|
|
4976
|
-
const parent = instance.target;
|
|
4977
|
-
if (!parent) return { useFastPath: false, reason: "no-root" };
|
|
4978
|
-
const firstChild = parent.children[0];
|
|
4979
|
-
if (!firstChild) return { useFastPath: false, reason: "no-first-child" };
|
|
4980
|
-
if (firstChild.tagName.toLowerCase() !== String(vnode.type).toLowerCase())
|
|
4981
|
-
return { useFastPath: false, reason: "root-tag-mismatch" };
|
|
4982
|
-
const children = vnode.children || vnode.props?.children;
|
|
4983
|
-
if (!Array.isArray(children))
|
|
4984
|
-
return { useFastPath: false, reason: "no-children-array" };
|
|
4985
|
-
for (const c of children) {
|
|
4986
|
-
if (typeof c === "object" && c !== null && "type" in c && typeof c.type === "function") {
|
|
4987
|
-
return { useFastPath: false, reason: "component-child-present" };
|
|
4988
|
-
}
|
|
4989
|
-
}
|
|
4990
|
-
if (instance.mountOperations.length > 0)
|
|
4991
|
-
return { useFastPath: false, reason: "pending-mounts" };
|
|
4992
|
-
try {
|
|
4993
|
-
populateKeyMapForElement(firstChild);
|
|
4994
|
-
} catch {
|
|
4995
|
-
}
|
|
4996
|
-
const oldKeyMap = getKeyMapForElement(firstChild);
|
|
4997
|
-
const decision = isKeyedReorderFastPathEligible(
|
|
4998
|
-
firstChild,
|
|
4999
|
-
children,
|
|
5000
|
-
oldKeyMap
|
|
5001
|
-
);
|
|
5002
|
-
if (!decision.useFastPath || decision.totalKeyed < 128)
|
|
5003
|
-
return { ...decision, useFastPath: false, reason: "renderer-declined" };
|
|
5004
|
-
return { ...decision, useFastPath: true };
|
|
5005
|
-
}
|
|
5006
|
-
function commitReorderOnly(instance, result) {
|
|
5007
|
-
const evaluate2 = globalThis.__ASKR_RENDERER?.evaluate;
|
|
5008
|
-
if (typeof evaluate2 !== "function") {
|
|
5009
|
-
logger.warn(
|
|
5010
|
-
"[Tempo][FASTPATH][DEV] renderer.evaluate not available; declining fast-lane"
|
|
5011
|
-
);
|
|
5012
|
-
return false;
|
|
5013
|
-
}
|
|
5014
|
-
const schedBefore = process.env.NODE_ENV !== "production" ? globalScheduler.getState() : null;
|
|
5015
|
-
enterBulkCommit();
|
|
5016
|
-
try {
|
|
5017
|
-
globalScheduler.runWithSyncProgress(() => {
|
|
5018
|
-
evaluate2(result, instance.target);
|
|
5019
|
-
try {
|
|
5020
|
-
finalizeReadSubscriptions(instance);
|
|
5021
|
-
} catch (e) {
|
|
5022
|
-
if (process.env.NODE_ENV !== "production") throw e;
|
|
5023
|
-
}
|
|
5024
|
-
});
|
|
5025
|
-
const clearedAfter = globalScheduler.clearPendingSyncTasks?.() ?? 0;
|
|
5026
|
-
setDevValue("__FASTLANE_CLEARED_AFTER", clearedAfter);
|
|
5027
|
-
if (process.env.NODE_ENV !== "production") {
|
|
5028
|
-
validateFastLaneInvariants(instance, schedBefore);
|
|
5029
|
-
}
|
|
5030
|
-
return true;
|
|
5031
|
-
} finally {
|
|
5032
|
-
exitBulkCommit();
|
|
3809
|
+
"createIsland does not accept routes; use createSPA for routed apps"
|
|
3810
|
+
);
|
|
5033
3811
|
}
|
|
5034
|
-
|
|
5035
|
-
|
|
3812
|
+
try {
|
|
3813
|
+
const g = globalThis;
|
|
3814
|
+
if (g[HAS_ROUTES_KEY2]) {
|
|
5036
3815
|
throw new Error(
|
|
5037
|
-
"
|
|
3816
|
+
"Routes are not supported with islands. Use createSPA (client) or createSSR (server) instead."
|
|
5038
3817
|
);
|
|
5039
3818
|
}
|
|
3819
|
+
} catch {
|
|
5040
3820
|
}
|
|
3821
|
+
mountOrUpdate(rootElement, config.component, {
|
|
3822
|
+
cleanupStrict: config.cleanupStrict
|
|
3823
|
+
});
|
|
5041
3824
|
}
|
|
5042
|
-
function
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
mountOps: instance.mountOperations.length,
|
|
5047
|
-
cleanupFns: instance.cleanupFns.length
|
|
5048
|
-
};
|
|
5049
|
-
setDevValue("__LAST_FASTLANE_INVARIANTS", invariants);
|
|
5050
|
-
if (commitCount !== 1) {
|
|
5051
|
-
console.error(
|
|
5052
|
-
"[FASTLANE][INV] commitCount",
|
|
5053
|
-
commitCount,
|
|
5054
|
-
"diag",
|
|
5055
|
-
globalThis.__ASKR_DIAG
|
|
5056
|
-
);
|
|
5057
|
-
throw new Error(
|
|
5058
|
-
"Fast-lane invariant violated: expected exactly one DOM commit during reorder-only commit"
|
|
5059
|
-
);
|
|
3825
|
+
async function createSPA(config) {
|
|
3826
|
+
assertExecutionModel("spa");
|
|
3827
|
+
if (!config || typeof config !== "object") {
|
|
3828
|
+
throw new Error("createSPA requires a config object");
|
|
5060
3829
|
}
|
|
5061
|
-
if (
|
|
3830
|
+
if (!Array.isArray(config.routes) || config.routes.length === 0) {
|
|
5062
3831
|
throw new Error(
|
|
5063
|
-
"
|
|
3832
|
+
"createSPA requires a route table. If you are enhancing existing HTML, use createIsland instead."
|
|
5064
3833
|
);
|
|
5065
3834
|
}
|
|
5066
|
-
|
|
3835
|
+
const rootElement = typeof config.root === "string" ? document.getElementById(config.root) : config.root;
|
|
3836
|
+
if (!rootElement) throw new Error(`Root element not found: ${config.root}`);
|
|
3837
|
+
const { clearRoutes: clearRoutes2, route: route2, lockRouteRegistration: lockRouteRegistration2, resolveRoute: resolveRoute2 } = await Promise.resolve().then(() => (init_route(), route_exports));
|
|
3838
|
+
clearRoutes2();
|
|
3839
|
+
for (const r of config.routes) {
|
|
3840
|
+
route2(r.path, r.handler, r.namespace);
|
|
3841
|
+
}
|
|
3842
|
+
if (process.env.NODE_ENV === "production") lockRouteRegistration2();
|
|
3843
|
+
const path = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
3844
|
+
const resolved = resolveRoute2(path);
|
|
3845
|
+
if (!resolved) {
|
|
3846
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3847
|
+
logger.warn(
|
|
3848
|
+
`createSPA: no route found for current path (${path}). Mounting empty placeholder; navigation will activate routes when requested.`
|
|
3849
|
+
);
|
|
3850
|
+
}
|
|
3851
|
+
mountOrUpdate(rootElement, () => ({ type: "div", children: [] }), {
|
|
3852
|
+
cleanupStrict: false
|
|
3853
|
+
});
|
|
3854
|
+
const instance2 = instancesByRoot.get(rootElement);
|
|
3855
|
+
if (!instance2) throw new Error("Internal error: app instance missing");
|
|
3856
|
+
registerAppInstance(instance2, path);
|
|
3857
|
+
initializeNavigation();
|
|
3858
|
+
return;
|
|
3859
|
+
}
|
|
3860
|
+
mountOrUpdate(rootElement, resolved.handler, {
|
|
3861
|
+
cleanupStrict: false
|
|
3862
|
+
});
|
|
3863
|
+
const instance = instancesByRoot.get(rootElement);
|
|
3864
|
+
if (!instance) throw new Error("Internal error: app instance missing");
|
|
3865
|
+
registerAppInstance(instance, path);
|
|
3866
|
+
initializeNavigation();
|
|
3867
|
+
}
|
|
3868
|
+
|
|
3869
|
+
// src/runtime/state.ts
|
|
3870
|
+
init_scheduler();
|
|
3871
|
+
init_component();
|
|
3872
|
+
init_invariant();
|
|
3873
|
+
init_fastlane();
|
|
3874
|
+
function state(initialValue) {
|
|
3875
|
+
const instance = getCurrentInstance();
|
|
3876
|
+
if (!instance) {
|
|
5067
3877
|
throw new Error(
|
|
5068
|
-
"
|
|
3878
|
+
"state() can only be called during component render execution. Move state() calls to the top level of your component function."
|
|
5069
3879
|
);
|
|
5070
3880
|
}
|
|
5071
|
-
const
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
"[FASTLANE] schedBefore, schedAfter",
|
|
5075
|
-
schedBefore,
|
|
5076
|
-
schedAfter
|
|
5077
|
-
);
|
|
5078
|
-
console.error("[FASTLANE] enqueue logs", getDevValue("__ENQUEUE_LOGS"));
|
|
3881
|
+
const index = getNextStateIndex();
|
|
3882
|
+
const stateValues = instance.stateValues;
|
|
3883
|
+
if (index < instance.stateIndexCheck) {
|
|
5079
3884
|
throw new Error(
|
|
5080
|
-
|
|
3885
|
+
`State index violation: state() call at index ${index}, but previously saw index ${instance.stateIndexCheck}. This happens when state() is called conditionally (inside if/for/etc). Move all state() calls to the top level of your component function, before any conditionals.`
|
|
5081
3886
|
);
|
|
5082
3887
|
}
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
0,
|
|
5087
|
-
finalState.taskCount - (executing ? 1 : 0)
|
|
3888
|
+
invariant(
|
|
3889
|
+
index >= instance.stateIndexCheck,
|
|
3890
|
+
"[State] State indices must increase monotonically"
|
|
5088
3891
|
);
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
attempts++;
|
|
5095
|
-
}
|
|
5096
|
-
finalState = globalScheduler.getState();
|
|
5097
|
-
outstandingAfter = Math.max(
|
|
5098
|
-
0,
|
|
5099
|
-
finalState.taskCount - (globalScheduler.isExecuting() ? 1 : 0)
|
|
5100
|
-
);
|
|
5101
|
-
if (outstandingAfter !== 0) {
|
|
5102
|
-
console.error(
|
|
5103
|
-
"[FASTLANE] Post-commit enqueue logs:",
|
|
5104
|
-
getDevValue("__ENQUEUE_LOGS")
|
|
5105
|
-
);
|
|
5106
|
-
console.error(
|
|
5107
|
-
"[FASTLANE] Cleared counts:",
|
|
5108
|
-
getDevValue("__FASTLANE_CLEARED_TASKS"),
|
|
5109
|
-
getDevValue("__FASTLANE_CLEARED_AFTER")
|
|
3892
|
+
instance.stateIndexCheck = index;
|
|
3893
|
+
if (instance.firstRenderComplete) {
|
|
3894
|
+
if (!instance.expectedStateIndices.includes(index)) {
|
|
3895
|
+
throw new Error(
|
|
3896
|
+
`Hook order violation: state() called at index ${index}, but this index was not in the first render's sequence [${instance.expectedStateIndices.join(", ")}]. This usually means state() is inside a conditional or loop. Move all state() calls to the top level of your component function.`
|
|
5110
3897
|
);
|
|
3898
|
+
}
|
|
3899
|
+
} else {
|
|
3900
|
+
instance.expectedStateIndices.push(index);
|
|
3901
|
+
}
|
|
3902
|
+
if (stateValues[index]) {
|
|
3903
|
+
const existing = stateValues[index];
|
|
3904
|
+
if (existing._owner !== instance) {
|
|
5111
3905
|
throw new Error(
|
|
5112
|
-
`
|
|
3906
|
+
`State ownership violation: state() called at index ${index} is owned by a different component instance. State ownership is positional and immutable.`
|
|
5113
3907
|
);
|
|
5114
3908
|
}
|
|
3909
|
+
return existing;
|
|
5115
3910
|
}
|
|
3911
|
+
const cell = createStateCell(initialValue, instance);
|
|
3912
|
+
stateValues[index] = cell;
|
|
3913
|
+
return cell;
|
|
5116
3914
|
}
|
|
5117
|
-
function
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
return false;
|
|
3915
|
+
function createStateCell(initialValue, instance) {
|
|
3916
|
+
let value = initialValue;
|
|
3917
|
+
const readers = /* @__PURE__ */ new Map();
|
|
3918
|
+
function read() {
|
|
3919
|
+
read._hasBeenRead = true;
|
|
3920
|
+
const inst = getCurrentInstance();
|
|
3921
|
+
if (inst && inst._currentRenderToken !== void 0) {
|
|
3922
|
+
if (!inst._pendingReadStates) inst._pendingReadStates = /* @__PURE__ */ new Set();
|
|
3923
|
+
inst._pendingReadStates.add(read);
|
|
3924
|
+
}
|
|
3925
|
+
return value;
|
|
5129
3926
|
}
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
3927
|
+
read._readers = readers;
|
|
3928
|
+
read._owner = instance;
|
|
3929
|
+
read.set = (newValueOrUpdater) => {
|
|
3930
|
+
const currentInst = getCurrentInstance();
|
|
3931
|
+
if (currentInst !== null) {
|
|
3932
|
+
throw new Error(
|
|
3933
|
+
`[Askr] state.set() cannot be called during component render. State mutations during render break the actor model and cause infinite loops. Move state updates to event handlers or use conditional rendering instead.`
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
let newValue;
|
|
3937
|
+
if (typeof newValueOrUpdater === "function") {
|
|
3938
|
+
const updater = newValueOrUpdater;
|
|
3939
|
+
newValue = updater(value);
|
|
3940
|
+
} else {
|
|
3941
|
+
newValue = newValueOrUpdater;
|
|
3942
|
+
}
|
|
3943
|
+
if (Object.is(value, newValue)) return;
|
|
3944
|
+
if (isBulkCommitActive2()) {
|
|
3945
|
+
value = newValue;
|
|
3946
|
+
return;
|
|
3947
|
+
}
|
|
3948
|
+
value = newValue;
|
|
3949
|
+
const readersMap = read._readers;
|
|
3950
|
+
if (readersMap) {
|
|
3951
|
+
for (const [subInst, token] of readersMap) {
|
|
3952
|
+
if (subInst.lastRenderToken !== token) continue;
|
|
3953
|
+
if (!subInst.hasPendingUpdate) {
|
|
3954
|
+
subInst.hasPendingUpdate = true;
|
|
3955
|
+
const subTask = subInst._pendingFlushTask;
|
|
3956
|
+
if (subTask) globalScheduler.enqueue(subTask);
|
|
3957
|
+
else
|
|
3958
|
+
globalScheduler.enqueue(() => {
|
|
3959
|
+
subInst.hasPendingUpdate = false;
|
|
3960
|
+
subInst.notifyUpdate?.();
|
|
3961
|
+
});
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
const readersMapForOwner = readersMap;
|
|
3966
|
+
const ownerRecordedToken = readersMapForOwner?.get(instance);
|
|
3967
|
+
const ownerShouldEnqueue = (
|
|
3968
|
+
// Normal case: owner read this state in last committed render
|
|
3969
|
+
ownerRecordedToken !== void 0 && instance.lastRenderToken === ownerRecordedToken
|
|
3970
|
+
);
|
|
3971
|
+
if (ownerShouldEnqueue && !instance.hasPendingUpdate) {
|
|
3972
|
+
instance.hasPendingUpdate = true;
|
|
3973
|
+
const task = instance._pendingFlushTask;
|
|
3974
|
+
if (task) globalScheduler.enqueue(task);
|
|
3975
|
+
else
|
|
3976
|
+
globalScheduler.enqueue(() => {
|
|
3977
|
+
instance.hasPendingUpdate = false;
|
|
3978
|
+
instance.notifyUpdate?.();
|
|
3979
|
+
});
|
|
3980
|
+
}
|
|
5139
3981
|
};
|
|
3982
|
+
return read;
|
|
5140
3983
|
}
|
|
5141
3984
|
|
|
5142
|
-
// src/
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
if (!
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
3985
|
+
// src/runtime/derive.ts
|
|
3986
|
+
init_component();
|
|
3987
|
+
var deriveCaches = /* @__PURE__ */ new WeakMap();
|
|
3988
|
+
function getDeriveCache(instance) {
|
|
3989
|
+
let cache = deriveCaches.get(instance);
|
|
3990
|
+
if (!cache) {
|
|
3991
|
+
cache = /* @__PURE__ */ new Map();
|
|
3992
|
+
deriveCaches.set(instance, cache);
|
|
3993
|
+
}
|
|
3994
|
+
return cache;
|
|
3995
|
+
}
|
|
3996
|
+
function derive(source, map) {
|
|
3997
|
+
if (map === void 0 && typeof source === "function") {
|
|
3998
|
+
const value2 = source();
|
|
3999
|
+
if (value2 == null) return null;
|
|
4000
|
+
const instance2 = getCurrentComponentInstance();
|
|
4001
|
+
if (!instance2) {
|
|
4002
|
+
return value2;
|
|
4003
|
+
}
|
|
4004
|
+
const cache2 = getDeriveCache(instance2);
|
|
4005
|
+
if (cache2.has(value2)) return cache2.get(value2);
|
|
4006
|
+
cache2.set(value2, value2);
|
|
4007
|
+
return value2;
|
|
4008
|
+
}
|
|
4009
|
+
let value;
|
|
4010
|
+
if (typeof source === "function" && !("value" in source)) {
|
|
4011
|
+
value = source();
|
|
4012
|
+
} else {
|
|
4013
|
+
value = source?.value ?? source;
|
|
4014
|
+
}
|
|
4015
|
+
if (value == null) return null;
|
|
4016
|
+
const instance = getCurrentComponentInstance();
|
|
4017
|
+
if (!instance) {
|
|
4018
|
+
return map(value);
|
|
4019
|
+
}
|
|
4020
|
+
const cache = getDeriveCache(instance);
|
|
4021
|
+
if (cache.has(value)) {
|
|
4022
|
+
return cache.get(value);
|
|
4023
|
+
}
|
|
4024
|
+
const result = map(value);
|
|
4025
|
+
cache.set(value, result);
|
|
4026
|
+
return result;
|
|
5151
4027
|
}
|
|
5152
4028
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5153
4029
|
0 && (module.exports = {
|
|
5154
|
-
DefaultPortal,
|
|
5155
|
-
Fragment,
|
|
5156
|
-
Link,
|
|
5157
|
-
Slot,
|
|
5158
|
-
_resetDefaultPortal,
|
|
5159
|
-
cleanupApp,
|
|
5160
|
-
clearRoutes,
|
|
5161
|
-
collectResources,
|
|
5162
4030
|
createIsland,
|
|
5163
4031
|
createSPA,
|
|
5164
|
-
defineContext,
|
|
5165
|
-
definePortal,
|
|
5166
4032
|
derive,
|
|
5167
|
-
|
|
5168
|
-
getNamespaceRoutes,
|
|
5169
|
-
getRoutes,
|
|
5170
|
-
getSignal,
|
|
5171
|
-
hasApp,
|
|
5172
|
-
hydrateSPA,
|
|
5173
|
-
jsx,
|
|
5174
|
-
jsxs,
|
|
5175
|
-
layout,
|
|
5176
|
-
navigate,
|
|
5177
|
-
readContext,
|
|
5178
|
-
renderToStream,
|
|
5179
|
-
renderToString,
|
|
5180
|
-
renderToStringSync,
|
|
5181
|
-
renderToStringSyncForUrl,
|
|
5182
|
-
resolveResources,
|
|
5183
|
-
resource,
|
|
5184
|
-
route,
|
|
5185
|
-
scheduleEventHandler,
|
|
5186
|
-
setServerLocation,
|
|
5187
|
-
state,
|
|
5188
|
-
task,
|
|
5189
|
-
unloadNamespace
|
|
4033
|
+
state
|
|
5190
4034
|
});
|
|
5191
4035
|
//# sourceMappingURL=index.cjs.map
|