ripple 0.3.72 → 0.3.76

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 (172) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +4 -10
  4. package/src/runtime/dynamic-client.js +33 -0
  5. package/src/runtime/dynamic-server.js +80 -0
  6. package/src/runtime/index-client.js +5 -13
  7. package/src/runtime/index-server.js +2 -0
  8. package/src/runtime/internal/client/blocks.js +6 -27
  9. package/src/runtime/internal/client/composite.js +11 -6
  10. package/src/runtime/internal/client/for.js +80 -5
  11. package/src/runtime/internal/client/index.js +0 -2
  12. package/src/runtime/internal/client/render.js +5 -2
  13. package/src/runtime/internal/client/types.d.ts +0 -10
  14. package/src/runtime/internal/server/index.js +8 -1
  15. package/tests/client/__snapshots__/computed-properties.test.tsrx.snap +8 -0
  16. package/tests/client/__snapshots__/for.test.tsrx.snap +22 -0
  17. package/tests/client/__snapshots__/html.test.tsrx.snap +4 -0
  18. package/tests/client/array/array.copy-within.test.tsrx +19 -19
  19. package/tests/client/array/array.derived.test.tsrx +97 -109
  20. package/tests/client/array/array.iteration.test.tsrx +28 -28
  21. package/tests/client/array/array.mutations.test.tsrx +68 -68
  22. package/tests/client/array/array.static.test.tsrx +82 -92
  23. package/tests/client/array/array.to-methods.test.tsrx +15 -15
  24. package/tests/client/async-suspend.test.tsrx +180 -179
  25. package/tests/client/basic/__snapshots__/basic.attributes.test.tsrx.snap +2 -0
  26. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +4 -0
  27. package/tests/client/basic/basic.attributes.test.tsrx +273 -317
  28. package/tests/client/basic/basic.collections.test.tsrx +55 -61
  29. package/tests/client/basic/basic.components.test.tsrx +198 -220
  30. package/tests/client/basic/basic.errors.test.tsrx +70 -76
  31. package/tests/client/basic/basic.events.test.tsrx +80 -85
  32. package/tests/client/basic/basic.get-set.test.tsrx +54 -64
  33. package/tests/client/basic/basic.hmr.test.tsrx +15 -19
  34. package/tests/client/basic/basic.reactivity.test.tsrx +121 -135
  35. package/tests/client/basic/basic.rendering.test.tsrx +273 -178
  36. package/tests/client/basic/basic.styling.test.tsrx +16 -14
  37. package/tests/client/basic/basic.utilities.test.tsrx +8 -10
  38. package/tests/client/boundaries.test.tsrx +18 -18
  39. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -76
  40. package/tests/client/compiler/compiler.attributes.test.tsrx +18 -14
  41. package/tests/client/compiler/compiler.basic.test.tsrx +357 -288
  42. package/tests/client/compiler/compiler.regex.test.tsrx +40 -44
  43. package/tests/client/compiler/compiler.tracked-access.test.tsrx +57 -38
  44. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  45. package/tests/client/compiler/compiler.typescript.test.tsrx +4 -3
  46. package/tests/client/composite/composite.dynamic-components.test.tsrx +62 -47
  47. package/tests/client/composite/composite.generics.test.tsrx +165 -167
  48. package/tests/client/composite/composite.props.test.tsrx +66 -74
  49. package/tests/client/composite/composite.reactivity.test.tsrx +132 -166
  50. package/tests/client/composite/composite.render.test.tsrx +92 -101
  51. package/tests/client/computed-properties.test.tsrx +14 -18
  52. package/tests/client/context.test.tsrx +14 -18
  53. package/tests/client/css/global-additional-cases.test.tsrx +493 -439
  54. package/tests/client/css/global-advanced-selectors.test.tsrx +169 -153
  55. package/tests/client/css/global-at-rules.test.tsrx +71 -66
  56. package/tests/client/css/global-basic.test.tsrx +105 -98
  57. package/tests/client/css/global-classes-ids.test.tsrx +128 -114
  58. package/tests/client/css/global-combinators.test.tsrx +83 -78
  59. package/tests/client/css/global-complex-nesting.test.tsrx +134 -120
  60. package/tests/client/css/global-edge-cases.test.tsrx +138 -120
  61. package/tests/client/css/global-keyframes.test.tsrx +108 -96
  62. package/tests/client/css/global-nested.test.tsrx +88 -78
  63. package/tests/client/css/global-pseudo.test.tsrx +104 -98
  64. package/tests/client/css/global-scoping.test.tsrx +145 -125
  65. package/tests/client/css/style-identifier.test.tsrx +65 -72
  66. package/tests/client/date.test.tsrx +83 -83
  67. package/tests/client/dynamic-elements.test.tsrx +318 -299
  68. package/tests/client/events.test.tsrx +252 -266
  69. package/tests/client/for.test.tsrx +120 -127
  70. package/tests/client/head.test.tsrx +74 -48
  71. package/tests/client/html.test.tsrx +37 -49
  72. package/tests/client/input-value.test.tsrx +1125 -1354
  73. package/tests/client/lazy-array.test.tsrx +10 -16
  74. package/tests/client/lazy-destructuring.test.tsrx +169 -221
  75. package/tests/client/map.test.tsrx +39 -41
  76. package/tests/client/media-query.test.tsrx +15 -19
  77. package/tests/client/object.test.tsrx +46 -56
  78. package/tests/client/portal.test.tsrx +31 -37
  79. package/tests/client/ref.test.tsrx +173 -193
  80. package/tests/client/return.test.tsrx +62 -37
  81. package/tests/client/set.test.tsrx +33 -33
  82. package/tests/client/svg.test.tsrx +197 -216
  83. package/tests/client/switch.test.tsrx +201 -191
  84. package/tests/client/track-async-hydration.test.tsrx +14 -18
  85. package/tests/client/tracked-index-access.test.tsrx +18 -28
  86. package/tests/client/try.test.tsrx +494 -619
  87. package/tests/client/tsx.test.tsrx +286 -292
  88. package/tests/client/typescript-generics.test.tsrx +121 -129
  89. package/tests/client/url/url.derived.test.tsrx +21 -25
  90. package/tests/client/url/url.parsing.test.tsrx +35 -35
  91. package/tests/client/url/url.partial-removal.test.tsrx +32 -32
  92. package/tests/client/url/url.reactivity.test.tsrx +68 -72
  93. package/tests/client/url/url.serialization.test.tsrx +8 -8
  94. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +21 -27
  95. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +16 -16
  96. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +37 -37
  97. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +56 -60
  98. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +32 -34
  99. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +9 -9
  100. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +10 -10
  101. package/tests/hydration/compiled/client/basic.js +390 -319
  102. package/tests/hydration/compiled/client/composite.js +52 -44
  103. package/tests/hydration/compiled/client/for.js +734 -604
  104. package/tests/hydration/compiled/client/head.js +183 -103
  105. package/tests/hydration/compiled/client/html.js +93 -86
  106. package/tests/hydration/compiled/client/if-children.js +95 -71
  107. package/tests/hydration/compiled/client/if.js +113 -89
  108. package/tests/hydration/compiled/client/mixed-control-flow.js +225 -209
  109. package/tests/hydration/compiled/client/nested-control-flow.js +94 -98
  110. package/tests/hydration/compiled/client/reactivity.js +26 -24
  111. package/tests/hydration/compiled/client/return.js +8 -42
  112. package/tests/hydration/compiled/client/switch.js +208 -173
  113. package/tests/hydration/compiled/client/track-async-serialization.js +176 -128
  114. package/tests/hydration/compiled/client/try.js +29 -21
  115. package/tests/hydration/compiled/server/basic.js +210 -221
  116. package/tests/hydration/compiled/server/composite.js +13 -14
  117. package/tests/hydration/compiled/server/for.js +427 -444
  118. package/tests/hydration/compiled/server/head.js +199 -189
  119. package/tests/hydration/compiled/server/html.js +33 -41
  120. package/tests/hydration/compiled/server/if-children.js +114 -117
  121. package/tests/hydration/compiled/server/if.js +77 -83
  122. package/tests/hydration/compiled/server/mixed-control-flow.js +145 -150
  123. package/tests/hydration/compiled/server/nested-control-flow.js +10 -0
  124. package/tests/hydration/compiled/server/reactivity.js +24 -22
  125. package/tests/hydration/compiled/server/return.js +6 -18
  126. package/tests/hydration/compiled/server/switch.js +179 -176
  127. package/tests/hydration/compiled/server/track-async-serialization.js +88 -70
  128. package/tests/hydration/compiled/server/try.js +31 -35
  129. package/tests/hydration/components/basic.tsrx +216 -258
  130. package/tests/hydration/components/composite.tsrx +32 -42
  131. package/tests/hydration/components/events.tsrx +81 -101
  132. package/tests/hydration/components/for.tsrx +270 -336
  133. package/tests/hydration/components/head.tsrx +43 -39
  134. package/tests/hydration/components/hmr.tsrx +16 -22
  135. package/tests/hydration/components/html-in-template.tsrx +15 -21
  136. package/tests/hydration/components/html.tsrx +442 -526
  137. package/tests/hydration/components/if-children.tsrx +107 -125
  138. package/tests/hydration/components/if.tsrx +68 -90
  139. package/tests/hydration/components/mixed-control-flow.tsrx +65 -72
  140. package/tests/hydration/components/nested-control-flow.tsrx +202 -216
  141. package/tests/hydration/components/portal.tsrx +33 -41
  142. package/tests/hydration/components/reactivity.tsrx +26 -34
  143. package/tests/hydration/components/return.tsrx +4 -6
  144. package/tests/hydration/components/switch.tsrx +73 -78
  145. package/tests/hydration/components/track-async-serialization.tsrx +83 -93
  146. package/tests/hydration/components/try.tsrx +37 -51
  147. package/tests/hydration/switch.test.js +8 -8
  148. package/tests/server/await.test.tsrx +3 -3
  149. package/tests/server/basic.attributes.test.tsrx +117 -162
  150. package/tests/server/basic.components.test.tsrx +164 -194
  151. package/tests/server/basic.test.tsrx +299 -199
  152. package/tests/server/compiler.test.tsrx +142 -72
  153. package/tests/server/composite.props.test.tsrx +54 -58
  154. package/tests/server/composite.test.tsrx +165 -167
  155. package/tests/server/context.test.tsrx +13 -17
  156. package/tests/server/dynamic-elements.test.tsrx +147 -148
  157. package/tests/server/for.test.tsrx +115 -84
  158. package/tests/server/head.test.tsrx +54 -31
  159. package/tests/server/html-nesting-validation.test.tsrx +16 -8
  160. package/tests/server/if.test.tsrx +49 -59
  161. package/tests/server/lazy-destructuring.test.tsrx +288 -366
  162. package/tests/server/return.test.tsrx +58 -36
  163. package/tests/server/streaming-ssr.test.tsrx +4 -4
  164. package/tests/server/style-identifier.test.tsrx +61 -69
  165. package/tests/server/switch.test.tsrx +89 -97
  166. package/tests/server/track-async-serialization.test.tsrx +85 -103
  167. package/tests/server/try.test.tsrx +275 -360
  168. package/tests/utils/ref-types.test.js +72 -0
  169. package/tests/utils/vite-plugin-config.test.js +41 -74
  170. package/types/index.d.ts +29 -4
  171. package/src/runtime/internal/client/compat.js +0 -40
  172. package/tests/utils/compiler-compat-config.test.js +0 -38
