wasm: reading from stdin fails with Windows
What version of Go are you using (go version)?
$ go version go version go1.15.7 windows/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env)?
go env Output
$ go env set GO111MODULE= set GOARCH=wasm set GOBIN= set GOCACHE=C:\Users\User\AppData\Local\go-build set GOENV=C:\Users\User\AppData\Roaming\go\env set GOEXE= set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOINSECURE= set GOMODCACHE=C:\Users\User\go\pkg\mod set GONOPROXY= set GONOSUMDB= set GOOS=js set GOPATH=C:\Users\User\go set GOPRIVATE= set GOPROXY=https://proxy.golang.org,direct set GOROOT=c:\go set GOSUMDB=sum.golang.org set GOTMPDIR= set GOTOOLDIR=c:\go\pkg\tool\windows_amd64 set GCCGO=gccgo set GOWASM= set AR=ar set CC=gcc set CXX=g++ set CGO_ENABLED=0 set GOMOD= set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-fPIC -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\User\AppData\Local\Temp\go-build540642258=/tmp/go-build -gno-record-gcc-switches
What did you do?
Code:
package main
import "fmt"
import "io/ioutil"
import "os"
func main() {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
fmt.Printf("err is %q\n", err.Error())
} else {
fmt.Printf("stdin is %q\n", string(bytes))
}
}
Build with:
C:\Users\User\Desktop>set GOROOT=js
C:\Users\User\Desktop>set GOARCH=wasm
C:\Users\User\Desktop>go build -o main.wasm main.go
What did you expect to see?
C:\Users\User\Desktop>echo abc | node c:\go\misc\wasm\wasm_exec.js main.wasm
stdin is "abc \r\n"
What did you see instead?
C:\Users\User\Desktop>echo abc | node c:\go\misc\wasm\wasm_exec.js main.wasm
panic: <object>
goroutine 6 [running]:
syscall.mapJSError(0x7ff8000100000015, 0x418128, 0x160f0008, 0x7ff8000100000011)
c:/go/src/syscall/fs_js.go:552 +0x1e
syscall.fsCall.func1(0x0, 0x0, 0x432240, 0x3, 0x3, 0x418120, 0x40000430700)
c:/go/src/syscall/fs_js.go:507 +0xb
syscall/js.handleEvent()
c:/go/src/syscall/js/func.go:96 +0x24
This is due to a bug in node where fs.read behaves incorrectly on Windows. It returns an EOF error when it hits the end of the file (the <object> is the EOF error object). There are at least two reports including https://github.com/nodejs/node/issues/35997 and https://github.com/nodejs/node/issues/19831.
However, I'm reporting it here because a) this bug is really old so it's all over the place in the wild and b) I think it's easy for Go to work around. My suggested workaround is to treat an EOF error from fs.read as null which should both avoid the panic and match Go's behavior on Unix.
I ran into this in a different case. the root issue is that the parser currently only works with objects that have "code" mappings here: https://github.com/golang/go/blob/go1.19beta1/src/syscall/fs_js.go#L548-L554
I think this issue has been fixed with the latest version of nodejs. I tried nodejs v22.8.0
I am using Node 23.0.0 on an Asahi Linux machine, and I ran node ./scripts/run-yarn.js build:cli --no-git-hash in a checkout of yarn berry and it gave a similar error... I am assuming this is related because this is the only result when I search for this error 🤔
theo@theo-macbookpro:~/src/berry$ node ./scripts/run-yarn.js build:cli --no-git-hash
➤ YN0000: ┌ Building the CLI
panic: <object>
goroutine 7 [running]:
syscall.mapJSError({{}, 0x7ff8000100000075, 0x19bddd0})
syscall/fs_js.go:565 +0x1e
syscall.fsCall.func1({{}, 0x0, 0x0}, {0x1815070, 0x1, 0x1})
syscall/fs_js.go:520 +0x7
syscall/js.handleEvent()
syscall/js/func.go:100 +0x23