Using Deno runtime as a v8 isolate runner
Deno is awesome, not just the end product but also the core runtime. I've spend the past couple of weeks off-and-on diving into the codebase and learning how the system works. It's fantastic.
I have a rust application and I would like to run arbitrary javascript code within v8 isolates. The challenge is that I would need to implement and provide all of the web runtime APIs (Fetch, Stream, etc) to support the javascript code. So I began to wonder if I could use Deno for this?
As I have ascertained thus far, the core runtime is structured to bootstrap a worker and then run a javascript module within. I'm hoping someone could simply point me in the direction for how I might do the following:
1 - Initialize a v8 isolate with the Deno runtime + ops, from a snapshot
2 - Inject javascript into the isolate that exports one or more functions
3 - Call one or more of those functions from within rust
4 - Retrieve the response
5 - Shut down the isolate
Perhaps this is already possible with the Worker api, I'm just trying to wrap my head around it.
Also, I'm not looking for this to be a supported feature and I understand that the core runtime API will change from time-to-time, use at my own risk, etc.
Much appreciation in advance!
3 Replies
Based on the documentation, it seems like you're on the right track with your approach. Deno's core runtime is indeed designed to bootstrap a worker and run a JavaScript module within it.
To achieve your goals, you might find the "Roll your own JavaScript runtime" blog post particularly useful. This post walks through creating a custom JavaScript runtime, which is essentially what you're trying to do. It demonstrates how to create a CLI that executes JavaScript files, which is similar to your goal of running arbitrary JavaScript code within V8 isolates.
Here's a rough outline of how you might approach this, based on the documentation:
1. Initialize a V8 isolate with the Deno runtime + ops, from a snapshot: The documentation explains how to add the
deno_core
and tokio
dependencies to your project, which are necessary for creating a JavaScript runtime. The deno_core
crate abstracts away interactions with the V8 JavaScript engine, and tokio
is an asynchronous Rust runtime that you can use as an event loop. Together, these allow JavaScript's Promise
s to be easily mapped onto Rust's Future
s.
2. Inject JavaScript into the isolate that exports one or more functions: The documentation provides an example of how to write an asynchronous Rust function that creates an instance of JsRuntime
, which is responsible for JavaScript execution. You can use this to inject JavaScript into the isolate.
3. Call one or more of those functions from within Rust: The documentation doesn't provide a specific example of this, but it does show how to create a console
API that can be used to print messages from JavaScript. You might be able to adapt this approach to call your own functions.
4. Retrieve the response: Again, the documentation doesn't provide aspecific example of this, but the
console
API example might give you some ideas. You could potentially use a similar approach to retrieve responses from your functions.
5. Shut down the isolate: The documentation doesn't provide information on this step, so you might need to refer to the deno_core
and tokio
documentation or source code for more details.
Remember, this is a high-level overview and the actual implementation might be more complex. But hopefully, this gives you a good starting point! 🦕The roll your own Javascript runtime is helpful, thanks for the reference! Still struggling to understand how I can call a javascript function within the isolate from the rust program.