XUL/XBL Replacement Newsletter 16

This is the sixteenth edition of the XUL/XBL Replacement Newsletter. Since the last edition, we’ve removed the XULDocument implementation and have been helped with XBL removal by two big projects completed by other teams. We’re getting close to finishing the burndown of XBL bindings and are doing some prep work to allow building Firefox without the XBL implementation once that happens.

XULDocument is gone

Over the course of the last year we’ve been working through a plan to remove XUL documents from mozilla-central. We first reviewed all the functionality in XULDocument, then removed obsolete features and migrated ones we wanted to keep into the base Document or into standalone pieces. By the end of July, XULDocument was mostly a skeleton and Brendan Dahl landed a patch that caused all .xul files to be loaded exactly as if they were .xhtml files. After a few weeks with no issues, he removed the XULDocument implementation entirely.

While XULDocument is now gone, there’s still plenty of work to be done to old XUL files:

  • The file extension is still .xul so those files will need to be converted to .xhtml. Since they are already loaded as such, this should involve only renaming files.
  • Most still contain a “XUL like” DOM structure (<window>), whereas we’d rather them be more like regular HTML documents (<html><head><body>). By making our consumers more standardized with the web, they’ll be easier to understand for the uninitiated, allow tooling to work more easily, and let us remove more special case code we have for XUL document elements.

Old about:addons removal

The old about:addons page had the largest block of remaining XBL with 10+ unique bindings. The addons team also wanted to add some new features to about:addons, like abuse reporting and inline recommendations. We met last year to coordinate plans for the page and it became clear that the best way to accomplish both of these goals would be to rewrite the old UI with an updated HTML version.

We knew we’d like it to be done mid-year in order to line up with progress on XBL removal, and I’m happy to report that the addons team has now shipped the new version in Firefox 68, which allowed us to remove the bindings. Thanks to everyone who helped to get the new page shipped on time, especially Mark Striemer, Luca Greco, Rob Wu, and David Durst.

Old URL bar removal

Another project that allowed us to remove a number bindings landed in Firefox 68. QuantumBar is a rewrite of the AwesomeBar which makes experimentation and maintenance easier. It’s also built with HTML/JS instead of XUL/XBL, so after it shipped the team was able to remove quite a few bindings (including the most complex remaining binding: legacy-urlbar). Thanks to everyone who worked on this, especially Marco Bonardo, Dão Gottwald, Drew Willcoxon, Harry Twyford, and Mike de Boer.

Binding Removals

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

XUL/XBL Replacement Newsletter 15

This is the fifteenth edition of the XUL/XBL Replacement Newsletter. Since the last edition we’ve been working to incorporate more web standard code into the browser frontend, and converted some particularly complex XBL bindings to Custom Elements.

CSS Shadow Parts

With XBL, direct descendant CSS selectors are able to traverse the anonymous content boundary. For instance, if dropmarker has some anonymous content like: <content><image class="dropmarker-icon" /></content>, then the icon could be selected from a document stylesheet with: dropmarker > .dropmarker-icon. This is handy and we’ve relied on it all over the place, but can be confusing: it’s not always clear when reading the CSS if you are working with anonymous or explicit content. Also, it’s unsound in the presence of dynamic changes to the DOM, and fixing that in the style engine would be very complicated.

Previously, we didn’t have a way to do this with Shadow DOM. Because of that, we would often convert bindings to use explicit DOM children instead of Shadow DOM (using appendChild etc in the connectedCallback) so that we could continue to style contents from our stylesheets. The CSS Shadow Parts specification aims to close this gap. With Shadow Parts you can expose an element in the Shadow DOM like: <image part="icon"> and then target it from CSS with syntax like: host-element::part(icon).

Emilio Cobos Álvarez has added partial support for this feature in bug 1505489, and we recently started using it in our first chrome Custom Element. Here’s the changeset that shows what that consumer looks like. We are planning to keep working with it in order to provide usage feedback to the standards process, and also to convert XBL bindings that need to use Shadow DOM and are also extensively styled from document sheets (like arrow panels).

Box object removal

XUL box objects were helper objects used to implement some layout features that could be tailored to the specific layout used by an element. Replacements for box object properties are generally available as web standard properties like getBoundingClientRect, screenX, and screenY.

Neil Deakin has now completely removed this feature. Frontend code was migrated to use the standard properties when possible. For cases where there is no standard property, the functionality has been moved to specific XUL element subclasses.

Binding Removals

There are 25 bindings left, compared to 33 from the last update and 300 from the start of the project. We also have a bug on file for every remaining XBL binding and are looking forward to a big drop after the upcoming merge to 70, once the old about:addons and old awesomebar code gets removed.

Here’s a list of changes since the last update:

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: