@oomfware/jsx 0.1.4 → 0.1.6

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,6 +1,14 @@
1
1
  import { describe, expect, it } from 'bun:test';
2
2
 
3
- import { createContext, render, renderToStream, renderToString, Suspense, use } from '../index.ts';
3
+ import {
4
+ createContext,
5
+ ErrorBoundary,
6
+ render,
7
+ renderToStream,
8
+ renderToString,
9
+ Suspense,
10
+ use,
11
+ } from '../index.ts';
4
12
 
5
13
  // suspense runtime script (injected once before first resolution)
6
14
  const SR = '$sr';
@@ -171,6 +179,43 @@ describe('stream', () => {
171
179
  const html = await renderToString(<button onclick={() => {}} />);
172
180
  expect(html).toBe('<button></button>');
173
181
  });
182
+
183
+ it('renders string class as-is', async () => {
184
+ const html = await renderToString(<div class="foo bar" />);
185
+ expect(html).toBe('<div class="foo bar"></div>');
186
+ });
187
+
188
+ it('concatenates class array', async () => {
189
+ const html = await renderToString(<div class={['foo', 'bar', 'baz']} />);
190
+ expect(html).toBe('<div class="foo bar baz"></div>');
191
+ });
192
+
193
+ it('filters out falsy values from class array', async () => {
194
+ const html = await renderToString(<div class={['foo', false, 'bar', null, 'baz', undefined, 0]} />);
195
+ expect(html).toBe('<div class="foo bar baz"></div>');
196
+ });
197
+
198
+ it('conditionally applies classes', async () => {
199
+ const isActive = true;
200
+ const isDisabled = false;
201
+ const html = await renderToString(<div class={['btn', isActive && 'active', isDisabled && 'disabled']} />);
202
+ expect(html).toBe('<div class="btn active"></div>');
203
+ });
204
+
205
+ it('omits class attribute when array is all falsy', async () => {
206
+ const html = await renderToString(<div class={[false, null, undefined, 0]} />);
207
+ expect(html).toBe('<div></div>');
208
+ });
209
+
210
+ it('handles empty class array', async () => {
211
+ const html = await renderToString(<div class={[]} />);
212
+ expect(html).toBe('<div></div>');
213
+ });
214
+
215
+ it('handles single-element class array', async () => {
216
+ const html = await renderToString(<div class={['solo']} />);
217
+ expect(html).toBe('<div class="solo"></div>');
218
+ });
174
219
  });
175
220
 
176
221
  describe('escaping', () => {
@@ -225,7 +270,7 @@ describe('stream', () => {
225
270
  const html = await renderToString(
226
271
  <div style={{ color: 'green', 'margin-top': '10px', padding: '5px' }} />,
227
272
  );
228
- expect(html).toBe('<div style="color:green;margin-top:10px;padding:5px"></div>');
273
+ expect(html).toBe('<div style="color:green; margin-top:10px; padding:5px"></div>');
229
274
  });
230
275
  });
231
276
 
@@ -621,5 +666,403 @@ describe('stream', () => {
621
666
  expect(e).toBe(error);
622
667
  }
623
668
  });
