ripple 0.4.2 → 0.4.4

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 (98) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/package.json +10 -4
  3. package/src/constants.js +6 -0
  4. package/src/jsx-runtime.d.ts +2 -1
  5. package/src/runtime/array.js +15 -9
  6. package/src/runtime/index-client.js +25 -7
  7. package/src/runtime/index-server.js +1 -0
  8. package/src/runtime/internal/client/attributes.js +439 -0
  9. package/src/runtime/internal/client/blocks.js +20 -20
  10. package/src/runtime/internal/client/component.js +2 -5
  11. package/src/runtime/internal/client/composite.js +295 -95
  12. package/src/runtime/internal/client/constants.js +14 -6
  13. package/src/runtime/internal/client/context.js +3 -2
  14. package/src/runtime/internal/client/css.js +11 -26
  15. package/src/runtime/internal/client/errors.js +188 -0
  16. package/src/runtime/internal/client/events.js +79 -34
  17. package/src/runtime/internal/client/expression.js +25 -120
  18. package/src/runtime/internal/client/for.js +113 -262
  19. package/src/runtime/internal/client/head.js +4 -3
  20. package/src/runtime/internal/client/html.js +5 -3
  21. package/src/runtime/internal/client/hydrate.js +484 -0
  22. package/src/runtime/internal/client/hydration-enabled.js +7 -0
  23. package/src/runtime/internal/client/hydration.js +16 -81
  24. package/src/runtime/internal/client/if.js +69 -10
  25. package/src/runtime/internal/client/index.js +18 -10
  26. package/src/runtime/internal/client/operations.js +11 -7
  27. package/src/runtime/internal/client/portal.js +3 -2
  28. package/src/runtime/internal/client/render.js +42 -325
  29. package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
  30. package/src/runtime/internal/client/runtime.js +157 -371
  31. package/src/runtime/internal/client/template-ns.js +88 -0
  32. package/src/runtime/internal/client/template.js +118 -139
  33. package/src/runtime/internal/client/track-async.js +356 -0
  34. package/src/runtime/internal/client/try.js +133 -319
  35. package/src/runtime/internal/client/types.d.ts +48 -24
  36. package/src/runtime/internal/server/index.js +31 -29
  37. package/src/runtime/internal/server/prerender.js +27 -0
  38. package/src/server/index.js +1 -0
  39. package/src/utils/class-name.js +28 -0
  40. package/tests/client/basic/basic.errors.test.tsrx +3 -3
  41. package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
  42. package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
  43. package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
  44. package/tests/client/composite/composite.dynamic-components.test.tsrx +40 -0
  45. package/tests/client/composite/composite.props.test.tsrx +10 -10
  46. package/tests/client/css/scoped-styles.test.tsrx +3 -1
  47. package/tests/client/derived-release.test.tsrx +3 -3
  48. package/tests/client/for-item.test.tsrx +39 -0
  49. package/tests/client/for-selector.test.tsrx +95 -0
  50. package/tests/client/svg.test.tsrx +273 -1
  51. package/tests/hydration/compiled/client/basic.js +88 -87
  52. package/tests/hydration/compiled/client/composite.js +15 -6
  53. package/tests/hydration/compiled/client/events.js +40 -48
  54. package/tests/hydration/compiled/client/for.js +191 -199
  55. package/tests/hydration/compiled/client/fragment-cursor.js +633 -334
  56. package/tests/hydration/compiled/client/head.js +22 -22
  57. package/tests/hydration/compiled/client/hmr.js +14 -5
  58. package/tests/hydration/compiled/client/html-in-template.js +5 -5
  59. package/tests/hydration/compiled/client/html.js +195 -177
  60. package/tests/hydration/compiled/client/if-children.js +136 -63
  61. package/tests/hydration/compiled/client/if-fragment-controlflow.js +63 -43
  62. package/tests/hydration/compiled/client/if.js +78 -30
  63. package/tests/hydration/compiled/client/mixed-control-flow.js +90 -72
  64. package/tests/hydration/compiled/client/nested-control-flow.js +266 -307
  65. package/tests/hydration/compiled/client/portal.js +20 -11
  66. package/tests/hydration/compiled/client/reactivity.js +29 -29
  67. package/tests/hydration/compiled/client/return.js +2 -2
  68. package/tests/hydration/compiled/client/streaming.js +33 -35
  69. package/tests/hydration/compiled/client/switch.js +25 -25
  70. package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
  71. package/tests/hydration/compiled/client/try.js +15 -15
  72. package/tests/hydration/compiled/client/typed-text.js +8 -7
  73. package/tests/hydration/compiled/server/basic.js +6 -6
  74. package/tests/hydration/compiled/server/events.js +8 -8
  75. package/tests/hydration/compiled/server/for.js +22 -22
  76. package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
  77. package/tests/hydration/compiled/server/head.js +6 -6
  78. package/tests/hydration/compiled/server/hmr.js +1 -1
  79. package/tests/hydration/compiled/server/html.js +1 -1
  80. package/tests/hydration/compiled/server/if-children.js +9 -9
  81. package/tests/hydration/compiled/server/if.js +5 -5
  82. package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
  83. package/tests/hydration/compiled/server/portal.js +1 -1
  84. package/tests/hydration/compiled/server/reactivity.js +9 -9
  85. package/tests/hydration/compiled/server/streaming.js +9 -9
  86. package/tests/hydration/compiled/server/switch.js +4 -4
  87. package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
  88. package/tests/hydration/compiled/server/try.js +4 -4
  89. package/tests/hydration/compiled/server/typed-text.js +1 -1
  90. package/tests/hydration/components/fragment-cursor.tsrx +60 -0
  91. package/tests/hydration/components/track-async-serialization.tsrx +2 -2
  92. package/tests/hydration/fragment-cursor.test.js +34 -1
  93. package/tests/hydration/track-async-serialization.test.js +1 -1
  94. package/tests/server/basic.components.test.tsrx +3 -3
  95. package/tests/server/track-async-serialization.test.tsrx +6 -6
  96. package/tests/utils/tracked-types.test.js +3 -3
  97. package/types/index.d.ts +8 -8
  98. package/types/server.d.ts +17 -0
@@ -3,6 +3,7 @@
3
3
  import {
4
4
  block,
5
5
  branch,
6
+ create_block,
6
7
  destroy_block,
7
8
  get_first_node,
8
9
  get_last_node,
@@ -10,10 +11,12 @@ import {
10
11
  remove_block_dom,
11
12
  } from './blocks.js';
12
13
  import { DETACHED_BLOCK, IF_BLOCK, RENDER_BLOCK, UNINITIALIZED } from './constants.js';
14
+ import { IF_ROOT_CONTROLLED, IF_TRACKED } from '../../../constants.js';
13
15
  import { hydrate_next, hydrate_node, hydrating } from './hydration.js';
14
16
  import { create_text, resolve_anchor } from './operations.js';
15
- import { active_block, probe_if, run_untracked } from './runtime.js';
17
+ import { active_block, probe_if, run_in_block, run_untracked } from './runtime.js';
16
18
  import { append } from './template.js';
19
+ import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
17
20
 
18
21
  /**
19
22
  * The if block renders its branch directly: the block owns the branch's DOM
@@ -108,7 +111,9 @@ function destroy_branch(state, block) {
108
111
  * is materialized as late as possible: when a branch swap needs the position
109
112
  * of the branch being replaced (still rendered), or when the if renders
110
113
  * nothing and would otherwise have no position at all. Until then a list of
111
- * `@if` items keeps no anchor nodes in the DOM.
114
+ * `@if` items keeps no anchor nodes in the DOM. A tail sentinel (the if is
115
+ * the last thing rendered into its parent) is never materialized: appending
116
+ * to the parent stays right for the if's whole life.
112
117
  * @param {IfState} state
113
118
  * @param {Block} block
114
119
  */
@@ -147,9 +152,14 @@ function update_branch(state, fn) {
147
152
 
148
153
  var block = /** @type {Block} */ (active_block);
149
154
 
155
+ var anchor = /** @type {AppendIntoAnchor} */ (state.a);
156
+ // A sentinel the if may still materialize (a tail sentinel never is).
157
+ var sentinel = anchor.into === true && anchor.tail !== true;
158
+
150
159
  if (previous !== UNINITIALIZED) {
151
- if (/** @type {AppendIntoAnchor} */ (state.a).into === true) {
160
+ if (sentinel) {
152
161
  materialize_anchor(state, block);
162
+ sentinel = false;
153
163
  }
154
164
  destroy_branch(state, block);
155
165
  }
@@ -161,14 +171,10 @@ function update_branch(state, fn) {
161
171
 
162
172
  if (o !== null) {
163
173
  move_block_last(o);
164
- } else if (
165
- /** @type {AppendIntoAnchor} */ (state.a).into === true &&
166
- state.start === null &&
167
- first_child_node(block, null) === null
168
- ) {
174
+ } else if (sentinel && state.start === null && first_child_node(block, null) === null) {
169
175
  materialize_anchor(state, block);
170
176
  }
171
- } else if (/** @type {AppendIntoAnchor} */ (state.a).into === true) {
177
+ } else if (sentinel) {
172
178
  materialize_anchor(state, block);
173
179
  }
174
180
  }
@@ -222,7 +228,7 @@ export function if_block(node, fn, root_controlled, x) {
222
228
  var boundary;
223
229
  var anchor = node;
224
230
 
225
- if (!hydrating) {
231
+ if (!(HYDRATION && hydrating)) {
226
232
  // Evaluate the condition before deciding whether the if needs a block:
227
233
  // a condition that read no tracked state has its branch rendered by the
228
234
  // probe itself, directly under the current block, with no if block, no
@@ -258,3 +264,56 @@ export function if_block(node, fn, root_controlled, x) {
258
264
  append(/** @type {ChildNode} */ (node), /** @type {Node} */ (boundary));
259
265
  }
260
266
  }
267
+
268
+ /**
269
+ * An if whose condition the enclosing render function evaluates (see the
270
+ * compiler's if lowering): the block only owns the branch, its DOM range and
271
+ * its blocks, and never runs itself. The render function calls `if_update`
272
+ * with the branch the condition selected whenever that changes. As
273
+ * `if_block` does, a condition that read no tracked state has its branch
274
+ * rendered by the probe, with no block at all: null is returned and the
275
+ * updates are no-ops. While hydrating, the if keeps a block of its own that
276
+ * runs the condition, exactly as `if_block` creates: the branch claims its
277
+ * server nodes in document order, and that block owns the condition's
278
+ * subscription and a pending read it throws; null is returned then too.
279
+ * @param {Node | AppendIntoAnchor} node
280
+ * @param {IfState['fn']} fn
281
+ * @param {number} [flags] `IF_ROOT_CONTROLLED` (see `if_block`) and
282
+ * `IF_TRACKED`, set when the compiler proved the condition reads tracked
283
+ * state, so the probe is skipped
284
+ * @param {any} [x] see `if_block`
285
+ * @returns {Block | null}
286
+ */
287
+ export function if_static(node, fn, flags = 0, x) {
288
+ var root_controlled = (flags & IF_ROOT_CONTROLLED) !== 0;
289
+
290
+ if (HYDRATION && hydrating) {
291
+ if_block(node, fn, root_controlled, x);
292
+ return null;
293
+ }
294
+ if ((flags & IF_TRACKED) === 0) {
295
+ var rendered;
296
+ try {
297
+ rendered = probe_if(fn, x, node);
298
+ } catch {
299
+ rendered = false;
300
+ }
301
+ if (rendered) {
302
+ return null;
303
+ }
304
+ }
305
+
306
+ return create_block(IF_BLOCK, noop, if_block_state(node, fn, x));
307
+ }
308
+
309
+ /**
310
+ * Renders `fn` as the branch of an if created by `if_static`, when it is not
311
+ * the current one. The branch's blocks belong to the if block.
312
+ * @param {Block | null} block
313
+ * @param {Branch | undefined} fn
314
+ */
315
+ export function if_update(block, fn) {
316
+ if (block !== null) {
317
+ run_in_block(block, update_branch, fn);
318
+ }
319
+ }
@@ -14,8 +14,7 @@ export {
14
14
  set_text,
15
15
  set_text_content,
16
16
  set_class,
17
- set_style,
18
- set_attribute,
17
+ set_class_value,
19
18
  set_value,
20
19
  set_checked,
21
20
  set_selected,
@@ -23,7 +22,6 @@ export {
23
22
 
24
23
  export {
25
24
  render,
26
- render_spread,
27
25
  ref,
28
26
  branch,
29
27
  destroy_block,
@@ -41,7 +39,8 @@ export {
41
39
  SUSPENSE_REJECTED,
42
40
  RENDER_ENTRY as $r,
43
41
  } from './constants.js';
44
- export { event, render_event, delegate } from './events.js';
42
+ export { event, render_event, delegate, listen } from './events.js';
43
+ export { set_style, set_attribute, render_spread, spread } from './attributes.js';
45
44
  export { portal } from './portal.js';
46
45
 
47
46
  export {
@@ -63,7 +62,7 @@ export {
63
62
  update_property,
64
63
  update_pre_property,
65
64
  track,
66
- track_async,
65
+ track_read_only,
67
66
  is_tracked_pending,
68
67
  peek_tracked,
69
68
  push_component,
@@ -74,13 +73,15 @@ export {
74
73
  derived,
75
74
  tick,
76
75
  with_block,
77
- with_ns,
76
+ set_ns,
78
77
  handle_error,
79
78
  queue_post_block_flush_callback,
80
79
  schedule_update,
81
80
  } from './runtime.js';
82
81
 
83
- export { composite } from './composite.js';
82
+ export { track_async } from './track-async.js';
83
+
84
+ export { composite, dynamic, dynamic_init } from './composite.js';
84
85
 
85
86
  export { render_component } from './component.js';
86
87
 
@@ -88,15 +89,22 @@ export { for_block as for, for_block_keyed as for_keyed, item } from './for.js';
88
89
 
89
90
  export { selector, selector_match } from './selector.js';
90
91
 
91
- export { if_block as if } from './if.js';
92
+ export { if_block as if, if_static, if_update } from './if.js';
92
93
 
93
94
  export { try_block as try, get_pending_boundary } from './try.js';
94
95
 
95
96
  export { if_block as switch } from './if.js';
96
97
 
97
- export { template, append, text } from './template.js';
98
+ export { template, template_el, append, text } from './template.js';
99
+
100
+ export { template_ns, with_ns, render_component_ns } from './template-ns.js';
98
101
 
99
- export { ripple_array } from '../../array.js';
102
+ export {
103
+ ripple_array,
104
+ ripple_array_from,
105
+ ripple_array_of,
106
+ ripple_array_from_async,
107
+ } from '../../array.js';
100
108
 
101
109
  export { ripple_object } from '../../object.js';
102
110
 
@@ -8,6 +8,7 @@ import {
8
8
  set_hydrate_node,
9
9
  } from './hydration.js';
10
10
  import { get_descriptor } from '@tsrx/core/runtime/language-helpers';
11
+ import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
11
12
 
12
13
  export { hydrate_first_child, hydrate_next_sibling };
13
14
 
@@ -76,7 +77,7 @@ export function get_last_child(node) {
76
77
  * @returns {Node | null}
77
78
  */
78
79
  export function first_child(node, is_text) {
79
- if (!hydrating) {
80
+ if (!(HYDRATION && hydrating)) {
80
81
  return node.firstChild;
81
82
  }
82
83
  return hydrate_first_child(is_text);
@@ -89,10 +90,13 @@ export function first_child(node, is_text) {
89
90
  * hydration we descend the cursor into `parent` (mirroring first_child) so the
90
91
  * first appended component adopts the server's first child of `parent`.
91
92
  * @param {Node} parent
93
+ * @param {boolean} [tail] the sentinel stands for the tail of `parent`: what
94
+ * it anchors is the last thing the framework appends there, so it stays the
95
+ * right insertion point for its whole life (see the `if` runtime)
92
96
  * @returns {AppendIntoAnchor}
93
97
  */
94
- export function append_into(parent) {
95
- if (hydrating) {
98
+ export function append_into(parent, tail) {
99
+ if (HYDRATION && hydrating) {
96
100
  var child = get_first_child(/** @type {Node} */ (hydrate_node));
97
101
 
98
102
  if (child === null) {
@@ -102,7 +106,7 @@ export function append_into(parent) {
102
106
  set_hydrate_node(child);
103
107
  }
104
108
 
105
- return { parent, into: true };
109
+ return { parent, into: true, tail: tail === true };
106
110
  }
107
111
 
108
112
  /**
@@ -121,7 +125,7 @@ export function resolve_anchor(node) {
121
125
  if (/** @type {AppendIntoAnchor} */ (node).into !== true) {
122
126
  return /** @type {Node} */ (node);
123
127
  }
124
- if (hydrating) {
128
+ if (HYDRATION && hydrating) {
125
129
  return /** @type {Node} */ (hydrate_node);
126
130
  }
127
131
  return /** @type {AppendIntoAnchor} */ (node).parent.appendChild(create_text());
@@ -136,7 +140,7 @@ export function resolve_anchor(node) {
136
140
  export function first_child_frag(node, is_text) {
137
141
  // During hydration, for fragment templates, hydrate_node is already
138
142
  // pointing to the first element of the fragment. Don't descend into it.
139
- if (hydrating) {
143
+ if (HYDRATION && hydrating) {
140
144
  return hydrate_node;
141
145
  }
142
146
  var child = /** @type {Text} */ (first_child(node, is_text));
@@ -163,7 +167,7 @@ export function get_next_sibling(node) {
163
167
  * @returns {Node | null}
164
168
  */
165
169
  export function next_sibling(node, is_text) {
166
- if (!hydrating) {
170
+ if (!(HYDRATION && hydrating)) {
167
171
  return node.nextSibling;
168
172
  }
169
173
  return hydrate_next_sibling(is_text);
@@ -6,6 +6,7 @@ import { handle_root_events, release_root_events } from './events.js';
6
6
  import { active_block } from './runtime.js';
7
7
  import { hydrating, hydrate_node, set_hydration, set_hydrating } from './hydration.js';
8
8
  import { is_tsrx_element, tsrx_element } from '../../element.js';
9
+ import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
9
10
 
10
11
  /**
11
12
  * @typedef {(anchor: AppendIntoAnchor, block: Block) => void} PortalRender
@@ -67,7 +68,7 @@ function run_portal(s) {
67
68
  end: null,
68
69
  r: s.r,
69
70
  c: next_children,
70
- a: { parent: next_target, into: true },
71
+ a: { parent: next_target, into: true, tail: false },
71
72
  b: /** @type {Block} */ (s.p),
72
73
  });
73
74
 
@@ -126,7 +127,7 @@ function create_portal(get_target, render_children, get_children) {
126
127
  p: null,
127
128
  };
128
129
 
129
- if (!hydrating) {
130
+ if (!(HYDRATION && hydrating)) {
130
131
  render(run_portal, state);
131
132
  return;
132
133
  }