[Node] Node attaches errno information to some exceptions.

This is valuable information for Node applications that need to figure out why a particular system call failed.

Note that errno can either be a string or a number, which is why I have typed it as 'any'.

While this is undocumented, it is tested:
Code property: https://github.com/joyent/node/blob/v0.10.23-release/test/simple/test-fs-open.js#L34
Errno property [string]: https://github.com/joyent/node/blob/v0.10.23-release/test/internet/test-dns.js#L148
Errno property [number]: https://github.com/joyent/node/blob/v0.10.23-release/test/simple/test-domain-implicit-fs.js#L43
Syscall property: https://github.com/joyent/node/blob/v0.10.23-release/test/simple/test-stdout-close-catch.js#L38
Path property (I can’t find a test, but many examples have this line): https://github.com/joyent/node/blob/v0.10.23-release/deps/npm/node_modules/fstream-npm/example/bundle.js#L6

..and well supported in the code for all platforms (this is where I got the name 'ErrnoException' from):
*nix: https://github.com/joyent/node/blob/v0.10.23-release/src/node.cc#L719
Windows: https://github.com/joyent/node/blob/v0.10.23-release/src/node.cc#L856

Unfortunately, while every errno exception is guaranteed to have the ‘errno’ and ‘code’ properties (see the logic in the source code in node.cc), there is no hard guarantee that particular library functions will always pass an ErrnoException to the callback. I cannot find a counterexample at this moment, though. Since we can’t have union types in TypeScript, I simply made all of the properties on ErrnoException optional as a compromise.

I am only adding modifications to the fs module, which definitely throws ErrnoExceptions. But according to the examples above, other modules (e.g. dns) also pass errno information back to applications. People familiar with those other modules can update their typings to reference this interface when applicable; I lack the experience with those modules to update their typings.

Further proof:
```javascript
$ node
> var fs = require('fs');
undefined
> fs.open('doesntexistlol', 'r', function(e) { console.log(Object.keys(e)); console.log(e.code); console.log(e.errno); console.log(e.path); });
undefined
> [ 'errno', 'code', 'path' ]
ENOENT
34
doesntexistlol
```
This commit is contained in:
John Vilk
2013-12-17 15:35:25 -05:00
parent 718eff7763
commit cddd0b7aab

97
node/node.d.ts vendored
View File

