ripple 0.2.27 → 0.2.28
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 +1 -1
- package/src/compiler/phases/1-parse/index.js +35 -0
- package/src/compiler/phases/2-analyze/index.js +18 -8
- package/src/compiler/phases/3-transform/index.js +48 -1
- package/src/runtime/array.js +47 -4
- package/src/runtime/internal/client/blocks.js +51 -4
- package/src/runtime/internal/client/runtime.js +57 -15
- package/src/runtime/internal/client/types.d.ts +6 -5
package/package.json
CHANGED
|
@@ -90,6 +90,41 @@ function RipplePlugin(config) {
|
|
|
90
90
|
|
|
91
91
|
jsx_parseAttribute() {
|
|
92
92
|
let node = this.startNode();
|
|
93
|
+
const lookahead = this.lookahead();
|
|
94
|
+
|
|
95
|
+
if (lookahead.type?.label === ':') {
|
|
96
|
+
let id = this.startNode();
|
|
97
|
+
id.name = this.value;
|
|
98
|
+
node.name = id;
|
|
99
|
+
this.next();
|
|
100
|
+
this.finishNode(id, 'Identifier');
|
|
101
|
+
|
|
102
|
+
if (this.lookahead().value !== '=') {
|
|
103
|
+
this.unexpected();
|
|
104
|
+
}
|
|
105
|
+
this.next();
|
|
106
|
+
if (this.lookahead().type !== tt.braceL) {
|
|
107
|
+
this.unexpected();
|
|
108
|
+
}
|
|
109
|
+
this.next();
|
|
110
|
+
const value = this.jsx_parseAttributeValue();
|
|
111
|
+
const expression = value.expression;
|
|
112
|
+
node.get = null;
|
|
113
|
+
node.set = null;
|
|
114
|
+
|
|
115
|
+
if (expression.type == 'SequenceExpression') {
|
|
116
|
+
node.get = expression.expressions[0];
|
|
117
|
+
node.set = expression.expressions[1];
|
|
118
|
+
if (expression.expressions.length > 2) {
|
|
119
|
+
this.unexpected();
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
node.get = expression;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return this.finishNode(node, 'AccessorAttribute');
|
|
126
|
+
}
|
|
127
|
+
|
|
93
128
|
if (this.eat(tt.braceL)) {
|
|
94
129
|
if (this.type.label === '@') {
|
|
95
130
|
this.next();
|
|
@@ -321,12 +321,7 @@ const visitors = {
|
|
|
321
321
|
binding.transform = {
|
|
322
322
|
read: (_) => b.call('$.get_computed', path.node),
|
|
323
323
|
assign: (node, value) => {
|
|
324
|
-
return b.call(
|
|
325
|
-
'$.set',
|
|
326
|
-
path.node,
|
|
327
|
-
value,
|
|
328
|
-
b.id('__block'),
|
|
329
|
-
);
|
|
324
|
+
return b.call('$.set', path.node, value, b.id('__block'));
|
|
330
325
|
},
|
|
331
326
|
update: (_) =>
|
|
332
327
|
b.call(
|
|
@@ -451,6 +446,12 @@ const visitors = {
|
|
|
451
446
|
}
|
|
452
447
|
}
|
|
453
448
|
}
|
|
449
|
+
} else if (attr.type === 'AccessorAttribute') {
|
|
450
|
+
error(
|
|
451
|
+
'Accessor props are not supported on DOM elements',
|
|
452
|
+
state.analysis.module.filename,
|
|
453
|
+
attr,
|
|
454
|
+
);
|
|
454
455
|
}
|
|
455
456
|
}
|
|
456
457
|
} else {
|
|
@@ -459,6 +460,15 @@ const visitors = {
|
|
|
459
460
|
if (attr.name.type === 'Identifier') {
|
|
460
461
|
attribute_names.add(attr.name);
|
|
461
462
|
}
|
|
463
|
+
} else if (attr.type === 'AccessorAttribute') {
|
|
464
|
+
if (!attr.name.name.startsWith('$')) {
|
|
465
|
+
error(
|
|
466
|
+
'Accessor props must always be $ prefixed as they are reactive',
|
|
467
|
+
state.analysis.module.filename,
|
|
468
|
+
attr,
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
attribute_names.add(attr.name);
|
|
462
472
|
}
|
|
463
473
|
}
|
|
464
474
|
|
|
@@ -472,7 +482,7 @@ const visitors = {
|
|
|
472
482
|
if (implicit_children) {
|
|
473
483
|
error(
|
|
474
484
|
'Cannot have both implicit and explicit children',
|
|
475
|
-
|
|
485
|
+
state.analysis.module.filename,
|
|
476
486
|
node,
|
|
477
487
|
);
|
|
478
488
|
}
|
|
@@ -482,7 +492,7 @@ const visitors = {
|
|
|
482
492
|
if (explicit_children) {
|
|
483
493
|
error(
|
|
484
494
|
'Cannot have both implicit and explicit children',
|
|
485
|
-
|
|
495
|
+
state.analysis.module.filename,
|
|
486
496
|
node,
|
|
487
497
|
);
|
|
488
498
|
}
|
|
@@ -617,6 +617,52 @@ const visitors = {
|
|
|
617
617
|
);
|
|
618
618
|
} else if (attr.type === 'UseAttribute') {
|
|
619
619
|
props.push(b.prop('init', b.call('$.use_prop'), visit(attr.argument, state), true));
|
|
620
|
+
} else if (attr.type === 'AccessorAttribute') {
|
|
621
|
+
// # means it's an accessor to the runtime
|
|
622
|
+
tracked.push(b.literal('#' + attr.name.name));
|
|
623
|
+
let get_expr;
|
|
624
|
+
|
|
625
|
+
if (
|
|
626
|
+
attr.get.type === 'FunctionExpression' ||
|
|
627
|
+
attr.get.type === 'ArrowFunctionExpression'
|
|
628
|
+
) {
|
|
629
|
+
get_expr = context.state.scope.generate(attr.name.name + '_get');
|
|
630
|
+
|
|
631
|
+
state.init.push(b.const(get_expr, visit(attr.get, state)));
|
|
632
|
+
} else {
|
|
633
|
+
get_expr = visit(attr.get, state);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
props.push(
|
|
637
|
+
b.prop('get', attr.name, b.function(null, [], b.block([b.return(b.call(get_expr))]))),
|
|
638
|
+
);
|
|
639
|
+
|
|
640
|
+
if (attr.set) {
|
|
641
|
+
let set_expr;
|
|
642
|
+
|
|
643
|
+
if (
|
|
644
|
+
attr.set.type === 'FunctionExpression' ||
|
|
645
|
+
attr.set.type === 'ArrowFunctionExpression'
|
|
646
|
+
) {
|
|
647
|
+
set_expr = context.state.scope.generate(attr.name.name + '_set');
|
|
648
|
+
|
|
649
|
+
state.init.push(b.const(set_expr, visit(attr.set, state)));
|
|
650
|
+
} else {
|
|
651
|
+
set_expr = visit(attr.set, state);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
props.push(
|
|
655
|
+
b.prop(
|
|
656
|
+
'set',
|
|
657
|
+
attr.name,
|
|
658
|
+
b.function(
|
|
659
|
+
null,
|
|
660
|
+
[b.id('__value')],
|
|
661
|
+
b.block([b.return(b.call(set_expr, b.id('__value')))]),
|
|
662
|
+
),
|
|
663
|
+
),
|
|
664
|
+
);
|
|
665
|
+
}
|
|
620
666
|
} else {
|
|
621
667
|
throw new Error('TODO');
|
|
622
668
|
}
|
|
@@ -802,7 +848,8 @@ const visitors = {
|
|
|
802
848
|
if (
|
|
803
849
|
left.type === 'MemberExpression' &&
|
|
804
850
|
left.property.type === 'Identifier' &&
|
|
805
|
-
is_tracked_name(left.property.name)
|
|
851
|
+
is_tracked_name(left.property.name) &&
|
|
852
|
+
left.property.name !== '$length'
|
|
806
853
|
) {
|
|
807
854
|
return b.call(
|
|
808
855
|
'$.set_property',
|
package/src/runtime/array.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** @import { Block } from '#client' */
|
|
2
|
+
|
|
1
3
|
import { TRACKED_OBJECT } from './internal/client/constants.js';
|
|
2
4
|
import { get, increment, scope, set, tracked } from './internal/client/runtime.js';
|
|
3
5
|
|
|
@@ -35,6 +37,16 @@ const introspect_methods = [
|
|
|
35
37
|
|
|
36
38
|
let init = false;
|
|
37
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @param {Block | null} block
|
|
42
|
+
* @throws {Error}
|
|
43
|
+
*/
|
|
44
|
+
function check_block(block) {
|
|
45
|
+
if (block === null) {
|
|
46
|
+
throw new Error('Cannot set $length outside of a reactive context');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
export class RippleArray extends Array {
|
|
39
51
|
#tracked_elements = [];
|
|
40
52
|
#tracked_index;
|
|
@@ -51,6 +63,7 @@ export class RippleArray extends Array {
|
|
|
51
63
|
super(...elements);
|
|
52
64
|
|
|
53
65
|
var block = scope();
|
|
66
|
+
check_block(block);
|
|
54
67
|
var tracked_elements = this.#tracked_elements;
|
|
55
68
|
|
|
56
69
|
for (var i = 0; i < this.length; i++) {
|
|
@@ -79,6 +92,7 @@ export class RippleArray extends Array {
|
|
|
79
92
|
|
|
80
93
|
fill() {
|
|
81
94
|
var block = scope();
|
|
95
|
+
check_block(block);
|
|
82
96
|
var tracked_elements = this.#tracked_elements;
|
|
83
97
|
|
|
84
98
|
super.fill();
|
|
@@ -89,6 +103,7 @@ export class RippleArray extends Array {
|
|
|
89
103
|
|
|
90
104
|
reverse() {
|
|
91
105
|
var block = scope();
|
|
106
|
+
check_block(block);
|
|
92
107
|
var tracked_elements = this.#tracked_elements;
|
|
93
108
|
|
|
94
109
|
super.reverse();
|
|
@@ -99,6 +114,7 @@ export class RippleArray extends Array {
|
|
|
99
114
|
|
|
100
115
|
sort(fn) {
|
|
101
116
|
var block = scope();
|
|
117
|
+
check_block(block);
|
|
102
118
|
var tracked_elements = this.#tracked_elements;
|
|
103
119
|
|
|
104
120
|
super.sort(fn);
|
|
@@ -107,8 +123,13 @@ export class RippleArray extends Array {
|
|
|
107
123
|
}
|
|
108
124
|
}
|
|
109
125
|
|
|
126
|
+
/**
|
|
127
|
+
* @param {...any} elements
|
|
128
|
+
* @returns {number}
|
|
129
|
+
*/
|
|
110
130
|
unshift(...elements) {
|
|
111
131
|
var block = scope();
|
|
132
|
+
check_block(block);
|
|
112
133
|
var tracked_elements = this.#tracked_elements;
|
|
113
134
|
|
|
114
135
|
super.unshift(...elements);
|
|
@@ -117,11 +138,14 @@ export class RippleArray extends Array {
|
|
|
117
138
|
}
|
|
118
139
|
tracked_elements.unshift(...elements.map(() => tracked(0, block)));
|
|
119
140
|
|
|
120
|
-
|
|
141
|
+
var length = this.length;
|
|
142
|
+
set(this.#tracked_index, length, block);
|
|
143
|
+
return length;
|
|
121
144
|
}
|
|
122
145
|
|
|
123
146
|
shift() {
|
|
124
147
|
var block = scope();
|
|
148
|
+
check_block(block);
|
|
125
149
|
var tracked_elements = this.#tracked_elements;
|
|
126
150
|
|
|
127
151
|
super.shift();
|
|
@@ -133,8 +157,13 @@ export class RippleArray extends Array {
|
|
|
133
157
|
set(this.#tracked_index, this.length, block);
|
|
134
158
|
}
|
|
135
159
|
|
|
160
|
+
/**
|
|
161
|
+
* @param {...any} elements
|
|
162
|
+
* @returns {number}
|
|
163
|
+
*/
|
|
136
164
|
push(...elements) {
|
|
137
165
|
var block = scope();
|
|
166
|
+
check_block(block);
|
|
138
167
|
var start_index = this.length;
|
|
139
168
|
var tracked_elements = this.#tracked_elements;
|
|
140
169
|
|
|
@@ -143,11 +172,14 @@ export class RippleArray extends Array {
|
|
|
143
172
|
for (var i = 0; i < elements.length; i++) {
|
|
144
173
|
tracked_elements[start_index + i] = tracked(0, block);
|
|
145
174
|
}
|
|
175
|
+
var length = this.length;
|
|
146
176
|
set(this.#tracked_index, this.length, block);
|
|
177
|
+
return length;
|
|
147
178
|
}
|
|
148
179
|
|
|
149
180
|
pop() {
|
|
150
181
|
var block = scope();
|
|
182
|
+
check_block(block);
|
|
151
183
|
var tracked_elements = this.#tracked_elements;
|
|
152
184
|
|
|
153
185
|
super.pop();
|
|
@@ -159,8 +191,15 @@ export class RippleArray extends Array {
|
|
|
159
191
|
set(this.#tracked_index, this.length, block);
|
|
160
192
|
}
|
|
161
193
|
|
|
194
|
+
/**
|
|
195
|
+
* @param {number} start
|
|
196
|
+
* @param {number} [delete_count]
|
|
197
|
+
* @param {...any} elements
|
|
198
|
+
* @returns {any[]}
|
|
199
|
+
*/
|
|
162
200
|
splice(start, delete_count, ...elements) {
|
|
163
201
|
var block = scope();
|
|
202
|
+
check_block(block);
|
|
164
203
|
var tracked_elements = this.#tracked_elements;
|
|
165
204
|
|
|
166
205
|
super.splice(start, delete_count, ...elements);
|
|
@@ -182,6 +221,7 @@ export class RippleArray extends Array {
|
|
|
182
221
|
|
|
183
222
|
set $length(length) {
|
|
184
223
|
var block = scope();
|
|
224
|
+
check_block(block);
|
|
185
225
|
var tracked_elements = this.#tracked_elements;
|
|
186
226
|
|
|
187
227
|
if (length !== this.$length) {
|
|
@@ -189,13 +229,12 @@ export class RippleArray extends Array {
|
|
|
189
229
|
increment(tracked_elements[i], block);
|
|
190
230
|
}
|
|
191
231
|
this.length = length;
|
|
232
|
+
set(this.#tracked_index, length, block);
|
|
192
233
|
tracked_elements.length = length;
|
|
193
|
-
|
|
194
|
-
return true;
|
|
195
234
|
}
|
|
196
|
-
return false;
|
|
197
235
|
}
|
|
198
236
|
|
|
237
|
+
/** @param {number} _ */
|
|
199
238
|
set length(_) {
|
|
200
239
|
throw new Error('Cannot set length on RippleArray, use $length instead');
|
|
201
240
|
}
|
|
@@ -206,6 +245,10 @@ export class RippleArray extends Array {
|
|
|
206
245
|
}
|
|
207
246
|
}
|
|
208
247
|
|
|
248
|
+
/**
|
|
249
|
+
* @param {RippleArray} array
|
|
250
|
+
* @returns {any[]}
|
|
251
|
+
*/
|
|
209
252
|
export function get_all_elements(array) {
|
|
210
253
|
var tracked_elements = array[TRACKED_OBJECT];
|
|
211
254
|
var arr = [];
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
active_block,
|
|
19
19
|
active_component,
|
|
20
20
|
active_reaction,
|
|
21
|
+
is_block_dirty,
|
|
21
22
|
run_block,
|
|
22
23
|
run_teardown,
|
|
23
24
|
schedule_update,
|
|
@@ -93,21 +94,28 @@ export function async(fn) {
|
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @param {Element} element
|
|
99
|
+
* @param {() => (element: Element) => (void | (() => void))} get_fn
|
|
100
|
+
* @returns {Block}
|
|
101
|
+
*/
|
|
96
102
|
export function use(element, get_fn) {
|
|
97
|
-
|
|
103
|
+
/** @type {(element: Element) => (void | (() => void) | undefined)} */
|
|
104
|
+
var use_fn;
|
|
105
|
+
/** @type {Block | null} */
|
|
98
106
|
var e;
|
|
99
107
|
|
|
100
108
|
return block(RENDER_BLOCK, () => {
|
|
101
|
-
if (
|
|
109
|
+
if (use_fn !== (use_fn = get_fn())) {
|
|
102
110
|
if (e) {
|
|
103
111
|
destroy_block(e);
|
|
104
112
|
e = null;
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
if (
|
|
115
|
+
if (use_fn) {
|
|
108
116
|
e = branch(() => {
|
|
109
117
|
effect(() => {
|
|
110
|
-
return
|
|
118
|
+
return use_fn(element);
|
|
111
119
|
});
|
|
112
120
|
});
|
|
113
121
|
}
|
|
@@ -115,14 +123,27 @@ export function use(element, get_fn) {
|
|
|
115
123
|
});
|
|
116
124
|
}
|
|
117
125
|
|
|
126
|
+
/**
|
|
127
|
+
* @param {() => void} fn
|
|
128
|
+
* @returns {Block}
|
|
129
|
+
*/
|
|
118
130
|
export function root(fn) {
|
|
119
131
|
return block(ROOT_BLOCK, fn);
|
|
120
132
|
}
|
|
121
133
|
|
|
134
|
+
/**
|
|
135
|
+
* @param {() => void} fn
|
|
136
|
+
* @param {any} state
|
|
137
|
+
* @returns {Block}
|
|
138
|
+
*/
|
|
122
139
|
export function create_try_block(fn, state) {
|
|
123
140
|
return block(TRY_BLOCK, fn, state);
|
|
124
141
|
}
|
|
125
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @param {Block} block
|
|
145
|
+
* @param {Block} parent_block
|
|
146
|
+
*/
|
|
126
147
|
function push_block(block, parent_block) {
|
|
127
148
|
var parent_last = parent_block.last;
|
|
128
149
|
if (parent_last === null) {
|
|
@@ -174,6 +195,10 @@ export function block(flags, fn, state = null) {
|
|
|
174
195
|
return block;
|
|
175
196
|
}
|
|
176
197
|
|
|
198
|
+
/**
|
|
199
|
+
* @param {Block} parent
|
|
200
|
+
* @param {boolean} [remove_dom]
|
|
201
|
+
*/
|
|
177
202
|
export function destroy_block_children(parent, remove_dom = false) {
|
|
178
203
|
var block = parent.first;
|
|
179
204
|
parent.first = parent.last = null;
|
|
@@ -187,6 +212,10 @@ export function destroy_block_children(parent, remove_dom = false) {
|
|
|
187
212
|
}
|
|
188
213
|
}
|
|
189
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @param {Block} parent
|
|
217
|
+
* @param {boolean} [remove_dom]
|
|
218
|
+
*/
|
|
190
219
|
export function destroy_non_branch_children(parent, remove_dom = false) {
|
|
191
220
|
var block = parent.first;
|
|
192
221
|
|
|
@@ -207,6 +236,9 @@ export function destroy_non_branch_children(parent, remove_dom = false) {
|
|
|
207
236
|
}
|
|
208
237
|
}
|
|
209
238
|
|
|
239
|
+
/**
|
|
240
|
+
* @param {Block} block
|
|
241
|
+
*/
|
|
210
242
|
export function unlink_block(block) {
|
|
211
243
|
var parent = block.p;
|
|
212
244
|
var prev = block.prev;
|
|
@@ -221,6 +253,9 @@ export function unlink_block(block) {
|
|
|
221
253
|
}
|
|
222
254
|
}
|
|
223
255
|
|
|
256
|
+
/**
|
|
257
|
+
* @param {Block} block
|
|
258
|
+
*/
|
|
224
259
|
export function pause_block(block) {
|
|
225
260
|
if ((block.f & PAUSED) !== 0) {
|
|
226
261
|
return;
|
|
@@ -238,6 +273,9 @@ export function pause_block(block) {
|
|
|
238
273
|
run_teardown(block);
|
|
239
274
|
}
|
|
240
275
|
|
|
276
|
+
/**
|
|
277
|
+
* @param {Block} block
|
|
278
|
+
*/
|
|
241
279
|
export function resume_block(block) {
|
|
242
280
|
if ((block.f & PAUSED) === 0) {
|
|
243
281
|
return;
|
|
@@ -257,7 +295,12 @@ export function resume_block(block) {
|
|
|
257
295
|
}
|
|
258
296
|
}
|
|
259
297
|
|
|
298
|
+
/**
|
|
299
|
+
* @param {Block} target_block
|
|
300
|
+
* @returns {boolean}
|
|
301
|
+
*/
|
|
260
302
|
export function is_destroyed(target_block) {
|
|
303
|
+
/** @type {Block | null} */
|
|
261
304
|
var block = target_block;
|
|
262
305
|
|
|
263
306
|
while (block !== null) {
|
|
@@ -274,6 +317,10 @@ export function is_destroyed(target_block) {
|
|
|
274
317
|
return true;
|
|
275
318
|
}
|
|
276
319
|
|
|
320
|
+
/**
|
|
321
|
+
* @param {Block} block
|
|
322
|
+
* @param {boolean} [remove_dom]
|
|
323
|
+
*/
|
|
277
324
|
export function destroy_block(block, remove_dom = true) {
|
|
278
325
|
block.f ^= DESTROYED;
|
|
279
326
|
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
USE_PROP,
|
|
29
29
|
} from './constants';
|
|
30
30
|
import { capture, suspend } from './try.js';
|
|
31
|
-
import { define_property, is_array } from './utils';
|
|
31
|
+
import { define_property, get_descriptor, is_array } from './utils';
|
|
32
32
|
import {
|
|
33
33
|
object_keys as original_object_keys,
|
|
34
34
|
object_values as original_object_values,
|
|
@@ -192,6 +192,7 @@ function run_computed(computed) {
|
|
|
192
192
|
* @param {Block} block
|
|
193
193
|
*/
|
|
194
194
|
export function handle_error(error, block) {
|
|
195
|
+
/** @type {Block | null} */
|
|
195
196
|
var current = block;
|
|
196
197
|
|
|
197
198
|
while (current !== null) {
|
|
@@ -230,6 +231,7 @@ export function run_block(block) {
|
|
|
230
231
|
|
|
231
232
|
if (typeof res === 'function') {
|
|
232
233
|
block.t = res;
|
|
234
|
+
/** @type {Block | null} */
|
|
233
235
|
let current = block;
|
|
234
236
|
|
|
235
237
|
while (current !== null && (current.f & CONTAINS_TEARDOWN) === 0) {
|
|
@@ -332,7 +334,7 @@ function is_tracking_dirty(tracking) {
|
|
|
332
334
|
/**
|
|
333
335
|
* @param {Block} block
|
|
334
336
|
*/
|
|
335
|
-
function is_block_dirty(block) {
|
|
337
|
+
export function is_block_dirty(block) {
|
|
336
338
|
var flags = block.f;
|
|
337
339
|
|
|
338
340
|
if ((flags & (ROOT_BLOCK | BRANCH_BLOCK)) !== 0) {
|
|
@@ -407,6 +409,7 @@ export function deferred(fn) {
|
|
|
407
409
|
var parent = active_block;
|
|
408
410
|
var block = active_scope;
|
|
409
411
|
var res = [UNINITIALIZED];
|
|
412
|
+
// TODO implement DEFERRED flag on tracked
|
|
410
413
|
var t = tracked(UNINITIALIZED, block, DEFERRED);
|
|
411
414
|
var tracked_properties = [t];
|
|
412
415
|
var prev_value = UNINITIALIZED;
|
|
@@ -535,7 +538,7 @@ function flush_updates(root_block) {
|
|
|
535
538
|
}
|
|
536
539
|
}
|
|
537
540
|
|
|
538
|
-
/** @type {Block} */
|
|
541
|
+
/** @type {Block | null} */
|
|
539
542
|
var parent = current.p;
|
|
540
543
|
current = current.next;
|
|
541
544
|
|
|
@@ -626,7 +629,7 @@ export function schedule_update(block) {
|
|
|
626
629
|
if ((flags & ROOT_BLOCK) !== 0) {
|
|
627
630
|
break;
|
|
628
631
|
}
|
|
629
|
-
current = current.p;
|
|
632
|
+
current = /** @type {Block} */ (current.p);
|
|
630
633
|
}
|
|
631
634
|
|
|
632
635
|
queued_root_blocks.push(current);
|
|
@@ -773,6 +776,11 @@ export function flush_sync(fn) {
|
|
|
773
776
|
}
|
|
774
777
|
}
|
|
775
778
|
|
|
779
|
+
/**
|
|
780
|
+
* @template T
|
|
781
|
+
* @param {() => T} fn
|
|
782
|
+
* @returns {T & { [SPREAD_OBJECT]: () => T }}
|
|
783
|
+
*/
|
|
776
784
|
export function tracked_spread_object(fn) {
|
|
777
785
|
var obj = fn();
|
|
778
786
|
|
|
@@ -784,7 +792,14 @@ export function tracked_spread_object(fn) {
|
|
|
784
792
|
return obj;
|
|
785
793
|
}
|
|
786
794
|
|
|
795
|
+
/**
|
|
796
|
+
* @param {any} obj
|
|
797
|
+
* @param {string[]} properties
|
|
798
|
+
* @param {Block} block
|
|
799
|
+
* @returns {object}
|
|
800
|
+
*/
|
|
787
801
|
export function tracked_object(obj, properties, block) {
|
|
802
|
+
/** @type {Record<string, Tracked | Computed>} */
|
|
788
803
|
var tracked_properties = obj[TRACKED_OBJECT];
|
|
789
804
|
|
|
790
805
|
if (tracked_properties === undefined) {
|
|
@@ -797,27 +812,42 @@ export function tracked_object(obj, properties, block) {
|
|
|
797
812
|
|
|
798
813
|
for (var i = 0; i < properties.length; i++) {
|
|
799
814
|
var property = properties[i];
|
|
800
|
-
|
|
815
|
+
/** @type {Tracked | Computed} */
|
|
801
816
|
var tracked_property;
|
|
802
817
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
818
|
+
// accessor passed in, to avoid an expensive get_descriptor call
|
|
819
|
+
// in the fast path
|
|
820
|
+
if (property[0] === '#') {
|
|
821
|
+
property = property.slice(1);
|
|
822
|
+
var descriptor = /** @type {PropertyDescriptor} */ (get_descriptor(obj, property));
|
|
823
|
+
var desc_get = descriptor.get;
|
|
824
|
+
tracked_property = computed(desc_get, block);
|
|
825
|
+
/** @type {any} */
|
|
826
|
+
var initial = run_computed(/** @type {Computed} */ (tracked_property));
|
|
806
827
|
obj[property] = initial;
|
|
807
|
-
// TODO If nothing is tracked in the computed function, we can make it a standard tracked
|
|
808
|
-
// however this is more allocations, so we probably want to minimize this
|
|
809
|
-
// if (tracked_property.d === null) {
|
|
810
|
-
// tracked_property = tracked(initial, block);
|
|
811
|
-
// }
|
|
812
828
|
} else {
|
|
813
|
-
|
|
829
|
+
var initial = obj[property];
|
|
830
|
+
|
|
831
|
+
if (typeof initial === 'function' && initial[COMPUTED_PROPERTY] === true) {
|
|
832
|
+
tracked_property = computed(initial, block);
|
|
833
|
+
initial = run_computed(/** @type {Computed} */ (tracked_property));
|
|
834
|
+
obj[property] = initial;
|
|
835
|
+
} else {
|
|
836
|
+
tracked_property = tracked(initial, block);
|
|
837
|
+
}
|
|
814
838
|
}
|
|
839
|
+
|
|
815
840
|
tracked_properties[property] = tracked_property;
|
|
816
841
|
}
|
|
817
842
|
|
|
818
843
|
return obj;
|
|
819
844
|
}
|
|
820
845
|
|
|
846
|
+
/**
|
|
847
|
+
* @template T
|
|
848
|
+
* @param {() => T} fn
|
|
849
|
+
* @returns {() => T}
|
|
850
|
+
*/
|
|
821
851
|
export function computed_property(fn) {
|
|
822
852
|
define_property(fn, COMPUTED_PROPERTY, {
|
|
823
853
|
value: true,
|
|
@@ -1002,6 +1032,12 @@ export function spread_object(obj) {
|
|
|
1002
1032
|
return values;
|
|
1003
1033
|
}
|
|
1004
1034
|
|
|
1035
|
+
/**
|
|
1036
|
+
* @template T
|
|
1037
|
+
* @param {Block} block
|
|
1038
|
+
* @param {() => T} fn
|
|
1039
|
+
* @returns {T}
|
|
1040
|
+
*/
|
|
1005
1041
|
export function with_scope(block, fn) {
|
|
1006
1042
|
var previous_scope = active_scope;
|
|
1007
1043
|
try {
|
|
@@ -1054,6 +1090,12 @@ export function use_prop() {
|
|
|
1054
1090
|
return Symbol(USE_PROP);
|
|
1055
1091
|
}
|
|
1056
1092
|
|
|
1093
|
+
/**
|
|
1094
|
+
* @template T
|
|
1095
|
+
* @param {T | undefined} value
|
|
1096
|
+
* @param {T} fallback
|
|
1097
|
+
* @returns {T}
|
|
1098
|
+
*/
|
|
1057
1099
|
export function fallback(value, fallback) {
|
|
1058
1100
|
return value === undefined ? fallback : value;
|
|
1059
|
-
}
|
|
1101
|
+
}
|
|
@@ -5,7 +5,7 @@ export type Component = {
|
|
|
5
5
|
e: null | Array<{
|
|
6
6
|
b: Block;
|
|
7
7
|
fn: Function;
|
|
8
|
-
r: null | Block;
|
|
8
|
+
r: null | Block | Computed;
|
|
9
9
|
}>;
|
|
10
10
|
p: null | Component;
|
|
11
11
|
m: boolean;
|
|
@@ -40,10 +40,11 @@ export type Block = {
|
|
|
40
40
|
first: null | Block;
|
|
41
41
|
f: number;
|
|
42
42
|
fn: any;
|
|
43
|
-
last: null;
|
|
44
|
-
next: null;
|
|
43
|
+
last: null | Block;
|
|
44
|
+
next: null | Block;
|
|
45
45
|
p: null | Block;
|
|
46
|
-
prev: null;
|
|
46
|
+
prev: null | Block;
|
|
47
47
|
s: any;
|
|
48
|
-
|
|
48
|
+
// teardown function
|
|
49
|
+
t: (() => {}) | null;
|
|
49
50
|
};
|