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.
Files changed (110) hide show
  1. package/CHANGELOG.md +43 -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 +290 -26
  5. package/src/compiler/phases/3-transform/client/index.js +54 -14
  6. package/src/compiler/phases/3-transform/server/index.js +19 -35
  7. package/src/compiler/types/index.d.ts +3 -1
  8. package/src/compiler/types/parse.d.ts +0 -8
  9. package/src/compiler/utils.js +10 -6
  10. package/src/runtime/internal/client/composite.js +2 -2
  11. package/src/runtime/internal/client/index.js +2 -0
  12. package/src/runtime/internal/client/runtime.js +95 -45
  13. package/src/runtime/internal/client/types.d.ts +10 -0
  14. package/src/runtime/internal/client/utils.js +12 -0
  15. package/src/runtime/internal/server/index.js +89 -17
  16. package/src/runtime/internal/server/types.d.ts +10 -0
  17. package/src/utils/ast.js +1 -1
  18. package/tests/client/array/array.copy-within.test.ripple +12 -12
  19. package/tests/client/array/array.derived.test.ripple +46 -46
  20. package/tests/client/array/array.iteration.test.ripple +10 -10
  21. package/tests/client/array/array.mutations.test.ripple +20 -20
  22. package/tests/client/array/array.to-methods.test.ripple +6 -6
  23. package/tests/client/async-suspend.test.ripple +5 -5
  24. package/tests/client/basic/basic.attributes.test.ripple +81 -81
  25. package/tests/client/basic/basic.collections.test.ripple +9 -9
  26. package/tests/client/basic/basic.components.test.ripple +28 -28
  27. package/tests/client/basic/basic.errors.test.ripple +18 -18
  28. package/tests/client/basic/basic.events.test.ripple +37 -37
  29. package/tests/client/basic/basic.get-set.test.ripple +6 -6
  30. package/tests/client/basic/basic.reactivity.test.ripple +68 -68
  31. package/tests/client/basic/basic.rendering.test.ripple +19 -19
  32. package/tests/client/basic/basic.utilities.test.ripple +3 -3
  33. package/tests/client/boundaries.test.ripple +12 -12
  34. package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
  35. package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
  36. package/tests/client/compiler/compiler.basic.test.ripple +44 -15
  37. package/tests/client/compiler/compiler.tracked-access.test.ripple +68 -2
  38. package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
  39. package/tests/client/composite/composite.props.test.ripple +11 -11
  40. package/tests/client/composite/composite.reactivity.test.ripple +43 -43
  41. package/tests/client/composite/composite.render.test.ripple +3 -3
  42. package/tests/client/computed-properties.test.ripple +4 -4
  43. package/tests/client/date.test.ripple +42 -42
  44. package/tests/client/dynamic-elements.test.ripple +42 -42
  45. package/tests/client/events.test.ripple +70 -70
  46. package/tests/client/for.test.ripple +25 -25
  47. package/tests/client/head.test.ripple +19 -19
  48. package/tests/client/html.test.ripple +3 -3
  49. package/tests/client/input-value.test.ripple +84 -84
  50. package/tests/client/lazy-destructuring.test.ripple +123 -14
  51. package/tests/client/map.test.ripple +16 -16
  52. package/tests/client/media-query.test.ripple +7 -7
  53. package/tests/client/portal.test.ripple +11 -11
  54. package/tests/client/ref.test.ripple +4 -4
  55. package/tests/client/return.test.ripple +52 -52
  56. package/tests/client/set.test.ripple +6 -6
  57. package/tests/client/svg.test.ripple +5 -5
  58. package/tests/client/switch.test.ripple +44 -44
  59. package/tests/client/try.test.ripple +5 -5
  60. package/tests/client/url/url.derived.test.ripple +6 -6
  61. package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
  62. package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
  63. package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
  64. package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
  65. package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
  66. package/tests/hydration/compiled/client/events.js +25 -25
  67. package/tests/hydration/compiled/client/for.js +70 -66
  68. package/tests/hydration/compiled/client/head.js +25 -25
  69. package/tests/hydration/compiled/client/hmr.js +2 -2
  70. package/tests/hydration/compiled/client/html.js +3 -3
  71. package/tests/hydration/compiled/client/if-children.js +24 -24
  72. package/tests/hydration/compiled/client/if.js +18 -18
  73. package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
  74. package/tests/hydration/compiled/client/portal.js +3 -3
  75. package/tests/hydration/compiled/client/reactivity.js +16 -16
  76. package/tests/hydration/compiled/client/return.js +40 -40
  77. package/tests/hydration/compiled/client/switch.js +12 -12
  78. package/tests/hydration/compiled/server/events.js +19 -19
  79. package/tests/hydration/compiled/server/for.js +41 -41
  80. package/tests/hydration/compiled/server/head.js +26 -26
  81. package/tests/hydration/compiled/server/hmr.js +2 -2
  82. package/tests/hydration/compiled/server/html.js +2 -2
  83. package/tests/hydration/compiled/server/if-children.js +16 -16
  84. package/tests/hydration/compiled/server/if.js +11 -11
  85. package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
  86. package/tests/hydration/compiled/server/portal.js +2 -2
  87. package/tests/hydration/compiled/server/reactivity.js +16 -16
  88. package/tests/hydration/compiled/server/return.js +25 -25
  89. package/tests/hydration/compiled/server/switch.js +8 -8
  90. package/tests/hydration/components/events.ripple +25 -25
  91. package/tests/hydration/components/for.ripple +66 -66
  92. package/tests/hydration/components/head.ripple +16 -16
  93. package/tests/hydration/components/hmr.ripple +2 -2
  94. package/tests/hydration/components/html.ripple +3 -3
  95. package/tests/hydration/components/if-children.ripple +24 -24
  96. package/tests/hydration/components/if.ripple +18 -18
  97. package/tests/hydration/components/mixed-control-flow.ripple +9 -9
  98. package/tests/hydration/components/portal.ripple +3 -3
  99. package/tests/hydration/components/reactivity.ripple +16 -16
  100. package/tests/hydration/components/return.ripple +40 -40
  101. package/tests/hydration/components/switch.ripple +20 -20
  102. package/tests/server/await.test.ripple +3 -3
  103. package/tests/server/basic.attributes.test.ripple +34 -34
  104. package/tests/server/basic.components.test.ripple +10 -10
  105. package/tests/server/basic.test.ripple +38 -40
  106. package/tests/server/composite.props.test.ripple +9 -9
  107. package/tests/server/dynamic-elements.test.ripple +13 -12
  108. package/tests/server/head.test.ripple +11 -11
  109. package/tests/server/lazy-destructuring.test.ripple +72 -0
  110. package/types/index.d.ts +7 -2
