ilha 0.14.10 → 0.15.1
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/dist/define.d.ts +1 -1
- package/dist/define.js +1 -1
- package/dist/index.d.ts +9 -17
- package/dist/index.js +3 -2
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/jsx-dev-runtime.js +1 -1
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/jsx-runtime.js +1 -1
- package/dist/mount-DCu8b0hE.js +482 -0
- package/dist/{mount-BzNrfVW4.js → paint-core-D9VO-oUM.js} +221 -622
- package/dist/renderer.d.ts +119 -0
- package/dist/renderer.js +75 -0
- package/dist/runtime-Baq7MtkE.d.ts +97 -0
- package/dist/{types-CJF2qMK6.d.ts → types-DsdtZMhG.d.ts} +29 -2
- package/dist/{vnode-M-oJMKcv.js → vnode-BHUY61Rm.js} +11 -2
- package/dist/{vnode-CUTNGblA.d.ts → vnode-CpSQZnLM.d.ts} +1 -1
- package/package.json +5 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { S as toError, _ as isString, a as ISLAND, b as asFailure, c as KEEP, f as errorView, g as isObject, h as isNumber, i as Fragment, l as KEY_ATTR, m as isFunction, n as isSetupFn, o as ISLAND_MOUNT_INTERNAL, p as isBigInt, r as isVNode, s as ISLAND_SLOT_TAG, u as SLOT_ATTR, v as skip, x as failureMessage, y as unwrap } from "./vnode-BHUY61Rm.js";
|
|
2
2
|
import * as Atom from "effect/reactivity/Atom";
|
|
3
3
|
import { Equal } from "effect";
|
|
4
4
|
import * as Effect$1 from "effect/Effect";
|
|
@@ -44,6 +44,8 @@ const clearFiberView = (fiber) => {
|
|
|
44
44
|
fiber.watchI = 0;
|
|
45
45
|
fiber.primitives = void 0;
|
|
46
46
|
fiber.primitiveI = 0;
|
|
47
|
+
for (const release of fiber.primitiveHolds ?? []) release();
|
|
48
|
+
fiber.primitiveHolds = void 0;
|
|
47
49
|
fiber.islandFrame = void 0;
|
|
48
50
|
fiber.keyedHoles = void 0;
|
|
49
51
|
for (const h of fiber.holes) h.dispose();
|
|
@@ -93,6 +95,7 @@ const makeRuntime = (opts) => {
|
|
|
93
95
|
holeSeq += 1;
|
|
94
96
|
return holeSeq;
|
|
95
97
|
},
|
|
98
|
+
onError: opts?.onError,
|
|
96
99
|
registry,
|
|
97
100
|
scope,
|
|
98
101
|
setIdle: (onReady) => {
|
|
@@ -148,6 +151,20 @@ const reportFiberError = (fiber, error) => {
|
|
|
148
151
|
}
|
|
149
152
|
return false;
|
|
150
153
|
};
|
|
154
|
+
/**
|
|
155
|
+
* Open a mount's root fiber. A failing root component reports to
|
|
156
|
+
* `runtime.onError`, paints the error view, and settles the mount.
|
|
157
|
+
*/
|
|
158
|
+
const makeRootFiber = ({ runtime, root, paint, settle }) => {
|
|
159
|
+
const fiber = makeFiber(runtime, root, paint, { onFail: (e) => {
|
|
160
|
+
const error = toError(e);
|
|
161
|
+
runtime.onError?.(error);
|
|
162
|
+
console.error(error);
|
|
163
|
+
fiber.paint(errorView(error));
|
|
164
|
+
settle();
|
|
165
|
+
} });
|
|
166
|
+
return fiber;
|
|
167
|
+
};
|
|
151
168
|
|
|
152
169
|
//#endregion
|
|
153
170
|
//#region src/atom.ts
|
|
@@ -272,6 +289,19 @@ const usePrimitiveSlot = (fiber, make) => {
|
|
|
272
289
|
fresh: true
|
|
273
290
|
};
|
|
274
291
|
};
|
|
292
|
+
/**
|
|
293
|
+
* Keep a component's own state atom in the registry while its fiber lives.
|
|
294
|
+
*
|
|
295
|
+
* The registry drops an atom nothing subscribes to. State that a handler
|
|
296
|
+
* writes and the view never reads would otherwise reset between events.
|
|
297
|
+
*/
|
|
298
|
+
const holdState = (fiber, atom) => {
|
|
299
|
+
if (!fiber.runtime.ssr) {
|
|
300
|
+
fiber.primitiveHolds ??= [];
|
|
301
|
+
fiber.primitiveHolds.push(fiber.registry.mount(atom));
|
|
302
|
+
}
|
|
303
|
+
return atom;
|
|
304
|
+
};
|
|
275
305
|
const withTrackGetRun = (fiber, fn, onOk, onErr) => {
|
|
276
306
|
const deps = /* @__PURE__ */ new Set();
|
|
277
307
|
const get = (a) => {
|
|
@@ -332,8 +362,10 @@ const subscribeRenderDeps = (fiber, deps, run) => {
|
|
|
332
362
|
const schedule = () => {
|
|
333
363
|
if (scheduled) return;
|
|
334
364
|
scheduled = true;
|
|
365
|
+
const seen = fiber.renderGen;
|
|
335
366
|
fiber.runtime.later(() => {
|
|
336
367
|
scheduled = false;
|
|
368
|
+
if (fiber.renderGen !== seen) return;
|
|
337
369
|
run();
|
|
338
370
|
});
|
|
339
371
|
};
|
|
@@ -378,9 +410,9 @@ const makeAtom = (init, options) => {
|
|
|
378
410
|
if (Effect$1.isEffect(seed) || Stream$1.isStream(seed)) return Atom.make(seed);
|
|
379
411
|
const made = Atom.make(seed);
|
|
380
412
|
const eq = options?.equals;
|
|
381
|
-
if (eq === void 0) return made;
|
|
413
|
+
if (eq === void 0) return holdState(fiber, made);
|
|
382
414
|
const equalsFn = eq === "structural" ? structuralEqual : eq;
|
|
383
|
-
return Atom.withEquality(made, equalsFn);
|
|
415
|
+
return holdState(fiber, Atom.withEquality(made, equalsFn));
|
|
384
416
|
});
|
|
385
417
|
const handle = wrapHandle(a, fiber);
|
|
386
418
|
if (fresh && fiber.runtime.ssr) fiber.runtime.ssrValues.push(fiber.registry.get(a));
|
|
@@ -396,7 +428,7 @@ const atomLazy = (init) => {
|
|
|
396
428
|
fiber.runtime.hydrateI += 1;
|
|
397
429
|
if (v !== void 0) seed = v;
|
|
398
430
|
}
|
|
399
|
-
return Atom.make(seed);
|
|
431
|
+
return holdState(fiber, Atom.make(seed));
|
|
400
432
|
});
|
|
401
433
|
const handle = wrapHandle(a, fiber);
|
|
402
434
|
if (fresh && fiber.runtime.ssr) fiber.runtime.ssrValues.push(fiber.registry.get(a));
|
|
@@ -477,6 +509,7 @@ const runSetup = (fiber, fn) => {
|
|
|
477
509
|
},
|
|
478
510
|
render: () => {
|
|
479
511
|
if (fiber.closed) return;
|
|
512
|
+
fiber.renderGen = (fiber.renderGen ?? 0) + 1;
|
|
480
513
|
fiber.runtime.begin();
|
|
481
514
|
beginPrimitiveFrame(fiber);
|
|
482
515
|
withTrackGetRun(fiber, () => fn(), ({ value: out, deps }) => {
|
|
@@ -502,7 +535,7 @@ const runSetup = (fiber, fn) => {
|
|
|
502
535
|
|
|
503
536
|
//#endregion
|
|
504
537
|
//#region src/events.ts
|
|
505
|
-
const ACTION_CALL
|
|
538
|
+
const ACTION_CALL = Symbol.for("ilha.actionCall");
|
|
506
539
|
const eventTypeFromProp = (key) => {
|
|
507
540
|
if (key.length < 4) return;
|
|
508
541
|
let type;
|
|
@@ -537,7 +570,7 @@ const bindSsrActions = (el, props, fiber) => {
|
|
|
537
570
|
seen.add(type);
|
|
538
571
|
const fn = props[key];
|
|
539
572
|
if (!isFunction(fn)) continue;
|
|
540
|
-
const branded = fn[ACTION_CALL
|
|
573
|
+
const branded = fn[ACTION_CALL];
|
|
541
574
|
const rec = branded?.k ? {
|
|
542
575
|
a: branded.a ?? [],
|
|
543
576
|
k: branded.k
|
|
@@ -1103,27 +1136,107 @@ const elementNs = (lower, parentNs) => {
|
|
|
1103
1136
|
if (parentNs === "http://www.w3.org/2000/svg" || parentNs === "http://www.w3.org/1998/Math/MathML") return parentNs;
|
|
1104
1137
|
};
|
|
1105
1138
|
const canMorphRoot = (root) => typeof Element !== "undefined" && typeof document !== "undefined" && root instanceof Element && root.childNodes.length > 0;
|
|
1139
|
+
/** Close a child hole through the parent's hole list, so it disposes once. */
|
|
1140
|
+
const releaseHole = (fiber, hole) => {
|
|
1141
|
+
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
1142
|
+
if (idx === -1) closeFiber(hole);
|
|
1143
|
+
else {
|
|
1144
|
+
const [removed] = fiber.holes.splice(idx, 1);
|
|
1145
|
+
removed?.dispose();
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1106
1148
|
const sweepComponentSlots = (fiber) => {
|
|
1107
1149
|
const cframe = fiber.componentFrame;
|
|
1108
1150
|
if (!cframe) return;
|
|
1109
1151
|
const { slots } = cframe;
|
|
1110
1152
|
for (let j = cframe.i; j < slots.length; j += 1) {
|
|
1111
1153
|
const s = slots[j];
|
|
1112
|
-
if (s)
|
|
1113
|
-
const { hole } = s;
|
|
1114
|
-
if (!hole.closed) {
|
|
1115
|
-
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
1116
|
-
if (idx === -1) closeFiber(hole);
|
|
1117
|
-
else {
|
|
1118
|
-
const [removed] = fiber.holes.splice(idx, 1);
|
|
1119
|
-
removed?.dispose();
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1154
|
+
if (s && !s.hole.closed) releaseHole(fiber, s.hole);
|
|
1123
1155
|
slots[j] = void 0;
|
|
1124
1156
|
}
|
|
1125
1157
|
slots.length = cframe.i;
|
|
1126
1158
|
};
|
|
1159
|
+
/** Close the keyed components the paint that just ran did not reach. */
|
|
1160
|
+
const sweepKeyedHoles = (fiber) => {
|
|
1161
|
+
const { keyedHoles, keyedGen } = fiber;
|
|
1162
|
+
if (!keyedHoles) return;
|
|
1163
|
+
for (const [k, hole] of keyedHoles) {
|
|
1164
|
+
if (!hole.closed && hole.keyedSeen === keyedGen) continue;
|
|
1165
|
+
keyedHoles.delete(k);
|
|
1166
|
+
if (!hole.closed) releaseHole(fiber, hole);
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
/**
|
|
1170
|
+
* Run `fn` as one paint of `fiber`: the keyed components it materializes stay
|
|
1171
|
+
* alive, and the ones it no longer reaches are closed afterwards.
|
|
1172
|
+
*/
|
|
1173
|
+
const pass = (fiber, fn) => {
|
|
1174
|
+
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
1175
|
+
fiber.keyedGen = (fiber.keyedGen ?? 0) + 1;
|
|
1176
|
+
fn();
|
|
1177
|
+
sweepKeyedHoles(fiber);
|
|
1178
|
+
};
|
|
1179
|
+
/**
|
|
1180
|
+
* Dispose a hole fiber's child holes before it repaints, except the component
|
|
1181
|
+
* and island holes the repaint can reuse: positional children, keyed
|
|
1182
|
+
* children, and islands. Reuse pushes new props instead of remounting, and the
|
|
1183
|
+
* sweeps that end the paint close whatever it did not reach.
|
|
1184
|
+
*/
|
|
1185
|
+
const keepReusableHoles = (fiber, cframe, frame) => {
|
|
1186
|
+
const kept = /* @__PURE__ */ new Set();
|
|
1187
|
+
for (const s of cframe.slots) if (s && !s.hole.closed) kept.add(s.hole);
|
|
1188
|
+
for (const hole of fiber.keyedHoles?.values() ?? []) if (!hole.closed) kept.add(hole);
|
|
1189
|
+
const keptIslands = new Set(frame.slots);
|
|
1190
|
+
const keep = [];
|
|
1191
|
+
for (const h of fiber.holes) {
|
|
1192
|
+
if (h.holeFiber && kept.has(h.holeFiber) || h.islandSlot && keptIslands.has(h.islandSlot)) {
|
|
1193
|
+
keep.push(h);
|
|
1194
|
+
continue;
|
|
1195
|
+
}
|
|
1196
|
+
h.dispose();
|
|
1197
|
+
}
|
|
1198
|
+
fiber.holes = keep;
|
|
1199
|
+
};
|
|
1200
|
+
/** Shallow equality of two prop bags, children compared item by item. */
|
|
1201
|
+
const sameProps = (prev, next) => {
|
|
1202
|
+
if (!prev) return false;
|
|
1203
|
+
const keys = Object.keys(next);
|
|
1204
|
+
if (keys.length !== Object.keys(prev).length) return false;
|
|
1205
|
+
return keys.every((k) => {
|
|
1206
|
+
const a = prev[k];
|
|
1207
|
+
const b = next[k];
|
|
1208
|
+
if (k === "children" && Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => Object.is(x, b[i]));
|
|
1209
|
+
return Object.is(a, b);
|
|
1210
|
+
});
|
|
1211
|
+
};
|
|
1212
|
+
/**
|
|
1213
|
+
* Rerun a reused component hole with new props, in its own fiber. The props
|
|
1214
|
+
* box is updated in place, so every render closure of the hole reads the
|
|
1215
|
+
* latest props, including a self-render queued while an async render ran.
|
|
1216
|
+
*/
|
|
1217
|
+
const rerunHole = (hole, run, props) => {
|
|
1218
|
+
const box = hole.propsBox ?? { current: props };
|
|
1219
|
+
box.current = props;
|
|
1220
|
+
hole.propsBox = box;
|
|
1221
|
+
runSetup(hole, () => run(box.current));
|
|
1222
|
+
};
|
|
1223
|
+
/**
|
|
1224
|
+
* Run a new component hole's first render after the paint that opened it. A
|
|
1225
|
+
* repaint that reached the hole first already rendered it with newer props.
|
|
1226
|
+
*/
|
|
1227
|
+
const mountHoleLater = (fiber, hole, run) => {
|
|
1228
|
+
fiber.runtime.later(() => {
|
|
1229
|
+
const box = hole.propsBox;
|
|
1230
|
+
if (hole.closed || hole.renderGen !== void 0 || !box) return;
|
|
1231
|
+
runSetup(hole, () => run(box.current));
|
|
1232
|
+
});
|
|
1233
|
+
};
|
|
1234
|
+
const warnedKeys = /* @__PURE__ */ new Set();
|
|
1235
|
+
const warnDuplicateKey = (key) => {
|
|
1236
|
+
if (warnedKeys.has(key)) return;
|
|
1237
|
+
warnedKeys.add(key);
|
|
1238
|
+
console.warn(`ilha: key "${key}" is used by more than one component in the same parent component; keys must be unique there. The duplicate keeps its state by position instead.`);
|
|
1239
|
+
};
|
|
1127
1240
|
const sweepIslandSlots = (fiber) => {
|
|
1128
1241
|
const frame = fiber.islandFrame;
|
|
1129
1242
|
if (!frame) return;
|
|
@@ -1156,10 +1269,6 @@ const styleCss = (v) => {
|
|
|
1156
1269
|
if (isString(v) || isObject(v)) return serializeStyleAttr(v);
|
|
1157
1270
|
return "";
|
|
1158
1271
|
};
|
|
1159
|
-
const isThenable = (value) => {
|
|
1160
|
-
if (!isObject(value) && !isFunction(value)) return false;
|
|
1161
|
-
return isFunction(value.then);
|
|
1162
|
-
};
|
|
1163
1272
|
const writeAttr = (el, k, v) => {
|
|
1164
1273
|
if (v === false || v === null || v === void 0) {
|
|
1165
1274
|
el.removeAttribute(k);
|
|
@@ -1218,6 +1327,7 @@ const createPainter = (ops) => {
|
|
|
1218
1327
|
const applyProps = (el, props, fiber) => {
|
|
1219
1328
|
for (const [k, v] of Object.entries(props)) {
|
|
1220
1329
|
if (isSkippedPropKey(k)) continue;
|
|
1330
|
+
if (ops.setProp?.(el, k, v) === true) continue;
|
|
1221
1331
|
if (k === "className") {
|
|
1222
1332
|
el.setAttribute("class", String(v ?? ""));
|
|
1223
1333
|
continue;
|
|
@@ -1263,6 +1373,7 @@ const createPainter = (ops) => {
|
|
|
1263
1373
|
onFail: (e) => {
|
|
1264
1374
|
const error = toError(e);
|
|
1265
1375
|
if (reportFiberError(child, error)) return;
|
|
1376
|
+
parent.runtime.onError?.(error);
|
|
1266
1377
|
console.error(error);
|
|
1267
1378
|
api.paintHole(child, errorView(error));
|
|
1268
1379
|
},
|
|
@@ -1273,57 +1384,47 @@ const createPainter = (ops) => {
|
|
|
1273
1384
|
nodes: [host]
|
|
1274
1385
|
};
|
|
1275
1386
|
},
|
|
1276
|
-
paintHole: (fiber, view) =>
|
|
1387
|
+
paintHole: (fiber, view) => {
|
|
1277
1388
|
if (view === KEEP) return;
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
const tmp = document.createElement("div");
|
|
1318
|
-
for (const n of fresh) tmp.append(n);
|
|
1319
|
-
morphInner(fiber.root, tmp);
|
|
1320
|
-
} else {
|
|
1321
|
-
ops.clearRoot(fiber.root);
|
|
1322
|
-
api.insert(fiber, fresh);
|
|
1323
|
-
}
|
|
1324
|
-
sweepComponentSlots(fiber);
|
|
1325
|
-
sweepIslandSlots(fiber);
|
|
1326
|
-
})
|
|
1389
|
+
commit(() => {
|
|
1390
|
+
pass(fiber, () => {
|
|
1391
|
+
let frame = fiber.islandFrame;
|
|
1392
|
+
if (!frame) {
|
|
1393
|
+
frame = {
|
|
1394
|
+
i: 0,
|
|
1395
|
+
slots: []
|
|
1396
|
+
};
|
|
1397
|
+
fiber.islandFrame = frame;
|
|
1398
|
+
}
|
|
1399
|
+
frame.i = 0;
|
|
1400
|
+
let cframe = fiber.componentFrame;
|
|
1401
|
+
if (!cframe) {
|
|
1402
|
+
cframe = {
|
|
1403
|
+
i: 0,
|
|
1404
|
+
slots: []
|
|
1405
|
+
};
|
|
1406
|
+
fiber.componentFrame = cframe;
|
|
1407
|
+
}
|
|
1408
|
+
cframe.i = 0;
|
|
1409
|
+
const list = Array.isArray(view) ? view : null;
|
|
1410
|
+
if (list && list.length > 0 && list.every((v) => isVNode(v) && isFunction(v.type) && v.key !== null && v.key !== void 0)) {
|
|
1411
|
+
paintFns.keyedPaintHole(fiber, list);
|
|
1412
|
+
sweepComponentSlots(fiber);
|
|
1413
|
+
sweepIslandSlots(fiber);
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
keepReusableHoles(fiber, cframe, frame);
|
|
1417
|
+
const fresh = api.materialize(view, fiber);
|
|
1418
|
+
if (canMorphRoot(fiber.root)) {
|
|
1419
|
+
const tmp = document.createElement("div");
|
|
1420
|
+
for (const n of fresh) tmp.append(n);
|
|
1421
|
+
morphInner(fiber.root, tmp);
|
|
1422
|
+
} else ops.placeChildren(fiber.root, fresh);
|
|
1423
|
+
sweepComponentSlots(fiber);
|
|
1424
|
+
sweepIslandSlots(fiber);
|
|
1425
|
+
});
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1327
1428
|
};
|
|
1328
1429
|
const materializeAtom = (view, fiber) => {
|
|
1329
1430
|
const reused = findReusableAtomHost(fiber, view.atom);
|
|
@@ -1426,18 +1527,10 @@ const createPainter = (ops) => {
|
|
|
1426
1527
|
if (existing) {
|
|
1427
1528
|
const { hole } = existing;
|
|
1428
1529
|
if (existing.type === type && !hole.closed) {
|
|
1429
|
-
hole
|
|
1430
|
-
runSetup(hole, () => run(props));
|
|
1530
|
+
rerunHole(hole, run, props);
|
|
1431
1531
|
return [ops.reuseNode(hole.root)];
|
|
1432
1532
|
}
|
|
1433
|
-
if (!hole.closed)
|
|
1434
|
-
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
1435
|
-
if (idx === -1) closeFiber(hole);
|
|
1436
|
-
else {
|
|
1437
|
-
const [removed] = fiber.holes.splice(idx, 1);
|
|
1438
|
-
removed?.dispose();
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1533
|
+
if (!hole.closed) releaseHole(fiber, hole);
|
|
1441
1534
|
}
|
|
1442
1535
|
const { fiber: hole, nodes } = api.openHole(fiber);
|
|
1443
1536
|
hole.propsBox = { current: props };
|
|
@@ -1446,15 +1539,36 @@ const createPainter = (ops) => {
|
|
|
1446
1539
|
hole,
|
|
1447
1540
|
type
|
|
1448
1541
|
};
|
|
1449
|
-
fiber
|
|
1450
|
-
if (hole.closed) return;
|
|
1451
|
-
const box = hole.propsBox;
|
|
1452
|
-
if (!box) return;
|
|
1453
|
-
runSetup(hole, () => run(box.current));
|
|
1454
|
-
});
|
|
1542
|
+
mountHoleLater(fiber, hole, run);
|
|
1455
1543
|
trackHole(fiber, hole, void 0, { keyed: true });
|
|
1456
1544
|
return nodes;
|
|
1457
1545
|
};
|
|
1546
|
+
const materializeKeyedComponent = ({ run, type, props, key, fiber }) => {
|
|
1547
|
+
let reuse = fiber.keyedHoles?.get(key);
|
|
1548
|
+
const gen = fiber.keyedGen;
|
|
1549
|
+
if (reuse && !reuse.closed && reuse.keyedSeen === gen) {
|
|
1550
|
+
warnDuplicateKey(key);
|
|
1551
|
+
return materializeUnkeyedComponent(run, type, props, fiber);
|
|
1552
|
+
}
|
|
1553
|
+
if (reuse && !reuse.closed && reuse.componentType !== type) {
|
|
1554
|
+
fiber.keyedHoles?.delete(key);
|
|
1555
|
+
releaseHole(fiber, reuse);
|
|
1556
|
+
reuse = void 0;
|
|
1557
|
+
}
|
|
1558
|
+
if (reuse && !reuse.closed) {
|
|
1559
|
+
reuse.keyedSeen = gen;
|
|
1560
|
+
if (!sameProps(reuse.propsBox?.current, props)) rerunHole(reuse, run, props);
|
|
1561
|
+
return [ops.reuseNode(reuse.root)];
|
|
1562
|
+
}
|
|
1563
|
+
const { fiber: khole, nodes: knodes } = api.openHole(fiber);
|
|
1564
|
+
khole.propsBox = { current: props };
|
|
1565
|
+
khole.componentType = type;
|
|
1566
|
+
khole.keyedSeen = gen;
|
|
1567
|
+
fiber.keyedHoles?.set(key, khole);
|
|
1568
|
+
mountHoleLater(fiber, khole, run);
|
|
1569
|
+
trackHole(fiber, khole, void 0, { keyed: true });
|
|
1570
|
+
return knodes;
|
|
1571
|
+
};
|
|
1458
1572
|
const materializeComponent = (view, type, fiber) => {
|
|
1459
1573
|
const props = {
|
|
1460
1574
|
...view.props,
|
|
@@ -1462,28 +1576,15 @@ const createPainter = (ops) => {
|
|
|
1462
1576
|
};
|
|
1463
1577
|
const branded = type;
|
|
1464
1578
|
if (branded[ISLAND] === true) return materializeIsland(branded, props, fiber);
|
|
1465
|
-
const k = view.key === null || view.key === void 0 ? void 0 : String(view.key);
|
|
1466
|
-
const reuse = k ? fiber.keyedHoles?.get(k) : void 0;
|
|
1467
1579
|
const run = type;
|
|
1468
|
-
if (
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
const { fiber: khole, nodes: knodes } = api.openHole(fiber);
|
|
1476
|
-
khole.propsBox = { current: props };
|
|
1477
|
-
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
1478
|
-
fiber.keyedHoles.set(k, khole);
|
|
1479
|
-
fiber.runtime.later(() => {
|
|
1480
|
-
if (khole.closed) return;
|
|
1481
|
-
const box = khole.propsBox;
|
|
1482
|
-
if (!box) return;
|
|
1483
|
-
runSetup(khole, () => run(box.current));
|
|
1580
|
+
if (view.key === null || view.key === void 0) return materializeUnkeyedComponent(run, type, props, fiber);
|
|
1581
|
+
return materializeKeyedComponent({
|
|
1582
|
+
fiber,
|
|
1583
|
+
key: String(view.key),
|
|
1584
|
+
props,
|
|
1585
|
+
run,
|
|
1586
|
+
type
|
|
1484
1587
|
});
|
|
1485
|
-
trackHole(fiber, khole, void 0, { keyed: true });
|
|
1486
|
-
return knodes;
|
|
1487
1588
|
};
|
|
1488
1589
|
const materializeElement = (view, fiber) => {
|
|
1489
1590
|
const tag = view.type;
|
|
@@ -1492,7 +1593,6 @@ const createPainter = (ops) => {
|
|
|
1492
1593
|
const el = ops.createElement(tag, ns);
|
|
1493
1594
|
if (view.key !== null && view.key !== void 0) el.setAttribute(KEY_ATTR, String(view.key));
|
|
1494
1595
|
api.applyProps(el, view.props, fiber);
|
|
1495
|
-
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
1496
1596
|
const childFiber = {
|
|
1497
1597
|
...fiber,
|
|
1498
1598
|
holes: fiber.holes,
|
|
@@ -1526,25 +1626,22 @@ const createPainter = (ops) => {
|
|
|
1526
1626
|
return [ops.createText(String(view))];
|
|
1527
1627
|
};
|
|
1528
1628
|
paintFns.keyedPaintHole = (fiber, views) => {
|
|
1529
|
-
const prev = fiber.keyedHoles ?? /* @__PURE__ */ new Map();
|
|
1530
|
-
const keep = new Set(views.map((v) => String(v.key)));
|
|
1531
|
-
for (const [k, h] of prev) if (!keep.has(k)) closeFiber(h);
|
|
1532
|
-
const next = /* @__PURE__ */ new Map();
|
|
1533
1629
|
const nodes = [];
|
|
1534
1630
|
for (const v of views) {
|
|
1535
|
-
const
|
|
1536
|
-
const
|
|
1537
|
-
if (reuse &&
|
|
1538
|
-
|
|
1631
|
+
const reuse = fiber.keyedHoles?.get(String(v.key));
|
|
1632
|
+
const reusable = reuse && !reuse.closed && reuse.keyedSeen !== fiber.keyedGen && reuse.componentType === v.type;
|
|
1633
|
+
if (reuse && reusable) {
|
|
1634
|
+
reuse.keyedSeen = fiber.keyedGen;
|
|
1635
|
+
const props = {
|
|
1636
|
+
...v.props,
|
|
1637
|
+
children: v.children
|
|
1638
|
+
};
|
|
1639
|
+
if (!sameProps(reuse.propsBox?.current, props)) rerunHole(reuse, v.type, props);
|
|
1539
1640
|
nodes.push(ops.asNode(reuse.root));
|
|
1540
1641
|
continue;
|
|
1541
1642
|
}
|
|
1542
|
-
|
|
1543
|
-
const hole = fiber.keyedHoles?.get(k);
|
|
1544
|
-
if (hole) next.set(k, hole);
|
|
1545
|
-
nodes.push(...made);
|
|
1643
|
+
nodes.push(...api.materialize(v, fiber));
|
|
1546
1644
|
}
|
|
1547
|
-
fiber.keyedHoles = next;
|
|
1548
1645
|
ops.placeChildren(fiber.root, nodes);
|
|
1549
1646
|
};
|
|
1550
1647
|
return {
|
|
@@ -1553,508 +1650,10 @@ const createPainter = (ops) => {
|
|
|
1553
1650
|
disposeHoles: (fiber, opts) => disposeHoles(fiber, opts),
|
|
1554
1651
|
insert: api.insert,
|
|
1555
1652
|
materialize: api.materialize,
|
|
1556
|
-
paintHole: api.paintHole
|
|
1653
|
+
paintHole: api.paintHole,
|
|
1654
|
+
pass
|
|
1557
1655
|
};
|
|
1558
1656
|
};
|
|
1559
1657
|
|
|
1560
1658
|
//#endregion
|
|
1561
|
-
|
|
1562
|
-
const noopDisconnect = () => {};
|
|
1563
|
-
const core$1 = createPainter({
|
|
1564
|
-
appendRoot: (root, node) => insertRendered(root, node, null),
|
|
1565
|
-
asElement: (el) => el,
|
|
1566
|
-
asNode: (host) => host,
|
|
1567
|
-
asRoot: (el) => el,
|
|
1568
|
-
bindEvents,
|
|
1569
|
-
clearRoot: (root) => {
|
|
1570
|
-
if (root instanceof Element) root.replaceChildren();
|
|
1571
|
-
},
|
|
1572
|
-
committed: committedElement,
|
|
1573
|
-
createElement: (tag, ns) => ns ? document.createElementNS(ns, tag) : document.createElement(tag),
|
|
1574
|
-
createRaw: (html, parent) => {
|
|
1575
|
-
const range = document.createRange();
|
|
1576
|
-
range.selectNodeContents(parent);
|
|
1577
|
-
return [...range.createContextualFragment(html).childNodes];
|
|
1578
|
-
},
|
|
1579
|
-
createSlotHost: (slotId) => {
|
|
1580
|
-
const host = document.createElement("span");
|
|
1581
|
-
if (slotId !== null) host.setAttribute(SLOT_ATTR, slotId);
|
|
1582
|
-
host.style.display = "contents";
|
|
1583
|
-
return host;
|
|
1584
|
-
},
|
|
1585
|
-
createText: (text) => document.createTextNode(text),
|
|
1586
|
-
disconnect: noopDisconnect,
|
|
1587
|
-
placeChildren: (root, nodes) => {
|
|
1588
|
-
if (root instanceof Element) placeChildren(root, nodes);
|
|
1589
|
-
},
|
|
1590
|
-
reuseNode: (host) => host instanceof Element && host.isConnected ? standInFor(host) : host,
|
|
1591
|
-
setFormControl: (el, key, v) => {
|
|
1592
|
-
const node = el;
|
|
1593
|
-
if (key === "value") {
|
|
1594
|
-
if (v === null || v === void 0) {
|
|
1595
|
-
el.removeAttribute("value");
|
|
1596
|
-
node.value = "";
|
|
1597
|
-
} else {
|
|
1598
|
-
el.setAttribute("value", String(v));
|
|
1599
|
-
node.value = String(v);
|
|
1600
|
-
}
|
|
1601
|
-
} else if (key === "checked") {
|
|
1602
|
-
node.checked = Boolean(v);
|
|
1603
|
-
if (v) el.setAttribute("checked", "");
|
|
1604
|
-
else el.removeAttribute("checked");
|
|
1605
|
-
} else {
|
|
1606
|
-
node.selected = Boolean(v);
|
|
1607
|
-
if (v) el.setAttribute("selected", "");
|
|
1608
|
-
else el.removeAttribute("selected");
|
|
1609
|
-
}
|
|
1610
|
-
},
|
|
1611
|
-
setStyle: (el, css) => {
|
|
1612
|
-
el.style.cssText = css;
|
|
1613
|
-
}
|
|
1614
|
-
});
|
|
1615
|
-
const refreshAtomHost = (fiber, atom, host, hole) => {
|
|
1616
|
-
if (hole.closed || !host.isConnected) return;
|
|
1617
|
-
const next = unwrap(fiber.registry.get(atom));
|
|
1618
|
-
if (next === KEEP) return;
|
|
1619
|
-
core$1.paintHole(hole, next);
|
|
1620
|
-
};
|
|
1621
|
-
const refreshAllAtomHosts = (fiber) => {
|
|
1622
|
-
for (const h of fiber.holes) if (h.atom && h.host && h.holeFiber) refreshAtomHost(fiber, h.atom, h.host, h.holeFiber);
|
|
1623
|
-
};
|
|
1624
|
-
const pruneDisconnectedAtomHoles = (fiber) => {
|
|
1625
|
-
fiber.holes = fiber.holes.filter((h) => {
|
|
1626
|
-
if (!h.atom || !h.host || !h.holeFiber) return true;
|
|
1627
|
-
if (h.host.isConnected) return true;
|
|
1628
|
-
h.dispose();
|
|
1629
|
-
return false;
|
|
1630
|
-
});
|
|
1631
|
-
};
|
|
1632
|
-
const canHydrate = (fiber, view) => {
|
|
1633
|
-
if (!isVNode(view) || !isString(view.type)) return false;
|
|
1634
|
-
const el = fiber.root.firstElementChild;
|
|
1635
|
-
return !!el && el.tagName === view.type.toUpperCase();
|
|
1636
|
-
};
|
|
1637
|
-
const paintHydrate = (fiber, view) => {
|
|
1638
|
-
const el = fiber.root.firstElementChild;
|
|
1639
|
-
if (!el) return;
|
|
1640
|
-
fiber.hydrate = false;
|
|
1641
|
-
fiber.liveEl = el;
|
|
1642
|
-
core$1.applyProps(el, view.props, fiber);
|
|
1643
|
-
const childFiber = {
|
|
1644
|
-
...fiber,
|
|
1645
|
-
holes: fiber.holes,
|
|
1646
|
-
root: el
|
|
1647
|
-
};
|
|
1648
|
-
el.replaceChildren();
|
|
1649
|
-
for (const c of view.children) for (const n of core$1.materialize(c, childFiber)) insertRendered(el, n, null);
|
|
1650
|
-
};
|
|
1651
|
-
const paintMorphLive = (fiber, view) => {
|
|
1652
|
-
if (!fiber.liveEl) return;
|
|
1653
|
-
core$1.disposeHoles(fiber, { morph: true });
|
|
1654
|
-
core$1.applyProps(fiber.liveEl, view.props, fiber);
|
|
1655
|
-
const liveNs = fiber.liveEl.namespaceURI;
|
|
1656
|
-
const tmp = liveNs && liveNs !== "http://www.w3.org/1999/xhtml" ? document.createElementNS(liveNs, fiber.liveEl.localName) : document.createElement(fiber.liveEl.localName);
|
|
1657
|
-
const childFiber = {
|
|
1658
|
-
...fiber,
|
|
1659
|
-
holes: fiber.holes,
|
|
1660
|
-
root: tmp
|
|
1661
|
-
};
|
|
1662
|
-
for (const c of view.children) for (const n of core$1.materialize(c, childFiber)) tmp.append(n);
|
|
1663
|
-
morphInner(fiber.liveEl, tmp);
|
|
1664
|
-
refreshAllAtomHosts(fiber);
|
|
1665
|
-
pruneDisconnectedAtomHoles(fiber);
|
|
1666
|
-
};
|
|
1667
|
-
const paintRoot = (fiber, view) => {
|
|
1668
|
-
fiber.islandFrame ??= {
|
|
1669
|
-
i: 0,
|
|
1670
|
-
slots: []
|
|
1671
|
-
};
|
|
1672
|
-
if (fiber.hydrate) {
|
|
1673
|
-
if (canHydrate(fiber, view)) {
|
|
1674
|
-
paintHydrate(fiber, view);
|
|
1675
|
-
return;
|
|
1676
|
-
}
|
|
1677
|
-
console.warn("[ilha] hydrate mismatch, full mount");
|
|
1678
|
-
fiber.hydrate = false;
|
|
1679
|
-
if (fiber.root instanceof Element) fiber.root.replaceChildren();
|
|
1680
|
-
}
|
|
1681
|
-
if (fiber.liveEl && isVNode(view) && isString(view.type) && fiber.liveEl.localName === view.type) {
|
|
1682
|
-
paintMorphLive(fiber, view);
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
core$1.disposeHoles(fiber, { morph: true });
|
|
1686
|
-
if (fiber.root instanceof Element && fiber.root.childNodes.length > 0) {
|
|
1687
|
-
const tmp = document.createElement("div");
|
|
1688
|
-
for (const n of core$1.materialize(view, fiber)) tmp.append(n);
|
|
1689
|
-
morphInner(fiber.root, tmp);
|
|
1690
|
-
const first = fiber.root.firstElementChild;
|
|
1691
|
-
if (first) fiber.liveEl = first;
|
|
1692
|
-
return;
|
|
1693
|
-
}
|
|
1694
|
-
core$1.insert(fiber, core$1.materialize(view, fiber));
|
|
1695
|
-
const first = fiber.root instanceof Element ? fiber.root.firstElementChild : null;
|
|
1696
|
-
if (first) fiber.liveEl = first;
|
|
1697
|
-
};
|
|
1698
|
-
const paint$1 = (fiber, view) => {
|
|
1699
|
-
core$1.commit(() => {
|
|
1700
|
-
paintRoot(fiber, view);
|
|
1701
|
-
});
|
|
1702
|
-
};
|
|
1703
|
-
const paintError$1 = (fiber, e) => {
|
|
1704
|
-
console.error(e);
|
|
1705
|
-
paint$1(fiber, errorView(e));
|
|
1706
|
-
};
|
|
1707
|
-
|
|
1708
|
-
//#endregion
|
|
1709
|
-
//#region src/snapshot.ts
|
|
1710
|
-
const MAX_SNAPSHOT_CHARS = 262144;
|
|
1711
|
-
const MAX_SNAPSHOT_DEPTH = 32;
|
|
1712
|
-
const exceedsMaxDepth = (value, depth) => {
|
|
1713
|
-
if (depth > MAX_SNAPSHOT_DEPTH) return true;
|
|
1714
|
-
if (value === null || !isObject(value)) {
|
|
1715
|
-
if (Array.isArray(value)) {
|
|
1716
|
-
for (const item of value) if (exceedsMaxDepth(item, depth + 1)) return true;
|
|
1717
|
-
}
|
|
1718
|
-
return false;
|
|
1719
|
-
}
|
|
1720
|
-
const obj = value;
|
|
1721
|
-
for (const key of Object.keys(obj)) if (exceedsMaxDepth(obj[key], depth + 1)) return true;
|
|
1722
|
-
return false;
|
|
1723
|
-
};
|
|
1724
|
-
const deleteUnsafeKey = (obj, key) => {
|
|
1725
|
-
if (Object.hasOwn(obj, key)) Reflect.deleteProperty(obj, key);
|
|
1726
|
-
};
|
|
1727
|
-
const stripUnsafeKeys = (value) => {
|
|
1728
|
-
if (Array.isArray(value)) {
|
|
1729
|
-
for (const item of value) stripUnsafeKeys(item);
|
|
1730
|
-
return;
|
|
1731
|
-
}
|
|
1732
|
-
if (value === null || !isObject(value)) return;
|
|
1733
|
-
const obj = value;
|
|
1734
|
-
deleteUnsafeKey(obj, "__proto__");
|
|
1735
|
-
deleteUnsafeKey(obj, "constructor");
|
|
1736
|
-
deleteUnsafeKey(obj, "prototype");
|
|
1737
|
-
for (const key of Object.getOwnPropertyNames(obj)) stripUnsafeKeys(obj[key]);
|
|
1738
|
-
};
|
|
1739
|
-
const safeParseSnapshot = (raw) => {
|
|
1740
|
-
if (raw.length > MAX_SNAPSHOT_CHARS) return;
|
|
1741
|
-
let parsed;
|
|
1742
|
-
try {
|
|
1743
|
-
parsed = JSON.parse(raw);
|
|
1744
|
-
} catch {
|
|
1745
|
-
return;
|
|
1746
|
-
}
|
|
1747
|
-
if (exceedsMaxDepth(parsed, 1)) return;
|
|
1748
|
-
if (!isObject(parsed) || Array.isArray(parsed)) return;
|
|
1749
|
-
stripUnsafeKeys(parsed);
|
|
1750
|
-
return parsed;
|
|
1751
|
-
};
|
|
1752
|
-
const encodeSnapshot = (values) => JSON.stringify({ v: values });
|
|
1753
|
-
const decodeSnapshot = (raw) => {
|
|
1754
|
-
const values = safeParseSnapshot(raw)?.v;
|
|
1755
|
-
return Array.isArray(values) ? values : void 0;
|
|
1756
|
-
};
|
|
1757
|
-
|
|
1758
|
-
//#endregion
|
|
1759
|
-
//#region src/ssr-dom.ts
|
|
1760
|
-
const VOID = /* @__PURE__ */ new Set([
|
|
1761
|
-
"area",
|
|
1762
|
-
"base",
|
|
1763
|
-
"br",
|
|
1764
|
-
"col",
|
|
1765
|
-
"embed",
|
|
1766
|
-
"hr",
|
|
1767
|
-
"img",
|
|
1768
|
-
"input",
|
|
1769
|
-
"link",
|
|
1770
|
-
"meta",
|
|
1771
|
-
"param",
|
|
1772
|
-
"source",
|
|
1773
|
-
"track",
|
|
1774
|
-
"wbr"
|
|
1775
|
-
]);
|
|
1776
|
-
/** Tags whose children are raw text — do not HTML-escape content. */
|
|
1777
|
-
const RAW_TEXT = /* @__PURE__ */ new Set(["script", "style"]);
|
|
1778
|
-
const escapeText = (s) => s.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
1779
|
-
const escapeAttr = (s) => escapeText(s).replaceAll("\"", """);
|
|
1780
|
-
const createSsrRaw = (html) => ({
|
|
1781
|
-
html,
|
|
1782
|
-
kind: "raw"
|
|
1783
|
-
});
|
|
1784
|
-
const createSsrText = (text) => ({
|
|
1785
|
-
kind: "text",
|
|
1786
|
-
text
|
|
1787
|
-
});
|
|
1788
|
-
const serializeRawText = (tag, text) => {
|
|
1789
|
-
if (new RegExp(`</${tag}\\b`, "iu").test(text)) throw new Error(`ilha: unsafe raw text in <${tag}> (contains "</${tag}")`);
|
|
1790
|
-
return text;
|
|
1791
|
-
};
|
|
1792
|
-
const serializeNode = (node) => {
|
|
1793
|
-
if (node.kind === "text") return escapeText(node.text);
|
|
1794
|
-
if (node.kind === "raw") return node.html;
|
|
1795
|
-
const parts = [];
|
|
1796
|
-
for (const [name, value] of node.attrs) parts.push(`${name}="${escapeAttr(value)}"`);
|
|
1797
|
-
const attr = parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
1798
|
-
const { tag } = node;
|
|
1799
|
-
if (VOID.has(tag)) return `<${tag}${attr}>`;
|
|
1800
|
-
if (RAW_TEXT.has(tag)) return `<${tag}${attr}>${serializeRawText(tag, node.textContent)}</${tag}>`;
|
|
1801
|
-
return `<${tag}${attr}>${node.children.map(serializeNode).join("")}</${tag}>`;
|
|
1802
|
-
};
|
|
1803
|
-
const toDataAttr = (key) => `data-${key.replaceAll(/[A-Z]/gu, (ch) => `-${ch.toLowerCase()}`)}`;
|
|
1804
|
-
const isSymbolKey = (value) => Object.prototype.toString.call(value) === "[object Symbol]";
|
|
1805
|
-
const createSsrElement = (tag) => {
|
|
1806
|
-
const lower = tag.toLowerCase();
|
|
1807
|
-
const children = [];
|
|
1808
|
-
const el = {
|
|
1809
|
-
append: (...nodes) => {
|
|
1810
|
-
children.push(...nodes);
|
|
1811
|
-
},
|
|
1812
|
-
appendChild: (node) => {
|
|
1813
|
-
children.push(node);
|
|
1814
|
-
},
|
|
1815
|
-
attrs: /* @__PURE__ */ new Map(),
|
|
1816
|
-
children,
|
|
1817
|
-
dataset: new Proxy({}, {
|
|
1818
|
-
get: (_t, prop) => {
|
|
1819
|
-
if (prop === "undefined" || isSymbolKey(prop)) return;
|
|
1820
|
-
return el.getAttribute(toDataAttr(prop)) ?? void 0;
|
|
1821
|
-
},
|
|
1822
|
-
set: (_t, prop, value) => {
|
|
1823
|
-
if (isSymbolKey(prop)) return false;
|
|
1824
|
-
const attr = toDataAttr(prop);
|
|
1825
|
-
if (value === void 0 || value === null) el.removeAttribute(attr);
|
|
1826
|
-
else el.setAttribute(attr, String(value));
|
|
1827
|
-
return true;
|
|
1828
|
-
}
|
|
1829
|
-
}),
|
|
1830
|
-
getAttribute: (name) => {
|
|
1831
|
-
const value = el.attrs.get(name);
|
|
1832
|
-
return value === void 0 ? null : value;
|
|
1833
|
-
},
|
|
1834
|
-
hasAttribute: (name) => el.attrs.has(name),
|
|
1835
|
-
isConnected: true,
|
|
1836
|
-
kind: "element",
|
|
1837
|
-
localName: lower,
|
|
1838
|
-
removeAttribute: (name) => {
|
|
1839
|
-
el.attrs.delete(name);
|
|
1840
|
-
},
|
|
1841
|
-
replaceChildren: (...nodes) => {
|
|
1842
|
-
children.length = 0;
|
|
1843
|
-
children.push(...nodes);
|
|
1844
|
-
},
|
|
1845
|
-
setAttribute: (name, value) => {
|
|
1846
|
-
el.attrs.set(name, value);
|
|
1847
|
-
},
|
|
1848
|
-
tag: lower,
|
|
1849
|
-
tagName: lower.toUpperCase(),
|
|
1850
|
-
get textContent() {
|
|
1851
|
-
return children.map((n) => {
|
|
1852
|
-
if (n.kind === "text") return n.text;
|
|
1853
|
-
if (n.kind === "raw") return n.html;
|
|
1854
|
-
return n.textContent;
|
|
1855
|
-
}).join("");
|
|
1856
|
-
},
|
|
1857
|
-
set textContent(value) {
|
|
1858
|
-
children.length = 0;
|
|
1859
|
-
children.push(createSsrText(value));
|
|
1860
|
-
}
|
|
1861
|
-
};
|
|
1862
|
-
return el;
|
|
1863
|
-
};
|
|
1864
|
-
const createSsrRoot = () => {
|
|
1865
|
-
const children = [];
|
|
1866
|
-
return {
|
|
1867
|
-
append: (...nodes) => {
|
|
1868
|
-
children.push(...nodes);
|
|
1869
|
-
},
|
|
1870
|
-
appendChild: (node) => {
|
|
1871
|
-
children.push(node);
|
|
1872
|
-
},
|
|
1873
|
-
children,
|
|
1874
|
-
get innerHTML() {
|
|
1875
|
-
return children.map(serializeNode).join("");
|
|
1876
|
-
},
|
|
1877
|
-
kind: "root",
|
|
1878
|
-
replaceChildren: () => {
|
|
1879
|
-
children.length = 0;
|
|
1880
|
-
}
|
|
1881
|
-
};
|
|
1882
|
-
};
|
|
1883
|
-
|
|
1884
|
-
//#endregion
|
|
1885
|
-
//#region src/ssr-paint.ts
|
|
1886
|
-
const ssrAs = (n) => n;
|
|
1887
|
-
const ACTION_CALL = Symbol.for("ilha.actionCall");
|
|
1888
|
-
const defer$1 = () => {
|
|
1889
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
1890
|
-
return {
|
|
1891
|
-
promise,
|
|
1892
|
-
resolve: () => {
|
|
1893
|
-
resolve(null);
|
|
1894
|
-
}
|
|
1895
|
-
};
|
|
1896
|
-
};
|
|
1897
|
-
const bindSsrEvents = (el, props, fiber) => {
|
|
1898
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1899
|
-
for (const key of Object.keys(props)) {
|
|
1900
|
-
const type = eventTypeFromProp(key);
|
|
1901
|
-
if (!type || seen.has(type)) continue;
|
|
1902
|
-
seen.add(type);
|
|
1903
|
-
const fn = props[key];
|
|
1904
|
-
if (!isFunction(fn)) continue;
|
|
1905
|
-
const branded = fn[ACTION_CALL];
|
|
1906
|
-
const rec = branded?.k ? {
|
|
1907
|
-
a: branded.a ?? [],
|
|
1908
|
-
k: branded.k
|
|
1909
|
-
} : void 0;
|
|
1910
|
-
if (!rec) continue;
|
|
1911
|
-
const id = `${type}:${fiber.runtime.ssrEventI}`;
|
|
1912
|
-
fiber.runtime.ssrEventI += 1;
|
|
1913
|
-
fiber.runtime.ssrActions[id] = rec;
|
|
1914
|
-
const existing = el.dataset.ilhaOn;
|
|
1915
|
-
el.dataset.ilhaOn = existing ? `${existing},${id}` : id;
|
|
1916
|
-
}
|
|
1917
|
-
};
|
|
1918
|
-
const ssrOps = {
|
|
1919
|
-
appendRoot: (root, node) => ssrAs(root).append(node),
|
|
1920
|
-
asElement: (el) => ssrAs(el),
|
|
1921
|
-
asNode: (host) => ssrAs(host),
|
|
1922
|
-
asRoot: (el) => ssrAs(el),
|
|
1923
|
-
bindEvents: bindSsrEvents,
|
|
1924
|
-
clearRoot: (root) => ssrAs(root).replaceChildren(),
|
|
1925
|
-
committed: (el) => el,
|
|
1926
|
-
createElement: createSsrElement,
|
|
1927
|
-
createRaw: (html, _parent) => [createSsrRaw(html)],
|
|
1928
|
-
createSlotHost: (slotId) => {
|
|
1929
|
-
const host = createSsrElement("span");
|
|
1930
|
-
if (slotId !== null) host.setAttribute(SLOT_ATTR, slotId);
|
|
1931
|
-
host.setAttribute("style", "display:contents");
|
|
1932
|
-
return host;
|
|
1933
|
-
},
|
|
1934
|
-
createText: createSsrText,
|
|
1935
|
-
disconnect: (el) => {
|
|
1936
|
-
el.isConnected = false;
|
|
1937
|
-
},
|
|
1938
|
-
placeChildren: (root, nodes) => {
|
|
1939
|
-
const host = ssrAs(root);
|
|
1940
|
-
host.replaceChildren();
|
|
1941
|
-
for (const n of nodes) host.append(n);
|
|
1942
|
-
},
|
|
1943
|
-
reuseNode: (host) => ssrAs(host),
|
|
1944
|
-
setFormControl: (el, key, v) => {
|
|
1945
|
-
if (key === "value") el.setAttribute("value", String(v ?? ""));
|
|
1946
|
-
else if (v) el.setAttribute(key, "");
|
|
1947
|
-
else el.removeAttribute(key);
|
|
1948
|
-
},
|
|
1949
|
-
setStyle: (el, css) => el.setAttribute("style", css)
|
|
1950
|
-
};
|
|
1951
|
-
const core = createPainter(ssrOps);
|
|
1952
|
-
const paint = (fiber, view) => {
|
|
1953
|
-
fiber.islandFrame ??= {
|
|
1954
|
-
i: 0,
|
|
1955
|
-
slots: []
|
|
1956
|
-
};
|
|
1957
|
-
core.disposeHoles(fiber);
|
|
1958
|
-
ssrOps.clearRoot(fiber.root);
|
|
1959
|
-
core.insert(fiber, core.materialize(view, fiber));
|
|
1960
|
-
};
|
|
1961
|
-
const paintError = (fiber, e) => {
|
|
1962
|
-
console.error(e);
|
|
1963
|
-
paint(fiber, errorView(e));
|
|
1964
|
-
};
|
|
1965
|
-
const attachSsr = (fn, opts) => {
|
|
1966
|
-
const root = createSsrRoot();
|
|
1967
|
-
const runtime = makeRuntime({
|
|
1968
|
-
ssr: true,
|
|
1969
|
-
ssrCapture: opts?.ssrCapture === true
|
|
1970
|
-
});
|
|
1971
|
-
const { promise: ready, resolve } = defer$1();
|
|
1972
|
-
const fiber = makeFiber(runtime, ssrAs(root), paint, { onFail: (e) => {
|
|
1973
|
-
opts?.onError?.(e);
|
|
1974
|
-
paintError(fiber, e);
|
|
1975
|
-
resolve();
|
|
1976
|
-
} });
|
|
1977
|
-
runtime.begin();
|
|
1978
|
-
runtime.setIdle(resolve);
|
|
1979
|
-
runSetup(fiber, fn);
|
|
1980
|
-
runtime.end();
|
|
1981
|
-
return {
|
|
1982
|
-
ready,
|
|
1983
|
-
root,
|
|
1984
|
-
runtime,
|
|
1985
|
-
unmount: () => {
|
|
1986
|
-
closeFiber(fiber);
|
|
1987
|
-
runtime.close();
|
|
1988
|
-
root.replaceChildren();
|
|
1989
|
-
}
|
|
1990
|
-
};
|
|
1991
|
-
};
|
|
1992
|
-
|
|
1993
|
-
//#endregion
|
|
1994
|
-
//#region src/mount.ts
|
|
1995
|
-
const defer = () => {
|
|
1996
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
1997
|
-
return {
|
|
1998
|
-
promise,
|
|
1999
|
-
resolve: () => {
|
|
2000
|
-
resolve(null);
|
|
2001
|
-
}
|
|
2002
|
-
};
|
|
2003
|
-
};
|
|
2004
|
-
const readHydrate = (el) => {
|
|
2005
|
-
const raw = (el.matches("[data-ilha]") ? el : el.querySelector("[data-ilha]"))?.dataset.ilhaState;
|
|
2006
|
-
if (raw) return decodeSnapshot(raw);
|
|
2007
|
-
const first = el.firstElementChild;
|
|
2008
|
-
if (first?.tagName === "TEMPLATE" && first.matches("[data-ilha-state]")) {
|
|
2009
|
-
const tplRaw = first.dataset.ilhaState;
|
|
2010
|
-
first.remove();
|
|
2011
|
-
return tplRaw ? decodeSnapshot(tplRaw) : void 0;
|
|
2012
|
-
}
|
|
2013
|
-
};
|
|
2014
|
-
const delay = (ms) => {
|
|
2015
|
-
const { promise, resolve } = defer();
|
|
2016
|
-
setTimeout(resolve, ms);
|
|
2017
|
-
return promise;
|
|
2018
|
-
};
|
|
2019
|
-
const attach = (el, fn, opts) => {
|
|
2020
|
-
if (!opts?.hydrate) el.innerHTML = "";
|
|
2021
|
-
const runtime = makeRuntime({ hydrate: opts?.hydrate ? readHydrate(el) : void 0 });
|
|
2022
|
-
const { promise: ready, resolve } = defer();
|
|
2023
|
-
const fiber = makeFiber(runtime, el, paint$1, { onFail: (e) => {
|
|
2024
|
-
opts?.onError?.(e);
|
|
2025
|
-
paintError$1(fiber, e);
|
|
2026
|
-
resolve();
|
|
2027
|
-
} });
|
|
2028
|
-
if (opts?.hydrate) fiber.hydrate = true;
|
|
2029
|
-
runtime.begin();
|
|
2030
|
-
runtime.setIdle(resolve);
|
|
2031
|
-
runSetup(fiber, fn);
|
|
2032
|
-
runtime.end();
|
|
2033
|
-
return {
|
|
2034
|
-
ready,
|
|
2035
|
-
runtime,
|
|
2036
|
-
unmount: () => {
|
|
2037
|
-
closeFiber(fiber);
|
|
2038
|
-
runtime.close();
|
|
2039
|
-
if (!opts?.hydrate) el.innerHTML = "";
|
|
2040
|
-
}
|
|
2041
|
-
};
|
|
2042
|
-
};
|
|
2043
|
-
const mount = (el, fn, opts) => attach(el, fn, opts).unmount;
|
|
2044
|
-
const renderToString = async (fn, opts) => {
|
|
2045
|
-
const snapshot = opts?.snapshot !== false;
|
|
2046
|
-
const markers = opts?.markers !== false;
|
|
2047
|
-
const { unmount, ready, runtime, root } = attachSsr(fn, { ssrCapture: opts?.captureActions === true });
|
|
2048
|
-
const timeout = opts?.timeout;
|
|
2049
|
-
await (timeout === void 0 ? ready : Promise.race([ready, delay(timeout)]));
|
|
2050
|
-
let inner = root.innerHTML;
|
|
2051
|
-
const actions = runtime.ssrActions;
|
|
2052
|
-
if (Object.keys(actions).length > 0) inner = `<template data-ilha-actions="${escapeAttr(JSON.stringify(actions))}"></template>${inner}`;
|
|
2053
|
-
const snap = snapshot ? encodeSnapshot(runtime.ssrValues) : void 0;
|
|
2054
|
-
unmount();
|
|
2055
|
-
if (!markers) return snap ? `<template data-ilha-state="${escapeAttr(snap)}"></template>${inner}` : inner;
|
|
2056
|
-
return `<div data-ilha${snap ? ` data-ilha-state="${escapeAttr(snap)}"` : ""}>${inner}</div>`;
|
|
2057
|
-
};
|
|
2058
|
-
|
|
2059
|
-
//#endregion
|
|
2060
|
-
export { makeFiber as _, interpret as a, handleOwner as c, structuralEqual as d, untrack as f, getFiber as g, closeFiber as h, runSetup as i, instr as l, clearFiberView as m, renderToString as n, atom as o, wrapHandle as p, unsafe as r, batch as s, mount as t, isAtomHandle as u };
|
|
1659
|
+
export { makeFiber as C, getFiber as S, makeRuntime as T, structuralEqual as _, morphInner as a, clearFiberView as b, bindEvents as c, interpret as d, atom as f, isAtomHandle as g, instr as h, insertRendered as i, eventTypeFromProp as l, handleOwner as m, unsafe as n, placeChildren as o, batch as p, committedElement as r, standInFor as s, createPainter as t, runSetup as u, untrack as v, makeRootFiber as w, closeFiber as x, wrapHandle as y };
|