36

With support for WebAssembly coming into all new major browsers, how can I check whether the current browser which is visiting my website supports it?

Ayush Gupta
  • 8,716
  • 8
  • 59
  • 92

3 Answers3

60

There are a few ways that you can detect the presence of WebAssembly. The basic one is to check whether WebAssembly if of type "object" in the global scope, but "global scope" is a tricky thing to get to in different JavaScript environments (main browser thread, worker, node.js).

Doing so is also not technically sufficient because you could have WebAssembly support but be unable to actually compile or instantiate because of CSP (and exactly what CSP disallows isn't standardized yet, work ongoing here).

A conservative check could be as follows:

const supported = (() => {
    try {
        if (typeof WebAssembly === "object"
            && typeof WebAssembly.instantiate === "function") {
            const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
            if (module instanceof WebAssembly.Module)
                return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
        }
    } catch (e) {
    }
    return false;
})();

console.log(supported ? "WebAssembly is supported" : "WebAssembly is not supported");

It does the following:

  • Check whether WebAssembly is accessible in the current scope. If it's not global we don't really care!
  • See whether it has the .instantiate function, which we don't actually use here but which you'd want to use when you actually instantiate because it's asynchronous and can handle large modules on the main thread or off.
  • Try to synchronously compile the smallest possible module (magic number '\0', 'a', 's', 'm', followed by version number 1 encoded as a uint32), and see if we get a WebAssembly.Module out of it.
  • Finally, try to synchronously instantiate that module, and check that it's a WebAssembly.Instance.

This is a bit much but should work regardless of:

  • Where code is running (main thread, worker, node.js).
  • How CSP ends up being standardized.
JF Bastien
  • 6,673
  • 2
  • 26
  • 34
  • Threw a quick test together and this test took 1 ms, can't beat that with a baseball bat – Dexygen Nov 30 '18 at 01:00
  • @GeorgeJempty I just ran it on JSBench, and I get at least 20x that on Safari, 6x that on Chrome. If it actually becomes a bottleneck on the web, browsers will optimize it. – JF Bastien Dec 11 '18 at 00:37
  • Odd, the html code from [this](https://webassemblycode.com/browser-supports-webassembly-degree/) doesn't say not supported(in red) on Chromium `74.0.3729.169-2` (on Arch Linux), but does so on Firefox; while this answer's code says not supported on both. I did find it odd also that protonmail works with webassembly disabled on Chromium though, I guess maybe it's not disabled anymore via: `--disable-asm-webassembly --disable-features=AsmJsToWebAssembly --disable-features=WebAssembly,WebAssemblyStreaming` –  May 29 '19 at 15:10
  • The `Hello world` example from [here](https://webassembly.org/getting-started/developers-guide/) also works on chromium `74.0.3729.169-2` (but not on firefox). I guess WebAssembly can't be disabled on chromium anymore, but it can be disabled on Firefox `69.0a1 (2019-05-26) (64-bit)`. –  May 29 '19 at 15:34
  • Ok, chromium webassembly can be disabled via `--js-flags=--noexpose_wasm`, [source](https://github.com/stevespringett/disable-webassembly#disabling-guidance) –  May 29 '19 at 15:39
  • While I agree this answer is the robust way to do it, since I had no concerns with CSP or non-browser contexts, I simplified this to `function isWebAssemblySupported() { return (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function"); };` – Patrick Szalapski May 18 '20 at 12:30
3

(Insufficent reputation to comment so....) If you're testing on older browsers the () => syntax is not supported, so it can be done as a function all instead:

function wasmSupported() {
    // try/catch, return false; as in JF Bastien's answer
}
    
if(wasmSupported()) { ... }
Ayush Gupta
  • 8,716
  • 8
  • 59
  • 92
  • But if youre testing on older browsers WebAssembly certainly isnt supported anyways? – pacukluka Feb 20 '21 at 17:56
  • @pacukluka I'm assuming in most cases that the `if` comes with an `else` in practice to let end users know what's going wrong with the webpage. – Ora Walters May 23 '21 at 05:16
1

In case it helps, I've just found Google Chrome Labs' "wasm-feature-detect" library:

https://github.com/GoogleChromeLabs/wasm-feature-detect

It's used to power the "Your browser" column at https://webassembly.org/roadmap/

HTH.

jaimet
  • 353
  • 3
  • 8