ripple 0.3.71 → 0.3.74

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 (165) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +2 -8
  4. package/src/runtime/index-client.js +3 -13
  5. package/src/runtime/internal/client/blocks.js +3 -25
  6. package/src/runtime/internal/client/for.js +80 -5
  7. package/src/runtime/internal/client/index.js +0 -2
  8. package/src/runtime/internal/client/types.d.ts +0 -10
  9. package/tests/client/__snapshots__/computed-properties.test.tsrx.snap +8 -0
  10. package/tests/client/__snapshots__/for.test.tsrx.snap +22 -0
  11. package/tests/client/__snapshots__/html.test.tsrx.snap +4 -0
  12. package/tests/client/array/array.copy-within.test.tsrx +19 -19
  13. package/tests/client/array/array.derived.test.tsrx +97 -109
  14. package/tests/client/array/array.iteration.test.tsrx +28 -28
  15. package/tests/client/array/array.mutations.test.tsrx +68 -68
  16. package/tests/client/array/array.static.test.tsrx +82 -92
  17. package/tests/client/array/array.to-methods.test.tsrx +15 -15
  18. package/tests/client/async-suspend.test.tsrx +180 -179
  19. package/tests/client/basic/__snapshots__/basic.attributes.test.tsrx.snap +2 -0
  20. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +4 -0
  21. package/tests/client/basic/basic.attributes.test.tsrx +273 -317
  22. package/tests/client/basic/basic.collections.test.tsrx +59 -71
  23. package/tests/client/basic/basic.components.test.tsrx +196 -222
  24. package/tests/client/basic/basic.errors.test.tsrx +72 -78
  25. package/tests/client/basic/basic.events.test.tsrx +80 -85
  26. package/tests/client/basic/basic.get-set.test.tsrx +54 -64
  27. package/tests/client/basic/basic.hmr.test.tsrx +15 -19
  28. package/tests/client/basic/basic.reactivity.test.tsrx +121 -135
  29. package/tests/client/basic/basic.rendering.test.tsrx +273 -178
  30. package/tests/client/basic/basic.utilities.test.tsrx +8 -10
  31. package/tests/client/boundaries.test.tsrx +18 -18
  32. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -76
  33. package/tests/client/compiler/compiler.attributes.test.tsrx +18 -14
  34. package/tests/client/compiler/compiler.basic.test.tsrx +364 -296
  35. package/tests/client/compiler/compiler.regex.test.tsrx +40 -44
  36. package/tests/client/compiler/compiler.tracked-access.test.tsrx +57 -38
  37. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  38. package/tests/client/compiler/compiler.typescript.test.tsrx +4 -3
  39. package/tests/client/composite/composite.dynamic-components.test.tsrx +41 -44
  40. package/tests/client/composite/composite.generics.test.tsrx +165 -167
  41. package/tests/client/composite/composite.props.test.tsrx +66 -74
  42. package/tests/client/composite/composite.reactivity.test.tsrx +132 -166
  43. package/tests/client/composite/composite.render.test.tsrx +92 -101
  44. package/tests/client/computed-properties.test.tsrx +14 -18
  45. package/tests/client/context.test.tsrx +14 -18
  46. package/tests/client/css/global-additional-cases.test.tsrx +491 -437
  47. package/tests/client/css/global-advanced-selectors.test.tsrx +169 -153
  48. package/tests/client/css/global-at-rules.test.tsrx +71 -66
  49. package/tests/client/css/global-basic.test.tsrx +105 -98
  50. package/tests/client/css/global-classes-ids.test.tsrx +128 -114
  51. package/tests/client/css/global-combinators.test.tsrx +83 -78
  52. package/tests/client/css/global-complex-nesting.test.tsrx +134 -120
  53. package/tests/client/css/global-edge-cases.test.tsrx +138 -120
  54. package/tests/client/css/global-keyframes.test.tsrx +108 -96
  55. package/tests/client/css/global-nested.test.tsrx +88 -78
  56. package/tests/client/css/global-pseudo.test.tsrx +104 -98
  57. package/tests/client/css/global-scoping.test.tsrx +145 -125
  58. package/tests/client/css/style-identifier.test.tsrx +62 -69
  59. package/tests/client/date.test.tsrx +83 -83
  60. package/tests/client/dynamic-elements.test.tsrx +227 -283
  61. package/tests/client/events.test.tsrx +252 -266
  62. package/tests/client/for.test.tsrx +120 -127
  63. package/tests/client/head.test.tsrx +40 -48
  64. package/tests/client/html.test.tsrx +37 -49
  65. package/tests/client/input-value.test.tsrx +1125 -1354
  66. package/tests/client/lazy-array.test.tsrx +10 -16
  67. package/tests/client/lazy-destructuring.test.tsrx +169 -221
  68. package/tests/client/map.test.tsrx +39 -41
  69. package/tests/client/media-query.test.tsrx +15 -19
  70. package/tests/client/object.test.tsrx +46 -56
  71. package/tests/client/portal.test.tsrx +31 -37
  72. package/tests/client/ref.test.tsrx +173 -193
  73. package/tests/client/return.test.tsrx +62 -37
  74. package/tests/client/set.test.tsrx +33 -33
  75. package/tests/client/svg.test.tsrx +195 -215
  76. package/tests/client/switch.test.tsrx +201 -191
  77. package/tests/client/track-async-hydration.test.tsrx +14 -18
  78. package/tests/client/tracked-index-access.test.tsrx +18 -28
  79. package/tests/client/try.test.tsrx +494 -619
  80. package/tests/client/tsx.test.tsrx +290 -371
  81. package/tests/client/typescript-generics.test.tsrx +121 -129
  82. package/tests/client/url/url.derived.test.tsrx +21 -25
  83. package/tests/client/url/url.parsing.test.tsrx +35 -35
  84. package/tests/client/url/url.partial-removal.test.tsrx +32 -32
  85. package/tests/client/url/url.reactivity.test.tsrx +68 -72
  86. package/tests/client/url/url.serialization.test.tsrx +8 -8
  87. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +21 -27
  88. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +16 -16
  89. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +37 -37
  90. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +56 -60
  91. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +32 -34
  92. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +9 -9
  93. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +10 -10
  94. package/tests/hydration/compiled/client/basic.js +396 -325
  95. package/tests/hydration/compiled/client/composite.js +52 -44
  96. package/tests/hydration/compiled/client/for.js +734 -604
  97. package/tests/hydration/compiled/client/head.js +183 -103
  98. package/tests/hydration/compiled/client/html.js +93 -86
  99. package/tests/hydration/compiled/client/if-children.js +95 -71
  100. package/tests/hydration/compiled/client/if.js +113 -89
  101. package/tests/hydration/compiled/client/mixed-control-flow.js +225 -209
  102. package/tests/hydration/compiled/client/nested-control-flow.js +94 -98
  103. package/tests/hydration/compiled/client/reactivity.js +26 -24
  104. package/tests/hydration/compiled/client/return.js +8 -42
  105. package/tests/hydration/compiled/client/switch.js +208 -173
  106. package/tests/hydration/compiled/client/track-async-serialization.js +176 -128
  107. package/tests/hydration/compiled/client/try.js +29 -21
  108. package/tests/hydration/compiled/server/basic.js +210 -221
  109. package/tests/hydration/compiled/server/composite.js +13 -14
  110. package/tests/hydration/compiled/server/for.js +427 -444
  111. package/tests/hydration/compiled/server/head.js +199 -189
  112. package/tests/hydration/compiled/server/html.js +33 -41
  113. package/tests/hydration/compiled/server/if-children.js +114 -117
  114. package/tests/hydration/compiled/server/if.js +77 -83
  115. package/tests/hydration/compiled/server/mixed-control-flow.js +145 -150
  116. package/tests/hydration/compiled/server/nested-control-flow.js +10 -0
  117. package/tests/hydration/compiled/server/reactivity.js +24 -22
  118. package/tests/hydration/compiled/server/return.js +6 -18
  119. package/tests/hydration/compiled/server/switch.js +179 -176
  120. package/tests/hydration/compiled/server/track-async-serialization.js +88 -70
  121. package/tests/hydration/compiled/server/try.js +31 -35
  122. package/tests/hydration/components/basic.tsrx +216 -286
  123. package/tests/hydration/components/composite.tsrx +32 -42
  124. package/tests/hydration/components/events.tsrx +81 -101
  125. package/tests/hydration/components/for.tsrx +270 -336
  126. package/tests/hydration/components/head.tsrx +43 -39
  127. package/tests/hydration/components/hmr.tsrx +16 -22
  128. package/tests/hydration/components/html-in-template.tsrx +15 -21
  129. package/tests/hydration/components/html.tsrx +442 -526
  130. package/tests/hydration/components/if-children.tsrx +107 -125
  131. package/tests/hydration/components/if.tsrx +68 -90
  132. package/tests/hydration/components/mixed-control-flow.tsrx +65 -72
  133. package/tests/hydration/components/nested-control-flow.tsrx +202 -216
  134. package/tests/hydration/components/portal.tsrx +33 -41
  135. package/tests/hydration/components/reactivity.tsrx +26 -34
  136. package/tests/hydration/components/return.tsrx +4 -6
  137. package/tests/hydration/components/switch.tsrx +73 -78
  138. package/tests/hydration/components/track-async-serialization.tsrx +83 -93
  139. package/tests/hydration/components/try.tsrx +37 -51
  140. package/tests/hydration/switch.test.js +8 -8
  141. package/tests/server/await.test.tsrx +3 -3
  142. package/tests/server/basic.attributes.test.tsrx +120 -167
  143. package/tests/server/basic.components.test.tsrx +163 -197
  144. package/tests/server/basic.test.tsrx +298 -220
  145. package/tests/server/compiler.test.tsrx +142 -72
  146. package/tests/server/composite.props.test.tsrx +54 -58
  147. package/tests/server/composite.test.tsrx +165 -167
  148. package/tests/server/context.test.tsrx +13 -17
  149. package/tests/server/dynamic-elements.test.tsrx +103 -135
  150. package/tests/server/for.test.tsrx +115 -84
  151. package/tests/server/head.test.tsrx +31 -31
  152. package/tests/server/html-nesting-validation.test.tsrx +16 -8
  153. package/tests/server/if.test.tsrx +49 -59
  154. package/tests/server/lazy-destructuring.test.tsrx +288 -366
  155. package/tests/server/return.test.tsrx +58 -36
  156. package/tests/server/streaming-ssr.test.tsrx +4 -4
  157. package/tests/server/style-identifier.test.tsrx +58 -66
  158. package/tests/server/switch.test.tsrx +89 -97
  159. package/tests/server/track-async-serialization.test.tsrx +85 -103
  160. package/tests/server/try.test.tsrx +275 -360
  161. package/tests/utils/ref-types.test.js +72 -0
  162. package/tests/utils/vite-plugin-config.test.js +41 -74
  163. package/types/index.d.ts +1 -0
  164. package/src/runtime/internal/client/compat.js +0 -40
  165. package/tests/utils/compiler-compat-config.test.js +0 -38
