Convert menuitem bindings to Custom Element
Categories
(Toolkit :: UI Widgets, task, P3)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox68 | --- | fixed |
People
(Reporter: bgrins, Assigned: bgrins)
References
Details
Attachments
(4 files)
| Assignee | ||
Comment 1•7 years ago
|
||
Updated•7 years ago
|
Comment 2•7 years ago
|
||
| Assignee | ||
Comment 3•7 years ago
|
||
Comment 4•7 years ago
|
||
| Assignee | ||
Comment 5•7 years ago
|
||
Comment 6•7 years ago
|
||
| Assignee | ||
Updated•7 years ago
|
| Assignee | ||
Comment 8•7 years ago
|
||
From https://bugzilla.mozilla.org/show_bug.cgi?id=1519495#c2:
When moving anonymous content to document DOM, add
role="none"sinceXULMenuitemAccesibleshould ignore them.
| Assignee | ||
Comment 9•7 years ago
|
||
From https://bugzilla.mozilla.org/show_bug.cgi?id=1519495#c0:
The following bindings can be converted into multiple custom elements, tie to one
menuitemtag name and differentisvalues.
- menuitem
- menuitem-iconic
- menuitem-iconic-noaccel
They have
<children>but we won't be moving them. Rather, we can simply prepend/append nodes before and after the children. They might not be used and if so they can be cleaned up.raw meeting note:
menuitem
It’s a base binding. Uses <content> but not children. Two extended bindings
menuitem-iconic
We need to figure out if <children> is actually used here (inmenuitem[type="checkbox"], menuitem[type="radio"] (content/xul.css), menuitem.menuitem-iconic (content/xul.css), menuitem:not([type]) (viewsource/viewsource.css))
Could confirm with a try push, but this was originally added for a single case: https://hg.mozilla.org/mozilla-central/rev/c868ce24344c#l1.23
<children /> is a direct child of <content>; we don’t need to move it and hit layout assertion.
menuitem-iconic-noaccel
This is overloaded with iconic and plain menuitem, but if we don’t need slotting above then we could make this a runtime check and toggle the correct <content> based on that. May be perf issues to deal with since there’s a ton of these not visible initially
Also:
menuitem-base
[implements], 2 children, totally doable but can’t be removed yet for same reason as basecontrol. Bug can be filed to track dependency.
| Assignee | ||
Comment 10•7 years ago
|
||
Neil and Gijs, to simplify things I'm considering whether we can remove the <children /> slotting for menuitem-iconic at https://searchfox.org/mozilla-central/rev/5e3bffe964110b8d1885b4236b8abd5c94d8f609/toolkit/content/widgets/menu.xml#180. I did a try push where I throw if there is a child node at XBL construction time and so far I'm just seeing a single test which I think could be changed to use a <box> or some other element (layout/xul/test/test_bug372685.xul): https://treeherder.mozilla.org/#/jobs?repo=try&revision=695bcb3417a1350e1ee5dcce81e6a2b14a109668&selectedJob=227738607.
Is there any case you can think of where we want to allow the page to put arbitrary children inside of a menuitem and have it slotted before the menu-accel-container? Every <menuitem /> I've seen at least in markup is self closing with no children.
Comment 11•7 years ago
|
||
(In reply to Brian Grinstead [:bgrins] from comment #10)
Is there any case you can think of where we want to allow the page to put arbitrary children inside of a menuitem and have it slotted before the menu-accel-container?
Nope. We should change bindings / subclass if so (like we did for the icons in the context menu).
| Assignee | ||
Comment 12•7 years ago
|
||
(In reply to :Gijs (he/him) from comment #11)
(In reply to Brian Grinstead [:bgrins] from comment #10)
Is there any case you can think of where we want to allow the page to put arbitrary children inside of a menuitem and have it slotted before the menu-accel-container?
Nope. We should change bindings / subclass if so (like we did for the icons in the context menu).
Thanks, will remove it in Bug 1527115.
| Assignee | ||
Comment 13•6 years ago
|
||
Happily, talos looks good with this: https://treeherder.mozilla.org/perf.html#/compare?originalProject=try&originalRevision=5904dc025a2bc21b445e6ec2b54503e0183ae1ed&newProject=try&newRevision=bea727a2e7deb379f5a9d8c5a86e11b2cd0c61d1&framework=1. I see < 1ms of time in the class spent at startup (since we can lazily create DOM in most cases sans Comment 2). Still a couple of mochitest failures to work through but this is looking pretty close.
| Assignee | ||
Comment 14•6 years ago
|
||
Emilio, there's something weird I'm seeing here where we aren't getting a Custom Element attached in certain circumstances:
STR:
- Apply https://phabricator.services.mozilla.com/D9322
- Open about:preferences
- Scroll down to "Fonts and Colors" and click the "Size" dropdown
- See "TypeError: el.render is not a function"
A few notes:
- The Custom Element seems to just not get attached -
instanceof customElements.get("menuitem")is false, no properties available, etc. - This gets fixed by switching CDATA to an <html:template> (Bug 1545962)
- This call is happening in popupshowing at https://hg.mozilla.org/try/rev/e0fdf0ed517a0371e840f9728073f4100bca2c22#l6.23. The <menuitem /> elements themselves seem to have no Custom Element attached (the same call to
el.render()works fine with all the other menuitems that I've tested). - Looks like TB is seeing some similar behavior with <menu> in https://bugzilla.mozilla.org/show_bug.cgi?id=1545263#c8. Though I'm not sure if this is also a CDATA issue.
| Assignee | ||
Comment 15•6 years ago
|
||
The way CDATA is being used here is:
- There's a box with CDATA at https://searchfox.org/mozilla-central/rev/f46e2bf881d522a440b30cbf5cf8d76fc212eaf4/browser/components/preferences/in-content/main.xul#19 (the broken menuitems are inside it at https://searchfox.org/mozilla-central/rev/f46e2bf881d522a440b30cbf5cf8d76fc212eaf4/browser/components/preferences/in-content/main.xul#146)
- When the section is shown, we take the text from CDATA and send it into parseXULToFragment then replace the box (https://searchfox.org/mozilla-central/rev/f46e2bf881d522a440b30cbf5cf8d76fc212eaf4/browser/components/preferences/in-content/preferences.js#50 / https://searchfox.org/mozilla-central/rev/f46e2bf881d522a440b30cbf5cf8d76fc212eaf4/toolkit/content/customElements.js#411)
Comment 16•6 years ago
|
||
Does manually upgrading the menuitem work out of curiosity?
| Assignee | ||
Comment 17•6 years ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #16)
Does manually upgrading the menuitem work out of curiosity?
No it doesn't, see screenshot
Comment 18•6 years ago
|
||
Alright, I'll take a look, probably tomorrow.
Updated•6 years ago
|
| Assignee | ||
Comment 19•6 years ago
|
||
I was working with or debugging these in the process of doing the previous
changeset, so took the oppurtunity to switch these to add_task and do some
miscellaneous cleanup.
Depends on D9322
| Assignee | ||
Comment 20•6 years ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #18)
Alright, I'll take a look, probably tomorrow.
Thank you! Also, sorry to complicate the STR but if Bug 1545962 / https://hg.mozilla.org/integration/autoland/rev/8ce092764f60 sticks you'll have to back that out as well - that's migrating CDATA to <template> in preferences which we wanted to do anyway, and also fixes this bug. I still think we need to figure out what's going on here since I'm not sure this is only triggered by CDATA - it looks like TB is hitting something similar with a different case which they suspect has to do with importing nodes from a another document (https://bugzilla.mozilla.org/show_bug.cgi?id=1545263#c10).
| Assignee | ||
Comment 21•6 years ago
|
||
Interesting, if I replace this line https://searchfox.org/mozilla-central/rev/f46e2bf881d522a440b30cbf5cf8d76fc212eaf4/browser/components/preferences/in-content/preferences.js#50:
let frag = MozXULElement.parseXULToFragment(template.firstChild.data);
with:
let frag = document.importNode(MozXULElement.parseXULToFragment(template.firstChild.data), true);
it starts working again. The weird thing is that there are other custom elements in there that do get attached like the sibling menulist (document.getElementById("defaultFont") instanceof customElements.get("menulist") returns true).
| Assignee | ||
Comment 22•6 years ago
|
||
Here's an easier STR for the browser console that doesn't require loading about:preferences (again, this requires the patch here so that customElements.get("menuitem") is defined):
if (document.getElementById("defaultFontSize")) {
document.getElementById("defaultFontSize").remove();
}
var frag = MozXULElement.parseXULToFragment(`
<menulist id="defaultFontSize" delayprefsave="true">
<menupopup>
<menuitem value="9" label="9"/>
</menupopup>
</menulist>
`);
document.documentElement.append(frag);
console.log(document.getElementById("defaultFontSize") instanceof customElements.get("menulist")); // true
console.log(document.getElementById("defaultFontSize menuitem") instanceof customElements.get("menuitem")) // false
Comment 23•6 years ago
|
||
(In reply to Brian Grinstead [:bgrins] from comment #22)
Here's an easier STR for the browser console that doesn't require loading about:preferences (again, this requires the patch here so that
customElements.get("menuitem")is defined):
[...]
These STR don't reflect the issue. document.getElementById("defaultFontSize menuitem") returns null. Changing it to document.querySelector("#defaultFontSize menuitem") it works.
So I'll try with the about:preferences str for now :)
Comment 24•6 years ago
|
||
So I tried and managed to reproduce this, but it's very intermittent and I couldn't catch it on a debugger easily. I'll try a bit harder later.
| Assignee | ||
Comment 25•6 years ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #24)
So I tried and managed to reproduce this, but it's very intermittent and I couldn't catch it on a debugger easily. I'll try a bit harder later.
FWIW I can reproduce basically every time in an opt (+ artifact) build on OSX using STR in Comment 14 + the backout in Comment 20.
Comment 26•6 years ago
|
||
Yeah, I managed to get it on a debug build and I have rr... I have an hypothesis. If in the menuitem custom element constructor or connectedCallback() you define a property (like this.foo = "bar"), does the bug go away?
Comment 27•6 years ago
|
||
(What's happening is that the JS wrapper that gets created in the menu connected callback (when you access this.children via setSelectedIndex get gc'd... I thought it'd be trivial to reproduce in content but haven't found the right test-case yet)
| Assignee | ||
Comment 28•6 years ago
|
||
Adding this.foo = "bar" to both the connectedCallback and the constructor fixes the problem!
| Assignee | ||
Comment 29•6 years ago
|
||
(In reply to Brian Grinstead [:bgrins] from comment #28)
Adding
this.foo = "bar"to both the connectedCallback and the constructor fixes the problem!
To clarify, the problem is fixed when adding it to just the constructor or just the connectedCallback (not needed to add it to both at the same time).
Comment 30•6 years ago
|
||
Eventually this test-case throws a TypeError: document.body.firstElementChild.myFunction is not a function.
If you remove the:
(function() {
let foo = document.body.firstElementChild;
}())
Or do the property dance, it starts working as expected.
The issue is that we create the wrapper with the canonical proto, and then modify its prototype. If we do it in the other order it just works, because of:
Jandem very helpfully pointed out to me that we have a bug on file for this kind of issue (bug 1354015). We do preserve wrappers when you add a property, but not when you change proto.
Well that was fun to debug.
Updated•6 years ago
|
Comment 31•6 years ago
|
||
Comment 32•6 years ago
|
||
| bugherder | ||
Updated•6 years ago
|
Description
•