ripple 0.3.72 → 0.3.76

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 (172) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +4 -10
  4. package/src/runtime/dynamic-client.js +33 -0
  5. package/src/runtime/dynamic-server.js +80 -0
  6. package/src/runtime/index-client.js +5 -13
  7. package/src/runtime/index-server.js +2 -0
  8. package/src/runtime/internal/client/blocks.js +6 -27
  9. package/src/runtime/internal/client/composite.js +11 -6
  10. package/src/runtime/internal/client/for.js +80 -5
  11. package/src/runtime/internal/client/index.js +0 -2
  12. package/src/runtime/internal/client/render.js +5 -2
  13. package/src/runtime/internal/client/types.d.ts +0 -10
  14. package/src/runtime/internal/server/index.js +8 -1
  15. package/tests/client/__snapshots__/computed-properties.test.tsrx.snap +8 -0
  16. package/tests/client/__snapshots__/for.test.tsrx.snap +22 -0
  17. package/tests/client/__snapshots__/html.test.tsrx.snap +4 -0
  18. package/tests/client/array/array.copy-within.test.tsrx +19 -19
  19. package/tests/client/array/array.derived.test.tsrx +97 -109
  20. package/tests/client/array/array.iteration.test.tsrx +28 -28
  21. package/tests/client/array/array.mutations.test.tsrx +68 -68
  22. package/tests/client/array/array.static.test.tsrx +82 -92
  23. package/tests/client/array/array.to-methods.test.tsrx +15 -15
  24. package/tests/client/async-suspend.test.tsrx +180 -179
  25. package/tests/client/basic/__snapshots__/basic.attributes.test.tsrx.snap +2 -0
  26. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +4 -0
  27. package/tests/client/basic/basic.attributes.test.tsrx +273 -317
  28. package/tests/client/basic/basic.collections.test.tsrx +55 -61
  29. package/tests/client/basic/basic.components.test.tsrx +198 -220
  30. package/tests/client/basic/basic.errors.test.tsrx +70 -76
  31. package/tests/client/basic/basic.events.test.tsrx +80 -85
  32. package/tests/client/basic/basic.get-set.test.tsrx +54 -64
  33. package/tests/client/basic/basic.hmr.test.tsrx +15 -19
  34. package/tests/client/basic/basic.reactivity.test.tsrx +121 -135
  35. package/tests/client/basic/basic.rendering.test.tsrx +273 -178
  36. package/tests/client/basic/basic.styling.test.tsrx +16 -14
  37. package/tests/client/basic/basic.utilities.test.tsrx +8 -10
  38. package/tests/client/boundaries.test.tsrx +18 -18
  39. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -76
  40. package/tests/client/compiler/compiler.attributes.test.tsrx +18 -14
  41. package/tests/client/compiler/compiler.basic.test.tsrx +357 -288
  42. package/tests/client/compiler/compiler.regex.test.tsrx +40 -44
  43. package/tests/client/compiler/compiler.tracked-access.test.tsrx +57 -38
  44. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  45. package/tests/client/compiler/compiler.typescript.test.tsrx +4 -3
  46. package/tests/client/composite/composite.dynamic-components.test.tsrx +62 -47
  47. package/tests/client/composite/composite.generics.test.tsrx +165 -167
  48. package/tests/client/composite/composite.props.test.tsrx +66 -74
  49. package/tests/client/composite/composite.reactivity.test.tsrx +132 -166
  50. package/tests/client/composite/composite.render.test.tsrx +92 -101
  51. package/tests/client/computed-properties.test.tsrx +14 -18
  52. package/tests/client/context.test.tsrx +14 -18
  53. package/tests/client/css/global-additional-cases.test.tsrx +493 -439
  54. package/tests/client/css/global-advanced-selectors.test.tsrx +169 -153
  55. package/tests/client/css/global-at-rules.test.tsrx +71 -66
  56. package/tests/client/css/global-basic.test.tsrx +105 -98
  57. package/tests/client/css/global-classes-ids.test.tsrx +128 -114
  58. package/tests/client/css/global-combinators.test.tsrx +83 -78
  59. package/tests/client/css/global-complex-nesting.test.tsrx +134 -120
  60. package/tests/client/css/global-edge-cases.test.tsrx +138 -120
  61. package/tests/client/css/global-keyframes.test.tsrx +108 -96
  62. package/tests/client/css/global-nested.test.tsrx +88 -78
  63. package/tests/client/css/global-pseudo.test.tsrx +104 -98
  64. package/tests/client/css/global-scoping.test.tsrx +145 -125
  65. package/tests/client/css/style-identifier.test.tsrx +65 -72
  66. package/tests/client/date.test.tsrx +83 -83
  67. package/tests/client/dynamic-elements.test.tsrx +318 -299
  68. package/tests/client/events.test.tsrx +252 -266
  69. package/tests/client/for.test.tsrx +120 -127
  70. package/tests/client/head.test.tsrx +74 -48
  71. package/tests/client/html.test.tsrx +37 -49
  72. package/tests/client/input-value.test.tsrx +1125 -1354
  73. package/tests/client/lazy-array.test.tsrx +10 -16
  74. package/tests/client/lazy-destructuring.test.tsrx +169 -221
  75. package/tests/client/map.test.tsrx +39 -41
  76. package/tests/client/media-query.test.tsrx +15 -19
  77. package/tests/client/object.test.tsrx +46 -56
  78. package/tests/client/portal.test.tsrx +31 -37
  79. package/tests/client/ref.test.tsrx +173 -193
  80. package/tests/client/return.test.tsrx +62 -37
  81. package/tests/client/set.test.tsrx +33 -33
  82. package/tests/client/svg.test.tsrx +197 -216
  83. package/tests/client/switch.test.tsrx +201 -191
  84. package/tests/client/track-async-hydration.test.tsrx +14 -18
  85. package/tests/client/tracked-index-access.test.tsrx +18 -28
  86. package/tests/client/try.test.tsrx +494 -619
  87. package/tests/client/tsx.test.tsrx +286 -292
  88. package/tests/client/typescript-generics.test.tsrx +121 -129
  89. package/tests/client/url/url.derived.test.tsrx +21 -25
  90. package/tests/client/url/url.parsing.test.tsrx +35 -35
  91. package/tests/client/url/url.partial-removal.test.tsrx +32 -32
  92. package/tests/client/url/url.reactivity.test.tsrx +68 -72
  93. package/tests/client/url/url.serialization.test.tsrx +8 -8
  94. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +21 -27
  95. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +16 -16
  96. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +37 -37
  97. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +56 -60
  98. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +32 -34
  99. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +9 -9
  100. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +10 -10
  101. package/tests/hydration/compiled/client/basic.js +390 -319
  102. package/tests/hydration/compiled/client/composite.js +52 -44
  103. package/tests/hydration/compiled/client/for.js +734 -604
  104. package/tests/hydration/compiled/client/head.js +183 -103
  105. package/tests/hydration/compiled/client/html.js +93 -86
  106. package/tests/hydration/compiled/client/if-children.js +95 -71
  107. package/tests/hydration/compiled/client/if.js +113 -89
  108. package/tests/hydration/compiled/client/mixed-control-flow.js +225 -209
  109. package/tests/hydration/compiled/client/nested-control-flow.js +94 -98
  110. package/tests/hydration/compiled/client/reactivity.js +26 -24
  111. package/tests/hydration/compiled/client/return.js +8 -42
  112. package/tests/hydration/compiled/client/switch.js +208 -173
  113. package/tests/hydration/compiled/client/track-async-serialization.js +176 -128
  114. package/tests/hydration/compiled/client/try.js +29 -21
  115. package/tests/hydration/compiled/server/basic.js +210 -221
  116. package/tests/hydration/compiled/server/composite.js +13 -14
  117. package/tests/hydration/compiled/server/for.js +427 -444
  118. package/tests/hydration/compiled/server/head.js +199 -189
  119. package/tests/hydration/compiled/server/html.js +33 -41
  120. package/tests/hydration/compiled/server/if-children.js +114 -117
  121. package/tests/hydration/compiled/server/if.js +77 -83
  122. package/tests/hydration/compiled/server/mixed-control-flow.js +145 -150
  123. package/tests/hydration/compiled/server/nested-control-flow.js +10 -0
  124. package/tests/hydration/compiled/server/reactivity.js +24 -22
  125. package/tests/hydration/compiled/server/return.js +6 -18
  126. package/tests/hydration/compiled/server/switch.js +179 -176
  127. package/tests/hydration/compiled/server/track-async-serialization.js +88 -70
  128. package/tests/hydration/compiled/server/try.js +31 -35
  129. package/tests/hydration/components/basic.tsrx +216 -258
  130. package/tests/hydration/components/composite.tsrx +32 -42
  131. package/tests/hydration/components/events.tsrx +81 -101
  132. package/tests/hydration/components/for.tsrx +270 -336
  133. package/tests/hydration/components/head.tsrx +43 -39
  134. package/tests/hydration/components/hmr.tsrx +16 -22
  135. package/tests/hydration/components/html-in-template.tsrx +15 -21
  136. package/tests/hydration/components/html.tsrx +442 -526
  137. package/tests/hydration/components/if-children.tsrx +107 -125
  138. package/tests/hydration/components/if.tsrx +68 -90
  139. package/tests/hydration/components/mixed-control-flow.tsrx +65 -72
  140. package/tests/hydration/components/nested-control-flow.tsrx +202 -216
  141. package/tests/hydration/components/portal.tsrx +33 -41
  142. package/tests/hydration/components/reactivity.tsrx +26 -34
  143. package/tests/hydration/components/return.tsrx +4 -6
  144. package/tests/hydration/components/switch.tsrx +73 -78
  145. package/tests/hydration/components/track-async-serialization.tsrx +83 -93
  146. package/tests/hydration/components/try.tsrx +37 -51
  147. package/tests/hydration/switch.test.js +8 -8
  148. package/tests/server/await.test.tsrx +3 -3
  149. package/tests/server/basic.attributes.test.tsrx +117 -162
  150. package/tests/server/basic.components.test.tsrx +164 -194
  151. package/tests/server/basic.test.tsrx +299 -199
  152. package/tests/server/compiler.test.tsrx +142 -72
  153. package/tests/server/composite.props.test.tsrx +54 -58
  154. package/tests/server/composite.test.tsrx +165 -167
  155. package/tests/server/context.test.tsrx +13 -17
  156. package/tests/server/dynamic-elements.test.tsrx +147 -148
  157. package/tests/server/for.test.tsrx +115 -84
  158. package/tests/server/head.test.tsrx +54 -31
  159. package/tests/server/html-nesting-validation.test.tsrx +16 -8
  160. package/tests/server/if.test.tsrx +49 -59
  161. package/tests/server/lazy-destructuring.test.tsrx +288 -366
  162. package/tests/server/return.test.tsrx +58 -36
  163. package/tests/server/streaming-ssr.test.tsrx +4 -4
  164. package/tests/server/style-identifier.test.tsrx +61 -69
  165. package/tests/server/switch.test.tsrx +89 -97
  166. package/tests/server/track-async-serialization.test.tsrx +85 -103
  167. package/tests/server/try.test.tsrx +275 -360
  168. package/tests/utils/ref-types.test.js +72 -0
  169. package/tests/utils/vite-plugin-config.test.js +41 -74
  170. package/types/index.d.ts +29 -4
  171. package/src/runtime/internal/client/compat.js +0 -40
  172. package/tests/utils/compiler-compat-config.test.js +0 -38
