From 509f5ef623864c97e5b4ed04ff862c8aee4bba1c Mon Sep 17 00:00:00 2001 From: Dimitri Benin Date: Sat, 8 Dec 2018 12:39:23 +0100 Subject: [PATCH] Add types for experimetal worker_threads module --- types/node/index.d.ts | 125 +++++++++++++++++++++++++++++++++++++++ types/node/node-tests.ts | 51 ++++++++++++++++ 2 files changed, 176 insertions(+) diff --git a/types/node/index.d.ts b/types/node/index.d.ts index b9edae0587b43dd..9cce2bb9e5fbad7 100644 --- a/types/node/index.d.ts +++ b/types/node/index.d.ts @@ -1618,6 +1618,131 @@ declare module "cluster" { function eventNames(): string[]; } +declare module "worker_threads" { + import * as events from "events"; + import * as stream from "stream"; + + const isMainThread: boolean; + const parentPort: null | MessagePort; + const threadId: number; + const workerData: any; + + class MessageChannel { + readonly port1: MessagePort; + readonly port2: MessagePort; + } + + class MessagePort extends events.EventEmitter { + close(): void; + postMessage(value: any, transferList?: Array): void; + ref(): void; + unref(): void; + start(): void; + + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: "close", listener: () => void): this; + addListener(event: "message", listener: (value: any) => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "close"): boolean; + emit(event: "message", value: any): boolean; + + on(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: "close", listener: () => void): this; + on(event: "message", listener: (value: any) => void): this; + + once(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: "close", listener: () => void): this; + once(event: "message", listener: (value: any) => void): this; + + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependListener(event: "close", listener: () => void): this; + prependListener(event: "message", listener: (value: any) => void): this; + + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + prependOnceListener(event: "message", listener: (value: any) => void): this; + + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: "close", listener: () => void): this; + removeListener(event: "message", listener: (value: any) => void): this; + + off(event: string | symbol, listener: (...args: any[]) => void): this; + off(event: "close", listener: () => void): this; + off(event: "message", listener: (value: any) => void): this; + } + + interface WorkerOptions { + eval?: boolean; + workerData?: any; + stdin?: boolean; + stdout?: boolean; + stderr?: boolean; + } + + class Worker extends events.EventEmitter { + readonly stdin: stream.Writable | null; + readonly stdout: stream.Readable; + readonly stderr: stream.Readable; + readonly threadId: number; + + constructor(filename: string, options?: WorkerOptions); + + postMessage(value: any, transferList?: Array): void; + ref(): void; + unref(): void; + terminate(callback?: (err: any, exitCode: number) => void): void; + + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + addListener(event: "error", listener: (err: any) => void): this; + addListener(event: "exit", listener: (exitCode: number) => void): this; + addListener(event: "message", listener: (value: any) => void): this; + addListener(event: "online", listener: () => void): this; + + emit(event: string | symbol, ...args: any[]): boolean; + emit(event: "error", err: any): boolean; + emit(event: "exit", exitCode: number): boolean; + emit(event: "message", value: any): boolean; + emit(event: "online"): boolean; + + on(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: "error", listener: (err: any) => void): this; + on(event: "exit", listener: (exitCode: number) => void): this; + on(event: "message", listener: (value: any) => void): this; + on(event: "online", listener: () => void): this; + + once(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: "error", listener: (err: any) => void): this; + once(event: "exit", listener: (exitCode: number) => void): this; + once(event: "message", listener: (value: any) => void): this; + once(event: "online", listener: () => void): this; + + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependListener(event: "error", listener: (err: any) => void): this; + prependListener(event: "exit", listener: (exitCode: number) => void): this; + prependListener(event: "message", listener: (value: any) => void): this; + prependListener(event: "online", listener: () => void): this; + + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: "error", listener: (err: any) => void): this; + prependOnceListener(event: "exit", listener: (exitCode: number) => void): this; + prependOnceListener(event: "message", listener: (value: any) => void): this; + prependOnceListener(event: "online", listener: () => void): this; + + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: "error", listener: (err: any) => void): this; + removeListener(event: "exit", listener: (exitCode: number) => void): this; + removeListener(event: "message", listener: (value: any) => void): this; + removeListener(event: "online", listener: () => void): this; + + off(event: string | symbol, listener: (...args: any[]) => void): this; + off(event: "error", listener: (err: any) => void): this; + off(event: "exit", listener: (exitCode: number) => void): this; + off(event: "message", listener: (value: any) => void): this; + off(event: "online", listener: () => void): this; + } +} + declare module "zlib" { import * as stream from "stream"; diff --git a/types/node/node-tests.ts b/types/node/node-tests.ts index c0f80728fca9e5a..a638f0fee88f760 100644 --- a/types/node/node-tests.ts +++ b/types/node/node-tests.ts @@ -17,6 +17,7 @@ import * as path from "path"; import * as readline from "readline"; import * as childProcess from "child_process"; import * as cluster from "cluster"; +import * as workerThreads from "worker_threads"; import * as os from "os"; import * as vm from "vm"; import * as console2 from "console"; @@ -2932,6 +2933,56 @@ async function asyncStreamPipelineFinished() { } } +////////////////////////////////////////////////////////////////////// +/// worker_threads tests: https://nodejs.org/api/worker_threads.html /// +////////////////////////////////////////////////////////////////////// + +{ + { + if (workerThreads.isMainThread) { + module.exports = async function parseJSAsync(script: string) { + return new Promise((resolve, reject) => { + const worker = new workerThreads.Worker(__filename, { + workerData: script + }); + worker.on('message', resolve); + worker.on('error', reject); + worker.on('exit', (code) => { + if (code !== 0) + reject(new Error(`Worker stopped with exit code ${code}`)); + }); + }); + }; + } else { + const script = workerThreads.workerData; + workerThreads.parentPort.postMessage(script); + } + } + + { + const { port1, port2 } = new workerThreads.MessageChannel(); + port1.on('message', (message) => console.log('received', message)); + port2.postMessage({ foo: 'bar' }); + } + + { + if (workerThreads.isMainThread) { + const worker = new workerThreads.Worker(__filename); + const subChannel = new workerThreads.MessageChannel(); + worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]); + subChannel.port2.on('message', (value) => { + console.log('received:', value); + }); + } else { + workerThreads.parentPort.once('message', (value) => { + assert(value.hereIsYourPort instanceof MessagePort); + value.hereIsYourPort.postMessage('the worker is sending this'); + value.hereIsYourPort.close(); + }); + } + } +} + //////////////////////////////////////////////////// /// os tests : https://nodejs.org/api/os.html ////////////////////////////////////////////////////