ripple 0.3.7 → 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.
Files changed (100) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +2 -2
  3. package/src/compiler/phases/1-parse/index.js +37 -194
  4. package/src/compiler/phases/2-analyze/index.js +63 -18
  5. package/src/compiler/phases/3-transform/client/index.js +19 -3
  6. package/src/compiler/phases/3-transform/server/index.js +16 -24
  7. package/src/compiler/types/parse.d.ts +0 -8
  8. package/src/runtime/internal/client/composite.js +2 -2
  9. package/tests/client/array/array.copy-within.test.ripple +12 -12
  10. package/tests/client/array/array.derived.test.ripple +46 -46
  11. package/tests/client/array/array.iteration.test.ripple +10 -10
  12. package/tests/client/array/array.mutations.test.ripple +20 -20
  13. package/tests/client/array/array.to-methods.test.ripple +6 -6
  14. package/tests/client/async-suspend.test.ripple +5 -5
  15. package/tests/client/basic/basic.attributes.test.ripple +81 -81
  16. package/tests/client/basic/basic.collections.test.ripple +9 -9
  17. package/tests/client/basic/basic.components.test.ripple +28 -28
  18. package/tests/client/basic/basic.errors.test.ripple +18 -18
  19. package/tests/client/basic/basic.events.test.ripple +37 -37
  20. package/tests/client/basic/basic.get-set.test.ripple +6 -6
  21. package/tests/client/basic/basic.reactivity.test.ripple +68 -68
  22. package/tests/client/basic/basic.rendering.test.ripple +19 -19
  23. package/tests/client/basic/basic.utilities.test.ripple +3 -3
  24. package/tests/client/boundaries.test.ripple +12 -12
  25. package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
  26. package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
  27. package/tests/client/compiler/compiler.basic.test.ripple +16 -16
  28. package/tests/client/compiler/compiler.tracked-access.test.ripple +2 -2
  29. package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
  30. package/tests/client/composite/composite.props.test.ripple +11 -11
  31. package/tests/client/composite/composite.reactivity.test.ripple +43 -43
  32. package/tests/client/composite/composite.render.test.ripple +3 -3
  33. package/tests/client/computed-properties.test.ripple +4 -4
  34. package/tests/client/date.test.ripple +42 -42
  35. package/tests/client/dynamic-elements.test.ripple +42 -42
  36. package/tests/client/events.test.ripple +70 -70
  37. package/tests/client/for.test.ripple +25 -25
  38. package/tests/client/head.test.ripple +19 -19
  39. package/tests/client/html.test.ripple +3 -3
  40. package/tests/client/input-value.test.ripple +84 -84
  41. package/tests/client/lazy-destructuring.test.ripple +71 -16
  42. package/tests/client/map.test.ripple +16 -16
  43. package/tests/client/media-query.test.ripple +7 -7
  44. package/tests/client/portal.test.ripple +11 -11
  45. package/tests/client/ref.test.ripple +4 -4
  46. package/tests/client/return.test.ripple +52 -52
  47. package/tests/client/set.test.ripple +6 -6
  48. package/tests/client/svg.test.ripple +5 -5
  49. package/tests/client/switch.test.ripple +44 -44
  50. package/tests/client/try.test.ripple +5 -5
  51. package/tests/client/url/url.derived.test.ripple +6 -6
  52. package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
  53. package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
  54. package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
  55. package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
  56. package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
  57. package/tests/hydration/compiled/client/events.js +25 -25
  58. package/tests/hydration/compiled/client/for.js +70 -66
  59. package/tests/hydration/compiled/client/head.js +25 -25
  60. package/tests/hydration/compiled/client/hmr.js +2 -2
  61. package/tests/hydration/compiled/client/html.js +3 -3
  62. package/tests/hydration/compiled/client/if-children.js +24 -24
  63. package/tests/hydration/compiled/client/if.js +18 -18
  64. package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
  65. package/tests/hydration/compiled/client/portal.js +3 -3
  66. package/tests/hydration/compiled/client/reactivity.js +16 -16
  67. package/tests/hydration/compiled/client/return.js +40 -40
  68. package/tests/hydration/compiled/client/switch.js +12 -12
  69. package/tests/hydration/compiled/server/events.js +19 -19
  70. package/tests/hydration/compiled/server/for.js +41 -41
  71. package/tests/hydration/compiled/server/head.js +26 -26
  72. package/tests/hydration/compiled/server/hmr.js +2 -2
  73. package/tests/hydration/compiled/server/html.js +2 -2
  74. package/tests/hydration/compiled/server/if-children.js +16 -16
  75. package/tests/hydration/compiled/server/if.js +11 -11
  76. package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
  77. package/tests/hydration/compiled/server/portal.js +2 -2
  78. package/tests/hydration/compiled/server/reactivity.js +16 -16
  79. package/tests/hydration/compiled/server/return.js +25 -25
  80. package/tests/hydration/compiled/server/switch.js +8 -8
  81. package/tests/hydration/components/events.ripple +25 -25
  82. package/tests/hydration/components/for.ripple +66 -66
  83. package/tests/hydration/components/head.ripple +16 -16
  84. package/tests/hydration/components/hmr.ripple +2 -2
  85. package/tests/hydration/components/html.ripple +3 -3
  86. package/tests/hydration/components/if-children.ripple +24 -24
  87. package/tests/hydration/components/if.ripple +18 -18
  88. package/tests/hydration/components/mixed-control-flow.ripple +9 -9
  89. package/tests/hydration/components/portal.ripple +3 -3
  90. package/tests/hydration/components/reactivity.ripple +16 -16
  91. package/tests/hydration/components/return.ripple +40 -40
  92. package/tests/hydration/components/switch.ripple +20 -20
  93. package/tests/server/await.test.ripple +3 -3
  94. package/tests/server/basic.attributes.test.ripple +34 -34
  95. package/tests/server/basic.components.test.ripple +10 -10
  96. package/tests/server/basic.test.ripple +38 -40
  97. package/tests/server/composite.props.test.ripple +9 -9
  98. package/tests/server/dynamic-elements.test.ripple +13 -12
  99. package/tests/server/head.test.ripple +11 -11
  100. package/tests/server/lazy-destructuring.test.ripple +27 -4
