ripple 0.3.68 → 0.3.70

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 (182) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +2 -2
  4. package/src/runtime/element.js +1 -1
  5. package/src/runtime/index-client.js +11 -11
  6. package/src/runtime/index-server.js +7 -4
  7. package/src/runtime/internal/client/bindings.js +1 -1
  8. package/src/runtime/internal/client/blocks.js +13 -4
  9. package/src/runtime/internal/client/component.js +55 -0
  10. package/src/runtime/internal/client/composite.js +4 -2
  11. package/src/runtime/internal/client/expression.js +65 -7
  12. package/src/runtime/internal/client/hmr.js +54 -43
  13. package/src/runtime/internal/client/index.js +5 -1
  14. package/src/runtime/internal/client/portal.js +70 -69
  15. package/src/runtime/internal/client/render.js +3 -0
  16. package/src/runtime/internal/server/index.js +92 -8
  17. package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
  18. package/tests/client/array/array.copy-within.test.tsrx +33 -31
  19. package/tests/client/array/array.derived.test.tsrx +186 -169
  20. package/tests/client/array/array.iteration.test.tsrx +40 -37
  21. package/tests/client/array/array.mutations.test.tsrx +113 -101
  22. package/tests/client/array/array.static.test.tsrx +119 -101
  23. package/tests/client/array/array.to-methods.test.tsrx +24 -21
  24. package/tests/client/async-suspend.test.tsrx +247 -246
  25. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
  26. package/tests/client/basic/basic.attributes.test.tsrx +428 -423
  27. package/tests/client/basic/basic.collections.test.tsrx +109 -102
  28. package/tests/client/basic/basic.components.test.tsrx +323 -205
  29. package/tests/client/basic/basic.errors.test.tsrx +91 -91
  30. package/tests/client/basic/basic.events.test.tsrx +114 -115
  31. package/tests/client/basic/basic.get-set.test.tsrx +97 -87
  32. package/tests/client/basic/basic.hmr.test.tsrx +19 -16
  33. package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
  34. package/tests/client/basic/basic.rendering.test.tsrx +272 -182
  35. package/tests/client/basic/basic.styling.test.tsrx +23 -22
  36. package/tests/client/basic/basic.utilities.test.tsrx +10 -8
  37. package/tests/client/boundaries.test.tsrx +26 -26
  38. package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
  39. package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
  40. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
  41. package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
  42. package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
  43. package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
  44. package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
  45. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  46. package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
  47. package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
  48. package/tests/client/composite/composite.generics.test.tsrx +168 -192
  49. package/tests/client/composite/composite.props.test.tsrx +97 -81
  50. package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
  51. package/tests/client/composite/composite.render.test.tsrx +122 -105
  52. package/tests/client/computed-properties.test.tsrx +28 -28
  53. package/tests/client/context.test.tsrx +21 -21
  54. package/tests/client/css/global-additional-cases.test.tsrx +58 -58
  55. package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
  56. package/tests/client/css/global-at-rules.test.tsrx +10 -10
  57. package/tests/client/css/global-basic.test.tsrx +14 -14
  58. package/tests/client/css/global-classes-ids.test.tsrx +14 -14
  59. package/tests/client/css/global-combinators.test.tsrx +10 -10
  60. package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
  61. package/tests/client/css/global-edge-cases.test.tsrx +18 -18
  62. package/tests/client/css/global-keyframes.test.tsrx +12 -12
  63. package/tests/client/css/global-nested.test.tsrx +10 -10
  64. package/tests/client/css/global-pseudo.test.tsrx +12 -12
  65. package/tests/client/css/global-scoping.test.tsrx +20 -20
  66. package/tests/client/css/style-identifier.test.tsrx +126 -259
  67. package/tests/client/date.test.tsrx +146 -133
  68. package/tests/client/dynamic-elements.test.tsrx +398 -365
  69. package/tests/client/events.test.tsrx +292 -290
  70. package/tests/client/for.test.tsrx +156 -153
  71. package/tests/client/head.test.tsrx +105 -96
  72. package/tests/client/html.test.tsrx +122 -26
  73. package/tests/client/input-value.test.tsrx +1361 -1314
  74. package/tests/client/lazy-array.test.tsrx +16 -13
  75. package/tests/client/lazy-destructuring.test.tsrx +257 -213
  76. package/tests/client/map.test.tsrx +65 -60
  77. package/tests/client/media-query.test.tsrx +22 -20
  78. package/tests/client/object.test.tsrx +87 -81
  79. package/tests/client/portal.test.tsrx +57 -51
  80. package/tests/client/ref.test.tsrx +233 -202
  81. package/tests/client/return.test.tsrx +71 -2560
  82. package/tests/client/set.test.tsrx +54 -45
  83. package/tests/client/svg.test.tsrx +216 -186
  84. package/tests/client/switch.test.tsrx +194 -193
  85. package/tests/client/track-async-hydration.test.tsrx +18 -14
  86. package/tests/client/tracked-index-access.test.tsrx +28 -18
  87. package/tests/client/try.test.tsrx +675 -548
  88. package/tests/client/tsx.test.tsrx +373 -311
  89. package/tests/client/typescript-generics.test.tsrx +145 -145
  90. package/tests/client/url/url.derived.test.tsrx +33 -28
  91. package/tests/client/url/url.parsing.test.tsrx +61 -51
  92. package/tests/client/url/url.partial-removal.test.tsrx +56 -48
  93. package/tests/client/url/url.reactivity.test.tsrx +142 -125
  94. package/tests/client/url/url.serialization.test.tsrx +13 -11
  95. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
  96. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
  97. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
  98. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
  99. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
  100. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
  101. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
  102. package/tests/hydration/basic.test.js +3 -3
  103. package/tests/hydration/compiled/client/basic.js +586 -651
  104. package/tests/hydration/compiled/client/composite.js +79 -104
  105. package/tests/hydration/compiled/client/events.js +140 -148
  106. package/tests/hydration/compiled/client/for.js +1005 -1018
  107. package/tests/hydration/compiled/client/head.js +124 -134
  108. package/tests/hydration/compiled/client/hmr.js +41 -48
  109. package/tests/hydration/compiled/client/html-in-template.js +38 -41
  110. package/tests/hydration/compiled/client/html.js +970 -1314
  111. package/tests/hydration/compiled/client/if-children.js +234 -249
  112. package/tests/hydration/compiled/client/if.js +182 -189
  113. package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
  114. package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
  115. package/tests/hydration/compiled/client/portal.js +65 -85
  116. package/tests/hydration/compiled/client/reactivity.js +84 -90
  117. package/tests/hydration/compiled/client/return.js +38 -1939
  118. package/tests/hydration/compiled/client/switch.js +218 -224
  119. package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
  120. package/tests/hydration/compiled/client/try.js +123 -132
  121. package/tests/hydration/compiled/server/basic.js +773 -831
  122. package/tests/hydration/compiled/server/composite.js +166 -191
  123. package/tests/hydration/compiled/server/events.js +170 -184
  124. package/tests/hydration/compiled/server/for.js +851 -909
  125. package/tests/hydration/compiled/server/head.js +206 -216
  126. package/tests/hydration/compiled/server/hmr.js +64 -72
  127. package/tests/hydration/compiled/server/html-in-template.js +42 -76
  128. package/tests/hydration/compiled/server/html.js +1362 -1667
  129. package/tests/hydration/compiled/server/if-children.js +419 -445
  130. package/tests/hydration/compiled/server/if.js +194 -208
  131. package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
  132. package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
  133. package/tests/hydration/compiled/server/portal.js +152 -160
  134. package/tests/hydration/compiled/server/reactivity.js +94 -106
  135. package/tests/hydration/compiled/server/return.js +28 -2172
  136. package/tests/hydration/compiled/server/switch.js +274 -286
  137. package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
  138. package/tests/hydration/compiled/server/try.js +167 -185
  139. package/tests/hydration/components/basic.tsrx +320 -272
  140. package/tests/hydration/components/composite.tsrx +44 -32
  141. package/tests/hydration/components/events.tsrx +101 -91
  142. package/tests/hydration/components/for.tsrx +510 -452
  143. package/tests/hydration/components/head.tsrx +87 -80
  144. package/tests/hydration/components/hmr.tsrx +22 -17
  145. package/tests/hydration/components/html-in-template.tsrx +22 -17
  146. package/tests/hydration/components/html.tsrx +525 -443
  147. package/tests/hydration/components/if-children.tsrx +158 -148
  148. package/tests/hydration/components/if.tsrx +109 -95
  149. package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
  150. package/tests/hydration/components/nested-control-flow.tsrx +215 -203
  151. package/tests/hydration/components/portal.tsrx +41 -34
  152. package/tests/hydration/components/reactivity.tsrx +37 -27
  153. package/tests/hydration/components/return.tsrx +12 -556
  154. package/tests/hydration/components/switch.tsrx +120 -114
  155. package/tests/hydration/components/track-async-serialization.tsrx +107 -91
  156. package/tests/hydration/components/try.tsrx +55 -40
  157. package/tests/hydration/html.test.js +4 -4
  158. package/tests/hydration/return.test.js +13 -532
  159. package/tests/server/await.test.tsrx +3 -3
  160. package/tests/server/basic.attributes.test.tsrx +264 -195
  161. package/tests/server/basic.components.test.tsrx +296 -169
  162. package/tests/server/basic.test.tsrx +300 -198
  163. package/tests/server/compiler.test.tsrx +62 -60
  164. package/tests/server/composite.props.test.tsrx +77 -63
  165. package/tests/server/composite.test.tsrx +168 -192
  166. package/tests/server/context.test.tsrx +18 -12
  167. package/tests/server/dynamic-elements.test.tsrx +197 -180
  168. package/tests/server/for.test.tsrx +85 -78
  169. package/tests/server/head.test.tsrx +50 -43
  170. package/tests/server/html-nesting-validation.test.tsrx +8 -8
  171. package/tests/server/if.test.tsrx +57 -51
  172. package/tests/server/lazy-destructuring.test.tsrx +366 -294
  173. package/tests/server/return.test.tsrx +76 -1355
  174. package/tests/server/streaming-ssr.test.tsrx +4 -75
  175. package/tests/server/style-identifier.test.tsrx +169 -131
  176. package/tests/server/switch.test.tsrx +91 -85
  177. package/tests/server/track-async-serialization.test.tsrx +105 -85
  178. package/tests/server/try.test.tsrx +374 -280
  179. package/tests/utils/compiler-compat-config.test.js +2 -2
  180. package/tests/utils/runtime-imports.test.js +10 -0
  181. package/types/index.d.ts +8 -0
  182. package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
@@ -18,13 +18,15 @@ describe('try block with catch and pending', () => {
18
18
  resolve_value = resolve;
19
19
  });
20
20
 
21
- component App() {
22
- <span class="before">{'before'}</span>
23
- try {
24
- let &[data] = trackAsync(() => promise);
25
- <p class="resolved">{data}</p>
26
- } pending {}
27
- <span class="after">{'after'}</span>
21
+ function App() {
22
+ return <>
23
+ <span class="before">{'before'}</span>
24
+ try {
25
+ let &[data] = trackAsync(() => promise);
26
+ <p class="resolved">{data}</p>
27
+ } pending {}
28
+ <span class="after">{'after'}</span>
29
+ </>;
28
30
  }
29
31
 
30
32
  render(App);
@@ -47,18 +49,22 @@ describe('try block with catch and pending', () => {
47
49
  });
48
50
 
49
51
  it('catch block works when a child throws synchronously', async () => {
50
- component App() {
51
- try {
52
- <ThrowingChild />
53
- } pending {
54
- <p>{'loading...'}</p>
55
- } catch (err) {
56
- <p>{'caught error'}</p>
57
- }
52
+ function App() {
53
+ return <>
54
+ try {
55
+ <ThrowingChild />
56
+ } pending {
57
+ <p>{'loading...'}</p>
58
+ } catch (err) {
59
+ <p>{'caught error'}</p>
60
+ }
61
+ </>;
58
62
  }
59
63
 
60
- component ThrowingChild() {
61
- throw new Error('sync error');
64
+ function ThrowingChild() {
65
+ return <>
66
+ throw new Error('sync error');
67
+ </>;
62
68
  }
63
69
 
64
70
  render(App);
@@ -70,20 +76,24 @@ describe('try block with catch and pending', () => {
70
76
  });
71
77
 
72
78
  it('catch block works when component throws after trackAsync with pending block', async () => {
73
- component App() {
74
- try {
75
- <ThrowingAfterAsync />
76
- } pending {
77
- <p>{'loading...'}</p>
78
- } catch (err) {
79
- <p>{'caught error'}</p>
80
- }
79
+ function App() {
80
+ return <>
81
+ try {
82
+ <ThrowingAfterAsync />
83
+ } pending {
84
+ <p>{'loading...'}</p>
85
+ } catch (err) {
86
+ <p>{'caught error'}</p>
87
+ }
88
+ </>;
81
89
  }
82
90
 
83
- component ThrowingAfterAsync() {
84
- let &[data] = trackAsync(() => Promise.resolve('hello'));
85
- throw new Error('error after await');
86
- <p>{data}</p>
91
+ function ThrowingAfterAsync() {
92
+ return <>
93
+ let &[data] = trackAsync(() => Promise.resolve('hello'));
94
+ throw new Error('error after await');
95
+ <p>{data}</p>
96
+ </>;
87
97
  }
88
98
 
89
99
  render(App);
@@ -96,15 +106,17 @@ describe('try block with catch and pending', () => {
96
106
  });
97
107
 
98
108
  it('catch block works when trackAsync rejects', async () => {
99
- component App() {
100
- try {
101
- let &[data] = trackAsync(() => Promise.reject(new Error('rejected')));
102
- <p>{data}</p>
103
- } pending {
104
- <p>{'loading...'}</p>
105
- } catch (err) {
106
- <p>{'caught rejection'}</p>
107
- }
109
+ function App() {
110
+ return <>
111
+ try {
112
+ let &[data] = trackAsync(() => Promise.reject(new Error('rejected')));
113
+ <p>{data}</p>
114
+ } pending {
115
+ <p>{'loading...'}</p>
116
+ } catch (err) {
117
+ <p>{'caught rejection'}</p>
118
+ }
119
+ </>;
108
120
  }
109
121
 
110
122
  render(App);
@@ -135,19 +147,19 @@ describe('try block with catch and pending', () => {
135
147
  return promise;
136
148
  }
137
149
 
138
- component App() {
139
- let &[version] = track(0);
140
-
141
- try {
142
- let &[data] = trackAsync(() => createRequest(version));
143
- <p class="resolved">{data}</p>
144
- } pending {
145
- <p class="pending">{'loading...'}</p>
146
- } catch (err) {
147
- <p class="caught">{(err as Error).message}</p>
148
- }
149
-
150
- <button class="retry" onClick={() => version++}>{'Retry'}</button>
150
+ function App() {
151
+ return <>
152
+ let &[version] = track(0);
153
+ try {
154
+ let &[data] = trackAsync(() => createRequest(version));
155
+ <p class="resolved">{data}</p>
156
+ } pending {
157
+ <p class="pending">{'loading...'}</p>
158
+ } catch (err) {
159
+ <p class="caught">{(err as Error).message}</p>
160
+ }
161
+ <button class="retry" onClick={() => version++}>{'Retry'}</button>
162
+ </>;
151
163
  }
152
164
 
153
165
  render(App);
@@ -199,29 +211,30 @@ describe('try block with catch and pending', () => {
199
211
  return promise;
200
212
  }
201
213
 
202
- component App() {
203
- let &[version] = track(0);
204
-
205
- try {
206
- let &[data] = trackAsync(() => {
207
- version;
208
- return createRequest(version);
209
- });
210
- <p class="resolved">{data}</p>
211
- } pending {
212
- <p class="pending">{'loading...'}</p>
213
- } catch (err, reset) {
214
- <p class="caught">{(err as Error).message}</p>
215
- <button
216
- class="retry"
217
- onClick={() => {
218
- version++;
219
- reset();
220
- }}
221
- >
222
- {'Retry'}
223
- </button>
224
- }
214
+ function App() {
215
+ return <>
216
+ let &[version] = track(0);
217
+ try {
218
+ let &[data] = trackAsync(() => {
219
+ version;
220
+ return createRequest(version);
221
+ });
222
+ <p class="resolved">{data}</p>
223
+ } pending {
224
+ <p class="pending">{'loading...'}</p>
225
+ } catch (err, reset) {
226
+ <p class="caught">{(err as Error).message}</p>
227
+ <button
228
+ class="retry"
229
+ onClick={() => {
230
+ version++;
231
+ reset();
232
+ }}
233
+ >
234
+ {'Retry'}
235
+ </button>
236
+ }
237
+ </>;
225
238
  }
226
239
 
227
240
  render(App);
@@ -261,16 +274,17 @@ describe('try block', () => {
261
274
  it(
262
275
  'does not compile ref binds as async callbacks inside try/pending trackAsync branches',
263
276
  async () => {
264
- component App() {
265
- let &[value, valueTracked] = track(1);
266
-
267
- try {
268
- let &[loaded] = trackAsync(() => Promise.resolve(value + 1));
269
- <input type="number" {ref bindValue(valueTracked)} />
270
- <span>{loaded}</span>
271
- } pending {
272
- <p>{'loading...'}</p>
273
- }
277
+ function App() {
278
+ return <>
279
+ let &[value, valueTracked] = track(1);
280
+ try {
281
+ let &[loaded] = trackAsync(() => Promise.resolve(value + 1));
282
+ <input type="number" ref={bindValue(valueTracked)} />
283
+ <span>{loaded}</span>
284
+ } pending {
285
+ <p>{'loading...'}</p>
286
+ }
287
+ </>;
274
288
  }
275
289
 
276
290
  render(App);
@@ -286,22 +300,25 @@ describe('try block', () => {
286
300
  );
287
301
 
288
302
  it('does not crash when trackAsync is used to render a list inside try/pending', async () => {
289
- component App() {
290
- try {
291
- <AsyncChild />
292
- } pending {
293
- <p>{'loading...'}</p>
294
- }
303
+ function App() {
304
+ return <>
305
+ try {
306
+ <AsyncChild />
307
+ } pending {
308
+ <p>{'loading...'}</p>
309
+ }
310
+ </>;
295
311
  }
296
312
 
297
- component AsyncChild() {
298
- let &[data] = trackAsync(() => Promise.resolve(['a', 'b', 'c']));
299
-
300
- <ul>
301
- for (let item of data) {
302
- <li>{item}</li>
303
- }
304
- </ul>
313
+ function AsyncChild() {
314
+ return <>
315
+ let &[data] = trackAsync(() => Promise.resolve(['a', 'b', 'c']));
316
+ <ul>
317
+ for (let item of data) {
318
+ <li>{item}</li>
319
+ }
320
+ </ul>
321
+ </>;
305
322
  }
306
323
 
307
324
  render(App);
@@ -318,27 +335,29 @@ describe('try block', () => {
318
335
  it(
319
336
  'does not crash when async component with tracked state is used inside try/pending',
320
337
  async () => {
321
- component App() {
322
- let &[query, queryTracked] = track('');
323
-
324
- try {
325
- <FilteredList {queryTracked} />
326
- } pending {
327
- <p>{'loading...'}</p>
328
- }
338
+ function App() {
339
+ return <>
340
+ let &[query, queryTracked] = track('');
341
+ try {
342
+ <FilteredList {queryTracked} />
343
+ } pending {
344
+ <p>{'loading...'}</p>
345
+ }
346
+ </>;
329
347
  }
330
348
 
331
- component FilteredList({ queryTracked }: { queryTracked: Tracked<string> }) {
332
- let &[items] = trackAsync(() => Promise.resolve(['apple', 'banana', 'cherry']));
333
- let &[filtered] = track(
334
- () => items.filter((item: string) => item.includes(queryTracked.value)),
335
- );
336
-
337
- <ul>
338
- for (let item of filtered) {
339
- <li>{item}</li>
340
- }
341
- </ul>
349
+ function FilteredList({ queryTracked }: { queryTracked: Tracked<string> }) {
350
+ return <>
351
+ let &[items] = trackAsync(() => Promise.resolve(['apple', 'banana', 'cherry']));
352
+ let &[filtered] = track(
353
+ () => items.filter((item: string) => item.includes(queryTracked.value)),
354
+ );
355
+ <ul>
356
+ for (let item of filtered) {
357
+ <li>{item}</li>
358
+ }
359
+ </ul>
360
+ </>;
342
361
  }
343
362
 
344
363
  render(App);
@@ -352,18 +371,20 @@ describe('try block', () => {
352
371
  );
353
372
 
354
373
  it('if test condition stays synchronous once trackAsync has resolved', async () => {
355
- component App() {
356
- try {
357
- let &[items] = trackAsync(() => Promise.resolve(['apple', 'banana', 'cherry']));
358
-
359
- if (items.includes('not-in-list')) {
360
- <p>{'not-in-list is in the list!'}</p>
361
- } else {
362
- <p>{'not-in-list is not in the list.'}</p>
374
+ function App() {
375
+ return <>
376
+ try {
377
+ let &[items] = trackAsync(() => Promise.resolve(['apple', 'banana', 'cherry']));
378
+
379
+ if (items.includes('not-in-list')) {
380
+ <p>{'not-in-list is in the list!'}</p>
381
+ } else {
382
+ <p>{'not-in-list is not in the list.'}</p>
383
+ }
384
+ } pending {
385
+ <p>{'loading...'}</p>
363
386
  }
364
- } pending {
365
- <p>{'loading...'}</p>
366
- }
387
+ </>;
367
388
  }
368
389
 
369
390
  render(App);
@@ -377,28 +398,30 @@ describe('try block', () => {
377
398
  it('destroying try block while in pending state cleans up pending branch', async () => {
378
399
  let pending_effect_teardown_count = 0;
379
400
 
380
- component PendingChild() {
381
- effect(() => {
382
- return () => {
383
- pending_effect_teardown_count++;
384
- };
385
- });
386
- <p class="pending">{'loading...'}</p>
401
+ function PendingChild() {
402
+ return <>
403
+ effect(() => {
404
+ return () => {
405
+ pending_effect_teardown_count++;
406
+ };
407
+ });
408
+ <p class="pending">{'loading...'}</p>
409
+ </>;
387
410
  }
388
411
 
389
- component App() {
390
- let &[show] = track(true);
391
-
392
- if (show) {
393
- try {
394
- let &[data] = trackAsync(() => new Promise(() => {}));
395
- <p class="resolved">{data}</p>
396
- } pending {
397
- <PendingChild />
412
+ function App() {
413
+ return <>
414
+ let &[show] = track(true);
415
+ if (show) {
416
+ try {
417
+ let &[data] = trackAsync(() => new Promise(() => {}));
418
+ <p class="resolved">{data}</p>
419
+ } pending {
420
+ <PendingChild />
421
+ }
398
422
  }
399
- }
400
-
401
- <button class="toggle" onClick={() => (show = !show)}>{'toggle'}</button>
423
+ <button class="toggle" onClick={() => (show = !show)}>{'toggle'}</button>
424
+ </>;
402
425
  }
403
426
 
404
427
  render(App);
@@ -423,30 +446,32 @@ describe('try block', () => {
423
446
  it('destroying try block while in resolved state cleans up resolved branch', async () => {
424
447
  let resolved_effect_teardown_count = 0;
425
448
 
426
- component ResolvedChild(&{ data }: { data: string }) {
427
- effect(() => {
428
- return () => {
429
- resolved_effect_teardown_count++;
430
- };
431
- });
432
- <p class="resolved">{data}</p>
449
+ function ResolvedChild(&{ data }: { data: string }) {
450
+ return <>
451
+ effect(() => {
452
+ return () => {
453
+ resolved_effect_teardown_count++;
454
+ };
455
+ });
456
+ <p class="resolved">{data}</p>
457
+ </>;
433
458
  }
434
459
 
435
- component App() {
436
- let &[show] = track(true);
437
-
438
- if (show) {
439
- try {
440
- let &[data] = trackAsync(() => Promise.resolve('hello'));
441
- <ResolvedChild {data} />
442
- } pending {
443
- <p class="pending">{'loading...'}</p>
444
- } catch (err) {
445
- <p class="caught">{(err as Error).message}</p>
460
+ function App() {
461
+ return <>
462
+ let &[show] = track(true);
463
+ if (show) {
464
+ try {
465
+ let &[data] = trackAsync(() => Promise.resolve('hello'));
466
+ <ResolvedChild {data} />
467
+ } pending {
468
+ <p class="pending">{'loading...'}</p>
469
+ } catch (err) {
470
+ <p class="caught">{(err as Error).message}</p>
471
+ }
446
472
  }
447
- }
448
-
449
- <button class="toggle" onClick={() => (show = !show)}>{'toggle'}</button>
473
+ <button class="toggle" onClick={() => (show = !show)}>{'toggle'}</button>
474
+ </>;
450
475
  }
451
476
 
452
477
  render(App);
@@ -472,30 +497,32 @@ describe('try block', () => {
472
497
  it('destroying try block while in catch state cleans up catch branch', async () => {
473
498
  let catch_effect_teardown_count = 0;
474
499
 
475
- component CatchChild({ error }: { error: Error }) {
476
- effect(() => {
477
- return () => {
478
- catch_effect_teardown_count++;
479
- };
480
- });
481
- <p class="caught">{error.message}</p>
500
+ function CatchChild({ error }: { error: Error }) {
501
+ return <>
502
+ effect(() => {
503
+ return () => {
504
+ catch_effect_teardown_count++;
505
+ };
506
+ });
507
+ <p class="caught">{error.message}</p>
508
+ </>;
482
509
  }
483
510
 
484
- component App() {
485
- let &[show] = track(true);
486
-
487
- if (show) {
488
- try {
489
- let &[data] = trackAsync(() => Promise.reject(new Error('fail')));
490
- <p class="resolved">{data}</p>
491
- } pending {
492
- <p class="pending">{'loading...'}</p>
493
- } catch (err) {
494
- <CatchChild error={err as Error} />
511
+ function App() {
512
+ return <>
513
+ let &[show] = track(true);
514
+ if (show) {
515
+ try {
516
+ let &[data] = trackAsync(() => Promise.reject(new Error('fail')));
517
+ <p class="resolved">{data}</p>
518
+ } pending {
519
+ <p class="pending">{'loading...'}</p>
520
+ } catch (err) {
521
+ <CatchChild error={err as Error} />
522
+ }
495
523
  }
496
- }
497
-
498
- <button class="toggle" onClick={() => (show = !show)}>{'toggle'}</button>
524
+ <button class="toggle" onClick={() => (show = !show)}>{'toggle'}</button>
525
+ </>;
499
526
  }
500
527
 
501
528
  render(App);
@@ -516,20 +543,24 @@ describe('try block', () => {
516
543
  });
517
544
 
518
545
  it('pending block throwing renders catch block from the same try block', async () => {
519
- component ThrowingPending() {
520
- throw new Error('pending exploded');
521
- <p>{'should not render'}</p>
546
+ function ThrowingPending() {
547
+ return <>
548
+ throw new Error('pending exploded');
549
+ <p>{'should not render'}</p>
550
+ </>;
522
551
  }
523
552
 
524
- component App() {
525
- try {
526
- let &[data] = trackAsync(() => new Promise(() => {}));
527
- <p class="resolved">{data}</p>
528
- } pending {
529
- <ThrowingPending />
530
- } catch (err) {
531
- <p class="caught">{(err as Error).message}</p>
532
- }
553
+ function App() {
554
+ return <>
555
+ try {
556
+ let &[data] = trackAsync(() => new Promise(() => {}));
557
+ <p class="resolved">{data}</p>
558
+ } pending {
559
+ <ThrowingPending />
560
+ } catch (err) {
561
+ <p class="caught">{(err as Error).message}</p>
562
+ }
563
+ </>;
533
564
  }
534
565
 
535
566
  render(App);
@@ -545,26 +576,32 @@ describe('try block', () => {
545
576
  });
546
577
 
547
578
  it('pending block throwing without catch bubbles to parent try/catch', async () => {
548
- component ThrowingPending() {
549
- throw new Error('pending exploded');
550
- <p>{'should not render'}</p>
579
+ function ThrowingPending() {
580
+ return <>
581
+ throw new Error('pending exploded');
582
+ <p>{'should not render'}</p>
583
+ </>;
551
584
  }
552
585
 
553
- component App() {
554
- try {
555
- <Inner />
556
- } catch (err) {
557
- <p class="parent-caught">{(err as Error).message}</p>
558
- }
586
+ function App() {
587
+ return <>
588
+ try {
589
+ <Inner />
590
+ } catch (err) {
591
+ <p class="parent-caught">{(err as Error).message}</p>
592
+ }
593
+ </>;
559
594
  }
560
595
 
561
- component Inner() {
562
- try {
563
- let &[data] = trackAsync(() => new Promise(() => {}));
564
- <p class="resolved">{data}</p>
565
- } pending {
566
- <ThrowingPending />
567
- }
596
+ function Inner() {
597
+ return <>
598
+ try {
599
+ let &[data] = trackAsync(() => new Promise(() => {}));
600
+ <p class="resolved">{data}</p>
601
+ } pending {
602
+ <ThrowingPending />
603
+ }
604
+ </>;
568
605
  }
569
606
 
570
607
  render(App);
@@ -586,25 +623,27 @@ describe('try block', () => {
586
623
  first_resolve = resolve;
587
624
  });
588
625
 
589
- component App() {
590
- try {
591
- let &[name] = trackAsync(() => first_promise);
592
- let &[length] = trackAsync(() => {
593
- // Read name synchronously throws ASYNC_DERIVED_READ_THROWN
594
- // while name is still pending, triggering the deferred mechanism.
595
- const n = name;
596
- return new Promise<number>((resolve) => {
597
- second_resolve = resolve;
598
- }).then((val) => n.length + val);
599
- });
600
- <p class="resolved">
601
- {name}
602
- {' has length '}
603
- {length}
604
- </p>
605
- } pending {
606
- <p class="pending">{'loading...'}</p>
607
- }
626
+ function App() {
627
+ return <>
628
+ try {
629
+ let &[name] = trackAsync(() => first_promise);
630
+ let &[length] = trackAsync(() => {
631
+ // Read name synchronously throws ASYNC_DERIVED_READ_THROWN
632
+ // while name is still pending, triggering the deferred mechanism.
633
+ const n = name;
634
+ return new Promise<number>((resolve) => {
635
+ second_resolve = resolve;
636
+ }).then((val) => n.length + val);
637
+ });
638
+ <p class="resolved">
639
+ {name}
640
+ {' has length '}
641
+ {length}
642
+ </p>
643
+ } pending {
644
+ <p class="pending">{'loading...'}</p>
645
+ }
646
+ </>;
608
647
  }
609
648
 
610
649
  render(App);
@@ -647,28 +686,32 @@ describe('try block', () => {
647
686
  first_resolve = resolve;
648
687
  });
649
688
 
650
- component PendingTracker() {
651
- pending_render_count++;
652
- <p class="pending">{'loading...'}</p>
689
+ function PendingTracker() {
690
+ return <>
691
+ pending_render_count++;
692
+ <p class="pending">{'loading...'}</p>
693
+ </>;
653
694
  }
654
695
 
655
- component App() {
656
- try {
657
- let &[name] = trackAsync(() => first_promise);
658
- let &[length] = trackAsync(() => {
659
- const n = name;
660
- return new Promise<number>((resolve) => {
661
- second_resolve = resolve;
662
- }).then((val) => n.length + val);
663
- });
664
- <p class="resolved">
665
- {name}
666
- {' has length '}
667
- {length}
668
- </p>
669
- } pending {
670
- <PendingTracker />
671
- }
696
+ function App() {
697
+ return <>
698
+ try {
699
+ let &[name] = trackAsync(() => first_promise);
700
+ let &[length] = trackAsync(() => {
701
+ const n = name;
702
+ return new Promise<number>((resolve) => {
703
+ second_resolve = resolve;
704
+ }).then((val) => n.length + val);
705
+ });
706
+ <p class="resolved">
707
+ {name}
708
+ {' has length '}
709
+ {length}
710
+ </p>
711
+ } pending {
712
+ <PendingTracker />
713
+ }
714
+ </>;
672
715
  }
673
716
 
674
717
  render(App);
@@ -710,25 +753,27 @@ describe('try block', () => {
710
753
  first_reject = reject;
711
754
  });
712
755
 
713
- component App() {
714
- try {
715
- let &[name] = trackAsync(() => first_promise);
716
- let &[length] = trackAsync(() => {
717
- const n = name;
718
- return new Promise<number>((resolve) => {
719
- second_resolve = resolve;
720
- }).then((val) => n.length + val);
721
- });
722
- <p class="resolved">
723
- {name}
724
- {' has length '}
725
- {length}
726
- </p>
727
- } pending {
728
- <p class="pending">{'loading...'}</p>
729
- } catch (err) {
730
- <p class="caught">{(err as Error).message}</p>
731
- }
756
+ function App() {
757
+ return <>
758
+ try {
759
+ let &[name] = trackAsync(() => first_promise);
760
+ let &[length] = trackAsync(() => {
761
+ const n = name;
762
+ return new Promise<number>((resolve) => {
763
+ second_resolve = resolve;
764
+ }).then((val) => n.length + val);
765
+ });
766
+ <p class="resolved">
767
+ {name}
768
+ {' has length '}
769
+ {length}
770
+ </p>
771
+ } pending {
772
+ <p class="pending">{'loading...'}</p>
773
+ } catch (err) {
774
+ <p class="caught">{(err as Error).message}</p>
775
+ }
776
+ </>;
732
777
  }
733
778
 
734
779
  render(App);
@@ -765,25 +810,27 @@ describe('try block', () => {
765
810
  first_resolve = resolve;
766
811
  });
767
812
 
768
- component App() {
769
- try {
770
- let &[name] = trackAsync(() => first_promise);
771
- let &[length] = trackAsync(() => {
772
- const n = name;
773
- return new Promise<number>((_, reject) => {
774
- second_reject = reject;
813
+ function App() {
814
+ return <>
815
+ try {
816
+ let &[name] = trackAsync(() => first_promise);
817
+ let &[length] = trackAsync(() => {
818
+ const n = name;
819
+ return new Promise<number>((_, reject) => {
820
+ second_reject = reject;
821
+ });
775
822
  });
776
- });
777
- <p class="resolved">
778
- {name}
779
- {' has length '}
780
- {length}
781
- </p>
782
- } pending {
783
- <p class="pending">{'loading...'}</p>
784
- } catch (err) {
785
- <p class="caught">{(err as Error).message}</p>
786
- }
823
+ <p class="resolved">
824
+ {name}
825
+ {' has length '}
826
+ {length}
827
+ </p>
828
+ } pending {
829
+ <p class="pending">{'loading...'}</p>
830
+ } catch (err) {
831
+ <p class="caught">{(err as Error).message}</p>
832
+ }
833
+ </>;
787
834
  }
788
835
 
789
836
  render(App);
@@ -817,25 +864,31 @@ describe('try block', () => {
817
864
  );
818
865
 
819
866
  it('resolved try block without catch bubbles error to parent try/catch', async () => {
820
- component ThrowingChild() {
821
- let &[data] = trackAsync(() => Promise.reject(new Error('async failed')));
822
- <p class="resolved">{data}</p>
867
+ function ThrowingChild() {
868
+ return <>
869
+ let &[data] = trackAsync(() => Promise.reject(new Error('async failed')));
870
+ <p class="resolved">{data}</p>
871
+ </>;
823
872
  }
824
873
 
825
- component App() {
826
- try {
827
- <Inner />
828
- } catch (err) {
829
- <p class="parent-caught">{(err as Error).message}</p>
830
- }
874
+ function App() {
875
+ return <>
876
+ try {
877
+ <Inner />
878
+ } catch (err) {
879
+ <p class="parent-caught">{(err as Error).message}</p>
880
+ }
881
+ </>;
831
882
  }
832
883
 
833
- component Inner() {
834
- try {
835
- <ThrowingChild />
836
- } pending {
837
- <p class="pending">{'loading...'}</p>
838
- }
884
+ function Inner() {
885
+ return <>
886
+ try {
887
+ <ThrowingChild />
888
+ } pending {
889
+ <p class="pending">{'loading...'}</p>
890
+ }
891
+ </>;
839
892
  }
840
893
 
841
894
  render(App);
@@ -869,15 +922,17 @@ describe('try block', () => {
869
922
 
870
923
  let data: any;
871
924
 
872
- component App() {
873
- try {
874
- data = trackAsync(() => user_promise);
875
- <p class="resolved">{data.value}</p>
876
- } pending {
877
- <p class="pending">{'loading...'}</p>
878
- } catch (err) {
879
- <p class="caught">{(err as Error).message}</p>
880
- }
925
+ function App() {
926
+ return <>
927
+ try {
928
+ data = trackAsync(() => user_promise);
929
+ <p class="resolved">{data.value}</p>
930
+ } pending {
931
+ <p class="pending">{'loading...'}</p>
932
+ } catch (err) {
933
+ <p class="caught">{(err as Error).message}</p>
934
+ }
935
+ </>;
881
936
  }
882
937
 
883
938
  render(App);
@@ -922,25 +977,27 @@ describe('try block', () => {
922
977
  let name: any;
923
978
  let length: any;
924
979
 
925
- component App() {
926
- try {
927
- name = trackAsync(() => first_promise);
928
- length = trackAsync(() => {
929
- const n = name.value;
930
- return new Promise<number>((resolve) => {
931
- resolve(n.length);
980
+ function App() {
981
+ return <>
982
+ try {
983
+ name = trackAsync(() => first_promise);
984
+ length = trackAsync(() => {
985
+ const n = name.value;
986
+ return new Promise<number>((resolve) => {
987
+ resolve(n.length);
988
+ });
932
989
  });
933
- });
934
- <p class="resolved">
935
- {name.value}
936
- {' has length '}
937
- {length.value}
938
- </p>
939
- } pending {
940
- <p class="pending">{'loading...'}</p>
941
- } catch (err) {
942
- <p class="caught">{(err as Error).message}</p>
943
- }
990
+ <p class="resolved">
991
+ {name.value}
992
+ {' has length '}
993
+ {length.value}
994
+ </p>
995
+ } pending {
996
+ <p class="pending">{'loading...'}</p>
997
+ } catch (err) {
998
+ <p class="caught">{(err as Error).message}</p>
999
+ }
1000
+ </>;
944
1001
  }
945
1002
 
946
1003
  render(App);
@@ -990,29 +1047,31 @@ describe('try block', () => {
990
1047
  let a: any;
991
1048
  let b: any;
992
1049
  let c: any;
993
- component App() {
994
- try {
995
- a = trackAsync(() => a_promise);
996
- b = trackAsync(() => {
997
- const val = a.value;
998
- return Promise.resolve(val.toUpperCase());
999
- });
1000
- c = trackAsync(() => {
1001
- const val = b.value;
1002
- return Promise.resolve(val.length);
1003
- });
1004
- <p class="resolved">
1005
- {a.value}
1006
- {' → '}
1007
- {b.value}
1008
- {' → '}
1009
- {c.value}
1010
- </p>
1011
- } pending {
1012
- <p class="pending">{'loading...'}</p>
1013
- } catch (err) {
1014
- <p class="caught">{(err as Error).message}</p>
1015
- }
1050
+ function App() {
1051
+ return <>
1052
+ try {
1053
+ a = trackAsync(() => a_promise);
1054
+ b = trackAsync(() => {
1055
+ const val = a.value;
1056
+ return Promise.resolve(val.toUpperCase());
1057
+ });
1058
+ c = trackAsync(() => {
1059
+ const val = b.value;
1060
+ return Promise.resolve(val.length);
1061
+ });
1062
+ <p class="resolved">
1063
+ {a.value}
1064
+ {' → '}
1065
+ {b.value}
1066
+ {' → '}
1067
+ {c.value}
1068
+ </p>
1069
+ } pending {
1070
+ <p class="pending">{'loading...'}</p>
1071
+ } catch (err) {
1072
+ <p class="caught">{(err as Error).message}</p>
1073
+ }
1074
+ </>;
1016
1075
  }
1017
1076
 
1018
1077
  render(App);
@@ -1074,20 +1133,22 @@ describe('try block', () => {
1074
1133
 
1075
1134
  let name: any;
1076
1135
  let count: any;
1077
- component App() {
1078
- try {
1079
- name = trackAsync(() => first_promise);
1080
- count = trackAsync(() => second_promise);
1081
- <p class="resolved">
1082
- {name.value}
1083
- {' count: '}
1084
- {count.value}
1085
- </p>
1086
- } pending {
1087
- <p class="pending">{'loading...'}</p>
1088
- } catch (err) {
1089
- <p class="caught">{(err as Error).message}</p>
1090
- }
1136
+ function App() {
1137
+ return <>
1138
+ try {
1139
+ name = trackAsync(() => first_promise);
1140
+ count = trackAsync(() => second_promise);
1141
+ <p class="resolved">
1142
+ {name.value}
1143
+ {' count: '}
1144
+ {count.value}
1145
+ </p>
1146
+ } pending {
1147
+ <p class="pending">{'loading...'}</p>
1148
+ } catch (err) {
1149
+ <p class="caught">{(err as Error).message}</p>
1150
+ }
1151
+ </>;
1091
1152
  }
1092
1153
 
1093
1154
  render(App);
@@ -1140,25 +1201,31 @@ describe('sync error while async deriveds are pending', () => {
1140
1201
  (e) => (promise_settled = { type: 'rejected', value: e }),
1141
1202
  );
1142
1203
 
1143
- component App() {
1144
- try {
1145
- <AsyncChild />
1146
- <ThrowingChild />
1147
- } pending {
1148
- <p class="pending">{'loading...'}</p>
1149
- } catch (err: Error) {
1150
- <p class="caught">{err.message}</p>
1151
- }
1204
+ function App() {
1205
+ return <>
1206
+ try {
1207
+ <AsyncChild />
1208
+ <ThrowingChild />
1209
+ } pending {
1210
+ <p class="pending">{'loading...'}</p>
1211
+ } catch (err: Error) {
1212
+ <p class="caught">{err.message}</p>
1213
+ }
1214
+ </>;
1152
1215
  }
1153
1216
 
1154
1217
  let data: any;
1155
- component AsyncChild() {
1156
- data = trackAsync(() => user_promise);
1157
- <p class="async-resolved">{data.value}</p>
1218
+ function AsyncChild() {
1219
+ return <>
1220
+ data = trackAsync(() => user_promise);
1221
+ <p class="async-resolved">{data.value}</p>
1222
+ </>;
1158
1223
  }
1159
1224
 
1160
- component ThrowingChild() {
1161
- throw new Error('sync boom');
1225
+ function ThrowingChild() {
1226
+ return <>
1227
+ throw new Error('sync boom');
1228
+ </>;
1162
1229
  }
1163
1230
 
1164
1231
  render(App);
@@ -1205,25 +1272,31 @@ describe('sync error while async deriveds are pending', () => {
1205
1272
  (e) => (promise_settled = { type: 'rejected', value: e }),
1206
1273
  );
1207
1274
 
1208
- component App() {
1209
- try {
1210
- <AsyncChild />
1211
- <ThrowingChild />
1212
- } pending {
1213
- <p class="pending">{'loading...'}</p>
1214
- } catch (err: Error) {
1215
- <p class="caught">{err.message}</p>
1216
- }
1275
+ function App() {
1276
+ return <>
1277
+ try {
1278
+ <AsyncChild />
1279
+ <ThrowingChild />
1280
+ } pending {
1281
+ <p class="pending">{'loading...'}</p>
1282
+ } catch (err: Error) {
1283
+ <p class="caught">{err.message}</p>
1284
+ }
1285
+ </>;
1217
1286
  }
1218
1287
 
1219
1288
  let data: any;
1220
- component AsyncChild() {
1221
- data = trackAsync(() => user_promise);
1222
- <p class="async-resolved">{data.value}</p>
1289
+ function AsyncChild() {
1290
+ return <>
1291
+ data = trackAsync(() => user_promise);
1292
+ <p class="async-resolved">{data.value}</p>
1293
+ </>;
1223
1294
  }
1224
1295
 
1225
- component ThrowingChild() {
1226
- throw new Error('sync boom');
1296
+ function ThrowingChild() {
1297
+ return <>
1298
+ throw new Error('sync boom');
1299
+ </>;
1227
1300
  }
1228
1301
 
1229
1302
  render(App);
@@ -1277,32 +1350,40 @@ describe('sync error while async deriveds are pending', () => {
1277
1350
  (e) => (settled_b = { type: 'rejected', value: e }),
1278
1351
  );
1279
1352
 
1280
- component App() {
1281
- try {
1282
- <ChildA />
1283
- <ChildB />
1284
- <ThrowingChild />
1285
- } pending {
1286
- <p class="pending">{'loading...'}</p>
1287
- } catch (err: Error) {
1288
- <p class="caught">{err.message}</p>
1289
- }
1353
+ function App() {
1354
+ return <>
1355
+ try {
1356
+ <ChildA />
1357
+ <ChildB />
1358
+ <ThrowingChild />
1359
+ } pending {
1360
+ <p class="pending">{'loading...'}</p>
1361
+ } catch (err: Error) {
1362
+ <p class="caught">{err.message}</p>
1363
+ }
1364
+ </>;
1290
1365
  }
1291
1366
 
1292
1367
  let dataA: any;
1293
- component ChildA() {
1294
- dataA = trackAsync(() => promise_a);
1295
- <p class="a">{dataA.value}</p>
1368
+ function ChildA() {
1369
+ return <>
1370
+ dataA = trackAsync(() => promise_a);
1371
+ <p class="a">{dataA.value}</p>
1372
+ </>;
1296
1373
  }
1297
1374
 
1298
1375
  let dataB: any;
1299
- component ChildB() {
1300
- dataB = trackAsync(() => promise_b);
1301
- <p class="b">{dataB.value}</p>
1376
+ function ChildB() {
1377
+ return <>
1378
+ dataB = trackAsync(() => promise_b);
1379
+ <p class="b">{dataB.value}</p>
1380
+ </>;
1302
1381
  }
1303
1382
 
1304
- component ThrowingChild() {
1305
- throw new Error('sync boom');
1383
+ function ThrowingChild() {
1384
+ return <>
1385
+ throw new Error('sync boom');
1386
+ </>;
1306
1387
  }
1307
1388
 
1308
1389
  render(App);
@@ -1362,32 +1443,40 @@ describe('sync error while async deriveds are pending', () => {
1362
1443
  (e) => (settled_b = { type: 'rejected', value: e }),
1363
1444
  );
1364
1445
 
1365
- component App() {
1366
- try {
1367
- <ChildA />
1368
- <ChildB />
1369
- <ThrowingChild />
1370
- } pending {
1371
- <p class="pending">{'loading...'}</p>
1372
- } catch (err: Error) {
1373
- <p class="caught">{err.message}</p>
1374
- }
1446
+ function App() {
1447
+ return <>
1448
+ try {
1449
+ <ChildA />
1450
+ <ChildB />
1451
+ <ThrowingChild />
1452
+ } pending {
1453
+ <p class="pending">{'loading...'}</p>
1454
+ } catch (err: Error) {
1455
+ <p class="caught">{err.message}</p>
1456
+ }
1457
+ </>;
1375
1458
  }
1376
1459
 
1377
1460
  let dataA: any;
1378
- component ChildA() {
1379
- dataA = trackAsync(() => promise_a);
1380
- <p class="a">{dataA.value}</p>
1461
+ function ChildA() {
1462
+ return <>
1463
+ dataA = trackAsync(() => promise_a);
1464
+ <p class="a">{dataA.value}</p>
1465
+ </>;
1381
1466
  }
1382
1467
 
1383
1468
  let dataB: any;
1384
- component ChildB() {
1385
- dataB = trackAsync(() => promise_b);
1386
- <p class="b">{dataB.value}</p>
1469
+ function ChildB() {
1470
+ return <>
1471
+ dataB = trackAsync(() => promise_b);
1472
+ <p class="b">{dataB.value}</p>
1473
+ </>;
1387
1474
  }
1388
1475
 
1389
- component ThrowingChild() {
1390
- throw new Error('sync boom');
1476
+ function ThrowingChild() {
1477
+ return <>
1478
+ throw new Error('sync boom');
1479
+ </>;
1391
1480
  }
1392
1481
 
1393
1482
  render(App);
@@ -1425,25 +1514,31 @@ describe('sync error while async deriveds are pending', () => {
1425
1514
  );
1426
1515
 
1427
1516
  it('try block without catch propagates sync error to upstream boundary', async () => {
1428
- component ThrowingChild() {
1429
- throw new Error('no catch here');
1430
- <p>{'should not render'}</p>
1517
+ function ThrowingChild() {
1518
+ return <>
1519
+ throw new Error('no catch here');
1520
+ <p>{'should not render'}</p>
1521
+ </>;
1431
1522
  }
1432
1523
 
1433
- component App() {
1434
- try {
1435
- <Inner />
1436
- } catch (err) {
1437
- <p class="upstream-caught">{(err as Error).message}</p>
1438
- }
1524
+ function App() {
1525
+ return <>
1526
+ try {
1527
+ <Inner />
1528
+ } catch (err) {
1529
+ <p class="upstream-caught">{(err as Error).message}</p>
1530
+ }
1531
+ </>;
1439
1532
  }
1440
1533
 
1441
- component Inner() {
1442
- try {
1443
- <ThrowingChild />
1444
- } pending {
1445
- <p class="inner-pending">{'loading...'}</p>
1446
- }
1534
+ function Inner() {
1535
+ return <>
1536
+ try {
1537
+ <ThrowingChild />
1538
+ } pending {
1539
+ <p class="inner-pending">{'loading...'}</p>
1540
+ }
1541
+ </>;
1447
1542
  }
1448
1543
 
1449
1544
  render(App);
@@ -1454,21 +1549,25 @@ describe('sync error while async deriveds are pending', () => {
1454
1549
  });
1455
1550
 
1456
1551
  it('try block without catch propagates async rejection to upstream boundary', async () => {
1457
- component App() {
1458
- try {
1459
- <Inner />
1460
- } catch (err) {
1461
- <p class="upstream-caught">{(err as Error).message}</p>
1462
- }
1552
+ function App() {
1553
+ return <>
1554
+ try {
1555
+ <Inner />
1556
+ } catch (err) {
1557
+ <p class="upstream-caught">{(err as Error).message}</p>
1558
+ }
1559
+ </>;
1463
1560
  }
1464
1561
 
1465
- component Inner() {
1466
- try {
1467
- let &[data] = trackAsync(() => Promise.reject(new Error('async no catch')));
1468
- <p class="resolved">{data}</p>
1469
- } pending {
1470
- <p class="inner-pending">{'loading...'}</p>
1471
- }
1562
+ function Inner() {
1563
+ return <>
1564
+ try {
1565
+ let &[data] = trackAsync(() => Promise.reject(new Error('async no catch')));
1566
+ <p class="resolved">{data}</p>
1567
+ } pending {
1568
+ <p class="inner-pending">{'loading...'}</p>
1569
+ }
1570
+ </>;
1472
1571
  }
1473
1572
 
1474
1573
  render(App);
@@ -1487,21 +1586,25 @@ describe('sync error while async deriveds are pending', () => {
1487
1586
  reject_fn = reject;
1488
1587
  });
1489
1588
 
1490
- component App() {
1491
- try {
1492
- <Inner />
1493
- } catch (err) {
1494
- <p class="upstream-caught">{(err as Error).message}</p>
1495
- }
1589
+ function App() {
1590
+ return <>
1591
+ try {
1592
+ <Inner />
1593
+ } catch (err) {
1594
+ <p class="upstream-caught">{(err as Error).message}</p>
1595
+ }
1596
+ </>;
1496
1597
  }
1497
1598
 
1498
- component Inner() {
1499
- try {
1500
- let &[data] = trackAsync(() => user_promise);
1501
- <p class="resolved">{data}</p>
1502
- } pending {
1503
- <p class="inner-pending">{'loading...'}</p>
1504
- }
1599
+ function Inner() {
1600
+ return <>
1601
+ try {
1602
+ let &[data] = trackAsync(() => user_promise);
1603
+ <p class="resolved">{data}</p>
1604
+ } pending {
1605
+ <p class="inner-pending">{'loading...'}</p>
1606
+ }
1607
+ </>;
1505
1608
  }
1506
1609
 
1507
1610
  render(App);
@@ -1522,33 +1625,41 @@ describe('sync error while async deriveds are pending', () => {
1522
1625
  );
1523
1626
 
1524
1627
  it('nested try blocks without catch propagate error through multiple levels', async () => {
1525
- component ThrowingChild() {
1526
- throw new Error('deep error');
1527
- <p>{'should not render'}</p>
1628
+ function ThrowingChild() {
1629
+ return <>
1630
+ throw new Error('deep error');
1631
+ <p>{'should not render'}</p>
1632
+ </>;
1528
1633
  }
1529
1634
 
1530
- component App() {
1531
- try {
1532
- <Middle />
1533
- } catch (err) {
1534
- <p class="top-caught">{(err as Error).message}</p>
1535
- }
1635
+ function App() {
1636
+ return <>
1637
+ try {
1638
+ <Middle />
1639
+ } catch (err) {
1640
+ <p class="top-caught">{(err as Error).message}</p>
1641
+ }
1642
+ </>;
1536
1643
  }
1537
1644
 
1538
- component Middle() {
1539
- try {
1540
- <Inner />
1541
- } pending {
1542
- <p class="mid-pending">{'loading...'}</p>
1543
- }
1645
+ function Middle() {
1646
+ return <>
1647
+ try {
1648
+ <Inner />
1649
+ } pending {
1650
+ <p class="mid-pending">{'loading...'}</p>
1651
+ }
1652
+ </>;
1544
1653
  }
1545
1654
 
1546
- component Inner() {
1547
- try {
1548
- <ThrowingChild />
1549
- } pending {
1550
- <p class="inner-pending">{'loading...'}</p>
1551
- }
1655
+ function Inner() {
1656
+ return <>
1657
+ try {
1658
+ <ThrowingChild />
1659
+ } pending {
1660
+ <p class="inner-pending">{'loading...'}</p>
1661
+ }
1662
+ </>;
1552
1663
  }
1553
1664
 
1554
1665
  render(App);
@@ -1559,17 +1670,21 @@ describe('sync error while async deriveds are pending', () => {
1559
1670
  });
1560
1671
 
1561
1672
  it('try block without catch throws to global when no upstream boundary exists', async () => {
1562
- component ThrowingChild() {
1563
- throw new Error('unhandled error');
1564
- <p>{'should not render'}</p>
1673
+ function ThrowingChild() {
1674
+ return <>
1675
+ throw new Error('unhandled error');
1676
+ <p>{'should not render'}</p>
1677
+ </>;
1565
1678
  }
1566
1679
 
1567
- component App() {
1568
- try {
1569
- <ThrowingChild />
1570
- } pending {
1571
- <p class="pending">{'loading...'}</p>
1572
- }
1680
+ function App() {
1681
+ return <>
1682
+ try {
1683
+ <ThrowingChild />
1684
+ } pending {
1685
+ <p class="pending">{'loading...'}</p>
1686
+ }
1687
+ </>;
1573
1688
  }
1574
1689
 
1575
1690
  expect(() => {
@@ -1585,21 +1700,25 @@ describe('sync error while async deriveds are pending', () => {
1585
1700
  reject_fn = reject;
1586
1701
  });
1587
1702
 
1588
- component Inner() {
1589
- try {
1590
- let &[data] = trackAsync(() => user_promise);
1591
- <p class="resolved">{data}</p>
1592
- } catch (err) {
1593
- <p class="downstream-caught">{(err as Error).message}</p>
1594
- }
1703
+ function Inner() {
1704
+ return <>
1705
+ try {
1706
+ let &[data] = trackAsync(() => user_promise);
1707
+ <p class="resolved">{data}</p>
1708
+ } catch (err) {
1709
+ <p class="downstream-caught">{(err as Error).message}</p>
1710
+ }
1711
+ </>;
1595
1712
  }
1596
1713
 
1597
- component App() {
1598
- try {
1599
- <Inner />
1600
- } pending {
1601
- <p class="outer-pending">{'loading...'}</p>
1602
- }
1714
+ function App() {
1715
+ return <>
1716
+ try {
1717
+ <Inner />
1718
+ } pending {
1719
+ <p class="outer-pending">{'loading...'}</p>
1720
+ }
1721
+ </>;
1603
1722
  }
1604
1723
 
1605
1724
  render(App);
@@ -1638,22 +1757,26 @@ describe('sync error while async deriveds are pending', () => {
1638
1757
  (e) => (user_settled = { type: 'rejected', value: e }),
1639
1758
  );
1640
1759
 
1641
- component Inner() {
1642
- try {
1643
- let &[data] = trackAsync(() => user_promise);
1644
- throw new Error('synchronous error');
1645
- <p class="resolved">{data}</p>
1646
- } catch (err) {
1647
- <p class="downstream-caught">{(err as Error).message}</p>
1648
- }
1760
+ function Inner() {
1761
+ return <>
1762
+ try {
1763
+ let &[data] = trackAsync(() => user_promise);
1764
+ throw new Error('synchronous error');
1765
+ <p class="resolved">{data}</p>
1766
+ } catch (err) {
1767
+ <p class="downstream-caught">{(err as Error).message}</p>
1768
+ }
1769
+ </>;
1649
1770
  }
1650
1771
 
1651
- component App() {
1652
- try {
1653
- <Inner />
1654
- } pending {
1655
- <p class="outer-pending">{'loading...'}</p>
1656
- }
1772
+ function App() {
1773
+ return <>
1774
+ try {
1775
+ <Inner />
1776
+ } pending {
1777
+ <p class="outer-pending">{'loading...'}</p>
1778
+ }
1779
+ </>;
1657
1780
  }
1658
1781
 
1659
1782
  render(App);
@@ -1693,22 +1816,26 @@ describe('sync error while async deriveds are pending', () => {
1693
1816
  (e) => (user_settled = { type: 'rejected', value: e }),
1694
1817
  );
1695
1818
 
1696
- component Inner() {
1697
- try {
1698
- let &[data] = trackAsync(() => user_promise);
1699
- throw new Error('synchronous error');
1700
- <p class="resolved">{data}</p>
1701
- } catch (err) {
1702
- <p class="downstream-caught">{(err as Error).message}</p>
1703
- }
1819
+ function Inner() {
1820
+ return <>
1821
+ try {
1822
+ let &[data] = trackAsync(() => user_promise);
1823
+ throw new Error('synchronous error');
1824
+ <p class="resolved">{data}</p>
1825
+ } catch (err) {
1826
+ <p class="downstream-caught">{(err as Error).message}</p>
1827
+ }
1828
+ </>;
1704
1829
  }
1705
1830
 
1706
- component App() {
1707
- try {
1708
- <Inner />
1709
- } pending {
1710
- <p class="outer-pending">{'loading...'}</p>
1711
- }
1831
+ function App() {
1832
+ return <>
1833
+ try {
1834
+ <Inner />
1835
+ } pending {
1836
+ <p class="outer-pending">{'loading...'}</p>
1837
+ }
1838
+ </>;
1712
1839
  }
1713
1840
 
1714
1841
  render(App);