ripple 0.2.86 → 0.2.88

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.
Files changed (32) hide show
  1. package/package.json +3 -1
  2. package/src/compiler/phases/1-parse/index.js +30 -1
  3. package/src/compiler/phases/2-analyze/index.js +3 -1
  4. package/src/compiler/phases/3-transform/client/index.js +23 -10
  5. package/src/compiler/scope.js +2 -0
  6. package/src/compiler/types/index.d.ts +5 -0
  7. package/src/runtime/array.js +12 -5
  8. package/src/runtime/index-client.js +0 -1
  9. package/src/runtime/index-server.js +18 -3
  10. package/src/runtime/internal/client/blocks.js +209 -205
  11. package/src/runtime/internal/client/composite.js +9 -0
  12. package/src/runtime/internal/client/events.js +219 -189
  13. package/src/runtime/internal/client/for.js +467 -383
  14. package/src/runtime/internal/client/if.js +36 -25
  15. package/src/runtime/internal/client/index.js +2 -0
  16. package/src/runtime/internal/client/operations.js +7 -2
  17. package/src/runtime/internal/client/portal.js +15 -4
  18. package/src/runtime/internal/client/render.js +48 -6
  19. package/src/runtime/internal/client/runtime.js +98 -83
  20. package/src/runtime/internal/client/script.js +16 -0
  21. package/src/runtime/internal/client/template.js +8 -5
  22. package/src/runtime/internal/client/try.js +42 -4
  23. package/src/runtime/internal/client/utils.js +18 -3
  24. package/src/runtime/internal/server/context.js +2 -0
  25. package/src/runtime/internal/server/index.js +39 -3
  26. package/src/runtime/internal/server/types.d.ts +21 -0
  27. package/src/runtime/map.js +37 -2
  28. package/src/runtime/set.js +22 -9
  29. package/src/utils/builders.js +1 -0
  30. package/tests/client/__snapshots__/basic.test.ripple.snap +13 -0
  31. package/tests/client/basic.test.ripple +15 -0
  32. package/tests/client/ref.test.ripple +33 -2
@@ -1,3 +1,5 @@
1
+ /** @import { Block } from '#client' */
2
+
1
3
  import { IS_CONTROLLED, IS_INDEXED } from '../../../constants.js';
2
4
  import { branch, destroy_block, destroy_block_children, render } from './blocks.js';
3
5
  import { FOR_BLOCK, TRACKED_ARRAY } from './constants.js';
@@ -5,428 +7,510 @@ import { create_text, next_sibling } from './operations.js';
5
7
  import { active_block, set, tracked, untrack } from './runtime.js';
6
8
  import { array_from, is_array } from './utils.js';
7
9
 
10
+ /**
11
+ * @template V
12
+ * @param {Node} anchor
13
+ * @param {V} value
14
+ * @param {number} index
15
+ * @param {(anchor: Node, value: V, index?: any) => Block} render_fn
16
+ * @param {boolean} is_indexed
17
+ * @returns {Block}
18
+ */
8
19
  function create_item(anchor, value, index, render_fn, is_indexed) {
9
- var b = branch(() => {
10
- var tracked_index;
11
-
12
- if (is_indexed) {
13
- var block = /** @type {Block} */ (active_block);
14
-
15
- if (block.s === null) {
16
- tracked_index = tracked(index, block);
17
-
18
- block.s = {
19
- start: null,
20
- end: null,
21
- i: tracked_index,
22
- };
23
- } else {
24
- tracked_index = block.s.i;
25
- }
26
- render_fn(anchor, value, tracked_index);
27
- } else {
28
- render_fn(anchor, value);
29
- }
30
- });
31
- return b;
20
+ var b = branch(() => {
21
+ var tracked_index;
22
+
23
+ if (is_indexed) {
24
+ var block = /** @type {Block} */ (active_block);
25
+
26
+ if (block.s === null) {
27
+ tracked_index = tracked(index, block);
28
+
29
+ block.s = {
30
+ start: null,
31
+ end: null,
32
+ i: tracked_index,
33
+ };
34
+ } else {
35
+ tracked_index = block.s.i;
36
+ }
37
+ render_fn(anchor, value, tracked_index);
38
+ } else {
39
+ render_fn(anchor, value);
40
+ }
41
+ });
42
+ return b;
32
43
  }
33
44
 
