XUL/XBL Replacement Newsletter 7

This is the seventh edition of the XUL/XBL Replacement Newsletter. Since the last edition, we’ve gotten some tooling improvements, landed an experimental HTML browser window and removed a bunch of listbox code.

Web Components Support in DevTools

As you may have heard, Custom Elements and Shadow DOM are riding the train for 63. The DevTools team has also done a lot of work to make sure we have good tooling for these features.

One of these features that I’d like to mention is called “Show Custom Element definition”. A badge appears next to a Custom Element in the Inspector, and when you click on that it takes you directly to your Custom Element class in the Debugger. This also works in the Browser Toolbox and can be seen on any of the Custom Elements we currently ship in the browser window. For example: search for “moz-input-box” nodes in the Inspector to try it.

This highlights some benefits to using web standard tech within the Firefox frontend. We get to use the same DevTools features that we’re shipping to web devs. And (at least in my experience) Firefox devs are quite likely to give feedback and file bugs on tools, which ends up improving those same features.

Finally, I’d like to point out that coordinating the release of a complex platform feature and tooling to go with it is hard to do. It takes a lot of planning and cooperation between the the DOM and DevTools teams. Thanks to Julian Descottes, Belén Albeza, Emilio Cobos Álvarez, Jim Blandy, and many others for making this happen.

browser.xhtml

The main browser window is currently a XUL document with (mostly) XUL elements in the DOM. We’d ultimately like to support an HTML document with (mostly) HTML elements in the DOM. That’s a long road, though. One milestone we hope to hit along the way is loading an HTML document with (mostly) XUL elements in the DOM.

Practically, this can be done by loading a browser.xhtml file with the same markup as browser.xul. This will allow us to audit and fix issues affecting top-level HTML windows without rewriting the browser window from scratch. And since we have a large suite of browser tests to track progress against, we can be pretty confident about what’s working and what’s still broken. We’ll be tracking that in the top-level HTML metabug

An experimental version of this has now landed. you can try it out by adding this to your .mozconfig file: mk_add_options 'export MOZ_BROWSER_XHTML=1'. It’s worth calling out some of the changes we made to set thi up, so I’ve split them into two groups below.

First group: burning down XULDocument.webidl so that the browser JS doesn’t rely on XUL-specific APIs. This is now finished - see the webidl file when we started vs now. Here are some notable changes:

  • Migrated all calls of document.persist to Services.xulStore.persist (bug 1476030, firefox-dev post).
  • Removed document.width and document.height from XULDocument (bug 1475305).
  • Moved document.getElementsByAttribute[NS] from XULDocument to ParentNode, so it supports all chrome documents and elements (bug 1475342).
  • Moved popupNode, popupRangeParent, popupRangeOffset, and tooltipNode from XULDocument to Document (bug 1480206).
  • Removed addBroadcastListenerFor and removeBroadcastListenerFor (bug 1482170).

Second group: adapting the frontend to work while running inside of an HTML document. This is ongoing, here are some of the changes so far:

  • Added support for XUL Custom Elements inside of chrome HTML documents (bug 1480465).
  • Rewrote callers of document.createElement in browser JS to document.createXULElement to explicitly construct XUL elements even when the document namespace is HTML (bug 1479050).
  • Updated all references to “browser.xul” to `AppConstants.BROWSER_CHROME_URL, which lets us change the URL in one place (bug 1476333, firefox-dev post).
  • XUL documents drop whitespace when parsing, so we frequently refer to APIs like node.firstChild and assume it’s an element. For that to work in HTML documents callers were rewritten as node.firstElementChild (bug 1479125, firefox-dev post).
  • Stopped using <broadcaster> and <observer> (which only work in XUL documents) in browser.xul (bug 1479908).

Thanks to everyone who’s helped with planning, patches, and reviews so far. In particular I’d like to acknowledge Brendan Dahl and Mossop for pushing this forward.

Listbox Removal

We don’t have any <listbox> elements in Firefox anymore. If that sounds surprising, like saying “we don’t have any buttons in Firefox anymore”, there’s a distinction to be made as we still use a lot of lists in the UI.

Previously, there were two main widgets to choose from when rendering a list in chrome: <listbox> and <richlistbox>. Richlistbox is more powerful and more “webby”, and over the course of time most of the UI was updated to use it. Listbox relied on custom layout code to guarantee that the height of a list was a multiple of the height of a row, and handle scrolling differently. This can be useful, but it just wasn’t required for the remaining consumers.

Since only a few <listbox> elements were left, it was a pretty easy decision to remove it and unify on a single list widget. Being able to support just richlistbox lets us focus effort on it and makes it easier to decide what to use when adding new UI. It also allowed us to delete around 3K lines of platform code and 2K lines of frontend code.

Finally, it’s worth mentioning that the <tree> element is implemented similarly to <listbox>, but with more features. This element is on our radar for replacement in the coming year, but it will be more work because we have many instances of trees in Firefox and those UIs are more complex and performance sensitive than listboxes.

Binding Removals

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