Closed Bug 1926630 Opened 1 year ago Closed 1 year ago

Menuitems added via async onPopupShowing handler create duplicates on macos

Categories

(Core :: Widget: Cocoa, defect, P1)

defect

Tracking

()

RESOLVED FIXED
134 Branch
Tracking Status
firefox134 --- fixed

People

(Reporter: jhirsch, Assigned: mstange)

References

Details

Attachments

(3 files)

If a menubar menupopup is populated by an async onPopupShowing handler, which awaits some async data, and then renders it into menuitems, then on macos only (not windows) each of the inserted menuitems creates a second menuitem, rendered in the menu in reverse order, see screenshot.

Attempting to delete these extra menuitems via DOM JS APIs fails--these extra menuitems are not counted as children from the DOM perspective.

This behavior is observed whether the items are inserted one-by-one or whether they are added to a document fragment which is then inserted into the XUL DOM.

Based on initial debugging it seems that dynamically added items are double-inserted by a mutation observer: nsINode::InsertBefore is called, triggering MutationObserverWrapper::ContentInserted, which calls nsMenuGroupOwnerX::ContentInserted, then nsMenuX::ObserveContentInserted, then nsMenuX::InsertMenuChild.

On the other hand, elements left over from the previous rendering of the menu are initially displayed via nsMenuX::menuOpened calling nsMenuX::rebuildMenu calling nsMenuX::addMenuChild.

See screenshot and https://phabricator.services.mozilla.com/D226415 for a demo of this bug (you should have some extra profiles to test this out, they can be created via about:profiles).

I can reproduce this. I haven't started debugging yet.

Assignee: nobody → mstange.moz
Status: NEW → ASSIGNED

This is a legitimate bug. I think this might be the first use of this type:

  • A menupopup is being mutated while it's open
  • The menu is not the root menupopup of a context menu

From what I can tell, the way the native menu system sets up its mutation observers is bound to cause duplicate notifications: We register the observer on the <menubar>, on the context menu's root <menupopup>, and on every nested <menu>. But mutation observers observe the entire DOM subtree. So we get lots of duplicate mutation callbacks for anything that's nested at least one level deep.

And it seems we've always been getting these duplicate callbacks. It's just that, if our observer is called while the menu is closed, we just set a "need to rebuild" flag and return.

But when the menu is open, these duplicate notifications cause trouble.

I have a super simple fix, writing a test now.

Severity: -- → S3
Priority: -- → P3
Blocks: 1927938
Severity: S3 → S2
Priority: P3 → P1

In the case of this bug, we were creating different NSMenuItem
objects which ended up referring to the same nsIContent object.

Attachment #9433214 - Attachment description: WIP: Bug 1926630 - Only register the mutation observer with the subtree root of the menu structure, to avoid duplicate notifications. → Bug 1926630 - Only register the mutation observer with the subtree root of the menu structure, to avoid duplicate notifications. r=#mac-reviewers
Pushed by mstange@themasta.com: https://hg.mozilla.org/integration/autoland/rev/9d0fb0e1ce38 Make CheckNativeMenuConsistency detect duplicate menuitems more reliably. r=mac-reviewers,bradwerth https://hg.mozilla.org/integration/autoland/rev/e369109c2e87 Only register the mutation observer with the subtree root of the menu structure, to avoid duplicate notifications. r=mac-reviewers,bradwerth
Pushed by mstange@themasta.com: https://hg.mozilla.org/integration/autoland/rev/f5b68fee6dbd Make CheckNativeMenuConsistency detect duplicate menuitems more reliably. r=mac-reviewers,bradwerth https://hg.mozilla.org/integration/autoland/rev/dbc9c8f60473 Only register the mutation observer with the subtree root of the menu structure, to avoid duplicate notifications. r=mac-reviewers,bradwerth

Backed out for causing mochitest failures at test_native_menus.xhtml.

No longer blocks: 1927938

In the try push, two out of the three bc4 tests fail with "WARNING: YOU ARE LEAKING THE WORLD", so I think having an unconditional mutation listener on the root element of the menu hierarchy keeps things alive for too long. I'll try to make it so that we only have the root mutation listener if there are registered menu change observers.

Pushed by mstange@themasta.com: https://hg.mozilla.org/integration/autoland/rev/c57ae217dc8c Make CheckNativeMenuConsistency detect duplicate menuitems more reliably. r=mac-reviewers,bradwerth https://hg.mozilla.org/integration/autoland/rev/f001943cbf9b Only register the mutation observer with the subtree root of the menu structure, to avoid duplicate notifications. r=mac-reviewers,bradwerth
Status: ASSIGNED → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 134 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: