hadars 0.1.40 → 0.2.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.
@@ -38,6 +38,13 @@ function swapContextMap(map) {
38
38
  function captureMap() {
39
39
  return _g[MAP_KEY];
40
40
  }
41
+ var UNSUSPEND_KEY = "__hadarsUnsuspend";
42
+ function captureUnsuspend() {
43
+ return _g[UNSUSPEND_KEY];
44
+ }
45
+ function restoreUnsuspend(u) {
46
+ _g[UNSUSPEND_KEY] = u;
47
+ }
41
48
  function getContextValue(context) {
42
49
  const map = _g[MAP_KEY];
43
50
  if (map && map.has(context)) return map.get(context);
@@ -45,10 +52,14 @@ function getContextValue(context) {
45
52
  return "_defaultValue" in c ? c._defaultValue : c._currentValue;
46
53
  }
47
54
  function pushContextValue(context, value) {
48
- const map = _g[MAP_KEY];
55
+ let map = _g[MAP_KEY];
56
+ if (map === null) {
57
+ map = /* @__PURE__ */ new Map();
58
+ _g[MAP_KEY] = map;
59
+ }
49
60
  const c = context;
50
- const prev = map && map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
51
- map?.set(context, value);
61
+ const prev = map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
62
+ map.set(context, value);
52
63
  return prev;
53
64
  }
54
65
  function popContextValue(context, prev) {
@@ -56,48 +67,57 @@ function popContextValue(context, prev) {
56
67
  }
57
68
  var GLOBAL_KEY = "__slimReactRenderState";
58
69
  var EMPTY = { id: 1, overflow: "" };
70
+ var _stateCache = null;
59
71
  function s() {
60
- const g = globalThis;
61
- if (!g[GLOBAL_KEY]) {
62
- g[GLOBAL_KEY] = { currentTreeContext: { ...EMPTY }, localIdCounter: 0, idPrefix: "" };
72
+ if (_stateCache !== null) return _stateCache;
73
+ if (!_g[GLOBAL_KEY]) {
74
+ _g[GLOBAL_KEY] = { currentTreeContext: { ...EMPTY }, localIdCounter: 0, idPrefix: "" };
63
75
  }
64
- return g[GLOBAL_KEY];
76
+ _stateCache = _g[GLOBAL_KEY];
77
+ return _stateCache;
65
78
  }
79
+ var _treeIdStack = [];
80
+ var _treeOvStack = [];
81
+ var _treeDepth = 0;
66
82
  function resetRenderState(idPrefix = "") {
67
83
  const st = s();
68
- st.currentTreeContext = { ...EMPTY };
84
+ st.currentTreeContext.id = EMPTY.id;
85
+ st.currentTreeContext.overflow = EMPTY.overflow;
69
86
  st.localIdCounter = 0;
70
87
  st.idPrefix = idPrefix;
88
+ _treeDepth = 0;
71
89
  }
72
90
  function pushTreeContext(totalChildren, index) {
73
91
  const st = s();
74
- const saved = { ...st.currentTreeContext };
75
- const baseIdWithLeadingBit = st.currentTreeContext.id;
76
- const baseOverflow = st.currentTreeContext.overflow;
92
+ const ctx = st.currentTreeContext;
93
+ const depth = _treeDepth++;
94
+ _treeIdStack[depth] = ctx.id;
95
+ _treeOvStack[depth] = ctx.overflow;
96
+ const baseIdWithLeadingBit = ctx.id;
97
+ const baseOverflow = ctx.overflow;
77
98
  const baseLength = 31 - Math.clz32(baseIdWithLeadingBit);
78
99
  let baseId = baseIdWithLeadingBit & ~(1 << baseLength);
79
100
  const slot = index + 1;
80
101
  const newBits = 32 - Math.clz32(totalChildren);
81
102
  const length = newBits + baseLength;
82
103
  if (30 < length) {
83
- const numberOfOverflowBits = baseLength - baseLength % 5;
84
- const overflowStr = (baseId & (1 << numberOfOverflowBits) - 1).toString(32);
85
- baseId >>= numberOfOverflowBits;
86
- const newBaseLength = baseLength - numberOfOverflowBits;
87
- st.currentTreeContext = {
88
- id: 1 << newBits + newBaseLength | slot << newBaseLength | baseId,
89
- overflow: overflowStr + baseOverflow
90
- };
104
+ const overflowBits = baseLength - baseLength % 5;
105
+ const overflowStr = (baseId & (1 << overflowBits) - 1).toString(32);
106
+ baseId >>= overflowBits;
107
+ const newBaseLength = baseLength - overflowBits;
108
+ ctx.id = 1 << newBits + newBaseLength | slot << newBaseLength | baseId;
109
+ ctx.overflow = overflowStr + baseOverflow;
91
110
  } else {
92
- st.currentTreeContext = {
93
- id: 1 << length | slot << baseLength | baseId,
94
- overflow: baseOverflow
95
- };
111
+ ctx.id = 1 << length | slot << baseLength | baseId;
112
+ ctx.overflow = baseOverflow;
96
113
  }
97
- return saved;
114
+ return depth;
98
115
  }
99
- function popTreeContext(saved) {
100
- s().currentTreeContext = saved;
116
+ function popTreeContext(depth) {
117
+ const ctx = s().currentTreeContext;
118
+ ctx.id = _treeIdStack[depth];
119
+ ctx.overflow = _treeOvStack[depth];
120
+ _treeDepth = depth;
101
121
  }
102
122
  function pushComponentScope() {
103
123
  const st = s();
@@ -113,12 +133,16 @@ function componentCalledUseId() {
113
133
  }
114
134
  function snapshotContext() {
115
135
  const st = s();
116
- return { tree: { ...st.currentTreeContext }, localId: st.localIdCounter };
136
+ const ctx = st.currentTreeContext;
137
+ return { tree: { id: ctx.id, overflow: ctx.overflow }, localId: st.localIdCounter, treeDepth: _treeDepth };
117
138
  }
118
139
  function restoreContext(snap) {
119
140
  const st = s();
120
- st.currentTreeContext = { ...snap.tree };
141
+ const ctx = st.currentTreeContext;
142
+ ctx.id = snap.tree.id;
143
+ ctx.overflow = snap.tree.overflow;
121
144
  st.localIdCounter = snap.localId;
145
+ _treeDepth = snap.treeDepth;
122
146
  }
123
147
  function getTreeId() {
124
148
  const { id, overflow } = s().currentTreeContext;
@@ -249,19 +273,80 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
249
273
  "wbr"
250
274
  ]);
251
275
  var HTML_ESC = { "&": "&amp;", "<": "&lt;", ">": "&gt;", "'": "&#x27;" };
276
+ var HTML_ESC_RE = /[&<>']/;
252
277
  function escapeHtml(str) {
278
+ if (!HTML_ESC_RE.test(str)) return str;
253
279
  return str.replace(/[&<>']/g, (c) => HTML_ESC[c]);
254
280
  }
255
281
  var ATTR_ESC = { "&": "&amp;", '"': "&quot;", "<": "&lt;", ">": "&gt;" };
282
+ var ATTR_ESC_RE = /[&"<>]/;
256
283
  function escapeAttr(str) {
284
+ if (!ATTR_ESC_RE.test(str)) return str;
257
285
  return str.replace(/[&"<>]/g, (c) => ATTR_ESC[c]);
258
286
  }
287
+ var UNITLESS_CSS = /* @__PURE__ */ new Set([
288
+ "animationIterationCount",
289
+ "aspectRatio",
290
+ "borderImageOutset",
291
+ "borderImageSlice",
292
+ "borderImageWidth",
293
+ "boxFlex",
294
+ "boxFlexGroup",
295
+ "boxOrdinalGroup",
296
+ "columnCount",
297
+ "columns",
298
+ "flex",
299
+ "flexGrow",
300
+ "flexPositive",
301
+ "flexShrink",
302
+ "flexNegative",
303
+ "flexOrder",
304
+ "gridArea",
305
+ "gridRow",
306
+ "gridRowEnd",
307
+ "gridRowSpan",
308
+ "gridRowStart",
309
+ "gridColumn",
310
+ "gridColumnEnd",
311
+ "gridColumnSpan",
312
+ "gridColumnStart",
313
+ "fontWeight",
314
+ "lineClamp",
315
+ "lineHeight",
316
+ "opacity",
317
+ "order",
318
+ "orphans",
319
+ "scale",
320
+ "tabSize",
321
+ "widows",
322
+ "zIndex",
323
+ "zoom",
324
+ "fillOpacity",
325
+ "floodOpacity",
326
+ "stopOpacity",
327
+ "strokeDasharray",
328
+ "strokeDashoffset",
329
+ "strokeMiterlimit",
330
+ "strokeOpacity",
331
+ "strokeWidth"
332
+ ]);
333
+ var _cssKeyCache = /* @__PURE__ */ new Map();
259
334
  function styleObjectToString(style) {
260
335
  let result = "";
261
336
  for (const key in style) {
337
+ const value = style[key];
338
+ if (value == null || typeof value === "boolean") continue;
262
339
  if (result) result += ";";
263
- const cssKey = key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
264
- result += cssKey + ":" + style[key];
340
+ let cssKey = _cssKeyCache.get(key);
341
+ if (cssKey === void 0) {
342
+ cssKey = key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
343
+ _cssKeyCache.set(key, cssKey);
344
+ }
345
+ if (typeof value === "number" && value !== 0 && !UNITLESS_CSS.has(key)) {
346
+ result += cssKey + ":" + value + "px";
347
+ } else {
348
+ result += cssKey + ":" + value;
349
+ }
265
350
  }
266
351
  return result;
267
352
  }
@@ -396,14 +481,22 @@ var SVG_ATTR_MAP = {
396
481
  xChannelSelector: "xChannelSelector",
397
482
  yChannelSelector: "yChannelSelector"
398
483
  };
399
- function renderAttributes(props, isSvg) {
400
- let attrs = "";
484
+ var TEXTAREA_SKIP_PROPS = /* @__PURE__ */ new Set(["value", "defaultValue", "children"]);
485
+ var SELECT_SKIP_PROPS = /* @__PURE__ */ new Set(["value", "defaultValue"]);
486
+ var INTERNAL_PROPS = /* @__PURE__ */ new Set([
487
+ "children",
488
+ "key",
489
+ "ref",
490
+ "dangerouslySetInnerHTML",
491
+ "suppressHydrationWarning",
492
+ "suppressContentEditableWarning"
493
+ ]);
494
+ function writeAttributes(writer, props, isSvg, skip) {
401
495
  for (const key in props) {
496
+ if (skip !== void 0 && skip.has(key)) continue;
402
497
  const value = props[key];
403
- if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || key === "suppressHydrationWarning" || key === "suppressContentEditableWarning")
404
- continue;
405
- if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase())
406
- continue;
498
+ if (INTERNAL_PROPS.has(key)) continue;
499
+ if (key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key.charCodeAt(2) >= 65 && key.charCodeAt(2) <= 90) continue;
407
500
  let attrName;
408
501
  if (isSvg && key in SVG_ATTR_MAP) {
409
502
  attrName = SVG_ATTR_MAP[key];
@@ -411,41 +504,46 @@ function renderAttributes(props, isSvg) {
411
504
  attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key;
412
505
  }
413
506
  if (value === false || value == null) {
414
- if (value === false && (attrName.startsWith("aria-") || attrName.startsWith("data-"))) {
415
- attrs += ` ${attrName}="false"`;
507
+ if (value === false && (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-"))) {
508
+ writer.write(` ${attrName}="false"`);
416
509
  }
417
510
  continue;
418
511
  }
419
512
  if (value === true) {
420
- if (attrName.startsWith("aria-") || attrName.startsWith("data-")) {
421
- attrs += ` ${attrName}="true"`;
513
+ if (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-")) {
514
+ writer.write(` ${attrName}="true"`);
422
515
  } else {
423
- attrs += ` ${attrName}=""`;
516
+ writer.write(` ${attrName}=""`);
424
517
  }
425
518
  continue;
426
519
  }
427
520
  if (key === "style" && typeof value === "object") {
428
521
  const styleStr = styleObjectToString(value);
429
- if (styleStr) attrs += ` style="${escapeAttr(styleStr)}"`;
522
+ if (styleStr) writer.write(` style="${escapeAttr(styleStr)}"`);
430
523
  continue;
431
524
  }
432
- attrs += ` ${attrName}="${escapeAttr(String(value))}"`;
525
+ writer.write(` ${attrName}="${escapeAttr(typeof value === "string" ? value : String(value))}"`);
433
526
  }
434
- return attrs;
435
527
  }
436
- var BufferWriter = class {
437
- chunks = [];
528
+ var BufferWriter = class _BufferWriter {
529
+ data = "";
438
530
  lastWasText = false;
439
531
  write(chunk) {
440
- this.chunks.push(chunk);
532
+ this.data += chunk;
441
533
  this.lastWasText = false;
442
534
  }
443
535
  text(s2) {
444
- this.chunks.push(s2);
536
+ this.data += s2;
445
537
  this.lastWasText = true;
446
538
  }
447
- flush(target) {
448
- for (const c of this.chunks) target.write(c);
539
+ /** Flush accumulated output into a parent writer and reset. */
540
+ flushTo(target) {
541
+ if (!this.data) return;
542
+ if (target instanceof _BufferWriter) {
543
+ target.data += this.data;
544
+ } else {
545
+ target.write(this.data);
546
+ }
449
547
  target.lastWasText = this.lastWasText;
450
548
  }
451
549
  };
@@ -462,15 +560,12 @@ function renderNode(node, writer, isSvg = false) {
462
560
  if (Array.isArray(node)) {
463
561
  return renderChildArray(node, writer, isSvg);
464
562
  }
465
- if (typeof node === "object" && node !== null && Symbol.iterator in node && !("$$typeof" in node)) {
466
- return renderChildArray(
467
- Array.from(node),
468
- writer,
469
- isSvg
470
- );
563
+ const obj = node;
564
+ if (Symbol.iterator in obj && !("$$typeof" in obj)) {
565
+ return renderChildArray(Array.from(obj), writer, isSvg);
471
566
  }
472
- if (typeof node === "object" && node !== null && "$$typeof" in node) {
473
- const elType = node["$$typeof"];
567
+ if ("$$typeof" in obj) {
568
+ const elType = obj["$$typeof"];
474
569
  if (elType !== SLIM_ELEMENT && elType !== REACT19_ELEMENT) return;
475
570
  const element = node;
476
571
  const { type, props } = element;
@@ -480,15 +575,15 @@ function renderNode(node, writer, isSvg = false) {
480
575
  if (type === SUSPENSE_TYPE) {
481
576
  return renderSuspense(props, writer, isSvg);
482
577
  }
578
+ if (typeof type === "string") {
579
+ return renderHostElement(type, props, writer, isSvg);
580
+ }
483
581
  if (typeof type === "function") {
484
582
  return renderComponent(type, props, writer, isSvg);
485
583
  }
486
584
  if (typeof type === "object" && type !== null) {
487
585
  return renderComponent(type, props, writer, isSvg);
488
586
  }
489
- if (typeof type === "string") {
490
- return renderHostElement(type, props, writer, isSvg);
491
- }
492
587
  }
493
588
  }
494
589
  function markSelectedOptionsMulti(children, selectedValues) {
@@ -514,26 +609,21 @@ function markSelectedOptionsMulti(children, selectedValues) {
514
609
  return children;
515
610
  }
516
611
  function renderHostElement(tag, props, writer, isSvg) {
517
- const enteringSvg = tag === "svg";
518
- const childSvg = isSvg || enteringSvg;
612
+ const childSvg = isSvg || tag === "svg";
519
613
  if (tag === "textarea") {
520
614
  const textContent = props.value ?? props.defaultValue ?? props.children ?? "";
521
- const filteredProps = {};
522
- for (const k of Object.keys(props)) {
523
- if (k !== "value" && k !== "defaultValue" && k !== "children") filteredProps[k] = props[k];
524
- }
525
- writer.write(`<textarea${renderAttributes(filteredProps, false)}>`);
615
+ writer.write("<textarea");
616
+ writeAttributes(writer, props, false, TEXTAREA_SKIP_PROPS);
617
+ writer.write(">");
526
618
  writer.text(escapeHtml(String(textContent)));
527
619
  writer.write("</textarea>");
528
620
  return;
529
621
  }
530
622
  if (tag === "select") {
531
623
  const selectedValue = props.value ?? props.defaultValue;
532
- const filteredProps = {};
533
- for (const k of Object.keys(props)) {
534
- if (k !== "value" && k !== "defaultValue") filteredProps[k] = props[k];
535
- }
536
- writer.write(`<select${renderAttributes(filteredProps, false)}>`);
624
+ writer.write("<select");
625
+ writeAttributes(writer, props, false, SELECT_SKIP_PROPS);
626
+ writer.write(">");
537
627
  const selectedSet = selectedValue == null ? null : Array.isArray(selectedValue) ? new Set(selectedValue.map(String)) : /* @__PURE__ */ new Set([String(selectedValue)]);
538
628
  const patchedChildren = selectedSet != null ? markSelectedOptionsMulti(props.children, selectedSet) : props.children;
539
629
  const inner2 = renderChildren(patchedChildren, writer, false);
@@ -545,7 +635,8 @@ function renderHostElement(tag, props, writer, isSvg) {
545
635
  writer.write("</select>");
546
636
  return;
547
637
  }
548
- writer.write(`<${tag}${renderAttributes(props, childSvg)}`);
638
+ writer.write(`<${tag}`);
639
+ writeAttributes(writer, props, childSvg);
549
640
  if (VOID_ELEMENTS.has(tag)) {
550
641
  writer.write("/>");
551
642
  return;
@@ -571,8 +662,25 @@ var REACT_PROVIDER = /* @__PURE__ */ Symbol.for("react.provider");
571
662
  var REACT_CONTEXT = /* @__PURE__ */ Symbol.for("react.context");
572
663
  var REACT_CONSUMER = /* @__PURE__ */ Symbol.for("react.consumer");
573
664
  var REACT_LAZY = /* @__PURE__ */ Symbol.for("react.lazy");
574
- function renderComponent(type, props, writer, isSvg) {
575
- const typeOf = type?.$$typeof;
665
+ var SUSPENSE_RETRY_LIMIT = /* @__PURE__ */ Symbol("SuspenseRetryLimit");
666
+ var MAX_COMPONENT_SUSPENSE_RETRIES = 25;
667
+ function patchPromiseStatus(p) {
668
+ const w = p;
669
+ if (w.status) return;
670
+ w.status = "pending";
671
+ w.then(
672
+ (v) => {
673
+ w.status = "fulfilled";
674
+ w.value = v;
675
+ },
676
+ (r) => {
677
+ w.status = "rejected";
678
+ w.reason = r;
679
+ }
680
+ );
681
+ }
682
+ function renderComponent(type, props, writer, isSvg, _suspenseRetries = 0) {
683
+ const typeOf = type.$$typeof;
576
684
  if (typeOf === REACT_MEMO) {
577
685
  return renderNode(
578
686
  { $$typeof: SLIM_ELEMENT, type: type.type, props, key: null },
@@ -584,7 +692,23 @@ function renderComponent(type, props, writer, isSvg) {
584
692
  return renderComponent(type.render, props, writer, isSvg);
585
693
  }
586
694
  if (typeOf === REACT_LAZY) {
587
- const resolved = type._init(type._payload);
695
+ let resolved;
696
+ try {
697
+ resolved = type._init(type._payload);
698
+ } catch (e) {
699
+ if (e && typeof e.then === "function") {
700
+ if (_suspenseRetries + 1 >= MAX_COMPONENT_SUSPENSE_RETRIES) throw SUSPENSE_RETRY_LIMIT;
701
+ patchPromiseStatus(e);
702
+ const m = captureMap();
703
+ const u = captureUnsuspend();
704
+ return e.then(() => {
705
+ swapContextMap(m);
706
+ restoreUnsuspend(u);
707
+ return renderComponent(type, props, writer, isSvg, _suspenseRetries + 1);
708
+ });
709
+ }
710
+ throw e;
711
+ }
588
712
  const LazyComp = resolved?.default ?? resolved;
589
713
  return renderComponent(LazyComp, props, writer, isSvg);
590
714
  }
@@ -593,12 +717,12 @@ function renderComponent(type, props, writer, isSvg) {
593
717
  const value = ctx2 ? getContextValue(ctx2) : void 0;
594
718
  const result2 = typeof props.children === "function" ? props.children(value) : null;
595
719
  const savedScope2 = pushComponentScope();
596
- const finish2 = () => popComponentScope(savedScope2);
720
+ const finish = () => popComponentScope(savedScope2);
597
721
  const r2 = renderNode(result2, writer, isSvg);
598
722
  if (r2 && typeof r2.then === "function") {
599
- return r2.then(finish2);
723
+ return r2.then(finish);
600
724
  }
601
- finish2();
725
+ finish();
602
726
  return;
603
727
  }
604
728
  const isProvider = "_context" in type || typeOf === REACT_PROVIDER || typeOf === REACT_CONTEXT && "value" in props;
@@ -610,26 +734,29 @@ function renderComponent(type, props, writer, isSvg) {
610
734
  }
611
735
  const savedScope = pushComponentScope();
612
736
  if (isProvider && typeof type !== "function") {
613
- const finish2 = () => {
737
+ const finish = () => {
614
738
  popComponentScope(savedScope);
615
739
  popContextValue(ctx, prevCtxValue);
616
740
  };
617
741
  const r2 = renderChildren(props.children, writer, isSvg);
618
742
  if (r2 && typeof r2.then === "function") {
619
743
  const m = captureMap();
744
+ const u = captureUnsuspend();
620
745
  return r2.then(
621
746
  () => {
622
747
  swapContextMap(m);
623
- finish2();
748
+ restoreUnsuspend(u);
749
+ finish();
624
750
  },
625
751
  (e) => {
626
752
  swapContextMap(m);
627
- finish2();
753
+ restoreUnsuspend(u);
754
+ finish();
628
755
  throw e;
629
756
  }
630
757
  );
631
758
  }
632
- finish2();
759
+ finish();
633
760
  return;
634
761
  }
635
762
  let result;
@@ -649,6 +776,17 @@ function renderComponent(type, props, writer, isSvg) {
649
776
  restoreDispatcher(prevDispatcher);
650
777
  popComponentScope(savedScope);
651
778
  if (isProvider) popContextValue(ctx, prevCtxValue);
779
+ if (e && typeof e.then === "function") {
780
+ if (_suspenseRetries + 1 >= MAX_COMPONENT_SUSPENSE_RETRIES) throw SUSPENSE_RETRY_LIMIT;
781
+ patchPromiseStatus(e);
782
+ const m = captureMap();
783
+ const u = captureUnsuspend();
784
+ return e.then(() => {
785
+ swapContextMap(m);
786
+ restoreUnsuspend(u);
787
+ return renderComponent(type, props, writer, isSvg, _suspenseRetries + 1);
788
+ });
789
+ }
652
790
  throw e;
653
791
  }
654
792
  restoreDispatcher(prevDispatcher);
@@ -656,97 +794,93 @@ function renderComponent(type, props, writer, isSvg) {
656
794
  if (!(result instanceof Promise) && componentCalledUseId()) {
657
795
  savedIdTree = pushTreeContext(1, 0);
658
796
  }
659
- const finish = () => {
660
- if (savedIdTree !== void 0) popTreeContext(savedIdTree);
661
- popComponentScope(savedScope);
662
- if (isProvider) popContextValue(ctx, prevCtxValue);
663
- };
664
797
  if (result instanceof Promise) {
665
798
  const m = captureMap();
799
+ const u = captureUnsuspend();
666
800
  return result.then((resolved) => {
667
801
  swapContextMap(m);
802
+ restoreUnsuspend(u);
668
803
  let asyncSavedIdTree;
669
804
  if (componentCalledUseId()) {
670
805
  asyncSavedIdTree = pushTreeContext(1, 0);
671
806
  }
672
- const asyncFinish = () => {
673
- if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
674
- popComponentScope(savedScope);
675
- if (isProvider) popContextValue(ctx, prevCtxValue);
676
- };
677
807
  const r2 = renderNode(resolved, writer, isSvg);
678
808
  if (r2 && typeof r2.then === "function") {
679
809
  const m2 = captureMap();
810
+ const u2 = captureUnsuspend();
680
811
  return r2.then(
681
812
  () => {
682
813
  swapContextMap(m2);
683
- asyncFinish();
814
+ restoreUnsuspend(u2);
815
+ if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
816
+ popComponentScope(savedScope);
817
+ if (isProvider) popContextValue(ctx, prevCtxValue);
684
818
  },
685
819
  (e) => {
686
820
  swapContextMap(m2);
687
- asyncFinish();
821
+ restoreUnsuspend(u2);
822
+ if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
823
+ popComponentScope(savedScope);
824
+ if (isProvider) popContextValue(ctx, prevCtxValue);
688
825
  throw e;
689
826
  }
690
827
  );
691
828
  }
692
- asyncFinish();
829
+ if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
830
+ popComponentScope(savedScope);
831
+ if (isProvider) popContextValue(ctx, prevCtxValue);
693
832
  }, (e) => {
694
833
  swapContextMap(m);
695
- finish();
834
+ restoreUnsuspend(u);
835
+ popComponentScope(savedScope);
836
+ if (isProvider) popContextValue(ctx, prevCtxValue);
696
837
  throw e;
697
838
  });
698
839
  }
699
840
  const r = renderNode(result, writer, isSvg);
700
841
  if (r && typeof r.then === "function") {
701
842
  const m = captureMap();
843
+ const u = captureUnsuspend();
702
844
  return r.then(
703
845
  () => {
704
846
  swapContextMap(m);
705
- finish();
847
+ restoreUnsuspend(u);
848
+ if (savedIdTree !== void 0) popTreeContext(savedIdTree);
849
+ popComponentScope(savedScope);
850
+ if (isProvider) popContextValue(ctx, prevCtxValue);
706
851
  },
707
852
  (e) => {
708
853
  swapContextMap(m);
709
- finish();
854
+ restoreUnsuspend(u);
855
+ if (savedIdTree !== void 0) popTreeContext(savedIdTree);
856
+ popComponentScope(savedScope);
857
+ if (isProvider) popContextValue(ctx, prevCtxValue);
710
858
  throw e;
711
859
  }
712
860
  );
713
861
  }
714
- finish();
715
- }
716
- function isTextLike(node) {
717
- return typeof node === "string" || typeof node === "number";
862
+ if (savedIdTree !== void 0) popTreeContext(savedIdTree);
863
+ popComponentScope(savedScope);
864
+ if (isProvider) popContextValue(ctx, prevCtxValue);
718
865
  }
719
866
  function renderChildArray(children, writer, isSvg) {
720
- const totalChildren = children.length;
721
- for (let i = 0; i < totalChildren; i++) {
722
- if (isTextLike(children[i]) && writer.lastWasText) {
723
- writer.write("<!-- -->");
724
- }
725
- const savedTree = pushTreeContext(totalChildren, i);
726
- const r = renderNode(children[i], writer, isSvg);
727
- if (r && typeof r.then === "function") {
728
- const m = captureMap();
729
- return r.then(() => {
730
- swapContextMap(m);
731
- popTreeContext(savedTree);
732
- return renderChildArrayFrom(children, i + 1, writer, isSvg);
733
- });
734
- }
735
- popTreeContext(savedTree);
736
- }
867
+ return renderChildArrayFrom(children, 0, writer, isSvg);
737
868
  }
738
869
  function renderChildArrayFrom(children, startIndex, writer, isSvg) {
739
870
  const totalChildren = children.length;
740
871
  for (let i = startIndex; i < totalChildren; i++) {
741
- if (isTextLike(children[i]) && writer.lastWasText) {
872
+ const child = children[i];
873
+ if ((typeof child === "string" || typeof child === "number") && writer.lastWasText) {
742
874
  writer.write("<!-- -->");
743
875
  }
744
876
  const savedTree = pushTreeContext(totalChildren, i);
745
- const r = renderNode(children[i], writer, isSvg);
877
+ const r = renderNode(child, writer, isSvg);
746
878
  if (r && typeof r.then === "function") {
747
879
  const m = captureMap();
880
+ const u = captureUnsuspend();
748
881
  return r.then(() => {
749
882
  swapContextMap(m);
883
+ restoreUnsuspend(u);
750
884
  popTreeContext(savedTree);
751
885
  return renderChildArrayFrom(children, i + 1, writer, isSvg);
752
886
  });
@@ -761,118 +895,93 @@ function renderChildren(children, writer, isSvg = false) {
761
895
  }
762
896
  return renderNode(children, writer, isSvg);
763
897
  }
764
- var MAX_SUSPENSE_RETRIES = 25;
765
898
  async function renderSuspense(props, writer, isSvg = false) {
766
899
  const { children, fallback } = props;
767
- let attempts = 0;
768
900
  const snap = snapshotContext();
769
- while (attempts < MAX_SUSPENSE_RETRIES) {
770
- restoreContext(snap);
771
- let buffer = new BufferWriter();
772
- try {
773
- const r = renderNode(children, buffer, isSvg);
774
- if (r && typeof r.then === "function") {
775
- const m = captureMap();
776
- await r;
777
- swapContextMap(m);
778
- }
779
- writer.write("<!--$-->");
780
- buffer.flush(writer);
781
- writer.write("<!--/$-->");
782
- return;
783
- } catch (error) {
784
- if (error && typeof error.then === "function") {
785
- const m = captureMap();
786
- await error;
787
- swapContextMap(m);
788
- attempts++;
789
- } else {
790
- throw error;
791
- }
792
- }
793
- }
794
- restoreContext(snap);
795
- writer.write("<!--$?-->");
796
- if (fallback) {
797
- const r = renderNode(fallback, writer, isSvg);
901
+ const savedMap = captureMap();
902
+ const savedMapClone = savedMap ? new Map(savedMap) : null;
903
+ const buffer = new BufferWriter();
904
+ try {
905
+ const r = renderNode(children, buffer, isSvg);
798
906
  if (r && typeof r.then === "function") {
799
907
  const m = captureMap();
908
+ const u = captureUnsuspend();
800
909
  await r;
801
910
  swapContextMap(m);
911
+ restoreUnsuspend(u);
802
912
  }
803
- }
804
- writer.write("<!--/$-->");
805
- }
806
- async function renderToString(element, options) {
807
- const idPrefix = options?.identifierPrefix ?? "";
808
- const contextMap = /* @__PURE__ */ new Map();
809
- const prev = swapContextMap(contextMap);
810
- try {
811
- for (let attempt = 0; attempt < MAX_SUSPENSE_RETRIES; attempt++) {
812
- resetRenderState(idPrefix);
813
- swapContextMap(contextMap);
814
- const chunks = [];
815
- const writer = {
816
- lastWasText: false,
817
- write(c) {
818
- chunks.push(c);
819
- this.lastWasText = false;
820
- },
821
- text(s2) {
822
- chunks.push(s2);
823
- this.lastWasText = true;
824
- }
825
- };
826
- try {
827
- const r = renderNode(element, writer);
913
+ writer.write("<!--$-->");
914
+ buffer.flushTo(writer);
915
+ writer.write("<!--/$-->");
916
+ writer.flush?.();
917
+ } catch (error) {
918
+ if (error === SUSPENSE_RETRY_LIMIT) {
919
+ restoreContext(snap);
920
+ swapContextMap(savedMapClone);
921
+ writer.write("<!--$?-->");
922
+ if (fallback) {
923
+ const r = renderNode(fallback, writer, isSvg);
828
924
  if (r && typeof r.then === "function") {
829
925
  const m = captureMap();
926
+ const u = captureUnsuspend();
830
927
  await r;
831
928
  swapContextMap(m);
929
+ restoreUnsuspend(u);
832
930
  }
833
- return chunks.join("");
834
- } catch (error) {
835
- if (error && typeof error.then === "function") {
836
- const m = captureMap();
837
- await error;
838
- swapContextMap(m);
839
- continue;
840
- }
841
- throw error;
842
931
  }
932
+ writer.write("<!--/$-->");
933
+ } else {
934
+ throw error;
935
+ }
936
+ }
937
+ }
938
+ var _streamEncoder = new TextEncoder();
939
+ async function renderToString(element, options) {
940
+ const idPrefix = options?.identifierPrefix ?? "";
941
+ const prev = swapContextMap(null);
942
+ let output = "";
943
+ const writer = {
944
+ lastWasText: false,
945
+ write(c) {
946
+ output += c;
947
+ this.lastWasText = false;
948
+ },
949
+ text(s2) {
950
+ output += s2;
951
+ this.lastWasText = true;
843
952
  }
844
- throw new Error("[slim-react] renderToString exceeded maximum retries");
953
+ };
954
+ try {
955
+ resetRenderState(idPrefix);
956
+ const r = renderNode(element, writer);
957
+ if (r && typeof r.then === "function") {
958
+ const m = captureMap();
959
+ await r;
960
+ swapContextMap(m);
961
+ }
962
+ return output;
845
963
  } finally {
846
964
  swapContextMap(prev);
847
965
  }
848
966
  }
849
967
 
850
- // src/ssr-render-worker.ts
851
- var { ssrBundlePath } = workerData;
852
- var _ssrMod = null;
853
- async function init() {
854
- if (_ssrMod) return;
855
- _ssrMod = await import(pathToFileURL(ssrBundlePath).href);
856
- }
857
- function deserializeRequest(s2) {
858
- const init2 = { method: s2.method, headers: new Headers(s2.headers) };
859
- if (s2.body) init2.body = s2.body.buffer;
860
- const req = new Request(s2.url, init2);
861
- Object.assign(req, { pathname: s2.pathname, search: s2.search, location: s2.location, cookies: s2.cookies });
862
- return req;
863
- }
968
+ // src/utils/response.tsx
864
969
  var ESC = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" };
865
970
  var escAttr = (s2) => s2.replace(/[&<>"]/g, (c) => ESC[c] ?? c);
866
971
  var escText = (s2) => s2.replace(/[&<>]/g, (c) => ESC[c] ?? c);
867
- var HEAD_ATTR = {
972
+ var ATTR = {
868
973
  className: "class",
869
974
  htmlFor: "for",
870
975
  httpEquiv: "http-equiv",
871
976
  charSet: "charset",
872
- crossOrigin: "crossorigin"
977
+ crossOrigin: "crossorigin",
978
+ noModule: "nomodule",
979
+ referrerPolicy: "referrerpolicy",
980
+ fetchPriority: "fetchpriority",
981
+ hrefLang: "hreflang"
873
982
  };
874
983
  function renderHeadTag(tag, id, opts, selfClose = false) {
875
- let a = ` id="${escAttr(id)}"`;
984
+ let attrs = ` id="${escAttr(id)}"`;
876
985
  let inner = "";
877
986
  for (const [k, v] of Object.entries(opts)) {
878
987
  if (k === "key" || k === "children") continue;
@@ -880,24 +989,39 @@ function renderHeadTag(tag, id, opts, selfClose = false) {
880
989
  inner = v.__html ?? "";
881
990
  continue;
882
991
  }
883
- const attr = HEAD_ATTR[k] ?? k;
884
- if (v === true) a += ` ${attr}`;
885
- else if (v !== false && v != null) a += ` ${attr}="${escAttr(String(v))}"`;
992
+ const attr = ATTR[k] ?? k;
993
+ if (v === true) attrs += ` ${attr}`;
994
+ else if (v !== false && v != null) attrs += ` ${attr}="${escAttr(String(v))}"`;
886
995
  }
887
- return selfClose ? `<${tag}${a}>` : `<${tag}${a}>${inner}</${tag}>`;
996
+ return selfClose ? `<${tag}${attrs}>` : `<${tag}${attrs}>${inner}</${tag}>`;
888
997
  }
889
- function buildHeadHtml(head) {
890
- let html = `<title>${escText(head.title ?? "")}</title>`;
891
- for (const [id, opts] of Object.entries(head.meta ?? {}))
998
+ function buildHeadHtml(seoData) {
999
+ let html = `<title>${escText(seoData.title ?? "")}</title>`;
1000
+ for (const [id, opts] of Object.entries(seoData.meta))
892
1001
  html += renderHeadTag("meta", id, opts, true);
893
- for (const [id, opts] of Object.entries(head.link ?? {}))
1002
+ for (const [id, opts] of Object.entries(seoData.link))
894
1003
  html += renderHeadTag("link", id, opts, true);
895
- for (const [id, opts] of Object.entries(head.style ?? {}))
1004
+ for (const [id, opts] of Object.entries(seoData.style))
896
1005
  html += renderHeadTag("style", id, opts);
897
- for (const [id, opts] of Object.entries(head.script ?? {}))
1006
+ for (const [id, opts] of Object.entries(seoData.script))
898
1007
  html += renderHeadTag("script", id, opts);
899
1008
  return html;
900
1009
  }
1010
+
1011
+ // src/ssr-render-worker.ts
1012
+ var { ssrBundlePath } = workerData;
1013
+ var _ssrMod = null;
1014
+ async function init() {
1015
+ if (_ssrMod) return;
1016
+ _ssrMod = await import(pathToFileURL(ssrBundlePath).href);
1017
+ }
1018
+ function deserializeRequest(s2) {
1019
+ const init2 = { method: s2.method, headers: new Headers(s2.headers) };
1020
+ if (s2.body) init2.body = s2.body.buffer;
1021
+ const req = new Request(s2.url, init2);
1022
+ Object.assign(req, { pathname: s2.pathname, search: s2.search, location: s2.location, cookies: s2.cookies });
1023
+ return req;
1024
+ }
901
1025
  async function runFullLifecycle(serialReq) {
902
1026
  const Component = _ssrMod.default;
903
1027
  const { getInitProps, getFinalProps } = _ssrMod;
@@ -918,19 +1042,25 @@ async function runFullLifecycle(serialReq) {
918
1042
  } finally {
919
1043
  globalThis.__hadarsUnsuspend = null;
920
1044
  }
1045
+ const headHtml = buildHeadHtml(context.head);
1046
+ const status = context.head.status ?? 200;
921
1047
  const { context: _ctx, ...restProps } = getFinalProps ? await getFinalProps(props) : props;
922
1048
  const serverData = {};
1049
+ let hasServerData = false;
923
1050
  for (const [key, entry] of unsuspend.cache) {
924
- if (entry.status === "fulfilled") serverData[key] = entry.value;
1051
+ if (entry.status === "fulfilled") {
1052
+ serverData[key] = entry.value;
1053
+ hasServerData = true;
1054
+ }
925
1055
  }
926
1056
  const clientProps = {
927
1057
  ...restProps,
928
1058
  location: serialReq.location,
929
- ...Object.keys(serverData).length > 0 ? { __serverData: serverData } : {}
1059
+ ...hasServerData ? { __serverData: serverData } : {}
930
1060
  };
931
1061
  const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
932
1062
  const html = `<div id="app">${appHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>`;
933
- return { html, headHtml: buildHeadHtml(context.head), status: context.head.status ?? 200 };
1063
+ return { html, headHtml, status };
934
1064
  }
935
1065
  parentPort.on("message", async (msg) => {
936
1066
  const { id, type, request } = msg;