Crate dioxus_use_js

Crate dioxus_use_js 

Source
Expand description

§dioxus-use-js

github crates.io test status

A macro that generates Rust bindings to JavaScript or TypeScript functions, with compile time checks. For use with Dioxus. No need to use eval directly anymore! Works across all eval supported platforms (Web, Desktop, Mobile, and liveview) — no wasm-bindgen required.


§JavaScript Usage

You can write plain JavaScript and bind exported functions directly.

// assets/example.js

export function greeting(from, to) {
    return `Hello ${to}, this is ${from} speaking from JavaScript!`;
}

Bind it in Rust:

use dioxus_use_js::use_js;

use_js!("assets/example.js"::greeting);

Generated Rust signature:

async fn greeting<T: DeserializeOwned>(from: impl Serialize, to: impl Serialize) -> Result<T, JsError>;

Use it like:

let val: String = greeting("Alice", "Bob").await?;

§TypeScript Usage

If you use TypeScript, the macro will parse types to produce more accurate Rust bindings. See the Type Mapping section for details on how TypeScript types are mapped to Rust types.

// js-utils/example.ts

export function greeting(from: string, to: string): string {
    return `Hello ${to}, this is ${from} speaking from JavaScript!`;
}

Compile with:

bun build js-utils/example.ts --outfile assets/example.js

See BunTsCompile for use in build.rs as well - Example

Bind with:

use_js!("js-utils/example.ts", "assets/example.js"::{greeting});

Generated Rust signature:

async fn greeting(from: &str, to: &str) -> Result<String, JsError>;

§Macro Syntax

§Js

use_js!("bundle.js"::function);
use_js!("bundle.js"::{func1, func2});
use_js!("bundle.js"::*);

§Ts

use_js!("source.ts", "bundle.js"::function);
use_js!("source.ts", "bundle.js"::{func1, func2});
use_js!("source.ts", "bundle.js"::*);

§Type Mapping

§Built-in TypeScript Types

TypeScriptRust InputRust Output
string&strString
numberf64f64
booleanboolbool
T | nullOption<&T>Option<T>
T[]&[T]Vec<T>
Map<T, TT>&HashMap<T, TT>HashMap<T, TT>
Set<T>&HashSet<T>HashSet<T>
void, undefined, never, null-()
any, unknown, object, -, *impl serde::SerializeT: serde::de::DeserializeOwned
Promise<T>&TT

§Special Types

TypeScriptRust InputRust Output
Json&serde_json::Valueserde_json::Value
JsValue<T>, JsValue&JsValueJsValue
RustCallback<T,TT>impl AsyncFnMut(T) -> Result<TT, Box<dyn Error + Send + Sync>>-
RustCallback<void,TT>impl AsyncFnMut() -> Result<TT, Box<dyn Error + Send + Sync>>-

§Special Types

Special types are types not included in the regular Typescript type system, but are understood by the use_js! macro and may augment the generated binding code.

§Json

Json is a simple type that represents valid json. This type can best nested.

type Json = string | number | boolean | null | { [key: string]: Json } | Json[];
§Example Usage

TypeScript:

type Json = string | number | boolean | null | { [key: string]: Json } | Json[];

export function json(): Json[] {
    return [
        {"key": "value"},
        {"key": "value"},
    ];
}

Generated Rust signature:

pub async fn json() -> Result<Vec<Value> ,JsError>;

§JsValue: Javascript References

This special TypeScript type signals to the macro to bypass serialization and pass native JS values as opaque references between Rust and JavaScript. The macro generates the glue code required. The JS value is automatically disposed when all references on the Rust side go out of scope. Only the following are valid representations:

Valid Ts UsesInputOutput
JsValue<T>, JsValue&JsValueJsValue
Promise<JsValue<T>>, Promise<JsValue>-JsValue
JsValue<T> | null JsValue | nullOption<&JsValue>Option<JsValue>
Promise<JsValue<T> | null>, Promise<JsValue | null>-Option<JsValue>
type JsValue<T = any> = T;
§Example Usage

TypeScript:

type JsValue<T = any> = T;

type MyObject = {
    name: string;
    method: (value: number) => number;
};

export function createJsObject(): JsValue<MyObject> {
    return {
        name: "example",
        method: function (value) {
            return value + 25;
        },
    };
}

export function useJsObject(value: JsValue<MyObject>): number {
    let result = value.method(2);
    return result;
}

Generated Rust signature:

pub async fn createJsObject() -> Result<JsValue, JsError>;

pub async fn useJsObject(value: &JsValue) -> Result<f64, JsError>;

Usage:

let js_value_example: Resource<Result<f64, JsError>> = use_resource(|| async move {
    // No serialization!
    // The value is kept on the js side and a reference to it is kept on the rust side.
    // The value is automatically disposed when all rust references no longer exist.
    let js_value = createJsObject().await?;
    let output = useJsObject(&js_value).await?;
    // Since `js_value` is dropped here and all references no longer exist,
    // the referenced value will be disposed on the js side.
    Ok(output)
});

§RustCallback: Passing Closures from Rust to JavaScript

This special TypeScript type signals to the macro that a Rust async closure will be passed into the JavaScript function. The macro generates the glue code required. This enables advanced interop patterns, such as calling Rust logic from within JS — all while preserving type safety. This type cannot be nested.

type RustCallback<A, R> = (arg: A) => Promise<R>;

If input A is void then the Rust closure will take no input. If output R is void then the Rust closure will return no output.

§Example Usage

TypeScript:

type RustCallback<A, R> = (arg: A) => Promise<R>;

export async function useCallback(
  startingValue: number,
  callback: RustCallback<number, number>
): Promise<number> {
  let doubledValue = startingValue * 2;
  let quadValue = await callback(doubledValue); // Calls back into Rust
  return quadValue * 2;
}

Generated Rust signature:

pub async fn useCallback(
    startingValue: f64,
    mut callback: impl AsyncFnMut(f64) -> Result<f64, Box<dyn Error + Send + Sync>>,
) -> Result<f64, JsError>;

Usage:

let callback_example: Resource<Result<f64, JsError>> = use_resource(|| async move {
    // Rust async closure that will be called by JS
    let callback = async |value: f64| Ok(value * 2.0);

    // Pass it into the JS function
    let value = useCallback(2.0, callback).await?;
    Ok(value)
});

Macros§

use_js
A macro to create rust bindings to javascript and typescript functions. See README and example for more.

Structs§

BunTsCompilecompile
BunTsCompileBuildercompile
Use builder syntax to set the inputs and finish with build().
JsValue
A reference to a javascript value that can be held on the dioxus side and passed to functions generated by this crate.

Enums§

JsError
An error related to the execution of a javascript operation