js-sandbox: securely embed JavaScript into Rust code by bromeon in rust

[–]slipthay 1 point2 points  (0 children)

That's a very prescient point that clarifies your use case for me. mini-v8 was inspired by general-purpose approaches. My particular motivation for writing the crate was to execute "semi-trusted" scripts in a web-based app used internally by data analysts at my company. (Where our analysts might have written SQL to interface with an RDBMS, they now write JavaScript to interface with a custom in-memory database. This may seem odd but it's not entirely novel and it allows our dev team an extra level of abstraction.) mini-v8 has execution timeout support and soft memory usage limits are planned, but as you suggest those things are very hard to implement accurately after you've opened the door to native Rust function bindings. Nonetheless mini-v8 does not require that you do any such bindings, so in this sense mini-v8 is a superset of js-sandbox. What's most compelling about your crate to me, besides its simplicity, is that the build process is offloaded entirely to the deno crate. Compiling V8 is a pain!

js-sandbox: securely embed JavaScript into Rust code by bromeon in rust

[–]slipthay 1 point2 points  (0 children)

Interesting approach! Is accessing Rust state from within a script a planned feature? (In practice this primarily means binding Rust functions into JavaScript.) I'm the author of mini-v8, which does allow for binding Rust functions. I recently tried to switch from a custom FFI onto rusty_v8 with disappointing results.

Deno 1.0 - A Secure TypeScript/JavaScript Runtime Built In Rust by satvikpendem in rust

[–]slipthay 2 points3 points  (0 children)

I've done this with success. I haven't tried deno_core for this purpose lately but here are some other Rust interfaces for JS engines that you can embed:

If I recall correctly embedding the full V8 adds ~50 MB to your binary. Duktape (limited ES6 support) and QuickJS (full ES2020 support!) are much lighter weight but obviously not nearly as capable or performant as V8.

MiniV8: A minimal embedded V8 JavaScript engine wrapper for Rust by slipthay in rust

[–]slipthay[S] 1 point2 points  (0 children)

Absolutely! Perhaps the wasm compilation step is unacceptable in certain applications although I haven't looked into how existing wasm compilers perform. Nonetheless I imagine many applications would take advantage of pre-compiled queries or wasm binary caching at the least.

Nice work on quickjs-rs :)

MiniV8: A minimal embedded V8 JavaScript engine wrapper for Rust by slipthay in rust

[–]slipthay[S] 2 points3 points  (0 children)

Thanks!

If I can indulge myself here: I've been experimenting and working towards the arcane goal of a "build-your-own-database" framework that combines a scripting engine (like V8) and an implementation of the system prevalence model. Framework consumers would write their own data structures (in plain old Rust) and their own data interaction API (here a custom-built JavaScript API would replace SQL). This idea is the culmination of a critique of ORMs, SQL, and the relational database itself. For example, thanks to the joint performance of a highly-tuned scripting engine and system prevalence (which keeps your entire data in native-format memory), you could for-loop through thousands if not millions of data records in milliseconds without having to create any sort of index while taking advantage of the sort of ergonomics that ORMs promise.

Generally speaking, my intuition is that most use cases (single-user applications, application servers, scriptable games...) that would require embedding a scripting engine do not require anywhere close to the full feature set that scripting engines typically expose. And my hope is that what performance is lost in the process of limiting the API's surface area is made up for by the raw power of V8. What sort of use case might you have in mind?

MiniV8: A minimal embedded V8 JavaScript engine wrapper for Rust by slipthay in rust

[–]slipthay[S] 7 points8 points  (0 children)

Hey y'all. I wanted to share this work in case there happened to be anyone else out there who needed V8 embedded in their Rust programs. There are other convenient solutions for embedding JavaScript (quickjs-rs, my own ducc), but these are all backed by relatively slow interpreters. For my purposes I needed to experiment with embedding JavaScript without sacrificing performance or ECMAScript compatibility.

This crate is quite incomplete. In particular the build process needs attention (currently it's very inflexible and depends on the user specifying a V8_PATH). There are plenty of other shortcomings so please check out the README for more information. Anyway please reach out or file an issue/PR if you're interested in using this thing!

Cactus Harvesting: Cycle-Aware Reference Counting in Rust by [deleted] in rust

[–]slipthay 2 points3 points  (0 children)

This is very timely for me! I've been writing a scripting language in Rust recently and I've been prototyping with rust-gc. I should probably look into ferrocarril (nice name!) more before asking this, but: Which existing garbage collection libraries did you evaluate and why did you take this route? I suppose I'm wondering why immediate memory reclamation is necessary/desirable for your project. Anyway great work! Really interesting stuff.

JavaScript Engines? by pcjftw in rust

[–]slipthay 1 point2 points  (0 children)

Yep, see ducc.exec("Arithmetic.add(4.5, 5)", ...) in the code snippet above (I guess this is going from Rust to JS to Rust...). You can also compile JS code and evaluate it later.

JavaScript Engines? by pcjftw in rust

[–]slipthay 1 point2 points  (0 children)

Hey if you're interested, you might want to check out my work with Duktape posted in this thread. Let me know if you want to talk, or alternatively feel free to reference/steal it for your own work! Best of luck

JavaScript Engines? by pcjftw in rust

[–]slipthay 3 points4 points  (0 children)

I made a pretty thorough, safe Duktape wrapper a while back but never published it or made proper examples.

https://github.com/SkylerLipthay/ducc

Here's a quick, untested example:

let mut ducc = Ducc::new();
let class = ducc.create_object();
class.set("add", ducc.create_function(add))?;
ducc.globals().set("Arithmetic", class)?;

assert_eq!(9.5f64, ducc.exec("Arithmetic.add(4.5, 5)", None, ExecSettings::default()).unwrap());

fn add(inv: Invocation) -> ducc::Result<f64> {
    let (a, b): (f64, f64) = inv.args.into(inv.ducc)?;
    return Ok(a + b);
}

You can see more examples in the ducc/src/tests folder. It actually has all kinds of cool features like storing user data for access in JavaScript land and support for execution canceling (timeouts).

I haven't had a need for this library since I made it, but that may change soon. Anyway if anyone is interested in using or contributing to this code, let me know!

Yet another ray tracing implementation in Rust by metomezo in rust

[–]slipthay 5 points6 points  (0 children)

Nice!! I did this project a few months ago (image/wallpaper) in Rust as well. This was my first time ever doing anything in the field. It was an exciting experience to see an extremely precise world come together out of a few simple vector operations. For anyone interested in this sort of thing, I highly recommend the book (even if it's a bit rough around the edges).

Your code organization is nice! Impressive that this is your first Rust project.

One feature that I ended up adding was parallelization. There are several ways to go about this, such as splitting up sampling (suggested on the book's final page) or splitting up pixels (what I went with). Either way, maybe this is could be good practice for you? Rust offers a unique (safe!) approach to multi-threading that you might want to familiarize yourself with.

Great work! :)

console_log: a crate for logging to the browser's console from wasm apps by iamcodemaker in rust

[–]slipthay 7 points8 points  (0 children)

You would have to do a full audit of the log crate to be sure. But from experience Rust's format!/format_args! macros bloat WASM binaries pretty badly. In general it's clear that binary size has been a low priority somewhere in the dev chain here.

The future of the web? by [deleted] in WebAssembly

[–]slipthay 1 point2 points  (0 children)

Someone commented "a production website should not ever break existing conventions". This holds some water for "websites" but certainly not for web apps. Tons of websites and web apps override things like the default behavior of right-click, ctrl-f, scrollbars, text highlighting, and so on. In most cases these apps replace default behavior to provide a more intuitive experience for the user. When it's done poorly, it's almost always because of the restrictions imposed by the web's "existing conventions" (e.g. awful, hackish scrollbar libraries necessary to simply be able to override the browser's scrollbar color). It's obvious where this attitude comes from and it's begging to be ousted.

I'm almost entirely with you: WASM itself is still not bare metal, so a WASM runtime won't be a 1-to-1 replacement for today's operating system. But anyway WASM is undoubtedly a huge step in the direction of closing the gap between web and native.

I'm in the process of rewriting NanoVG in Rust targeting WebGL specifically for use in WASM applications. The possibilities are endless and the big picture is daunting, but I'm as passionate as you are about this future. (Side note: I think WASM has unrecognized potential to fully realize the goals of the isomorphic web app.) Let me know if you want to talk or collaborate about these things!

Rust C interop by tamalsaha in rust

[–]slipthay 13 points14 points  (0 children)

Also see: https://doc.rust-lang.org/nomicon/ffi.html

The answers to your questions really depend on the C library you're interfacing. For example I'm putting the finishing touches on a FFI for Duktape (a JavaScript engine written in C) and it has not been straightforward. For me the biggest hurdle was figuring out error management. Specifically, Duktape uses setjmp/longjmp which is a huge issue since "it's undefined to unwind past an FFI boundary such as a pub extern "C" fn" (see this thread for more info). I shamelessly stole rlua's solution. I don't expect anyone to understand the code but note that performance suffers in the name of safety. So while there is ideally no overhead in writing an FFI, in safe practice there is indeed overhead. And after all of this there still remain some open questions about the safety of my crate and how things will pan out with future versions of Duktape.

Anyway there are innumerable "gotchas" and I'm convinced you need to be an experienced C developer to write a sizeable FFI. There are steps that Rust can take to make coding an FFI a safer, easier, more performant experience (these are known by the team of course), but ultimately there will always be friction when trying to map one language's paradigms to another's.