669
+
670
+ it('component throwing multiple sequential promises', async () => {
671
+ const { promise: p1, resolve: r1 } = Promise.withResolvers<string>();
672
+ const { promise: p2, resolve: r2 } = Promise.withResolvers<string>();
673
+
674
+ let callCount = 0;
675
+ function MultiAsyncComponent() {
676
+ callCount++;
677
+ const first = use(p1);
678
+ const second = use(p2);
679
+ return (
680
+ <div>
681
+ {first} {second}
682
+ </div>
683
+ );
684
+ }
685
+
686
+ const stream = renderToStream(
687
+ <Suspense fallback={<span>loading...</span>}>
688
+ <MultiAsyncComponent />
689
+ </Suspense>,
690
+ );
691
+
692
+ // resolve first promise, component will re-render and throw second
693
+ r1('hello');
694
+ await Promise.resolve();
695
+
696
+ // resolve second promise, component will complete
697
+ r2('world');
698
+
699
+ const html = await drain(stream);
700
+ expect(html).toBe(
701
+ '<!--$s:s1--><span>loading...</span><!--/$s:s1-->' +
702
+ SUSPENSE_RUNTIME +
703
+ '<template data-suspense="s1"><div>hello world</div></template>' +
704
+ SUSPENSE_CALL,
705
+ );
706
+ // component should be called multiple times as it re-renders after each promise
707
+ expect(callCount).toBeGreaterThan(1);
708
+ });
709
+
710
+ it('parallel renders have isolated context', async () => {
711
+ const ThemeContext = createContext('default');
712
+
713
+ function ThemedComponent() {
714
+ const theme = use(ThemeContext);
715
+ return <div class={theme}>content</div>;
716
+ }
717
+
718
+ // run two renders in parallel with different context values
719
+ const [html1, html2] = await Promise.all([
720
+ renderToString(
721
+ <ThemeContext.Provider value="dark">
722
+ <ThemedComponent />
723
+ </ThemeContext.Provider>,
724
+ ),
725
+ renderToString(
726
+ <ThemeContext.Provider value="light">
727
+ <ThemedComponent />
728
+ </ThemeContext.Provider>,
729
+ ),
730
+ ]);
731
+
732
+ expect(html1).toBe('<div class="dark">content</div>');
733
+ expect(html2).toBe('<div class="light">content</div>');
734
+ });
735
+
736
+ it('parallel renders with suspense have isolated context', async () => {
737
+ const ThemeContext = createContext('default');
738
+ const { promise: p1, resolve: r1 } = Promise.withResolvers<string>();
739
+ const { promise: p2, resolve: r2 } = Promise.withResolvers<string>();
740
+
741
+ function AsyncThemedComponent({ promise }: { promise: Promise<string> }) {
742
+ const theme = use(ThemeContext);
743
+ const data = use(promise);
744
+ return <div class={theme}>{data}</div>;
745
+ }
746
+
747
+ // start both renders
748
+ const render1 = renderToString(
749
+ <ThemeContext.Provider value="dark">
750
+ <Suspense fallback={<span>loading dark...</span>}>
751
+ <AsyncThemedComponent promise={p1} />
752
+ </Suspense>
753
+ </ThemeContext.Provider>,
754
+ );
755
+
756
+ const render2 = renderToString(
757
+ <ThemeContext.Provider value="light">
758
+ <Suspense fallback={<span>loading light...</span>}>
759
+ <AsyncThemedComponent promise={p2} />
760
+ </Suspense>
761
+ </ThemeContext.Provider>,
762
+ );
763
+
764
+ // resolve in reverse order to test isolation
765
+ r2('second');
766
+ r1('first');
767
+
768
+ const [html1, html2] = await Promise.all([render1, render2]);
769
+
770
+ expect(html1).toBe(
771
+ '<!--$s:s1--><span>loading dark...</span><!--/$s:s1-->' +
772
+ SUSPENSE_RUNTIME +
773
+ '<template data-suspense="s1"><div class="dark">first</div></template>' +
774
+ SUSPENSE_CALL,
775
+ );
776
+ expect(html2).toBe(
777
+ '<!--$s:s1--><span>loading light...</span><!--/$s:s1-->' +
778
+ SUSPENSE_RUNTIME +
779
+ '<template data-suspense="s1"><div class="light">second</div></template>' +
780
+ SUSPENSE_CALL,
781
+ );
782
+ });
783
+
784
+ it('throws error when suspense exceeds max retry attempts', async () => {
785
+ let throwCount = 0;
786
+ function InfiniteThrowComponent(): never {
787
+ throwCount++;
788
+ // always throw a new promise
789
+ throw Promise.resolve();
790
+ }
791
+
792
+ const errors: unknown[] = [];
793
+ try {
794
+ await renderToString(
795
+ <Suspense fallback={<div>loading...</div>}>
796
+ <InfiniteThrowComponent />
797
+ </Suspense>,
798
+ { onError: (e) => errors.push(e) },
799
+ );
800
+ } catch {
801
+ // expected - error propagates through stream
802
+ }
803
+
804
+ expect(throwCount).toBe(20); // 1 initial + 19 retries, error thrown before 20th retry
805
+ expect(errors.length).toBe(1);
806
+ expect((errors[0] as Error).message).toBe('suspense boundary exceeded maximum retry attempts (20)');
807
+ });
808
+ });
809
+
810
+ describe('error boundary', () => {
811
+ it('catches sync render errors', async () => {
812
+ function ThrowingComponent(): never {
813
+ throw new Error('sync error');
814
+ }
815
+
816
+ const html = await renderToString(
817
+ <ErrorBoundary fallback={(e) => <div>caught: {(e as Error).message}</div>}>
818
+ <ThrowingComponent />
819
+ </ErrorBoundary>,
820
+ );
821
+
822
+ expect(html).toBe('<div>caught: sync error</div>');
823
+ });
824
+
825
+ it('catches async suspense errors (max attempts)', async () => {
826
+ function InfiniteThrowComponent(): never {
827
+ throw Promise.resolve();
828
+ }
829
+
830
+ const html = await renderToString(
831
+ <ErrorBoundary fallback={(e) => <div>caught: {(e as Error).message}</div>}>
832
+ <Suspense fallback={<div>loading...</div>}>
833
+ <InfiniteThrowComponent />
834
+ </Suspense>
835
+ </ErrorBoundary>,
836
+ );
837
+
838
+ expect(html).toBe(
839
+ '<div>caught: suspense boundary exceeded maximum retry attempts (20)</div>' + SUSPENSE_RUNTIME,
840
+ );
841
+ });
842
+
843
+ it('passes error object to fallback function', async () => {
844
+ const testError = new Error('test error');
845
+ function ThrowingComponent(): never {
846
+ throw testError;
847
+ }
848
+
849
+ let receivedError: unknown;
850
+ const html = await renderToString(
851
+ <ErrorBoundary
852
+ fallback={(e) => {
853
+ receivedError = e;
854
+ return <div>error</div>;
855
+ }}
856
+ >
857
+ <ThrowingComponent />
858
+ </ErrorBoundary>,
859
+ );
860
+
861
+ expect(receivedError).toBe(testError);
862
+ expect(html).toBe('<div>error</div>');
863
+ });
864
+
865
+ it('nested ErrorBoundary catches at nearest boundary', async () => {
866
+ function ThrowingComponent(): never {
867
+ throw new Error('inner error');
868
+ }
869
+
870
+ const html = await renderToString(
871
+ <ErrorBoundary fallback={() => <div>outer</div>}>
872
+ <div>
873
+ <ErrorBoundary fallback={() => <div>inner</div>}>
874
+ <ThrowingComponent />
875
+ </ErrorBoundary>
876
+ </div>
877
+ </ErrorBoundary>,
878
+ );
879
+
880
+ expect(html).toBe('<div><div>inner</div></div>');
881
+ });
882
+
883
+ it('renders children when no error', async () => {
884
+ const html = await renderToString(
885
+ <ErrorBoundary fallback={() => <div>error</div>}>
886
+ <div>success</div>
887
+ </ErrorBoundary>,
888
+ );
889
+
890
+ expect(html).toBe('<div>success</div>');
891
+ });
892
+
893
+ it('lets promises pass through to Suspense', async () => {
894
+ const { promise, resolve } = Promise.withResolvers<string>();
895
+
896
+ function AsyncComponent() {
897
+ const data = use(promise);
898
+ return <div>{data}</div>;
899
+ }
900
+
901
+ const stream = renderToStream(
902
+ <ErrorBoundary fallback={() => <div>error</div>}>
903
+ <Suspense fallback={<div>loading...</div>}>
904
+ <AsyncComponent />
905
+ </Suspense>
906
+ </ErrorBoundary>,
907
+ );
908
+
909
+ resolve('loaded');
910
+
911
+ const html = await drain(stream);
912
+ expect(html).toBe(
913
+ '<!--$s:s1--><div>loading...</div><!--/$s:s1-->' +
914
+ SUSPENSE_RUNTIME +
915
+ '<template data-suspense="s1"><div>loaded</div></template>' +
916
+ SUSPENSE_CALL,
917
+ );
918
+ });
919
+
920
+ it('fallback error caught by parent ErrorBoundary (sync)', async () => {
921
+ function ThrowingComponent(): never {
922
+ throw new Error('child error');
923
+ }
924
+
925
+ function ThrowingFallback(): never {
926
+ throw new Error('fallback error');
927
+ }
928
+
929
+ const html = await renderToString(
930
+ <ErrorBoundary fallback={(e) => <div>outer: {(e as Error).message}</div>}>
931
+ <ErrorBoundary fallback={() => <ThrowingFallback />}>
932
+ <ThrowingComponent />
933
+ </ErrorBoundary>
934
+ </ErrorBoundary>,
935
+ );
936
+
937
+ expect(html).toBe('<div>outer: fallback error</div>');
938
+ });
939
+
940
+ it('fallback error caught by parent ErrorBoundary (async)', async () => {
941
+ function InfiniteThrowComponent(): never {
942
+ throw Promise.resolve();
943
+ }
944
+
945
+ function ThrowingFallback(): never {
946
+ throw new Error('fallback error');
947
+ }
948
+
949
+ const html = await renderToString(
950
+ <ErrorBoundary fallback={(e) => <div>outer: {(e as Error).message}</div>}>
951
+ <ErrorBoundary fallback={() => <ThrowingFallback />}>
952
+ <Suspense fallback={<div>loading...</div>}>
953
+ <InfiniteThrowComponent />
954
+ </Suspense>
955
+ </ErrorBoundary>
956
+ </ErrorBoundary>,
957
+ );
958
+
959
+ expect(html).toBe('<div>outer: fallback error</div>' + SUSPENSE_RUNTIME);
960
+ });
961
+
962
+ it('fallback error goes to onError when no parent ErrorBoundary (sync)', async () => {
963
+ function ThrowingComponent(): never {
964
+ throw new Error('child error');
965
+ }
966
+
967
+ function ThrowingFallback(): never {
968
+ throw new Error('fallback error');
969
+ }
970
+
971
+ const errors: unknown[] = [];
972
+ try {
973
+ await renderToString(
974
+ <ErrorBoundary fallback={() => <ThrowingFallback />}>
975
+ <ThrowingComponent />
976
+ </ErrorBoundary>,
977
+ { onError: (e) => errors.push(e) },
978
+ );
979
+ } catch {
980
+ // expected
981
+ }
982
+
983
+ expect(errors.length).toBe(1);
984
+ expect((errors[0] as Error).message).toBe('fallback error');
985
+ });
986
+
987
+ it('fallback error goes to onError when no parent ErrorBoundary (async)', async () => {
988
+ function InfiniteThrowComponent(): never {
989
+ throw Promise.resolve();
990
+ }
991
+
992
+ function ThrowingFallback(): never {
993
+ throw new Error('fallback error');
994
+ }
995
+
996
+ const errors: unknown[] = [];
997
+ try {
998
+ await renderToString(
999
+ <ErrorBoundary fallback={() => <ThrowingFallback />}>
1000
+ <Suspense fallback={<div>loading...</div>}>
1001
+ <InfiniteThrowComponent />
1002
+ </Suspense>
1003
+ </ErrorBoundary>,
1004
+ { onError: (e) => errors.push(e) },
1005
+ );
1006
+ } catch {
1007
+ // expected
1008
+ }
1009
+
1010
+ expect(errors.length).toBe(1);
1011
+ expect((errors[0] as Error).message).toBe('fallback error');
1012
+ });
1013
+
1014
+ it('fallback error goes to onError during streaming', async () => {
1015
+ // this tests the onError path in streamPendingSuspense specifically:
1016
+ // 1. outer error boundary catches and renders fallback with suspense
1017
+ // 2. that suspense is processed during streaming
1018
+ // 3. its content has an error boundary whose fallback throws
1019
+
1020
+ function InfiniteThrowComponent(): never {
1021
+ throw Promise.resolve();
1022
+ }
1023
+
1024
+ function ThrowingFallback(): never {
1025
+ throw new Error('streaming fallback error');
1026
+ }
1027
+
1028
+ const { promise, resolve } = Promise.withResolvers<void>();
1029
+
1030
+ function AsyncThenErrorBoundary() {
1031
+ use(promise);
1032
+ return (
1033
+ <ErrorBoundary fallback={() => <ThrowingFallback />}>
1034
+ <Suspense fallback={<div>inner loading</div>}>
1035
+ <InfiniteThrowComponent />
1036
+ </Suspense>
1037
+ </ErrorBoundary>
1038
+ );
1039
+ }
1040
+
1041
+ function FallbackWithSuspense() {
1042
+ return (
1043
+ <Suspense fallback={<div>fallback loading</div>}>
1044
+ <AsyncThenErrorBoundary />
1045
+ </Suspense>
1046
+ );
1047
+ }
1048
+
1049
+ const errors: unknown[] = [];
1050
+ const streamPromise = renderToString(
1051
+ <ErrorBoundary fallback={() => <FallbackWithSuspense />}>
1052
+ <Suspense fallback={<div>outer loading</div>}>
1053
+ <InfiniteThrowComponent />
1054
+ </Suspense>
1055
+ </ErrorBoundary>,
1056
+ { onError: (e) => errors.push(e) },
1057
+ );
1058
+
1059
+ // resolve the inner async component to trigger the streaming error path
1060
+ resolve();
1061
+
1062
+ await streamPromise;
1063
+
1064
+ expect(errors.length).toBe(1);
1065
+ expect((errors[0] as Error).message).toBe('streaming fallback error');
1066
+ });
624
1067
  });
625
1068
  });
@@ -1,6 +1,7 @@
1
1
  import { Fragment, jsx } from '../jsx-runtime.js';
2
2
 
3
- import { inject, type Context } from './context.js';
3
+ import type { Context } from './context.js';
4
+ import { inject } from './render-context.js';
4
5
  import type { JSXElement, JSXNode } from './types.js';
5
6
 
6
7
  export interface SuspenseProps {
@@ -16,6 +17,19 @@ export function Suspense({ children }: SuspenseProps): JSXElement {
16
17
  return jsx(Fragment, { children });
17
18
  }
18
19
 
20
+ export interface ErrorBoundaryProps {
21
+ fallback: (error: unknown) => JSXNode;
22
+ children?: JSXNode;
23
+ }
24
+
25
+ /**
26
+ * error boundary - catches render errors and displays fallback
27
+ */
28
+ export function ErrorBoundary({ children }: ErrorBoundaryProps): JSXElement {
29
+ // ErrorBoundary is handled specially in buildSegment, this is just for typing
30
+ return jsx(Fragment, { children });
31
+ }
32
+
19
33
  /** cache for resolved/rejected promise values */
20
34
  const promiseCache = new WeakMap<
21
35
  Promise<unknown>,
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsx-runtime-CpxZaJu6.d.mts","names":[],"sources":["../src/lib/types.ts","../src/lib/intrinsic-elements.ts","../src/jsx-runtime.ts"],"sourcesContent":[],"mappings":"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ACI;QACN;SACC;aACI;SACJ;YACG;SACH;QACD;QACA;QACA;WACG;cACG;gBACE;YACJ;YACA;UACF;QACF;QACA;QACA;QACA;QACA;QACA;UACE;YACE;YACA;QACJ;UACE;OACH;YACK;SACH;WACE;SACF;SACA;YACG;WACD;YACC;QACJ;UACE;UACA;SACD;UACC;UACA;cACI;UACJ;WACC;SACF;aACI;cACC;YACF;QACJ;cACM;YACF;YACA;OACL;WACI;aACE;SACJ;cACK;OACP;QACC;QACA;UACE;OACH;UACG;YACE;UACF;YACE;aACC;YACD;WACD;YACC;UACF;YACE;WACD;SACF;aACI;SACJ;WACE;cACG;WACH;QACH;cACM;WACH;QACH;WACG;UACD;WACC;QACH;WACG;OACJ;QACC;SACC;WACE;SACF;aACI;SAGJ;aAEI;mBACM;sBACG;YACV;cACE;UACJ;UACA;aACG;aACA;mBACM;yBACM;iBACR;sBACK;uBACC;uBACA;oBACH;kBACF;aACL;aACA;aACA;aACA;aACA;oBACO;aACP;aACA;iBACI;kBACC;cACJ;kBACI;wBACM;iBACP;YACL;kBACM;YACN;mBACO;OACZ;WACI;UACD;oBACU;YACR;UACF;cACI;WACH;UACD;aACG;aACA;cACC;oBACM;UACV;SACD;UACC;YACE;YACA;UACF;cACI;WACH;SACF;UACC;;;;;;;ADvjDR;AAGA;AAWA;;AAAsF,iBEbtE,GFasE,CAAA,CAAA,EAAA,UAAA,MAAA,GEb5C,SFa4C,CAAA,GAAA,CAAA,CAAA,CAAA,IAAA,EEbtB,CFasB,EAAA,KAAA,EEbZ,CFaY,CAAA,EEbR,UFaQ,CEbG,CFaH,EEbM,CFaN,CAAA;AAE9E,iBETQ,QAAA,CFSR,KAAA,EAAA;EAAC,QAAA,CAAA,EEToC,OFSpC;AAWT,CAAA,CAAA,EEpByD,OFoB7C"}