ripple 0.3.7 → 0.3.9

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 (119) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +2 -2
  3. package/src/compiler/phases/1-parse/index.js +48 -349
  4. package/src/compiler/phases/2-analyze/index.js +343 -52
  5. package/src/compiler/phases/3-transform/client/index.js +28 -160
  6. package/src/compiler/phases/3-transform/segments.js +0 -7
  7. package/src/compiler/phases/3-transform/server/index.js +31 -154
  8. package/src/compiler/types/acorn.d.ts +1 -1
  9. package/src/compiler/types/estree.d.ts +1 -1
  10. package/src/compiler/types/import.d.ts +0 -2
  11. package/src/compiler/types/index.d.ts +5 -17
  12. package/src/compiler/types/parse.d.ts +1 -17
  13. package/src/compiler/utils.js +53 -20
  14. package/src/runtime/index-client.js +2 -13
  15. package/src/runtime/index-server.js +2 -2
  16. package/src/runtime/internal/client/bindings.js +3 -1
  17. package/src/runtime/internal/client/composite.js +3 -2
  18. package/src/runtime/internal/client/events.js +1 -1
  19. package/src/runtime/internal/client/head.js +3 -4
  20. package/src/runtime/internal/client/index.js +0 -1
  21. package/src/runtime/internal/client/runtime.js +0 -52
  22. package/src/runtime/internal/server/index.js +31 -55
  23. package/tests/client/array/array.copy-within.test.ripple +12 -12
  24. package/tests/client/array/array.derived.test.ripple +46 -46
  25. package/tests/client/array/array.iteration.test.ripple +10 -10
  26. package/tests/client/array/array.mutations.test.ripple +20 -20
  27. package/tests/client/array/array.to-methods.test.ripple +6 -6
  28. package/tests/client/async-suspend.test.ripple +5 -5
  29. package/tests/client/basic/basic.attributes.test.ripple +81 -81
  30. package/tests/client/basic/basic.collections.test.ripple +9 -9
  31. package/tests/client/basic/basic.components.test.ripple +28 -28
  32. package/tests/client/basic/basic.errors.test.ripple +46 -18
  33. package/tests/client/basic/basic.events.test.ripple +37 -37
  34. package/tests/client/basic/basic.get-set.test.ripple +6 -6
  35. package/tests/client/basic/basic.reactivity.test.ripple +58 -203
  36. package/tests/client/basic/basic.rendering.test.ripple +19 -19
  37. package/tests/client/basic/basic.utilities.test.ripple +3 -3
  38. package/tests/client/boundaries.test.ripple +12 -12
  39. package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
  40. package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
  41. package/tests/client/compiler/compiler.basic.test.ripple +46 -27
  42. package/tests/client/compiler/compiler.tracked-access.test.ripple +2 -2
  43. package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
  44. package/tests/client/composite/composite.props.test.ripple +14 -16
  45. package/tests/client/composite/composite.reactivity.test.ripple +69 -70
  46. package/tests/client/composite/composite.render.test.ripple +3 -3
  47. package/tests/client/computed-properties.test.ripple +4 -4
  48. package/tests/client/date.test.ripple +42 -42
  49. package/tests/client/dynamic-elements.test.ripple +44 -45
  50. package/tests/client/events.test.ripple +70 -70
  51. package/tests/client/for.test.ripple +25 -25
  52. package/tests/client/head.test.ripple +19 -19
  53. package/tests/client/html.test.ripple +3 -3
  54. package/tests/client/input-value.test.ripple +84 -84
  55. package/tests/client/lazy-destructuring.test.ripple +138 -26
  56. package/tests/client/map.test.ripple +16 -16
  57. package/tests/client/media-query.test.ripple +7 -7
  58. package/tests/client/portal.test.ripple +11 -11
  59. package/tests/client/ref.test.ripple +4 -4
  60. package/tests/client/return.test.ripple +52 -52
  61. package/tests/client/set.test.ripple +6 -6
  62. package/tests/client/svg.test.ripple +5 -5
  63. package/tests/client/switch.test.ripple +44 -44
  64. package/tests/client/try.test.ripple +5 -5
  65. package/tests/client/url/url.derived.test.ripple +6 -6
  66. package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
  67. package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
  68. package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
  69. package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
  70. package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
  71. package/tests/hydration/compiled/client/events.js +25 -25
  72. package/tests/hydration/compiled/client/for.js +70 -66
  73. package/tests/hydration/compiled/client/head.js +25 -25
  74. package/tests/hydration/compiled/client/hmr.js +2 -2
  75. package/tests/hydration/compiled/client/html.js +3 -3
  76. package/tests/hydration/compiled/client/if-children.js +24 -24
  77. package/tests/hydration/compiled/client/if.js +18 -18
  78. package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
  79. package/tests/hydration/compiled/client/portal.js +3 -3
  80. package/tests/hydration/compiled/client/reactivity.js +16 -16
  81. package/tests/hydration/compiled/client/return.js +40 -40
  82. package/tests/hydration/compiled/client/switch.js +12 -12
  83. package/tests/hydration/compiled/server/events.js +19 -19
  84. package/tests/hydration/compiled/server/for.js +41 -41
  85. package/tests/hydration/compiled/server/head.js +26 -26
  86. package/tests/hydration/compiled/server/hmr.js +2 -2
  87. package/tests/hydration/compiled/server/html.js +2 -2
  88. package/tests/hydration/compiled/server/if-children.js +16 -16
  89. package/tests/hydration/compiled/server/if.js +11 -11
  90. package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
  91. package/tests/hydration/compiled/server/portal.js +2 -2
  92. package/tests/hydration/compiled/server/reactivity.js +16 -16
  93. package/tests/hydration/compiled/server/return.js +25 -25
  94. package/tests/hydration/compiled/server/switch.js +8 -8
  95. package/tests/hydration/components/events.ripple +25 -25
  96. package/tests/hydration/components/for.ripple +66 -66
  97. package/tests/hydration/components/head.ripple +16 -16
  98. package/tests/hydration/components/hmr.ripple +2 -2
  99. package/tests/hydration/components/html.ripple +3 -3
  100. package/tests/hydration/components/if-children.ripple +24 -24
  101. package/tests/hydration/components/if.ripple +18 -18
  102. package/tests/hydration/components/mixed-control-flow.ripple +9 -9
  103. package/tests/hydration/components/portal.ripple +3 -3
  104. package/tests/hydration/components/reactivity.ripple +16 -16
  105. package/tests/hydration/components/return.ripple +40 -40
  106. package/tests/hydration/components/switch.ripple +20 -20
  107. package/tests/server/await.test.ripple +3 -3
  108. package/tests/server/basic.attributes.test.ripple +34 -34
  109. package/tests/server/basic.components.test.ripple +10 -10
  110. package/tests/server/basic.test.ripple +38 -40
  111. package/tests/server/compiler.test.ripple +22 -0
  112. package/tests/server/composite.props.test.ripple +12 -14
  113. package/tests/server/dynamic-elements.test.ripple +15 -15
  114. package/tests/server/head.test.ripple +11 -11
  115. package/tests/server/lazy-destructuring.test.ripple +92 -13
  116. package/tsconfig.typecheck.json +4 -0
  117. package/types/index.d.ts +0 -19
  118. package/tests/client/__snapshots__/tracked-expression.test.ripple.snap +0 -34
  119. package/tests/client/tracked-expression.test.ripple +0 -26