@@ -1,31 +1,29 @@
1
1
  describe('compiler > regex', () => {
2
2
  it('renders without crashing using regex literals in method calls', () => {
3
- function App() {
4
- return <>
5
- let text = 'Hello <span>world</span> and <div>content</div>';
6
- // Test various regex patterns in method calls that previously failed
7
- let matchResult = text.match(/<span>/);
8
- let replaceResult = text.replace(/<div>/g, '[DIV]');
9
- let searchResult = text.search(/<span>/);
10
- // Test regex literals in variable assignments (should work)
11
- let spanRegex = /<span>/g;
12
- let divRegex = /<div.*?>/;
13
- // Test more complex regex patterns
14
- let complexMatch = text.match(/<[^>]*>/g);
15
- let htmlTags = text.replace(/<(\/*)(\w+)[^>]*>/g, '[$1$2]');
16
- // Test edge cases with multiple angle brackets
17
- let multiAngle = '<<test>> <span>content</span>'.match(/<span>/);
18
- <div>
19
- <span>{String(matchResult)}</span>
20
- <span>{replaceResult}</span>
21
- <span>{String(searchResult)}</span>
22
- <span>{String(spanRegex)}</span>
23
- <span>{String(divRegex)}</span>
24
- <span>{String(complexMatch)}</span>
25
- <span>{htmlTags}</span>
26
- <span>{String(multiAngle)}</span>
27
- </div>
28
- </>;
3
+ function App() @{
4
+ let text = 'Hello <span>world</span> and <div>content</div>';
5
+ // Test various regex patterns in method calls that previously failed
6
+ let matchResult = text.match(/<span>/);
7
+ let replaceResult = text.replace(/<div>/g, '[DIV]');
8
+ let searchResult = text.search(/<span>/);
9
+ // Test regex literals in variable assignments (should work)
10
+ let spanRegex = /<span>/g;
11
+ let divRegex = /<div.*?>/;
12
+ // Test more complex regex patterns
13
+ let complexMatch = text.match(/<[^>]*>/g);
14
+ let htmlTags = text.replace(/<(\/*)(\w+)[^>]*>/g, '[$1$2]');
15
+ // Test edge cases with multiple angle brackets
16
+ let multiAngle = '<<test>> <span>content</span>'.match(/<span>/);
17
+ <div>
18
+ <span>{String(matchResult)}</span>
19
+ <span>{replaceResult}</span>
20
+ <span>{String(searchResult)}</span>
21
+ <span>{String(spanRegex)}</span>
22
+ <span>{String(divRegex)}</span>
23
+ <span>{String(complexMatch)}</span>
24
+ <span>{htmlTags}</span>
25
+ <span>{String(multiAngle)}</span>
26
+ </div>
29
27
  }
30
28
 
31
29
  render(App);
@@ -50,25 +48,23 @@ describe('compiler > regex', () => {
50
48
  });
51
49
 
52
50
  it('renders without crashing mixing regex and JSX syntax', () => {
53
- function App() {
54
- return <>
55
- let htmlString = '<p>Paragraph</p><div>Content</div>';
56
- // Mix of regex parsing and legitimate JSX
57
- let paragraphs = htmlString.match(/<p[^>]*>.*?<\/p>/g);
58
- let cleaned = htmlString.replace(/<\/?[^>]+>/g, '');
59
- let splitArray = htmlString.split(/<\/?\w+>/g).filter((s) => s.trim());
60
- <div class="container">
61
- <span class="result">{String(paragraphs)}</span>
62
- <span class="cleaned">{cleaned}</span>
63
- <p>{'This is real JSX'}</p>
64
- <div>
65
- <span>
66
- {'Split result: '}
67
- {splitArray.join(', ')}
68
- </span>
69
- </div>
51
+ function App() @{
52
+ let htmlString = '<p>Paragraph</p><div>Content</div>';
53
+ // Mix of regex parsing and legitimate JSX
54
+ let paragraphs = htmlString.match(/<p[^>]*>.*?<\/p>/g);
55
+ let cleaned = htmlString.replace(/<\/?[^>]+>/g, '');
56
+ let splitArray = htmlString.split(/<\/?\w+>/g).filter((s) => s.trim());
57
+ <div class="container">
58
+ <span class="result">{String(paragraphs)}</span>
59
+ <span class="cleaned">{cleaned}</span>
60
+ <p>{'This is real JSX'}</p>
61
+ <div>
62
+ <span>
63
+ {'Split result: '}
64
+ {splitArray.join(', ')}
65
+ </span>
70
66
  </div>
71
- </>;
67
+ </div>
72
68
  }
73
69
 
74
70
  render(App);
@@ -7,10 +7,11 @@ describe('Compiler: Tracked Object Direct Access Checks', () => {
7
7
  it('should error on direct access to __v of a tracked object', () => {
8
8
  const code = `
9
9
  import { track } from 'ripple';
10
- export default function App() { return <>
10
+ export default function App() @{
11
11
  let count = track(0);
12
12
  console.log(count.__v);
13
- </>; }
13
+ <></>
14
+ }
14
15
  `;
15
16
  expect(() => compile(code, 'test.tsrx')).toThrow(
16
17
  /Directly accessing internal property "__v" of a tracked object is not allowed/,
@@ -20,10 +21,11 @@ import { track } from 'ripple';
20
21
  it('should error on direct access to "a" (get/set config) of a tracked object', () => {
21
22
  const code = `
22
23
  import { track } from 'ripple';
23
- export default function App() { return <>
24
+ export default function App() @{
24
25
  let myTracked = track(0);
25
26
  console.log(myTracked.a);
26
- </>; }
27
+ <></>
28
+ }
27
29
  `;
28
30
  expect(() => compile(code, 'test.tsrx')).toThrow(
29
31
  /Directly accessing internal property "a" of a tracked object is not allowed/,
@@ -33,10 +35,11 @@ import { track } from 'ripple';
33
35
  it('should error on direct access to "b" (block) of a tracked object', () => {
34
36
  const code = `
35
37
  import { track } from 'ripple';
36
- export default function App() { return <>
38
+ export default function App() @{
37
39
  let myTracked = track(0);
38
40
  console.log(myTracked.b);
39
- </>; }
41
+ <></>
42
+ }
40
43
  `;
41
44
  expect(() => compile(code, 'test.tsrx')).toThrow(
42
45
  /Directly accessing internal property "b" of a tracked object is not allowed/,
@@ -46,10 +49,11 @@ import { track } from 'ripple';
46
49
  it('should error on direct access to "c" (clock) of a tracked object', () => {
47
50
  const code = `
48
51
  import { track } from 'ripple';
49
- export default function App() { return <>
52
+ export default function App() @{
50
53
  let myTracked = track(0);
51
54
  console.log(myTracked.c);
52
- </>; }
55
+ <></>
56
+ }
53
57
  `;
54
58
  expect(() => compile(code, 'test.tsrx')).toThrow(
55
59
  /Directly accessing internal property "c" of a tracked object is not allowed/,
@@ -59,10 +63,11 @@ import { track } from 'ripple';
59
63
  it('should error on direct access to "f" (flags) of a tracked object', () => {
60
64
  const code = `
61
65
  import { track } from 'ripple';
62
- export default function App() { return <>
66
+ export default function App() @{
63
67
  let myTracked = track(0);
64
68
  console.log(myTracked.f);
65
- </>; }
69
+ <></>
70
+ }
66
71
  `;
67
72
  expect(() => compile(code, 'test.tsrx')).toThrow(
68
73
  /Directly accessing internal property "f" of a tracked object is not allowed/,
@@ -72,10 +77,11 @@ import { track } from 'ripple';
72
77
  it('should compile successfully with correct @ syntax access', () => {
73
78
  const code = `
74
79
  import { track } from 'ripple';
75
- export default function App() { return <>
80
+ export default function App() @{
76
81
  let &[count] = track(0);
77
82
  console.log(count);
78
- </>; }
83
+ <></>
84
+ }
79
85
  `;
80
86
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
81
87
  });
@@ -83,30 +89,33 @@ import { track } from 'ripple';
83
89
  it('should compile successfully with correct value access', () => {
84
90
  const code = `
85
91
  import { track } from 'ripple';
86
- export default function App() { return <>
92
+ export default function App() @{
87
93
  let count = track(0);
88
94
  console.log(count.value);
89
- </>; }
95
+ <></>
96
+ }
90
97
  `;
91
98
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
92
99
  });
93
100
 
94
101
  it('should not error on accessing __v of a non-tracked object', () => {
95
102
  const code = `
96
- export default function App() { return <>
103
+ export default function App() @{
97
104
  let obj = { __v: 123 };
98
105
  console.log(obj.__v);
99
- </>; }
106
+ <></>
107
+ }
100
108
  `;
101
109
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
102
110
  });
103
111
 
104
112
  it('should not error on accessing __v of a non-tracked object (member expression)', () => {
105
113
  const code = `
106
- export default function App() { return <>
114
+ export default function App() @{
107
115
  let data = { value: { __v: 456 } };
108
116
  console.log(data.value.__v);
109
- </>; }
117
+ <></>
118
+ }
110
119
  `;
111
120
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
112
121
  });
@@ -115,11 +124,12 @@ import { track } from 'ripple';
115
124
  'should not error on accessing a property named like an internal one on a non-tracked object',
116
125
  () => {
117
126
  const code = `
118
- export default function App() { return <>
127
+ export default function App() @{
119
128
  let config = { a: 'some_value', b: 'another_value' };
120
129
  console.log(config.a);
121
130
  console.log(config.b);
122
- </>; }
131
+ <></>
132
+ }
123
133
  `;
124
134
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
125
135
  },
@@ -128,10 +138,11 @@ import { track } from 'ripple';
128
138
  it('should error on indexed [0] access on a tracked object', () => {
129
139
  const code = `
130
140
  import { track } from 'ripple';
131
- export default function App() { return <>
141
+ export default function App() @{
132
142
  let count = track(0);
133
143
  console.log(count[0]);
134
- </>; }
144
+ <></>
145
+ }
135
146
  `;
136
147
  expect(() => compile(code, 'test.tsrx')).toThrow(value_message);
137
148
  });
@@ -139,10 +150,11 @@ import { track } from 'ripple';
139
150
  it('should error on indexed [1] access on a tracked object', () => {
140
151
  const code = `
141
152
  import { track } from 'ripple';
142
- export default function App() { return <>
153
+ export default function App() @{
143
154
  let count = track(0);
144
155
  let raw = count[1];
145
- </>; }
156
+ <></>
157
+ }
146
158
  `;
147
159
  expect(() => compile(code, 'test.tsrx')).toThrow(reference_message);
148
160
  });
@@ -150,10 +162,11 @@ import { track } from 'ripple';
150
162
  it('should error on indexed [0] write on a tracked object', () => {
151
163
  const code = `
152
164
  import { track } from 'ripple';
153
- export default function App() { return <>
165
+ export default function App() @{
154
166
  let count = track(0);
155
167
  count[0] = 5;
156
- </>; }
168
+ <></>
169
+ }
157
170
  `;
158
171
  expect(() => compile(code, 'test.tsrx')).toThrow(value_message);
159
172
  });
@@ -161,11 +174,12 @@ import { track } from 'ripple';
161
174
  it('collects tracked numeric index errors in loose mode', () => {
162
175
  const code = `
163
176
  import { track } from 'ripple';
164
- export default function App() { return <>
177
+ export default function App() @{
165
178
  let count = track(0);
166
179
  console.log(count[0]);
167
180
  let raw = count[1];
168
- </>; }
181
+ <></>
182
+ }
169
183
  `;
170
184
  const result = compile(code, 'test.tsrx', { loose: true });
171
185
 
@@ -180,10 +194,11 @@ import { track } from 'ripple';
180
194
  it('should error on indexed access through a known tracked lazy ref binding', () => {
181
195
  const code = `
182
196
  import { track } from 'ripple';
183
- export default function App() { return <>
197
+ export default function App() @{
184
198
  let &[value, tracked_ref] = track(0);
185
199
  tracked_ref[0]++;
186
- </>; }
200
+ <></>
201
+ }
187
202
  `;
188
203
  expect(() => compile(code, 'test.tsrx')).toThrow(value_message);
189
204
  });
@@ -191,10 +206,11 @@ import { track } from 'ripple';
191
206
  it('should allow lazy destructuring a tracked value', () => {
192
207
  const code = `
193
208
  import { track } from 'ripple';
194
- export default function App() { return <>
209
+ export default function App() @{
195
210
  let &[value, tracked_ref] = track(0);
196
211
  console.log(value, tracked_ref.value);
197
- </>; }
212
+ <></>
213
+ }
198
214
  `;
199
215
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
200
216
  });
@@ -202,10 +218,11 @@ import { track } from 'ripple';
202
218
  it('should allow .value read access on a tracked object', () => {
203
219
  const code = `
204
220
  import { track } from 'ripple';
205
- export default function App() { return <>
221
+ export default function App() @{
206
222
  let count = track(0);
207
223
  console.log(count.value);
208
- </>; }
224
+ <></>
225
+ }
209
226
  `;
210
227
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
211
228
  });
@@ -213,10 +230,11 @@ import { track } from 'ripple';
213
230
  it('should allow .value assignment on a tracked object', () => {
214
231
  const code = `
215
232
  import { track } from 'ripple';
216
- export default function App() { return <>
233
+ export default function App() @{
217
234
  let count = track(0);
218
235
  count.value = 5;
219
- </>; }
236
+ <></>
237
+ }
220
238
  `;
221
239
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
222
240
  });
@@ -224,10 +242,11 @@ import { track } from 'ripple';
224
242
  it('should allow .length read access on a tracked object', () => {
225
243
  const code = `
226
244
  import { track } from 'ripple';
227
- export default function App() { return <>
245
+ export default function App() @{
228
246
  let count = track(0);
229
247
  console.log(count.length);
230
- </>; }
248
+ <></>
249
+ }
231
250
  `;
232
251
  expect(() => compile(code, 'test.tsrx')).not.toThrow();
233
252
  });
@@ -18,7 +18,7 @@ function count_occurrences(string: string, sub_string: string): number {
18
18
 
19
19
  describe('compiler > Volar transform does not duplicate try blocks from functions', () => {
20
20
  it('try inside an async function', () => {
21
- const source = `export function App() { return <>
21
+ const source = `export function App() @{
22
22
  async function doWork() {
23
23
  try {
24
24
  await fetch('/api');
@@ -27,7 +27,7 @@ describe('compiler > Volar transform does not duplicate try blocks from function
27
27
  }
28
28
  }
29
29
  <div onclick={doWork}>{"click"}</div>
30
- </>; }`;
30
+ }`;
31
31
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
32
32
 
33
33
  expect(count_occurrences(result, 'try {')).toBe(1);
@@ -36,14 +36,14 @@ describe('compiler > Volar transform does not duplicate try blocks from function
36
36
  });
37
37
 
38
38
  it('try inside an arrow function', () => {
39
- const source = `export function App() { return <>
39
+ const source = `export function App() @{
40
40
  const doWork = async () => {
41
41
  try {
42
42
  await fetch('/api');
43
43
  } catch (e) {}
44
44
  };
45
45
  <div onclick={doWork}>{"click"}</div>
46
- </>; }`;
46
+ }`;
47
47
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
48
48
 
49
49
  expect(count_occurrences(result, 'try {')).toBe(1);
@@ -51,7 +51,7 @@ describe('compiler > Volar transform does not duplicate try blocks from function
51
51
  });
52
52
 
53
53
  it('try-catch-finally inside a function', () => {
54
- const source = `export function App() { return <>
54
+ const source = `export function App() @{
55
55
  async function save() {
56
56
  try {
57
57
  await fetch('/save');
@@ -62,7 +62,7 @@ describe('compiler > Volar transform does not duplicate try blocks from function
62
62
  }
63
63
  }
64
64
  <div onclick={save}>{"save"}</div>
65
- </>; }`;
65
+ }`;
66
66
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
67
67
 
68
68
  expect(count_occurrences(result, 'try {')).toBe(1);
@@ -72,12 +72,12 @@ describe('compiler > Volar transform does not duplicate try blocks from function
72
72
 
73
73
  it('try at component top level is preserved', () => {
74
74
  const source = `import { trackAsync } from 'ripple';
75
- export function App() { return <>
75
+ export function App() @{
76
76
  try {
77
77
  let &[data] = trackAsync(() => fetch('/api'));
78
78
  } catch (e) {}
79
79
  <div>{"hi"}</div>
80
- </>; }`;
80
+ }`;
81
81
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
82
82
 
83
83
  expect(count_occurrences(result, 'try {')).toBe(1);
@@ -86,7 +86,7 @@ export function App() { return <>
86
86
 
87
87
  it('component-level try and function-level try coexist without duplication', () => {
88
88
  const source = `import { trackAsync } from 'ripple';
89
- export function App() { return <>
89
+ export function App() @{
90
90
  try {
91
91
  let &[data] = trackAsync(() => fetch('/init'));
92
92
  } catch (e) {}
@@ -97,7 +97,7 @@ export function App() { return <>
97
97
  } catch (e) {}
98
98
  }
99
99
  <div onclick={refresh}>{"click"}</div>
100
- </>; }`;
100
+ }`;
101
101
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
102
102
 
103
103
  expect(count_occurrences(result, 'try {')).toBe(2);
@@ -106,7 +106,7 @@ export function App() { return <>
106
106
  });
107
107
 
108
108
  it('try in nested functions', () => {
109
- const source = `export function App() { return <>
109
+ const source = `export function App() @{
110
110
  function outer() {
111
111
  async function inner() {
112
112
  try {
@@ -115,7 +115,7 @@ export function App() { return <>
115
115
  }
116
116
  }
117
117
  <div>{"hi"}</div>
118
- </>; }`;
118
+ }`;
119
119
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
120
120
 
121
121
  expect(count_occurrences(result, 'try {')).toBe(1);
@@ -123,7 +123,7 @@ export function App() { return <>
123
123
  });
124
124
 
125
125
  it('multiple functions with try blocks each appear once', () => {
126
- const source = `export function App() { return <>
126
+ const source = `export function App() @{
127
127
  async function load() {
128
128
  try {
129
129
  await fetch('/load');
@@ -135,7 +135,7 @@ export function App() { return <>
135
135
  } catch (e) {}
136
136
  }
137
137
  <div>{"hi"}</div>
138
- </>; }`;
138
+ }`;
139
139
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
140
140
 
141
141
  expect(count_occurrences(result, 'try {')).toBe(2);
@@ -143,7 +143,7 @@ export function App() { return <>
143
143
  });
144
144
 
145
145
  it('try in object method', () => {
146
- const source = `export function App() { return <>
146
+ const source = `export function App() @{
147
147
  const handlers = {
148
148
  async onClick() {
149
149
  try {
@@ -152,7 +152,7 @@ export function App() { return <>
152
152
  }
153
153
  };
154
154
  <div>{"hi"}</div>
155
- </>; }`;
155
+ }`;
156
156
  const result = compile_to_volar_mappings(source, 'test.tsrx').code;
157
157
 
158
158
  expect(count_occurrences(result, 'try {')).toBe(1);
@@ -33,11 +33,12 @@ beforeAll(() => {
33
33
  (global as any).count++;
34
34
  });
35
35
 
36
- function Test() { return <>
36
+ function Test() @{
37
37
  let toggle: { value: boolean } | undefined;
38
38
  toggle!.value = false;
39
39
  toggle!.value++;
40
- </>; }`;
40
+ <></>
41
+ }`;
41
42
 
42
43
  const { code } = compile(source, 'test.tsrx', { mode: 'client' });
43
44
 
@@ -46,7 +47,7 @@ function Test() { return <>
46
47
  expect(code).toContain('toggle.value = false');
47
48
  expect(code).toContain('toggle.value++');
48
49
  expect(code).not.toContain('as any');
49
- expect(code).not.toContain('!');
50
+ expect(code).not.toContain('toggle!');
50
51
  });
51
52
 
52
53
  it('removes class TypeScript syntax from JS output', () => {
@@ -1,15 +1,14 @@
1
- import { flushSync, track } from 'ripple';
1
+ import { Dynamic, flushSync, track } from 'ripple';
2
2
 
3
3
  describe('composite > dynamic components', () => {
4
- it('supports rendering composite components using <@component> syntax', () => {
5
- function App() {
6
- return <>
7
- function basic() {
8
- return <><div>{'Basic Component'}</div></>;
9
- }
10
- const tracked_basic = track(() => basic);
11
- <@tracked_basic />
12
- </>;
4
+ it('supports rendering composite components using <Dynamic is={component}> syntax', () => {
5
+ function basic() @{
6
+ <div>{'Basic Component'}</div>
7
+ }
8
+
9
+ function App() @{
10
+ const tracked_basic = track(() => basic);
11
+ <Dynamic is={tracked_basic} />
13
12
  }
14
13
 
15
14
  render(App);
@@ -19,18 +18,17 @@ describe('composite > dynamic components', () => {
19
18
  });
20
19
 
21
20
  it('supports rendering composite components from object properties', () => {
22
- function App() {
23
- return <>
24
- function basic() {
25
- return <><div>{'Basic Component'}</div></>;
26
- }
27
- const tracked_basic = track(() => basic);
28
- const obj = {
29
- tracked_basic,
30
- };
31
- const comp = obj.tracked_basic;
32
- <@comp />
33
- </>;
21
+ function basic() @{
22
+ <div>{'Basic Component'}</div>
23
+ }
24
+
25
+ function App() @{
26
+ const tracked_basic = track(() => basic);
27
+ const obj = {
28
+ tracked_basic,
29
+ };
30
+ const comp = obj.tracked_basic;
31
+ <Dynamic is={comp} />
34
32
  }
35
33
 
36
34
  render(App);
@@ -40,19 +38,18 @@ describe('composite > dynamic components', () => {
40
38
  });
41
39
 
42
40
  it('supports rendering composite components from tracked object properties', () => {
43
- function App() {
44
- return <>
45
- function basic() {
46
- return <><div>{'Basic Component'}</div></>;
47
- }
48
- const tracked_basic = track(() => basic);
49
- const obj = {
50
- tracked_basic,
51
- };
52
- let &[inner] = track(obj);
53
- const comp = inner.tracked_basic;
54
- <@comp />
55
- </>;
41
+ function basic() @{
42
+ <div>{'Basic Component'}</div>
43
+ }
44
+
45
+ function App() @{
46
+ const tracked_basic = track(() => basic);
47
+ const obj = {
48
+ tracked_basic,
49
+ };
50
+ let &[inner] = track(obj);
51
+ const comp = inner.tracked_basic;
52
+ <Dynamic is={comp} />
56
53
  }
57
54
 
58
55
  render(App);
@@ -61,25 +58,43 @@ describe('composite > dynamic components', () => {
61
58
  expect(container.textContent).toBe('Basic Component');
62
59
  });
63
60
 
61
+ it('does not pass is to dynamic component props', () => {
62
+ function Child(props) @{
63
+ <div>
64
+ {props.is === undefined && !('is' in props) ? 'hidden' : 'leaked'}
65
+ </div>
66
+ }
67
+
68
+ function App() @{
69
+ const component = track(() => Child);
70
+ <Dynamic is={component} label="child" />
71
+ }
72
+
73
+ render(App);
74
+ flushSync();
75
+
76
+ expect(container.textContent).toBe('hidden');
77
+ });
78
+
64
79
  it('handles dynamic component switching', () => {
65
- function Child1() {
66
- return <><div>{'I am child 1'}</div></>;
80
+ function Child1() @{
81
+ <div>{'I am child 1'}</div>
67
82
  }
68
83
 
69
- function Child2() {
70
- return <><div>{'I am child 2'}</div></>;
84
+ function Child2() @{
85
+ <div>{'I am child 2'}</div>
71
86
  }
72
87
 
73
- function App() {
74
- return <>
75
- let &[thing] = track(() => Child1);
88
+ function App() @{
89
+ let &[thing] = track(() => Child1);
90
+ <>
76
91
  <div id="container">
77
- <@thing />
92
+ <Dynamic is={thing} />
78
93
  </div>
79
- <button onClick={() => (thing = thing === Child1 ? Child2 : Child1)}>
80
- {'Change Child'}
81
- </button>
82
- </>;
94
+ <button
95
+ onClick={() => (thing = thing === Child1 ? Child2 : Child1)}
96
+ >{'Change Child'}</button>
97
+ </>
83
98
  }
84
99
 
85
100
  render(App);