Gecko 的 New DOM bindings

来源:互联网 发布:nba2k18超帅捏脸数据 编辑:程序博客网 时间:2024/04/20 03:03

原文:http://tech.mozilla.com.tw/posts/1172/gecko-new-dom-bindings

注意:本篇討論 Gecko 內部 DOM bindings 的實作,可能會有比較多的程式碼。

目前網頁的通用語言是 JavaScript,可是主流瀏覽器大多由 C++ 開發實作,DOM bindings 就是一些處理如何從 JavaScript 引擎使用以 C++ 實作的 DOM API 的程式碼。有關 Mozilla 過往的 DOM bindings 的相關資訊,可以參考 Mozilla DOM bindings 的一段歷史。

在此篇文章完成時,Gecko 內部使用最多的還是基於 XPConnect 上所謂的「New style DOM bindings」,使用 ScriptableHelper 來幫助把 XPCOM 元件暴露在網頁上,此方法仍然有一些記憶體管理及速度上的缺點,以及 XPIDL 與 WebIDL 一些語意上的差別,導致各種加速的方法,處理語意問題的 wrapper,都需要手工針對不同的 API 打造。於是有一天在法國巴黎一些開發 DOM bindings 的人集合起來,討論新的方法。詳細可以參考 New DOM bindings 的歷史。

新的 DOM bindings 因為在法國巴黎討論開發出來,所以在早期總是被稱作「Paris Bindings」這個令人困惑的名字。以下我們叫它「WebIDL DOM binding」。它的速度比原有的 XPConnect 快上許多,因為這些 DOM API 其實用不到 XPCOM 的許多功能,透過 WebIDL DOM bindings 可以省掉一些 virtual function 的開銷,還可以省掉 XPCOM 處理 thread 安全的花費,以後透過新的 JIT 技術,從 JavaScript 呼叫 DOM API 甚至可以直接呼叫到 C++ 的實作。最終,可能所有 DOM API 都可以不需要 XPCOM,描述 API 的語言都統一為 WebIDL。

假設我們已經有一個使用 XPConnect 的 binding 存在,要怎麼把它轉成 WebIDL DOM binding 呢?以 WakeLock 為例,首先我們要新增一個新的 WakeLock.webidl 檔案到 dom/webidl 目錄下:

然後把剛剛新增的 WakeLock.webidl 加到 dom/webidl/WebIDL.mk 的 webidl_files 中。

然後我們可以到 objdir/dom/bindings 目錄下打 make WakeLock-example 就會產生出 WakeLock-example.cpp 和 WakeLock-example.h 兩個檔案可以當作範本。最重要的是在 class 的建構子內記得呼叫 SetIsDOMBinding() 。

如果被修改的 class 和 WakeLock 一樣不是活在 mozilla::dom 這個 namespace 下,記得還要修改 dom/bindings 目錄下的 Bindings.conf 這個檔案,裡面是描述各個 interface 的一些特徵:

這樣我們新的 WebIDL DOM binding 就完成一半了!接下來要改一些程式碼,WakeLock 要繼承nsWrapperCache

然後 WakeLock 的實作還要加上兩個 function,都可以在剛剛的範例程式裡面看到,分別是GetParentObject 和 WrapObject,記得 GetParentObject 必須每次都傳回一樣的指標,指向自己的 parent object,而 WrapObject 則直接使用範例裡面的程式碼就可以:

最後要改的地方就是一些 WebIDL 產生出來的 function signature 會和 XPIDL 有些不一樣,有些 function 可以直接沿用,有些會丟例外的 function 就要改用不同的方式來傳回 error code,如:

以上是一些比較大項的修改,還有一些零碎的修改最好還是親自操作一遍比較容易理解,且每個不同的 class 可能都會有各自需要處理的問題,就不一一列出。對於如何使用這個新的 WebIDL DOM bindings 可以參考 MDN 文章 WebIDL bindings。

以上都還在開發中,隨時都可能會改變,文件也還不齊全,有興趣的人可以到 Bugzilla 搜尋「Paris Bindings」、「New DOM Bindings」、「JSClass-based DOM Bindings」或是「WebIDL Bindings」。


0 0