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.
- package/CHANGELOG.md +107 -0
- package/package.json +9 -3
- 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 +313 -0
- package/src/runtime/internal/client/blocks.js +4 -14
- package/src/runtime/internal/client/component.js +2 -5
- package/src/runtime/internal/client/composite.js +14 -6
- package/src/runtime/internal/client/constants.js +6 -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 +21 -116
- package/src/runtime/internal/client/for.js +108 -232
- 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 +13 -9
- package/src/runtime/internal/client/index.js +14 -6
- 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 +87 -363
- package/src/runtime/internal/client/template-ns.js +47 -0
- package/src/runtime/internal/client/template.js +63 -140
- 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.props.test.tsrx +10 -10
- 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/hydration/compiled/client/basic.js +87 -87
- package/tests/hydration/compiled/client/composite.js +5 -5
- package/tests/hydration/compiled/client/events.js +40 -48
- package/tests/hydration/compiled/client/for.js +162 -181
- package/tests/hydration/compiled/client/fragment-cursor.js +521 -289
- package/tests/hydration/compiled/client/head.js +22 -22
- package/tests/hydration/compiled/client/hmr.js +4 -4
- package/tests/hydration/compiled/client/html-in-template.js +5 -5
- package/tests/hydration/compiled/client/html.js +152 -162
- package/tests/hydration/compiled/client/if-children.js +58 -53
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +39 -39
- package/tests/hydration/compiled/client/if.js +26 -26
- package/tests/hydration/compiled/client/mixed-control-flow.js +56 -68
- package/tests/hydration/compiled/client/nested-control-flow.js +139 -271
- package/tests/hydration/compiled/client/portal.js +10 -10
- 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 +7 -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
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
} from './constants.js';
|
|
19
19
|
import { hydrating } from './hydration.js';
|
|
20
20
|
import { next_sibling } from './operations.js';
|
|
21
|
-
import { apply_element_spread } from './render.js';
|
|
22
21
|
import { is_array } from '@tsrx/core/runtime/language-helpers';
|
|
23
22
|
import {
|
|
24
23
|
active_block,
|
|
@@ -34,15 +33,15 @@ import {
|
|
|
34
33
|
untrack,
|
|
35
34
|
} from './runtime.js';
|
|
36
35
|
import { is_ripple_object } from './utils.js';
|
|
36
|
+
import { effect_orphan } from './errors.js';
|
|
37
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* @param {Function} fn
|
|
40
41
|
*/
|
|
41
42
|
export function user_effect(fn) {
|
|
42
43
|
if (active_block === null) {
|
|
43
|
-
|
|
44
|
-
'effect() must be called within an active context, such as a component or effect',
|
|
45
|
-
);
|
|
44
|
+
effect_orphan();
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
var component = active_component;
|
|
@@ -85,15 +84,6 @@ export function render(fn, state, flags = 0) {
|
|
|
85
84
|
return block;
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
/**
|
|
89
|
-
* @param {any} element
|
|
90
|
-
* @param {any} fn
|
|
91
|
-
* @param {number} [flags]
|
|
92
|
-
*/
|
|
93
|
-
export function render_spread(element, fn, flags = 0) {
|
|
94
|
-
return block(RENDER_BLOCK | flags, apply_element_spread(element, fn));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
87
|
/**
|
|
98
88
|
* @param {Function} fn
|
|
99
89
|
* @param {number} [flags]
|
|
@@ -117,7 +107,7 @@ function noop() {}
|
|
|
117
107
|
* @param {Node} anchor
|
|
118
108
|
*/
|
|
119
109
|
export function own_anchor(node, anchor) {
|
|
120
|
-
if (anchor === node || hydrating) return;
|
|
110
|
+
if (anchor === node || (HYDRATION && hydrating)) return;
|
|
121
111
|
branch(noop, 0, { start: anchor, end: anchor });
|
|
122
112
|
}
|
|
123
113
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { is_tsrx_element } from '../../element.js';
|
|
4
4
|
import { render_value } from './expression.js';
|
|
5
5
|
import { active_block } from './runtime.js';
|
|
6
|
+
import { component_invalid } from './errors.js';
|
|
6
7
|
|
|
7
8
|
export { render_component } from './runtime.js';
|
|
8
9
|
|
|
@@ -21,9 +22,5 @@ export function render_tsrx_element(value, anchor, block = active_block) {
|
|
|
21
22
|
* @returns {never}
|
|
22
23
|
*/
|
|
23
24
|
export function throw_invalid_component_type(value) {
|
|
24
|
-
|
|
25
|
-
throw new TypeError('Invalid component type: received a TSRXElement value.');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
throw new TypeError('Invalid component type: expected a component function.');
|
|
25
|
+
component_invalid(is_tsrx_element(value));
|
|
29
26
|
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/** @import { Block } from '#client' */
|
|
2
|
+
import { component_invalid } from './errors.js';
|
|
2
3
|
|
|
3
|
-
import { branch, destroy_block, render
|
|
4
|
+
import { branch, destroy_block, render } from './blocks.js';
|
|
5
|
+
import { render_spread } from './attributes.js';
|
|
4
6
|
import { COMPOSITE_BLOCK, DEFAULT_NAMESPACE, NAMESPACE_URI } from './constants.js';
|
|
5
7
|
import { hydrate_node, hydrate_next, hydrating, set_hydrate_node } from './hydration.js';
|
|
6
8
|
import { first_child } from './operations.js';
|
|
7
9
|
import { active_block, active_namespace, get, untrack, with_ns } from './runtime.js';
|
|
8
10
|
import { top_element_to_ns } from './utils.js';
|
|
11
|
+
import { install_ns_templates } from './template-ns.js';
|
|
9
12
|
import { is_tsrx_element } from '../../element.js';
|
|
10
13
|
import { render_component } from './component.js';
|
|
14
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* @typedef {Function | string | null | undefined | false} CompositeTarget
|
|
@@ -19,7 +23,7 @@ import { render_component } from './component.js';
|
|
|
19
23
|
* @returns {void}
|
|
20
24
|
*/
|
|
21
25
|
export function composite(get_component, node, get_props) {
|
|
22
|
-
if (hydrating) {
|
|
26
|
+
if (HYDRATION && hydrating) {
|
|
23
27
|
// During hydration, `node` may already point at the first real SSR node
|
|
24
28
|
// (e.g. layout children). Only skip forward when we are on an empty
|
|
25
29
|
// comment anchor from a client template placeholder.
|
|
@@ -49,16 +53,20 @@ export function composite(get_component, node, get_props) {
|
|
|
49
53
|
render_component(component, anchor, props);
|
|
50
54
|
});
|
|
51
55
|
} else if (is_tsrx_element(component)) {
|
|
52
|
-
|
|
56
|
+
component_invalid(true);
|
|
53
57
|
} else if (component != null) {
|
|
54
58
|
// Custom element - only create if component is not null/undefined
|
|
55
59
|
const ns = top_element_to_ns(component, active_namespace);
|
|
60
|
+
if (ns !== DEFAULT_NAMESPACE) {
|
|
61
|
+
// Templates cloned inside the element parse in its namespace.
|
|
62
|
+
install_ns_templates();
|
|
63
|
+
}
|
|
56
64
|
var run = () => {
|
|
57
65
|
var block = /** @type {Block} */ (active_block);
|
|
58
66
|
|
|
59
67
|
/** @type {Element} */
|
|
60
68
|
var element;
|
|
61
|
-
if (hydrating) {
|
|
69
|
+
if (HYDRATION && hydrating) {
|
|
62
70
|
// Claim the SSR-rendered element instead of creating a new one.
|
|
63
71
|
element = /** @type {Element} */ (hydrate_node);
|
|
64
72
|
} else {
|
|
@@ -86,7 +94,7 @@ export function composite(get_component, node, get_props) {
|
|
|
86
94
|
if (is_tsrx_element(props.children)) {
|
|
87
95
|
/** @type {Node} */
|
|
88
96
|
var child_anchor;
|
|
89
|
-
if (hydrating) {
|
|
97
|
+
if (HYDRATION && hydrating) {
|
|
90
98
|
// The server renders children directly inside the element with no
|
|
91
99
|
// extra markers; descend the cursor so they claim those nodes.
|
|
92
100
|
child_anchor = /** @type {Node} */ (first_child(element));
|
|
@@ -101,7 +109,7 @@ export function composite(get_component, node, get_props) {
|
|
|
101
109
|
props.children.render(child_anchor, block, props.children.p);
|
|
102
110
|
}
|
|
103
111
|
|
|
104
|
-
if (hydrating) {
|
|
112
|
+
if (HYDRATION && hydrating) {
|
|
105
113
|
// Reset the cursor to the claimed element so sibling traversal
|
|
106
114
|
// continues after it.
|
|
107
115
|
set_hydrate_node(element);
|
|
@@ -39,7 +39,7 @@ export var ITEM_BLOCK = 1 << 26;
|
|
|
39
39
|
export var CONTROL_FLOW_BLOCK = FOR_BLOCK | IF_BLOCK | SWITCH_BLOCK | TRY_BLOCK | COMPOSITE_BLOCK;
|
|
40
40
|
|
|
41
41
|
/** @type {unique symbol} */
|
|
42
|
-
export const UNINITIALIZED = Symbol(
|
|
42
|
+
export const UNINITIALIZED = Symbol();
|
|
43
43
|
/** @type {unique symbol} */
|
|
44
44
|
export const TRACKED_ARRAY = Symbol();
|
|
45
45
|
/** @type {unique symbol} */
|
|
@@ -58,13 +58,13 @@ export const NAMESPACE_URI = {
|
|
|
58
58
|
mathml: 'http://www.w3.org/1998/Math/MathML',
|
|
59
59
|
};
|
|
60
60
|
/** @type {unique symbol} */
|
|
61
|
-
export const TRACKED_UPDATED = Symbol(
|
|
61
|
+
export const TRACKED_UPDATED = Symbol();
|
|
62
62
|
/** @type {unique symbol} */
|
|
63
|
-
export const SUSPENSE_PENDING = Symbol(
|
|
63
|
+
export const SUSPENSE_PENDING = Symbol();
|
|
64
64
|
/** @type {unique symbol} */
|
|
65
|
-
export const SUSPENSE_REJECTED = Symbol(
|
|
65
|
+
export const SUSPENSE_REJECTED = Symbol();
|
|
66
66
|
/** @type {unique symbol} */
|
|
67
|
-
export const ASYNC_DERIVED_READ_THROWN = Symbol(
|
|
67
|
+
export const ASYNC_DERIVED_READ_THROWN = Symbol();
|
|
68
68
|
|
|
69
69
|
/** The hoisted render function a module-level component carries (see `render_component`). */
|
|
70
|
-
export const RENDER_ENTRY = Symbol(
|
|
70
|
+
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
|
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { DEV } from 'esm-env';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The runtime's errors, one function per error as in Svelte: in development
|
|
5
|
+
* the message is thrown with a link to its reference page; in production only
|
|
6
|
+
* the link is, so the message text never ships. Each page lives at
|
|
7
|
+
* `https://ripple-ts.com/e/<code>`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} code
|
|
12
|
+
* @param {string} message
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
function text(code, message) {
|
|
16
|
+
var link = `https://ripple-ts.com/e/${code}`;
|
|
17
|
+
return DEV ? `${message}\n${link}` : link;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** @returns {never} */
|
|
21
|
+
export function effect_orphan() {
|
|
22
|
+
throw new Error(
|
|
23
|
+
DEV
|
|
24
|
+
? text(
|
|
25
|
+
'effect_orphan',
|
|
26
|
+
'effect() must be called within an active context, such as a component or effect',
|
|
27
|
+
)
|
|
28
|
+
: text('effect_orphan', ''),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** @returns {never} */
|
|
33
|
+
export function track_orphan() {
|
|
34
|
+
throw new TypeError(
|
|
35
|
+
DEV
|
|
36
|
+
? text('track_orphan', 'track() requires a valid component context')
|
|
37
|
+
: text('track_orphan', ''),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** @returns {never} */
|
|
42
|
+
export function track_async_orphan() {
|
|
43
|
+
throw new TypeError(
|
|
44
|
+
DEV
|
|
45
|
+
? text('track_async_orphan', 'trackAsync() requires a valid component context')
|
|
46
|
+
: text('track_async_orphan', ''),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @returns {never} */
|
|
51
|
+
export function track_async_argument() {
|
|
52
|
+
throw new TypeError(
|
|
53
|
+
DEV
|
|
54
|
+
? text(
|
|
55
|
+
'track_async_argument',
|
|
56
|
+
'trackAsync() only accepts function arguments that return a promise or an object with a promise property',
|
|
57
|
+
)
|
|
58
|
+
: text('track_async_argument', ''),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @returns {never} */
|
|
63
|
+
export function track_async_boundary() {
|
|
64
|
+
throw new Error(
|
|
65
|
+
DEV
|
|
66
|
+
? text('track_async_boundary', 'Missing parent `try { ... } pending { ... }` statement')
|
|
67
|
+
: text('track_async_boundary', ''),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {boolean} in_component the read sits directly in a component body,
|
|
73
|
+
* otherwise in a try/pending/catch body
|
|
74
|
+
* @returns {never}
|
|
75
|
+
*/
|
|
76
|
+
export function pending_read_direct(in_component) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
DEV
|
|
79
|
+
? text(
|
|
80
|
+
'pending_read_direct',
|
|
81
|
+
`Reads on pending tracked values directly inside ${in_component ? 'component' : 'try/pending/catch'} body are prohibited. Use trackPending() test or peek() for safe access or create another derived instead.`,
|
|
82
|
+
)
|
|
83
|
+
: text('pending_read_direct', ''),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @returns {never} */
|
|
88
|
+
export function update_depth_exceeded() {
|
|
89
|
+
throw new Error(
|
|
90
|
+
DEV
|
|
91
|
+
? text(
|
|
92
|
+
'update_depth_exceeded',
|
|
93
|
+
'Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state.',
|
|
94
|
+
)
|
|
95
|
+
: text('update_depth_exceeded', ''),
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** @returns {never} */
|
|
100
|
+
export function set_in_derived() {
|
|
101
|
+
throw new Error(
|
|
102
|
+
DEV
|
|
103
|
+
? text(
|
|
104
|
+
'set_in_derived',
|
|
105
|
+
'Assignments or updates to tracked values are not allowed during computed "track(() => ...)" evaluation',
|
|
106
|
+
)
|
|
107
|
+
: text('set_in_derived', ''),
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {string} [message] a caller's own wording
|
|
113
|
+
* @returns {never}
|
|
114
|
+
*/
|
|
115
|
+
export function scope_orphan(message) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
DEV
|
|
118
|
+
? text('scope_orphan', message ?? 'Cannot access outside of a component context')
|
|
119
|
+
: text('scope_orphan', ''),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {boolean} is_element the value is a TSRX element rather than a
|
|
125
|
+
* component function
|
|
126
|
+
* @returns {never}
|
|
127
|
+
*/
|
|
128
|
+
export function component_invalid(is_element) {
|
|
129
|
+
throw new TypeError(
|
|
130
|
+
DEV
|
|
131
|
+
? text(
|
|
132
|
+
'component_invalid',
|
|
133
|
+
`Invalid component type: ${is_element ? 'received a TSRXElement value.' : 'expected a component function.'}`,
|
|
134
|
+
)
|
|
135
|
+
: text('component_invalid', ''),
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {boolean} is_set `Context#set` rather than `Context#get`
|
|
141
|
+
* @returns {never}
|
|
142
|
+
*/
|
|
143
|
+
export function context_orphan(is_set) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
DEV
|
|
146
|
+
? text(
|
|
147
|
+
'context_orphan',
|
|
148
|
+
`No active component found, cannot ${is_set ? 'set' : 'get'} context`,
|
|
149
|
+
)
|
|
150
|
+
: text('context_orphan', ''),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {string} kind the block whose end marker is missing
|
|
156
|
+
* @returns {never}
|
|
157
|
+
*/
|
|
158
|
+
export function hydration_mismatch(kind) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
DEV
|
|
161
|
+
? text('hydration_mismatch', `Hydration mismatch: expected end marker for ${kind} block`)
|
|
162
|
+
: text('hydration_mismatch', ''),
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** @returns {never} */
|
|
167
|
+
export function hydration_disabled() {
|
|
168
|
+
throw new Error(
|
|
169
|
+
DEV
|
|
170
|
+
? text(
|
|
171
|
+
'hydration_disabled',
|
|
172
|
+
'hydrate() is not available in a client-only build: this build was compiled with `ssr: false`, which leaves the hydration runtime out',
|
|
173
|
+
)
|
|
174
|
+
: text('hydration_disabled', ''),
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** @returns {never} */
|
|
179
|
+
export function root_boundary_disabled() {
|
|
180
|
+
throw new Error(
|
|
181
|
+
DEV
|
|
182
|
+
? text(
|
|
183
|
+
'root_boundary_disabled',
|
|
184
|
+
'A root boundary is not available in this build: it was compiled with `rootBoundary: false`, which leaves the boundary runtime out, so `mount()` and `hydrate()` cannot take `rootBoundary` options',
|
|
185
|
+
)
|
|
186
|
+
: text('root_boundary_disabled', ''),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
@@ -23,7 +23,9 @@ import { render } from './blocks.js';
|
|
|
23
23
|
var all_registered_events = new Set();
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* A root delegation target: its acquire count, the event names it listens
|
|
27
|
+
* for, and the element.
|
|
28
|
+
* @typedef {{ n: number, e: Set<string>, t: Element }} RootTargetRef
|
|
27
29
|
*/
|
|
28
30
|
|
|
29
31
|
/**
|
|
@@ -103,8 +105,6 @@ export function on(element, type, handler, options = {}) {
|
|
|
103
105
|
};
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
var last_propagated_event = null;
|
|
107
|
-
|
|
108
108
|
/**
|
|
109
109
|
* @this {EventTarget}
|
|
110
110
|
* @param {Event} event
|
|
@@ -114,19 +114,19 @@ export function handle_event_propagation(event) {
|
|
|
114
114
|
var handler_element = this;
|
|
115
115
|
var owner_document = /** @type {Node} */ (handler_element).ownerDocument;
|
|
116
116
|
var event_name = event.type;
|
|
117
|
-
|
|
118
|
-
var current_target
|
|
119
|
-
|
|
120
|
-
last_propagated_event = event;
|
|
117
|
+
/** @type {null | Element} */
|
|
118
|
+
var current_target;
|
|
121
119
|
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
var handled_at =
|
|
120
|
+
// __root marks the root that already handled this event: this listener
|
|
121
|
+
// then belongs to a parent of a nested mounted app, and the walk resumes
|
|
122
|
+
// from that root so nothing below it handles the event twice. Only then
|
|
123
|
+
// is the composed path needed; a plain event starts at its target (the
|
|
124
|
+
// composed target when it was retargeted out of a shadow tree).
|
|
125
|
+
var handled_at = event.__root;
|
|
128
126
|
|
|
129
127
|
if (handled_at) {
|
|
128
|
+
var path = event.composedPath?.() || [];
|
|
129
|
+
var path_idx = 0;
|
|
130
130
|
var at_idx = path.indexOf(handled_at);
|
|
131
131
|
if (at_idx !== -1 && (handler_element === document || handler_element === window)) {
|
|
132
132
|
// This is the fallback document listener or a window listener, but the event was already handled
|
|
@@ -151,9 +151,14 @@ export function handle_event_propagation(event) {
|
|
|
151
151
|
if (at_idx <= handler_idx) {
|
|
152
152
|
path_idx = at_idx;
|
|
153
153
|
}
|
|
154
|
+
current_target = /** @type {Element} */ (path[path_idx] || event.target);
|
|
155
|
+
} else {
|
|
156
|
+
current_target = /** @type {Element} */ (event.target);
|
|
157
|
+
if (current_target !== null && /** @type {any} */ (current_target).shadowRoot) {
|
|
158
|
+
current_target = /** @type {Element} */ (event.composedPath?.()[0] || current_target);
|
|
159
|
+
}
|
|
154
160
|
}
|
|
155
161
|
|
|
156
|
-
current_target = /** @type {Element} */ (path[path_idx] || event.target);
|
|
157
162
|
// there can only be one delegated event per element, and we either already handled the current target,
|
|
158
163
|
// or this is the very first target in the chain which has a non-delegated listener, in which case it's safe
|
|
159
164
|
// to handle a possible delegated event on it later (through the root delegation listener for example).
|
|
@@ -181,9 +186,10 @@ export function handle_event_propagation(event) {
|
|
|
181
186
|
*/
|
|
182
187
|
var throw_error;
|
|
183
188
|
/**
|
|
184
|
-
* @type {unknown[]}
|
|
189
|
+
* @type {unknown[] | null}
|
|
185
190
|
*/
|
|
186
|
-
var other_errors =
|
|
191
|
+
var other_errors = null;
|
|
192
|
+
var prop = '__' + event_name;
|
|
187
193
|
|
|
188
194
|
while (current_target !== null) {
|
|
189
195
|
/** @type {null | Element} */
|
|
@@ -194,7 +200,7 @@ export function handle_event_propagation(event) {
|
|
|
194
200
|
null;
|
|
195
201
|
|
|
196
202
|
try {
|
|
197
|
-
var delegated = /** @type {Record<string, any>} */ (current_target)[
|
|
203
|
+
var delegated = /** @type {Record<string, any>} */ (current_target)[prop];
|
|
198
204
|
|
|
199
205
|
if (delegated !== undefined && !(/** @type {any} */ (current_target).disabled)) {
|
|
200
206
|
if (is_array(delegated)) {
|
|
@@ -207,7 +213,7 @@ export function handle_event_propagation(event) {
|
|
|
207
213
|
}
|
|
208
214
|
} catch (error) {
|
|
209
215
|
if (throw_error) {
|
|
210
|
-
other_errors.push(error);
|
|
216
|
+
(other_errors ??= []).push(error);
|
|
211
217
|
} else {
|
|
212
218
|
throw_error = error;
|
|
213
219
|
}
|
|
@@ -219,16 +225,17 @@ export function handle_event_propagation(event) {
|
|
|
219
225
|
}
|
|
220
226
|
|
|
221
227
|
if (throw_error) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
if (other_errors !== null) {
|
|
229
|
+
for (let error of other_errors) {
|
|
230
|
+
// Throw the rest of the errors, one-by-one on a microtask
|
|
231
|
+
queueMicrotask(() => {
|
|
232
|
+
throw error;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
227
235
|
}
|
|
228
236
|
throw throw_error;
|
|
229
237
|
}
|
|
230
238
|
} finally {
|
|
231
|
-
set_active_block(previous_block);
|
|
232
239
|
event.__root = handler_element;
|
|
233
240
|
// @ts-ignore remove proxy on currentTarget
|
|
234
241
|
delete event.currentTarget;
|
|
@@ -412,6 +419,44 @@ export function event(event_name, dom, handler) {
|
|
|
412
419
|
event_listener(event_name, dom, handler);
|
|
413
420
|
}
|
|
414
421
|
|
|
422
|
+
/**
|
|
423
|
+
* Compiler-emitted listener for a static `onEvent={fn}` whose name can never
|
|
424
|
+
* be delegated (`onBlur`, `onScroll`, a `Capture` variant): a native listener
|
|
425
|
+
* on the element, with the handler run outside any reactive context as a
|
|
426
|
+
* delegated handler is. Nothing is returned, as for `event()`. The name is the
|
|
427
|
+
* DOM event name the compiler resolved, so no name table is consulted here.
|
|
428
|
+
* @param {string} name
|
|
429
|
+
* @param {EventTarget} dom
|
|
430
|
+
* @param {EventListener} handler
|
|
431
|
+
* @param {boolean} [capture]
|
|
432
|
+
* @returns {void}
|
|
433
|
+
*/
|
|
434
|
+
export function listen(name, dom, handler, capture) {
|
|
435
|
+
dom.addEventListener(
|
|
436
|
+
name,
|
|
437
|
+
/**
|
|
438
|
+
* @this {EventTarget}
|
|
439
|
+
* @param {Event} event
|
|
440
|
+
*/
|
|
441
|
+
function (event) {
|
|
442
|
+
var previous_block = active_block;
|
|
443
|
+
var previous_reaction = active_reaction;
|
|
444
|
+
var previous_tracking = tracking;
|
|
445
|
+
set_active_block(null);
|
|
446
|
+
set_active_reaction(null);
|
|
447
|
+
set_tracking(false);
|
|
448
|
+
try {
|
|
449
|
+
return handler.call(this, event);
|
|
450
|
+
} finally {
|
|
451
|
+
set_active_block(previous_block);
|
|
452
|
+
set_active_reaction(previous_reaction);
|
|
453
|
+
set_tracking(previous_tracking);
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
capture,
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
415
460
|
/**
|
|
416
461
|
* Attaches a listener and returns its remover; `event()` is the one-shot
|
|
417
462
|
* compiled form of this.
|
|
@@ -496,8 +541,8 @@ export function delegate(events) {
|
|
|
496
541
|
* @param {Iterable<string>} events
|
|
497
542
|
*/
|
|
498
543
|
function register_root_events(ref, events) {
|
|
499
|
-
var registered_events = ref.
|
|
500
|
-
var target = ref.
|
|
544
|
+
var registered_events = ref.e;
|
|
545
|
+
var target = ref.t;
|
|
501
546
|
|
|
502
547
|
for (var event_name of events) {
|
|
503
548
|
if (registered_events.has(event_name)) continue;
|
|
@@ -519,17 +564,17 @@ export function handle_root_events(target) {
|
|
|
519
564
|
// Sibling portals mostly share one target, so check the last ref first.
|
|
520
565
|
/** @type {RootTargetRef | undefined} */
|
|
521
566
|
var ref =
|
|
522
|
-
last_root_ref !== null && last_root_ref.
|
|
567
|
+
last_root_ref !== null && last_root_ref.t === target
|
|
523
568
|
? last_root_ref
|
|
524
569
|
: root_target_refs.get(target);
|
|
525
570
|
|
|
526
571
|
if (ref === undefined) {
|
|
527
|
-
ref = {
|
|
572
|
+
ref = { n: 0, e: new Set(), t: target };
|
|
528
573
|
root_target_refs.set(target, ref);
|
|
529
574
|
register_root_events(ref, all_registered_events);
|
|
530
575
|
}
|
|
531
576
|
|
|
532
|
-
ref.
|
|
577
|
+
ref.n += 1;
|
|
533
578
|
last_root_ref = ref;
|
|
534
579
|
return ref;
|
|
535
580
|
}
|
|
@@ -539,18 +584,18 @@ export function handle_root_events(target) {
|
|
|
539
584
|
* @returns {void}
|
|
540
585
|
*/
|
|
541
586
|
export function release_root_events(ref) {
|
|
542
|
-
// The map entry for `ref.
|
|
587
|
+
// The map entry for `ref.t` is always this `ref`: it is only deleted
|
|
543
588
|
// when the count hits 0, which requires every acquirer to have released.
|
|
544
|
-
ref.
|
|
545
|
-
if (ref.
|
|
589
|
+
ref.n -= 1;
|
|
590
|
+
if (ref.n > 0) return;
|
|
546
591
|
|
|
547
592
|
// Last caller for this target: actually tear down the shared listeners.
|
|
548
|
-
var target = ref.
|
|
593
|
+
var target = ref.t;
|
|
549
594
|
root_target_refs.delete(target);
|
|
550
595
|
if (last_root_ref === ref) {
|
|
551
596
|
last_root_ref = null;
|
|
552
597
|
}
|
|
553
|
-
for (var event_name of ref.
|
|
598
|
+
for (var event_name of ref.e) {
|
|
554
599
|
target.removeEventListener(event_name, /** @type {EventListener} */ (handle_event_propagation));
|
|
555
600
|
}
|
|
556
601
|
}
|