Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,33 @@ func TestWasmExport(t *testing.T) {
}
}

// Test js.FuncOf (for syscall/js).
// This test might be extended in the future to cover more cases in syscall/js.
func TestWasmFuncOf(t *testing.T) {
// Build the wasm binary.
tmpdir := t.TempDir()
options := optionsFromTarget("wasm", sema)
buildConfig, err := builder.NewConfig(&options)
if err != nil {
t.Fatal(err)
}
result, err := builder.Build("testdata/wasmfunc.go", ".wasm", tmpdir, buildConfig)
if err != nil {
t.Fatal("failed to build binary:", err)
}

// Test the resulting binary using NodeJS.
output := &bytes.Buffer{}
cmd := exec.Command("node", "testdata/wasmfunc.js", result.Binary, buildConfig.BuildMode())
cmd.Stdout = output
cmd.Stderr = output
err = cmd.Run()
if err != nil {
t.Error("failed to run node:", err)
}
checkOutput(t, "testdata/wasmfunc.txt", output.Bytes())
}

// Test //go:wasmexport in JavaScript (using NodeJS).
func TestWasmExportJS(t *testing.T) {
type testCase struct {
Expand Down
7 changes: 0 additions & 7 deletions src/runtime/runtime_wasm_js.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ package runtime

type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript

// wasmNested is used to detect scheduler nesting (WASM calls into JS calls back into WASM).
// When this happens, we need to use a reduced version of the scheduler.
//
// TODO: this variable can probably be removed once //go:wasmexport is the only
// allowed way to export a wasm function (currently, //export also works).
var wasmNested bool

var handleEvent func()

//go:linkname setEventHandler syscall/js.setEventHandler
Expand Down
14 changes: 0 additions & 14 deletions src/runtime/runtime_wasm_js_scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,10 @@ func resume() {
handleEvent()
}()

if wasmNested {
minSched()
return
}

wasmNested = true
scheduler(false)
wasmNested = false
}

//export go_scheduler
func go_scheduler() {
if wasmNested {
minSched()
return
}

wasmNested = true
scheduler(false)
wasmNested = false
}
18 changes: 0 additions & 18 deletions src/runtime/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,24 +247,6 @@ func scheduler(returnAtDeadlock bool) {
}
}

// This horrible hack exists to make WASM work properly.
// When a WASM program calls into JS which calls back into WASM, the event with which we called back in needs to be handled before returning.
// Thus there are two copies of the scheduler running at once.
// This is a reduced version of the scheduler which does not deal with the timer queue (that is a problem for the outer scheduler).
func minSched() {
scheduleLog("start nested scheduler")
for !schedulerDone {
t := runqueue.Pop()
if t == nil {
break
}

scheduleLogTask(" run:", t)
t.Resume()
}
scheduleLog("stop nested scheduler")
}

func Gosched() {
runqueue.Push(task.Current())
task.Pause()
Expand Down
17 changes: 17 additions & 0 deletions testdata/wasmfunc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import "syscall/js"

func main() {
js.Global().Call("setCallback", js.FuncOf(func(this js.Value, args []js.Value) any {
println("inside callback! parameters:")
sum := 0
for _, value := range args {
n := value.Int()
println(" parameter:", n)
sum += n
}
return sum
}))
js.Global().Call("callCallback")
}
21 changes: 21 additions & 0 deletions testdata/wasmfunc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require('../targets/wasm_exec.js');

var callback;

global.setCallback = (cb) => {
callback = cb;
};

global.callCallback = () => {
console.log('calling callback!');
let result = callback(1, 2, 3, 4);
console.log('result from callback:', result);
};

let go = new Go();
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
go.run(result.instance);
}).catch((err) => {
console.error(err);
process.exit(1);
});
7 changes: 7 additions & 0 deletions testdata/wasmfunc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
calling callback!
inside callback! parameters:
parameter: 1
parameter: 2
parameter: 3
parameter: 4
result from callback: 10
Loading