45
+ /**
46
+ * @param {Block} block
47
+ * @param {Element} anchor
48
+ * @returns {void}
49
+ */
34
50
  function move(block, anchor) {
35
- var node = block.s.start;
36
- var end = block.s.end;
37
-
38
- if (node === end) {
39
- anchor.before(node);
40
- return;
41
- }
42
- while (node !== null) {
43
- var next_node = /** @type {TemplateNode} */ (next_sibling(node));
44
- anchor.before(node);
45
- node = next_node;
46
- if (node === end) {
47
- anchor.before(end);
48
- break;
49
- }
50
- }
51
+ var node = block.s.start;
52
+ var end = block.s.end;
53
+
54
+ if (node === end) {
55
+ anchor.before(node);
56
+ return;
57
+ }
58
+ while (node !== null) {
59
+ var next_node = /** @type {Node} */ (next_sibling(node));
60
+ anchor.before(node);
61
+ node = next_node;
62
+ if (node === end) {
63
+ anchor.before(end);
64
+ break;
65
+ }
66
+ }
51
67
  }
52
68
 
69
+ /**
70
+ * @template V
71
+ * @param {V[] | Iterable<V>} collection
72
+ * @returns {V[]}
73
+ */
53
74
  function collection_to_array(collection) {
54
- var array = is_array(collection) ? collection : collection == null ? [] : array_from(collection);
75
+ var array = is_array(collection) ? collection : collection == null ? [] : array_from(collection);
55
76
 
56
- // If we are working with a tracked array, then we need to get a copy of
57
- // the elements, as the array itself is proxied, and not useful in diffing
58
- if (TRACKED_ARRAY in array) {
59
- array = array_from(array);
60
- }
77
+ // If we are working with a tracked array, then we need to get a copy of
78
+ // the elements, as the array itself is proxied, and not useful in diffing
79
+ if (TRACKED_ARRAY in array) {
80
+ array = array_from(array);
81
+ }
61
82
 
62
- return array;
83
+ return array;
63
84
  }
64
85
 
86
+ /**
87
+ * @template V
88
+ * @param {Element} node
89
+ * @param {() => V[] | Iterable<V>} get_collection
90
+ * @param {(anchor: Node, value: V, index?: any) => Block} render_fn
91
+ * @param {number} flags
92
+ * @returns {void}
93
+ */
65
94
  export function for_block(node, get_collection, render_fn, flags) {
66
- var is_controlled = (flags & IS_CONTROLLED) !== 0;
67
- var is_indexed = (flags & IS_INDEXED) !== 0;
68
- var anchor = node;
69
-
70
- if (is_controlled) {
71
- anchor = node.appendChild(create_text());
72
- }
73
-
74
- render(() => {
75
- var block = /** @type {Block} */ (active_block);
76
- var collection = get_collection();
77
- var array = collection_to_array(collection);
78
-
79
- untrack(() => {
80
- reconcile(anchor, block, array, render_fn, is_controlled, is_indexed);
81
- });
82
- }, FOR_BLOCK);
95
+ var is_controlled = (flags & IS_CONTROLLED) !== 0;
96
+ var is_indexed = (flags & IS_INDEXED) !== 0;
97
+ var anchor = /** @type {Element | Text} */ (node);
98
+
99
+ if (is_controlled) {
100
+ anchor = node.appendChild(create_text());
101
+ }
102
+
103
+ render(() => {
104
+ var block = /** @type {Block} */ (active_block);
105
+ var collection = get_collection();
106
+ var array = collection_to_array(collection);
107
+
108
+ untrack(() => {
109
+ reconcile(anchor, block, array, render_fn, is_controlled, is_indexed);
110
+ });
111
+ }, FOR_BLOCK);
83
112
  }
84
113
 
114
+ /**
115
+ * @template V
116
+ * @param {Element | Text} anchor
117
+ * @param {Block} block
118
+ * @param {V[]} array
119
+ * @returns {void}
120
+ */
85
121
  function reconcile_fast_clear(anchor, block, array) {
86
- var state = block.s;
87
- var parent_node = anchor.parentNode;
88
- parent_node.textContent = '';
89
- destroy_block_children(block);
90
- parent_node.append(anchor);
91
- state.array = array;
92
- state.blocks = [];
122
+ var state = block.s;
123
+ var parent_node = /** @type {Element} */ (anchor.parentNode);
124
+ parent_node.textContent = '';
125
+ destroy_block_children(block);
126
+ parent_node.append(anchor);
127
+ state.array = array;
128
+ state.blocks = [];
93
129
  }
