diff --git a/src/syscall/fs_js.go b/src/syscall/fs_js.go index 00d6c76979..22a055a040 100644 --- a/src/syscall/fs_js.go +++ b/src/syscall/fs_js.go @@ -81,15 +81,15 @@ func Open(path string, openmode int, perm uint32) (int, error) { return 0, errors.New("syscall.Open: O_SYNC is not supported by js/wasm") } - jsFD, err := fsCall("openSync", path, flags, perm) + jsFD, err := fsCall("open", 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 stat, err := fsCall("fstat", fd); err == nil && stat.Call("isDirectory").Bool() { + dir, err := fsCall("readdir", path) if err != nil { return 0, err } @@ -113,7 +113,7 @@ func Close(fd int) error { filesMu.Lock() delete(files, fd) filesMu.Unlock() - _, err := fsCall("closeSync", fd) + _, err := fsCall("close", fd) return err } @@ -125,7 +125,7 @@ func Mkdir(path string, perm uint32) error { if err := checkPath(path); err != nil { return err } - _, err := fsCall("mkdirSync", path, perm) + _, err := fsCall("mkdir", path, perm) return err } @@ -182,7 +182,7 @@ func Stat(path string, st *Stat_t) error { if err := checkPath(path); err != nil { return err } - jsSt, err := fsCall("statSync", path) + jsSt, err := fsCall("stat", path) if err != nil { return err } @@ -194,7 +194,7 @@ func Lstat(path string, st *Stat_t) error { if err := checkPath(path); err != nil { return err } - jsSt, err := fsCall("lstatSync", path) + jsSt, err := fsCall("lstat", path) if err != nil { return err } @@ -203,7 +203,7 @@ func Lstat(path string, st *Stat_t) error { } func Fstat(fd int, st *Stat_t) error { - jsSt, err := fsCall("fstatSync", fd) + jsSt, err := fsCall("fstat", fd) if err != nil { return err } @@ -215,7 +215,7 @@ func Unlink(path string) error { if err := checkPath(path); err != nil { return err } - _, err := fsCall("unlinkSync", path) + _, err := fsCall("unlink", path) return err } @@ -223,7 +223,7 @@ func Rmdir(path string) error { if err := checkPath(path); err != nil { return err } - _, err := fsCall("rmdirSync", path) + _, err := fsCall("rmdir", path) return err } @@ -231,12 +231,12 @@ func Chmod(path string, mode uint32) error { if err := checkPath(path); err != nil { return err } - _, err := fsCall("chmodSync", path, mode) + _, err := fsCall("chmod", path, mode) return err } func Fchmod(fd int, mode uint32) error { - _, err := fsCall("fchmodSync", fd, mode) + _, err := fsCall("fchmod", fd, mode) return err } @@ -267,7 +267,7 @@ func UtimesNano(path string, ts []Timespec) error { } atime := ts[0].Sec mtime := ts[1].Sec - _, err := fsCall("utimesSync", path, atime, mtime) + _, err := fsCall("utimes", path, atime, mtime) return err } @@ -278,7 +278,7 @@ func Rename(from, to string) error { if err := checkPath(to); err != nil { return err } - _, err := fsCall("renameSync", from, to) + _, err := fsCall("rename", from, to) return err } @@ -286,12 +286,12 @@ func Truncate(path string, length int64) error { if err := checkPath(path); err != nil { return err } - _, err := fsCall("truncateSync", path, length) + _, err := fsCall("truncate", path, length) return err } func Ftruncate(fd int, length int64) error { - _, err := fsCall("ftruncateSync", fd, length) + _, err := fsCall("ftruncate", fd, length) return err } @@ -299,7 +299,7 @@ func Getcwd(buf []byte) (n int, err error) { defer recoverErr(&err) cwd := jsProcess.Call("cwd").String() n = copy(buf, cwd) - return n, nil + return } func Chdir(path string) (err error) { @@ -323,7 +323,7 @@ func Readlink(path string, buf []byte) (n int, err error) { if err := checkPath(path); err != nil { return 0, err } - dst, err := fsCall("readlinkSync", path) + dst, err := fsCall("readlink", path) if err != nil { return 0, err } @@ -338,7 +338,7 @@ func Link(path, link string) error { if err := checkPath(link); err != nil { return err } - _, err := fsCall("linkSync", path, link) + _, err := fsCall("link", path, link) return err } @@ -349,12 +349,12 @@ func Symlink(path, link string) error { if err := checkPath(link); err != nil { return err } - _, err := fsCall("symlinkSync", path, link) + _, err := fsCall("symlink", path, link) return err } func Fsync(fd int) error { - _, err := fsCall("fsyncSync", fd) + _, err := fsCall("fsync", fd) return err } @@ -371,7 +371,7 @@ func Read(fd int, b []byte) (int, error) { } a := js.TypedArrayOf(b) - n, err := fsCall("readSync", fd, a, 0, len(b)) + n, err := fsCall("read", fd, a, 0, len(b), nil) a.Release() if err != nil { return 0, err @@ -394,7 +394,7 @@ func Write(fd int, b []byte) (int, error) { } a := js.TypedArrayOf(b) - n, err := fsCall("writeSync", fd, a, 0, len(b)) + n, err := fsCall("write", fd, a, 0, len(b), nil) a.Release() if err != nil { return 0, err @@ -406,7 +406,7 @@ func Write(fd int, b []byte) (int, error) { func Pread(fd int, b []byte, offset int64) (int, error) { a := js.TypedArrayOf(b) - n, err := fsCall("readSync", fd, a, 0, len(b), offset) + n, err := fsCall("read", fd, a, 0, len(b), offset) a.Release() if err != nil { return 0, err @@ -416,7 +416,7 @@ func Pread(fd int, b []byte, offset int64) (int, error) { func Pwrite(fd int, b []byte, offset int64) (int, error) { a := js.TypedArrayOf(b) - n, err := fsCall("writeSync", fd, a, 0, len(b), offset) + n, err := fsCall("write", fd, a, 0, len(b), offset) a.Release() if err != nil { return 0, err @@ -467,10 +467,31 @@ 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 +func fsCall(name string, args ...interface{}) (js.Value, error) { + type callResult struct { + val js.Value + err error + } + + c := make(chan callResult) + jsFS.Call(name, append(args, js.NewCallback(func(args []js.Value) { + var res callResult + + if len(args) >= 1 { // on Node.js 8, fs.utimes calls the callback without any arguments + if jsErr := args[0]; jsErr != js.Null() { + res.err = mapJSError(jsErr) + } + } + + res.val = js.Undefined() + if len(args) >= 2 { + res.val = args[1] + } + + c <- res + }))...) + res := <-c + return res.val, res.err } // checkPath checks that the path is not empty and that it contains no null characters. @@ -492,10 +513,15 @@ func recoverErr(errPtr *error) { if !ok { panic(err) } - errno, ok := errnoByCode[jsErr.Get("code").String()] - if !ok { - panic(err) - } - *errPtr = errnoErr(Errno(errno)) + *errPtr = mapJSError(jsErr.Value) } } + +// mapJSError maps an error given by Node.js to the appropriate Go error +func mapJSError(jsErr js.Value) error { + errno, ok := errnoByCode[jsErr.Get("code").String()] + if !ok { + panic(jsErr) + } + return errnoErr(Errno(errno)) +}