quickjs_runtime is a library for quickly getting started with embedding a javascript engine in your rust project.
DISCLAIMER: This project is far from what I would call "Battle Tested", use at your own risk.
quickjs_runtime focuses purely on making quickjs easy to use and does not add anny additional features, that where these projects come in: * A more feature-rich runtime can be found in ESsesLib-q. * There is also a commandline client: ESsesCmd-q. * And last but not least there is GreenCopper which aspires to be a full fledged application platform: Green-Copper-q.
This project is heavily inspired by the awesome 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 EventQueue.
Please see the DOCS for all inner workings
Same goals as https://github.com/HiRoFa/es_runtime but with using quickjs
so * slower js
but
For some of my projects those are a big plus!
Here are some quickstarts:
Cargo.toml
toml
[dependencies]
quickjs_runtime = "0.2"
log = "0.4.11"
simple-logging = "2.0.2"
main.rs
```rust use quickjsruntime::esruntimebuilder::EsRuntimeBuilder; use quickjsruntime::esscript::EsScript; use log::LevelFilter; use futures::executor::blockon; use std::sync::Arc; use quickjsruntime::esruntime::EsRuntime;
async fn test(rt: Arc
assert_eq!(res.get_i32(), 84);
}
fn main() { simplelogging::logto_stderr(LevelFilter::Info);
let rt = EsRuntimeBuilder::new()
.build();
block_on(test(rt));
} ```
rust
let res = rt.call_function(vec!["myAppUtils"], "some_func", es_args![8, 7]).await;
match res {
Ok(val) => log::info!("8*7 in JavaScript = {}", val.get_i32()),
Err(e) => println!("script failed: {}", e),
}
```rust rt.setfunction(vec!["nl", "my", "utils"], "methodA", |args| { if args.len() != 2 || !args.get(0).unwrap().isi32() || !args.get(1).unwrap().isi32() { Err(EsError::newstr( "i'd really like 2 args of the int32 kind please", )) } else { let a = args[0].geti32(); let b = args[1].geti32(); log::info!("rust is multiplying {} and {}", a, b); Ok((a * b).toesvaluefacade()) } }) .ok() .expect("setfunction failed");
let method_a_res = rt.eval(EsScript::new(
"test_func.es",
"(nl.my.utils.methodA(13, 56));",
)).await;
match method_a_res {
Ok(val) => {
assert_eq!(val.get_i32(), 13 * 56);
}
Err(e) => {
panic!("test_func.es failed: {}", e);
}
}
```
rust
rt.eval_module(EsScript::new(
"my_app.mes",
"\
import {foo} from 'example.mes';\
console.log('static foo is ' + foo);\
",
)).await
.ok()
.expect("module failed");
```rust
rt.eval_module(EsScript::new(
"my_app2.es",
"\
import('example.mes')\
.then((example_module) => {\
console.log('dynamic foo is ' + example_module.foo);\
});\
",
)).await
.ok()
.expect("script failed");
```
```rust rt.setfunction(vec!["nl", "my", "utils"], "methodB", |mut args| { if args.len() != 1 || !args[0].isfunction() { Err(EsError::newstr( "i'd really like 1 arg of the function kind please", )) } else { let consumerfunc = args.remove(0);
// invoke the func async, just because we can
std::thread::spawn(move || {
consumer_func
.invoke_function_sync(es_args![19, 17])
.ok()
.expect("func failed");
});
Ok(quickjs_es_runtime::esvalue::EsNullValue {}.to_es_value_facade())
}
})
.ok()
.expect("set_function failed");
rt.eval(EsScript::new(
"test_func2.es",
"(nl.my.utils.methodB(function(a, b){console.log('consumer was called with ' +a + ', ' + b);}));",
)).await.ok().expect("test_func2.es failed");
// wait a sec for the async onvoker to run
std::thread::sleep(Duration::from_secs(1));
```