@@ -29,14 +29,14 @@ describe('lazy destructuring', () => {
29
29
  }
30
30
 
31
31
  component Test() {
32
- let a = track(1);
33
- let b = track('hello');
32
+ let &[a] = track(1);
33
+ let &[b] = track('hello');
34
34
 
35
- <Inner {@a} {@b} />
35
+ <Inner {a} {b} />
36
36
  <button
37
37
  onClick={() => {
38
- @a = 2;
39
- @b = 'world';
38
+ a = 2;
39
+ b = 'world';
40
40
  }}
41
41
  >
42
42
  {'update'}
@@ -56,14 +56,14 @@ describe('lazy destructuring', () => {
56
56
  }
57
57
 
58
58
  component Test() {
59
- let first = track(10);
60
- let second = track(20);
59
+ let &[first] = track(10);
60
+ let &[second] = track(20);
61
61
 
62
- <Inner {@first} {@second} />
62
+ <Inner {first} {second} />
63
63
  <button
64
64
  onClick={() => {
65
- @first = 30;
66
- @second = 40;
65
+ first = 30;
66
+ second = 40;
67
67
  }}
68
68
  >
69
69
  {'update'}
@@ -107,12 +107,12 @@ describe('lazy destructuring', () => {
107
107
  }
108
108
 
109
109
  component Test() {
110
- let count = track(0);
110
+ let &[count] = track(0);
111
111
 
112
- <Inner {@count} />
112
+ <Inner {count} />
113
113
  <button
114
114
  onClick={() => {
115
- @count++;
115
+ count++;
116
116
  }}
117
117
  >
118
118
  {'increment'}
@@ -208,8 +208,8 @@ describe('lazy destructuring', () => {
208
208
  it('does not apply the track tuple fast-path to trackSplit lazy arrays', () => {
209
209
  component Test() {
210
210
  const source = { a: 1, b: 2, c: 3 };
211
- let &[a, b, rest] = trackSplit(source, ['a', 'b']);
212
- <pre>{`${@a}-${@b}-${@rest.c}`}</pre>
211
+ let [a, b, rest] = trackSplit(source, ['a', 'b']);
212
+ <pre>{`${a.value}-${b.value}-${rest.value.c}`}</pre>
213
213
  }
214
214
 
215
215
  render(Test);
@@ -219,7 +219,7 @@ describe('lazy destructuring', () => {
219
219
  it('supports rest destructuring from iterable array-like tracked values', () => {
220
220
  component Test() {
221
221
  let &[value, ...rest] = track(0);
222
- <pre>{`${value}-${@rest.length}-${@rest[0] === value}`}</pre>
222
+ <pre>{`${value}-${rest.length}-${rest[0] === value}`}</pre>
223
223
  }
224
224
 
225
225
  render(Test);
@@ -260,4 +260,59 @@ describe('lazy destructuring', () => {
260
260
  render(Test);
261
261
  expect(container.querySelector('pre')!.textContent).toBe('Alice-30');
262
262
  });
263
+
264
+ it('supports standalone lazy array destructuring with track()', () => {
265
+ component Test() {
266
+ let count;
267
+ &[count] = track(0);
268
+ <div>{count}</div>
269
+ <button
270
+ onClick={() => {
271
+ count++;
272
+ }}
273
+ >
274
+ {'inc'}
275
+ </button>
276
+ }
277
+
278
+ render(Test);
279
+ expect(container.querySelector('div')!.textContent).toBe('0');
280
+ container.querySelector('button')!.click();
281
+ flushSync();
282
+ expect(container.querySelector('div')!.textContent).toBe('1');
283
+ });
284
+
285
+ it('supports standalone lazy array destructuring with second element', () => {
286
+ component Test() {
287
+ let value;
288
+ let tracked;
289
+ &[value, tracked] = track(42);
290
+ <div>{value}</div>
291
+ <button
292
+ onClick={() => {
293
+ value = 100;
294
+ }}
295
+ >
296
+ {'set'}
297
+ </button>
298
+ }
299
+
300
+ render(Test);
301
+ expect(container.querySelector('div')!.textContent).toBe('42');
302
+ container.querySelector('button')!.click();
303
+ flushSync();
304
+ expect(container.querySelector('div')!.textContent).toBe('100');
305
+ });
306
+
307
+ it('supports standalone lazy object destructuring', () => {
308
+ component Test() {
309
+ let a;
310
+ let b;
311
+ &{ a, b } = { a: 10, b: 20 };
312
+ <pre>{`${a}-${b}`}</pre>
313
+ }
314
+
315
+ render(Test);
316
+ expect(container.querySelector('pre')!.textContent).toBe('10-20');
317
+ });
263
318
  });
@@ -4,16 +4,16 @@ describe('RippleMap', () => {
4
4
  it('handles set with update and delete operations with a reactive size var', () => {
5
5
  component MapTest() {
6
6
  let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
7
- let value = track(() => map.get('a'));
8
- let size = track(() => map.size);
7
+ let &[value] = track(() => map.get('a'));
8
+ let &[size] = track(() => map.size);
9
9
 
10
10
  <button onClick={() => map.set('d', 4)}>{'set'}</button>
11
11
  <button onClick={() => map.delete('b')}>{'delete'}</button>
12
12
  <button onClick={() => map.set('a', 5)}>{'update'}</button>
13
13
 
14
14
  <pre>{map.get('d')}</pre>
15
- <pre>{@size}</pre>
16
- <pre>{@value}</pre>
15
+ <pre>{size}</pre>
16
+ <pre>{value}</pre>
17
17
  }
18
18
 
19
19
  render(MapTest);
@@ -61,10 +61,10 @@ describe('RippleMap', () => {
61
61
  it('handles has operation and tracks reactive $has', () => {
62
62
  component MapTest() {
63
63
  let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
64
- let has = track(() => map.has('b'));
64
+ let &[has] = track(() => map.has('b'));
65
65
 
66
66
  <button onClick={() => map.delete('b')}>{'delete'}</button>
67
- <pre>{@has}</pre>
67
+ <pre>{has}</pre>
68
68
  }
69
69
 
70
70
  render(MapTest);
@@ -81,15 +81,15 @@ describe('RippleMap', () => {
81
81
  it('handles reactivity of keys, values, and entries', () => {
82
82
  component MapTest() {
83
83
  let map = RippleMap([['x', 10], ['y', 20]]);
84
- let keys = track(() => Array.from(map.keys()));
85
- let values = track(() => Array.from(map.values()));
86
- let entries = track(() => Array.from(map.entries()));
84
+ let &[keys] = track(() => Array.from(map.keys()));
85
+ let &[values] = track(() => Array.from(map.values()));
86
+ let &[entries] = track(() => Array.from(map.entries()));
87
87
 
88
88
  <button onClick={() => map.delete('x')}>{'delete'}</button>
89
89
 
90
- <pre>{JSON.stringify(@keys)}</pre>
91
- <pre>{JSON.stringify(@values)}</pre>
92
- <pre>{JSON.stringify(@entries)}</pre>
90
+ <pre>{JSON.stringify(keys)}</pre>
91
+ <pre>{JSON.stringify(values)}</pre>
92
+ <pre>{JSON.stringify(entries)}</pre>
93
93
  }
94
94
 
95
95
  render(MapTest);
@@ -142,11 +142,11 @@ describe('RippleMap', () => {
142
142
  it('creates RippleMap with initial entries using RippleMap() shorthand syntax', () => {
143
143
  component MapTest() {
144
144
  let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
145
- let value = track(() => map.get('b'));
145
+ let &[value] = track(() => map.get('b'));
146
146
 
147
147
  <button onClick={() => map.set('b', 10)}>{'update'}</button>
148
148
  <pre>{map.size}</pre>
149
- <pre>{@value}</pre>
149
+ <pre>{value}</pre>
150
150
  }
151
151
 
152
152
  render(MapTest);
@@ -164,13 +164,13 @@ describe('RippleMap', () => {
164
164
  it('handles all operations with RippleMap() shorthand syntax', () => {
165
165
  component MapTest() {
166
166
  let map = RippleMap([['x', 100], ['y', 200]]);
167
- let keys = track(() => Array.from(map.keys()));
167
+ let &[keys] = track(() => Array.from(map.keys()));
168
168
 
169
169
  <button onClick={() => map.set('z', 300)}>{'add'}</button>
170
170
  <button onClick={() => map.delete('x')}>{'delete'}</button>
171
171
  <button onClick={() => map.clear()}>{'clear'}</button>
172
172
 
173
- <pre>{JSON.stringify(@keys)}</pre>
173
+ <pre>{JSON.stringify(keys)}</pre>
174
174
  <pre>{map.size}</pre>
175
175
  }
176
176
 
@@ -51,10 +51,10 @@ describe('MediaQuery', () => {
51
51
  const media = '(min-width: 600px)';
52
52
 
53
53
  component App() {
54
- const medium = MediaQuery(media);
54
+ let &[medium] = MediaQuery(media);
55
55
 
56
56
  <div>
57
- <p>{@medium}</p>
57
+ <p>{medium}</p>
58
58
  </div>
59
59
  }
60
60
 
@@ -86,20 +86,20 @@ describe('MediaQuery', () => {
86
86
  const media = '(min-width: 600px)';
87
87
 
88
88
  component App() {
89
- let show = track(true);
89
+ let &[show] = track(true);
90
90
 
91
- if (@show) {
91
+ if (show) {
92
92
  <Child />
93
93
  }
94
94
 
95
- <button onClick={() => (@show = !@show)}>{'Toggle Child'}</button>
95
+ <button onClick={() => (show = !show)}>{'Toggle Child'}</button>
96
96
  }
97
97
 
98
98
  component Child() {
99
- const medium = MediaQuery(media);
99
+ let &[medium] = MediaQuery(media);
100
100
 
101
101
  <div>
102
- <p>{@medium}</p>
102
+ <p>{medium}</p>
103
103
  </div>
104
104
  }
105
105
 
@@ -46,15 +46,15 @@ describe('Portal', () => {
46
46
 
47
47
  it('cleans up portal content when destroyed via conditional rendering', () => {
48
48
  component TestPortal() {
49
- let open = track(true);
49
+ let &[open] = track(true);
50
50
 
51
- if (@open) {
51
+ if (open) {
52
52
  <Portal target={document.body}>
53
53
  <div class="test-portal">{'Conditional content'}</div>
54
54
  </Portal>
55
55
  }
56
56
 
57
- <button onClick={() => (@open = false)}>{'Close'}</button>
57
+ <button onClick={() => (open = false)}>{'Close'}</button>
58
58
  }
59
59
 
60
60
  render(TestPortal);
@@ -72,19 +72,19 @@ describe('Portal', () => {
72
72
 
73
73
  it('opens and closes portal via conditional rendering', () => {
74
74
  component TestPortal() {
75
- let open = track(false);
75
+ let &[open] = track(false);
76
76
 
77
- if (@open) {
77
+ if (open) {
78
78
  <Portal target={document.body}>
79
79
  <div class="test-portal">
80
80
  {'Content'}
81
- <button onClick={() => (@open = false)}>{'Close'}</button>
81
+ <button onClick={() => (open = false)}>{'Close'}</button>
82
82
  </div>
83
83
  </Portal>
84
84
  }
85
85
 
86
- if (!@open) {
87
- <button onClick={() => (@open = true)}>{'Open'}</button>
86
+ if (!open) {
87
+ <button onClick={() => (open = true)}>{'Open'}</button>
88
88
  }
89
89
  }
90
90
 
@@ -138,13 +138,13 @@ describe('Portal', () => {
138
138
 
139
139
  it('handles portal with reactive content', () => {
140
140
  component TestReactivePortal() {
141
- let count = track(0);
141
+ let &[count] = track(0);
142
142
 
143
143
  <Portal target={document.body}>
144
144
  <div class="test-portal">
145
145
  {'Count: '}
146
- {String(@count)}
147
- <button onClick={() => @count++}>{'Increment'}</button>
146
+ {String(count)}
147
+ <button onClick={() => count++}>{'Increment'}</button>
148
148
  </div>
149
149
  </Portal>
150
150
  }
@@ -50,7 +50,7 @@ describe('refs', () => {
50
50
  let logs: string[] = [];
51
51
 
52
52
  component App() {
53
- let value = track('test');
53
+ let &[value] = track('test');
54
54
 
55
55
  function inputRef(node: HTMLInputElement) {
56
56
  logs.push('ref called');
@@ -58,7 +58,7 @@ describe('refs', () => {
58
58
 
59
59
  const props = {
60
60
  id: 'example',
61
- @value,
61
+ value,
62
62
  [createRefKey()]: inputRef,
63
63
  };
64
64
 
@@ -81,7 +81,7 @@ describe('refs', () => {
81
81
  let logs: string[] = [];
82
82
 
83
83
  component App() {
84
- let value = track('test');
84
+ let &[value] = track('test');
85
85
 
86
86
  function inputRef(node: HTMLInputElement) {
87
87
  logs.push('ref called');
@@ -89,7 +89,7 @@ describe('refs', () => {
89
89
 
90
90
  const props = {
91
91
  id: 'example',
92
- @value,
92
+ value,
93
93
  };
94
94
 
95
95
  <input type="text" {ref inputRef} {...props} />
@@ -64,16 +64,16 @@ describe('early return in client components', () => {
64
64
 
65
65
  it('reactive: condition changes from false to true hides rest', () => {
66
66
  component App() {
67
- let condition = track(false);
67
+ let &[condition] = track(false);
68
68
 
69
69
  <button
70
70
  onClick={() => {
71
- @condition = true;
71
+ condition = true;
72
72
  }}
73
73
  >
74
74
  {'toggle'}
75
75
  </button>
76
- if (@condition) {
76
+ if (condition) {
77
77
  <div class="guard">{'guard hit'}</div>
78
78
  return;
79
79
  }
@@ -93,16 +93,16 @@ describe('early return in client components', () => {
93
93
 
94
94
  it('reactive: condition changes from true to false shows rest', () => {
95
95
  component App() {
96
- let condition = track(true);
96
+ let &[condition] = track(true);
97
97
 
98
98
  <button
99
99
  onClick={() => {
100
- @condition = false;
100
+ condition = false;
101
101
  }}
102
102
  >
103
103
  {'toggle'}
104
104
  </button>
105
- if (@condition) {
105
+ if (condition) {
106
106
  <div class="guard">{'guard hit'}</div>
107
107
  return;
108
108
  }
@@ -905,19 +905,19 @@ describe('early return in client components', () => {
905
905
 
906
906
  it('reactive: nested return condition changes', () => {
907
907
  component App() {
908
- let a = track(true);
909
- let b = track(true);
908
+ let &[a] = track(true);
909
+ let &[b] = track(true);
910
910
 
911
911
  <button
912
912
  onClick={() => {
913
- @b = false;
913
+ b = false;
914
914
  }}
915
915
  >
916
916
  {'toggle b'}
917
917
  </button>
918
- if (@a) {
918
+ if (a) {
919
919
  <div class="a">{'a is true'}</div>
920
- if (@b) {
920
+ if (b) {
921
921
  <div class="b">{'b is true'}</div>
922
922
  return;
923
923
  }
@@ -940,18 +940,18 @@ describe('early return in client components', () => {
940
940
 
941
941
  it('reactive: return in nested element scope', () => {
942
942
  component App() {
943
- let show = track(true);
943
+ let &[show] = track(true);
944
944
 
945
945
  <button
946
946
  onClick={() => {
947
- @show = false;
947
+ show = false;
948
948
  }}
949
949
  >
950
950
  {'toggle'}
951
951
  </button>
952
952
  <div class="outer">
953
953
  <span class="label">{'outer'}</span>
954
- if (@show) {
954
+ if (show) {
955
955
  <p class="inner">{'inner'}</p>
956
956
  return;
957
957
  }
@@ -1214,17 +1214,17 @@ describe('early return in client components', () => {
1214
1214
 
1215
1215
  it('reactive: nested return - outer condition changes to false shows rest', () => {
1216
1216
  component App() {
1217
- let a = track(true);
1217
+ let &[a] = track(true);
1218
1218
  let b = true;
1219
1219
 
1220
1220
  <button
1221
1221
  onClick={() => {
1222
- @a = false;
1222
+ a = false;
1223
1223
  }}
1224
1224
  >
1225
1225
  {'toggle a'}
1226
1226
  </button>
1227
- if (@a) {
1227
+ if (a) {
1228
1228
  <div class="a">{'a'}</div>
1229
1229
  if (b) {
1230
1230
  <div class="b">{'b'}</div>
@@ -1251,11 +1251,11 @@ describe('early return in client components', () => {
1251
1251
  component App() {
1252
1252
  let a = true;
1253
1253
  let b = true;
1254
- let c = track(true);
1254
+ let &[c] = track(true);
1255
1255
 
1256
1256
  <button
1257
1257
  onClick={() => {
1258
- @c = false;
1258
+ c = false;
1259
1259
  }}
1260
1260
  >
1261
1261
  {'toggle c'}
@@ -1264,7 +1264,7 @@ describe('early return in client components', () => {
1264
1264
  <div class="a">{'a'}</div>
1265
1265
  if (b) {
1266
1266
  <div class="b">{'b'}</div>
1267
- if (@c) {
1267
+ if (c) {
1268
1268
  <div class="c">{'c'}</div>
1269
1269
  return;
1270
1270
  }
@@ -2208,15 +2208,15 @@ describe('early return in client components', () => {
2208
2208
 
2209
2209
  it('nested reactive: toggling conditions updates DOM', () => {
2210
2210
  component App() {
2211
- let a = track(false);
2212
- let b = track(false);
2213
- let c = track(false);
2214
- let d = track(false);
2211
+ let &[a] = track(false);
2212
+ let &[b] = track(false);
2213
+ let &[c] = track(false);
2214
+ let &[d] = track(false);
2215
2215
 
2216
2216
  <button
2217
2217
  class="toggle-c"
2218
2218
  onClick={() => {
2219
- @c = !@c;
2219
+ c = !c;
2220
2220
  }}
2221
2221
  >
2222
2222
  {'toggle c'}
@@ -2224,24 +2224,24 @@ describe('early return in client components', () => {
2224
2224
  <button
2225
2225
  class="toggle-d"
2226
2226
  onClick={() => {
2227
- @d = !@d;
2227
+ d = !d;
2228
2228
  }}
2229
2229
  >
2230
2230
  {'toggle d'}
2231
2231
  </button>
2232
2232
 
2233
2233
  <div class="outer">
2234
- if (@a) {
2234
+ if (a) {
2235
2235
  <span class="a">{'branch a'}</span>
2236
2236
  }
2237
2237
  <div class="inner">
2238
- if (@b) {
2238
+ if (b) {
2239
2239
  <span class="b">{'branch b'}</span>
2240
2240
  }
2241
- if (@c) {
2241
+ if (c) {
2242
2242
  return;
2243
2243
  }
2244
- if (@d) {
2244
+ if (d) {
2245
2245
  <span class="d">{'branch d'}</span>
2246
2246
  return;
2247
2247
  }
@@ -2279,19 +2279,19 @@ describe('early return in client components', () => {
2279
2279
  () => {
2280
2280
  component App() {
2281
2281
  let a = true;
2282
- let b = track(true);
2282
+ let &[b] = track(true);
2283
2283
 
2284
2284
  <button
2285
2285
  class="toggle"
2286
2286
  onClick={() => {
2287
- @b = !@b;
2287
+ b = !b;
2288
2288
  }}
2289
2289
  >
2290
2290
  {'Toggle'}
2291
2291
  </button>
2292
2292
  if (a) {
2293
2293
  <div class="a">{'a'}</div>
2294
- if (@b) {
2294
+ if (b) {
2295
2295
  <div class="b">{'b'}</div>
2296
2296
  return;
2297
2297
  }
@@ -2326,29 +2326,29 @@ describe('early return in client components', () => {
2326
2326
 
2327
2327
  it('reactive sibling returns cycle through first, second, and fallback branches', () => {
2328
2328
  component App() {
2329
- let mode = track('first');
2329
+ let &[mode] = track('first');
2330
2330
 
2331
2331
  <button
2332
2332
  class="toggle"
2333
2333
  onClick={() => {
2334
- if (@mode === 'first') {
2335
- @mode = 'second';
2336
- } else if (@mode === 'second') {
2337
- @mode = 'none';
2334
+ if (mode === 'first') {
2335
+ mode = 'second';
2336
+ } else if (mode === 'second') {
2337
+ mode = 'none';
2338
2338
  } else {
2339
- @mode = 'first';
2339
+ mode = 'first';
2340
2340
  }
2341
2341
  }}
2342
2342
  >
2343
2343
  {'toggle'}
2344
2344
  </button>
2345
2345
 
2346
- if (@mode === 'first') {
2346
+ if (mode === 'first') {
2347
2347
  <div class="first">{'first guard'}</div>
2348
2348
  return;
2349
2349
  }
2350
2350
 
2351
- if (@mode === 'second') {
2351
+ if (mode === 'second') {
2352
2352
  <div class="second">{'second guard'}</div>
2353
2353
  return;
2354
2354
  }
@@ -2382,13 +2382,13 @@ describe('early return in client components', () => {
2382
2382
 
2383
2383
  it('reactive nested returns with tracked outer and inner flags transition correctly', () => {
2384
2384
  component App() {
2385
- let a = track(true);
2386
- let b = track(true);
2385
+ let &[a] = track(true);
2386
+ let &[b] = track(true);
2387
2387
 
2388
2388
  <button
2389
2389
  class="toggle-a"
2390
2390
  onClick={() => {
2391
- @a = !@a;
2391
+ a = !a;
2392
2392
  }}
2393
2393
  >
2394
2394
  {'toggle a'}
@@ -2397,21 +2397,21 @@ describe('early return in client components', () => {
2397
2397
  <button
2398
2398
  class="toggle-b"
2399
2399
  onClick={() => {
2400
- @b = !@b;
2400
+ b = !b;
2401
2401
  }}
2402
2402
  >
2403
2403
  {'toggle b'}
2404
2404
  </button>
2405
2405
 
2406
- if (@a) {
2406
+ if (a) {
2407
2407
  <div class="a">{'a'}</div>
2408
- if (@b) {
2408
+ if (b) {
2409
2409
  <div class="b">{'b'}</div>
2410
2410
  return;
2411
2411
  }
2412
2412
  }
2413
2413
 
2414
- <div class="rest">{@a ? 'a-on rest' : 'a-off rest'}</div>
2414
+ <div class="rest">{a ? 'a-on rest' : 'a-off rest'}</div>
2415
2415
  }
2416
2416
 
2417
2417
  render(App);
@@ -2446,21 +2446,21 @@ describe('early return in client components', () => {
2446
2446
 
2447
2447
  it('reactive else-if return chain transitions between return and non-return states', () => {
2448
2448
  component App() {
2449
- let status = track(0);
2449
+ let &[status] = track(0);
2450
2450
 
2451
2451
  <button
2452
2452
  class="toggle"
2453
2453
  onClick={() => {
2454
- @status = (@status + 1) % 3;
2454
+ status = (status + 1) % 3;
2455
2455
  }}
2456
2456
  >
2457
2457
  {'toggle'}
2458
2458
  </button>
2459
2459
 
2460
- if (@status === 0) {
2460
+ if (status === 0) {
2461
2461
  <div class="zero">{'zero'}</div>
2462
2462
  return;
2463
- } else if (@status === 1) {
2463
+ } else if (status === 1) {
2464
2464
  <div class="one">{'one'}</div>
2465
2465
  return;
2466
2466
  }