@@ -19,13 +19,13 @@ describe('head elements', () => {
19
19
 
20
20
  it('renders reactive title element', async () => {
21
21
  component App() {
22
- let title = track('Initial Title');
22
+ let &[title] = track('Initial Title');
23
23
 
24
24
  <head>
25
- <title>{@title}</title>
25
+ <title>{title}</title>
26
26
  </head>
27
27
  <div>
28
- <span>{@title}</span>
28
+ <span>{title}</span>
29
29
  </div>
30
30
  }
31
31
 
@@ -38,10 +38,10 @@ describe('head elements', () => {
38
38
 
39
39
  it('renders title with template literal', async () => {
40
40
  component App() {
41
- let name = track('World');
41
+ let &[name] = track('World');
42
42
 
43
43
  <head>
44
- <title>{`Hello ${@name}!`}</title>
44
+ <title>{`Hello ${name}!`}</title>
45
45
  </head>
46
46
  }
47
47
 
@@ -53,14 +53,14 @@ describe('head elements', () => {
53
53
 
54
54
  it('renders title with computed value', async () => {
55
55
  component App() {
56
- let count = track(0);
56
+ let &[count] = track(0);
57
57
  let prefix = 'Count: ';
58
58
 
59
59
  <head>
60
- <title>{prefix + @count}</title>
60
+ <title>{prefix + count}</title>
61
61
  </head>
62
62
  <div>
63
- <span>{@count}</span>
63
+ <span>{count}</span>
64
64
  </div>
65
65
  }
66
66
 
@@ -86,11 +86,11 @@ describe('head elements', () => {
86
86
 
87
87
  it('renders title with conditional content', async () => {
88
88
  component App() {
89
- let showPrefix = track(true);
90
- let title = track('Main Page');
89
+ let &[showPrefix] = track(true);
90
+ let &[title] = track('Main Page');
91
91
 
92
92
  <head>
93
- <title>{@showPrefix ? 'App - ' + @title : @title}</title>
93
+ <title>{showPrefix ? 'App - ' + title : title}</title>
94
94
  </head>
95
95
  }
96
96
 
@@ -1,4 +1,5 @@
1
- import { track, trackSplit } from 'ripple';
1
+ import type { Tracked } from 'ripple';
2
+ import { track } from 'ripple';
2
3
 
3
4
  describe('lazy destructuring', () => {
4
5
  it('supports tracked value getter and setter', async () => {
@@ -30,7 +31,7 @@ describe('lazy destructuring', () => {
30
31
 
31
32
  it('supports default values in lazy object destructuring', async () => {
32
33
  component Test() {
33
- const obj = { a: 5 };
34
+ const obj: { a: number; b?: number } = { a: 5 };
34
35
  const &{ a, b = 99 } = obj;
35
36
  <pre>{`${a}-${b}`}</pre>
36
37
  }
@@ -39,6 +40,20 @@ describe('lazy destructuring', () => {
39
40
  expect(body).toBeHtml('<pre>5-99</pre>');
40
41
  });
41
42
 
43
+ it('supports nested lazy destructuring in non-lazy component params', async () => {
44
+ component Inner({ something: &[first, second] }: { something: Tracked<number> }) {
45
+ first = second.value + 1;
46
+ <pre>{`${first}-${second.value}`}</pre>
47
+ }
48
+
49
+ component Test() {
50
+ <Inner something={track(1)} />
51
+ }
52
+
53
+ const { body } = await render(Test);
54
+ expect(body).toBeHtml('<pre>2-2</pre>');
55
+ });
56
+
42
57
  it('supports let lazy destructuring with assignment writeback', async () => {
43
58
  component Test() {
44
59
  const obj = { a: 1, b: 2 };
@@ -106,33 +121,74 @@ describe('lazy destructuring', () => {
106
121
  expect(body).toBeHtml('<pre>15-105</pre>');
107
122
  });
108
123
 
109
- it('supports member access on lazy destructured objects', async () => {
124
+ it('supports nested lazy destructuring in non-lazy function params', async () => {
110
125
  component Test() {
111
- const obj = { user: { name: 'Alice', age: 30 } };
112
- const &{ user } = obj;
113
- <pre>{`${user.name}-${user.age}`}</pre>
126
+ const something = track(1);
127
+
128
+ function getInfo({ something: &[first, second] }: { something: Tracked<number> }) {
129
+ first = second.value + 1;
130
+ return `${first}-${second.value}`;
131
+ }
132
+
133
+ <pre>{getInfo({ something })}</pre>
114
134
  }
115
135
 
116
136
  const { body } = await render(Test);
117
- expect(body).toBeHtml('<pre>Alice-30</pre>');
137
+ expect(body).toBeHtml('<pre>2-2</pre>');
118
138
  });
119
139
 
120
- it('treats lazy array destructuring of trackSplit as regular array access', async () => {
140
+ it(
141
+ 'preserves lazy getter/setter behavior for RestElement nested destructuring in non-lazy component params',
142
+ async () => {
143
+ component Inner({ values: [head, ...&{ 0: first_rest, length: rest_length }] }) {
144
+ const before = `${first_rest}-${rest_length}`;
145
+ rest_length = 0;
146
+ <pre>{`${head}-${before}-${first_rest}-${rest_length}`}</pre>
147
+ }
148
+
149
+ component Test() {
150
+ <Inner values={[10, 20, 30]} />
151
+ }
152
+
153
+ const { body } = await render(Test);
154
+ expect(body).toBeHtml('<pre>10-20-2-undefined-0</pre>');
155
+ },
156
+ );
157
+
158
+ it(
159
+ 'preserves lazy getter/setter behavior for RestElement nested destructuring in non-lazy function params',
160
+ async () => {
161
+ component Test() {
162
+ function getInfo({ values: [head, ...&{ 0: first_rest, length: rest_length }] }) {
163
+ const before = `${first_rest}-${rest_length}`;
164
+ rest_length = 0;
165
+ return `${head}-${before}-${first_rest}-${rest_length}`;
166
+ }
167
+
168
+ <pre>{getInfo({ values: [5, 6, 7] })}</pre>
169
+ }
170
+
171
+ const { body } = await render(Test);
172
+ expect(body).toBeHtml('<pre>5-6-2-undefined-0</pre>');
173
+ },
174
+ );
175
+
176
+ it('supports member access on lazy destructured objects', async () => {
121
177
  component Test() {
122
- const source = { a: 1, b: 2, c: 3 };
123
- const &[a, b, rest] = trackSplit(source, ['a', 'b']);
124
- <pre>{`${@a}-${@b}-${@rest.c}`}</pre>
178
+ const obj = { user: { name: 'Alice', age: 30 } };
179
+ const &{ user } = obj;
180
+ <pre>{`${user.name}-${user.age}`}</pre>
125
181
  }
126
182
 
127
183
  const { body } = await render(Test);
128
- expect(body).toBeHtml('<pre>1-2-3</pre>');
184
+ expect(body).toBeHtml('<pre>Alice-30</pre>');
129
185
  });
130
186
 
131
187
  it('supports rest in lazy array destructuring for tracked tuples (iterable)', async () => {
132
188
  component Test() {
133
189
  let tracked_value = track(0);
134
190
  let &[value, ...rest] = tracked_value;
135
- <pre>{`${value}-${@rest.length}-${@rest[0] === tracked_value}`}</pre>
191
+ <pre>{`${value}-${rest.length}-${rest[0] === tracked_value}`}</pre>
136
192
  }
137
193
 
138
194
  const { body } = await render(Test);
@@ -149,4 +205,27 @@ describe('lazy destructuring', () => {
149
205
  const { body } = await render(Test);
150
206
  expect(body).toBeHtml('<pre>x-yz</pre>');
151
207
  });
208
+
209
+ it('supports standalone lazy array destructuring with track()', async () => {
210
+ component Test() {
211
+ let count;
212
+ &[count] = track(0);
213
+ <div>{count}</div>
214
+ }
215
+
216
+ const { body } = await render(Test);
217
+ expect(body).toBeHtml('<div>0</div>');
218
+ });
219
+
220
+ it('supports standalone lazy object destructuring', async () => {
221
+ component Test() {
222
+ let a;
223
+ let b;
224
+ &{ a, b } = { a: 10, b: 20 };
225
+ <pre>{`${a}-${b}`}</pre>
226
+ }
227
+
228
+ const { body } = await render(Test);
229
+ expect(body).toBeHtml('<pre>10-20</pre>');
230
+ });
152
231
  });
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["./src/runtime/"]
4
+ }
package/types/index.d.ts CHANGED
@@ -176,19 +176,6 @@ export type PropsNoChildren<T extends object = {}> = Expand<T>;
176
176
 
177
177
  type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
178
178
 
179
- type WrapTracked<V> = V extends Tracked<any> ? V : Tracked<V>;
180
-
181
- type PickKeys<T, K extends readonly (keyof T)[]> = {
182
- [I in keyof K]: WrapTracked<T[K[I] & keyof T]>;
183
- };
184
-
185
- type RestKeys<T, K extends readonly (keyof T)[]> = Expand<Omit<T, K[number]>>;
186
-
187
- type SplitResult<T extends Props, K extends readonly (keyof T)[]> = [
188
- ...PickKeys<T, K>,
189
- Tracked<RestKeys<T, K>>,
190
- ];
191
-
192
179
  export function get<V>(tracked: Tracked<V>): V;
193
180
 
194
181
  export function set<V>(tracked: Tracked<V>, value: V): void;
@@ -204,11 +191,6 @@ export function track<V>(
204
191
  // Overload for non-function values
205
192
  export function track<V>(value?: V, get?: (v: V) => V, set?: (next: V, prev: V) => V): Tracked<V>;
206
193
 
207
- export function trackSplit<V extends Props, const K extends readonly (keyof V)[]>(
208
- value: V,
209
- splitKeys: K,
210
- ): SplitResult<V, K>;
211
-
212
194
  export interface AddEventOptions extends ExtendedEventOptions {
213
195
  customName?: string;
214
196
  }
@@ -568,7 +550,6 @@ export interface RippleNamespace {
568
550
  urlSearchParams: RippleURLSearchParamsCallable;
569
551
  untrack: typeof untrack;
570
552
  track: typeof track;
571
- trackSplit: typeof trackSplit;
572
553
  style: Record<string, string>;
573
554
  server: ServerBlock;
574
555
  }
@@ -1,34 +0,0 @@
1
- // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
-
3
- exports[`TrackedExpression tests > should handle the syntax correctly 1`] = `
4
- <div>
5
- <div>
6
- 0
7
- </div>
8
- <div>
9
- 4
10
- </div>
11
- <div>
12
- 1
13
- </div>
14
- <div>
15
- 2
16
- </div>
17
- <div>
18
- 2
19
- </div>
20
- <div>
21
- 3
22
- </div>
23
- <div>
24
- 4
25
- </div>
26
- <div>
27
- false
28
- </div>
29
- <div>
30
- true
31
- </div>
32
-
33
- </div>
34
- `;
@@ -1,26 +0,0 @@
1
- import { track } from 'ripple';
2
-
3
- describe('TrackedExpression tests', () => {
4
- it('should handle the syntax correctly', () => {
5
- component App() {
6
- let count = track(0);
7
-
8
- function get_count() {
9
- return count;
10
- }
11
-
12
- <div>{@(count)}</div>
13
- <div>{@(get_count())}</div>
14
- <div>{++@(count)}</div>
15
- <div>{++@(get_count())}</div>
16
- <div>{@(count)++}</div>
17
- <div>{@(get_count())++}</div>
18
- <div>{@(count)}</div>
19
- <div>{!@(count)}</div>
20
- <div>{!!@(count)}</div>
21
- }
22
-
23
- render(App);
24
- expect(container).toMatchSnapshot();
25
- });
26
- });