@@ -15,9 +15,9 @@ const errorMap = new ErrorMap();`;
15
15
 
16
16
  it('removes type assertions from function parameters and leaves default values', () => {
17
17
  const source = `
18
- function getString(e: string = 'test') {
19
- return e;
20
- }`;
18
+ function getString(e: string = 'test') {
19
+ return e;
20
+ }`;
21
21
 
22
22
  const result = compile(source, 'test.tsrx', { mode: 'server' });
23
23
 
@@ -31,11 +31,11 @@ beforeAll(() => {
31
31
  (global as any).count++;
32
32
  });
33
33
 
34
- function Test() { return <>
35
- let toggle: { value: boolean } | undefined;
36
- toggle!.value = false;
37
- toggle!.value++;
38
- </>; }`;
34
+ function Test() @{
35
+ let toggle: { value: boolean } | undefined;
36
+ toggle!.value = false;
37
+ toggle!.value++;
38
+ }`;
39
39
 
40
40
  const { code } = compile(source, 'test.tsrx', { mode: 'server' });
41
41
 
@@ -50,13 +50,13 @@ function Test() { return <>
50
50
  it(
51
51
  'compiles writes to unknown lazy array index 1 through lazy array helpers in SSR output',
52
52
  () => {
53
- const source = `function Child({ pair: &[first, second] }) { return <>
53
+ const source = `function Child({ pair: &[first, second] }) @{
54
54
  second = 10;
55
55
  <div>{first}</div>
56
- </>; }
57
- function App() { return <>
56
+ }
57
+ function App() @{
58
58
  <Child pair={[0, 1]} />
59
- </>; }`;
59
+ }`;
60
60
  const { code } = compile(source, 'test.tsrx', { mode: 'server' });
61
61
 
62
62
  expect(code).toContain('_$_.lazy_array_set(lazy, 10, 1)');
@@ -65,13 +65,13 @@ function App() { return <>
65
65
  );
66
66
 
67
67
  it('does not double-wrap member access on lazy array value bindings in SSR output', () => {
68
- const source = `function Child({ pair: &[first] }) { return <>
68
+ const source = `function Child({ pair: &[first] }) @{
69
69
  let value = first[0];
70
70
  <div>{value}</div>
71
- </>; }
72
- function App() { return <>
71
+ }
72
+ function App() @{
73
73
  <Child pair={[{ 0: 'x' }]} />
74
- </>; }`;
74
+ }`;
75
75
  const { code } = compile(source, 'test.tsrx', { mode: 'server' });
76
76
 
77
77
  expect(code).toContain('let value = _$_.lazy_array_get(lazy, 0)[0];');
@@ -80,13 +80,13 @@ function App() { return <>
80
80
 
81
81
  it('throws on indexed access through known tracked lazy destructures in SSR output', () => {
82
82
  const source = `import { track } from 'ripple';
83
- function App() { return <>
83
+ function App() @{
84
84
  let &[value, tracked_ref] = track({ 0: 'x' });
85
85
  let nested = value[0];
86
86
  tracked_ref[0] = { 0: 'y' };
87
87
  let next = value[0];
88
88
  <div>{nested}{next}</div>
89
- </>; }`;
89
+ }`;
90
90
 
91
91
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrow(
92
92
  /Use \.value or &\[\] lazy destructuring/,
@@ -95,7 +95,7 @@ function App() { return <>
95
95
 
96
96
  it('throws on known tracked indexed access in SSR output', () => {
97
97
  const source = `import { track } from 'ripple';
98
- function App() { return <>
98
+ function App() @{
99
99
  let tracked = track(0);
100
100
  ++tracked[0];
101
101
  tracked[0]++;
@@ -103,7 +103,7 @@ function App() { return <>
103
103
  let value = tracked[0];
104
104
  let ref = tracked[1];
105
105
  <div>{value}</div>
106
- </>; }`;
106
+ }`;
107
107
 
108
108
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrow(
109
109
  /Use \.value or &\[\] lazy destructuring/,
@@ -114,15 +114,15 @@ function App() { return <>
114
114
  'compiles indexed access on unknown lazy tracked refs through lazy array helpers in SSR output',
115
115
  () => {
116
116
  const source = `import { track } from 'ripple';
117
- function Child({ pair: &[value, tracked_ref] }) { return <>
117
+ function Child({ pair: &[value, tracked_ref] }) @{
118
118
  ++tracked_ref[0];
119
119
  tracked_ref[0]++;
120
120
  <div>{value}</div>
121
- </>; }
122
- function App() { return <>
121
+ }
122
+ function App() @{
123
123
  let tracked = track(0);
124
124
  <Child pair={tracked} />
125
- </>; }`;
125
+ }`;
126
126
  const { code } = compile(source, 'test.tsrx', { mode: 'server' });
127
127
 
128
128
  expect(code).toContain('_$_.lazy_array_get(lazy, 1)');
@@ -166,29 +166,29 @@ class PrintEvent implements BaseEvent {
166
166
 
167
167
  it('throws error for interpolating children as text in SSR mode', () => {
168
168
  const source = `
169
- export function Layout({ children }) { return <>
169
+ export function Layout({ children }) @{
170
170
  <div>{children}</div>
171
- </>; }`;
171
+ }`;
172
172
 
173
173
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).not.toThrow();
174
174
  });
175
175
 
176
176
  it('throws error for interpolating props.children as text in SSR mode', () => {
177
177
  const source = `
178
- export function Layout(props) { return <>
178
+ export function Layout(props) @{
179
179
  <div>{props.children}</div>
180
- </>; }`;
180
+ }`;
181
181
 
182
182
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).not.toThrow();
183
183
  });
184
184
 
185
- it('compiles indented direct double-quoted text children in SSR mode', () => {
185
+ it('compiles indented direct JSX text children in SSR mode', () => {
186
186
  const source = `
187
- export default function A() { return <>
187
+ export default function A() @{
188
188
  <div>
189
- "Hello"
189
+ Hello
190
190
  </div>
191
- </>; }`;
191
+ }`;
192
192
 
193
193
  const result = compile(source, 'test.tsrx', { mode: 'server' }).code;
194
194
 
@@ -196,11 +196,81 @@ export default function A() { return <>
196
196
  expect(result).not.toContain(`"Hello";`);
197
197
  });
198
198
 
199
+ it('does not merge adjacent call-containing children into stringified text in SSR output', () => {
200
+ const setup = `function child(label) {
201
+ <span>{label}</span>
202
+ }
203
+ function Constructed(label) {
204
+ return child(label);
205
+ }
206
+ const factory = child;
207
+ function identity(value) {
208
+ return value;
209
+ }
210
+ function empty() {
211
+ return null;
212
+ }
213
+ let assigned;
214
+ const lookup = { member: child('member') };
215
+ function getKey() {
216
+ return 'member';
217
+ }
218
+ function touch() {
219
+ return null;
220
+ }
221
+ function tag() {
222
+ return child('tagged');
223
+ }
224
+ const values = { member: 0 };`;
225
+
226
+ const cases = [
227
+ { name: 'call expression', expression: 'child(\'call\')' },
228
+ { name: 'new expression', expression: 'new Constructed(\'new\')' },
229
+ { name: 'chain expression', expression: 'factory?.(\'chain\')' },
230
+ { name: 'parenthesized expression', expression: '(child(\'parenthesized\'))' },
231
+ { name: 'TS as expression', expression: 'child(\'as\') as any' },
232
+ { name: 'TS non-null expression', expression: 'child(\'non-null\')!' },
233
+ { name: 'TS satisfies expression', expression: 'child(\'satisfies\') satisfies any' },
234
+ {
235
+ name: 'TS instantiation expression',
236
+ expression: 'identity<typeof child>(child)(\'instantiation\')',
237
+ },
238
+ { name: 'array expression', expression: '[child(\'array\')]' },
239
+ { name: 'assignment expression', expression: 'assigned = child(\'assignment\')' },
240
+ { name: 'binary expression', expression: 'empty() + \'\'' },
241
+ { name: 'logical expression', expression: 'true && child(\'logical\')' },
242
+ { name: 'conditional expression', expression: 'true ? child(\'conditional\') : \'\'' },
243
+ { name: 'member expression', expression: 'lookup[getKey()]' },
244
+ {
245
+ name: 'object expression',
246
+ expression: '{ [Symbol.for(\'ripple.element\')]: true, render() { return child(\'object\'); } }',
247
+ },
248
+ { name: 'sequence expression', expression: '(touch(), child(\'sequence\'))' },
249
+ { name: 'tagged template expression', expression: 'tag`tagged`' },
250
+ { name: 'template literal', expression: '`${empty()}`' },
251
+ { name: 'unary expression', expression: 'void empty()' },
252
+ { name: 'update expression', expression: 'values[getKey()]++' },
253
+ ];
254
+
255
+ for (const test_case of cases) {
256
+ const source = `${setup}
257
+ export function App() @{
258
+ <div>{'${test_case.name}:'}{${test_case.expression}}</div>
259
+ }`;
260
+
261
+ const { code } = compile(source, `${test_case.name}.tsrx`, { mode: 'server' });
262
+
263
+ if (code.includes('String(')) {
264
+ throw new Error(`${test_case.name} was merged into a stringified text expression:\n${code}`);
265
+ }
266
+ }
267
+ });
268
+
199
269
  it('decodes JSX-style entities before server text escaping', () => {
200
270
  const result = compile(
201
- `function App() { return <>
202
- <div>"Rock &amp; &quot;Roll&quot;"</div>
203
- </>; }`,
271
+ `function App() @{
272
+ <div>Rock &amp; &quot;Roll&quot;</div>
273
+ }`,
204
274
  '/src/App.tsrx',
205
275
  { mode: 'server' },
206
276
  );
@@ -210,10 +280,10 @@ export default function A() { return <>
210
280
 
211
281
  it('emits anonymous component expressions as arrows in SSR output', () => {
212
282
  const source = `
213
- const Inline = (props) => <>
214
- <div>{props.x}</div>
215
- </>
216
- `;
283
+ const Inline = (props) => @{
284
+ <div>{props.x}</div>
285
+ }
286
+ `;
217
287
  const result = compile(source, 'anonymous-component.tsrx', { mode: 'server' }).code;
218
288
 
219
289
  expect(result).toContain('const Inline = (props) => {');
@@ -225,9 +295,9 @@ const Inline = (props) => <>
225
295
 
226
296
  it('emits function-expression components as functions in SSR output', () => {
227
297
  const source = `
228
- const Inline = function(props) { return <>
298
+ const Inline = function(props) @{
229
299
  <div>{props.x}</div>
230
- </>; }
300
+ }
231
301
  `;
232
302
  const result = compile(source, 'anonymous-component.tsrx', { mode: 'server' }).code;
233
303
 
@@ -240,9 +310,9 @@ const Inline = function(props) { return <>
240
310
 
241
311
  it('throws error for calling children as a function in SSR mode', () => {
242
312
  const source = `
243
- export function Layout({ children }) { return <>
313
+ export function Layout({ children }) @{
244
314
  {children()}
245
- </>; }`;
315
+ }`;
246
316
 
247
317
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrow(
248
318
  '`children` cannot be called like a regular function. Render it with `{children}` or `{props.children}` instead.',
@@ -251,9 +321,9 @@ export function Layout({ children }) { return <>
251
321
 
252
322
  it('throws error for calling props.children as a function in SSR mode', () => {
253
323
  const source = `
254
- export function Layout(props) { return <>
324
+ export function Layout(props) @{
255
325
  {props.children()}
256
- </>; }`;
326
+ }`;
257
327
 
258
328
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrow(
259
329
  '`children` cannot be called like a regular function. Render it with `{children}` or `{props.children}` instead.',
@@ -262,17 +332,17 @@ export function Layout(props) { return <>
262
332
 
263
333
  it('merges explicit children prop with implicit children in SSR output', () => {
264
334
  const source = `
265
- function Card(props) { return <>
335
+ function Card(props) @{
266
336
  <div>{props.children}</div>
267
- </>; }
337
+ }
268
338
 
269
- export function App() { return <>
339
+ export function App() @{
270
340
  const fallback = 'fallback';
271
341
 
272
342
  <Card children={fallback}>
273
343
  <span>{'content'}</span>
274
344
  </Card>
275
- </>; }
345
+ }
276
346
  `;
277
347
 
278
348
  const result = compile(source, 'test.tsrx', { mode: 'server' }).code;
@@ -284,18 +354,18 @@ export function App() { return <>
284
354
 
285
355
  it('routes calls to functions with nested template returns through render_expression', () => {
286
356
  const source = `
287
- function App() { return <>
288
357
  function make(flag) {
289
358
  if (flag) {
290
- return <tsx><span>{'nested'}</span></tsx>;
359
+ return <span>{'nested'}</span>;
291
360
  }
292
361
 
293
362
  return null;
294
363
  }
295
364
 
296
- <div>{make(true)}</div>
297
- </>; }
298
- `;
365
+ function App() @{
366
+ <div>{make(true)}</div>
367
+ }
368
+ `;
299
369
 
300
370
  const result = compile(source, 'test.tsrx', { mode: 'server' }).code;
301
371
 
@@ -305,23 +375,23 @@ function App() { return <>
305
375
 
306
376
  it('does not treat nested function template returns as outer function returns', () => {
307
377
  const source = `
308
- function App() { return <>
309
378
  function make() {
310
- function nested() {
311
- return <tsx><span>{'nested'}</span></tsx>;
379
+ function nested() @{
380
+ <span>{'nested'}</span>
312
381
  }
313
382
 
314
383
  return nested;
315
384
  }
316
385
 
317
- <div>{make()}</div>
318
- </>; }
319
- `;
386
+ function App() @{
387
+ <div>{make()}</div>
388
+ }
389
+ `;
320
390
 
321
391
  const result = compile(source, 'test.tsrx', { mode: 'server' }).code;
322
392
 
323
- expect(result).toContain('_$_.output_push(_$_.escape(make()))');
324
- expect(result).not.toContain('_$_.render_expression(make())');
393
+ expect(result).toContain('_$_.render_expression(make())');
394
+ expect(result).not.toContain('_$_.render_tsrx_element(make())');
325
395
  });
326
396
  });
327
397
 
@@ -374,10 +444,10 @@ module server {
374
444
 
375
445
  import { loadUser as getUser } from server;
376
446
 
377
- export function App() { return <>
447
+ export function App() @{
378
448
  const user = getUser('1');
379
449
  <div>{user.id}</div>
380
- </>; }`;
450
+ }`;
381
451
 
382
452
  const result = compile(source, 'test.tsrx', { mode: 'server' });
383
453
  expect(result.code).toContain('const getUser = function (...args)');
@@ -442,15 +512,15 @@ module server {
442
512
 
443
513
  it('wraps children in normalize_children for explicit children prop passed to component', () => {
444
514
  const source = `
445
- function Card(props) { return <>
515
+ function Card(props) @{
446
516
  <div>{props.children}</div>
447
- </>; }
517
+ }
448
518
 
449
- export function App() { return <>
519
+ export function App() @{
450
520
  const content = 'hello';
451
521
 
452
522
  <Card children={content} />
453
- </>; }
523
+ }
454
524
  `;
455
525
 
456
526
  const result = compile(source, 'test.tsrx', { mode: 'server' }).code;
@@ -460,15 +530,15 @@ export function App() { return <>
460
530
 
461
531
  it('passes spread through to component when spread may contain children', () => {
462
532
  const source = `
463
- function Card(props) { return <>
533
+ function Card(props) @{
464
534
  <div>{props.children}</div>
465
- </>; }
535
+ }
466
536
 
467
- export function App() { return <>
537
+ export function App() @{
468
538
  const props = { children: 'hello' };
469
539
 
470
540
  <Card {...props} />
471
- </>; }
541
+ }
472
542
  `;
473
543
 
474
544
  const result = compile(source, 'test.tsrx', { mode: 'server' }).code;
@@ -3,16 +3,16 @@ import type { Tracked, Props } from 'ripple';
3
3
 
4
4
  describe('composite > props', () => {
5
5
  it('correctly handles default prop values', async () => {
6
- function Child({ foo = 456 }) {
7
- return <><div>{foo}</div></>;
6
+ function Child({ foo = 456 }) @{
7
+ <div>{foo}</div>
8
8
  }
9
9
 
10
- function App() {
11
- return <>
12
- let &[foo] = track(123);
10
+ function App() @{
11
+ let &[foo] = track(123);
12
+ <>
13
13
  <Child />
14
14
  <Child {foo} />
15
- </>;
15
+ </>
16
16
  }
17
17
 
18
18
  const { body } = await render(App);
@@ -23,16 +23,16 @@ describe('composite > props', () => {
23
23
  });
24
24
 
25
25
  it('correctly handles default prop values #2', async () => {
26
- function Child({ foo = 456 }) {
27
- return <><div>{foo}</div></>;
26
+ function Child({ foo = 456 }) @{
27
+ <div>{foo}</div>
28
28
  }
29
29
 
30
- function App() {
31
- return <>
32
- let foo = 123;
30
+ function App() @{
31
+ let foo = 123;
32
+ <>
33
33
  <Child />
34
34
  <Child {foo} />
35
- </>;
35
+ </>
36
36
  }
37
37
 
38
38
  const { body } = await render(App);
@@ -43,16 +43,18 @@ describe('composite > props', () => {
43
43
  });
44
44
 
45
45
  it('correctly handles no props', async () => {
46
- function Child(props: { foo?: Tracked<number> }) {
47
- return <><div>{props.foo?.value}</div></>;
46
+ function Child(props: { foo?: Tracked<number> }) @{
47
+ <div>
48
+ {props.foo?.value}
49
+ </div>
48
50
  }
49
51
 
50
- function App() {
51
- return <>
52
- let foo = track(123);
52
+ function App() @{
53
+ let foo = track(123);
54
+ <>
53
55
  <Child />
54
56
  <Child {foo} />
55
- </>;
57
+ </>
56
58
  }
57
59
 
58
60
  const { body } = await render(App);
@@ -63,16 +65,16 @@ describe('composite > props', () => {
63
65
  });
64
66
 
65
67
  it('correctly handles no props #2', async () => {
66
- function Child({ foo }: { foo?: number }) {
67
- return <><div>{foo}</div></>;
68
+ function Child({ foo }: { foo?: number }) @{
69
+ <div>{foo}</div>
68
70
  }
69
71
 
70
- function App() {
71
- return <>
72
- let &[foo] = track(123);
72
+ function App() @{
73
+ let &[foo] = track(123);
74
+ <>
73
75
  <Child />
74
76
  <Child {foo} />
75
- </>;
77
+ </>
76
78
  }
77
79
 
78
80
  const { body } = await render(App);
@@ -83,8 +85,8 @@ describe('composite > props', () => {
83
85
  });
84
86
 
85
87
  it('correctly retains prop accessors and reactivity when using rest props', async () => {
86
- function Button(&{ children, ...rest }: Props) {
87
- return <>
88
+ function Button(&{ children, ...rest }: Props) @{
89
+ <>
88
90
  <button {...rest}>{children}</button>
89
91
  <style>
90
92
  .on {
@@ -94,22 +96,20 @@ describe('composite > props', () => {
94
96
  color: red;
95
97
  }
96
98
  </style>
97
- </>;
99
+ </>
98
100
  }
99
101
 
100
- function Toggle(&{ pressed, ...rest }: { pressed: Tracked<boolean> }) {
101
- return <>
102
- const onClick = () => (pressed.value = !pressed.value);
102
+ function Toggle(&{ pressed, ...rest }: { pressed: Tracked<boolean> }) @{
103
+ const onClick = () => (pressed.value = !pressed.value);
104
+ <>
103
105
  <Button {...rest} class={pressed.value ? 'on' : 'off'} {onClick}>{'button 1'}</Button>
104
106
  <Button class={pressed.value ? 'on' : 'off'} {onClick}>{'button 2'}</Button>
105
- </>;
107
+ </>
106
108
  }
107
109
 
108
- function App() {
109
- return <>
110
- const pressed = track(true);
111
- <Toggle {pressed} />
112
- </>;
110
+ function App() @{
111
+ const pressed = track(true);
112
+ <Toggle {pressed} />
113
113
  }
114
114
 
115
115
  const { body } = await render(App);
@@ -132,30 +132,26 @@ describe('composite > props', () => {
132
132
  price: number;
133
133
  }
134
134
 
135
- function Product({ id, name, organizationName, description, imageUrl, price }: ProductInfo) {
136
- return <>
137
- <article class="no-padding">
138
- <img class="responsive small" src={imageUrl} alt={name} />
139
- <span>{id}</span>
140
- <h5>{name}</h5>
141
- <h3>{organizationName}</h3>
142
- <p>{description}</p>
143
- <price class="price">{price}</price>
144
- </article>
145
- </>;
135
+ function Product({ id, name, organizationName, description, imageUrl, price }: ProductInfo) @{
136
+ <article class="no-padding">
137
+ <img class="responsive small" src={imageUrl} alt={name} />
138
+ <span>{id}</span>
139
+ <h5>{name}</h5>
140
+ <h3>{organizationName}</h3>
141
+ <p>{description}</p>
142
+ <price class="price">{price}</price>
143
+ </article>
146
144
  }
147
145
 
148
- function App() {
149
- return <>
150
- <Product
151
- id="1"
152
- name="Product 1"
153
- organizationName="Org 1"
154
- description="Description 1"
155
- imageUrl="https://picsum.photos/300/200"
156
- price={15}
157
- />
158
- </>;
146
+ function App() @{
147
+ <Product
148
+ id="1"
149
+ name="Product 1"
150
+ organizationName="Org 1"
151
+ description="Description 1"
152
+ imageUrl="https://picsum.photos/300/200"
153
+ price={15}
154
+ />
159
155
  }
160
156
 
161
157
  const { body } = await render(App);