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
@@ -4,19 +4,19 @@ import { effect, flushSync, on, track } from 'ripple';
4
4
  describe('on() event handler', () => {
5
5
  it('should attach multiple handlers via onClick attribute (delegated)', () => {
6
6
  component Basic() {
7
- let count1 = track(0);
8
- let count2 = track(0);
7
+ let &[count1] = track(0);
8
+ let &[count2] = track(0);
9
9
 
10
10
  <button
11
11
  onClick={() => {
12
- @count1++;
13
- @count2++;
12
+ count1++;
13
+ count2++;
14
14
  }}
15
15
  >
16
16
  {'Click me'}
17
17
  </button>
18
- <div class="count1">{@count1}</div>
19
- <div class="count2">{@count2}</div>
18
+ <div class="count1">{count1}</div>
19
+ <div class="count2">{count2}</div>
20
20
  }
21
21
 
22
22
  render(Basic);
@@ -36,16 +36,16 @@ describe('on() event handler', () => {
36
36
 
37
37
  it('should attach and remove a single event handler', () => {
38
38
  component Basic() {
39
- let count = track(0);
39
+ let &[count] = track(0);
40
40
 
41
41
  const setupListener = (node: HTMLButtonElement) => {
42
42
  const remove = on(node, 'click', () => {
43
- @count++;
43
+ count++;
44
44
  });
45
45
  return remove;
46
46
  };
47
47
  <button {ref setupListener}>{'Click me'}</button>
48
- <div class="count">{@count}</div>
48
+ <div class="count">{count}</div>
49
49
  }
50
50
 
51
51
  render(Basic);
@@ -67,15 +67,15 @@ describe('on() event handler', () => {
67
67
 
68
68
  it('should handle multiple different event types on same element', () => {
69
69
  component Basic() {
70
- let clickCount = track(0);
71
- let mousedownCount = track(0);
70
+ let &[clickCount] = track(0);
71
+ let &[mousedownCount] = track(0);
72
72
 
73
73
  const setupListeners = (node: HTMLButtonElement) => {
74
74
  const remove1 = on(node, 'click', () => {
75
- @clickCount++;
75
+ clickCount++;
76
76
  });
77
77
  const remove2 = on(node, 'mousedown', () => {
78
- @mousedownCount++;
78
+ mousedownCount++;
79
79
  });
80
80
  return () => {
81
81
  remove1();
@@ -83,8 +83,8 @@ describe('on() event handler', () => {
83
83
  };
84
84
  };
85
85
  <button {ref setupListeners}>{'Test'}</button>
86
- <div class="click-count">{@clickCount}</div>
87
- <div class="mousedown-count">{@mousedownCount}</div>
86
+ <div class="click-count">{clickCount}</div>
87
+ <div class="mousedown-count">{mousedownCount}</div>
88
88
  }
89
89
 
90
90
  render(Basic);
@@ -116,17 +116,17 @@ describe('on() event handler', () => {
116
116
 
117
117
  it('should handle multiple handlers for same event type on same element', () => {
118
118
  component Basic() {
119
- let callOrder = track<number[]>([]);
119
+ let &[callOrder] = track<number[]>([]);
120
120
 
121
121
  const setupListeners = (node: HTMLButtonElement) => {
122
122
  const remove1 = on(node, 'click', () => {
123
- @callOrder = [...@callOrder, 1];
123
+ callOrder = [...callOrder, 1];
124
124
  });
125
125
  const remove2 = on(node, 'click', () => {
126
- @callOrder = [...@callOrder, 2];
126
+ callOrder = [...callOrder, 2];
127
127
  });
128
128
  const remove3 = on(node, 'click', () => {
129
- @callOrder = [...@callOrder, 3];
129
+ callOrder = [...callOrder, 3];
130
130
  });
131
131
  return () => {
132
132
  remove1();
@@ -135,7 +135,7 @@ describe('on() event handler', () => {
135
135
  };
136
136
  };
137
137
  <button {ref setupListeners}>{'Click me'}</button>
138
- <div class="order">{@callOrder.join(',')}</div>
138
+ <div class="order">{callOrder.join(',')}</div>
139
139
  }
140
140
 
141
141
  render(Basic);
@@ -158,20 +158,20 @@ describe('on() event handler', () => {
158
158
 
159
159
  it('should remove specific handler without affecting others', () => {
160
160
  component Basic() {
161
- let handler1Called = track(0);
162
- let handler2Called = track(0);
163
- let handler3Called = track(0);
161
+ let &[handler1Called] = track(0);
162
+ let &[handler2Called] = track(0);
163
+ let &[handler3Called] = track(0);
164
164
  let removeHandler2: OnEventListenerRemover | undefined;
165
165
 
166
166
  const setupListeners = (node: HTMLButtonElement) => {
167
167
  const remove1 = on(node, 'click', () => {
168
- @handler1Called++;
168
+ handler1Called++;
169
169
  });
170
170
  removeHandler2 = on(node, 'click', () => {
171
- @handler2Called++;
171
+ handler2Called++;
172
172
  });
173
173
  const remove3 = on(node, 'click', () => {
174
- @handler3Called++;
174
+ handler3Called++;
175
175
  });
176
176
  return () => {
177
177
  remove1();
@@ -190,9 +190,9 @@ describe('on() event handler', () => {
190
190
  >
191
191
  {'Remove handler 2'}
192
192
  </button>
193
- <div class="h1">{@handler1Called}</div>
194
- <div class="h2">{@handler2Called}</div>
195
- <div class="h3">{@handler3Called}</div>
193
+ <div class="h1">{handler1Called}</div>
194
+ <div class="h2">{handler2Called}</div>
195
+ <div class="h3">{handler3Called}</div>
196
196
  </div>
197
197
  }
198
198
 
@@ -235,18 +235,18 @@ describe('on() event handler', () => {
235
235
  'should handle change event with multiple handlers (like bindChecked and bindIndeterminate)',
236
236
  () => {
237
237
  component Basic() {
238
- let checked = track(false);
239
- let indeterminate = track(true);
238
+ let &[checked] = track(false);
239
+ let &[indeterminate] = track(true);
240
240
 
241
241
  const setupListeners = (node: HTMLInputElement) => {
242
- node.indeterminate = @indeterminate;
243
- node.checked = @checked;
242
+ node.indeterminate = indeterminate;
243
+ node.checked = checked;
244
244
 
245
245
  const remove1 = on(node, 'change', () => {
246
- @checked = node.checked;
246
+ checked = node.checked;
247
247
  });
248
248
  const remove2 = on(node, 'change', () => {
249
- @indeterminate = node.indeterminate;
249
+ indeterminate = node.indeterminate;
250
250
  });
251
251
  return () => {
252
252
  remove1();
@@ -255,8 +255,8 @@ describe('on() event handler', () => {
255
255
  };
256
256
  <div>
257
257
  <input type="checkbox" {ref setupListeners} />
258
- <div class="checked">{@checked ? 'true' : 'false'}</div>
259
- <div class="indeterminate">{@indeterminate ? 'true' : 'false'}</div>
258
+ <div class="checked">{checked ? 'true' : 'false'}</div>
259
+ <div class="indeterminate">{indeterminate ? 'true' : 'false'}</div>
260
260
  </div>
261
261
  }
262
262
 
@@ -283,17 +283,17 @@ describe('on() event handler', () => {
283
283
 
284
284
  it('should support non-delegated events', () => {
285
285
  component Basic() {
286
- let focusCount = track(0);
286
+ let &[focusCount] = track(0);
287
287
 
288
288
  const setupListener = (node: HTMLInputElement) => {
289
289
  const remove = on(node, 'focus', () => {
290
- @focusCount++;
290
+ focusCount++;
291
291
  });
292
292
  return remove;
293
293
  };
294
294
 
295
295
  <input {ref setupListener} />
296
- <div class="focus-count">{@focusCount}</div>
296
+ <div class="focus-count">{focusCount}</div>
297
297
  }
298
298
 
299
299
  render(Basic);
@@ -315,20 +315,20 @@ describe('on() event handler', () => {
315
315
 
316
316
  it('should handle removal of all handlers for same event type', () => {
317
317
  component Basic() {
318
- let count = track(0);
318
+ let &[count] = track(0);
319
319
  let remove1: OnEventListenerRemover | undefined;
320
320
  let remove2: OnEventListenerRemover | undefined;
321
321
  let remove3: OnEventListenerRemover | undefined;
322
322
 
323
323
  const setupListeners = (node: HTMLButtonElement) => {
324
324
  remove1 = on(node, 'click', () => {
325
- @count++;
325
+ count++;
326
326
  });
327
327
  remove2 = on(node, 'click', () => {
328
- @count += 10;
328
+ count += 10;
329
329
  });
330
330
  remove3 = on(node, 'click', () => {
331
- @count += 100;
331
+ count += 100;
332
332
  });
333
333
  return () => {
334
334
  remove1?.();
@@ -349,7 +349,7 @@ describe('on() event handler', () => {
349
349
  >
350
350
  {'Remove all'}
351
351
  </button>
352
- <div class="count">{@count}</div>
352
+ <div class="count">{count}</div>
353
353
  </div>
354
354
  }
355
355
 
@@ -379,10 +379,10 @@ describe('on() event handler', () => {
379
379
 
380
380
  it('should not add duplicate handlers when same handler is attached multiple times', () => {
381
381
  component Basic() {
382
- let count = track(0);
382
+ let &[count] = track(0);
383
383
 
384
384
  const sharedHandler = () => {
385
- @count++;
385
+ count++;
386
386
  };
387
387
 
388
388
  const setupListeners = (node: HTMLButtonElement) => {
@@ -399,7 +399,7 @@ describe('on() event handler', () => {
399
399
  };
400
400
 
401
401
  <button {ref setupListeners}>{'Click me'}</button>
402
- <div class="count">{@count}</div>
402
+ <div class="count">{count}</div>
403
403
  }
404
404
 
405
405
  render(Basic);
@@ -422,10 +422,10 @@ describe('on() event handler', () => {
422
422
 
423
423
  it('should allow duplicate handlers when delegated is false (no deduplication)', () => {
424
424
  component Basic() {
425
- let count = track(0);
425
+ let &[count] = track(0);
426
426
 
427
427
  const sharedHandler = () => {
428
- @count++;
428
+ count++;
429
429
  };
430
430
 
431
431
  const setupListeners = (node: HTMLButtonElement) => {
@@ -442,7 +442,7 @@ describe('on() event handler', () => {
442
442
  };
443
443
 
444
444
  <button {ref setupListeners}>{'Click me'}</button>
445
- <div class="count">{@count}</div>
445
+ <div class="count">{count}</div>
446
446
  }
447
447
 
448
448
  render(Basic);
@@ -466,14 +466,14 @@ describe('on() event handler', () => {
466
466
 
467
467
  it('should fire capture event on parent before bubbling event on child', () => {
468
468
  component Basic() {
469
- let callOrder = track<string[]>([]);
469
+ let &[callOrder] = track<string[]>([]);
470
470
 
471
471
  const parentCaptureHandler = () => {
472
- @callOrder = [...@callOrder, 'parent-capture'];
472
+ callOrder = [...callOrder, 'parent-capture'];
473
473
  };
474
474
 
475
475
  const childBubbleHandler = () => {
476
- @callOrder = [...@callOrder, 'child-bubble'];
476
+ callOrder = [...callOrder, 'child-bubble'];
477
477
  };
478
478
 
479
479
  const setupParent = (node: HTMLDivElement) => {
@@ -487,7 +487,7 @@ describe('on() event handler', () => {
487
487
  <div {ref setupParent} class="parent">
488
488
  <button {ref setupChild} class="child">{'Click me'}</button>
489
489
  </div>
490
- <div class="order">{@callOrder.join(',')}</div>
490
+ <div class="order">{callOrder.join(',')}</div>
491
491
  }
492
492
 
493
493
  render(Basic);
@@ -511,16 +511,16 @@ describe('on() event handler', () => {
511
511
 
512
512
  it('should fire handler only once when once option is true', () => {
513
513
  component Basic() {
514
- let count = track(0);
515
- let permanentCount = track(0);
514
+ let &[count] = track(0);
515
+ let &[permanentCount] = track(0);
516
516
 
517
517
  const setupListeners = (node: HTMLButtonElement) => {
518
518
  const onceHandler = on(node, 'click', () => {
519
- @count++;
519
+ count++;
520
520
  }, { once: true });
521
521
 
522
522
  const permanentHandler = on(node, 'click', () => {
523
- @permanentCount++;
523
+ permanentCount++;
524
524
  });
525
525
 
526
526
  return () => {
@@ -530,8 +530,8 @@ describe('on() event handler', () => {
530
530
  };
531
531
 
532
532
  <button {ref setupListeners}>{'Click me'}</button>
533
- <div class="once-count">{@count}</div>
534
- <div class="permanent-count">{@permanentCount}</div>
533
+ <div class="once-count">{count}</div>
534
+ <div class="permanent-count">{permanentCount}</div>
535
535
  }
536
536
 
537
537
  render(Basic);
@@ -565,18 +565,18 @@ describe('on() event handler', () => {
565
565
 
566
566
  it('should handle click events on window', () => {
567
567
  component Basic() {
568
- let windowClickCount = track(0);
568
+ let &[windowClickCount] = track(0);
569
569
 
570
570
  effect(() => {
571
571
  const removeWindowListener = on(window, 'click', () => {
572
- @windowClickCount++;
572
+ windowClickCount++;
573
573
  });
574
574
  return removeWindowListener;
575
575
  });
576
576
 
577
577
  <div>
578
578
  <button class="test-btn">{'Click me'}</button>
579
- <div class="window-count">{@windowClickCount}</div>
579
+ <div class="window-count">{windowClickCount}</div>
580
580
  </div>
581
581
  }
582
582
 
@@ -601,18 +601,18 @@ describe('on() event handler', () => {
601
601
 
602
602
  it('should handle click events on document', () => {
603
603
  component Basic() {
604
- let documentClickCount = track(0);
604
+ let &[documentClickCount] = track(0);
605
605
 
606
606
  effect(() => {
607
607
  const removeDocumentListener = on(document, 'click', () => {
608
- @documentClickCount++;
608
+ documentClickCount++;
609
609
  });
610
610
  return removeDocumentListener;
611
611
  });
612
612
 
613
613
  <div>
614
614
  <button class="test-btn">{'Click me'}</button>
615
- <div class="document-count">{@documentClickCount}</div>
615
+ <div class="document-count">{documentClickCount}</div>
616
616
  </div>
617
617
  }
618
618
 
@@ -637,18 +637,18 @@ describe('on() event handler', () => {
637
637
 
638
638
  it('should handle click events on body', () => {
639
639
  component Basic() {
640
- let bodyClickCount = track(0);
640
+ let &[bodyClickCount] = track(0);
641
641
 
642
642
  effect(() => {
643
643
  const removeBodyListener = on(document.body, 'click', () => {
644
- @bodyClickCount++;
644
+ bodyClickCount++;
645
645
  });
646
646
  return removeBodyListener;
647
647
  });
648
648
 
649
649
  <div>
650
650
  <button class="test-btn">{'Click me'}</button>
651
- <div class="body-count">{@bodyClickCount}</div>
651
+ <div class="body-count">{bodyClickCount}</div>
652
652
  </div>
653
653
  }
654
654
 
@@ -101,19 +101,19 @@ describe('for statements', () => {
101
101
 
102
102
  it('correctly handles keyed for...of loops', () => {
103
103
  component App() {
104
- let items = track([
104
+ let &[items] = track([
105
105
  { id: 1, text: 'Item 1' },
106
106
  { id: 2, text: 'Item 2' },
107
107
  { id: 3, text: 'Item 3' },
108
108
  ]);
109
109
 
110
- for (let item of @items; index i; key item.id) {
110
+ for (let item of items; index i; key item.id) {
111
111
  <div>{i + ':' + item.text}</div>
112
112
  }
113
113
 
114
114
  <button
115
115
  onClick={() => {
116
- @items = @items.toReversed();
116
+ items = items.toReversed();
117
117
  }}
118
118
  >
119
119
  {'Reverse'}
@@ -134,23 +134,23 @@ describe('for statements', () => {
134
134
 
135
135
  it('keyed for over derived updates sibling text nodes', () => {
136
136
  component App() {
137
- let count = track(0);
137
+ let &[count] = track(0);
138
138
 
139
- const items = track(
140
- () => Array.from({ length: @count }).map((_, id) => ({ id, label: `Item ${id}` })),
139
+ let &[items] = track(
140
+ () => Array.from({ length: count }).map((_, id) => ({ id, label: `Item ${id}` })),
141
141
  );
142
142
 
143
143
  <button
144
144
  onClick={() => {
145
- @count++;
145
+ count++;
146
146
  }}
147
147
  >
148
148
  {'Add'}
149
149
  </button>
150
- for (const item of @items; key item.id) {
150
+ for (const item of items; key item.id) {
151
151
  <div class="item">{item.label}</div>
152
152
  }
153
- <p class="count">{@count}</p>
153
+ <p class="count">{count}</p>
154
154
  }
155
155
 
156
156
  render(App);
@@ -175,17 +175,17 @@ describe('for statements', () => {
175
175
 
176
176
  it('keyed for with 32+ items: full reversal updates values via Map path', () => {
177
177
  component App() {
178
- let items = track(Array.from({ length: 40 }, (_, i) => ({ id: i, text: `Item ${i}` })));
178
+ let &[items] = track(Array.from({ length: 40 }, (_, i) => ({ id: i, text: `Item ${i}` })));
179
179
 
180
180
  <div>
181
- for (let item of @items; index idx; key item.id) {
181
+ for (let item of items; index idx; key item.id) {
182
182
  <span class="item">{idx + ':' + item.text}</span>
183
183
  }
184
184
  </div>
185
185
 
186
186
  <button
187
187
  onClick={() => {
188
- @items = @items.toReversed();
188
+ items = items.toReversed();
189
189
  }}
190
190
  >
191
191
  {'Reverse'}
@@ -208,26 +208,26 @@ describe('for statements', () => {
208
208
 
209
209
  it('handles updating with new objects with same key', () => {
210
210
  component App() {
211
- let items = track([
211
+ let &[items] = track([
212
212
  { id: 1, text: 'Item 1' },
213
213
  { id: 2, text: 'Item 2' },
214
214
  { id: 3, text: 'Item 3' },
215
215
  ]);
216
216
 
217
- for (let item of @items; index i; key item.id) {
217
+ for (let item of items; index i; key item.id) {
218
218
  <div>{i + ':' + item.text}</div>
219
219
  }
220
220
 
221
221
  <button
222
222
  onClick={() => {
223
- @items[0].id = 3;
224
- @items[1].id = 2;
225
- @items[2].id = 1;
226
-
227
- @items = [
228
- { ...@items[0], text: 'Item 1!' },
229
- { ...@items[1], text: 'Item 2!' },
230
- { ...@items[2], text: 'Item 3!' },
223
+ items[0].id = 3;
224
+ items[1].id = 2;
225
+ items[2].id = 1;
226
+
227
+ items = [
228
+ { ...items[0], text: 'Item 1!' },
229
+ { ...items[1], text: 'Item 2!' },
230
+ { ...items[2], text: 'Item 3!' },
231
231
  ];
232
232
  }}
233
233
  >
@@ -249,17 +249,17 @@ describe('for statements', () => {
249
249
  const objects = Array.from({ length: 50 }, (_, i) => ({ id: i, text: `Obj ${i}` }));
250
250
 
251
251
  component App() {
252
- let items = track(objects.slice());
252
+ let &[items] = track(objects.slice());
253
253
 
254
254
  <div>
255
- for (const item of @items) {
255
+ for (const item of items) {
256
256
  <span class="item">{item.text}</span>
257
257
  }
258
258
  </div>
259
259
 
260
260
  <button
261
261
  onClick={() => {
262
- @items = objects.slice(15).reverse();
262
+ items = objects.slice(15).reverse();
263
263
  }}
264
264
  >
265
265
  {'Trim and reverse'}
@@ -29,20 +29,20 @@ describe('head elements', () => {
29
29
 
30
30
  it('renders reactive title element', () => {
31
31
  component App() {
32
- let title = track('Initial Title');
32
+ let &[title] = track('Initial Title');
33
33
 
34
34
  <head>
35
- <title>{@title}</title>
35
+ <title>{title}</title>
36
36
  </head>
37
37
  <div>
38
38
  <button
39
39
  onClick={() => {
40
- @title = 'Updated Title';
40
+ title = 'Updated Title';
41
41
  }}
42
42
  >
43
43
  {'Update Title'}
44
44
  </button>
45
- <span>{@title}</span>
45
+ <span>{title}</span>
46
46
  </div>
47
47
  }
48
48
 
@@ -61,15 +61,15 @@ describe('head elements', () => {
61
61
 
62
62
  it('renders title with template literal', () => {
63
63
  component App() {
64
- let name = track('World');
64
+ let &[name] = track('World');
65
65
 
66
66
  <head>
67
- <title>{`Hello ${@name}!`}</title>
67
+ <title>{`Hello ${name}!`}</title>
68
68
  </head>
69
69
  <div>
70
70
  <button
71
71
  onClick={() => {
72
- @name = 'Ripple';
72
+ name = 'Ripple';
73
73
  }}
74
74
  >
75
75
  {'Change Name'}
@@ -90,21 +90,21 @@ describe('head elements', () => {
90
90
 
91
91
  it('renders title with computed value', () => {
92
92
  component App() {
93
- let count = track(0);
93
+ let &[count] = track(0);
94
94
  let prefix = 'Count: ';
95
95
 
96
96
  <head>
97
- <title>{prefix + @count}</title>
97
+ <title>{prefix + count}</title>
98
98
  </head>
99
99
  <div>
100
100
  <button
101
101
  onClick={() => {
102
- @count++;
102
+ count++;
103
103
  }}
104
104
  >
105
105
  {'Increment'}
106
106
  </button>
107
- <span>{@count}</span>
107
+ <span>{count}</span>
108
108
  </div>
109
109
  }
110
110
 
@@ -122,15 +122,15 @@ describe('head elements', () => {
122
122
 
123
123
  it('handles multiple title updates', () => {
124
124
  component App() {
125
- let step = track(1);
125
+ let &[step] = track(1);
126
126
 
127
127
  <head>
128
- <title>{`Step ${@step} of 3`}</title>
128
+ <title>{`Step ${step} of 3`}</title>
129
129
  </head>
130
130
  <div>
131
131
  <button
132
132
  onClick={() => {
133
- @step = @step % 3 + 1;
133
+ step = step % 3 + 1;
134
134
  }}
135
135
  >
136
136
  {'Next Step'}
@@ -172,23 +172,23 @@ describe('head elements', () => {
172
172
 
173
173
  it('renders title with conditional content', () => {
174
174
  component App() {
175
- let showPrefix = track(true);
176
- let title = track('Main Page');
175
+ let &[showPrefix] = track(true);
176
+ let &[title] = track('Main Page');
177
177
 
178
178
  <head>
179
- <title>{@showPrefix ? 'App - ' + @title : @title}</title>
179
+ <title>{showPrefix ? 'App - ' + title : title}</title>
180
180
  </head>
181
181
  <div>
182
182
  <button
183
183
  onClick={() => {
184
- @showPrefix = !@showPrefix;
184
+ showPrefix = !showPrefix;
185
185
  }}
186
186
  >
187
187
  {'Toggle Prefix'}
188
188
  </button>
189
189
  <button
190
190
  onClick={() => {
191
- @title = @title === 'Main Page' ? 'Settings' : 'Main Page';
191
+ title = title === 'Main Page' ? 'Settings' : 'Main Page';
192
192
  }}
193
193
  >
194
194
  {'Change Page'}
@@ -14,13 +14,13 @@ describe('html directive', () => {
14
14
 
15
15
  it('renders dynamic html', () => {
16
16
  component App() {
17
- let str = track('<div>Test</div>');
17
+ let &[str] = track('<div>Test</div>');
18
18
 
19
- {html @str}
19
+ {html str}
20
20
 
21
21
  <button
22
22
  onClick={() => {
23
- @str = '<div>Updated</div>';
23
+ str = '<div>Updated</div>';
24
24
  }}
25
25
  >
26
26
  {'Update'}