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
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Fragment, track } from 'ripple';
|
|
1
|
+
import { Dynamic, Fragment, track } from 'ripple';
|
|
2
2
|
import type { Tracked, PropsNoChildren } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('basic client', () => {
|
|
5
5
|
it('render static text', async () => {
|
|
6
|
-
function Basic() {
|
|
7
|
-
|
|
6
|
+
function Basic() @{
|
|
7
|
+
<div>{'Hello World'}</div>
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const { head, body } = await render(Basic);
|
|
@@ -14,11 +14,9 @@ describe('basic client', () => {
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
it('renders string interpolation as escaped text', async () => {
|
|
17
|
-
function Basic() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<div>{markup}</div>
|
|
21
|
-
</>;
|
|
17
|
+
function Basic() @{
|
|
18
|
+
let markup = '<span>Not HTML</span>';
|
|
19
|
+
<div>{markup}</div>
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
const { body } = await render(Basic);
|
|
@@ -26,32 +24,35 @@ describe('basic client', () => {
|
|
|
26
24
|
expect(body).toBeHtml('<div><span>Not HTML</span></div>');
|
|
27
25
|
});
|
|
28
26
|
|
|
29
|
-
it('renders direct
|
|
30
|
-
function Basic() {
|
|
31
|
-
|
|
32
|
-
<div>
|
|
33
|
-
<div>
|
|
34
|
-
<pre>
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
it('renders direct JSX text children as text', async () => {
|
|
28
|
+
function Basic() @{
|
|
29
|
+
<>
|
|
30
|
+
<div>Rock & "Roll"</div>
|
|
31
|
+
<div>line break</div>
|
|
32
|
+
<pre>
|
|
33
|
+
first
|
|
34
|
+
second
|
|
35
|
+
</pre>
|
|
36
|
+
</>
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const { body } = await render(Basic);
|
|
40
40
|
|
|
41
41
|
expect(body).toBeHtml(
|
|
42
|
-
'<div>Rock & "Roll"</div><div>line
|
|
42
|
+
'<div>Rock & "Roll"</div><div>line break</div><pre>first\nsecond</pre>',
|
|
43
43
|
);
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
it('does not render
|
|
47
|
-
function Basic() {
|
|
46
|
+
it('does not render JavaScript statements outside returned component templates', async () => {
|
|
47
|
+
function Basic() @{
|
|
48
48
|
const ready = true;
|
|
49
49
|
|
|
50
50
|
if (ready) {
|
|
51
|
-
|
|
51
|
+
const leaked = 'should not render';
|
|
52
|
+
void leaked;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
<>Hello world</>
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
const { body } = await render(Basic);
|
|
@@ -60,14 +61,12 @@ second"</pre>
|
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
it('renders primitive component return branches', async () => {
|
|
63
|
-
function Basic() {
|
|
64
|
+
function Basic() @{
|
|
64
65
|
const ready = false;
|
|
65
|
-
|
|
66
66
|
if (!ready) {
|
|
67
67
|
return 'Waiting';
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
return <>"Ready"</>;
|
|
69
|
+
<>Ready</>
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
const { body } = await render(Basic);
|
|
@@ -105,10 +104,115 @@ second"</pre>
|
|
|
105
104
|
expect(body).toBeHtml('');
|
|
106
105
|
});
|
|
107
106
|
|
|
108
|
-
it('does not
|
|
107
|
+
it('does not stringify adjacent call-containing expression children', async () => {
|
|
108
|
+
function child(label: string) @{
|
|
109
|
+
<span>{label}</span>
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function empty() {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const Constructed = function Constructed(label: string) {
|
|
117
|
+
return child(label);
|
|
118
|
+
} as unknown as {
|
|
119
|
+
new (label: string): ReturnType<typeof child>;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const factory = child;
|
|
123
|
+
|
|
124
|
+
function tag(_strings: TemplateStringsArray) {
|
|
125
|
+
return child('tagged');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const lookup = {
|
|
129
|
+
member: child('member'),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
function getKey(): keyof typeof lookup {
|
|
133
|
+
return 'member';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function touch() {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let assigned;
|
|
141
|
+
|
|
142
|
+
function Basic() @{
|
|
143
|
+
<>
|
|
144
|
+
<div>
|
|
145
|
+
{'call:'}
|
|
146
|
+
{child('call')}
|
|
147
|
+
</div>
|
|
148
|
+
<div>
|
|
149
|
+
{'new:'}
|
|
150
|
+
{new Constructed('new')}
|
|
151
|
+
</div>
|
|
152
|
+
<div>
|
|
153
|
+
{'chain:'}
|
|
154
|
+
{factory?.('chain')}
|
|
155
|
+
</div>
|
|
156
|
+
<div>
|
|
157
|
+
{'ts-wrapper:'}
|
|
158
|
+
{child('ts-wrapper')!}
|
|
159
|
+
</div>
|
|
160
|
+
<div>
|
|
161
|
+
{'array:'}
|
|
162
|
+
{[child('array')]}
|
|
163
|
+
</div>
|
|
164
|
+
<div>
|
|
165
|
+
{'assignment:'}
|
|
166
|
+
{assigned = child('assignment')}
|
|
167
|
+
</div>
|
|
168
|
+
<div>
|
|
169
|
+
{'logical:'}
|
|
170
|
+
{true && child('logical')}
|
|
171
|
+
</div>
|
|
172
|
+
<div>
|
|
173
|
+
{'conditional:'}
|
|
174
|
+
{true ? child('conditional') : ''}
|
|
175
|
+
</div>
|
|
176
|
+
<div>
|
|
177
|
+
{'member:'}
|
|
178
|
+
{lookup[getKey()]}
|
|
179
|
+
</div>
|
|
180
|
+
<div>
|
|
181
|
+
{'object:'}
|
|
182
|
+
{{
|
|
183
|
+
[Symbol.for('ripple.element')]: true,
|
|
184
|
+
render() {
|
|
185
|
+
return child('object');
|
|
186
|
+
},
|
|
187
|
+
}}
|
|
188
|
+
</div>
|
|
189
|
+
<div>
|
|
190
|
+
{'sequence:'}
|
|
191
|
+
{(touch(), child('sequence'))}
|
|
192
|
+
</div>
|
|
193
|
+
<div>
|
|
194
|
+
{'tagged:'}
|
|
195
|
+
{tag`tagged`}
|
|
196
|
+
</div>
|
|
197
|
+
<div>
|
|
198
|
+
{'unary:'}
|
|
199
|
+
{void empty()}
|
|
200
|
+
</div>
|
|
201
|
+
</>
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const { body } = await render(Basic);
|
|
205
|
+
|
|
206
|
+
expect(body).toBeHtml(
|
|
207
|
+
'<div>call:<span>call</span></div><div>new:<span>new</span></div><div>chain:<span>chain</span></div><div>ts-wrapper:<span>ts-wrapper</span></div><div>array:<span>array</span></div><div>assignment:<span>assignment</span></div><div>logical:<span>logical</span></div><div>conditional:<span>conditional</span></div><div>member:<span>member</span></div><div>object:<span>object</span></div><div>sequence:<span>sequence</span></div><div>tagged:<span>tagged</span></div><div>unary:</div>',
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('does not render unreachable statements after an ASI return', async () => {
|
|
109
212
|
function Basic() {
|
|
110
213
|
return;
|
|
111
|
-
|
|
214
|
+
const leaked = 'should not render';
|
|
215
|
+
void leaked;
|
|
112
216
|
}
|
|
113
217
|
|
|
114
218
|
const { body } = await render(Basic);
|
|
@@ -117,14 +221,10 @@ second"</pre>
|
|
|
117
221
|
});
|
|
118
222
|
|
|
119
223
|
it('renders inline tsrx fragments', async () => {
|
|
120
|
-
function Basic() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<span>{label}</span>
|
|
125
|
-
</>;
|
|
126
|
-
<div>{content}</div>
|
|
127
|
-
</>;
|
|
224
|
+
function Basic() @{
|
|
225
|
+
const label = 'Server';
|
|
226
|
+
const content = <span>{label}</span>;
|
|
227
|
+
<div>{content}</div>
|
|
128
228
|
}
|
|
129
229
|
|
|
130
230
|
const { body } = await render(Basic);
|
|
@@ -133,11 +233,9 @@ second"</pre>
|
|
|
133
233
|
});
|
|
134
234
|
|
|
135
235
|
it('renders Fragment innerHTML', async () => {
|
|
136
|
-
function Basic() {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
<Fragment innerHTML={html} />
|
|
140
|
-
</>;
|
|
236
|
+
function Basic() @{
|
|
237
|
+
const html = '<strong>Server Fragment HTML</strong>';
|
|
238
|
+
<Fragment innerHTML={html} />
|
|
141
239
|
}
|
|
142
240
|
|
|
143
241
|
const { body } = await render(Basic);
|
|
@@ -148,20 +246,20 @@ second"</pre>
|
|
|
148
246
|
|
|
149
247
|
it('renders deeply nested tsx and tsrx expression values', async () => {
|
|
150
248
|
function makeFragment(label: string) {
|
|
249
|
+
const test = <>
|
|
250
|
+
{[1, 2, 3, 4].map((item) => <div class="helper-item">{item}</div>)}
|
|
251
|
+
</>;
|
|
151
252
|
return <>
|
|
152
253
|
<span class="label">{label}</span>
|
|
153
|
-
const test = <>
|
|
154
|
-
{[1, 2, 3, 4].map((item) => <>{<><div class="helper-item">{item}</div></>}</>)}
|
|
155
|
-
</>;
|
|
156
254
|
{test}
|
|
157
255
|
</>;
|
|
158
256
|
}
|
|
159
257
|
|
|
160
|
-
function Basic() {
|
|
161
|
-
|
|
162
|
-
{
|
|
258
|
+
function Basic() @{
|
|
259
|
+
<>
|
|
260
|
+
{[1, 2, 3].map((item) => <div class="app-item">{item}</div>)}
|
|
163
261
|
{makeFragment('from helper')}
|
|
164
|
-
|
|
262
|
+
</>
|
|
165
263
|
}
|
|
166
264
|
|
|
167
265
|
const { body } = await render(Basic);
|
|
@@ -172,15 +270,15 @@ second"</pre>
|
|
|
172
270
|
});
|
|
173
271
|
|
|
174
272
|
it('renders tsrx nested directly inside a top-level tsx expression value', async () => {
|
|
175
|
-
function Basic() {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
</section>
|
|
181
|
-
</>;
|
|
182
|
-
{content}
|
|
273
|
+
function Basic() @{
|
|
274
|
+
const content = <>
|
|
275
|
+
<section class="outer">
|
|
276
|
+
<div class="inner">{'from tsrx'}</div>
|
|
277
|
+
</section>
|
|
183
278
|
</>;
|
|
279
|
+
<>
|
|
280
|
+
{content}
|
|
281
|
+
</>
|
|
184
282
|
}
|
|
185
283
|
|
|
186
284
|
const { body } = await render(Basic);
|
|
@@ -189,19 +287,17 @@ second"</pre>
|
|
|
189
287
|
});
|
|
190
288
|
|
|
191
289
|
it('renders nested elements from tsrx inside a top-level tsx value', async () => {
|
|
192
|
-
function Basic() {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
<
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
</section>
|
|
200
|
-
</>}
|
|
201
|
-
</div>
|
|
202
|
-
</>;
|
|
203
|
-
{content}
|
|
290
|
+
function Basic() @{
|
|
291
|
+
const content = <>
|
|
292
|
+
<div class="wrapper">
|
|
293
|
+
<section class="native">
|
|
294
|
+
<span class="nested-tsrx">{'inside nested tsrx'}</span>
|
|
295
|
+
</section>
|
|
296
|
+
</div>
|
|
204
297
|
</>;
|
|
298
|
+
<>
|
|
299
|
+
{content}
|
|
300
|
+
</>
|
|
205
301
|
}
|
|
206
302
|
|
|
207
303
|
const { body } = await render(Basic);
|
|
@@ -212,12 +308,12 @@ second"</pre>
|
|
|
212
308
|
});
|
|
213
309
|
|
|
214
310
|
it('renders tsx declared before a top-level tsx value', async () => {
|
|
215
|
-
function Basic() {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
311
|
+
function Basic() @{
|
|
312
|
+
const nested = <span class="nested-tsx">inside nested tsx</span>;
|
|
313
|
+
const content = <><div class="native">{nested}</div></>;
|
|
314
|
+
<>
|
|
219
315
|
{content}
|
|
220
|
-
|
|
316
|
+
</>
|
|
221
317
|
}
|
|
222
318
|
|
|
223
319
|
const { body } = await render(Basic);
|
|
@@ -228,19 +324,17 @@ second"</pre>
|
|
|
228
324
|
});
|
|
229
325
|
|
|
230
326
|
it('flattens nested primitive arrays inside mixed tsrx collections', async () => {
|
|
231
|
-
function Basic() {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
</div>
|
|
243
|
-
</>;
|
|
327
|
+
function Basic() @{
|
|
328
|
+
<div>
|
|
329
|
+
{<>
|
|
330
|
+
{[
|
|
331
|
+
'start:',
|
|
332
|
+
['one', 2, true, null, false],
|
|
333
|
+
<strong>{'!'}</strong>,
|
|
334
|
+
':end',
|
|
335
|
+
]}
|
|
336
|
+
</>}
|
|
337
|
+
</div>
|
|
244
338
|
}
|
|
245
339
|
|
|
246
340
|
const { body } = await render(Basic);
|
|
@@ -249,12 +343,14 @@ second"</pre>
|
|
|
249
343
|
});
|
|
250
344
|
|
|
251
345
|
it('flattens direct primitive array expressions', async () => {
|
|
252
|
-
function Basic() {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
<div>
|
|
346
|
+
function Basic() @{
|
|
347
|
+
const items = ['start:', ['one', 2], null, true, false, ':end'];
|
|
348
|
+
<>
|
|
349
|
+
<div>
|
|
350
|
+
{['start:', ['one', 2], null, true, false, ':end']}
|
|
351
|
+
</div>
|
|
256
352
|
<div>{items}</div>
|
|
257
|
-
|
|
353
|
+
</>
|
|
258
354
|
}
|
|
259
355
|
|
|
260
356
|
const { body } = await render(Basic);
|
|
@@ -263,16 +359,16 @@ second"</pre>
|
|
|
263
359
|
});
|
|
264
360
|
|
|
265
361
|
it('flattens conditional primitive array expressions', async () => {
|
|
266
|
-
function Basic() {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
362
|
+
function Basic() @{
|
|
363
|
+
const condition = true;
|
|
364
|
+
const ternary_items = condition
|
|
365
|
+
? ['start:', ['one', 2], null, true, false, ':end']
|
|
366
|
+
: ['fallback'];
|
|
367
|
+
const logical_items = condition && ['start:', ['one', 2], null, true, false, ':end'];
|
|
368
|
+
<>
|
|
273
369
|
<div>{ternary_items}</div>
|
|
274
370
|
<div>{logical_items}</div>
|
|
275
|
-
|
|
371
|
+
</>
|
|
276
372
|
}
|
|
277
373
|
|
|
278
374
|
const { body } = await render(Basic);
|
|
@@ -281,13 +377,11 @@ second"</pre>
|
|
|
281
377
|
});
|
|
282
378
|
|
|
283
379
|
it('renders tracked state updates', async () => {
|
|
284
|
-
function Counter() {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
<div>{count}</div>
|
|
290
|
-
</>;
|
|
380
|
+
function Counter() @{
|
|
381
|
+
let &[count] = track(0);
|
|
382
|
+
count++;
|
|
383
|
+
count = count + 5;
|
|
384
|
+
<div>{count}</div>
|
|
291
385
|
}
|
|
292
386
|
|
|
293
387
|
const { body } = await render(Counter);
|
|
@@ -299,19 +393,17 @@ second"</pre>
|
|
|
299
393
|
function Child({ count, ...rest }: PropsNoChildren<{
|
|
300
394
|
count: Tracked<number>;
|
|
301
395
|
class: { test: boolean };
|
|
302
|
-
}>) {
|
|
303
|
-
|
|
396
|
+
}>) @{
|
|
397
|
+
<>
|
|
304
398
|
<div {...rest}>{'Child Component'}</div>
|
|
305
399
|
<div>{count.value}</div>
|
|
306
|
-
|
|
400
|
+
</>
|
|
307
401
|
}
|
|
308
402
|
|
|
309
|
-
function Parent() {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
<@Dynamic {count} class={{ test: true }} />
|
|
314
|
-
</>;
|
|
403
|
+
function Parent() @{
|
|
404
|
+
const count = track(10);
|
|
405
|
+
let DynamicChild = track(() => Child);
|
|
406
|
+
<Dynamic is={DynamicChild} {count} class={{ test: true }} />
|
|
315
407
|
}
|
|
316
408
|
|
|
317
409
|
const { body } = await render(Parent);
|
|
@@ -320,13 +412,11 @@ second"</pre>
|
|
|
320
412
|
});
|
|
321
413
|
|
|
322
414
|
it('renders tracked object properties', async () => {
|
|
323
|
-
function ObjCounter() {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<div>{obj.count.value}</div>
|
|
329
|
-
</>;
|
|
415
|
+
function ObjCounter() @{
|
|
416
|
+
const obj = { count: track(2) };
|
|
417
|
+
obj.count.value += 3;
|
|
418
|
+
obj.count.value = obj.count.value + 1;
|
|
419
|
+
<div>{obj.count.value}</div>
|
|
330
420
|
}
|
|
331
421
|
|
|
332
422
|
const { body } = await render(ObjCounter);
|
|
@@ -335,13 +425,11 @@ second"</pre>
|
|
|
335
425
|
});
|
|
336
426
|
|
|
337
427
|
it('renders spread props with tracked values', async () => {
|
|
338
|
-
function SpreadProps() {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
<div {...{ id: id, class: { active: isActive }, style: styles }}>{'Spread Props'}</div>
|
|
344
|
-
</>;
|
|
428
|
+
function SpreadProps() @{
|
|
429
|
+
let &[id] = track('unique-id');
|
|
430
|
+
let &[isActive] = track(true);
|
|
431
|
+
let &[styles] = track({ color: 'red', fontSize: '16px' });
|
|
432
|
+
<div {...{ id: id, class: { active: isActive }, style: styles }}>{'Spread Props'}</div>
|
|
345
433
|
}
|
|
346
434
|
|
|
347
435
|
const { body } = await render(SpreadProps);
|
|
@@ -352,15 +440,15 @@ second"</pre>
|
|
|
352
440
|
});
|
|
353
441
|
|
|
354
442
|
it('handles AssignExpressions with tracked values or properties correctly', async () => {
|
|
355
|
-
function Assignments() {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
443
|
+
function Assignments() @{
|
|
444
|
+
let &[count] = track(0);
|
|
445
|
+
const obj = { value: track(5) };
|
|
446
|
+
count += 10;
|
|
447
|
+
obj.value.value *= 2;
|
|
448
|
+
<>
|
|
361
449
|
<div>{count}</div>
|
|
362
450
|
<div>{obj.value.value}</div>
|
|
363
|
-
|
|
451
|
+
</>
|
|
364
452
|
}
|
|
365
453
|
|
|
366
454
|
const { body } = await render(Assignments);
|
|
@@ -369,15 +457,17 @@ second"</pre>
|
|
|
369
457
|
});
|
|
370
458
|
|
|
371
459
|
it(`handles derived changes via tracked dependencies' changes`, async () => {
|
|
372
|
-
function Derived() {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
460
|
+
function Derived() @{
|
|
461
|
+
let &[base] = track(5);
|
|
462
|
+
let &[multiplier] = track(3);
|
|
463
|
+
let &[derived] = track(() => base * multiplier);
|
|
464
|
+
const before = derived;
|
|
465
|
+
base += 2;
|
|
466
|
+
const after = derived;
|
|
467
|
+
<>
|
|
468
|
+
<div>{before}</div>
|
|
469
|
+
<div>{after}</div>
|
|
470
|
+
</>
|
|
381
471
|
}
|
|
382
472
|
|
|
383
473
|
const { body } = await render(Derived);
|
|
@@ -386,16 +476,18 @@ second"</pre>
|
|
|
386
476
|
});
|
|
387
477
|
|
|
388
478
|
it(`handles derived changes based on another derived's dependencies' changes`, async () => {
|
|
389
|
-
function NestedDerived() {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
479
|
+
function NestedDerived() @{
|
|
480
|
+
let &[a] = track(2);
|
|
481
|
+
let &[b] = track(3);
|
|
482
|
+
let &[sum] = track(() => a + b);
|
|
483
|
+
let &[product] = track(() => sum * 2);
|
|
484
|
+
const before = product;
|
|
485
|
+
a = 4;
|
|
486
|
+
const after = product;
|
|
487
|
+
<>
|
|
488
|
+
<div>{before}</div>
|
|
489
|
+
<div>{after}</div>
|
|
490
|
+
</>
|
|
399
491
|
}
|
|
400
492
|
|
|
401
493
|
const { body } = await render(NestedDerived);
|
|
@@ -404,23 +496,31 @@ second"</pre>
|
|
|
404
496
|
});
|
|
405
497
|
|
|
406
498
|
it('handles lexical scopes correctly', async () => {
|
|
407
|
-
function LexicalScopes() {
|
|
408
|
-
|
|
409
|
-
|
|
499
|
+
function LexicalScopes() @{
|
|
500
|
+
let &[x] = track(1);
|
|
501
|
+
let nested = '';
|
|
502
|
+
let deep = '';
|
|
503
|
+
let deeper = '';
|
|
504
|
+
{
|
|
505
|
+
let &[x] = track(10);
|
|
506
|
+
nested = String(x);
|
|
507
|
+
}
|
|
508
|
+
{
|
|
509
|
+
let &[x] = track(12);
|
|
510
|
+
deep = String(x);
|
|
511
|
+
{
|
|
512
|
+
let &[x] = track(15);
|
|
513
|
+
deeper = String(x);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
<>
|
|
410
517
|
<div>{x}</div>
|
|
518
|
+
<div>{nested}</div>
|
|
411
519
|
<div>
|
|
412
|
-
|
|
413
|
-
{
|
|
414
|
-
</div>
|
|
415
|
-
<div>
|
|
416
|
-
let &[x] = track(12);
|
|
417
|
-
{x}
|
|
418
|
-
<span>
|
|
419
|
-
let &[x] = track(15);
|
|
420
|
-
{x}
|
|
421
|
-
</span>
|
|
520
|
+
{deep}
|
|
521
|
+
<span>{deeper}</span>
|
|
422
522
|
</div>
|
|
423
|
-
|
|
523
|
+
</>
|
|
424
524
|
}
|
|
425
525
|
|
|
426
526
|
const { body } = await render(LexicalScopes);
|
|
@@ -429,48 +529,48 @@ second"</pre>
|
|
|
429
529
|
});
|
|
430
530
|
|
|
431
531
|
it('runs nested JavaScript blocks inside component-local callables', async () => {
|
|
432
|
-
function App() {
|
|
433
|
-
|
|
434
|
-
function
|
|
435
|
-
|
|
436
|
-
|
|
532
|
+
function App() @{
|
|
533
|
+
function readFunction() {
|
|
534
|
+
const label = 'function outer';
|
|
535
|
+
let result = '';
|
|
536
|
+
|
|
537
|
+
{
|
|
538
|
+
const label = 'function inner';
|
|
539
|
+
result = label;
|
|
540
|
+
}
|
|
437
541
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
542
|
+
return `${result} / ${label}`;
|
|
543
|
+
}
|
|
544
|
+
const readArrow = () => {
|
|
545
|
+
const offset = 5;
|
|
546
|
+
let value = offset;
|
|
442
547
|
|
|
443
|
-
|
|
548
|
+
{
|
|
549
|
+
const offset = 17;
|
|
550
|
+
value += offset;
|
|
444
551
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
552
|
+
|
|
553
|
+
return value;
|
|
554
|
+
};
|
|
555
|
+
class Reader {
|
|
556
|
+
read() {
|
|
557
|
+
const label = 'method outer';
|
|
558
|
+
let result = '';
|
|
448
559
|
|
|
449
560
|
{
|
|
450
|
-
const
|
|
451
|
-
|
|
561
|
+
const label = 'method inner';
|
|
562
|
+
result = label;
|
|
452
563
|
}
|
|
453
564
|
|
|
454
|
-
return
|
|
455
|
-
};
|
|
456
|
-
class Reader {
|
|
457
|
-
read() {
|
|
458
|
-
const label = 'method outer';
|
|
459
|
-
let result = '';
|
|
460
|
-
|
|
461
|
-
{
|
|
462
|
-
const label = 'method inner';
|
|
463
|
-
result = label;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
return `${result} / ${label}`;
|
|
467
|
-
}
|
|
565
|
+
return `${result} / ${label}`;
|
|
468
566
|
}
|
|
469
|
-
|
|
567
|
+
}
|
|
568
|
+
const reader = new Reader();
|
|
569
|
+
<>
|
|
470
570
|
<div class="block-function">{readFunction()}</div>
|
|
471
571
|
<div class="block-arrow">{readArrow()}</div>
|
|
472
572
|
<div class="block-method">{reader.read()}</div>
|
|
473
|
-
|
|
573
|
+
</>
|
|
474
574
|
}
|
|
475
575
|
|
|
476
576
|
const { body } = await render(App);
|