javascriptrustwasm-bindgenwasm-pack

Can't call function on object in javascript even though it is there


I cannot call a function on an object in javascript of a class made by wasm-pack (0.13.0), wasm-bindgen, rust.

This is the rust code:

use wasm_bindgen::prelude::*;
use web_sys::HtmlCanvasElement;
use wgpu::{Surface, SurfaceError};

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: String);
}

#[wasm_bindgen]
// #[derive(Debug)]
struct StateW {
    state_wasm: StateWasm<'static>,
}

#[derive(Debug)]
struct StateWasm<'a> {
    instance: wgpu::Instance,
    surface: Surface<'a>,
    device: wgpu::Device,
    queue: wgpu::Queue,
    config: wgpu::SurfaceConfiguration,
    size: (u32, u32),
}

impl<'a> StateWasm<'a> {
    pub async fn new(canvas: HtmlCanvasElement) -> Self {..}

    pub fn render(&mut self) -> Result<(), SurfaceError> {..}
}

#[wasm_bindgen]
impl StateW {
    #[wasm_bindgen(constructor)]
    pub async fn new(canvas: HtmlCanvasElement) -> Self {
        Self {
            state_wasm: StateWasm::new(canvas).await,
        }
    }

    #[wasm_bindgen(js_name="renderWasm")]
    pub fn render_wasm(&mut self) {
        let error = self.state_wasm.render();
        match error {
            Ok(_) => {},
            Err(e) => log(e.to_string()),
        };
    }

    pub fn good() -> String {
        String::new()
    }
}

This is the class made by wasm-pack:

export class StateW {

    static __wrap(ptr) {
        ptr = ptr >>> 0;
        const obj = Object.create(StateW.prototype);
        obj.__wbg_ptr = ptr;
        StateWFinalization.register(obj, obj.__wbg_ptr, obj);
        return obj;
    }

    __destroy_into_raw() {
        const ptr = this.__wbg_ptr;
        this.__wbg_ptr = 0;
        StateWFinalization.unregister(this);
        return ptr;
    }

    free() {
        const ptr = this.__destroy_into_raw();
        wasm.__wbg_statew_free(ptr, 0);
    }
    /**
    * @param {HTMLCanvasElement} canvas
    */
    constructor(canvas) {
        const ret = wasm.statew_new(addHeapObject(canvas));
        return takeObject(ret);
    }
    /**
    */
    renderWasm() {
        wasm.statew_renderWasm(this.__wbg_ptr);
    }
    /**
    * @returns {string}
    */
    static good() {
        let deferred1_0;
        let deferred1_1;
        try {
            const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
            wasm.statew_good(retptr);
            var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
            var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
            deferred1_0 = r0;
            deferred1_1 = r1;
            return getStringFromWasm0(r0, r1);
        } finally {
            wasm.__wbindgen_add_to_stack_pointer(16);
            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
        }
    }
}

This is my javascript file:

import init, { StateW } from './pkg/game.js';

await init();

document.body.setAttribute("style", "margin:0;")

let canvas = document.getElementById("canvas");
canvas.width = innerWidth;
canvas.height = innerHeight;
 
const statew = new StateW(canvas);

console.log(StateW.good());
statew.renderWasm();

This is the error from browser (chrome Version 128.0.6613.120 (Official Build) (arm64)):

Uncaught TypeError: statew.renderWasm is not a function
    at index.js:15:8

I tried changing the name of the class, function, variable, changing the variable to const and even adding a dummy function (pub fn good). When the dummy function is a static function it works as intended. But just as when it is not static it gives an error.


Solution

  • Just removed #[wasm-bindgen(constructor)] above new function.