solid-js 1.4.8 → 1.5.0-beta.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.
Files changed (58) hide show
  1. package/dist/dev.cjs +119 -134
  2. package/dist/dev.js +119 -134
  3. package/dist/server.cjs +98 -49
  4. package/dist/server.js +98 -49
  5. package/dist/solid.cjs +119 -132
  6. package/dist/solid.js +119 -132
  7. package/h/jsx-runtime/types/jsx.d.ts +8 -1401
  8. package/h/types/hyperscript.d.ts +17 -0
  9. package/html/types/lit.d.ts +37 -0
  10. package/package.json +103 -41
  11. package/store/dist/dev.cjs +40 -22
  12. package/store/dist/dev.js +41 -23
  13. package/store/dist/store.cjs +40 -22
  14. package/store/dist/store.js +40 -22
  15. package/store/types/index.d.ts +4 -4
  16. package/store/types/mutable.d.ts +1 -1
  17. package/store/types/server.d.ts +1 -1
  18. package/store/types/store.d.ts +1 -1
  19. package/types/index.d.ts +8 -8
  20. package/types/jsx.d.ts +196 -1580
  21. package/types/reactive/array.d.ts +1 -1
  22. package/types/reactive/observable.d.ts +1 -1
  23. package/types/reactive/signal.d.ts +69 -34
  24. package/types/render/Suspense.d.ts +1 -1
  25. package/types/render/component.d.ts +22 -7
  26. package/types/render/flow.d.ts +2 -2
  27. package/types/render/index.d.ts +4 -4
  28. package/types/server/index.d.ts +3 -3
  29. package/types/server/reactive.d.ts +8 -3
  30. package/types/server/rendering.d.ts +11 -6
  31. package/universal/dist/dev.cjs +0 -0
  32. package/universal/dist/dev.js +0 -0
  33. package/universal/dist/universal.cjs +0 -0
  34. package/universal/dist/universal.js +0 -0
  35. package/universal/types/index.d.ts +1 -1
  36. package/web/dist/dev.cjs +3 -3
  37. package/web/dist/dev.js +3 -3
  38. package/web/dist/server.cjs +66 -90
  39. package/web/dist/server.js +66 -90
  40. package/web/dist/web.cjs +3 -3
  41. package/web/dist/web.js +3 -3
  42. package/web/types/client.d.ts +1 -1
  43. package/web/types/core.d.ts +3 -3
  44. package/web/types/index.d.ts +8 -9
  45. package/web/types/jsx.d.ts +1 -1
  46. package/web/types/server-mock.d.ts +4 -2
  47. package/web/types/server.d.ts +70 -0
  48. package/h/README.md +0 -99
  49. package/h/jsx-runtime/package.json +0 -8
  50. package/h/package.json +0 -8
  51. package/html/README.md +0 -84
  52. package/html/package.json +0 -8
  53. package/store/README.md +0 -23
  54. package/store/package.json +0 -35
  55. package/universal/README.md +0 -102
  56. package/universal/package.json +0 -18
  57. package/web/README.md +0 -7
  58. package/web/package.json +0 -35
@@ -7,6 +7,7 @@ var solidJs = require('solid-js');
7
7
  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"];
8
8
  const BooleanAttributes = /*#__PURE__*/new Set(booleans);
9
9
  /*#__PURE__*/new Set(["className", "value", "readOnly", "formNoValidate", "isMap", "noModule", "playsInline", ...booleans]);
