Skip to content

Commit b963e53

Browse files
authored
fix: parse ongotpointercapture and onlostpointercapture events correctly (#11790)
Fixes #11789
1 parent 0c4c2b0 commit b963e53

File tree

7 files changed

+63
-23
lines changed

7 files changed

+63
-23
lines changed

.changeset/sleepy-cats-eat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: parse ongotpointercapture and onlostpointercapture events correctly

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ import { validation_legacy, validation_runes, validation_runes_js } from './vali
1818
import check_graph_for_cycles from './utils/check_graph_for_cycles.js';
1919
import { regex_starts_with_newline } from '../patterns.js';
2020
import { create_attribute, is_element_node } from '../nodes.js';
21-
import { DelegatedEvents, namespace_mathml, namespace_svg } from '../../../constants.js';
21+
import {
22+
DelegatedEvents,
23+
is_capture_event,
24+
namespace_mathml,
25+
namespace_svg
26+
} from '../../../constants.js';
2227
import { should_proxy_or_freeze } from '../3-transform/client/utils.js';
2328
import { analyze_css } from './css/css-analyze.js';
2429
import { prune } from './css/css-prune.js';
@@ -1508,23 +1513,13 @@ function determine_element_spread(node) {
15081513
* @param {string} event_name
15091514
*/
15101515
function get_attribute_event_name(event_name) {
1511-
if (is_capture_event(event_name)) {
1516+
if (is_capture_event(event_name, 'include-on')) {
15121517
event_name = event_name.slice(0, -7);
15131518
}
15141519
event_name = event_name.slice(2);
15151520
return event_name;
15161521
}
15171522

1518-
/**
1519-
* @param {string} name
1520-
* @returns boolean
1521-
*/
1522-
function is_capture_event(name) {
1523-
return (
1524-
name.endsWith('capture') && name !== 'ongotpointercapture' && name !== 'onlostpointercapture'
1525-
);
1526-
}
1527-
15281523
/**
15291524
* @param {Map<import('estree').LabeledStatement, import('../types.js').ReactiveStatement>} unsorted_reactive_declarations
15301525
*/

packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
EACH_IS_STRICT_EQUALS,
3333
EACH_ITEM_REACTIVE,
3434
EACH_KEYED,
35+
is_capture_event,
3536
TEMPLATE_FRAGMENT,
3637
TEMPLATE_USE_IMPORT_NODE,
3738
TRANSITION_GLOBAL,
@@ -1410,11 +1411,7 @@ function serialize_event_attribute(node, context) {
14101411
const modifiers = [];
14111412

14121413
let event_name = node.name.slice(2);
1413-
if (
1414-
event_name.endsWith('capture') &&
1415-
event_name !== 'ongotpointercapture' &&
1416-
event_name !== 'onlostpointercapture'
1417-
) {
1414+
if (is_capture_event(event_name)) {
14181415
event_name = event_name.slice(0, -7);
14191416
modifiers.push('capture');
14201417
}

packages/svelte/src/constants.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,16 @@ export function is_tag_valid_with_parent(tag, parent_tag) {
279279

280280
return true;
281281
}
282+
283+
/**
284+
* @param {string} name
285+
* @param {"include-on" | "exclude-on"} [mode] - wether if name starts with `on` or `on` is excluded at this point
286+
*/
287+
export function is_capture_event(name, mode = 'exclude-on') {
288+
if (!name.endsWith('capture')) {
289+
return false;
290+
}
291+
return mode == 'exclude-on'
292+
? name !== 'gotpointercapture' && name !== 'lostpointercapture'
293+
: name !== 'ongotpointercapture' && name !== 'onlostpointercapture';
294+
}

packages/svelte/src/internal/client/dom/elements/attributes.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { DEV } from 'esm-env';
22
import { hydrating } from '../hydration.js';
33
import { get_descriptors, get_prototype_of, map_get, map_set } from '../../utils.js';
4-
import { AttributeAliases, DelegatedEvents, namespace_svg } from '../../../../constants.js';
4+
import {
5+
AttributeAliases,
6+
DelegatedEvents,
7+
is_capture_event,
8+
namespace_svg
9+
} from '../../../../constants.js';
510
import { create_event, delegate } from './events.js';
611
import { add_form_reset_listener, autofocus } from './misc.js';
712
import { effect, effect_root } from '../../reactivity/effects.js';
@@ -172,11 +177,7 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
172177
let event_name = key.slice(2);
173178
var delegated = DelegatedEvents.includes(event_name);
174179

175-
if (
176-
event_name.endsWith('capture') &&
177-
event_name !== 'ongotpointercapture' &&
178-
event_name !== 'onlostpointercapture'
179-
) {
180+
if (is_capture_event(event_name)) {
180181
event_name = event_name.slice(0, -7);
181182
opts.capture = true;
182183
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../assert';
3+
4+
export default test({
5+
async test({ assert, window }) {
6+
const div = window.document.querySelector('div');
7+
8+
div?.dispatchEvent(new PointerEvent('gotpointercapture'));
9+
div?.dispatchEvent(new PointerEvent('lostpointercapture'));
10+
11+
await tick();
12+
13+
assert.equal(div?.dataset.lostCaptured, 'true');
14+
assert.equal(div?.dataset.gotCaptured, 'true');
15+
}
16+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
</script>
3+
4+
<div
5+
ongotpointercapture={(e) => {
6+
e.target.dataset.gotCaptured = "true";
7+
}}
8+
onlostpointercapture={(e) => {
9+
e.target.dataset.lostCaptured = "true";
10+
}}
11+
>
12+
</div>
13+

0 commit comments

Comments
 (0)