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