diff --git a/types/node/async_hooks.d.ts b/types/node/async_hooks.d.ts index fdfb41191c..a32036a127 100644 --- a/types/node/async_hooks.d.ts +++ b/types/node/async_hooks.d.ts @@ -143,4 +143,105 @@ declare module "async_hooks" { */ triggerAsyncId(): number; } + + /** + * When having multiple instances of `AsyncLocalStorage`, they are independent + * from each other. It is safe to instantiate this class multiple times. + */ + class AsyncLocalStorage { + /** + * This method disables the instance of `AsyncLocalStorage`. All subsequent calls + * to `asyncLocalStorage.getStore()` will return `undefined` until + * `asyncLocalStorage.run()` or `asyncLocalStorage.runSyncAndReturn()` + * is called again. + * + * When calling `asyncLocalStorage.disable()`, all current contexts linked to the + * instance will be exited. + * + * Calling `asyncLocalStorage.disable()` is required before the + * `asyncLocalStorage` can be garbage collected. This does not apply to stores + * provided by the `asyncLocalStorage`, as those objects are garbage collected + * along with the corresponding async resources. + * + * This method is to be used when the `asyncLocalStorage` is not in use anymore + * in the current process. + */ + disable(): void; + + /** + * This method returns the current store. + * If this method is called outside of an asynchronous context initialized by + * calling `asyncLocalStorage.run` or `asyncLocalStorage.runAndReturn`, it will + * return `undefined`. + */ + getStore(): T | undefined; + + /** + * Calling `asyncLocalStorage.run(callback)` will create a new asynchronous + * context. + * Within the callback function and the asynchronous operations from the callback, + * `asyncLocalStorage.getStore()` will return an instance of `Map` known as + * "the store". This store will be persistent through the following + * asynchronous calls. + * + * The callback will be ran asynchronously. Optionally, arguments can be passed + * to the function. They will be passed to the callback function. + * + * If an error is thrown by the callback function, it will not be caught by + * a `try/catch` block as the callback is ran in a new asynchronous resource. + * Also, the stacktrace will be impacted by the asynchronous call. + */ + // TODO: Apply generic vararg once available + run(store: T, callback: (...args: any[]) => void, ...args: any[]): void; + + /** + * Calling `asyncLocalStorage.exit(callback)` will create a new asynchronous + * context. + * Within the callback function and the asynchronous operations from the callback, + * `asyncLocalStorage.getStore()` will return `undefined`. + * + * The callback will be ran asynchronously. Optionally, arguments can be passed + * to the function. They will be passed to the callback function. + * + * If an error is thrown by the callback function, it will not be caught by + * a `try/catch` block as the callback is ran in a new asynchronous resource. + * Also, the stacktrace will be impacted by the asynchronous call. + */ + exit(callback: (...args: any[]) => void, ...args: any[]): void; + + /** + * This methods runs a function synchronously within a context and return its + * return value. The store is not accessible outside of the callback function or + * the asynchronous operations created within the callback. + * + * Optionally, arguments can be passed to the function. They will be passed to + * the callback function. + * + * If the callback function throws an error, it will be thrown by + * `runSyncAndReturn` too. The stacktrace will not be impacted by this call and + * the context will be exited. + */ + runSyncAndReturn(store: T, callback: (...args: any[]) => R, ...args: any[]): R; + + /** + * This methods runs a function synchronously outside of a context and return its + * return value. The store is not accessible within the callback function or + * the asynchronous operations created within the callback. + * + * Optionally, arguments can be passed to the function. They will be passed to + * the callback function. + * + * If the callback function throws an error, it will be thrown by + * `exitSyncAndReturn` too. The stacktrace will not be impacted by this call and + * the context will be re-entered. + */ + exitSyncAndReturn(callback: (...args: any[]) => R, ...args: any[]): R; + + /** + * Calling `asyncLocalStorage.enterWith(store)` will transition into the context + * for the remainder of the current synchronous execution and will persist + * through any following asynchronous calls. + */ + enterWith(store: T): void; + } } diff --git a/types/node/fs.d.ts b/types/node/fs.d.ts index f894332b35..ace1e5b958 100644 --- a/types/node/fs.d.ts +++ b/types/node/fs.d.ts @@ -855,12 +855,13 @@ declare module "fs" { interface MakeDirectoryOptions { /** * Indicates whether parent folders should be created. + * If a folder was created, the path to the first created folder will be returned. * @default false */ recursive?: boolean; /** * A file mode. If a string is passed, it is parsed as an octal integer. If not specified - * @default 0o777. + * @default 0o777 */ mode?: number | string; } @@ -871,7 +872,23 @@ declare module "fs" { * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. */ - function mkdir(path: PathLike, options: number | string | MakeDirectoryOptions | undefined | null, callback: NoParamCallback): void; + function mkdir(path: PathLike, options: MakeDirectoryOptions & { recursive: true }, callback: (err: NodeJS.ErrnoException | null, path: string) => void): void; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options: number | string | (MakeDirectoryOptions & { recursive?: false; }) | null | undefined, callback: NoParamCallback): void; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options: number | string | MakeDirectoryOptions | null | undefined, callback: (err: NodeJS.ErrnoException | null, path: string | undefined) => void): void; /** * Asynchronous mkdir(2) - create a directory with a mode of `0o777`. @@ -887,7 +904,23 @@ declare module "fs" { * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. */ - function __promisify__(path: PathLike, options?: number | string | MakeDirectoryOptions | null): Promise; + function __promisify__(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__(path: PathLike, options?: number | string | (MakeDirectoryOptions & { recursive?: false; }) | null): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function __promisify__(path: PathLike, options?: number | string | MakeDirectoryOptions | null): Promise; } /** @@ -896,7 +929,23 @@ declare module "fs" { * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. */ - function mkdirSync(path: PathLike, options?: number | string | MakeDirectoryOptions | null): void; + function mkdirSync(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): string; + + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdirSync(path: PathLike, options?: number | string | (MakeDirectoryOptions & { recursive?: false; }) | null): void; + + /** + * Synchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdirSync(path: PathLike, options?: number | string | MakeDirectoryOptions | null): string | undefined; /** * Asynchronously creates a unique temporary directory. @@ -2278,7 +2327,23 @@ declare module "fs" { * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. */ - function mkdir(path: PathLike, options?: number | string | MakeDirectoryOptions | null): Promise; + function mkdir(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options?: number | string | (MakeDirectoryOptions & { recursive?: false; }) | null): Promise; + + /** + * Asynchronous mkdir(2) - create a directory. + * @param path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders + * should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. + */ + function mkdir(path: PathLike, options?: number | string | MakeDirectoryOptions | null): Promise; /** * Asynchronous readdir(3) - read a directory. diff --git a/types/node/index.d.ts b/types/node/index.d.ts index f347ff748f..a1e1e32fc6 100644 --- a/types/node/index.d.ts +++ b/types/node/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for non-npm package Node.js 13.9 +// Type definitions for non-npm package Node.js 13.11 // Project: http://nodejs.org/ // Definitions by: Microsoft TypeScript // DefinitelyTyped diff --git a/types/node/os.d.ts b/types/node/os.d.ts index 59980e7422..289b2f3aa7 100644 --- a/types/node/os.d.ts +++ b/types/node/os.d.ts @@ -209,6 +209,14 @@ declare module "os" { } function arch(): string; + /** + * Returns a string identifying the kernel version. + * On POSIX systems, the operating system release is determined by calling + * [uname(3)][]. On Windows, `pRtlGetVersion` is used, and if it is not available, + * `GetVersionExW()` will be used. See + * https://en.wikipedia.org/wiki/Uname#Examples for more information. + */ + function version(): string; function platform(): NodeJS.Platform; function tmpdir(): string; const EOL: string; diff --git a/types/node/test/async_hooks.ts b/types/node/test/async_hooks.ts index 658f8bb653..4555859a9f 100644 --- a/types/node/test/async_hooks.ts +++ b/types/node/test/async_hooks.ts @@ -1,7 +1,7 @@ -import * as async_hooks from 'async_hooks'; +import { AsyncResource, createHook, triggerAsyncId, executionAsyncId, executionAsyncResource, HookCallbacks, AsyncLocalStorage } from 'async_hooks'; { - const hooks: async_hooks.HookCallbacks = { + const hooks: HookCallbacks = { init() {}, before() {}, after() {}, @@ -9,21 +9,21 @@ import * as async_hooks from 'async_hooks'; promiseResolve() {}, }; - const asyncHook = async_hooks.createHook(hooks); + const asyncHook = createHook(hooks); asyncHook.enable().disable().enable(); - const tId: number = async_hooks.triggerAsyncId(); - const eId: number = async_hooks.executionAsyncId(); - const curRes: object = async_hooks.executionAsyncResource(); + const tId: number = triggerAsyncId(); + const eId: number = executionAsyncId(); + const curRes: object = executionAsyncResource(); - class TestResource extends async_hooks.AsyncResource { + class TestResource extends AsyncResource { constructor() { super('TEST_RESOURCE'); } } - class AnotherTestResource extends async_hooks.AsyncResource { + class AnotherTestResource extends AsyncResource { constructor() { super('TEST_RESOURCE', 42); const aId: number = this.asyncId(); @@ -39,12 +39,30 @@ import * as async_hooks from 'async_hooks'; } // check AsyncResource constructor options. - new async_hooks.AsyncResource(''); - new async_hooks.AsyncResource('', 0); - new async_hooks.AsyncResource('', {}); - new async_hooks.AsyncResource('', { triggerAsyncId: 0 }); - new async_hooks.AsyncResource('', { + new AsyncResource(''); + new AsyncResource('', 0); + new AsyncResource('', {}); + new AsyncResource('', { triggerAsyncId: 0 }); + new AsyncResource('', { triggerAsyncId: 0, requireManualDestroy: true }); } + +{ + const ctx = new AsyncLocalStorage(); + ctx.disable(); + ctx.exit((a: number) => { + // noop? + }, 1); + const esRet: number = ctx.exitSyncAndReturn((a: number) => { + return 123; + }, 1); + ctx.run('test', (a: number) => { + const store: string | undefined = ctx.getStore(); + }, 1); + const rsSet = ctx.runSyncAndReturn('test', (a: number) => { + return 123; + }, 1); + ctx.enterWith('test'); +} diff --git a/types/node/test/fs.ts b/types/node/test/fs.ts index 9f7ca72a72..4045bc5cea 100644 --- a/types/node/test/fs.ts +++ b/types/node/test/fs.ts @@ -275,13 +275,28 @@ async function testPromisify() { fs.mkdir('some/test/path', { recursive: true, mode: 0o777, - }, () => { + }, (err, path) => { + err; // $ExpectType ErrnoException | null + path; // $ExpectType string }); + // $ExpectType string fs.mkdirSync('some/test/path', { recursive: true, mode: 0o777, }); + + // $ExpectType Promise + util.promisify(fs.mkdir)('some/test/path', { + recursive: true, + mode: 0o777, + }); + + // $ExpectType Promise + fs.promises.mkdir('some/test/path', { + recursive: true, + mode: 0o777, + }); } { diff --git a/types/node/test/os.ts b/types/node/test/os.ts index 8920b81319..9f690aacb9 100644 --- a/types/node/test/os.ts +++ b/types/node/test/os.ts @@ -7,6 +7,7 @@ import * as os from 'os'; result = os.endianness(); result = os.hostname(); result = os.type(); + result = os.version(); result = os.arch(); result = os.release(); result = os.EOL; diff --git a/types/node/test/tls.ts b/types/node/test/tls.ts index ff9913248b..71e76c2d1c 100644 --- a/types/node/test/tls.ts +++ b/types/node/test/tls.ts @@ -57,6 +57,8 @@ import * as fs from "fs"; const curve: string = DEFAULT_ECDH_CURVE; const maxVersion: string = DEFAULT_MAX_VERSION; const minVersion: string = DEFAULT_MIN_VERSION; + + const buf: Buffer = tlsSocket.exportKeyingMaterial(123, 'test', Buffer.from('nope')); } { diff --git a/types/node/test/vm.ts b/types/node/test/vm.ts index 2d3e6bcfc1..cf2c12e603 100644 --- a/types/node/test/vm.ts +++ b/types/node/test/vm.ts @@ -1,4 +1,4 @@ -import { createContext, isContext, Script, runInNewContext, runInThisContext, compileFunction } from 'vm'; +import { createContext, isContext, Script, runInNewContext, runInThisContext, compileFunction, measureMemory, MemoryMeasurement } from 'vm'; import { inspect } from 'util'; { @@ -60,3 +60,10 @@ import { inspect } from 'util'; cachedData: Buffer.from('nope'), }); } + +{ + const usage = measureMemory({ + mode: 'detailed', + context: createContext(), + }).then((data: MemoryMeasurement) => { }); +} diff --git a/types/node/tls.d.ts b/types/node/tls.d.ts index a1a03b5644..8db6f796c8 100644 --- a/types/node/tls.d.ts +++ b/types/node/tls.d.ts @@ -297,6 +297,14 @@ declare module "tls" { */ enableTrace(): void; + /** + * @param length number of bytes to retrieve from keying material + * @param label an application specific label, typically this will be a value from the + * [IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels). + * @param context optionally provide a context. + */ + exportKeyingMaterial(length: number, label: string, context: Buffer): Buffer; + addListener(event: string, listener: (...args: any[]) => void): this; addListener(event: "OCSPResponse", listener: (response: Buffer) => void): this; addListener(event: "secureConnect", listener: () => void): this; diff --git a/types/node/ts3.5/node-tests.ts b/types/node/ts3.5/node-tests.ts index 651f0d76ea..a0a1c9252f 100644 --- a/types/node/ts3.5/node-tests.ts +++ b/types/node/ts3.5/node-tests.ts @@ -36,7 +36,8 @@ const wasi = new WASI({ env: process.env, preopens: { '/sandbox': '/some/real/path/that/wasm/can/access' - } + }, + returnOnExit: false, }); const importObject = { wasi_unstable: wasi.wasiImport }; (async () => { diff --git a/types/node/ts3.5/wasi.d.ts b/types/node/ts3.5/wasi.d.ts index 50c147e4df..4a79ecc2ac 100644 --- a/types/node/ts3.5/wasi.d.ts +++ b/types/node/ts3.5/wasi.d.ts @@ -20,6 +20,15 @@ declare module 'wasi' { preopens?: { [key: string]: string; }; + + /** + * By default, WASI applications terminate the Node.js + * process via the `__wasi_proc_exit()` function. Setting this option to `true` + * causes `wasi.start()` to return the exit code rather than terminate the + * process. + * @default false + */ + returnOnExit?: boolean; } class WASI { diff --git a/types/node/vm.d.ts b/types/node/vm.d.ts index ffef7c3b6a..7f8ff9c74e 100644 --- a/types/node/vm.d.ts +++ b/types/node/vm.d.ts @@ -94,6 +94,23 @@ declare module "vm" { }; } + type MeasureMemoryMode = 'summary' | 'detailed'; + + interface MeasureMemoryOptions { + /** + * @default 'summary' + */ + mode?: MeasureMemoryMode; + context?: Context; + } + + interface MemoryMeasurement { + total: { + jsMemoryEstimate: number; + jsMemoryRange: [number, number]; + }; + } + class Script { constructor(code: string, options?: ScriptOptions); runInContext(contextifiedSandbox: Context, options?: RunningScriptOptions): any; @@ -107,4 +124,21 @@ declare module "vm" { function runInNewContext(code: string, sandbox?: Context, options?: RunningScriptOptions | string): any; function runInThisContext(code: string, options?: RunningScriptOptions | string): any; function compileFunction(code: string, params?: string[], options?: CompileFunctionOptions): Function; + + /** + * Measure the memory known to V8 and used by the current execution context or a specified context. + * + * The format of the object that the returned Promise may resolve with is + * specific to the V8 engine and may change from one version of V8 to the next. + * + * The returned result is different from the statistics returned by + * `v8.getHeapSpaceStatistics()` in that `vm.measureMemory()` measures + * the memory reachable by V8 from a specific context, while + * `v8.getHeapSpaceStatistics()` measures the memory used by an instance + * of V8 engine, which can switch among multiple contexts that reference + * objects in the heap of one engine. + * + * @experimental + */ + function measureMemory(options?: MeasureMemoryOptions): Promise; }