ripple 0.3.128 → 0.4.0

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 (192) hide show
  1. package/CHANGELOG.md +267 -0
  2. package/package.json +10 -4
  3. package/src/runtime/element.js +23 -6
  4. package/src/runtime/index-client.js +81 -41
  5. package/src/runtime/index-server.js +1 -0
  6. package/src/runtime/internal/client/blocks.js +173 -91
  7. package/src/runtime/internal/client/component.js +4 -30
  8. package/src/runtime/internal/client/composite.js +12 -13
  9. package/src/runtime/internal/client/constants.js +9 -0
  10. package/src/runtime/internal/client/context.js +12 -19
  11. package/src/runtime/internal/client/css.js +7 -9
  12. package/src/runtime/internal/client/events.js +178 -90
  13. package/src/runtime/internal/client/expression.js +45 -25
  14. package/src/runtime/internal/client/for.js +409 -129
  15. package/src/runtime/internal/client/head.js +10 -5
  16. package/src/runtime/internal/client/html.js +1 -0
  17. package/src/runtime/internal/client/hydration.js +152 -10
  18. package/src/runtime/internal/client/if.js +239 -50
  19. package/src/runtime/internal/client/index.js +4 -12
  20. package/src/runtime/internal/client/operations.js +40 -61
  21. package/src/runtime/internal/client/portal.js +163 -85
  22. package/src/runtime/internal/client/render.js +39 -39
  23. package/src/runtime/internal/client/rpc.js +3 -3
  24. package/src/runtime/internal/client/runtime.js +592 -433
  25. package/src/runtime/internal/client/selector.js +5 -2
  26. package/src/runtime/internal/client/template.js +133 -158
  27. package/src/runtime/internal/client/transport.js +38 -0
  28. package/src/runtime/internal/client/try.js +465 -426
  29. package/src/runtime/internal/client/types.d.ts +56 -23
  30. package/src/runtime/internal/client/utils.js +1 -3
  31. package/src/runtime/internal/server/dynamic.js +20 -21
  32. package/src/runtime/internal/server/index.js +325 -275
  33. package/src/runtime/internal/server/rpc.js +3 -2
  34. package/src/runtime/internal/server/transport.js +16 -0
  35. package/src/runtime/transport.js +21 -0
  36. package/tests/client/__snapshots__/for.test.tsrx.snap +0 -5
  37. package/tests/client/array/array.copy-within.test.tsrx +12 -12
  38. package/tests/client/array/array.derived.test.tsrx +46 -46
  39. package/tests/client/array/array.iteration.test.tsrx +10 -10
  40. package/tests/client/array/array.mutations.test.tsrx +20 -20
  41. package/tests/client/array/array.static.test.tsrx +11 -11
  42. package/tests/client/array/array.to-methods.test.tsrx +6 -6
  43. package/tests/client/async-suspend.test.tsrx +74 -75
  44. package/tests/client/basic/basic.attributes.test.tsrx +86 -83
  45. package/tests/client/basic/basic.collections.test.tsrx +12 -12
  46. package/tests/client/basic/basic.components.test.tsrx +99 -25
  47. package/tests/client/basic/basic.errors.test.tsrx +18 -18
  48. package/tests/client/basic/basic.events.test.tsrx +42 -42
  49. package/tests/client/basic/basic.get-set.test.tsrx +8 -8
  50. package/tests/client/basic/basic.reactivity.test.tsrx +73 -38
  51. package/tests/client/basic/basic.rendering.test.tsrx +25 -25
  52. package/tests/client/basic/basic.utilities.test.tsrx +3 -3
  53. package/tests/client/boundaries.test.tsrx +8 -8
  54. package/tests/client/boxed-locals.test.tsrx +452 -0
  55. package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +6 -6
  56. package/tests/client/compiler/compiler.assignments.test.tsrx +9 -73
  57. package/tests/client/compiler/compiler.attributes.test.tsrx +23 -23
  58. package/tests/client/compiler/compiler.basic.test.tsrx +15 -60
  59. package/tests/client/compiler/compiler.tracked-access.test.tsrx +18 -43
  60. package/tests/client/compiler/compiler.try-in-function.test.tsrx +2 -2
  61. package/tests/client/composite/__snapshots__/composite.render.test.tsrx.snap +0 -1
  62. package/tests/client/composite/composite.dynamic-components.test.tsrx +77 -6
  63. package/tests/client/composite/composite.props.test.tsrx +149 -12
  64. package/tests/client/composite/composite.reactivity.test.tsrx +51 -52
  65. package/tests/client/composite/composite.render.test.tsrx +26 -9
  66. package/tests/client/css/scoped-styles.test.tsrx +8 -8
  67. package/tests/client/date.test.tsrx +42 -42
  68. package/tests/client/derived-release.test.tsrx +370 -0
  69. package/tests/client/dynamic-elements.test.tsrx +45 -45
  70. package/tests/client/events.test.tsrx +97 -71
  71. package/tests/client/for-selector.test.tsrx +14 -14
  72. package/tests/client/for-single-root-items.test.tsrx +118 -3
  73. package/tests/client/for.test.tsrx +332 -31
  74. package/tests/client/head.test.tsrx +19 -19
  75. package/tests/client/html.test.tsrx +11 -9
  76. package/tests/client/if-block.test.tsrx +80 -0
  77. package/tests/client/map.test.tsrx +16 -16
  78. package/tests/client/media-query.test.tsrx +7 -7
  79. package/tests/client/portal.test.tsrx +224 -26
  80. package/tests/client/primitive-text.test.tsrx +50 -0
  81. package/tests/client/prop-kind-switch.test.tsrx +141 -0
  82. package/tests/client/ref.test.tsrx +17 -17
  83. package/tests/client/return.test.tsrx +26 -3
  84. package/tests/client/root-boundary.test.tsrx +42 -0
  85. package/tests/client/scoped-flush.test.tsrx +8 -8
  86. package/tests/client/set.test.tsrx +6 -6
  87. package/tests/client/svg.test.tsrx +11 -11
  88. package/tests/client/switch.test.tsrx +44 -44
  89. package/tests/client/track-async-hydration.test.tsrx +4 -4
  90. package/tests/client/try.test.tsrx +151 -83
  91. package/tests/client/tsx.test.tsrx +43 -40
  92. package/tests/client/url/url.derived.test.tsrx +6 -6
  93. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +8 -8
  94. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +10 -10
  95. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +10 -10
  96. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +18 -18
  97. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +2 -2
  98. package/tests/hydration/basic.test.js +74 -1
  99. package/tests/hydration/build-components.js +22 -1
  100. package/tests/hydration/compiled/client/basic.js +1142 -713
  101. package/tests/hydration/compiled/client/composite.js +151 -100
  102. package/tests/hydration/compiled/client/events.js +184 -171
  103. package/tests/hydration/compiled/client/for.js +1472 -1132
  104. package/tests/hydration/compiled/client/fragment-cursor.js +2341 -0
  105. package/tests/hydration/compiled/client/head.js +254 -201
  106. package/tests/hydration/compiled/client/hmr.js +54 -41
  107. package/tests/hydration/compiled/client/html-in-template.js +54 -39
  108. package/tests/hydration/compiled/client/html.js +1633 -1263
  109. package/tests/hydration/compiled/client/if-children.js +420 -270
  110. package/tests/hydration/compiled/client/if-fragment-controlflow.js +363 -317
  111. package/tests/hydration/compiled/client/if.js +229 -219
  112. package/tests/hydration/compiled/client/mixed-control-flow.js +420 -404
  113. package/tests/hydration/compiled/client/nested-control-flow.js +1326 -1277
  114. package/tests/hydration/compiled/client/portal.js +87 -95
  115. package/tests/hydration/compiled/client/reactivity.js +135 -101
  116. package/tests/hydration/compiled/client/return.js +28 -19
  117. package/tests/hydration/compiled/client/streaming.js +390 -306
  118. package/tests/hydration/compiled/client/switch.js +258 -266
  119. package/tests/hydration/compiled/client/track-async-serialization.js +448 -280
  120. package/tests/hydration/compiled/client/try.js +173 -129
  121. package/tests/hydration/compiled/client/typed-text.js +71 -0
  122. package/tests/hydration/compiled/fixtures/money.js +10 -0
  123. package/tests/hydration/compiled/server/basic.js +123 -6
  124. package/tests/hydration/compiled/server/composite.js +16 -30
  125. package/tests/hydration/compiled/server/events.js +66 -18
  126. package/tests/hydration/compiled/server/for.js +117 -41
  127. package/tests/hydration/compiled/server/fragment-cursor.js +1687 -0
  128. package/tests/hydration/compiled/server/head.js +20 -20
  129. package/tests/hydration/compiled/server/hmr.js +2 -2
  130. package/tests/hydration/compiled/server/html.js +70 -238
  131. package/tests/hydration/compiled/server/if-children.js +107 -15
  132. package/tests/hydration/compiled/server/if.js +11 -15
  133. package/tests/hydration/compiled/server/mixed-control-flow.js +8 -8
  134. package/tests/hydration/compiled/server/portal.js +14 -22
  135. package/tests/hydration/compiled/server/reactivity.js +14 -14
  136. package/tests/hydration/compiled/server/streaming.js +19 -19
  137. package/tests/hydration/compiled/server/switch.js +8 -8
  138. package/tests/hydration/compiled/server/track-async-serialization.js +150 -23
  139. package/tests/hydration/compiled/server/try.js +8 -8
  140. package/tests/hydration/compiled/server/typed-text.js +17 -0
  141. package/tests/hydration/components/basic.tsrx +44 -8
  142. package/tests/hydration/components/composite.tsrx +2 -2
  143. package/tests/hydration/components/events.tsrx +25 -25
  144. package/tests/hydration/components/for.tsrx +115 -67
  145. package/tests/hydration/components/fragment-cursor.tsrx +650 -0
  146. package/tests/hydration/components/head.tsrx +16 -16
  147. package/tests/hydration/components/hmr.tsrx +2 -2
  148. package/tests/hydration/components/html.tsrx +7 -7
  149. package/tests/hydration/components/if-children.tsrx +72 -25
  150. package/tests/hydration/components/if.tsrx +18 -18
  151. package/tests/hydration/components/mixed-control-flow.tsrx +11 -11
  152. package/tests/hydration/components/portal.tsrx +3 -3
  153. package/tests/hydration/components/reactivity.tsrx +16 -16
  154. package/tests/hydration/components/streaming.tsrx +20 -20
  155. package/tests/hydration/components/switch.tsrx +20 -20
  156. package/tests/hydration/components/text-types.ts +4 -0
  157. package/tests/hydration/components/track-async-serialization.tsrx +80 -26
  158. package/tests/hydration/components/try.tsrx +8 -8
  159. package/tests/hydration/components/typed-text.tsrx +22 -0
  160. package/tests/hydration/fixtures/money.js +10 -0
  161. package/tests/hydration/for.test.js +36 -0
  162. package/tests/hydration/fragment-cursor.test.js +111 -0
  163. package/tests/hydration/if-children.test.js +24 -0
  164. package/tests/hydration/streaming.test.js +19 -0
  165. package/tests/hydration/track-async-serialization.test.js +87 -2
  166. package/tests/hydration/tsconfig.text-types.json +10 -0
  167. package/tests/hydration/typed-text.test.js +34 -0
  168. package/tests/server/await.test.tsrx +3 -3
  169. package/tests/server/basic.attributes.test.tsrx +42 -42
  170. package/tests/server/basic.components.test.tsrx +64 -8
  171. package/tests/server/basic.test.tsrx +34 -32
  172. package/tests/server/compiler.test.tsrx +1 -70
  173. package/tests/server/composite.props.test.tsrx +6 -6
  174. package/tests/server/dynamic-elements.test.tsrx +31 -8
  175. package/tests/server/for.test.tsrx +94 -0
  176. package/tests/server/head.test.tsrx +11 -11
  177. package/tests/server/scoped-styles.test.tsrx +2 -2
  178. package/tests/server/streaming-ssr.test.tsrx +48 -43
  179. package/tests/server/track-async-serialization.test.tsrx +204 -21
  180. package/tests/server/try.test.tsrx +48 -48
  181. package/tests/types/transport.ts +40 -0
  182. package/tests/utils/vite-plugin-config.test.js +23 -0
  183. package/types/index.d.ts +48 -7
  184. package/types/server.d.ts +3 -0
  185. package/types/transport.d.ts +15 -0
  186. package/src/runtime/internal/client/switch.js +0 -113
  187. package/src/utils/errors.js +0 -13
  188. package/tests/client/lazy-array.test.tsrx +0 -31
  189. package/tests/client/lazy-destructuring.test.tsrx +0 -438
  190. package/tests/client/tracked-index-access.test.tsrx +0 -113
  191. package/tests/server/lazy-destructuring.test.tsrx +0 -595
  192. package/tests/server/tracked-index-access.test.tsrx +0 -76
