ripple 0.2.52 → 0.2.54
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/2-analyze/index.js +1 -32
- package/src/compiler/phases/3-transform/index.js +13 -84
- package/src/compiler/phases/3-transform/stylesheet.js +16 -3
- package/src/compiler/utils.js +0 -20
- package/src/runtime/array.js +158 -610
- package/src/runtime/index.js +3 -3
- package/src/runtime/internal/client/constants.js +1 -1
- package/src/runtime/internal/client/for.js +5 -5
- package/src/runtime/internal/client/index.js +1 -11
- package/src/runtime/internal/client/operations.js +0 -3
- package/src/runtime/internal/client/portal.js +5 -6
- package/src/runtime/internal/client/runtime.js +54 -316
- package/src/runtime/internal/client/utils.js +0 -10
- package/src/runtime/map.js +28 -15
- package/src/runtime/set.js +47 -21
- package/tests/array.test.ripple +75 -187
- package/tests/basic.test.ripple +33 -9
- package/tests/compiler.test.ripple +5 -5
- package/tests/composite.test.ripple +253 -3
- package/tests/for.test.ripple +3 -3
- package/tests/map.test.ripple +10 -10
- package/tests/ref.test.ripple +3 -3
- package/tests/set.test.ripple +7 -7
- package/types/index.d.ts +18 -31
package/src/runtime/array.js
CHANGED
|
@@ -1,661 +1,209 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
ARRAY_SET_INDEX_AT,
|
|
4
|
-
MAX_ARRAY_LENGTH,
|
|
5
|
-
} from './internal/client/constants.js';
|
|
1
|
+
/** @import { Block } from '#client' */
|
|
2
|
+
import { MAX_ARRAY_LENGTH, TRACKED_ARRAY, UNINITIALIZED } from './internal/client/constants.js';
|
|
6
3
|
import { get, safe_scope, set, tracked } from './internal/client/runtime.js';
|
|
7
|
-
import {
|
|
8
|
-
/** @import { Block, Tracked } from '#client' */
|
|
9
|
-
|
|
10
|
-
/** @type {unique symbol} */
|
|
11
|
-
const INIT_AFTER_NEW = Symbol();
|
|
12
|
-
|
|
13
|
-
/** @type {(symbol | string | any)[]} */
|
|
14
|
-
const introspect_methods = [
|
|
15
|
-
'concat',
|
|
16
|
-
'entries',
|
|
17
|
-
'every',
|
|
18
|
-
'filter',
|
|
19
|
-
'find',
|
|
20
|
-
'findIndex',
|
|
21
|
-
'findLast',
|
|
22
|
-
'findLastIndex',
|
|
23
|
-
'flat',
|
|
24
|
-
'flatMap',
|
|
25
|
-
'forEach',
|
|
26
|
-
'includes',
|
|
27
|
-
'indexOf',
|
|
28
|
-
'join',
|
|
29
|
-
'keys',
|
|
30
|
-
'lastIndexOf',
|
|
31
|
-
'map',
|
|
32
|
-
'reduce',
|
|
33
|
-
'reduceRight',
|
|
34
|
-
'some',
|
|
35
|
-
'slice',
|
|
36
|
-
'toLocaleString',
|
|
37
|
-
'toReversed',
|
|
38
|
-
'toSorted',
|
|
39
|
-
'toSpliced',
|
|
40
|
-
'toString',
|
|
41
|
-
Symbol.iterator,
|
|
42
|
-
'values',
|
|
43
|
-
'with',
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
let is_proto_set = false;
|
|
4
|
+
import { get_descriptor } from './internal/client/utils.js';
|
|
47
5
|
|
|
48
6
|
/**
|
|
49
7
|
* @template T
|
|
50
|
-
* @
|
|
8
|
+
* @constructor
|
|
9
|
+
* @param {...T} elements
|
|
10
|
+
* @returns {TrackedArray<T>}
|
|
51
11
|
*/
|
|
52
|
-
export
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/** @type {Tracked} */
|
|
56
|
-
// @ts-expect-error
|
|
57
|
-
#tracked_index;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @template U
|
|
61
|
-
* @param {ArrayLike<U> | Iterable<U>} arrayLike
|
|
62
|
-
* @param {(v: U, k: number) => any | undefined} [mapFn]
|
|
63
|
-
* @param {any} [thisArg]
|
|
64
|
-
* @returns {RippleArray<U>}
|
|
65
|
-
*/
|
|
66
|
-
static from(arrayLike, mapFn, thisArg) {
|
|
67
|
-
var arr = mapFn ? Array.from(arrayLike, mapFn, thisArg) : Array.from(arrayLike);
|
|
68
|
-
|
|
69
|
-
return get_instance_from_static(arr);
|
|
12
|
+
export function TrackedArray(...elements) {
|
|
13
|
+
if (!new.target) {
|
|
14
|
+
throw new Error("TrackedArray must be called with 'new'");
|
|
70
15
|
}
|
|
71
16
|
|
|
72
|
-
|
|
73
|
-
* @template U
|
|
74
|
-
* @param {ArrayLike<U> | Iterable<U>} arrayLike
|
|
75
|
-
* @param {(v: U, k: number) => any | undefined} [mapFn]
|
|
76
|
-
* @param {any} [thisArg]
|
|
77
|
-
* @returns {Promise<RippleArray<U>>}
|
|
78
|
-
*/
|
|
79
|
-
static async fromAsync(arrayLike, mapFn, thisArg) {
|
|
80
|
-
var block = safe_scope();
|
|
81
|
-
// create empty array to get the right scope
|
|
82
|
-
var result = new RippleArray();
|
|
83
|
-
|
|
84
|
-
var arr = mapFn
|
|
85
|
-
? await Array.fromAsync(arrayLike, mapFn, thisArg)
|
|
86
|
-
: await Array.fromAsync(arrayLike);
|
|
87
|
-
|
|
88
|
-
var first = get_first_if_length(arr);
|
|
89
|
-
|
|
90
|
-
if (first) {
|
|
91
|
-
result[0] = first;
|
|
92
|
-
} else {
|
|
93
|
-
result.length = arr.length;
|
|
94
|
-
for (let i = 0; i < arr.length; i++) {
|
|
95
|
-
if (i in arr) {
|
|
96
|
-
result[i] = arr[i];
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
17
|
+
var block = safe_scope();
|
|
100
18
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
19
|
+
return proxy(elements, block);
|
|
20
|
+
}
|
|
105
21
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
22
|
+
/**
|
|
23
|
+
* @template T
|
|
24
|
+
* @param {ArrayLike<T> | Iterable<T>} arrayLike
|
|
25
|
+
* @param {(v: T, k: number) => any | undefined} [mapFn]
|
|
26
|
+
* @param {*} [thisArg]
|
|
27
|
+
* @returns {TrackedArray<T>}
|
|
28
|
+
*/
|
|
29
|
+
TrackedArray.from = function (arrayLike, mapFn, thisArg) {
|
|
30
|
+
var block = safe_scope();
|
|
31
|
+
var elements = mapFn ? Array.from(arrayLike, mapFn, thisArg) : Array.from(arrayLike);
|
|
32
|
+
return proxy(elements, block, true);
|
|
33
|
+
};
|
|
113
34
|
|
|
114
|
-
|
|
115
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @template T
|
|
37
|
+
* @param {...T} items
|
|
38
|
+
* @returns {TrackedArray<T>}
|
|
39
|
+
*/
|
|
40
|
+
TrackedArray.of = function (...items) {
|
|
41
|
+
var block = safe_scope();
|
|
42
|
+
var elements = Array.of(...items);
|
|
43
|
+
return proxy(elements, block, true);
|
|
44
|
+
};
|
|
116
45
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
46
|
+
/**
|
|
47
|
+
* @template T
|
|
48
|
+
* @param {ArrayLike<T> | Iterable<T>} arrayLike
|
|
49
|
+
* @param {(v: T, k: number) => any | undefined} [mapFn]
|
|
50
|
+
* @param {any} [thisArg]
|
|
51
|
+
* @returns {Promise<TrackedArray<T>>}
|
|
52
|
+
*/
|
|
53
|
+
TrackedArray.fromAsync = async function (arrayLike, mapFn, thisArg) {
|
|
54
|
+
var block = safe_scope();
|
|
55
|
+
var elements = mapFn
|
|
56
|
+
? await Array.fromAsync(arrayLike, mapFn, thisArg)
|
|
57
|
+
: await Array.fromAsync(arrayLike);
|
|
58
|
+
return proxy(elements, block, true);
|
|
59
|
+
};
|
|
122
60
|
|
|
123
|
-
|
|
61
|
+
/**
|
|
62
|
+
* @template T
|
|
63
|
+
* @param {Iterable<T>} elements
|
|
64
|
+
* @param {Block} block
|
|
65
|
+
* @param {boolean} is_from_static
|
|
66
|
+
* @returns {TrackedArray<T>}
|
|
67
|
+
*/
|
|
68
|
+
function proxy(elements, block, is_from_static = false) {
|
|
69
|
+
var arr;
|
|
70
|
+
var first;
|
|
124
71
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
72
|
+
if (
|
|
73
|
+
is_from_static &&
|
|
74
|
+
(first = get_first_if_length(/** @type {Array<T>} */ (elements))) !== undefined
|
|
75
|
+
) {
|
|
76
|
+
arr = new Array();
|
|
77
|
+
arr[0] = first;
|
|
78
|
+
} else {
|
|
79
|
+
arr = new Array(...elements);
|
|
129
80
|
}
|
|
130
81
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
for (var i = 0; i < this.length; i++) {
|
|
135
|
-
if (!(i in this)) {
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
tracked_elements[i] = tracked(this[i], block);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (!this.#tracked_index) {
|
|
143
|
-
this.#tracked_index = tracked(this.length, block);
|
|
144
|
-
} else if (this.#tracked_index.v !== this.length) {
|
|
145
|
-
set(this.#tracked_index, this.length, block);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
82
|
+
var tracked_elements = new Map();
|
|
83
|
+
var tracked_len = tracked(arr.length, block);
|
|
84
|
+
tracked_elements.set('length', tracked_len);
|
|
148
85
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
86
|
+
return new Proxy(arr, {
|
|
87
|
+
get(target, prop, receiver) {
|
|
88
|
+
var t = tracked_elements.get(prop);
|
|
89
|
+
var exists = prop in target;
|
|
152
90
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
91
|
+
if (t === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
|
|
92
|
+
t = tracked(exists ? target[prop] : UNINITIALIZED, block);
|
|
93
|
+
tracked_elements.set(prop, t);
|
|
156
94
|
}
|
|
157
95
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (is_ripple_array(result) && this !== result) {
|
|
163
|
-
var tracked_elements = result[TRACKED_OBJECT];
|
|
164
|
-
var block = safe_scope();
|
|
96
|
+
if (t !== undefined) {
|
|
97
|
+
var v = get(t);
|
|
98
|
+
return v === UNINITIALIZED ? undefined : v;
|
|
99
|
+
}
|
|
165
100
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
101
|
+
return Reflect.get(target, prop, receiver);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
set(target, prop, value, receiver) {
|
|
105
|
+
var t = tracked_elements.get(prop);
|
|
106
|
+
var exists = prop in target;
|
|
107
|
+
|
|
108
|
+
if (prop === 'length') {
|
|
109
|
+
for (var i = value; i < tracked_len.v; i += 1) {
|
|
110
|
+
var other_t = tracked_elements.get(i + '');
|
|
111
|
+
if (other_t !== undefined) {
|
|
112
|
+
set(other_t, UNINITIALIZED, block);
|
|
113
|
+
} else if (i in target) {
|
|
114
|
+
// If the item exists in the original, we need to create a uninitialized tracked,
|
|
115
|
+
// else a later read of the property would result in a tracked being created with
|
|
116
|
+
// the value of the original item at that index.
|
|
117
|
+
other_t = tracked(UNINITIALIZED, block);
|
|
118
|
+
tracked_elements.set(i + '', other_t);
|
|
172
119
|
}
|
|
173
120
|
}
|
|
174
|
-
|
|
175
|
-
// the caller reruns on length changes
|
|
176
|
-
this.$length;
|
|
177
|
-
// the caller reruns on element changes
|
|
178
|
-
establish_trackable_deps(this);
|
|
179
|
-
return result;
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* @param {number} target
|
|
186
|
-
* @param {number} start
|
|
187
|
-
* @param {number} [end]
|
|
188
|
-
* @returns {this}
|
|
189
|
-
*/
|
|
190
|
-
copyWithin(target, start, end) {
|
|
191
|
-
var block = safe_scope();
|
|
192
|
-
var tracked_elements = this.#tracked_elements;
|
|
193
|
-
var length = this.length;
|
|
194
|
-
|
|
195
|
-
super.copyWithin(target, start, end);
|
|
196
|
-
|
|
197
|
-
if (!target && !start) {
|
|
198
|
-
return this;
|
|
199
|
-
} else if (!target && start) {
|
|
200
|
-
target = 0;
|
|
201
|
-
} else if (target && !start) {
|
|
202
|
-
start = 0;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (target < 0) {
|
|
206
|
-
target = Math.max(length + target, 0);
|
|
207
|
-
} else {
|
|
208
|
-
target = Math.min(target, length);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (start < 0) {
|
|
212
|
-
start = Math.max(length + start, 0);
|
|
213
|
-
} else {
|
|
214
|
-
start = Math.min(start, length);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (end === undefined) {
|
|
218
|
-
end = length;
|
|
219
|
-
} else if (end < 0) {
|
|
220
|
-
end = Math.max(length + end, 0);
|
|
221
|
-
} else {
|
|
222
|
-
end = Math.min(end, length);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (target >= length) {
|
|
226
|
-
return this;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const copyCount = Math.min(end - start, length - target);
|
|
230
|
-
|
|
231
|
-
// If no elements are copied (start >= end or copyCount <= 0), return early
|
|
232
|
-
if (start >= end || copyCount <= 0) {
|
|
233
|
-
return this;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
for (let i = 0; i < copyCount; i++) {
|
|
237
|
-
const index = target + i;
|
|
238
|
-
// Only update if source and target are different positions
|
|
239
|
-
// to avoid unnecessary updates when copying onto itself
|
|
240
|
-
if (index !== start + i) {
|
|
241
|
-
this.#update_tracked_at_index({ array: this, i: index, block, tracked_elements });
|
|
242
121
|
}
|
|
243
|
-
}
|
|
244
122
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
*/
|
|
254
|
-
fill(value, start, end) {
|
|
255
|
-
var block = safe_scope();
|
|
256
|
-
var tracked_elements = this.#tracked_elements;
|
|
257
|
-
var length = this.length;
|
|
258
|
-
|
|
259
|
-
// avoid unexpected behavior with method args being undefined
|
|
260
|
-
if (value === undefined && start === undefined && end === undefined) {
|
|
261
|
-
// @ts-ignore
|
|
262
|
-
super.fill();
|
|
263
|
-
} else if (start === undefined && end === undefined) {
|
|
264
|
-
super.fill(value);
|
|
265
|
-
} else if (end === undefined) {
|
|
266
|
-
super.fill(value, start);
|
|
267
|
-
} else {
|
|
268
|
-
super.fill(value, start, end);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
let actual_start = 0;
|
|
272
|
-
if (start !== undefined) {
|
|
273
|
-
if (start < 0) {
|
|
274
|
-
actual_start = Math.max(length + start, 0);
|
|
275
|
-
} else {
|
|
276
|
-
actual_start = Math.min(start, length);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
123
|
+
// If we haven't yet created a tracked for this property, we need to ensure
|
|
124
|
+
// we do so otherwise if we read it later, then the write won't be tracked and
|
|
125
|
+
// the heuristics of effects will be different vs if we had read the proxied
|
|
126
|
+
// object property before writing to that property.
|
|
127
|
+
if (t === undefined) {
|
|
128
|
+
if (!exists || get_descriptor(target, prop)?.writable) {
|
|
129
|
+
t = tracked(undefined, block);
|
|
130
|
+
set(t, value, block);
|
|
279
131
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (end < 0) {
|
|
283
|
-
actual_end = Math.max(length + end, 0);
|
|
284
|
-
} else {
|
|
285
|
-
actual_end = Math.min(end, length);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
for (let i = actual_start; i < actual_end; i++) {
|
|
290
|
-
if (tracked_elements[i] === undefined) {
|
|
291
|
-
tracked_elements[i] = tracked(this[i], block);
|
|
132
|
+
tracked_elements.set(prop, t);
|
|
133
|
+
}
|
|
292
134
|
} else {
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return this;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
reverse() {
|
|
301
|
-
var result = /** @type {RippleArray<T>} */ (super.reverse());
|
|
302
|
-
this.#update_all_tracked_from_array(result);
|
|
303
|
-
return result;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* @param {(a: T, b: T) => number} [fn]
|
|
308
|
-
* @returns {this}
|
|
309
|
-
*/
|
|
310
|
-
sort(fn) {
|
|
311
|
-
var result = super.sort(fn);
|
|
312
|
-
this.#update_all_tracked_from_array(result);
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* @param {RippleArray<T>} array
|
|
318
|
-
* @returns {RippleArray<T>}
|
|
319
|
-
*/
|
|
320
|
-
#update_all_tracked_from_array(array) {
|
|
321
|
-
var block = safe_scope();
|
|
322
|
-
var tracked_elements = this.#tracked_elements;
|
|
323
|
-
|
|
324
|
-
for (var i = 0; i < array.length; i++) {
|
|
325
|
-
this.#update_tracked_at_index({ array, i, block, tracked_elements });
|
|
326
|
-
}
|
|
327
|
-
return array;
|
|
328
|
-
}
|
|
135
|
+
exists = t.v !== UNINITIALIZED;
|
|
329
136
|
|
|
330
|
-
|
|
331
|
-
* @param {Object} param0
|
|
332
|
-
* @param {RippleArray<T>} param0.array
|
|
333
|
-
* @param {number} param0.i
|
|
334
|
-
* @param {Block} param0.block
|
|
335
|
-
* @param {Tracked[]} param0.tracked_elements
|
|
336
|
-
*/
|
|
337
|
-
#update_tracked_at_index({
|
|
338
|
-
array,
|
|
339
|
-
i,
|
|
340
|
-
block = safe_scope(),
|
|
341
|
-
tracked_elements = this.#tracked_elements,
|
|
342
|
-
}) {
|
|
343
|
-
if (i in array) {
|
|
344
|
-
if (tracked_elements[i] === undefined) {
|
|
345
|
-
tracked_elements[i] = tracked(array[i], block);
|
|
346
|
-
} else {
|
|
347
|
-
set(tracked_elements[i], array[i], block);
|
|
348
|
-
}
|
|
349
|
-
} else {
|
|
350
|
-
if (tracked_elements[i] !== undefined) {
|
|
351
|
-
set(tracked_elements[i], undefined, block);
|
|
137
|
+
set(t, value, block);
|
|
352
138
|
}
|
|
353
|
-
delete tracked_elements[i];
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* @param {...T} elements
|
|
359
|
-
* @returns {number}
|
|
360
|
-
*/
|
|
361
|
-
unshift(...elements) {
|
|
362
|
-
var block = safe_scope();
|
|
363
|
-
var tracked_elements = this.#tracked_elements;
|
|
364
|
-
var length = this.length;
|
|
365
|
-
var shift_len = elements.length;
|
|
366
|
-
var new_len = length + shift_len;
|
|
367
|
-
|
|
368
|
-
super.unshift(...elements);
|
|
369
|
-
|
|
370
|
-
// extend the array to fit the new elements
|
|
371
|
-
tracked_elements.push(...elements.map(() => tracked(undefined, block)));
|
|
372
|
-
|
|
373
|
-
// copy the existing ones to the end
|
|
374
|
-
for (let i = length - 1; i >= 0; i--) {
|
|
375
|
-
set(tracked_elements[i + shift_len], tracked_elements[i].v, block);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// set new values at the start
|
|
379
|
-
for (let i = shift_len - 1; i >= 0; i--) {
|
|
380
|
-
set(tracked_elements[i], elements[i], block);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
set(this.#tracked_index, new_len, block);
|
|
384
|
-
return new_len;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
shift() {
|
|
388
|
-
var block = safe_scope();
|
|
389
|
-
var tracked_elements = this.#tracked_elements;
|
|
390
139
|
|
|
391
|
-
|
|
392
|
-
for (var i = 0; i < tracked_elements.length; i++) {
|
|
393
|
-
// the last must be set to undefined
|
|
394
|
-
set(tracked_elements[i], tracked_elements[i + 1]?.v, block);
|
|
395
|
-
}
|
|
396
|
-
tracked_elements.pop();
|
|
140
|
+
var result = Reflect.set(target, prop, value, receiver);
|
|
397
141
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
*/
|
|
406
|
-
push(...elements) {
|
|
407
|
-
var block = safe_scope();
|
|
408
|
-
var start_index = this.length;
|
|
409
|
-
var tracked_elements = this.#tracked_elements;
|
|
142
|
+
if (!exists) {
|
|
143
|
+
// If we have mutated an array directly, we might need to
|
|
144
|
+
// signal that length has also changed. Do it before updating metadata
|
|
145
|
+
// to ensure that iterating over the array as a result of a metadata update
|
|
146
|
+
// will not cause the length to be out of sync.
|
|
147
|
+
if (typeof prop === 'string') {
|
|
148
|
+
var n = Number(prop);
|
|
410
149
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
continue;
|
|
150
|
+
if (Number.isInteger(n) && n >= tracked_len.v) {
|
|
151
|
+
set(tracked_len, n + 1, block);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
416
154
|
}
|
|
417
|
-
tracked_elements[start_index + i] = tracked(elements[i], block);
|
|
418
|
-
}
|
|
419
|
-
var length = this.length;
|
|
420
|
-
set(this.#tracked_index, this.length, block);
|
|
421
|
-
return length;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
pop() {
|
|
425
|
-
var block = safe_scope();
|
|
426
|
-
var tracked_elements = this.#tracked_elements;
|
|
427
|
-
var length = tracked_elements.length;
|
|
428
|
-
var result = super.pop();
|
|
429
|
-
|
|
430
|
-
if (length > 0 && tracked_elements[length - 1] !== undefined) {
|
|
431
|
-
set(tracked_elements[length - 1], undefined, block);
|
|
432
|
-
}
|
|
433
|
-
tracked_elements.pop();
|
|
434
|
-
|
|
435
|
-
set(this.#tracked_index, this.length, block);
|
|
436
|
-
return result;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Assigns value at index
|
|
441
|
-
* Same as bracket [] assignment
|
|
442
|
-
* Supports negative index to count back from the end
|
|
443
|
-
* @param {number} index
|
|
444
|
-
* @param {T} value
|
|
445
|
-
* @returns {T}
|
|
446
|
-
*/
|
|
447
|
-
[ARRAY_SET_INDEX_AT](index, value) {
|
|
448
|
-
var block = safe_scope();
|
|
449
|
-
var tracked_elements = this.#tracked_elements;
|
|
450
|
-
var length = this.length;
|
|
451
|
-
var init_index = index;
|
|
452
|
-
|
|
453
|
-
if (!Number.isInteger(index)) {
|
|
454
|
-
throw new TypeError('Provided index must be a valid integer');
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (init_index < -length) {
|
|
458
|
-
throw new RangeError('Provided negative index out of bounds');
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
index = index < 0 ? index + length : index;
|
|
462
|
-
|
|
463
|
-
super[index] = value;
|
|
464
|
-
|
|
465
|
-
if (tracked_elements[index] === undefined) {
|
|
466
|
-
tracked_elements[index] = tracked(value, block);
|
|
467
|
-
} else {
|
|
468
|
-
set(tracked_elements[index], value, block);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
if (this.length > length) {
|
|
472
|
-
set(this.#tracked_index, this.length, block);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
return value;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* @param {number} index
|
|
480
|
-
* @returns {T | undefined}
|
|
481
|
-
*/
|
|
482
|
-
at(index) {
|
|
483
|
-
var tracked_elements = this.#tracked_elements;
|
|
484
|
-
var normalized = index < 0 ? index + this.length : index;
|
|
485
|
-
|
|
486
|
-
if (tracked_elements[normalized] !== undefined) {
|
|
487
|
-
get(tracked_elements[normalized]);
|
|
488
|
-
}
|
|
489
|
-
this.$length;
|
|
490
155
|
|
|
491
|
-
return super.at(index);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* @param {number} start
|
|
496
|
-
* @param {number} [delete_count]
|
|
497
|
-
* @param {...T} elements
|
|
498
|
-
* @returns {Array<T>}
|
|
499
|
-
*/
|
|
500
|
-
splice(start, delete_count, ...elements) {
|
|
501
|
-
var block = safe_scope();
|
|
502
|
-
var tracked_elements = this.#tracked_elements;
|
|
503
|
-
var tracked_len = tracked_elements.length;
|
|
504
|
-
var before_len = this.length;
|
|
505
|
-
var el_len = elements.length;
|
|
506
|
-
var result;
|
|
507
|
-
|
|
508
|
-
if (start !== undefined && delete_count === undefined && !el_len) {
|
|
509
|
-
// we can't just call super.splice(start, delete_count, ...elements)
|
|
510
|
-
// delete_count if undefined will be converted to 0 and nothing will be removed
|
|
511
|
-
result = super.splice(start);
|
|
512
|
-
} else if (start === undefined && delete_count === undefined && !el_len) {
|
|
513
|
-
// If start is undefined the native code will get converted to 0
|
|
514
|
-
// which would cause to remove all elements.
|
|
515
|
-
// Typically no sense to `.splice()` with no args as it does nothing
|
|
516
|
-
// since we get args as undefined, we need to handle this case
|
|
517
|
-
|
|
518
|
-
// @ts-ignore
|
|
519
|
-
result = super.splice();
|
|
520
|
-
} else {
|
|
521
|
-
// @ts-ignore
|
|
522
|
-
result = super.splice(start, delete_count, ...elements);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
var after_len = this.length;
|
|
526
|
-
delete_count = result.length;
|
|
527
|
-
|
|
528
|
-
if (delete_count === 0 && !el_len) {
|
|
529
156
|
return result;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
if (start < 0) {
|
|
533
|
-
start = Math.max(before_len + start, 0);
|
|
534
|
-
} else {
|
|
535
|
-
start = Math.min(start, before_len);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
var range_end = el_len - delete_count === 0 ? start + el_len : Math.max(after_len, before_len);
|
|
157
|
+
},
|
|
539
158
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
159
|
+
setPrototypeOf() {
|
|
160
|
+
throw new Error(`Cannot set prototype of \`TrackedArray\``);
|
|
161
|
+
},
|
|
543
162
|
|
|
544
|
-
|
|
163
|
+
deleteProperty(target, prop) {
|
|
164
|
+
var t = tracked_elements.get(prop);
|
|
545
165
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
get [TRACKED_OBJECT]() {
|
|
551
|
-
return this.#tracked_elements;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
get $length() {
|
|
555
|
-
return get(this.#tracked_index);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/** @param {number} length */
|
|
559
|
-
set $length(length) {
|
|
560
|
-
if (length === this.length) {
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
var block = safe_scope();
|
|
565
|
-
var tracked_elements = this.#tracked_elements;
|
|
566
|
-
var tracked_len = tracked_elements.length;
|
|
567
|
-
|
|
568
|
-
if (length < tracked_len) {
|
|
569
|
-
for (var i = length; i < tracked_len; i++) {
|
|
570
|
-
if (tracked_elements[i] !== undefined) {
|
|
571
|
-
set(tracked_elements[i], undefined, block);
|
|
166
|
+
if (t === undefined) {
|
|
167
|
+
if (prop in target) {
|
|
168
|
+
const t = tracked(UNINITIALIZED, block);
|
|
169
|
+
tracked_elements.set(prop, t);
|
|
572
170
|
}
|
|
171
|
+
} else {
|
|
172
|
+
set(t, UNINITIALIZED, block);
|
|
573
173
|
}
|
|
574
|
-
}
|
|
575
174
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
set(this.#tracked_index, length, block);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/** @param {number} _ */
|
|
582
|
-
set length(_) {
|
|
583
|
-
// This doesn't actually work because length cannot be overridden.
|
|
584
|
-
// This error is now moved to runtime to catch direct assignments to length
|
|
585
|
-
throw new Error('Cannot set length on RippleArray, use $length instead');
|
|
586
|
-
}
|
|
175
|
+
return Reflect.deleteProperty(target, prop);
|
|
176
|
+
},
|
|
587
177
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* @template T
|
|
596
|
-
* @param {RippleArray<T>} array
|
|
597
|
-
* @returns {T[]}
|
|
598
|
-
*/
|
|
599
|
-
export function get_all_elements(array) {
|
|
600
|
-
/** @type {Tracked[]} */
|
|
601
|
-
var tracked_elements = /** @type {Tracked[]} */ (array[TRACKED_OBJECT]);
|
|
602
|
-
// pre-allocate to support holey arrays
|
|
603
|
-
var result = new Array(array.length);
|
|
604
|
-
|
|
605
|
-
for (var i = 0; i < array.length; i++) {
|
|
606
|
-
if (tracked_elements[i] !== undefined) {
|
|
607
|
-
get(tracked_elements[i]);
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
if (i in array) {
|
|
611
|
-
result[i] = array[i];
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
return result;
|
|
616
|
-
}
|
|
178
|
+
has(target, prop) {
|
|
179
|
+
if (prop === TRACKED_ARRAY) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
var t = tracked_elements.get(prop);
|
|
183
|
+
var exists = (t !== undefined && t.v !== UNINITIALIZED) || Reflect.has(target, prop);
|
|
617
184
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
* @returns {void}
|
|
622
|
-
*/
|
|
623
|
-
function establish_trackable_deps(array) {
|
|
624
|
-
var tracked_elements = array[TRACKED_OBJECT];
|
|
185
|
+
if (t !== undefined || !exists || get_descriptor(target, prop)?.writable) {
|
|
186
|
+
if (t === undefined) {
|
|
187
|
+
t = tracked(exists ? target[prop] : UNINITIALIZED, block);
|
|
625
188
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
get(tracked_elements[i]);
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
189
|
+
tracked_elements.set(prop, t);
|
|
190
|
+
}
|
|
632
191
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
function get_instance_from_static(array) {
|
|
639
|
-
/** @type RippleArray<T> */
|
|
640
|
-
var result;
|
|
641
|
-
/** @type {T | void} */
|
|
642
|
-
var first = get_first_if_length(array);
|
|
643
|
-
|
|
644
|
-
if (first) {
|
|
645
|
-
result = new RippleArray();
|
|
646
|
-
result[0] = first;
|
|
647
|
-
result[INIT_AFTER_NEW]();
|
|
648
|
-
} else {
|
|
649
|
-
result = new RippleArray(...array);
|
|
650
|
-
}
|
|
192
|
+
var value = get(t);
|
|
193
|
+
if (value === UNINITIALIZED) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
651
197
|
|
|
652
|
-
|
|
198
|
+
return exists;
|
|
199
|
+
},
|
|
200
|
+
});
|
|
653
201
|
}
|
|
654
202
|
|
|
655
203
|
/**
|
|
656
204
|
* @template T
|
|
657
|
-
* @param {T
|
|
658
|
-
* @returns {
|
|
205
|
+
* @param {Array<T>} array
|
|
206
|
+
* @returns {number | void}
|
|
659
207
|
*/
|
|
660
208
|
function get_first_if_length(array) {
|
|
661
209
|
var first = array[0];
|
|
@@ -667,6 +215,6 @@ function get_first_if_length(array) {
|
|
|
667
215
|
/** @type {number} */ (first) >= 0 &&
|
|
668
216
|
/** @type {number} */ (first) <= MAX_ARRAY_LENGTH
|
|
669
217
|
) {
|
|
670
|
-
return first;
|
|
218
|
+
return /** @type {number} */ (first);
|
|
671
219
|
}
|
|
672
220
|
}
|