ilha 0.14.0 → 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 +25 -20
- package/dist/define.d.ts +1 -1
- package/dist/define.js +1 -1
- package/dist/index.d.ts +13 -11
- package/dist/index.js +62 -40
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/{mount-Dcy4teaf.js → mount-CCMOkDSb.js} +803 -134
- package/dist/{types-DU46exHq.d.ts → types-Cie0Ihl6.d.ts} +1 -2
- package/dist/{vnode-BZLcG8lC.d.ts → vnode-DyFwtMVw.d.ts} +1 -1
- package/package.json +2 -4
|
@@ -40,6 +40,12 @@ const runInScope = (effect, registry, scope, onOk, onErr, onDone) => {
|
|
|
40
40
|
function closeFiber(fiber) {
|
|
41
41
|
if (fiber.closed) return;
|
|
42
42
|
fiber.closed = true;
|
|
43
|
+
fiber.trackRestore?.();
|
|
44
|
+
fiber.trackRestore = void 0;
|
|
45
|
+
fiber.renderSub?.();
|
|
46
|
+
fiber.renderSub = void 0;
|
|
47
|
+
for (const slot of fiber.watchSlots ?? []) slot?.dispose();
|
|
48
|
+
fiber.watchSlots = [];
|
|
43
49
|
for (const h of fiber.holes) h.dispose();
|
|
44
50
|
fiber.holes = [];
|
|
45
51
|
Effect.runFork(Scope.close(fiber.scope, Exit.void));
|
|
@@ -150,11 +156,124 @@ function isAtomHandle(x) {
|
|
|
150
156
|
return typeof x === "function" && x.$$atom === 1;
|
|
151
157
|
}
|
|
152
158
|
let trackGet;
|
|
159
|
+
const trackStack = [];
|
|
160
|
+
function beginPrimitiveFrame(fiber) {
|
|
161
|
+
const used = fiber.primitiveI ?? 0;
|
|
162
|
+
const slots = fiber.primitives?.length ?? 0;
|
|
163
|
+
if (used > 0 && used !== slots) console.warn(`ilha: atom/watch slot count changed between renders (${slots} → ${used}); keep primitive order stable`);
|
|
164
|
+
fiber.primitiveI = 0;
|
|
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;
|
|
182
|
+
}
|
|
183
|
+
function readTracked(atom, registry) {
|
|
184
|
+
const frame = trackStack.at(-1);
|
|
185
|
+
const active = getActiveFiber();
|
|
186
|
+
if (trackGet && frame && active === frame.fiber) return trackGet(atom);
|
|
187
|
+
return registry.get(atom);
|
|
188
|
+
}
|
|
189
|
+
function usePrimitiveSlot(fiber, make) {
|
|
190
|
+
const i = fiber.primitiveI ?? 0;
|
|
191
|
+
fiber.primitiveI = i + 1;
|
|
192
|
+
fiber.primitives ??= [];
|
|
193
|
+
const existing = fiber.primitives[i];
|
|
194
|
+
if (existing) return {
|
|
195
|
+
atom: existing,
|
|
196
|
+
fresh: false
|
|
197
|
+
};
|
|
198
|
+
const a = make();
|
|
199
|
+
fiber.primitives[i] = a;
|
|
200
|
+
return {
|
|
201
|
+
atom: a,
|
|
202
|
+
fresh: true
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function withTrackGetRun(fiber, fn, onOk, onErr) {
|
|
206
|
+
const deps = /* @__PURE__ */ new Set();
|
|
207
|
+
const get = (a) => {
|
|
208
|
+
deps.add(a);
|
|
209
|
+
return fiber.registry.get(a);
|
|
210
|
+
};
|
|
211
|
+
const restore = () => {
|
|
212
|
+
if (fiber.trackRestore !== restore) return;
|
|
213
|
+
const top = trackStack.pop();
|
|
214
|
+
if (top?.get !== get) {
|
|
215
|
+
if (top) trackStack.push(top);
|
|
216
|
+
const i = trackStack.findIndex((frame) => frame.get === get);
|
|
217
|
+
if (i >= 0) trackStack.splice(i, 1);
|
|
218
|
+
}
|
|
219
|
+
trackGet = trackStack.at(-1)?.get;
|
|
220
|
+
fiber.trackRestore = void 0;
|
|
221
|
+
};
|
|
222
|
+
trackStack.push({
|
|
223
|
+
fiber,
|
|
224
|
+
deps,
|
|
225
|
+
get
|
|
226
|
+
});
|
|
227
|
+
trackGet = get;
|
|
228
|
+
fiber.trackRestore = restore;
|
|
229
|
+
try {
|
|
230
|
+
const result = withFiber(fiber, () => fn());
|
|
231
|
+
if (result instanceof Promise) {
|
|
232
|
+
restore();
|
|
233
|
+
result.then((value) => {
|
|
234
|
+
if (fiber.closed) return;
|
|
235
|
+
onOk({
|
|
236
|
+
value,
|
|
237
|
+
deps
|
|
238
|
+
});
|
|
239
|
+
}).catch((e) => {
|
|
240
|
+
if (fiber.closed) return;
|
|
241
|
+
onErr(e);
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
restore();
|
|
246
|
+
onOk({
|
|
247
|
+
value: result,
|
|
248
|
+
deps
|
|
249
|
+
});
|
|
250
|
+
} catch (e) {
|
|
251
|
+
restore();
|
|
252
|
+
onErr(e);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function subscribeRenderDeps(fiber, deps, run) {
|
|
256
|
+
if (deps.size === 0) return () => {};
|
|
257
|
+
let scheduled = false;
|
|
258
|
+
const schedule = () => {
|
|
259
|
+
if (scheduled) return;
|
|
260
|
+
scheduled = true;
|
|
261
|
+
fiber.runtime.later(() => {
|
|
262
|
+
scheduled = false;
|
|
263
|
+
run();
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
const unsubs = [];
|
|
267
|
+
for (const dep of deps) unsubs.push(fiber.registry.subscribe(dep, schedule));
|
|
268
|
+
return () => {
|
|
269
|
+
for (const unsub of unsubs) unsub();
|
|
270
|
+
};
|
|
271
|
+
}
|
|
153
272
|
function wrapHandle(atom, fiber) {
|
|
154
273
|
const registry = fiber.registry;
|
|
155
274
|
const read = (() => {
|
|
156
275
|
guardHandleFiber(read);
|
|
157
|
-
return
|
|
276
|
+
return readTracked(atom, registry);
|
|
158
277
|
});
|
|
159
278
|
handleOwner.set(read, fiber);
|
|
160
279
|
Object.defineProperties(read, {
|
|
@@ -171,34 +290,40 @@ function wrapHandle(atom, fiber) {
|
|
|
171
290
|
});
|
|
172
291
|
return read;
|
|
173
292
|
}
|
|
174
|
-
function
|
|
293
|
+
function makeAtom(init) {
|
|
175
294
|
const fiber = getFiber();
|
|
176
|
-
const computed = typeof init === "function" && !Atom.isAtom(init) && !Effect.isEffect(init) && !Stream.isStream(init);
|
|
177
|
-
let seed = init;
|
|
178
295
|
const snap = fiber.runtime.hydrateValues;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
296
|
+
const { atom: a, fresh } = usePrimitiveSlot(fiber, () => {
|
|
297
|
+
let seed = init;
|
|
298
|
+
if (snap && !Atom.isAtom(init) && !Effect.isEffect(init) && !Stream.isStream(init)) {
|
|
299
|
+
const v = snap[fiber.runtime.hydrateI++];
|
|
300
|
+
if (v !== void 0) seed = v;
|
|
301
|
+
}
|
|
302
|
+
if (Atom.isAtom(seed)) return seed;
|
|
303
|
+
if (Effect.isEffect(seed) || Stream.isStream(seed)) return Atom.make(seed);
|
|
304
|
+
return Atom.make(seed);
|
|
305
|
+
});
|
|
306
|
+
const handle = wrapHandle(a, fiber);
|
|
307
|
+
if (fresh && fiber.runtime.ssr) fiber.runtime.ssrValues.push(fiber.registry.get(a));
|
|
308
|
+
return handle;
|
|
309
|
+
}
|
|
310
|
+
function atomLazy(init) {
|
|
311
|
+
const fiber = getFiber();
|
|
312
|
+
const snap = fiber.runtime.hydrateValues;
|
|
313
|
+
const { atom: a, fresh } = usePrimitiveSlot(fiber, () => {
|
|
314
|
+
let seed = init();
|
|
315
|
+
if (snap) {
|
|
316
|
+
const v = snap[fiber.runtime.hydrateI++];
|
|
317
|
+
if (v !== void 0) seed = v;
|
|
318
|
+
}
|
|
319
|
+
return Atom.make(seed);
|
|
320
|
+
});
|
|
198
321
|
const handle = wrapHandle(a, fiber);
|
|
199
|
-
if (fiber.runtime.ssr) fiber.runtime.ssrValues.push(fiber.registry.get(a));
|
|
322
|
+
if (fresh && fiber.runtime.ssr) fiber.runtime.ssrValues.push(fiber.registry.get(a));
|
|
200
323
|
return handle;
|
|
201
324
|
}
|
|
325
|
+
const atom = Object.assign(makeAtom, { lazy: atomLazy });
|
|
326
|
+
const batch = Atom.batch;
|
|
202
327
|
|
|
203
328
|
//#endregion
|
|
204
329
|
//#region src/errors.ts
|
|
@@ -308,12 +433,12 @@ function bindEvents(node, props, fiber) {
|
|
|
308
433
|
//#endregion
|
|
309
434
|
//#region src/morph.ts
|
|
310
435
|
const PRESERVE_ATTR = "data-morph-preserve";
|
|
311
|
-
const KEY_ATTR = "data-ilha-key";
|
|
312
|
-
const SLOT_ATTR = "data-ilha-slot";
|
|
436
|
+
const KEY_ATTR$1 = "data-ilha-key";
|
|
437
|
+
const SLOT_ATTR$1 = "data-ilha-slot";
|
|
313
438
|
function morphKeyOf(el) {
|
|
314
|
-
const k = el.getAttribute(KEY_ATTR);
|
|
439
|
+
const k = el.getAttribute(KEY_ATTR$1);
|
|
315
440
|
if (k !== null) return `k:${k}`;
|
|
316
|
-
const s = el.getAttribute(SLOT_ATTR);
|
|
441
|
+
const s = el.getAttribute(SLOT_ATTR$1);
|
|
317
442
|
return s === null ? null : `s:${s}`;
|
|
318
443
|
}
|
|
319
444
|
function shouldPreserveMorphAttr(el, name) {
|
|
@@ -396,17 +521,17 @@ function morphChildren(fromParent, toParent) {
|
|
|
396
521
|
if (fromNode instanceof Element) {
|
|
397
522
|
const fromKey = morphKeyOf(fromNode);
|
|
398
523
|
if (fromKey !== null && fromKey !== toKey && toKeys.has(fromKey)) {
|
|
399
|
-
fromParent.insertBefore(toNode
|
|
524
|
+
fromParent.insertBefore(toNode, fromNode);
|
|
400
525
|
continue;
|
|
401
526
|
}
|
|
402
527
|
}
|
|
403
528
|
}
|
|
404
529
|
if (!fromNode) {
|
|
405
|
-
fromParent.appendChild(toNode
|
|
530
|
+
fromParent.appendChild(toNode);
|
|
406
531
|
continue;
|
|
407
532
|
}
|
|
408
533
|
if (fromNode.nodeType !== toNode.nodeType) {
|
|
409
|
-
fromParent.replaceChild(toNode
|
|
534
|
+
fromParent.replaceChild(toNode, fromNode);
|
|
410
535
|
continue;
|
|
411
536
|
}
|
|
412
537
|
if (fromNode.nodeType === 3 || fromNode.nodeType === 8) {
|
|
@@ -417,10 +542,10 @@ function morphChildren(fromParent, toParent) {
|
|
|
417
542
|
const fromEl = fromNode;
|
|
418
543
|
const toEl = toNode;
|
|
419
544
|
if (fromEl.localName !== toEl.localName) {
|
|
420
|
-
fromParent.replaceChild(toEl
|
|
545
|
+
fromParent.replaceChild(toEl, fromEl);
|
|
421
546
|
continue;
|
|
422
547
|
}
|
|
423
|
-
const slotId = toEl.getAttribute(SLOT_ATTR);
|
|
548
|
+
const slotId = toEl.getAttribute(SLOT_ATTR$1);
|
|
424
549
|
if (slotId !== null && fromEl.getAttribute("data-ilha-slot") === slotId) continue;
|
|
425
550
|
if (fromEl.localName === "input") {
|
|
426
551
|
const hadChecked = fromEl.hasAttribute("checked");
|
|
@@ -552,19 +677,39 @@ function finish(fiber, view) {
|
|
|
552
677
|
fiber.park();
|
|
553
678
|
}
|
|
554
679
|
function runSetup(fiber, fn) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
680
|
+
const disposeRenderSub = () => {
|
|
681
|
+
fiber.renderSub?.();
|
|
682
|
+
fiber.renderSub = void 0;
|
|
683
|
+
};
|
|
684
|
+
const commit = (out, deps) => {
|
|
685
|
+
if (isGen(out)) {
|
|
686
|
+
disposeRenderSub();
|
|
687
|
+
interpret((() => out), fiber);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
disposeRenderSub();
|
|
691
|
+
if (!fiber.runtime.ssr) fiber.renderSub = subscribeRenderDeps(fiber, deps, render);
|
|
692
|
+
withFiber(fiber, () => finish(fiber, out));
|
|
693
|
+
};
|
|
694
|
+
const render = () => {
|
|
695
|
+
if (fiber.closed) return;
|
|
696
|
+
fiber.runtime.begin();
|
|
697
|
+
beginPrimitiveFrame(fiber);
|
|
698
|
+
withTrackGetRun(fiber, () => fn(), ({ value: out, deps }) => {
|
|
699
|
+
try {
|
|
700
|
+
commit(out, deps);
|
|
701
|
+
} catch (e) {
|
|
564
702
|
withFiber(fiber, () => fiber.fail(asFailure(e)));
|
|
703
|
+
} finally {
|
|
565
704
|
fiber.runtime.end();
|
|
566
|
-
}
|
|
567
|
-
}
|
|
705
|
+
}
|
|
706
|
+
}, (e) => {
|
|
707
|
+
withFiber(fiber, () => fiber.fail(asFailure(e)));
|
|
708
|
+
fiber.runtime.end();
|
|
709
|
+
});
|
|
710
|
+
};
|
|
711
|
+
try {
|
|
712
|
+
render();
|
|
568
713
|
} catch (e) {
|
|
569
714
|
fiber.fail(asFailure(e));
|
|
570
715
|
}
|
|
@@ -572,20 +717,27 @@ function runSetup(fiber, fn) {
|
|
|
572
717
|
|
|
573
718
|
//#endregion
|
|
574
719
|
//#region src/paint.ts
|
|
575
|
-
const ISLAND = Symbol.for("ilha.island");
|
|
576
|
-
const ISLAND_MOUNT_INTERNAL = Symbol.for("ilha.islandMountInternal");
|
|
577
|
-
const ISLAND_SLOT_TAG = Symbol.for("ilha.islandSlotTag");
|
|
578
|
-
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) {
|
|
579
724
|
for (const n of nodes) fiber.root.appendChild(n);
|
|
580
725
|
}
|
|
581
|
-
function disposeHoles(fiber) {
|
|
582
|
-
|
|
583
|
-
fiber.holes
|
|
726
|
+
function disposeHoles$1(fiber, opts) {
|
|
727
|
+
const keep = [];
|
|
728
|
+
for (const h of fiber.holes) {
|
|
729
|
+
if (opts?.morph && h.keepOnMorph) {
|
|
730
|
+
keep.push(h);
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
h.dispose();
|
|
734
|
+
}
|
|
735
|
+
fiber.holes = keep;
|
|
584
736
|
}
|
|
585
|
-
function skip(x) {
|
|
737
|
+
function skip$1(x) {
|
|
586
738
|
return x === null || x === void 0 || typeof x === "boolean";
|
|
587
739
|
}
|
|
588
|
-
function applyProps(el, props, fiber) {
|
|
740
|
+
function applyProps$1(el, props, fiber) {
|
|
589
741
|
for (const [k, v] of Object.entries(props)) {
|
|
590
742
|
if (k === "children" || k === "key" || k === "ref") continue;
|
|
591
743
|
if (k === "className") {
|
|
@@ -640,10 +792,10 @@ function applyProps(el, props, fiber) {
|
|
|
640
792
|
fiber.holes.push({ dispose: () => ref(null) });
|
|
641
793
|
}
|
|
642
794
|
}
|
|
643
|
-
const KEEP = Symbol("keep");
|
|
644
|
-
function unwrap(value, keep) {
|
|
795
|
+
const KEEP$1 = Symbol("keep");
|
|
796
|
+
function unwrap$1(value, keep) {
|
|
645
797
|
if (AsyncResult.isAsyncResult(value)) {
|
|
646
|
-
if (AsyncResult.isWaiting(value) && keep !== void 0) return KEEP;
|
|
798
|
+
if (AsyncResult.isWaiting(value) && keep !== void 0) return KEEP$1;
|
|
647
799
|
if (AsyncResult.isFailure(value) && !AsyncResult.isWaiting(value)) return String(AsyncResult.error(value) ?? "error");
|
|
648
800
|
const v = AsyncResult.value(value);
|
|
649
801
|
if (v._tag === "Some") return v.value;
|
|
@@ -651,18 +803,23 @@ function unwrap(value, keep) {
|
|
|
651
803
|
}
|
|
652
804
|
return value;
|
|
653
805
|
}
|
|
654
|
-
function paintHole(fiber, view) {
|
|
655
|
-
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;
|
|
656
813
|
const list = Array.isArray(view) ? view : null;
|
|
657
814
|
if (list && list.length > 0 && list.every((v) => isVNode(v) && v.key != null)) {
|
|
658
|
-
keyedPaintHole(fiber, list);
|
|
815
|
+
keyedPaintHole$1(fiber, list);
|
|
659
816
|
return;
|
|
660
817
|
}
|
|
661
|
-
disposeHoles(fiber);
|
|
818
|
+
disposeHoles$1(fiber);
|
|
662
819
|
if (fiber.root instanceof Element) fiber.root.replaceChildren();
|
|
663
|
-
insert(fiber, materialize(view, fiber));
|
|
820
|
+
insert$1(fiber, materialize$1(view, fiber));
|
|
664
821
|
}
|
|
665
|
-
function keyedPaintHole(fiber, views) {
|
|
822
|
+
function keyedPaintHole$1(fiber, views) {
|
|
666
823
|
const prev = fiber.keyedHoles ?? /* @__PURE__ */ new Map();
|
|
667
824
|
const keep = new Set(views.map((v) => String(v.key)));
|
|
668
825
|
for (const [k, h] of prev) if (!keep.has(k)) closeFiber(h);
|
|
@@ -676,34 +833,34 @@ function keyedPaintHole(fiber, views) {
|
|
|
676
833
|
nodes.push(reuse.root);
|
|
677
834
|
continue;
|
|
678
835
|
}
|
|
679
|
-
const made = materialize(v, fiber);
|
|
836
|
+
const made = materialize$1(v, fiber);
|
|
680
837
|
const hole = fiber.keyedHoles?.get(k);
|
|
681
838
|
if (hole) next.set(k, hole);
|
|
682
839
|
nodes.push(...made);
|
|
683
840
|
}
|
|
684
841
|
fiber.keyedHoles = next;
|
|
685
842
|
if (fiber.root instanceof Element) fiber.root.replaceChildren();
|
|
686
|
-
insert(fiber, nodes);
|
|
843
|
+
insert$1(fiber, nodes);
|
|
687
844
|
}
|
|
688
|
-
function openHole(parent) {
|
|
845
|
+
function openHole$1(parent) {
|
|
689
846
|
const id = parent.runtime.nextHole();
|
|
690
847
|
const host = document.createElement("span");
|
|
691
|
-
host.setAttribute(SLOT_ATTR, String(id));
|
|
848
|
+
host.setAttribute(SLOT_ATTR$1, String(id));
|
|
692
849
|
host.style.display = "contents";
|
|
693
850
|
const child = makeFiber(parent.runtime, host, (f, v) => {
|
|
694
|
-
disposeHoles(f);
|
|
851
|
+
disposeHoles$1(f);
|
|
695
852
|
if (f.root instanceof Element) f.root.replaceChildren();
|
|
696
|
-
insert(f, materialize(v, f));
|
|
853
|
+
insert$1(f, materialize$1(v, f));
|
|
697
854
|
}, { onFail: (e) => {
|
|
698
855
|
console.error(e);
|
|
699
|
-
paintHole(child, errorView(e));
|
|
856
|
+
paintHole$1(child, errorView$1(e));
|
|
700
857
|
} });
|
|
701
858
|
return {
|
|
702
859
|
fiber: child,
|
|
703
860
|
nodes: [host]
|
|
704
861
|
};
|
|
705
862
|
}
|
|
706
|
-
function errorView(e) {
|
|
863
|
+
function errorView$1(e) {
|
|
707
864
|
return {
|
|
708
865
|
$$ilha: 1,
|
|
709
866
|
type: "pre",
|
|
@@ -711,67 +868,133 @@ function errorView(e) {
|
|
|
711
868
|
children: [failureMessage(e)]
|
|
712
869
|
};
|
|
713
870
|
}
|
|
714
|
-
function
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
}
|
|
871
|
+
function findReusableAtomHost$1(fiber, atom) {
|
|
872
|
+
for (const h of fiber.holes) if (h.atom === atom && h.host?.isConnected && h.holeFiber && !h.holeFiber.closed) return {
|
|
873
|
+
host: h.host,
|
|
874
|
+
hole: h.holeFiber
|
|
875
|
+
};
|
|
719
876
|
}
|
|
720
|
-
function
|
|
721
|
-
if (
|
|
877
|
+
function refreshAtomHost(fiber, atom, host, hole) {
|
|
878
|
+
if (hole.closed || !host.isConnected) return;
|
|
879
|
+
const next = unwrap$1(fiber.registry.get(atom), void 0);
|
|
880
|
+
if (next === KEEP$1) return;
|
|
881
|
+
paintHole$1(hole, next);
|
|
882
|
+
}
|
|
883
|
+
function refreshAllAtomHosts(fiber) {
|
|
884
|
+
for (const h of fiber.holes) if (h.atom && h.host && h.holeFiber) refreshAtomHost(fiber, h.atom, h.host, h.holeFiber);
|
|
885
|
+
}
|
|
886
|
+
function pruneDisconnectedAtomHoles(fiber) {
|
|
887
|
+
fiber.holes = fiber.holes.filter((h) => {
|
|
888
|
+
if (!h.atom || !h.host || !h.holeFiber) return true;
|
|
889
|
+
if (h.host.isConnected) return true;
|
|
890
|
+
h.dispose();
|
|
891
|
+
return false;
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
function atomHostPlaceholder$1(host) {
|
|
895
|
+
const placeholder = document.createElement("span");
|
|
896
|
+
const slot = host.getAttribute(SLOT_ATTR$1);
|
|
897
|
+
if (slot !== null) placeholder.setAttribute(SLOT_ATTR$1, slot);
|
|
898
|
+
placeholder.style.display = "contents";
|
|
899
|
+
return placeholder;
|
|
900
|
+
}
|
|
901
|
+
function trackHole$1(parent, hole, extra, meta) {
|
|
902
|
+
parent.holes.push({
|
|
903
|
+
keepOnMorph: !!(meta?.atom && meta?.host) || !!meta?.keyed,
|
|
904
|
+
atom: meta?.atom,
|
|
905
|
+
host: meta?.host,
|
|
906
|
+
holeFiber: hole,
|
|
907
|
+
dispose() {
|
|
908
|
+
extra?.();
|
|
909
|
+
closeFiber(hole);
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
function materialize$1(view, fiber) {
|
|
914
|
+
if (skip$1(view)) return [];
|
|
722
915
|
if (typeof view === "string" || typeof view === "number" || typeof view === "bigint") return [document.createTextNode(String(view))];
|
|
723
916
|
if (isAtomHandle(view)) {
|
|
724
|
-
const
|
|
917
|
+
const reused = findReusableAtomHost$1(fiber, view.atom);
|
|
918
|
+
if (reused) return [atomHostPlaceholder$1(reused.host)];
|
|
919
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
920
|
+
const host = nodes[0];
|
|
725
921
|
let unsub = () => {};
|
|
726
922
|
fiber.runtime.later(() => {
|
|
727
923
|
if (hole.closed) return;
|
|
728
924
|
let keep;
|
|
729
925
|
unsub = fiber.registry.subscribe(view.atom, (v) => {
|
|
730
926
|
if (hole.closed) return;
|
|
731
|
-
const next = unwrap(v, keep);
|
|
732
|
-
if (next === KEEP) return;
|
|
927
|
+
const next = unwrap$1(v, keep);
|
|
928
|
+
if (next === KEEP$1) return;
|
|
733
929
|
keep = next;
|
|
734
|
-
paintHole(hole, next);
|
|
930
|
+
paintHole$1(hole, next);
|
|
735
931
|
}, { immediate: true });
|
|
736
932
|
});
|
|
737
|
-
trackHole(fiber, hole, () => unsub()
|
|
933
|
+
trackHole$1(fiber, hole, () => unsub(), {
|
|
934
|
+
atom: view.atom,
|
|
935
|
+
host
|
|
936
|
+
});
|
|
738
937
|
return nodes;
|
|
739
938
|
}
|
|
740
939
|
if (Stream.isStream(view)) {
|
|
741
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
940
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
742
941
|
const src = fiber.runtime.ssr ? view.pipe(Stream.take(1)) : view;
|
|
743
942
|
hole.run(Stream.runForEach(src, (v) => Effect.sync(() => {
|
|
744
|
-
if (!hole.closed) paintHole(hole, v);
|
|
943
|
+
if (!hole.closed) paintHole$1(hole, v);
|
|
745
944
|
})).pipe(Effect.catch((e) => Effect.sync(() => {
|
|
746
|
-
if (!hole.closed) paintHole(hole, String(e));
|
|
945
|
+
if (!hole.closed) paintHole$1(hole, String(e));
|
|
747
946
|
}))), fiber.runtime.ssr ? () => {} : void 0);
|
|
748
|
-
trackHole(fiber, hole);
|
|
947
|
+
trackHole$1(fiber, hole);
|
|
749
948
|
return nodes;
|
|
750
949
|
}
|
|
751
950
|
if (isSetupFn(view)) {
|
|
752
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
951
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
753
952
|
fiber.runtime.later(() => {
|
|
754
953
|
if (!hole.closed) runSetup(hole, view);
|
|
755
954
|
});
|
|
756
|
-
trackHole(fiber, hole);
|
|
955
|
+
trackHole$1(fiber, hole);
|
|
757
956
|
return nodes;
|
|
758
957
|
}
|
|
759
958
|
if (isVNode(view)) {
|
|
760
|
-
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));
|
|
761
960
|
if (typeof view.type === "function") {
|
|
762
961
|
const props = {
|
|
763
962
|
...view.props,
|
|
764
963
|
children: view.children
|
|
765
964
|
};
|
|
766
965
|
const type = view.type;
|
|
767
|
-
if (type[ISLAND] === true) {
|
|
768
|
-
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";
|
|
769
979
|
const el = document.createElement(tag);
|
|
770
980
|
el.setAttribute("data-ilha", "");
|
|
771
|
-
const mountFn = type[ISLAND_MOUNT_INTERNAL];
|
|
981
|
+
const mountFn = type[ISLAND_MOUNT_INTERNAL$1];
|
|
772
982
|
if (typeof mountFn === "function") {
|
|
773
983
|
const handle = mountFn(el, props);
|
|
774
|
-
|
|
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
|
+
});
|
|
775
998
|
}
|
|
776
999
|
return [el];
|
|
777
1000
|
}
|
|
@@ -783,7 +1006,7 @@ function materialize(view, fiber) {
|
|
|
783
1006
|
if (next && typeof next.then !== "function" && !isSetupFn(next)) reuse.paint(next);
|
|
784
1007
|
return [reuse.root];
|
|
785
1008
|
}
|
|
786
|
-
const { fiber: hole, nodes } = openHole(fiber);
|
|
1009
|
+
const { fiber: hole, nodes } = openHole$1(fiber);
|
|
787
1010
|
hole.propsBox = { current: props };
|
|
788
1011
|
if (k) {
|
|
789
1012
|
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
@@ -792,12 +1015,12 @@ function materialize(view, fiber) {
|
|
|
792
1015
|
fiber.runtime.later(() => {
|
|
793
1016
|
if (!hole.closed) runSetup(hole, () => type(hole.propsBox.current));
|
|
794
1017
|
});
|
|
795
|
-
trackHole(fiber, hole);
|
|
1018
|
+
trackHole$1(fiber, hole, void 0, k ? { keyed: true } : void 0);
|
|
796
1019
|
return nodes;
|
|
797
1020
|
}
|
|
798
1021
|
const el = document.createElement(view.type);
|
|
799
|
-
if (view.key != null) el.setAttribute(KEY_ATTR, String(view.key));
|
|
800
|
-
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);
|
|
801
1024
|
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
802
1025
|
const childFiber = {
|
|
803
1026
|
...fiber,
|
|
@@ -805,10 +1028,10 @@ function materialize(view, fiber) {
|
|
|
805
1028
|
holes: fiber.holes,
|
|
806
1029
|
keyedHoles: fiber.keyedHoles
|
|
807
1030
|
};
|
|
808
|
-
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);
|
|
809
1032
|
return [el];
|
|
810
1033
|
}
|
|
811
|
-
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));
|
|
812
1035
|
return [document.createTextNode(String(view))];
|
|
813
1036
|
}
|
|
814
1037
|
function canHydrate(fiber, view) {
|
|
@@ -816,20 +1039,24 @@ function canHydrate(fiber, view) {
|
|
|
816
1039
|
const el = fiber.root.firstElementChild;
|
|
817
1040
|
return !!el && el.tagName === view.type.toUpperCase();
|
|
818
1041
|
}
|
|
819
|
-
function paint(fiber, view) {
|
|
1042
|
+
function paint$1(fiber, view) {
|
|
1043
|
+
fiber.islandFrame ??= {
|
|
1044
|
+
i: 0,
|
|
1045
|
+
slots: []
|
|
1046
|
+
};
|
|
820
1047
|
if (fiber.hydrate) {
|
|
821
1048
|
if (canHydrate(fiber, view)) {
|
|
822
1049
|
const el = fiber.root.firstElementChild;
|
|
823
1050
|
fiber.hydrate = false;
|
|
824
1051
|
fiber.liveEl = el;
|
|
825
|
-
applyProps(el, view.props, fiber);
|
|
1052
|
+
applyProps$1(el, view.props, fiber);
|
|
826
1053
|
const childFiber = {
|
|
827
1054
|
...fiber,
|
|
828
1055
|
root: el,
|
|
829
1056
|
holes: fiber.holes
|
|
830
1057
|
};
|
|
831
1058
|
el.replaceChildren();
|
|
832
|
-
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);
|
|
833
1060
|
return;
|
|
834
1061
|
} else {
|
|
835
1062
|
console.warn("[ilha] hydrate mismatch, full mount");
|
|
@@ -838,28 +1065,31 @@ function paint(fiber, view) {
|
|
|
838
1065
|
}
|
|
839
1066
|
}
|
|
840
1067
|
if (fiber.liveEl && isVNode(view) && typeof view.type === "string" && fiber.liveEl.localName === view.type) {
|
|
841
|
-
|
|
1068
|
+
disposeHoles$1(fiber, { morph: true });
|
|
1069
|
+
applyProps$1(fiber.liveEl, view.props, fiber);
|
|
842
1070
|
const tmp = document.createElement(fiber.liveEl.localName);
|
|
843
|
-
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);
|
|
844
1072
|
morphInner(fiber.liveEl, tmp);
|
|
1073
|
+
refreshAllAtomHosts(fiber);
|
|
1074
|
+
pruneDisconnectedAtomHoles(fiber);
|
|
845
1075
|
return;
|
|
846
1076
|
}
|
|
847
|
-
disposeHoles(fiber);
|
|
1077
|
+
disposeHoles$1(fiber);
|
|
848
1078
|
if (fiber.root instanceof Element && fiber.root.childNodes.length > 0) {
|
|
849
1079
|
const tmp = document.createElement("div");
|
|
850
|
-
for (const n of materialize(view, fiber)) tmp.appendChild(n);
|
|
1080
|
+
for (const n of materialize$1(view, fiber)) tmp.appendChild(n);
|
|
851
1081
|
morphInner(fiber.root, tmp);
|
|
852
1082
|
const first = fiber.root.firstElementChild;
|
|
853
1083
|
if (first) fiber.liveEl = first;
|
|
854
1084
|
return;
|
|
855
1085
|
}
|
|
856
|
-
insert(fiber, materialize(view, fiber));
|
|
1086
|
+
insert$1(fiber, materialize$1(view, fiber));
|
|
857
1087
|
const first = fiber.root instanceof Element ? fiber.root.firstElementChild : null;
|
|
858
1088
|
if (first) fiber.liveEl = first;
|
|
859
1089
|
}
|
|
860
|
-
function paintError(fiber, e) {
|
|
1090
|
+
function paintError$1(fiber, e) {
|
|
861
1091
|
console.error(e);
|
|
862
|
-
paint(fiber, errorView(e));
|
|
1092
|
+
paint$1(fiber, errorView$1(e));
|
|
863
1093
|
}
|
|
864
1094
|
|
|
865
1095
|
//#endregion
|
|
@@ -912,10 +1142,466 @@ function decodeSnapshot(raw) {
|
|
|
912
1142
|
}
|
|
913
1143
|
|
|
914
1144
|
//#endregion
|
|
915
|
-
//#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
|
+
}
|
|
916
1167
|
function escapeAttr(s) {
|
|
917
|
-
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
|
+
};
|
|
918
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
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
//#endregion
|
|
1604
|
+
//#region src/mount.ts
|
|
919
1605
|
function readHydrate(el) {
|
|
920
1606
|
const raw = (el.hasAttribute("data-ilha") ? el : el.querySelector("[data-ilha]"))?.getAttribute("data-ilha-state");
|
|
921
1607
|
if (raw) return decodeSnapshot(raw);
|
|
@@ -928,18 +1614,14 @@ function readHydrate(el) {
|
|
|
928
1614
|
}
|
|
929
1615
|
function attach(el, fn, opts) {
|
|
930
1616
|
if (!opts?.hydrate) el.innerHTML = "";
|
|
931
|
-
const runtime = makeRuntime({
|
|
932
|
-
ssr: opts?.ssr,
|
|
933
|
-
ssrCapture: opts?.ssrCapture,
|
|
934
|
-
hydrate: opts?.hydrate ? readHydrate(el) : void 0
|
|
935
|
-
});
|
|
1617
|
+
const runtime = makeRuntime({ hydrate: opts?.hydrate ? readHydrate(el) : void 0 });
|
|
936
1618
|
let resolve;
|
|
937
1619
|
const ready = new Promise((r) => {
|
|
938
1620
|
resolve = r;
|
|
939
1621
|
});
|
|
940
|
-
const fiber = makeFiber(runtime, el, paint, { onFail: (e) => {
|
|
1622
|
+
const fiber = makeFiber(runtime, el, paint$1, { onFail: (e) => {
|
|
941
1623
|
opts?.onError?.(e);
|
|
942
|
-
paintError(fiber, e);
|
|
1624
|
+
paintError$1(fiber, e);
|
|
943
1625
|
resolve();
|
|
944
1626
|
} });
|
|
945
1627
|
if (opts?.hydrate) fiber.hydrate = true;
|
|
@@ -960,26 +1642,13 @@ function attach(el, fn, opts) {
|
|
|
960
1642
|
function mount(el, fn, opts) {
|
|
961
1643
|
return attach(el, fn, opts).unmount;
|
|
962
1644
|
}
|
|
963
|
-
let domReady;
|
|
964
|
-
function ensureDocument() {
|
|
965
|
-
if (typeof globalThis.document !== "undefined") return Promise.resolve();
|
|
966
|
-
domReady ??= import("@happy-dom/global-registrator").then(({ GlobalRegistrator }) => {
|
|
967
|
-
if (typeof globalThis.document === "undefined") GlobalRegistrator.register();
|
|
968
|
-
});
|
|
969
|
-
return domReady;
|
|
970
|
-
}
|
|
971
1645
|
async function renderToString(fn, opts) {
|
|
972
|
-
await ensureDocument();
|
|
973
1646
|
const snapshot = opts?.snapshot !== false;
|
|
974
1647
|
const markers = opts?.markers !== false;
|
|
975
|
-
const
|
|
976
|
-
const { unmount, ready, runtime } = attach(el, fn, {
|
|
977
|
-
ssr: true,
|
|
978
|
-
ssrCapture: opts?.captureActions === true
|
|
979
|
-
});
|
|
1648
|
+
const { unmount, ready, runtime, root } = attachSsr(fn, { ssrCapture: opts?.captureActions === true });
|
|
980
1649
|
if (opts?.timeout == null) await ready;
|
|
981
1650
|
else await Promise.race([ready, new Promise((r) => setTimeout(r, opts.timeout))]);
|
|
982
|
-
let inner =
|
|
1651
|
+
let inner = root.innerHTML;
|
|
983
1652
|
const actions = runtime.ssrActions;
|
|
984
1653
|
if (Object.keys(actions).length > 0) inner = `<template data-ilha-actions="${escapeAttr(JSON.stringify(actions))}"></template>${inner}`;
|
|
985
1654
|
const snap = snapshot ? encodeSnapshot(runtime.ssrValues) : void 0;
|
|
@@ -989,4 +1658,4 @@ async function renderToString(fn, opts) {
|
|
|
989
1658
|
}
|
|
990
1659
|
|
|
991
1660
|
//#endregion
|
|
992
|
-
export { atom as a,
|
|
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 };
|