XUL が Web Components になったね
XBL が消えたね
Firefox の GUI は長らくMozilla固有のUI技術XMLであるXULでつくられてきたが、これはHTMLに置き換えられた…というのは実は間違っていてXULはWebComponentsに置き換えられた。基幹機能であるXBLが捨てられWebComponentsに置き換えられた。
WebComponentsの先祖みたいなMozilla固有のUI技術XMLであるXULを支える基幹機能であり、Webブラウザに高度な拡張機能のエコシステムをもたらしたXBLがお亡くなりになりました!
— dynamis (でゅなみす/レッサーパンダの人) (@dynamitter) October 10, 2019
したがって、現在のFirefoxのGUIはWebComponentsでいわば再実装されたXULで書かれている。WebComponentsなのでHTMLで書かれていることになる(正しくはXHTML)。
これはFirefoxでchrome://content/browser/browser.xhtml
と打ち込んだ後で、開発者ツールなどで確認することができる。
XUL の WebComponents 構造と XBL 構造を雑に眺めてみる
上述の開発者ツールで、たとえばダウンロードボタンがtoolbarbutton
という要素名なのだが、これはWebComponentsで登録されたものであることは、下記を実行すれば直ちにわかる。
$("#downloads-button") instanceof customElements.get("toolbarbutton")
// => true
クラスの階層構造は、XULとかDOMに関わらない純粋なJavaScriptのテクとして、 下記のようにして追っかけられる。 得られた配列の最後が祖先のクラス(のコンストラクタ)である。
function *hoge(obj) {
for (let proto = obj.__proto__; proto; proto = proto.__proto__) {
yield proto.constructor;
}
}
Array.from(hoge($("#downloads-button")))
// => Array(10) [ MozToolbarbutton(args), MozButtonBase(), BaseText(args),
// BaseControl(args), MozElementBase(), (), (), (), (), Object() ]
実際にこれを実行するとJavaScriptコードへの参照は定義場所へ移動するアイコン が表示されるのでJavaScriptで書かれているクラスに関しては追っていくのは結構簡単だ。
クラス階層を表すと下記の通りとなる。
Object
EventTarget
Node
Element
XULElement
(nsXULElement.h)MozElementBase
(chrome://global/content/customElements.js)BaseControl
(chrome://global/content/customElements.js)BaseText
(chrome://global/content/customElements.js)MozButtonBase
(chrome://global/content/elements/button.js)MozToolbarbutton
(chrome://global/content/elements/toolbarbutton.js)
Object
〜Element
まではDOM要素で共通だ。
HTML要素の場合はHTMLElement
が共通祖先になるが、
XUL要素の場合はあくまでHTMLElement
ではなくXULElement
である。
ちなみにXBL時代の古いFirefoxを使って同様に階層を調べると下記の通りと判明した。
Object
EventTarget
Node
Element
XULElement
(nsXULElement.h)- chrome://global/content/bindings/general.xml#basecontrol
- chrome://global/content/bindings/general.xml#basetext
- chrome://global/content/bindings/button.xml#button-base
- chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton
- chrome://global/content/bindings/button.xml#button-base
- chrome://global/content/bindings/general.xml#basetext
- chrome://global/content/bindings/general.xml#basecontrol
これは意図してやったことだが、
XBL時代の階層をほぼそのままにWebComponentsに移行していることがよくわかる。
BaseControl
以下がかつてXBLであった対応性がよくわかる。
それらのXBLで書かれていたところをJavaScriptに置き換えられたのだ。
興味深いことにXULElement
はネイティブコードのままで変えていない。
設計は変えずに実装方法だけを現代化した、リファクタリングしたというのはすごい。
参考文献
- Brian Grinstead, “The Firefox UI is now built with Web Components”
- Brian Grinstead, “XBL In Firefox”
- Are We XBL Still?
- Firefox/XUL and XBL Replacement - MozillaWiki