ripple 0.3.6 → 0.3.8
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 +43 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +37 -194
- package/src/compiler/phases/2-analyze/index.js +290 -26
- package/src/compiler/phases/3-transform/client/index.js +54 -14
- package/src/compiler/phases/3-transform/server/index.js +19 -35
- package/src/compiler/types/index.d.ts +3 -1
- package/src/compiler/types/parse.d.ts +0 -8
- package/src/compiler/utils.js +10 -6
- package/src/runtime/internal/client/composite.js +2 -2
- package/src/runtime/internal/client/index.js +2 -0
- package/src/runtime/internal/client/runtime.js +95 -45
- package/src/runtime/internal/client/types.d.ts +10 -0
- package/src/runtime/internal/client/utils.js +12 -0
- package/src/runtime/internal/server/index.js +89 -17
- package/src/runtime/internal/server/types.d.ts +10 -0
- package/src/utils/ast.js +1 -1
- package/tests/client/array/array.copy-within.test.ripple +12 -12
- package/tests/client/array/array.derived.test.ripple +46 -46
- package/tests/client/array/array.iteration.test.ripple +10 -10
- package/tests/client/array/array.mutations.test.ripple +20 -20
- package/tests/client/array/array.to-methods.test.ripple +6 -6
- package/tests/client/async-suspend.test.ripple +5 -5
- package/tests/client/basic/basic.attributes.test.ripple +81 -81
- package/tests/client/basic/basic.collections.test.ripple +9 -9
- package/tests/client/basic/basic.components.test.ripple +28 -28
- package/tests/client/basic/basic.errors.test.ripple +18 -18
- package/tests/client/basic/basic.events.test.ripple +37 -37
- package/tests/client/basic/basic.get-set.test.ripple +6 -6
- package/tests/client/basic/basic.reactivity.test.ripple +68 -68
- package/tests/client/basic/basic.rendering.test.ripple +19 -19
- package/tests/client/basic/basic.utilities.test.ripple +3 -3
- package/tests/client/boundaries.test.ripple +12 -12
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
- package/tests/client/compiler/compiler.basic.test.ripple +44 -15
- package/tests/client/compiler/compiler.tracked-access.test.ripple +68 -2
- package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
- package/tests/client/composite/composite.props.test.ripple +11 -11
- package/tests/client/composite/composite.reactivity.test.ripple +43 -43
- package/tests/client/composite/composite.render.test.ripple +3 -3
- package/tests/client/computed-properties.test.ripple +4 -4
- package/tests/client/date.test.ripple +42 -42
- package/tests/client/dynamic-elements.test.ripple +42 -42
- package/tests/client/events.test.ripple +70 -70
- package/tests/client/for.test.ripple +25 -25
- package/tests/client/head.test.ripple +19 -19
- package/tests/client/html.test.ripple +3 -3
- package/tests/client/input-value.test.ripple +84 -84
- package/tests/client/lazy-destructuring.test.ripple +123 -14
- package/tests/client/map.test.ripple +16 -16
- package/tests/client/media-query.test.ripple +7 -7
- package/tests/client/portal.test.ripple +11 -11
- package/tests/client/ref.test.ripple +4 -4
- package/tests/client/return.test.ripple +52 -52
- package/tests/client/set.test.ripple +6 -6
- package/tests/client/svg.test.ripple +5 -5
- package/tests/client/switch.test.ripple +44 -44
- package/tests/client/try.test.ripple +5 -5
- package/tests/client/url/url.derived.test.ripple +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
- package/tests/hydration/compiled/client/events.js +25 -25
- package/tests/hydration/compiled/client/for.js +70 -66
- package/tests/hydration/compiled/client/head.js +25 -25
- package/tests/hydration/compiled/client/hmr.js +2 -2
- package/tests/hydration/compiled/client/html.js +3 -3
- package/tests/hydration/compiled/client/if-children.js +24 -24
- package/tests/hydration/compiled/client/if.js +18 -18
- package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
- package/tests/hydration/compiled/client/portal.js +3 -3
- package/tests/hydration/compiled/client/reactivity.js +16 -16
- package/tests/hydration/compiled/client/return.js +40 -40
- package/tests/hydration/compiled/client/switch.js +12 -12
- package/tests/hydration/compiled/server/events.js +19 -19
- package/tests/hydration/compiled/server/for.js +41 -41
- package/tests/hydration/compiled/server/head.js +26 -26
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +2 -2
- package/tests/hydration/compiled/server/if-children.js +16 -16
- package/tests/hydration/compiled/server/if.js +11 -11
- package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
- package/tests/hydration/compiled/server/portal.js +2 -2
- package/tests/hydration/compiled/server/reactivity.js +16 -16
- package/tests/hydration/compiled/server/return.js +25 -25
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/components/events.ripple +25 -25
- package/tests/hydration/components/for.ripple +66 -66
- package/tests/hydration/components/head.ripple +16 -16
- package/tests/hydration/components/hmr.ripple +2 -2
- package/tests/hydration/components/html.ripple +3 -3
- package/tests/hydration/components/if-children.ripple +24 -24
- package/tests/hydration/components/if.ripple +18 -18
- package/tests/hydration/components/mixed-control-flow.ripple +9 -9
- package/tests/hydration/components/portal.ripple +3 -3
- package/tests/hydration/components/reactivity.ripple +16 -16
- package/tests/hydration/components/return.ripple +40 -40
- package/tests/hydration/components/switch.ripple +20 -20
- package/tests/server/await.test.ripple +3 -3
- package/tests/server/basic.attributes.test.ripple +34 -34
- package/tests/server/basic.components.test.ripple +10 -10
- package/tests/server/basic.test.ripple +38 -40
- package/tests/server/composite.props.test.ripple +9 -9
- package/tests/server/dynamic-elements.test.ripple +13 -12
- package/tests/server/head.test.ripple +11 -11
- package/tests/server/lazy-destructuring.test.ripple +72 -0
- package/types/index.d.ts +7 -2
|
@@ -15,18 +15,18 @@ export component SwitchStatic() {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export component SwitchReactive() {
|
|
18
|
-
let status = track<'a' | 'b' | 'c'>('a');
|
|
18
|
+
let &[status] = track<'a' | 'b' | 'c'>('a');
|
|
19
19
|
<button
|
|
20
20
|
class="toggle"
|
|
21
21
|
onClick={() => {
|
|
22
|
-
if (
|
|
23
|
-
else if (
|
|
24
|
-
else
|
|
22
|
+
if (status === 'a') status = 'b';
|
|
23
|
+
else if (status === 'b') status = 'c';
|
|
24
|
+
else status = 'a';
|
|
25
25
|
}}
|
|
26
26
|
>
|
|
27
27
|
{'Toggle'}
|
|
28
28
|
</button>
|
|
29
|
-
switch (
|
|
29
|
+
switch (status) {
|
|
30
30
|
case 'a':
|
|
31
31
|
<div class="case-a">{'Case A'}</div>
|
|
32
32
|
break;
|
|
@@ -51,18 +51,18 @@ export component SwitchFallthrough() {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export component SwitchNumericLevels() {
|
|
54
|
-
let level = track<1 | 2 | 3>(1);
|
|
54
|
+
let &[level] = track<1 | 2 | 3>(1);
|
|
55
55
|
<button
|
|
56
56
|
class="level-toggle"
|
|
57
57
|
onClick={() => {
|
|
58
|
-
if (
|
|
59
|
-
else if (
|
|
60
|
-
else
|
|
58
|
+
if (level === 1) level = 2;
|
|
59
|
+
else if (level === 2) level = 3;
|
|
60
|
+
else level = 1;
|
|
61
61
|
}}
|
|
62
62
|
>
|
|
63
63
|
{'Toggle Level'}
|
|
64
64
|
</button>
|
|
65
|
-
switch (
|
|
65
|
+
switch (level) {
|
|
66
66
|
case 1:
|
|
67
67
|
<div class="level-1">{'Level 1'}</div>
|
|
68
68
|
break;
|
|
@@ -76,18 +76,18 @@ export component SwitchNumericLevels() {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export component SwitchBlockScoped() {
|
|
79
|
-
let level = track<1 | 2 | 3>(1);
|
|
79
|
+
let &[level] = track<1 | 2 | 3>(1);
|
|
80
80
|
<button
|
|
81
81
|
class="block-toggle"
|
|
82
82
|
onClick={() => {
|
|
83
|
-
if (
|
|
84
|
-
else if (
|
|
85
|
-
else
|
|
83
|
+
if (level === 1) level = 2;
|
|
84
|
+
else if (level === 2) level = 3;
|
|
85
|
+
else level = 1;
|
|
86
86
|
}}
|
|
87
87
|
>
|
|
88
88
|
{'Toggle'}
|
|
89
89
|
</button>
|
|
90
|
-
switch (
|
|
90
|
+
switch (level) {
|
|
91
91
|
case 1: {
|
|
92
92
|
<div class="block-1">{'Block 1'}</div>
|
|
93
93
|
break;
|
|
@@ -104,18 +104,18 @@ export component SwitchBlockScoped() {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
export component SwitchNoBreak() {
|
|
107
|
-
let level = track<1 | 2 | 3>(1);
|
|
107
|
+
let &[level] = track<1 | 2 | 3>(1);
|
|
108
108
|
<button
|
|
109
109
|
class="nobreak-toggle"
|
|
110
110
|
onClick={() => {
|
|
111
|
-
if (
|
|
112
|
-
else if (
|
|
113
|
-
else
|
|
111
|
+
if (level === 1) level = 2;
|
|
112
|
+
else if (level === 2) level = 3;
|
|
113
|
+
else level = 1;
|
|
114
114
|
}}
|
|
115
115
|
>
|
|
116
116
|
{'Toggle'}
|
|
117
117
|
</button>
|
|
118
|
-
switch (
|
|
118
|
+
switch (level) {
|
|
119
119
|
case 1: {
|
|
120
120
|
<div class="nobreak-1">{'NoBreak 1'}</div>
|
|
121
121
|
}
|
|
@@ -8,16 +8,16 @@ describe('await in control flow', () => {
|
|
|
8
8
|
// it('should handle await inside if statement', async () => {
|
|
9
9
|
// component App() {
|
|
10
10
|
// let condition = true;
|
|
11
|
-
// let data = track('loading');
|
|
11
|
+
// let &[data] = track('loading');
|
|
12
12
|
|
|
13
13
|
// if (condition) {
|
|
14
14
|
// await new Promise((resolve) => setTimeout(() => {
|
|
15
|
-
//
|
|
15
|
+
// data = 'loaded';
|
|
16
16
|
// resolve();
|
|
17
17
|
// }, 10));
|
|
18
18
|
// }
|
|
19
19
|
|
|
20
|
-
// <div>{
|
|
20
|
+
// <div>{data}</div>
|
|
21
21
|
// }
|
|
22
22
|
|
|
23
23
|
// const { body } = await render(App);
|
|
@@ -19,9 +19,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
19
19
|
|
|
20
20
|
it('render dynamic class attribute', async () => {
|
|
21
21
|
component Basic() {
|
|
22
|
-
let active = track(false);
|
|
22
|
+
let &[active] = track(false);
|
|
23
23
|
|
|
24
|
-
<div class={
|
|
24
|
+
<div class={active ? 'active' : 'inactive'}>{'Dynamic Class'}</div>
|
|
25
25
|
|
|
26
26
|
<style>
|
|
27
27
|
.active {
|
|
@@ -89,9 +89,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
89
89
|
|
|
90
90
|
it('render dynamic class object', async () => {
|
|
91
91
|
component Basic() {
|
|
92
|
-
let active = track(false);
|
|
92
|
+
let &[active] = track(false);
|
|
93
93
|
|
|
94
|
-
<div class={{ active:
|
|
94
|
+
<div class={{ active: active, inactive: !active }}>{'Dynamic Class'}</div>
|
|
95
95
|
|
|
96
96
|
<style>
|
|
97
97
|
.active {
|
|
@@ -116,10 +116,10 @@ describe('basic server > attribute rendering', () => {
|
|
|
116
116
|
'applies scoped ripple class to multiple elements with dynamic class expressions',
|
|
117
117
|
async () => {
|
|
118
118
|
component Basic() {
|
|
119
|
-
let selected = track(1);
|
|
119
|
+
let &[selected] = track(1);
|
|
120
120
|
|
|
121
|
-
<div class={
|
|
122
|
-
<div class={
|
|
121
|
+
<div class={selected === 0 ? 'selected' : ''}>{`div 1`}</div>
|
|
122
|
+
<div class={selected === 0 ? 'selected' : ''}>{`div 2`}</div>
|
|
123
123
|
|
|
124
124
|
<style>
|
|
125
125
|
div {
|
|
@@ -147,9 +147,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
147
147
|
|
|
148
148
|
it('render dynamic id attribute', async () => {
|
|
149
149
|
component Basic() {
|
|
150
|
-
let count = track(0);
|
|
150
|
+
let &[count] = track(0);
|
|
151
151
|
|
|
152
|
-
<div id={`item-${
|
|
152
|
+
<div id={`item-${count}`}>{'Dynamic ID'}</div>
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
const { body } = await render(Basic);
|
|
@@ -162,9 +162,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
162
162
|
|
|
163
163
|
it('render dynamic style attribute', async () => {
|
|
164
164
|
component Basic() {
|
|
165
|
-
let color = track('red');
|
|
165
|
+
let &[color] = track('red');
|
|
166
166
|
|
|
167
|
-
<div style={`color: ${
|
|
167
|
+
<div style={`color: ${color}; font-weight: bold;`}>{'Dynamic Style'}</div>
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
const { body } = await render(Basic);
|
|
@@ -178,9 +178,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
178
178
|
|
|
179
179
|
it('render style attribute as dynamic object', async () => {
|
|
180
180
|
component Basic() {
|
|
181
|
-
let color = track('red');
|
|
181
|
+
let &[color] = track('red');
|
|
182
182
|
|
|
183
|
-
<div style={{ color:
|
|
183
|
+
<div style={{ color: color, fontWeight: 'bold' }}>{'Dynamic Style'}</div>
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
const { body } = await render(Basic);
|
|
@@ -194,9 +194,9 @@ describe('basic server > attribute rendering', () => {
|
|
|
194
194
|
|
|
195
195
|
it('render tracked variable as style attribute', async () => {
|
|
196
196
|
component Basic() {
|
|
197
|
-
let style = track({ color: 'red', fontWeight: 'bold' });
|
|
197
|
+
let &[style] = track({ color: 'red', fontWeight: 'bold' });
|
|
198
198
|
|
|
199
|
-
<div {
|
|
199
|
+
<div {style}>{'Dynamic Style'}</div>
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
const { body } = await render(Basic);
|
|
@@ -277,10 +277,10 @@ describe('basic server > attribute rendering', () => {
|
|
|
277
277
|
|
|
278
278
|
it('render dynamic boolean attributes as false', async () => {
|
|
279
279
|
component Basic() {
|
|
280
|
-
let disabled = track(false);
|
|
281
|
-
let checked = track(false);
|
|
280
|
+
let &[disabled] = track(false);
|
|
281
|
+
let &[checked] = track(false);
|
|
282
282
|
|
|
283
|
-
<input type="checkbox" {
|
|
283
|
+
<input type="checkbox" {disabled} {checked} />
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
const { body } = await render(Basic);
|
|
@@ -312,10 +312,10 @@ describe('basic server > attribute rendering', () => {
|
|
|
312
312
|
|
|
313
313
|
it('render dynamic boolean attributes as true', async () => {
|
|
314
314
|
component Basic() {
|
|
315
|
-
let disabled = track(true);
|
|
316
|
-
let checked = track(true);
|
|
315
|
+
let &[disabled] = track(true);
|
|
316
|
+
let &[checked] = track(true);
|
|
317
317
|
|
|
318
|
-
<input type="checkbox" {
|
|
318
|
+
<input type="checkbox" {disabled} {checked} />
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
const { body } = await render(Basic);
|
|
@@ -347,10 +347,10 @@ describe('basic server > attribute rendering', () => {
|
|
|
347
347
|
|
|
348
348
|
it('render multiple dynamic attributes', async () => {
|
|
349
349
|
component Basic() {
|
|
350
|
-
let theme = track('light');
|
|
351
|
-
let size = track('medium');
|
|
350
|
+
let &[theme] = track('light');
|
|
351
|
+
let &[size] = track('medium');
|
|
352
352
|
|
|
353
|
-
<div class={`theme-${
|
|
353
|
+
<div class={`theme-${theme} size-${size}`} data-theme={theme} data-size={size}>
|
|
354
354
|
{'Multiple Dynamic Attributes'}
|
|
355
355
|
</div>
|
|
356
356
|
}
|
|
@@ -367,12 +367,12 @@ describe('basic server > attribute rendering', () => {
|
|
|
367
367
|
|
|
368
368
|
it('render conditional attributes', async () => {
|
|
369
369
|
component Basic() {
|
|
370
|
-
let showTitle = track(false);
|
|
371
|
-
let showAria = track(false);
|
|
370
|
+
let &[showTitle] = track(false);
|
|
371
|
+
let &[showAria] = track(false);
|
|
372
372
|
|
|
373
373
|
<div
|
|
374
|
-
title={
|
|
375
|
-
aria-label={
|
|
374
|
+
title={showTitle ? 'This is a title' : undefined}
|
|
375
|
+
aria-label={showAria ? 'Accessible label' : undefined}
|
|
376
376
|
>
|
|
377
377
|
{'Conditional Attributes'}
|
|
378
378
|
</div>
|
|
@@ -389,14 +389,14 @@ describe('basic server > attribute rendering', () => {
|
|
|
389
389
|
|
|
390
390
|
it('render spread attributes', async () => {
|
|
391
391
|
component Basic() {
|
|
392
|
-
let attrs = track<TestAttributes>(
|
|
392
|
+
let &[attrs] = track<TestAttributes>(
|
|
393
393
|
{
|
|
394
394
|
class: 'initial',
|
|
395
395
|
id: 'test-1',
|
|
396
396
|
},
|
|
397
397
|
);
|
|
398
398
|
|
|
399
|
-
<div {
|
|
399
|
+
<div {...attrs}>{'Spread Attributes'}</div>
|
|
400
400
|
}
|
|
401
401
|
|
|
402
402
|
const { body } = await render(Basic);
|
|
@@ -411,14 +411,14 @@ describe('basic server > attribute rendering', () => {
|
|
|
411
411
|
|
|
412
412
|
it('renders with reactive attributes with nested reactive attributes', async () => {
|
|
413
413
|
component Basic() {
|
|
414
|
-
let value = track('parent-class');
|
|
414
|
+
let &[value] = track('parent-class');
|
|
415
415
|
|
|
416
|
-
<p class={
|
|
416
|
+
<p class={value}>{'Colored parent value'}</p>
|
|
417
417
|
|
|
418
418
|
<div>
|
|
419
|
-
let nested = track('nested-class');
|
|
419
|
+
let &[nested] = track('nested-class');
|
|
420
420
|
|
|
421
|
-
<p class={
|
|
421
|
+
<p class={nested}>{'Colored nested value'}</p>
|
|
422
422
|
</div>
|
|
423
423
|
}
|
|
424
424
|
|
|
@@ -107,15 +107,15 @@ describe('basic server > components & composition', () => {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
component Basic() {
|
|
110
|
-
let clicked = track(false);
|
|
110
|
+
let &[clicked] = track(false);
|
|
111
111
|
|
|
112
112
|
<Card
|
|
113
113
|
title="Test Card"
|
|
114
114
|
content="This is a test card"
|
|
115
115
|
buttonText="Click me"
|
|
116
|
-
onAction={() => (
|
|
116
|
+
onAction={() => (clicked = true)}
|
|
117
117
|
/>
|
|
118
|
-
<div class="status">{
|
|
118
|
+
<div class="status">{clicked ? 'Clicked' : 'Not clicked'}</div>
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
const { body } = await render(Basic);
|
|
@@ -139,19 +139,19 @@ describe('basic server > components & composition', () => {
|
|
|
139
139
|
text: Tracked<string>;
|
|
140
140
|
count: Tracked<number>;
|
|
141
141
|
}>) {
|
|
142
|
-
<div class="child-content">{props
|
|
143
|
-
<div class="child-count">{props
|
|
142
|
+
<div class="child-content">{props.text.value}</div>
|
|
143
|
+
<div class="child-count">{props.count.value}</div>
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
component Basic() {
|
|
147
|
-
let message = track('Hello');
|
|
148
|
-
let number = track(1);
|
|
147
|
+
let &[message, messageTracked] = track('Hello');
|
|
148
|
+
let &[number, numberTracked] = track(1);
|
|
149
149
|
|
|
150
|
-
<ChildComponent text={
|
|
150
|
+
<ChildComponent text={messageTracked} count={numberTracked} />
|
|
151
151
|
<button
|
|
152
152
|
onClick={() => {
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
message = message === 'Hello' ? 'Goodbye' : 'Hello';
|
|
154
|
+
number++;
|
|
155
155
|
}}
|
|
156
156
|
>
|
|
157
157
|
{'Update Props'}
|
|
@@ -15,12 +15,12 @@ describe('basic client', () => {
|
|
|
15
15
|
|
|
16
16
|
it('renders tracked state updates', async () => {
|
|
17
17
|
component Counter() {
|
|
18
|
-
|
|
18
|
+
let &[count] = track(0);
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
count++;
|
|
21
|
+
count = count + 5;
|
|
22
22
|
|
|
23
|
-
<div>{
|
|
23
|
+
<div>{count}</div>
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const { body } = await render(Counter);
|
|
@@ -34,7 +34,7 @@ describe('basic client', () => {
|
|
|
34
34
|
class: { test: boolean };
|
|
35
35
|
}>) {
|
|
36
36
|
<div {...rest}>{'Child Component'}</div>
|
|
37
|
-
<div>{
|
|
37
|
+
<div>{count.value}</div>
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
component Parent() {
|
|
@@ -53,10 +53,10 @@ describe('basic client', () => {
|
|
|
53
53
|
component ObjCounter() {
|
|
54
54
|
const obj = { count: track(2) };
|
|
55
55
|
|
|
56
|
-
obj
|
|
57
|
-
obj
|
|
56
|
+
obj.count.value += 3;
|
|
57
|
+
obj.count.value = obj.count.value + 1;
|
|
58
58
|
|
|
59
|
-
<div>{obj
|
|
59
|
+
<div>{obj.count.value}</div>
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
const { body } = await render(ObjCounter);
|
|
@@ -66,11 +66,11 @@ describe('basic client', () => {
|
|
|
66
66
|
|
|
67
67
|
it('renders spread props with tracked values', async () => {
|
|
68
68
|
component SpreadProps() {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
let &[id] = track('unique-id');
|
|
70
|
+
let &[isActive] = track(true);
|
|
71
|
+
let &[styles] = track({ color: 'red', fontSize: '16px' });
|
|
72
72
|
|
|
73
|
-
<div {...{ id:
|
|
73
|
+
<div {...{ id: id, class: { active: isActive }, style: styles }}>{'Spread Props'}</div>
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const { body } = await render(SpreadProps);
|
|
@@ -82,14 +82,14 @@ describe('basic client', () => {
|
|
|
82
82
|
|
|
83
83
|
it('handles AssignExpressions with tracked values or properties correctly', async () => {
|
|
84
84
|
component Assignments() {
|
|
85
|
-
|
|
85
|
+
let &[count] = track(0);
|
|
86
86
|
const obj = { value: track(5) };
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
obj
|
|
88
|
+
count += 10;
|
|
89
|
+
obj.value.value *= 2;
|
|
90
90
|
|
|
91
|
-
<div>{
|
|
92
|
-
<div>{obj
|
|
91
|
+
<div>{count}</div>
|
|
92
|
+
<div>{obj.value.value}</div>
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
const { body } = await render(Assignments);
|
|
@@ -99,16 +99,15 @@ describe('basic client', () => {
|
|
|
99
99
|
|
|
100
100
|
it(`handles derived changes via tracked dependencies' changes`, async () => {
|
|
101
101
|
component Derived() {
|
|
102
|
-
let base = track(5);
|
|
103
|
-
let multiplier = track(3);
|
|
104
|
-
|
|
102
|
+
let &[base] = track(5);
|
|
103
|
+
let &[multiplier] = track(3);
|
|
104
|
+
let &[derived] = track(() => base * multiplier);
|
|
105
105
|
|
|
106
|
-
<div>{
|
|
106
|
+
<div>{derived}</div>
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
base += 2;
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
<div>{@derived}</div>
|
|
110
|
+
<div>{derived}</div>
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
const { body } = await render(Derived);
|
|
@@ -118,17 +117,16 @@ describe('basic client', () => {
|
|
|
118
117
|
|
|
119
118
|
it(`handles derived changes based on another derived's dependencies' changes`, async () => {
|
|
120
119
|
component NestedDerived() {
|
|
121
|
-
let a = track(2);
|
|
122
|
-
let b = track(3);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
<div>{@product}</div>
|
|
120
|
+
let &[a] = track(2);
|
|
121
|
+
let &[b] = track(3);
|
|
122
|
+
let &[sum] = track(() => a + b);
|
|
123
|
+
let &[product] = track(() => sum * 2);
|
|
127
124
|
|
|
128
|
-
|
|
125
|
+
<div>{product}</div>
|
|
129
126
|
|
|
127
|
+
a = 4;
|
|
130
128
|
|
|
131
|
-
<div>{
|
|
129
|
+
<div>{product}</div>
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
const { body } = await render(NestedDerived);
|
|
@@ -138,20 +136,20 @@ describe('basic client', () => {
|
|
|
138
136
|
|
|
139
137
|
it('handles lexical scopes correctly', async () => {
|
|
140
138
|
component LexicalScopes() {
|
|
141
|
-
let x = track(1);
|
|
142
|
-
<div>{
|
|
139
|
+
let &[x] = track(1);
|
|
140
|
+
<div>{x}</div>
|
|
143
141
|
|
|
144
142
|
<div>
|
|
145
|
-
let x = track(10);
|
|
146
|
-
{
|
|
143
|
+
let &[x] = track(10);
|
|
144
|
+
{x}
|
|
147
145
|
</div>
|
|
148
146
|
|
|
149
147
|
<div>
|
|
150
|
-
let x = track(12);
|
|
151
|
-
{
|
|
148
|
+
let &[x] = track(12);
|
|
149
|
+
{x}
|
|
152
150
|
<span>
|
|
153
|
-
let x = track(15);
|
|
154
|
-
{
|
|
151
|
+
let &[x] = track(15);
|
|
152
|
+
{x}
|
|
155
153
|
</span>
|
|
156
154
|
</div>
|
|
157
155
|
}
|
|
@@ -8,10 +8,10 @@ describe('composite > props', () => {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
component App() {
|
|
11
|
-
let foo = track(123);
|
|
11
|
+
let &[foo] = track(123);
|
|
12
12
|
|
|
13
13
|
<Child />
|
|
14
|
-
<Child {
|
|
14
|
+
<Child {foo} />
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const { body } = await render(App);
|
|
@@ -42,7 +42,7 @@ describe('composite > props', () => {
|
|
|
42
42
|
|
|
43
43
|
it('correctly handles no props', async () => {
|
|
44
44
|
component Child(props: { foo?: Tracked<number> }) {
|
|
45
|
-
<div>{props
|
|
45
|
+
<div>{props.foo?.value}</div>
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
component App() {
|
|
@@ -65,10 +65,10 @@ describe('composite > props', () => {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
component App() {
|
|
68
|
-
let foo = track(123);
|
|
68
|
+
let &[foo] = track(123);
|
|
69
69
|
|
|
70
70
|
<Child />
|
|
71
|
-
<Child {
|
|
71
|
+
<Child {foo} />
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
const { body } = await render(App);
|
|
@@ -81,7 +81,7 @@ describe('composite > props', () => {
|
|
|
81
81
|
it('correctly retains prop accessors and reactivity when using rest props', async () => {
|
|
82
82
|
component Button(props: Props) {
|
|
83
83
|
const [children, rest] = trackSplit(props, ['children']);
|
|
84
|
-
<button {
|
|
84
|
+
<button {...rest.value}>
|
|
85
85
|
<@children />
|
|
86
86
|
</button>
|
|
87
87
|
<style>
|
|
@@ -96,9 +96,9 @@ describe('composite > props', () => {
|
|
|
96
96
|
|
|
97
97
|
component Toggle(props: { pressed: Tracked<boolean> }) {
|
|
98
98
|
const [pressed, rest] = trackSplit(props, ['pressed']);
|
|
99
|
-
const onClick = () => (
|
|
100
|
-
<Button {
|
|
101
|
-
<Button class={
|
|
99
|
+
const onClick = () => (pressed.value = !pressed.value);
|
|
100
|
+
<Button {...rest.value} class={pressed.value ? 'on' : 'off'} {onClick}>{'button 1'}</Button>
|
|
101
|
+
<Button class={pressed.value ? 'on' : 'off'} {onClick}>{'button 2'}</Button>
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
component App() {
|
|
@@ -19,8 +19,9 @@ describe('server dynamic DOM elements', () => {
|
|
|
19
19
|
it('renders static dynamic element from a plain object with a tracked property', async () => {
|
|
20
20
|
component App() {
|
|
21
21
|
let obj = { tag: track('div') };
|
|
22
|
+
let tag = obj.tag;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
<@tag>{'Hello World'}</@tag>
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
const { body } = await render(App);
|
|
@@ -31,8 +32,9 @@ describe('server dynamic DOM elements', () => {
|
|
|
31
32
|
it('renders static dynamic element from a tracked object with a tracked property', async () => {
|
|
32
33
|
component App() {
|
|
33
34
|
let obj = track({ tag: track('div') });
|
|
35
|
+
let tag = obj.value.tag;
|
|
34
36
|
|
|
35
|
-
<@
|
|
37
|
+
<@tag>{'Hello World'}</@tag>
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
const { body } = await render(App);
|
|
@@ -45,8 +47,9 @@ describe('server dynamic DOM elements', () => {
|
|
|
45
47
|
async () => {
|
|
46
48
|
component App() {
|
|
47
49
|
let obj = track({ tag: track('div') });
|
|
50
|
+
let tag = obj.value['tag'];
|
|
48
51
|
|
|
49
|
-
<@
|
|
52
|
+
<@tag>{'Hello World'}</@tag>
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
const { body } = await render(App);
|
|
@@ -70,9 +73,9 @@ describe('server dynamic DOM elements', () => {
|
|
|
70
73
|
it('handles dynamic element with attributes', async () => {
|
|
71
74
|
component App() {
|
|
72
75
|
let tag = track('div');
|
|
73
|
-
let className = track('test-class');
|
|
76
|
+
let &[className] = track('test-class');
|
|
74
77
|
|
|
75
|
-
<@tag class={
|
|
78
|
+
<@tag class={className} id="test" data-testid="dynamic-element">{'Content'}</@tag>
|
|
76
79
|
}
|
|
77
80
|
const { body } = await render(App);
|
|
78
81
|
const { document } = parseHtml(body);
|
|
@@ -109,11 +112,9 @@ describe('server dynamic DOM elements', () => {
|
|
|
109
112
|
it('handles dynamic element with class object', async () => {
|
|
110
113
|
component App() {
|
|
111
114
|
let tag = track('div');
|
|
112
|
-
let active = track(true);
|
|
115
|
+
let &[active] = track(true);
|
|
113
116
|
|
|
114
|
-
<@tag class={{ active:
|
|
115
|
-
{'Element with class object'}
|
|
116
|
-
</@tag>
|
|
117
|
+
<@tag class={{ active: active, 'dynamic-element': true }}>{'Element with class object'}</@tag>
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
const { body } = await render(App);
|
|
@@ -263,7 +264,7 @@ describe('server dynamic DOM elements', () => {
|
|
|
263
264
|
}>) {
|
|
264
265
|
const tag = track('button');
|
|
265
266
|
const [rest] = trackSplit(props, []);
|
|
266
|
-
<@tag {
|
|
267
|
+
<@tag {...rest.value}>{rest.value.class}</@tag>
|
|
267
268
|
|
|
268
269
|
<style>
|
|
269
270
|
.even {
|
|
@@ -276,8 +277,8 @@ describe('server dynamic DOM elements', () => {
|
|
|
276
277
|
}
|
|
277
278
|
|
|
278
279
|
component App() {
|
|
279
|
-
|
|
280
|
-
<DynamicButton class={
|
|
280
|
+
let &[count] = track(0);
|
|
281
|
+
<DynamicButton class={count % 2 ? 'even' : 'odd'} id={count % 2 ? 'even' : 'odd'} />
|
|
281
282
|
}
|
|
282
283
|
|
|
283
284
|
const { body } = await render(App);
|