diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js
index 233c5aa1877a6b28916ba767527b160f3c60d161..02a753c823036047e5474f427d4a34181bed7f02 100644
--- a/misc/wasm/wasm_exec.js
+++ b/misc/wasm/wasm_exec.js
@@ -333,14 +333,10 @@
 				false,
 				global,
 				this._inst.exports.mem,
-				() => { // resolveCallbackPromise
-					if (this.exited) {
-						throw new Error("bad callback: Go program has already exited");
-					}
-					setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous
-				},
+				this,
 			];
 			this._refs = new Map();
+			this._callbackShutdown = false;
 			this.exited = false;
 
 			const mem = new DataView(this._inst.exports.mem.buffer)
@@ -377,7 +373,12 @@
 
 			while (true) {
 				const callbackPromise = new Promise((resolve) => {
-					this._resolveCallbackPromise = resolve;
+					this._resolveCallbackPromise = () => {
+						if (this.exited) {
+							throw new Error("bad callback: Go program has already exited");
+						}
+						setTimeout(resolve, 0); // make sure it is asynchronous
+					};
 				});
 				this._inst.exports.run(argc, argv);
 				if (this.exited) {
@@ -399,17 +400,16 @@
 		go.env = process.env;
 		go.exit = process.exit;
 		WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
-			process.on("exit", () => { // Node.js exits if no callback is pending
-				if (!go.exited) {
-					console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!");
-					process.exit(1);
+			process.on("exit", (code) => { // Node.js exits if no callback is pending
+				if (code === 0 && !go.exited) {
+					// deadlock, make Go print error and stack traces
+					go._callbackShutdown = true;
+					go._inst.exports.run();
 				}
 			});
 			return go.run(result.instance);
 		}).catch((err) => {
-			console.error(err);
-			go.exited = true;
-			process.exit(1);
+			throw err;
 		});
 	}
 })();
diff --git a/src/syscall/js/callback.go b/src/syscall/js/callback.go
index fa8a03ab0c3997210d9c1ecad1a867b179c3b2bf..de9da888fd9e03219131f9454478846d2f67f8ae 100644
--- a/src/syscall/js/callback.go
+++ b/src/syscall/js/callback.go
@@ -11,10 +11,10 @@ import "sync"
 var pendingCallbacks = Global().Get("Array").New()
 
 var makeCallbackHelper = Global().Call("eval", `
-	(function(id, pendingCallbacks, resolveCallbackPromise) {
+	(function(id, pendingCallbacks, go) {
 		return function() {
 			pendingCallbacks.push({ id: id, args: arguments });
-			resolveCallbackPromise();
+			go._resolveCallbackPromise();
 		};
 	})
 `)
@@ -71,7 +71,7 @@ func NewCallback(fn func(args []Value)) Callback {
 	callbacks[id] = fn
 	callbacksMu.Unlock()
 	return Callback{
-		Value: makeCallbackHelper.Invoke(id, pendingCallbacks, resolveCallbackPromise),
+		Value: makeCallbackHelper.Invoke(id, pendingCallbacks, jsGo),
 		id:    id,
 	}
 }
@@ -116,7 +116,7 @@ func (c Callback) Release() {
 var callbackLoopOnce sync.Once
 
 func callbackLoop() {
-	for {
+	for !jsGo.Get("_callbackShutdown").Bool() {
 		sleepUntilCallback()
 		for {
 			cb := pendingCallbacks.Call("shift")
diff --git a/src/syscall/js/js.go b/src/syscall/js/js.go
index 0cc98bd52c631bd6803c1b798c24eba200d6adb0..4b55193c4126c277f32d9363db4c233315040817 100644
--- a/src/syscall/js/js.go
+++ b/src/syscall/js/js.go
@@ -56,14 +56,14 @@ func (e Error) Error() string {
 }
 
 var (
-	valueNaN               = predefValue(0)
-	valueUndefined         = predefValue(1)
-	valueNull              = predefValue(2)
-	valueTrue              = predefValue(3)
-	valueFalse             = predefValue(4)
-	valueGlobal            = predefValue(5)
-	memory                 = predefValue(6) // WebAssembly linear memory
-	resolveCallbackPromise = predefValue(7) // function that the callback helper uses to resume the execution of Go's WebAssembly code
+	valueNaN       = predefValue(0)
+	valueUndefined = predefValue(1)
+	valueNull      = predefValue(2)
+	valueTrue      = predefValue(3)
+	valueFalse     = predefValue(4)
+	valueGlobal    = predefValue(5)
+	memory         = predefValue(6) // WebAssembly linear memory
+	jsGo           = predefValue(7) // instance of the Go class in JavaScript
 )
 
 // Undefined returns the JavaScript value "undefined".