@@ -67,6 +67,13 @@ declare var Buffer: {
* *
************************************************/
interface ErrnoException extends Error {
errno?: any;
code?: string;
path?: string;
syscall?: string;
}
interface EventEmitter {
addListener(event: string, listener: Function): EventEmitter;
on(event: string, listener: Function): EventEmitter;
@@ -746,87 +753,87 @@ declare module "fs" {
export interface ReadStream extends stream.ReadableStream { }
export interface WriteStream extends stream.WritableStream { }
export function rename(oldPath: string, newPath: string, callback?: Function): void;
export function rename(oldPath: string, newPath: string, callback?: (err?: ErrnoException) => void): void;
export function renameSync(oldPath: string, newPath: string): void;
export function truncate(path: string, callback?: Function): void;
export function truncate(path: string, len: number, callback?: Function): void;
export function truncate(path: string, callback?: (err?: ErrnoException) => void): void;
export function truncate(path: string, len: number, callback?: (err?: ErrnoException) => void): void;
export function truncateSync(path: string, len?: number): void;
export function ftruncate(fd: number, callback?: Function): void;
export function ftruncate(fd: number, len: number, callback?: Function): void;
export function ftruncate(fd: number, callback?: (err?: ErrnoException) => void): void;
export function ftruncate(fd: number, len: number, callback?: (err?: ErrnoException) => void): void;
export function ftruncateSync(fd: number, len?: number): void;
export function chown(path: string, uid: number, gid: number, callback?: Function): void;
export function chown(path: string, uid: number, gid: number, callback?: (err?: ErrnoException) => void): void;
export function chownSync(path: string, uid: number, gid: number): void;
export function fchown(fd: number, uid: number, gid: number, callback?: Function): void;
export function fchown(fd: number, uid: number, gid: number, callback?: (err?: ErrnoException) => void): void;
export function fchownSync(fd: number, uid: number, gid: number): void;
export function lchown(path: string, uid: number, gid: number, callback?: Function): void;
export function lchown(path: string, uid: number, gid: number, callback?: (err?: ErrnoException) => void): void;
export function lchownSync(path: string, uid: number, gid: number): void;
export function chmod(path: string, mode: number, callback?: Function): void;
export function chmod(path: string, mode: string, callback?: Function): void;
export function chmod(path: string, mode: number, callback?: (err?: ErrnoException) => void): void;
export function chmod(path: string, mode: string, callback?: (err?: ErrnoException) => void): void;
export function chmodSync(path: string, mode: number): void;
export function chmodSync(path: string, mode: string): void;
export function fchmod(fd: number, mode: number, callback?: Function): void;
export function fchmod(fd: number, mode: string, callback?: Function): void;
export function fchmod(fd: number, mode: number, callback?: (err?: ErrnoException) => void): void;
export function fchmod(fd: number, mode: string, callback?: (err?: ErrnoException) => void): void;
export function fchmodSync(fd: number, mode: number): void;
export function fchmodSync(fd: number, mode: string): void;
export function lchmod(path: string, mode: number, callback?: Function): void;
export function lchmod(path: string, mode: string, callback?: Function): void;
export function lchmod(path: string, mode: number, callback?: (err?: ErrnoException) => void): void;
export function lchmod(path: string, mode: string, callback?: (err?: ErrnoException) => void): void;
export function lchmodSync(path: string, mode: number): void;
export function lchmodSync(path: string, mode: string): void;
export function stat(path: string, callback?: (err: Error, stats: Stats) => any): void;
export function lstat(path: string, callback?: (err: Error, stats: Stats) => any): void;
export function fstat(fd: number, callback?: (err: Error, stats: Stats) => any): void;
export function stat(path: string, callback?: (err: ErrnoException, stats: Stats) => any): void;
export function lstat(path: string, callback?: (err: ErrnoException, stats: Stats) => any): void;
export function fstat(fd: number, callback?: (err: ErrnoException, stats: Stats) => any): void;
export function statSync(path: string): Stats;
export function lstatSync(path: string): Stats;
export function fstatSync(fd: number): Stats;
export function link(srcpath: string, dstpath: string, callback?: Function): void;
export function link(srcpath: string, dstpath: string, callback?: (err?: ErrnoException) => void): void;
export function linkSync(srcpath: string, dstpath: string): void;
export function symlink(srcpath: string, dstpath: string, type?: string, callback?: Function): void;
export function symlink(srcpath: string, dstpath: string, type?: string, callback?: (err?: ErrnoException) => void): void;
export function symlinkSync(srcpath: string, dstpath: string, type?: string): void;
export function readlink(path: string, callback?: (err: Error, linkString: string) => any): void;
export function readlink(path: string, callback?: (err: ErrnoException, linkString: string) => any): void;
export function readlinkSync(path: string): string;
export function realpath(path: string, callback?: (err: Error, resolvedPath: string) => any): void;
export function realpath(path: string, cache: {[path: string]: string}, callback: (err: Error, resolvedPath: string) =>any): void;
export function realpath(path: string, callback?: (err: ErrnoException, resolvedPath: string) => any): void;
export function realpath(path: string, cache: {[path: string]: string}, callback: (err: ErrnoException, resolvedPath: string) =>any): void;
export function realpathSync(path: string, cache?: {[path: string]: string}): void;
export function unlink(path: string, callback?: Function): void;
export function unlink(path: string, callback?: (err?: ErrnoException) => void): void;
export function unlinkSync(path: string): void;
export function rmdir(path: string, callback?: Function): void;
export function rmdir(path: string, callback?: (err?: ErrnoException) => void): void;
export function rmdirSync(path: string): void;
export function mkdir(path: string, callback?: Function): void;
export function mkdir(path: string, mode: number, callback?: Function): void;
export function mkdir(path: string, mode: string, callback?: Function): void;
export function mkdir(path: string, callback?: (err?: ErrnoException) => void): void;
export function mkdir(path: string, mode: number, callback?: (err?: ErrnoException) => void): void;
export function mkdir(path: string, mode: string, callback?: (err?: ErrnoException) => void): void;
export function mkdirSync(path: string, mode?: number): void;
export function mkdirSync(path: string, mode?: string): void;
export function readdir(path: string, callback?: (err: Error, files: string[]) => void): void;
export function readdir(path: string, callback?: (err: ErrnoException, files: string[]) => void): void;
export function readdirSync(path: string): string[];
export function close(fd: number, callback?: Function): void;
export function close(fd: number, callback?: (err?: ErrnoException) => void): void;
export function closeSync(fd: number): void;
export function open(path: string, flags: string, callback?: (err: Error, fd: number) => any): void;
export function open(path: string, flags: string, mode: number, callback?: (err: Error, fd: number) => any): void;
export function open(path: string, flags: string, mode: string, callback?: (err: Error, fd: number) => any): void;
export function open(path: string, flags: string, callback?: (err: ErrnoException, fd: number) => any): void;
export function open(path: string, flags: string, mode: number, callback?: (err: ErrnoException, fd: number) => any): void;
export function open(path: string, flags: string, mode: string, callback?: (err: ErrnoException, fd: number) => any): void;
export function openSync(path: string, flags: string, mode?: number): number;
export function openSync(path: string, flags: string, mode?: string): number;
export function utimes(path: string, atime: number, mtime: number, callback?: Function): void;
export function utimes(path: string, atime: number, mtime: number, callback?: (err?: ErrnoException) => void): void;
export function utimesSync(path: string, atime: number, mtime: number): void;
export function futimes(fd: number, atime: number, mtime: number, callback?: Function): void;
export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: ErrnoException) => void): void;
export function futimesSync(fd: number, atime: number, mtime: number): void;
export function fsync(fd: number, callback?: Function): void;
export function fsync(fd: number, callback?: (err?: ErrnoException) => void): void;
export function fsyncSync(fd: number): void;
export function write(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number, callback?: (err: Error, written: number, buffer: NodeBuffer) => void): void;
export function write(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number, callback?: (err: ErrnoException, written: number, buffer: NodeBuffer) => void): void;
export function writeSync(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number): number;
export function read(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number, callback?: (err: Error, bytesRead: number, buffer: NodeBuffer) => void): void;
export function read(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number, callback?: (err: ErrnoException, bytesRead: number, buffer: NodeBuffer) => void): void;
export function readSync(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number): number;
export function readFile(filename: string, options: { encoding?: string; flag?: string; }, callback: (err: Error, data: any) => void): void;
export function readFile(filename: string, callback: (err: Error, data: NodeBuffer) => void ): void;
export function readFile(filename: string, options: { encoding?: string; flag?: string; }, callback: (err: ErrnoException, data: any) => void): void;
export function readFile(filename: string, callback: (err: ErrnoException, data: NodeBuffer) => void ): void;
export function readFileSync(filename: string, options?: { flag?: string; }): NodeBuffer;
export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string;
export function writeFile(filename: string, data: any, callback?: (err: Error) => void): void;
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: Error) => void): void;
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: Error) => void): void;
export function writeFile(filename: string, data: any, callback?: (err: ErrnoException) => void): void;
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: ErrnoException) => void): void;
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: ErrnoException) => void): void;
export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void;
export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void;
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: Error) => void): void;
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: Error) => void): void;
export function appendFile(filename: string, data: any, callback?: (err: Error) => void): void;
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: ErrnoException) => void): void;
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: ErrnoException) => void): void;
export function appendFile(filename: string, data: any, callback?: (err: ErrnoException) => void): void;
export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void;
export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void;
export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void;