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.
- package/CHANGELOG.md +164 -0
- package/package.json +10 -4
- package/src/constants.js +6 -0
- package/src/jsx-runtime.d.ts +2 -1
- package/src/runtime/array.js +15 -9
- package/src/runtime/index-client.js +25 -7
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/attributes.js +439 -0
- package/src/runtime/internal/client/blocks.js +20 -20
- package/src/runtime/internal/client/component.js +2 -5
- package/src/runtime/internal/client/composite.js +295 -95
- package/src/runtime/internal/client/constants.js +14 -6
- package/src/runtime/internal/client/context.js +3 -2
- package/src/runtime/internal/client/css.js +11 -26
- package/src/runtime/internal/client/errors.js +188 -0
- package/src/runtime/internal/client/events.js +79 -34
- package/src/runtime/internal/client/expression.js +25 -120
- package/src/runtime/internal/client/for.js +113 -262
- package/src/runtime/internal/client/head.js +4 -3
- package/src/runtime/internal/client/html.js +5 -3
- package/src/runtime/internal/client/hydrate.js +484 -0
- package/src/runtime/internal/client/hydration-enabled.js +7 -0
- package/src/runtime/internal/client/hydration.js +16 -81
- package/src/runtime/internal/client/if.js +69 -10
- package/src/runtime/internal/client/index.js +18 -10
- package/src/runtime/internal/client/operations.js +11 -7
- package/src/runtime/internal/client/portal.js +3 -2
- package/src/runtime/internal/client/render.js +42 -325
- package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
- package/src/runtime/internal/client/runtime.js +157 -371
- package/src/runtime/internal/client/template-ns.js +88 -0
- package/src/runtime/internal/client/template.js +118 -139
- package/src/runtime/internal/client/track-async.js +356 -0
- package/src/runtime/internal/client/try.js +133 -319
- package/src/runtime/internal/client/types.d.ts +48 -24
- package/src/runtime/internal/server/index.js +31 -29
- package/src/runtime/internal/server/prerender.js +27 -0
- package/src/server/index.js +1 -0
- package/src/utils/class-name.js +28 -0
- package/tests/client/basic/basic.errors.test.tsrx +3 -3
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
- package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
- package/tests/client/composite/composite.dynamic-components.test.tsrx +40 -0
- package/tests/client/composite/composite.props.test.tsrx +10 -10
- package/tests/client/css/scoped-styles.test.tsrx +3 -1
- package/tests/client/derived-release.test.tsrx +3 -3
- package/tests/client/for-item.test.tsrx +39 -0
- package/tests/client/for-selector.test.tsrx +95 -0
- package/tests/client/svg.test.tsrx +273 -1
- package/tests/hydration/compiled/client/basic.js +88 -87
- package/tests/hydration/compiled/client/composite.js +15 -6
- package/tests/hydration/compiled/client/events.js +40 -48
- package/tests/hydration/compiled/client/for.js +191 -199
- package/tests/hydration/compiled/client/fragment-cursor.js +633 -334
- package/tests/hydration/compiled/client/head.js +22 -22
- package/tests/hydration/compiled/client/hmr.js +14 -5
- package/tests/hydration/compiled/client/html-in-template.js +5 -5
- package/tests/hydration/compiled/client/html.js +195 -177
- package/tests/hydration/compiled/client/if-children.js +136 -63
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +63 -43
- package/tests/hydration/compiled/client/if.js +78 -30
- package/tests/hydration/compiled/client/mixed-control-flow.js +90 -72
- package/tests/hydration/compiled/client/nested-control-flow.js +266 -307
- package/tests/hydration/compiled/client/portal.js +20 -11
- package/tests/hydration/compiled/client/reactivity.js +29 -29
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/streaming.js +33 -35
- package/tests/hydration/compiled/client/switch.js +25 -25
- package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
- package/tests/hydration/compiled/client/try.js +15 -15
- package/tests/hydration/compiled/client/typed-text.js +8 -7
- package/tests/hydration/compiled/server/basic.js +6 -6
- package/tests/hydration/compiled/server/events.js +8 -8
- package/tests/hydration/compiled/server/for.js +22 -22
- package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
- package/tests/hydration/compiled/server/head.js +6 -6
- package/tests/hydration/compiled/server/hmr.js +1 -1
- package/tests/hydration/compiled/server/html.js +1 -1
- package/tests/hydration/compiled/server/if-children.js +9 -9
- package/tests/hydration/compiled/server/if.js +5 -5
- package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
- package/tests/hydration/compiled/server/portal.js +1 -1
- package/tests/hydration/compiled/server/reactivity.js +9 -9
- package/tests/hydration/compiled/server/streaming.js +9 -9
- package/tests/hydration/compiled/server/switch.js +4 -4
- package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
- package/tests/hydration/compiled/server/try.js +4 -4
- package/tests/hydration/compiled/server/typed-text.js +1 -1
- package/tests/hydration/components/fragment-cursor.tsrx +60 -0
- package/tests/hydration/components/track-async-serialization.tsrx +2 -2
- package/tests/hydration/fragment-cursor.test.js +34 -1
- package/tests/hydration/track-async-serialization.test.js +1 -1
- package/tests/server/basic.components.test.tsrx +3 -3
- package/tests/server/track-async-serialization.test.tsrx +6 -6
- package/tests/utils/tracked-types.test.js +3 -3
- package/types/index.d.ts +8 -8
- package/types/server.d.ts +17 -0
|
@@ -1,123 +1,323 @@
|
|
|
1
|
-
/** @import { Block } from '#client' */
|
|
1
|
+
/** @import { AppendIntoAnchor, Block } from '#client' */
|
|
2
|
+
/** @import { SpreadState } from './attributes.js' */
|
|
3
|
+
import { component_invalid } from './errors.js';
|
|
2
4
|
|
|
3
|
-
import { branch, destroy_block,
|
|
4
|
-
import {
|
|
5
|
+
import { branch, destroy_block, destroy_block_children, render } from './blocks.js';
|
|
6
|
+
import { release_spread, spread } from './attributes.js';
|
|
7
|
+
import { COMPOSITE_BLOCK, DEFAULT_NAMESPACE, NAMESPACE_URI, UNINITIALIZED } from './constants.js';
|
|
5
8
|
import { hydrate_node, hydrate_next, hydrating, set_hydrate_node } from './hydration.js';
|
|
6
9
|
import { first_child } from './operations.js';
|
|
7
|
-
import { active_block, active_namespace, get,
|
|
10
|
+
import { active_block, active_namespace, get, set_ns, set_tracking, untrack } from './runtime.js';
|
|
8
11
|
import { top_element_to_ns } from './utils.js';
|
|
12
|
+
import { push_ns, with_ns } from './template-ns.js';
|
|
13
|
+
import { append } from './template.js';
|
|
9
14
|
import { is_tsrx_element } from '../../element.js';
|
|
10
15
|
import { render_component } from './component.js';
|
|
16
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
19
|
* @typedef {Function | string | null | undefined | false} CompositeTarget
|
|
20
|
+
* The state of a composite block. A tag target is the block's own DOM range
|
|
21
|
+
* (`start`/`end`, the element) and its attributes the block's own spread; a
|
|
22
|
+
* component target renders in a branch, a child of the block.
|
|
23
|
+
* @typedef {{
|
|
24
|
+
* start: Element | null;
|
|
25
|
+
* end: Element | null;
|
|
26
|
+
* g: () => CompositeTarget;
|
|
27
|
+
* a: Node | AppendIntoAnchor;
|
|
28
|
+
* p: () => Record<string, any>;
|
|
29
|
+
* c: CompositeTarget | typeof UNINITIALIZED;
|
|
30
|
+
* s: SpreadState | undefined;
|
|
31
|
+
* }} CompositeState
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {CompositeState} state
|
|
36
|
+
*/
|
|
37
|
+
function run_composite(state) {
|
|
38
|
+
var block = /** @type {Block} */ (active_block);
|
|
39
|
+
// @ts-ignore — get() handles non-tracked values via is_ripple_object() check
|
|
40
|
+
var component = get(state.g());
|
|
41
|
+
var current = state.c;
|
|
42
|
+
var old = state.start;
|
|
43
|
+
|
|
44
|
+
if (component === current && typeof component === 'string') {
|
|
45
|
+
// The same tag keeps its element: only the attributes follow the props.
|
|
46
|
+
state.s = spread(/** @type {Element} */ (old), state.p(), state.s);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (current !== UNINITIALIZED) {
|
|
51
|
+
// The previous target's blocks: the children rendered into the element,
|
|
52
|
+
// whose DOM goes with it, or a component's branch, which removes its own.
|
|
53
|
+
destroy_block_children(block, old === null);
|
|
54
|
+
state.s = undefined;
|
|
55
|
+
}
|
|
56
|
+
state.c = component;
|
|
57
|
+
|
|
58
|
+
if (typeof component === 'function') {
|
|
59
|
+
if (old !== null) {
|
|
60
|
+
old.remove();
|
|
61
|
+
state.start = state.end = null;
|
|
62
|
+
}
|
|
63
|
+
var anchor = state.a;
|
|
64
|
+
var get_props = state.p;
|
|
65
|
+
// Handle as regular component
|
|
66
|
+
branch(() => {
|
|
67
|
+
var props = untrack(get_props);
|
|
68
|
+
render_component(component, /** @type {Node} */ (anchor), props);
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (is_tsrx_element(component)) {
|
|
73
|
+
component_invalid(true);
|
|
74
|
+
}
|
|
75
|
+
if (component == null) {
|
|
76
|
+
if (old !== null) {
|
|
77
|
+
old.remove();
|
|
78
|
+
state.start = state.end = null;
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// A tag: the element is created in the namespace the tag resolves to.
|
|
84
|
+
var ns = top_element_to_ns(component, active_namespace);
|
|
85
|
+
/** @type {Element} */
|
|
86
|
+
var element;
|
|
87
|
+
if (HYDRATION && hydrating) {
|
|
88
|
+
// Claim the SSR-rendered element instead of creating a new one.
|
|
89
|
+
element = /** @type {Element} */ (hydrate_node);
|
|
90
|
+
} else {
|
|
91
|
+
element =
|
|
92
|
+
ns !== DEFAULT_NAMESPACE
|
|
93
|
+
? document.createElementNS(
|
|
94
|
+
NAMESPACE_URI[ns],
|
|
95
|
+
/** @type {keyof HTMLElementTagNameMap} */ (component),
|
|
96
|
+
)
|
|
97
|
+
: document.createElement(/** @type {keyof HTMLElementTagNameMap} */ (component));
|
|
98
|
+
if (old !== null) {
|
|
99
|
+
// A tag change takes the previous element's place.
|
|
100
|
+
old.before(element);
|
|
101
|
+
old.remove();
|
|
102
|
+
} else {
|
|
103
|
+
append(/** @type {ChildNode | AppendIntoAnchor} */ (state.a), element);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
state.start = state.end = element;
|
|
107
|
+
|
|
108
|
+
// The spread reads the props once, tracked: a props change re-runs the
|
|
109
|
+
// block, which diffs the attributes above. The children come from that
|
|
110
|
+
// same read.
|
|
111
|
+
var spread_state = (state.s = spread(element, state.p(), undefined));
|
|
112
|
+
var props = /** @type {Record<string, any>} */ (spread_state.n);
|
|
113
|
+
if (is_tsrx_element(props.children)) {
|
|
114
|
+
/** @type {Node} */
|
|
115
|
+
var child_anchor;
|
|
116
|
+
if (HYDRATION && hydrating) {
|
|
117
|
+
// The server renders children directly inside the element with no
|
|
118
|
+
// extra markers; descend the cursor so they claim those nodes.
|
|
119
|
+
child_anchor = /** @type {Node} */ (first_child(element));
|
|
120
|
+
} else {
|
|
121
|
+
child_anchor = document.createComment('');
|
|
122
|
+
element.appendChild(child_anchor);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// The children render untracked, as a branch renders its content. The
|
|
126
|
+
// children of a `foreignObject` are HTML whatever namespace the element
|
|
127
|
+
// itself takes.
|
|
128
|
+
var child_ns = component === 'foreignObject' ? DEFAULT_NAMESPACE : ns;
|
|
129
|
+
set_tracking(false);
|
|
130
|
+
if (child_ns !== active_namespace) {
|
|
131
|
+
with_ns(child_ns, () => props.children.render(child_anchor, block, props.children.p));
|
|
132
|
+
} else {
|
|
133
|
+
props.children.render(child_anchor, block, props.children.p);
|
|
134
|
+
}
|
|
135
|
+
set_tracking(true);
|
|
136
|
+
|
|
137
|
+
if (HYDRATION && hydrating) {
|
|
138
|
+
// Reset the cursor to the claimed element so sibling traversal
|
|
139
|
+
// continues after it.
|
|
140
|
+
set_hydrate_node(element);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Renders a dynamic element or component (`<{expr}>`): the block re-runs
|
|
147
|
+
* when the expression or the props change. A tag that stays the same keeps
|
|
148
|
+
* its element and diffs the attributes; a new tag or component replaces the
|
|
149
|
+
* content in place.
|
|
14
150
|
* @param {() => CompositeTarget} get_component
|
|
15
|
-
* @param {Node} node
|
|
151
|
+
* @param {Node | AppendIntoAnchor} node
|
|
16
152
|
* @param {() => Record<string, any>} get_props the props literal of the call
|
|
17
153
|
* site: read once per rendered component (props are plain values), and
|
|
18
154
|
* re-read as element attributes when the target is a tag
|
|
155
|
+
* @param {keyof typeof NAMESPACE_URI} [namespace] the namespace of the
|
|
156
|
+
* template the call site sits in, when it is not HTML
|
|
19
157
|
* @returns {void}
|
|
20
158
|
*/
|
|
21
|
-
export function composite(get_component, node, get_props) {
|
|
22
|
-
if (hydrating) {
|
|
159
|
+
export function composite(get_component, node, get_props, namespace) {
|
|
160
|
+
if (HYDRATION && hydrating) {
|
|
23
161
|
// During hydration, `node` may already point at the first real SSR node
|
|
24
162
|
// (e.g. layout children). Only skip forward when we are on an empty
|
|
25
163
|
// comment anchor from a client template placeholder.
|
|
26
|
-
if (node.nodeType === 8 && /** @type {Comment} */ (node).data === '') {
|
|
164
|
+
if (/** @type {Node} */ (node).nodeType === 8 && /** @type {Comment} */ (node).data === '') {
|
|
27
165
|
hydrate_next();
|
|
28
166
|
}
|
|
29
167
|
}
|
|
30
168
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
169
|
+
/** @type {CompositeState} */
|
|
170
|
+
var state = {
|
|
171
|
+
start: null,
|
|
172
|
+
end: null,
|
|
173
|
+
g: get_component,
|
|
174
|
+
a: node,
|
|
175
|
+
p: get_props,
|
|
176
|
+
c: UNINITIALIZED,
|
|
177
|
+
s: undefined,
|
|
178
|
+
};
|
|
179
|
+
if (namespace === undefined) {
|
|
180
|
+
render(run_composite, state, COMPOSITE_BLOCK);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
var previous = push_ns(namespace);
|
|
184
|
+
try {
|
|
185
|
+
render(run_composite, state, COMPOSITE_BLOCK);
|
|
186
|
+
} finally {
|
|
187
|
+
set_ns(previous);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
34
190
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
191
|
+
/**
|
|
192
|
+
* The state of a dynamic element the enclosing render function drives (see
|
|
193
|
+
* `dynamic`): the element rendered for a tag, or the branch rendered for a
|
|
194
|
+
* component, and the tag or component itself.
|
|
195
|
+
* @typedef {{
|
|
196
|
+
* e: Element | null;
|
|
197
|
+
* b: Block | null;
|
|
198
|
+
* t: CompositeTarget | typeof UNINITIALIZED;
|
|
199
|
+
* s: SpreadState | undefined;
|
|
200
|
+
* g: (() => CompositeTarget) | null;
|
|
201
|
+
* p: (() => Record<string, any>) | null;
|
|
202
|
+
* }} DynamicState
|
|
203
|
+
*/
|
|
39
204
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
205
|
+
/**
|
|
206
|
+
* A dynamic element without children, applied from the render function of
|
|
207
|
+
* the content it sits in instead of a block of its own: `<{tag} {...attrs} />`
|
|
208
|
+
* compiles to `__prev.x = _$_.dynamic(__prev.x, anchor, tag, props)`, so the
|
|
209
|
+
* tag and the props are read by that render function, and a run whose tag is
|
|
210
|
+
* unchanged only diffs the attributes. The element sits in the enclosing
|
|
211
|
+
* template's range, which owns it. A component target is handed to a
|
|
212
|
+
* composite block of its own (in a branch the render function keeps), which
|
|
213
|
+
* reads the tag and the props through the thunks kept since creation and so
|
|
214
|
+
* remounts the component with fresh props whenever the tag expression
|
|
215
|
+
* re-evaluates, exactly as `<{expr}>` did before; from then on the slot is
|
|
216
|
+
* null and the calls are no-ops.
|
|
217
|
+
* @param {DynamicState | null | undefined} state null once a composite block
|
|
218
|
+
* owns the content (a component target, or the hydration claim, see
|
|
219
|
+
* `dynamic_init`)
|
|
220
|
+
* @param {Node | AppendIntoAnchor} anchor
|
|
221
|
+
* @param {CompositeTarget} tag
|
|
222
|
+
* @param {Record<string, any> | null | undefined} props
|
|
223
|
+
* @param {keyof typeof NAMESPACE_URI} [namespace] the namespace of the
|
|
224
|
+
* template the call site sits in, when it is not HTML
|
|
225
|
+
* @returns {DynamicState | null}
|
|
226
|
+
*/
|
|
227
|
+
export function dynamic(state, anchor, tag, props, namespace) {
|
|
228
|
+
if (state === null) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
// @ts-ignore — get() handles non-tracked values via is_ripple_object() check
|
|
232
|
+
tag = get(tag);
|
|
233
|
+
/** @type {DynamicState} */
|
|
234
|
+
var s;
|
|
235
|
+
if (state === undefined) {
|
|
236
|
+
s = { e: null, b: null, t: UNINITIALIZED, s: undefined, g: null, p: null };
|
|
237
|
+
} else {
|
|
238
|
+
s = state;
|
|
239
|
+
if (tag === s.t) {
|
|
240
|
+
if (s.e !== null) {
|
|
241
|
+
s.s = spread(s.e, props, s.s);
|
|
43
242
|
}
|
|
243
|
+
return s;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
44
246
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
/** @type {Node} */
|
|
88
|
-
var child_anchor;
|
|
89
|
-
if (hydrating) {
|
|
90
|
-
// The server renders children directly inside the element with no
|
|
91
|
-
// extra markers; descend the cursor so they claim those nodes.
|
|
92
|
-
child_anchor = /** @type {Node} */ (first_child(element));
|
|
93
|
-
} else {
|
|
94
|
-
child_anchor = document.createComment('');
|
|
95
|
-
element.appendChild(child_anchor);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (ns !== DEFAULT_NAMESPACE) {
|
|
99
|
-
with_ns(ns, () => props.children.render(child_anchor, block, props.children.p));
|
|
100
|
-
} else {
|
|
101
|
-
props.children.render(child_anchor, block, props.children.p);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (hydrating) {
|
|
105
|
-
// Reset the cursor to the claimed element so sibling traversal
|
|
106
|
-
// continues after it.
|
|
107
|
-
set_hydrate_node(element);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
if (ns !== active_namespace) {
|
|
113
|
-
// support top-level dynamic element svg/math tags
|
|
114
|
-
b = branch(() => with_ns(ns, run));
|
|
115
|
-
} else {
|
|
116
|
-
b = branch(run);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
null,
|
|
121
|
-
COMPOSITE_BLOCK,
|
|
247
|
+
var old = s.e;
|
|
248
|
+
if (s.b !== null) {
|
|
249
|
+
destroy_block(s.b);
|
|
250
|
+
s.b = null;
|
|
251
|
+
}
|
|
252
|
+
// The previous element's refs and listeners go with it.
|
|
253
|
+
release_spread(s.s);
|
|
254
|
+
s.t = tag;
|
|
255
|
+
s.s = undefined;
|
|
256
|
+
|
|
257
|
+
if (typeof tag === 'function') {
|
|
258
|
+
if (old !== null) {
|
|
259
|
+
old.remove();
|
|
260
|
+
s.e = null;
|
|
261
|
+
}
|
|
262
|
+
const get_component = s.g;
|
|
263
|
+
const get_props = s.p;
|
|
264
|
+
if (get_component !== null && get_props !== null) {
|
|
265
|
+
branch(() => composite(get_component, anchor, get_props, namespace));
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
// No thunks (a call site compiled without `dynamic_init`): the
|
|
269
|
+
// component renders once with these props.
|
|
270
|
+
s.b = branch(() => {
|
|
271
|
+
render_component(tag, /** @type {Node} */ (anchor), props ?? {});
|
|
272
|
+
});
|
|
273
|
+
return s;
|
|
274
|
+
}
|
|
275
|
+
if (is_tsrx_element(tag)) {
|
|
276
|
+
component_invalid(true);
|
|
277
|
+
}
|
|
278
|
+
if (tag == null || tag === false) {
|
|
279
|
+
if (old !== null) {
|
|
280
|
+
old.remove();
|
|
281
|
+
s.e = null;
|
|
282
|
+
}
|
|
283
|
+
return s;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
var ns = top_element_to_ns(
|
|
287
|
+
/** @type {Parameters<typeof top_element_to_ns>[0]} */ (tag),
|
|
288
|
+
namespace === undefined ? active_namespace : namespace,
|
|
122
289
|
);
|
|
290
|
+
var element =
|
|
291
|
+
ns !== DEFAULT_NAMESPACE
|
|
292
|
+
? document.createElementNS(NAMESPACE_URI[ns], /** @type {string} */ (tag))
|
|
293
|
+
: document.createElement(/** @type {string} */ (tag));
|
|
294
|
+
if (old !== null) {
|
|
295
|
+
old.before(element);
|
|
296
|
+
old.remove();
|
|
297
|
+
} else {
|
|
298
|
+
append(/** @type {ChildNode | AppendIntoAnchor} */ (anchor), element);
|
|
299
|
+
}
|
|
300
|
+
s.e = element;
|
|
301
|
+
s.s = spread(element, props, undefined);
|
|
302
|
+
return s;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* The initial state of a `dynamic` slot: the tag and props thunks a
|
|
307
|
+
* component target is handed over with. While hydrating, the element is
|
|
308
|
+
* rendered here by a composite block of its own, which claims its server
|
|
309
|
+
* nodes in document order and owns the content from then on, so the render
|
|
310
|
+
* function's `dynamic` calls are no-ops (null).
|
|
311
|
+
* @param {Node | AppendIntoAnchor} node
|
|
312
|
+
* @param {() => CompositeTarget} get_component
|
|
313
|
+
* @param {() => Record<string, any>} get_props
|
|
314
|
+
* @param {keyof typeof NAMESPACE_URI} [namespace]
|
|
315
|
+
* @returns {DynamicState | null}
|
|
316
|
+
*/
|
|
317
|
+
export function dynamic_init(node, get_component, get_props, namespace) {
|
|
318
|
+
if (HYDRATION && hydrating) {
|
|
319
|
+
composite(get_component, node, get_props, namespace);
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
return { e: null, b: null, t: UNINITIALIZED, s: undefined, g: get_component, p: get_props };
|
|
123
323
|
}
|
|
@@ -35,11 +35,19 @@ export var CREATES_DERIVEDS = 1 << 25;
|
|
|
35
35
|
* re-runs the body's update function.
|
|
36
36
|
*/
|
|
37
37
|
export var ITEM_BLOCK = 1 << 26;
|
|
38
|
+
/**
|
|
39
|
+
* The namespace a block was created in, so a rerun outside the `with_ns()`
|
|
40
|
+
* call that established it (a scheduled flush) creates its DOM in the same
|
|
41
|
+
* namespace. Neither bit set means HTML.
|
|
42
|
+
*/
|
|
43
|
+
export var SVG_BLOCK = 1 << 27;
|
|
44
|
+
export var MATHML_BLOCK = 1 << 28;
|
|
45
|
+
export var NAMESPACE_BLOCK = SVG_BLOCK | MATHML_BLOCK;
|
|
38
46
|
|
|
39
47
|
export var CONTROL_FLOW_BLOCK = FOR_BLOCK | IF_BLOCK | SWITCH_BLOCK | TRY_BLOCK | COMPOSITE_BLOCK;
|
|
40
48
|
|
|
41
49
|
/** @type {unique symbol} */
|
|
42
|
-
export const UNINITIALIZED = Symbol(
|
|
50
|
+
export const UNINITIALIZED = Symbol();
|
|
43
51
|
/** @type {unique symbol} */
|
|
44
52
|
export const TRACKED_ARRAY = Symbol();
|
|
45
53
|
/** @type {unique symbol} */
|
|
@@ -58,13 +66,13 @@ export const NAMESPACE_URI = {
|
|
|
58
66
|
mathml: 'http://www.w3.org/1998/Math/MathML',
|
|
59
67
|
};
|
|
60
68
|
/** @type {unique symbol} */
|
|
61
|
-
export const TRACKED_UPDATED = Symbol(
|
|
69
|
+
export const TRACKED_UPDATED = Symbol();
|
|
62
70
|
/** @type {unique symbol} */
|
|
63
|
-
export const SUSPENSE_PENDING = Symbol(
|
|
71
|
+
export const SUSPENSE_PENDING = Symbol();
|
|
64
72
|
/** @type {unique symbol} */
|
|
65
|
-
export const SUSPENSE_REJECTED = Symbol(
|
|
73
|
+
export const SUSPENSE_REJECTED = Symbol();
|
|
66
74
|
/** @type {unique symbol} */
|
|
67
|
-
export const ASYNC_DERIVED_READ_THROWN = Symbol(
|
|
75
|
+
export const ASYNC_DERIVED_READ_THROWN = Symbol();
|
|
68
76
|
|
|
69
77
|
/** The hoisted render function a module-level component carries (see `render_component`). */
|
|
70
|
-
export const RENDER_ENTRY = Symbol(
|
|
78
|
+
export const RENDER_ENTRY = Symbol();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** @import { Component, ContextEntry } from '#client' */
|
|
2
|
+
import { context_orphan } from './errors.js';
|
|
2
3
|
|
|
3
4
|
import { active_component } from './runtime.js';
|
|
4
5
|
|
|
@@ -18,7 +19,7 @@ export class Context {
|
|
|
18
19
|
const component = active_component;
|
|
19
20
|
|
|
20
21
|
if (component === null) {
|
|
21
|
-
|
|
22
|
+
context_orphan(false);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// A component inherits its parent's chain of set entries when it is
|
|
@@ -45,7 +46,7 @@ export class Context {
|
|
|
45
46
|
const component = active_component;
|
|
46
47
|
|
|
47
48
|
if (component === null) {
|
|
48
|
-
|
|
49
|
+
context_orphan(true);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
component.c = { k: this, v: value, n: component.c };
|
|
@@ -24,49 +24,34 @@ function remove() {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Calls back once every stylesheet link has loaded (or failed).
|
|
28
|
+
* @param {() => void} callback
|
|
28
29
|
* @returns {void}
|
|
29
30
|
*/
|
|
30
31
|
function remove_when_css_loaded(callback) {
|
|
31
|
-
/** @type {HTMLLinkElement
|
|
32
|
-
|
|
33
|
-
/** @type {NodeListOf<HTMLLinkElement>} */ (
|
|
34
|
-
document.querySelectorAll('link[rel="stylesheet"]')
|
|
35
|
-
),
|
|
32
|
+
var links = /** @type {NodeListOf<HTMLLinkElement>} */ (
|
|
33
|
+
document.querySelectorAll('link[rel="stylesheet"]')
|
|
36
34
|
);
|
|
37
|
-
|
|
35
|
+
var remaining = links.length;
|
|
38
36
|
|
|
39
37
|
if (remaining === 0) {
|
|
40
38
|
callback();
|
|
41
39
|
return;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
remaining
|
|
46
|
-
if (remaining === 0) {
|
|
47
|
-
// clean up all listeners
|
|
48
|
-
links.forEach((link) => {
|
|
49
|
-
link.removeEventListener('load', onLoad);
|
|
50
|
-
link.removeEventListener('error', onError);
|
|
51
|
-
});
|
|
42
|
+
var done = () => {
|
|
43
|
+
if (--remaining === 0) {
|
|
52
44
|
callback();
|
|
53
45
|
}
|
|
54
46
|
};
|
|
55
47
|
|
|
56
|
-
|
|
57
|
-
done();
|
|
58
|
-
}
|
|
59
|
-
function onError() {
|
|
60
|
-
done();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
links.forEach((link) => {
|
|
48
|
+
for (var link of links) {
|
|
64
49
|
if (link.sheet) {
|
|
65
50
|
// already loaded (possibly cached)
|
|
66
51
|
done();
|
|
67
52
|
} else {
|
|
68
|
-
link.addEventListener('load',
|
|
69
|
-
link.addEventListener('error',
|
|
53
|
+
link.addEventListener('load', done, { once: true });
|
|
54
|
+
link.addEventListener('error', done, { once: true });
|
|
70
55
|
}
|
|
71
|
-
}
|
|
56
|
+
}
|
|
72
57
|
}
|