Running the webassembly directly produces 'TypeError: import object field 'env' is not an Object'

2,004 views
Skip to first unread message

D Danser

unread,
Nov 5, 2017, 10:59:39 AM11/5/17
to emscripten-discuss
Hi All,

I am investigating how to run C code as WebAssembly in the browser.

To test it out I made a small C program:

#include <emscripten.h>

int  EMSCRIPTEN_KEEPALIVE add2(int x, int y) {
  return x+2*y;
}

And then I compiled it using:

emcc test.c -s WASM=1 -s ONLY_MY_CODE=1 

This produced a file a.out.wasm which is 256 bytes (which seems reasonable) and a file a.out.js which is 85K (which seems very large).

Further, the a.out.wasm file has the text "add2" inside, so this seemed promising!

Now, having read about WebAssembly on the web I did not understand why I would need the a.out.js file, so I went ahead and tried to use a.out.wasm directly inspired by https://developer.mozilla.org/en-US/docs/WebAssembly/Loading_and_running:

<script>
function fetchAndInstantiate(url, importObject) {
  return fetch(url).then(response =>
    response.arrayBuffer()
  ).then(bytes =>
    WebAssembly.instantiate(bytes, importObject)
  ).then(results =>
    results.instance
  );
}

importObject={}

fetchAndInstantiate('a.out.wasm', importObject).then(function(instance) {
  console.log(instance.exports._add2(2,4));
})
</script>

Unfortunately this did not work - I got this error in the JavaScript console:

TypeError: import object field 'env' is not an Object

Troubleshooting a bit further I tried this html:

<script>
fetch('a.out.wasm').then(response =>
  response.arrayBuffer()
).then(bytes =>
  WebAssembly.compile(bytes)
).then(function(mod) {
  var imports = WebAssembly.Module.imports(mod);
  console.log(imports[0]);
});
</script>

Which gave this output:

Object { module: "env", name: "STACKTOP", kind: "global" } 

Debugging a bit futher it seemed like the webassembly needs an env in importObject with a bunch of values in it, including this STACKTOP.

My questions are:

1) Can emscripten produce a webassembly file that does not need such values to be set externally?
2) If emscripten cannot, is there a recommend way to get less than 85K of JavaScript to set reasonable values?

I used FireFox version 56 and emscripten version 1.37.22.


Best,

Christian

Alon Zakai

unread,
Nov 5, 2017, 11:22:58 AM11/5/17
to emscripten-discuss
There is an experimental way to do something like that, using the SIDE_MODULE option, see


That will create a module that can be linked, which will have very minimal import requirements. However, it will still need some imports to set up the stack etc.

(ONLY_MY_CODE prevents linking in of system library code, but it does still generate a js runtime to load the wasm, which it sounds like you don't want)

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

D Danser

unread,
Nov 5, 2017, 11:38:47 AM11/5/17
to emscripten-discuss
Thanks Alon!

This looks exactly what I need - I will study it in more detail. 

For the record, I did manage to get my code above running by using:

importObject={.
  env: {.
    STACKTOP: 0,.
    STACK_MAX:65536,.
    abortStackOverflow: function(val) { throw new Error("stackoverfow"); },
    memory: new WebAssembly.Memory( { initial: 256, maximum:256 } ),
    table: new WebAssembly.Table( { initial:0, maximum:0, element: "anyfunc" } )
    memoryBase:0,
    tableBase:0
  }.
Reply all
Reply to author
Forward
0 new messages