MikeInnes / WebAssembly.jl

Other
83 stars 11 forks source link

JS Libraries #17

Open sjorn3 opened 6 years ago

sjorn3 commented 6 years ago

Add support for producing a js library out of a module.

Example output:

function wtype(i) {
  var t = typeof(i)
  if (t == "number") {
    return Number.isInteger(i) ? 'i32' : 'f64'
  } else if (t == "bigint") {
    return 'i64';
  }
  throw "Unsupported Type: " + i + " :: " + t;
}

const library = new ffi.Wrapper({
  addTwo_f64_i32: ['f64', ['f64', 'i32']], 
  addTwo_i32_f64: ['f64', ['i32', 'f64']], 
  addTwo_f64_f64: ['f64', ['f64', 'f64']], 
  addTwo_i32_i32: ['i32', ['i32', 'i32']]
}, {
  dialect: 'assemblyscript',
});

var addTwo_f64_i32, addTwo_i32_f64, addTwo_f64_f64, addTwo_i32_i32;

library.fetch_ = library.fetch;

library.fetch = (f => library.fetch_(f).then(() => {
  addTwo_f64_i32 = library.addTwo_f64_i32.bind(library);
  addTwo_i32_f64 = library.addTwo_i32_f64.bind(library);
  addTwo_f64_f64 = library.addTwo_f64_f64.bind(library);
  addTwo_i32_i32 = library.addTwo_i32_i32.bind(library);
}));

var addTwo = (...a) => eval("addTwo_" + a.map(wtype).join("_") + "(" + a.join() + ")");
library.addTwo = addTwo

export { addTwo_f64_i32, addTwo_i32_f64, addTwo_f64_f64, addTwo_i32_i32, addTwo };
export default library;

The library produced by wasm-ffi is exported, and the functions are all bound to their own names. addTwo is all of the different addTwos tied together, if the name addTwo was taken this wouldn't happen. It is also added to the library. I thought about the interface for dealing with the modules and this seems to be a good way. Used like so:

import JLAdd, { addTwo } from "./main.js"

JLAdd.fetch('./main.wasm').then(() => {
  console.log(addTwo(400, 400))
})

JLAdd could be any string, and then functions can be exported by name.

I think it would be safe to make wtype return i32 for anything else as it's probably a pointer if it's not one of those basic types, but it's not necessary yet.