ripple 0.3.127 → 0.4.0
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 +293 -0
- package/package.json +10 -4
- package/src/runtime/element.js +23 -6
- package/src/runtime/index-client.js +81 -41
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/blocks.js +192 -114
- package/src/runtime/internal/client/component.js +4 -30
- package/src/runtime/internal/client/composite.js +12 -13
- package/src/runtime/internal/client/constants.js +14 -5
- package/src/runtime/internal/client/context.js +12 -19
- package/src/runtime/internal/client/css.js +7 -9
- package/src/runtime/internal/client/events.js +178 -90
- package/src/runtime/internal/client/expression.js +185 -124
- package/src/runtime/internal/client/for.js +616 -264
- package/src/runtime/internal/client/head.js +10 -5
- package/src/runtime/internal/client/html.js +1 -0
- package/src/runtime/internal/client/hydration.js +152 -10
- package/src/runtime/internal/client/if.js +239 -50
- package/src/runtime/internal/client/index.js +9 -13
- package/src/runtime/internal/client/operations.js +44 -51
- package/src/runtime/internal/client/portal.js +163 -85
- package/src/runtime/internal/client/render.js +44 -25
- package/src/runtime/internal/client/rpc.js +3 -3
- package/src/runtime/internal/client/runtime.js +799 -576
- package/src/runtime/internal/client/selector.js +77 -0
- package/src/runtime/internal/client/template.js +133 -158
- package/src/runtime/internal/client/transport.js +38 -0
- package/src/runtime/internal/client/try.js +465 -426
- package/src/runtime/internal/client/types.d.ts +65 -21
- package/src/runtime/internal/client/utils.js +1 -3
- package/src/runtime/internal/server/dynamic.js +20 -21
- package/src/runtime/internal/server/index.js +327 -275
- package/src/runtime/internal/server/rpc.js +3 -2
- package/src/runtime/internal/server/transport.js +16 -0
- package/src/runtime/transport.js +21 -0
- package/tests/client/__snapshots__/for.test.tsrx.snap +0 -5
- package/tests/client/array/array.copy-within.test.tsrx +12 -12
- package/tests/client/array/array.derived.test.tsrx +46 -46
- package/tests/client/array/array.iteration.test.tsrx +10 -10
- package/tests/client/array/array.mutations.test.tsrx +20 -20
- package/tests/client/array/array.static.test.tsrx +11 -11
- package/tests/client/array/array.to-methods.test.tsrx +6 -6
- package/tests/client/async-suspend.test.tsrx +74 -75
- package/tests/client/basic/basic.attributes.test.tsrx +86 -83
- package/tests/client/basic/basic.collections.test.tsrx +12 -12
- package/tests/client/basic/basic.components.test.tsrx +99 -25
- package/tests/client/basic/basic.errors.test.tsrx +18 -18
- package/tests/client/basic/basic.events.test.tsrx +42 -42
- package/tests/client/basic/basic.get-set.test.tsrx +8 -8
- package/tests/client/basic/basic.reactivity.test.tsrx +97 -29
- package/tests/client/basic/basic.rendering.test.tsrx +25 -25
- package/tests/client/basic/basic.utilities.test.tsrx +3 -3
- package/tests/client/boundaries.test.tsrx +8 -8
- package/tests/client/boxed-locals.test.tsrx +452 -0
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +6 -6
- package/tests/client/compiler/compiler.assignments.test.tsrx +9 -73
- package/tests/client/compiler/compiler.attributes.test.tsrx +23 -23
- package/tests/client/compiler/compiler.basic.test.tsrx +15 -60
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +18 -43
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +2 -2
- package/tests/client/composite/__snapshots__/composite.render.test.tsrx.snap +0 -1
- package/tests/client/composite/composite.dynamic-components.test.tsrx +77 -6
- package/tests/client/composite/composite.props.test.tsrx +149 -12
- package/tests/client/composite/composite.reactivity.test.tsrx +51 -52
- package/tests/client/composite/composite.render.test.tsrx +26 -9
- package/tests/client/css/scoped-styles.test.tsrx +8 -8
- package/tests/client/date.test.tsrx +42 -42
- package/tests/client/derived-release.test.tsrx +370 -0
- package/tests/client/dynamic-elements.test.tsrx +45 -45
- package/tests/client/events.test.tsrx +97 -71
- package/tests/client/for-selector.test.tsrx +221 -0
- package/tests/client/for-single-root-items.test.tsrx +118 -3
- package/tests/client/for.test.tsrx +332 -31
- package/tests/client/head.test.tsrx +19 -19
- package/tests/client/html.test.tsrx +11 -9
- package/tests/client/if-block.test.tsrx +80 -0
- package/tests/client/map.test.tsrx +16 -16
- package/tests/client/media-query.test.tsrx +7 -7
- package/tests/client/portal.test.tsrx +224 -26
- package/tests/client/primitive-text.test.tsrx +50 -0
- package/tests/client/prop-kind-switch.test.tsrx +141 -0
- package/tests/client/ref.test.tsrx +17 -17
- package/tests/client/return.test.tsrx +26 -3
- package/tests/client/root-boundary.test.tsrx +42 -0
- package/tests/client/scoped-flush.test.tsrx +8 -8
- package/tests/client/set.test.tsrx +6 -6
- package/tests/client/svg.test.tsrx +11 -11
- package/tests/client/switch.test.tsrx +44 -44
- package/tests/client/track-async-hydration.test.tsrx +4 -4
- package/tests/client/try.test.tsrx +151 -83
- package/tests/client/tsx.test.tsrx +43 -40
- package/tests/client/url/url.derived.test.tsrx +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +2 -2
- package/tests/hydration/basic.test.js +74 -1
- package/tests/hydration/build-components.js +22 -1
- package/tests/hydration/compiled/client/basic.js +1142 -713
- package/tests/hydration/compiled/client/composite.js +151 -100
- package/tests/hydration/compiled/client/events.js +190 -150
- package/tests/hydration/compiled/client/for.js +1472 -1126
- package/tests/hydration/compiled/client/fragment-cursor.js +2341 -0
- package/tests/hydration/compiled/client/head.js +255 -199
- package/tests/hydration/compiled/client/hmr.js +54 -41
- package/tests/hydration/compiled/client/html-in-template.js +54 -39
- package/tests/hydration/compiled/client/html.js +1633 -1263
- package/tests/hydration/compiled/client/if-children.js +420 -270
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +363 -317
- package/tests/hydration/compiled/client/if.js +229 -219
- package/tests/hydration/compiled/client/mixed-control-flow.js +420 -400
- package/tests/hydration/compiled/client/nested-control-flow.js +1326 -1255
- package/tests/hydration/compiled/client/portal.js +87 -95
- package/tests/hydration/compiled/client/reactivity.js +140 -83
- package/tests/hydration/compiled/client/return.js +28 -19
- package/tests/hydration/compiled/client/streaming.js +390 -306
- package/tests/hydration/compiled/client/switch.js +258 -266
- package/tests/hydration/compiled/client/track-async-serialization.js +448 -280
- package/tests/hydration/compiled/client/try.js +173 -129
- package/tests/hydration/compiled/client/typed-text.js +71 -0
- package/tests/hydration/compiled/fixtures/money.js +10 -0
- package/tests/hydration/compiled/server/basic.js +123 -6
- package/tests/hydration/compiled/server/composite.js +16 -30
- package/tests/hydration/compiled/server/events.js +19 -19
- package/tests/hydration/compiled/server/for.js +109 -49
- package/tests/hydration/compiled/server/fragment-cursor.js +1687 -0
- package/tests/hydration/compiled/server/head.js +20 -28
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +71 -247
- package/tests/hydration/compiled/server/if-children.js +107 -15
- package/tests/hydration/compiled/server/if.js +11 -15
- package/tests/hydration/compiled/server/mixed-control-flow.js +8 -8
- package/tests/hydration/compiled/server/portal.js +14 -22
- package/tests/hydration/compiled/server/reactivity.js +14 -46
- package/tests/hydration/compiled/server/streaming.js +19 -19
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/compiled/server/track-async-serialization.js +150 -23
- package/tests/hydration/compiled/server/try.js +8 -8
- package/tests/hydration/compiled/server/typed-text.js +17 -0
- package/tests/hydration/components/basic.tsrx +44 -8
- package/tests/hydration/components/composite.tsrx +2 -2
- package/tests/hydration/components/events.tsrx +25 -25
- package/tests/hydration/components/for.tsrx +115 -67
- package/tests/hydration/components/fragment-cursor.tsrx +650 -0
- package/tests/hydration/components/head.tsrx +16 -16
- package/tests/hydration/components/hmr.tsrx +2 -2
- package/tests/hydration/components/html.tsrx +7 -7
- package/tests/hydration/components/if-children.tsrx +72 -25
- package/tests/hydration/components/if.tsrx +18 -18
- package/tests/hydration/components/mixed-control-flow.tsrx +11 -11
- package/tests/hydration/components/portal.tsrx +3 -3
- package/tests/hydration/components/reactivity.tsrx +16 -16
- package/tests/hydration/components/streaming.tsrx +20 -20
- package/tests/hydration/components/switch.tsrx +20 -20
- package/tests/hydration/components/text-types.ts +4 -0
- package/tests/hydration/components/track-async-serialization.tsrx +80 -26
- package/tests/hydration/components/try.tsrx +8 -8
- package/tests/hydration/components/typed-text.tsrx +22 -0
- package/tests/hydration/fixtures/money.js +10 -0
- package/tests/hydration/for.test.js +36 -0
- package/tests/hydration/fragment-cursor.test.js +111 -0
- package/tests/hydration/if-children.test.js +24 -0
- package/tests/hydration/streaming.test.js +19 -0
- package/tests/hydration/track-async-serialization.test.js +87 -2
- package/tests/hydration/tsconfig.text-types.json +10 -0
- package/tests/hydration/typed-text.test.js +34 -0
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +42 -42
- package/tests/server/basic.components.test.tsrx +64 -8
- package/tests/server/basic.test.tsrx +34 -32
- package/tests/server/compiler.test.tsrx +1 -70
- package/tests/server/composite.props.test.tsrx +6 -6
- package/tests/server/dynamic-elements.test.tsrx +31 -8
- package/tests/server/for.test.tsrx +94 -0
- package/tests/server/head.test.tsrx +11 -11
- package/tests/server/scoped-styles.test.tsrx +2 -2
- package/tests/server/streaming-ssr.test.tsrx +48 -43
- package/tests/server/track-async-serialization.test.tsrx +204 -21
- package/tests/server/try.test.tsrx +48 -48
- package/tests/types/transport.ts +40 -0
- package/tests/utils/vite-plugin-config.test.js +23 -0
- package/types/index.d.ts +48 -7
- package/types/server.d.ts +3 -0
- package/types/transport.d.ts +15 -0
- package/src/runtime/internal/client/switch.js +0 -113
- package/src/utils/errors.js +0 -13
- package/tests/client/lazy-array.test.tsrx +0 -31
- package/tests/client/lazy-destructuring.test.tsrx +0 -438
- package/tests/client/tracked-index-access.test.tsrx +0 -113
- package/tests/server/lazy-destructuring.test.tsrx +0 -595
- package/tests/server/tracked-index-access.test.tsrx +0 -76
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Component } from '#client' */
|
|
1
|
+
/** @import { Component, ContextEntry } from '#client' */
|
|
2
2
|
|
|
3
3
|
import { active_component } from './runtime.js';
|
|
4
4
|
|
|
@@ -16,25 +16,25 @@ export class Context {
|
|
|
16
16
|
|
|
17
17
|
get() {
|
|
18
18
|
const component = active_component;
|
|
19
|
-
const context = this;
|
|
20
19
|
|
|
21
20
|
if (component === null) {
|
|
22
21
|
throw new Error('No active component found, cannot get context');
|
|
23
22
|
}
|
|
24
|
-
/** @type {Component | null} */
|
|
25
|
-
let current_component = component;
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
// A component inherits its parent's chain of set entries when it is
|
|
25
|
+
// created, so only the values that were set are visited, not every
|
|
26
|
+
// ancestor; the most recent set of a context is nearest the head.
|
|
27
|
+
/** @type {ContextEntry | null} */
|
|
28
|
+
let entry = component.c;
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
while (entry !== null) {
|
|
31
|
+
if (entry.k === this) {
|
|
32
|
+
return entry.v;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
current_component = current_component.p;
|
|
34
|
+
entry = entry.n;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
return
|
|
37
|
+
return this._v;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -43,19 +43,12 @@ export class Context {
|
|
|
43
43
|
*/
|
|
44
44
|
set(value) {
|
|
45
45
|
const component = active_component;
|
|
46
|
-
const context = this;
|
|
47
46
|
|
|
48
47
|
if (component === null) {
|
|
49
48
|
throw new Error('No active component found, cannot set context');
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (current_context === null) {
|
|
55
|
-
current_context = component.c = new Map();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
current_context.set(context, value);
|
|
51
|
+
component.c = { k: this, v: value, n: component.c };
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { DEV } from 'esm-env';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function remove_styles() {
|
|
3
|
+
/**
|
|
4
|
+
* Removes the server's inline styles once the client stylesheets are in.
|
|
5
|
+
* Schedule it with `requestAnimationFrame`: the removal already waits for a
|
|
6
|
+
* frame after the stylesheets load, and starting from a frame keeps mounting
|
|
7
|
+
* and hydrating free of stylesheet queries.
|
|
8
|
+
*/
|
|
9
|
+
export function remove_styles() {
|
|
12
10
|
if (DEV) {
|
|
13
11
|
const styles = document.querySelector('style[data-vite-dev-id]');
|
|
14
12
|
if (styles) {
|
|
@@ -16,14 +16,15 @@ import {
|
|
|
16
16
|
set_tracking,
|
|
17
17
|
tracking,
|
|
18
18
|
} from './runtime.js';
|
|
19
|
-
import {
|
|
19
|
+
import { define_property, is_array } from '@tsrx/core/runtime/language-helpers';
|
|
20
20
|
import { render } from './blocks.js';
|
|
21
21
|
|
|
22
22
|
/** @type {Set<string>} */
|
|
23
23
|
var all_registered_events = new Set();
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {{ count: number, registered_events: Set<string>, target: Element }} RootTargetRef
|
|
27
|
+
*/
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Active root delegation targets, ref-counted per target. Multiple callers of
|
|
@@ -32,10 +33,13 @@ var root_event_handles = new Set();
|
|
|
32
33
|
* nested mounts. The shared delegated listeners for a target may only be torn
|
|
33
34
|
* down once every caller for that target has released it, otherwise
|
|
34
35
|
* unmounting one Portal silently kills event delegation for its siblings.
|
|
35
|
-
* @type {Map<Element,
|
|
36
|
+
* @type {Map<Element, RootTargetRef>}
|
|
36
37
|
*/
|
|
37
38
|
var root_target_refs = new Map();
|
|
38
39
|
|
|
40
|
+
/** @type {RootTargetRef | null} */
|
|
41
|
+
var last_root_ref = null;
|
|
42
|
+
|
|
39
43
|
/**
|
|
40
44
|
* Delegated handling only works for elements strictly below a root delegation
|
|
41
45
|
* target: the root listener's propagation walk never visits the target itself
|
|
@@ -271,30 +275,10 @@ function create_event(event_name, dom, handler, options) {
|
|
|
271
275
|
if (is_delegated) {
|
|
272
276
|
var prop = '__' + event_name;
|
|
273
277
|
var target = /** @type {DelegatedEventTarget} */ (dom);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
if (current === undefined) {
|
|
277
|
-
target[prop] = handler;
|
|
278
|
-
} else if (is_array(current)) {
|
|
279
|
-
if (!current.includes(handler)) {
|
|
280
|
-
current.push(handler);
|
|
281
|
-
}
|
|
282
|
-
} else {
|
|
283
|
-
if (current !== handler) {
|
|
284
|
-
target[prop] = [current, handler];
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
278
|
+
add_delegated_handler(target, prop, handler);
|
|
288
279
|
delegate([event_name]);
|
|
289
280
|
return () => {
|
|
290
|
-
|
|
291
|
-
if (is_array(handlers)) {
|
|
292
|
-
var filtered = handlers.filter((h) => h !== handler);
|
|
293
|
-
target[prop] =
|
|
294
|
-
filtered.length === 0 ? undefined : filtered.length === 1 ? filtered[0] : filtered;
|
|
295
|
-
} else {
|
|
296
|
-
target[prop] = undefined;
|
|
297
|
-
}
|
|
281
|
+
remove_delegated_handler(target, prop, handler);
|
|
298
282
|
};
|
|
299
283
|
}
|
|
300
284
|
|
|
@@ -336,12 +320,107 @@ function create_event(event_name, dom, handler, options) {
|
|
|
336
320
|
}
|
|
337
321
|
|
|
338
322
|
/**
|
|
323
|
+
* Delegated event name resolution per compiler-emitted name (`"Click"`,
|
|
324
|
+
* `"PointerMove"`, ...): the lowercase DOM name, or null when the event cannot
|
|
325
|
+
* be delegated (capture variants, non-bubbling events).
|
|
326
|
+
* @type {Map<string, string | null>}
|
|
327
|
+
*/
|
|
328
|
+
var delegated_event_names = new Map();
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* @param {string} event_name
|
|
332
|
+
* @returns {string | null}
|
|
333
|
+
*/
|
|
334
|
+
function get_delegated_event_name(event_name) {
|
|
335
|
+
var name = delegated_event_names.get(event_name);
|
|
336
|
+
|
|
337
|
+
if (name === undefined) {
|
|
338
|
+
if (is_capture_event(event_name)) {
|
|
339
|
+
name = null;
|
|
340
|
+
} else {
|
|
341
|
+
name = event_name.toLowerCase();
|
|
342
|
+
if (is_non_delegated(name)) {
|
|
343
|
+
name = null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
delegated_event_names.set(event_name, name);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return name;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* @param {DelegatedEventTarget} target
|
|
354
|
+
* @param {string} prop
|
|
355
|
+
* @param {EventListener} handler
|
|
356
|
+
* @returns {void}
|
|
357
|
+
*/
|
|
358
|
+
function add_delegated_handler(target, prop, handler) {
|
|
359
|
+
var current = target[prop];
|
|
360
|
+
|
|
361
|
+
if (current === undefined) {
|
|
362
|
+
target[prop] = handler;
|
|
363
|
+
} else if (is_array(current)) {
|
|
364
|
+
if (!current.includes(handler)) {
|
|
365
|
+
current.push(handler);
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
if (current !== handler) {
|
|
369
|
+
target[prop] = [current, handler];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* @param {DelegatedEventTarget} target
|
|
376
|
+
* @param {string} prop
|
|
377
|
+
* @param {EventListener} handler
|
|
378
|
+
* @returns {void}
|
|
379
|
+
*/
|
|
380
|
+
function remove_delegated_handler(target, prop, handler) {
|
|
381
|
+
var handlers = target[prop];
|
|
382
|
+
if (is_array(handlers)) {
|
|
383
|
+
var filtered = handlers.filter((h) => h !== handler);
|
|
384
|
+
target[prop] =
|
|
385
|
+
filtered.length === 0 ? undefined : filtered.length === 1 ? filtered[0] : filtered;
|
|
386
|
+
} else {
|
|
387
|
+
target[prop] = undefined;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Compiler-emitted one-shot listener for a static `onEvent={handler}`: the
|
|
393
|
+
* element's lifetime owns the handler, so nothing is returned for cleanup.
|
|
339
394
|
* @param {string} event_name
|
|
340
395
|
* @param {Element} dom
|
|
341
396
|
* @param {EventListener | AddEventObject} handler
|
|
342
|
-
* @returns {
|
|
397
|
+
* @returns {void}
|
|
343
398
|
*/
|
|
344
399
|
export function event(event_name, dom, handler) {
|
|
400
|
+
if (typeof handler === 'function') {
|
|
401
|
+
// Plain handler: the common compiled `onClick={fn}` shape. Resolve the
|
|
402
|
+
// delegated name from the cache and skip the options plumbing.
|
|
403
|
+
var name = get_delegated_event_name(event_name);
|
|
404
|
+
|
|
405
|
+
if (name !== null) {
|
|
406
|
+
add_delegated_handler(/** @type {DelegatedEventTarget} */ (dom), '__' + name, handler);
|
|
407
|
+
delegate([name]);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
event_listener(event_name, dom, handler);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Attaches a listener and returns its remover; `event()` is the one-shot
|
|
417
|
+
* compiled form of this.
|
|
418
|
+
* @param {string} event_name
|
|
419
|
+
* @param {Element} dom
|
|
420
|
+
* @param {EventListener | AddEventObject} handler
|
|
421
|
+
* @returns {() => void}
|
|
422
|
+
*/
|
|
423
|
+
export function event_listener(event_name, dom, handler) {
|
|
345
424
|
/** @type AddEventOptions */
|
|
346
425
|
var options = {};
|
|
347
426
|
/** @type {EventListener} */
|
|
@@ -350,7 +429,7 @@ export function event(event_name, dom, handler) {
|
|
|
350
429
|
if (typeof handler === 'object' && 'handleEvent' in handler) {
|
|
351
430
|
({ handleEvent: event_handler, ...options } = handler);
|
|
352
431
|
} else {
|
|
353
|
-
event_handler = handler;
|
|
432
|
+
event_handler = /** @type {EventListener} */ (handler);
|
|
354
433
|
}
|
|
355
434
|
|
|
356
435
|
return create_event(event_name, dom, event_handler, options);
|
|
@@ -381,7 +460,7 @@ export function render_event(event_name, dom, get_handler) {
|
|
|
381
460
|
prev = handler;
|
|
382
461
|
|
|
383
462
|
if (handler) {
|
|
384
|
-
remove_listener =
|
|
463
|
+
remove_listener = event_listener(event_name, dom, handler);
|
|
385
464
|
}
|
|
386
465
|
}
|
|
387
466
|
});
|
|
@@ -392,77 +471,86 @@ export function render_event(event_name, dom, get_handler) {
|
|
|
392
471
|
* @returns {void}
|
|
393
472
|
*/
|
|
394
473
|
export function delegate(events) {
|
|
474
|
+
var added = false;
|
|
475
|
+
|
|
395
476
|
for (var i = 0; i < events.length; i++) {
|
|
396
|
-
|
|
477
|
+
var event_name = events[i];
|
|
478
|
+
|
|
479
|
+
if (!all_registered_events.has(event_name)) {
|
|
480
|
+
all_registered_events.add(event_name);
|
|
481
|
+
added = true;
|
|
482
|
+
}
|
|
397
483
|
}
|
|
398
484
|
|
|
399
|
-
for
|
|
400
|
-
|
|
485
|
+
// Every root target already listens for every previously registered event,
|
|
486
|
+
// so only a new event name needs to fan out to the targets.
|
|
487
|
+
if (added) {
|
|
488
|
+
for (var ref of root_target_refs.values()) {
|
|
489
|
+
register_root_events(ref, events);
|
|
490
|
+
}
|
|
401
491
|
}
|
|
402
492
|
}
|
|
403
493
|
|
|
404
|
-
/**
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
};
|
|
410
|
-
ref.count += 1;
|
|
411
|
-
root_target_refs.set(target, ref);
|
|
494
|
+
/**
|
|
495
|
+
* @param {RootTargetRef} ref
|
|
496
|
+
* @param {Iterable<string>} events
|
|
497
|
+
*/
|
|
498
|
+
function register_root_events(ref, events) {
|
|
412
499
|
var registered_events = ref.registered_events;
|
|
500
|
+
var target = ref.target;
|
|
413
501
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
*/
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* @typedef {(
|
|
421
|
-
* events: Array<string>
|
|
422
|
-
* ) => void} EventHandle
|
|
423
|
-
*/
|
|
424
|
-
|
|
425
|
-
/** @type {EventHandle} */
|
|
426
|
-
var event_handle = (/** @type {Array<string>} */ events) => {
|
|
427
|
-
for (var i = 0; i < events.length; i++) {
|
|
428
|
-
var event_name = events[i];
|
|
429
|
-
|
|
430
|
-
if (registered_events.has(event_name)) continue;
|
|
431
|
-
registered_events.add(event_name);
|
|
502
|
+
for (var event_name of events) {
|
|
503
|
+
if (registered_events.has(event_name)) continue;
|
|
504
|
+
registered_events.add(event_name);
|
|
432
505
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
target.addEventListener(event_name, handle_event_propagation, options);
|
|
440
|
-
}
|
|
441
|
-
};
|
|
506
|
+
target.addEventListener(event_name, handle_event_propagation, {
|
|
507
|
+
passive: is_passive_event(event_name),
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
}
|
|
442
511
|
|
|
443
|
-
|
|
444
|
-
|
|
512
|
+
/**
|
|
513
|
+
* Acquires the delegated root listeners for `target` and returns the shared
|
|
514
|
+
* ref; every acquire must be paired with one `release_root_events` call.
|
|
515
|
+
* @param {Element} target
|
|
516
|
+
* @returns {RootTargetRef}
|
|
517
|
+
*/
|
|
518
|
+
export function handle_root_events(target) {
|
|
519
|
+
// Sibling portals mostly share one target, so check the last ref first.
|
|
520
|
+
/** @type {RootTargetRef | undefined} */
|
|
521
|
+
var ref =
|
|
522
|
+
last_root_ref !== null && last_root_ref.target === target
|
|
523
|
+
? last_root_ref
|
|
524
|
+
: root_target_refs.get(target);
|
|
525
|
+
|
|
526
|
+
if (ref === undefined) {
|
|
527
|
+
ref = { count: 0, registered_events: new Set(), target };
|
|
528
|
+
root_target_refs.set(target, ref);
|
|
529
|
+
register_root_events(ref, all_registered_events);
|
|
530
|
+
}
|
|
445
531
|
|
|
446
|
-
|
|
532
|
+
ref.count += 1;
|
|
533
|
+
last_root_ref = ref;
|
|
534
|
+
return ref;
|
|
535
|
+
}
|
|
447
536
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
};
|
|
537
|
+
/**
|
|
538
|
+
* @param {RootTargetRef} ref
|
|
539
|
+
* @returns {void}
|
|
540
|
+
*/
|
|
541
|
+
export function release_root_events(ref) {
|
|
542
|
+
// The map entry for `ref.target` is always this `ref`: it is only deleted
|
|
543
|
+
// when the count hits 0, which requires every acquirer to have released.
|
|
544
|
+
ref.count -= 1;
|
|
545
|
+
if (ref.count > 0) return;
|
|
546
|
+
|
|
547
|
+
// Last caller for this target: actually tear down the shared listeners.
|
|
548
|
+
var target = ref.target;
|
|
549
|
+
root_target_refs.delete(target);
|
|
550
|
+
if (last_root_ref === ref) {
|
|
551
|
+
last_root_ref = null;
|
|
552
|
+
}
|
|
553
|
+
for (var event_name of ref.registered_events) {
|
|
554
|
+
target.removeEventListener(event_name, /** @type {EventListener} */ (handle_event_propagation));
|
|
555
|
+
}
|
|
468
556
|
}
|