@@ -1,438 +0,0 @@
1
- import type { Tracked } from 'ripple';
2
- import { flushSync, track } from 'ripple';
3
-
4
- describe('lazy destructuring', () => {
5
- it('supports tracked value getter and setter', () => {
6
- function Test() @{
7
- let count = track(1);
8
- let doubled = track(() => count.value * 2);
9
- <>
10
- <div>{`${count.value}-${doubled.value}`}</div>
11
- <button
12
- onClick={() => {
13
- count.value = 5;
14
- }}
15
- >{'set'}</button>
16
- </>
17
- }
18
-
19
- render(Test);
20
- expect(container.querySelector('div')!.textContent).toBe('1-2');
21
- container.querySelector('button')!.click();
22
- flushSync();
23
- expect(container.querySelector('div')!.textContent).toBe('5-10');
24
- });
25
-
26
- it('lazily accesses object properties with const', () => {
27
- function Inner(&{ a, b }: { a: number; b: string }) @{
28
- <pre>{`${a}-${b}`}</pre>
29
- }
30
-
31
- function Test() @{
32
- let &[a] = track(1);
33
- let &[b] = track('hello');
34
- <>
35
- <Inner {a} {b} />
36
- <button
37
- onClick={() => {
38
- a = 2;
39
- b = 'world';
40
- }}
41
- >{'update'}</button>
42
- </>
43
- }
44
-
45
- render(Test);
46
- expect(container.querySelector('pre')!.textContent).toBe('1-hello');
47
- container.querySelector('button')!.click();
48
- flushSync();
49
- expect(container.querySelector('pre')!.textContent).toBe('2-world');
50
- });
51
-
52
- it('lazily accesses array elements with const', () => {
53
- function Inner(&{ first, second }: { first: number; second: number }) @{
54
- <pre>{`${first}-${second}`}</pre>
55
- }
56
-
57
- function Test() @{
58
- let &[first] = track(10);
59
- let &[second] = track(20);
60
- <>
61
- <Inner {first} {second} />
62
- <button
63
- onClick={() => {
64
- first = 30;
65
- second = 40;
66
- }}
67
- >{'update'}</button>
68
- </>
69
- }
70
-
71
- render(Test);
72
- expect(container.querySelector('pre')!.textContent).toBe('10-20');
73
- container.querySelector('button')!.click();
74
- flushSync();
75
- expect(container.querySelector('pre')!.textContent).toBe('30-40');
76
- });
77
-
78
- it('preserves numeric member access on lazy array value bindings', () => {
79
- function Child({ pair: &[first] }: { pair: [{ 0: string }] }) @{
80
- <pre>{first[0]}</pre>
81
- }
82
-
83
- function Test() @{
84
- <Child pair={[{ 0: 'x' }]} />
85
- }
86
-
87
- render(Test);
88
- expect(container.querySelector('pre')!.textContent).toBe('x');
89
- });
90
-
91
- it('supports default values in lazy object destructuring', () => {
92
- function Test() @{
93
- const obj: { a: number; b?: number } = { a: 5 };
94
- const &{ a, b = 99 } = obj;
95
- <pre>{`${a}-${b}`}</pre>
96
- }
97
-
98
- render(Test);
99
- expect(container.querySelector('pre')!.textContent).toBe('5-99');
100
- });
101
-
102
- it('supports lazy destructuring in component params', () => {
103
- function Inner(&{ name, age }: { name: string; age: number }) @{
104
- <pre>{`${name}-${age}`}</pre>
105
- }
106
-
107
- function Test() @{
108
- <Inner name="Alice" age={30} />
109
- }
110
-
111
- render(Test);
112
- expect(container.querySelector('pre')!.textContent).toBe('Alice-30');
113
- });
114
-
115
- it('supports lazy destructuring in component params with reactivity', () => {
116
- function Inner(&{ count }: { count: number }) @{
117
- <pre>{count}</pre>
118
- }
119
-
120
- function Test() @{
121
- let &[count] = track(0);
122
- <>
123
- <Inner {count} />
124
- <button
125
- onClick={() => {
126
- count++;
127
- }}
128
- >{'increment'}</button>
129
- </>
130
- }
131
-
132
- render(Test);
133
- expect(container.querySelector('pre')!.textContent).toBe('0');
134
- container.querySelector('button')!.click();
135
- flushSync();
136
- expect(container.querySelector('pre')!.textContent).toBe('1');
137
- });
138
-
139
- it('supports nested lazy destructuring in non-lazy component params', () => {
140
- function Inner({ something: &[first, second] }: { something: Tracked<number> }) @{
141
- first = second.value + 1;
142
- <pre>{`${first}-${second.value}`}</pre>
143
- }
144
-
145
- function Test() @{
146
- <Inner something={track(1)} />
147
- }
148
-
149
- render(Test);
150
- expect(container.querySelector('pre')!.textContent).toBe('2-2');
151
- });
152
-
153
- it(
154
- 'preserves lazy getter/setter behavior for nested rest destructuring in non-lazy component params',
155
- () => {
156
- function Inner({
157
- values: [head, ...&{ length: rest_length, 0: first_rest }],
158
- }: {
159
- values: [number, Tracked<number>, Tracked<number>];
160
- }) @{
161
- const before = `${first_rest?.value ?? 'nil'}-${rest_length}`;
162
- rest_length = 0;
163
- <pre>{`${head}-${before}-${first_rest?.value ?? 'nil'}-${rest_length}`}</pre>
164
- }
165
-
166
- function Test() @{
167
- <Inner values={[10, track(20), track(30)]} />
168
- }
169
-
170
- render(Test);
171
- expect(container.querySelector('pre')!.textContent).toBe('10-20-2-nil-0');
172
- },
173
- );
174
-
175
- it('supports lazy destructuring in function params', () => {
176
- function Test() @{
177
- function getInfo(&{ x, y }: { x: number; y: number }) {
178
- return x + y;
179
- }
180
- const result = getInfo({ x: 3, y: 7 });
181
- <pre>{result}</pre>
182
- }
183
-
184
- render(Test);
185
- expect(container.querySelector('pre')!.textContent).toBe('10');
186
- });
187
-
188
- it('supports nested lazy destructuring in non-lazy function params', () => {
189
- function Test() @{
190
- const something = track(1);
191
- function getInfo({ something: &[first, second] }: { something: Tracked<number> }) {
192
- first = second.value + 1;
193
- return `${first}-${second.value}`;
194
- }
195
- const result = getInfo({ something });
196
- <pre>{result}</pre>
197
- }
198
-
199
- render(Test);
200
- expect(container.querySelector('pre')!.textContent).toBe('2-2');
201
- });
202
-
203
- it(
204
- 'preserves lazy getter/setter behavior for nested rest destructuring in non-lazy function params',
205
- () => {
206
- function Test() @{
207
- function summarize({
208
- values: [head, ...&{ length: rest_length, 0: first_rest }],
209
- }: {
210
- values: [number, Tracked<number>, Tracked<number>];
211
- }) {
212
- const before = `${first_rest?.value ?? 'nil'}-${rest_length}`;
213
- rest_length = 0;
214
- return `${head}-${before}-${first_rest?.value ?? 'nil'}-${rest_length}`;
215
- }
216
- const result = summarize({ values: [5, track(6), track(7)] });
217
- <pre>{result}</pre>
218
- }
219
-
220
- render(Test);
221
- expect(container.querySelector('pre')!.textContent).toBe('5-6-2-nil-0');
222
- },
223
- );
224
-
225
- it('supports let lazy destructuring with assignment writeback', () => {
226
- function Test() @{
227
- const obj = { a: 1, b: 2 };
228
- let &{ a, b } = obj;
229
- a = 10;
230
- b = 20;
231
- <pre>{`${obj.a}-${obj.b}`}</pre>
232
- }
233
-
234
- render(Test);
235
- expect(container.querySelector('pre')!.textContent).toBe('10-20');
236
- });
237
-
238
- it('supports compound assignment operators on lazy bindings', () => {
239
- function Test() @{
240
- const obj = { a: 5, b: 10 };
241
- let &{ a, b } = obj;
242
- a += 3;
243
- b *= 2;
244
- <pre>{`${obj.a}-${obj.b}`}</pre>
245
- }
246
-
247
- render(Test);
248
- expect(container.querySelector('pre')!.textContent).toBe('8-20');
249
- });
250
-
251
- it('supports update expressions on lazy bindings', () => {
252
- function Test() @{
253
- const obj = { count: 0 };
254
- let &{ count } = obj;
255
- count++;
256
- count++;
257
- count--;
258
- <pre>{obj.count}</pre>
259
- }
260
-
261
- render(Test);
262
- expect(container.querySelector('pre')!.textContent).toBe('1');
263
- });
264
-
265
- it('supports function params with lazy destructuring and default values', () => {
266
- function Test() @{
267
- function calc(&{ x, y = 100 }: { x: number; y?: number }) {
268
- return x + y;
269
- }
270
- const a = calc({ x: 5, y: 10 });
271
- const b = calc({ x: 5 });
272
- <pre>{`${a}-${b}`}</pre>
273
- }
274
-
275
- render(Test);
276
- expect(container.querySelector('pre')!.textContent).toBe('15-105');
277
- });
278
-
279
- it('supports lazy destructuring with default value writeback', () => {
280
- function Test() @{
281
- const obj: { a: number; b?: number } = { a: 1 };
282
- let &{ a, b = 50 } = obj;
283
- b = 99;
284
- <pre>{`${a}-${obj.b}`}</pre>
285
- }
286
-
287
- render(Test);
288
- expect(container.querySelector('pre')!.textContent).toBe('1-99');
289
- });
290
-
291
- it('supports rest destructuring from iterable array-like tracked values', () => {
292
- function Test() @{
293
- let &[value, ...rest] = track(0);
294
- <pre>{`${value}-${rest.length}-${(rest[0] as Tracked<number>).value === value}`}</pre>
295
- }
296
-
297
- render(Test);
298
- expect(container.querySelector('pre')!.textContent).toBe('0-1-true');
299
- });
300
-
301
- it('supports rest destructuring from length-only array-like sources', () => {
302
- function Test() @{
303
- const source = { 0: 'x', 1: 'y', 2: 'z', length: 3 };
304
- const &[first, ...rest] = source;
305
- <pre>{`${first}-${rest.join(',')}`}</pre>
306
- }
307
-
308
- render(Test);
309
- expect(container.querySelector('pre')!.textContent).toBe('x-y,z');
310
- });
311
-
312
- it('supports rest destructuring from iterable sources', () => {
313
- function Test() @{
314
- const source = {
315
- *[Symbol.iterator]() {
316
- yield 'x';
317
- yield 'y';
318
- yield 'z';
319
- },
320
- };
321
- const &[first, ...rest] = source;
322
- <pre>{`${first}-${rest.join(',')}`}</pre>
323
- }
324
-
325
- render(Test);
326
- expect(container.querySelector('pre')!.textContent).toBe('x-y,z');
327
- });
328
-
329
- it('supports update expressions on lazy bindings with default values', () => {
330
- function Test() @{
331
- const obj: { count?: number } = {};
332
- let &{ count = 0 } = obj;
333
- count++;
334
- count++;
335
- <pre>{obj.count}</pre>
336
- }
337
-
338
- render(Test);
339
- expect(container.querySelector('pre')!.textContent).toBe('2');
340
- });
341
-
342
- it('supports member access on lazy destructured objects', () => {
343
- function Test() @{
344
- const obj = { user: { name: 'Alice', age: 30 } };
345
- const &{ user } = obj;
346
- <pre>{`${user.name}-${user.age}`}</pre>
347
- }
348
-
349
- render(Test);
350
- expect(container.querySelector('pre')!.textContent).toBe('Alice-30');
351
- });
352
-
353
- it('supports standalone lazy array destructuring with track()', () => {
354
- function Test() @{
355
- let count: number;
356
- &[count] = track(0);
357
- <>
358
- <div>{count}</div>
359
- <button
360
- onClick={() => {
361
- count++;
362
- }}
363
- >{'inc'}</button>
364
- </>
365
- }
366
-
367
- render(Test);
368
- expect(container.querySelector('div')!.textContent).toBe('0');
369
- container.querySelector('button')!.click();
370
- flushSync();
371
- expect(container.querySelector('div')!.textContent).toBe('1');
372
- });
373
-
374
- it('supports standalone lazy array destructuring with second element', () => {
375
- function Test() @{
376
- let value;
377
- let tracked;
378
- &[value, tracked] = track(42);
379
- <>
380
- <div>{value}</div>
381
- <button
382
- onClick={() => {
383
- value = 100;
384
- }}
385
- >{'set'}</button>
386
- </>
387
- }
388
-
389
- render(Test);
390
- expect(container.querySelector('div')!.textContent).toBe('42');
391
- container.querySelector('button')!.click();
392
- flushSync();
393
- expect(container.querySelector('div')!.textContent).toBe('100');
394
- });
395
-
396
- it('supports direct value access on tracked values', () => {
397
- function Test() @{
398
- let tracked = track(0);
399
- ++tracked.value;
400
- tracked.value++;
401
- tracked.value = tracked.value + 1;
402
- let value = tracked.value;
403
- let ref = tracked;
404
- <pre>{`${value}-${ref === tracked}`}</pre>
405
- }
406
-
407
- render(Test);
408
- expect(container.querySelector('pre')!.textContent).toBe('3-true');
409
- });
410
-
411
- it('supports lazy destructured tracked ref value access', () => {
412
- function Child({ pair: &[value, tracked_ref] }: { pair: Tracked<number> }) @{
413
- ++tracked_ref.value;
414
- tracked_ref.value++;
415
- <pre>{`${value}-${tracked_ref.value}`}</pre>
416
- }
417
-
418
- function Test() @{
419
- let tracked = track(0);
420
- <Child pair={tracked} />
421
- }
422
-
423
- render(Test);
424
- expect(container.querySelector('pre')!.textContent).toBe('2-2');
425
- });
426
-
427
- it('supports standalone lazy object destructuring', () => {
428
- function Test() @{
429
- let a;
430
- let b;
431
- &{ a, b } = { a: 10, b: 20 };
432
- <pre>{`${a}-${b}`}</pre>
433
- }
434
-
435
- render(Test);
436
- expect(container.querySelector('pre')!.textContent).toBe('10-20');
437
- });
438
- });
@@ -1,113 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { track } from 'ripple';
3
- import {
4
- lazy_array_get,
5
- lazy_array_set,
6
- lazy_array_update,
7
- } from '../../src/runtime/internal/client/runtime.js';
8
-
9
- const value_message = /Use \.value or &\[\] lazy destructuring/;
10
- const reference_message = /Use the tracked value directly instead/;
11
- const value_index = Number(0);
12
- const reference_index = Number(1);
13
-
14
- describe('client tracked numeric access', () => {
15
- it('throws when tracked values are accessed through numeric properties', () => {
16
- let value: any;
17
-
18
- function Test() @{
19
- value = track(0);
20
- <div />
21
- }
22
-
23
- render(Test);
24
-
25
- expect(() => value[value_index]).toThrow(value_message);
26
- expect(() => {
27
- value[value_index] = 1;
28
- }).toThrow(value_message);
29
- expect(() => value[reference_index]).toThrow(reference_message);
30
- });
31
-
32
- it('throws when derived values are accessed through numeric properties', () => {
33
- let value: any;
34
-
35
- function Test() @{
36
- value = track(() => 1);
37
- <div />
38
- }
39
-
40
- render(Test);
41
-
42
- expect(() => value[value_index]).toThrow(value_message);
43
- expect(() => {
44
- value[value_index] = 2;
45
- }).toThrow(value_message);
46
- expect(() => value[reference_index]).toThrow(reference_message);
47
- });
48
-
49
- it('sets tracked lazy index 0 and rejects tracked lazy index 1', () => {
50
- let value: any;
51
- let next: any;
52
-
53
- function Test() @{
54
- value = track(0);
55
- next = track(1);
56
- <div />
57
- }
58
-
59
- render(Test);
60
-
61
- lazy_array_set(value, 2, 0);
62
- expect(value.value).toBe(2);
63
- expect(() => {
64
- lazy_array_set(value, next, 1);
65
- }).toThrow(reference_message);
66
- expect(() => {
67
- lazy_array_update(value, 1);
68
- }).toThrow(reference_message);
69
- });
70
-
71
- it('returns undefined for tracked lazy indexes past the tuple length', () => {
72
- let value: any;
73
- let derived: any;
74
-
75
- function Test() @{
76
- value = track(0);
77
- derived = track(() => value.value + 1);
78
- <div />
79
- }
80
-
81
- render(Test);
82
-
83
- expect(lazy_array_get(value, 0)).toBe(0);
84
- expect(lazy_array_get(value, 1)).toBe(value);
85
- expect(lazy_array_get(value, 2)).toBeUndefined();
86
- expect(lazy_array_get(derived, 0)).toBe(1);
87
- expect(lazy_array_get(derived, 1)).toBe(derived);
88
- expect(lazy_array_get(derived, 2)).toBeUndefined();
89
- });
90
-
91
- it('ignores tracked lazy writes past the tuple length', () => {
92
- let value: any;
93
- let derived: any;
94
-
95
- function Test() @{
96
- value = track(0);
97
- derived = track(() => value.value + 1);
98
- <div />
99
- }
100
-
101
- render(Test);
102
-
103
- lazy_array_set(value, 10, 2);
104
- lazy_array_update(value, 2);
105
- lazy_array_set(derived, 20, 2);
106
- lazy_array_update(derived, 2);
107
-
108
- expect(lazy_array_get(value, 2)).toBeUndefined();
109
- expect(lazy_array_get(derived, 2)).toBeUndefined();
110
- expect(Object.hasOwn(value, 2)).toBe(false);
111
- expect(Object.hasOwn(derived, 2)).toBe(false);
112
- });
113
- });