aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/syscall
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-09-24 21:46:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-24 21:46:21 +0000
commitdd931d9b48647e898dc80927c532ae93cc09e192 (patch)
tree71be2295cd79b8a182f6130611658db8628772d5 /libgo/go/syscall
parent779d8a5ad09b01428726ea5a0e6c87bd9ac3c0e4 (diff)
downloadgcc-dd931d9b48647e898dc80927c532ae93cc09e192.zip
gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.gz
gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.bz2
libgo: update to Go 1.11
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
Diffstat (limited to 'libgo/go/syscall')
-rw-r--r--libgo/go/syscall/dirent.go2
-rw-r--r--libgo/go/syscall/endian_little.go2
-rw-r--r--libgo/go/syscall/env_unix.go2
-rw-r--r--libgo/go/syscall/env_windows.go2
-rw-r--r--libgo/go/syscall/exec_linux_test.go9
-rw-r--r--libgo/go/syscall/exec_windows.go2
-rw-r--r--libgo/go/syscall/export_linux_test.go9
-rw-r--r--libgo/go/syscall/forkpipe.go (renamed from libgo/go/syscall/forkpipe_bsd.go)3
-rw-r--r--libgo/go/syscall/forkpipe2.go (renamed from libgo/go/syscall/exec_freebsd.go)2
-rw-r--r--libgo/go/syscall/fs_js.go501
-rw-r--r--libgo/go/syscall/js/callback.go122
-rw-r--r--libgo/go/syscall/js/js.go382
-rw-r--r--libgo/go/syscall/js/js_test.go319
-rw-r--r--libgo/go/syscall/js/typedarray.go102
-rw-r--r--libgo/go/syscall/libcall_linux.go9
-rw-r--r--libgo/go/syscall/net_js.go128
-rw-r--r--libgo/go/syscall/pwd_plan9.go10
-rw-r--r--libgo/go/syscall/route_freebsd_32bit.go2
-rw-r--r--libgo/go/syscall/security_windows.go6
-rw-r--r--libgo/go/syscall/setuidgid_32_linux.go2
-rw-r--r--libgo/go/syscall/setuidgid_linux.go2
-rw-r--r--libgo/go/syscall/syscall.go13
-rw-r--r--libgo/go/syscall/syscall_errno.go2
-rw-r--r--libgo/go/syscall/syscall_js.go307
-rw-r--r--libgo/go/syscall/syscall_linux.go5
-rw-r--r--libgo/go/syscall/syscall_linux_test.go202
-rw-r--r--libgo/go/syscall/syscall_plan9_test.go53
-rw-r--r--libgo/go/syscall/syscall_test.go4
-rw-r--r--libgo/go/syscall/syscall_unix.go10
-rw-r--r--libgo/go/syscall/tables_nacljs.go490
-rw-r--r--libgo/go/syscall/timestruct.go2
31 files changed, 2676 insertions, 30 deletions
diff --git a/libgo/go/syscall/dirent.go b/libgo/go/syscall/dirent.go
index a09bf05..5c7af42 100644
--- a/libgo/go/syscall/dirent.go
+++ b/libgo/go/syscall/dirent.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package syscall
diff --git a/libgo/go/syscall/endian_little.go b/libgo/go/syscall/endian_little.go
index a5d32ae..0cd2d75 100644
--- a/libgo/go/syscall/endian_little.go
+++ b/libgo/go/syscall/endian_little.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
-// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv64 sh
+// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv64 sh wasm
package syscall
diff --git a/libgo/go/syscall/env_unix.go b/libgo/go/syscall/env_unix.go
index eb93e2e..0b6b711 100644
--- a/libgo/go/syscall/env_unix.go
+++ b/libgo/go/syscall/env_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
// Unix environment variables.
diff --git a/libgo/go/syscall/env_windows.go b/libgo/go/syscall/env_windows.go
index 1606b42..74b154e 100644
--- a/libgo/go/syscall/env_windows.go
+++ b/libgo/go/syscall/env_windows.go
@@ -57,7 +57,7 @@ func Clearenv() {
for _, s := range Environ() {
// Environment variables can begin with =
// so start looking for the separator = at j=1.
- // http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+ // https://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
for j := 1; j < len(s); j++ {
if s[j] == '=' {
Unsetenv(s[0:j])
diff --git a/libgo/go/syscall/exec_linux_test.go b/libgo/go/syscall/exec_linux_test.go
index 17df8f4..f551e87 100644
--- a/libgo/go/syscall/exec_linux_test.go
+++ b/libgo/go/syscall/exec_linux_test.go
@@ -84,6 +84,15 @@ func checkUserNS(t *testing.T) {
t.Skip("kernel doesn't support user namespaces")
}
}
+
+ // On Centos 7.5+, user namespaces are disabled if user.max_user_namespaces = 0
+ if _, err := os.Stat("/proc/sys/user/max_user_namespaces"); err == nil {
+ buf, errRead := ioutil.ReadFile("/proc/sys/user/max_user_namespaces")
+ if errRead == nil && buf[0] == '0' {
+ t.Skip("kernel doesn't support user namespaces")
+ }
+ }
+
// When running under the Go continuous build, skip tests for
// now when under Kubernetes. (where things are root but not quite)
// Both of these are our own environment variables.
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
index 91b0e84..c78bad8 100644
--- a/libgo/go/syscall/exec_windows.go
+++ b/libgo/go/syscall/exec_windows.go
@@ -15,7 +15,7 @@ import (
var ForkLock sync.RWMutex
// EscapeArg rewrites command line argument s as prescribed
-// in http://msdn.microsoft.com/en-us/library/ms880421.
+// in https://msdn.microsoft.com/en-us/library/ms880421.
// This function returns "" (2 double quotes) if s is empty.
// Alternatively, these transformations are done:
// - every back slash (\) is doubled, but only if immediately
diff --git a/libgo/go/syscall/export_linux_test.go b/libgo/go/syscall/export_linux_test.go
new file mode 100644
index 0000000..274849e
--- /dev/null
+++ b/libgo/go/syscall/export_linux_test.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+var RawSyscallNoError = rawSyscallNoError
+
+const Sys_GETEUID = sys_GETEUID
diff --git a/libgo/go/syscall/forkpipe_bsd.go b/libgo/go/syscall/forkpipe.go
index d479284..71890a2 100644
--- a/libgo/go/syscall/forkpipe_bsd.go
+++ b/libgo/go/syscall/forkpipe.go
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly netbsd openbsd solaris
+// +build darwin dragonfly solaris
package syscall
+// Try to open a pipe with O_CLOEXEC set on both file descriptors.
func forkExecPipe(p []int) error {
err := Pipe(p)
if err != nil {
diff --git a/libgo/go/syscall/exec_freebsd.go b/libgo/go/syscall/forkpipe2.go
index 1654b4b..c9a0c49 100644
--- a/libgo/go/syscall/exec_freebsd.go
+++ b/libgo/go/syscall/forkpipe2.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build freebsd netbsd openbsd
+
package syscall
func forkExecPipe(p []int) error {
diff --git a/libgo/go/syscall/fs_js.go b/libgo/go/syscall/fs_js.go
new file mode 100644
index 0000000..00d6c76
--- /dev/null
+++ b/libgo/go/syscall/fs_js.go
@@ -0,0 +1,501 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm
+
+package syscall
+
+import (
+ "errors"
+ "io"
+ "sync"
+ "syscall/js"
+)
+
+// Provided by package runtime.
+func now() (sec int64, nsec int32)
+
+var jsProcess = js.Global().Get("process")
+var jsFS = js.Global().Get("fs")
+var constants = jsFS.Get("constants")
+
+var (
+ nodeWRONLY = constants.Get("O_WRONLY").Int()
+ nodeRDWR = constants.Get("O_RDWR").Int()
+ nodeCREATE = constants.Get("O_CREAT").Int()
+ nodeTRUNC = constants.Get("O_TRUNC").Int()
+ nodeAPPEND = constants.Get("O_APPEND").Int()
+ nodeEXCL = constants.Get("O_EXCL").Int()
+)
+
+type jsFile struct {
+ path string
+ entries []string
+ pos int64
+ seeked bool
+}
+
+var filesMu sync.Mutex
+var files = map[int]*jsFile{
+ 0: &jsFile{},
+ 1: &jsFile{},
+ 2: &jsFile{},
+}
+
+func fdToFile(fd int) (*jsFile, error) {
+ filesMu.Lock()
+ f, ok := files[fd]
+ filesMu.Unlock()
+ if !ok {
+ return nil, EBADF
+ }
+ return f, nil
+}
+
+func Open(path string, openmode int, perm uint32) (int, error) {
+ if err := checkPath(path); err != nil {
+ return 0, err
+ }
+
+ flags := 0
+ if openmode&O_WRONLY != 0 {
+ flags |= nodeWRONLY
+ }
+ if openmode&O_RDWR != 0 {
+ flags |= nodeRDWR
+ }
+ if openmode&O_CREATE != 0 {
+ flags |= nodeCREATE
+ }
+ if openmode&O_TRUNC != 0 {
+ flags |= nodeTRUNC
+ }
+ if openmode&O_APPEND != 0 {
+ flags |= nodeAPPEND
+ }
+ if openmode&O_EXCL != 0 {
+ flags |= nodeEXCL
+ }
+ if openmode&O_SYNC != 0 {
+ return 0, errors.New("syscall.Open: O_SYNC is not supported by js/wasm")
+ }
+
+ jsFD, err := fsCall("openSync", path, flags, perm)
+ if err != nil {
+ return 0, err
+ }
+ fd := jsFD.Int()
+
+ var entries []string
+ if stat, err := fsCall("fstatSync", fd); err == nil && stat.Call("isDirectory").Bool() {
+ dir, err := fsCall("readdirSync", path)
+ if err != nil {
+ return 0, err
+ }
+ entries = make([]string, dir.Length())
+ for i := range entries {
+ entries[i] = dir.Index(i).String()
+ }
+ }
+
+ f := &jsFile{
+ path: path,
+ entries: entries,
+ }
+ filesMu.Lock()
+ files[fd] = f
+ filesMu.Unlock()
+ return fd, nil
+}
+
+func Close(fd int) error {
+ filesMu.Lock()
+ delete(files, fd)
+ filesMu.Unlock()
+ _, err := fsCall("closeSync", fd)
+ return err
+}
+
+func CloseOnExec(fd int) {
+ // nothing to do - no exec
+}
+
+func Mkdir(path string, perm uint32) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ _, err := fsCall("mkdirSync", path, perm)
+ return err
+}
+
+func ReadDirent(fd int, buf []byte) (int, error) {
+ f, err := fdToFile(fd)
+ if err != nil {
+ return 0, err
+ }
+ if f.entries == nil {
+ return 0, EINVAL
+ }
+
+ n := 0
+ for len(f.entries) > 0 {
+ entry := f.entries[0]
+ l := 2 + len(entry)
+ if l > len(buf) {
+ break
+ }
+ buf[0] = byte(l)
+ buf[1] = byte(l >> 8)
+ copy(buf[2:], entry)
+ buf = buf[l:]
+ n += l
+ f.entries = f.entries[1:]
+ }
+
+ return n, nil
+}
+
+func setStat(st *Stat_t, jsSt js.Value) {
+ st.Dev = int64(jsSt.Get("dev").Int())
+ st.Ino = uint64(jsSt.Get("ino").Int())
+ st.Mode = uint32(jsSt.Get("mode").Int())
+ st.Nlink = uint32(jsSt.Get("nlink").Int())
+ st.Uid = uint32(jsSt.Get("uid").Int())
+ st.Gid = uint32(jsSt.Get("gid").Int())
+ st.Rdev = int64(jsSt.Get("rdev").Int())
+ st.Size = int64(jsSt.Get("size").Int())
+ st.Blksize = int32(jsSt.Get("blksize").Int())
+ st.Blocks = int32(jsSt.Get("blocks").Int())
+ atime := int64(jsSt.Get("atimeMs").Int())
+ st.Atime = atime / 1000
+ st.AtimeNsec = (atime % 1000) * 1000000
+ mtime := int64(jsSt.Get("mtimeMs").Int())
+ st.Mtime = mtime / 1000
+ st.MtimeNsec = (mtime % 1000) * 1000000
+ ctime := int64(jsSt.Get("ctimeMs").Int())
+ st.Ctime = ctime / 1000
+ st.CtimeNsec = (ctime % 1000) * 1000000
+}
+
+func Stat(path string, st *Stat_t) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ jsSt, err := fsCall("statSync", path)
+ if err != nil {
+ return err
+ }
+ setStat(st, jsSt)
+ return nil
+}
+
+func Lstat(path string, st *Stat_t) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ jsSt, err := fsCall("lstatSync", path)
+ if err != nil {
+ return err
+ }
+ setStat(st, jsSt)
+ return nil
+}
+
+func Fstat(fd int, st *Stat_t) error {
+ jsSt, err := fsCall("fstatSync", fd)
+ if err != nil {
+ return err
+ }
+ setStat(st, jsSt)
+ return nil
+}
+
+func Unlink(path string) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ _, err := fsCall("unlinkSync", path)
+ return err
+}
+
+func Rmdir(path string) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ _, err := fsCall("rmdirSync", path)
+ return err
+}
+
+func Chmod(path string, mode uint32) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ _, err := fsCall("chmodSync", path, mode)
+ return err
+}
+
+func Fchmod(fd int, mode uint32) error {
+ _, err := fsCall("fchmodSync", fd, mode)
+ return err
+}
+
+func Chown(path string, uid, gid int) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ return ENOSYS
+}
+
+func Fchown(fd int, uid, gid int) error {
+ return ENOSYS
+}
+
+func Lchown(path string, uid, gid int) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ return ENOSYS
+}
+
+func UtimesNano(path string, ts []Timespec) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ if len(ts) != 2 {
+ return EINVAL
+ }
+ atime := ts[0].Sec
+ mtime := ts[1].Sec
+ _, err := fsCall("utimesSync", path, atime, mtime)
+ return err
+}
+
+func Rename(from, to string) error {
+ if err := checkPath(from); err != nil {
+ return err
+ }
+ if err := checkPath(to); err != nil {
+ return err
+ }
+ _, err := fsCall("renameSync", from, to)
+ return err
+}
+
+func Truncate(path string, length int64) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ _, err := fsCall("truncateSync", path, length)
+ return err
+}
+
+func Ftruncate(fd int, length int64) error {
+ _, err := fsCall("ftruncateSync", fd, length)
+ return err
+}
+
+func Getcwd(buf []byte) (n int, err error) {
+ defer recoverErr(&err)
+ cwd := jsProcess.Call("cwd").String()
+ n = copy(buf, cwd)
+ return n, nil
+}
+
+func Chdir(path string) (err error) {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ defer recoverErr(&err)
+ jsProcess.Call("chdir", path)
+ return
+}
+
+func Fchdir(fd int) error {
+ f, err := fdToFile(fd)
+ if err != nil {
+ return err
+ }
+ return Chdir(f.path)
+}
+
+func Readlink(path string, buf []byte) (n int, err error) {
+ if err := checkPath(path); err != nil {
+ return 0, err
+ }
+ dst, err := fsCall("readlinkSync", path)
+ if err != nil {
+ return 0, err
+ }
+ n = copy(buf, dst.String())
+ return n, nil
+}
+
+func Link(path, link string) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ if err := checkPath(link); err != nil {
+ return err
+ }
+ _, err := fsCall("linkSync", path, link)
+ return err
+}
+
+func Symlink(path, link string) error {
+ if err := checkPath(path); err != nil {
+ return err
+ }
+ if err := checkPath(link); err != nil {
+ return err
+ }
+ _, err := fsCall("symlinkSync", path, link)
+ return err
+}
+
+func Fsync(fd int) error {
+ _, err := fsCall("fsyncSync", fd)
+ return err
+}
+
+func Read(fd int, b []byte) (int, error) {
+ f, err := fdToFile(fd)
+ if err != nil {
+ return 0, err
+ }
+
+ if f.seeked {
+ n, err := Pread(fd, b, f.pos)
+ f.pos += int64(n)
+ return n, err
+ }
+
+ a := js.TypedArrayOf(b)
+ n, err := fsCall("readSync", fd, a, 0, len(b))
+ a.Release()
+ if err != nil {
+ return 0, err
+ }
+ n2 := n.Int()
+ f.pos += int64(n2)
+ return n2, err
+}
+
+func Write(fd int, b []byte) (int, error) {
+ f, err := fdToFile(fd)
+ if err != nil {
+ return 0, err
+ }
+
+ if f.seeked {
+ n, err := Pwrite(fd, b, f.pos)
+ f.pos += int64(n)
+ return n, err
+ }
+
+ a := js.TypedArrayOf(b)
+ n, err := fsCall("writeSync", fd, a, 0, len(b))
+ a.Release()
+ if err != nil {
+ return 0, err
+ }
+ n2 := n.Int()
+ f.pos += int64(n2)
+ return n2, err
+}
+
+func Pread(fd int, b []byte, offset int64) (int, error) {
+ a := js.TypedArrayOf(b)
+ n, err := fsCall("readSync", fd, a, 0, len(b), offset)
+ a.Release()
+ if err != nil {
+ return 0, err
+ }
+ return n.Int(), nil
+}
+
+func Pwrite(fd int, b []byte, offset int64) (int, error) {
+ a := js.TypedArrayOf(b)
+ n, err := fsCall("writeSync", fd, a, 0, len(b), offset)
+ a.Release()
+ if err != nil {
+ return 0, err
+ }
+ return n.Int(), nil
+}
+
+func Seek(fd int, offset int64, whence int) (int64, error) {
+ f, err := fdToFile(fd)
+ if err != nil {
+ return 0, err
+ }
+
+ var newPos int64
+ switch whence {
+ case io.SeekStart:
+ newPos = offset
+ case io.SeekCurrent:
+ newPos = f.pos + offset
+ case io.SeekEnd:
+ var st Stat_t
+ if err := Fstat(fd, &st); err != nil {
+ return 0, err
+ }
+ newPos = st.Size + offset
+ default:
+ return 0, errnoErr(EINVAL)
+ }
+
+ if newPos < 0 {
+ return 0, errnoErr(EINVAL)
+ }
+
+ f.seeked = true
+ f.pos = newPos
+ return newPos, nil
+}
+
+func Dup(fd int) (int, error) {
+ return 0, ENOSYS
+}
+
+func Dup2(fd, newfd int) error {
+ return ENOSYS
+}
+
+func Pipe(fd []int) error {
+ return ENOSYS
+}
+
+func fsCall(name string, args ...interface{}) (res js.Value, err error) {
+ defer recoverErr(&err)
+ res = jsFS.Call(name, args...)
+ return
+}
+
+// checkPath checks that the path is not empty and that it contains no null characters.
+func checkPath(path string) error {
+ if path == "" {
+ return EINVAL
+ }
+ for i := 0; i < len(path); i++ {
+ if path[i] == '\x00' {
+ return EINVAL
+ }
+ }
+ return nil
+}
+
+func recoverErr(errPtr *error) {
+ if err := recover(); err != nil {
+ jsErr, ok := err.(js.Error)
+ if !ok {
+ panic(err)
+ }
+ errno, ok := errnoByCode[jsErr.Get("code").String()]
+ if !ok {
+ panic(err)
+ }
+ *errPtr = errnoErr(Errno(errno))
+ }
+}
diff --git a/libgo/go/syscall/js/callback.go b/libgo/go/syscall/js/callback.go
new file mode 100644
index 0000000..9d57307
--- /dev/null
+++ b/libgo/go/syscall/js/callback.go
@@ -0,0 +1,122 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm
+
+package js
+
+import "sync"
+
+var (
+ pendingCallbacks = Global().Get("Array").New()
+ makeCallbackHelper = Global().Get("Go").Get("_makeCallbackHelper")
+ makeEventCallbackHelper = Global().Get("Go").Get("_makeEventCallbackHelper")
+)
+
+var (
+ callbacksMu sync.Mutex
+ callbacks = make(map[uint32]func([]Value))
+ nextCallbackID uint32 = 1
+)
+
+// Callback is a Go function that got wrapped for use as a JavaScript callback.
+type Callback struct {
+ Value // the JavaScript function that queues the callback for execution
+ id uint32
+}
+
+// NewCallback returns a wrapped callback function.
+//
+// Invoking the callback in JavaScript will queue the Go function fn for execution.
+// This execution happens asynchronously on a special goroutine that handles all callbacks and preserves
+// the order in which the callbacks got called.
+// As a consequence, if one callback blocks this goroutine, other callbacks will not be processed.
+// A blocking callback should therefore explicitly start a new goroutine.
+//
+// Callback.Release must be called to free up resources when the callback will not be used any more.
+func NewCallback(fn func(args []Value)) Callback {
+ callbackLoopOnce.Do(func() {
+ go callbackLoop()
+ })
+
+ callbacksMu.Lock()
+ id := nextCallbackID
+ nextCallbackID++
+ callbacks[id] = fn
+ callbacksMu.Unlock()
+ return Callback{
+ Value: makeCallbackHelper.Invoke(id, pendingCallbacks, jsGo),
+ id: id,
+ }
+}
+
+type EventCallbackFlag int
+
+const (
+ // PreventDefault can be used with NewEventCallback to call event.preventDefault synchronously.
+ PreventDefault EventCallbackFlag = 1 << iota
+ // StopPropagation can be used with NewEventCallback to call event.stopPropagation synchronously.
+ StopPropagation
+ // StopImmediatePropagation can be used with NewEventCallback to call event.stopImmediatePropagation synchronously.
+ StopImmediatePropagation
+)
+
+// NewEventCallback returns a wrapped callback function, just like NewCallback, but the callback expects to have
+// exactly one argument, the event. Depending on flags, it will synchronously call event.preventDefault,
+// event.stopPropagation and/or event.stopImmediatePropagation before queuing the Go function fn for execution.
+func NewEventCallback(flags EventCallbackFlag, fn func(event Value)) Callback {
+ c := NewCallback(func(args []Value) {
+ fn(args[0])
+ })
+ return Callback{
+ Value: makeEventCallbackHelper.Invoke(
+ flags&PreventDefault != 0,
+ flags&StopPropagation != 0,
+ flags&StopImmediatePropagation != 0,
+ c,
+ ),
+ id: c.id,
+ }
+}
+
+// Release frees up resources allocated for the callback.
+// The callback must not be invoked after calling Release.
+func (c Callback) Release() {
+ callbacksMu.Lock()
+ delete(callbacks, c.id)
+ callbacksMu.Unlock()
+}
+
+var callbackLoopOnce sync.Once
+
+func callbackLoop() {
+ for !jsGo.Get("_callbackShutdown").Bool() {
+ sleepUntilCallback()
+ for {
+ cb := pendingCallbacks.Call("shift")
+ if cb == Undefined() {
+ break
+ }
+
+ id := uint32(cb.Get("id").Int())
+ callbacksMu.Lock()
+ f, ok := callbacks[id]
+ callbacksMu.Unlock()
+ if !ok {
+ Global().Get("console").Call("error", "call to closed callback")
+ continue
+ }
+
+ argsObj := cb.Get("args")
+ args := make([]Value, argsObj.Length())
+ for i := range args {
+ args[i] = argsObj.Index(i)
+ }
+ f(args)
+ }
+ }
+}
+
+// sleepUntilCallback is defined in the runtime package
+func sleepUntilCallback()
diff --git a/libgo/go/syscall/js/js.go b/libgo/go/syscall/js/js.go
new file mode 100644
index 0000000..336586ca
--- /dev/null
+++ b/libgo/go/syscall/js/js.go
@@ -0,0 +1,382 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm
+
+// Package js gives access to the WebAssembly host environment when using the js/wasm architecture.
+// Its API is based on JavaScript semantics.
+//
+// This package is EXPERIMENTAL. Its current scope is only to allow tests to run, but not yet to provide a
+// comprehensive API for users. It is exempt from the Go compatibility promise.
+package js
+
+import (
+ "unsafe"
+)
+
+// ref is used to identify a JavaScript value, since the value itself can not be passed to WebAssembly.
+// A JavaScript number (64-bit float, except NaN) is represented by its IEEE 754 binary representation.
+// All other values are represented as an IEEE 754 binary representation of NaN with bits 0-31 used as
+// an ID and bits 32-33 used to differentiate between string, symbol, function and object.
+type ref uint64
+
+// nanHead are the upper 32 bits of a ref which are set if the value is not a JavaScript number or NaN itself.
+const nanHead = 0x7FF80000
+
+// Value represents a JavaScript value.
+type Value struct {
+ ref ref
+}
+
+func makeValue(v ref) Value {
+ return Value{ref: v}
+}
+
+func predefValue(id uint32) Value {
+ return Value{ref: nanHead<<32 | ref(id)}
+}
+
+func floatValue(f float64) Value {
+ if f != f {
+ return valueNaN
+ }
+ return Value{ref: *(*ref)(unsafe.Pointer(&f))}
+}
+
+// Error wraps a JavaScript error.
+type Error struct {
+ // Value is the underlying JavaScript error value.
+ Value
+}
+
+// Error implements the error interface.
+func (e Error) Error() string {
+ return "JavaScript error: " + e.Get("message").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
+ jsGo = predefValue(7) // instance of the Go class in JavaScript
+
+ objectConstructor = valueGlobal.Get("Object")
+ arrayConstructor = valueGlobal.Get("Array")
+)
+
+// Undefined returns the JavaScript value "undefined".
+func Undefined() Value {
+ return valueUndefined
+}
+
+// Null returns the JavaScript value "null".
+func Null() Value {
+ return valueNull
+}
+
+// Global returns the JavaScript global object, usually "window" or "global".
+func Global() Value {
+ return valueGlobal
+}
+
+// ValueOf returns x as a JavaScript value:
+//
+// | Go | JavaScript |
+// | ---------------------- | ---------------------- |
+// | js.Value | [its value] |
+// | js.TypedArray | typed array |
+// | js.Callback | function |
+// | nil | null |
+// | bool | boolean |
+// | integers and floats | number |
+// | string | string |
+// | []interface{} | new array |
+// | map[string]interface{} | new object |
+func ValueOf(x interface{}) Value {
+ switch x := x.(type) {
+ case Value:
+ return x
+ case TypedArray:
+ return x.Value
+ case Callback:
+ return x.Value
+ case nil:
+ return valueNull
+ case bool:
+ if x {
+ return valueTrue
+ } else {
+ return valueFalse
+ }
+ case int:
+ return floatValue(float64(x))
+ case int8:
+ return floatValue(float64(x))
+ case int16:
+ return floatValue(float64(x))
+ case int32:
+ return floatValue(float64(x))
+ case int64:
+ return floatValue(float64(x))
+ case uint:
+ return floatValue(float64(x))
+ case uint8:
+ return floatValue(float64(x))
+ case uint16:
+ return floatValue(float64(x))
+ case uint32:
+ return floatValue(float64(x))
+ case uint64:
+ return floatValue(float64(x))
+ case uintptr:
+ return floatValue(float64(x))
+ case unsafe.Pointer:
+ return floatValue(float64(uintptr(x)))
+ case float32:
+ return floatValue(float64(x))
+ case float64:
+ return floatValue(x)
+ case string:
+ return makeValue(stringVal(x))
+ case []interface{}:
+ a := arrayConstructor.New(len(x))
+ for i, s := range x {
+ a.SetIndex(i, s)
+ }
+ return a
+ case map[string]interface{}:
+ o := objectConstructor.New()
+ for k, v := range x {
+ o.Set(k, v)
+ }
+ return o
+ default:
+ panic("ValueOf: invalid value")
+ }
+}
+
+func stringVal(x string) ref
+
+// Type represents the JavaScript type of a Value.
+type Type int
+
+const (
+ TypeUndefined Type = iota
+ TypeNull
+ TypeBoolean
+ TypeNumber
+ TypeString
+ TypeSymbol
+ TypeObject
+ TypeFunction
+)
+
+func (t Type) String() string {
+ switch t {
+ case TypeUndefined:
+ return "undefined"
+ case TypeNull:
+ return "null"
+ case TypeBoolean:
+ return "boolean"
+ case TypeNumber:
+ return "number"
+ case TypeString:
+ return "string"
+ case TypeSymbol:
+ return "symbol"
+ case TypeObject:
+ return "object"
+ case TypeFunction:
+ return "function"
+ default:
+ panic("bad type")
+ }
+}
+
+// Type returns the JavaScript type of the value v. It is similar to JavaScript's typeof operator,
+// except that it returns TypeNull instead of TypeObject for null.
+func (v Value) Type() Type {
+ switch v.ref {
+ case valueUndefined.ref:
+ return TypeUndefined
+ case valueNull.ref:
+ return TypeNull
+ case valueTrue.ref, valueFalse.ref:
+ return TypeBoolean
+ }
+ if v.isNumber() {
+ return TypeNumber
+ }
+ typeFlag := v.ref >> 32 & 3
+ switch typeFlag {
+ case 1:
+ return TypeString
+ case 2:
+ return TypeSymbol
+ case 3:
+ return TypeFunction
+ default:
+ return TypeObject
+ }
+}
+
+// Get returns the JavaScript property p of value v.
+func (v Value) Get(p string) Value {
+ return makeValue(valueGet(v.ref, p))
+}
+
+func valueGet(v ref, p string) ref
+
+// Set sets the JavaScript property p of value v to ValueOf(x).
+func (v Value) Set(p string, x interface{}) {
+ valueSet(v.ref, p, ValueOf(x).ref)
+}
+
+func valueSet(v ref, p string, x ref)
+
+// Index returns JavaScript index i of value v.
+func (v Value) Index(i int) Value {
+ return makeValue(valueIndex(v.ref, i))
+}
+
+func valueIndex(v ref, i int) ref
+
+// SetIndex sets the JavaScript index i of value v to ValueOf(x).
+func (v Value) SetIndex(i int, x interface{}) {
+ valueSetIndex(v.ref, i, ValueOf(x).ref)
+}
+
+func valueSetIndex(v ref, i int, x ref)
+
+func makeArgs(args []interface{}) []ref {
+ argVals := make([]ref, len(args))
+ for i, arg := range args {
+ argVals[i] = ValueOf(arg).ref
+ }
+ return argVals
+}
+
+// Length returns the JavaScript property "length" of v.
+func (v Value) Length() int {
+ return valueLength(v.ref)
+}
+
+func valueLength(v ref) int
+
+// Call does a JavaScript call to the method m of value v with the given arguments.
+// It panics if v has no method m.
+// The arguments get mapped to JavaScript values according to the ValueOf function.
+func (v Value) Call(m string, args ...interface{}) Value {
+ res, ok := valueCall(v.ref, m, makeArgs(args))
+ if !ok {
+ if vType := v.Type(); vType != TypeObject && vType != TypeFunction { // check here to avoid overhead in success case
+ panic(&ValueError{"Value.Call", vType})
+ }
+ if propType := v.Get(m).Type(); propType != TypeFunction {
+ panic("syscall/js: Value.Call: property " + m + " is not a function, got " + propType.String())
+ }
+ panic(Error{makeValue(res)})
+ }
+ return makeValue(res)
+}
+
+func valueCall(v ref, m string, args []ref) (ref, bool)
+
+// Invoke does a JavaScript call of the value v with the given arguments.
+// It panics if v is not a function.
+// The arguments get mapped to JavaScript values according to the ValueOf function.
+func (v Value) Invoke(args ...interface{}) Value {
+ res, ok := valueInvoke(v.ref, makeArgs(args))
+ if !ok {
+ if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case
+ panic(&ValueError{"Value.Invoke", vType})
+ }
+ panic(Error{makeValue(res)})
+ }
+ return makeValue(res)
+}
+
+func valueInvoke(v ref, args []ref) (ref, bool)
+
+// New uses JavaScript's "new" operator with value v as constructor and the given arguments.
+// It panics if v is not a function.
+// The arguments get mapped to JavaScript values according to the ValueOf function.
+func (v Value) New(args ...interface{}) Value {
+ res, ok := valueNew(v.ref, makeArgs(args))
+ if !ok {
+ panic(Error{makeValue(res)})
+ }
+ return makeValue(res)
+}
+
+func valueNew(v ref, args []ref) (ref, bool)
+
+func (v Value) isNumber() bool {
+ return v.ref>>32&nanHead != nanHead || v.ref == valueNaN.ref
+}
+
+func (v Value) float(method string) float64 {
+ if !v.isNumber() {
+ panic(&ValueError{method, v.Type()})
+ }
+ return *(*float64)(unsafe.Pointer(&v.ref))
+}
+
+// Float returns the value v as a float64. It panics if v is not a JavaScript number.
+func (v Value) Float() float64 {
+ return v.float("Value.Float")
+}
+
+// Int returns the value v truncated to an int. It panics if v is not a JavaScript number.
+func (v Value) Int() int {
+ return int(v.float("Value.Int"))
+}
+
+// Bool returns the value v as a bool. It panics if v is not a JavaScript boolean.
+func (v Value) Bool() bool {
+ switch v.ref {
+ case valueTrue.ref:
+ return true
+ case valueFalse.ref:
+ return false
+ default:
+ panic(&ValueError{"Value.Bool", v.Type()})
+ }
+}
+
+// String returns the value v converted to string according to JavaScript type conversions.
+func (v Value) String() string {
+ str, length := valuePrepareString(v.ref)
+ b := make([]byte, length)
+ valueLoadString(str, b)
+ return string(b)
+}
+
+func valuePrepareString(v ref) (ref, int)
+
+func valueLoadString(v ref, b []byte)
+
+// InstanceOf reports whether v is an instance of type t according to JavaScript's instanceof operator.
+func (v Value) InstanceOf(t Value) bool {
+ return valueInstanceOf(v.ref, t.ref)
+}
+
+func valueInstanceOf(v ref, t ref) bool
+
+// A ValueError occurs when a Value method is invoked on
+// a Value that does not support it. Such cases are documented
+// in the description of each method.
+type ValueError struct {
+ Method string
+ Type Type
+}
+
+func (e *ValueError) Error() string {
+ return "syscall/js: call of " + e.Method + " on " + e.Type.String()
+}
diff --git a/libgo/go/syscall/js/js_test.go b/libgo/go/syscall/js/js_test.go
new file mode 100644
index 0000000..9cc931a
--- /dev/null
+++ b/libgo/go/syscall/js/js_test.go
@@ -0,0 +1,319 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm
+
+package js_test
+
+import (
+ "fmt"
+ "math"
+ "syscall/js"
+ "testing"
+)
+
+var dummys = js.Global().Call("eval", `({
+ someBool: true,
+ someString: "abc\u1234",
+ someInt: 42,
+ someFloat: 42.123,
+ someArray: [41, 42, 43],
+ add: function(a, b) {
+ return a + b;
+ },
+ NaN: NaN,
+})`)
+
+func TestBool(t *testing.T) {
+ want := true
+ o := dummys.Get("someBool")
+ if got := o.Bool(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ dummys.Set("otherBool", want)
+ if got := dummys.Get("otherBool").Bool(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ if dummys.Get("someBool") != dummys.Get("someBool") {
+ t.Errorf("same value not equal")
+ }
+}
+
+func TestString(t *testing.T) {
+ want := "abc\u1234"
+ o := dummys.Get("someString")
+ if got := o.String(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ dummys.Set("otherString", want)
+ if got := dummys.Get("otherString").String(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ if dummys.Get("someString") != dummys.Get("someString") {
+ t.Errorf("same value not equal")
+ }
+
+ wantInt := "42"
+ o = dummys.Get("someInt")
+ if got := o.String(); got != wantInt {
+ t.Errorf("got %#v, want %#v", got, wantInt)
+ }
+}
+
+func TestInt(t *testing.T) {
+ want := 42
+ o := dummys.Get("someInt")
+ if got := o.Int(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ dummys.Set("otherInt", want)
+ if got := dummys.Get("otherInt").Int(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ if dummys.Get("someInt") != dummys.Get("someInt") {
+ t.Errorf("same value not equal")
+ }
+}
+
+func TestIntConversion(t *testing.T) {
+ testIntConversion(t, 0)
+ testIntConversion(t, 1)
+ testIntConversion(t, -1)
+ testIntConversion(t, 1<<20)
+ testIntConversion(t, -1<<20)
+ testIntConversion(t, 1<<40)
+ testIntConversion(t, -1<<40)
+ testIntConversion(t, 1<<60)
+ testIntConversion(t, -1<<60)
+}
+
+func testIntConversion(t *testing.T, want int) {
+ if got := js.ValueOf(want).Int(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+}
+
+func TestFloat(t *testing.T) {
+ want := 42.123
+ o := dummys.Get("someFloat")
+ if got := o.Float(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ dummys.Set("otherFloat", want)
+ if got := dummys.Get("otherFloat").Float(); got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ if dummys.Get("someFloat") != dummys.Get("someFloat") {
+ t.Errorf("same value not equal")
+ }
+}
+
+func TestObject(t *testing.T) {
+ if dummys.Get("someArray") != dummys.Get("someArray") {
+ t.Errorf("same value not equal")
+ }
+
+ // An object and its prototype should not be equal.
+ proto := js.Global().Get("Object").Get("prototype")
+ o := js.Global().Call("eval", "new Object()")
+ if proto == o {
+ t.Errorf("object equals to its prototype")
+ }
+}
+
+func TestFrozenObject(t *testing.T) {
+ o := js.Global().Call("eval", "(function () { let o = new Object(); o.field = 5; Object.freeze(o); return o; })()")
+ want := 5
+ if got := o.Get("field").Int(); want != got {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+}
+
+func TestTypedArrayOf(t *testing.T) {
+ testTypedArrayOf(t, "[]int8", []int8{0, -42, 0}, -42)
+ testTypedArrayOf(t, "[]int16", []int16{0, -42, 0}, -42)
+ testTypedArrayOf(t, "[]int32", []int32{0, -42, 0}, -42)
+ testTypedArrayOf(t, "[]uint8", []uint8{0, 42, 0}, 42)
+ testTypedArrayOf(t, "[]uint16", []uint16{0, 42, 0}, 42)
+ testTypedArrayOf(t, "[]uint32", []uint32{0, 42, 0}, 42)
+ testTypedArrayOf(t, "[]float32", []float32{0, -42.5, 0}, -42.5)
+ testTypedArrayOf(t, "[]float64", []float64{0, -42.5, 0}, -42.5)
+}
+
+func testTypedArrayOf(t *testing.T, name string, slice interface{}, want float64) {
+ t.Run(name, func(t *testing.T) {
+ a := js.TypedArrayOf(slice)
+ got := a.Index(1).Float()
+ a.Release()
+ if got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ })
+}
+
+func TestNaN(t *testing.T) {
+ want := js.ValueOf(math.NaN())
+ got := dummys.Get("NaN")
+ if got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+}
+
+func TestUndefined(t *testing.T) {
+ dummys.Set("test", js.Undefined())
+ if dummys == js.Undefined() || dummys.Get("test") != js.Undefined() || dummys.Get("xyz") != js.Undefined() {
+ t.Errorf("js.Undefined expected")
+ }
+}
+
+func TestNull(t *testing.T) {
+ dummys.Set("test1", nil)
+ dummys.Set("test2", js.Null())
+ if dummys == js.Null() || dummys.Get("test1") != js.Null() || dummys.Get("test2") != js.Null() {
+ t.Errorf("js.Null expected")
+ }
+}
+
+func TestLength(t *testing.T) {
+ if got := dummys.Get("someArray").Length(); got != 3 {
+ t.Errorf("got %#v, want %#v", got, 3)
+ }
+}
+
+func TestIndex(t *testing.T) {
+ if got := dummys.Get("someArray").Index(1).Int(); got != 42 {
+ t.Errorf("got %#v, want %#v", got, 42)
+ }
+}
+
+func TestSetIndex(t *testing.T) {
+ dummys.Get("someArray").SetIndex(2, 99)
+ if got := dummys.Get("someArray").Index(2).Int(); got != 99 {
+ t.Errorf("got %#v, want %#v", got, 99)
+ }
+}
+
+func TestCall(t *testing.T) {
+ var i int64 = 40
+ if got := dummys.Call("add", i, 2).Int(); got != 42 {
+ t.Errorf("got %#v, want %#v", got, 42)
+ }
+ if got := dummys.Call("add", js.Global().Call("eval", "40"), 2).Int(); got != 42 {
+ t.Errorf("got %#v, want %#v", got, 42)
+ }
+}
+
+func TestInvoke(t *testing.T) {
+ var i int64 = 40
+ if got := dummys.Get("add").Invoke(i, 2).Int(); got != 42 {
+ t.Errorf("got %#v, want %#v", got, 42)
+ }
+}
+
+func TestNew(t *testing.T) {
+ if got := js.Global().Get("Array").New(42).Length(); got != 42 {
+ t.Errorf("got %#v, want %#v", got, 42)
+ }
+}
+
+func TestInstanceOf(t *testing.T) {
+ someArray := js.Global().Get("Array").New()
+ if got, want := someArray.InstanceOf(js.Global().Get("Array")), true; got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+ if got, want := someArray.InstanceOf(js.Global().Get("Function")), false; got != want {
+ t.Errorf("got %#v, want %#v", got, want)
+ }
+}
+
+func TestType(t *testing.T) {
+ if got, want := js.Undefined().Type(), js.TypeUndefined; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.Null().Type(), js.TypeNull; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.ValueOf(true).Type(), js.TypeBoolean; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.ValueOf(42).Type(), js.TypeNumber; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.ValueOf("test").Type(), js.TypeString; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.Global().Get("Symbol").Invoke("test").Type(), js.TypeSymbol; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.Global().Get("Array").New().Type(), js.TypeObject; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ if got, want := js.Global().Get("Array").Type(), js.TypeFunction; got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+}
+
+type object = map[string]interface{}
+type array = []interface{}
+
+func TestValueOf(t *testing.T) {
+ a := js.ValueOf(array{0, array{0, 42, 0}, 0})
+ if got := a.Index(1).Index(1).Int(); got != 42 {
+ t.Errorf("got %v, want %v", got, 42)
+ }
+
+ o := js.ValueOf(object{"x": object{"y": 42}})
+ if got := o.Get("x").Get("y").Int(); got != 42 {
+ t.Errorf("got %v, want %v", got, 42)
+ }
+}
+
+func TestCallback(t *testing.T) {
+ c := make(chan struct{})
+ cb := js.NewCallback(func(args []js.Value) {
+ if got := args[0].Int(); got != 42 {
+ t.Errorf("got %#v, want %#v", got, 42)
+ }
+ c <- struct{}{}
+ })
+ defer cb.Release()
+ js.Global().Call("setTimeout", cb, 0, 42)
+ <-c
+}
+
+func TestEventCallback(t *testing.T) {
+ for _, name := range []string{"preventDefault", "stopPropagation", "stopImmediatePropagation"} {
+ c := make(chan struct{})
+ var flags js.EventCallbackFlag
+ switch name {
+ case "preventDefault":
+ flags = js.PreventDefault
+ case "stopPropagation":
+ flags = js.StopPropagation
+ case "stopImmediatePropagation":
+ flags = js.StopImmediatePropagation
+ }
+ cb := js.NewEventCallback(flags, func(event js.Value) {
+ c <- struct{}{}
+ })
+ defer cb.Release()
+
+ event := js.Global().Call("eval", fmt.Sprintf("({ called: false, %s: function() { this.called = true; } })", name))
+ cb.Invoke(event)
+ if !event.Get("called").Bool() {
+ t.Errorf("%s not called", name)
+ }
+
+ <-c
+ }
+}
+
+func ExampleNewCallback() {
+ var cb js.Callback
+ cb = js.NewCallback(func(args []js.Value) {
+ fmt.Println("button clicked")
+ cb.Release() // release the callback if the button will not be clicked again
+ })
+ js.Global().Get("document").Call("getElementById", "myButton").Call("addEventListener", "click", cb)
+}
diff --git a/libgo/go/syscall/js/typedarray.go b/libgo/go/syscall/js/typedarray.go
new file mode 100644
index 0000000..afa1548
--- /dev/null
+++ b/libgo/go/syscall/js/typedarray.go
@@ -0,0 +1,102 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm
+
+package js
+
+import (
+ "sync"
+ "unsafe"
+)
+
+var (
+ int8Array = Global().Get("Int8Array")
+ int16Array = Global().Get("Int16Array")
+ int32Array = Global().Get("Int32Array")
+ uint8Array = Global().Get("Uint8Array")
+ uint16Array = Global().Get("Uint16Array")
+ uint32Array = Global().Get("Uint32Array")
+ float32Array = Global().Get("Float32Array")
+ float64Array = Global().Get("Float64Array")
+)
+
+// TypedArray represents a JavaScript typed array.
+type TypedArray struct {
+ Value
+}
+
+// Release frees up resources allocated for the typed array.
+// The typed array and its buffer must not be accessed after calling Release.
+func (a TypedArray) Release() {
+ openTypedArraysMutex.Lock()
+ delete(openTypedArrays, a)
+ openTypedArraysMutex.Unlock()
+}
+
+var (
+ openTypedArraysMutex sync.Mutex
+ openTypedArrays = make(map[TypedArray]interface{})
+)
+
+// TypedArrayOf returns a JavaScript typed array backed by the slice's underlying array.
+//
+// The supported types are []int8, []int16, []int32, []uint8, []uint16, []uint32, []float32 and []float64.
+// Passing an unsupported value causes a panic.
+//
+// TypedArray.Release must be called to free up resources when the typed array will not be used any more.
+func TypedArrayOf(slice interface{}) TypedArray {
+ a := TypedArray{typedArrayOf(slice)}
+ openTypedArraysMutex.Lock()
+ openTypedArrays[a] = slice
+ openTypedArraysMutex.Unlock()
+ return a
+}
+
+func typedArrayOf(slice interface{}) Value {
+ switch slice := slice.(type) {
+ case []int8:
+ if len(slice) == 0 {
+ return int8Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return int8Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []int16:
+ if len(slice) == 0 {
+ return int16Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return int16Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []int32:
+ if len(slice) == 0 {
+ return int32Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return int32Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []uint8:
+ if len(slice) == 0 {
+ return uint8Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return uint8Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []uint16:
+ if len(slice) == 0 {
+ return uint16Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return uint16Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []uint32:
+ if len(slice) == 0 {
+ return uint32Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return uint32Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []float32:
+ if len(slice) == 0 {
+ return float32Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return float32Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ case []float64:
+ if len(slice) == 0 {
+ return float64Array.New(memory.Get("buffer"), 0, 0)
+ }
+ return float64Array.New(memory.Get("buffer"), unsafe.Pointer(&slice[0]), len(slice))
+ default:
+ panic("TypedArrayOf: not a supported slice")
+ }
+}
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
index 5f47784..7903328 100644
--- a/libgo/go/syscall/libcall_linux.go
+++ b/libgo/go/syscall/libcall_linux.go
@@ -238,15 +238,6 @@ func Getdents(fd int, buf []byte) (n int, err error) {
return
}
-func clen(n []byte) int {
- for i := 0; i < len(n); i++ {
- if n[i] == 0 {
- return i
- }
- }
- return len(n)
-}
-
func ReadDirent(fd int, buf []byte) (n int, err error) {
return Getdents(fd, buf)
}
diff --git a/libgo/go/syscall/net_js.go b/libgo/go/syscall/net_js.go
new file mode 100644
index 0000000..d5bf1f4
--- /dev/null
+++ b/libgo/go/syscall/net_js.go
@@ -0,0 +1,128 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// js/wasm uses fake networking directly implemented in the net package.
+// This file only exists to make the compiler happy.
+
+// +build js,wasm
+
+package syscall
+
+const (
+ AF_UNSPEC = iota
+ AF_UNIX
+ AF_INET
+ AF_INET6
+)
+
+const (
+ SOCK_STREAM = 1 + iota
+ SOCK_DGRAM
+ SOCK_RAW
+ SOCK_SEQPACKET
+)
+
+const (
+ IPPROTO_IP = 0
+ IPPROTO_IPV4 = 4
+ IPPROTO_IPV6 = 0x29
+ IPPROTO_TCP = 6
+ IPPROTO_UDP = 0x11
+)
+
+const (
+ _ = iota
+ IPV6_V6ONLY
+ SOMAXCONN
+ SO_ERROR
+)
+
+// Misc constants expected by package net but not supported.
+const (
+ _ = iota
+ F_DUPFD_CLOEXEC
+ SYS_FCNTL = 500 // unsupported; same value as net_nacl.go
+)
+
+type Sockaddr interface {
+}
+
+type SockaddrInet4 struct {
+ Port int
+ Addr [4]byte
+}
+
+type SockaddrInet6 struct {
+ Port int
+ ZoneId uint32
+ Addr [16]byte
+}
+
+type SockaddrUnix struct {
+ Name string
+}
+
+func Socket(proto, sotype, unused int) (fd int, err error) {
+ return 0, ENOSYS
+}
+
+func Bind(fd int, sa Sockaddr) error {
+ return ENOSYS
+}
+
+func StopIO(fd int) error {
+ return ENOSYS
+}
+
+func Listen(fd int, backlog int) error {
+ return ENOSYS
+}
+
+func Accept(fd int) (newfd int, sa Sockaddr, err error) {
+ return 0, nil, ENOSYS
+}
+
+func Connect(fd int, sa Sockaddr) error {
+ return ENOSYS
+}
+
+func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
+ return 0, nil, ENOSYS
+}
+
+func Sendto(fd int, p []byte, flags int, to Sockaddr) error {
+ return ENOSYS
+}
+
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) {
+ return 0, 0, 0, nil, ENOSYS
+}
+
+func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
+ return 0, ENOSYS
+}
+
+func GetsockoptInt(fd, level, opt int) (value int, err error) {
+ return 0, ENOSYS
+}
+
+func SetsockoptInt(fd, level, opt int, value int) error {
+ return nil
+}
+
+func SetReadDeadline(fd int, t int64) error {
+ return ENOSYS
+}
+
+func SetWriteDeadline(fd int, t int64) error {
+ return ENOSYS
+}
+
+func Shutdown(fd int, how int) error {
+ return ENOSYS
+}
+
+func SetNonblock(fd int, nonblocking bool) error {
+ return nil
+}
diff --git a/libgo/go/syscall/pwd_plan9.go b/libgo/go/syscall/pwd_plan9.go
index 1248613..1deeaa9 100644
--- a/libgo/go/syscall/pwd_plan9.go
+++ b/libgo/go/syscall/pwd_plan9.go
@@ -39,6 +39,15 @@ func fixwdLocked() {
}
}
+func fixwd(paths ...string) {
+ for _, path := range paths {
+ if path != "" && path[0] != '/' && path[0] != '#' {
+ Fixwd()
+ return
+ }
+ }
+}
+
// goroutine-specific getwd
func getwd() (wd string, err error) {
fd, err := open(".", O_RDONLY)
@@ -66,6 +75,7 @@ func Getwd() (wd string, err error) {
}
func Chdir(path string) error {
+ fixwd(path)
wdmu.Lock()
defer wdmu.Unlock()
diff --git a/libgo/go/syscall/route_freebsd_32bit.go b/libgo/go/syscall/route_freebsd_32bit.go
index 5c10b05..ec6f6b7 100644
--- a/libgo/go/syscall/route_freebsd_32bit.go
+++ b/libgo/go/syscall/route_freebsd_32bit.go
@@ -21,7 +21,7 @@ func (any *anyMessage) parseInterfaceMessage(b []byte) *InterfaceMessage {
p := (*InterfaceMessage)(unsafe.Pointer(any))
// FreeBSD 10 and beyond have a restructured mbuf
// packet header view.
- // See http://svnweb.freebsd.org/base?view=revision&revision=254804.
+ // See https://svnweb.freebsd.org/base?view=revision&revision=254804.
if freebsdVersion >= 1000000 {
m := (*ifMsghdr)(unsafe.Pointer(any))
p.Header.Data.Hwassist = uint32(m.Data.Hwassist)
diff --git a/libgo/go/syscall/security_windows.go b/libgo/go/syscall/security_windows.go
index e2a9dc5..ae8b3a1 100644
--- a/libgo/go/syscall/security_windows.go
+++ b/libgo/go/syscall/security_windows.go
@@ -30,7 +30,7 @@ const (
)
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
-// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
+// https://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
//sys TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
//sys GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
@@ -221,6 +221,7 @@ const (
TOKEN_ADJUST_PRIVILEGES
TOKEN_ADJUST_GROUPS
TOKEN_ADJUST_DEFAULT
+ TOKEN_ADJUST_SESSIONID
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
@@ -230,7 +231,8 @@ const (
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
- TOKEN_ADJUST_DEFAULT
+ TOKEN_ADJUST_DEFAULT |
+ TOKEN_ADJUST_SESSIONID
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
TOKEN_ADJUST_PRIVILEGES |
diff --git a/libgo/go/syscall/setuidgid_32_linux.go b/libgo/go/syscall/setuidgid_32_linux.go
index 182f5d2..1fe7120 100644
--- a/libgo/go/syscall/setuidgid_32_linux.go
+++ b/libgo/go/syscall/setuidgid_32_linux.go
@@ -8,6 +8,8 @@
package syscall
const (
+ sys_GETEUID = SYS_GETEUID32
+
sys_SETGID = SYS_SETGID32
sys_SETUID = SYS_SETUID32
)
diff --git a/libgo/go/syscall/setuidgid_linux.go b/libgo/go/syscall/setuidgid_linux.go
index bf40d2d..22fa334 100644
--- a/libgo/go/syscall/setuidgid_linux.go
+++ b/libgo/go/syscall/setuidgid_linux.go
@@ -8,6 +8,8 @@
package syscall
const (
+ sys_GETEUID = SYS_GETEUID
+
sys_SETGID = SYS_SETGID
sys_SETUID = SYS_SETUID
)
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
index 8e785dd..9b74afe 100644
--- a/libgo/go/syscall/syscall.go
+++ b/libgo/go/syscall/syscall.go
@@ -18,14 +18,11 @@
// err is an operating system error describing the failure.
// On most systems, that error has type syscall.Errno.
//
-// NOTE: This package is locked down. Code outside the standard
-// Go repository should be migrated to use the corresponding
-// package in the golang.org/x/sys repository. That is also where updates
-// required by new systems or versions should be applied.
-// Signal, Errno and SysProcAttr are not yet available in
-// golang.org/x/sys and must still be referenced from the
-// syscall package. See https://golang.org/s/go1.4-syscall
-// for more information.
+// Deprecated: this package is locked down. Callers should use the
+// corresponding package in the golang.org/x/sys repository instead.
+// That is also where updates required by new systems or versions
+// should be applied. See https://golang.org/s/go1.4-syscall for more
+// information.
//
package syscall
diff --git a/libgo/go/syscall/syscall_errno.go b/libgo/go/syscall/syscall_errno.go
index 01618d1..810572f 100644
--- a/libgo/go/syscall/syscall_errno.go
+++ b/libgo/go/syscall/syscall_errno.go
@@ -18,7 +18,7 @@ func (e Errno) Error() string {
}
func (e Errno) Temporary() bool {
- return e == EINTR || e == EMFILE || e == ECONNRESET || e == ECONNABORTED || e.Timeout()
+ return e == EINTR || e == EMFILE || e.Timeout()
}
func (e Errno) Timeout() bool {
diff --git a/libgo/go/syscall/syscall_js.go b/libgo/go/syscall/syscall_js.go
new file mode 100644
index 0000000..6822eec
--- /dev/null
+++ b/libgo/go/syscall/syscall_js.go
@@ -0,0 +1,307 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+)
+
+const direntSize = 8 + 8 + 2 + 256
+
+type Dirent struct {
+ Reclen uint16
+ Name [256]byte
+}
+
+func direntIno(buf []byte) (uint64, bool) {
+ return 1, true
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ reclen, ok := direntReclen(buf)
+ if !ok {
+ return 0, false
+ }
+ return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
+}
+
+const PathMax = 256
+
+// An Errno is an unsigned number describing an error condition.
+// It implements the error interface. The zero Errno is by convention
+// a non-error, so code to convert from Errno to error should use:
+// err = nil
+// if errno != 0 {
+// err = errno
+// }
+type Errno uintptr
+
+func (e Errno) Error() string {
+ if 0 <= int(e) && int(e) < len(errorstr) {
+ s := errorstr[e]
+ if s != "" {
+ return s
+ }
+ }
+ return "errno " + itoa(int(e))
+}
+
+func (e Errno) Temporary() bool {
+ return e == EINTR || e == EMFILE || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+ return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
+}
+
+// A Signal is a number describing a process signal.
+// It implements the os.Signal interface.
+type Signal int
+
+const (
+ _ Signal = iota
+ SIGCHLD
+ SIGINT
+ SIGKILL
+ SIGTRAP
+ SIGQUIT
+)
+
+func (s Signal) Signal() {}
+
+func (s Signal) String() string {
+ if 0 <= s && int(s) < len(signals) {
+ str := signals[s]
+ if str != "" {
+ return str
+ }
+ }
+ return "signal " + itoa(int(s))
+}
+
+var signals = [...]string{}
+
+// File system
+
+const (
+ Stdin = 0
+ Stdout = 1
+ Stderr = 2
+)
+
+const (
+ O_RDONLY = 0
+ O_WRONLY = 1
+ O_RDWR = 2
+
+ O_CREAT = 0100
+ O_CREATE = O_CREAT
+ O_TRUNC = 01000
+ O_APPEND = 02000
+ O_EXCL = 0200
+ O_SYNC = 010000
+
+ O_CLOEXEC = 0
+)
+
+const (
+ F_DUPFD = 0
+ F_GETFD = 1
+ F_SETFD = 2
+ F_GETFL = 3
+ F_SETFL = 4
+ F_GETOWN = 5
+ F_SETOWN = 6
+ F_GETLK = 7
+ F_SETLK = 8
+ F_SETLKW = 9
+ F_RGETLK = 10
+ F_RSETLK = 11
+ F_CNVT = 12
+ F_RSETLKW = 13
+
+ F_RDLCK = 1
+ F_WRLCK = 2
+ F_UNLCK = 3
+ F_UNLKSYS = 4
+)
+
+const (
+ S_IFMT = 0000370000
+ S_IFSHM_SYSV = 0000300000
+ S_IFSEMA = 0000270000
+ S_IFCOND = 0000260000
+ S_IFMUTEX = 0000250000
+ S_IFSHM = 0000240000
+ S_IFBOUNDSOCK = 0000230000
+ S_IFSOCKADDR = 0000220000
+ S_IFDSOCK = 0000210000
+
+ S_IFSOCK = 0000140000
+ S_IFLNK = 0000120000
+ S_IFREG = 0000100000
+ S_IFBLK = 0000060000
+ S_IFDIR = 0000040000
+ S_IFCHR = 0000020000
+ S_IFIFO = 0000010000
+
+ S_UNSUP = 0000370000
+
+ S_ISUID = 0004000
+ S_ISGID = 0002000
+ S_ISVTX = 0001000
+
+ S_IREAD = 0400
+ S_IWRITE = 0200
+ S_IEXEC = 0100
+
+ S_IRWXU = 0700
+ S_IRUSR = 0400
+ S_IWUSR = 0200
+ S_IXUSR = 0100
+
+ S_IRWXG = 070
+ S_IRGRP = 040
+ S_IWGRP = 020
+ S_IXGRP = 010
+
+ S_IRWXO = 07
+ S_IROTH = 04
+ S_IWOTH = 02
+ S_IXOTH = 01
+)
+
+type Stat_t struct {
+ Dev int64
+ Ino uint64
+ Mode uint32
+ Nlink uint32
+ Uid uint32
+ Gid uint32
+ Rdev int64
+ Size int64
+ Blksize int32
+ Blocks int32
+ Atime int64
+ AtimeNsec int64
+ Mtime int64
+ MtimeNsec int64
+ Ctime int64
+ CtimeNsec int64
+}
+
+// Processes
+// Not supported - just enough for package os.
+
+var ForkLock sync.RWMutex
+
+type WaitStatus uint32
+
+func (w WaitStatus) Exited() bool { return false }
+func (w WaitStatus) ExitStatus() int { return 0 }
+func (w WaitStatus) Signaled() bool { return false }
+func (w WaitStatus) Signal() Signal { return 0 }
+func (w WaitStatus) CoreDump() bool { return false }
+func (w WaitStatus) Stopped() bool { return false }
+func (w WaitStatus) Continued() bool { return false }
+func (w WaitStatus) StopSignal() Signal { return 0 }
+func (w WaitStatus) TrapCause() int { return 0 }
+
+// XXX made up
+type Rusage struct {
+ Utime Timeval
+ Stime Timeval
+}
+
+// XXX made up
+type ProcAttr struct {
+ Dir string
+ Env []string
+ Files []uintptr
+ Sys *SysProcAttr
+}
+
+type SysProcAttr struct {
+}
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
+ return 0, 0, ENOSYS
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
+ return 0, 0, ENOSYS
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
+ return 0, 0, ENOSYS
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
+ return 0, 0, ENOSYS
+}
+
+func Sysctl(key string) (string, error) {
+ if key == "kern.hostname" {
+ return "js", nil
+ }
+ return "", ENOSYS
+}
+
+const ImplementsGetwd = true
+
+func Getwd() (wd string, err error) {
+ var buf [PathMax]byte
+ n, err := Getcwd(buf[0:])
+ if err != nil {
+ return "", err
+ }
+ return string(buf[:n]), nil
+}
+
+func Getegid() int { return 1 }
+func Geteuid() int { return 1 }
+func Getgid() int { return 1 }
+func Getgroups() ([]int, error) { return []int{1}, nil }
+func Getppid() int { return 2 }
+func Getpid() int { return 3 }
+func Gettimeofday(tv *Timeval) error { return ENOSYS }
+func Getuid() int { return 1 }
+func Kill(pid int, signum Signal) error { return ENOSYS }
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ return 0, ENOSYS
+}
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
+ return 0, 0, ENOSYS
+}
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+ return 0, ENOSYS
+}
+
+type Iovec struct{} // dummy
+
+type Timespec struct {
+ Sec int64
+ Nsec int64
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int64
+}
+
+func setTimespec(sec, nsec int64) Timespec {
+ return Timespec{Sec: sec, Nsec: nsec}
+}
+
+func setTimeval(sec, usec int64) Timeval {
+ return Timeval{Sec: sec, Usec: usec}
+}
diff --git a/libgo/go/syscall/syscall_linux.go b/libgo/go/syscall/syscall_linux.go
index 338a971..d2d49c3 100644
--- a/libgo/go/syscall/syscall_linux.go
+++ b/libgo/go/syscall/syscall_linux.go
@@ -6,6 +6,11 @@ package syscall
import "unsafe"
+func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
+ r1, r2, _ = RawSyscall(trap, a1, a2, a3)
+ return
+}
+
func direntIno(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
}
diff --git a/libgo/go/syscall/syscall_linux_test.go b/libgo/go/syscall/syscall_linux_test.go
index 2c4d953..99de6eb 100644
--- a/libgo/go/syscall/syscall_linux_test.go
+++ b/libgo/go/syscall/syscall_linux_test.go
@@ -13,16 +13,139 @@ import (
"os/exec"
"os/signal"
"path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
"syscall"
"testing"
"time"
)
+// chtmpdir changes the working directory to a new temporary directory and
+// provides a cleanup function. Used when PWD is read-only.
+func chtmpdir(t *testing.T) func() {
+ oldwd, err := os.Getwd()
+ if err != nil {
+ t.Fatalf("chtmpdir: %v", err)
+ }
+ d, err := ioutil.TempDir("", "test")
+ if err != nil {
+ t.Fatalf("chtmpdir: %v", err)
+ }
+ if err := os.Chdir(d); err != nil {
+ t.Fatalf("chtmpdir: %v", err)
+ }
+ return func() {
+ if err := os.Chdir(oldwd); err != nil {
+ t.Fatalf("chtmpdir: %v", err)
+ }
+ os.RemoveAll(d)
+ }
+}
+
+func touch(t *testing.T, name string) {
+ f, err := os.Create(name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := f.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+const (
+ _AT_SYMLINK_NOFOLLOW = 0x100
+ _AT_FDCWD = -0x64
+ _AT_EACCESS = 0x200
+ _F_OK = 0
+ _R_OK = 4
+)
+
+func TestFaccessat(t *testing.T) {
+ defer chtmpdir(t)()
+ touch(t, "file1")
+
+ err := syscall.Faccessat(_AT_FDCWD, "file1", _R_OK, 0)
+ if err != nil {
+ t.Errorf("Faccessat: unexpected error: %v", err)
+ }
+
+ err = syscall.Faccessat(_AT_FDCWD, "file1", _R_OK, 2)
+ if err != syscall.EINVAL {
+ t.Errorf("Faccessat: unexpected error: %v, want EINVAL", err)
+ }
+
+ err = syscall.Faccessat(_AT_FDCWD, "file1", _R_OK, _AT_EACCESS)
+ if err != nil {
+ t.Errorf("Faccessat: unexpected error: %v", err)
+ }
+
+ err = os.Symlink("file1", "symlink1")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = syscall.Faccessat(_AT_FDCWD, "symlink1", _R_OK, _AT_SYMLINK_NOFOLLOW)
+ if err != nil {
+ t.Errorf("Faccessat SYMLINK_NOFOLLOW: unexpected error %v", err)
+ }
+
+ // We can't really test _AT_SYMLINK_NOFOLLOW, because there
+ // doesn't seem to be any way to change the mode of a symlink.
+ // We don't test _AT_EACCESS because such tests are only
+ // meaningful if run as root.
+
+ err = syscall.Fchmodat(_AT_FDCWD, "file1", 0, 0)
+ if err != nil {
+ t.Errorf("Fchmodat: unexpected error %v", err)
+ }
+
+ err = syscall.Faccessat(_AT_FDCWD, "file1", _F_OK, _AT_SYMLINK_NOFOLLOW)
+ if err != nil {
+ t.Errorf("Faccessat: unexpected error: %v", err)
+ }
+
+ err = syscall.Faccessat(_AT_FDCWD, "file1", _R_OK, _AT_SYMLINK_NOFOLLOW)
+ if err != syscall.EACCES {
+ if syscall.Getuid() != 0 {
+ t.Errorf("Faccessat: unexpected error: %v, want EACCES", err)
+ }
+ }
+}
+
+func TestFchmodat(t *testing.T) {
+ defer chtmpdir(t)()
+
+ touch(t, "file1")
+ os.Symlink("file1", "symlink1")
+
+ err := syscall.Fchmodat(_AT_FDCWD, "symlink1", 0444, 0)
+ if err != nil {
+ t.Fatalf("Fchmodat: unexpected error: %v", err)
+ }
+
+ fi, err := os.Stat("file1")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if fi.Mode() != 0444 {
+ t.Errorf("Fchmodat: failed to change mode: expected %v, got %v", 0444, fi.Mode())
+ }
+
+ err = syscall.Fchmodat(_AT_FDCWD, "symlink1", 0444, _AT_SYMLINK_NOFOLLOW)
+ if err != syscall.EOPNOTSUPP {
+ t.Fatalf("Fchmodat: unexpected error: %v, expected EOPNOTSUPP", err)
+ }
+}
+
func TestMain(m *testing.M) {
if os.Getenv("GO_DEATHSIG_PARENT") == "1" {
deathSignalParent()
} else if os.Getenv("GO_DEATHSIG_CHILD") == "1" {
deathSignalChild()
+ } else if os.Getenv("GO_SYSCALL_NOERROR") == "1" {
+ syscallNoError()
}
os.Exit(m.Run())
@@ -166,3 +289,82 @@ func TestParseNetlinkMessage(t *testing.T) {
}
}
}
+
+func TestSyscallNoError(t *testing.T) {
+ // On Linux there are currently no syscalls which don't fail and return
+ // a value larger than 0xfffffffffffff001 so we could test RawSyscall
+ // vs. RawSyscallNoError on 64bit architectures.
+ if runtime.GOARCH != "386" && runtime.GOARCH != "arm" {
+ t.Skip("skipping on non-32bit architecture")
+ }
+
+ if os.Getuid() != 0 {
+ t.Skip("skipping root only test")
+ }
+
+ // Copy the test binary to a location that a non-root user can read/execute
+ // after we drop privileges
+ tempDir, err := ioutil.TempDir("", "TestSyscallNoError")
+ if err != nil {
+ t.Fatalf("cannot create temporary directory: %v", err)
+ }
+ defer os.RemoveAll(tempDir)
+ os.Chmod(tempDir, 0755)
+
+ tmpBinary := filepath.Join(tempDir, filepath.Base(os.Args[0]))
+
+ src, err := os.Open(os.Args[0])
+ if err != nil {
+ t.Fatalf("cannot open binary %q, %v", os.Args[0], err)
+ }
+ defer src.Close()
+
+ dst, err := os.OpenFile(tmpBinary, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
+ if err != nil {
+ t.Fatalf("cannot create temporary binary %q, %v", tmpBinary, err)
+ }
+ if _, err := io.Copy(dst, src); err != nil {
+ t.Fatalf("failed to copy test binary to %q, %v", tmpBinary, err)
+ }
+ err = dst.Close()
+ if err != nil {
+ t.Fatalf("failed to close test binary %q, %v", tmpBinary, err)
+ }
+
+ uid := uint32(0xfffffffe)
+ err = os.Chown(tmpBinary, int(uid), -1)
+ if err != nil {
+ t.Fatalf("failed to chown test binary %q, %v", tmpBinary, err)
+ }
+
+ err = os.Chmod(tmpBinary, 0755|os.ModeSetuid)
+ if err != nil {
+ t.Fatalf("failed to set setuid bit on test binary %q, %v", tmpBinary, err)
+ }
+
+ cmd := exec.Command(tmpBinary)
+ cmd.Env = []string{"GO_SYSCALL_NOERROR=1"}
+
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("failed to start first child process: %v", err)
+ }
+
+ got := strings.TrimSpace(string(out))
+ want := strconv.FormatUint(uint64(uid)+1, 10) + " / " +
+ strconv.FormatUint(uint64(-uid), 10) + " / " +
+ strconv.FormatUint(uint64(uid), 10)
+ if got != want {
+ t.Errorf("expected %s, got %s", want, got)
+ }
+}
+
+func syscallNoError() {
+ // Test that the return value from SYS_GETEUID32 (which cannot fail)
+ // doesn't get treated as an error (see https://golang.org/issue/22924)
+ euid1, _, e := syscall.RawSyscall(syscall.Sys_GETEUID, 0, 0, 0)
+ euid2, _ := syscall.RawSyscallNoError(syscall.Sys_GETEUID, 0, 0, 0)
+
+ fmt.Println(uintptr(euid1), "/", int(e), "/", uintptr(euid2))
+ os.Exit(0)
+}
diff --git a/libgo/go/syscall/syscall_plan9_test.go b/libgo/go/syscall/syscall_plan9_test.go
new file mode 100644
index 0000000..c0b3af5
--- /dev/null
+++ b/libgo/go/syscall/syscall_plan9_test.go
@@ -0,0 +1,53 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall_test
+
+import (
+ "syscall"
+ "testing"
+)
+
+// testalias checks for aliasing of error strings returned by sys1 and sys2,
+// which both call the function named fn in package syscall
+func testalias(t *testing.T, fn string, sys1, sys2 func() error) {
+ err := sys1().Error()
+ errcopy := string([]byte(err))
+ sys2()
+ if err != errcopy {
+ t.Errorf("syscall.%s error string changed from %q to %q\n", fn, errcopy, err)
+ }
+}
+
+// issue 13770: errors cannot be nested in Plan 9
+
+func TestPlan9Syserr(t *testing.T) {
+ testalias(t,
+ "Syscall",
+ func() error {
+ return syscall.Mkdir("/", 0)
+ },
+ func() error {
+ return syscall.Mkdir("#", 0)
+ })
+ testalias(t,
+ "Syscall6",
+ func() error {
+ return syscall.Mount(0, 0, "", 0, "")
+ },
+ func() error {
+ return syscall.Mount(-1, 0, "", 0, "")
+ })
+ // originally failed only on plan9_arm
+ testalias(t,
+ "seek",
+ func() error {
+ _, err := syscall.Seek(0, 0, -1)
+ return err
+ },
+ func() error {
+ _, err := syscall.Seek(-1, 0, 0)
+ return err
+ })
+}
diff --git a/libgo/go/syscall/syscall_test.go b/libgo/go/syscall/syscall_test.go
index c3fffda..2a9d90e 100644
--- a/libgo/go/syscall/syscall_test.go
+++ b/libgo/go/syscall/syscall_test.go
@@ -62,8 +62,8 @@ func TestExecErrPermutedFds(t *testing.T) {
}
func TestGettimeofday(t *testing.T) {
- if runtime.GOOS == "nacl" {
- t.Skip("not implemented on nacl")
+ if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
+ t.Skip("not implemented on " + runtime.GOOS)
}
tv := &syscall.Timeval{}
if err := syscall.Gettimeofday(tv); err != nil {
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
index 61aa1c4..9455c3f 100644
--- a/libgo/go/syscall/syscall_unix.go
+++ b/libgo/go/syscall/syscall_unix.go
@@ -99,6 +99,16 @@ func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errn
return r, 0, err
}
+// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
+func clen(n []byte) int {
+ for i := 0; i < len(n); i++ {
+ if n[i] == 0 {
+ return i
+ }
+ }
+ return len(n)
+}
+
// Mmap manager, for use by operating system-specific implementations.
// Gccgo only has one implementation but we do this to correspond to gc.
diff --git a/libgo/go/syscall/tables_nacljs.go b/libgo/go/syscall/tables_nacljs.go
new file mode 100644
index 0000000..1c265f2
--- /dev/null
+++ b/libgo/go/syscall/tables_nacljs.go
@@ -0,0 +1,490 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build nacl js,wasm
+
+package syscall
+
+import "runtime"
+
+// TODO: generate with runtime/mknacl.sh, allow override with IRT.
+const (
+ sys_null = 1
+ sys_nameservice = 2
+ sys_dup = 8
+ sys_dup2 = 9
+ sys_open = 10
+ sys_close = 11
+ sys_read = 12
+ sys_write = 13
+ sys_lseek = 14
+ sys_stat = 16
+ sys_fstat = 17
+ sys_chmod = 18
+ sys_isatty = 19
+ sys_brk = 20
+ sys_mmap = 21
+ sys_munmap = 22
+ sys_getdents = 23
+ sys_mprotect = 24
+ sys_list_mappings = 25
+ sys_exit = 30
+ sys_getpid = 31
+ sys_sched_yield = 32
+ sys_sysconf = 33
+ sys_gettimeofday = 40
+ sys_clock = 41
+ sys_nanosleep = 42
+ sys_clock_getres = 43
+ sys_clock_gettime = 44
+ sys_mkdir = 45
+ sys_rmdir = 46
+ sys_chdir = 47
+ sys_getcwd = 48
+ sys_unlink = 49
+ sys_imc_makeboundsock = 60
+ sys_imc_accept = 61
+ sys_imc_connect = 62
+ sys_imc_sendmsg = 63
+ sys_imc_recvmsg = 64
+ sys_imc_mem_obj_create = 65
+ sys_imc_socketpair = 66
+ sys_mutex_create = 70
+ sys_mutex_lock = 71
+ sys_mutex_trylock = 72
+ sys_mutex_unlock = 73
+ sys_cond_create = 74
+ sys_cond_wait = 75
+ sys_cond_signal = 76
+ sys_cond_broadcast = 77
+ sys_cond_timed_wait_abs = 79
+ sys_thread_create = 80
+ sys_thread_exit = 81
+ sys_tls_init = 82
+ sys_thread_nice = 83
+ sys_tls_get = 84
+ sys_second_tls_set = 85
+ sys_second_tls_get = 86
+ sys_exception_handler = 87
+ sys_exception_stack = 88
+ sys_exception_clear_flag = 89
+ sys_sem_create = 100
+ sys_sem_wait = 101
+ sys_sem_post = 102
+ sys_sem_get_value = 103
+ sys_dyncode_create = 104
+ sys_dyncode_modify = 105
+ sys_dyncode_delete = 106
+ sys_test_infoleak = 109
+ sys_test_crash = 110
+ sys_test_syscall_1 = 111
+ sys_test_syscall_2 = 112
+ sys_futex_wait_abs = 120
+ sys_futex_wake = 121
+ sys_pread = 130
+ sys_pwrite = 131
+ sys_truncate = 140
+ sys_lstat = 141
+ sys_link = 142
+ sys_rename = 143
+ sys_symlink = 144
+ sys_access = 145
+ sys_readlink = 146
+ sys_utimes = 147
+ sys_get_random_bytes = 150
+)
+
+// TODO: Auto-generate some day. (Hard-coded in binaries so not likely to change.)
+const (
+ // native_client/src/trusted/service_runtime/include/sys/errno.h
+ // The errors are mainly copied from Linux.
+ EPERM Errno = 1 /* Operation not permitted */
+ ENOENT Errno = 2 /* No such file or directory */
+ ESRCH Errno = 3 /* No such process */
+ EINTR Errno = 4 /* Interrupted system call */
+ EIO Errno = 5 /* I/O error */
+ ENXIO Errno = 6 /* No such device or address */
+ E2BIG Errno = 7 /* Argument list too long */
+ ENOEXEC Errno = 8 /* Exec format error */
+ EBADF Errno = 9 /* Bad file number */
+ ECHILD Errno = 10 /* No child processes */
+ EAGAIN Errno = 11 /* Try again */
+ ENOMEM Errno = 12 /* Out of memory */
+ EACCES Errno = 13 /* Permission denied */
+ EFAULT Errno = 14 /* Bad address */
+ EBUSY Errno = 16 /* Device or resource busy */
+ EEXIST Errno = 17 /* File exists */
+ EXDEV Errno = 18 /* Cross-device link */
+ ENODEV Errno = 19 /* No such device */
+ ENOTDIR Errno = 20 /* Not a directory */
+ EISDIR Errno = 21 /* Is a directory */
+ EINVAL Errno = 22 /* Invalid argument */
+ ENFILE Errno = 23 /* File table overflow */
+ EMFILE Errno = 24 /* Too many open files */
+ ENOTTY Errno = 25 /* Not a typewriter */
+ EFBIG Errno = 27 /* File too large */
+ ENOSPC Errno = 28 /* No space left on device */
+ ESPIPE Errno = 29 /* Illegal seek */
+ EROFS Errno = 30 /* Read-only file system */
+ EMLINK Errno = 31 /* Too many links */
+ EPIPE Errno = 32 /* Broken pipe */
+ ENAMETOOLONG Errno = 36 /* File name too long */
+ ENOSYS Errno = 38 /* Function not implemented */
+ EDQUOT Errno = 122 /* Quota exceeded */
+ EDOM Errno = 33 /* Math arg out of domain of func */
+ ERANGE Errno = 34 /* Math result not representable */
+ EDEADLK Errno = 35 /* Deadlock condition */
+ ENOLCK Errno = 37 /* No record locks available */
+ ENOTEMPTY Errno = 39 /* Directory not empty */
+ ELOOP Errno = 40 /* Too many symbolic links */
+ ENOMSG Errno = 42 /* No message of desired type */
+ EIDRM Errno = 43 /* Identifier removed */
+ ECHRNG Errno = 44 /* Channel number out of range */
+ EL2NSYNC Errno = 45 /* Level 2 not synchronized */
+ EL3HLT Errno = 46 /* Level 3 halted */
+ EL3RST Errno = 47 /* Level 3 reset */
+ ELNRNG Errno = 48 /* Link number out of range */
+ EUNATCH Errno = 49 /* Protocol driver not attached */
+ ENOCSI Errno = 50 /* No CSI structure available */
+ EL2HLT Errno = 51 /* Level 2 halted */
+ EBADE Errno = 52 /* Invalid exchange */
+ EBADR Errno = 53 /* Invalid request descriptor */
+ EXFULL Errno = 54 /* Exchange full */
+ ENOANO Errno = 55 /* No anode */
+ EBADRQC Errno = 56 /* Invalid request code */
+ EBADSLT Errno = 57 /* Invalid slot */
+ EDEADLOCK Errno = EDEADLK /* File locking deadlock error */
+ EBFONT Errno = 59 /* Bad font file fmt */
+ ENOSTR Errno = 60 /* Device not a stream */
+ ENODATA Errno = 61 /* No data (for no delay io) */
+ ETIME Errno = 62 /* Timer expired */
+ ENOSR Errno = 63 /* Out of streams resources */
+ ENONET Errno = 64 /* Machine is not on the network */
+ ENOPKG Errno = 65 /* Package not installed */
+ EREMOTE Errno = 66 /* The object is remote */
+ ENOLINK Errno = 67 /* The link has been severed */
+ EADV Errno = 68 /* Advertise error */
+ ESRMNT Errno = 69 /* Srmount error */
+ ECOMM Errno = 70 /* Communication error on send */
+ EPROTO Errno = 71 /* Protocol error */
+ EMULTIHOP Errno = 72 /* Multihop attempted */
+ EDOTDOT Errno = 73 /* Cross mount point (not really error) */
+ EBADMSG Errno = 74 /* Trying to read unreadable message */
+ EOVERFLOW Errno = 75 /* Value too large for defined data type */
+ ENOTUNIQ Errno = 76 /* Given log. name not unique */
+ EBADFD Errno = 77 /* f.d. invalid for this operation */
+ EREMCHG Errno = 78 /* Remote address changed */
+ ELIBACC Errno = 79 /* Can't access a needed shared lib */
+ ELIBBAD Errno = 80 /* Accessing a corrupted shared lib */
+ ELIBSCN Errno = 81 /* .lib section in a.out corrupted */
+ ELIBMAX Errno = 82 /* Attempting to link in too many libs */
+ ELIBEXEC Errno = 83 /* Attempting to exec a shared library */
+ EILSEQ Errno = 84
+ EUSERS Errno = 87
+ ENOTSOCK Errno = 88 /* Socket operation on non-socket */
+ EDESTADDRREQ Errno = 89 /* Destination address required */
+ EMSGSIZE Errno = 90 /* Message too long */
+ EPROTOTYPE Errno = 91 /* Protocol wrong type for socket */
+ ENOPROTOOPT Errno = 92 /* Protocol not available */
+ EPROTONOSUPPORT Errno = 93 /* Unknown protocol */
+ ESOCKTNOSUPPORT Errno = 94 /* Socket type not supported */
+ EOPNOTSUPP Errno = 95 /* Operation not supported on transport endpoint */
+ EPFNOSUPPORT Errno = 96 /* Protocol family not supported */
+ EAFNOSUPPORT Errno = 97 /* Address family not supported by protocol family */
+ EADDRINUSE Errno = 98 /* Address already in use */
+ EADDRNOTAVAIL Errno = 99 /* Address not available */
+ ENETDOWN Errno = 100 /* Network interface is not configured */
+ ENETUNREACH Errno = 101 /* Network is unreachable */
+ ENETRESET Errno = 102
+ ECONNABORTED Errno = 103 /* Connection aborted */
+ ECONNRESET Errno = 104 /* Connection reset by peer */
+ ENOBUFS Errno = 105 /* No buffer space available */
+ EISCONN Errno = 106 /* Socket is already connected */
+ ENOTCONN Errno = 107 /* Socket is not connected */
+ ESHUTDOWN Errno = 108 /* Can't send after socket shutdown */
+ ETOOMANYREFS Errno = 109
+ ETIMEDOUT Errno = 110 /* Connection timed out */
+ ECONNREFUSED Errno = 111 /* Connection refused */
+ EHOSTDOWN Errno = 112 /* Host is down */
+ EHOSTUNREACH Errno = 113 /* Host is unreachable */
+ EALREADY Errno = 114 /* Socket already connected */
+ EINPROGRESS Errno = 115 /* Connection already in progress */
+ ESTALE Errno = 116
+ ENOTSUP Errno = EOPNOTSUPP /* Not supported */
+ ENOMEDIUM Errno = 123 /* No medium (in tape drive) */
+ ECANCELED Errno = 125 /* Operation canceled. */
+ ELBIN Errno = 2048 /* Inode is remote (not really error) */
+ EFTYPE Errno = 2049 /* Inappropriate file type or format */
+ ENMFILE Errno = 2050 /* No more files */
+ EPROCLIM Errno = 2051
+ ENOSHARE Errno = 2052 /* No such host or network path */
+ ECASECLASH Errno = 2053 /* Filename exists with different case */
+ EWOULDBLOCK Errno = EAGAIN /* Operation would block */
+)
+
+// TODO: Auto-generate some day. (Hard-coded in binaries so not likely to change.)
+var errorstr = [...]string{
+ EPERM: "Operation not permitted",
+ ENOENT: "No such file or directory",
+ ESRCH: "No such process",
+ EINTR: "Interrupted system call",
+ EIO: "I/O error",
+ ENXIO: "No such device or address",
+ E2BIG: "Argument list too long",
+ ENOEXEC: "Exec format error",
+ EBADF: "Bad file number",
+ ECHILD: "No child processes",
+ EAGAIN: "Try again",
+ ENOMEM: "Out of memory",
+ EACCES: "Permission denied",
+ EFAULT: "Bad address",
+ EBUSY: "Device or resource busy",
+ EEXIST: "File exists",
+ EXDEV: "Cross-device link",
+ ENODEV: "No such device",
+ ENOTDIR: "Not a directory",
+ EISDIR: "Is a directory",
+ EINVAL: "Invalid argument",
+ ENFILE: "File table overflow",
+ EMFILE: "Too many open files",
+ ENOTTY: "Not a typewriter",
+ EFBIG: "File too large",
+ ENOSPC: "No space left on device",
+ ESPIPE: "Illegal seek",
+ EROFS: "Read-only file system",
+ EMLINK: "Too many links",
+ EPIPE: "Broken pipe",
+ ENAMETOOLONG: "File name too long",
+ ENOSYS: "not implemented on " + runtime.GOOS,
+ EDQUOT: "Quota exceeded",
+ EDOM: "Math arg out of domain of func",
+ ERANGE: "Math result not representable",
+ EDEADLK: "Deadlock condition",
+ ENOLCK: "No record locks available",
+ ENOTEMPTY: "Directory not empty",
+ ELOOP: "Too many symbolic links",
+ ENOMSG: "No message of desired type",
+ EIDRM: "Identifier removed",
+ ECHRNG: "Channel number out of range",
+ EL2NSYNC: "Level 2 not synchronized",
+ EL3HLT: "Level 3 halted",
+ EL3RST: "Level 3 reset",
+ ELNRNG: "Link number out of range",
+ EUNATCH: "Protocol driver not attached",
+ ENOCSI: "No CSI structure available",
+ EL2HLT: "Level 2 halted",
+ EBADE: "Invalid exchange",
+ EBADR: "Invalid request descriptor",
+ EXFULL: "Exchange full",
+ ENOANO: "No anode",
+ EBADRQC: "Invalid request code",
+ EBADSLT: "Invalid slot",
+ EBFONT: "Bad font file fmt",
+ ENOSTR: "Device not a stream",
+ ENODATA: "No data (for no delay io)",
+ ETIME: "Timer expired",
+ ENOSR: "Out of streams resources",
+ ENONET: "Machine is not on the network",
+ ENOPKG: "Package not installed",
+ EREMOTE: "The object is remote",
+ ENOLINK: "The link has been severed",
+ EADV: "Advertise error",
+ ESRMNT: "Srmount error",
+ ECOMM: "Communication error on send",
+ EPROTO: "Protocol error",
+ EMULTIHOP: "Multihop attempted",
+ EDOTDOT: "Cross mount point (not really error)",
+ EBADMSG: "Trying to read unreadable message",
+ EOVERFLOW: "Value too large for defined data type",
+ ENOTUNIQ: "Given log. name not unique",
+ EBADFD: "f.d. invalid for this operation",
+ EREMCHG: "Remote address changed",
+ ELIBACC: "Can't access a needed shared lib",
+ ELIBBAD: "Accessing a corrupted shared lib",
+ ELIBSCN: ".lib section in a.out corrupted",
+ ELIBMAX: "Attempting to link in too many libs",
+ ELIBEXEC: "Attempting to exec a shared library",
+ ENOTSOCK: "Socket operation on non-socket",
+ EDESTADDRREQ: "Destination address required",
+ EMSGSIZE: "Message too long",
+ EPROTOTYPE: "Protocol wrong type for socket",
+ ENOPROTOOPT: "Protocol not available",
+ EPROTONOSUPPORT: "Unknown protocol",
+ ESOCKTNOSUPPORT: "Socket type not supported",
+ EOPNOTSUPP: "Operation not supported on transport endpoint",
+ EPFNOSUPPORT: "Protocol family not supported",
+ EAFNOSUPPORT: "Address family not supported by protocol family",
+ EADDRINUSE: "Address already in use",
+ EADDRNOTAVAIL: "Address not available",
+ ENETDOWN: "Network interface is not configured",
+ ENETUNREACH: "Network is unreachable",
+ ECONNABORTED: "Connection aborted",
+ ECONNRESET: "Connection reset by peer",
+ ENOBUFS: "No buffer space available",
+ EISCONN: "Socket is already connected",
+ ENOTCONN: "Socket is not connected",
+ ESHUTDOWN: "Can't send after socket shutdown",
+ ETIMEDOUT: "Connection timed out",
+ ECONNREFUSED: "Connection refused",
+ EHOSTDOWN: "Host is down",
+ EHOSTUNREACH: "Host is unreachable",
+ EALREADY: "Socket already connected",
+ EINPROGRESS: "Connection already in progress",
+ ENOMEDIUM: "No medium (in tape drive)",
+ ECANCELED: "Operation canceled.",
+ ELBIN: "Inode is remote (not really error)",
+ EFTYPE: "Inappropriate file type or format",
+ ENMFILE: "No more files",
+ ENOSHARE: "No such host or network path",
+ ECASECLASH: "Filename exists with different case",
+}
+
+// Do the interface allocations only once for common
+// Errno values.
+var (
+ errEAGAIN error = EAGAIN
+ errEINVAL error = EINVAL
+ errENOENT error = ENOENT
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e Errno) error {
+ switch e {
+ case 0:
+ return nil
+ case EAGAIN:
+ return errEAGAIN
+ case EINVAL:
+ return errEINVAL
+ case ENOENT:
+ return errENOENT
+ }
+ return e
+}
+
+var errnoByCode = map[string]Errno{
+ "EPERM": EPERM,
+ "ENOENT": ENOENT,
+ "ESRCH": ESRCH,
+ "EINTR": EINTR,
+ "EIO": EIO,
+ "ENXIO": ENXIO,
+ "E2BIG": E2BIG,
+ "ENOEXEC": ENOEXEC,
+ "EBADF": EBADF,
+ "ECHILD": ECHILD,
+ "EAGAIN": EAGAIN,
+ "ENOMEM": ENOMEM,
+ "EACCES": EACCES,
+ "EFAULT": EFAULT,
+ "EBUSY": EBUSY,
+ "EEXIST": EEXIST,
+ "EXDEV": EXDEV,
+ "ENODEV": ENODEV,
+ "ENOTDIR": ENOTDIR,
+ "EISDIR": EISDIR,
+ "EINVAL": EINVAL,
+ "ENFILE": ENFILE,
+ "EMFILE": EMFILE,
+ "ENOTTY": ENOTTY,
+ "EFBIG": EFBIG,
+ "ENOSPC": ENOSPC,
+ "ESPIPE": ESPIPE,
+ "EROFS": EROFS,
+ "EMLINK": EMLINK,
+ "EPIPE": EPIPE,
+ "ENAMETOOLONG": ENAMETOOLONG,
+ "ENOSYS": ENOSYS,
+ "EDQUOT": EDQUOT,
+ "EDOM": EDOM,
+ "ERANGE": ERANGE,
+ "EDEADLK": EDEADLK,
+ "ENOLCK": ENOLCK,
+ "ENOTEMPTY": ENOTEMPTY,
+ "ELOOP": ELOOP,
+ "ENOMSG": ENOMSG,
+ "EIDRM": EIDRM,
+ "ECHRNG": ECHRNG,
+ "EL2NSYNC": EL2NSYNC,
+ "EL3HLT": EL3HLT,
+ "EL3RST": EL3RST,
+ "ELNRNG": ELNRNG,
+ "EUNATCH": EUNATCH,
+ "ENOCSI": ENOCSI,
+ "EL2HLT": EL2HLT,
+ "EBADE": EBADE,
+ "EBADR": EBADR,
+ "EXFULL": EXFULL,
+ "ENOANO": ENOANO,
+ "EBADRQC": EBADRQC,
+ "EBADSLT": EBADSLT,
+ "EDEADLOCK": EDEADLOCK,
+ "EBFONT": EBFONT,
+ "ENOSTR": ENOSTR,
+ "ENODATA": ENODATA,
+ "ETIME": ETIME,
+ "ENOSR": ENOSR,
+ "ENONET": ENONET,
+ "ENOPKG": ENOPKG,
+ "EREMOTE": EREMOTE,
+ "ENOLINK": ENOLINK,
+ "EADV": EADV,
+ "ESRMNT": ESRMNT,
+ "ECOMM": ECOMM,
+ "EPROTO": EPROTO,
+ "EMULTIHOP": EMULTIHOP,
+ "EDOTDOT": EDOTDOT,
+ "EBADMSG": EBADMSG,
+ "EOVERFLOW": EOVERFLOW,
+ "ENOTUNIQ": ENOTUNIQ,
+ "EBADFD": EBADFD,
+ "EREMCHG": EREMCHG,
+ "ELIBACC": ELIBACC,
+ "ELIBBAD": ELIBBAD,
+ "ELIBSCN": ELIBSCN,
+ "ELIBMAX": ELIBMAX,
+ "ELIBEXEC": ELIBEXEC,
+ "EILSEQ": EILSEQ,
+ "EUSERS": EUSERS,
+ "ENOTSOCK": ENOTSOCK,
+ "EDESTADDRREQ": EDESTADDRREQ,
+ "EMSGSIZE": EMSGSIZE,
+ "EPROTOTYPE": EPROTOTYPE,
+ "ENOPROTOOPT": ENOPROTOOPT,
+ "EPROTONOSUPPORT": EPROTONOSUPPORT,
+ "ESOCKTNOSUPPORT": ESOCKTNOSUPPORT,
+ "EOPNOTSUPP": EOPNOTSUPP,
+ "EPFNOSUPPORT": EPFNOSUPPORT,
+ "EAFNOSUPPORT": EAFNOSUPPORT,
+ "EADDRINUSE": EADDRINUSE,
+ "EADDRNOTAVAIL": EADDRNOTAVAIL,
+ "ENETDOWN": ENETDOWN,
+ "ENETUNREACH": ENETUNREACH,
+ "ENETRESET": ENETRESET,
+ "ECONNABORTED": ECONNABORTED,
+ "ECONNRESET": ECONNRESET,
+ "ENOBUFS": ENOBUFS,
+ "EISCONN": EISCONN,
+ "ENOTCONN": ENOTCONN,
+ "ESHUTDOWN": ESHUTDOWN,
+ "ETOOMANYREFS": ETOOMANYREFS,
+ "ETIMEDOUT": ETIMEDOUT,
+ "ECONNREFUSED": ECONNREFUSED,
+ "EHOSTDOWN": EHOSTDOWN,
+ "EHOSTUNREACH": EHOSTUNREACH,
+ "EALREADY": EALREADY,
+ "EINPROGRESS": EINPROGRESS,
+ "ESTALE": ESTALE,
+ "ENOTSUP": ENOTSUP,
+ "ENOMEDIUM": ENOMEDIUM,
+ "ECANCELED": ECANCELED,
+ "ELBIN": ELBIN,
+ "EFTYPE": EFTYPE,
+ "ENMFILE": ENMFILE,
+ "EPROCLIM": EPROCLIM,
+ "ENOSHARE": ENOSHARE,
+ "ECASECLASH": ECASECLASH,
+ "EWOULDBLOCK": EWOULDBLOCK,
+}
diff --git a/libgo/go/syscall/timestruct.go b/libgo/go/syscall/timestruct.go
index 6ece338..d17811c 100644
--- a/libgo/go/syscall/timestruct.go
+++ b/libgo/go/syscall/timestruct.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package syscall