title: 在JavaScript中建立WebAssembly模組例項
date: 2018-3-22 23:58:00
categories: WebAssembly, 翻譯
tags: WebAssembly
source: 原文地址
auther: Lin Clark
在JavaScript中建立WebAssembly模組例項
這是此係列的第一篇文章:
- Creating a WebAssembly module instance with JavaScript
- Memory in WebAssembly (and why it’s safer than you think)
- WebAssembly table imports… what are they?
WebAssembly是在Web上執行程式碼的新方法。有了它,你可以用 C/C++ & Rust 等語言編寫模組,並在瀏覽器中執行它們。
但是,目前模組無法獨立執行。隨著瀏覽器對ES模組化的支援,預計會發生變化。一旦到位,WebAssembly模組將或許可以能夠與其他ES模組使用相同的方式載入,例如,使用<script type="module">
。
但是到目前為止,要在瀏覽器中使用WebAssembly還是需要使用JavaScript包裝的。這將會建立一個模組的例項,之後你的JavaScript就能夠呼叫在WebAssembly模組中定義的方法。
舉個栗子,我們可以看看如何在React中例項化一個WebAssembly模組。 (您可以在此視訊中瞭解更多關於React如何應用WebAssembly的相關內容。)
當使用者載入頁面時,它會以相同的方式啟動。
瀏覽器會先下載JS檔案,此外.wasm檔案也會被Fetch,這個.wasm檔案中包含了WebAssembly的二進位制程式碼
我們需要載入檔案中的程式碼才能執行它。 首先是.js檔案,該檔案承載了React的JavaScript部分。然後,JavaScript將建立一個WebAssembly模組的例項————調解器。
為此,JS將呼叫WebAssembly.instantiate
。
讓我們深入一點探究到底發生了什麼。
我們傳入WebAssembly.instantiate
的第一個引數將是我們在.wasm檔案中獲得的二進位制程式碼。這就是模組程式碼。
所以我們將二進位制檔案提取到緩衝區中,然後作為引數傳入
這使主執行緒可以回到其他工作。主執行緒知道,一旦編譯器編譯完這個模組,它就會通過promise回撥來通知。Promise的resolve會攜帶解析好的模組勝利歸來。
但經過編譯的模組並不是建立例項唯一所需的東西。我認為這個模組就像一本說明書。
這個例項就像是一個試圖用指令書做點什麼的人。為了做到這一點,他們也需要原材料。他們需要能夠與之配合的東西。
這就是WebAssembly.instantiate的第二個引數出場的地方————imports物件。
我將這些進口物品看作是一箱原材料,就像你從宜家那裡得到的那樣。例項使用這些原材料和這些匯入的資源,再 按照指令說明構建一個東西。正如說明手冊所預期的某些原材料一樣,每個模組都需要一組特定的匯入資源。
所以,當你例項化一個模組時,你需要傳遞一個imports物件和附加在imports上的其他東西。每個匯入都可以是以下四種imports中的一種:
- values
- function closures
- memory
- tables
** Values ** 它可以是原始全域性變數的值。 WebAssembly現在支援的唯一型別是整數和浮點數,所以值必須是這兩種型別之一。這將隨著WebAssembly規範中新增更多型別而改變。
** Function Closures ** 它也可以有函式閉包。這意味著您可以傳遞JavaScript函式,然後WebAssembly可以呼叫該函式及閉包中的變數。
這會特別有用!因為目前WebAssembly不能直接呼叫DOM方法。直接訪問DOM在WebAssembly路線圖上,但並沒有成為規範的一部分。
同時你可以做的是傳遞一個JavaScript函式,它可以包含你所需要的DOM操作。然後WebAssembly可以呼叫該JS函式。
** Memory ** 另一種匯入資源是記憶體物件。該物件使WebAssembly程式碼可以模擬手動記憶體管理。記憶體物件的概念容易讓人產生困惑,所以我在下一篇文章中進行了深入探討
** Tables **
最後的型別與安全有關。它被稱為Tables
。它使你可以使用被稱為函式指標的東西。Again,這有點複雜,所以我在本系列的第三部分中解釋它。
下面就是你可以裝載進你的例項的不同種類的imports資源
當 WebAssembly.instantiate
完成了解析,promise狀態轉換為resolved,promise回撥就會進入microtask queue,它攜帶兩件東西:例項和獨立的編譯完成的模組。
返回已編譯的模組的好處是可以快速建立同一模組的其他例項。你所需要做的只是將模組作為源引數傳入。模組本身沒有任何狀態(狀態在例項上)。這意味著例項可以共享已編譯的模組程式碼。
你的例項現在已經裝備齊全並準備好了。它是已編譯的程式碼, 有它的指令手冊,以及它所有的mports資源。你現在可以呼叫它的方法。