94
130
 
131
+ /**
132
+ * @param {Block} block
133
+ * @param {number} index
134
+ * @returns {void}
135
+ */
95
136
  function update_index(block, index) {
96
- set(block.s.i, index, block);
137
+ set(block.s.i, index, block);
97
138
  }
98
139
 
140
+ /**
141
+ * @template V
142
+ * @param {Element | Text} anchor
143
+ * @param {Block} block
144
+ * @param {V[]} b
145
+ * @param {(anchor: Node, value: V, index?: any) => Block} render_fn
146
+ * @param {boolean} is_controlled
147
+ * @param {boolean} is_indexed
148
+ * @returns {void}
149
+ */
99
150
  function reconcile(anchor, block, b, render_fn, is_controlled, is_indexed) {
100
- var state = block.s;
101
-
102
- if (state === null) {
103
- state = block.s = {
104
- array: [],
105
- blocks: [],
106
- };
107
- }
108
-
109
- var a = state.array;
110
- var a_length = a.length;
111
- var b_length = b.length;
112
- var j = 0;
113
-
114
- // Fast-path for clear
115
- if (is_controlled && b_length === 0) {
116
- if (a_length > 0) {
117
- reconcile_fast_clear(anchor, block, b);
118
- }
119
- return;
120
- }
121
- var b_blocks = Array(b_length);
122
-
123
- // Fast-path for create
124
- if (a_length === 0) {
125
- for (; j < b_length; j++) {
126
- b_blocks[j] = create_item(anchor, b[j], j, render_fn, is_indexed);
127
- }
128
- state.array = b;
129
- state.blocks = b_blocks;
130
- return;
131
- }
132
-
133
- var a_blocks = state.blocks;
134
- var a_val = a[j];
135
- var b_val = b[j];
136
- var a_end = a_length - 1;
137
- var b_end = b_length - 1;
138
- var b_block;
139
-
140
- outer: {
141
- while (a_val === b_val) {
142
- a[j] = b_val;
143
- b_block = b_blocks[j] = a_blocks[j];
144
- if (is_indexed) {
145
- update_index(b_block, j);
146
- }
147
- ++j;
148
- if (j > a_end || j > b_end) {
149
- break outer;
150
- }
151
- a_val = a[j];
152
- b_val = b[j];
153
- }
154
-
155
- a_val = a[a_end];
156
- b_val = b[b_end];
157
-
158
- while (a_val === b_val) {
159
- a[a_end] = b_val;
160
- b_block = b_blocks[b_end] = a_blocks[a_end];
161
- if (is_indexed) {
162
- update_index(b_block, b_end);
163
- }
164
- a_end--;
165
- b_end--;
166
- if (j > a_end || j > b_end) {
167
- break outer;
168
- }
169
- a_val = a[a_end];
170
- b_val = b[b_end];
171
- }
172
- }
173
-
174
- var fast_path_removal = false;
175
-
176
- if (j > a_end) {
177
- if (j <= b_end) {
178
- while (j <= b_end) {
179
- b_val = b[j];
180
- var target = j >= a_length ? anchor : a_blocks[j].s.start;
181
- b_blocks[j] = create_item(target, b_val, j, render_fn, is_indexed);
182
- j++;
183
- }
184
- }
185
- } else if (j > b_end) {
186
- while (j <= a_end) {
187
- destroy_block(a_blocks[j++]);
188
- }
189
- } else {
190
- var a_start = j;
191
- var b_start = j;
192
- var a_left = a_end - j + 1;
193
- var b_left = b_end - j + 1;
194
- var sources = new Int32Array(b_left + 1);
195
- var moved = false;
196
- var pos = 0;
197
- var patched = 0;
198
- var i = 0;
199
-
200
- fast_path_removal = is_controlled && a_left === a_length;
201
-
202
- // When sizes are small, just loop them through
203
- if (b_length < 4 || (a_left | b_left) < 32) {
204
- for (i = a_start; i <= a_end; ++i) {
205
- a_val = a[i];
206
- if (patched < b_left) {
207
- for (j = b_start; j <= b_end; j++) {
208
- b_val = b[j];
209
- if (a_val === b_val) {
210
- sources[j - b_start] = i + 1;
211
- if (fast_path_removal) {
212
- fast_path_removal = false;
213
- while (a_start < i) {
214
- destroy_block(a_blocks[a_start++]);
215
- }
216
- }
217
- if (pos > j) {
218
- moved = true;
219
- } else {
220
- pos = j;
221
- }
222
- b_block = b_blocks[j] = a_blocks[i];
223
- if (is_indexed) {
224
- update_index(b_block, j);
225
- }
226
- ++patched;
227
- break;
228
- }
229
- }
230
- if (!fast_path_removal && j > b_end) {
231
- destroy_block(a_blocks[i]);
232
- }
233
- } else if (!fast_path_removal) {
234
- destroy_block(a_blocks[i]);
235
- }
236
- }
237
- } else {
238
- var map = new Map();
239
-
240
- for (i = b_start; i <= b_end; ++i) {
241
- map.set(b[i], i);
242
- }
243
-
244
- for (i = a_start; i <= a_end; ++i) {
245
- a_val = a[i];
246
-
247
- if (patched < b_left) {
248
- j = map.get(a_val);
249
-
250
- if (j !== undefined) {
251
- if (fast_path_removal) {
252
- fast_path_removal = false;
253
- // while (i > a_start) {
254
- // destroy_block(a[a_start++]);
255
- // }
256
- }
257
- sources[j - b_start] = i + 1;
258
- if (pos > j) {
259
- moved = true;
260
- } else {
261
- pos = j;
262
- }
263
- b_val = b[j];
264
- block = b_blocks[j] = a_blocks[i];
265
- if (is_indexed) {
266
- update_index(block, j);
267
- }
268
- ++patched;
269
- } else if (!fast_path_removal) {
270
- destroy_block(a_blocks[i]);
271
- }
272
- } else if (!fast_path_removal) {
273
- destroy_block(a_blocks[i]);
274
- }
275
- }
276
- }
277
- }
278
-
279
- if (fast_path_removal) {
280
- reconcile_fast_clear(anchor, block, []);
281
- reconcile(anchor, block, b, render_fn, is_controlled, is_indexed);
282
- return;
283
- } else if (moved) {
284
- var next_pos = 0;
285
- var seq = lis_algorithm(sources);
286
- j = seq.length - 1;
287
-
288
- for (i = b_left - 1; i >= 0; i--) {
289
- if (sources[i] === 0) {
290
- pos = i + b_start;
291
- b_val = b[pos];
292
- next_pos = pos + 1;
293
-
294
- var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
295
- b_blocks[pos] = create_item(target, b_val, pos, render_fn, is_indexed);
296
- } else if (j < 0 || i !== seq[j]) {
297
- pos = i + b_start;
298
- b_val = b[pos];
299
- next_pos = pos + 1;
300
-
301
- var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
302
- move(b_blocks[pos], target);
303
- } else {
304
- j--;
305
- }
306
- }
307
- } else if (patched !== b_left) {
308
- for (i = b_left - 1; i >= 0; i--) {
309
- if (sources[i] === 0) {
310
- pos = i + b_start;
311
- b_val = b[pos];
312
- next_pos = pos + 1;
313
-
314
- var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
315
- b_blocks[pos] = create_item(target, b_val, pos, render_fn, is_indexed);
316
- }
317
- }
318
- }
319
-
320
- state.array = b;
321
- state.blocks = b_blocks;
151
+ var state = block.s;
152
+
153
+ // Variables used in conditional branches - declare with initial values
154
+ /** @type {number} */
155
+ var a_start = 0;
156
+ /** @type {number} */
157
+ var b_start = 0;
158
+ /** @type {number} */
159
+ var a_left = 0;
160
+ /** @type {number} */
161
+ var b_left = 0;
162
+ /** @type {Int32Array} */
163
+ var sources = new Int32Array(0);
164
+ /** @type {boolean} */
165
+ var moved = false;
166
+ /** @type {number} */
167
+ var pos = 0;
168
+ /** @type {number} */
169
+ var patched = 0;
170
+ /** @type {number} */
171
+ var i = 0;
172
+
173
+ if (state === null) {
174
+ state = block.s = {
175
+ array: [],
176
+ blocks: [],
177
+ };
178
+ }
179
+
180
+ var a = state.array;
181
+ var a_length = a.length;
182
+ var b_length = b.length;
183
+ var j = 0;
184
+
185
+ // Fast-path for clear
186
+ if (is_controlled && b_length === 0) {
187
+ if (a_length > 0) {
188
+ reconcile_fast_clear(anchor, block, b);
189
+ }
190
+ return;
191
+ }
192
+ var b_blocks = Array(b_length);
193
+
194
+ // Fast-path for create
195
+ if (a_length === 0) {
196
+ for (; j < b_length; j++) {
197
+ b_blocks[j] = create_item(anchor, b[j], j, render_fn, is_indexed);
198
+ }
199
+ state.array = b;
200
+ state.blocks = b_blocks;
201
+ return;
202
+ }
203
+
204
+ var a_blocks = state.blocks;
205
+ var a_val = a[j];
206
+ var b_val = b[j];
207
+ var a_end = a_length - 1;
208
+ var b_end = b_length - 1;
209
+ var b_block;
210
+
211
+ outer: {
212
+ while (a_val === b_val) {
213
+ a[j] = b_val;
214
+ b_block = b_blocks[j] = a_blocks[j];
215
+ if (is_indexed) {
216
+ update_index(b_block, j);
217
+ }
218
+ ++j;
219
+ if (j > a_end || j > b_end) {
220
+ break outer;
221
+ }
222
+ a_val = a[j];
223
+ b_val = b[j];
224
+ }
225
+
226
+ a_val = a[a_end];
227
+ b_val = b[b_end];
228
+
229
+ while (a_val === b_val) {
230
+ a[a_end] = b_val;
231
+ b_block = b_blocks[b_end] = a_blocks[a_end];
232
+ if (is_indexed) {
233
+ update_index(b_block, b_end);
234
+ }
235
+ a_end--;
236
+ b_end--;
237
+ if (j > a_end || j > b_end) {
238
+ break outer;
239
+ }
240
+ a_val = a[a_end];
241
+ b_val = b[b_end];
242
+ }
243
+ }
244
+
245
+ var fast_path_removal = false;
246
+
247
+ if (j > a_end) {
248
+ if (j <= b_end) {
249
+ while (j <= b_end) {
250
+ b_val = b[j];
251
+ var target = j >= a_length ? anchor : a_blocks[j].s.start;
252
+ b_blocks[j] = create_item(target, b_val, j, render_fn, is_indexed);
253
+ j++;
254
+ }
255
+ }
256
+ } else if (j > b_end) {
257
+ while (j <= a_end) {
258
+ destroy_block(a_blocks[j++]);
259
+ }
260
+ } else {
261
+ a_start = j;
262
+ b_start = j;
263
+ a_left = a_end - j + 1;
264
+ b_left = b_end - j + 1;
265
+ sources = new Int32Array(b_left + 1);
266
+ moved = false;
267
+ pos = 0;
268
+ patched = 0;
269
+ i = 0;
270
+
271
+ fast_path_removal = is_controlled && a_left === a_length;
272
+
273
+ // When sizes are small, just loop them through
274
+ if (b_length < 4 || (a_left | b_left) < 32) {
275
+ for (i = a_start; i <= a_end; ++i) {
276
+ a_val = a[i];
277
+ if (patched < b_left) {
278
+ for (j = b_start; j <= b_end; j++) {
279
+ b_val = b[j];
280
+ if (a_val === b_val) {
281
+ sources[j - b_start] = i + 1;
282
+ if (fast_path_removal) {
283
+ fast_path_removal = false;
284
+ while (a_start < i) {
285
+ destroy_block(a_blocks[a_start++]);
286
+ }
287
+ }
288
+ if (pos > j) {
289
+ moved = true;
290
+ } else {
291
+ pos = j;
292
+ }
293
+ b_block = b_blocks[j] = a_blocks[i];
294
+ if (is_indexed) {
295
+ update_index(b_block, j);
296
+ }
297
+ ++patched;
298
+ break;
299
+ }
300
+ }
301
+ if (!fast_path_removal && j > b_end) {
302
+ destroy_block(a_blocks[i]);
303
+ }
304
+ } else if (!fast_path_removal) {
305
+ destroy_block(a_blocks[i]);
306
+ }
307
+ }
308
+ } else {
309
+ var map = new Map();
310
+
311
+ for (i = b_start; i <= b_end; ++i) {
312
+ map.set(b[i], i);
313
+ }
314
+
315
+ for (i = a_start; i <= a_end; ++i) {
316
+ a_val = a[i];
317
+
318
+ if (patched < b_left) {
319
+ j = map.get(a_val);
320
+
321
+ if (j !== undefined) {
322
+ if (fast_path_removal) {
323
+ fast_path_removal = false;
324
+ // while (i > a_start) {
325
+ // destroy_block(a[a_start++]);
326
+ // }
327
+ }
328
+ sources[j - b_start] = i + 1;
329
+ if (pos > j) {
330
+ moved = true;
331
+ } else {
332
+ pos = j;
333
+ }
334
+ b_val = b[j];
335
+ block = b_blocks[j] = a_blocks[i];
336
+ if (is_indexed) {
337
+ update_index(block, j);
338
+ }
339
+ ++patched;
340
+ } else if (!fast_path_removal) {
341
+ destroy_block(a_blocks[i]);
342
+ }
343
+ } else if (!fast_path_removal) {
344
+ destroy_block(a_blocks[i]);
345
+ }
346
+ }
347
+ }
348
+ }
349
+
350
+ if (fast_path_removal) {
351
+ reconcile_fast_clear(anchor, block, []);
352
+ reconcile(anchor, block, b, render_fn, is_controlled, is_indexed);
353
+ return;
354
+ } else if (moved) {
355
+ var next_pos = 0;
356
+ var seq = lis_algorithm(sources);
357
+ j = seq.length - 1;
358
+
359
+ for (i = b_left - 1; i >= 0; i--) {
360
+ if (sources[i] === 0) {
361
+ pos = i + b_start;
362
+ b_val = b[pos];
363
+ next_pos = pos + 1;
364
+
365
+ var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
366
+ b_blocks[pos] = create_item(target, b_val, pos, render_fn, is_indexed);
367
+ } else if (j < 0 || i !== seq[j]) {
368
+ pos = i + b_start;
369
+ b_val = b[pos];
370
+ next_pos = pos + 1;
371
+
372
+ var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
373
+ move(b_blocks[pos], target);
374
+ } else {
375
+ j--;
376
+ }
377
+ }
378
+ } else if (patched !== b_left) {
379
+ for (i = b_left - 1; i >= 0; i--) {
380
+ if (sources[i] === 0) {
381
+ pos = i + b_start;
382
+ b_val = b[pos];
383
+ next_pos = pos + 1;
384
+
385
+ var target = next_pos < b_length ? b_blocks[next_pos].s.start : anchor;
386
+ b_blocks[pos] = create_item(target, b_val, pos, render_fn, is_indexed);
387
+ }
388
+ }
389
+ }
390
+
391
+ state.array = b;
392
+ state.blocks = b_blocks;
322
393
  }
323
394
 
395
+ /** @type {Int32Array} */
324
396
  let result;
397
+ /** @type {Int32Array} */
325
398
  let p;
326
399
  let maxLen = 0;
327
400
  // https://en.wikipedia.org/wiki/Longest_increasing_subsequence
401
+ /**
402
+ * @param {Int32Array} arr
403
+ * @returns {Int32Array}
404
+ */
328
405
  function lis_algorithm(arr) {
329
- let arrI = 0;
330
- let i = 0;
331
- let j = 0;
332
- let k = 0;
333
- let u = 0;
334
- let v = 0;
335
- let c = 0;
336
- var len = arr.length;
337
-
338
- if (len > maxLen) {
339
- maxLen = len;
340
- result = new Int32Array(len);
341
- p = new Int32Array(len);
342
- }
343
-
344
- for (; i < len; ++i) {
345
- arrI = arr[i];
346
-
347
- if (arrI !== 0) {
348
- j = result[k];
349
- if (arr[j] < arrI) {
350
- p[i] = j;
351
- result[++k] = i;
352
- continue;
353
- }
354
-
355
- u = 0;
356
- v = k;
357
-
358
- while (u < v) {
359
- c = (u + v) >> 1;
360
- if (arr[result[c]] < arrI) {
361
- u = c + 1;
362
- } else {
363
- v = c;
364
- }
365
- }
366
-
367
- if (arrI < arr[result[u]]) {
368
- if (u > 0) {
369
- p[i] = result[u - 1];
370
- }
371
- result[u] = i;
372
- }
373
- }
374
- }
375
-
376
- u = k + 1;
377
- var seq = new Int32Array(u);
378
- v = result[u - 1];
379
-
380
- while (u-- > 0) {
381
- seq[u] = v;
382
- v = p[v];
383
- result[u] = 0;
384
- }
385
-
386
- return seq;
406
+ let arrI = 0;
407
+ let i = 0;
408
+ let j = 0;
409
+ let k = 0;
410
+ let u = 0;
411
+ let v = 0;
412
+ let c = 0;
413
+ var len = arr.length;
414
+
415
+ if (len > maxLen) {
416
+ maxLen = len;
417
+ result = new Int32Array(len);
418
+ p = new Int32Array(len);
419
+ }
420
+
421
+ for (; i < len; ++i) {
422
+ arrI = arr[i];
423
+
424
+ if (arrI !== 0) {
425
+ j = result[k];
426
+ if (arr[j] < arrI) {
427
+ p[i] = j;
428
+ result[++k] = i;
429
+ continue;
430
+ }
431
+
432
+ u = 0;
433
+ v = k;
434
+
435
+ while (u < v) {
436
+ c = (u + v) >> 1;
437
+ if (arr[result[c]] < arrI) {
438
+ u = c + 1;
439
+ } else {
440
+ v = c;
441
+ }
442
+ }
443
+
444
+ if (arrI < arr[result[u]]) {
445
+ if (u > 0) {
446
+ p[i] = result[u - 1];
447
+ }
448
+ result[u] = i;
449
+ }
450
+ }
451
+ }
452
+
453
+ u = k + 1;
454
+ var seq = new Int32Array(u);
455
+ v = result[u - 1];
456
+
457
+ while (u-- > 0) {
458
+ seq[u] = v;
459
+ v = p[v];
460
+ result[u] = 0;
461
+ }
462
+
463
+ return seq;
387
464
  }
388
465
 
466
+ /**
467
+ * @template V
468
+ * @template K
469
+ * @param {V[] | Iterable<V>} collection
470
+ * @param {(item: V) => K} key_fn
471
+ * @returns {V[]}
472
+ */
389
473
  export function keyed(collection, key_fn) {
390
- var block = active_block;
391
- if (block === null || (block.f & FOR_BLOCK) === 0) {
392
- throw new Error('keyed() must be used inside a for block');
393
- }
474
+ var block = active_block;
475
+ if (block === null || (block.f & FOR_BLOCK) === 0) {
476
+ throw new Error('keyed() must be used inside a for block');
477
+ }
394
478
 
395
- var b_array = collection_to_array(collection);
396
- var b_keys = b_array.map(key_fn);
479
+ var b_array = collection_to_array(collection);
480
+ var b_keys = b_array.map(key_fn);
397
481
 
398
- // We only need to do this in DEV
399
- var b = new Set(b_keys);
400
- if (b.size !== b_keys.length) {
401
- throw new Error('Duplicate keys are not allowed');
402
- }
482
+ // We only need to do this in DEV
483
+ var b = new Set(b_keys);
484
+ if (b.size !== b_keys.length) {
485
+ throw new Error('Duplicate keys are not allowed');
486
+ }
403
487
 
404
- var state = block.s;
488
+ var state = block.s;
405
489
 
406
- if (state === null) {
407
- return collection;
408
- }
490
+ if (state === null) {
491
+ return b_array;
492
+ }
409
493
 
410
- var a_array = state.array;
411
- var a_keys = a_array.map(key_fn);
412
- var a = new Map();
494
+ var a_array = state.array;
495
+ var a_keys = a_array.map(key_fn);
496
+ var a = new Map();
413
497
 
414
- for (let i = 0; i < a_keys.length; i++) {
415
- a.set(a_keys[i], i);
416
- }
498
+ for (let i = 0; i < a_keys.length; i++) {
499
+ a.set(a_keys[i], i);
500
+ }
417
501
 
418
- if (a.size !== a_keys.length) {
419
- throw new Error('Duplicate keys are not allowed');
420
- }
502
+ if (a.size !== a_keys.length) {
503
+ throw new Error('Duplicate keys are not allowed');
504
+ }
421
505
 
422
- for (let i = 0; i < b_keys.length; i++) {
423
- var b_val = b_keys[i];
424
- var index = a.get(b_val);
506
+ for (let i = 0; i < b_keys.length; i++) {
507
+ var b_val = b_keys[i];
508
+ var index = a.get(b_val);
425
509
 
426
- if (index !== undefined) {
427
- b_array[i] = a_array[index];
428
- }
429
- }
510
+ if (index !== undefined) {
511
+ b_array[i] = a_array[index];
512
+ }
513
+ }
430
514
 
431
- return b_array;
515
+ return b_array;
432
516
  }