plnkr / feedback

Feedback on Plunker
19 stars 11 forks source link

A simple "hello world" example with Box2D-WASM doesn't work on Plunker #597

Closed 8Observer8 closed 1 year ago

8Observer8 commented 1 year ago

This example works on PlayCode: https://playcode.io/1512368 but it doesn't work on Plunker: https://plnkr.co/edit/YQTyTFtudEFTq9tj

index.html

<!DOCTYPE html>

<html>

<head>
    <title>Example</title>
</head>

<body>
    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "box2d-wasm": "https://cdn.jsdelivr.net/npm/box2d-wasm@7.0.0/+esm"
            }
        }
    </script>

    <script type="module" src="./js/index.js"></script>
</body>

</html>

js/index.js

import { box2d, initBox2D } from "./init-box2d.js";

let world;
const pixlesPerMeter = 30;

async function init() {
    await initBox2D();

    const {
        b2Vec2
    } = box2d;

    const gravity = new b2Vec2(0, -9.8);
    console.log(`gravity = (${gravity.x}, ${gravity.y})`);
}

init();

js/init-box2d.js

import Box2DLib from "box2d-wasm";

export let box2d = null;

export function initBox2D() {
    return new Promise(resolve => {
        Box2DLib().then((re) => {
            box2d = re;
            resolve();
        });
    });
}

You can see these messages in the browser console:

Box2D.simd.js:30     GET https://cdn.jsdelivr.net/npm/box2d-wasm@7.0.0/dist/es/Box2D.simd.js/Box2D.simd.wasm 404
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:30 wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': HTTP status code is not ok
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:30 falling back to ArrayBuffer instantiation
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:19     GET https://cdn.jsdelivr.net/npm/box2d-wasm@7.0.0/dist/es/Box2D.simd.js/Box2D.simd.wasm 404
V @ Box2D.simd.js:19
o @ Box2D.simd.js:29
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:17 Aborted(both async and sync fetching of the wasm failed)
O @ Box2D.simd.js:17
z @ Box2D.simd.js:18
(anonymous) @ Box2D.simd.js:19
Promise.catch (async)
V @ Box2D.simd.js:19
o @ Box2D.simd.js:29
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:29 failed to asynchronously prepare wasm: RuntimeError: Aborted(both async and sync fetching of the wasm failed). Build with -s ASSERTIONS=1 for more info.
(anonymous) @ Box2D.simd.js:29
Promise.then (async)
o @ Box2D.simd.js:29
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:17 Aborted(RuntimeError: Aborted(both async and sync fetching of the wasm failed). Build with -s ASSERTIONS=1 for more info.)
O @ Box2D.simd.js:17
(anonymous) @ Box2D.simd.js:29
Promise.then (async)
o @ Box2D.simd.js:29
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
Promise.then (async)
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:30
(anonymous) @ Box2D.simd.js:29
s @ entry.js:30
await in s (async)
(anonymous) @ init-box2d.js:7
initBox2D @ init-box2d.js:6
init @ index.js:7
(anonymous) @ index.js:17
Box2D.simd.js:17 Uncaught (in promise) RuntimeError: Aborted(both async and sync fetching of the wasm failed). Build with -s ASSERTIONS=1 for more info.
    at O (Box2D.simd.js:17:75)
    at z (Box2D.simd.js:18:151)
    at Box2D.simd.js:19:260
ggoodman commented 1 year ago

As far as I can tell playcode appears to be running some form of in-process bundler that seems to be paving over a module resolution issue in jsDeliver's magic /+esm transform.

In the box2d-wasm's wasm loader, you can see the code:

new URL("Box2D.simd.wasm",import.meta.url)

Knowing that code is being loaded from https://cdn.jsdelivr.net/npm/box2d-wasm@7.0.0/dist/es/Box2D.simd.js/+esm, we can test it out:

new URL("Box2D.simd.wasm","https://cdn.jsdelivr.net/npm/box2d-wasm@7.0.0/dist/es/Box2D.simd.js/+esm").toString()
'https://cdn.jsdelivr.net/npm/box2d-wasm@7.0.0/dist/es/Box2D.simd.js/Box2D.simd.wasm'

So I would say that while it is unfortunate that this doesn't work natively on Plunker, the bug is either in the jsDeliver ESM transform or the actual box2d distribution. PlayCode has done some clever work with their in-browser bundling solution to pave this over.

8Observer8 commented 1 year ago

Thanks a lot for the detailed answer. The solution is to upload the "box2d-wasm" files to the hosting. For example on GitHub Pages:

image

In my case I have a link to box2d-wasm.min.js that I can use with import map:

    <!-- Since importmap is not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.min.js -->
    <script async src="https://unpkg.com/es-module-shims@0.1.7/dist/es-module-shims.min.js"></script>

    <script type="importmap">
        {
            "imports": {
                "box2d-wasm": "https://8observer8.github.io/lib/box2d-wasm-7.0.0-box2d-2.4.1/box2d-wasm.min.js",
                "pixi.js": "https://cdn.jsdelivr.net/npm/pixi.js@7.2.4/+esm"
            }
        }
    </script>

    <script type="module" src="./js/index.js"></script>

For example, using box2d-wasm with Pixi.js with drawing colliders and ray casting:

ray-casting-box2dwasm-pixijs-js

8Observer8 commented 8 months ago

UNPKG version works without the problem:

Playground: https://plnkr.co/edit/BGNYcIJRiJXpd9N4?preview

    <!-- Since import maps are not yet supported by all browsers, its is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://unpkg.com/es-module-shims@1.8.3/dist/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "box2d-wasm": "https://unpkg.com/box2d-wasm@7.0.0/dist/es/Box2D.js",
                "gl-matrix": "https://cdn.jsdelivr.net/npm/gl-matrix@3.4.3/+esm"
            }
        }
    </script>

    <script type="module">
        import { mat4, vec3 } from "gl-matrix";

        const v = vec3.fromValues(1, 2, 3);
        console.log(v);

        const m = mat4.create();
        console.log(m);
    </script>

    <!-- <script type="module" src="./js/index.js"></script> -->