container2wasm icon indicating copy to clipboard operation
container2wasm copied to clipboard

c2w --to-js no index.html

Open wangyenshu opened this issue 10 months ago • 8 comments

I run ./c2w --build-arg SOURCE_REPO_VERSION=main --to-js ghcr.io/sagemath/sage/sage-ubuntu-xenial-toolchain-gcc_9-minimal-with-system-packages:10.6.beta8 ./sage-ubuntu-xenial-toolchain-gcc_9-minimal-with-system-packages:10.6.beta8/ And in the sage-ubuntu-xenial-toolchain-gcc_9-minimal-with-system-packages:10.6.beta8 directory, there are arg-module.js qemu-system-x86_64.wasm out.js qemu-system-x86_64.worker.js load.js qemu-system-x86_64.data

What should I do to run the wasm in static pages? I tried writing HTML that imports arg-module.js, qemu-system-x86_64.worker.js, and load.js. It doesn't work. The documentation didn't say how to write the webpack config. I am confused.

wangyenshu avatar Apr 12 '25 03:04 wangyenshu

If you don't need to setup networking, something like the following should be enough. This uses xterm-pty for setting up console for the container. If you want networking, you need /examples/emscripten/htdocs/.

You might also need the workaround discussed in #400.

<html>
  <head>
    <title>container</title>
    <link rel="stylesheet" href="https://unpkg.com/@xterm/[email protected]/css/xterm.css" />
  </head>
  <body>
    <div id="terminal"></div>
    <script src="./load.js"></script>
    <script type="module">
      import 'https://unpkg.com/[email protected]/lib/xterm.js';
      import 'https://unpkg.com/xterm-pty/index.js';
      import './arg-module.js'
      import initEmscriptenModule from './out.js';

      const xterm = new Terminal();
      xterm.open(document.getElementById("terminal"));

      const { master, slave } = openpty();

      xterm.loadAddon(master);

      Module.pty = slave;
      Module['mainScriptUrlOrBlob'] = location.origin + "/out.js";

      (async () => {
          const instance = await initEmscriptenModule(Module);
          var oldPoll = Module['TTY'].stream_ops.poll;
          Module['TTY'].stream_ops.poll = (stream, timeout) => oldPoll.call(stream, 0);
      })();
    </script>
  </body>
</html>

You still need for additional config for the server: https://github.com/container2wasm/container2wasm/blob/10a8f23ef388d40cf90d83f5dca4347e0661ddbb/examples/emscripten/xterm-pty.conf

ktock avatar Apr 12 '25 16:04 ktock

I changed the default allocator to -sMALLOC=emmalloc in the Dockerfile and tried the index.html you provided. I tried to serve it by python3 -m http.server 8000.

It said

Uncaught (in promise) ReferenceError: SharedArrayBuffer is not defined
    Module http://0.0.0.0:8000/out.js:246
    <anonymous> http://0.0.0.0:8000/:26
    <anonymous> http://0.0.0.0:8000/:29

And the page is blank.

wangyenshu avatar Apr 13 '25 02:04 wangyenshu

What browser are you using, and did you configured your http server with this? https://github.com/container2wasm/container2wasm/blob/10a8f23ef388d40cf90d83f5dca4347e0661ddbb/examples/emscripten/xterm-pty.conf

ktock avatar Apr 13 '25 04:04 ktock

@ktock I use Firefox Developer Edition version 134.0b10 (64-bit) on Ubuntu 24 LTS.

I tried again on Chromium Version 135.0.7049.84 (Official Build) snap (64-bit) using the following Python script

from http.server import HTTPServer, SimpleHTTPRequestHandler

class CustomHandler(SimpleHTTPRequestHandler):
    def end_headers(self):
        # Add custom headers before ending the header section.
        self.send_header("Cross-Origin-Opener-Policy", "same-origin")
        self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    server_address = ('', 8080)  # Listen on all interfaces, port 8080
    httpd = HTTPServer(server_address, CustomHandler)
    print("Serving HTTP on port 8080 (http://localhost:8080)...")
    httpd.serve_forever()

The terminal displays

panic: failed to stat info file: stat /mnt/wasi1/info: channel number out of range

goroutine 1 [running]:
main.main()
        /work/cmd/init/main.go:35 +0x27

And the console says

lockdown-install.js:1 Removing unpermitted intrinsics
out.js:3911 WebSocket connection to 'ws://localhost:8888/' failed: 
createPeer @ out.js:3911
connect @ out.js:4090
___syscall_connect @ out.js:4562
__emscripten_receive_on_main_thread_js @ out.js:5738
$run_js_func @ qemu-system-x86_64.wasm:0x9c9c16
$call_then_finish_task @ qemu-system-x86_64.wasm:0x9c9988
$call_with_ctx @ qemu-system-x86_64.wasm:0x9c9604
$em_task_queue_execute @ qemu-system-x86_64.wasm:0x9c7e27
$receive_notification @ qemu-system-x86_64.wasm:0x9c84cc
$em_task_queue_execute @ qemu-system-x86_64.wasm:0x9c7e27
$_emscripten_check_mailbox @ qemu-system-x86_64.wasm:0x9d5621
ret.<computed> @ out.js:6006
callUserCallback @ out.js:5670
checkMailbox @ out.js:5693

wangyenshu avatar Apr 13 '25 20:04 wangyenshu

@ktock I put it on the web https://yanshuwang.heliohost.us/index.html. And configure the header

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

On Chromium Version 135.0.7049.84 (Official Build) snap (64-bit) , it is blank and it says

lockdown-install.js:1 Removing unpermitted intrinsics
out.js:241 Uncaught (in promise) RangeError: WebAssembly.Memory(): could not allocate memory
    at out.js:241:16
    at index.html:26:34
    at index.html:29:9
(anonymous) @ out.js:241
(anonymous) @ index.html:26
(anonymous) @ index.html:29

On Firefox Developer Edition version 134.0b10 (64-bit), it displays

panic: failed to stat info file: stat /mnt/wasi1/info: channel number out of range

goroutine 1 [running]:
main.main()
        /work/cmd/init/main.go:35 +0x27

it says

wasm streaming compile failed: TypeError: WebAssembly: Response has unsupported MIME type '' expected 'application/wasm' [out.js:454:8](https://yanshuwang.heliohost.us/out.js)
falling back to ArrayBuffer instantiation [out.js:455:8](https://yanshuwang.heliohost.us/out.js)
Firefox can’t establish a connection to the server at ws://localhost:8888/.

wangyenshu avatar Apr 14 '25 04:04 wangyenshu

lockdown-install.js:1 Removing unpermitted intrinsics

Did you add additional scripts? What does this do?

I tried again on Chromium Version 135.0.7049.84 (Official Build) snap (64-bit) using the following Python script

Do you get the same result with httpd, as shown in the README?

ktock avatar Apr 17 '25 13:04 ktock

@ktock Thanks for replying.

The Python script might have some issues. Please ignore it.

The test website https://yanshuwang.heliohost.us/index.html doesn't have any additional scripts. The files are

	 qemu-system-x86_64.worker.js		5.9 KB	rw- r-- r--	
	 qemu-system-x86_64.wasm		39.0 MB	rw- r-- r--	
	 qemu-system-x86_64.data		587.0 MB	rw- r-- r--	
	 out.js		222.1 KB	rw- r-- r--	 
	 load.js		7.4 KB	rw- r-- r--	
	 index.html		975 B	rw- r-- r--	
	 arg-module.js		739 B	rw- r-- r--

And the header is correct, you can verify it by curl -I https://yanshuwang.heliohost.us And it returns

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

wangyenshu avatar Apr 17 '25 23:04 wangyenshu

@wangyenshu I've just added a simpler example without using webpack. Can you try this example and see if it works on your setup? https://github.com/container2wasm/container2wasm/tree/5a22a8f633c20a252dc2894ee54b71d386cffbc6/examples/emscripten-simple

ktock avatar May 04 '25 13:05 ktock