@@ -27,16 +27,16 @@ describe('basic client > rendering & text', () => {
27
27
 
28
28
  it('renders dynamic text', () => {
29
29
  component Basic() {
30
- let text = track('Hello World');
30
+ let &[text] = track('Hello World');
31
31
 
32
32
  <button
33
33
  onClick={() => {
34
- @text = 'Hello Ripple';
34
+ text = 'Hello Ripple';
35
35
  }}
36
36
  >
37
37
  {'Change Text'}
38
38
  </button>
39
- <div>{@text}</div>
39
+ <div>{text}</div>
40
40
  }
41
41
 
42
42
  render(Basic);
@@ -104,24 +104,24 @@ describe('basic client > rendering & text', () => {
104
104
 
105
105
  it('renders with mixed static and dynamic content', () => {
106
106
  component Basic() {
107
- let name = track('World');
108
- let count = track(0);
107
+ let &[name] = track('World');
108
+ let &[count] = track(0);
109
109
  const staticMessage = 'Welcome to Ripple!';
110
110
 
111
111
  <div class="mixed-content">
112
112
  <h1>{staticMessage}</h1>
113
- <p class="greeting">{'Hello, ' + @name + '!'}</p>
114
- <p class="notifications">{'You have ' + @count + ' notifications'}</p>
113
+ <p class="greeting">{'Hello, ' + name + '!'}</p>
114
+ <p class="notifications">{'You have ' + count + ' notifications'}</p>
115
115
  <button
116
116
  onClick={() => {
117
- @count++;
117
+ count++;
118
118
  }}
119
119
  >
120
120
  {'Add Notification'}
121
121
  </button>
122
122
  <button
123
123
  onClick={() => {
124
- @name = @name === 'World' ? 'User' : 'World';
124
+ name = name === 'World' ? 'User' : 'World';
125
125
  }}
126
126
  >
127
127
  {'Toggle Name'}
@@ -151,11 +151,11 @@ describe('basic client > rendering & text', () => {
151
151
 
152
152
  it('basic operations', () => {
153
153
  component App() {
154
- let count = track(0);
155
- <div>{@count++}</div>
156
- <div>{++@count}</div>
154
+ let &[count] = track(0);
155
+ <div>{count++}</div>
156
+ <div>{++count}</div>
157
157
  <div>{5}</div>
158
- <div>{@count}</div>
158
+ <div>{count}</div>
159
159
  }
160
160
 
161
161
  render(App);
@@ -164,27 +164,27 @@ describe('basic client > rendering & text', () => {
164
164
 
165
165
  it('renders with conditional rendering using if statements', () => {
166
166
  component Basic() {
167
- let showContent = track(false);
168
- let userRole = track('guest');
167
+ let &[showContent] = track(false);
168
+ let &[userRole] = track('guest');
169
169
 
170
170
  <button
171
171
  onClick={() => {
172
- @showContent = !@showContent;
172
+ showContent = !showContent;
173
173
  }}
174
174
  >
175
175
  {'Toggle Content'}
176
176
  </button>
177
177
  <button
178
178
  onClick={() => {
179
- @userRole = @userRole === 'guest' ? 'admin' : 'guest';
179
+ userRole = userRole === 'guest' ? 'admin' : 'guest';
180
180
  }}
181
181
  >
182
182
  {'Toggle Role'}
183
183
  </button>
184
184
 
185
185
  <div class="content">
186
- if (@showContent) {
187
- if (@userRole === 'admin') {
186
+ if (showContent) {
187
+ if (userRole === 'admin') {
188
188
  <div class="admin-content">{'Admin content'}</div>
189
189
  } else {
190
190
  <div class="user-content">{'User content'}</div>
@@ -6,14 +6,14 @@ describe('basic client > utilities', () => {
6
6
  const promise = new Promise<void>((res) => (resolve = res));
7
7
 
8
8
  component Basic() {
9
- let value = track(0);
9
+ let &[value] = track(0);
10
10
  effect(() => {
11
11
  untrack(() => {
12
- @value++;
12
+ value++;
13
13
  tick().then(() => resolve());
14
14
  });
15
15
  });
16
- <p>{@value}</p>
16
+ <p>{value}</p>
17
17
  }
18
18
  render(Basic);
19
19
 
@@ -4,25 +4,25 @@ describe('passing reactivity between boundaries tests', () => {
4
4
  it('can pass reactivity between functions with simple arrays and destructuring', () => {
5
5
  let log: string[] = [];
6
6
 
7
- function createDouble([count]: [Tracked<number>]) {
8
- const double = track(() => @count * 2);
7
+ function createDouble(&[count]: Tracked<number>) {
8
+ const double = track(() => count * 2);
9
9
 
10
10
  effect(() => {
11
- log.push('Count:' + @count);
11
+ log.push('Count:' + count);
12
12
  });
13
13
 
14
- return [double];
14
+ return double;
15
15
  }
16
16
 
17
17
  component App() {
18
- let count = track(0);
18
+ let &[count, countTracked] = track(0);
19
19
 
20
- const [double] = createDouble([count]);
20
+ const &[double] = createDouble(countTracked);
21
21
 
22
- <div>{'Double: ' + @double}</div>
22
+ <div>{'Double: ' + double}</div>
23
23
  <button
24
24
  onClick={() => {
25
- @count++;
25
+ count++;
26
26
  }}
27
27
  >
28
28
  {'Increment'}
@@ -54,10 +54,10 @@ describe('passing reactivity between boundaries tests', () => {
54
54
  let log: string[] = [];
55
55
 
56
56
  function createDouble({ count }: { count: Tracked<number> }) {
57
- const double = track(() => @count * 2);
57
+ const double = track(() => count.value * 2);
58
58
 
59
59
  effect(() => {
60
- log.push('Count:' + @count);
60
+ log.push('Count:' + count.value);
61
61
  });
62
62
 
63
63
  return { double };
@@ -68,10 +68,10 @@ describe('passing reactivity between boundaries tests', () => {
68
68
 
69
69
  const { double } = createDouble({ count });
70
70
 
71
- <div>{'Double: ' + @double}</div>
71
+ <div>{'Double: ' + double.value}</div>
72
72
  <button
73
73
  onClick={() => {
74
- @count++;
74
+ count.value++;
75
75
  }}
76
76
  >
77
77
  {'Increment'}
@@ -1,12 +1,12 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`compiler > assignments > compiles tracked values in effect with assignment expression 1`] = `"state.count = _$_.get(count);"`;
3
+ exports[`compiler > assignments > compiles tracked values in effect with assignment expression 1`] = `"state.count = _$_.get(lazy);"`;
4
4
 
5
5
  exports[`compiler > assignments > compiles tracked values in effect with update expressions 1`] = `
6
6
  "_$_.untrack(() => {
7
- state.preIncrement = _$_.update_pre(count);
8
- state.postIncrement = _$_.update(count);
9
- state.preDecrement = _$_.update_pre(count, -1);
10
- state.postDecrement = _$_.update(count, -1);
7
+ state.preIncrement = _$_.update_pre(lazy);
8
+ state.postIncrement = _$_.update(lazy);
9
+ state.preDecrement = _$_.update_pre(lazy, -1);
10
+ state.postDecrement = _$_.update(lazy, -1);
11
11
  });"
12
12
  `;
@@ -16,8 +16,8 @@ describe('compiler > assignments', () => {
16
16
 
17
17
  logs.push(items[0]);
18
18
  logs.push(items[i]);
19
- logs.push(@tracked_items[0]);
20
- logs.push(@tracked_items[i]);
19
+ logs.push(tracked_items.value[0]);
20
+ logs.push(tracked_items.value[i]);
21
21
  logs.push(items2[0]);
22
22
  logs.push(items2[i]);
23
23
  logs.push(items3[0]);
@@ -25,8 +25,8 @@ describe('compiler > assignments', () => {
25
25
 
26
26
  items[0] = 123;
27
27
  items[i] = 123;
28
- @tracked_items[0] = 123;
29
- @tracked_items[i] = 123;
28
+ tracked_items.value[0] = 123;
29
+ tracked_items.value[i] = 123;
30
30
  items2[0] = 123;
31
31
  items2[i] = 123;
32
32
  items3[0] = 123;
@@ -34,8 +34,8 @@ describe('compiler > assignments', () => {
34
34
 
35
35
  logs.push(items[0]);
36
36
  logs.push(items[i]);
37
- logs.push(@tracked_items[0]);
38
- logs.push(@tracked_items[i]);
37
+ logs.push(tracked_items.value[0]);
38
+ logs.push(tracked_items.value[i]);
39
39
  logs.push(items2[0]);
40
40
  logs.push(items2[i]);
41
41
  logs.push(items3[0]);
@@ -43,8 +43,8 @@ describe('compiler > assignments', () => {
43
43
 
44
44
  items[0]++;
45
45
  items[i]++;
46
- @tracked_items[0]++;
47
- @tracked_items[i]++;
46
+ tracked_items.value[0]++;
47
+ tracked_items.value[i]++;
48
48
  items2[0]++;
49
49
  items2[i]++;
50
50
  items3[0]++;
@@ -52,8 +52,8 @@ describe('compiler > assignments', () => {
52
52
 
53
53
  logs.push(items[0]);
54
54
  logs.push(items[i]);
55
- logs.push(@tracked_items[0]);
56
- logs.push(@tracked_items[i]);
55
+ logs.push(tracked_items.value[0]);
56
+ logs.push(tracked_items.value[i]);
57
57
  logs.push(items2[0]);
58
58
  logs.push(items2[i]);
59
59
  logs.push(items3[0]);
@@ -61,8 +61,8 @@ describe('compiler > assignments', () => {
61
61
 
62
62
  logs.push(--items[0]);
63
63
  logs.push(--items[i]);
64
- logs.push(--@tracked_items[0]);
65
- logs.push(--@tracked_items[i]);
64
+ logs.push(--tracked_items.value[0]);
65
+ logs.push(--tracked_items.value[i]);
66
66
  logs.push(--items2[0]);
67
67
  logs.push(--items2[i]);
68
68
  logs.push(--items3[0]);
@@ -110,10 +110,10 @@ describe('compiler > assignments', () => {
110
110
  it('compiles tracked values in effect with assignment expression', () => {
111
111
  const source = `import { track, effect } from 'ripple';
112
112
  component App() {
113
- let count = track(0);
113
+ let &[count] = track(0);
114
114
 
115
115
  effect(() => {
116
- state.count = @count;
116
+ state.count = count;
117
117
  });
118
118
  }`;
119
119
  const result = compile(source, 'test.ripple');
@@ -124,14 +124,14 @@ component App() {
124
124
  it('compiles tracked values in effect with update expressions', () => {
125
125
  const source = `import { track, effect, untrack } from 'ripple';
126
126
  component App() {
127
- let count = track(5);
127
+ let &[count] = track(5);
128
128
 
129
129
  effect(() => {
130
130
  untrack(() => {
131
- state.preIncrement = ++@count;
132
- state.postIncrement = @count++;
133
- state.preDecrement = --@count;
134
- state.postDecrement = @count--;
131
+ state.preIncrement = ++count;
132
+ state.postIncrement = count++;
133
+ state.preDecrement = --count;
134
+ state.postDecrement = count--;
135
135
  });
136
136
  });
137
137
  }`;
@@ -324,20 +324,49 @@ describe('compiler > basics', () => {
324
324
  const source = `
325
325
  import { RippleArray, RippleMap, RippleObject, RippleSet, createRefKey, effect, track, untrack } from 'ripple';
326
326
  component App() {
327
- let value = track('test');
328
- function inputRef(node) {}
329
-
330
- const props = {
331
- id: 'example',
332
- @value,
333
- [createRefKey()]: inputRef,
334
- };
327
+ let value = track('test');
328
+ function inputRef(node) {}
329
+
330
+ const props = {
331
+ id: 'example',
332
+ value: value.value,
333
+ [createRefKey()]: inputRef,
334
+ };
335
335
  }
336
336
  `;
337
337
 
338
338
  const result = compile_to_volar_mappings(source, 'test.ripple').code;
339
339
 
340
- expect(result).toMatch(/value:\s*value\??\.\['#v'\]/);
340
+ expect(result).toMatch(/value:\s*value\.value/);
341
+ });
342
+
343
+ it('keeps lazy destructuring as plain destructuring in to_ts output', () => {
344
+ const track_split_source = `
345
+ import { trackSplit } from 'ripple';
346
+ component App() {
347
+ const source = { a: 1, b: 2, c: 3 };
348
+ let &[a, b, rest] = trackSplit(source, ['a', 'b']);
349
+ const sum = a + b + rest.c;
350
+ }
351
+ `;
352
+ const track_split_result = compile_to_volar_mappings(track_split_source, 'test.ripple').code;
353
+ expect(track_split_result).toContain('let [a, b, rest] = trackSplit(source, [\'a\', \'b\']);');
354
+ expect(track_split_result).not.toContain('let lazy = trackSplit');
355
+
356
+ const track_source = `
357
+ import { track } from 'ripple';
358
+ component App() {
359
+ let &[value, ...rest] = track(0);
360
+ const x = value;
361
+ }
362
+ `;
363
+ const track_result = compile_to_volar_mappings(track_source, 'test.ripple').code;
364
+ expect(track_result).toContain('let [value, ...rest] = track(0);');
365
+ expect(track_result).toContain('const x = value;');
366
+ expect(track_result).not.toContain('let lazy = track(0)');
367
+ expect(track_result).not.toContain('.slice(');
368
+ expect(track_result).not.toContain('_$_.get(');
369
+ expect(track_result).not.toContain('lazy0');
341
370
  });
342
371
 
343
372
  it('preserves generic type args in interface extends for Volar mappings', () => {
@@ -364,13 +393,13 @@ export component App(props: Props) {
364
393
  const source = `
365
394
  import { track } from 'ripple';
366
395
  export component App() {
367
- let level = track(1);
396
+ let &[level] = track(1);
368
397
 
369
398
  <button
370
399
  onClick={() => {
371
- if (@level === 1) @level = 2;
372
- else if (@level === 2) @level = 3;
373
- else @level = 1;
400
+ if (level === 1) level = 2;
401
+ else if (level === 2) level = 3;
402
+ else level = 1;
374
403
  }}
375
404
  >
376
405
  {'Toggle'}
@@ -467,10 +496,10 @@ export component App() {
467
496
  import { track, effect, untrack } from 'ripple';
468
497
 
469
498
  component App() {
470
- let count = track(0);
499
+ let &[count] = track(0);
471
500
 
472
501
  effect(() => {
473
- const snapshot = untrack(() => @count);
502
+ const snapshot = untrack(() => count);
474
503
  console.log(snapshot);
475
504
  });
476
505
  }
@@ -70,8 +70,8 @@ import { track } from 'ripple';
70
70
  const code = `
71
71
  import { track } from 'ripple';
72
72
  export default component App() {
73
- let count = track(0);
74
- console.log(@count);
73
+ let &[count] = track(0);
74
+ console.log(count);
75
75
  }
76
76
  `;
77
77
  expect(() => compile(code, 'test.ripple')).not.toThrow();
@@ -121,4 +121,70 @@ import { get, track } from 'ripple';
121
121
  expect(() => compile(code, 'test.ripple')).not.toThrow();
122
122
  },
123
123
  );
124
+
125
+ it('should allow indexed [0] access on a tracked object', () => {
126
+ const code = `
127
+ import { track } from 'ripple';
128
+ export default component App() {
129
+ let count = track(0);
130
+ console.log(count[0]);
131
+ }
132
+ `;
133
+ expect(() => compile(code, 'test.ripple')).not.toThrow();
134
+ });
135
+
136
+ it('should allow indexed [1] access on a tracked object', () => {
137
+ const code = `
138
+ import { track } from 'ripple';
139
+ export default component App() {
140
+ let count = track(0);
141
+ let raw = count[1];
142
+ }
143
+ `;
144
+ expect(() => compile(code, 'test.ripple')).not.toThrow();
145
+ });
146
+
147
+ it('should allow [0] write on a tracked object', () => {
148
+ const code = `
149
+ import { track } from 'ripple';
150
+ export default component App() {
151
+ let count = track(0);
152
+ count[0] = 5;
153
+ }
154
+ `;
155
+ expect(() => compile(code, 'test.ripple')).not.toThrow();
156
+ });
157
+
158
+ it('should allow .value read access on a tracked object', () => {
159
+ const code = `
160
+ import { track } from 'ripple';
161
+ export default component App() {
162
+ let count = track(0);
163
+ console.log(count.value);
164
+ }
165
+ `;
166
+ expect(() => compile(code, 'test.ripple')).not.toThrow();
167
+ });
168
+
169
+ it('should allow .value assignment on a tracked object', () => {
170
+ const code = `
171
+ import { track } from 'ripple';
172
+ export default component App() {
173
+ let count = track(0);
174
+ count.value = 5;
175
+ }
176
+ `;
177
+ expect(() => compile(code, 'test.ripple')).not.toThrow();
178
+ });
179
+
180
+ it('should allow .length read access on a tracked object', () => {
181
+ const code = `
182
+ import { track } from 'ripple';
183
+ export default component App() {
184
+ let count = track(0);
185
+ console.log(count.length);
186
+ }
187
+ `;
188
+ expect(() => compile(code, 'test.ripple')).not.toThrow();
189
+ });
124
190
  });
@@ -18,7 +18,7 @@ describe('composite > dynamic components', () => {
18
18
  expect(container.textContent).toBe('Basic Component');
19
19
  });
20
20
 
21
- it('supports rendering composite components using <object.@component> syntax', () => {
21
+ it('supports rendering composite components from object properties', () => {
22
22
  component App() {
23
23
  component basic() {
24
24
  <div>{'Basic Component'}</div>
@@ -30,7 +30,8 @@ describe('composite > dynamic components', () => {
30
30
  tracked_basic,
31
31
  };
32
32
 
33
- <obj.@tracked_basic />
33
+ const comp = obj.tracked_basic;
34
+ <@comp />
34
35
  }
35
36
 
36
37
  render(App);
@@ -39,7 +40,7 @@ describe('composite > dynamic components', () => {
39
40
  expect(container.textContent).toBe('Basic Component');
40
41
  });
41
42
 
42
- it('supports rendering composite components using <@object.@component> syntax', () => {
43
+ it('supports rendering composite components from tracked object properties', () => {
43
44
  component App() {
44
45
  component basic() {
45
46
  <div>{'Basic Component'}</div>
@@ -51,9 +52,10 @@ describe('composite > dynamic components', () => {
51
52
  tracked_basic,
52
53
  };
53
54
 
54
- const ripple_object = track(obj);
55
+ let &[inner] = track(obj);
55
56
 
56
- <@ripple_object.@tracked_basic />
57
+ const comp = inner.tracked_basic;
58
+ <@comp />
57
59
  }
58
60
 
59
61
  render(App);
@@ -72,15 +74,13 @@ describe('composite > dynamic components', () => {
72
74
  }
73
75
 
74
76
  component App() {
75
- let thing = track(() => Child1);
77
+ let &[thing] = track(() => Child1);
76
78
 
77
79
  <div id="container">
78
80
  <@thing />
79
81
  </div>
80
82
 
81
- <button onClick={() => (@thing = @thing === Child1 ? Child2 : Child1)}>
82
- {'Change Child'}
83
- </button>
83
+ <button onClick={() => (thing = thing === Child1 ? Child2 : Child1)}>{'Change Child'}</button>
84
84
  }
85
85
 
86
86
  render(App);
@@ -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 {@foo} />
14
+ <Child {foo} />
15
15
  }
16
16
 
17
17
  render(App);
@@ -40,7 +40,7 @@ describe('composite > props', () => {
40
40
 
41
41
  it('correctly handles no props', () => {
42
42
  component Child(props: { foo?: Tracked<number> }) {
43
- <div>{props.@foo}</div>
43
+ <div>{props.foo?.value}</div>
44
44
  }
45
45
 
46
46
  component App() {
@@ -62,10 +62,10 @@ describe('composite > props', () => {
62
62
  }
63
63
 
64
64
  component App() {
65
- let foo = track(123);
65
+ let &[foo] = track(123);
66
66
 
67
67
  <Child />
68
- <Child {@foo} />
68
+ <Child {foo} />
69
69
  }
70
70
 
71
71
  render(App);
@@ -79,10 +79,10 @@ describe('composite > props', () => {
79
79
 
80
80
  component Counter({ count }: { count: Tracked<number> }) {
81
81
  effect(() => {
82
- logs.push(@count);
82
+ logs.push(count.value);
83
83
  });
84
84
 
85
- <button onClick={() => (@count = @count + 1)}>{'+'}</button>
85
+ <button onClick={() => (count.value = count.value + 1)}>{'+'}</button>
86
86
  }
87
87
 
88
88
  component App() {
@@ -108,7 +108,7 @@ describe('composite > props', () => {
108
108
  it('correctly retains prop accessors and reactivity when using rest props', () => {
109
109
  component Button(props: Props) {
110
110
  const [children, rest] = trackSplit(props, ['children']);
111
- <button {...@rest}>
111
+ <button {...rest.value}>
112
112
  <@children />
113
113
  </button>
114
114
  <style>
@@ -123,9 +123,9 @@ describe('composite > props', () => {
123
123
 
124
124
  component Toggle(props: { pressed: Tracked<boolean> }) {
125
125
  const [pressed, rest] = trackSplit(props, ['pressed']);
126
- const onClick = () => (@pressed = !@pressed);
127
- <Button {...@rest} class={@pressed ? 'on' : 'off'} {onClick}>{'button 1'}</Button>
128
- <Button class={@pressed ? 'on' : 'off'} {onClick}>{'button 2'}</Button>
126
+ const onClick = () => (pressed.value = !pressed.value);
127
+ <Button {...rest.value} class={pressed.value ? 'on' : 'off'} {onClick}>{'button 1'}</Button>
128
+ <Button class={pressed.value ? 'on' : 'off'} {onClick}>{'button 2'}</Button>
129
129
  }
130
130
 
131
131
  component App() {