hadars 0.1.23 → 0.1.25

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.
@@ -9,6 +9,35 @@ import {
9
9
  } from "../chunk-OS3V4CPN.js";
10
10
 
11
11
  // src/slim-react/renderContext.ts
12
+ var MAP_KEY = "__slimReactContextMap";
13
+ var _g = globalThis;
14
+ if (!("__slimReactContextMap" in _g))
15
+ _g[MAP_KEY] = null;
16
+ function swapContextMap(map) {
17
+ const prev = _g[MAP_KEY];
18
+ _g[MAP_KEY] = map;
19
+ return prev;
20
+ }
21
+ function captureMap() {
22
+ return _g[MAP_KEY];
23
+ }
24
+ function getContextValue(context) {
25
+ const map = _g[MAP_KEY];
26
+ if (map && map.has(context))
27
+ return map.get(context);
28
+ const c = context;
29
+ return "_defaultValue" in c ? c._defaultValue : c._currentValue;
30
+ }
31
+ function pushContextValue(context, value) {
32
+ const map = _g[MAP_KEY];
33
+ const c = context;
34
+ const prev = map && map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
35
+ map?.set(context, value);
36
+ return prev;
37
+ }
38
+ function popContextValue(context, prev) {
39
+ _g[MAP_KEY]?.set(context, prev);
40
+ }
12
41
  var GLOBAL_KEY = "__slimReactRenderState";
13
42
  var EMPTY = { id: 0, overflow: "", bits: 0 };
14
43
  function s() {
@@ -134,8 +163,8 @@ function useActionState(_action, initialState, _permalink) {
134
163
  }, false];
135
164
  }
