solid-js 1.2.5 → 1.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { sharedConfig, awaitSuspense, splitProps } from 'solid-js';
1
+ import { sharedConfig, splitProps } from 'solid-js';
2
2
  export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, createComponent, mergeProps } from 'solid-js';
3
3
 
4
4
  const booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"];
@@ -229,111 +229,162 @@ function stringifyString(str) {
229
229
  return result;
230
230
  }
231
231
 
232
+ const REPLACE_SCRIPT = `function $df(e,t){t=document.getElementById(e),document.getElementById("pl"+e).replaceWith(...t.childNodes),_$HY.set(e)}`;
233
+ const SYNC_SCRIPT = `_$HY.sync=!0;for(let e=0;e<_$HY.queue.length;e++)_$HY.queue[e]()`;
232
234
  function renderToString(code, options = {}) {
233
- sharedConfig.context = Object.assign({
235
+ sharedConfig.context = {
234
236
  id: "",
235
237
  count: 0,
236
- assets: []
237
- }, options);
238
+ suspense: {},
239
+ assets: [],
240
+ nonce: options.nonce
241
+ };
238
242
  let html = resolveSSRNode(escape(code()));
239
- return injectAssets(sharedConfig.context.assets, html);
243
+ return injectAssets(sharedConfig.context.assets, html) + `<script${options.nonce ? ` nonce="${options.nonce}"` : ""}>${SYNC_SCRIPT}</script>`;
240
244
  }
