Loading and running WebAssembly code

자바 스크립트에서 WebAssembly를 사용하려면 먼저 컴파일 / 인스턴스화 전에 모듈을 메모리로 가져와야합니다. 여기서 WebAssembly 바이트 코드를 가져 오는 데 사용할 수있는 다양한 메커니즘에 대한 참조와 함께 컴파일 / 인스턴스화 및 실행 방법에 대해 설명합니다.

뭐가 문제인가요 ?

WebAssembly는 아직 <script type='module'> 또는 ES2015 import statements와 통합되어 있지 않으므로 imports를 사용하여 브라우저에서 가져올 방법이 없습니다.

이전의 WebAssembly.compile / WebAssembly.instantiate 메소드를 사용하려면 WebAssembly 모듈 바이너리를 포함하는 ArrayBuffer를 생성해야합니다. 원시 바이트를 가져온 다음 컴파일 / 인스턴스화합니다. 이것은 new Function(string)과 유사합니다. 단, 문자열 (JavaScript 소스 코드)을 바이트 배열 버퍼 (WebAssembly 소스 코드)로 대체한다는 점만 다릅니다.

최신 WebAssembly.compileStreaming/WebAssembly.instantiateStreaming 방법이 훨씬 더 효율적입니다. 네트워크에서는 ArrayBuffer 단계가 필요하지 않게 하면서 직접 바이트의 원시 스트림에 대한 작업을 수행합니다.

그러면 어떻게 이 바이트를 어레이 버퍼에 넣고 컴파일할 수 있을까요? 다음 단원에서 설명합니다.

Using Fetch

Fetch는 네트워크 리소스를 가져 오는 편리한 최신 API입니다.

wasm 모듈을 가져오는 가장 빠르고 효율적인 방법은 새로운 WebAssembly.instantiateStreaming() 방법을 사용하는 것입니다. 이 method는 첫번째 인수로 fetch() 호출을 수행할 수 있는 메서드이며, 서버에서 스트리밍할 때 원시 바이트 코드에 액세스하면서 모듈 가져오기, 컴파일 및 인스턴스화를 한 번에 처리합니다.

js
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject).then(
  (results) => {
    // Do something with the results!
  },
);

직접 스트림에서 작동하지 않는 이전 WebAssembly.instantiate 메서드를 사용한 경우에는 가져온 바이트 코드를 ArrayBuffer 로 변환하는 추가단계가 필요합니다.

js
fetch("module.wasm")
  .then((response) => response.arrayBuffer())
  .then((bytes) => WebAssembly.instantiate(bytes, importObject))
  .then((results) => {
    // Do something with the results!
  });

Aside on instantiate() overloads

WebAssembly.instantiate() 함수에는 두 가지 오버로드 양식이 있습니다. 위에 표시된 형식은 바이트 코드를 인수로 컴파일하여 컴파일된 모듈 객체가 포함된 개체로 resolve되는 'promise'을 반환합니다. 개체는 다음과 같습니다.

js
{
  module: Module; // The newly compiled WebAssembly.Module object,
  instance: Instance; // A new WebAssembly.Instance of the module object
}

참고: 일반적으로 인스턴스자체만 신경 쓰지만, 모듈을 캐시하거나, postMessage()를 통해 다른 worker나 윈도우와 공유하거나, 단순히 인스턴스를 더 생성하고자 할 때도 유용합니다.

참고: 두 번째 오버로드 형식은 WebAssembly.Module 객체를 인수로 사용하여 인스턴스 객체를 직접 포함하는 promise를 결과로 반환합니다. Second overload 예제를 참조하십시오.

Running your WebAssembly code

JavaScript에서 WebAssembly 인스턴스를 사용할 수있게되면 WebAssembly.Instance.exports 속성을 통해 내 보낸 속성을 사용할 수 있습니다 . 코드는 다음과 같습니다.

js
WebAssembly.instantiateStreaming(fetch("myModule.wasm"), importObject).then(
  (obj) => {
    // Call an exported function:
    obj.instance.exports.exported_func();

    // or access the buffer contents of an exported memory:
    var i32 = new Uint32Array(obj.instance.exports.memory.buffer);

    // or access the elements of an exported table:
    var table = obj.instance.exports.table;
    console.log(table.get(0)());
  },
);

참고: WebAssembly 모듈에서 내보내는 방법에 대한 자세한 내용은 Using the WebAssembly JavaScript APIUnderstanding WebAssembly text format를 참조하십시오.

Using XMLHttpRequest

XMLHttpRequest는 Fetch보다 다소 오래된 방법이지만 형식화 된 배열을 얻는 데 부족함이 없습니다. simple.wasm을 그대로 사용하여 진행하겠습니다.

  1. 새로운 XMLHttpRequest() 인스턴스를 만들고 open() 메서드를 사용하여 요청을 열고 요청 메서드를 GET으로 설정합니다. , 가져올 파일의 경로를 선언하십시오.
  2. 핵심 부분은 responseType 속성을 사용하여 응답 유형을 'arraybuffer'로 설정하는 것입니다.
  3. 그런 다음 XMLHttpRequest.send()을 사용하여 요청을 전송합니다.
  4. 그런 다음 응답이 다운로드 완료되면 함수를 호출하기 위해 onload 이벤트 핸들러를 사용합니다. 이 함수에서는 response 프로퍼티를 생성 한 다음, Fetch와 마찬가지로 WebAssembly.instantiate() 메소드로 넘겨 줍니다.

최종코드는 다음과 같습니다.

js
request = new XMLHttpRequest();
request.open("GET", "simple.wasm");
request.responseType = "arraybuffer";
request.send();

request.onload = function () {
  var bytes = request.response;
  WebAssembly.instantiate(bytes, importObject).then((results) => {
    results.instance.exports.exported_func();
  });
};

참고: xhr-wasm.html 에서도 예제를 확인할 수 있습니다.