ripple 0.3.72 → 0.3.74

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