Search code examples
javascriptc++screepscheerp

How do I load a cheerp-wasm program in absence of a 'path' module?


Cheerp has a cheerp-wasm target that compiles C++ to both a .js and its associated .wasm file. The way I understand it is that the .js file is effectively a loader for the webassembly.

This loader🔗 calls require("path") to import required filesystem functionalities to load the .wasm as a file. The environment in which my code runs (Screeps) does not provide access to this "path" module.


[8:39:54 AM][shard3]Error: Unknown module 'path'
                        at Object.requireFn (<runtime>:31712:23)
                        at fetchBuffer (main:10:5)
                        at main:30:1
                        at main:42:3
                        at Object.exports.evalCode (<runtime>:15584:76)
                        at Object.requireFn (<runtime>:31730:28)
                        at Object.exports.run (<runtime>:31673:60)

How do I load my wasm code if the Cheerp loader depends on functionality I cannot provide?


While Cheerp provides some flags that can be set, none seem applicable to the current sitation.

Can I hint at Cheerp to just directly call bytecode = require("mycode.wasm") and use that? Maybe Cheerp can embed the wasm as bytecode in the .js itself? Should I instead write my own loader?


Solution

  • Cheerp retrieves the wasm file in different ways based on the environment.

    The supported environments are: browser, node.js, d8 and js.

    The node environments assumes that there is a path module for reading the wasm from the filesystem.

    It seems that this is not available in your environment.

    We plan to allow more flexibility in passing the wasm file in the future, but it is a tricky problem to do it in a general way.

    For now, I can suggest a workaround.

    This is the current definition of the function that fetches the wasm:

    function fetchBuffer(p){
        var b=null,f='function';
        if(typeof fetch===f)b=fetch(p).then(r=>r.arrayBuffer());
        else if(typeof require===f){
            p=require('path').join(__dirname, p);
            b=new Promise((y,n)=>{
                require('fs').readFile(p,(e,d)=>{
                    if(e)n(e);
                    else y(d);
                });
            });
        }else b=new Promise((y,n)=>{
            y(read(p,'binary'));
        });
        return b;
    }
    

    As you can see it first tries to use the fetch function if available.

    Since it seems to be undefined in your environment, you can define it yourself before the cheerp code, and implement it using your require("mycode.wasm").

    Example (not tested):

    function fetch(path) {
      return new Promise((y,n)=> {
        let ret = {
          arrayBuffer: () => {
            return require("mycode.wasm");
          }
        };
        y(ret);
    
      });
    }