ข้ามไปยังเนื้อหา

JS Interop & การโหลด

WebAssembly ไม่สามารถทำงานได้โดยลำพัง ทำงานอยู่ภายใน host environment เสมอ และบนเว็บนั้น host ก็คือ JavaScript ฝั่ง JS มีหน้าที่ดึงข้อมูล bytes จากไฟล์ .wasm คอมไพล์ให้กลายเป็น WebAssembly.Module สร้าง instance ของ module นั้นพร้อมกับ imports ที่จำเป็น และในที่สุดก็เรียกฟังก์ชันที่ module เปิดเผยออกมา ส่วน Wasm นั้นอาศัยอยู่ในสภาพแวดล้อมหน่วยความจำที่ถูก sandbox อย่างเข้มงวด — ไม่สามารถเข้าถึง DOM, เครือข่าย หรือ browser API ใด ๆ ได้เลย เว้นแต่ JavaScript จะส่งฟังก์ชันที่ทำสิ่งนั้นมาให้

ความสัมพันธ์ระหว่าง JS และ Wasm นั้นมีเจตนาและชัดเจน ก่อนที่โค้ด Wasm ใด ๆ จะทำงาน JavaScript ต้องเตรียม imports object — JS object ธรรมดาที่มี keys ตรงกับการประกาศ import ภายใน module WAT

imports เหล่านั้นอาจเป็นฟังก์ชัน JS, instance ของ WebAssembly.Memory, instance ของ WebAssembly.Global หรือ instance ของ WebAssembly.Table ก็ได้ ในทางกลับกัน เมื่อ module ถูก instantiate แล้ว JS จะได้รับ object instance.exports กลับมา ซึ่งประกอบด้วยทุก symbol ที่ module เลือกจะ export ออกมา

flowchart LR
  JS["JavaScript (host)"]
  COMPILE["WebAssembly.instantiate(bytes, imports)"]
  IMPORTS["imports object
(functions, memory, globals)"]
  MODULE["WebAssembly Module"]
  EXPORTS["instance.exports
(functions, memory, globals)"]

  JS -->|"fetch .wasm bytes"| COMPILE
  JS -->|"provides"| IMPORTS
  IMPORTS --> COMPILE
  COMPILE --> MODULE
  MODULE -->|"exposes"| EXPORTS
  EXPORTS -->|"JS calls exports"| JS
The JS ↔ Wasm boundary

module WAT ด้านล่าง export ฟังก์ชันเดียวชื่อ greet ที่ไม่รับอาร์กิวเมนต์และคืนค่าจำนวนเต็ม 42 ฝั่ง JavaScript คอมไพล์ bytes สร้าง instance ของ module ด้วย imports object ว่าง {} และเรียก instance.exports.greet()

(module
(func (export "greet") (result i32)
i32.const 42))
const bytes = await compileWat(wat);
const { instance } = await WebAssembly.instantiate(bytes, {});
console.log('greet() =', instance.exports.greet()); // 42
WebAssembly
JavaScript ส่งอะไรให้ Wasm module ตอน instantiate?
JS API ใดที่ใช้ instantiate โมดูล Wasm ที่คอมไพล์แล้ว?
Wasm สามารถเรียก DOM APIs โดยตรงได้หรือไม่?