-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
State-preserving atomic move integration #10657
Conversation
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 don't think you mentioned connectedMoveCallback everywhere connectedCallback is mentioned (and it's relevant).
- https://html.spec.whatwg.org/#custom-element-reactions
- https://html.spec.whatwg.org/#element-definition (this one seems especially important)
- It could do with some examples as well.
This was there already, see https://whatpr.org/html/10657/custom-elements.html#custom-element-reactions ("When it is moved"). Not sure what's missing?
Done
Added non-normative note and an example |
Seems like #10828 should be addressed here too? |
05e204b
to
9ee1673
Compare
source
Outdated
<var>oldParent</var>, are:</p> | ||
|
||
<ol> | ||
<li><p>If <var>movedNode</var>'s next sibling was an <code>img</code> element 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.
"was"? So somehow this algorithm needs to get the old sibling as argument?
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 yes I guess, but the same goes for the removing steps which pre-date this PR and this API. I think fixing that is best left to a follow-up where we evaluate and perhaps overhaul the inputs to these steps.
For example, we could hack together a single parameter hot fix for this hook, but that's not ideal. Rather we need to do something consistent with what's desired in whatwg/dom#1288, where we teach the various hooks to take in a bundle of contextual information (ChildrenChange
and ContainerNode
in Chromium).
So I think I'd prefer to fix this and removing steps in one swoop after this, since it's easy, ensures nothing diverges, and this doesn't make the problem any worse. How does that sound?
Furthermore, I am actually skeptical that the spec has been doing the right thing in this case anyways. For example, Chromium doesn't track the "old next sibling" of the removed source
, and trigger a relevant mutation on it. It triggers relevant mutations on all image children of the picture
(https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/html_picture_element.cc;l=26-29;drc=a7096322ab1e5c9e70ae7b773faed492ed8461cb) so maybe implementations are compatible with that, and we can simplify all of this anyways. Regardless, I'd prefer it not block this.
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.
Fixing move and removing steps as a followup should be ok.
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.
Please file an issue to track this. And ideally leave a source comment pointing to it.
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.
This CL ships the `ParentNode#moveBefore` API to Chrome stable, targeting M133. See: - https://chromestatus.com/feature/5135990159835136 - https://groups.google.com/a/chromium.org/g/blink-dev/c/YE_xLH6MkRs - https://issues.chromium.org/issues/40150299 - whatwg/dom#1255 - whatwg/dom#1307 - whatwg/html#10657 R=chrishtr, masonf, nrosenthal Bug: 40150299 Change-Id: I005f1db250d731d6845b5238048bbd0b90b20c81 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6112499 Reviewed-by: Noam Rosenthal <[email protected]> Reviewed-by: Mason Freed <[email protected]> Reviewed-by: Chris Harrelson <[email protected]> Commit-Queue: Chris Harrelson <[email protected]> Cr-Commit-Position: refs/heads/main@{#1400559}
Just noting #10954 (comment), which will require a small change to this PR if/when that one lands. |
First off, I want to say that That said, I wanted to raise a concern about the following part of the specification: <p>To opt in to a state-preserving behavior while <span
data-x="concept-node-move-ext">moving</span>, the author can implement a "<code
data-x="">connectedMoveCallback</code>". The existence of this callback, even if empty, would
supercede the default behavior of calling "<code data-x="">disconnectedCallback</code>" and "<code
data-x="">connectedCallback</code>". "<code data-x="">connectedMoveCallback</code>" can also be an
appropriate place to execute logic that depends on the element's ancestors. For example:</p> I find it confusing that the existence of a By way of counter point, I don’t think the presence of an Is there any flexibility in the specification at this point to change that? Or, would it be possible to understand the rationale on this decision in a little more detail? |
This is by design. By adding this empty callback you signal that your component is capable of handling moves.
I don't think this analogy is valid. The presence of the callback doesn't change how ’moveBefore’ works, only which custom element callbacks are called.
It's late at this point. To explain the rationale: |
7c0a2fc
to
39b3664
Compare
This introduces a new API on the ParentNode mixin: moveBefore(). It mirrors insertBefore() in shape, but uses a new manipulation primitive that is also added here: "move". The move primitive contains some of the node tree bookkeeping steps from the remove primitive, as well as the insert primitive, and does three more interesting things: 1. Calls the moving steps hook with the moved node and the old parent (possibly null, just like the removing steps). 2. Queues a custom element callback reaction for the connectedMoveCallback(). 3. Queues two back-to-back mutation record tasks: one for removal from the old parent; one for insertion into the new one. The power of the move primitive comes from the fact that the algorithm does not defer to the traditional insert and remove primitives, and therefore does not invoke the removing steps and insertion steps. This allows most state to be preserved by default (i.e., we don't tear down iframes, or close dialogs). Sometimes, the insertion/removing step overrides in other specifications have steps that do need to be performed during a move anyways. These specifications are expected to override the moving steps hook and perform the necessary work accordingly. Corresponding HTML PR: whatwg/html#10657. Tests: https://github.com/web-platform-tests/wpt/tree/master/dom/nodes/moveBefore (the tentative directory will be flattened). Closes #1255. Closes #1335. Co-authored-by: Anne van Kesteren <[email protected]>
@noamr — Thanks for the thoughtful response. I get your point from a “don’t break the web perspective”, but I am struggling to understand the mental model related to I had previously thought that part of the point of using Either way, I’ll just bake |
It also fires the connectedCallback straight after. The mental model is that if your existing component is not prepared for a move, it should fall back to disconnecting and reconnecting, like a "restart" to make sure it didn't go into some funky state.
|
In case it helps, a possible mental model might be that it disconnects and reconnects the vast majority of elements (e.g. |
@domenic — That is actually super helpful! Makes much more sense to me that this works the way it does 🤘 |
Thanks for asking for clarifications, I will make sure this is reflected in documentation. |
This PR is a supplementary PR to whatwg/dom#1307. It provides the HTML-overrides for the DOM Standard's "moving steps" extension, to allow pieces of the HTML Standard to react to atomic DOM moves without the use of the "insertion steps" or "removing steps", which by default, intentionally fail to preserve most state. The changes in this PR are inspired by the audit carried out in https://docs.google.com/document/d/1qfYyvdK4zhzloABKeh0K1lHPm-SpnEcsWEE9UdDuoMk/edit.
Node.prototype.moveBefore
) WebKit/standards-positions#375Node.prototype.moveBefore
) mozilla/standards-positions#1053moveBefore()
API mdn/mdn#613 & theimpacts-documentation
label(See WHATWG Working Mode: Changes for more details.)
/custom-elements.html ( diff )
/embedded-content.html ( diff )
/form-control-infrastructure.html ( diff )
/form-elements.html ( diff )
/images.html ( diff )
/index.html ( diff )
/infrastructure.html ( diff )
/media.html ( diff )