Closed Bug 1907932 Opened 4 months ago Closed 4 months ago

Reselect logic when editing a tagname in the markup view is brittle

Categories

(DevTools :: Inspector, defect, P3)

defect

Tracking

(firefox130 fixed)

RESOLVED FIXED
130 Branch
Tracking Status
firefox130 --- fixed

People

(Reporter: nchevobbe, Assigned: nchevobbe)

References

Details

Attachments

(1 file)

When editing a node tagname in the markup view, we actually create a new node, insert it before the old one, move all the children from the old node to the new one, and finally remove the old node.
Because we're actually getting a new node, we want to select it again once we get it on the client.

https://searchfox.org/mozilla-central/rev/54a5c4f14f3eb514a29e0cebcb5a095144bcd450/devtools/client/inspector/markup/views/element-editor.js#1181

this.markup.reselectOnRemoved(this.node, "edittagname");

For this we're listening for mutations, and try to reselect the node if we get a childList mutation on the original parent of the node we renamed

https://searchfox.org/mozilla-central/rev/54a5c4f14f3eb514a29e0cebcb5a095144bcd450/devtools/client/inspector/markup/markup.js#1860,1875,1897-1898,1900,1904,1910-1911,1915-1916

reselectOnRemoved(removedNode, reason) {
...
  const onMutations = (this._removedNodeObserver = mutations => {
...
    if (
      this.inspector.selection.nodeFront === parentContainer.node ||
...
    ) {
...
        this._markContainerAsSelected(childContainer, reason);
...
    }
  });
...
  this.inspector.on("markupmutation", onMutations);
},

The issue is that we can get other mutations in the meantime, that would cause another node to be selected and make us fail the "reselection"

https://searchfox.org/mozilla-central/rev/54a5c4f14f3eb514a29e0cebcb5a095144bcd450/devtools/client/framework/selection.js#72-73,79,83-90,94,103-105

Selection.prototype = {
  _onMutations(mutations) {
...
    for (const m of mutations) {
...
      if (m.type == "childList") {
        if (!detached && !this.isConnected()) {
          if (this.isNode()) {
            parentNode = m.target;
          }
          detached = true;
        }
      }
...
    }
...
    if (detached) {
      this.emit("detached-front", parentNode);
    }

here we'll emit detached-front with the parent node front of the first mutation item we get, given the node isn't connected.
which triggers the selection of the parent

https://searchfox.org/mozilla-central/rev/54a5c4f14f3eb514a29e0cebcb5a095144bcd450/devtools/client/inspector/inspector.js#1673-1678,1681-1682

/**
 * When a node is deleted, select its parent node or the defaultNode if no
 * parent is found (may happen when deleting an iframe inside which the
 * node was selected).
 */
onDetached(parentNode) {
...
  this.selection.setNodeFront(nodeFront, { reason: "detached" });
},

In one of my test, I was hitting this test case as we were getting mutation when anonymouscontentroot were created (e.g. scrollbar, moz-caret-accessible), which we don't show in regular toolboxes, so were seen as "disconnected".


So here I'm not sure what's the proper fix:

  • should we consider it very unlikely that just after editing the tagname the user selected another node?
  • or maybe we should not emit mutations for node we wouldn't show in the markup view?
  • or making sure that we don't consider the selection as "changed" if the change in the selection wasn't due to the user actually interacting with the UI?

When editing a tagname, we're actually removing the node and replacing it with
a new one, with the new tagname.
This triggers a mutation, and on the client, we detect that the currently
selected node was detached, and we select its parent.
The markup view then has some logic to know that it should reselect a node,
by checking that the currently selected node was the parent of the edited node.
Unfortunately, the way we were selecting the parent node could be "highjacked" if
other mutations are reported at the same time (mutations are throttled); we were
picking the first node who was mutated as the one we should select, although the
mutations array could actually contain the parent of the renamed node, which is
the one we want to reselect.
To fix this, we flag the tag we rename so we can identify it in the mutations
we get, and send the flag to the client. On the client, we'd then select this
parent node with the expected mutation in it.

We're not adding a specific test for it, the next patch on the queue (for Bug 1173057),
has a test which was failing intermittently without this fix.

Assignee: nobody → nchevobbe
Status: NEW → ASSIGNED
Severity: -- → S3
Priority: -- → P3
Attachment #9412962 - Attachment description: Bug 1907932 - [devtools] Properly handle detached front node when editing tagname. r=#devtools-reviewers. → Bug 1907932 - [devtools] Pick detached-front parentNode from mutation's remove node. r=#devtools-reviewers.
Pushed by nchevobbe@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/e9922adffff8 [devtools] Pick detached-front parentNode from mutation's remove node. r=devtools-reviewers,ochameau.
Status: ASSIGNED → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → 130 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: