wasmerio / wasmer-js

Monorepo for Javascript WebAssembly packages by Wasmer

Home Page:https://wasmerio.github.io/wasmer-js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wasmer-JS running on Node

syrusakbary opened this issue · comments

The JavaScript SDK currently only officially supports running in a browser. This issue tracks what is needed to add NodeJS support.

  • Spawning Web Workers using a data URL (needed for spawning a worker)
  • Requires access to the navigator.hardwareConcurrency API (required by WASIX syscalls - here)

It looks like NodeJS doesn't let you spawn a new worker with a blob URL, so in #399 (ad304b4) I tried encoding the worker.js file as a base64 data URL.

This seems to work fine for NodeJS, but it looks like we run into Cross-Origin Isolation issues in the browser when passing the data URL to new Worker().

According to the spec...

Any same-origin URL (including blob: URLs) can be used. data: URLs can also be used, but they create a worker with an opaque origin.

The concrete error I'm seeing is this (when running wasm-pack test):

Access to script at 'http://127.0.0.1:8000/wasm-bindgen-test' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
data:text/javascript;base64,RXJ..wo=:55 Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: http://127.0.0.1:8000/wasm-bindgen-test

For posterity's sake, here is the change I made:

diff --git a/src/tasks/worker.js b/src/tasks/worker.js
index 18c5b97..e3596d7 100644
--- a/src/tasks/worker.js
+++ b/src/tasks/worker.js
@@ -15,9 +15,7 @@ let handleMessage = async data => {
 globalThis.onmessage = async ev => {
     if (ev.data.type == "init") {
         const { memory, module, id, import_url } = ev.data;
-        const imported = await import(
-            new URL(import_url, self.location.origin)
-        );
+        const imported = await import(new URL(import_url));
 
         // HACK: How we load our imports will change depending on how the code
         // is deployed. If we are being used in "wasm-pack test" then we can
diff --git a/src/tasks/worker_handle.rs b/src/tasks/worker_handle.rs
index 7ff6a6e..46af8c6 100644
--- a/src/tasks/worker_handle.rs
+++ b/src/tasks/worker_handle.rs
@@ -1,7 +1,8 @@
 use std::fmt::Debug;
 
 use anyhow::{Context, Error};
-use js_sys::{Array, JsString, Uint8Array};
+use base64::{engine::general_purpose::STANDARD, Engine};
+use js_sys::JsString;
 use once_cell::sync::Lazy;
 use wasm_bindgen::{
     prelude::{wasm_bindgen, Closure},
@@ -165,12 +166,6 @@ fn import_meta_url() -> String {
 /// A data URL containing our worker's bootstrap script.
 static WORKER_URL: Lazy<String> = Lazy::new(|| {
     let script = include_str!("worker.js");
-
-    let blob = web_sys::Blob::new_with_u8_array_sequence_and_options(
-        Array::from_iter([Uint8Array::from(script.as_bytes())]).as_ref(),
-        web_sys::BlobPropertyBag::new().type_("application/javascript"),
-    )
-    .unwrap();
-
-    web_sys::Url::create_object_url_with_blob(&blob).unwrap()
+    let encoded = STANDARD.encode(script);
+    format!("data:text/javascript;base64,{encoded}")
 });