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

Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded. #88

Open
erg opened this issue Dec 27, 2022 · 2 comments

Comments

@erg
Copy link

erg commented Dec 27, 2022

On WSL Ubuntu, I'm trying to run this in Chrome 108.0.5359.125 (Official Build) (64-bit) (cohort: Stable).

Uncaught (in promise) DOMException: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
    at decodeWasmBinary (http://localhost:3000/static/js/bundle.js:1598:18)
    at http://localhost:3000/static/js/bundle.js:1591:16

My code is just the example code:

import argon2 from 'argon2-browser';
const hashIt = async (email, password) => {
    const res = await argon2.hash({ pass: 'password', salt: 'salt' });
    ...
}

Some of the code in question is below:

  function loadWasmBinary() {
    if (global.loadArgon2WasmBinary) {
      return global.loadArgon2WasmBinary();
    }
    if (true) {
      return Promise.resolve(__webpack_require__(/*! ../dist/argon2.wasm */ "./node_modules/argon2-browser/dist/argon2.wasm")).then(wasmModule => {
        return decodeWasmBinary(wasmModule);
      });
    }
    const wasmPath = global.argon2WasmPath || 'node_modules/argon2-browser/dist/argon2.wasm';
    return fetch(wasmPath).then(response => response.arrayBuffer()).then(ab => new Uint8Array(ab));
  }

  function decodeWasmBinary(base64) {
    const text = atob(base64);
    const binary = new Uint8Array(new ArrayBuffer(text.length));
    for (let i = 0; i < text.length; i++) {
      binary[i] = text.charCodeAt(i);
    }
    return binary;
  }

requirements from package.json:

{
  "name": "argon2-demo-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^14.4.3",
    "argon2-browser": "^1.18.0",
    "base64-loader": "^1.0.0",
    "fs": "npm:fs-browsers",
    "fs-browsers": "^1.3.0",
    "path": "^0.12.7",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.6.1",
    "react-scripts": "5.0.1",
    "util": "^0.12.5",
    "web-vitals": "^3.1.0",
    "zustand": "^4.1.5"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
@mreinertssgr
Copy link

Sorry to necropost, @erg did you find any solution to this error?

@shinobu-uwu
Copy link

shinobu-uwu commented Sep 27, 2024

I was getting the same error, so I dug into the issue and found out it was because the bundler I was using, bun, by default generates the wasm file in the final bundle and resolves it to its filename, however this package expects the file to be embedded into the code as a base64 string.

Unfortunately bun does not support such thing out of the box, but luckily it's pretty trivial to create a plugin that does that.

This is what works for me:

import dts from 'bun-plugin-dts';

await Bun.build({
    entrypoints: ['./src/index.ts'],
    outdir: './dist',
    minify: true,
    plugins: [dts(), base64Loader()],
});

function base64Loader() {
    return {
        name: 'base64-loader',
        setup(build) {
            build.onLoad({ filter: /\.wasm$/ }, async (args) => {
                const wasmBuffer = await Bun.file(args.path).arrayBuffer();
                const base64Wasm = arrayBufferToBase64(wasmBuffer);

                return {
                    contents: `module.exports = "${base64Wasm}"`,
                    loader: 'js',
                };
            });
        },
    };
}

function arrayBufferToBase64(buffer) {
    const binary = new Uint8Array(buffer);
    return btoa(String.fromCharCode(...binary));
}

TL;DR, that error means this package couldn't load the wasm file, probably because it's not loaded the way it expects. Check your bundler's documentation on how to embed wasm files as base64 strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants