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.
- package/CHANGELOG.md +57 -0
- package/package.json +3 -3
- package/src/jsx-runtime.d.ts +2 -2
- package/src/runtime/element.js +1 -1
- package/src/runtime/index-client.js +11 -11
- package/src/runtime/index-server.js +7 -4
- package/src/runtime/internal/client/bindings.js +1 -1
- package/src/runtime/internal/client/blocks.js +13 -4
- package/src/runtime/internal/client/component.js +55 -0
- package/src/runtime/internal/client/composite.js +4 -2
- package/src/runtime/internal/client/expression.js +65 -7
- package/src/runtime/internal/client/hmr.js +54 -43
- package/src/runtime/internal/client/index.js +5 -1
- package/src/runtime/internal/client/portal.js +70 -69
- package/src/runtime/internal/client/render.js +3 -0
- package/src/runtime/internal/server/index.js +92 -8
- package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
- package/tests/client/array/array.copy-within.test.tsrx +33 -31
- package/tests/client/array/array.derived.test.tsrx +186 -169
- package/tests/client/array/array.iteration.test.tsrx +40 -37
- package/tests/client/array/array.mutations.test.tsrx +113 -101
- package/tests/client/array/array.static.test.tsrx +119 -101
- package/tests/client/array/array.to-methods.test.tsrx +24 -21
- package/tests/client/async-suspend.test.tsrx +247 -246
- package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
- package/tests/client/basic/basic.attributes.test.tsrx +428 -423
- package/tests/client/basic/basic.collections.test.tsrx +109 -102
- package/tests/client/basic/basic.components.test.tsrx +323 -205
- package/tests/client/basic/basic.errors.test.tsrx +91 -91
- package/tests/client/basic/basic.events.test.tsrx +114 -115
- package/tests/client/basic/basic.get-set.test.tsrx +97 -87
- package/tests/client/basic/basic.hmr.test.tsrx +19 -16
- package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
- package/tests/client/basic/basic.rendering.test.tsrx +272 -182
- package/tests/client/basic/basic.styling.test.tsrx +23 -22
- package/tests/client/basic/basic.utilities.test.tsrx +10 -8
- package/tests/client/boundaries.test.tsrx +26 -26
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
- package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
- package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
- package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
- package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
- package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
- package/tests/client/composite/composite.generics.test.tsrx +168 -192
- package/tests/client/composite/composite.props.test.tsrx +97 -81
- package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
- package/tests/client/composite/composite.render.test.tsrx +122 -105
- package/tests/client/computed-properties.test.tsrx +28 -28
- package/tests/client/context.test.tsrx +21 -21
- package/tests/client/css/global-additional-cases.test.tsrx +58 -58
- package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
- package/tests/client/css/global-at-rules.test.tsrx +10 -10
- package/tests/client/css/global-basic.test.tsrx +14 -14
- package/tests/client/css/global-classes-ids.test.tsrx +14 -14
- package/tests/client/css/global-combinators.test.tsrx +10 -10
- package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
- package/tests/client/css/global-edge-cases.test.tsrx +18 -18
- package/tests/client/css/global-keyframes.test.tsrx +12 -12
- package/tests/client/css/global-nested.test.tsrx +10 -10
- package/tests/client/css/global-pseudo.test.tsrx +12 -12
- package/tests/client/css/global-scoping.test.tsrx +20 -20
- package/tests/client/css/style-identifier.test.tsrx +126 -259
- package/tests/client/date.test.tsrx +146 -133
- package/tests/client/dynamic-elements.test.tsrx +398 -365
- package/tests/client/events.test.tsrx +292 -290
- package/tests/client/for.test.tsrx +156 -153
- package/tests/client/head.test.tsrx +105 -96
- package/tests/client/html.test.tsrx +122 -26
- package/tests/client/input-value.test.tsrx +1361 -1314
- package/tests/client/lazy-array.test.tsrx +16 -13
- package/tests/client/lazy-destructuring.test.tsrx +257 -213
- package/tests/client/map.test.tsrx +65 -60
- package/tests/client/media-query.test.tsrx +22 -20
- package/tests/client/object.test.tsrx +87 -81
- package/tests/client/portal.test.tsrx +57 -51
- package/tests/client/ref.test.tsrx +233 -202
- package/tests/client/return.test.tsrx +71 -2560
- package/tests/client/set.test.tsrx +54 -45
- package/tests/client/svg.test.tsrx +216 -186
- package/tests/client/switch.test.tsrx +194 -193
- package/tests/client/track-async-hydration.test.tsrx +18 -14
- package/tests/client/tracked-index-access.test.tsrx +28 -18
- package/tests/client/try.test.tsrx +675 -548
- package/tests/client/tsx.test.tsrx +373 -311
- package/tests/client/typescript-generics.test.tsrx +145 -145
- package/tests/client/url/url.derived.test.tsrx +33 -28
- package/tests/client/url/url.parsing.test.tsrx +61 -51
- package/tests/client/url/url.partial-removal.test.tsrx +56 -48
- package/tests/client/url/url.reactivity.test.tsrx +142 -125
- package/tests/client/url/url.serialization.test.tsrx +13 -11
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
- package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
- package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
- package/tests/hydration/basic.test.js +3 -3
- package/tests/hydration/compiled/client/basic.js +586 -651
- package/tests/hydration/compiled/client/composite.js +79 -104
- package/tests/hydration/compiled/client/events.js +140 -148
- package/tests/hydration/compiled/client/for.js +1005 -1018
- package/tests/hydration/compiled/client/head.js +124 -134
- package/tests/hydration/compiled/client/hmr.js +41 -48
- package/tests/hydration/compiled/client/html-in-template.js +38 -41
- package/tests/hydration/compiled/client/html.js +970 -1314
- package/tests/hydration/compiled/client/if-children.js +234 -249
- package/tests/hydration/compiled/client/if.js +182 -189
- package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
- package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
- package/tests/hydration/compiled/client/portal.js +65 -85
- package/tests/hydration/compiled/client/reactivity.js +84 -90
- package/tests/hydration/compiled/client/return.js +38 -1939
- package/tests/hydration/compiled/client/switch.js +218 -224
- package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
- package/tests/hydration/compiled/client/try.js +123 -132
- package/tests/hydration/compiled/server/basic.js +773 -831
- package/tests/hydration/compiled/server/composite.js +166 -191
- package/tests/hydration/compiled/server/events.js +170 -184
- package/tests/hydration/compiled/server/for.js +851 -909
- package/tests/hydration/compiled/server/head.js +206 -216
- package/tests/hydration/compiled/server/hmr.js +64 -72
- package/tests/hydration/compiled/server/html-in-template.js +42 -76
- package/tests/hydration/compiled/server/html.js +1362 -1667
- package/tests/hydration/compiled/server/if-children.js +419 -445
- package/tests/hydration/compiled/server/if.js +194 -208
- package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
- package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
- package/tests/hydration/compiled/server/portal.js +152 -160
- package/tests/hydration/compiled/server/reactivity.js +94 -106
- package/tests/hydration/compiled/server/return.js +28 -2172
- package/tests/hydration/compiled/server/switch.js +274 -286
- package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
- package/tests/hydration/compiled/server/try.js +167 -185
- package/tests/hydration/components/basic.tsrx +320 -272
- package/tests/hydration/components/composite.tsrx +44 -32
- package/tests/hydration/components/events.tsrx +101 -91
- package/tests/hydration/components/for.tsrx +510 -452
- package/tests/hydration/components/head.tsrx +87 -80
- package/tests/hydration/components/hmr.tsrx +22 -17
- package/tests/hydration/components/html-in-template.tsrx +22 -17
- package/tests/hydration/components/html.tsrx +525 -443
- package/tests/hydration/components/if-children.tsrx +158 -148
- package/tests/hydration/components/if.tsrx +109 -95
- package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
- package/tests/hydration/components/nested-control-flow.tsrx +215 -203
- package/tests/hydration/components/portal.tsrx +41 -34
- package/tests/hydration/components/reactivity.tsrx +37 -27
- package/tests/hydration/components/return.tsrx +12 -556
- package/tests/hydration/components/switch.tsrx +120 -114
- package/tests/hydration/components/track-async-serialization.tsrx +107 -91
- package/tests/hydration/components/try.tsrx +55 -40
- package/tests/hydration/html.test.js +4 -4
- package/tests/hydration/return.test.js +13 -532
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +264 -195
- package/tests/server/basic.components.test.tsrx +296 -169
- package/tests/server/basic.test.tsrx +300 -198
- package/tests/server/compiler.test.tsrx +62 -60
- package/tests/server/composite.props.test.tsrx +77 -63
- package/tests/server/composite.test.tsrx +168 -192
- package/tests/server/context.test.tsrx +18 -12
- package/tests/server/dynamic-elements.test.tsrx +197 -180
- package/tests/server/for.test.tsrx +85 -78
- package/tests/server/head.test.tsrx +50 -43
- package/tests/server/html-nesting-validation.test.tsrx +8 -8
- package/tests/server/if.test.tsrx +57 -51
- package/tests/server/lazy-destructuring.test.tsrx +366 -294
- package/tests/server/return.test.tsrx +76 -1355
- package/tests/server/streaming-ssr.test.tsrx +4 -75
- package/tests/server/style-identifier.test.tsrx +169 -131
- package/tests/server/switch.test.tsrx +91 -85
- package/tests/server/track-async-serialization.test.tsrx +105 -85
- package/tests/server/try.test.tsrx +374 -280
- package/tests/utils/compiler-compat-config.test.js +2 -2
- package/tests/utils/runtime-imports.test.js +10 -0
- package/types/index.d.ts +8 -0
- package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
|
@@ -2,13 +2,15 @@ import { trackAsync } from 'ripple';
|
|
|
2
2
|
|
|
3
3
|
describe('try block with catch and pending (server)', () => {
|
|
4
4
|
it('renders resolved content with an empty pending fallback', async () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
function App() {
|
|
6
|
+
return <>
|
|
7
|
+
<span>{'before'}</span>
|
|
8
|
+
try {
|
|
9
|
+
let &[data] = trackAsync(() => Promise.resolve('resolved value'));
|
|
10
|
+
<p>{data}</p>
|
|
11
|
+
} pending {}
|
|
12
|
+
<span>{'after'}</span>
|
|
13
|
+
</>;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
const { body } = await render(App);
|
|
@@ -19,20 +21,24 @@ describe('try block with catch and pending (server)', () => {
|
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
it('catch block works when component throws before await with pending block', async () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
function ThrowingChild() {
|
|
25
|
+
return <>
|
|
26
|
+
throw new Error('sync error');
|
|
27
|
+
let &[data] = trackAsync(() => Promise.resolve('hello'));
|
|
28
|
+
<p>{data}</p>
|
|
29
|
+
</>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
return <>
|
|
34
|
+
try {
|
|
35
|
+
<ThrowingChild />
|
|
36
|
+
} pending {
|
|
37
|
+
<p>{'loading...'}</p>
|
|
38
|
+
} catch (err) {
|
|
39
|
+
<p>{'caught error'}</p>
|
|
40
|
+
}
|
|
41
|
+
</>;
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
const { body } = await render(App);
|
|
@@ -41,20 +47,24 @@ describe('try block with catch and pending (server)', () => {
|
|
|
41
47
|
});
|
|
42
48
|
|
|
43
49
|
it('catch block works when component throws after await with pending block', async () => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
function ThrowingAfterAwait() {
|
|
51
|
+
return <>
|
|
52
|
+
let &[data] = trackAsync(() => Promise.resolve('hello'));
|
|
53
|
+
throw new Error('error after await');
|
|
54
|
+
<p>{data}</p>
|
|
55
|
+
</>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function App() {
|
|
59
|
+
return <>
|
|
60
|
+
try {
|
|
61
|
+
<ThrowingAfterAwait />
|
|
62
|
+
} pending {
|
|
63
|
+
<p>{'loading...'}</p>
|
|
64
|
+
} catch (err) {
|
|
65
|
+
<p>{'caught error'}</p>
|
|
66
|
+
}
|
|
67
|
+
</>;
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
const { body } = await render(App);
|
|
@@ -63,15 +73,17 @@ describe('try block with catch and pending (server)', () => {
|
|
|
63
73
|
});
|
|
64
74
|
|
|
65
75
|
it('catch block works with try/catch/pending when async body rejects', async () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
function App() {
|
|
77
|
+
return <>
|
|
78
|
+
try {
|
|
79
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('rejected')));
|
|
80
|
+
<p>{data}</p>
|
|
81
|
+
} pending {
|
|
82
|
+
<p>{'loading...'}</p>
|
|
83
|
+
} catch (err) {
|
|
84
|
+
<p>{'caught rejection'}</p>
|
|
85
|
+
}
|
|
86
|
+
</>;
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
const { body } = await render(App);
|
|
@@ -80,17 +92,19 @@ describe('try block with catch and pending (server)', () => {
|
|
|
80
92
|
});
|
|
81
93
|
|
|
82
94
|
it('removes pending content for nested try/pending blocks', async () => {
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
function App() {
|
|
96
|
+
return <>
|
|
85
97
|
try {
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
try {
|
|
99
|
+
let &[data] = trackAsync(() => Promise.resolve('resolved'));
|
|
100
|
+
<p>{data}</p>
|
|
101
|
+
} pending {
|
|
102
|
+
<p>{'inner loading...'}</p>
|
|
103
|
+
}
|
|
88
104
|
} pending {
|
|
89
|
-
<p>{'
|
|
105
|
+
<p>{'outer loading...'}</p>
|
|
90
106
|
}
|
|
91
|
-
|
|
92
|
-
<p>{'outer loading...'}</p>
|
|
93
|
-
}
|
|
107
|
+
</>;
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
const { body } = await render(App);
|
|
@@ -102,17 +116,21 @@ describe('try block with catch and pending (server)', () => {
|
|
|
102
116
|
|
|
103
117
|
describe('trackAsync directly in component body (server)', () => {
|
|
104
118
|
it('resolves trackAsync used directly in a component', async () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
function App() {
|
|
120
|
+
return <>
|
|
121
|
+
try {
|
|
122
|
+
<DataChild />
|
|
123
|
+
} catch (err) {
|
|
124
|
+
<p>{'error'}</p>
|
|
125
|
+
}
|
|
126
|
+
</>;
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
function DataChild() {
|
|
130
|
+
return <>
|
|
131
|
+
let &[data] = trackAsync(() => Promise.resolve('from child'));
|
|
132
|
+
<p>{data}</p>
|
|
133
|
+
</>;
|
|
116
134
|
}
|
|
117
135
|
|
|
118
136
|
const { body } = await render(App);
|
|
@@ -121,18 +139,20 @@ describe('trackAsync directly in component body (server)', () => {
|
|
|
121
139
|
});
|
|
122
140
|
|
|
123
141
|
it('resolves multiple trackAsync values in the same component', async () => {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
142
|
+
function App() {
|
|
143
|
+
return <>
|
|
144
|
+
try {
|
|
145
|
+
let &[a] = trackAsync(() => Promise.resolve('hello'));
|
|
146
|
+
let &[b] = trackAsync(() => Promise.resolve('world'));
|
|
147
|
+
<p>
|
|
148
|
+
{a}
|
|
149
|
+
{' '}
|
|
150
|
+
{b}
|
|
151
|
+
</p>
|
|
152
|
+
} catch (err) {
|
|
153
|
+
<p>{'error'}</p>
|
|
154
|
+
}
|
|
155
|
+
</>;
|
|
136
156
|
}
|
|
137
157
|
|
|
138
158
|
const { body } = await render(App);
|
|
@@ -141,17 +161,21 @@ describe('trackAsync directly in component body (server)', () => {
|
|
|
141
161
|
});
|
|
142
162
|
|
|
143
163
|
it('renders catch when trackAsync rejects in a child component without its own try', async () => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
164
|
+
function RejectChild() {
|
|
165
|
+
return <>
|
|
166
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('child rejected')));
|
|
167
|
+
<p>{data}</p>
|
|
168
|
+
</>;
|
|
147
169
|
}
|
|
148
170
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
171
|
+
function App() {
|
|
172
|
+
return <>
|
|
173
|
+
try {
|
|
174
|
+
<RejectChild />
|
|
175
|
+
} catch (err) {
|
|
176
|
+
<p>{'parent caught it'}</p>
|
|
177
|
+
}
|
|
178
|
+
</>;
|
|
155
179
|
}
|
|
156
180
|
|
|
157
181
|
const { body } = await render(App);
|
|
@@ -159,17 +183,19 @@ describe('trackAsync directly in component body (server)', () => {
|
|
|
159
183
|
});
|
|
160
184
|
|
|
161
185
|
it('chained trackAsync resolves both values', async () => {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
186
|
+
function App() {
|
|
187
|
+
return <>
|
|
188
|
+
try {
|
|
189
|
+
let &[name] = trackAsync(() => Promise.resolve('ripple'));
|
|
190
|
+
let &[upper] = trackAsync(() => {
|
|
191
|
+
const n = name;
|
|
192
|
+
return Promise.resolve(n.toUpperCase());
|
|
193
|
+
});
|
|
194
|
+
<p>{upper}</p>
|
|
195
|
+
} catch (err) {
|
|
196
|
+
<p>{'error'}</p>
|
|
197
|
+
}
|
|
198
|
+
</>;
|
|
173
199
|
}
|
|
174
200
|
|
|
175
201
|
const { body } = await render(App);
|
|
@@ -178,17 +204,19 @@ describe('trackAsync directly in component body (server)', () => {
|
|
|
178
204
|
});
|
|
179
205
|
|
|
180
206
|
it('chained trackAsync catches when first rejects', async () => {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
function App() {
|
|
208
|
+
return <>
|
|
209
|
+
try {
|
|
210
|
+
let &[name] = trackAsync(() => Promise.reject<string>(new Error('first failed')));
|
|
211
|
+
let &[upper] = trackAsync(() => {
|
|
212
|
+
const n = name;
|
|
213
|
+
return Promise.resolve(n.toUpperCase());
|
|
214
|
+
});
|
|
215
|
+
<p>{upper}</p>
|
|
216
|
+
} catch (err: Error) {
|
|
217
|
+
<p>{err.message}</p>
|
|
218
|
+
}
|
|
219
|
+
</>;
|
|
192
220
|
}
|
|
193
221
|
|
|
194
222
|
const { body } = await render(App);
|
|
@@ -196,17 +224,19 @@ describe('trackAsync directly in component body (server)', () => {
|
|
|
196
224
|
});
|
|
197
225
|
|
|
198
226
|
it('chained trackAsync catches when second rejects', async () => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
227
|
+
function App() {
|
|
228
|
+
return <>
|
|
229
|
+
try {
|
|
230
|
+
let &[name] = trackAsync(() => Promise.resolve('ripple'));
|
|
231
|
+
let &[upper] = trackAsync(() => {
|
|
232
|
+
const n = name;
|
|
233
|
+
return Promise.reject(new Error('second failed'));
|
|
234
|
+
});
|
|
235
|
+
<p>{upper}</p>
|
|
236
|
+
} catch (err: Error) {
|
|
237
|
+
<p>{err.message}</p>
|
|
238
|
+
}
|
|
239
|
+
</>;
|
|
210
240
|
}
|
|
211
241
|
|
|
212
242
|
const { body } = await render(App);
|
|
@@ -216,25 +246,31 @@ describe('trackAsync directly in component body (server)', () => {
|
|
|
216
246
|
|
|
217
247
|
describe('nested child components with try/catch boundaries (server)', () => {
|
|
218
248
|
it('inner try/catch catches error from its own child', async () => {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
249
|
+
function ThrowingChild() {
|
|
250
|
+
return <>
|
|
251
|
+
throw new Error('inner error');
|
|
252
|
+
<p>{'should not render'}</p>
|
|
253
|
+
</>;
|
|
222
254
|
}
|
|
223
255
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
256
|
+
function Inner() {
|
|
257
|
+
return <>
|
|
258
|
+
try {
|
|
259
|
+
<ThrowingChild />
|
|
260
|
+
} catch (err: Error) {
|
|
261
|
+
<p>{err.message}</p>
|
|
262
|
+
}
|
|
263
|
+
</>;
|
|
230
264
|
}
|
|
231
265
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
266
|
+
function App() {
|
|
267
|
+
return <>
|
|
268
|
+
try {
|
|
269
|
+
<Inner />
|
|
270
|
+
} catch (err) {
|
|
271
|
+
<p>{'outer caught'}</p>
|
|
272
|
+
}
|
|
273
|
+
</>;
|
|
238
274
|
}
|
|
239
275
|
|
|
240
276
|
const { body } = await render(App);
|
|
@@ -243,25 +279,31 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
243
279
|
});
|
|
244
280
|
|
|
245
281
|
it('inner try/catch catches async rejection from its own child', async () => {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
282
|
+
function AsyncChild() {
|
|
283
|
+
return <>
|
|
284
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('async inner error')));
|
|
285
|
+
<p>{data}</p>
|
|
286
|
+
</>;
|
|
249
287
|
}
|
|
250
288
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
289
|
+
function Inner() {
|
|
290
|
+
return <>
|
|
291
|
+
try {
|
|
292
|
+
<AsyncChild />
|
|
293
|
+
} catch (err: Error) {
|
|
294
|
+
<p>{err.message}</p>
|
|
295
|
+
}
|
|
296
|
+
</>;
|
|
257
297
|
}
|
|
258
298
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
299
|
+
function App() {
|
|
300
|
+
return <>
|
|
301
|
+
try {
|
|
302
|
+
<Inner />
|
|
303
|
+
} catch (err) {
|
|
304
|
+
<p>{'outer caught'}</p>
|
|
305
|
+
}
|
|
306
|
+
</>;
|
|
265
307
|
}
|
|
266
308
|
|
|
267
309
|
const { body } = await render(App);
|
|
@@ -270,25 +312,31 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
270
312
|
});
|
|
271
313
|
|
|
272
314
|
it('error propagates to outer catch when inner try has no catch', async () => {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
315
|
+
function ThrowingChild() {
|
|
316
|
+
return <>
|
|
317
|
+
throw new Error('propagated error');
|
|
318
|
+
<p>{'should not render'}</p>
|
|
319
|
+
</>;
|
|
276
320
|
}
|
|
277
321
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
322
|
+
function Inner() {
|
|
323
|
+
return <>
|
|
324
|
+
try {
|
|
325
|
+
<ThrowingChild />
|
|
326
|
+
} pending {
|
|
327
|
+
<p>{'loading...'}</p>
|
|
328
|
+
}
|
|
329
|
+
</>;
|
|
284
330
|
}
|
|
285
331
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
332
|
+
function App() {
|
|
333
|
+
return <>
|
|
334
|
+
try {
|
|
335
|
+
<Inner />
|
|
336
|
+
} catch (err: Error) {
|
|
337
|
+
<p>{err.message}</p>
|
|
338
|
+
}
|
|
339
|
+
</>;
|
|
292
340
|
}
|
|
293
341
|
|
|
294
342
|
const { body } = await render(App);
|
|
@@ -297,25 +345,31 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
297
345
|
});
|
|
298
346
|
|
|
299
347
|
it('async rejection propagates to outer catch when inner try has no catch', async () => {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
348
|
+
function AsyncChild() {
|
|
349
|
+
return <>
|
|
350
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('async propagated')));
|
|
351
|
+
<p>{data}</p>
|
|
352
|
+
</>;
|
|
303
353
|
}
|
|
304
354
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
355
|
+
function Inner() {
|
|
356
|
+
return <>
|
|
357
|
+
try {
|
|
358
|
+
<AsyncChild />
|
|
359
|
+
} pending {
|
|
360
|
+
<p>{'loading...'}</p>
|
|
361
|
+
}
|
|
362
|
+
</>;
|
|
311
363
|
}
|
|
312
364
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
365
|
+
function App() {
|
|
366
|
+
return <>
|
|
367
|
+
try {
|
|
368
|
+
<Inner />
|
|
369
|
+
} catch (err: Error) {
|
|
370
|
+
<p>{err.message}</p>
|
|
371
|
+
}
|
|
372
|
+
</>;
|
|
319
373
|
}
|
|
320
374
|
|
|
321
375
|
const { body } = await render(App);
|
|
@@ -326,33 +380,41 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
326
380
|
it(
|
|
327
381
|
'multiple nested levels: error propagates through pending-only boundaries to nearest catch',
|
|
328
382
|
async () => {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
383
|
+
function ThrowingChild() {
|
|
384
|
+
return <>
|
|
385
|
+
throw new Error('deep error');
|
|
386
|
+
<p>{'should not render'}</p>
|
|
387
|
+
</>;
|
|
332
388
|
}
|
|
333
389
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
390
|
+
function Level3() {
|
|
391
|
+
return <>
|
|
392
|
+
try {
|
|
393
|
+
<ThrowingChild />
|
|
394
|
+
} pending {
|
|
395
|
+
<p>{'level3 loading'}</p>
|
|
396
|
+
}
|
|
397
|
+
</>;
|
|
340
398
|
}
|
|
341
399
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
400
|
+
function Level2() {
|
|
401
|
+
return <>
|
|
402
|
+
try {
|
|
403
|
+
<Level3 />
|
|
404
|
+
} pending {
|
|
405
|
+
<p>{'level2 loading'}</p>
|
|
406
|
+
}
|
|
407
|
+
</>;
|
|
348
408
|
}
|
|
349
409
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
410
|
+
function App() {
|
|
411
|
+
return <>
|
|
412
|
+
try {
|
|
413
|
+
<Level2 />
|
|
414
|
+
} catch (err: Error) {
|
|
415
|
+
<p>{err.message}</p>
|
|
416
|
+
}
|
|
417
|
+
</>;
|
|
356
418
|
}
|
|
357
419
|
|
|
358
420
|
const { body } = await render(App);
|
|
@@ -361,23 +423,29 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
361
423
|
);
|
|
362
424
|
|
|
363
425
|
it('sibling components: one fails, the other does not affect catch', async () => {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
426
|
+
function GoodChild() {
|
|
427
|
+
return <>
|
|
428
|
+
let &[data] = trackAsync(() => Promise.resolve('good'));
|
|
429
|
+
<p>{data}</p>
|
|
430
|
+
</>;
|
|
367
431
|
}
|
|
368
432
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
433
|
+
function BadChild() {
|
|
434
|
+
return <>
|
|
435
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('bad child')));
|
|
436
|
+
<p>{data}</p>
|
|
437
|
+
</>;
|
|
372
438
|
}
|
|
373
439
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
440
|
+
function App() {
|
|
441
|
+
return <>
|
|
442
|
+
try {
|
|
443
|
+
<GoodChild />
|
|
444
|
+
<BadChild />
|
|
445
|
+
} catch (err: Error) {
|
|
446
|
+
<p>{err.message}</p>
|
|
447
|
+
}
|
|
448
|
+
</>;
|
|
381
449
|
}
|
|
382
450
|
|
|
383
451
|
const { body } = await render(App);
|
|
@@ -386,27 +454,33 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
386
454
|
});
|
|
387
455
|
|
|
388
456
|
it('independent try/catch boundaries each handle their own errors', async () => {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
457
|
+
function FailChild() {
|
|
458
|
+
return <>
|
|
459
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('fail')));
|
|
460
|
+
<p>{data}</p>
|
|
461
|
+
</>;
|
|
392
462
|
}
|
|
393
463
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
464
|
+
function SuccessChild() {
|
|
465
|
+
return <>
|
|
466
|
+
let &[data] = trackAsync(() => Promise.resolve('success'));
|
|
467
|
+
<p>{data}</p>
|
|
468
|
+
</>;
|
|
397
469
|
}
|
|
398
470
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
471
|
+
function App() {
|
|
472
|
+
return <>
|
|
473
|
+
try {
|
|
474
|
+
<FailChild />
|
|
475
|
+
} catch (err: Error) {
|
|
476
|
+
<p>{err.message}</p>
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
<SuccessChild />
|
|
480
|
+
} catch (err) {
|
|
481
|
+
<p>{'should not catch'}</p>
|
|
482
|
+
}
|
|
483
|
+
</>;
|
|
410
484
|
}
|
|
411
485
|
|
|
412
486
|
const { body } = await render(App);
|
|
@@ -416,24 +490,30 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
416
490
|
});
|
|
417
491
|
|
|
418
492
|
it('inner catch handles rejection, outer renders normally', async () => {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
493
|
+
function AsyncChild() {
|
|
494
|
+
return <>
|
|
495
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('handled inside')));
|
|
496
|
+
<p>{data}</p>
|
|
497
|
+
</>;
|
|
422
498
|
}
|
|
423
499
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
500
|
+
function Inner() {
|
|
501
|
+
return <>
|
|
502
|
+
try {
|
|
503
|
+
<AsyncChild />
|
|
504
|
+
} catch (err: Error) {
|
|
505
|
+
<span>{err.message}</span>
|
|
506
|
+
}
|
|
507
|
+
</>;
|
|
430
508
|
}
|
|
431
509
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
<
|
|
435
|
-
|
|
436
|
-
|
|
510
|
+
function App() {
|
|
511
|
+
return <>
|
|
512
|
+
<div>
|
|
513
|
+
<h1>{'App'}</h1>
|
|
514
|
+
<Inner />
|
|
515
|
+
</div>
|
|
516
|
+
</>;
|
|
437
517
|
}
|
|
438
518
|
|
|
439
519
|
const { body } = await render(App);
|
|
@@ -442,22 +522,26 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
442
522
|
});
|
|
443
523
|
|
|
444
524
|
it('sync error in child after trackAsync routes to catch boundary', async () => {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
525
|
+
function BrokenChild() {
|
|
526
|
+
return <>
|
|
527
|
+
let &[data] = trackAsync(() => Promise.resolve('loaded'));
|
|
528
|
+
throw new Error('sync after async');
|
|
529
|
+
<p>{data}</p>
|
|
530
|
+
</>;
|
|
449
531
|
}
|
|
450
532
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
533
|
+
function Inner() {
|
|
534
|
+
return <>
|
|
535
|
+
try {
|
|
536
|
+
<BrokenChild />
|
|
537
|
+
} catch (err: Error) {
|
|
538
|
+
<p>{err.message}</p>
|
|
539
|
+
}
|
|
540
|
+
</>;
|
|
457
541
|
}
|
|
458
542
|
|
|
459
|
-
|
|
460
|
-
|
|
543
|
+
function App() {
|
|
544
|
+
return <><Inner /></>;
|
|
461
545
|
}
|
|
462
546
|
|
|
463
547
|
const { body } = await render(App);
|
|
@@ -465,25 +549,31 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
465
549
|
});
|
|
466
550
|
|
|
467
551
|
it('outer try with pending, inner try with catch: rejection goes to inner catch', async () => {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
552
|
+
function AsyncChild() {
|
|
553
|
+
return <>
|
|
554
|
+
let &[data] = trackAsync(() => Promise.reject(new Error('inner rejection')));
|
|
555
|
+
<p>{data}</p>
|
|
556
|
+
</>;
|
|
471
557
|
}
|
|
472
558
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
559
|
+
function Inner() {
|
|
560
|
+
return <>
|
|
561
|
+
try {
|
|
562
|
+
<AsyncChild />
|
|
563
|
+
} catch (err: Error) {
|
|
564
|
+
<p>{err.message}</p>
|
|
565
|
+
}
|
|
566
|
+
</>;
|
|
479
567
|
}
|
|
480
568
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
569
|
+
function App() {
|
|
570
|
+
return <>
|
|
571
|
+
try {
|
|
572
|
+
<Inner />
|
|
573
|
+
} pending {
|
|
574
|
+
<p>{'outer loading'}</p>
|
|
575
|
+
}
|
|
576
|
+
</>;
|
|
487
577
|
}
|
|
488
578
|
|
|
489
579
|
const { body } = await render(App);
|
|
@@ -492,25 +582,29 @@ describe('nested child components with try/catch boundaries (server)', () => {
|
|
|
492
582
|
});
|
|
493
583
|
|
|
494
584
|
it('deeply nested: async resolves through multiple component layers', async () => {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
585
|
+
function DataFetcher() {
|
|
586
|
+
return <>
|
|
587
|
+
let &[data] = trackAsync(() => Promise.resolve('deep data'));
|
|
588
|
+
<span>{data}</span>
|
|
589
|
+
</>;
|
|
498
590
|
}
|
|
499
591
|
|
|
500
|
-
|
|
501
|
-
|
|
592
|
+
function Level2() {
|
|
593
|
+
return <><div><DataFetcher /></div></>;
|
|
502
594
|
}
|
|
503
595
|
|
|
504
|
-
|
|
505
|
-
|
|
596
|
+
function Level1() {
|
|
597
|
+
return <><section><Level2 /></section></>;
|
|
506
598
|
}
|
|
507
599
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
600
|
+
function App() {
|
|
601
|
+
return <>
|
|
602
|
+
try {
|
|
603
|
+
<Level1 />
|
|
604
|
+
} catch (err) {
|
|
605
|
+
<p>{'error'}</p>
|
|
606
|
+
}
|
|
607
|
+
</>;
|
|
514
608
|
}
|
|
515
609
|
|
|
516
610
|
const { body } = await render(App);
|