XUL/XBL Replacement Newsletter 14

This is the fourteenth edition of the XUL/XBL Replacement Newsletter. Since the last edition, we’ve shipped browser.xhtml, started the process of removing the rest of the XUL documents in the tree, and continued to remove more XBL bindings.

Shipping browser.xhtml

As of this week the main browser window is no longer a XUL document. Also, the hidden XUL window (which is used on mac to provide menus when no browser window is visible) has been converted to XHTML. You (hopefully) didn’t notice this change in the UI but it’s the culmination of a lot of work, most notably by Brendan Dahl.

After we got the tree pretty much green with browser.xhtml (~75 bugs tracked mostly on the top-level html metabug and also detailed in newsletter #7), we began a performance investigation. We would have liked to have been able to load the browser window through the regular web-exposed HTML loading path, but investigation showed that getting to first paint in XHTML was slower than in XUL. Specifically, Talos performance tests showed regressions in tests that timed opening new browser windows or restoring the browser on startup.

The main reasons were that in XUL (1) we skip the XML parser in the “warm” startup case which Talos covers, and (2) we begin layout later, after the DOM is ready. We tried a bunch of workarounds for these. For example: making the document nearly empty and importing a shared fragment from JS, preventing early layout by hiding elements or suppressing it from Gecko, changing when various events fire in the document lifecycle. We would see incremental improvements with each approach, but nothing that reached the goal of parity with current performance, which is sensitive to even minor changes in the window opening time.

At the end of the investigation, we had learned enough about the internals here that it seemed viable to expand prototype cache support to XHTML documents as well. So the implementation was moved out of XULDocument and into PrototypeDocumentParser and PrototypeDocumentContentSink. Thanks a lot to Smaug for the guidance and reviews in this process.

I still hold out hope that someday the normal loading path with a bit of tuning will be fast enough for our use-cases, but in the meantime this approach has a few nice benefits:

  • The faster path is now enabled automatically for any chrome:// XHTML document.
  • It nearly emptied out what was left of the XULDocument implementation, which sets the stage for the rest of the XUL document burndown project - more on that below.
  • We could expand support to other chrome document types if we’d like (for instance, SVG).

What’s next? We are planning to migrate the root <xul:window> element to <html>, which will make the Browser Toolbox highlighters work like they do for web content. We’ll also rename the file in tree from browser.xul to browser.xhtml: we were waiting to make sure it stuck before doing any file moves since that can break in-flight patches.

XUL document burndown

We are also starting on a plan to remove all XUL documents from mozilla-central. Based on feedback from a dev-platform post outlining the plan, we are going to adjust it to not focus as much on converting straight to .html and aim for .xhtml for most documents. See the post for more details but from a high level this looks like:

  1. Load all XUL documents as XHTML using the prototype cache. This doesn’t require any file renaming, we will just detect a .xul file and act like it’s .xhtml. This is tracked in Bug 1550801
  2. Delete the XULDocument implementation.
  3. For most files, rename .xul->.xhtml. In this case everything should work identically with the file name changed since it’s already being loaded as such with (1). The main extra task here is to update bug, code, and comments referencing the old file name
  4. For the now-xhtml documents apply cleanups when appropriate. For instance, migrate <xul:window>-><html>, convert ProcessingInstruction stylesheets to <link>, etc. We’d like to automate this as much as possible since there are over 1500 xul documents in the tree.

This work is being tracked in the following metabug.

Binding Removals

There are 33 bindings left, compared to 44 from the last update and 300 from the start of the project. Here’s a list of changes:

XUL/XBL Replacement Newsletter 13

This is the thirteenth edition of the XUL/XBL Replacement Newsletter. Since the last edition, we’ve gotten close to shipping the main browser window as an HTML document, made some platform improvements related to ongoing frontend work, and continued to remove XBL bindings.

Progress towards browser.xhtml

We’ve gotten close to shipping the main browser window as XHTML instead of XUL. In addition to the broader top-level HTML support which is now complete, we filed a new metabug specifically for shipping browser.xhtml.

The biggest piece of work here was Brendan Dahl adding prototype cache support to XHTML documents. With this change we are seeing equivalent performance between browser.xul and browser.xhtml.

As part of that project, he also added <html:template> support to documents loaded with the prototype cache. This is a nice change to bring our chrome UI more in line with the Web platform and gives us a more standard way to lazify DOM creation (there’s a metabug to do so).

The final steps before enabling browser.xhtml are fixing some assertions (1, 2) that surfaced due to nsHTMLDocument being a DOM proxy and XULDocument not being a proxy. Once those are resolved we plan to flip the switch to enable browser.xhtml by default.

Platform improvements

I wanted to mention some platform improvements and code removal related to these projects, and acknowledge the people who’ve worked on them. These are mostly changes that were unblocked by removing in-content XBL and XBL stylesheets, and fixes for bugs we’ve discovered from dogfooding Web Components in the browser chrome.

Binding Removals

There are 44 bindings left, compared to 55 from the last update and 300 from the start of the project. Here’s a list of changes:

XUL/XBL Replacement Newsletter 12

This is the twelfth edition of the XUL/XBL Replacement Newsletter. Since the last edition, we’ve Custom-Element’ified XUL trees, removed a complex XBL platform feature, and removed a bunch of bindings.

XUL trees no longer use XBL

XUL <tree> elements are used for rendering important parts of Firefox, like the Places UI. They are implemented partly in C++ and partly in JS. Though similar functionality and performance can now be achieved in JS alone, the full migration away from this element is a big project that relies on a number of moving parts. Victor Porof has put together a more detailed document outlining the state of things here.

Because of this, we decided it would be helpful to migrate the JS portion of XUL trees out of XBL and into Custom Elements to unblock the XBL removal project. This was after already having removed bindings for child elements over the last few months (including tree-base, treecols, treecol-base, treecol, treecol-image, columnpicker, treerows, and treebody).

One challenge with this element was that it was using XBL <children /> slotting that was hard to work around with light DOM alone. We’d tried to use Shadow DOM on other XBL migrations in the past, but struggled to make it work because we can’t nest a XBL element with <children /> inside of a Shadow DOM <slot />. This means we can only use Shadow DOM if we know there’s never XBL slotted into the element, which is hard to guarantee in the general case. Luckily, <tree>has a templated structure, we’ve de-XBL’ed its children, and instrumented the code at runtime to ensure no unsupported elements are inserted. So this means that <tree> is the now first consumer of Shadow DOM in our chrome Custom Elements.

The migrated source can be seen in the MozTree class in tree.js and the MozPlacesTree class in places-tree.js.

Removing the ability to override the node name in XBL

XBL had a feature which allowed a binding to override the node name of an element. For example, if there was a <tab> element that had <binding display="xul:button"> attached to it, then the element would pretend to be a <button>.This was done by adding the [display="xul:element"] attribute, and also the [extends="xul:element"] syntax which (confusingly) did mostly the same thing.

This feature didn’t have an equivalent in the Web platform, was applied inconsistently inside Gecko, and wasn’t well understood. So Emilio Cobos Álvarez filed bug 1450652 to track the work required to remove it.

Over time, we’ve either removed the bindings using this feature or removed the need for it within the binding. Usually this meant wiring up the proper CSS frame based on the real node name rather than the one defined in XBL, but there were lots of small mysteries to figure out for individual bindings along the way. Last week, Emilio removed the final consumer and also removed the platform implementation.

Binding Removals

There are 55 bindings left, compared to 78 from the last update and 300 from the start of the project. Here’s a list of changes:

XUL/XBL Replacement Newsletter 11

This is the eleventh edition of the XUL/XBL Replacement Newsletter. We’ve continued to make consistent progress removing XBL bindings, and are aiming to get down to 62 bindings by the end of Q1. That will put us on track for the last bindings being removed around Q3.

In-content XBL is gone

As announced in newsletter #8, we created a system called UA Widgets to replace instances of running XBL in the content process. Then as announced in newsletter #10, the final in-content binding was removed and the feature was turned off by default. I’m happy to announce now that in-content XBL has been entirely removed from mozilla-central and the metabug has been closed.

This will allow us to improve the security and performance of content processes in Firefox. Here are some known areas to investigate:

  • Make element JS reflection simpler in the content process since we don’t need to check if they have XBL attached.
  • Rip out all the XBL scope, bindToUntrustedContent, and exposeToUntrustedContent machinery.
  • Disable XBL handling for Stylo in the content process.

If you know of other areas that can be simplified or want to take on some of this work, then please let me know or file a bug depending on the metabug so we can track it.

<browser> is now a Custom Element

The <browser> element is used for rendering the actual web content inside a tab, so it’s quite a complex and important element. After the tabbrowser and videoControls bindings were removed last year, this was the largest remaining binding at around 2000 LOC.

It took a lot of debugging, but after merging together the remote-browser and browser bindings, the converter tool gave a good starting point to get it done. Thanks to Mike Conley for having fun with the review and Neil Deakin for making QueryInterface work properly for this use case. More details can be seen in the bug and in the post to firefox-dev.

This opens up the ability to start looking into creating a build with XBL disabled, since this was the last element in Android using XBL.

Removing some uses of XUL grid layout

Tim Nguyen noticed that within the Firefox UI we have a relatively small number of consumers using XUL grid layout (most often seen as the <grid>, <columns>, <column>, <rows>, and <row> elements). He filed a metabug to track removing them. Long term, doing this will help us migrate our UI to web-exposed layout algorithms, and remove the XUL-specific grid implementation.

After converting a number of them that don’t actually need to be grids to flexbox, the next step was looking into our options for using either CSS grids or CSS table layout for the remainder. It appears that these will have to be put on hold until we ship the XUL flexbox -> CSS flexbox emulation feature, since XUL flexbox children don’t always play nicely inside of non-XUL layouts.

Binding Removals

There are 78 bindings left, compared to 94 from the last update and 300 from the start of the project. Here’s a list of changes:

XUL/XBL Replacement Newsletter 10

This is the tenth edition of the XUL/XBL Replacement Newsletter. Since the last edition, we’ve stopped relying on two major components of the XBL implementation: “in-content” XBL and XBL stylesheets.

Final In-Content XBL Bindings Removed

After recently landing UA Widget alternatives for <marquee>, “plugin problem” UI, and the date / time picker, we don’t need to rely on XBL in the content process anymore. This will allow us to improve the security and performance of the content process in Firefox.

It also makes the widgets themselves simpler, since they’re implemented with more well-known technologies like frame scripts, JS classes, and Shadow DOM (see the in-tree UA Widget docs for more information). There’s DevTools support as well - if you run this command you can see the UA Shadow DOM and <slot> in the Inspector panel:

./mach run 'data:text/html,<marquee>slotted child</marquee>' --devtools --temp-profile --setpref devtools.inspector.showUserAgentShadowRoots=true

The next steps are to enable the UA widget pref by default in release, and then to remove the pref and start tearing out platform support. Barring any unforeseen issues, we expect to enable the pref by default in Firefox 65, and then start removing the feature in a subsequent release.

I’d like to again thank Tim Guan-tin Chien for leading this work, and to the many others who’ve been involved with planning, reviews, and patches. If you have a look at the metabug and graph tracking the number of bindings, you can see the amount of work involved. It took us on a tour of the DOM via scrollbars, video controls (on desktop and android), input fields (filepickers and datepickers), and even to unexpected places like the little resizer thing inside textareas, XML pretty printing and key handling inside input fields.

Final XBL Stylesheets Migrated to Document Sheets

Back in June, Paolo Amadini announced that we were starting the process of migrating our XBL scoped stylesheets to be standard document-level author sheets. This would allow us to remove an extra unspecified CSS cascade level in the style engine, and make it easier for frontend developers to figure out which rule takes precedence over others based only on the specificity.

This work was broken down into individual bugs per stylesheet to make it easier to track regressions. Paolo, Dão Gottwald, and Tim Nguyen have been pushing this forward over the months. Recently, Dão took this over the finish line by converting some of the more tricky sheets (textbox.css, button.css, and toolbarbutton.css). All of the XBL stylesheets in chrome have now either been removed or ported into widgets.css.

We still have some leftovers to take care of before platform support can be removed (including deleting the preffed off in-content bindings as discussed above), but when we remove support it’ll be a significant simplification.

Customizable UI Bindings Removed

It used to be the case that the “Customizable UI” feature, along with many of the toolbars used in the primary browser chrome, required XBL to implement their behavior. Gijs Kruitbosch did a detailed breakdown of the work required to remove this dependency. Most of the bindings were able to be converted into plain JS instead of being attached to DOM nodes. In addition to helping burn down the number of bindings in the browser/ directory, this will give us more control over when to initialize different components during browser startup.

Binding Removals

There are 94 bindings left, compared to 115 from the last update and 300 from the start of the project. Here’s a list of changes: