ilha 0.14.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/define.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{mount-CzFZBgZG.js → mount-CCMOkDSb.js} +587 -99
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@ if (host) mount(host, Counter, { hydrate: true });
|
|
|
117
117
|
| `timeout` | none | Serialize after this many ms |
|
|
118
118
|
| `captureActions` | `false` | Probe handlers for server RPCs |
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
`renderToString` builds HTML without a DOM — no polyfill in Node, Bun, or edge runtimes.
|
|
121
121
|
|
|
122
122
|
---
|
|
123
123
|
|
package/dist/define.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as atom, c as instr, d as getFiber, f as makeFiber, i as interpret, l as isAtomHandle, n as renderToString, o as batch, r as paint, s as handleOwner, t as mount, u as closeFiber } from "./mount-
|
|
1
|
+
import { a as atom, c as instr, d as getFiber, f as makeFiber, i as interpret, l as isAtomHandle, n as renderToString, o as batch, r as paint, s as handleOwner, t as mount, u as closeFiber } from "./mount-CCMOkDSb.js";
|
|
2
2
|
import { i as Fragment, t as h } from "./vnode-DHN2EFHi.js";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Stream from "effect/Stream";
|
|
@@ -163,6 +163,22 @@ function beginPrimitiveFrame(fiber) {
|
|
|
163
163
|
if (used > 0 && used !== slots) console.warn(`ilha: atom/watch slot count changed between renders (${slots} → ${used}); keep primitive order stable`);
|
|
164
164
|
fiber.primitiveI = 0;
|
|
165
165
|
fiber.watchI = 0;
|
|
166
|
+
const islandFrame = fiber.islandFrame ??= {
|
|
167
|
+
i: 0,
|
|
168
|
+
slots: []
|
|
169
|
+
};
|
|
170
|
+
const usedIslands = islandFrame.i;
|
|
171
|
+
if (usedIslands < islandFrame.slots.length) {
|
|
172
|
+
for (let j = usedIslands; j < islandFrame.slots.length; j++) {
|
|
173
|
+
const slot = islandFrame.slots[j];
|
|
174
|
+
if (slot) {
|
|
175
|
+
slot.unmount?.();
|
|
176
|
+
islandFrame.slots[j] = void 0;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
islandFrame.slots.length = usedIslands;
|
|
180
|
+
}
|
|
181
|
+
islandFrame.i = 0;
|
|
166
182
|
}
|
|
167
183
|
function readTracked(atom, registry) {
|
|
168
184
|
const frame = trackStack.at(-1);
|
|
@@ -417,12 +433,12 @@ function bindEvents(node, props, fiber) {
|
|
|
417
433
|
//#endregion
|
|
418
434
|
//#region src/morph.ts
|
|
419
435
|
const PRESERVE_ATTR = "data-morph-preserve";
|
|
420
|
-
const KEY_ATTR = "data-ilha-key";
|
|
421
|
-
const SLOT_ATTR = "data-ilha-slot";
|
|
436
|
+
const KEY_ATTR$1 = "data-ilha-key";
|
|
437
|
+
const SLOT_ATTR$1 = "data-ilha-slot";
|
|
422
438
|
function morphKeyOf(el) {
|
|
423
|
-
const k = el.getAttribute(KEY_ATTR);
|
|
439
|
+
const k = el.getAttribute(KEY_ATTR$1);
|
|
424
440
|
if (k !== null) return `k:${k}`;
|
|
425
|
-
const s = el.getAttribute(SLOT_ATTR);
|
|
441
|
+
const s = el.getAttribute(SLOT_ATTR$1);
|
|
426
442
|
return s === null ? null : `s:${s}`;
|
|
427
443
|
}
|
|
428
444
|
function shouldPreserveMorphAttr(el, name) {
|
|
@@ -529,7 +545,7 @@ function morphChildren(fromParent, toParent) {
|
|
|
529
545
|
fromParent.replaceChild(toEl, fromEl);
|
|
530
546
|
continue;
|
|
531
547
|
}
|
|
532
|
-
const slotId = toEl.getAttribute(SLOT_ATTR);
|
|
548
|
+
const slotId = toEl.getAttribute(SLOT_ATTR$1);
|
|
533
549
|
if (slotId !== null && fromEl.getAttribute("data-ilha-slot") === slotId) continue;
|
|
534
550
|
if (fromEl.localName === "input") {
|
|
535
551
|
const hadChecked = fromEl.hasAttribute("checked");
|
|
@@ -701,13 +717,13 @@ function runSetup(fiber, fn) {
|
|
|
701
717
|
|
|
702
718
|
//#endregion
|
|
703
719
|
//#region src/paint.ts
|
|
704
|
-
const ISLAND = Symbol.for("ilha.island");
|
|
705
|
-
const ISLAND_MOUNT_INTERNAL = Symbol.for("ilha.islandMountInternal");
|
|
706
|
-
const ISLAND_SLOT_TAG = Symbol.for("ilha.islandSlotTag");
|
|
707
|
-
function insert(fiber, nodes) {
|
|
720
|
+
const ISLAND$1 = Symbol.for("ilha.island");
|
|
721
|
+
const ISLAND_MOUNT_INTERNAL$1 = Symbol.for("ilha.islandMountInternal");
|
|
722
|
+
const ISLAND_SLOT_TAG$1 = Symbol.for("ilha.islandSlotTag");
|
|
723
|
+
function insert$1(fiber, nodes) {
|
|
708
724
|
for (const n of nodes) fiber.root.appendChild(n);
|
|
709
725
|
}
|
|
710
|
-
function disposeHoles(fiber, opts) {
|
|
726
|
+
function disposeHoles$1(fiber, opts) {
|
|
711
727
|
const keep = [];
|
|
712
728
|
for (const h of fiber.holes) {
|
|
713
729
|
if (opts?.morph && h.keepOnMorph) {
|
|
@@ -718,10 +734,10 @@ function disposeHoles(fiber, opts) {
|
|
|
718
734
|
}
|
|
719
735
|
fiber.holes = keep;
|
|
720
736
|
}
|
|
721
|
-
function skip(x) {
|
|
737
|
+
function skip$1(x) {
|
|
722
738
|
return x === null || x === void 0 || typeof x === "boolean";
|
|
723
739
|
}
|
|
724
|
-
function applyProps(el, props, fiber) {
|
|
740
|
+
function applyProps$1(el, props, fiber) {
|
|
725
741
|
for (const [k, v] of Object.entries(props)) {
|
|
726
742
|
if (k === "children" || k === "key" || k === "ref") continue;
|
|
727
743
|
if (k === "className") {
|
|
@@ -776,10 +792,10 @@ function applyProps(el, props, fiber) {
|
|
|
776
792
|
fiber.holes.push({ dispose: () => ref(null) });
|
|
777
793
|
}
|
|
778
794
|
}
|
|
779
|
-
const KEEP = Symbol("keep");
|
|
780
|
-
function unwrap(value, keep) {
|
|
795
|
+
const KEEP$1 = Symbol("keep");
|
|
796
|
+
function unwrap$1(value, keep) {
|
|
781
797
|
if (AsyncResult.isAsyncResult(value)) {
|
|
782
|
-
if (AsyncResult.isWaiting(value) && keep !== void 0) return KEEP;
|
|
798
|
+
if (AsyncResult.isWaiting(value) && keep !== void 0) return KEEP$1;
|
|
783
799
|
if (AsyncResult.isFailure(value) && !AsyncResult.isWaiting(value)) return String(AsyncResult.error(value) ?? "error");
|
|
784
800
|
const v = AsyncResult.value(value);
|
|
785
801
|
if (v._tag === "Some") return v.value;
|
|
@@ -787,18 +803,23 @@ function unwrap(value, keep) {
|
|
|
787
803
|
}
|
|
788
804
|
return value;
|
|
789
805
|
}
|
|
790
|
-
function paintHole(fiber, view) {
|
|
791
|
-
if (view === KEEP) return;
|
|
806
|
+
function paintHole$1(fiber, view) {
|
|
807
|
+
if (view === KEEP$1) return;
|
|
808
|
+
const frame = fiber.islandFrame ??= {
|
|
809
|
+
i: 0,
|
|
810
|
+
slots: []
|
|
811
|
+
};
|
|
812
|
+
frame.i = 0;
|
|
792
813
|
const list = Array.isArray(view) ? view : null;
|
|
793
814
|
if (list && list.length > 0 && list.every((v) => isVNode(v) && v.key != null)) {
|
|
794
|
-
keyedPaintHole(fiber, list);
|
|
815
|
+
keyedPaintHole$1(fiber, list);
|
|
795
816
|
return;
|
|
796
817
|
}
|
|
797
|
-
disposeHoles(fiber);
|
|
818
|
+
disposeHoles$1(fiber);
|
|
798
819
|
if (fiber.root instanceof Element) fiber.root.replaceChildren();
|
|
799
|
-
insert(fiber, materialize(view, fiber));
|
|
820
|
+
insert$1(fiber, materialize$1(view, fiber));
|
|
800
821
|
}
|
|
801
|
-
function keyedPaintHole(fiber, views) {
|
|
822
|
+
function keyedPaintHole$1(fiber, views) {
|
|
802
823
|
const prev = fiber.keyedHoles ?? /* @__PURE__ */ new Map();
|
|
803
824
|
const keep = new Set(views.map((v) => String(v.key)));
|
|
804
825
|
for (const [k, h] of prev) if (!keep.has(k)) closeFiber(h);
|
|
@@ -812,34 +833,34 @@ function keyedPaintHole(fiber, views) {
|
|
|
812
833
|
nodes.push(reuse.root);
|
|
813
834
|
continue;
|
|
814
835
|
}
|
|
815
|
-
const made = materialize(v, fiber);
|
|
836
|
+
const made = materialize$1(v, fiber);
|
|
816
837
|
const hole = fiber.keyedHoles?.get(k);
|
|
817
838
|
if (hole) next.set(k, hole);
|
|
818
839
|
nodes.push(...made);
|
|
819
840
|
}
|
|
820
841
|
fiber.keyedHoles = next;
|
|
821
842
|
if (fiber.root instanceof Element) fiber.root.replaceChildren();
|
|
822
|
-
insert(fiber, nodes);
|
|
843
|
+
insert$1(fiber, nodes);
|
|
823
844
|
}
|
|
824
|
-
function openHole(parent) {
|
|
845
|
+
function openHole$1(parent) {
|
|
825
846
|
const id = parent.runtime.nextHole();
|
|
826
847
|
const host = document.createElement("span");
|
|
827
|
-
host.setAttribute(SLOT_ATTR, String(id));
|
|
848
|
+
host.setAttribute(SLOT_ATTR$1, String(id));
|
|
828
849
|
host.style.display = "contents";
|
|
829
850
|
const child = makeFiber(parent.runtime, host, (f, v) => {
|
|
830
|
-
disposeHoles(f);
|
|
851
|
+
disposeHoles$1(f);
|
|
831
852
|
if (f.root instanceof Element) f.root.replaceChildren();
|
|
832
|
-
insert(f, materialize(v, f));
|
|
853
|
+
insert$1(f, materialize$1(v, f));
|
|
833
854
|
}, { onFail: (e) => {
|
|
834
855
|
console.error(e);
|
|
835
|
-
paintHole(child, errorView(e));
|
|
856
|
+
paintHole$1(child, errorView$1(e));
|
|
836
857
|
} });
|
|
837
858
|
return {
|
|
838
859
|
fiber: child,
|
|
839
860
|
nodes: [host]
|
|
840
861
|
};
|
|
841
862
|
}
|
|
842
|
-
function errorView(e) {
|
|
863
|
+
function errorView$1(e) {
|
|
843
864
|
return {
|
|
844
865
|
$$ilha: 1,
|
|
845
866
|
type: "pre",
|
|
@@ -847,7 +868,7 @@ function errorView(e) {
|
|
|
847
868
|
children: [failureMessage(e)]
|
|
848
869
|
};
|
|
849
870
|
}
|
|
850
|
-
function findReusableAtomHost(fiber, atom) {
|
|
871
|
+
function findReusableAtomHost$1(fiber, atom) {
|
|
851
872
|
for (const h of fiber.holes) if (h.atom === atom && h.host?.isConnected && h.holeFiber && !h.holeFiber.closed) return {
|
|
852
873
|
host: h.host,
|
|
853
874
|
hole: h.holeFiber
|
|
@@ -855,9 +876,9 @@ function findReusableAtomHost(fiber, atom) {
|
|
|
855
876
|
}
|
|
856
877
|
function refreshAtomHost(fiber, atom, host, hole) {
|
|
857
878
|
if (hole.closed || !host.isConnected) return;
|
|
858
|
-
const next = unwrap(fiber.registry.get(atom), void 0);
|
|
859
|
-
if (next === KEEP) return;
|
|
860
|
-
paintHole(hole, next);
|
|
879
|
+
const next = unwrap$1(fiber.registry.get(atom), void 0);
|
|
880
|
+
if (next === KEEP$1) return;
|
|
881
|
+
paintHole$1(hole, next);
|
|
861
882
|
}
|
|
862
883
|
function refreshAllAtomHosts(fiber) {
|
|
863
884
|
for (const h of fiber.holes) if (h.atom && h.host && h.holeFiber) refreshAtomHost(fiber, h.atom, h.host, h.holeFiber);
|
|
@@ -870,14 +891,14 @@ function pruneDisconnectedAtomHoles(fiber) {
|
|
|
870
891
|
return false;
|
|
871
892
|
});
|
|
872
893
|
}
|
|
873
|
-
function atomHostPlaceholder(host) {
|
|
894
|
+
function atomHostPlaceholder$1(host) {
|
|
874
895
|
const placeholder = document.createElement("span");
|
|
875
|
-
const slot = host.getAttribute(SLOT_ATTR);
|
|
876
|
-
if (slot !== null) placeholder.setAttribute(SLOT_ATTR, slot);
|
|
896
|
+
const slot = host.getAttribute(SLOT_ATTR$1);
|
|
897
|
+
if (slot !== null) placeholder.setAttribute(SLOT_ATTR$1, slot);
|
|
877
898
|
placeholder.style.display = "contents";
|
|
878
899
|
return placeholder;
|
|
879
900
|
}
|
|
880
|
-
function trackHole(parent, hole, extra, meta) {
|
|
901
|
+
function trackHole$1(parent, hole, extra, meta) {
|
|
881
902
|
parent.holes.push({
|
|
882
903
|
keepOnMorph: !!(meta?.atom && meta?.host) || !!meta?.keyed,
|
|
883
904
|
atom: meta?.atom,
|
|
@@ -889,13 +910,13 @@ function trackHole(parent, hole, extra, meta) {
|
|
|
889
910
|
}
|
|
890
911
|
});
|
|
891
912
|
}
|
|
892
|
-
function materialize(view, fiber) {
|
|
893
|
-
if (skip(view)) return [];
|
|
913
|
+
function materialize$1(view, fiber) {
|
|
914
|
+
if (skip$1(view)) return [];
|
|
894
915
|
if (typeof view === "string" || typeof view === "number" || typeof view === "bigint") return [document.createTextNode(String(view))];
|
|
895
916
|
if (isAtomHandle(view)) {
|
|
896
|
-
const reused = findReusableAtomHost(fiber, view.atom);
|
|
897
|
-
if (reused) return [atomHostPlaceholder(reused.host)];
|
|
898
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
917
|
+
const reused = findReusableAtomHost$1(fiber, view.atom);
|
|
918
|
+
if (reused) return [atomHostPlaceholder$1(reused.host)];
|
|
919
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
899
920
|
const host = nodes[0];
|
|
900
921
|
let unsub = () => {};
|
|
901
922
|
fiber.runtime.later(() => {
|
|
@@ -903,53 +924,77 @@ function materialize(view, fiber) {
|
|
|
903
924
|
let keep;
|
|
904
925
|
unsub = fiber.registry.subscribe(view.atom, (v) => {
|
|
905
926
|
if (hole.closed) return;
|
|
906
|
-
const next = unwrap(v, keep);
|
|
907
|
-
if (next === KEEP) return;
|
|
927
|
+
const next = unwrap$1(v, keep);
|
|
928
|
+
if (next === KEEP$1) return;
|
|
908
929
|
keep = next;
|
|
909
|
-
paintHole(hole, next);
|
|
930
|
+
paintHole$1(hole, next);
|
|
910
931
|
}, { immediate: true });
|
|
911
932
|
});
|
|
912
|
-
trackHole(fiber, hole, () => unsub(), {
|
|
933
|
+
trackHole$1(fiber, hole, () => unsub(), {
|
|
913
934
|
atom: view.atom,
|
|
914
935
|
host
|
|
915
936
|
});
|
|
916
937
|
return nodes;
|
|
917
938
|
}
|
|
918
939
|
if (Stream.isStream(view)) {
|
|
919
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
940
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
920
941
|
const src = fiber.runtime.ssr ? view.pipe(Stream.take(1)) : view;
|
|
921
942
|
hole.run(Stream.runForEach(src, (v) => Effect.sync(() => {
|
|
922
|
-
if (!hole.closed) paintHole(hole, v);
|
|
943
|
+
if (!hole.closed) paintHole$1(hole, v);
|
|
923
944
|
})).pipe(Effect.catch((e) => Effect.sync(() => {
|
|
924
|
-
if (!hole.closed) paintHole(hole, String(e));
|
|
945
|
+
if (!hole.closed) paintHole$1(hole, String(e));
|
|
925
946
|
}))), fiber.runtime.ssr ? () => {} : void 0);
|
|
926
|
-
trackHole(fiber, hole);
|
|
947
|
+
trackHole$1(fiber, hole);
|
|
927
948
|
return nodes;
|
|
928
949
|
}
|
|
929
950
|
if (isSetupFn(view)) {
|
|
930
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
951
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
931
952
|
fiber.runtime.later(() => {
|
|
932
953
|
if (!hole.closed) runSetup(hole, view);
|
|
933
954
|
});
|
|
934
|
-
trackHole(fiber, hole);
|
|
955
|
+
trackHole$1(fiber, hole);
|
|
935
956
|
return nodes;
|
|
936
957
|
}
|
|
937
958
|
if (isVNode(view)) {
|
|
938
|
-
if (view.type === Fragment) return view.children.flatMap((c) => materialize(c, fiber));
|
|
959
|
+
if (view.type === Fragment) return view.children.flatMap((c) => materialize$1(c, fiber));
|
|
939
960
|
if (typeof view.type === "function") {
|
|
940
961
|
const props = {
|
|
941
962
|
...view.props,
|
|
942
963
|
children: view.children
|
|
943
964
|
};
|
|
944
965
|
const type = view.type;
|
|
945
|
-
if (type[ISLAND] === true) {
|
|
946
|
-
const
|
|
966
|
+
if (type[ISLAND$1] === true) {
|
|
967
|
+
const frame = fiber.islandFrame ??= {
|
|
968
|
+
i: 0,
|
|
969
|
+
slots: []
|
|
970
|
+
};
|
|
971
|
+
const i = frame.i++;
|
|
972
|
+
const existing = frame.slots[i];
|
|
973
|
+
if (existing && existing.type === type && existing.host.isConnected && typeof existing.updateProps === "function") {
|
|
974
|
+
existing.updateProps(props);
|
|
975
|
+
return [existing.host];
|
|
976
|
+
}
|
|
977
|
+
existing?.unmount?.();
|
|
978
|
+
const tag = typeof type[ISLAND_SLOT_TAG$1] === "string" ? type[ISLAND_SLOT_TAG$1] : "div";
|
|
947
979
|
const el = document.createElement(tag);
|
|
948
980
|
el.setAttribute("data-ilha", "");
|
|
949
|
-
const mountFn = type[ISLAND_MOUNT_INTERNAL];
|
|
981
|
+
const mountFn = type[ISLAND_MOUNT_INTERNAL$1];
|
|
950
982
|
if (typeof mountFn === "function") {
|
|
951
983
|
const handle = mountFn(el, props);
|
|
952
|
-
|
|
984
|
+
const slot = {
|
|
985
|
+
type,
|
|
986
|
+
host: el,
|
|
987
|
+
updateProps: handle?.updateProps,
|
|
988
|
+
unmount: handle?.unmount
|
|
989
|
+
};
|
|
990
|
+
frame.slots[i] = slot;
|
|
991
|
+
fiber.holes.push({
|
|
992
|
+
keepOnMorph: true,
|
|
993
|
+
dispose: () => {
|
|
994
|
+
handle?.unmount?.();
|
|
995
|
+
if (frame.slots[i] === slot) frame.slots[i] = void 0;
|
|
996
|
+
}
|
|
997
|
+
});
|
|
953
998
|
}
|
|
954
999
|
return [el];
|
|
955
1000
|
}
|
|
@@ -961,7 +1006,7 @@ function materialize(view, fiber) {
|
|
|
961
1006
|
if (next && typeof next.then !== "function" && !isSetupFn(next)) reuse.paint(next);
|
|
962
1007
|
return [reuse.root];
|
|
963
1008
|
}
|
|
964
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
1009
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
965
1010
|
hole.propsBox = { current: props };
|
|
966
1011
|
if (k) {
|
|
967
1012
|
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
@@ -970,12 +1015,12 @@ function materialize(view, fiber) {
|
|
|
970
1015
|
fiber.runtime.later(() => {
|
|
971
1016
|
if (!hole.closed) runSetup(hole, () => type(hole.propsBox.current));
|
|
972
1017
|
});
|
|
973
|
-
trackHole(fiber, hole, void 0, k ? { keyed: true } : void 0);
|
|
1018
|
+
trackHole$1(fiber, hole, void 0, k ? { keyed: true } : void 0);
|
|
974
1019
|
return nodes;
|
|
975
1020
|
}
|
|
976
1021
|
const el = document.createElement(view.type);
|
|
977
|
-
if (view.key != null) el.setAttribute(KEY_ATTR, String(view.key));
|
|
978
|
-
applyProps(el, view.props, fiber);
|
|
1022
|
+
if (view.key != null) el.setAttribute(KEY_ATTR$1, String(view.key));
|
|
1023
|
+
applyProps$1(el, view.props, fiber);
|
|
979
1024
|
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
980
1025
|
const childFiber = {
|
|
981
1026
|
...fiber,
|
|
@@ -983,10 +1028,10 @@ function materialize(view, fiber) {
|
|
|
983
1028
|
holes: fiber.holes,
|
|
984
1029
|
keyedHoles: fiber.keyedHoles
|
|
985
1030
|
};
|
|
986
|
-
for (const c of view.children) for (const n of materialize(c, childFiber)) el.appendChild(n);
|
|
1031
|
+
for (const c of view.children) for (const n of materialize$1(c, childFiber)) el.appendChild(n);
|
|
987
1032
|
return [el];
|
|
988
1033
|
}
|
|
989
|
-
if (Array.isArray(view) || view && typeof view === "object" && Symbol.iterator in Object(view)) return [...view].flatMap((c) => materialize(c, fiber));
|
|
1034
|
+
if (Array.isArray(view) || view && typeof view === "object" && Symbol.iterator in Object(view)) return [...view].flatMap((c) => materialize$1(c, fiber));
|
|
990
1035
|
return [document.createTextNode(String(view))];
|
|
991
1036
|
}
|
|
992
1037
|
function canHydrate(fiber, view) {
|
|
@@ -994,20 +1039,24 @@ function canHydrate(fiber, view) {
|
|
|
994
1039
|
const el = fiber.root.firstElementChild;
|
|
995
1040
|
return !!el && el.tagName === view.type.toUpperCase();
|
|
996
1041
|
}
|
|
997
|
-
function paint(fiber, view) {
|
|
1042
|
+
function paint$1(fiber, view) {
|
|
1043
|
+
fiber.islandFrame ??= {
|
|
1044
|
+
i: 0,
|
|
1045
|
+
slots: []
|
|
1046
|
+
};
|
|
998
1047
|
if (fiber.hydrate) {
|
|
999
1048
|
if (canHydrate(fiber, view)) {
|
|
1000
1049
|
const el = fiber.root.firstElementChild;
|
|
1001
1050
|
fiber.hydrate = false;
|
|
1002
1051
|
fiber.liveEl = el;
|
|
1003
|
-
applyProps(el, view.props, fiber);
|
|
1052
|
+
applyProps$1(el, view.props, fiber);
|
|
1004
1053
|
const childFiber = {
|
|
1005
1054
|
...fiber,
|
|
1006
1055
|
root: el,
|
|
1007
1056
|
holes: fiber.holes
|
|
1008
1057
|
};
|
|
1009
1058
|
el.replaceChildren();
|
|
1010
|
-
for (const c of view.children) for (const n of materialize(c, childFiber)) el.appendChild(n);
|
|
1059
|
+
for (const c of view.children) for (const n of materialize$1(c, childFiber)) el.appendChild(n);
|
|
1011
1060
|
return;
|
|
1012
1061
|
} else {
|
|
1013
1062
|
console.warn("[ilha] hydrate mismatch, full mount");
|
|
@@ -1016,31 +1065,31 @@ function paint(fiber, view) {
|
|
|
1016
1065
|
}
|
|
1017
1066
|
}
|
|
1018
1067
|
if (fiber.liveEl && isVNode(view) && typeof view.type === "string" && fiber.liveEl.localName === view.type) {
|
|
1019
|
-
disposeHoles(fiber, { morph: true });
|
|
1020
|
-
applyProps(fiber.liveEl, view.props, fiber);
|
|
1068
|
+
disposeHoles$1(fiber, { morph: true });
|
|
1069
|
+
applyProps$1(fiber.liveEl, view.props, fiber);
|
|
1021
1070
|
const tmp = document.createElement(fiber.liveEl.localName);
|
|
1022
|
-
for (const c of view.children) for (const n of materialize(c, fiber)) tmp.appendChild(n);
|
|
1071
|
+
for (const c of view.children) for (const n of materialize$1(c, fiber)) tmp.appendChild(n);
|
|
1023
1072
|
morphInner(fiber.liveEl, tmp);
|
|
1024
1073
|
refreshAllAtomHosts(fiber);
|
|
1025
1074
|
pruneDisconnectedAtomHoles(fiber);
|
|
1026
1075
|
return;
|
|
1027
1076
|
}
|
|
1028
|
-
disposeHoles(fiber);
|
|
1077
|
+
disposeHoles$1(fiber);
|
|
1029
1078
|
if (fiber.root instanceof Element && fiber.root.childNodes.length > 0) {
|
|
1030
1079
|
const tmp = document.createElement("div");
|
|
1031
|
-
for (const n of materialize(view, fiber)) tmp.appendChild(n);
|
|
1080
|
+
for (const n of materialize$1(view, fiber)) tmp.appendChild(n);
|
|
1032
1081
|
morphInner(fiber.root, tmp);
|
|
1033
1082
|
const first = fiber.root.firstElementChild;
|
|
1034
1083
|
if (first) fiber.liveEl = first;
|
|
1035
1084
|
return;
|
|
1036
1085
|
}
|
|
1037
|
-
insert(fiber, materialize(view, fiber));
|
|
1086
|
+
insert$1(fiber, materialize$1(view, fiber));
|
|
1038
1087
|
const first = fiber.root instanceof Element ? fiber.root.firstElementChild : null;
|
|
1039
1088
|
if (first) fiber.liveEl = first;
|
|
1040
1089
|
}
|
|
1041
|
-
function paintError(fiber, e) {
|
|
1090
|
+
function paintError$1(fiber, e) {
|
|
1042
1091
|
console.error(e);
|
|
1043
|
-
paint(fiber, errorView(e));
|
|
1092
|
+
paint$1(fiber, errorView$1(e));
|
|
1044
1093
|
}
|
|
1045
1094
|
|
|
1046
1095
|
//#endregion
|
|
@@ -1093,10 +1142,466 @@ function decodeSnapshot(raw) {
|
|
|
1093
1142
|
}
|
|
1094
1143
|
|
|
1095
1144
|
//#endregion
|
|
1096
|
-
//#region src/
|
|
1145
|
+
//#region src/ssr-dom.ts
|
|
1146
|
+
const VOID = /* @__PURE__ */ new Set([
|
|
1147
|
+
"area",
|
|
1148
|
+
"base",
|
|
1149
|
+
"br",
|
|
1150
|
+
"col",
|
|
1151
|
+
"embed",
|
|
1152
|
+
"hr",
|
|
1153
|
+
"img",
|
|
1154
|
+
"input",
|
|
1155
|
+
"link",
|
|
1156
|
+
"meta",
|
|
1157
|
+
"param",
|
|
1158
|
+
"source",
|
|
1159
|
+
"track",
|
|
1160
|
+
"wbr"
|
|
1161
|
+
]);
|
|
1162
|
+
/** Tags whose children are raw text — do not HTML-escape content. */
|
|
1163
|
+
const RAW_TEXT = /* @__PURE__ */ new Set(["script", "style"]);
|
|
1164
|
+
function escapeText(s) {
|
|
1165
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1166
|
+
}
|
|
1097
1167
|
function escapeAttr(s) {
|
|
1098
|
-
return s
|
|
1168
|
+
return escapeText(s).replace(/"/g, """);
|
|
1169
|
+
}
|
|
1170
|
+
function createSsrText(text) {
|
|
1171
|
+
return {
|
|
1172
|
+
kind: "text",
|
|
1173
|
+
text
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
function createSsrElement(tag) {
|
|
1177
|
+
const lower = tag.toLowerCase();
|
|
1178
|
+
const children = [];
|
|
1179
|
+
const el = {
|
|
1180
|
+
kind: "element",
|
|
1181
|
+
tag: lower,
|
|
1182
|
+
attrs: /* @__PURE__ */ new Map(),
|
|
1183
|
+
children,
|
|
1184
|
+
isConnected: true,
|
|
1185
|
+
tagName: lower.toUpperCase(),
|
|
1186
|
+
localName: lower,
|
|
1187
|
+
setAttribute(name, value) {
|
|
1188
|
+
el.attrs.set(name, value);
|
|
1189
|
+
},
|
|
1190
|
+
getAttribute(name) {
|
|
1191
|
+
return el.attrs.has(name) ? el.attrs.get(name) : null;
|
|
1192
|
+
},
|
|
1193
|
+
removeAttribute(name) {
|
|
1194
|
+
el.attrs.delete(name);
|
|
1195
|
+
},
|
|
1196
|
+
hasAttribute(name) {
|
|
1197
|
+
return el.attrs.has(name);
|
|
1198
|
+
},
|
|
1199
|
+
replaceChildren(...nodes) {
|
|
1200
|
+
children.length = 0;
|
|
1201
|
+
children.push(...nodes);
|
|
1202
|
+
},
|
|
1203
|
+
appendChild(node) {
|
|
1204
|
+
children.push(node);
|
|
1205
|
+
},
|
|
1206
|
+
get textContent() {
|
|
1207
|
+
return children.map((n) => n.kind === "text" ? n.text : n.textContent).join("");
|
|
1208
|
+
},
|
|
1209
|
+
set textContent(value) {
|
|
1210
|
+
children.length = 0;
|
|
1211
|
+
children.push(createSsrText(value));
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
return el;
|
|
1215
|
+
}
|
|
1216
|
+
function createSsrRoot() {
|
|
1217
|
+
const children = [];
|
|
1218
|
+
return {
|
|
1219
|
+
kind: "root",
|
|
1220
|
+
children,
|
|
1221
|
+
appendChild(node) {
|
|
1222
|
+
children.push(node);
|
|
1223
|
+
},
|
|
1224
|
+
replaceChildren() {
|
|
1225
|
+
children.length = 0;
|
|
1226
|
+
},
|
|
1227
|
+
get innerHTML() {
|
|
1228
|
+
return children.map(serializeNode).join("");
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function serializeRawText(tag, text) {
|
|
1233
|
+
if (new RegExp(`</${tag}\\b`, "i").test(text)) throw new Error(`ilha: unsafe raw text in <${tag}> (contains "</${tag}")`);
|
|
1234
|
+
return text;
|
|
1235
|
+
}
|
|
1236
|
+
function serializeNode(node) {
|
|
1237
|
+
if (node.kind === "text") return escapeText(node.text);
|
|
1238
|
+
const parts = [];
|
|
1239
|
+
for (const [name, value] of node.attrs) parts.push(`${name}="${escapeAttr(value)}"`);
|
|
1240
|
+
const attr = parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
1241
|
+
const tag = node.tag;
|
|
1242
|
+
if (VOID.has(tag)) return `<${tag}${attr}>`;
|
|
1243
|
+
if (RAW_TEXT.has(tag)) return `<${tag}${attr}>${serializeRawText(tag, node.textContent)}</${tag}>`;
|
|
1244
|
+
return `<${tag}${attr}>${node.children.map(serializeNode).join("")}</${tag}>`;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
//#endregion
|
|
1248
|
+
//#region src/ssr-paint.ts
|
|
1249
|
+
const KEY_ATTR = "data-ilha-key";
|
|
1250
|
+
const SLOT_ATTR = "data-ilha-slot";
|
|
1251
|
+
const ISLAND = Symbol.for("ilha.island");
|
|
1252
|
+
const ISLAND_MOUNT_INTERNAL = Symbol.for("ilha.islandMountInternal");
|
|
1253
|
+
const ISLAND_SLOT_TAG = Symbol.for("ilha.islandSlotTag");
|
|
1254
|
+
function insert(fiber, nodes) {
|
|
1255
|
+
const root = fiber.root;
|
|
1256
|
+
for (const n of nodes) root.appendChild(n);
|
|
1257
|
+
}
|
|
1258
|
+
function disposeHoles(fiber) {
|
|
1259
|
+
for (const h of fiber.holes) h.dispose();
|
|
1260
|
+
fiber.holes = [];
|
|
1261
|
+
}
|
|
1262
|
+
function skip(x) {
|
|
1263
|
+
return x === null || x === void 0 || typeof x === "boolean";
|
|
1264
|
+
}
|
|
1265
|
+
function bindSsrEvents(el, props, fiber) {
|
|
1266
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1267
|
+
for (const key of Object.keys(props)) {
|
|
1268
|
+
const type = eventTypeFromProp(key);
|
|
1269
|
+
if (!type || seen.has(type)) continue;
|
|
1270
|
+
seen.add(type);
|
|
1271
|
+
const fn = props[key];
|
|
1272
|
+
if (typeof fn !== "function") continue;
|
|
1273
|
+
const branded = fn[Symbol.for("ilha.actionCall")];
|
|
1274
|
+
const rec = branded?.k ? {
|
|
1275
|
+
k: branded.k,
|
|
1276
|
+
a: branded.a ?? []
|
|
1277
|
+
} : void 0;
|
|
1278
|
+
if (!rec) continue;
|
|
1279
|
+
const id = `${type}:${fiber.runtime.ssrEventI++}`;
|
|
1280
|
+
fiber.runtime.ssrActions[id] = rec;
|
|
1281
|
+
const existing = el.getAttribute("data-ilha-on");
|
|
1282
|
+
el.setAttribute("data-ilha-on", existing ? `${existing},${id}` : id);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
function applyProps(el, props, fiber) {
|
|
1286
|
+
for (const [k, v] of Object.entries(props)) {
|
|
1287
|
+
if (k === "children" || k === "key" || k === "ref") continue;
|
|
1288
|
+
if (k === "className") {
|
|
1289
|
+
el.setAttribute("class", String(v ?? ""));
|
|
1290
|
+
continue;
|
|
1291
|
+
}
|
|
1292
|
+
if (k === "htmlFor") {
|
|
1293
|
+
el.setAttribute("for", String(v ?? ""));
|
|
1294
|
+
continue;
|
|
1295
|
+
}
|
|
1296
|
+
if (k.toLowerCase() === "srcdoc") continue;
|
|
1297
|
+
if (k === "style" && v != null && v !== false) {
|
|
1298
|
+
const css = typeof v === "string" || typeof v === "object" ? serializeStyleAttr(v) : "";
|
|
1299
|
+
if (css) el.setAttribute("style", css);
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
if (isEventProp(k)) continue;
|
|
1303
|
+
if (/^on[A-Z]/.test(k)) continue;
|
|
1304
|
+
if (k === "value" || k === "checked" || k === "selected") {
|
|
1305
|
+
const setProp = (x) => {
|
|
1306
|
+
if (k === "value") el.setAttribute("value", String(x ?? ""));
|
|
1307
|
+
else if (k === "checked") {
|
|
1308
|
+
if (x) el.setAttribute("checked", "");
|
|
1309
|
+
else el.removeAttribute("checked");
|
|
1310
|
+
} else if (x) el.setAttribute("selected", "");
|
|
1311
|
+
else el.removeAttribute("selected");
|
|
1312
|
+
};
|
|
1313
|
+
if (isAtomHandle(v)) {
|
|
1314
|
+
const unsub = fiber.registry.subscribe(v.atom, setProp, { immediate: true });
|
|
1315
|
+
fiber.holes.push({ dispose: unsub });
|
|
1316
|
+
} else setProp(v);
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1319
|
+
if (typeof v === "function") continue;
|
|
1320
|
+
if (v === false || v === null || v === void 0) el.removeAttribute(k);
|
|
1321
|
+
else {
|
|
1322
|
+
const str = v === true ? "" : String(v);
|
|
1323
|
+
if (isUrlAttributeName(k) && !isSafeUrlAttrValue(el.tagName, k, str)) continue;
|
|
1324
|
+
el.setAttribute(k, str);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
bindSsrEvents(el, props, fiber);
|
|
1328
|
+
const ref = props.ref;
|
|
1329
|
+
if (typeof ref === "function") {
|
|
1330
|
+
ref(el);
|
|
1331
|
+
fiber.holes.push({ dispose: () => ref(null) });
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
const KEEP = Symbol("keep");
|
|
1335
|
+
function unwrap(value, keep) {
|
|
1336
|
+
if (AsyncResult.isAsyncResult(value)) {
|
|
1337
|
+
if (AsyncResult.isWaiting(value) && keep !== void 0) return KEEP;
|
|
1338
|
+
if (AsyncResult.isFailure(value) && !AsyncResult.isWaiting(value)) return String(AsyncResult.error(value) ?? "error");
|
|
1339
|
+
const v = AsyncResult.value(value);
|
|
1340
|
+
if (v._tag === "Some") return v.value;
|
|
1341
|
+
return "";
|
|
1342
|
+
}
|
|
1343
|
+
return value;
|
|
1344
|
+
}
|
|
1345
|
+
function paintHole(fiber, view) {
|
|
1346
|
+
if (view === KEEP) return;
|
|
1347
|
+
const frame = fiber.islandFrame ??= {
|
|
1348
|
+
i: 0,
|
|
1349
|
+
slots: []
|
|
1350
|
+
};
|
|
1351
|
+
frame.i = 0;
|
|
1352
|
+
const list = Array.isArray(view) ? view : null;
|
|
1353
|
+
if (list && list.length > 0 && list.every((v) => isVNode(v) && v.key != null)) {
|
|
1354
|
+
keyedPaintHole(fiber, list);
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
disposeHoles(fiber);
|
|
1358
|
+
fiber.root.replaceChildren();
|
|
1359
|
+
insert(fiber, materialize(view, fiber));
|
|
1360
|
+
}
|
|
1361
|
+
function keyedPaintHole(fiber, views) {
|
|
1362
|
+
const prev = fiber.keyedHoles ?? /* @__PURE__ */ new Map();
|
|
1363
|
+
const keep = new Set(views.map((v) => String(v.key)));
|
|
1364
|
+
for (const [k, h] of prev) if (!keep.has(k)) closeFiber(h);
|
|
1365
|
+
const next = /* @__PURE__ */ new Map();
|
|
1366
|
+
const nodes = [];
|
|
1367
|
+
for (const v of views) {
|
|
1368
|
+
const k = String(v.key);
|
|
1369
|
+
const reuse = prev.get(k);
|
|
1370
|
+
if (reuse && !reuse.closed) {
|
|
1371
|
+
next.set(k, reuse);
|
|
1372
|
+
nodes.push(reuse.root);
|
|
1373
|
+
continue;
|
|
1374
|
+
}
|
|
1375
|
+
const made = materialize(v, fiber);
|
|
1376
|
+
const hole = fiber.keyedHoles?.get(k);
|
|
1377
|
+
if (hole) next.set(k, hole);
|
|
1378
|
+
nodes.push(...made);
|
|
1379
|
+
}
|
|
1380
|
+
fiber.keyedHoles = next;
|
|
1381
|
+
fiber.root.replaceChildren();
|
|
1382
|
+
insert(fiber, nodes);
|
|
1383
|
+
}
|
|
1384
|
+
function openHole(parent) {
|
|
1385
|
+
const id = parent.runtime.nextHole();
|
|
1386
|
+
const host = createSsrElement("span");
|
|
1387
|
+
host.setAttribute(SLOT_ATTR, String(id));
|
|
1388
|
+
host.setAttribute("style", "display:contents");
|
|
1389
|
+
const child = makeFiber(parent.runtime, host, paint, { onFail: (e) => {
|
|
1390
|
+
console.error(e);
|
|
1391
|
+
paintHole(child, errorView(e));
|
|
1392
|
+
} });
|
|
1393
|
+
return {
|
|
1394
|
+
fiber: child,
|
|
1395
|
+
nodes: [host]
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
function errorView(e) {
|
|
1399
|
+
return {
|
|
1400
|
+
$$ilha: 1,
|
|
1401
|
+
type: "pre",
|
|
1402
|
+
props: { "data-ilha-error": "" },
|
|
1403
|
+
children: [failureMessage(e)]
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
function findReusableAtomHost(fiber, atom) {
|
|
1407
|
+
for (const h of fiber.holes) {
|
|
1408
|
+
const host = h.host;
|
|
1409
|
+
if (h.atom === atom && host?.isConnected && h.holeFiber && !h.holeFiber.closed) return {
|
|
1410
|
+
host,
|
|
1411
|
+
hole: h.holeFiber
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
function atomHostPlaceholder(host) {
|
|
1416
|
+
const placeholder = createSsrElement("span");
|
|
1417
|
+
const slot = host.getAttribute(SLOT_ATTR);
|
|
1418
|
+
if (slot !== null) placeholder.setAttribute(SLOT_ATTR, slot);
|
|
1419
|
+
placeholder.setAttribute("style", "display:contents");
|
|
1420
|
+
return placeholder;
|
|
1421
|
+
}
|
|
1422
|
+
function trackHole(parent, hole, extra, meta) {
|
|
1423
|
+
parent.holes.push({
|
|
1424
|
+
keepOnMorph: !!(meta?.atom && meta?.host) || !!meta?.keyed,
|
|
1425
|
+
atom: meta?.atom,
|
|
1426
|
+
host: meta?.host,
|
|
1427
|
+
holeFiber: hole,
|
|
1428
|
+
dispose() {
|
|
1429
|
+
extra?.();
|
|
1430
|
+
if (meta?.host) meta.host.isConnected = false;
|
|
1431
|
+
closeFiber(hole);
|
|
1432
|
+
}
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
function materialize(view, fiber) {
|
|
1436
|
+
if (skip(view)) return [];
|
|
1437
|
+
if (typeof view === "string" || typeof view === "number" || typeof view === "bigint") return [createSsrText(String(view))];
|
|
1438
|
+
if (isAtomHandle(view)) {
|
|
1439
|
+
const reused = findReusableAtomHost(fiber, view.atom);
|
|
1440
|
+
if (reused) return [atomHostPlaceholder(reused.host)];
|
|
1441
|
+
const { fiber: hole, nodes } = openHole(fiber);
|
|
1442
|
+
const host = nodes[0];
|
|
1443
|
+
let unsub = () => {};
|
|
1444
|
+
fiber.runtime.later(() => {
|
|
1445
|
+
if (hole.closed) return;
|
|
1446
|
+
let keep;
|
|
1447
|
+
unsub = fiber.registry.subscribe(view.atom, (v) => {
|
|
1448
|
+
if (hole.closed) return;
|
|
1449
|
+
const next = unwrap(v, keep);
|
|
1450
|
+
if (next === KEEP) return;
|
|
1451
|
+
keep = next;
|
|
1452
|
+
paintHole(hole, next);
|
|
1453
|
+
}, { immediate: true });
|
|
1454
|
+
});
|
|
1455
|
+
trackHole(fiber, hole, () => unsub(), {
|
|
1456
|
+
atom: view.atom,
|
|
1457
|
+
host
|
|
1458
|
+
});
|
|
1459
|
+
return nodes;
|
|
1460
|
+
}
|
|
1461
|
+
if (Stream.isStream(view)) {
|
|
1462
|
+
const { fiber: hole, nodes } = openHole(fiber);
|
|
1463
|
+
hole.run(Stream.runForEach(view.pipe(Stream.take(1)), (v) => Effect.sync(() => {
|
|
1464
|
+
if (!hole.closed) paintHole(hole, v);
|
|
1465
|
+
})).pipe(Effect.catch((e) => Effect.sync(() => {
|
|
1466
|
+
if (!hole.closed) paintHole(hole, String(e));
|
|
1467
|
+
}))), () => {});
|
|
1468
|
+
trackHole(fiber, hole);
|
|
1469
|
+
return nodes;
|
|
1470
|
+
}
|
|
1471
|
+
if (isSetupFn(view)) {
|
|
1472
|
+
const { fiber: hole, nodes } = openHole(fiber);
|
|
1473
|
+
fiber.runtime.later(() => {
|
|
1474
|
+
if (!hole.closed) runSetup(hole, view);
|
|
1475
|
+
});
|
|
1476
|
+
trackHole(fiber, hole);
|
|
1477
|
+
return nodes;
|
|
1478
|
+
}
|
|
1479
|
+
if (isVNode(view)) {
|
|
1480
|
+
if (view.type === Fragment) return view.children.flatMap((c) => materialize(c, fiber));
|
|
1481
|
+
if (typeof view.type === "function") {
|
|
1482
|
+
const props = {
|
|
1483
|
+
...view.props,
|
|
1484
|
+
children: view.children
|
|
1485
|
+
};
|
|
1486
|
+
const type = view.type;
|
|
1487
|
+
if (type[ISLAND] === true) {
|
|
1488
|
+
const frame = fiber.islandFrame ??= {
|
|
1489
|
+
i: 0,
|
|
1490
|
+
slots: []
|
|
1491
|
+
};
|
|
1492
|
+
const i = frame.i++;
|
|
1493
|
+
const existing = frame.slots[i];
|
|
1494
|
+
if (existing && existing.type === type && existing.host.isConnected && typeof existing.updateProps === "function") {
|
|
1495
|
+
existing.updateProps(props);
|
|
1496
|
+
return [existing.host];
|
|
1497
|
+
}
|
|
1498
|
+
existing?.unmount?.();
|
|
1499
|
+
const tag = typeof type[ISLAND_SLOT_TAG] === "string" ? type[ISLAND_SLOT_TAG] : "div";
|
|
1500
|
+
const el = createSsrElement(tag);
|
|
1501
|
+
el.setAttribute("data-ilha", "");
|
|
1502
|
+
const mountFn = type[ISLAND_MOUNT_INTERNAL];
|
|
1503
|
+
if (typeof mountFn === "function") {
|
|
1504
|
+
const handle = mountFn(el, props);
|
|
1505
|
+
const slot = {
|
|
1506
|
+
type,
|
|
1507
|
+
host: el,
|
|
1508
|
+
updateProps: handle?.updateProps,
|
|
1509
|
+
unmount: handle?.unmount
|
|
1510
|
+
};
|
|
1511
|
+
frame.slots[i] = slot;
|
|
1512
|
+
fiber.holes.push({
|
|
1513
|
+
keepOnMorph: true,
|
|
1514
|
+
dispose: () => {
|
|
1515
|
+
el.isConnected = false;
|
|
1516
|
+
handle?.unmount?.();
|
|
1517
|
+
if (frame.slots[i] === slot) frame.slots[i] = void 0;
|
|
1518
|
+
}
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
return [el];
|
|
1522
|
+
}
|
|
1523
|
+
const k = view.key == null ? void 0 : String(view.key);
|
|
1524
|
+
const reuse = k ? fiber.keyedHoles?.get(k) : void 0;
|
|
1525
|
+
if (reuse && !reuse.closed) {
|
|
1526
|
+
if (reuse.propsBox) reuse.propsBox.current = props;
|
|
1527
|
+
const next = withFiber(fiber, () => type(reuse.propsBox?.current ?? props));
|
|
1528
|
+
if (next && typeof next.then !== "function" && !isSetupFn(next)) reuse.paint(next);
|
|
1529
|
+
return [reuse.root];
|
|
1530
|
+
}
|
|
1531
|
+
const { fiber: hole, nodes } = openHole(fiber);
|
|
1532
|
+
hole.propsBox = { current: props };
|
|
1533
|
+
if (k) {
|
|
1534
|
+
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
1535
|
+
fiber.keyedHoles.set(k, hole);
|
|
1536
|
+
}
|
|
1537
|
+
fiber.runtime.later(() => {
|
|
1538
|
+
if (!hole.closed) runSetup(hole, () => type(hole.propsBox.current));
|
|
1539
|
+
});
|
|
1540
|
+
trackHole(fiber, hole, void 0, k ? { keyed: true } : void 0);
|
|
1541
|
+
return nodes;
|
|
1542
|
+
}
|
|
1543
|
+
const el = createSsrElement(view.type);
|
|
1544
|
+
if (view.key != null) el.setAttribute(KEY_ATTR, String(view.key));
|
|
1545
|
+
applyProps(el, view.props, fiber);
|
|
1546
|
+
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
1547
|
+
const childFiber = {
|
|
1548
|
+
...fiber,
|
|
1549
|
+
root: el,
|
|
1550
|
+
holes: fiber.holes,
|
|
1551
|
+
keyedHoles: fiber.keyedHoles
|
|
1552
|
+
};
|
|
1553
|
+
for (const c of view.children) for (const n of materialize(c, childFiber)) el.appendChild(n);
|
|
1554
|
+
return [el];
|
|
1555
|
+
}
|
|
1556
|
+
if (Array.isArray(view) || view && typeof view === "object" && Symbol.iterator in Object(view)) return [...view].flatMap((c) => materialize(c, fiber));
|
|
1557
|
+
return [createSsrText(String(view))];
|
|
1558
|
+
}
|
|
1559
|
+
function paint(fiber, view) {
|
|
1560
|
+
fiber.islandFrame ??= {
|
|
1561
|
+
i: 0,
|
|
1562
|
+
slots: []
|
|
1563
|
+
};
|
|
1564
|
+
disposeHoles(fiber);
|
|
1565
|
+
fiber.root.replaceChildren();
|
|
1566
|
+
insert(fiber, materialize(view, fiber));
|
|
1567
|
+
}
|
|
1568
|
+
function paintError(fiber, e) {
|
|
1569
|
+
console.error(e);
|
|
1570
|
+
paint(fiber, errorView(e));
|
|
1571
|
+
}
|
|
1572
|
+
function attachSsr(fn, opts) {
|
|
1573
|
+
const root = createSsrRoot();
|
|
1574
|
+
const runtime = makeRuntime({
|
|
1575
|
+
ssr: true,
|
|
1576
|
+
ssrCapture: opts?.ssrCapture === true
|
|
1577
|
+
});
|
|
1578
|
+
let resolve;
|
|
1579
|
+
const ready = new Promise((r) => {
|
|
1580
|
+
resolve = r;
|
|
1581
|
+
});
|
|
1582
|
+
const fiber = makeFiber(runtime, root, paint, { onFail: (e) => {
|
|
1583
|
+
opts?.onError?.(e);
|
|
1584
|
+
paintError(fiber, e);
|
|
1585
|
+
resolve();
|
|
1586
|
+
} });
|
|
1587
|
+
runtime.begin();
|
|
1588
|
+
runtime.setIdle(resolve);
|
|
1589
|
+
runSetup(fiber, fn);
|
|
1590
|
+
runtime.end();
|
|
1591
|
+
return {
|
|
1592
|
+
root,
|
|
1593
|
+
ready,
|
|
1594
|
+
runtime,
|
|
1595
|
+
unmount() {
|
|
1596
|
+
closeFiber(fiber);
|
|
1597
|
+
runtime.close();
|
|
1598
|
+
root.replaceChildren();
|
|
1599
|
+
}
|
|
1600
|
+
};
|
|
1099
1601
|
}
|
|
1602
|
+
|
|
1603
|
+
//#endregion
|
|
1604
|
+
//#region src/mount.ts
|
|
1100
1605
|
function readHydrate(el) {
|
|
1101
1606
|
const raw = (el.hasAttribute("data-ilha") ? el : el.querySelector("[data-ilha]"))?.getAttribute("data-ilha-state");
|
|
1102
1607
|
if (raw) return decodeSnapshot(raw);
|
|
@@ -1109,18 +1614,14 @@ function readHydrate(el) {
|
|
|
1109
1614
|
}
|
|
1110
1615
|
function attach(el, fn, opts) {
|
|
1111
1616
|
if (!opts?.hydrate) el.innerHTML = "";
|
|
1112
|
-
const runtime = makeRuntime({
|
|
1113
|
-
ssr: opts?.ssr,
|
|
1114
|
-
ssrCapture: opts?.ssrCapture,
|
|
1115
|
-
hydrate: opts?.hydrate ? readHydrate(el) : void 0
|
|
1116
|
-
});
|
|
1617
|
+
const runtime = makeRuntime({ hydrate: opts?.hydrate ? readHydrate(el) : void 0 });
|
|
1117
1618
|
let resolve;
|
|
1118
1619
|
const ready = new Promise((r) => {
|
|
1119
1620
|
resolve = r;
|
|
1120
1621
|
});
|
|
1121
|
-
const fiber = makeFiber(runtime, el, paint, { onFail: (e) => {
|
|
1622
|
+
const fiber = makeFiber(runtime, el, paint$1, { onFail: (e) => {
|
|
1122
1623
|
opts?.onError?.(e);
|
|
1123
|
-
paintError(fiber, e);
|
|
1624
|
+
paintError$1(fiber, e);
|
|
1124
1625
|
resolve();
|
|
1125
1626
|
} });
|
|
1126
1627
|
if (opts?.hydrate) fiber.hydrate = true;
|
|
@@ -1141,26 +1642,13 @@ function attach(el, fn, opts) {
|
|
|
1141
1642
|
function mount(el, fn, opts) {
|
|
1142
1643
|
return attach(el, fn, opts).unmount;
|
|
1143
1644
|
}
|
|
1144
|
-
let domReady;
|
|
1145
|
-
function ensureDocument() {
|
|
1146
|
-
if (typeof globalThis.document !== "undefined") return Promise.resolve();
|
|
1147
|
-
domReady ??= import("@happy-dom/global-registrator").then(({ GlobalRegistrator }) => {
|
|
1148
|
-
if (typeof globalThis.document === "undefined") GlobalRegistrator.register();
|
|
1149
|
-
});
|
|
1150
|
-
return domReady;
|
|
1151
|
-
}
|
|
1152
1645
|
async function renderToString(fn, opts) {
|
|
1153
|
-
await ensureDocument();
|
|
1154
1646
|
const snapshot = opts?.snapshot !== false;
|
|
1155
1647
|
const markers = opts?.markers !== false;
|
|
1156
|
-
const
|
|
1157
|
-
const { unmount, ready, runtime } = attach(el, fn, {
|
|
1158
|
-
ssr: true,
|
|
1159
|
-
ssrCapture: opts?.captureActions === true
|
|
1160
|
-
});
|
|
1648
|
+
const { unmount, ready, runtime, root } = attachSsr(fn, { ssrCapture: opts?.captureActions === true });
|
|
1161
1649
|
if (opts?.timeout == null) await ready;
|
|
1162
1650
|
else await Promise.race([ready, new Promise((r) => setTimeout(r, opts.timeout))]);
|
|
1163
|
-
let inner =
|
|
1651
|
+
let inner = root.innerHTML;
|
|
1164
1652
|
const actions = runtime.ssrActions;
|
|
1165
1653
|
if (Object.keys(actions).length > 0) inner = `<template data-ilha-actions="${escapeAttr(JSON.stringify(actions))}"></template>${inner}`;
|
|
1166
1654
|
const snap = snapshot ? encodeSnapshot(runtime.ssrValues) : void 0;
|
|
@@ -1170,4 +1658,4 @@ async function renderToString(fn, opts) {
|
|
|
1170
1658
|
}
|
|
1171
1659
|
|
|
1172
1660
|
//#endregion
|
|
1173
|
-
export { atom as a, instr as c, getFiber as d, makeFiber as f, interpret as i, isAtomHandle as l, renderToString as n, batch as o, paint as r, handleOwner as s, mount as t, closeFiber as u };
|
|
1661
|
+
export { atom as a, instr as c, getFiber as d, makeFiber as f, interpret as i, isAtomHandle as l, renderToString as n, batch as o, paint$1 as r, handleOwner as s, mount as t, closeFiber as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilha",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2",
|
|
4
4
|
"description": "Generator-first island UI on Effect",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect",
|
|
@@ -62,10 +62,8 @@
|
|
|
62
62
|
"cleanup": "rimraf dist node_modules",
|
|
63
63
|
"test": "bun test"
|
|
64
64
|
},
|
|
65
|
-
"dependencies": {
|
|
66
|
-
"@happy-dom/global-registrator": "^20.11.2"
|
|
67
|
-
},
|
|
68
65
|
"devDependencies": {
|
|
66
|
+
"@happy-dom/global-registrator": "^20.11.2",
|
|
69
67
|
"effect": "^4.0.0-rc.112"
|
|
70
68
|
},
|
|
71
69
|
"peerDependencies": {
|