@@ -1,131 +1,123 @@
1
1
  describe('SSR: switch statements', () => {
2
2
  it('renders simple switch with literal cases', async () => {
3
- function App() {
4
- return <>
5
- let value = 'b';
6
- switch (value) {
7
- case 'a':
8
- <div>{'Case A'}</div>
9
- break;
10
- case 'b':
11
- <div>{'Case B'}</div>
12
- break;
13
- case 'c':
14
- <div>{'Case C'}</div>
15
- break;
16
- default:
17
- <div>{'Default Case'}</div>
18
- }
19
- </>;
3
+ function App() @{
4
+ let value = 'b';
5
+ @switch (value) {
6
+ @case 'a': {
7
+ <div>Case A</div>
8
+ }
9
+ @case 'b': {
10
+ <div>Case B</div>
11
+ }
12
+ @case 'c': {
13
+ <div>{'Case C'}</div>
14
+ }
15
+ @default: {
16
+ <div>{'Default Case'}</div>
17
+ }
18
+ }
20
19
  }
21
20
 
22
21
  const { body } = await render(App);
23
22
  expect(body).toBeHtml('<div>Case B</div>');
24
23
  });
25
24
 
26
- it('renders a fall-through with an empty switch case', async () => {
27
- function App() {
28
- return <>
29
- let value = 'b';
30
- switch (value) {
31
- case 'a':
32
- <div>{'Case A'}</div>
33
- break;
34
- case 'b':
35
- case 'c':
36
- <div>{'Case B or C'}</div>
37
- break;
38
- default:
39
- <div>{'Default Case'}</div>
40
- }
41
- </>;
25
+ it('renders an empty switch case without falling through', async () => {
26
+ function App() @{
27
+ let value = 'b';
28
+ @switch (value) {
29
+ @case 'a': {
30
+ <div>Case A</div>
31
+ }
32
+ @case 'b': {
33
+ }
34
+ @case 'c': {
35
+ <div>Case B or C</div>
36
+ }
37
+ @default: {
38
+ <div>{'Default Case'}</div>
39
+ }
40
+ }
42
41
  }
43
42
 
44
43
  const { body } = await render(App);
45
- expect(body).toBeHtml('<div>Case B or C</div>');
44
+ expect(body).toBeHtml('');
46
45
  });
47
46
 
48
- it('renders a fall-through with a case that has elements', async () => {
49
- function App() {
50
- return <>
51
- let value = 'a';
52
- switch (value) {
53
- case 'a':
54
- <div>{'Case A'}</div>
55
- case 'b':
56
- <div>{'Case B'}</div>
57
- case 'c':
58
- <div>{'Case C'}</div>
59
- break;
60
- default:
61
- <div>{'Default Case'}</div>
62
- }
63
- </>;
47
+ it('renders a case with elements without falling through', async () => {
48
+ function App() @{
49
+ let value = 'a';
50
+ @switch (value) {
51
+ @case 'a': {
52
+ <div>Case A</div>
53
+ }
54
+ @case 'b': {
55
+ <div>Case B</div>
56
+ }
57
+ @case 'c': {
58
+ <div>{'Case C'}</div>
59
+ }
60
+ @default: {
61
+ <div>{'Default Case'}</div>
62
+ }
63
+ }
64
64
  }
65
65
 
66
66
  const { body } = await render(App);
67
- expect(body).toBeHtml('<div>Case A</div><div>Case B</div><div>Case C</div>');
67
+ expect(body).toBeHtml('<div>Case A</div>');
68
68
  });
69
69
 
70
- it('renders a fall-through with a default case in the middle', async () => {
71
- function App() {
72
- return <>
73
- let value = 'x';
74
- switch (value) {
75
- case 'a':
76
- <div>{'Case A'}</div>
77
- default:
78
- <div>{'Default Case'}</div>
79
- case 'b':
80
- <div>{'Case B'}</div>
81
- break;
82
- case 'c':
83
- <div>{'Case C'}</div>
84
- break;
85
- }
86
- </>;
70
+ it('renders a default case', async () => {
71
+ function App() @{
72
+ let value = 'x';
73
+ @switch (value) {
74
+ @case 'a': {
75
+ <div>Case A</div>
76
+ }
77
+ @default: {
78
+ <div>{'Default Case'}</div>
79
+ }
80
+ }
87
81
  }
88
82
 
89
83
  const { body } = await render(App);
90
- expect(body).toBeHtml('<div>Default Case</div><div>Case B</div>');
84
+ expect(body).toBeHtml('<div>Default Case</div>');
91
85
  });
92
86
 
93
- it('renders bare text nodes in switch fall-through cases without element wrappers', async () => {
94
- function App() {
95
- return <>
96
- let value = 'a';
97
- <div>
98
- <span>{'before'}</span>
99
- switch (value) {
100
- case 'a':
101
- {'Case A'}
102
- case 'b':
103
- {'Case B'}
87
+ it('renders bare text nodes in switch cases without falling through', async () => {
88
+ function App() @{
89
+ let value = 'a';
90
+ <div>
91
+ <span>{'before'}</span>
92
+ @switch (value) {
93
+ @case 'a': {
94
+ <>Case A</>
95
+ }
96
+ @case 'b': {
97
+ <>Case B</>
104
98
  }
105
- </div>
106
- </>;
99
+ }
100
+ </div>
107
101
  }
108
102
 
109
103
  const { body } = await render(App);
110
- expect(body).toBeHtml('<div><span>before</span>Case ACase B</div>');
104
+ expect(body).toBeHtml('<div><span>before</span>Case A</div>');
111
105
  });
112
106
 
113
107
  it('renders bare text nodes in switch cases without element wrappers', async () => {
114
- function App() {
115
- return <>
116
- let value = 'a';
117
- <div>
118
- <span>{'before'}</span>
119
- switch (value) {
120
- case 'a':
121
- {'Case A'}
122
- break;
123
- case 'b':
124
- {'Case B'}
125
- break;
108
+ function App() @{
109
+ let value = 'a';
110
+ <div>
111
+ <span>{'before'}</span>
112
+ @switch (value) {
113
+ @case 'a': {
114
+ <>Case A</>
126
115
  }
127
- </div>
128
- </>;
116
+ @case 'b': {
117
+ <>Case B</>
118
+ }
119
+ }
120
+ </div>
129
121
  }
130
122
 
131
123
  const { body } = await render(App);
@@ -5,15 +5,13 @@ const TRACK_ASYNC_PUBLIC_ERROR_MESSAGE = 'An error occurred during async renderi
5
5
 
6
6
  describe('trackAsync serialization (server)', () => {
7
7
  it('serializes resolved trackAsync data as a script tag in SSR output', async () => {
8
- function App() {
9
- return <>
10
- try {
11
- let &[data] = trackAsync(() => Promise.resolve('hello world'));
12
- <p class="result">{data}</p>
13
- } pending {
14
- <p class="loading">{'loading...'}</p>
15
- }
16
- </>;
8
+ function App() @{
9
+ @try {
10
+ let &[data] = trackAsync(() => Promise.resolve('hello world'));
11
+ <p class="result">{data}</p>
12
+ } @pending {
13
+ <p class="loading">{'loading...'}</p>
14
+ }
17
15
  }
18
16
 
19
17
  const { body } = await render(App);
@@ -24,15 +22,13 @@ describe('trackAsync serialization (server)', () => {
24
22
  });
25
23
 
26
24
  it('serializes numeric trackAsync data correctly', async () => {
27
- function App() {
28
- return <>
29
- try {
30
- let &[count] = trackAsync(() => Promise.resolve(42));
31
- <span class="count">{count}</span>
32
- } pending {
33
- <span>{'...'}</span>
34
- }
35
- </>;
25
+ function App() @{
26
+ @try {
27
+ let &[count] = trackAsync(() => Promise.resolve(42));
28
+ <span class="count">{count}</span>
29
+ } @pending {
30
+ <span>{'...'}</span>
31
+ }
36
32
  }
37
33
 
38
34
  const { body } = await render(App);
@@ -41,15 +37,13 @@ describe('trackAsync serialization (server)', () => {
41
37
  });
42
38
 
43
39
  it('serializes object trackAsync data correctly', async () => {
44
- function App() {
45
- return <>
46
- try {
47
- let &[data] = trackAsync(() => Promise.resolve({ name: 'Alice', age: 30 }));
48
- <p>{data.name}</p>
49
- } pending {
50
- <p>{'...'}</p>
51
- }
52
- </>;
40
+ function App() @{
41
+ @try {
42
+ let &[data] = trackAsync(() => Promise.resolve({ name: 'Alice', age: 30 }));
43
+ <p>{data.name}</p>
44
+ } @pending {
45
+ <p>{'...'}</p>
46
+ }
53
47
  }
54
48
 
55
49
  const { body } = await render(App);
@@ -58,19 +52,17 @@ describe('trackAsync serialization (server)', () => {
58
52
  });
59
53
 
60
54
  it('serializes array trackAsync data correctly', async () => {
61
- function App() {
62
- return <>
63
- try {
64
- let &[items] = trackAsync(() => Promise.resolve(['a', 'b', 'c']));
65
- <ul>
66
- for (let item of items) {
67
- <li>{item}</li>
68
- }
69
- </ul>
70
- } pending {
71
- <p>{'...'}</p>
72
- }
73
- </>;
55
+ function App() @{
56
+ @try {
57
+ let &[items] = trackAsync(() => Promise.resolve(['a', 'b', 'c']));
58
+ <ul>
59
+ @for (let item of items) {
60
+ <li>{item}</li>
61
+ }
62
+ </ul>
63
+ } @pending {
64
+ <p>{'...'}</p>
65
+ }
74
66
  }
75
67
 
76
68
  const { body } = await render(App);
@@ -79,17 +71,15 @@ describe('trackAsync serialization (server)', () => {
79
71
  });
80
72
 
81
73
  it('serializes rejected trackAsync as error envelope', async () => {
82
- function App() {
83
- return <>
84
- try {
85
- let &[data] = trackAsync(() => Promise.reject(new Error('fetch failed')));
86
- <p class="result">{data}</p>
87
- } pending {
88
- <p class="loading">{'loading...'}</p>
89
- } catch (e) {
90
- <p class="error">{(e as Error).message}</p>
91
- }
92
- </>;
74
+ function App() @{
75
+ @try {
76
+ let &[data] = trackAsync(() => Promise.reject(new Error('fetch failed')));
77
+ <p class="result">{data}</p>
78
+ } @pending {
79
+ <p class="loading">{'loading...'}</p>
80
+ } @catch (e) {
81
+ <p class="error">{(e as Error).message}</p>
82
+ }
93
83
  }
94
84
 
95
85
  const { body } = await render(App);
@@ -101,25 +91,21 @@ describe('trackAsync serialization (server)', () => {
101
91
  });
102
92
 
103
93
  it('serializes error when child component error bubbles to parent catch', async () => {
104
- function Child() {
105
- return <>
106
- try {
107
- let &[data] = trackAsync(() => Promise.reject(new Error('child error')));
108
- <p class="result">{data}</p>
109
- } pending {
110
- <p class="pending">{'loading...'}</p>
111
- }
112
- </>;
94
+ function Child() @{
95
+ @try {
96
+ let &[data] = trackAsync(() => Promise.reject(new Error('child error')));
97
+ <p class="result">{data}</p>
98
+ } @pending {
99
+ <p class="pending">{'loading...'}</p>
100
+ }
113
101
  }
114
102
 
115
- function Parent() {
116
- return <>
117
- try {
118
- <Child />
119
- } catch (e) {
120
- <p class="parent-error">{(e as Error).message}</p>
121
- }
122
- </>;
103
+ function Parent() @{
104
+ @try {
105
+ <Child />
106
+ } @catch (e) {
107
+ <p class="parent-error">{(e as Error).message}</p>
108
+ }
123
109
  }
124
110
 
125
111
  const { body } = await render(Parent);
@@ -131,19 +117,17 @@ describe('trackAsync serialization (server)', () => {
131
117
  });
132
118
 
133
119
  it('serializes sync trackAsync throw using original cause message', async () => {
134
- function App() {
135
- return <>
136
- try {
137
- let &[data] = trackAsync(() => {
138
- throw new Error('sync failure');
139
- });
140
- <p class="result">{data}</p>
141
- } pending {
142
- <p class="loading">{'loading...'}</p>
143
- } catch (e) {
144
- <p class="error">{(e as Error).message}</p>
145
- }
146
- </>;
120
+ function App() @{
121
+ @try {
122
+ let &[data] = trackAsync(() => {
123
+ throw new Error('sync failure');
124
+ });
125
+ <p class="result">{data}</p>
126
+ } @pending {
127
+ <p class="loading">{'loading...'}</p>
128
+ } @catch (e) {
129
+ <p class="error">{(e as Error).message}</p>
130
+ }
147
131
  }
148
132
 
149
133
  const { body } = await render(App);
@@ -156,19 +140,17 @@ describe('trackAsync serialization (server)', () => {
156
140
  });
157
141
 
158
142
  it('escapes serialized error payload to keep script tag safe', async () => {
159
- function App() {
160
- return <>
161
- try {
162
- let &[data] = trackAsync(
163
- () => Promise.reject(new Error('</script><div data-injected="1">boom</div>')),
164
- );
165
- <p class="result">{data}</p>
166
- } pending {
167
- <p class="loading">{'loading...'}</p>
168
- } catch (e) {
169
- <p class="error">{(e as Error).message}</p>
170
- }
171
- </>;
143
+ function App() @{
144
+ @try {
145
+ let &[data] = trackAsync(
146
+ () => Promise.reject(new Error('</script><div data-injected="1">boom</div>')),
147
+ );
148
+ <p class="result">{data}</p>
149
+ } @pending {
150
+ <p class="loading">{'loading...'}</p>
151
+ } @catch (e) {
152
+ <p class="error">{(e as Error).message}</p>
153
+ }
172
154
  }
173
155
 
174
156
  const { body } = await render(App);
@@ -182,17 +164,17 @@ describe('trackAsync serialization (server)', () => {
182
164
  });
183
165
 
184
166
  it('generates unique hashes for multiple trackAsync calls', async () => {
185
- function App() {
186
- return <>
187
- try {
188
- let &[a] = trackAsync(() => Promise.resolve('first'));
189
- let &[b] = trackAsync(() => Promise.resolve('second'));
167
+ function App() @{
168
+ @try {
169
+ let &[a] = trackAsync(() => Promise.resolve('first'));
170
+ let &[b] = trackAsync(() => Promise.resolve('second'));
171
+ <>
190
172
  <p>{a}</p>
191
173
  <p>{b}</p>
192
- } pending {
193
- <p>{'...'}</p>
194
- }
195
- </>;
174
+ </>
175
+ } @pending {
176
+ <p>{'...'}</p>
177
+ }
196
178
  }
197
179
 
198
180
  const { body } = await render(App);