ripple 0.3.128 → 0.4.1

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 (197) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/package.json +11 -4
  3. package/src/jsx-runtime.d.ts +12 -2
  4. package/src/runtime/element.js +23 -6
  5. package/src/runtime/index-client.js +81 -41
  6. package/src/runtime/index-server.js +1 -0
  7. package/src/runtime/internal/client/blocks.js +173 -91
  8. package/src/runtime/internal/client/component.js +4 -30
  9. package/src/runtime/internal/client/composite.js +12 -13
  10. package/src/runtime/internal/client/constants.js +9 -0
  11. package/src/runtime/internal/client/context.js +12 -19
  12. package/src/runtime/internal/client/css.js +7 -9
  13. package/src/runtime/internal/client/events.js +178 -90
  14. package/src/runtime/internal/client/expression.js +45 -25
  15. package/src/runtime/internal/client/for.js +409 -129
  16. package/src/runtime/internal/client/head.js +10 -5
  17. package/src/runtime/internal/client/html.js +1 -0
  18. package/src/runtime/internal/client/hydration.js +152 -10
  19. package/src/runtime/internal/client/if.js +239 -50
  20. package/src/runtime/internal/client/index.js +4 -12
  21. package/src/runtime/internal/client/operations.js +40 -61
  22. package/src/runtime/internal/client/portal.js +163 -85
  23. package/src/runtime/internal/client/render.js +44 -43
  24. package/src/runtime/internal/client/rpc.js +3 -3
  25. package/src/runtime/internal/client/runtime.js +592 -433
  26. package/src/runtime/internal/client/selector.js +5 -2
  27. package/src/runtime/internal/client/template.js +133 -158
  28. package/src/runtime/internal/client/transport.js +38 -0
  29. package/src/runtime/internal/client/try.js +465 -426
  30. package/src/runtime/internal/client/types.d.ts +56 -23
  31. package/src/runtime/internal/client/utils.js +1 -3
  32. package/src/runtime/internal/server/dynamic.js +20 -21
  33. package/src/runtime/internal/server/index.js +329 -277
  34. package/src/runtime/internal/server/rpc.js +3 -2
  35. package/src/runtime/internal/server/transport.js +16 -0
  36. package/src/runtime/transport.js +21 -0
  37. package/tests/client/__snapshots__/for.test.tsrx.snap +0 -5
  38. package/tests/client/array/array.copy-within.test.tsrx +12 -12
  39. package/tests/client/array/array.derived.test.tsrx +46 -46
  40. package/tests/client/array/array.iteration.test.tsrx +10 -10
  41. package/tests/client/array/array.mutations.test.tsrx +20 -20
  42. package/tests/client/array/array.static.test.tsrx +11 -11
  43. package/tests/client/array/array.to-methods.test.tsrx +6 -6
  44. package/tests/client/async-suspend.test.tsrx +74 -75
  45. package/tests/client/basic/basic.attributes.test.tsrx +123 -83
  46. package/tests/client/basic/basic.collections.test.tsrx +12 -12
  47. package/tests/client/basic/basic.components.test.tsrx +99 -25
  48. package/tests/client/basic/basic.errors.test.tsrx +18 -18
  49. package/tests/client/basic/basic.events.test.tsrx +42 -42
  50. package/tests/client/basic/basic.get-set.test.tsrx +8 -8
  51. package/tests/client/basic/basic.reactivity.test.tsrx +73 -38
  52. package/tests/client/basic/basic.rendering.test.tsrx +25 -25
  53. package/tests/client/basic/basic.utilities.test.tsrx +3 -3
  54. package/tests/client/boundaries.test.tsrx +8 -8
  55. package/tests/client/boxed-locals.test.tsrx +452 -0
  56. package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +6 -6
  57. package/tests/client/compiler/compiler.assignments.test.tsrx +9 -73
  58. package/tests/client/compiler/compiler.attributes.test.tsrx +23 -23
  59. package/tests/client/compiler/compiler.basic.test.tsrx +15 -60
  60. package/tests/client/compiler/compiler.tracked-access.test.tsrx +18 -43
  61. package/tests/client/compiler/compiler.try-in-function.test.tsrx +2 -2
  62. package/tests/client/composite/__snapshots__/composite.render.test.tsrx.snap +0 -1
  63. package/tests/client/composite/composite.dynamic-components.test.tsrx +77 -6
  64. package/tests/client/composite/composite.props.test.tsrx +149 -12
  65. package/tests/client/composite/composite.reactivity.test.tsrx +51 -52
  66. package/tests/client/composite/composite.render.test.tsrx +26 -9
  67. package/tests/client/css/scoped-styles.test.tsrx +8 -8
  68. package/tests/client/date.test.tsrx +42 -42
  69. package/tests/client/derived-release.test.tsrx +370 -0
  70. package/tests/client/dynamic-elements.test.tsrx +45 -45
  71. package/tests/client/events.test.tsrx +97 -71
  72. package/tests/client/for-selector.test.tsrx +14 -14
  73. package/tests/client/for-single-root-items.test.tsrx +118 -3
  74. package/tests/client/for.test.tsrx +332 -31
  75. package/tests/client/head.test.tsrx +19 -19
  76. package/tests/client/html.test.tsrx +11 -9
  77. package/tests/client/if-block.test.tsrx +80 -0
  78. package/tests/client/map.test.tsrx +16 -16
  79. package/tests/client/media-query.test.tsrx +7 -7
  80. package/tests/client/portal.test.tsrx +224 -26
  81. package/tests/client/primitive-text.test.tsrx +50 -0
  82. package/tests/client/prop-kind-switch.test.tsrx +141 -0
  83. package/tests/client/ref.test.tsrx +17 -17
  84. package/tests/client/return.test.tsrx +26 -3
  85. package/tests/client/root-boundary.test.tsrx +42 -0
  86. package/tests/client/scoped-flush.test.tsrx +8 -8
  87. package/tests/client/set.test.tsrx +6 -6
  88. package/tests/client/svg.test.tsrx +11 -11
  89. package/tests/client/switch.test.tsrx +44 -44
  90. package/tests/client/track-async-hydration.test.tsrx +4 -4
  91. package/tests/client/try.test.tsrx +151 -83
  92. package/tests/client/tsx.test.tsrx +43 -40
  93. package/tests/client/url/url.derived.test.tsrx +6 -6
  94. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +8 -8
  95. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +10 -10
  96. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +10 -10
  97. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +18 -18
  98. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +2 -2
  99. package/tests/hydration/basic.test.js +74 -1
  100. package/tests/hydration/build-components.js +22 -1
  101. package/tests/hydration/compiled/client/basic.js +1142 -713
  102. package/tests/hydration/compiled/client/composite.js +151 -100
  103. package/tests/hydration/compiled/client/events.js +184 -171
  104. package/tests/hydration/compiled/client/for.js +1472 -1132
  105. package/tests/hydration/compiled/client/fragment-cursor.js +2341 -0
  106. package/tests/hydration/compiled/client/head.js +254 -201
  107. package/tests/hydration/compiled/client/hmr.js +54 -41
  108. package/tests/hydration/compiled/client/html-in-template.js +54 -39
  109. package/tests/hydration/compiled/client/html.js +1633 -1263
  110. package/tests/hydration/compiled/client/if-children.js +420 -270
  111. package/tests/hydration/compiled/client/if-fragment-controlflow.js +363 -317
  112. package/tests/hydration/compiled/client/if.js +229 -219
  113. package/tests/hydration/compiled/client/mixed-control-flow.js +420 -404
  114. package/tests/hydration/compiled/client/nested-control-flow.js +1326 -1277
  115. package/tests/hydration/compiled/client/portal.js +87 -95
  116. package/tests/hydration/compiled/client/reactivity.js +135 -101
  117. package/tests/hydration/compiled/client/return.js +28 -19
  118. package/tests/hydration/compiled/client/streaming.js +390 -306
  119. package/tests/hydration/compiled/client/switch.js +258 -266
  120. package/tests/hydration/compiled/client/track-async-serialization.js +448 -280
  121. package/tests/hydration/compiled/client/try.js +173 -129
  122. package/tests/hydration/compiled/client/typed-text.js +71 -0
  123. package/tests/hydration/compiled/fixtures/money.js +10 -0
  124. package/tests/hydration/compiled/server/basic.js +123 -6
  125. package/tests/hydration/compiled/server/composite.js +16 -30
  126. package/tests/hydration/compiled/server/events.js +66 -18
  127. package/tests/hydration/compiled/server/for.js +117 -41
  128. package/tests/hydration/compiled/server/fragment-cursor.js +1687 -0
  129. package/tests/hydration/compiled/server/head.js +20 -20
  130. package/tests/hydration/compiled/server/hmr.js +2 -2
  131. package/tests/hydration/compiled/server/html.js +70 -238
  132. package/tests/hydration/compiled/server/if-children.js +107 -15
  133. package/tests/hydration/compiled/server/if.js +11 -15
  134. package/tests/hydration/compiled/server/mixed-control-flow.js +8 -8
  135. package/tests/hydration/compiled/server/portal.js +14 -22
  136. package/tests/hydration/compiled/server/reactivity.js +14 -14
  137. package/tests/hydration/compiled/server/streaming.js +19 -19
  138. package/tests/hydration/compiled/server/switch.js +8 -8
  139. package/tests/hydration/compiled/server/track-async-serialization.js +150 -23
  140. package/tests/hydration/compiled/server/try.js +8 -8
  141. package/tests/hydration/compiled/server/typed-text.js +17 -0
  142. package/tests/hydration/components/basic.tsrx +44 -8
  143. package/tests/hydration/components/composite.tsrx +2 -2
  144. package/tests/hydration/components/events.tsrx +25 -25
  145. package/tests/hydration/components/for.tsrx +115 -67
  146. package/tests/hydration/components/fragment-cursor.tsrx +650 -0
  147. package/tests/hydration/components/head.tsrx +16 -16
  148. package/tests/hydration/components/hmr.tsrx +2 -2
  149. package/tests/hydration/components/html.tsrx +7 -7
  150. package/tests/hydration/components/if-children.tsrx +72 -25
  151. package/tests/hydration/components/if.tsrx +18 -18
  152. package/tests/hydration/components/mixed-control-flow.tsrx +11 -11
  153. package/tests/hydration/components/portal.tsrx +3 -3
  154. package/tests/hydration/components/reactivity.tsrx +16 -16
  155. package/tests/hydration/components/streaming.tsrx +20 -20
  156. package/tests/hydration/components/switch.tsrx +20 -20
  157. package/tests/hydration/components/text-types.ts +4 -0
  158. package/tests/hydration/components/track-async-serialization.tsrx +80 -26
  159. package/tests/hydration/components/try.tsrx +8 -8
  160. package/tests/hydration/components/typed-text.tsrx +22 -0
  161. package/tests/hydration/fixtures/money.js +10 -0
  162. package/tests/hydration/for.test.js +36 -0
  163. package/tests/hydration/fragment-cursor.test.js +111 -0
  164. package/tests/hydration/if-children.test.js +24 -0
  165. package/tests/hydration/streaming.test.js +19 -0
  166. package/tests/hydration/track-async-serialization.test.js +87 -2
  167. package/tests/hydration/tsconfig.text-types.json +10 -0
  168. package/tests/hydration/typed-text.test.js +34 -0
  169. package/tests/server/await.test.tsrx +3 -3
  170. package/tests/server/basic.attributes.test.tsrx +70 -42
  171. package/tests/server/basic.components.test.tsrx +64 -8
  172. package/tests/server/basic.test.tsrx +34 -32
  173. package/tests/server/compiler.test.tsrx +1 -70
  174. package/tests/server/composite.props.test.tsrx +6 -6
  175. package/tests/server/dynamic-elements.test.tsrx +31 -8
  176. package/tests/server/for.test.tsrx +94 -0
  177. package/tests/server/head.test.tsrx +11 -11
  178. package/tests/server/scoped-styles.test.tsrx +2 -2
  179. package/tests/server/streaming-ssr.test.tsrx +48 -43
  180. package/tests/server/track-async-serialization.test.tsrx +204 -21
  181. package/tests/server/try.test.tsrx +48 -48
  182. package/tests/types/transport.ts +40 -0
  183. package/tests/utils/jsx-runtime-types.test.js +67 -2
  184. package/tests/utils/tracked-types.test.js +117 -0
  185. package/tests/utils/vite-plugin-config.test.js +23 -0
  186. package/types/index.d.ts +49 -9
  187. package/types/server.d.ts +3 -0
  188. package/types/transport.d.ts +15 -0
  189. package/src/runtime/internal/client/switch.js +0 -113
  190. package/src/utils/errors.js +0 -13
  191. package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +0 -12
  192. package/tests/client/compiler/__snapshots__/compiler.typescript.test.rsrx.snap +0 -46
  193. package/tests/client/lazy-array.test.tsrx +0 -31
  194. package/tests/client/lazy-destructuring.test.tsrx +0 -438
  195. package/tests/client/tracked-index-access.test.tsrx +0 -113
  196. package/tests/server/lazy-destructuring.test.tsrx +0 -595
  197. 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
- });