241
245
  function renderToStringAsync(code, options = {}) {
242
- options = {
243
- timeoutMs: 30000,
244
- ...options
245
- };
246
- const context = sharedConfig.context = Object.assign({
246
+ const {
247
+ nonce,
248
+ timeoutMs = 30000
249
+ } = options;
250
+ const context = sharedConfig.context = {
247
251
  id: "",
248
252
  count: 0,
249
253
  resources: {},
250
254
  suspense: {},
251
255
  assets: [],
252
- async: true
253
- }, options);
254
- const timeout = new Promise((_, reject) => setTimeout(() => reject("renderToString timed out"), options.timeoutMs));
255
- return Promise.race([awaitSuspense(() => escape(code())), timeout]).then(res => {
256
+ async: true,
257
+ nonce
258
+ };
259
+ let scripts = "";
260
+ sharedConfig.context.writeResource = (id, p) => p.then(d => scripts += `_$HY.set("${id}", ${devalue(d)});`);
261
+ const timeout = new Promise((_, reject) => setTimeout(() => reject("renderToString timed out"), timeoutMs));
262
+ return Promise.race([asyncWrap(() => escape(code())), timeout]).then(res => {
256
263
  let html = resolveSSRNode(res);
264
+ html += `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts.length ? scripts + ";" : ""}${SYNC_SCRIPT}</script>`;
257
265
  return injectAssets(context.assets, html);
258
266
  });
259
267
  }
260
- function pipeToNodeWritable(code, writable, options = {}) {
268
+ function renderToPipeableStream(code, options) {
261
269
  const {
262
270
  nonce,
263
- onReady = ({
264
- startWriting
265
- }) => startWriting(),
266
- onComplete
271
+ onCompleteShell,
272
+ onCompleteAll
267
273
  } = options;
268
274
  const tmp = [];
269
- let count = 0,
270
- completed = 0,
271
- buffer = {
272
- write(payload) {
273
- tmp.push(payload);
275
+ const tasks = [];
276
+ const registry = new Set();
277
+ const checkEnd = () => {
278
+ if (!registry.size && !completed) {
279
+ onCompleteAll && onCompleteAll(result);
280
+ writable && writable.end();
281
+ completed = true;
274
282
  }
275
283
  };
276
- const result = {
277
- startWriting() {
278
- buffer = writable;
279
- tmp.forEach(chunk => buffer.write(chunk));
280
- setTimeout(checkEnd);
281
- },
282
- write(c) {
283
- writable.write(c);
284
- },
285
- abort() {
286
- completed = count;
287
- checkEnd();
284
+ const writeInitialScript = () => {
285
+ if (tasks.length) {
286
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`);
287
+ tasks.length = 0;
288
288
  }
289
+ scheduled = false;
289
290
  };
290
- const checkEnd = () => {
291
- if (completed === count) {
292
- onComplete && onComplete(result);
293
- writable.end();
291
+ let writable;
292
+ let completed = false;
293
+ let scriptFlushed = false;
294
+ let scheduled = true;
295
+ let buffer = {
296
+ write(payload) {
297
+ tmp.push(payload);
294
298
  }
295
299
  };
296
- sharedConfig.context = Object.assign({
300
+ sharedConfig.context = {
297
301
  id: "",
298
302
  count: 0,
303
+ async: true,
299
304
  streaming: true,
305
+ resources: {},
300
306
  suspense: {},
301
- assets: []
302
- }, options);
303
- sharedConfig.context.writeResource = (id, p) => {
304
- count++;
305
- Promise.resolve().then(() => buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.startResource("${id}")</script>`));
306
- p.then(d => {
307
- buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.resolveResource("${id}", ${devalue(d)})</script>`);
308
- ++completed && checkEnd();
309
- });
307
+ assets: [],
308
+ nonce,
309
+ writeResource(id, p) {
310
+ if (!scheduled) {
311
+ Promise.resolve().then(writeInitialScript);
312
+ scheduled = true;
313
+ }
314
+ tasks.push(`_$HY.init("${id}")`);
315
+ p.then(d => {
316
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HY.set("${id}", ${devalue(d)})</script>`);
317
+ });
318
+ },
319
+ registerFragment(key) {
320
+ registry.add(key);
321
+ Promise.resolve().then(() => {
322
+ if (registry.has(key)) {
323
+ if (!scheduled) {
324
+ Promise.resolve().then(writeInitialScript);
325
+ scheduled = true;
326
+ }
327
+ tasks.push(`_$HY.init("${key}")`);
328
+ }
329
+ });
330
+ return value => {
331
+ registry.delete(key);
332
+ if (!value) return;
333
+ Promise.resolve().then(() => {
334
+ buffer.write(`<div hidden id="${key}">${value}</div><script${nonce ? ` nonce="${nonce}"` : ""}>${!scriptFlushed ? REPLACE_SCRIPT : ""}$df("${key}")</script>`);
335
+ scriptFlushed = true;
336
+ checkEnd();
337
+ });
338
+ };
339
+ }
310
340
  };
311
341
  let html = resolveSSRNode(escape(code()));
312
342
  html = injectAssets(sharedConfig.context.assets, html);
313
343
  buffer.write(html);
314
- onReady(result);
344
+ Promise.resolve().then(() => {
345
+ writeInitialScript();
346
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${SYNC_SCRIPT}</script>`);
347
+ onCompleteShell && onCompleteShell();
348
+ });
349
+ return {
350
+ pipe(w) {
351
+ buffer = writable = w;
352
+ tmp.forEach(chunk => buffer.write(chunk));
353
+ if (completed) writable.end();else setTimeout(checkEnd);
354
+ }
355
+ };
315
356
  }
316
357
  function pipeToWritable(code, writable, options = {}) {
317
358
  const {
318
359
  nonce,
319
- onReady = ({
360
+ onCompleteShell = ({
320
361
  startWriting
321
362
  }) => startWriting(),
322
- onComplete
363
+ onCompleteAll
323
364
  } = options;
324
365
  const tmp = [];
366
+ const tasks = [];
325
367
  const writer = writable.getWriter();
326
368
  const encoder = new TextEncoder();
327
- sharedConfig.context = Object.assign({
328
- id: "",
329
- count: 0,
330
- streaming: true,
331
- suspense: {},
332
- assets: []
333
- }, options);
334
- let count = 0,
335
- completed = 0,
336
- buffer = {
369
+ const registry = new Set();
370
+ const checkEnd = () => {
371
+ if (!registry.size && !completed) {
372
+ onCompleteAll && onCompleteAll(result);
373
+ writable && writable.close();
374
+ completed = true;
375
+ }
376
+ };
377
+ const writeInitialScript = () => {
378
+ if (tasks.length) {
379
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`));
380
+ tasks.length = 0;
381
+ }
382
+ scheduled = false;
383
+ };
384
+ let completed = false;
385
+ let scriptFlushed = false;
386
+ let scheduled = true;
387
+ let buffer = {
337
388
  write(payload) {
338
389
  tmp.push(payload);
339
390
  }
@@ -348,28 +399,62 @@ function pipeToWritable(code, writable, options = {}) {
348
399
  writer.write(encoder.encode(c));
349
400
  },
350
401
  abort() {
351
- completed = count;
402
+ registry.clear();
352
403
  checkEnd();
353
404
  }
354
405
  };
355
- const checkEnd = () => {
356
- if (completed === count) {
357
- onComplete && onComplete(result);
358
- writable.close();
406
+ sharedConfig.context = {
407
+ id: "",
408
+ count: 0,
409
+ async: true,
410
+ streaming: true,
411
+ resources: {},
412
+ suspense: {},
413
+ assets: [],
414
+ nonce,
415
+ writeResource(id, p) {
416
+ if (!scheduled) {
417
+ Promise.resolve().then(writeInitialScript);
418
+ scheduled = true;
419
+ }
420
+ tasks.push(`_$HY.init("${id}")`);
421
+ p.then(d => {
422
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HY.set("${id}", ${devalue(d)})</script>`));
423
+ });
424
+ },
425
+ registerFragment(key) {
426
+ registry.add(key);
427
+ Promise.resolve().then(() => {
428
+ if (registry.has(key)) {
429
+ if (!scheduled) {
430
+ Promise.resolve().then(writeInitialScript);
431
+ scheduled = true;
432
+ }
433
+ tasks.push(`_$HY.init("${key}")`);
434
+ }
435
+ });
436
+ return value => {
437
+ registry.delete(key);
438
+ if (!value) return;
439
+ Promise.resolve().then(() => {
440
+ buffer.write(encoder.encode(`<div hidden id="${key}">${value}</div><script${nonce ? ` nonce="${nonce}"` : ""}>${!scriptFlushed ? REPLACE_SCRIPT : ""}$df("${key}")</script>`));
441
+ scriptFlushed = true;
442
+ checkEnd();
443
+ });
444
+ };
359
445
  }
360
446
  };
361
- sharedConfig.context.writeResource = (id, p) => {
362
- count++;
363
- Promise.resolve().then(() => buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.startResource("${id}")</script>`)));
364
- p.then(d => {
365
- buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>_$HYDRATION.resolveResource("${id}", ${devalue(d)})</script>`));
366
- ++completed && checkEnd();
367
- });
368
- };
369
447
  let html = resolveSSRNode(escape(code()));
370
448
  html = injectAssets(sharedConfig.context.assets, html);
371
449
  buffer.write(encoder.encode(html));
372
- onReady(result);
450
+ Promise.resolve().then(() => {
451
+ writeInitialScript();
452
+ buffer.write(encoder.encode(`<script${nonce ? ` nonce="${nonce}"` : ""}>${SYNC_SCRIPT}</script>`));
453
+ onCompleteShell && onCompleteShell(result);
454
+ });
455
+ }
456
+ function pipeToNodeWritable(code, writable, options = {}) {
457
+ renderToPipeableStream(code, options).pipe(writable);
373
458
  }
374
459
  function Assets(props) {
375
460
  sharedConfig.context.assets.push(() => NoHydration({
@@ -379,15 +464,21 @@ function Assets(props) {
379
464
  }));
380
465
  return ssr(`%%$${sharedConfig.context.assets.length - 1}%%`);
381
466
  }
382
- function HydrationScript() {
383
- sharedConfig.context.assets.push(generateHydrationScript);
467
+ function HydrationScript(props) {
468
+ const {
469
+ nonce
470
+ } = sharedConfig.context;
471
+ sharedConfig.context.assets.push(() => generateHydrationScript({
472
+ nonce,
473
+ ...props
474
+ }));
384
475
  return ssr(`%%$${sharedConfig.context.assets.length - 1}%%`);
385
476
  }
386
477
  function NoHydration(props) {
387
478
  const c = sharedConfig.context;
388
- delete sharedConfig.context;
479
+ c.noHydrate = true;
389
480
  const children = props.children;
390
- sharedConfig.context = c;
481
+ c.noHydrate = false;
391
482
  return children;
392
483
  }
393
484
  function ssr(t, ...nodes) {
@@ -515,26 +606,13 @@ function resolveSSRNode(node) {
515
606
  }
516
607
  function getHydrationKey() {
517
608
  const hydrate = sharedConfig.context;
518
- return hydrate && `${hydrate.id}${hydrate.count++}`;
609
+ return hydrate && !hydrate.noHydrate && `${hydrate.id}${hydrate.count++}`;
519
610
  }
520
- function generateHydrationScript() {
521
- const {
522
- nonce,
523
- streaming,
524
- resources,
525
- eventNames = ["click", "input"]
526
- } = sharedConfig.context;
527
- let s = `<script${nonce ? ` nonce="${nonce}"` : ""}>(()=>{_$HYDRATION={events:[],completed:new WeakSet};const t=e=>e&&e.hasAttribute&&(e.hasAttribute("data-hk")?e:t(e.host&&e.host instanceof Node?e.host:e.parentNode)),e=e=>{let o=e.composedPath&&e.composedPath()[0]||e.target,s=t(o);s&&!_$HYDRATION.completed.has(s)&&_$HYDRATION.events.push([s,e])};["${eventNames.join('","')}"].forEach(t=>document.addEventListener(t,e))})();`;
528
- if (streaming) {
529
- s += `(()=>{const e=_$HYDRATION,o={};e.startResource=e=>{let r;o[e]=[new Promise(e=>r=e),r]},e.resolveResource=(e,r)=>{const n=o[e];if(!n)return o[e]=[r];n[1](r)},e.loadResource=e=>{const r=o[e];if(r)return r[0]}})();`;
530
- }
531
- if (resources) {
532
- s += `_$HYDRATION.resources = ${devalue(Object.keys(resources).reduce((r, k) => {
533
- r[k] = resources[k].data;
534
- return r;
535
- }, {}))};`;
536
- }
537
- return s + `</script>`;
611
+ function generateHydrationScript({
612
+ eventNames = ["click", "input"],
613
+ nonce
614
+ }) {
615
+ return `<script${nonce ? ` nonce="${nonce}"` : ""}>((e,t,o={})=>{t=e=>e&&e.hasAttribute&&(e.hasAttribute("data-hk")?e:t(e.host&&e.host instanceof Node?e.host:e.parentNode)),["${eventNames.join('","')}"].forEach((o=>document.addEventListener(o,(o=>{let n=o.composedPath&&o.composedPath()[0]||o.target,s=t(n);s&&!e.completed.has(s)&&e.events.push([s,o])})))),e.init=(e,t)=>{o[e]=[new Promise((e=>t=e)),t]},e.set=(e,t,n)=>{if(!(n=o[e]))return o[e]=[t];n[1](t)},e.load=(e,t)=>{if(t=o[e])return t[0]}})(window._$HY||(_$HY={events:[],completed:new WeakSet,queue:[]}));</script>`;
538
616
  }
539
617
  function injectAssets(assets, html) {
540
618
  for (let i = 0; i < assets.length; i++) {
@@ -542,6 +620,33 @@ function injectAssets(assets, html) {
542
620
  }
543
621
  return html;
544
622
  }
623
+ const FRAGMENT_REPLACE = /<!\[([\d.]+)\]>/;
624
+ function asyncWrap(fn) {
625
+ return new Promise(resolve => {
626
+ const registry = new Set();
627
+ const cache = Object.create(null);
628
+ sharedConfig.context.registerFragment = register;
629
+ const rendered = fn();
630
+ if (!registry.size) resolve(rendered);
631
+ function register(key) {
632
+ registry.add(key);
633
+ return value => {
634
+ if (value) cache[key] = value;
635
+ registry.delete(key);
636
+ if (!registry.size) Promise.resolve().then(() => {
637
+ let source = resolveSSRNode(rendered);
638
+ let final = "";
639
+ let match;
640
+ while (match = source.match(FRAGMENT_REPLACE)) {
641
+ final += source.substring(0, match.index);
642
+ source = cache[match[1]] + source.substring(match.index + match[0].length);
643
+ }
644
+ resolve(final + source);
645
+ });
646
+ };
647
+ }
648
+ });
649
+ }
545
650
 
546
651
  const isServer = true;
547
652
  function spread() {}
@@ -560,4 +665,4 @@ function Portal(props) {
560
665
  return "";
561
666
  }
562
667
 
563
- export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle };
668
+ export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToPipeableStream, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle };
package/web/dist/web.cjs CHANGED
@@ -218,27 +218,25 @@ function assign(node, props, isSVG, skipChildren, prevProps = {}) {
218
218
  }
219
219
  }
220
220
  function hydrate(code, element) {
221
- solidJs.sharedConfig.resources = globalThis._$HYDRATION.resources;
222
- solidJs.sharedConfig.completed = globalThis._$HYDRATION.completed;
223
- solidJs.sharedConfig.events = globalThis._$HYDRATION.events;
221
+ if (!globalThis._$HY.sync) {
222
+ let dispose;
223
+ globalThis._$HY.queue.push(() => dispose = hydrate(code, element));
224
+ return () => dispose();
225
+ }
226
+ solidJs.sharedConfig.completed = globalThis._$HY.completed;
227
+ solidJs.sharedConfig.events = globalThis._$HY.events;
228
+ solidJs.sharedConfig.load = globalThis._$HY.load;
229
+ solidJs.sharedConfig.gather = root => gatherHydratable(element, root);
230
+ solidJs.sharedConfig.registry = new Map();
224
231
  solidJs.sharedConfig.context = {
225
232
  id: "",
226
- count: 0,
227
- loadResource: globalThis._$HYDRATION.loadResource
233
+ count: 0
228
234
  };
229
- solidJs.sharedConfig.registry = new Map();
230
235
  gatherHydratable(element);
231
236
  const dispose = render(code, element, [...element.childNodes]);
232
237
  solidJs.sharedConfig.context = null;
233
238
  return dispose;
234
239
  }
235
- function gatherHydratable(element) {
236
- const templates = element.querySelectorAll(`*[data-hk]`);
237
- for (let i = 0; i < templates.length; i++) {
238
- const node = templates[i];
239
- solidJs.sharedConfig.registry.set(node.getAttribute("data-hk"), node);
240
- }
241
- }
242
240
  function getNextElement(template) {
243
241
  let node, key;
244
242
  if (!solidJs.sharedConfig.context || !(node = solidJs.sharedConfig.registry.get(key = getHydrationKey()))) {
@@ -332,7 +330,7 @@ function eventHandler(e) {
332
330
  Object.defineProperty(e, "currentTarget", {
333
331
  configurable: true,
334
332
  get() {
335
- return node;
333
+ return node || document;
336
334
  }
337
335
  });
338
336
  while (node !== null) {
@@ -387,7 +385,12 @@ function insertExpression(parent, value, current, marker, unwrapArray) {
387
385
  solidJs.createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
388
386
  return () => current;
389
387
  }
390
- if (solidJs.sharedConfig.context && current && current.length) return current;
388
+ if (solidJs.sharedConfig.context && current && current.length) {
389
+ for (let i; i < array.length; i++) {
390
+ if (array[i].parentNode) return array;
391
+ }
392
+ return current;
393
+ }
391
394
  if (array.length === 0) {
392
395
  current = cleanChildren(parent, current, marker);
393
396
  if (multi) return current;
@@ -455,6 +458,14 @@ function cleanChildren(parent, current, marker, replacement) {
455
458
  } else parent.insertBefore(node, marker);
456
459
  return [node];
457
460
  }
461
+ function gatherHydratable(element, root) {
462
+ const templates = element.querySelectorAll(`*[data-hk]`);
463
+ for (let i = 0; i < templates.length; i++) {
464
+ const node = templates[i];
465
+ const key = node.getAttribute("data-hk");
466
+ if (!root || key.startsWith(root)) solidJs.sharedConfig.registry.set(key, node);
467
+ }
468
+ }
458
469
  function getHydrationKey() {
459
470
  const hydrate = solidJs.sharedConfig.context;
460
471
  return `${hydrate.id}${hydrate.count++}`;
@@ -629,7 +640,6 @@ exports.clearDelegatedEvents = clearDelegatedEvents;
629
640
  exports.delegateEvents = delegateEvents;
630
641
  exports.dynamicProperty = dynamicProperty;
631
642
  exports.escape = escape;
632
- exports.gatherHydratable = gatherHydratable;
633
643
  exports.generateHydrationScript = generateHydrationScript;
634
644
  exports.getHydrationKey = getHydrationKey;
635
645
  exports.getNextElement = getNextElement;
package/web/dist/web.js CHANGED
@@ -215,27 +215,25 @@ function assign(node, props, isSVG, skipChildren, prevProps = {}) {
215
215
  }
216
216
  }
217
217
  function hydrate(code, element) {
218
- sharedConfig.resources = globalThis._$HYDRATION.resources;
219
- sharedConfig.completed = globalThis._$HYDRATION.completed;
220
- sharedConfig.events = globalThis._$HYDRATION.events;
218
+ if (!globalThis._$HY.sync) {
219
+ let dispose;
220
+ globalThis._$HY.queue.push(() => dispose = hydrate(code, element));
221
+ return () => dispose();
222
+ }
223
+ sharedConfig.completed = globalThis._$HY.completed;
224
+ sharedConfig.events = globalThis._$HY.events;
225
+ sharedConfig.load = globalThis._$HY.load;
226
+ sharedConfig.gather = root => gatherHydratable(element, root);
227
+ sharedConfig.registry = new Map();
221
228
  sharedConfig.context = {
222
229
  id: "",
223
- count: 0,
224
- loadResource: globalThis._$HYDRATION.loadResource
230
+ count: 0
225
231
  };
226
- sharedConfig.registry = new Map();
227
232
  gatherHydratable(element);
228
233
  const dispose = render(code, element, [...element.childNodes]);
229
234
  sharedConfig.context = null;
230
235
  return dispose;
231
236
  }
232
- function gatherHydratable(element) {
233
- const templates = element.querySelectorAll(`*[data-hk]`);
234
- for (let i = 0; i < templates.length; i++) {
235
- const node = templates[i];
236
- sharedConfig.registry.set(node.getAttribute("data-hk"), node);
237
- }
238
- }
239
237
  function getNextElement(template) {
240
238
  let node, key;
241
239
  if (!sharedConfig.context || !(node = sharedConfig.registry.get(key = getHydrationKey()))) {
@@ -329,7 +327,7 @@ function eventHandler(e) {
329
327
  Object.defineProperty(e, "currentTarget", {
330
328
  configurable: true,
331
329
  get() {
332
- return node;
330
+ return node || document;
333
331
  }
334
332
  });
335
333
  while (node !== null) {
@@ -384,7 +382,12 @@ function insertExpression(parent, value, current, marker, unwrapArray) {
384
382
  createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
385
383
  return () => current;
386
384
  }
387
- if (sharedConfig.context && current && current.length) return current;
385
+ if (sharedConfig.context && current && current.length) {
386
+ for (let i; i < array.length; i++) {
387
+ if (array[i].parentNode) return array;
388
+ }
389
+ return current;
390
+ }
388
391
  if (array.length === 0) {
389
392
  current = cleanChildren(parent, current, marker);
390
393
  if (multi) return current;
@@ -452,6 +455,14 @@ function cleanChildren(parent, current, marker, replacement) {
452
455
  } else parent.insertBefore(node, marker);
453
456
  return [node];
454
457
  }
458
+ function gatherHydratable(element, root) {
459
+ const templates = element.querySelectorAll(`*[data-hk]`);
460
+ for (let i = 0; i < templates.length; i++) {
461
+ const node = templates[i];
462
+ const key = node.getAttribute("data-hk");
463
+ if (!root || key.startsWith(root)) sharedConfig.registry.set(key, node);
464
+ }
465
+ }
455
466
  function getHydrationKey() {
456
467
  const hydrate = sharedConfig.context;
457
468
  return `${hydrate.id}${hydrate.count++}`;
@@ -535,4 +546,4 @@ function Dynamic(props) {
535
546
  });
536
547
  }
537
548
 
538
- export { Aliases, Assets, ChildProperties, DelegatedEvents, Dynamic, Assets as HydrationScript, NoHydration, Portal, PropAliases, Properties, SVGElements, SVGNamespace, addEventListener, assign, classList, clearDelegatedEvents, delegateEvents, dynamicProperty, escape, gatherHydratable, generateHydrationScript, getHydrationKey, getNextElement, getNextMarker, getNextMatch, hydrate, insert, isServer, memo, pipeToNodeWritable, pipeToWritable, render, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle, style, template };
549
+ export { Aliases, Assets, ChildProperties, DelegatedEvents, Dynamic, Assets as HydrationScript, NoHydration, Portal, PropAliases, Properties, SVGElements, SVGNamespace, addEventListener, assign, classList, clearDelegatedEvents, delegateEvents, dynamicProperty, escape, generateHydrationScript, getHydrationKey, getNextElement, getNextMarker, getNextMatch, hydrate, insert, isServer, memo, pipeToNodeWritable, pipeToWritable, render, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, spread, ssr, ssrBoolean, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle, style, template };
@@ -46,7 +46,6 @@ export function mergeProps(...sources: unknown[]): unknown;
46
46
  export function dynamicProperty(props: unknown, key: string): unknown;
47
47
 
48
48
  export function hydrate(fn: () => JSX.Element, node: MountableElement): () => void;
49
- export function gatherHydratable(node: Element): void;
50
49
  export function getHydrationKey(): string;
51
50
  export function getNextElement(template?: HTMLTemplateElement): Element;
52
51
  export function getNextMatch(start: Node, elementName: string): Element;
@@ -1,3 +1,3 @@
1
- import { createRoot, createRenderEffect, createComponent, getOwner, sharedConfig, awaitSuspense } from "../..";
1
+ import { createRoot, createRenderEffect, createComponent, getOwner, sharedConfig } from "../..";
2
2
  declare function memo<T>(fn: () => T, equals: boolean): import("../..").Accessor<T>;
3
- export { getOwner, createComponent, createRoot as root, createRenderEffect as effect, memo, sharedConfig, awaitSuspense as asyncWrap };
3
+ export { getOwner, createComponent, createRoot as root, createRenderEffect as effect, memo, sharedConfig };