return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
                        }
 
+                       const testCallExport = (a, b) => {
+                               return this._inst.exports.testExport(a, b);
+                       }
+
                        const timeOrigin = Date.now() - performance.now();
                        this.importObject = {
                                _gotest: {
                                        add: (a, b) => a + b,
+                                       callExport: testCallExport,
                                },
                                gojs: {
                                        // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
 
                ctxt.Out.WriteByte(0x02)      // mem export
                writeUleb128(ctxt.Out, 0)     // memidx
        case "js":
-               writeUleb128(ctxt.Out, 4) // number of exports
+               writeUleb128(ctxt.Out, uint64(4+len(ldr.WasmExports))) // number of exports
                for _, name := range []string{"run", "resume", "getsp"} {
                        s := ldr.Lookup("wasm_export_"+name, 0)
                        if s == 0 {
                        ctxt.Out.WriteByte(0x00)            // func export
                        writeUleb128(ctxt.Out, uint64(idx)) // funcidx
                }
+               for _, s := range ldr.WasmExports {
+                       idx := uint32(lenHostImports) + uint32(ldr.SymValue(s)>>16) - funcValueOffset
+                       writeName(ctxt.Out, ldr.SymName(s))
+                       ctxt.Out.WriteByte(0x00)            // func export
+                       writeUleb128(ctxt.Out, uint64(idx)) // funcidx
+               }
                writeName(ctxt.Out, "mem") // inst.exports.mem in wasm_exec.js
                ctxt.Out.WriteByte(0x02)   // mem export
                writeUleb128(ctxt.Out, 0)  // memidx
 
        }
 }
 
+// testCallExport is imported from host (wasm_exec.js), which calls testExport.
+//
+//go:wasmimport _gotest callExport
+func testCallExport(a int32, b int64) int64
+
+//go:wasmexport testExport
+func testExport(a int32, b int64) int64 {
+       testExportCalled = true
+       // test stack growth
+       growStack(1000)
+       // force a goroutine switch
+       ch := make(chan int64)
+       go func() {
+               ch <- int64(a)
+               ch <- b
+       }()
+       return <-ch + <-ch
+}
+
+var testExportCalled bool
+
+func growStack(n int64) {
+       if n > 0 {
+               growStack(n - 1)
+       }
+}
+
+func TestWasmExport(t *testing.T) {
+       testExportCalled = false
+       a := int32(123)
+       b := int64(456)
+       want := int64(a) + b
+       if got := testCallExport(a, b); got != want {
+               t.Errorf("got %v, want %v", got, want)
+       }
+       if !testExportCalled {
+               t.Error("testExport not called")
+       }
+}
+
 func TestBool(t *testing.T) {
        want := true
        o := dummys.Get("someBool")
 // Note: All JavaScript functions return a JavaScript array, which will cause
 // one allocation to be created to track the Value.gcPtr for the Value finalizer.
 var allocTests = []struct {
-       argLen  int // The number of arguments to use for the syscall
+       argLen   int // The number of arguments to use for the syscall
        expected int // The expected number of allocations
 }{
        // For less than or equal to 16 arguments, we expect 1 allocation:
        // - makeValue new(ref)
-       {0,  1},
-       {2,  1},
+       {0, 1},
+       {2, 1},
        {15, 1},
        {16, 1},
        // For greater than 16 arguments, we expect 3 allocation:
                tmpArray := js.Global().Get("Array").New(0)
                numAllocs := testing.AllocsPerRun(100, func() {
                        tmpArray.Call("concat", args...)
-               });
+               })
 
                if numAllocs != float64(test.expected) {
                        t.Errorf("got numAllocs %#v, want %#v", numAllocs, test.expected)
                concatFunc := tmpArray.Get("concat").Call("bind", tmpArray)
                numAllocs := testing.AllocsPerRun(100, func() {
                        concatFunc.Invoke(args...)
-               });
+               })
 
                if numAllocs != float64(test.expected) {
                        t.Errorf("got numAllocs %#v, want %#v", numAllocs, test.expected)
 
                numAllocs := testing.AllocsPerRun(100, func() {
                        arrayConstructor.New(args...)
-               });
+               })
 
                if numAllocs != float64(test.expected) {
                        t.Errorf("got numAllocs %#v, want %#v", numAllocs, test.expected)