136
165
  function use(usable) {
137
- if (typeof usable === "object" && usable !== null && "_currentValue" in usable) {
138
- return usable._currentValue;
166
+ if (typeof usable === "object" && usable !== null && ("_currentValue" in usable || "_defaultValue" in usable)) {
167
+ return getContextValue(usable);
139
168
  }
140
169
  const promise = usable;
141
170
  if (promise.status === "fulfilled")
@@ -151,6 +180,7 @@ function startTransition(callback) {
151
180
  // src/slim-react/context.ts
152
181
  function createContext(defaultValue) {
153
182
  const context = {
183
+ _defaultValue: defaultValue,
154
184
  _currentValue: defaultValue,
155
185
  Provider: null,
156
186
  Consumer: null
@@ -526,7 +556,7 @@ function renderComponent(type, props, writer, isSvg) {
526
556
  }
527
557
  if (typeOf === REACT_CONSUMER) {
528
558
  const ctx2 = type._context;
529
- const value = ctx2?._currentValue;
559
+ const value = ctx2 ? getContextValue(ctx2) : void 0;
530
560
  const result2 = typeof props.children === "function" ? props.children(value) : null;
531
561
  const savedScope2 = pushComponentScope();
532
562
  const finish2 = () => popComponentScope(savedScope2);
@@ -542,18 +572,28 @@ function renderComponent(type, props, writer, isSvg) {
542
572
  let ctx;
543
573
  if (isProvider) {
544
574
  ctx = type._context ?? type;
545
- prevCtxValue = ctx._currentValue;
546
- ctx._currentValue = props.value;
575
+ prevCtxValue = pushContextValue(ctx, props.value);
547
576
  }
548
577
  const savedScope = pushComponentScope();
549
578
  if (isProvider && typeof type !== "function") {
550
579
  const finish2 = () => {
551
580
  popComponentScope(savedScope);
552
- ctx._currentValue = prevCtxValue;
581
+ popContextValue(ctx, prevCtxValue);
553
582
  };
554
583
  const r2 = renderChildren(props.children, writer, isSvg);
555
584
  if (r2 && typeof r2.then === "function") {
556
- return r2.then(finish2);
585
+ const m = captureMap();
586
+ return r2.then(
587
+ () => {
588
+ swapContextMap(m);
589
+ finish2();
590
+ },
591
+ (e) => {
592
+ swapContextMap(m);
593
+ finish2();
594
+ throw e;
595
+ }
596
+ );
557
597
  }
558
598
  finish2();
559
599
  return;
@@ -574,26 +614,54 @@ function renderComponent(type, props, writer, isSvg) {
574
614
  } catch (e) {
575
615
  popComponentScope(savedScope);
576
616
  if (isProvider)
577
- ctx._currentValue = prevCtxValue;
617
+ popContextValue(ctx, prevCtxValue);
578
618
  throw e;
579
619
  }
580
620
  const finish = () => {
581
621
  popComponentScope(savedScope);
582
622
  if (isProvider)
583
- ctx._currentValue = prevCtxValue;
623
+ popContextValue(ctx, prevCtxValue);
584
624
  };
585
625
  if (result instanceof Promise) {
626
+ const m = captureMap();
586
627
  return result.then((resolved) => {
628
+ swapContextMap(m);
587
629
  const r2 = renderNode(resolved, writer, isSvg);
588
630
  if (r2 && typeof r2.then === "function") {
589
- return r2.then(finish);
631
+ const m2 = captureMap();
632
+ return r2.then(
633
+ () => {
634
+ swapContextMap(m2);
635
+ finish();
636
+ },
637
+ (e) => {
638
+ swapContextMap(m2);
639
+ finish();
640
+ throw e;
641
+ }
642
+ );
590
643
  }
591
644
  finish();
645
+ }, (e) => {
646
+ swapContextMap(m);
647
+ finish();
648
+ throw e;
592
649
  });
593
650
  }
594
651
  const r = renderNode(result, writer, isSvg);
595
652
  if (r && typeof r.then === "function") {
596
- return r.then(finish);
653
+ const m = captureMap();
654
+ return r.then(
655
+ () => {
656
+ swapContextMap(m);
657
+ finish();
658
+ },
659
+ (e) => {
660
+ swapContextMap(m);
661
+ finish();
662
+ throw e;
663
+ }
664
+ );
597
665
  }
598
666
  finish();
599
667
  }
@@ -609,7 +677,9 @@ function renderChildArray(children, writer, isSvg) {
609
677
  const savedTree = pushTreeContext(totalChildren, i);
610
678
  const r = renderNode(children[i], writer, isSvg);
611
679
  if (r && typeof r.then === "function") {
680
+ const m = captureMap();
612
681
  return r.then(() => {
682
+ swapContextMap(m);
613
683
  popTreeContext(savedTree);
614
684
  return renderChildArrayFrom(children, i + 1, writer, isSvg);
615
685
  });
@@ -626,7 +696,9 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
626
696
  const savedTree = pushTreeContext(totalChildren, i);
627
697
  const r = renderNode(children[i], writer, isSvg);
628
698
  if (r && typeof r.then === "function") {
699
+ const m = captureMap();
629
700
  return r.then(() => {
701
+ swapContextMap(m);
630
702
  popTreeContext(savedTree);
631
703
  return renderChildArrayFrom(children, i + 1, writer, isSvg);
632
704
  });
@@ -653,7 +725,9 @@ async function renderSuspense(props, writer, isSvg = false) {
653
725
  const buffer = new BufferWriter();
654
726
  const r = renderNode(children, buffer, isSvg);
655
727
  if (r && typeof r.then === "function") {
728
+ const m = captureMap();
656
729
  await r;
730
+ swapContextMap(m);
657
731
  }
658
732
  writer.write("<!--$-->");
659
733
  buffer.flush(writer);
@@ -661,7 +735,9 @@ async function renderSuspense(props, writer, isSvg = false) {
661
735
  return;
662
736
  } catch (error) {
663
737
  if (error && typeof error.then === "function") {
738
+ const m = captureMap();
664
739
  await error;
740
+ swapContextMap(m);
665
741
  attempts++;
666
742
  } else {
667
743
  throw error;
@@ -672,16 +748,21 @@ async function renderSuspense(props, writer, isSvg = false) {
672
748
  writer.write("<!--$?-->");
673
749
  if (fallback) {
674
750
  const r = renderNode(fallback, writer, isSvg);
675
- if (r && typeof r.then === "function")
751
+ if (r && typeof r.then === "function") {
752
+ const m = captureMap();
676
753
  await r;
754
+ swapContextMap(m);
755
+ }
677
756
  }
678
757
  writer.write("<!--/$-->");
679
758
  }
680
759
  function renderToStream(element) {
681
760
  const encoder = new TextEncoder();
761
+ const contextMap = /* @__PURE__ */ new Map();
682
762
  return new ReadableStream({
683
763
  async start(controller) {
684
764
  resetRenderState();
765
+ const prev = swapContextMap(contextMap);
685
766
  const writer = {
686
767
  lastWasText: false,
687
768
  write(chunk) {
@@ -695,49 +776,66 @@ function renderToStream(element) {
695
776
  };
696
777
  try {
697
778
  const r = renderNode(element, writer);
698
- if (r && typeof r.then === "function")
779
+ if (r && typeof r.then === "function") {
780
+ const m = captureMap();
699
781
  await r;
782
+ swapContextMap(m);
783
+ }
700
784
  controller.close();
701
785
  } catch (error) {
702
786
  controller.error(error);
787
+ } finally {
788
+ swapContextMap(prev);
703
789
  }
704
790
  }
705
791
  });
706
792
  }
707
793
  async function renderToString(element) {
708
- for (let attempt = 0; attempt < MAX_SUSPENSE_RETRIES; attempt++) {
709
- resetRenderState();
710
- const chunks = [];
711
- const writer = {
712
- lastWasText: false,
713
- write(c) {
714
- chunks.push(c);
715
- this.lastWasText = false;
716
- },
717
- text(s2) {
718
- chunks.push(s2);
719
- this.lastWasText = true;
720
- }
721
- };
722
- try {
723
- const r = renderNode(element, writer);
724
- if (r && typeof r.then === "function")
725
- await r;
726
- return chunks.join("");
727
- } catch (error) {
728
- if (error && typeof error.then === "function") {
729
- await error;
730
- continue;
794
+ const contextMap = /* @__PURE__ */ new Map();
795
+ const prev = swapContextMap(contextMap);
796
+ try {
797
+ for (let attempt = 0; attempt < MAX_SUSPENSE_RETRIES; attempt++) {
798
+ resetRenderState();
799
+ swapContextMap(contextMap);
800
+ const chunks = [];
801
+ const writer = {
802
+ lastWasText: false,
803
+ write(c) {
804
+ chunks.push(c);
805
+ this.lastWasText = false;
806
+ },
807
+ text(s2) {
808
+ chunks.push(s2);
809
+ this.lastWasText = true;
810
+ }
811
+ };
812
+ try {
813
+ const r = renderNode(element, writer);
814
+ if (r && typeof r.then === "function") {
815
+ const m = captureMap();
816
+ await r;
817
+ swapContextMap(m);
818
+ }
819
+ return chunks.join("");
820
+ } catch (error) {
821
+ if (error && typeof error.then === "function") {
822
+ const m = captureMap();
823
+ await error;
824
+ swapContextMap(m);
825
+ continue;
826
+ }
827
+ throw error;
731
828
  }
732
- throw error;
733
829
  }
830
+ throw new Error("[slim-react] renderToString exceeded maximum retries");
831
+ } finally {
832
+ swapContextMap(prev);
734
833
  }
735
- throw new Error("[slim-react] renderToString exceeded maximum retries");
736
834
  }
737
835
 
738
836
  // src/slim-react/index.ts
739
837
  function useContext(context) {
740
- return context._currentValue;
838
+ return getContextValue(context);
741
839
  }
742
840
  var Suspense = SUSPENSE_TYPE;
743
841
  function isValidElement(obj) {
@@ -67,6 +67,35 @@ function createElement(type, props, ...children) {
67
67
  }
68
68
 
69
69
  // src/slim-react/renderContext.ts
70
+ var MAP_KEY = "__slimReactContextMap";
71
+ var _g = globalThis;
72
+ if (!("__slimReactContextMap" in _g))
73
+ _g[MAP_KEY] = null;
74
+ function swapContextMap(map) {
75
+ const prev = _g[MAP_KEY];
76
+ _g[MAP_KEY] = map;
77
+ return prev;
78
+ }
79
+ function captureMap() {
80
+ return _g[MAP_KEY];
81
+ }
82
+ function getContextValue(context) {
83
+ const map = _g[MAP_KEY];
84
+ if (map && map.has(context))
85
+ return map.get(context);
86
+ const c = context;
87
+ return "_defaultValue" in c ? c._defaultValue : c._currentValue;
88
+ }
89
+ function pushContextValue(context, value) {
90
+ const map = _g[MAP_KEY];
91
+ const c = context;
92
+ const prev = map && map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
93
+ map?.set(context, value);
94
+ return prev;
95
+ }
96
+ function popContextValue(context, prev) {
97
+ _g[MAP_KEY]?.set(context, prev);
98
+ }
70
99
  var GLOBAL_KEY = "__slimReactRenderState";
71
100
  var EMPTY = { id: 0, overflow: "", bits: 0 };
72
101
  function s() {
@@ -479,7 +508,7 @@ function renderComponent(type, props, writer, isSvg) {
479
508
  }
480
509
  if (typeOf === REACT_CONSUMER) {
481
510
  const ctx2 = type._context;
482
- const value = ctx2?._currentValue;
511
+ const value = ctx2 ? getContextValue(ctx2) : void 0;
483
512
  const result2 = typeof props.children === "function" ? props.children(value) : null;
484
513
  const savedScope2 = pushComponentScope();
485
514
  const finish2 = () => popComponentScope(savedScope2);
@@ -495,18 +524,28 @@ function renderComponent(type, props, writer, isSvg) {
495
524
  let ctx;
496
525
  if (isProvider) {
497
526
  ctx = type._context ?? type;
498
- prevCtxValue = ctx._currentValue;
499
- ctx._currentValue = props.value;
527
+ prevCtxValue = pushContextValue(ctx, props.value);
500
528
  }
501
529
  const savedScope = pushComponentScope();
502
530
  if (isProvider && typeof type !== "function") {
503
531
  const finish2 = () => {
504
532
  popComponentScope(savedScope);
505
- ctx._currentValue = prevCtxValue;
533
+ popContextValue(ctx, prevCtxValue);
506
534
  };
507
535
  const r2 = renderChildren(props.children, writer, isSvg);
508
536
  if (r2 && typeof r2.then === "function") {
509
- return r2.then(finish2);
537
+ const m = captureMap();
538
+ return r2.then(
539
+ () => {
540
+ swapContextMap(m);
541
+ finish2();
542
+ },
543
+ (e) => {
544
+ swapContextMap(m);
545
+ finish2();
546
+ throw e;
547
+ }
548
+ );
510
549
  }
511
550
  finish2();
512
551
  return;
@@ -527,26 +566,54 @@ function renderComponent(type, props, writer, isSvg) {
527
566
  } catch (e) {
528
567
  popComponentScope(savedScope);
529
568
  if (isProvider)
530
- ctx._currentValue = prevCtxValue;
569
+ popContextValue(ctx, prevCtxValue);
531
570
  throw e;
532
571
  }
533
572
  const finish = () => {
534
573
  popComponentScope(savedScope);
535
574
  if (isProvider)
536
- ctx._currentValue = prevCtxValue;
575
+ popContextValue(ctx, prevCtxValue);
537
576
  };
538
577
  if (result instanceof Promise) {
578
+ const m = captureMap();
539
579
  return result.then((resolved) => {
580
+ swapContextMap(m);
540
581
  const r2 = renderNode(resolved, writer, isSvg);
541
582
  if (r2 && typeof r2.then === "function") {
542
- return r2.then(finish);
583
+ const m2 = captureMap();
584
+ return r2.then(
585
+ () => {
586
+ swapContextMap(m2);
587
+ finish();
588
+ },
589
+ (e) => {
590
+ swapContextMap(m2);
591
+ finish();
592
+ throw e;
593
+ }
594
+ );
543
595
  }
544
596
  finish();
597
+ }, (e) => {
598
+ swapContextMap(m);
599
+ finish();
600
+ throw e;
545
601
  });
546
602
  }
547
603
  const r = renderNode(result, writer, isSvg);
548
604
  if (r && typeof r.then === "function") {
549
- return r.then(finish);
605
+ const m = captureMap();
606
+ return r.then(
607
+ () => {
608
+ swapContextMap(m);
609
+ finish();
610
+ },
611
+ (e) => {
612
+ swapContextMap(m);
613
+ finish();
614
+ throw e;
615
+ }
616
+ );
550
617
  }
551
618
  finish();
552
619
  }
@@ -562,7 +629,9 @@ function renderChildArray(children, writer, isSvg) {
562
629
  const savedTree = pushTreeContext(totalChildren, i);
563
630
  const r = renderNode(children[i], writer, isSvg);
564
631
  if (r && typeof r.then === "function") {
632
+ const m = captureMap();
565
633
  return r.then(() => {
634
+ swapContextMap(m);
566
635
  popTreeContext(savedTree);
567
636
  return renderChildArrayFrom(children, i + 1, writer, isSvg);
568
637
  });
@@ -579,7 +648,9 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
579
648
  const savedTree = pushTreeContext(totalChildren, i);
580
649
  const r = renderNode(children[i], writer, isSvg);
581
650
  if (r && typeof r.then === "function") {
651
+ const m = captureMap();
582
652
  return r.then(() => {
653
+ swapContextMap(m);
583
654
  popTreeContext(savedTree);
584
655
  return renderChildArrayFrom(children, i + 1, writer, isSvg);
585
656
  });
@@ -606,7 +677,9 @@ async function renderSuspense(props, writer, isSvg = false) {
606
677
  const buffer = new BufferWriter();
607
678
  const r = renderNode(children, buffer, isSvg);
608
679
  if (r && typeof r.then === "function") {
680
+ const m = captureMap();
609
681
  await r;
682
+ swapContextMap(m);
610
683
  }
611
684
  writer.write("<!--$-->");
612
685
  buffer.flush(writer);
@@ -614,7 +687,9 @@ async function renderSuspense(props, writer, isSvg = false) {
614
687
  return;
615
688
  } catch (error) {
616
689
  if (error && typeof error.then === "function") {
690
+ const m = captureMap();
617
691
  await error;
692
+ swapContextMap(m);
618
693
  attempts++;
619
694
  } else {
620
695
  throw error;
@@ -625,40 +700,55 @@ async function renderSuspense(props, writer, isSvg = false) {
625
700
  writer.write("<!--$?-->");
626
701
  if (fallback) {
627
702
  const r = renderNode(fallback, writer, isSvg);
628
- if (r && typeof r.then === "function")
703
+ if (r && typeof r.then === "function") {
704
+ const m = captureMap();
629
705
  await r;
706
+ swapContextMap(m);
707
+ }
630
708
  }
631
709
  writer.write("<!--/$-->");
632
710
  }
633
711
  async function renderToString(element) {
634
- for (let attempt = 0; attempt < MAX_SUSPENSE_RETRIES; attempt++) {
635
- resetRenderState();
636
- const chunks = [];
637
- const writer = {
638
- lastWasText: false,
639
- write(c) {
640
- chunks.push(c);
641
- this.lastWasText = false;
642
- },
643
- text(s2) {
644
- chunks.push(s2);
645
- this.lastWasText = true;
646
- }
647
- };
648
- try {
649
- const r = renderNode(element, writer);
650
- if (r && typeof r.then === "function")
651
- await r;
652
- return chunks.join("");
653
- } catch (error) {
654
- if (error && typeof error.then === "function") {
655
- await error;
656
- continue;
712
+ const contextMap = /* @__PURE__ */ new Map();
713
+ const prev = swapContextMap(contextMap);
714
+ try {
715
+ for (let attempt = 0; attempt < MAX_SUSPENSE_RETRIES; attempt++) {
716
+ resetRenderState();
717
+ swapContextMap(contextMap);
718
+ const chunks = [];
719
+ const writer = {
720
+ lastWasText: false,
721
+ write(c) {
722
+ chunks.push(c);
723
+ this.lastWasText = false;
724
+ },
725
+ text(s2) {
726
+ chunks.push(s2);
727
+ this.lastWasText = true;
728
+ }
729
+ };
730
+ try {
731
+ const r = renderNode(element, writer);
732
+ if (r && typeof r.then === "function") {
733
+ const m = captureMap();
734
+ await r;
735
+ swapContextMap(m);
736
+ }
737
+ return chunks.join("");
738
+ } catch (error) {
739
+ if (error && typeof error.then === "function") {
740
+ const m = captureMap();
741
+ await error;
742
+ swapContextMap(m);
743
+ continue;
744
+ }
745
+ throw error;
657
746
  }
658
- throw error;
659
747
  }
748
+ throw new Error("[slim-react] renderToString exceeded maximum retries");
749
+ } finally {
750
+ swapContextMap(prev);
660
751
  }
661
- throw new Error("[slim-react] renderToString exceeded maximum retries");
662
752
  }
663
753
 
664
754
  // src/ssr-render-worker.ts
package/dist/ssr-watch.js CHANGED
@@ -179,6 +179,12 @@ var buildCompilerConfig = (entry2, opts, includeHotPlugin) => {
179
179
  "@emotion/styled": path.resolve(process.cwd(), "node_modules", "@emotion", "styled")
180
180
  } : void 0;
181
181
  const externals = isServerBuild ? [
182
+ // Node.js built-ins — must not be bundled; resolved by the runtime.
183
+ "node:fs",
184
+ "node:path",
185
+ "node:os",
186
+ "node:stream",
187
+ "node:util",
182
188
  // react / react-dom are replaced by slim-react via alias above — not external.
183
189
  // emotion should be external on server builds to avoid client/browser code
184
190
  "@emotion/react",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hadars",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "Minimal SSR framework for React — rspack, HMR, TypeScript, Bun/Node/Deno",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",
@@ -9,7 +9,8 @@ import type { SlimNode } from "./types";
9
9
  */
10
10
 
11
11
  export interface Context<T> {
12
- _currentValue: T;
12
+ _defaultValue: T;
13
+ _currentValue: T; // kept for external compat (real React contexts passed to useContext)
13
14
  Provider: ContextProvider<T>;
14
15
  Consumer: (props: { children: (value: T) => SlimNode }) => SlimNode;
15
16
  }
@@ -23,6 +24,7 @@ export type ContextProvider<T> = ((props: {
23
24
 
24
25
  export function createContext<T>(defaultValue: T): Context<T> {
25
26
  const context: Context<T> = {
27
+ _defaultValue: defaultValue,
26
28
  _currentValue: defaultValue,
27
29
  Provider: null!,
28
30
  Consumer: null!,
@@ -6,7 +6,7 @@
6
6
  * compatible libraries to work during server-side rendering.
7
7
  */
8
8
 
9
- import { makeId } from "./renderContext";
9
+ import { makeId, getContextValue } from "./renderContext";
10
10
 
11
11
  // ---- useState ----
12
12
  export function useState<T>(
@@ -115,9 +115,9 @@ export function use<T>(
115
115
  if (
116
116
  typeof usable === "object" &&
117
117
  usable !== null &&
118
- "_currentValue" in usable
118
+ ("_currentValue" in usable || "_defaultValue" in usable)
119
119
  ) {
120
- return (usable as { _currentValue: T })._currentValue;
120
+ return getContextValue<T>(usable as object);
121
121
  }
122
122
 
123
123
  // Promise – Suspense protocol
@@ -67,12 +67,10 @@ export {
67
67
  import { createContext } from "./context";
68
68
  export { createContext, type Context } from "./context";
69
69
 
70
- // Re-export useContext from hooks.ts? No – we have it in context.ts
71
- // Actually useContext reads from the context object, let's export a
72
- // single implementation that lives close to createContext:
70
+ import { getContextValue } from "./renderContext";
73
71
  import type { Context } from "./context";
74
72
  export function useContext<T>(context: Context<T>): T {
75
- return context._currentValue;
73
+ return getContextValue<T>(context);
76
74
  }
77
75
 
78
76
  // ---- Rendering ----