For JS running in browser.xul, please use children/firstElementChild/lastElementChild instead of childNodes/firstChild/lastChild if you expect to receive elements back

Brian Grinstead bgrinstead at mozilla.com
Mon Aug 13 18:17:46 UTC 2018


We're starting to experiment with loading the main browser document (browser.xul) as an HTML document (browser.xhtml). Expect a separate update with more details about that project soon, but in the meantime I wanted to call out a frontend change that we needed to make to get that running.

In XUL documents, text nodes don't get created by the parser. So, given this markup:
```
<box>
  <label />
</box>
```

`box.firstChild` is the label. However in HTML documents, where text nodes do get created, `box.firstChild` is a whitespace text node (`box.firstElementChild` is the label). Since the majority of our frontend code accesses `firstChild` assuming that it's an element, that means a bunch of the JS/DOM is broken when we introduce text nodes. In Bug 1479125, I landed an initial migration of the relevant callers in browser.xul.

Inconveniently, there are some cases where accessing `firstChild` continues to make sense to use in both XUL and HTML documents. For instance, when dealing with elements that explicitly have added textNodes, or when emptying out a DOM node like `while (box.hasChildNodes()) { box.firstChild.remove();`.

Because of that, it's tricky to write an eslint rule to prevent code from using those APIs. So this is mostly just an ask for help to use the "element" APIs when you are writing or reviewing code that runs in browser.xul. If you notice some callers that were missed, then letting me know or filing a bug blocking Bug 1453783 would be great. Since there's a lot of muscle memory involved and we don't yet have anything running in automation to prevent it, I'm expecting it'll take a few follow ups to get to all callers.

Here's the list of API changes:
  childNodes->children
  firstChild->firstElementChild
  lastChild->lastElementChild
  nextSibling->nextElementSibling
  previousSibling->previousElementSibling

Thanks,
Brian


More information about the firefox-dev mailing list