載入、運行 WebAssembly


在之前的文件中,使用了 Fetch API 來取得 .wasm 檔案,並將 fetch 傳回的 Promise 作為引數,傳遞給 WebAssembly.instantiateStreaming,例如:

WebAssembly.instantiateStreaming(fetch('program.wasm'), importObj)
           .then(prog => {
               console.log(prog.instance.exports.add(1, 2)); 
           });

實際上,WebAssembly.instantiateStreaming 會透過傳入的 Promise 取得儲存著 .wasm 的 ArrayBuffer,然後再進行實例化,因此上例相當於:

fetch('program.wasm')
    .then(response => response.arrayBuffer())
    .then(wasm => WebAssembly.instantiate(wasm, importObj))
    .then(prog => {
        console.log(prog.instance.exports.add(1, 2)); 
    });

也就是說,只要能取得儲存著 .wasm 的 ArrayBuffer,就不一定要使用 Fetch API,例如,透過 XMLHttpRequest 也是可以的:

const request = new XMLHttpRequest();
request.responseType = 'arraybuffer';
request.onload = function() {
    const wasm = request.response;
    WebAssembly.instantiate(wasm, importObj)
               .then(prog => {
                   console.log(prog.instance.exports.add(1, 2)); 
               });
};
request.open('GET', 'program.wasm');
request.send();

WebAssembly.instantiate 可以接受 ArrayBufferTypedArray,傳回值是個 Promise,處理完後會得到一個物件,包含 moduleinstance 兩個特性,前者是 WebAssembly.Module 的實例,代表編譯過後的位元組碼,後者是 WebAssembly.Instance 的實例,代表著模組的可執行形式,具體而言就是包含了模組中被匯出、可被呼叫的函式。

如果只是想要 WebAssembly.Module 的實例,可以使用 WebAssembly.compileStreaming,它可以接受結果為 fetch 傳回的 PromiseWebAssembly.compileStreaming 執行後傳回 Promise,任務完成後可以取得 Module 實例:

WebAssembly.compileStreaming(fetch('program.wasm'))
       .then(module => new WebAssembly.Instance(module, importObj))
       .then(instance => {   
           console.log(instance.exports.add(1, 2)); 
       });

在上面可以看到,若想進一步建立 Instance,是將 Module 實例做為引數。實際上,WebAssembly.compileStreaming 會取得 ArrayBuffer,然後使用 WebAssembly.compile 來編譯、生成 Module 實例,也就是上例相當於:

fetch('program.wasm')
    .then(response => response.arrayBuffer())
    .then(wasm => WebAssembly.compile(wasm))
    .then(module => new WebAssembly.Instance(module, importObj))
    .then(instance => {   
        console.log(instance.exports.add(1, 2)); 
    });

如同若手中已經有個 Module 實例,可以用來建構 WebAssembly.Instance 實例,若手中已經有個 ArrayBuffer,也可以用來建構 WebAssembly.Module 實例:

const module = new WebAssembly.Module(wasm);

直接建構 WebAssembly.InstanceWebAssembly.Module 實例,與使用 WebAssembly.compile()WebAssembly.instantiate() 等 API 的差別是,後者會傳回 Promise,而結果是直接取得 WebAssembly.InstanceWebAssembly.Module 實例。

如果想要驗證 WebAssembly 二進位內容是否正確,可以使用 WebAssembly.validate 方法。