-
Notifications
You must be signed in to change notification settings - Fork 294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correct setting of target and relatedTargets post-dispatch #585
Conversation
Helps with issue whatwg/dom#562 and PR whatwg/dom#585.
I would like to take a look, however, I will take a vacation for a few days. Let me review in the next week. |
dom.bs
Outdated
|
||
<li><p>If <var>target</var> is <var>relatedTarget</var> and <var>target</var> is not | ||
<var>event</var>'s <a for=Event>relatedTarget</a>, then return true. | ||
<li><p>If <var>relatedTargets</var> <a for=list>contains</a> <var>target</var> and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt this is quite right in Touch case. Need to think this case some more.
I have some such case in mind where one of the relatedTargets does contain target before retargeting and then retargeting makes also some other relatedTarget to be target.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems https://github.com/w3c/web-platform-tests/blob/master/touch-events/touch-retargeting.html can be extended somehow for more test coverage for touch. It's not entirely clear to me how that works given that on desktop the events are not really exposed.
dom.bs
Outdated
<li><p>Otherwise, if <var>parent</var> and <var>relatedTarget</var> are identical, then set | ||
<var>parent</var> to null. | ||
<li><p>Otherwise, if <var>relatedTargets</var> <a for=list>contains</a> <var>parent</var>, then | ||
set <var>parent</var> to null. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gut feeling is that also this has similar problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I confirmed the Blink's implementation.
We need to distinguish relatedTarget and relatedTargets somehow because only relatedTarget (in the sense of before this PR) should be considered here.
"relaterTagets contains parent" causes a sort of false positive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How should touch targets be adjusted though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the feedback I got before was that whenever we have relatedTarget handling, we also need to consider touch target handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These steps always need some time to understand its intention exactly. :(
My intention is:
- All touch targets should be adjusted in the same way as relatedTarget should be adjusted. They both should be adjusted.
- However, there is one difference between relatedTarget and touch targets. Only relatedTarget should be used to decide to exit this while loop "11. While parent is non-null". This step sets parent to null, thus I think this is an attempt to exit the loop.
To decide to exit this loop or not, in other words, to decide whether an event should be stopped at a shadow root or not, only relatedTarget should be used as its judgement. Touch targets shouldn't be used there.
Since TouchEvent doesn't look to have a relatedTarget to me, TouchEvent never set parent to null here. In other words, TouchEvent is never stopped at a shadow root even if its target and one of touch targets are same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so we effectively need to have relatedTarget as an internal slot and touchTargets as an internal slot and most of the time we do the same thing for both, but not there and not at the other place @smaug---- pointed out (which is hidden now for some reason).
I can make that change. I'd love some help with tests for touch targets btw since I don't really have a good way to run them here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(The alternative option is that we keep one slot but branch on event interface, but that seems a little icky, but let me know if you'd prefer that.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love to help to write more tests, though I'm afraid I can write tests only for synthetic TouchEvents. I am not sure how to write a test for non-synthetic TouchEvents.
(The alternative option is that we keep one slot but branch on event interface, but that seems a little icky, but let me know if you'd prefer that.)
I don't have any preference.
btw, I am wondering how these relatedTargets will be used in TouchEvent spec.
TouchEvents has 3 relatedTargets lists.
readonly attribute TouchList touches;
readonly attribute TouchList targetTouches;
readonly attribute TouchList changedTouches;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that since those lists are all immutable, a flattened list backing them is fine, but that only works if retargeting is consistent regardless of which list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Your assumption is correct. Retargeting is consistent regardless of which list.
dom.bs
Outdated
<a for=tree>root</a> is a <a>shadow-including inclusive ancestor</a> of <var>B</var>, then return | ||
<var>A</var>. | ||
<li><p>If <var>A</var> is a {{Window}} object, then set <var>A</var> to <var>A</var>'s | ||
<a>associated <code>Document</code></a>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, retargeting Window gives Document? Shouldn't this just return Window
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah, I guess we just want it to behave as if you passed document.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I should just remove this step altogether then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because window is not an instance of a Node, it falls into the line 5767 (A is not a node)?
Sounds good - but wondering what's the reasoning behind adding this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this because of #580 (comment), but I didn't really think it through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think removing this step is not enough.
e.g. If A is a node in a shadow tree and B is a Window, we should loop until A reaches the outer most shadow host.
The following should work, I think.
-
If one of the following is true
- A is not a node
- A’s root is not a shadow root
- B is a node and A’s root is a shadow-including inclusive ancestor of B
then return A.
-
Set A to A’s root’s host.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that does look good.
dom.bs
Outdated
|
||
<ul class=brief> | ||
<li><var>A</var> is not a <a>node</a> | ||
<li><var>B</var> is not a <a>node</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically the change for retargeting algorithm from the original is these 2 lines above, am I understanding correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.
431c2ae
to
b7713de
Compare
The PR now separates relatedTarget and touch target list and only has the special cases for relatedTarget. I still need to define an event creation callback of sorts so we can define TouchTarget / FocusEvent et al properly. I was also thinking of incorporating #402 here since we'll have to test that case anyway. |
dom.bs
Outdated
|
||
<li><p>If <var>target</var> is <var>relatedTarget</var> and <var>target</var> is not | ||
<var>event</var>'s <a for=Event>relatedTarget</a>, then return true. | ||
<!-- XXX Since we return early, we might want to unset more flags here. See #402. --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also unset target et al here if clearTargetsPostDispatch is true? It seems that would be consistent... (If that's the case it seems we should turn this into a short algorithm that we invoke here and later on.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have never thought about this case seriously so far. In this early return, I assume that any event listener is never called.
In this case, we don't have to worry about any leaking of a node in a shadow tree via an event object. Users don't have any change to access an event object, other than the original event dispatcher.
btw, the consistency may matter. I'm fine to reset target, relatedTarget, and touch target list here too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm mostly wondering about it from a consistency perspective. I could see you'd have some custom dispatching code and later store the event object after dispatch in a global place and maybe you don't want things to be leaked there ever. Doesn't seem like a sound setup, but other than this case we do provide the guarantee that nothing would leak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now made this change.
I consider this ready apart from the event construction specification callback, which is being discussed in #414. The ongoing feedback here is much appreciated though, please keep it coming. |
@@ -10070,6 +10112,7 @@ Tab Atkins, | |||
Takashi Sakamoto, | |||
Takayoshi Kochi, | |||
Theresa O'Connor, | |||
Theodore Dubois, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this related to this pr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes: #392.
<li><p>Set <var>event</var>'s <a for=Event>relatedTarget</a> to <var>tuple</var>'s | ||
<a for=Event/path>relatedTarget</a>. | ||
|
||
<li><p>Set <var>event</var>'s <a for=Event>touch target list</a> to <var>tuple</var>'s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, perhaps a bit confusing, but I guess should be enough for touch objects. They just need to have a pointer to the event, so that they can update their target form there (basically map their original target to retargeted target or so)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks ok. It is possible that touch target list stuff will need some tweaking when Touch spec is updated
Looks okay to me. Thank you for updating this! |
So thinking about this in light of the tests at I think clearTargets should instead be based on event's path. You find the last tuple in event's path with a non-null target. And then if that tuple contains a node inside a shadow tree in one of the three target fields, you set clearTargets to true. |
Hmm, and should https://whatpr.org/dom/585.html#concept-event-listener-invoke be updated to check the propagation flag later, so target et al still get updated? That would lead to problems too otherwise I think. |
Does this need another review? Please ping me if the PR is ready. |
@hayatoito I'd like input from you and @smaug---- on #585 (comment) (and the next comment) and what a solution to that might look like. The other thing we need here are more tests I suppose. |
I think that approach sounds good. So, in case all the targets after actual dispatch are in light DOM, targets wouldn't get cleared. |
I see. This sounds a reasonable change. Nice catch. |
d7a2136
to
67e64b4
Compare
Tentative commit message:
So more review is welcome here (for the last four commits and this commit message in particular) and more tests. Sorry it got so big, but I'm not sure this could be elegantly made smaller. |
I've reviewed it, and it looks okay to me. A really great work! |
Bugs:
(No bug for Edge since they haven't started yet as far as I'm aware.) |
Automatic update from web-platform-testsDOM: reset target/relatedTarget For whatwg/dom#585. wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919
Automatic update from web-platform-testsDOM: reset target/relatedTarget For whatwg/dom#585. wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 UltraBlame original commit: 2d92f37b4443fac2124163799a2cb0c9f1835f95
Automatic update from web-platform-testsDOM: reset target/relatedTarget For whatwg/dom#585. wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 UltraBlame original commit: 2d92f37b4443fac2124163799a2cb0c9f1835f95
Automatic update from web-platform-testsDOM: reset target/relatedTarget For whatwg/dom#585. wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 wpt-commits: 2f758ac5c16e44915f270ceec31a84eed8f85769 wpt-pr: 9919 UltraBlame original commit: 2d92f37b4443fac2124163799a2cb0c9f1835f95
@whatwg/components this fixes the following:
(The one thing remaining here is having a good look at event constructors and making sure we can make that work for the relatedTargets design. I think that requires some kind of callback type thing.)
Preview | Diff