All Projects → HiRoFa → quickjs_es_runtime

HiRoFa / quickjs_es_runtime

Licence: MIT license
this is a wrapper library for the javascript runtime quickjs written in rust which works with modules, promises, async, await and much more

Programming Languages

rust
11053 projects
shell
77523 projects

Projects that are alternatives of or similar to quickjs es runtime

Tomorrowland
Lightweight Promises for Swift & Obj-C
Stars: ✭ 106 (+146.51%)
Mutual labels:  promises
Promise
Promise / Future library for Go
Stars: ✭ 149 (+246.51%)
Mutual labels:  promises
Q
A platform-independent promise library for C++, implementing asynchronous continuations.
Stars: ✭ 179 (+316.28%)
Mutual labels:  promises
Symfony Async Kernel
[Deprecated] Symfony Async Kernel adpater
Stars: ✭ 111 (+158.14%)
Mutual labels:  promises
Asynquence
Asynchronous flow control (promises, generators, observables, CSP, etc)
Stars: ✭ 1,737 (+3939.53%)
Mutual labels:  promises
Brightfutures
Write great asynchronous code in Swift using futures and promises
Stars: ✭ 1,890 (+4295.35%)
Mutual labels:  promises
React Transmit
Relay-inspired library based on Promises instead of GraphQL.
Stars: ✭ 1,335 (+3004.65%)
Mutual labels:  promises
Bliss
Blissful JavaScript
Stars: ✭ 2,352 (+5369.77%)
Mutual labels:  promises
Tascalate Concurrent
Implementation of blocking (IO-Bound) cancellable java.util.concurrent.CompletionStage and related extensions to java.util.concurrent.ExecutorService-s
Stars: ✭ 144 (+234.88%)
Mutual labels:  promises
Redux Promise Middleware
Enables simple, yet robust handling of async action creators in Redux
Stars: ✭ 2,001 (+4553.49%)
Mutual labels:  promises
Fetch Plus
🐕 Fetch+ is a convenient Fetch API replacement with first-class middleware support.
Stars: ✭ 116 (+169.77%)
Mutual labels:  promises
Functional Promises
Write code like a story w/ a powerful Fluent (function chaining) API
Stars: ✭ 141 (+227.91%)
Mutual labels:  promises
Async Javascript Cheatsheet
Cheatsheet for promises and async/await.
Stars: ✭ 1,902 (+4323.26%)
Mutual labels:  promises
Promis
The easiest Future and Promises framework in Swift. No magic. No boilerplate.
Stars: ✭ 110 (+155.81%)
Mutual labels:  promises
Crank
Write JSX-driven components with functions, promises and generators.
Stars: ✭ 2,487 (+5683.72%)
Mutual labels:  promises
Pify
Promisify a callback-style function
Stars: ✭ 1,342 (+3020.93%)
Mutual labels:  promises
Atdatabases
TypeScript clients for databases that prevent SQL Injection
Stars: ✭ 154 (+258.14%)
Mutual labels:  promises
opensource
Collection of Open Source packages by Otherwise
Stars: ✭ 21 (-51.16%)
Mutual labels:  modules
Promisekit
Promises for Swift & ObjC.
Stars: ✭ 13,699 (+31758.14%)
Mutual labels:  promises
Hydra
⚡️ Lightweight full-featured Promises, Async & Await Library in Swift
Stars: ✭ 1,954 (+4444.19%)
Mutual labels:  promises

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 purely 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) (JSValueRef)
  • 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

  • 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

Same goals as https://github.com/HiRoFa/es_runtime but with using quickjs

so

  • slower js

but

  • smaller footprint
  • much faster compilation

For some of my projects those are a big plus!

examples

Here are some quickstarts:

Cargo.toml

[dependencies]
hirofa_utils = "0.5"
quickjs_runtime = "0.8"
log = "0.4"
simple-logging = "2.0"
use crate::builder::QuickJsRuntimeBuilder;
    use crate::facades::QuickJsRuntimeFacade;
    use crate::quickjsrealmadapter::QuickJsRealmAdapter;
    use futures::executor::block_on;
    use hirofa_utils::js_utils::adapters::proxies::JsProxy;
    use hirofa_utils::js_utils::adapters::JsRealmAdapter;
    use hirofa_utils::js_utils::facades::values::{JsValueConvertable, JsValueFacade};
    use hirofa_utils::js_utils::facades::{JsRuntimeBuilder, JsRuntimeFacade};
    use hirofa_utils::js_utils::{JsError, Script};
    use log::LevelFilter;
    use std::time::Duration;

    #[test]
    fn test_examples() {
        let rt = QuickJsRuntimeBuilder::new().js_build();
        let outcome = block_on(run_examples(&rt));
        if outcome.is_err() {
            log::error!("an error occured: {}", outcome.err().unwrap());
        }
        log::info!("done");
    }

    async fn take_long() -> i32 {
        std::thread::sleep(Duration::from_millis(500));
        537
    }

    async fn run_examples(rt: &QuickJsRuntimeFacade) -> Result<(), JsError> {
        // ensure console.log calls get outputted
        simple_logging::log_to_stderr(LevelFilter::Info);

        // do a simple eval on the main realm
        let eval_res = rt
            .js_eval(None, Script::new("simple_eval.js", "2*7;"))
            .await?;
        log::info!("simple eval:{}", eval_res.get_i32());

        // invoke a JS method from rust

        let meth_res = rt
            .js_function_invoke(None, &["Math"], "round", vec![12.321.to_js_value_facade()])
            .await?;
        log::info!("Math.round(12.321) = {}", meth_res.get_i32());

        // add a rust function to js as a callback

        let cb = JsValueFacade::new_callback(|args| {
            let a = args[0].get_i32();
            let b = args[1].get_i32();
            log::info!("rust cb was called with a:{} and b:{}", a, b);
            Ok(JsValueFacade::Null)
        });
        rt.js_function_invoke(
            None,
            &[],
            "setTimeout",
            vec![
                cb,
                10.to_js_value_facade(),
                12.to_js_value_facade(),
                13.to_js_value_facade(),
            ],
        )
        .await?;
        std::thread::sleep(Duration::from_millis(20));
        log::info!("rust cb should have been called by now");

        // create simple proxy class with an async function
        rt.js_loop_realm_sync(None, |_rt_adapter, realm_adapter| {
            let proxy = JsProxy::new(&["com", "mystuff"], "MyProxy").add_static_method(
                "doSomething",
                |_rt_adapter, realm_adapter: &QuickJsRealmAdapter, _args| {
                    realm_adapter.js_promise_create_resolving_async(
                        async { Ok(take_long().await) },
                        |realm_adapter, producer_result| {
                            realm_adapter.js_i32_create(producer_result)
                        },
                    )
                },
            );
            realm_adapter
                .js_proxy_install(proxy, true)
                .ok()
                .expect("could not install proxy");
        });

        rt.js_eval(
            None,
            Script::new(
                "testMyProxy.js",
                "async function a() {\
                            console.log('a called at %s ms', new Date().getTime());\
                            let res = await com.mystuff.MyProxy.doSomething();\
                            console.log('a got result %s at %s ms', res, new Date().getTime());\
                           }; a();",
            ),
        )
        .await?;
        std::thread::sleep(Duration::from_millis(600));
        log::info!("a should have been called by now");

        Ok(())
    }
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].