4

I am trying to add some web-assembly to my project. On the beginning I created a simple method to check is my webpack works well and can I use my .wasm modules. So I created somthing like this:

#[wasm_bindgen]
pub fn return_char() -> char {
    return 'a';
}

And then I used this inside constructor of my web-component (just to check is everything works fine):

constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = template;
    console.log(return_char());
}

This worked as expected I saw 'a' in my web-app console:

enter image description here

Then when I saw that everything works fine I created struct with implementation:

#[wasm_bindgen]
pub struct Test {
    value: char
}

#[wasm_bindgen]
impl Test {
    pub fn new() -> Test {
        let value: char = 'a';
        Test {
            value
        }
    }

    pub fn value(&self) -> char {
        self.value
    }

    pub fn change_value(&mut self) {
        self.value = 'b';
    }
}

Then I add created instance of Test inside the same web-component class constructor and call methods of this Test impl. I thought that I should see 'a' and 'b' in my console

constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = template;
    const test: Test = Test.new();
    console.log(test.value());
    test.change_value();
    console.log(test.value());
}

But this didn't happen and I saw only this error:

Uncaught (in promise) ReferenceError: Cannot access '__wbindgen_throw' before initialization at Module.__wbindgen_throw (calculator_engine_bg.js:5)

I do not know why I am getting this error and how can I fix this. Maybe there is a problem with my webpack.config.js ?

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    devtool: 'eval-source-map',
    entry: './src/index.ts',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    experiments: {
        asyncWebAssembly: true
    },
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: 'ts-loader',
                include: [path.resolve(__dirname, 'src')],
            },
        ],
    },
    resolve: {
        extensions: ['.ts', '.js'],
    },
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
    },
    plugins: [
        new HTMLWebpackPlugin({
            template: path.resolve(__dirname, 'src/index.html'),
            filename: 'index.html',
        }),
    ],
};

GitHub repository with minimal code needed to reproduce: webpack-web-assembly-rust-impl-bug

webpack version: 5.0.0-beta.26

Krzysztof Kaczyński
  • 4,412
  • 6
  • 28
  • 51
  • Can you create a [mcve] that demonstrates the problem? The example code you have there works fine when I try it with a `create-wasm-app` project. – Herohtar Aug 20 '20 at 02:36
  • @Herohtar I added [repro steps to README.md](https://github.com/kaczor6418/webpack-web-assembly-rust-impl-bug/blob/example-without-error/README.md). Did you follow this steps and you still don't see any error ? – Krzysztof Kaczyński Aug 20 '20 at 07:16

1 Answers1

2

So as sokra mentioned in his answer under issue which I created. I should use experiments.syncWebAssembly instead of experiments.asyncWebAssembly. If I use this experiments.syncWebAssembly I have to add additional file which will asynchronously load index.ts file.

webpack.config.js

module.exports = {
    mode: 'development',
    devtool: 'eval-source-map',
    entry: './src/bootstrap.ts', // !! <- change path to bootstrap.ts
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    experiments: {
        syncWebAssembly: true // !! <- use syncWebAssembly instead of asyncWebAssembly
    },
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: 'ts-loader',
                include: [path.resolve(__dirname, 'src')],
            },
        ],
    },
    resolve: {
        extensions: ['.ts', '.js'],
    },
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
    },
    plugins: [
        new HTMLWebpackPlugin({
            template: path.resolve(__dirname, 'src/index.html'),
            filename: 'index.html',
        }),
    ],
};

bootstrap.ts

import('./index').catch(e => console.error('Error importing `index.js`:', e))

Full solution you can find here:: webpack-web-assembly-rust-impl-bug

Krzysztof Kaczyński
  • 4,412
  • 6
  • 28
  • 51
  • `syncWebAssembly ` is deprecated now :( – kigawas Dec 11 '20 at 03:03
  • @kigawas `syncWebAssembly` is not deprecated. More about this experimental feature you can find it here ***[experiments - sync WebAssembly](https://webpack.js.org/configuration/experiments/)*** – Krzysztof Kaczyński Jan 16 '21 at 15:31
  • This is still an issue until now. Any follow ups or fix? Setting webpack to syncWebAssembly causes another issue. – iismaell May 19 '21 at 22:45
  • @iismaell what issue you are getting? Did you have tried the template [web-assembly-rust-typescript-template](https://github.com/kaczor6418/web-assembly-rust-typescript-template) which I have created? – Krzysztof Kaczyński May 19 '21 at 23:39