Importing Emscripten module

Hi All,

I’m trying to wrap a module that I generated using Emscripten. Originally, I compiled with default options and could import using the following:

libtn93 = new Promise(resolve => {
 require("https:/cdn.rawgit.com/sdwfrost/libtn93/master/emscripten/libtn93.js").catch(()=>resolve(window.Module));
})

However, this strategy didn’t allow me to load multiple modules, so I now compile with -s EXPORT_NAME="'libtn93'" -s MODULARIZE=1, which results in all of the generated JavaScript in a function.

In Node, I can just do this:

libtn93 = require("./libtn93.js")();

I also have a WASM file that requires slightly different treatment as the WebAssembly is loaded asynchronously:

libtn93 = require("./libtn93wasm.js")().then(function(Module){
    
});

I’ve tried everything I can think of to get either of these imported into Observable, but so far, I’ve had no luck. Any tips?

It appears to “just work”:

libtn93 = require("https://cdn.rawgit.com/sdwfrost/libtn93/master/emscripten/libtn93.js")

However, calling the libtn93 function appears to hang the browser. (And also, the way the script is defined, it also leaks a libtn93 global because the script isn’t wrapped in an immediately-invoked function expression.)

By the way, you can shorten your original code as follows:

libtn93 = require("https:/cdn.rawgit.com/sdwfrost/libtn93/master/emscripten/libtn93.js").catch(() => window.Module)

Sorry for not being clear; my original code does ‘just work’; however, this defines a global ‘Module’ object that prevents me from having multiple Emscripten modules. The new modularised version doesn’t work, however, and though I’m sure I’m making a silly mistake, the following gives Error: unable to load module

libtn93 = require("https:/rawgit.com/sdwfrost/libtn93/master/emscripten/libtn93.js")

and this gives undefined:

libtn93 = require("https:/rawgit.com/sdwfrost/libtn93/master/emscripten/libtn93.js").catch(()=>{window.libtn93})

This has happened before when I didn’t export the correct name, but this looks fine in the JS…

var libtn93 = function(libtn93) {
  libtn93 = libtn93 || {};
...
  return libtn93;
};
if (typeof exports === 'object' && typeof module === 'object')
  module.exports = libtn93;
else if (typeof define === 'function' && define['amd'])
  define([], function() { return libtn93; });
else if (typeof exports === 'object')
  exports["libtn93"] = libtn93;

I am sort of having similar problems with importing an emscripten-compiled module into an observable notebook. I paraphrased your code in the following test notebook but for some reason, the module only becomes available if I wait a few milliseconds (see cell m). Indeed, this is a bit tricky because once the module is loaded, everything works, but if I comment out the line

await Promises.delay(100);

and then reload the notebook, the last cell fails with error “TypeError: Cannot read property ‘apply’ of undefined”.

Incidentally, have you found out a solution for your problem?

You need to wait for the runtime to be ready. Details here:

It works! But I am feeling extremely dense today, as I cannot see how to follow your hint about setting MODULARIZE=1. I followed the FAQ instructions and recompiled my module with
-s MODULARIZE=1 -s 'EXPORT_NAME="MyCode"'

The compiled module is available at [https://www.lcg.ufrj.br/~bfcosta/test4.js]. How should I require it then?

My tentative notebook is at https://beta.observablehq.com/@bfcosta/webassembly-emscripten-with-modularize

Thanks!