Crate quickjs_runtime
source · [−]Expand description
quickjs_runtime
This crate consists of two main parts:
- thread-safe utils and wrappers you can call these from any thread, all logic is directed to a single worker-thread(EventLoop) which invokes the quickjs API
- quickjs bindings and utils these talk to the quickjs API directly and need to run in the same thread as the Runtime
Noteworthy structs
These are the structs you’ll use the most
Thread safe | Abstracted in hirofa_utils as | Runtime Thread-local | Abstracted in hirofa_utils as |
---|---|---|---|
QuickjsRuntimeFacade the ‘starting point’ | JsRuntimeFacade | QuickJsRuntimeAdapter the wrapper for all things quickjs | JsRuntimeAdapter |
- | - | QuickJsRealmAdapter a realm or context | JsRealmAdapter |
- | JsValueFacade copy of- or reference to a value in the JsRuntimeAdapter | JSValueRef reference counting pointer to a Value | JsValueAdapter |
Doing something in the runtime worker thread
You always start with building a new QuickjsRuntimeFacade
use quickjs_runtime::builder::QuickJsRuntimeBuilder;
let rt: JsRuntimeFacade = QuickJsRuntimeBuilder::new().js_build();
JsRuntimeFacade has plenty public methods you can check out but one of the things you’ll need to understand is how to communicate with the JsRuntimeAdapter and the JsRealmAdapter This is done by adding a job to the EventLoop of the JsRuntimeFacade
// with the first Option you may specify which realm to use, None indicates the default or main realm
let res = rt.js_loop_realm(None, |rt: JsRuntimeAdapter, realm: JsRealmAdapter| {
// this will run in the Worker thread, here we can use the Adapters
return true;
}).await;
All the non-sync functions return a Future so you can .await them from async functions.
In order to do something and get the result synchronously you can use the sync variant
use quickjs_runtime::quickjsruntime::QuickJsRuntime;
let res = rt.js_loop_realm_sync(None, |rt, realm| {
// this will run in the Worker thread, here we can use the quickjs API
return 1;
});
One last thing you need to know is how to pass values from the js engine out of the worker thread
This is where the JsValueFacade comes in
// init a simple function
rt.js_eval(Script::new("init_func.js", "globalThis.myObj = {someMember: {someFunction: function(input){return(input + " > hello rust!");}}};")).await;
let input_facade = JsValueFacade::new_str("hello js!");
let res = rt.js_loop_realm(None, move |rt: JsRuntimeAdapter, realm: JsRealmAdapter| {
// convert JsValueFacade to JsValueAdapter
let input_adapter = realm.from_js_value_facade(input_facade);
// call myObj.someMember.someFunction();
let result_adapter = realm.js_function_invoke_by_name(&["myObj", "someMember"], "someFunction", &[input_adapter])?;
// convert adapter to facade again so it may move out of the worker thread
return realm.to_js_value_facade();
}).await;
assert_eq!(res.get_str(), "hello_js! > hello rust!");
For more details and examples please explore the packages below
Modules
contains the QuickJsRuntimeBuilder which may be used to instantiate a new QuickjsRuntimeFacade
contains the legacy EsValueFacade which will be deprecated in favour of utils::JsValueFacade in the near future
contains the QuickJsRuntimeFacade
contains engine features like console, setTimeout, setInterval and setImmediate
low level contains utils for calling the quickjs api
utils for implementing proxy classes which can be used to use rust structs from JS (define method/getters/setters/etc)
JSValueRef is a wrapper for quickjs’s JSValue. it provides automatic reference counting making it safer to use