ripple 0.3.6 → 0.3.8

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 (110) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/package.json +2 -2
  3. package/src/compiler/phases/1-parse/index.js +37 -194
  4. package/src/compiler/phases/2-analyze/index.js +290 -26
  5. package/src/compiler/phases/3-transform/client/index.js +54 -14
  6. package/src/compiler/phases/3-transform/server/index.js +19 -35
  7. package/src/compiler/types/index.d.ts +3 -1
  8. package/src/compiler/types/parse.d.ts +0 -8
  9. package/src/compiler/utils.js +10 -6
  10. package/src/runtime/internal/client/composite.js +2 -2
  11. package/src/runtime/internal/client/index.js +2 -0
  12. package/src/runtime/internal/client/runtime.js +95 -45
  13. package/src/runtime/internal/client/types.d.ts +10 -0
  14. package/src/runtime/internal/client/utils.js +12 -0
  15. package/src/runtime/internal/server/index.js +89 -17
  16. package/src/runtime/internal/server/types.d.ts +10 -0
  17. package/src/utils/ast.js +1 -1
  18. package/tests/client/array/array.copy-within.test.ripple +12 -12
  19. package/tests/client/array/array.derived.test.ripple +46 -46
  20. package/tests/client/array/array.iteration.test.ripple +10 -10
  21. package/tests/client/array/array.mutations.test.ripple +20 -20
  22. package/tests/client/array/array.to-methods.test.ripple +6 -6
  23. package/tests/client/async-suspend.test.ripple +5 -5
  24. package/tests/client/basic/basic.attributes.test.ripple +81 -81
  25. package/tests/client/basic/basic.collections.test.ripple +9 -9
  26. package/tests/client/basic/basic.components.test.ripple +28 -28
  27. package/tests/client/basic/basic.errors.test.ripple +18 -18
  28. package/tests/client/basic/basic.events.test.ripple +37 -37
  29. package/tests/client/basic/basic.get-set.test.ripple +6 -6
  30. package/tests/client/basic/basic.reactivity.test.ripple +68 -68
  31. package/tests/client/basic/basic.rendering.test.ripple +19 -19
  32. package/tests/client/basic/basic.utilities.test.ripple +3 -3
  33. package/tests/client/boundaries.test.ripple +12 -12
  34. package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
  35. package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
  36. package/tests/client/compiler/compiler.basic.test.ripple +44 -15
  37. package/tests/client/compiler/compiler.tracked-access.test.ripple +68 -2
  38. package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
  39. package/tests/client/composite/composite.props.test.ripple +11 -11
  40. package/tests/client/composite/composite.reactivity.test.ripple +43 -43
  41. package/tests/client/composite/composite.render.test.ripple +3 -3
  42. package/tests/client/computed-properties.test.ripple +4 -4
  43. package/tests/client/date.test.ripple +42 -42
  44. package/tests/client/dynamic-elements.test.ripple +42 -42
  45. package/tests/client/events.test.ripple +70 -70
  46. package/tests/client/for.test.ripple +25 -25
  47. package/tests/client/head.test.ripple +19 -19
  48. package/tests/client/html.test.ripple +3 -3
  49. package/tests/client/input-value.test.ripple +84 -84
  50. package/tests/client/lazy-destructuring.test.ripple +123 -14
  51. package/tests/client/map.test.ripple +16 -16
  52. package/tests/client/media-query.test.ripple +7 -7
  53. package/tests/client/portal.test.ripple +11 -11
  54. package/tests/client/ref.test.ripple +4 -4
  55. package/tests/client/return.test.ripple +52 -52
  56. package/tests/client/set.test.ripple +6 -6
  57. package/tests/client/svg.test.ripple +5 -5
  58. package/tests/client/switch.test.ripple +44 -44
  59. package/tests/client/try.test.ripple +5 -5
  60. package/tests/client/url/url.derived.test.ripple +6 -6
  61. package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
  62. package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
  63. package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
  64. package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
  65. package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
  66. package/tests/hydration/compiled/client/events.js +25 -25
  67. package/tests/hydration/compiled/client/for.js +70 -66
  68. package/tests/hydration/compiled/client/head.js +25 -25
  69. package/tests/hydration/compiled/client/hmr.js +2 -2
  70. package/tests/hydration/compiled/client/html.js +3 -3
  71. package/tests/hydration/compiled/client/if-children.js +24 -24
  72. package/tests/hydration/compiled/client/if.js +18 -18
  73. package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
  74. package/tests/hydration/compiled/client/portal.js +3 -3
  75. package/tests/hydration/compiled/client/reactivity.js +16 -16
  76. package/tests/hydration/compiled/client/return.js +40 -40
  77. package/tests/hydration/compiled/client/switch.js +12 -12
  78. package/tests/hydration/compiled/server/events.js +19 -19
  79. package/tests/hydration/compiled/server/for.js +41 -41
  80. package/tests/hydration/compiled/server/head.js +26 -26
  81. package/tests/hydration/compiled/server/hmr.js +2 -2
  82. package/tests/hydration/compiled/server/html.js +2 -2
  83. package/tests/hydration/compiled/server/if-children.js +16 -16
  84. package/tests/hydration/compiled/server/if.js +11 -11
  85. package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
  86. package/tests/hydration/compiled/server/portal.js +2 -2
  87. package/tests/hydration/compiled/server/reactivity.js +16 -16
  88. package/tests/hydration/compiled/server/return.js +25 -25
  89. package/tests/hydration/compiled/server/switch.js +8 -8
  90. package/tests/hydration/components/events.ripple +25 -25
  91. package/tests/hydration/components/for.ripple +66 -66
  92. package/tests/hydration/components/head.ripple +16 -16
  93. package/tests/hydration/components/hmr.ripple +2 -2
  94. package/tests/hydration/components/html.ripple +3 -3
  95. package/tests/hydration/components/if-children.ripple +24 -24
  96. package/tests/hydration/components/if.ripple +18 -18
  97. package/tests/hydration/components/mixed-control-flow.ripple +9 -9
  98. package/tests/hydration/components/portal.ripple +3 -3
  99. package/tests/hydration/components/reactivity.ripple +16 -16
  100. package/tests/hydration/components/return.ripple +40 -40
  101. package/tests/hydration/components/switch.ripple +20 -20
  102. package/tests/server/await.test.ripple +3 -3
  103. package/tests/server/basic.attributes.test.ripple +34 -34
  104. package/tests/server/basic.components.test.ripple +10 -10
  105. package/tests/server/basic.test.ripple +38 -40
  106. package/tests/server/composite.props.test.ripple +9 -9
  107. package/tests/server/dynamic-elements.test.ripple +13 -12
  108. package/tests/server/head.test.ripple +11 -11
  109. package/tests/server/lazy-destructuring.test.ripple +72 -0
  110. package/types/index.d.ts +7 -2
