[譯]使用JavaScript建立WebAssembly模組例項

xlaoyu發表於2018-03-31

作者:Lin Clark
譯者:xlaoyu
英文原文:Creating a WebAssembly module instance with JavaScript

轉載請註明出處,保留原文連結以及作者資訊


這是 WebAssembly 使用系列介紹的第一篇文章:

  1. 使用JavaScript建立WebAssembly模組例項
  2. 安全的WebAssembly記憶體操作
  3. WebAssembly的匯入型別 table 到底是什麼?

WebAssembly 是一種在瀏覽器中執行程式碼的新方法。通過這項新技術,我們可以使用 C 或 C++ 等語言編寫模組然後執行在瀏覽器中執行它們。

儘管當前這些模組無法直接執行,但是隨著瀏覽器對 ES6 模組規範的逐步支援,這將會有所改變。一旦這一天到來,我們將可以像載入 ES 模組那樣去載入 WebAssembly 模組,比如使用<script type="module">標籤載入。

目前為止,我們需要使用 JavaScript 來啟動 WebAssembly 模組。首先建立一個模組例項,然後通過再呼叫該 WebAssembly 模組例項上的函式。

(原文提供了一個在 React 中使用 WebAssembly 的視訊,因為需要梯子才能觀看,這裡忽略了)

瀏覽器會先下載 JS 檔案,然後在 js 中去載入 .wasm 檔案(包含 WebAssembly 程式碼的二進位制檔案)。

file-download

檔案載入回來後,我們呼叫 WebAssembly.instantiate 方法去例項化 WebAssembly 模組得到一個**WebAssembly例項**。

[譯]使用JavaScript建立WebAssembly模組例項

我們來詳細看看 WebAssembly.instantiate方法的使用,

Promise<ResultObject> WebAssembly.instantiate(bufferSource, importObject);

// or
Promise<WebAssembly.Instance> WebAssembly.instantiate(module, importObject);
複製程式碼

第一種情況的返回結果**ResultObject**物件包含兩個欄位:

  • module - WebAssembly 模組物件表示經過編譯的 WebAssembly 模組,可以重複例項化。
  • instance - WebAssembly 例項包含了 WebAssembly 模組所有的輸出函式。第二種方式的返回值就是這個物件。

bufferSource是我們準備例項化的包含 .wasm 模組二進位制程式碼的 typed arrayArrayBuffer

譯者注:新版 WebAssembly 新增了 instantiateStreaming() 方法,可以直接使用流進行例項化,配合 Fetch API 一起使用可以更進一步提升效能。

instantiate

JS 引擎會把模組程式碼編譯為針對當前瀏覽器執行機器的程式碼。顯而易見的是,我們不希望這個過程在主執行緒中發生,因為主執行緒就像一個全棧開發那樣需要處理 JavaScript 程式碼、DOM 事件和頁面重繪,我們不能讓編譯阻塞了主執行緒的執行,所以 WebAssembly.instantiate 是返回一個 promise。

promise

通過使用 promise 非同步編譯,主執行緒可以繼續執行其餘的工作。編譯工作一旦完成,promise 會通知主執行緒從 promise 結果中獲取例項。

從上面 instantiate 方法的使用用例可以看到,模組原始碼並不是建立例項唯一需要的東西,還有第二個引數 importObject。我們可以把 WebAssembly 模組看做是一本說明書,例項物件是一個人,此時人需要根據說明書去做某些事情,所以對應的,他們還需要原材料。

book

我們直接把 WebAssembly 模組看作 ES6 模組,這個模組暴露了很多方法,而這些方法有些需要入參,而在 WebAssembly 模組中,我們把這些引數放在 importObject 中傳入。 (原文作者在這裡舉了一個在宜家買東西組裝的?,因為過於抽象,譯者替換為使用 ES6 模組來說明)

meterial

所以當我們例項化一個模組時,我們把需要傳入模組的內容掛在 importObject 上,這些內容可以是以下四種型別之一:

  • values
  • function closures
  • memory
  • tables

Ps:這裡四個單詞不作翻譯了,感覺強行翻譯就類似於要把 JAVA 翻譯成中文一樣,o(╯□╰)o。

Values

普通值,一般來說是全域性變數。目前 WebAssembly 模組只接收整數和浮點數,所以值必須是這兩種型別之一。將來有可能會增加支援更多的型別。

Function closures

閉包函式,這表示能把 JavaScript 函式傳進去,然後在 WebAssembly 呼叫這些函式。

在當前 WebAssembly 版本中這個特性尤其有用,因為當前我們不能在 WebAssembly 程式碼中直接進行 DOM 操作。此特性可能未來會加入,但是現在還沒有支援。

Memory

memory 物件使 WebAssembly 程式碼可以模擬手動記憶體管理。由於這個物件的概念比較容易讓人產生困惑,尤其是沒有接觸過記憶體管理的純前端開發人員,所以將在下一篇文章(第二篇系列文章)中詳細講解。

Table

最後一個型別是與安全相關的,它能使我們去操作一種叫 函式指標 的東西,將在第三篇文章中詳細說明。

all

一旦 WebAssembly.instantiate 執行完成,我們從已經 resolved 的 promise 中可以獲取到兩樣東西:例項(instance)和編譯完成的模組物件(module)。

編譯模組的好處是可以快速建立同一模組的其他例項。你所做的就是將模組作為 source 引數傳入。模組本身沒有任何狀態(全部附加到例項)。這意味著例項可以共享已編譯的模組程式碼。

你的例項現在已經裝備齊全並準備好了。它有它的指導手冊,它是編譯的程式碼,以及它的所有輸入物件。我們終於可以呼叫它的方法了。??

run

下篇文章主要解釋 Memory 到底是什麼東西以及怎麼使用。

相關文章