Bromeon/js-sandbox

Passing HashMaps/Dynamic Objects as script function argument.

alwinmark opened this issue · 1 comments

Hello,

maybe I'm doing something wrong (which is very likely as I'm new to rust), but currently I'm struggling to pass an HashMap or similar to a function as an argument.

I want to render Javascript Templates in Rust, where I want to pass dynamic objects to the render function in order to render the template as HTML.

basically its shoudl look just like:

    let context = HashMap::from([
        ("doesWhat", "rocks in rust"),
    ]);

    script.call("render", context)

or:

 let context = [
        ("doesWhat", "rocks in rust"),
    ];

    script.call("render", &context);

Unfortunately this ends up with:

  --> src/main.rs:13:27
   |
13 |     script.call("render", context);
   |                           ^^^^^^^ the trait `js_sandbox::call_args::CallArgs` is not implemented for `HashMap<&str, &str>`

or

the trait `js_sandbox::call_args::CallArgs` is not implemented for `&[(&str, &str); 1]

I'm also not able to implement the trait, as it is in a private module (js_sandbox::call_args::CallArgs).

The latest version of js-sandbox allows passing multiple parameters, not just one. This in turn means that the syntax needs to be adjusted -- concretely, Script::call() now takes a tuple:

let context = HashMap::from([
    ("doesWhat", "rocks in rust"),
]);

script.call("render", (context,)); // note the trailing comma for 1-tuple

I admit it's not the most beautiful; unfortunately, I cannot "overload" call() by implementing CallArgs also for T: Serializable, as this overlaps with the tuples, and specialization is not supported in current Rust. If this happens a lot, a special method for this case might be added.

But for nicer code, consider also using the #[js_api] macro like in this test.

I also realized that the ReadMe.md was outdated; I forgot to sync it manually with the updated lib.rs. Sorry for that. To make sure this doesn't happen again, I simply automated it via CI.