ripple 0.2.216 → 0.3.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.
- package/CHANGELOG.md +39 -0
- package/package.json +16 -7
- package/src/compiler/errors.js +1 -1
- package/src/compiler/identifier-utils.js +2 -0
- package/src/compiler/index.d.ts +2 -6
- package/src/compiler/phases/1-parse/index.js +171 -233
- package/src/compiler/phases/2-analyze/index.js +192 -16
- package/src/compiler/phases/2-analyze/prune.js +2 -2
- package/src/compiler/phases/3-transform/client/index.js +308 -91
- package/src/compiler/phases/3-transform/segments.js +43 -15
- package/src/compiler/phases/3-transform/server/index.js +71 -21
- package/src/compiler/scope.js +31 -12
- package/src/compiler/source-map-utils.js +4 -6
- package/src/compiler/types/acorn.d.ts +11 -0
- package/src/compiler/types/estree-jsx.d.ts +11 -0
- package/src/compiler/types/estree.d.ts +11 -0
- package/src/compiler/types/import.d.ts +32 -18
- package/src/compiler/types/index.d.ts +75 -23
- package/src/compiler/types/parse.d.ts +7 -10
- package/src/compiler/utils.js +48 -0
- package/src/runtime/array.js +53 -22
- package/src/runtime/date.js +15 -5
- package/src/runtime/index-client.js +41 -7
- package/src/runtime/index-server.js +7 -7
- package/src/runtime/internal/client/bindings.js +2 -2
- package/src/runtime/internal/client/blocks.js +40 -1
- package/src/runtime/internal/client/context.js +8 -0
- package/src/runtime/internal/client/for.js +3 -3
- package/src/runtime/internal/client/index.js +32 -5
- package/src/runtime/internal/client/render.js +20 -8
- package/src/runtime/internal/client/runtime.js +9 -7
- package/src/runtime/internal/client/try.js +15 -22
- package/src/runtime/internal/client/utils.js +1 -1
- package/src/runtime/internal/server/context.js +8 -0
- package/src/runtime/internal/server/index.js +99 -6
- package/src/runtime/map.js +7 -7
- package/src/runtime/media-query.js +10 -1
- package/src/runtime/object.js +6 -6
- package/src/runtime/proxy.js +6 -6
- package/src/runtime/set.js +11 -11
- package/src/runtime/url-search-params.js +13 -2
- package/src/runtime/url.js +15 -5
- package/src/utils/builders.js +13 -3
- package/tests/client/array/array.copy-within.test.ripple +11 -11
- package/tests/client/array/array.derived.test.ripple +42 -42
- package/tests/client/array/array.iteration.test.ripple +12 -12
- package/tests/client/array/array.mutations.test.ripple +25 -25
- package/tests/client/array/array.static.test.ripple +103 -106
- package/tests/client/array/array.to-methods.test.ripple +8 -8
- package/tests/client/async-suspend.test.ripple +94 -0
- package/tests/client/basic/basic.attributes.test.ripple +31 -31
- package/tests/client/basic/basic.collections.test.ripple +7 -7
- package/tests/client/basic/basic.components.test.ripple +48 -10
- package/tests/client/basic/basic.errors.test.ripple +46 -31
- package/tests/client/basic/basic.events.test.ripple +11 -11
- package/tests/client/basic/basic.get-set.test.ripple +18 -18
- package/tests/client/basic/basic.reactivity.test.ripple +47 -42
- package/tests/client/basic/basic.rendering.test.ripple +7 -7
- package/tests/client/basic/basic.utilities.test.ripple +4 -4
- package/tests/client/boundaries.test.ripple +7 -7
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +2 -2
- package/tests/client/compiler/compiler.assignments.test.ripple +21 -21
- package/tests/client/compiler/compiler.basic.test.ripple +223 -82
- package/tests/client/compiler/compiler.tracked-access.test.ripple +8 -9
- package/tests/client/composite/composite.dynamic-components.test.ripple +8 -8
- package/tests/client/composite/composite.generics.test.ripple +4 -4
- package/tests/client/composite/composite.props.test.ripple +9 -9
- package/tests/client/composite/composite.reactivity.test.ripple +32 -26
- package/tests/client/composite/composite.render.test.ripple +13 -4
- package/tests/client/computed-properties.test.ripple +3 -3
- package/tests/client/context.test.ripple +3 -3
- package/tests/client/css/global-additional-cases.test.ripple +4 -4
- package/tests/client/css/style-identifier.test.ripple +49 -41
- package/tests/client/date.test.ripple +40 -40
- package/tests/client/dynamic-elements.test.ripple +165 -30
- package/tests/client/events.test.ripple +25 -25
- package/tests/client/for.test.ripple +76 -8
- package/tests/client/function-overload.test.ripple +0 -1
- package/tests/client/head.test.ripple +7 -7
- package/tests/client/html.test.ripple +2 -2
- package/tests/client/input-value.test.ripple +174 -176
- package/tests/client/map.test.ripple +21 -21
- package/tests/client/media-query.test.ripple +4 -4
- package/tests/client/object.test.ripple +12 -12
- package/tests/client/portal.test.ripple +4 -4
- package/tests/client/ref.test.ripple +5 -5
- package/tests/client/return.test.ripple +17 -17
- package/tests/client/set.test.ripple +16 -16
- package/tests/client/svg.test.ripple +6 -7
- package/tests/client/switch.test.ripple +10 -10
- package/tests/client/tracked-expression.test.ripple +1 -3
- package/tests/client/try.test.ripple +33 -4
- package/tests/client/url/url.derived.test.ripple +10 -9
- package/tests/client/url/url.parsing.test.ripple +10 -10
- package/tests/client/url/url.partial-removal.test.ripple +10 -10
- package/tests/client/url/url.reactivity.test.ripple +17 -17
- package/tests/client/url/url.serialization.test.ripple +4 -4
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +11 -10
- package/tests/client/url-search-params/url-search-params.initialization.test.ripple +5 -7
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +13 -13
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +19 -19
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +17 -17
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +5 -5
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +5 -5
- package/tests/hydration/compiled/client/events.js +8 -11
- package/tests/hydration/compiled/client/for.js +20 -23
- package/tests/hydration/compiled/client/head.js +17 -19
- package/tests/hydration/compiled/client/hmr.js +1 -3
- package/tests/hydration/compiled/client/html.js +1 -15
- package/tests/hydration/compiled/client/if-children.js +7 -9
- package/tests/hydration/compiled/client/if.js +5 -7
- package/tests/hydration/compiled/client/mixed-control-flow.js +3 -5
- package/tests/hydration/compiled/client/portal.js +1 -1
- package/tests/hydration/compiled/client/reactivity.js +9 -11
- package/tests/hydration/compiled/client/return.js +11 -13
- package/tests/hydration/compiled/client/switch.js +4 -6
- package/tests/hydration/compiled/server/basic.js +0 -1
- package/tests/hydration/compiled/server/composite.js +0 -3
- package/tests/hydration/compiled/server/events.js +8 -12
- package/tests/hydration/compiled/server/for.js +20 -23
- package/tests/hydration/compiled/server/head.js +17 -19
- package/tests/hydration/compiled/server/hmr.js +1 -4
- package/tests/hydration/compiled/server/html.js +1 -35
- package/tests/hydration/compiled/server/if-children.js +7 -11
- package/tests/hydration/compiled/server/if.js +5 -7
- package/tests/hydration/compiled/server/mixed-control-flow.js +3 -5
- package/tests/hydration/compiled/server/portal.js +1 -9
- package/tests/hydration/compiled/server/reactivity.js +9 -11
- package/tests/hydration/compiled/server/return.js +11 -13
- package/tests/hydration/compiled/server/switch.js +4 -6
- package/tests/hydration/components/events.ripple +8 -9
- package/tests/hydration/components/for.ripple +20 -21
- package/tests/hydration/components/head.ripple +6 -8
- package/tests/hydration/components/hmr.ripple +1 -2
- package/tests/hydration/components/html.ripple +1 -3
- package/tests/hydration/components/if-children.ripple +7 -8
- package/tests/hydration/components/if.ripple +5 -6
- package/tests/hydration/components/mixed-control-flow.ripple +4 -6
- package/tests/hydration/components/portal.ripple +1 -1
- package/tests/hydration/components/reactivity.ripple +9 -10
- package/tests/hydration/components/return.ripple +11 -12
- package/tests/hydration/components/switch.ripple +6 -8
- package/tests/server/await.test.ripple +2 -2
- package/tests/server/basic.attributes.test.ripple +19 -21
- package/tests/server/basic.components.test.ripple +13 -7
- package/tests/server/basic.test.ripple +20 -21
- package/tests/server/compiler.test.ripple +5 -5
- package/tests/server/composite.props.test.ripple +6 -7
- package/tests/server/composite.test.ripple +4 -4
- package/tests/server/context.test.ripple +1 -3
- package/tests/server/dynamic-elements.test.ripple +24 -24
- package/tests/server/head.test.ripple +5 -7
- package/tests/server/style-identifier.test.ripple +16 -17
- package/types/index.d.ts +266 -62
- package/types/server.d.ts +6 -6
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
Tracked,
|
|
3
|
+
Props,
|
|
4
|
+
PropsWithChildren,
|
|
5
|
+
PropsWithExtras,
|
|
6
|
+
Component,
|
|
7
|
+
PropsWithChildrenOptional,
|
|
8
|
+
} from 'ripple';
|
|
9
|
+
import { flushSync } from 'ripple';
|
|
3
10
|
|
|
4
11
|
describe('basic client > components & composition', () => {
|
|
5
12
|
it('renders with component composition and children', () => {
|
|
@@ -27,18 +34,48 @@ describe('basic client > components & composition', () => {
|
|
|
27
34
|
});
|
|
28
35
|
|
|
29
36
|
it('does not render a falsy component call', () => {
|
|
30
|
-
component Card(props:
|
|
37
|
+
component Card(props: PropsWithChildrenOptional<{ test?: Component }>) {
|
|
31
38
|
<div class="card">
|
|
32
|
-
|
|
39
|
+
if (props.children) {
|
|
40
|
+
<props.children />
|
|
41
|
+
}
|
|
42
|
+
</div>
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
component Basic() {
|
|
46
|
+
<Card>
|
|
47
|
+
component test() {
|
|
48
|
+
<p>{'Card content here'}</p>
|
|
49
|
+
}
|
|
50
|
+
</Card>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
render(Basic);
|
|
54
|
+
|
|
55
|
+
const card = container.querySelector('.card');
|
|
56
|
+
const paragraph = card.querySelector('p');
|
|
57
|
+
|
|
58
|
+
expect(card).toBeTruthy();
|
|
59
|
+
expect(paragraph).toBeFalsy();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('allows tracked variable and slot component with same name in nested scope', () => {
|
|
63
|
+
component Card(props: PropsWithChildrenOptional<{ test?: Component }>) {
|
|
64
|
+
<div class="card">
|
|
65
|
+
if (props.children) {
|
|
66
|
+
<props.children />
|
|
67
|
+
}
|
|
33
68
|
</div>
|
|
34
69
|
}
|
|
35
70
|
|
|
36
71
|
component Basic() {
|
|
72
|
+
let test = #ripple.track(false);
|
|
37
73
|
<Card>
|
|
38
74
|
component test() {
|
|
39
75
|
<p>{'Card content here'}</p>
|
|
40
76
|
}
|
|
41
77
|
</Card>
|
|
78
|
+
<div>{@test ? 'yes' : 'no'}</div>
|
|
42
79
|
}
|
|
43
80
|
|
|
44
81
|
render(Basic);
|
|
@@ -48,6 +85,7 @@ describe('basic client > components & composition', () => {
|
|
|
48
85
|
|
|
49
86
|
expect(card).toBeTruthy();
|
|
50
87
|
expect(paragraph).toBeFalsy();
|
|
88
|
+
expect(container.textContent).toContain('no');
|
|
51
89
|
});
|
|
52
90
|
|
|
53
91
|
it('renders a component when children is set a component prop', () => {
|
|
@@ -96,7 +134,7 @@ describe('basic client > components & composition', () => {
|
|
|
96
134
|
}
|
|
97
135
|
|
|
98
136
|
component Basic() {
|
|
99
|
-
let clicked = track(false);
|
|
137
|
+
let clicked = #ripple.track(false);
|
|
100
138
|
|
|
101
139
|
<Card
|
|
102
140
|
title="Test Card"
|
|
@@ -137,8 +175,8 @@ describe('basic client > components & composition', () => {
|
|
|
137
175
|
}
|
|
138
176
|
|
|
139
177
|
component Basic() {
|
|
140
|
-
let message = track('Hello');
|
|
141
|
-
let number = track(1);
|
|
178
|
+
let message = #ripple.track('Hello');
|
|
179
|
+
let number = #ripple.track(1);
|
|
142
180
|
|
|
143
181
|
<ChildComponent text={message} count={number} />
|
|
144
182
|
<button
|
|
@@ -176,14 +214,14 @@ describe('basic client > components & composition', () => {
|
|
|
176
214
|
it('it retains this context with bracketed prop functions and keeps original chaining', () => {
|
|
177
215
|
component App() {
|
|
178
216
|
const SYMBOL_PROP = Symbol();
|
|
179
|
-
let hasError = track(false);
|
|
217
|
+
let hasError = #ripple.track(false);
|
|
180
218
|
const obj: {
|
|
181
219
|
count: Tracked<number>;
|
|
182
220
|
increment: () => void;
|
|
183
221
|
[key: symbol]: () => void;
|
|
184
222
|
arr: Array<() => void>;
|
|
185
223
|
} = {
|
|
186
|
-
count: track(0),
|
|
224
|
+
count: #ripple.track(0),
|
|
187
225
|
increment() {
|
|
188
226
|
this.@count++;
|
|
189
227
|
},
|
|
@@ -364,7 +402,7 @@ describe('basic client > components & composition', () => {
|
|
|
364
402
|
}
|
|
365
403
|
|
|
366
404
|
component App() {
|
|
367
|
-
let Content = track(() => Noop);
|
|
405
|
+
let Content = #ripple.track(() => Noop);
|
|
368
406
|
<@Content />
|
|
369
407
|
|
|
370
408
|
<button onClick={() => (@Content = Op)}>{'Show Op'}</button>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { flushSync } from 'ripple';
|
|
2
2
|
import { compile } from 'ripple/compiler';
|
|
3
3
|
|
|
4
4
|
describe('basic client > errors', () => {
|
|
5
5
|
it('renders with error handling simulation', () => {
|
|
6
6
|
component Basic() {
|
|
7
|
-
let hasError = track(false);
|
|
8
|
-
let errorMessage = track('');
|
|
7
|
+
let hasError = #ripple.track(false);
|
|
8
|
+
let errorMessage = #ripple.track('');
|
|
9
9
|
|
|
10
10
|
const triggerError = () => {
|
|
11
11
|
try {
|
|
@@ -89,11 +89,11 @@ describe('basic client > errors', () => {
|
|
|
89
89
|
);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
it('errors on mutating tracked value inside computed track() evaluation', () => {
|
|
92
|
+
it('errors on mutating tracked value inside computed #ripple.track() evaluation', () => {
|
|
93
93
|
component Basic() {
|
|
94
|
-
let count = track(0);
|
|
94
|
+
let count = #ripple.track(0);
|
|
95
95
|
|
|
96
|
-
const doubled = track(() => {
|
|
96
|
+
const doubled = #ripple.track(() => {
|
|
97
97
|
try {
|
|
98
98
|
@count *= 2;
|
|
99
99
|
} catch (e) {
|
|
@@ -107,39 +107,42 @@ describe('basic client > errors', () => {
|
|
|
107
107
|
render(Basic);
|
|
108
108
|
|
|
109
109
|
expect(error).toBe(
|
|
110
|
-
'Assignments or updates to tracked values are not allowed during computed "track(() => ...)" evaluation',
|
|
110
|
+
'Assignments or updates to tracked values are not allowed during computed "#ripple.track(() => ...)" evaluation',
|
|
111
111
|
);
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
it(
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
it(
|
|
115
|
+
'errors on mutating tracked value inside #ripple.untrack() in computed #ripple.track() evaluation',
|
|
116
|
+
() => {
|
|
117
|
+
component Basic() {
|
|
118
|
+
let count = #ripple.track(0);
|
|
119
|
+
|
|
120
|
+
const doubled = #ripple.track(() => {
|
|
121
|
+
try {
|
|
122
|
+
#ripple.untrack(() => {
|
|
123
|
+
@count *= 2;
|
|
124
|
+
});
|
|
125
|
+
} catch (e) {
|
|
126
|
+
error = (e as Error).message;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
untrack(() => {
|
|
121
|
-
@count *= 2;
|
|
122
|
-
});
|
|
123
|
-
} catch (e) {
|
|
124
|
-
error = (e as Error).message;
|
|
125
|
-
}
|
|
126
|
-
});
|
|
130
|
+
<p>{@doubled}</p>
|
|
131
|
+
}
|
|
127
132
|
|
|
128
|
-
|
|
129
|
-
}
|
|
133
|
+
render(Basic);
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
expect(error).toBe(
|
|
136
|
+
'Assignments or updates to tracked values are not allowed during computed "#ripple.track(() => ...)" evaluation',
|
|
137
|
+
);
|
|
138
|
+
},
|
|
139
|
+
);
|
|
132
140
|
|
|
133
|
-
|
|
134
|
-
'Assignments or updates to tracked values are not allowed during computed "track(() => ...)" evaluation',
|
|
135
|
-
);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it('errors on mutating a tracked variable in track() getter', () => {
|
|
141
|
+
it('errors on mutating a tracked variable in #ripple.track() getter', () => {
|
|
139
142
|
component Basic() {
|
|
140
|
-
let count = track(0);
|
|
143
|
+
let count = #ripple.track(0);
|
|
141
144
|
|
|
142
|
-
const doubled = track(0, (value) => {
|
|
145
|
+
const doubled = #ripple.track(0, (value) => {
|
|
143
146
|
try {
|
|
144
147
|
@count += 1;
|
|
145
148
|
} catch (e) {
|
|
@@ -154,7 +157,7 @@ describe('basic client > errors', () => {
|
|
|
154
157
|
render(Basic);
|
|
155
158
|
|
|
156
159
|
expect(error).toBe(
|
|
157
|
-
'Assignments or updates to tracked values are not allowed during computed "track(() => ...)" evaluation',
|
|
160
|
+
'Assignments or updates to tracked values are not allowed during computed "#ripple.track(() => ...)" evaluation',
|
|
158
161
|
);
|
|
159
162
|
});
|
|
160
163
|
|
|
@@ -239,4 +242,16 @@ describe('basic client > errors', () => {
|
|
|
239
242
|
compile(code, 'test.ripple');
|
|
240
243
|
}).not.toThrow();
|
|
241
244
|
});
|
|
245
|
+
|
|
246
|
+
it('should throw error for variables using the reserved _$_ prefix', () => {
|
|
247
|
+
const code = `
|
|
248
|
+
export default component App() {
|
|
249
|
+
const _$_test = 'hello';
|
|
250
|
+
<div>{_$_test}</div>
|
|
251
|
+
}
|
|
252
|
+
`;
|
|
253
|
+
expect(() => {
|
|
254
|
+
compile(code, 'test.ripple');
|
|
255
|
+
}).toThrow('identifiers starting with "_$_" are reserved');
|
|
256
|
+
});
|
|
242
257
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import { flushSync } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('basic client > events', () => {
|
|
5
5
|
it('renders with different event types', () => {
|
|
6
6
|
component Basic() {
|
|
7
|
-
let focusCount = track(0);
|
|
8
|
-
let clickCount = track(0);
|
|
7
|
+
let focusCount = #ripple.track(0);
|
|
8
|
+
let clickCount = #ripple.track(0);
|
|
9
9
|
|
|
10
10
|
<button
|
|
11
11
|
onFocus={() => {
|
|
@@ -38,8 +38,8 @@ describe('basic client > events', () => {
|
|
|
38
38
|
|
|
39
39
|
it('renders with capture events', () => {
|
|
40
40
|
component Basic() {
|
|
41
|
-
let captureClicks = track(0);
|
|
42
|
-
let bubbleClicks = track(0);
|
|
41
|
+
let captureClicks = #ripple.track(0);
|
|
42
|
+
let bubbleClicks = #ripple.track(0);
|
|
43
43
|
|
|
44
44
|
<div
|
|
45
45
|
onClick={{
|
|
@@ -76,7 +76,7 @@ describe('basic client > events', () => {
|
|
|
76
76
|
|
|
77
77
|
it('renders with event listeners in spread props', () => {
|
|
78
78
|
component Basic() {
|
|
79
|
-
let count = track(0);
|
|
79
|
+
let count = #ripple.track(0);
|
|
80
80
|
|
|
81
81
|
const minus = {
|
|
82
82
|
onClick() {
|
|
@@ -125,8 +125,8 @@ describe('basic client > events', () => {
|
|
|
125
125
|
|
|
126
126
|
it('handles both delegated and non-delegated events in spread props', () => {
|
|
127
127
|
component Basic() {
|
|
128
|
-
let clickCount = track(0);
|
|
129
|
-
let focusCount = track(0);
|
|
128
|
+
let clickCount = #ripple.track(0);
|
|
129
|
+
let focusCount = #ripple.track(0);
|
|
130
130
|
|
|
131
131
|
const mixedHandler = {
|
|
132
132
|
onClick() {
|
|
@@ -168,9 +168,9 @@ describe('basic client > events', () => {
|
|
|
168
168
|
|
|
169
169
|
it('renders with complex event handling and state updates', () => {
|
|
170
170
|
component Basic() {
|
|
171
|
-
let counter = track(0);
|
|
172
|
-
let history = track<string[]>([]);
|
|
173
|
-
let isEven = track(true);
|
|
171
|
+
let counter = #ripple.track(0);
|
|
172
|
+
let history = #ripple.track<string[]>([]);
|
|
173
|
+
let isEven = #ripple.track(true);
|
|
174
174
|
|
|
175
175
|
const handleIncrement = () => {
|
|
176
176
|
@counter++;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { flushSync, get, set } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('basic client > get/set functions', () => {
|
|
4
4
|
it('gets tracked value', () => {
|
|
5
5
|
component Test() {
|
|
6
|
-
let count = track(0);
|
|
6
|
+
let count = #ripple.track(0);
|
|
7
7
|
|
|
8
8
|
<div>{get(count)}</div>
|
|
9
9
|
}
|
|
@@ -16,7 +16,7 @@ describe('basic client > get/set functions', () => {
|
|
|
16
16
|
|
|
17
17
|
it('gets tracked value after mutation', () => {
|
|
18
18
|
component Test() {
|
|
19
|
-
let count = track(0);
|
|
19
|
+
let count = #ripple.track(0);
|
|
20
20
|
|
|
21
21
|
<p>{get(count)}</p>
|
|
22
22
|
<button onClick={() => @count++}>{'increment'}</button>
|
|
@@ -36,7 +36,7 @@ describe('basic client > get/set functions', () => {
|
|
|
36
36
|
|
|
37
37
|
it('gets tracked value after multiple mutations', () => {
|
|
38
38
|
component Test() {
|
|
39
|
-
let count = track(0);
|
|
39
|
+
let count = #ripple.track(0);
|
|
40
40
|
|
|
41
41
|
<p>{get(count)}</p>
|
|
42
42
|
<button
|
|
@@ -64,7 +64,7 @@ describe('basic client > get/set functions', () => {
|
|
|
64
64
|
|
|
65
65
|
it('sets tracked value', () => {
|
|
66
66
|
component Test() {
|
|
67
|
-
let count = track(0);
|
|
67
|
+
let count = #ripple.track(0);
|
|
68
68
|
|
|
69
69
|
<p>{get(count)}</p>
|
|
70
70
|
<button onClick={() => set(count, 10)}>{'set to 10'}</button>
|
|
@@ -84,7 +84,7 @@ describe('basic client > get/set functions', () => {
|
|
|
84
84
|
|
|
85
85
|
it('sets tracked value multiple times', () => {
|
|
86
86
|
component Test() {
|
|
87
|
-
let count = track(0);
|
|
87
|
+
let count = #ripple.track(0);
|
|
88
88
|
|
|
89
89
|
<p>{get(count)}</p>
|
|
90
90
|
<button
|
|
@@ -112,7 +112,7 @@ describe('basic client > get/set functions', () => {
|
|
|
112
112
|
|
|
113
113
|
it('sets tracked value based on previous value', () => {
|
|
114
114
|
component Test() {
|
|
115
|
-
let count = track(0);
|
|
115
|
+
let count = #ripple.track(0);
|
|
116
116
|
|
|
117
117
|
<p>{get(count)}</p>
|
|
118
118
|
<button onClick={() => set(count, get(count) + 10)}>{'add 10'}</button>
|
|
@@ -138,7 +138,7 @@ describe('basic client > get/set functions', () => {
|
|
|
138
138
|
|
|
139
139
|
it('sets tracked value multiple times based on previous value', () => {
|
|
140
140
|
component Test() {
|
|
141
|
-
let count = track(0);
|
|
141
|
+
let count = #ripple.track(0);
|
|
142
142
|
|
|
143
143
|
<p>{get(count)}</p>
|
|
144
144
|
<button
|
|
@@ -172,7 +172,7 @@ describe('basic client > get/set functions', () => {
|
|
|
172
172
|
|
|
173
173
|
it('gets value declared outside Ripple component', () => {
|
|
174
174
|
function store() {
|
|
175
|
-
return track(0);
|
|
175
|
+
return #ripple.track(0);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
component Test() {
|
|
@@ -188,7 +188,7 @@ describe('basic client > get/set functions', () => {
|
|
|
188
188
|
|
|
189
189
|
it('sets value declared outside Ripple component', () => {
|
|
190
190
|
function store() {
|
|
191
|
-
return track(0);
|
|
191
|
+
return #ripple.track(0);
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
component Test() {
|
|
@@ -212,10 +212,10 @@ describe('basic client > get/set functions', () => {
|
|
|
212
212
|
|
|
213
213
|
it('works with effects', () => {
|
|
214
214
|
component Test() {
|
|
215
|
-
let count = track(0);
|
|
216
|
-
let double = track(0);
|
|
215
|
+
let count = #ripple.track(0);
|
|
216
|
+
let double = #ripple.track(0);
|
|
217
217
|
|
|
218
|
-
effect(() => {
|
|
218
|
+
#ripple.effect(() => {
|
|
219
219
|
set(double, get(count) * 2);
|
|
220
220
|
});
|
|
221
221
|
|
|
@@ -242,11 +242,11 @@ describe('basic client > get/set functions', () => {
|
|
|
242
242
|
|
|
243
243
|
it('works with effects and untrack', () => {
|
|
244
244
|
component Test() {
|
|
245
|
-
let count = track(0);
|
|
246
|
-
let double = track(0);
|
|
245
|
+
let count = #ripple.track(0);
|
|
246
|
+
let double = #ripple.track(0);
|
|
247
247
|
|
|
248
|
-
effect(() => {
|
|
249
|
-
untrack(() => {
|
|
248
|
+
#ripple.effect(() => {
|
|
249
|
+
#ripple.untrack(() => {
|
|
250
250
|
set(double, get(count) * 2);
|
|
251
251
|
});
|
|
252
252
|
});
|
|
@@ -274,6 +274,6 @@ describe('basic client > get/set functions', () => {
|
|
|
274
274
|
});
|
|
275
275
|
|
|
276
276
|
it('throws on trying to create tracked Ripple component', () => {
|
|
277
|
-
expect(() => track(0)).toThrow();
|
|
277
|
+
expect(() => #ripple.track(0)).toThrow();
|
|
278
278
|
});
|
|
279
279
|
});
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PropsWithChildren, Tracked } from 'ripple';
|
|
2
|
+
import { flushSync } from 'ripple';
|
|
2
3
|
|
|
3
4
|
describe('basic client > reactivity', () => {
|
|
4
5
|
it('renders multiple reactive lexical blocks', () => {
|
|
5
6
|
component Basic() {
|
|
6
7
|
<div>
|
|
7
8
|
let obj = {
|
|
8
|
-
count: track(0),
|
|
9
|
+
count: #ripple.track(0),
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
<span>{obj.@count}</span>
|
|
12
13
|
</div>
|
|
13
14
|
<div>
|
|
14
15
|
let b = {
|
|
15
|
-
count: track(0),
|
|
16
|
+
count: #ripple.track(0),
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
<button
|
|
@@ -53,27 +54,27 @@ describe('basic client > reactivity', () => {
|
|
|
53
54
|
|
|
54
55
|
<div>
|
|
55
56
|
let obj = {
|
|
56
|
-
count: track(0),
|
|
57
|
+
count: #ripple.track(0),
|
|
57
58
|
};
|
|
58
59
|
|
|
59
|
-
<span>{obj[
|
|
60
|
+
<span>{obj.@[count]}</span>
|
|
60
61
|
</div>
|
|
61
62
|
<div>
|
|
62
63
|
let b = {
|
|
63
|
-
count: track(0),
|
|
64
|
+
count: #ripple.track(0),
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
<button
|
|
67
68
|
onClick={() => {
|
|
68
|
-
b[
|
|
69
|
+
b.@[count]--;
|
|
69
70
|
}}
|
|
70
71
|
>
|
|
71
72
|
{'-'}
|
|
72
73
|
</button>
|
|
73
|
-
<span class="count">{b[
|
|
74
|
+
<span class="count">{b.@[count]}</span>
|
|
74
75
|
<button
|
|
75
76
|
onClick={() => {
|
|
76
|
-
b[
|
|
77
|
+
b.@[count]++;
|
|
77
78
|
}}
|
|
78
79
|
>
|
|
79
80
|
{'+'}
|
|
@@ -97,7 +98,7 @@ describe('basic client > reactivity', () => {
|
|
|
97
98
|
|
|
98
99
|
it('renders with computed reactive state', () => {
|
|
99
100
|
component Basic() {
|
|
100
|
-
let count = track(5);
|
|
101
|
+
let count = #ripple.track(5);
|
|
101
102
|
|
|
102
103
|
<div class="count">{@count}</div>
|
|
103
104
|
<div class="doubled">{@count * 2}</div>
|
|
@@ -134,11 +135,11 @@ describe('basic client > reactivity', () => {
|
|
|
134
135
|
let logs: string[] = [];
|
|
135
136
|
|
|
136
137
|
component App() {
|
|
137
|
-
let first = track(0);
|
|
138
|
-
let second = track(0);
|
|
138
|
+
let first = #ripple.track(0);
|
|
139
|
+
let second = #ripple.track(0);
|
|
139
140
|
const arr = [first, second];
|
|
140
141
|
|
|
141
|
-
const total = track(() => arr.reduce((a, b) => a + @b, 0));
|
|
142
|
+
const total = #ripple.track(() => arr.reduce((a, b) => a + @b, 0));
|
|
142
143
|
|
|
143
144
|
<button
|
|
144
145
|
onClick={() => {
|
|
@@ -155,7 +156,7 @@ describe('basic client > reactivity', () => {
|
|
|
155
156
|
{'second: ' + @second}
|
|
156
157
|
</button>
|
|
157
158
|
|
|
158
|
-
effect(() => {
|
|
159
|
+
#ripple.effect(() => {
|
|
159
160
|
let _arr: number[] = [];
|
|
160
161
|
|
|
161
162
|
arr.forEach((item) => {
|
|
@@ -165,7 +166,7 @@ describe('basic client > reactivity', () => {
|
|
|
165
166
|
logs.push(_arr.join(', '));
|
|
166
167
|
});
|
|
167
168
|
|
|
168
|
-
effect(() => {
|
|
169
|
+
#ripple.effect(() => {
|
|
169
170
|
if (arr.map((a) => @a).includes(1)) {
|
|
170
171
|
logs.push('arr includes 1');
|
|
171
172
|
}
|
|
@@ -210,7 +211,7 @@ describe('basic client > reactivity', () => {
|
|
|
210
211
|
|
|
211
212
|
it('uses track get and set where both mutate value', () => {
|
|
212
213
|
component App() {
|
|
213
|
-
let count = track(0, (v) => v + 1, (v) => v * 2);
|
|
214
|
+
let count = #ripple.track(0, (v) => v + 1, (v) => v * 2);
|
|
214
215
|
|
|
215
216
|
<div class="count">{@count}</div>
|
|
216
217
|
<button
|
|
@@ -236,7 +237,7 @@ describe('basic client > reactivity', () => {
|
|
|
236
237
|
|
|
237
238
|
it('uses track get and set where set only mutates value', () => {
|
|
238
239
|
component App() {
|
|
239
|
-
let count = track(1, (v) => v, (v) => v * 2);
|
|
240
|
+
let count = #ripple.track(1, (v) => v, (v) => v * 2);
|
|
240
241
|
|
|
241
242
|
<div class="count">{@count}</div>
|
|
242
243
|
<button
|
|
@@ -262,7 +263,7 @@ describe('basic client > reactivity', () => {
|
|
|
262
263
|
|
|
263
264
|
it('uses track get and set where get only mutates value', () => {
|
|
264
265
|
component App() {
|
|
265
|
-
let count = track(0, (v) => v + 1, (v) => v);
|
|
266
|
+
let count = #ripple.track(0, (v) => v + 1, (v) => v);
|
|
266
267
|
|
|
267
268
|
<div class="count">{@count}</div>
|
|
268
269
|
<button
|
|
@@ -290,7 +291,7 @@ describe('basic client > reactivity', () => {
|
|
|
290
291
|
let logs: number[] = [];
|
|
291
292
|
|
|
292
293
|
component App() {
|
|
293
|
-
let count = track(0, (v) => v, (next, prev) => {
|
|
294
|
+
let count = #ripple.track(0, (v) => v, (next, prev) => {
|
|
294
295
|
logs.push(prev, next);
|
|
295
296
|
return next;
|
|
296
297
|
});
|
|
@@ -313,11 +314,11 @@ describe('basic client > reactivity', () => {
|
|
|
313
314
|
expect(logs).toEqual([0, 1]);
|
|
314
315
|
});
|
|
315
316
|
|
|
316
|
-
it('doesn\'t error on mutating a tracked variable in track() setter', () => {
|
|
317
|
+
it('doesn\'t error on mutating a tracked variable in #ripple.track() setter', () => {
|
|
317
318
|
component Basic() {
|
|
318
|
-
let count = track(0);
|
|
319
|
+
let count = #ripple.track(0);
|
|
319
320
|
|
|
320
|
-
const doubled = track(0, undefined, (value) => {
|
|
321
|
+
const doubled = #ripple.track(0, undefined, (value) => {
|
|
321
322
|
@count += value;
|
|
322
323
|
return value;
|
|
323
324
|
});
|
|
@@ -334,9 +335,9 @@ describe('basic client > reactivity', () => {
|
|
|
334
335
|
let state: { count?: number } = {};
|
|
335
336
|
|
|
336
337
|
component Basic() {
|
|
337
|
-
let count = track(0);
|
|
338
|
+
let count = #ripple.track(0);
|
|
338
339
|
|
|
339
|
-
effect(() => {
|
|
340
|
+
#ripple.effect(() => {
|
|
340
341
|
state.count = @count;
|
|
341
342
|
});
|
|
342
343
|
}
|
|
@@ -358,10 +359,10 @@ describe('basic client > reactivity', () => {
|
|
|
358
359
|
} = {};
|
|
359
360
|
|
|
360
361
|
component Basic() {
|
|
361
|
-
let count = track(5);
|
|
362
|
+
let count = #ripple.track(5);
|
|
362
363
|
|
|
363
|
-
effect(() => {
|
|
364
|
-
untrack(() => {
|
|
364
|
+
#ripple.effect(() => {
|
|
365
|
+
#ripple.untrack(() => {
|
|
365
366
|
state.initialValue = @count;
|
|
366
367
|
state.preIncrement = ++@count;
|
|
367
368
|
state.postIncrement = @count++;
|
|
@@ -386,10 +387,10 @@ describe('basic client > reactivity', () => {
|
|
|
386
387
|
describe('track/trackSplit APIs', () => {
|
|
387
388
|
it('errors on invalid value as null for track with trackSplit', () => {
|
|
388
389
|
component App() {
|
|
389
|
-
let message = track('');
|
|
390
|
+
let message = #ripple.track('');
|
|
390
391
|
|
|
391
392
|
try {
|
|
392
|
-
const [a, b, rest] = trackSplit(null, ['a', 'b']);
|
|
393
|
+
const [a, b, rest] = #ripple.trackSplit(null, ['a', 'b']);
|
|
393
394
|
} catch (e) {
|
|
394
395
|
@message = (e as Error).message;
|
|
395
396
|
}
|
|
@@ -405,10 +406,10 @@ describe('basic client > reactivity', () => {
|
|
|
405
406
|
|
|
406
407
|
it('errors on invalid value as array for track with trackSplit', () => {
|
|
407
408
|
component App() {
|
|
408
|
-
let message = track('');
|
|
409
|
+
let message = #ripple.track('');
|
|
409
410
|
|
|
410
411
|
try {
|
|
411
|
-
const [a, b, rest] = trackSplit([1, 2, 3], ['a', 'b']);
|
|
412
|
+
const [a, b, rest] = #ripple.trackSplit([1, 2, 3], ['a', 'b']);
|
|
412
413
|
} catch (e) {
|
|
413
414
|
@message = (e as Error).message;
|
|
414
415
|
}
|
|
@@ -424,11 +425,11 @@ describe('basic client > reactivity', () => {
|
|
|
424
425
|
|
|
425
426
|
it('errors on invalid value as tracked for track with trackSplit', () => {
|
|
426
427
|
component App() {
|
|
427
|
-
const t = track({ a: 1, b: 2, c: 3 });
|
|
428
|
-
let message = track('');
|
|
428
|
+
const t = #ripple.track({ a: 1, b: 2, c: 3 });
|
|
429
|
+
let message = #ripple.track('');
|
|
429
430
|
|
|
430
431
|
try {
|
|
431
|
-
const [a, b, rest] = trackSplit(t, ['a', 'b']);
|
|
432
|
+
const [a, b, rest] = #ripple.trackSplit(t, ['a', 'b']);
|
|
432
433
|
} catch (e) {
|
|
433
434
|
@message = (e as Error).message;
|
|
434
435
|
}
|
|
@@ -444,7 +445,7 @@ describe('basic client > reactivity', () => {
|
|
|
444
445
|
|
|
445
446
|
it('returns undefined for non-existent props in track with trackSplit', () => {
|
|
446
447
|
component App() {
|
|
447
|
-
const [a, b, rest] = trackSplit({ a: 1, c: 1 }, ['a', 'b']);
|
|
448
|
+
const [a, b, rest] = #ripple.trackSplit({ a: 1, c: 1 }, ['a', 'b']);
|
|
448
449
|
|
|
449
450
|
<pre>{@a}</pre>
|
|
450
451
|
<pre>{String(@b)}</pre>
|
|
@@ -464,8 +465,8 @@ describe('basic client > reactivity', () => {
|
|
|
464
465
|
|
|
465
466
|
it('returns the same tracked object if plain track is called with a tracked object', () => {
|
|
466
467
|
component App() {
|
|
467
|
-
const t = track({ a: 1, b: 2, c: 3 });
|
|
468
|
-
const doublet = track(t);
|
|
468
|
+
const t = #ripple.track({ a: 1, b: 2, c: 3 });
|
|
469
|
+
const doublet = #ripple.track(t);
|
|
469
470
|
|
|
470
471
|
<pre>{t === doublet}</pre>
|
|
471
472
|
}
|
|
@@ -480,8 +481,8 @@ describe('basic client > reactivity', () => {
|
|
|
480
481
|
let logs: string[] = [];
|
|
481
482
|
|
|
482
483
|
component App() {
|
|
483
|
-
let count = track(0);
|
|
484
|
-
let name = track('Click Me');
|
|
484
|
+
let count = #ripple.track(0);
|
|
485
|
+
let name = #ripple.track('Click Me');
|
|
485
486
|
|
|
486
487
|
function buttonRef(el: HTMLButtonElement) {
|
|
487
488
|
logs.push('ref called');
|
|
@@ -493,7 +494,7 @@ describe('basic client > reactivity', () => {
|
|
|
493
494
|
<Child
|
|
494
495
|
class="my-button"
|
|
495
496
|
onClick={() => @name === 'Click Me' ? @name = 'Clicked' : @name = 'Click Me'}
|
|
496
|
-
{
|
|
497
|
+
{count}
|
|
497
498
|
{ref buttonRef}
|
|
498
499
|
>
|
|
499
500
|
{@name}
|
|
@@ -502,8 +503,12 @@ describe('basic client > reactivity', () => {
|
|
|
502
503
|
<button onClick={() => @count++}>{'Increment Count'}</button>
|
|
503
504
|
}
|
|
504
505
|
|
|
505
|
-
component Child(props: PropsWithChildren<{
|
|
506
|
-
|
|
506
|
+
component Child(props: PropsWithChildren<{
|
|
507
|
+
count: Tracked<number>;
|
|
508
|
+
class: string;
|
|
509
|
+
onClick: () => void;
|
|
510
|
+
}>) {
|
|
511
|
+
const [children, count, rest] = #ripple.trackSplit(props, ['children', 'count']);
|
|
507
512
|
|
|
508
513
|
if (@count < 2) {
|
|
509
514
|
<button {...@rest}>
|