10
+ const ChildProperties = /*#__PURE__*/new Set(["innerHTML", "textContent", "innerText", "children"]);
10
11
  const Aliases = {
11
12
  className: "class",
12
13
  htmlFor: "for"
@@ -232,8 +233,7 @@ function stringifyString(str) {
232
233
  return result;
233
234
  }
234
235
 
235
- const REPLACE_SCRIPT = `function $df(e,t,d,l){d=document.getElementById(e),(l=document.getElementById("pl-"+e))&&l.replaceWith(...d.childNodes),d.remove(),_$HY.set(e,t||null)}`;
236
- const FRAGMENT_REPLACE = /<!\[([\d-]+)\]>/;
236
+ const REPLACE_SCRIPT = `function $df(e,t,d,l){d=document.getElementById(e),(l=document.getElementById("pl-"+e))&&l.replaceWith(...d.childNodes),d.remove(),_$HY.set(e,t)}`;
237
237
  function renderToString(code, options = {}) {
238
238
  let scripts = "";
239
239
  solidJs.sharedConfig.context = {
@@ -252,77 +252,25 @@ function renderToString(code, options = {}) {
252
252
  return html;
253
253
  }
254
254
  function renderToStringAsync(code, options = {}) {
255
- let scripts = "";
256
255
  const {
257
- nonce,
258
- renderId,
259
256
  timeoutMs = 30000
260
257
  } = options;
261
- const dedupe = new WeakMap();
262
- const context = solidJs.sharedConfig.context = {
263
- id: renderId || "",
264
- count: 0,
265
- resources: {},
266
- suspense: {},
267
- assets: [],
268
- async: true,
269
- nonce,
270
- writeResource(id, p, error) {
271
- if (error) return scripts += `_$HY.set("${id}", ${serializeError(p)});`;
272
- if (!p || typeof p !== "object" || !("then" in p)) return scripts += serializeSet(dedupe, id, p) + ";";
273
- p.then(d => scripts += serializeSet(dedupe, id, d) + ";").catch(() => scripts += `_$HY.set("${id}", {});`);
274
- }
275
- };
276
258
  let timeoutHandle;
277
259
  const timeout = new Promise((_, reject) => {
278
260
  timeoutHandle = setTimeout(() => reject("renderToString timed out"), timeoutMs);
279
261
  });
280
- function asyncWrap(fn) {
281
- return new Promise(resolve => {
282
- const registry = new Map();
283
- const cache = Object.create(null);
284
- solidJs.sharedConfig.context.registerFragment = register;
285
- const rendered = fn();
286
- if (!registry.size) resolve(rendered);
287
- function register(key) {
288
- if (!registry.has(key)) registry.set(key, []);
289
- return (value = "", error) => {
290
- if (!registry.has(key)) return;
291
- cache[key] = value;
292
- registry.delete(key);
293
- if (waitForFragments(registry, key)) return;
294
- if (error) scripts += `_$HY.set("${key}", Promise.resolve(${serializeError(error)}));`;else scripts += `_$HY.set("${key}", null);`;
295
- if (!registry.size) Promise.resolve().then(() => {
296
- let source = resolveSSRNode(rendered);
297
- let final = "";
298
- let match;
299
- while (match = source.match(FRAGMENT_REPLACE)) {
300
- final += source.substring(0, match.index);
301
- source = cache[match[1]] + source.substring(match.index + match[0].length);
302
- }
303
- resolve(final + source);
304
- });
305
- return true;
306
- };
307
- }
308
- });
309
- }
310
- return Promise.race([asyncWrap(() => escape(code())), timeout]).then(res => {
262
+ return Promise.race([renderToStream(code, options), timeout]).then(html => {
311
263
  clearTimeout(timeoutHandle);
312
- let html = injectAssets(context.assets, resolveSSRNode(res));
313
- if (scripts.length) html = injectScripts(html, scripts, nonce);
314
264
  return html;
315
265
  });
316
266
  }
317
267
  function renderToStream(code, options = {}) {
318
- const {
268
+ let {
319
269
  nonce,
320
270
  onCompleteShell,
321
271
  onCompleteAll,
322
272
  renderId
323
273
  } = options;
324
- const tmp = [];
325
- const tasks = [];
326
274
  const blockingResources = [];
327
275
  const registry = new Map();
328
276
  const dedupe = new WeakMap();
@@ -339,42 +287,52 @@ function renderToStream(code, options = {}) {
339
287
  }
340
288
  };
341
289
  const pushTask = task => {
342
- tasks.push(task);
343
- if (!scheduled) {
290
+ tasks += task + ";";
291
+ if (!scheduled && firstFlushed) {
344
292
  Promise.resolve().then(writeTasks);
345
293
  scheduled = true;
346
294
  }
347
295
  };
348
296
  const writeTasks = () => {
349
- if (tasks.length && !completed) {
350
- buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`);
351
- tasks.length = 0;
297
+ if (tasks.length && !completed && firstFlushed) {
298
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
299
+ tasks = "";
352
300
  }
353
301
  scheduled = false;
354
302
  };
303
+ let context;
355
304
  let writable;
305
+ let tmp = "";
306
+ let tasks = "";
356
307
  let firstFlushed = false;
357
308
  let completed = false;
358
309
  let scriptFlushed = false;
359
310
  let scheduled = true;
360
311
  let buffer = {
361
312
  write(payload) {
362
- tmp.push(payload);
313
+ tmp += payload;
363
314
  }
364
315
  };
365
- solidJs.sharedConfig.context = {
316
+ solidJs.sharedConfig.context = context = {
366
317
  id: renderId || "",
367
318
  count: 0,
368
319
  async: true,
369
- streaming: true,
370
320
  resources: {},
371
321
  suspense: {},
372
322
  assets: [],
373
323
  nonce,
324
+ replace(id, payloadFn) {
325
+ if (firstFlushed) return;
326
+ const placeholder = `<!${id}>`;
327
+ const first = html.indexOf(placeholder);
328
+ if (first === -1) return;
329
+ const last = html.indexOf(`<!/${id}>`, first + placeholder.length);
330
+ html = html.replace(html.slice(first, last + placeholder.length + 1), resolveSSRNode(payloadFn()));
331
+ },
374
332
  writeResource(id, p, error, wait) {
375
- if (error) return pushTask(`_$HY.set("${id}", ${serializeError(p)})`);
333
+ if (error) return pushTask(serializeSet(dedupe, id, p, serializeError));
376
334
  if (!p || typeof p !== "object" || !("then" in p)) return pushTask(serializeSet(dedupe, id, p));
377
- if (wait && !firstFlushed) blockingResources.push(p);else pushTask(`_$HY.init("${id}")`);
335
+ if (!firstFlushed) wait && blockingResources.push(p);else pushTask(`_$HY.init("${id}")`);
378
336
  p.then(d => {
379
337
  !completed && pushTask(serializeSet(dedupe, id, d));
380
338
  }).catch(() => {
@@ -384,7 +342,7 @@ function renderToStream(code, options = {}) {
384
342
  registerFragment(key) {
385
343
  if (!registry.has(key)) {
386
344
  registry.set(key, []);
387
- pushTask(`_$HY.init("${key}")`);
345
+ firstFlushed && pushTask(`_$HY.init("${key}")`);
388
346
  }
389
347
  return (value, error) => {
390
348
  if (registry.has(key)) {
@@ -394,7 +352,7 @@ function renderToStream(code, options = {}) {
394
352
  if ((value !== undefined || error) && !completed) {
395
353
  if (!firstFlushed) {
396
354
  Promise.resolve().then(() => html = replacePlaceholder(html, key, value !== undefined ? value : ""));
397
- pushTask(`${keys.length ? keys.map(k => `_$HY.unset("${k}");`) : ""}_$HY.set("${key}",${error ? serializeError(error) : "null"})`);
355
+ error && pushTask(serializeSet(dedupe, key, error, serializeError));
398
356
  } else {
399
357
  buffer.write(`<div hidden id="${key}">${value !== undefined ? value : " "}</div>`);
400
358
  pushTask(`${keys.length ? keys.map(k => `_$HY.unset("${k}")`).join(";") + ";" : ""}$df("${key}"${error ? "," + serializeError(error) : ""})${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
@@ -402,17 +360,21 @@ function renderToStream(code, options = {}) {
402
360
  }
403
361
  }
404
362
  }
405
- if (firstFlushed) checkEnd();
406
- return true;
363
+ Promise.resolve().then(checkEnd);
364
+ return firstFlushed;
407
365
  };
408
366
  }
409
367
  };
410
368
  let html = resolveSSRNode(escape(code()));
411
369
  function doShell() {
412
- html = injectAssets(solidJs.sharedConfig.context.assets, html);
413
- if (tasks.length) html = injectScripts(html, tasks.join(";"), nonce);
370
+ html = injectAssets(context.assets, html);
371
+ for (const key in context.resources) {
372
+ if (!("data" in context.resources[key] || context.resources[key].ref[0].error)) pushTask(`_$HY.init("${key}")`);
373
+ }
374
+ for (const key of registry.keys()) pushTask(`_$HY.init("${key}")`);
375
+ if (tasks.length) html = injectScripts(html, tasks, nonce);
414
376
  buffer.write(html);
415
- tasks.length = 0;
377
+ tasks = "";
416
378
  scheduled = false;
417
379
  onCompleteShell && onCompleteShell({
418
380
  write(v) {
@@ -421,11 +383,25 @@ function renderToStream(code, options = {}) {
421
383
  });
422
384
  }
423
385
  return {
386
+ then(fn) {
387
+ function complete() {
388
+ doShell();
389
+ fn(tmp);
390
+ }
391
+ if (onCompleteAll) {
392
+ ogComplete = onCompleteAll;
393
+ onCompleteAll = options => {
394
+ ogComplete(options);
395
+ complete();
396
+ };
397
+ } else onCompleteAll = complete;
398
+ checkEnd();
399
+ },
424
400
  pipe(w) {
425
401
  Promise.allSettled(blockingResources).then(() => {
426
402
  doShell();
427
403
  buffer = writable = w;
428
- tmp.forEach(chunk => buffer.write(chunk));
404
+ buffer.write(tmp);
429
405
  firstFlushed = true;
430
406
  if (completed) writable.end();else setTimeout(checkEnd);
431
407
  });
@@ -446,7 +422,7 @@ function renderToStream(code, options = {}) {
446
422
  writer.write(encoder.encode(payload));
447
423
  }
448
424
  };
449
- tmp.forEach(chunk => buffer.write(chunk));
425
+ buffer.write(tmp);
450
426
  firstFlushed = true;
451
427
  if (completed) writable.end();else setTimeout(checkEnd);
452
428
  });
@@ -481,12 +457,12 @@ function NoHydration(props) {
481
457
  function ssr(t, ...nodes) {
482
458
  if (nodes.length) {
483
459
  let result = "";
484
- for (let i = 0; i < t.length; i++) {
460
+ for (let i = 0; i < nodes.length; i++) {
485
461
  result += t[i];
486
462
  const node = nodes[i];
487
463
  if (node !== undefined) result += resolveSSRNode(node);
488
464
  }
489
- t = result;
465
+ t = result + t[nodes.length];
490
466
  }
491
467
  return {
492
468
  t
@@ -517,16 +493,15 @@ function ssrStyle(value) {
517
493
  }
518
494
  return result;
519
495
  }
520
- function ssrSpread(props, isSVG, skipChildren) {
521
- let result = "";
522
- if (props == null) return results;
496
+ function ssrElement(tag, props, children, needsId) {
497
+ let result = `<${tag}${needsId ? ssrHydrationKey() : ""} `;
523
498
  if (typeof props === "function") props = props();
524
499
  const keys = Object.keys(props);
525
500
  let classResolved;
526
501
  for (let i = 0; i < keys.length; i++) {
527
502
  const prop = keys[i];
528
- if (prop === "children") {
529
- !skipChildren && console.warn(`SSR currently does not support spread children.`);
503
+ if (ChildProperties.has(prop) && children === undefined) {
504
+ children = prop === "innerHTML" ? props[prop] : escape(props[prop]);
530
505
  continue;
531
506
  }
532
507
  const value = props[prop];
@@ -546,7 +521,9 @@ function ssrSpread(props, isSVG, skipChildren) {
546
521
  }
547
522
  if (i !== keys.length - 1) result += " ";
548
523
  }
549
- return result;
524
+ return {
525
+ t: result + `>${resolveSSRNode(children)}</${tag}>`
526
+ };
550
527
  }
551
528
  function ssrAttribute(key, value, isBoolean) {
552
529
  return isBoolean ? value ? " " + key : "" : value != null ? ` ${key}="${value}"` : "";
@@ -606,7 +583,7 @@ function resolveSSRNode(node) {
606
583
  for (let i = 0, len = node.length; i < len; i++) mapped += resolveSSRNode(node[i]);
607
584
  return mapped;
608
585
  }
609
- if (t === "object") return resolveSSRNode(node.t);
586
+ if (t === "object") return node.t;
610
587
  if (t === "function") return resolveSSRNode(node());
611
588
  return String(node);
612
589
  }
@@ -618,7 +595,7 @@ function generateHydrationScript({
618
595
  eventNames = ["click", "input"],
619
596
  nonce
620
597
  } = {}) {
621
- return `<script${nonce ? ` nonce="${nonce}"` : ""}>var e,t;e=window._$HY||(_$HY={events:[],completed:new WeakSet,r:{}}),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 s=o.composedPath&&o.composedPath()[0]||o.target,a=t(s);a&&!e.completed.has(a)&&e.events.push([a,o])})))),e.init=(t,o)=>{e.r[t]=[new Promise(((e,t)=>o=e)),o]},e.set=(t,o,s)=>{(s=e.r[t])&&s[1](o),e.r[t]=[o]},e.unset=t=>{delete e.r[t]},e.load=(t,o)=>{if(o=e.r[t])return o[0]};</script><!--xs-->`;
598
+ return `<script${nonce ? ` nonce="${nonce}"` : ""}>var e,t;e=window._$HY||(_$HY={events:[],completed:new WeakSet,r:{}}),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 s=o.composedPath&&o.composedPath()[0]||o.target,a=t(s);a&&!e.completed.has(a)&&e.events.push([a,o])})))),e.init=(t,o)=>{e.r[t]=[new Promise(((e,t)=>o=e)),o]},e.set=(t,o,s)=>{(s=e.r[t])&&s[1](o),e.r[t]=[o]},e.unset=t=>{delete e.r[t]},e.load=t=>e.r[t];</script><!--xs-->`;
622
599
  }
623
600
  function injectAssets(assets, html) {
624
601
  for (let i = 0; i < assets.length; i++) {
@@ -658,11 +635,11 @@ function waitForFragments(registry, key) {
658
635
  }
659
636
  return false;
660
637
  }
661
- function serializeSet(registry, key, value) {
638
+ function serializeSet(registry, key, value, serializer = devalue) {
662
639
  const exist = registry.get(value);
663
640
  if (exist) return `_$HY.set("${key}", _$HY.r["${exist}"][0])`;
664
641
  value !== null && typeof value === "object" && registry.set(value, key);
665
- return `_$HY.set("${key}", ${devalue(value)})`;
642
+ return `_$HY.set("${key}", ${serializer(value)})`;
666
643
  }
667
644
  function replacePlaceholder(html, key, value) {
668
645
  const nextRegex = /(<[/]?span[^>]*>)/g;
@@ -722,8 +699,7 @@ function Dynamic(props) {
722
699
  t = typeof comp;
723
700
  if (comp) {
724
701
  if (t === "function") return comp(others);else if (t === "string") {
725
- const [local, sOthers] = solidJs.splitProps(others, ["children"]);
726
- return ssr([`<${comp}`, ' ', ">", `</${comp}>`], ssrHydrationKey(), ssrSpread(sOthers), escape(local.children || ""));
702
+ return ssrElement(comp, others, undefined, true);
727
703
  }
728
704
  }
729
705
  }
@@ -790,6 +766,6 @@ exports.spread = spread;
790
766
  exports.ssr = ssr;
791
767
  exports.ssrAttribute = ssrAttribute;
792
768
  exports.ssrClassList = ssrClassList;
769
+ exports.ssrElement = ssrElement;
793
770
  exports.ssrHydrationKey = ssrHydrationKey;
794
- exports.ssrSpread = ssrSpread;
795
771
  exports.ssrStyle = ssrStyle;
@@ -4,6 +4,7 @@ export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch,
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"];
5
5
  const BooleanAttributes = /*#__PURE__*/new Set(booleans);
6
6
  /*#__PURE__*/new Set(["className", "value", "readOnly", "formNoValidate", "isMap", "noModule", "playsInline", ...booleans]);
7
+ const ChildProperties = /*#__PURE__*/new Set(["innerHTML", "textContent", "innerText", "children"]);
7
8
  const Aliases = {
8
9
  className: "class",
9
10
  htmlFor: "for"
@@ -229,8 +230,7 @@ function stringifyString(str) {
229
230
  return result;
230
231
  }
231
232
 
232
- const REPLACE_SCRIPT = `function $df(e,t,d,l){d=document.getElementById(e),(l=document.getElementById("pl-"+e))&&l.replaceWith(...d.childNodes),d.remove(),_$HY.set(e,t||null)}`;
233
- const FRAGMENT_REPLACE = /<!\[([\d-]+)\]>/;
233
+ const REPLACE_SCRIPT = `function $df(e,t,d,l){d=document.getElementById(e),(l=document.getElementById("pl-"+e))&&l.replaceWith(...d.childNodes),d.remove(),_$HY.set(e,t)}`;
234
234
  function renderToString(code, options = {}) {
235
235
  let scripts = "";
236
236
  sharedConfig.context = {
@@ -249,77 +249,25 @@ function renderToString(code, options = {}) {
249
249
  return html;
250
250
  }
251
251
  function renderToStringAsync(code, options = {}) {
252
- let scripts = "";
253
252
  const {
254
- nonce,
255
- renderId,
256
253
  timeoutMs = 30000
257
254
  } = options;
258
- const dedupe = new WeakMap();
259
- const context = sharedConfig.context = {
260
- id: renderId || "",
261
- count: 0,
262
- resources: {},
263
- suspense: {},
264
- assets: [],
265
- async: true,
266
- nonce,
267
- writeResource(id, p, error) {
268
- if (error) return scripts += `_$HY.set("${id}", ${serializeError(p)});`;
269
- if (!p || typeof p !== "object" || !("then" in p)) return scripts += serializeSet(dedupe, id, p) + ";";
270
- p.then(d => scripts += serializeSet(dedupe, id, d) + ";").catch(() => scripts += `_$HY.set("${id}", {});`);
271
- }
272
- };
273
255
  let timeoutHandle;
274
256
  const timeout = new Promise((_, reject) => {
275
257
  timeoutHandle = setTimeout(() => reject("renderToString timed out"), timeoutMs);
276
258
  });
277
- function asyncWrap(fn) {
278
- return new Promise(resolve => {
279
- const registry = new Map();
280
- const cache = Object.create(null);
281
- sharedConfig.context.registerFragment = register;
282
- const rendered = fn();
283
- if (!registry.size) resolve(rendered);
284
- function register(key) {
285
- if (!registry.has(key)) registry.set(key, []);
286
- return (value = "", error) => {
287
- if (!registry.has(key)) return;
288
- cache[key] = value;
289
- registry.delete(key);
290
- if (waitForFragments(registry, key)) return;
291
- if (error) scripts += `_$HY.set("${key}", Promise.resolve(${serializeError(error)}));`;else scripts += `_$HY.set("${key}", null);`;
292
- if (!registry.size) Promise.resolve().then(() => {
293
- let source = resolveSSRNode(rendered);
294
- let final = "";
295
- let match;
296
- while (match = source.match(FRAGMENT_REPLACE)) {
297
- final += source.substring(0, match.index);
298
- source = cache[match[1]] + source.substring(match.index + match[0].length);
299
- }
300
- resolve(final + source);
301
- });
302
- return true;
303
- };
304
- }
305
- });
306
- }
307
- return Promise.race([asyncWrap(() => escape(code())), timeout]).then(res => {
259
+ return Promise.race([renderToStream(code, options), timeout]).then(html => {
308
260
  clearTimeout(timeoutHandle);
309
- let html = injectAssets(context.assets, resolveSSRNode(res));
310
- if (scripts.length) html = injectScripts(html, scripts, nonce);
311
261
  return html;
312
262
  });
313
263
  }
314
264
  function renderToStream(code, options = {}) {
315
- const {
265
+ let {
316
266
  nonce,
317
267
  onCompleteShell,
318
268
  onCompleteAll,
319
269
  renderId
320
270
  } = options;
321
- const tmp = [];
322
- const tasks = [];
323
271
  const blockingResources = [];
324
272
  const registry = new Map();
325
273
  const dedupe = new WeakMap();
@@ -336,42 +284,52 @@ function renderToStream(code, options = {}) {
336
284
  }
337
285
  };
338
286
  const pushTask = task => {
339
- tasks.push(task);
340
- if (!scheduled) {
287
+ tasks += task + ";";
288
+ if (!scheduled && firstFlushed) {
341
289
  Promise.resolve().then(writeTasks);
342
290
  scheduled = true;
343
291
  }
344
292
  };
345
293
  const writeTasks = () => {
346
- if (tasks.length && !completed) {
347
- buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks.join(";")}</script>`);
348
- tasks.length = 0;
294
+ if (tasks.length && !completed && firstFlushed) {
295
+ buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
296
+ tasks = "";
349
297
  }
350
298
  scheduled = false;
351
299
  };
300
+ let context;
352
301
  let writable;
302
+ let tmp = "";
303
+ let tasks = "";
353
304
  let firstFlushed = false;
354
305
  let completed = false;
355
306
  let scriptFlushed = false;
356
307
  let scheduled = true;
357
308
  let buffer = {
358
309
  write(payload) {
359
- tmp.push(payload);
310
+ tmp += payload;
360
311
  }
361
312
  };
362
- sharedConfig.context = {
313
+ sharedConfig.context = context = {
363
314
  id: renderId || "",
364
315
  count: 0,
365
316
  async: true,
366
- streaming: true,
367
317
  resources: {},
368
318
  suspense: {},
369
319
  assets: [],
370
320
  nonce,
321
+ replace(id, payloadFn) {
322
+ if (firstFlushed) return;
323
+ const placeholder = `<!${id}>`;
324
+ const first = html.indexOf(placeholder);
325
+ if (first === -1) return;
326
+ const last = html.indexOf(`<!/${id}>`, first + placeholder.length);
327
+ html = html.replace(html.slice(first, last + placeholder.length + 1), resolveSSRNode(payloadFn()));
328
+ },
371
329
  writeResource(id, p, error, wait) {
372
- if (error) return pushTask(`_$HY.set("${id}", ${serializeError(p)})`);
330
+ if (error) return pushTask(serializeSet(dedupe, id, p, serializeError));
373
331
  if (!p || typeof p !== "object" || !("then" in p)) return pushTask(serializeSet(dedupe, id, p));
374
- if (wait && !firstFlushed) blockingResources.push(p);else pushTask(`_$HY.init("${id}")`);
332
+ if (!firstFlushed) wait && blockingResources.push(p);else pushTask(`_$HY.init("${id}")`);
375
333
  p.then(d => {
376
334
  !completed && pushTask(serializeSet(dedupe, id, d));
377
335
  }).catch(() => {
@@ -381,7 +339,7 @@ function renderToStream(code, options = {}) {
381
339
  registerFragment(key) {
382
340
  if (!registry.has(key)) {
383
341
  registry.set(key, []);
384
- pushTask(`_$HY.init("${key}")`);
342
+ firstFlushed && pushTask(`_$HY.init("${key}")`);
385
343
  }
386
344
  return (value, error) => {
387
345
  if (registry.has(key)) {
@@ -391,7 +349,7 @@ function renderToStream(code, options = {}) {
391
349
  if ((value !== undefined || error) && !completed) {
392
350
  if (!firstFlushed) {
393
351
  Promise.resolve().then(() => html = replacePlaceholder(html, key, value !== undefined ? value : ""));
394
- pushTask(`${keys.length ? keys.map(k => `_$HY.unset("${k}");`) : ""}_$HY.set("${key}",${error ? serializeError(error) : "null"})`);
352
+ error && pushTask(serializeSet(dedupe, key, error, serializeError));
395
353
  } else {
396
354
  buffer.write(`<div hidden id="${key}">${value !== undefined ? value : " "}</div>`);
397
355
  pushTask(`${keys.length ? keys.map(k => `_$HY.unset("${k}")`).join(";") + ";" : ""}$df("${key}"${error ? "," + serializeError(error) : ""})${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
@@ -399,17 +357,21 @@ function renderToStream(code, options = {}) {
399
357
  }
400
358
  }
401
359
  }
402
- if (firstFlushed) checkEnd();
403
- return true;
360
+ Promise.resolve().then(checkEnd);
361
+ return firstFlushed;
404
362
  };
405
363
  }
406
364
  };
407
365
  let html = resolveSSRNode(escape(code()));
408
366
  function doShell() {
409
- html = injectAssets(sharedConfig.context.assets, html);
410
- if (tasks.length) html = injectScripts(html, tasks.join(";"), nonce);
367
+ html = injectAssets(context.assets, html);
368
+ for (const key in context.resources) {
369
+ if (!("data" in context.resources[key] || context.resources[key].ref[0].error)) pushTask(`_$HY.init("${key}")`);
370
+ }
371
+ for (const key of registry.keys()) pushTask(`_$HY.init("${key}")`);
372
+ if (tasks.length) html = injectScripts(html, tasks, nonce);
411
373
  buffer.write(html);
412
- tasks.length = 0;
374
+ tasks = "";
413
375
  scheduled = false;
414
376
  onCompleteShell && onCompleteShell({
415
377
  write(v) {
@@ -418,11 +380,25 @@ function renderToStream(code, options = {}) {
418
380
  });
419
381
  }
420
382
  return {
383
+ then(fn) {
384
+ function complete() {
385
+ doShell();
386
+ fn(tmp);
387
+ }
388
+ if (onCompleteAll) {
389
+ ogComplete = onCompleteAll;
390
+ onCompleteAll = options => {
391
+ ogComplete(options);
392
+ complete();
393
+ };
394
+ } else onCompleteAll = complete;
395
+ checkEnd();
396
+ },
421
397
  pipe(w) {
422
398
  Promise.allSettled(blockingResources).then(() => {
423
399
  doShell();
424
400
  buffer = writable = w;
425
- tmp.forEach(chunk => buffer.write(chunk));
401
+ buffer.write(tmp);
426
402
  firstFlushed = true;
427
403
  if (completed) writable.end();else setTimeout(checkEnd);
428
404
  });
@@ -443,7 +419,7 @@ function renderToStream(code, options = {}) {
443
419
  writer.write(encoder.encode(payload));
444
420
  }
445
421
  };
446
- tmp.forEach(chunk => buffer.write(chunk));
422
+ buffer.write(tmp);
447
423
  firstFlushed = true;
448
424
  if (completed) writable.end();else setTimeout(checkEnd);
449
425
  });
@@ -478,12 +454,12 @@ function NoHydration(props) {
478
454
  function ssr(t, ...nodes) {
479
455
  if (nodes.length) {
480
456
  let result = "";
481
- for (let i = 0; i < t.length; i++) {
457
+ for (let i = 0; i < nodes.length; i++) {
482
458
  result += t[i];
483
459
  const node = nodes[i];
484
460
  if (node !== undefined) result += resolveSSRNode(node);
485
461
  }
486
- t = result;
462
+ t = result + t[nodes.length];
487
463
  }
488
464
  return {
489
465
  t
@@ -514,16 +490,15 @@ function ssrStyle(value) {
514
490
  }
515
491
  return result;
516
492
  }
517
- function ssrSpread(props, isSVG, skipChildren) {
518
- let result = "";
519
- if (props == null) return results;
493
+ function ssrElement(tag, props, children, needsId) {
494
+ let result = `<${tag}${needsId ? ssrHydrationKey() : ""} `;
520
495
  if (typeof props === "function") props = props();
521
496
  const keys = Object.keys(props);
522
497
  let classResolved;
523
498
  for (let i = 0; i < keys.length; i++) {
524
499
  const prop = keys[i];
525
- if (prop === "children") {
526
- !skipChildren && console.warn(`SSR currently does not support spread children.`);
500
+ if (ChildProperties.has(prop) && children === undefined) {
501
+ children = prop === "innerHTML" ? props[prop] : escape(props[prop]);
527
502
  continue;
528
503
  }
529
504
  const value = props[prop];
@@ -543,7 +518,9 @@ function ssrSpread(props, isSVG, skipChildren) {
543
518
  }
544
519
  if (i !== keys.length - 1) result += " ";
545
520
  }
546
- return result;
521
+ return {
522
+ t: result + `>${resolveSSRNode(children)}</${tag}>`
523
+ };
547
524
  }
548
525
  function ssrAttribute(key, value, isBoolean) {
549
526
  return isBoolean ? value ? " " + key : "" : value != null ? ` ${key}="${value}"` : "";
@@ -603,7 +580,7 @@ function resolveSSRNode(node) {
603
580
  for (let i = 0, len = node.length; i < len; i++) mapped += resolveSSRNode(node[i]);
604
581
  return mapped;
605
582
  }
606
- if (t === "object") return resolveSSRNode(node.t);
583
+ if (t === "object") return node.t;
607
584
  if (t === "function") return resolveSSRNode(node());
608
585
  return String(node);
609
586
  }
@@ -615,7 +592,7 @@ function generateHydrationScript({
615
592
  eventNames = ["click", "input"],
616
593
  nonce
617
594
  } = {}) {
618
- return `<script${nonce ? ` nonce="${nonce}"` : ""}>var e,t;e=window._$HY||(_$HY={events:[],completed:new WeakSet,r:{}}),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 s=o.composedPath&&o.composedPath()[0]||o.target,a=t(s);a&&!e.completed.has(a)&&e.events.push([a,o])})))),e.init=(t,o)=>{e.r[t]=[new Promise(((e,t)=>o=e)),o]},e.set=(t,o,s)=>{(s=e.r[t])&&s[1](o),e.r[t]=[o]},e.unset=t=>{delete e.r[t]},e.load=(t,o)=>{if(o=e.r[t])return o[0]};</script><!--xs-->`;
595
+ return `<script${nonce ? ` nonce="${nonce}"` : ""}>var e,t;e=window._$HY||(_$HY={events:[],completed:new WeakSet,r:{}}),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 s=o.composedPath&&o.composedPath()[0]||o.target,a=t(s);a&&!e.completed.has(a)&&e.events.push([a,o])})))),e.init=(t,o)=>{e.r[t]=[new Promise(((e,t)=>o=e)),o]},e.set=(t,o,s)=>{(s=e.r[t])&&s[1](o),e.r[t]=[o]},e.unset=t=>{delete e.r[t]},e.load=t=>e.r[t];</script><!--xs-->`;
619
596
  }
620
597
  function injectAssets(assets, html) {
621
598
  for (let i = 0; i < assets.length; i++) {
@@ -655,11 +632,11 @@ function waitForFragments(registry, key) {
655
632
  }
656
633
  return false;
657
634
  }
658
- function serializeSet(registry, key, value) {
635
+ function serializeSet(registry, key, value, serializer = devalue) {
659
636
  const exist = registry.get(value);
660
637
  if (exist) return `_$HY.set("${key}", _$HY.r["${exist}"][0])`;
661
638
  value !== null && typeof value === "object" && registry.set(value, key);
662
- return `_$HY.set("${key}", ${devalue(value)})`;
639
+ return `_$HY.set("${key}", ${serializer(value)})`;
663
640
  }
664
641
  function replacePlaceholder(html, key, value) {
665
642
  const nextRegex = /(<[/]?span[^>]*>)/g;
@@ -719,8 +696,7 @@ function Dynamic(props) {
719
696
  t = typeof comp;
720
697
  if (comp) {
721
698
  if (t === "function") return comp(others);else if (t === "string") {
722
- const [local, sOthers] = splitProps(others, ["children"]);
723
- return ssr([`<${comp}`, ' ', ">", `</${comp}>`], ssrHydrationKey(), ssrSpread(sOthers), escape(local.children || ""));
699
+ return ssrElement(comp, others, undefined, true);
724
700
  }
725
701
  }
726
702
  }
@@ -728,4 +704,4 @@ function Portal(props) {
728
704
  return "";
729
705
  }
730
706
 
731
- export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrAttribute, ssrClassList, ssrHydrationKey, ssrSpread, ssrStyle };
707
+ export { Assets, Dynamic, HydrationScript, NoHydration, Portal, escape, generateHydrationScript, getHydrationKey, isServer, pipeToNodeWritable, pipeToWritable, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle };