ripple 0.3.7 → 0.3.9

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 (119) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +2 -2
  3. package/src/compiler/phases/1-parse/index.js +48 -349
  4. package/src/compiler/phases/2-analyze/index.js +343 -52
  5. package/src/compiler/phases/3-transform/client/index.js +28 -160
  6. package/src/compiler/phases/3-transform/segments.js +0 -7
  7. package/src/compiler/phases/3-transform/server/index.js +31 -154
  8. package/src/compiler/types/acorn.d.ts +1 -1
  9. package/src/compiler/types/estree.d.ts +1 -1
  10. package/src/compiler/types/import.d.ts +0 -2
  11. package/src/compiler/types/index.d.ts +5 -17
  12. package/src/compiler/types/parse.d.ts +1 -17
  13. package/src/compiler/utils.js +53 -20
  14. package/src/runtime/index-client.js +2 -13
  15. package/src/runtime/index-server.js +2 -2
  16. package/src/runtime/internal/client/bindings.js +3 -1
  17. package/src/runtime/internal/client/composite.js +3 -2
  18. package/src/runtime/internal/client/events.js +1 -1
  19. package/src/runtime/internal/client/head.js +3 -4
  20. package/src/runtime/internal/client/index.js +0 -1
  21. package/src/runtime/internal/client/runtime.js +0 -52
  22. package/src/runtime/internal/server/index.js +31 -55
  23. package/tests/client/array/array.copy-within.test.ripple +12 -12
  24. package/tests/client/array/array.derived.test.ripple +46 -46
  25. package/tests/client/array/array.iteration.test.ripple +10 -10
  26. package/tests/client/array/array.mutations.test.ripple +20 -20
  27. package/tests/client/array/array.to-methods.test.ripple +6 -6
  28. package/tests/client/async-suspend.test.ripple +5 -5
  29. package/tests/client/basic/basic.attributes.test.ripple +81 -81
  30. package/tests/client/basic/basic.collections.test.ripple +9 -9
  31. package/tests/client/basic/basic.components.test.ripple +28 -28
  32. package/tests/client/basic/basic.errors.test.ripple +46 -18
  33. package/tests/client/basic/basic.events.test.ripple +37 -37
  34. package/tests/client/basic/basic.get-set.test.ripple +6 -6
  35. package/tests/client/basic/basic.reactivity.test.ripple +58 -203
  36. package/tests/client/basic/basic.rendering.test.ripple +19 -19
  37. package/tests/client/basic/basic.utilities.test.ripple +3 -3
  38. package/tests/client/boundaries.test.ripple +12 -12
  39. package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
  40. package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
  41. package/tests/client/compiler/compiler.basic.test.ripple +46 -27
  42. package/tests/client/compiler/compiler.tracked-access.test.ripple +2 -2
  43. package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
  44. package/tests/client/composite/composite.props.test.ripple +14 -16
  45. package/tests/client/composite/composite.reactivity.test.ripple +69 -70
  46. package/tests/client/composite/composite.render.test.ripple +3 -3
  47. package/tests/client/computed-properties.test.ripple +4 -4
  48. package/tests/client/date.test.ripple +42 -42
  49. package/tests/client/dynamic-elements.test.ripple +44 -45
  50. package/tests/client/events.test.ripple +70 -70
  51. package/tests/client/for.test.ripple +25 -25
  52. package/tests/client/head.test.ripple +19 -19
  53. package/tests/client/html.test.ripple +3 -3
  54. package/tests/client/input-value.test.ripple +84 -84
  55. package/tests/client/lazy-destructuring.test.ripple +138 -26
  56. package/tests/client/map.test.ripple +16 -16
  57. package/tests/client/media-query.test.ripple +7 -7
  58. package/tests/client/portal.test.ripple +11 -11
  59. package/tests/client/ref.test.ripple +4 -4
  60. package/tests/client/return.test.ripple +52 -52
  61. package/tests/client/set.test.ripple +6 -6
  62. package/tests/client/svg.test.ripple +5 -5
  63. package/tests/client/switch.test.ripple +44 -44
  64. package/tests/client/try.test.ripple +5 -5
  65. package/tests/client/url/url.derived.test.ripple +6 -6
  66. package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
  67. package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
  68. package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
  69. package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
  70. package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
  71. package/tests/hydration/compiled/client/events.js +25 -25
  72. package/tests/hydration/compiled/client/for.js +70 -66
  73. package/tests/hydration/compiled/client/head.js +25 -25
  74. package/tests/hydration/compiled/client/hmr.js +2 -2
  75. package/tests/hydration/compiled/client/html.js +3 -3
  76. package/tests/hydration/compiled/client/if-children.js +24 -24
  77. package/tests/hydration/compiled/client/if.js +18 -18
  78. package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
  79. package/tests/hydration/compiled/client/portal.js +3 -3
  80. package/tests/hydration/compiled/client/reactivity.js +16 -16
  81. package/tests/hydration/compiled/client/return.js +40 -40
  82. package/tests/hydration/compiled/client/switch.js +12 -12
  83. package/tests/hydration/compiled/server/events.js +19 -19
  84. package/tests/hydration/compiled/server/for.js +41 -41
  85. package/tests/hydration/compiled/server/head.js +26 -26
  86. package/tests/hydration/compiled/server/hmr.js +2 -2
  87. package/tests/hydration/compiled/server/html.js +2 -2
  88. package/tests/hydration/compiled/server/if-children.js +16 -16
  89. package/tests/hydration/compiled/server/if.js +11 -11
  90. package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
  91. package/tests/hydration/compiled/server/portal.js +2 -2
  92. package/tests/hydration/compiled/server/reactivity.js +16 -16
  93. package/tests/hydration/compiled/server/return.js +25 -25
  94. package/tests/hydration/compiled/server/switch.js +8 -8
  95. package/tests/hydration/components/events.ripple +25 -25
  96. package/tests/hydration/components/for.ripple +66 -66
  97. package/tests/hydration/components/head.ripple +16 -16
  98. package/tests/hydration/components/hmr.ripple +2 -2
  99. package/tests/hydration/components/html.ripple +3 -3
  100. package/tests/hydration/components/if-children.ripple +24 -24
  101. package/tests/hydration/components/if.ripple +18 -18
  102. package/tests/hydration/components/mixed-control-flow.ripple +9 -9
  103. package/tests/hydration/components/portal.ripple +3 -3
  104. package/tests/hydration/components/reactivity.ripple +16 -16
  105. package/tests/hydration/components/return.ripple +40 -40
  106. package/tests/hydration/components/switch.ripple +20 -20
  107. package/tests/server/await.test.ripple +3 -3
  108. package/tests/server/basic.attributes.test.ripple +34 -34
  109. package/tests/server/basic.components.test.ripple +10 -10
  110. package/tests/server/basic.test.ripple +38 -40
  111. package/tests/server/compiler.test.ripple +22 -0
  112. package/tests/server/composite.props.test.ripple +12 -14
  113. package/tests/server/dynamic-elements.test.ripple +15 -15
  114. package/tests/server/head.test.ripple +11 -11
  115. package/tests/server/lazy-destructuring.test.ripple +92 -13
  116. package/tsconfig.typecheck.json +4 -0
  117. package/types/index.d.ts +0 -19
  118. package/tests/client/__snapshots__/tracked-expression.test.ripple.snap +0 -34
  119. package/tests/client/tracked-expression.test.ripple +0 -26
@@ -292,25 +292,25 @@ export function is_component_level_function(context) {
292
292
  * Returns the matched Ripple tracking call name
293
293
  * @param {AST.Expression | AST.Super} callee
294
294
  * @param {CommonContext} context
295
- * @returns {'track' | 'trackSplit' | null}
295
+ * @returns {'track' | null}
296
296
  */
297
297
  export function is_ripple_track_call(callee, context) {
298
298
  // Super expressions cannot be Ripple track calls
299
299
  if (callee.type === 'Super') return null;
300
300
 
301
- if (callee.type === 'Identifier' && (callee.name === 'track' || callee.name === 'trackSplit')) {
302
- return is_ripple_import(callee, context) ? callee.name : null;
301
+ if (callee.type === 'Identifier' && callee.name === 'track') {
302
+ return is_ripple_import(callee, context) ? 'track' : null;
303
303
  }
304
304
 
305
305
  if (
306
306
  callee.type === 'MemberExpression' &&
307
307
  callee.object.type === 'Identifier' &&
308
308
  callee.property.type === 'Identifier' &&
309
- (callee.property.name === 'track' || callee.property.name === 'trackSplit') &&
309
+ callee.property.name === 'track' &&
310
310
  !callee.computed &&
311
311
  is_ripple_import(callee, context)
312
312
  ) {
313
- return callee.property.name;
313
+ return 'track';
314
314
  }
315
315
 
316
316
  return null;
@@ -606,21 +606,8 @@ export function is_element_dynamic(node) {
606
606
  * @returns {boolean}
607
607
  */
608
608
  function is_id_dynamic(node) {
609
- if (node.type === 'Identifier' || node.type === 'Literal') {
610
- if (node.tracked) {
611
- return true;
612
- }
613
-
614
- return false;
615
- } else if (node.type === 'MemberExpression') {
616
- if (/** @type {AST.Identifier} */ (node.object).tracked === true) {
617
- return true;
618
- }
619
- if (node.property.type === 'MemberExpression') {
620
- return is_id_dynamic(node.property);
621
- }
622
-
623
- return !!(/** @type {AST.Identifier} */ (node.property).tracked);
609
+ if (node.type === 'Identifier') {
610
+ return !!node.tracked;
624
611
  }
625
612
 
626
613
  return false;
@@ -686,6 +673,52 @@ function normalize_child(node, normalized, context) {
686
673
  }
687
674
  }
688
675
 
676
+ /**
677
+ * Replaces any lazy subpatterns in a parameter pattern with their generated identifiers.
678
+ * This is used by client and server transforms so nested lazy destructuring can coexist
679
+ * with otherwise normal object/array params.
680
+ * @param {AST.Pattern} pattern
681
+ * @returns {AST.Pattern}
682
+ */
683
+ export function replace_lazy_param_pattern(pattern) {
684
+ switch (pattern.type) {
685
+ case 'AssignmentPattern':
686
+ return { ...pattern, left: replace_lazy_param_pattern(pattern.left) };
687
+
688
+ case 'ObjectPattern':
689
+ if (pattern.lazy && pattern.metadata?.lazy_id) {
690
+ return /** @type {AST.Pattern} */ (b.id(pattern.metadata.lazy_id));
691
+ }
692
+
693
+ return {
694
+ ...pattern,
695
+ properties: pattern.properties.map((property) =>
696
+ property.type === 'RestElement'
697
+ ? { ...property, argument: replace_lazy_param_pattern(property.argument) }
698
+ : { ...property, value: replace_lazy_param_pattern(property.value) },
699
+ ),
700
+ };
701
+
702
+ case 'ArrayPattern':
703
+ if (pattern.lazy && pattern.metadata?.lazy_id) {
704
+ return /** @type {AST.Pattern} */ (b.id(pattern.metadata.lazy_id));
705
+ }
706
+
707
+ return {
708
+ ...pattern,
709
+ elements: pattern.elements.map((element) =>
710
+ element === null ? null : replace_lazy_param_pattern(element),
711
+ ),
712
+ };
713
+
714
+ case 'RestElement':
715
+ return { ...pattern, argument: replace_lazy_param_pattern(pattern.argument) };
716
+
717
+ default:
718
+ return pattern;
719
+ }
720
+ }
721
+
689
722
  /**
690
723
  * @param {CommonContext} context
691
724
  */
@@ -102,13 +102,7 @@ export function hydrate(component, options) {
102
102
 
103
103
  export { Context } from './internal/client/context.js';
104
104
 
105
- export {
106
- flush_sync as flushSync,
107
- track,
108
- track_split as trackSplit,
109
- untrack,
110
- tick,
111
- } from './internal/client/runtime.js';
105
+ export { flush_sync as flushSync, track, untrack, tick } from './internal/client/runtime.js';
112
106
 
113
107
  export { RippleArray } from './array.js';
114
108
 
@@ -165,10 +159,5 @@ import { RippleURL } from './url.js';
165
159
  import { RippleURLSearchParams } from './url-search-params.js';
166
160
  import { RippleDate } from './date.js';
167
161
  import { MediaQuery } from './media-query.js';
168
- import {
169
- track,
170
- track_split as trackSplit,
171
- untrack,
172
- ref_prop as createRefKey,
173
- } from './internal/client/runtime.js';
162
+ import { track, untrack, ref_prop as createRefKey } from './internal/client/runtime.js';
174
163
  import { user_effect as effect } from './internal/client/blocks.js';
@@ -1,8 +1,8 @@
1
- import { get, set, untrack, track, track_split } from './internal/server/index.js';
1
+ import { get, set, untrack, track } from './internal/server/index.js';
2
2
 
3
3
  export { Context } from './internal/server/context.js';
4
4
 
5
- export { get, set, untrack, track, track_split as trackSplit };
5
+ export { get, set, untrack, track };
6
6
 
7
7
  function noop() {}
8
8
 
@@ -186,7 +186,9 @@ function select_option(select, value, mounting = false) {
186
186
 
187
187
  // Otherwise, update the selection
188
188
  for (var option of select.options) {
189
- option.selected = /** @type {string[]} */ (value).includes(get_option_value(option));
189
+ option.selected = /** @type {string[]} */ (value).includes(
190
+ /** @type {string} */ (get_option_value(option)),
191
+ );
190
192
  }
191
193
 
192
194
  return;
@@ -3,7 +3,7 @@
3
3
  import { branch, destroy_block, render, render_spread } from './blocks.js';
4
4
  import { COMPOSITE_BLOCK, DEFAULT_NAMESPACE, NAMESPACE_URI } from './constants.js';
5
5
  import { hydrate_next, hydrating } from './hydration.js';
6
- import { active_block, active_namespace, with_ns } from './runtime.js';
6
+ import { active_block, active_namespace, get, with_ns } from './runtime.js';
7
7
  import { top_element_to_ns } from './utils.js';
8
8
 
9
9
  /**
@@ -29,7 +29,8 @@ export function composite(get_component, node, props) {
29
29
 
30
30
  render(
31
31
  () => {
32
- var component = get_component();
32
+ // @ts-ignore get() handles non-tracked values via is_ripple_object() check
33
+ var component = get(get_component());
33
34
 
34
35
  if (b !== null) {
35
36
  destroy_block(b);
@@ -168,7 +168,7 @@ export function handle_event_propagation(event) {
168
168
  null;
169
169
 
170
170
  try {
171
- var delegated = current_target['__' + event_name];
171
+ var delegated = /** @type {Record<string, any>} */ (current_target)['__' + event_name];
172
172
 
173
173
  if (delegated !== undefined && !(/** @type {any} */ (current_target).disabled)) {
174
174
  if (is_array(delegated)) {
@@ -1,4 +1,3 @@
1
- /** @import { TemplateNode } from '#client' */
2
1
  import { render } from './blocks.js';
3
2
  import { HEAD_BLOCK } from './constants.js';
4
3
  import { COMMENT_NODE } from '../../../constants.js';
@@ -38,8 +37,8 @@ export function head(hash, render_fn) {
38
37
  if (head_anchor === null) {
39
38
  set_hydrating(false);
40
39
  } else {
41
- var start = /** @type {TemplateNode} */ (get_next_sibling(head_anchor));
42
- head_anchor.remove(); // in case this component is repeated
40
+ var start = get_next_sibling(head_anchor);
41
+ /** @type {ChildNode} */ (head_anchor).remove(); // in case this component is repeated
43
42
 
44
43
  set_hydrate_node(start);
45
44
  }
@@ -54,7 +53,7 @@ export function head(hash, render_fn) {
54
53
  } finally {
55
54
  if (was_hydrating) {
56
55
  set_hydrating(true);
57
- set_hydrate_node(/** @type {TemplateNode} */ (previous_hydrate_node));
56
+ set_hydrate_node(previous_hydrate_node);
58
57
  }
59
58
  }
60
59
  }
@@ -52,7 +52,6 @@ export {
52
52
  update_property,
53
53
  update_pre_property,
54
54
  track,
55
- track_split,
56
55
  push_component,
57
56
  pop_component,
58
57
  untrack,
@@ -426,58 +426,6 @@ export function track(v, get, set, b) {
426
426
  return tracked(v, b, get, set);
427
427
  }
428
428
 
429
- /**
430
- * @param {Record<string|symbol, any>} v
431
- * @param {(symbol | string)[]} l
432
- * @param {Block} b
433
- * @returns {Tracked[]}
434
- */
435
- export function track_split(v, l, b) {
436
- var is_tracked = is_ripple_object(v);
437
-
438
- if (is_tracked || typeof v !== 'object' || v === null || is_array(v)) {
439
- throw new TypeError('Invalid value: expected a non-tracked object');
440
- }
441
-
442
- /** @type {Tracked[]} */
443
- var out = [];
444
- /** @type {Record<string|symbol, any>} */
445
- var rest = {};
446
- /** @type {Record<PropertyKey, 1>} */
447
- var done = {};
448
- var props = Reflect.ownKeys(v);
449
-
450
- for (let i = 0, key, t; i < l.length; i++) {
451
- key = l[i];
452
-
453
- if (props.includes(key)) {
454
- if (is_ripple_object(v[key])) {
455
- t = v[key];
456
- } else {
457
- t = tracked(undefined, b);
458
- t = define_property(t, '__v', /** @type {PropertyDescriptor} */ (get_descriptor(v, key)));
459
- }
460
- } else {
461
- t = tracked(undefined, b);
462
- }
463
-
464
- out[i] = t;
465
- done[key] = 1;
466
- }
467
-
468
- for (let i = 0, key; i < props.length; i++) {
469
- key = props[i];
470
- if (done[key]) {
471
- continue;
472
- }
473
- define_property(rest, key, /** @type {PropertyDescriptor} */ (get_descriptor(v, key)));
474
- }
475
-
476
- out.push(tracked(rest, b));
477
-
478
- return out;
479
- }
480
-
481
429
  /**
482
430
  * @param {Tracked | Derived} tracked
483
431
  * @returns {Dependency}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  @import { Component, Dependency, Derived, Tracked } from '#server';
3
- @import { SSRComponent, renderToStream, render } from 'ripple/server';
3
+ @import { SSRComponent } from 'ripple/server';
4
4
  */
5
5
 
6
6
  import { Readable } from 'stream';
@@ -231,12 +231,12 @@ class Output {
231
231
  }
232
232
  }
233
233
 
234
- /** @type {render} */
234
+ /** @type {import('ripple/server').render} */
235
235
  export async function render(component) {
236
236
  const output = new Output(null, null);
237
237
  let head = '';
238
238
  let body = '';
239
- let css = new Set();
239
+ let css = /** @type {Set<string>} */ (new Set());
240
240
 
241
241
  // Reset dev-mode element tracking state at the start of each render
242
242
  reset_element_state();
@@ -262,7 +262,7 @@ export async function render(component) {
262
262
  return { head, body, css };
263
263
  }
264
264
 
265
- /** @type {renderToStream} */
265
+ /** @type {import('ripple/server').renderToStream} */
266
266
  export function renderToStream(component) {
267
267
  const stream = new Readable({
268
268
  read() {},
@@ -702,6 +702,24 @@ function tracked(v, get, set) {
702
702
  return /** @type {Tracked} */ (new TrackedValue(v, get || set ? { get, set } : empty_get_set));
703
703
  }
704
704
 
705
+ /**
706
+ * @param {Record<string, unknown>} obj
707
+ * @param {string[]} exclude_keys
708
+ * @returns {Record<string, unknown>}
709
+ */
710
+ export function exclude_from_object(obj, exclude_keys) {
711
+ /** @type {Record<string, unknown>} */
712
+ var new_obj = {};
713
+
714
+ for (const key of Object.keys(obj)) {
715
+ if (!exclude_keys.includes(key)) {
716
+ new_obj[key] = obj[key];
717
+ }
718
+ }
719
+
720
+ return new_obj;
721
+ }
722
+
705
723
  /**
706
724
  * @param {any} v
707
725
  * @param {(value: any) => any} [get]
@@ -722,57 +740,6 @@ export function track(v, get, set) {
722
740
  return tracked(v, get, set);
723
741
  }
724
742
 
725
- /**
726
- * @param {Record<string|symbol, any>} v
727
- * @param {(symbol | string)[]} l
728
- * @returns {Tracked[]}
729
- */
730
- export function track_split(v, l) {
731
- var is_tracked = is_ripple_object(v);
732
-
733
- if (is_tracked || typeof v !== 'object' || v === null || is_array(v)) {
734
- throw new TypeError('Invalid value: expected a non-tracked object');
735
- }
736
-
737
- /** @type {Tracked[]} */
738
- var out = [];
739
- /** @type {Record<string|symbol, any>} */
740
- var rest = {};
741
- /** @type {Record<PropertyKey, 1>} */
742
- var done = {};
743
- var props = Reflect.ownKeys(v);
744
-
745
- for (let i = 0, key, t; i < l.length; i++) {
746
- key = l[i];
747
-
748
- if (props.includes(key)) {
749
- if (is_ripple_object(v[key])) {
750
- t = v[key];
751
- } else {
752
- t = tracked(undefined);
753
- t = define_property(t, 'v', /** @type {PropertyDescriptor} */ (get_descriptor(v, key)));
754
- }
755
- } else {
756
- t = tracked(undefined);
757
- }
758
-
759
- out[i] = t;
760
- done[key] = 1;
761
- }
762
-
763
- for (let i = 0, key; i < props.length; i++) {
764
- key = props[i];
765
- if (done[key]) {
766
- continue;
767
- }
768
- define_property(rest, key, /** @type {PropertyDescriptor} */ (get_descriptor(v, key)));
769
- }
770
-
771
- out.push(tracked(rest));
772
-
773
- return out;
774
- }
775
-
776
743
  /**
777
744
  * @param {any} _
778
745
  * @param {ConstructorParameters<typeof URL>} params
@@ -865,6 +832,15 @@ export function ripple_object(obj) {
865
832
  return obj;
866
833
  }
867
834
 
835
+ /**
836
+ * @template K, V
837
+ * @param {Iterable<readonly [K, V]>} [iterable]
838
+ * @returns {Map<K, V>}
839
+ */
840
+ export function ripple_map(iterable) {
841
+ return new Map(iterable);
842
+ }
843
+
868
844
  /**
869
845
  * Returns the fallback value if the given value is undefined.
870
846
  * @template T
@@ -4,16 +4,16 @@ describe('RippleArray copyWithin', () => {
4
4
  it('handles copyWithin operation with reactivity', () => {
5
5
  component ArrayTest() {
6
6
  let items = new RippleArray(1, 2, 3, 4, 5);
7
- let firstItem = track(() => items[0]);
8
- let thirdItem = track(() => items[2]);
9
- let fourthItem = track(() => items[3]);
7
+ let &[firstItem] = track(() => items[0]);
8
+ let &[thirdItem] = track(() => items[2]);
9
+ let &[fourthItem] = track(() => items[3]);
10
10
 
11
11
  <button onClick={() => items.copyWithin(0, 3)}>{'copy end to start'}</button>
12
12
  <button onClick={() => items.copyWithin(2, 0, 2)}>{'copy start to middle'}</button>
13
13
  <pre>{JSON.stringify(items)}</pre>
14
- <pre>{@firstItem}</pre>
15
- <pre>{@thirdItem}</pre>
16
- <pre>{@fourthItem}</pre>
14
+ <pre>{firstItem}</pre>
15
+ <pre>{thirdItem}</pre>
16
+ <pre>{fourthItem}</pre>
17
17
  }
18
18
 
19
19
  render(ArrayTest);
@@ -49,13 +49,13 @@ describe('RippleArray copyWithin', () => {
49
49
  it('handles copyWithin with negative indexes and reactivity', () => {
50
50
  component ArrayTest() {
51
51
  let items = new RippleArray(1, 2, 3, 4, 5);
52
- let secondItem = track(() => items[1]);
53
- let thirdItem = track(() => items[2]);
52
+ let &[secondItem] = track(() => items[1]);
53
+ let &[thirdItem] = track(() => items[2]);
54
54
 
55
55
  <button onClick={() => items.copyWithin(-4, -2)}>{'copy with negative indexes'}</button>
56
56
  <pre>{JSON.stringify(items)}</pre>
57
- <pre>{@secondItem}</pre>
58
- <pre>{@thirdItem}</pre>
57
+ <pre>{secondItem}</pre>
58
+ <pre>{thirdItem}</pre>
59
59
  }
60
60
 
61
61
  render(ArrayTest);
@@ -80,12 +80,12 @@ describe('RippleArray copyWithin', () => {
80
80
  it('handles copyWithin with overlapping ranges', () => {
81
81
  component ArrayTest() {
82
82
  let items = new RippleArray(1, 2, 3, 4, 5);
83
- let entries = track(() => Array.from(items.entries()));
83
+ let &[entries] = track(() => Array.from(items.entries()));
84
84
 
85
85
  <button onClick={() => items.copyWithin(2, 1, 4)}>{'copy with overlap'}</button>
86
86
  <pre>{JSON.stringify(items)}</pre>
87
87
 
88
- for (const [i, value] of @entries) {
88
+ for (const [i, value] of entries) {
89
89
  <pre>{`items[${i}]: ${value}`}</pre>
90
90
  }
91
91
  }