- From: Alice <notifications@github.com>
- Date: Mon, 14 Apr 2025 23:13:14 -0700
- To: WICG/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <WICG/webcomponents/issues/1098/2803925779@github.com>
alice left a comment (WICG/webcomponents#1098) #### Button with `commandFor` referring into shadow root via reference target From https://github.com/whatwg/html/issues/11148#issuecomment-2757687317 ```html <component-a id="componentA"> <template shadowRootMode="closed"> <button id="button" command="--foo" commandFor="componentB">…</button> <component-b id="componentB"> <template shadowRootMode="closed" shadowRootReferenceTarget="innerDiv"> <div id="innerDiv"></div> </template> </component-b> </template> </component-a> ``` 1. User clicks `button`. 2. The button [activation behaviour](https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour) algorithm gets to [Step 5.5](https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:event-command-2): > Let _continue_ be the result of [firing an event](https://dom.spec.whatwg.org/#concept-event-fire) named [command](https://html.spec.whatwg.org/multipage/indices.html#event-command) at _target_, using [CommandEvent](https://html.spec.whatwg.org/multipage/interaction.html#commandevent), with its [command](https://html.spec.whatwg.org/multipage/interaction.html#dom-commandevent-command) attribute initialized to _command_, its [source](https://html.spec.whatwg.org/multipage/interaction.html#dom-commandevent-source) attribute initialized to _element_, and its [cancelable](https://dom.spec.whatwg.org/#dom-event-cancelable) and [composed](https://dom.spec.whatwg.org/#dom-event-composed) attributes initialized to true. _target_ is `innerDiv`; _command_ is `"--foo"`, _element_ (and thus `source` on the event) is `button`. 🆕 Note: this says "composed [is] initialized to true", but I'm going to proceed as if it was false. Also, since `CommandEvent` already has a `source` attribute, I'm going to use `source` instead of [invoker](https://github.com/WICG/webcomponents/issues/1098#issuecomment-2800523352) here. 3. [Fire an event](https://dom.spec.whatwg.org/#concept-event-fire) calls into [dispatch an _event_](https://dom.spec.whatwg.org/#concept-event-dispatch) with `innerDiv` as _target_ and the `CommandEvent` as _event_. 4. In [step 6.8](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A2) and [step 6.9.9](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A3) of event dispatch, the algorithm calls into [get the parent](https://dom.spec.whatwg.org/#get-the-parent) with _event_. 5. When [a node's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A4) is invoked on `innerDiv`, it returns the _inner_ shadow root (as normal). 6. 🆕 When [a shadow root's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6) is invoked on the _inner_ shadow root, we go to the [new logic](https://github.com/WICG/webcomponents/issues/1098#issuecomment-2800523352): > 1. let _target_ be event’s path’s first struct’s invocation target; > 2. if _event_’s composed flag is set, or shadow root is not the root of _target_, return return shadow root’s host; > 3. otherwise, if _event_ has a `source`, and _event_'s `source`'s root is a shadow-including ancestor of shadow root, return the result of retargeting _target_ against event's triggering element; > 4. otherwise, return null. so _target_ is `innerDiv`; the composed flag is _not_ set, the inner shadow root _is_ the root of _target_; event has a `source`, `button`; `button`'s root (the outer shadow root) _is_ a shadow-including ancestor of the inner shadow root; so, we return the result of retargeting `innerDiv` against `button`, yielding `componentB` as the parent element. 7. When [a node's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A4) is invoked on `componentB`, it returns the _outer_ shadow root (as normal). 8. 🆕 When [a shadow root's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6) is invoked on the _outer_ shadow root, we go to the new logic again: > 1. let _target_ be event’s path’s first struct’s invocation target; > 2. if _event_’s composed flag is set, or shadow root is not the root of _target_, return return shadow root’s host; > 3. otherwise, if _event_ has a `source`, and _event_'s `source`'s root is a shadow-including ancestor of shadow root, return the result of retargeting _target_ against event's triggering element; > 4. otherwise, return null. so _target_ is `innerDiv`; the composed flag is _not_ set, the outer shadow root is _not_ the root of _target_; so, we return shadow root's host, yielding `componentA`. Hmm, damn. I don't know why the [original logic](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6) is "returns null if event’s [composed flag](https://dom.spec.whatwg.org/#composed-flag) is unset and [shadow root](https://dom.spec.whatwg.org/#concept-shadow-root) is the [root](https://dom.spec.whatwg.org/#concept-tree-root) of event’s [path](https://dom.spec.whatwg.org/#event-path)’s first struct’s [invocation target](https://dom.spec.whatwg.org/#event-path-invocation-target); otherwise [shadow root](https://dom.spec.whatwg.org/#concept-shadow-root)’s [host](https://dom.spec.whatwg.org/#concept-documentfragment-host)," but it means once we're outside of the inner shadow root the parent chain just keeps being added to regardless of `composed`. That might need some more thought. -- Reply to this email directly or view it on GitHub: https://github.com/WICG/webcomponents/issues/1098#issuecomment-2803925779 You are receiving this because you are subscribed to this thread. Message ID: <WICG/webcomponents/issues/1098/2803925779@github.com>
Received on Tuesday, 15 April 2025 06:13:18 UTC