ripple 0.2.85 → 0.2.87
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/package.json +3 -1
- package/src/compiler/scope.js +2 -0
- package/src/compiler/types/index.d.ts +5 -0
- package/src/runtime/array.js +12 -5
- package/src/runtime/index-client.js +0 -1
- package/src/runtime/index-server.js +18 -3
- package/src/runtime/internal/client/blocks.js +209 -205
- package/src/runtime/internal/client/composite.js +9 -0
- package/src/runtime/internal/client/events.js +219 -189
- package/src/runtime/internal/client/for.js +97 -13
- package/src/runtime/internal/client/if.js +11 -0
- package/src/runtime/internal/client/operations.js +7 -2
- package/src/runtime/internal/client/portal.js +15 -4
- package/src/runtime/internal/client/render.js +48 -6
- package/src/runtime/internal/client/runtime.js +101 -87
- package/src/runtime/internal/client/template.js +8 -5
- package/src/runtime/internal/client/try.js +42 -4
- package/src/runtime/internal/client/utils.js +18 -3
- package/src/runtime/internal/server/context.js +2 -0
- package/src/runtime/internal/server/index.js +39 -3
- package/src/runtime/internal/server/types.d.ts +21 -0
- package/src/runtime/map.js +37 -2
- package/src/runtime/set.js +22 -9
- package/src/utils/builders.js +1 -0
- package/tests/client/basic.test.ripple +21 -0
- package/tests/client/ref.test.ripple +33 -2
- package/types/index.d.ts +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** @import { Block } from '#client' */
|
|
2
|
+
|
|
1
3
|
import { branch, create_try_block, destroy_block, is_destroyed, resume_block } from './blocks.js';
|
|
2
4
|
import { TRY_BLOCK } from './constants.js';
|
|
3
5
|
import { next_sibling } from './operations.js';
|
|
@@ -13,13 +15,28 @@ import {
|
|
|
13
15
|
tracking,
|
|
14
16
|
} from './runtime.js';
|
|
15
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @param {Node} node
|
|
20
|
+
* @param {(anchor: Node) => void} fn
|
|
21
|
+
* @param {((anchor: Node, error: any) => void) | null} catch_fn
|
|
22
|
+
* @param {((anchor: Node) => void) | null} [pending_fn=null]
|
|
23
|
+
* @returns {void}
|
|
24
|
+
*/
|
|
16
25
|
export function try_block(node, fn, catch_fn, pending_fn = null) {
|
|
17
26
|
var anchor = node;
|
|
27
|
+
/** @type {Block | null} */
|
|
18
28
|
var b = null;
|
|
29
|
+
/** @type {Block | null} */
|
|
19
30
|
var suspended = null;
|
|
20
31
|
var pending_count = 0;
|
|
32
|
+
/** @type {DocumentFragment | null} */
|
|
21
33
|
var offscreen_fragment = null;
|
|
22
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {Block} block
|
|
37
|
+
* @param {DocumentFragment} fragment
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
23
40
|
function move_block(block, fragment) {
|
|
24
41
|
var state = block.s;
|
|
25
42
|
var node = state.start;
|
|
@@ -42,7 +59,7 @@ export function try_block(node, fn, catch_fn, pending_fn = null) {
|
|
|
42
59
|
move_block(b, offscreen_fragment);
|
|
43
60
|
|
|
44
61
|
b = branch(() => {
|
|
45
|
-
pending_fn(anchor);
|
|
62
|
+
/** @type {(anchor: Node) => void} */ (pending_fn)(anchor);
|
|
46
63
|
});
|
|
47
64
|
}
|
|
48
65
|
});
|
|
@@ -53,22 +70,26 @@ export function try_block(node, fn, catch_fn, pending_fn = null) {
|
|
|
53
70
|
if (b !== null) {
|
|
54
71
|
destroy_block(b);
|
|
55
72
|
}
|
|
56
|
-
anchor.before(offscreen_fragment);
|
|
73
|
+
/** @type {ChildNode} */ (anchor).before(/** @type {DocumentFragment} */ (offscreen_fragment));
|
|
57
74
|
offscreen_fragment = null;
|
|
58
|
-
resume_block(suspended);
|
|
75
|
+
resume_block(/** @type {Block} */ (suspended));
|
|
59
76
|
b = suspended;
|
|
60
77
|
suspended = null;
|
|
61
78
|
}
|
|
62
79
|
};
|
|
63
80
|
}
|
|
64
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @param {any} error
|
|
84
|
+
* @returns {void}
|
|
85
|
+
*/
|
|
65
86
|
function handle_error(error) {
|
|
66
87
|
if (b !== null) {
|
|
67
88
|
destroy_block(b);
|
|
68
89
|
}
|
|
69
90
|
|
|
70
91
|
b = branch(() => {
|
|
71
|
-
catch_fn(anchor, error);
|
|
92
|
+
/** @type {(anchor: Node, error: any) => void} */ (catch_fn)(anchor, error);
|
|
72
93
|
});
|
|
73
94
|
}
|
|
74
95
|
|
|
@@ -84,6 +105,9 @@ export function try_block(node, fn, catch_fn, pending_fn = null) {
|
|
|
84
105
|
}, state);
|
|
85
106
|
}
|
|
86
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @returns {() => void}
|
|
110
|
+
*/
|
|
87
111
|
export function suspend() {
|
|
88
112
|
var current = active_block;
|
|
89
113
|
|
|
@@ -98,6 +122,9 @@ export function suspend() {
|
|
|
98
122
|
throw new Error('Missing parent `try { ... } pending { ... }` statement');
|
|
99
123
|
}
|
|
100
124
|
|
|
125
|
+
/**
|
|
126
|
+
* @returns {void}
|
|
127
|
+
*/
|
|
101
128
|
function exit() {
|
|
102
129
|
set_tracking(false);
|
|
103
130
|
set_active_reaction(null);
|
|
@@ -105,6 +132,9 @@ function exit() {
|
|
|
105
132
|
set_active_component(null);
|
|
106
133
|
}
|
|
107
134
|
|
|
135
|
+
/**
|
|
136
|
+
* @returns {() => void}
|
|
137
|
+
*/
|
|
108
138
|
export function capture() {
|
|
109
139
|
var previous_tracking = tracking;
|
|
110
140
|
var previous_block = active_block;
|
|
@@ -121,6 +151,9 @@ export function capture() {
|
|
|
121
151
|
};
|
|
122
152
|
}
|
|
123
153
|
|
|
154
|
+
/**
|
|
155
|
+
* @returns {boolean}
|
|
156
|
+
*/
|
|
124
157
|
export function aborted() {
|
|
125
158
|
if (active_block === null) {
|
|
126
159
|
return true;
|
|
@@ -128,6 +161,11 @@ export function aborted() {
|
|
|
128
161
|
return is_destroyed(active_block);
|
|
129
162
|
}
|
|
130
163
|
|
|
164
|
+
/**
|
|
165
|
+
* @template T
|
|
166
|
+
* @param {Promise<T>} promise
|
|
167
|
+
* @returns {Promise<() => T>}
|
|
168
|
+
*/
|
|
131
169
|
export async function resume_context(promise) {
|
|
132
170
|
var restore = capture();
|
|
133
171
|
var value = await promise;
|
|
@@ -1,18 +1,33 @@
|
|
|
1
|
+
/** @type {typeof Object.getOwnPropertyDescriptor} */
|
|
1
2
|
export var get_descriptor = Object.getOwnPropertyDescriptor;
|
|
3
|
+
/** @type {typeof Object.getOwnPropertyDescriptors} */
|
|
2
4
|
export var get_descriptors = Object.getOwnPropertyDescriptors;
|
|
5
|
+
/** @type {typeof Array.from} */
|
|
3
6
|
export var array_from = Array.from;
|
|
7
|
+
/** @type {typeof Array.isArray} */
|
|
4
8
|
export var is_array = Array.isArray;
|
|
9
|
+
/** @type {typeof Object.defineProperty} */
|
|
5
10
|
export var define_property = Object.defineProperty;
|
|
11
|
+
/** @type {typeof Object.getPrototypeOf} */
|
|
6
12
|
export var get_prototype_of = Object.getPrototypeOf;
|
|
13
|
+
/** @type {typeof Object.values} */
|
|
7
14
|
export var object_values = Object.values;
|
|
15
|
+
/** @type {typeof Object.entries} */
|
|
8
16
|
export var object_entries = Object.entries;
|
|
17
|
+
/** @type {typeof Object.keys} */
|
|
9
18
|
export var object_keys = Object.keys;
|
|
19
|
+
/** @type {typeof Object.getOwnPropertySymbols} */
|
|
10
20
|
export var get_own_property_symbols = Object.getOwnPropertySymbols;
|
|
21
|
+
/** @type {typeof structuredClone} */
|
|
11
22
|
export var structured_clone = structuredClone;
|
|
12
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Creates a text node that serves as an anchor point in the DOM.
|
|
26
|
+
* @returns {Text}
|
|
27
|
+
*/
|
|
13
28
|
export function create_anchor() {
|
|
14
29
|
var t = document.createTextNode('');
|
|
15
|
-
t.__t = '';
|
|
30
|
+
/** @type {any} */ (t).__t = '';
|
|
16
31
|
return t;
|
|
17
32
|
}
|
|
18
33
|
|
|
@@ -26,9 +41,9 @@ export function is_positive_integer(value) {
|
|
|
26
41
|
|
|
27
42
|
/**
|
|
28
43
|
* Checks if an object is a tracked object (has a numeric 'f' property).
|
|
29
|
-
* @param {
|
|
44
|
+
* @param {any} v - The object to check.
|
|
30
45
|
* @returns {boolean}
|
|
31
46
|
*/
|
|
32
47
|
export function is_tracked_object(v) {
|
|
33
|
-
return typeof v === 'object' && v !== null && typeof v.f === 'number';
|
|
48
|
+
return typeof v === 'object' && v !== null && typeof /** @type {any} */ (v).f === 'number';
|
|
34
49
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Derived } from '#
|
|
1
|
+
/** @import { Component, Derived } from '#server' */
|
|
2
2
|
|
|
3
3
|
import { DERIVED, UNINITIALIZED } from '../client/constants';
|
|
4
4
|
import { is_tracked_object } from '../client/utils';
|
|
@@ -8,6 +8,7 @@ import { is_boolean_attribute } from '../../../compiler/utils';
|
|
|
8
8
|
|
|
9
9
|
export { escape };
|
|
10
10
|
|
|
11
|
+
/** @type {Component | null} */
|
|
11
12
|
export let active_component = null;
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -26,17 +27,29 @@ const replacements = {
|
|
|
26
27
|
class Output {
|
|
27
28
|
head = '';
|
|
28
29
|
body = '';
|
|
30
|
+
/** @type {Output | null} */
|
|
29
31
|
#parent = null;
|
|
30
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @param {Output | null} parent
|
|
35
|
+
*/
|
|
31
36
|
constructor(parent) {
|
|
32
37
|
this.#parent = parent;
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} str
|
|
42
|
+
* @returns {void}
|
|
43
|
+
*/
|
|
35
44
|
push(str) {
|
|
36
45
|
this.body += str;
|
|
37
46
|
}
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {((output: Output, props: Record<string, any>) => void | Promise<void>) & { async?: boolean }} component
|
|
51
|
+
* @returns {Promise<{head: string, body: string}>}
|
|
52
|
+
*/
|
|
40
53
|
export async function render(component) {
|
|
41
54
|
const output = new Output(null);
|
|
42
55
|
|
|
@@ -52,6 +65,9 @@ export async function render(component) {
|
|
|
52
65
|
return { head, body };
|
|
53
66
|
}
|
|
54
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @returns {void}
|
|
70
|
+
*/
|
|
55
71
|
export function push_component() {
|
|
56
72
|
var component = {
|
|
57
73
|
c: null,
|
|
@@ -60,15 +76,26 @@ export function push_component() {
|
|
|
60
76
|
active_component = component;
|
|
61
77
|
}
|
|
62
78
|
|
|
79
|
+
/**
|
|
80
|
+
* @returns {void}
|
|
81
|
+
*/
|
|
63
82
|
export function pop_component() {
|
|
64
|
-
var component = active_component;
|
|
65
|
-
active_component = component
|
|
83
|
+
var component = /** @type {Component} */ (active_component);
|
|
84
|
+
active_component = component;
|
|
66
85
|
}
|
|
67
86
|
|
|
87
|
+
/**
|
|
88
|
+
* @param {() => any} fn
|
|
89
|
+
* @returns {Promise<void>}
|
|
90
|
+
*/
|
|
68
91
|
export async function async(fn) {
|
|
69
92
|
// TODO
|
|
70
93
|
}
|
|
71
94
|
|
|
95
|
+
/**
|
|
96
|
+
* @param {Derived} tracked
|
|
97
|
+
* @returns {any}
|
|
98
|
+
*/
|
|
72
99
|
function get_derived(tracked) {
|
|
73
100
|
let v = tracked.v;
|
|
74
101
|
|
|
@@ -79,6 +106,10 @@ function get_derived(tracked) {
|
|
|
79
106
|
return v;
|
|
80
107
|
}
|
|
81
108
|
|
|
109
|
+
/**
|
|
110
|
+
* @param {any} tracked
|
|
111
|
+
* @returns {any}
|
|
112
|
+
*/
|
|
82
113
|
export function get(tracked) {
|
|
83
114
|
// reflect back the value if it's not boxed
|
|
84
115
|
if (!is_tracked_object(tracked)) {
|
|
@@ -105,6 +136,11 @@ export function attr(name, value, is_boolean = false) {
|
|
|
105
136
|
return ` ${name}${assignment}`;
|
|
106
137
|
}
|
|
107
138
|
|
|
139
|
+
/**
|
|
140
|
+
* @param {Record<string, any>} attrs
|
|
141
|
+
* @param {string | undefined} css_hash
|
|
142
|
+
* @returns {string}
|
|
143
|
+
*/
|
|
108
144
|
export function spread_attrs(attrs, css_hash) {
|
|
109
145
|
let attr_str = '';
|
|
110
146
|
let name;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Context } from './context.js';
|
|
2
|
+
|
|
3
|
+
export type Component = {
|
|
4
|
+
c: null | Map<Context<any>, any>;
|
|
5
|
+
p: null | Component;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export type Derived = {
|
|
10
|
+
a: { get?: Function, set?: Function };
|
|
11
|
+
co: null | Component;
|
|
12
|
+
f: number;
|
|
13
|
+
fn: Function;
|
|
14
|
+
v: any;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type Tracked = {
|
|
18
|
+
a: { get?: Function, set?: Function };
|
|
19
|
+
f: number;
|
|
20
|
+
v: any;
|
|
21
|
+
};
|
package/src/runtime/map.js
CHANGED
|
@@ -41,20 +41,27 @@ export class TrackedMap extends Map {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @returns {void}
|
|
46
|
+
*/
|
|
44
47
|
#init() {
|
|
45
48
|
var proto = TrackedMap.prototype;
|
|
46
49
|
var map_proto = Map.prototype;
|
|
47
50
|
|
|
48
51
|
for (const method of introspect_methods) {
|
|
49
|
-
proto[method] = function (...v) {
|
|
52
|
+
/** @type {any} */ (proto)[method] = function (/** @type {...any} */ ...v) {
|
|
50
53
|
this.size;
|
|
51
54
|
this.#read_all();
|
|
52
55
|
|
|
53
|
-
return map_proto[method].apply(this, v);
|
|
56
|
+
return /** @type {any} */ (map_proto)[method].apply(this, v);
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @param {K} key
|
|
63
|
+
* @returns {V | undefined}
|
|
64
|
+
*/
|
|
58
65
|
get(key) {
|
|
59
66
|
var tracked_items = this.#tracked_items;
|
|
60
67
|
var t = tracked_items.get(key);
|
|
@@ -69,6 +76,10 @@ export class TrackedMap extends Map {
|
|
|
69
76
|
return super.get(key);
|
|
70
77
|
}
|
|
71
78
|
|
|
79
|
+
/**
|
|
80
|
+
* @param {K} key
|
|
81
|
+
* @returns {boolean}
|
|
82
|
+
*/
|
|
72
83
|
has(key) {
|
|
73
84
|
var has = super.has(key);
|
|
74
85
|
var tracked_items = this.#tracked_items;
|
|
@@ -87,6 +98,11 @@ export class TrackedMap extends Map {
|
|
|
87
98
|
return has;
|
|
88
99
|
}
|
|
89
100
|
|
|
101
|
+
/**
|
|
102
|
+
* @param {K} key
|
|
103
|
+
* @param {V} value
|
|
104
|
+
* @returns {this}
|
|
105
|
+
*/
|
|
90
106
|
set(key, value) {
|
|
91
107
|
var block = this.#block;
|
|
92
108
|
var tracked_items = this.#tracked_items;
|
|
@@ -105,6 +121,10 @@ export class TrackedMap extends Map {
|
|
|
105
121
|
return this;
|
|
106
122
|
}
|
|
107
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @param {K} key
|
|
126
|
+
* @returns {boolean}
|
|
127
|
+
*/
|
|
108
128
|
delete(key) {
|
|
109
129
|
var block = this.#block;
|
|
110
130
|
var tracked_items = this.#tracked_items;
|
|
@@ -120,6 +140,9 @@ export class TrackedMap extends Map {
|
|
|
120
140
|
return result;
|
|
121
141
|
}
|
|
122
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @returns {void}
|
|
145
|
+
*/
|
|
123
146
|
clear() {
|
|
124
147
|
var block = this.#block;
|
|
125
148
|
|
|
@@ -136,21 +159,33 @@ export class TrackedMap extends Map {
|
|
|
136
159
|
set(this.#tracked_size, 0, block);
|
|
137
160
|
}
|
|
138
161
|
|
|
162
|
+
/**
|
|
163
|
+
* @returns {MapIterator<K>}
|
|
164
|
+
*/
|
|
139
165
|
keys() {
|
|
140
166
|
this.size;
|
|
141
167
|
return super.keys();
|
|
142
168
|
}
|
|
143
169
|
|
|
170
|
+
/**
|
|
171
|
+
* @returns {void}
|
|
172
|
+
*/
|
|
144
173
|
#read_all() {
|
|
145
174
|
for (const [, t] of this.#tracked_items) {
|
|
146
175
|
get(t);
|
|
147
176
|
}
|
|
148
177
|
}
|
|
149
178
|
|
|
179
|
+
/**
|
|
180
|
+
* @returns {number}
|
|
181
|
+
*/
|
|
150
182
|
get size() {
|
|
151
183
|
return get(this.#tracked_size);
|
|
152
184
|
}
|
|
153
185
|
|
|
186
|
+
/**
|
|
187
|
+
* @returns {Array<[K, V]>}
|
|
188
|
+
*/
|
|
154
189
|
toJSON() {
|
|
155
190
|
this.size;
|
|
156
191
|
this.#read_all();
|
package/src/runtime/set.js
CHANGED
|
@@ -23,7 +23,7 @@ export class TrackedSet extends Set {
|
|
|
23
23
|
#block;
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* @param {Iterable<T>} iterable
|
|
26
|
+
* @param {Iterable<T>} [iterable]
|
|
27
27
|
*/
|
|
28
28
|
constructor(iterable) {
|
|
29
29
|
super();
|
|
@@ -45,6 +45,9 @@ export class TrackedSet extends Set {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @returns {void}
|
|
50
|
+
*/
|
|
48
51
|
#init() {
|
|
49
52
|
var proto = TrackedSet.prototype;
|
|
50
53
|
var set_proto = Set.prototype;
|
|
@@ -54,11 +57,10 @@ export class TrackedSet extends Set {
|
|
|
54
57
|
continue;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
/** @
|
|
58
|
-
proto[method] = function (...v) {
|
|
60
|
+
/** @type {any} */ (proto)[method] = function (/** @type {...any} */ ...v) {
|
|
59
61
|
this.size;
|
|
60
62
|
|
|
61
|
-
return set_proto[method].apply(this, v);
|
|
63
|
+
return /** @type {any} */ (set_proto)[method].apply(this, v);
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -67,14 +69,14 @@ export class TrackedSet extends Set {
|
|
|
67
69
|
continue;
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
proto[method] = function (other, ...v) {
|
|
72
|
+
/** @type {any} */ (proto)[method] = function (/** @type {any} */ other, /** @type {...any} */ ...v) {
|
|
71
73
|
this.size;
|
|
72
74
|
|
|
73
75
|
if (other instanceof TrackedSet) {
|
|
74
76
|
other.size;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
return set_proto[method].apply(this, [other, ...v]);
|
|
79
|
+
return /** @type {any} */ (set_proto)[method].apply(this, [other, ...v]);
|
|
78
80
|
};
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -83,14 +85,14 @@ export class TrackedSet extends Set {
|
|
|
83
85
|
continue;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
proto[method] = function (other, ...v) {
|
|
88
|
+
/** @type {any} */ (proto)[method] = function (/** @type {any} */ other, /** @type {...any} */ ...v) {
|
|
87
89
|
this.size;
|
|
88
90
|
|
|
89
91
|
if (other instanceof TrackedSet) {
|
|
90
92
|
other.size;
|
|
91
93
|
}
|
|
92
94
|
|
|
93
|
-
return new TrackedSet(set_proto[method].apply(this, [other, ...v]));
|
|
95
|
+
return new TrackedSet(/** @type {any} */ (set_proto)[method].apply(this, [other, ...v]));
|
|
94
96
|
};
|
|
95
97
|
}
|
|
96
98
|
}
|
|
@@ -124,7 +126,9 @@ export class TrackedSet extends Set {
|
|
|
124
126
|
|
|
125
127
|
var t = this.#tracked_items.get(value);
|
|
126
128
|
|
|
127
|
-
|
|
129
|
+
if (t) {
|
|
130
|
+
increment(t, block);
|
|
131
|
+
}
|
|
128
132
|
this.#tracked_items.delete(value);
|
|
129
133
|
set(this.#tracked_size, super.size, block);
|
|
130
134
|
|
|
@@ -154,6 +158,9 @@ export class TrackedSet extends Set {
|
|
|
154
158
|
return has;
|
|
155
159
|
}
|
|
156
160
|
|
|
161
|
+
/**
|
|
162
|
+
* @returns {void}
|
|
163
|
+
*/
|
|
157
164
|
clear() {
|
|
158
165
|
var block = this.#block;
|
|
159
166
|
|
|
@@ -170,10 +177,16 @@ export class TrackedSet extends Set {
|
|
|
170
177
|
set(this.#tracked_size, 0, block);
|
|
171
178
|
}
|
|
172
179
|
|
|
180
|
+
/**
|
|
181
|
+
* @returns {number}
|
|
182
|
+
*/
|
|
173
183
|
get size() {
|
|
174
184
|
return get(this.#tracked_size);
|
|
175
185
|
}
|
|
176
186
|
|
|
187
|
+
/**
|
|
188
|
+
* @returns {T[]}
|
|
189
|
+
*/
|
|
177
190
|
toJSON() {
|
|
178
191
|
this.size;
|
|
179
192
|
|
package/src/utils/builders.js
CHANGED
|
@@ -1498,6 +1498,27 @@ describe('basic client', () => {
|
|
|
1498
1498
|
expect(countDiv.textContent).toBe('3');
|
|
1499
1499
|
});
|
|
1500
1500
|
|
|
1501
|
+
it('passes in next and prev to track set function', () => {
|
|
1502
|
+
let logs = [];
|
|
1503
|
+
|
|
1504
|
+
component App() {
|
|
1505
|
+
let count = track(0, v => v, (next, prev) => {
|
|
1506
|
+
logs.push(prev, next);
|
|
1507
|
+
return next;
|
|
1508
|
+
});
|
|
1509
|
+
|
|
1510
|
+
<button onClick={() => { @count++ }}>{'Increment'}</button>
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
render(App);
|
|
1514
|
+
|
|
1515
|
+
const button = container.querySelector('button');
|
|
1516
|
+
button.click();
|
|
1517
|
+
flushSync();
|
|
1518
|
+
|
|
1519
|
+
expect(logs).toEqual([0, 1]);
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1501
1522
|
it('works as a reactive TrackedArray when constructed using # syntactic sugar', () => {
|
|
1502
1523
|
component App() {
|
|
1503
1524
|
const array = #[1, 2, 3];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { mount, flushSync, TrackedArray } from 'ripple';
|
|
2
|
+
import { mount, flushSync, TrackedArray, track, createRefKey } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('refs', () => {
|
|
5
5
|
let container;
|
|
@@ -54,5 +54,36 @@ describe('refs', () => {
|
|
|
54
54
|
flushSync();
|
|
55
55
|
|
|
56
56
|
expect(_node).toBe(document.querySelector('pre'));
|
|
57
|
-
})
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should handle spreading into composite refs', () => {
|
|
60
|
+
let logs: string[] = [];
|
|
61
|
+
|
|
62
|
+
component App() {
|
|
63
|
+
let value = track('test');
|
|
64
|
+
|
|
65
|
+
function inputRef(node) {
|
|
66
|
+
logs.push('ref called');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const props = {
|
|
70
|
+
id: "example",
|
|
71
|
+
@value,
|
|
72
|
+
[createRefKey()]: inputRef
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
<input type="text" {...props} />
|
|
76
|
+
|
|
77
|
+
<Input {...props} />
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
component Input({ id, value, ...rest }) {
|
|
81
|
+
<input type="text" {id} {value} {...rest} />
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
render(App);
|
|
85
|
+
flushSync();
|
|
86
|
+
|
|
87
|
+
expect(logs).toEqual(['ref called', 'ref called']);
|
|
88
|
+
});
|
|
58
89
|
});
|
package/types/index.d.ts
CHANGED
|
@@ -86,7 +86,7 @@ type RestKeys<T, K extends readonly (keyof T)[]> = Expand<Omit<T, K[number]>>;
|
|
|
86
86
|
type SplitResult<T extends Props, K extends readonly (keyof T)[]> =
|
|
87
87
|
[...PickKeys<T, K>, Tracked<RestKeys<T, K>>];
|
|
88
88
|
|
|
89
|
-
export declare function track<V>(value?: V | (() => V), get?: (v: V) => V, set?: (
|
|
89
|
+
export declare function track<V>(value?: V | (() => V), get?: (v: V) => V, set?: (next: V, prev: V) => V): Tracked<V>;
|
|
90
90
|
|
|
91
91
|
export declare function trackSplit<V extends Props, const K extends readonly (keyof V)[]>(
|
|
92
92
|
value: V,
|