Re: [WICG/webcomponents] Reference Target: How to handle events fired on the reference target by related elements? (Issue #1098)

alice left a comment (WICG/webcomponents#1098)

#### form in twice-removed shadow root

From @jakearchibald's example in https://github.com/WICG/webcomponents/issues/1098#issuecomment-2804289613, but I'm going to add an extra shadow root for fun.

```html
<template shadowrootmode="open">
  <!-- shadow0 -->
  <x-form id="xForm">
    <template shadowrootmode="open" shadowrootreferencetarget="thing">
      <!-- shadow1 -->
      <inner-thing id="thing">
        <template shadowrootmode="open" shadowrootreferencetarget="form">
          <!-- shadow2 -->
          <form id="form"></form>
        </template>
      </inner-thing>
    </template>
  </x-form>
  <label>Name: <input id="input" form="xForm"></label>
</template>
```

1. User enters some text in `input` and presses "Enter", triggering [implicit submission](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission):
   > 2. [Submit](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-submit) the [form](https://html.spec.whatwg.org/multipage/forms.html#the-form-element) element from the [form](https://html.spec.whatwg.org/multipage/forms.html#the-form-element) element itself with [userInvolvement](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-user-involvement) set to "[activation](https://html.spec.whatwg.org/multipage/browsing-the-web.html#uni-activation)".
2. The [submit a form](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-submit) algorithm gets `form` as _form_ (via the `form` attribute and reference target) and `input` as _submitter_.
3. 🆕 At [step 5.6](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm:event-submit) of "submit a form", the `SubmitEvent` should have `source` initialized to `input` when firing the `submit` event at `form`.
4. 🆕 In [fire an event](https://dom.spec.whatwg.org/#concept-event-fire), the `source` is part of the initialization of `event` in step 4.9. 
5. 🆕 In [event dispatch](https://dom.spec.whatwg.org/#concept-event-dispatch), we now get a `source` as part of _event_.
6. 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_.
8. When [a node's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A4) is invoked on `form`, it returns `shadow2` as normal.
9. 🆕 When [a shadow root's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6) is invoked on `shadow2`, we go to the (_new_) new logic:
   > 1. let target be event’s path’s first struct’s invocation target;
   > 2. if event’s composed flag is set, return shadow root’s host;
   > 3. if shadow root is not the root of target, and event does not have a source or shadow root is not the root of event's source, return shadow root's host;
   > 4. 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;
   > 5. otherwise, return null.
   
   1. _target_ is `form`; 
   2. the composed flag is _not_ set
   3. `shadow2` _is_ the root of `form` (`false`); event has an `source`, `input`, and `shadow2` is _not_ the root of `input` (`true`), so `false && true` and we don't return shadow root's host but go to step (4)
   4. `input`'s root (`shadow0`) _is_ a shadow-including ancestor of `shadow2`; so, we return the result of retargeting `form` against `input`, yielding `xForm` as the parent element.
 
10. When [a node's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A4) is invoked on `xForm`, it returns `shadow0` as normal.
11. 🆕 When [a shadow root's get the parent](https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6) is invoked on `shadow0`, we go to the (_new_) new logic:
    > 1. let target be event’s path’s first struct’s invocation target;
    > 2. if event’s composed flag is set, return shadow root’s host;
    > 3. if shadow root is not the root of target, and event does not have a source or shadow root is not the root of event's source, return shadow root's host;
    > 4. 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;
    > 5. otherwise, return null.
   
    1. _target_ is `form`; 
    2. the composed flag is _not_ set
    3. `shadow0` is _not_ the root of `form` (`true`); event has an `source`, `input`, and `shadow0` _is_ the root of `input` (`false`), so `true && false` and we don't return shadow root's host but go to step (4)
    4. `input`'s root (`shadow0`) is _not_ a shadow-including exclusive ancestor of `shadow0`; so we go to step 5;
    5. return null.

11. 🆕 Back in event dispatch where the path would previously have just been [`form`, `shadow2`], it now goes [`form`, `shadow2`, `xForm`, `shadow0`] - `shadow1` gets skipped altogether.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/1098#issuecomment-2808089578
You are receiving this because you are subscribed to this thread.

Message ID: <WICG/webcomponents/issues/1098/2808089578@github.com>

Received on Wednesday, 16 April 2025 02:53:51 UTC