@@ -289,6 +289,95 @@ export function run_block(block) {
289
289
 
290
290
  var empty_get_set = { get: undefined, set: undefined };
291
291
 
292
+ class TrackedValue {
293
+ /**
294
+ * @param {any} v
295
+ * @param {Block} block
296
+ * @param {{ get?: Function; set?: Function }} a
297
+ */
298
+ constructor(v, block, a) {
299
+ this.a = a;
300
+ this.b = block;
301
+ this.c = 0;
302
+ this.f = TRACKED;
303
+ this.__v = v;
304
+ }
305
+ get [0]() {
306
+ return get_tracked(/** @type {Tracked} */ (this));
307
+ }
308
+ set [0](v) {
309
+ set(/** @type {Tracked} */ (this), v);
310
+ }
311
+ get [1]() {
312
+ return this;
313
+ }
314
+ get value() {
315
+ return get_tracked(/** @type {Tracked} */ (this));
316
+ }
317
+ /** @param {any} v */
318
+ set value(v) {
319
+ set(/** @type {Tracked} */ (this), v);
320
+ }
321
+ /** @returns {2} */
322
+ get length() {
323
+ return 2;
324
+ }
325
+ *[Symbol.iterator]() {
326
+ yield get_tracked(/** @type {Tracked} */ (this));
327
+ yield this;
328
+ }
329
+ }
330
+
331
+ class DerivedValue {
332
+ /**
333
+ * @param {Function} fn
334
+ * @param {Block} block
335
+ * @param {{ get?: Function; set?: Function }} a
336
+ */
337
+ constructor(fn, block, a) {
338
+ this.a = a;
339
+ this.b = block;
340
+ /** @type {null | Block[]} */
341
+ this.blocks = null;
342
+ this.c = 0;
343
+ this.co = active_component;
344
+ /** @type {null | Dependency} */
345
+ this.d = null;
346
+ this.f = TRACKED | DERIVED;
347
+ this.fn = fn;
348
+ this.__v = UNINITIALIZED;
349
+ }
350
+ get [0]() {
351
+ return get_derived(/** @type {Derived} */ (this));
352
+ }
353
+ set [0](v) {
354
+ set(/** @type {Derived} */ (this), v);
355
+ }
356
+ get [1]() {
357
+ return this;
358
+ }
359
+ get value() {
360
+ return get_derived(/** @type {Derived} */ (this));
361
+ }
362
+ /** @param {any} v */
363
+ set value(v) {
364
+ set(/** @type {Derived} */ (this), v);
365
+ }
366
+ /** @returns {2} */
367
+ get length() {
368
+ return 2;
369
+ }
370
+ *[Symbol.iterator]() {
371
+ yield get_derived(/** @type {Derived} */ (this));
372
+ yield this;
373
+ }
374
+ }
375
+
376
+ if (DEV) {
377
+ define_property(TrackedValue.prototype, 'DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY', { value: true });
378
+ define_property(DerivedValue.prototype, 'DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY', { value: true });
379
+ }
380
+
292
381
  /**
293
382
  *
294
383
  * @param {any} v
@@ -298,25 +387,9 @@ var empty_get_set = { get: undefined, set: undefined };
298
387
  * @returns {Tracked}
299
388
  */
300
389
  export function tracked(v, block, get, set) {
301
- // TODO: now we expose tracked, we should likely block access in DEV somehow
302
- if (DEV) {
303
- return {
304
- DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY: true,
305
- a: get || set ? { get, set } : empty_get_set,
306
- b: block || active_block,
307
- c: 0,
308
- f: TRACKED,
309
- __v: v,
310
- };
311
- }
312
-
313
- return {
314
- a: get || set ? { get, set } : empty_get_set,
315
- b: block || active_block,
316
- c: 0,
317
- f: TRACKED,
318
- __v: v,
319
- };
390
+ return /** @type {Tracked} */ (
391
+ new TrackedValue(v, block || active_block, get || set ? { get, set } : empty_get_set)
392
+ );
320
393
  }
321
394
 
322
395
  /**
@@ -327,32 +400,9 @@ export function tracked(v, block, get, set) {
327
400
  * @returns {Derived}
328
401
  */
329
402
  export function derived(fn, block, get, set) {
330
- if (DEV) {
331
- return {
332
- DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY: true,
333
- a: get || set ? { get, set } : empty_get_set,
334
- b: block || active_block,
335
- blocks: null,
336
- c: 0,
337
- co: active_component,
338
- d: null,
339
- f: TRACKED | DERIVED,
340
- fn,
341
- __v: UNINITIALIZED,
342
- };
343
- }
344
-
345
- return {
346
- a: get || set ? { get, set } : empty_get_set,
347
- b: block || active_block,
348
- blocks: null,
349
- c: 0,
350
- co: active_component,
351
- d: null,
352
- f: TRACKED | DERIVED,
353
- fn,
354
- __v: UNINITIALIZED,
355
- };
403
+ return /** @type {Derived} */ (
404
+ new DerivedValue(fn, block || active_block, get || set ? { get, set } : empty_get_set)
405
+ );
356
406
  }
357
407
 
358
408
  /**
@@ -24,6 +24,11 @@ export type Tracked<V = any> = {
24
24
  c: number;
25
25
  f: number;
26
26
  __v: V;
27
+ readonly [0]: V;
28
+ [1]: Tracked<V>;
29
+ value: V;
30
+ readonly length: 2;
31
+ [Symbol.iterator](): Iterator<V | Tracked<V>>;
27
32
  };
28
33
 
29
34
  export type Derived = {
@@ -37,6 +42,11 @@ export type Derived = {
37
42
  f: number;
38
43
  fn: Function;
39
44
  __v: any;
45
+ readonly [0]: any;
46
+ [1]: Derived;
47
+ value: any;
48
+ readonly length: 2;
49
+ [Symbol.iterator](): Iterator<any | Derived>;
40
50
  };
41
51
 
42
52
  export type Block = {
@@ -27,6 +27,18 @@ export var object_prototype = Object.prototype;
27
27
  /** @type {typeof Array.prototype} */
28
28
  export var array_prototype = Array.prototype;
29
29
 
30
+ /**
31
+ * Slice helper for arrays and array-like values.
32
+ * @param {ArrayLike<any>} array_like
33
+ * @param {...number} args
34
+ * @returns {any[]}
35
+ */
36
+ export function array_slice(array_like, ...args) {
37
+ return is_array(array_like)
38
+ ? array_like.slice(...args)
39
+ : array_prototype.slice.call(array_like, ...args);
40
+ }
41
+
30
42
  /**
31
43
  * Creates a text node that serves as an anchor point in the DOM.
32
44
  * @returns {Text}
@@ -5,7 +5,13 @@
5
5
 
6
6
  import { Readable } from 'stream';
7
7
  import { DERIVED, UNINITIALIZED, TRACKED } from '../client/constants.js';
8
- import { is_ripple_object, get_descriptor, define_property, is_array } from '../client/utils.js';
8
+ import {
9
+ is_ripple_object,
10
+ get_descriptor,
11
+ define_property,
12
+ is_array,
13
+ array_slice,
14
+ } from '../client/utils.js';
9
15
  import { escape } from '../../../utils/escaping.js';
10
16
  import { is_boolean_attribute } from '../../../compiler/utils.js';
11
17
  import { clsx } from 'clsx';
@@ -20,6 +26,7 @@ export { escape };
20
26
  export { register_component_css as register_css } from './css-registry.js';
21
27
  export { hash } from '../../../utils/hashing.js';
22
28
  export { context } from './context.js';
29
+ export { array_slice };
23
30
 
24
31
  /** @type {null | Component} */
25
32
  export let active_component = null;
@@ -607,6 +614,84 @@ export function spread_attrs(attrs, css_hash) {
607
614
 
608
615
  var empty_get_set = { get: undefined, set: undefined };
609
616
 
617
+ class TrackedValue {
618
+ /**
619
+ * @param {any} v
620
+ * @param {{ get?: Function; set?: Function }} a
621
+ */
622
+ constructor(v, a) {
623
+ this.a = a;
624
+ this.c = 0;
625
+ this.f = TRACKED;
626
+ this.v = v;
627
+ }
628
+ get [0]() {
629
+ return get(/** @type {Tracked} */ (this));
630
+ }
631
+ set [0](v) {
632
+ set(/** @type {Tracked} */ (this), v);
633
+ }
634
+ get [1]() {
635
+ return this;
636
+ }
637
+ get value() {
638
+ return get(/** @type {Tracked} */ (this));
639
+ }
640
+ /** @param {any} v */
641
+ set value(v) {
642
+ set(/** @type {Tracked} */ (this), v);
643
+ }
644
+ /** @returns {2} */
645
+ get length() {
646
+ return 2;
647
+ }
648
+ *[Symbol.iterator]() {
649
+ yield get(/** @type {Tracked} */ (this));
650
+ yield this;
651
+ }
652
+ }
653
+
654
+ class DerivedValue {
655
+ /**
656
+ * @param {Function} fn
657
+ * @param {{ get?: Function; set?: Function }} a
658
+ */
659
+ constructor(fn, a) {
660
+ this.a = a;
661
+ this.c = 0;
662
+ this.co = active_component;
663
+ /** @type {null | import('#server').Dependency} */
664
+ this.d = null;
665
+ this.f = TRACKED | DERIVED;
666
+ this.fn = fn;
667
+ this.v = UNINITIALIZED;
668
+ }
669
+ get [0]() {
670
+ return get(/** @type {Derived} */ (this));
671
+ }
672
+ set [0](v) {
673
+ set(/** @type {Derived} */ (this), v);
674
+ }
675
+ get [1]() {
676
+ return this;
677
+ }
678
+ get value() {
679
+ return get(/** @type {Derived} */ (this));
680
+ }
681
+ /** @param {any} v */
682
+ set value(v) {
683
+ set(/** @type {Derived} */ (this), v);
684
+ }
685
+ /** @returns {2} */
686
+ get length() {
687
+ return 2;
688
+ }
689
+ *[Symbol.iterator]() {
690
+ yield get(/** @type {Derived} */ (this));
691
+ yield this;
692
+ }
693
+ }
694
+
610
695
  /**
611
696
  * @param {any} v
612
697
  * @param {(value: any) => any} [get]
@@ -614,12 +699,7 @@ var empty_get_set = { get: undefined, set: undefined };
614
699
  * @returns {Tracked}
615
700
  */
616
701
  function tracked(v, get, set) {
617
- return {
618
- a: get || set ? { get, set } : empty_get_set,
619
- c: 0,
620
- f: TRACKED,
621
- v,
622
- };
702
+ return /** @type {Tracked} */ (new TrackedValue(v, get || set ? { get, set } : empty_get_set));
623
703
  }
624
704
 
625
705
  /**
@@ -636,15 +716,7 @@ export function track(v, get, set) {
636
716
  }
637
717
 
638
718
  if (typeof v === 'function') {
639
- return {
640
- a: get || set ? { get, set } : empty_get_set,
641
- c: 0,
642
- co: active_component,
643
- d: null,
644
- f: TRACKED | DERIVED,
645
- fn: v,
646
- v: UNINITIALIZED,
647
- };
719
+ return /** @type {Derived} */ (new DerivedValue(v, get || set ? { get, set } : empty_get_set));
648
720
  }
649
721
 
650
722
  return tracked(v, get, set);
@@ -678,7 +750,7 @@ export function track_split(v, l) {
678
750
  t = v[key];
679
751
  } else {
680
752
  t = tracked(undefined);
681
- t = define_property(t, '__v', /** @type {PropertyDescriptor} */ (get_descriptor(v, key)));
753
+ t = define_property(t, 'v', /** @type {PropertyDescriptor} */ (get_descriptor(v, key)));
682
754
  }
683
755
  } else {
684
756
  t = tracked(undefined);
@@ -19,6 +19,11 @@ export type Derived = {
19
19
  f: number;
20
20
  fn: Function;
21
21
  v: any;
22
+ readonly [0]: any;
23
+ [1]: Derived;
24
+ value: any;
25
+ readonly length: 2;
26
+ [Symbol.iterator](): Iterator<any | Derived>;
22
27
  };
23
28
 
24
29
  export type Tracked = {
@@ -26,4 +31,9 @@ export type Tracked = {
26
31
  c: number;
27
32
  f: number;
28
33
  v: any;
34
+ readonly [0]: any;
35
+ [1]: Tracked;
36
+ value: any;
37
+ readonly length: 2;
38
+ [Symbol.iterator](): Iterator<any | Tracked>;
29
39
  };
package/src/utils/ast.js CHANGED
@@ -195,7 +195,7 @@ function _extract_paths(assignments = [], param, expression, update_expression,
195
195
  if (element.type === 'RestElement') {
196
196
  /** @type {DestructuredAssignment['expression']} */
197
197
  const rest_expression = (object) =>
198
- b.call(b.member(expression(object), 'slice'), b.literal(i));
198
+ b.call('_$_.array_slice', expression(object), b.literal(i));
199
199
  if (element.argument.type === 'Identifier') {
200
200
  assignments.push({
201
201
  node: element.argument,
@@ -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
  }