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.
- package/CHANGELOG.md +43 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +37 -194
- package/src/compiler/phases/2-analyze/index.js +290 -26
- package/src/compiler/phases/3-transform/client/index.js +54 -14
- package/src/compiler/phases/3-transform/server/index.js +19 -35
- package/src/compiler/types/index.d.ts +3 -1
- package/src/compiler/types/parse.d.ts +0 -8
- package/src/compiler/utils.js +10 -6
- package/src/runtime/internal/client/composite.js +2 -2
- package/src/runtime/internal/client/index.js +2 -0
- package/src/runtime/internal/client/runtime.js +95 -45
- package/src/runtime/internal/client/types.d.ts +10 -0
- package/src/runtime/internal/client/utils.js +12 -0
- package/src/runtime/internal/server/index.js +89 -17
- package/src/runtime/internal/server/types.d.ts +10 -0
- package/src/utils/ast.js +1 -1
- package/tests/client/array/array.copy-within.test.ripple +12 -12
- package/tests/client/array/array.derived.test.ripple +46 -46
- package/tests/client/array/array.iteration.test.ripple +10 -10
- package/tests/client/array/array.mutations.test.ripple +20 -20
- package/tests/client/array/array.to-methods.test.ripple +6 -6
- package/tests/client/async-suspend.test.ripple +5 -5
- package/tests/client/basic/basic.attributes.test.ripple +81 -81
- package/tests/client/basic/basic.collections.test.ripple +9 -9
- package/tests/client/basic/basic.components.test.ripple +28 -28
- package/tests/client/basic/basic.errors.test.ripple +18 -18
- package/tests/client/basic/basic.events.test.ripple +37 -37
- package/tests/client/basic/basic.get-set.test.ripple +6 -6
- package/tests/client/basic/basic.reactivity.test.ripple +68 -68
- package/tests/client/basic/basic.rendering.test.ripple +19 -19
- package/tests/client/basic/basic.utilities.test.ripple +3 -3
- package/tests/client/boundaries.test.ripple +12 -12
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
- package/tests/client/compiler/compiler.basic.test.ripple +44 -15
- package/tests/client/compiler/compiler.tracked-access.test.ripple +68 -2
- package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
- package/tests/client/composite/composite.props.test.ripple +11 -11
- package/tests/client/composite/composite.reactivity.test.ripple +43 -43
- package/tests/client/composite/composite.render.test.ripple +3 -3
- package/tests/client/computed-properties.test.ripple +4 -4
- package/tests/client/date.test.ripple +42 -42
- package/tests/client/dynamic-elements.test.ripple +42 -42
- package/tests/client/events.test.ripple +70 -70
- package/tests/client/for.test.ripple +25 -25
- package/tests/client/head.test.ripple +19 -19
- package/tests/client/html.test.ripple +3 -3
- package/tests/client/input-value.test.ripple +84 -84
- package/tests/client/lazy-destructuring.test.ripple +123 -14
- package/tests/client/map.test.ripple +16 -16
- package/tests/client/media-query.test.ripple +7 -7
- package/tests/client/portal.test.ripple +11 -11
- package/tests/client/ref.test.ripple +4 -4
- package/tests/client/return.test.ripple +52 -52
- package/tests/client/set.test.ripple +6 -6
- package/tests/client/svg.test.ripple +5 -5
- package/tests/client/switch.test.ripple +44 -44
- package/tests/client/try.test.ripple +5 -5
- package/tests/client/url/url.derived.test.ripple +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
- package/tests/hydration/compiled/client/events.js +25 -25
- package/tests/hydration/compiled/client/for.js +70 -66
- package/tests/hydration/compiled/client/head.js +25 -25
- package/tests/hydration/compiled/client/hmr.js +2 -2
- package/tests/hydration/compiled/client/html.js +3 -3
- package/tests/hydration/compiled/client/if-children.js +24 -24
- package/tests/hydration/compiled/client/if.js +18 -18
- package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
- package/tests/hydration/compiled/client/portal.js +3 -3
- package/tests/hydration/compiled/client/reactivity.js +16 -16
- package/tests/hydration/compiled/client/return.js +40 -40
- package/tests/hydration/compiled/client/switch.js +12 -12
- package/tests/hydration/compiled/server/events.js +19 -19
- package/tests/hydration/compiled/server/for.js +41 -41
- package/tests/hydration/compiled/server/head.js +26 -26
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +2 -2
- package/tests/hydration/compiled/server/if-children.js +16 -16
- package/tests/hydration/compiled/server/if.js +11 -11
- package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
- package/tests/hydration/compiled/server/portal.js +2 -2
- package/tests/hydration/compiled/server/reactivity.js +16 -16
- package/tests/hydration/compiled/server/return.js +25 -25
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/components/events.ripple +25 -25
- package/tests/hydration/components/for.ripple +66 -66
- package/tests/hydration/components/head.ripple +16 -16
- package/tests/hydration/components/hmr.ripple +2 -2
- package/tests/hydration/components/html.ripple +3 -3
- package/tests/hydration/components/if-children.ripple +24 -24
- package/tests/hydration/components/if.ripple +18 -18
- package/tests/hydration/components/mixed-control-flow.ripple +9 -9
- package/tests/hydration/components/portal.ripple +3 -3
- package/tests/hydration/components/reactivity.ripple +16 -16
- package/tests/hydration/components/return.ripple +40 -40
- package/tests/hydration/components/switch.ripple +20 -20
- package/tests/server/await.test.ripple +3 -3
- package/tests/server/basic.attributes.test.ripple +34 -34
- package/tests/server/basic.components.test.ripple +10 -10
- package/tests/server/basic.test.ripple +38 -40
- package/tests/server/composite.props.test.ripple +9 -9
- package/tests/server/dynamic-elements.test.ripple +13 -12
- package/tests/server/head.test.ripple +11 -11
- package/tests/server/lazy-destructuring.test.ripple +72 -0
- package/types/index.d.ts +7 -2
|
@@ -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>{
|
|
25
|
+
<title>{title}</title>
|
|
26
26
|
</head>
|
|
27
27
|
<div>
|
|
28
|
-
<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 ${
|
|
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 +
|
|
60
|
+
<title>{prefix + count}</title>
|
|
61
61
|
</head>
|
|
62
62
|
<div>
|
|
63
|
-
<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>{
|
|
93
|
+
<title>{showPrefix ? 'App - ' + title : title}</title>
|
|
94
94
|
</head>
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -1,4 +1,20 @@
|
|
|
1
|
+
import { track, trackSplit } from 'ripple';
|
|
2
|
+
|
|
1
3
|
describe('lazy destructuring', () => {
|
|
4
|
+
it('supports tracked value getter and setter', async () => {
|
|
5
|
+
component Test() {
|
|
6
|
+
let count = track(1);
|
|
7
|
+
let derived = track(() => count.value * 2);
|
|
8
|
+
|
|
9
|
+
count.value = 3;
|
|
10
|
+
|
|
11
|
+
<pre>{`${count.value}-${derived.value}`}</pre>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { body } = await render(Test);
|
|
15
|
+
expect(body).toBeHtml('<pre>3-6</pre>');
|
|
16
|
+
});
|
|
17
|
+
|
|
2
18
|
it('lazily accesses object properties', async () => {
|
|
3
19
|
component Inner(&{ a, b }: { a: number; b: string }) {
|
|
4
20
|
<pre>{`${a}-${b}`}</pre>
|
|
@@ -100,4 +116,60 @@ describe('lazy destructuring', () => {
|
|
|
100
116
|
const { body } = await render(Test);
|
|
101
117
|
expect(body).toBeHtml('<pre>Alice-30</pre>');
|
|
102
118
|
});
|
|
119
|
+
|
|
120
|
+
it('treats array destructuring of trackSplit as regular array access', async () => {
|
|
121
|
+
component Test() {
|
|
122
|
+
const source = { a: 1, b: 2, c: 3 };
|
|
123
|
+
const [a, b, rest] = trackSplit(source, ['a', 'b']);
|
|
124
|
+
<pre>{`${a.value}-${b.value}-${rest.value.c}`}</pre>
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const { body } = await render(Test);
|
|
128
|
+
expect(body).toBeHtml('<pre>1-2-3</pre>');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('supports rest in lazy array destructuring for tracked tuples (iterable)', async () => {
|
|
132
|
+
component Test() {
|
|
133
|
+
let tracked_value = track(0);
|
|
134
|
+
let &[value, ...rest] = tracked_value;
|
|
135
|
+
<pre>{`${value}-${rest.length}-${rest[0] === tracked_value}`}</pre>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const { body } = await render(Test);
|
|
139
|
+
expect(body).toBeHtml('<pre>0-1-true</pre>');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('supports rest in lazy array destructuring for length-only array-like values', async () => {
|
|
143
|
+
component Test() {
|
|
144
|
+
const array_like = { 0: 'x', 1: 'y', 2: 'z', length: 3 };
|
|
145
|
+
const &[first, ...rest] = array_like;
|
|
146
|
+
<pre>{`${first}-${rest.join('')}`}</pre>
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const { body } = await render(Test);
|
|
150
|
+
expect(body).toBeHtml('<pre>x-yz</pre>');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('supports standalone lazy array destructuring with track()', async () => {
|
|
154
|
+
component Test() {
|
|
155
|
+
let count;
|
|
156
|
+
&[count] = track(0);
|
|
157
|
+
<div>{count}</div>
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const { body } = await render(Test);
|
|
161
|
+
expect(body).toBeHtml('<div>0</div>');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('supports standalone lazy object destructuring', async () => {
|
|
165
|
+
component Test() {
|
|
166
|
+
let a;
|
|
167
|
+
let b;
|
|
168
|
+
&{ a, b } = { a: 10, b: 20 };
|
|
169
|
+
<pre>{`${a}-${b}`}</pre>
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const { body } = await render(Test);
|
|
173
|
+
expect(body).toBeHtml('<pre>10-20</pre>');
|
|
174
|
+
});
|
|
103
175
|
});
|
package/types/index.d.ts
CHANGED
|
@@ -145,16 +145,21 @@ declare global {
|
|
|
145
145
|
export function createRefKey(): symbol;
|
|
146
146
|
|
|
147
147
|
// Base Tracked interface - all tracked values have a '#v' property containing the actual value
|
|
148
|
-
|
|
148
|
+
interface TrackedBase<V> {
|
|
149
149
|
'#v': V;
|
|
150
|
+
value: V;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
// Augment Tracked to be callable when V is a Component
|
|
153
154
|
// This allows <@Something /> to work in JSX when Something is Tracked<Component>
|
|
154
|
-
|
|
155
|
+
interface TrackedCallable<V> {
|
|
155
156
|
(props: V extends Component<infer P> ? P : never): V extends Component ? void : never;
|
|
156
157
|
}
|
|
157
158
|
|
|
159
|
+
// Supports indexed access: track(0)[0] → value, track(0)[1] → Tracked<V>
|
|
160
|
+
// And destructuring `const [one, two] = track(0);`
|
|
161
|
+
export type Tracked<V> = [V, Tracked<V>] & TrackedBase<V> & TrackedCallable<V>;
|
|
162
|
+
|
|
158
163
|
// Helper type to infer component type from a function that returns a component
|
|
159
164
|
// If T is a function returning a Component, extract the Component type itself, not the return type (void)
|
|
160
165
|
export type InferComponent<T> = T extends () => infer R ? (R extends Component<any> ? R : T) : T;
|