wasmedge-quickjs icon indicating copy to clipboard operation
wasmedge-quickjs copied to clipboard

Run as a Cloudflare worker

Open tysonrm opened this issue 3 years ago • 14 comments

  • [ ] Cloudflare recently added support for Wasm and offers a Rust SDK with compile target wasm32-unknown-unknown. Certain JS language features, like eval(), which are disabled in the web worker for security reasons, could run safely in the wasm sandbox as embedded js, using quickjs. Naturally, the target for wasmedge_quickjs is wasm32-wasi, given the purpose is to embed js in the wasmedge runtime.

tysonrm avatar Dec 18 '21 20:12 tysonrm

Thanks. I have not tried this. But can you take a few serverless function examples from cloudflare workers docs / examples, and try them in WasmEdge_quickjs? I am curious if they can run.

juntao avatar Dec 22 '21 09:12 juntao

Got this to work after removing http and sockets libs and setting target to wasm23-u-u. Then setting [dependencies] of Cargo.toml of the worker template to: wasmedge_quickjs = { git = "https://github.com/tysonrm/wasmedge-quickjs", package="wasmedge_quickjs" }. Will add some sample code...

tysonrm avatar Dec 22 '21 11:12 tysonrm

Almost...need to get rid of imports / provide impl for some std libs... https://github.com/tysonrm/rustwasm-worker-template

use serde_json::json;
use wasmedge_quickjs::*;
use worker::*;

mod utils;

fn js_hello(ctx: &mut Context) {
  println!("\n<----run_simple_js---->");
  let code = r#"print('hello quickjs')"#;
  let r = ctx.eval_global_str(code);
  println!("return value:{:?}", r);
}

#[event(fetch)]
pub async fn main(req: Request, env: Env) -> Result<Response> {
  let mut ctx = Context::new();
  js_hello(&mut ctx);

Uncaught Error: LinkError: WebAssembly.Instance(): Import #41 module="env" function="fopen" error: function import requires a callable at line 0 [API code: 10021]

tysonrm avatar Dec 22 '21 14:12 tysonrm

If it's possible to provide bindings to cloudflare for io that would most likely do the trick.

With emscripten and quickjs, I can get code to execute but as soon as I attempt to add host functions at runtime, like “fetch” with VM.newFunction - cloudflare throws assertion errors because I cannot instantiate WASM from a unit8array (the host2cCallback)

rust is advantageous because you can declare bindings easily during build. Doing this in C, I’d imagine I’d have to take the host callback and somehow generate a WASM file, then deploy it up independently.

ScriptedAlchemy avatar Dec 28 '21 07:12 ScriptedAlchemy

Hi @ScriptedAlchemy

Could you elaborate what kind of Cloudflare I/O bindings we should implement? Sorry I am not very familiar with the Cloudflare setup. WasmEdge provides a networking socket API, and can support host functions (wrappers) to interact with external systems. We would love to make it work with Cloudflare. :)

Cheers Michael

juntao avatar Dec 28 '21 09:12 juntao

If you have any time for a call with @tysonrm and myself, and we would jump at the opportunity to work together.

These binding would cover all Io on CF. Mainly we need fetch, request, response. But most importantly would be fetch capabilities https://github.com/cloudflare/workers-rs

ScriptedAlchemy avatar Dec 28 '21 10:12 ScriptedAlchemy

So here's a workaround: we can have a js worker instantiate quickjs and pass in a js function it can call to invoke fetch. As for the rust solution, under the hood its actually js based anyway. It's just a js worker that instantiates the wasm module. This will change when they roll out their wasi based solution, but we are already set up for that.

tysonrm avatar Dec 28 '21 19:12 tysonrm

Hi @ScriptedAlchemy and @tysonrm

Thank you so much for your ideas and experiments. Perhaps we can schedule a call to discuss these in the first week of the new year?

The Cloudflare Rust crate is designed to be compiled into wasm, right? Are we trying to run their compiled wasm bytecode in WasmEdge? Or do we plan to use the WasmEdge APIs in Cloudflare's v8 runtime?

Cheers Michael

juntao avatar Dec 28 '21 22:12 juntao

A call would be great. Thanks, Michael. Yes, the crate compiles to wasm. Our goal right now is the latter. That said, they are also looking at supporting a wasm based runtime.

  • [ ] Cloudflare recently added support for Wasm and offers a Rust SDK with compile target wasm32-unknown-unknown. Certain JS language features, like eval(), which are disabled in the web worker for security reasons, could run safely in the wasm sandbox as embedded js, using quickjs. Naturally, the target for wasmedge_quickjs is wasm32-wasi, given the purpose is to embed js in the wasmedge runtime.

tysonrm avatar Dec 29 '21 02:12 tysonrm

I also spoke with jake the maintainer of wuickjs emscripten. Who gave me a snippet to add extra bindings to C during compile time. Like console log so wasm comes out the box with extra host bindings. Not sure about fetch though.

Is there a better way we can coordinate a time to chat? Slack? Email?

We are highly motivated to see this through. Combined with our work on module federation, if we have quick + edge workers + module federation, we can essentially compute any code without any deployment or software installation ahead of time.

This would effectively nullify the need for AWS for a large portion of users.

With quick and cloudflare + federation. I can host about 1 million unique codebases with 0.5ms startup time per worker.

Compared to aws, which takes 1200ms to cold start a lambda - we can create about 1,000 environments and respond to 1000 requests to each env in less time than it takes to start that aws lambda.

We can update any codebase or part of it on the fly without ever redeploying or binding software to a specific deploy time artifact.

The largest roadblock we face on edge network is I cannot fetch() inside quick because of host function binding at runtime vs create bindings for fetch() at build time.

As Tyson said, edge providers disable certain code generation capabilities in V8, but if I don't use v8 I am not confined by their limits and it's far more secure. We can also have an edge worker execute up to 25mb of js through our mechanism compared to cloudflares 1mb limit they have today.

ScriptedAlchemy avatar Dec 29 '21 08:12 ScriptedAlchemy

Sure. My email is [email protected]

You can find me using the same email on Slack. I can see @tysonrm on CNCF's Slack. @ScriptedAlchemy if you are in CNCF slack too, we can form a channel. :)

juntao avatar Dec 29 '21 17:12 juntao

So here's a workaround: we can have a js worker instantiate quickjs and pass in a js function it can call to invoke fetch.

Hey, @tysonrm any rough code example on how this would work?

rishabhc32 avatar Jan 08 '22 20:01 rishabhc32

Sorry for the long delay. The code at this link shows Node.js instantiating a wasm module whose imports include a function that publishes events to an event broke nning in Node.js.

tysonrm avatar Feb 23 '22 18:02 tysonrm

Did this ever get sorted? Very interested in this too

danthegoodman1 avatar Jan 02 '23 19:01 danthegoodman1