Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: using wasm (with wasm-bindgen crate) is ok when it returns a number (like u32) but ko when it returns a String #536

Open
spacecodeur opened this issue Feb 9, 2025 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@spacecodeur
Copy link
Contributor

spacecodeur commented Feb 9, 2025

Description

For some reasons, I want to use a wasm file from a react component.
Using the crate wasm-bindgen, here a simple example of code I want to compile into wasm :

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn hello() -> u32 {
    42
}

Then I compile this with the command wasm-pack build --target web.
Then I import and use the compiled "hello" function from my src/index.tsx file like this :

import { useState, useEffect } from "react";
import init, { hello } from "../wasm/sample_wasm_example.js";

export default function IndexPage() {
  const [result, setResult] = useState<string | null>(null);

  useEffect(() => {
    init().then(() => {
      const output = hello();
      setResult(output);
    });
  }, []);

  return <>{result !== null && <h1>{result}</h1>}</>;
}

This code works perfectly (the index page from my browser shows the number 42)

But...! if instead of return a u32 I return a String like this :

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn hello() -> String {
    "banana".to_string()
}

Then I got this error (from the terminal where I ran tuono dev) if I load the index page from my browser :

<unknown>:46635: Uncaught Error: Failed to construct 'TextDecoder': the 'fatal' option is unsupported.
thread 'tokio-runtime-worker' panicked at /home/okli/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tuono_lib-0.17.6/src/ssr.rs:54:10:
called `Result::unwrap()` on an `Err` value: InvalidJs("Execute your script with d8 to debug")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

And my browser didn't display anything expect the error "The connection was reset" :

Image

I specify that the code works without any issues, whether I use u32 or String, when I use it in a simple React/ViteJS project (i.e., without going through Tuono).

Expected behaviour

I expect to see on my browser the text "banana" in a h1 tag

How to reproduce

  • create a new tuono project (version 0.17.7) named, by exemple, tuonowasm : tuono new tuonowasm
  • inside the "tuonowasm" dir, create the lib crate 'sample_wasm_example' : cargo new sample_wasm_example --lib
  • replace the default code in the tuonowasm/sample_wasm_example/src/lib.rs file by this :
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn hello() -> u32 {
    42
}

// #[wasm_bindgen]
// pub fn hello() -> String {
//     "banana".to_string()
// }
  • replace the default code in the tuonowasm/sample_wasm_example/Cargo.tomlfile by this :
[package]
name = "md_to_html"
version = "0.1.0"
edition = "2021"

[dependencies]
wasm-bindgen = "0.2.100"

[lib]
crate-type = ["cdylib", "rlib"]
  • install the binary wasm-pack : cargo install wasm-pack (or with binstall)
  • compile the sample_wasm_example crate into wasm file : cd sample_wasm_example && wasm-pack build --target web --out-dir ../src/wasm
  • replace the default code in the tuonowasm/src/routes/index.tsx file by this :
import { useState, useEffect } from "react";
import init, { hello } from "../wasm/md_to_html.js";

export default function IndexPage() {
  const [result, setResult] = useState<string | null>(null);

  useEffect(() => {
    init().then(() => {
      const output = hello();
      setResult(output);
    });
  }, []);

  return <>{result !== null && <h1>{result}</h1>}</>;
}
  • install npm packages in the main project : npm i
  • run the dev server : tuono dev
  • then run your favorite browser on http://localhost:3000

The number 42 is showed, all works fine.

  • but now, stop the tuono dev server and go again to the sample_wasm_example/src/lib.rs file then modify it like this :
use wasm_bindgen::prelude::*;

// #[wasm_bindgen]
// pub fn hello() -> u32 {
//     42
// }

#[wasm_bindgen]
pub fn hello() -> String {
    "banana".to_string()
}
  • then, remove the old wasm dir + compile the crate "sample_wasm_example" into wasm + re-run the tuono dev server : rm -rf src/wasm && cd sample_wasm_example && wasm-pack build --target web --out-dir ../src/wasm && cd .. && tuono dev then re-open your browser on http://localhost:3000

The browser shows the error page "The connection was reset" and an error appears in the terminal running the dev tuono server :

<unknown>:46635: Uncaught Error: Failed to construct 'TextDecoder': the 'fatal' option is unsupported.
thread 'tokio-runtime-worker' panicked at /home/okli/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tuono_lib-0.17.7/src/ssr.rs:54:10:
called `Result::unwrap()` on an `Err` value: InvalidJs("Execute your script with d8 to debug")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I have uploaded below the project's source code, which follows the steps above, in case you don't feel like doing them again 😉.
However, make sure to reinstall the npm packages before restarting the Tuono dev server (the wasm folder is already present in the src directory).

tuonowasm.zip

Screenshots

No response

System Info

System:
    OS: Linux 6.1 Debian GNU/Linux 12 (bookworm) 12 (bookworm)
    CPU: (32) x64 13th Gen Intel(R) Core(TM) i9-13900K
    Memory: 49.34 GB / 62.55 GB
    Container: Yes
    Shell: 5.2.15 - /bin/bash
  Binaries:
    Node: 22.11.0 - ~/apps/nodejs/bin/node
    npm: 11.0.0 - ~/apps/nodejs/bin/npm
    pnpm: 9.14.2 - ~/apps/nodejs/bin/pnpm
  Browsers:
    Brave Browser: 132.1.74.51
    Chrome: 132.0.6834.159
  npmPackages:
    tuono: 0.17.7 => 0.17.7

System info (Rust)

rustc 1.83.0 (90b35a623 2024-11-26)
cargo 1.83.0 (5ffbef321 2024-10-29)
tuono 0.17.7

Additional context

No response

@spacecodeur spacecodeur added the bug Something isn't working label Feb 9, 2025
@Valerioageno
Copy link
Member

That is really interesting. Thanks for sharing!

@Valerioageno Valerioageno self-assigned this Feb 10, 2025
@jacobhq
Copy link
Contributor

jacobhq commented Feb 15, 2025

This may be helpful: vercel/next.js#30312.

I've separately come across this issue when working with wasm myself. Maybe we need to write/find a polyfill for TextDecoder server side? Or perhaps the wasm should only be run in the browser?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants