ripple 0.4.2 → 0.4.3

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 (94) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/package.json +9 -3
  3. package/src/jsx-runtime.d.ts +2 -1
  4. package/src/runtime/array.js +15 -9
  5. package/src/runtime/index-client.js +25 -7
  6. package/src/runtime/index-server.js +1 -0
  7. package/src/runtime/internal/client/attributes.js +313 -0
  8. package/src/runtime/internal/client/blocks.js +4 -14
  9. package/src/runtime/internal/client/component.js +2 -5
  10. package/src/runtime/internal/client/composite.js +14 -6
  11. package/src/runtime/internal/client/constants.js +6 -6
  12. package/src/runtime/internal/client/context.js +3 -2
  13. package/src/runtime/internal/client/css.js +11 -26
  14. package/src/runtime/internal/client/errors.js +188 -0
  15. package/src/runtime/internal/client/events.js +79 -34
  16. package/src/runtime/internal/client/expression.js +21 -116
  17. package/src/runtime/internal/client/for.js +108 -232
  18. package/src/runtime/internal/client/head.js +4 -3
  19. package/src/runtime/internal/client/html.js +5 -3
  20. package/src/runtime/internal/client/hydrate.js +484 -0
  21. package/src/runtime/internal/client/hydration-enabled.js +7 -0
  22. package/src/runtime/internal/client/hydration.js +16 -81
  23. package/src/runtime/internal/client/if.js +13 -9
  24. package/src/runtime/internal/client/index.js +14 -6
  25. package/src/runtime/internal/client/operations.js +11 -7
  26. package/src/runtime/internal/client/portal.js +3 -2
  27. package/src/runtime/internal/client/render.js +42 -325
  28. package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
  29. package/src/runtime/internal/client/runtime.js +87 -363
  30. package/src/runtime/internal/client/template-ns.js +47 -0
  31. package/src/runtime/internal/client/template.js +63 -140
  32. package/src/runtime/internal/client/track-async.js +356 -0
  33. package/src/runtime/internal/client/try.js +133 -319
  34. package/src/runtime/internal/client/types.d.ts +48 -24
  35. package/src/runtime/internal/server/index.js +31 -29
  36. package/src/runtime/internal/server/prerender.js +27 -0
  37. package/src/server/index.js +1 -0
  38. package/src/utils/class-name.js +28 -0
  39. package/tests/client/basic/basic.errors.test.tsrx +3 -3
  40. package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
  41. package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
  42. package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
  43. package/tests/client/composite/composite.props.test.tsrx +10 -10
  44. package/tests/client/derived-release.test.tsrx +3 -3
  45. package/tests/client/for-item.test.tsrx +39 -0
  46. package/tests/client/for-selector.test.tsrx +95 -0
  47. package/tests/hydration/compiled/client/basic.js +87 -87
  48. package/tests/hydration/compiled/client/composite.js +5 -5
  49. package/tests/hydration/compiled/client/events.js +40 -48
  50. package/tests/hydration/compiled/client/for.js +162 -181
  51. package/tests/hydration/compiled/client/fragment-cursor.js +521 -289
  52. package/tests/hydration/compiled/client/head.js +22 -22
  53. package/tests/hydration/compiled/client/hmr.js +4 -4
  54. package/tests/hydration/compiled/client/html-in-template.js +5 -5
  55. package/tests/hydration/compiled/client/html.js +152 -162
  56. package/tests/hydration/compiled/client/if-children.js +58 -53
  57. package/tests/hydration/compiled/client/if-fragment-controlflow.js +39 -39
  58. package/tests/hydration/compiled/client/if.js +26 -26
  59. package/tests/hydration/compiled/client/mixed-control-flow.js +56 -68
  60. package/tests/hydration/compiled/client/nested-control-flow.js +139 -271
  61. package/tests/hydration/compiled/client/portal.js +10 -10
  62. package/tests/hydration/compiled/client/reactivity.js +29 -29
  63. package/tests/hydration/compiled/client/return.js +2 -2
  64. package/tests/hydration/compiled/client/streaming.js +33 -35
  65. package/tests/hydration/compiled/client/switch.js +25 -25
  66. package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
  67. package/tests/hydration/compiled/client/try.js +15 -15
  68. package/tests/hydration/compiled/client/typed-text.js +7 -7
  69. package/tests/hydration/compiled/server/basic.js +6 -6
  70. package/tests/hydration/compiled/server/events.js +8 -8
  71. package/tests/hydration/compiled/server/for.js +22 -22
  72. package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
  73. package/tests/hydration/compiled/server/head.js +6 -6
  74. package/tests/hydration/compiled/server/hmr.js +1 -1
  75. package/tests/hydration/compiled/server/html.js +1 -1
  76. package/tests/hydration/compiled/server/if-children.js +9 -9
  77. package/tests/hydration/compiled/server/if.js +5 -5
  78. package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
  79. package/tests/hydration/compiled/server/portal.js +1 -1
  80. package/tests/hydration/compiled/server/reactivity.js +9 -9
  81. package/tests/hydration/compiled/server/streaming.js +9 -9
  82. package/tests/hydration/compiled/server/switch.js +4 -4
  83. package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
  84. package/tests/hydration/compiled/server/try.js +4 -4
  85. package/tests/hydration/compiled/server/typed-text.js +1 -1
  86. package/tests/hydration/components/fragment-cursor.tsrx +60 -0
  87. package/tests/hydration/components/track-async-serialization.tsrx +2 -2
  88. package/tests/hydration/fragment-cursor.test.js +34 -1
  89. package/tests/hydration/track-async-serialization.test.js +1 -1
  90. package/tests/server/basic.components.test.tsrx +3 -3
  91. package/tests/server/track-async-serialization.test.tsrx +6 -6
  92. package/tests/utils/tracked-types.test.js +3 -3
  93. package/types/index.d.ts +8 -8
  94. package/types/server.d.ts +17 -0
