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}")
});