#quickjs #javascript #runtime #async #engine

quickjs_runtime

Wrapper API and utils for the QuickJS JavaScript engine with support for Promise, Modules, Async/await

33 releases

0.11.5 Aug 1, 2023
0.11.4 Jul 5, 2023
0.11.3 Jun 22, 2023
0.9.0 Mar 25, 2023
0.2.3 Mar 31, 2021

#432 in Development tools

Download history 115/week @ 2023-08-01 53/week @ 2023-08-08 47/week @ 2023-08-15 48/week @ 2023-08-22 50/week @ 2023-08-29 96/week @ 2023-09-05 73/week @ 2023-09-12 66/week @ 2023-09-19 47/week @ 2023-09-26 41/week @ 2023-10-03 71/week @ 2023-10-10 59/week @ 2023-10-17 52/week @ 2023-10-24 136/week @ 2023-10-31 128/week @ 2023-11-07 126/week @ 2023-11-14

449 downloads per month

MIT license

555KB
12K SLoC

quickjs_runtime

quickjs_runtime is a library for quickly getting started with embedding a javascript engine in your rust project.

DISCLAIMER: This project is not yet what I would call "Battle Tested", use at your own risk.

An example on how to embed a script engine in rust using this lib can be found here: github.com/andrieshiemstra/ScriptExtensionLayerExample. It was published in TWIR as a walkthrough.

quickjs_runtime focuses on making quickjs easy to use and does not add any additional features, that's where these projects come in:

This project is inspired by the quickjs wrapper at theduke/quickjs-rs and still uses its low level bindings libquickjs-sys.

The big difference to quickjs-rs is that quickjs_runtime executes all quickjs related code in a dedicated single-threaded EventLoop.

Please see the DOCS for all inner workings

This lib serves two main goals:

1. Provide simple utils for working with quickjs (these are located in the quickjs_utils mod)

  • The QuickJsRuntime struct, this is to be used from a single thread
  • E.g. objects::set_property(), functions::invoke_func()
  • Wrap JSValue to provide reference counting (+1 on init, -1 on drop) (QuickJsValueAdapter)
  • Pass a module loader

2. Wrap quickjs for use as a ready to go JavaScript Runtime

  • This is the EsRuntime struct, it provides an EventQueue which has a thread_local QuickJsRuntime
  • All values are copied or abstracted in an EsValueFacade
  • So no need to worry about Garbage collection
  • evaluate script and invoke functions while waiting for results blocking or with async/await
  • Get Promise result blocking or with async/await

What works?

Script and Modules

  • Typescript (via SWC)
  • console (.log/info/debug/trace/error) (docs)
  • Eval script (docs)
  • Create promises in JavaScript which execute async
  • Eval modules (docs)
  • Load modules (dynamic and static) (docs)
  • fetch api (moved to GreenCopperRuntime)
  • setImmediate
  • setTimeout/Interval (and clear)
  • script preprocessing (impls for ifdef/macro's/typescript can be found in GreenCopperRuntime)

Rust-Script interoperability

  • Return Promises from rust functions and resolve them from rust (docs)
  • Add functions from rust (docs)
  • Invoke JS functions from rust (docs)
  • Pass primitives, objects and arrays from and to rust (docs)
  • Create Classes from rust (docs)
  • async/await support on eval/call_function/promise resolution (docs)
  • import native Modules (e.g. dynamic loading of rust functions or Proxy classes) (docs)

Future / Todo

  • Worker support
  • WebAssembly support

Goals

Embedding a script engine in a rust project seems a very tedious job which involves learning a lot about the inner workings of that engine.

The main goal of this project is to make that job easy!

The manner in which this is achieved is primarily focused on abstracting the workings of the engine from the implementor, therefore some functionality may not be the fastest way of getting things done.

So a second goal is to make implementing a fast and efficient integration doable for the uninitiated, the most common tasks you do with the engine should be doable with the utils in this package and working examples should be provided in the test modules.

The reason I chose QuickJS as the engine is that I've been dealing with less modern engines in my java projects and not being able to use the latest and greatest ECMA-script features becomes quite disappointing at times.

The fun stuff about QuickJS:

  • small footprint
  • fast compilation / startup
  • great JS compatibility

examples

Cargo.toml

[dependencies]
quickjs_runtime = {version = "0.11", features=["default", "typescript"]}

Here are some quickstarts:

The quickjs Api utils:

Dependencies

~8–21MB
~332K SLoC