@@ -5,7 +5,7 @@ import { track } from 'ripple/server';
5
5
 
6
6
  export function IfWithChildren({ children }) {
7
7
  return _$_.tsrx_element(() => {
8
- const expanded = _$_.track(true, 'c64714b1');
8
+ const expanded = _$_.track(true, '1j0jg6p');
9
9
 
10
10
  _$_.regular_block(() => {
11
11
  let __out = '';
@@ -77,7 +77,7 @@ export function TestIfWithChildren() {
77
77
 
78
78
  export function IfWithStaticChildren() {
79
79
  return _$_.tsrx_element(() => {
80
- const expanded = _$_.track(true, '3bba8f77');
80
+ const expanded = _$_.track(true, 'gkm3jr');
81
81
 
82
82
  _$_.regular_block(() => {
83
83
  let __out = '';
@@ -96,7 +96,7 @@ export function IfWithStaticChildren() {
96
96
 
97
97
  export function IfWithSiblingsAndChildren({ children }) {
98
98
  return _$_.tsrx_element(() => {
99
- const expanded = _$_.track(true, 'a1b8fb4c');
99
+ const expanded = _$_.track(true, '18vegr0');
100
100
 
101
101
  _$_.regular_block(() => {
102
102
  let __out = '';
@@ -157,7 +157,7 @@ export function TestIfWithSiblingsAndChildren() {
157
157
 
158
158
  export function ElementWithChildrenThenIf() {
159
159
  return _$_.tsrx_element(() => {
160
- const show = _$_.track(true, '7cd4817b');
160
+ const show = _$_.track(true, 'ymw5ff');
161
161
 
162
162
  _$_.regular_block(() => {
163
163
  let __out = '';
@@ -176,7 +176,7 @@ export function ElementWithChildrenThenIf() {
176
176
 
177
177
  export function DeepNestingThenIf() {
178
178
  return _$_.tsrx_element(() => {
179
- const visible = _$_.track(true, '923116be');
179
+ const visible = _$_.track(true, '14k9o72');
180
180
 
181
181
  _$_.regular_block(() => {
182
182
  let __out = '';
@@ -195,7 +195,7 @@ export function DeepNestingThenIf() {
195
195
 
196
196
  export function DomElementChildrenThenSibling() {
197
197
  return _$_.tsrx_element(() => {
198
- const activeTab = _$_.track('code', '33a1e97f');
198
+ const activeTab = _$_.track('code', 'ebqq2n');
199
199
 
200
200
  _$_.regular_block(() => {
201
201
  let __out = '';
@@ -216,7 +216,7 @@ export function DomElementChildrenThenSibling() {
216
216
 
217
217
  export function DomChildrenThenStaticSiblings() {
218
218
  return _$_.tsrx_element(() => {
219
- const count = _$_.track(0, '0ea64305');
219
+ const count = _$_.track(0, '42buv9');
220
220
 
221
221
  _$_.regular_block(() => {
222
222
  let __out = '';
@@ -287,8 +287,8 @@ function TrailingChild() {
287
287
 
288
288
  export function ComponentChildrenWithControlFlowRoots() {
289
289
  return _$_.tsrx_element(() => {
290
- const on = _$_.track(true, 'f3e4c6ee');
291
- const items = _$_.track([1, 2, 3], '2bbbeeb0');
290
+ const on = _$_.track(true, '1vo6ory');
291
+ const items = _$_.track([1, 2, 3], 'c4uisw');
292
292
 
293
293
  _$_.regular_block(() => {
294
294
  let __out = '';
@@ -64,7 +64,7 @@ export function IfElse() {
64
64
 
65
65
  export function ReactiveIf() {
66
66
  return _$_.tsrx_element(() => {
67
- const show = _$_.track(true, '19a16ff0');
67
+ const show = _$_.track(true, '740m40');
68
68
 
69
69
  _$_.regular_block(() => {
70
70
  let __out = '';
@@ -83,7 +83,7 @@ export function ReactiveIf() {
83
83
 
84
84
  export function ReactiveIfElse() {
85
85
  return _$_.tsrx_element(() => {
86
- const isOn = _$_.track(false, '41177f39');
86
+ const isOn = _$_.track(false, 'i26m2h');
87
87
 
88
88
  _$_.regular_block(() => {
89
89
  let __out = '';
@@ -104,8 +104,8 @@ export function ReactiveIfElse() {
104
104
 
105
105
  export function NestedIf() {
106
106
  return _$_.tsrx_element(() => {
107
- const outer = _$_.track(true, '7894e1df');
108
- const inner = _$_.track(true, 'f21b8c26');
107
+ const outer = _$_.track(true, 'xggelb');
108
+ const inner = _$_.track(true, '1v6cfmu');
109
109
 
110
110
  _$_.regular_block(() => {
111
111
  let __out = '';
@@ -130,7 +130,7 @@ export function NestedIf() {
130
130
 
131
131
  export function IfElseIfChain() {
132
132
  return _$_.tsrx_element(() => {
133
- const status = _$_.track('loading', '4c69c94a');
133
+ const status = _$_.track('loading', 'l79qh6');
134
134
 
135
135
  _$_.regular_block(() => {
136
136
  let __out = '';
@@ -78,9 +78,9 @@ export function MixedControlFlowStatic() {
78
78
 
79
79
  export function MixedControlFlowReactive() {
80
80
  return _$_.tsrx_element(() => {
81
- const show = _$_.track(true, '5ae53d26');
82
- const mode = _$_.track('a', '5b53eda2');
83
- const items = _$_.track([{ id: 1, label: 'One' }, { id: 2, label: 'Two' }], '7890dad6');
81
+ const show = _$_.track(true, 'p7xgkm');
82
+ const mode = _$_.track('a', 'pc8xwi');
83
+ const items = _$_.track([{ id: 1, label: 'One' }, { id: 2, label: 'Two' }], 'xgaqxi');
84
84
 
85
85
  _$_.regular_block(() => {
86
86
  let __out = '';
@@ -214,7 +214,7 @@ export function MixedControlFlowAsyncPending() {
214
214
 
215
215
  function AsyncRow({ label }) {
216
216
  return _$_.tsrx_element(() => {
217
- const value = _$_.track_async(() => Promise.resolve(label), '10cc79a0');
217
+ const value = _$_.track_async(() => Promise.resolve(label), '4nsq00');
218
218
 
219
219
  _$_.regular_block(() => {
220
220
  let __out = '';
@@ -43,7 +43,7 @@ export function SimplePortal() {
43
43
 
44
44
  export function ConditionalPortal() {
45
45
  return _$_.tsrx_element(() => {
46
- const show = _$_.track(true, '4f6df174');
46
+ const show = _$_.track(true, 'm1ectw');
47
47
 
48
48
  _$_.regular_block(() => {
49
49
  let __out = '';
@@ -5,7 +5,7 @@ import { track } from 'ripple/server';
5
5
 
6
6
  export function TrackedState() {
7
7
  return _$_.tsrx_element(() => {
8
- const count = _$_.track(0, 'c1818584');
8
+ const count = _$_.track(0, '1hovkhw');
9
9
 
10
10
  _$_.regular_block(() => {
11
11
  let __out = '';
@@ -18,7 +18,7 @@ export function TrackedState() {
18
18
 
19
19
  export function CounterWithInitial(props) {
20
20
  return _$_.tsrx_element(() => {
21
- const count = _$_.track(props.initial, '03ea4348');
21
+ const count = _$_.track(props.initial, '133ubs');
22
22
 
23
23
  _$_.regular_block(() => {
24
24
  let __out = '';
@@ -52,8 +52,8 @@ export function CounterWrapper() {
52
52
 
53
53
  export function ComputedValues() {
54
54
  return _$_.tsrx_element(() => {
55
- const a = _$_.track(2, 'b78281db');
56
- const b = _$_.track(3, 'a0cf6c6d');
55
+ const a = _$_.track(2, '1ex10ij');
56
+ const b = _$_.track(3, '18mae7h');
57
57
  const sum = () => a.value + b.value;
58
58
 
59
59
  _$_.regular_block(() => {
@@ -75,9 +75,9 @@ export function ComputedValues() {
75
75
 
76
76
  export function MultipleTracked() {
77
77
  return _$_.tsrx_element(() => {
78
- const x = _$_.track(10, '843522de');
79
- const y = _$_.track(20, '1308996d');
80
- const z = _$_.track(30, '048c3fd0');
78
+ const x = _$_.track(10, '10ol1i6');
79
+ const y = _$_.track(20, '5a4d4d');
80
+ const z = _$_.track(30, '19fdn4');
81
81
 
82
82
  _$_.regular_block(() => {
83
83
  let __out = '';
@@ -90,8 +90,8 @@ export function MultipleTracked() {
90
90
 
91
91
  export function DerivedState() {
92
92
  return _$_.tsrx_element(() => {
93
- const firstName = _$_.track('John', '6015eeca');
94
- const lastName = _$_.track('Doe', '4fa9a20e');
93
+ const firstName = _$_.track('John', 'qnrtu2');
94
+ const lastName = _$_.track('Doe', 'm3q77y');
95
95
  const fullName = () => `${firstName.value} ${lastName.value}`;
96
96
 
97
97
  _$_.regular_block(() => {
@@ -32,8 +32,8 @@ resetControls();
32
32
 
33
33
  function BasicContent() {
34
34
  return _$_.tsrx_element(() => {
35
- const data = _$_.track_async(() => controls.basic.promise, '703e438e');
36
- const count = _$_.track(0, '928bce39');
35
+ const data = _$_.track_async(() => controls.basic.promise, 'v55zf2');
36
+ const count = _$_.track(0, '14nt3jt');
37
37
 
38
38
  _$_.regular_block(() => {
39
39
  let __out = '';
@@ -88,7 +88,7 @@ export function StreamPending() {
88
88
 
89
89
  function CatchOnlyContent() {
90
90
  return _$_.tsrx_element(() => {
91
- const data = _$_.track_async(() => controls.catchOnly.promise, '50f939c6');
91
+ const data = _$_.track_async(() => controls.catchOnly.promise, 'mgtlfq');
92
92
 
93
93
  _$_.regular_block(() => {
94
94
  let __out = '';
@@ -158,7 +158,7 @@ export function StreamCatchOnly() {
158
158
 
159
159
  function RejectContent() {
160
160
  return _$_.tsrx_element(() => {
161
- const data = _$_.track_async(() => controls.rejects.promise, '96452a54');
161
+ const data = _$_.track_async(() => controls.rejects.promise, '15p08yc');
162
162
 
163
163
  _$_.regular_block(() => {
164
164
  let __out = '';
@@ -247,7 +247,7 @@ export function StreamRejects() {
247
247
 
248
248
  function NoCatchContent() {
249
249
  return _$_.tsrx_element(() => {
250
- const data = _$_.track_async(() => controls.noCatch.promise, '6baa716b');
250
+ const data = _$_.track_async(() => controls.noCatch.promise, 'tvfywb');
251
251
 
252
252
  _$_.regular_block(() => {
253
253
  let __out = '';
@@ -342,7 +342,7 @@ export function RootPending() {
342
342
 
343
343
  function HeadContent() {
344
344
  return _$_.tsrx_element(() => {
345
- const data = _$_.track_async(() => controls.head.promise, '9cd3c3cd');
345
+ const data = _$_.track_async(() => controls.head.promise, '17ii47h');
346
346
 
347
347
  _$_.regular_block(() => {
348
348
  let __out = '';
@@ -420,7 +420,7 @@ export function StreamHead() {
420
420
 
421
421
  export function StreamRootDirect() {
422
422
  return _$_.tsrx_element(() => {
423
- const data = _$_.track_async(() => controls.rootDirect.promise, 'bc9e61da');
423
+ const data = _$_.track_async(() => controls.rootDirect.promise, '1gc250a');
424
424
 
425
425
  _$_.regular_block(() => {
426
426
  let __out = '';
@@ -441,7 +441,7 @@ export function StreamRootDirect() {
441
441
 
442
442
  function OuterContent() {
443
443
  return _$_.tsrx_element(() => {
444
- const data = _$_.track_async(() => controls.outer.promise, '35931cce');
444
+ const data = _$_.track_async(() => controls.outer.promise, 'ev54ge');
445
445
 
446
446
  _$_.regular_block(() => {
447
447
  let __out = '';
@@ -462,7 +462,7 @@ function OuterContent() {
462
462
 
463
463
  function InnerContent() {
464
464
  return _$_.tsrx_element(() => {
465
- const data = _$_.track_async(() => controls.inner.promise, '6c7d38ed');
465
+ const data = _$_.track_async(() => controls.inner.promise, 'u3o1kd');
466
466
 
467
467
  _$_.regular_block(() => {
468
468
  let __out = '';
@@ -34,7 +34,7 @@ export function SwitchStatic() {
34
34
 
35
35
  export function SwitchReactive() {
36
36
  return _$_.tsrx_element(() => {
37
- const status = _$_.track('a', '9b34d955');
37
+ const status = _$_.track('a', '172bas5');
38
38
 
39
39
  _$_.regular_block(() => {
40
40
  let __out = '';
@@ -91,7 +91,7 @@ export function SwitchFallthrough() {
91
91
 
92
92
  export function SwitchNumericLevels() {
93
93
  return _$_.tsrx_element(() => {
94
- const level = _$_.track(1, '7581a7ab');
94
+ const level = _$_.track(1, 'wlqm5n');
95
95
 
96
96
  _$_.regular_block(() => {
97
97
  let __out = '';
@@ -120,7 +120,7 @@ export function SwitchNumericLevels() {
120
120
 
121
121
  export function SwitchBlockScoped() {
122
122
  return _$_.tsrx_element(() => {
123
- const level = _$_.track(1, 'ca9f9852');
123
+ const level = _$_.track(1, '1k7y5oy');
124
124
 
125
125
  _$_.regular_block(() => {
126
126
  let __out = '';
@@ -149,7 +149,7 @@ export function SwitchBlockScoped() {
149
149
 
150
150
  export function SwitchNoBreak() {
151
151
  return _$_.tsrx_element(() => {
152
- const level = _$_.track(1, '6b7cb0ea');
152
+ const level = _$_.track(1, 'ttnpbe');
153
153
 
154
154
  _$_.regular_block(() => {
155
155
  let __out = '';
@@ -2,7 +2,7 @@
2
2
  import * as _$_ from 'ripple/internal/server';
3
3
 
4
4
  import { Money as _$_Money__ } from '../fixtures/money.js';
5
- import { track, trackAsync } from 'ripple/server';
5
+ import { track, trackAsync, trackReadOnly } from 'ripple/server';
6
6
  import { Money } from '../fixtures/money.js';
7
7
 
8
8
  export const transport = {
@@ -39,7 +39,7 @@ const formatValue = function (...args) {
39
39
 
40
40
  function MoneyResult({ count }) {
41
41
  return _$_.tsrx_element(() => {
42
- const money = _$_.track_async(() => doubleMoney(new Money(count.value, 'USD')), '2e21cbe9');
42
+ const money = _$_.track_async(() => doubleMoney(new Money(count.value, 'USD')), 'csssmh');
43
43
 
44
44
  _$_.regular_block(() => {
45
45
  let __out = '';
@@ -60,7 +60,7 @@ function MoneyResult({ count }) {
60
60
 
61
61
  export function AsyncCustomType() {
62
62
  return _$_.tsrx_element(() => {
63
- const count = _$_.track(6, 'f0c2b41e');
63
+ const count = _$_.track(6, '1usw1lq');
64
64
 
65
65
  _$_.regular_block(() => {
66
66
  let __out = '';
@@ -103,7 +103,7 @@ export function AsyncCustomType() {
103
103
 
104
104
  function ServerCallResult({ count }) {
105
105
  return _$_.tsrx_element(() => {
106
- const data = _$_.track_async(() => formatValue(count.value), '4e502c38');
106
+ const data = _$_.track_async(() => formatValue(count.value), 'lq8y0o');
107
107
 
108
108
  _$_.regular_block(() => {
109
109
  let __out = '';
@@ -124,7 +124,7 @@ function ServerCallResult({ count }) {
124
124
 
125
125
  export function AsyncWithServerCall() {
126
126
  return _$_.tsrx_element(() => {
127
- const count = _$_.track(0, '14891754');
127
+ const count = _$_.track(0, '5p4g2c');
128
128
 
129
129
  _$_.regular_block(() => {
130
130
  let __out = '';
@@ -173,7 +173,7 @@ export function AsyncSimpleValue() {
173
173
 
174
174
  __out += '<!--[-->';
175
175
 
176
- const data = _$_.track_async(() => Promise.resolve('hydrated value'), 'f325448a');
176
+ const data = _$_.track_async(() => Promise.resolve('hydrated value'), '1vgpoju');
177
177
 
178
178
  _$_.output_push(__out);
179
179
  __out = '';
@@ -226,7 +226,7 @@ export function AsyncNumericValue() {
226
226
 
227
227
  __out += '<!--[-->';
228
228
 
229
- const count = _$_.track_async(() => Promise.resolve(42), 'ab8199a0');
229
+ const count = _$_.track_async(() => Promise.resolve(42), '1bl4m1s');
230
230
 
231
231
  _$_.output_push(__out);
232
232
  __out = '';
@@ -279,7 +279,7 @@ export function AsyncObjectValue() {
279
279
 
280
280
  __out += '<!--[-->';
281
281
 
282
- const user = _$_.track_async(() => Promise.resolve({ name: 'Alice', age: 30 }), 'fb7ad40b');
282
+ const user = _$_.track_async(() => Promise.resolve({ name: 'Alice', age: 30 }), '1xrym8b');
283
283
 
284
284
  _$_.output_push(__out);
285
285
  __out = '';
@@ -340,8 +340,8 @@ export function AsyncMultipleValues() {
340
340
 
341
341
  __out += '<!--[-->';
342
342
 
343
- const first = _$_.track_async(() => Promise.resolve('alpha'), '99982de5');
344
- const second = _$_.track_async(() => Promise.resolve('beta'), '1dea4c85');
343
+ const first = _$_.track_async(() => Promise.resolve('alpha'), '16m7mxx');
344
+ const second = _$_.track_async(() => Promise.resolve('beta'), '8atc3p');
345
345
 
346
346
  _$_.output_push(__out);
347
347
  __out = '';
@@ -402,7 +402,7 @@ export function AsyncWithCatch() {
402
402
 
403
403
  __out += '<!--[-->';
404
404
 
405
- const data = _$_.track_async(() => Promise.reject(new Error('fetch failed')), 'c9d12acf');
405
+ const data = _$_.track_async(() => Promise.reject(new Error('fetch failed')), '1jzw72n');
406
406
 
407
407
  _$_.output_push(__out);
408
408
  __out = '';
@@ -479,7 +479,7 @@ export function ChildWithError() {
479
479
 
480
480
  __out += '<!--[-->';
481
481
 
482
- const data = _$_.track_async(() => Promise.reject(new Error('child error')), 'cdd1adb8');
482
+ const data = _$_.track_async(() => Promise.reject(new Error('child error')), '1l3vago');
483
483
 
484
484
  _$_.output_push(__out);
485
485
  __out = '';
@@ -578,7 +578,7 @@ export function ParentWithCatch() {
578
578
 
579
579
  function ReactiveDependencyResult({ count }) {
580
580
  return _$_.tsrx_element(() => {
581
- const data = _$_.track_async(() => Promise.resolve(`count-${count.value}`), '18c43c3a');
581
+ const data = _$_.track_async(() => Promise.resolve(`count-${count.value}`), '6vdwe2');
582
582
 
583
583
  _$_.regular_block(() => {
584
584
  let __out = '';
@@ -599,7 +599,7 @@ function ReactiveDependencyResult({ count }) {
599
599
 
600
600
  export function AsyncWithReactiveDependency() {
601
601
  return _$_.tsrx_element(() => {
602
- const count = _$_.track(0, 'd5dcc1d3');
602
+ const count = _$_.track(0, '1nc7lqr');
603
603
 
604
604
  _$_.regular_block(() => {
605
605
  let __out = '';
@@ -642,7 +642,7 @@ export function AsyncWithReactiveDependency() {
642
642
 
643
643
  export function AsyncWithReadOnlyDependency() {
644
644
  return _$_.tsrx_element(() => {
645
- const count = _$_.track(0, '75a97b64');
645
+ const count = _$_.track(0, 'wnak4k');
646
646
 
647
647
  _$_.regular_block(() => {
648
648
  let __out = '';
@@ -659,7 +659,7 @@ export function AsyncWithReadOnlyDependency() {
659
659
 
660
660
  {
661
661
  const comp = ReactiveDependencyResult;
662
- const args = [{ count: count.readOnly() }];
662
+ const args = [{ count: _$_.track_read_only(count) }];
663
663
 
664
664
  _$_.output_push(__out);
665
665
  __out = '';
@@ -48,7 +48,7 @@ export function RootThrows() {
48
48
 
49
49
  export function RootAsyncDirect() {
50
50
  return _$_.tsrx_element(() => {
51
- const value = _$_.track_async(() => Promise.resolve('root async value'), 'd6bf9e33');
51
+ const value = _$_.track_async(() => Promise.resolve('root async value'), '1nl29mb');
52
52
 
53
53
  _$_.regular_block(() => {
54
54
  let __out = '';
@@ -69,7 +69,7 @@ export function RootAsyncDirect() {
69
69
 
70
70
  export function RootAsyncRejects() {
71
71
  return _$_.tsrx_element(() => {
72
- const value = _$_.track_async(() => Promise.reject(new Error('root async failed')), 'd2fe7b64');
72
+ const value = _$_.track_async(() => Promise.reject(new Error('root async failed')), '1mjk6zo');
73
73
 
74
74
  _$_.regular_block(() => {
75
75
  let __out = '';
@@ -134,7 +134,7 @@ export function AsyncListInTryPending() {
134
134
 
135
135
  function AsyncList() {
136
136
  return _$_.tsrx_element(() => {
137
- const items = _$_.track_async(() => Promise.resolve(['alpha', 'beta', 'gamma']), 'b3d31627');
137
+ const items = _$_.track_async(() => Promise.resolve(['alpha', 'beta', 'gamma']), '1dw7tpj');
138
138
 
139
139
  _$_.regular_block(() => {
140
140
  let __out = '';
@@ -202,7 +202,7 @@ export function AsyncTryWithLeadingSibling() {
202
202
 
203
203
  function AsyncContent() {
204
204
  return _$_.tsrx_element(() => {
205
- const value = _$_.track_async(() => Promise.resolve('ready'), '15ea8758');
205
+ const value = _$_.track_async(() => Promise.resolve('ready'), '62wwns');
206
206
 
207
207
  _$_.regular_block(() => {
208
208
  let __out = '';
@@ -5,7 +5,7 @@ import { track } from 'ripple/server';
5
5
 
6
6
  export function TypedText() {
7
7
  return _$_.tsrx_element(() => {
8
- const row = _$_.track({ label: '<first>', count: 2 }, '9bf2304a');
8
+ const row = _$_.track({ label: '<first>', count: 2 }, '179p9ai');
9
9
 
10
10
  _$_.regular_block(() => {
11
11
  let __out = '';
@@ -648,3 +648,63 @@ export function WrapStaticThenStyleThenStatic() @{
648
648
  <button class="outer-inc" onClick={() => n.value++}>{'outer'}</button>
649
649
  </div>
650
650
  }
651
+
652
+ // A component, `@if`, or `@for` before a static element sibling inside an
653
+ // element inserts before that element (no placeholder of its own); the
654
+ // hydration cursor still steps from the node to the element.
655
+ export function CompThenStaticInDiv() @{
656
+ const n = track(0);
657
+ <div class="outer">
658
+ <Leaf />
659
+ <span class="after">{n.value}</span>
660
+ <button class="outer-inc" onClick={() => n.value++}>{'outer'}</button>
661
+ </div>
662
+ }
663
+
664
+ export function SiblingCompsInDiv() @{
665
+ const n = track(0);
666
+ <div class="outer">
667
+ <Leaf />
668
+ <Leaf />
669
+ <span class="after">{n.value}</span>
670
+ <button class="outer-inc" onClick={() => n.value++}>{'outer'}</button>
671
+ </div>
672
+ }
673
+
674
+ export function IfSwapThenStaticInDiv() @{
675
+ const n = track(0);
676
+ <div class="outer">
677
+ @if (n.value % 2 === 0) {
678
+ <b class="even">{'even'}</b>
679
+ } @else {
680
+ <i class="odd">{'odd'}</i>
681
+ }
682
+ <span class="after">{n.value}</span>
683
+ <button class="outer-inc" onClick={() => n.value++}>{'outer'}</button>
684
+ </div>
685
+ }
686
+
687
+ export function ForThenStaticInDiv() @{
688
+ const n = track(0);
689
+ const items = [1, 2];
690
+ <div class="outer">
691
+ @for (const item of items) {
692
+ <b class="item">{item}</b>
693
+ }
694
+ <span class="after">{n.value}</span>
695
+ <button class="outer-inc" onClick={() => n.value++}>{'outer'}</button>
696
+ </div>
697
+ }
698
+
699
+ export function CompThenStatementThenStaticInDiv() @{
700
+ const n = track(0);
701
+ <div class="outer">
702
+ <Leaf />
703
+ @{
704
+ const label = 'after';
705
+ console.assert(label === 'after');
706
+ }
707
+ <span class="after">{n.value}</span>
708
+ <button class="outer-inc" onClick={() => n.value++}>{'outer'}</button>
709
+ </div>
710
+ }
@@ -1,4 +1,4 @@
1
- import { track, trackAsync } from 'ripple';
1
+ import { track, trackAsync, trackReadOnly } from 'ripple';
2
2
  import { Money } from '../fixtures/money.js';
3
3
 
4
4
  export const transport = {
@@ -170,7 +170,7 @@ export function AsyncWithReadOnlyDependency() @{
170
170
  }}
171
171
  >{'increment'}</button>
172
172
  @try {
173
- <ReactiveDependencyResult count={count.readOnly()} />
173
+ <ReactiveDependencyResult count={trackReadOnly(count)} />
174
174
  } @pending {
175
175
  <p class="loading">{'loading...'}</p>
176
176
  }
@@ -45,7 +45,16 @@ const shapes = [
45
45
  ];
46
46
 
47
47
  // Single-root shapes whose children end on a slot the cursor must step past.
48
- const rootShapes = ['ExprThenSiblingInDiv', 'IfTwoInDiv', 'ForTwoNodeItems'];
48
+ const rootShapes = [
49
+ 'ExprThenSiblingInDiv',
50
+ 'IfTwoInDiv',
51
+ 'ForTwoNodeItems',
52
+ 'CompThenStaticInDiv',
53
+ 'SiblingCompsInDiv',
54
+ 'IfSwapThenStaticInDiv',
55
+ 'ForThenStaticInDiv',
56
+ 'CompThenStatementThenStaticInDiv',
57
+ ];
49
58
 
50
59
  /**
51
60
  * Server renders and hydrates a component, asserting the hydrated DOM matches
@@ -88,10 +97,34 @@ describe('hydration > fragment cursor', () => {
88
97
  it(`hydrates ${name}`, async () => {
89
98
  await hydrateShape(name);
90
99
  clickInner();
100
+
101
+ const after = container.querySelector('.after');
102
+ const inc = container.querySelector('.outer-inc');
103
+ if (after && inc) {
104
+ expect(after.textContent).toBe('0');
105
+ inc.click();
106
+ flushSync();
107
+ expect(after.textContent).toBe('1');
108
+ }
91
109
  });
92
110
  }
93
111
  });
94
112
 
113
+ it('swaps an @if branch before its static element sibling after hydration', async () => {
114
+ await hydrateShape('IfSwapThenStaticInDiv');
115
+ const outer = container.querySelector('.outer');
116
+ expect(outer?.querySelector('.even')).not.toBeNull();
117
+ container.querySelector('.outer-inc')?.click();
118
+ flushSync();
119
+ expect(outer?.querySelector('.even')).toBeNull();
120
+ expect(outer?.children[0]?.className).toBe('odd');
121
+ expect(outer?.children[1]?.className).toBe('after');
122
+ container.querySelector('.outer-inc')?.click();
123
+ flushSync();
124
+ expect(outer?.children[0]?.className).toBe('even');
125
+ expect(outer?.children[1]?.textContent).toBe('2');
126
+ });
127
+
95
128
  describe('fragment as a child with trailing siblings', () => {
96
129
  for (const name of shapes) {
97
130
  it(`hydrates ${name} followed by siblings`, async () => {
@@ -145,7 +145,7 @@ describe('hydration > trackAsync serialization', () => {
145
145
  expect(container.querySelector('.result')?.textContent).toBe('count-1');
146
146
  });
147
147
 
148
- it('reruns trackAsync when a dependency read through readOnly() changes after hydration', async () => {
148
+ it('reruns trackAsync when a dependency read through trackReadOnly() changes after hydration', async () => {
149
149
  await hydrateComponent(
150
150
  ServerComponents.AsyncWithReadOnlyDependency,
151
151
  ClientComponents.AsyncWithReadOnlyDependency,
@@ -1,4 +1,4 @@
1
- import { track } from 'ripple';
1
+ import { track, trackReadOnly } from 'ripple';
2
2
  import type {
3
3
  Derived,
4
4
  Tracked,
@@ -9,7 +9,7 @@ import type {
9
9
  } from 'ripple';
10
10
 
11
11
  describe('basic server > components & composition', () => {
12
- it('renders a read-only view passed through readOnly()', async () => {
12
+ it('renders a read-only view passed through trackReadOnly()', async () => {
13
13
  function Child({ count }: { count: Derived<number> }) @{
14
14
  <span>{count.value}</span>
15
15
  }
@@ -17,7 +17,7 @@ describe('basic server > components & composition', () => {
17
17
  function App() @{
18
18
  const count = track(5);
19
19
  <div>
20
- <Child count={count.readOnly()} />
20
+ <Child count={trackReadOnly(count)} />
21
21
  </div>
22
22
  }
23
23