pub struct Proxy { /* private fields */ }
Expand description

The Proxy struct can be used to create a class in JavaScript who’s methods can be implemented in rust

Example

use quickjs_runtime::builder::QuickJsRuntimeBuilder;
use quickjs_runtime::reflection::Proxy;
use quickjs_runtime::quickjsrealmadapter::QuickJsRealmAdapter;
use quickjs_runtime::valueref::JSValueRef;
use std::cell::RefCell;
use std::collections::HashMap;
use quickjs_runtime::quickjs_utils::primitives;
use hirofa_utils::js_utils::Script;
use quickjs_runtime::esvalue::EsValueFacade;

struct MyFunkyStruct{
    name: String
}

impl Drop for MyFunkyStruct {fn drop(&mut self) {
        println!("Funky drop: {}", self.name.as_str());
    }
}

thread_local! {
   static INSTANCES: RefCell<HashMap<usize, MyFunkyStruct>> = RefCell::new(HashMap::new());
}

//create a new EsRuntime
let rt = QuickJsRuntimeBuilder::new().build();

// install our proxy class as com.hirofa.FunkyClass
rt.exe_rt_task_in_event_loop(|q_js_rt| {
   let q_ctx = q_js_rt.get_main_context();
   Proxy::new()
   .namespace(vec!["com", "hirofa"])
   .name("FunkyClass")
   // the constructor is called when a script does new com.hirofa.FunkyClass, the reflection utils
   // generate an instance_id which may be used to identify the instance
   .constructor(|q_ctx: &QuickJsRealmAdapter, instance_id: usize, args: Vec<JSValueRef>| {
       // we'll assume our script always constructs the Proxy with a single name argument
       let name = primitives::to_string_q(q_ctx, &args[0]).ok().expect("bad constructor! bad!");
       // create a new instance of our struct and store it in a map
       let instance = MyFunkyStruct{name};
       // store our struct in a thread_local map
       INSTANCES.with(move |rc| {
           let map = &mut *rc.borrow_mut();
           map.insert(instance_id, instance);
       });
       // return Ok, or Err if the constructor failed (e.g. wrong args were passed)
       Ok(())
    })
   // next we create a simple getName method, this will return a String
   .method("getName", |q_ctx, instance_id, args| {
       INSTANCES.with(move |rc| {
           let map = & *rc.borrow();
           let instance = map.get(instance_id).unwrap();
           primitives::from_string_q(q_ctx, instance.name.as_str())
       })
   })
   // and lastly (but very important) implement a finalizer so our rust struct may be dropped
   .finalizer(|q_ctx, instance_id| {
       INSTANCES.with(move |rc| {
           let map = &mut *rc.borrow_mut();
           map.remove(&instance_id);
       });
    })
    // install the Proxy in the context
   .install(q_ctx, true);      
});

match rt.eval_sync(Script::new("test_proxy.es",
    "{let inst = new com.hirofa.FunkyClass('FooBar'); let name = inst.getName(); inst = null; name;}"
)) {
    Ok(name_esvf) => {
        // assert correct getName result
        assert_eq!(name_esvf.get_str(), "FooBar");
        let i_ct = INSTANCES.with(|rc| rc.borrow().len());
        // assert instance was finalized
        assert_eq!(i_ct, 0);
    }
    Err(e) => {
        panic!("script failed: {}", e);
    }
}
rt.gc_sync();

Implementations

set the name of the proxy class this will indicate how to construct the class from script

set the namespace of the proxy class

Example
use quickjs_runtime::reflection::Proxy;
Proxy::new().namespace(vec!["com", "hirofa"]).name("SomeClass");

means from script you can access the class by

let instance = new com.hirofa.SomeClass();

get the canonical classname of a Proxy

example
use quickjs_runtime::reflection::Proxy;
Proxy::new().namespace(vec!["com", "hirofa"]).name("SomeClass");

will result in a class_name of “com.hirofa.SomeClass”

add a constructor for the Proxy class this will enable a script to create a new instance of a Proxy class if omitted the Proxy class will not be constructable from script

add a finalizer for the Proxy class this will be called when an instance of the Proxy class is dropped or garbage collected

add a method to the Proxy class, this method will be available as a member of instances of the Proxy class

add a method to the Proxy class, this method will be available as a member of instances of the Proxy class

add a static method to the Proxy class, this method will be available as a member of the Proxy class itself

add a static method to the Proxy class, this method will be available as a member of the Proxy class itself

add a static getter and setter to the Proxy class

add a getter and setter to the Proxy class, these will be available as a member of an instance of this Proxy class

indicate the Proxy class should implement the EventTarget interface, this will result in the addEventListener, removeEventListener and dispatchEvent methods to be available on instances of the Proxy class

indicate the Proxy class should implement the EventTarget interface, this will result in the addEventListener, removeEventListener and dispatchEvent methods to be available

install the Proxy class in a QuickJsContext, this is always needed as a final step to actually make the Proxy class work

Trait Implementations

Returns the “default value” for a type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.