diff --git a/.eslintrc.js b/.eslintrc.js index bda641797e2951..f5100fd3cc91b8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -98,6 +98,14 @@ module.exports = { name: 'require', message: 'Use import instead', }, + { + name: 'Buffer', + message: 'Import Buffer instead of using the global' + }, + { + name: 'process', + message: 'Import process instead of using the global' + }, ] }, }, ], diff --git a/doc/api/assert.md b/doc/api/assert.md index 7eb952ace7be71..037d233be0acd9 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -240,6 +240,7 @@ for the verification to take place. The usual pattern would be to call it in a ```mjs import assert from 'assert'; +import process from 'process'; const tracker = new assert.CallTracker(); diff --git a/doc/api/async_context.md b/doc/api/async_context.md index 7092a2d5bf2913..11a7a55558707c 100644 --- a/doc/api/async_context.md +++ b/doc/api/async_context.md @@ -14,7 +14,11 @@ in other languages. The `AsyncLocalStorage` and `AsyncResource` classes are part of the `async_hooks` module: -```js +```mjs +import async_hooks from 'async_hooks'; +``` + +```cjs const async_hooks = require('async_hooks'); ``` @@ -40,7 +44,39 @@ The following example uses `AsyncLocalStorage` to build a simple logger that assigns IDs to incoming HTTP requests and includes them in messages logged within each request. -```js +```mjs +import http from 'http'; +import { AsyncLocalStorage } from 'async_hooks'; + +const asyncLocalStorage = new AsyncLocalStorage(); + +function logWithId(msg) { + const id = asyncLocalStorage.getStore(); + console.log(`${id !== undefined ? id : '-'}:`, msg); +} + +let idSeq = 0; +http.createServer((req, res) => { + asyncLocalStorage.run(idSeq++, () => { + logWithId('start'); + // Imagine any chain of async operations here + setImmediate(() => { + logWithId('finish'); + res.end(); + }); + }); +}).listen(8080); + +http.get('http://localhost:8080'); +http.get('http://localhost:8080'); +// Prints: +// 0: start +// 1: start +// 0: finish +// 1: finish +``` + +```cjs const http = require('http'); const { AsyncLocalStorage } = require('async_hooks'); @@ -299,7 +335,35 @@ The `init` hook will trigger when an `AsyncResource` is instantiated. The following is an overview of the `AsyncResource` API. -```js +```mjs +import { AsyncResource, executionAsyncId } from 'async_hooks'; + +// AsyncResource() is meant to be extended. Instantiating a +// new AsyncResource() also triggers init. If triggerAsyncId is omitted then +// async_hook.executionAsyncId() is used. +const asyncResource = new AsyncResource( + type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false } +); + +// Run a function in the execution context of the resource. This will +// * establish the context of the resource +// * trigger the AsyncHooks before callbacks +// * call the provided function `fn` with the supplied arguments +// * trigger the AsyncHooks after callbacks +// * restore the original execution context +asyncResource.runInAsyncScope(fn, thisArg, ...args); + +// Call AsyncHooks destroy callbacks. +asyncResource.emitDestroy(); + +// Return the unique ID assigned to the AsyncResource instance. +asyncResource.asyncId(); + +// Return the trigger ID for the AsyncResource instance. +asyncResource.triggerAsyncId(); +``` + +```cjs const { AsyncResource, executionAsyncId } = require('async_hooks'); // AsyncResource() is meant to be extended. Instantiating a @@ -446,7 +510,14 @@ database connection pools, can follow a similar model. Assuming that the task is adding two numbers, using a file named `task_processor.js` with the following content: -```js +```mjs +import { parentPort } from 'worker_threads'; +parentPort.on('message', (task) => { + parentPort.postMessage(task.a + task.b); +}); +``` + +```cjs const { parentPort } = require('worker_threads'); parentPort.on('message', (task) => { parentPort.postMessage(task.a + task.b); @@ -455,7 +526,95 @@ parentPort.on('message', (task) => { a Worker pool around it could use the following structure: -```js +```mjs +import { AsyncResource } from 'async_hooks'; +import { EventEmitter } from 'events'; +import path from 'path'; +import { Worker } from 'worker_threads'; + +const kTaskInfo = Symbol('kTaskInfo'); +const kWorkerFreedEvent = Symbol('kWorkerFreedEvent'); + +class WorkerPoolTaskInfo extends AsyncResource { + constructor(callback) { + super('WorkerPoolTaskInfo'); + this.callback = callback; + } + + done(err, result) { + this.runInAsyncScope(this.callback, null, err, result); + this.emitDestroy(); // `TaskInfo`s are used only once. + } +} + +export default class WorkerPool extends EventEmitter { + constructor(numThreads) { + super(); + this.numThreads = numThreads; + this.workers = []; + this.freeWorkers = []; + this.tasks = []; + + for (let i = 0; i < numThreads; i++) + this.addNewWorker(); + + // Any time the kWorkerFreedEvent is emitted, dispatch + // the next task pending in the queue, if any. + this.on(kWorkerFreedEvent, () => { + if (this.tasks.length > 0) { + const { task, callback } = this.tasks.shift(); + this.runTask(task, callback); + } + }); + } + + addNewWorker() { + const worker = new Worker(new URL('task_processer.js', import.meta.url)); + worker.on('message', (result) => { + // In case of success: Call the callback that was passed to `runTask`, + // remove the `TaskInfo` associated with the Worker, and mark it as free + // again. + worker[kTaskInfo].done(null, result); + worker[kTaskInfo] = null; + this.freeWorkers.push(worker); + this.emit(kWorkerFreedEvent); + }); + worker.on('error', (err) => { + // In case of an uncaught exception: Call the callback that was passed to + // `runTask` with the error. + if (worker[kTaskInfo]) + worker[kTaskInfo].done(err, null); + else + this.emit('error', err); + // Remove the worker from the list and start a new Worker to replace the + // current one. + this.workers.splice(this.workers.indexOf(worker), 1); + this.addNewWorker(); + }); + this.workers.push(worker); + this.freeWorkers.push(worker); + this.emit(kWorkerFreedEvent); + } + + runTask(task, callback) { + if (this.freeWorkers.length === 0) { + // No free threads, wait until a worker thread becomes free. + this.tasks.push({ task, callback }); + return; + } + + const worker = this.freeWorkers.pop(); + worker[kTaskInfo] = new WorkerPoolTaskInfo(callback); + worker.postMessage(task); + } + + close() { + for (const worker of this.workers) worker.terminate(); + } +} +``` + +```cjs const { AsyncResource } = require('async_hooks'); const { EventEmitter } = require('events'); const path = require('path'); @@ -553,7 +712,23 @@ were scheduled. This pool could be used as follows: -```js +```mjs +import WorkerPool from './worker_pool.js'; +import os from 'os'; + +const pool = new WorkerPool(os.cpus().length); + +let finished = 0; +for (let i = 0; i < 10; i++) { + pool.runTask({ a: 42, b: 100 }, (err, result) => { + console.log(i, err, result); + if (++finished === 10) + pool.close(); + }); +} +``` + +```cjs const WorkerPool = require('./worker_pool.js'); const os = require('os'); @@ -579,7 +754,22 @@ The following example shows how to use the `AsyncResource` class to properly associate an event listener with the correct execution context. The same approach can be applied to a [`Stream`][] or a similar event-driven class. -```js +```mjs +import { createServer } from 'http'; +import { AsyncResource, executionAsyncId } from 'async_hooks'; + +const server = createServer((req, res) => { + req.on('close', AsyncResource.bind(() => { + // Execution context is bound to the current outer scope. + })); + req.on('close', () => { + // Execution context is bound to the scope that caused 'close' to emit. + }); + res.end(); +}).listen(3000); +``` + +```cjs const { createServer } = require('http'); const { AsyncResource, executionAsyncId } = require('async_hooks'); @@ -593,6 +783,7 @@ const server = createServer((req, res) => { res.end(); }).listen(3000); ``` + [`AsyncResource`]: #async_context_class_asyncresource [`EventEmitter`]: events.md#events_class_eventemitter [`Stream`]: stream.md#stream_stream diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index f6805102fdf050..ea66f495fb1723 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -9,7 +9,11 @@ The `async_hooks` module provides an API to track asynchronous resources. It can be accessed using: -```js +```mjs +import async_hooks from 'async_hooks'; +``` + +```cjs const async_hooks = require('async_hooks'); ``` @@ -29,7 +33,55 @@ interface, and each thread will use a new set of async IDs. Following is a simple overview of the public API. -```js +```mjs +import async_hooks from 'async_hooks'; + +// Return the ID of the current execution context. +const eid = async_hooks.executionAsyncId(); + +// Return the ID of the handle responsible for triggering the callback of the +// current execution scope to call. +const tid = async_hooks.triggerAsyncId(); + +// Create a new AsyncHook instance. All of these callbacks are optional. +const asyncHook = + async_hooks.createHook({ init, before, after, destroy, promiseResolve }); + +// Allow callbacks of this AsyncHook instance to call. This is not an implicit +// action after running the constructor, and must be explicitly run to begin +// executing callbacks. +asyncHook.enable(); + +// Disable listening for new asynchronous events. +asyncHook.disable(); + +// +// The following are the callbacks that can be passed to createHook(). +// + +// init is called during object construction. The resource may not have +// completed construction when this callback runs, therefore all fields of the +// resource referenced by "asyncId" may not have been populated. +function init(asyncId, type, triggerAsyncId, resource) { } + +// Before is called just before the resource's callback is called. It can be +// called 0-N times for handles (such as TCPWrap), and will be called exactly 1 +// time for requests (such as FSReqCallback). +function before(asyncId) { } + +// After is called just after the resource's callback has finished. +function after(asyncId) { } + +// Destroy is called when the resource is destroyed. +function destroy(asyncId) { } + +// promiseResolve is called only for promise resources, when the +// `resolve` function passed to the `Promise` constructor is invoked +// (either directly or through other means of resolving a promise). +function promiseResolve(asyncId) { } +``` + +```cjs const async_hooks = require('async_hooks'); // Return the ID of the current execution context. @@ -102,7 +154,16 @@ be tracked, then only the `destroy` callback needs to be passed. The specifics of all functions that can be passed to `callbacks` is in the [Hook Callbacks][] section. -```js +```mjs +import { createHook } from 'async_hooks'; + +const asyncHook = createHook({ + init(asyncId, type, triggerAsyncId, resource) { }, + destroy(asyncId) { } +}); +``` + +```cjs const async_hooks = require('async_hooks'); const asyncHook = async_hooks.createHook({ @@ -158,7 +219,17 @@ synchronous logging operation such as `fs.writeFileSync(file, msg, flag)`. This will print to the file and will not invoke AsyncHooks recursively because it is synchronous. -```js +```mjs +import { writeFileSync } from 'fs'; +import { format } from 'util'; + +function debug(...args) { + // Use a function like this one when debugging inside an AsyncHooks callback + writeFileSync('log.out', `${format(...args)}\n`, { flag: 'a' }); +} +``` + +```cjs const fs = require('fs'); const util = require('util'); @@ -189,7 +260,13 @@ provided, enabling is a no-op. The `AsyncHook` instance is disabled by default. If the `AsyncHook` instance should be enabled immediately after creation, the following pattern can be used. -```js +```mjs +import { createHook } from 'async_hooks'; + +const hook = createHook(callbacks).enable(); +``` + +```cjs const async_hooks = require('async_hooks'); const hook = async_hooks.createHook(callbacks).enable(); @@ -229,7 +306,15 @@ This behavior can be observed by doing something like opening a resource then closing it before the resource can be used. The following snippet demonstrates this. -```js +```mjs +import { createServer } from 'net'; + +createServer().listen(function() { this.close(); }); +// OR +clearTimeout(setTimeout(() => {}, 10)); +``` + +```cjs require('net').createServer().listen(function() { this.close(); }); // OR clearTimeout(setTimeout(() => {}, 10)); @@ -270,12 +355,31 @@ created, while `triggerAsyncId` shows *why* a resource was created. The following is a simple demonstration of `triggerAsyncId`: -```js -const { fd } = process.stdout; +```mjs +import { createHook, executionASyncId } from 'async_hooks'; +import { stdout } from 'process'; +import net from 'net'; -async_hooks.createHook({ +createHook({ init(asyncId, type, triggerAsyncId) { - const eid = async_hooks.executionAsyncId(); + const eid = executionAsyncId(); + fs.writeSync( + stdout.fd, + `${type}(${asyncId}): trigger: ${triggerAsyncId} execution: ${eid}\n`); + } +}).enable(); + +net.createServer((conn) => {}).listen(8080); +``` + +```cjs +const { createHook, executionAsyncId } = require('async_hooks'); +const { fd } = require('process').stdout; +const net = require('net'); + +createHook({ + init(asyncId, type, triggerAsyncId) { + const eid = executionAsyncId(); fs.writeSync( fd, `${type}(${asyncId}): trigger: ${triggerAsyncId} execution: ${eid}\n`); @@ -506,7 +610,17 @@ Using `executionAsyncResource()` in the top-level execution context will return an empty object as there is no handle or request object to use, but having an object representing the top-level can be helpful. -```js +```mjs +import { open } from 'fs'; +import { executionAsyncId, executionAsyncResource } from 'async_hooks'; + +console.log(executionAsyncId(), executionAsyncResource()); // 1 {} +open(new URL(import.meta.url), 'r', (err, fd) => { + console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap +}); +``` + +```cjs const { open } = require('fs'); const { executionAsyncId, executionAsyncResource } = require('async_hooks'); @@ -519,7 +633,33 @@ open(__filename, 'r', (err, fd) => { This can be used to implement continuation local storage without the use of a tracking `Map` to store the metadata: -```js +```mjs +import { createServer } from 'http'; +import { + executionAsyncId, + executionAsyncResource, + createHook, +} from 'async_hooks'; +const sym = Symbol('state'); // Private symbol to avoid pollution + +createHook({ + init(asyncId, type, triggerAsyncId, resource) { + const cr = executionAsyncResource(); + if (cr) { + resource[sym] = cr[sym]; + } + } +}).enable(); + +const server = createServer((req, res) => { + executionAsyncResource()[sym] = { state: req.url }; + setTimeout(function() { + res.end(JSON.stringify(executionAsyncResource()[sym])); + }, 100); +}).listen(3000); +``` + +```cjs const { createServer } = require('http'); const { executionAsyncId, @@ -558,7 +698,16 @@ changes: * Returns: {number} The `asyncId` of the current execution context. Useful to track when something calls. -```js +```mjs +import { executionAsyncId } from 'async_hooks'; + +console.log(executionAsyncId()); // 1 - bootstrap +fs.open(path, 'r', (err, fd) => { + console.log(executionAsyncId()); // 6 - open() +}); +``` + +```cjs const async_hooks = require('async_hooks'); console.log(async_hooks.executionAsyncId()); // 1 - bootstrap @@ -616,10 +765,21 @@ expensive nature of the [promise introspection API][PromiseHooks] provided by V8. This means that programs using promises or `async`/`await` will not get correct execution and trigger ids for promise callback contexts by default. -```js -const ah = require('async_hooks'); +```mjs +import { executionAsyncId, triggerAsyncId } from 'async_hooks'; + +Promise.resolve(1729).then(() => { + console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`); +}); +// produces: +// eid 1 tid 0 +``` + +```cjs +const { executionAsyncId, triggerAsyncId } = require('async_hooks'); + Promise.resolve(1729).then(() => { - console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`); + console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`); }); // produces: // eid 1 tid 0 @@ -633,11 +793,22 @@ the resource that caused (triggered) the `then()` callback to be executed. Installing async hooks via `async_hooks.createHook` enables promise execution tracking: -```js -const ah = require('async_hooks'); -ah.createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled. +```mjs +import { createHook, executionAsyncId, triggerAsyncId } from 'async_hooks'; +createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled. +Promise.resolve(1729).then(() => { + console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`); +}); +// produces: +// eid 7 tid 6 +``` + +```cjs +const { createHook, exectionAsyncId, triggerAsyncId } = require('async_hooks'); + +createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled. Promise.resolve(1729).then(() => { - console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`); + console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`); }); // produces: // eid 7 tid 6 diff --git a/doc/api/buffer.md b/doc/api/buffer.md index dd965bbf226194..bd6057f39999ec 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -13,10 +13,45 @@ The `Buffer` class is a subclass of JavaScript's [`Uint8Array`][] class and extends it with methods that cover additional use cases. Node.js APIs accept plain [`Uint8Array`][]s wherever `Buffer`s are supported as well. -The `Buffer` class is within the global scope, making it unlikely that one -would need to ever use `require('buffer').Buffer`. +While the `Buffer` class is available within the global scope, it is still +recommended to explicitly reference it via an import or require statement. + +```mjs +import { Buffer } from 'buffer'; + +// Creates a zero-filled Buffer of length 10. +const buf1 = Buffer.alloc(10); + +// Creates a Buffer of length 10, +// filled with bytes which all have the value `1`. +const buf2 = Buffer.alloc(10, 1); + +// Creates an uninitialized buffer of length 10. +// This is faster than calling Buffer.alloc() but the returned +// Buffer instance might contain old data that needs to be +// overwritten using fill(), write(), or other functions that fill the Buffer's +// contents. +const buf3 = Buffer.allocUnsafe(10); + +// Creates a Buffer containing the bytes [1, 2, 3]. +const buf4 = Buffer.from([1, 2, 3]); + +// Creates a Buffer containing the bytes [1, 1, 1, 1] – the entries +// are all truncated using `(value & 255)` to fit into the range 0–255. +const buf5 = Buffer.from([257, 257.5, -255, '1']); + +// Creates a Buffer containing the UTF-8-encoded bytes for the string 'tést': +// [0x74, 0xc3, 0xa9, 0x73, 0x74] (in hexadecimal notation) +// [116, 195, 169, 115, 116] (in decimal notation) +const buf6 = Buffer.from('tést'); + +// Creates a Buffer containing the Latin-1 bytes [0x74, 0xe9, 0x73, 0x74]. +const buf7 = Buffer.from('tést', 'latin1'); +``` + +```cjs +const { Buffer } = require('buffer'); -```js // Creates a zero-filled Buffer of length 10. const buf1 = Buffer.alloc(10); @@ -65,7 +100,25 @@ When converting between `Buffer`s and strings, a character encoding may be specified. If no character encoding is specified, UTF-8 will be used as the default. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('hello world', 'utf8'); + +console.log(buf.toString('hex')); +// Prints: 68656c6c6f20776f726c64 +console.log(buf.toString('base64')); +// Prints: aGVsbG8gd29ybGQ= + +console.log(Buffer.from('fhqwhgads', 'utf8')); +// Prints: +console.log(Buffer.from('fhqwhgads', 'utf16le')); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('hello world', 'utf8'); console.log(buf.toString('hex')); @@ -142,7 +195,23 @@ The following legacy character encodings are also supported: of UTF-16 that did not support characters that had code points larger than U+FFFF. In Node.js, these code points are always supported. -```js +```mjs +import { Buffer } from 'buffer'; + +Buffer.from('1ag', 'hex'); +// Prints , data truncated when first non-hexadecimal value +// ('g') encountered. + +Buffer.from('1a7g', 'hex'); +// Prints , data truncated when data ends in single digit ('7'). + +Buffer.from('1634', 'hex'); +// Prints , all data represented. +``` + +```cjs +const { Buffer } = require('buffer'); + Buffer.from('1ag', 'hex'); // Prints , data truncated when first non-hexadecimal value // ('g') encountered. @@ -191,7 +260,20 @@ There are two ways to create new [`TypedArray`][] instances from a `Buffer`: contents, interpreted as an array of integers, and not as a byte sequence of the target type. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, 2, 3, 4]); +const uint32array = new Uint32Array(buf); + +console.log(uint32array); + +// Prints: Uint32Array(4) [ 1, 2, 3, 4 ] +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, 2, 3, 4]); const uint32array = new Uint32Array(buf); @@ -203,7 +285,23 @@ console.log(uint32array); * Passing the `Buffer`s underlying [`ArrayBuffer`][] will create a [`TypedArray`][] that shares its memory with the `Buffer`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('hello', 'utf16le'); +const uint16array = new Uint16Array( + buf.buffer, + buf.byteOffset, + buf.length / Uint16Array.BYTES_PER_ELEMENT); + +console.log(uint16array); + +// Prints: Uint16Array(5) [ 104, 101, 108, 108, 111 ] +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('hello', 'utf16le'); const uint16array = new Uint16Array( buf.buffer, @@ -220,7 +318,36 @@ memory as a [`TypedArray`][] instance by using the `TypedArray` object’s `.buffer` property in the same way. [`Buffer.from()`][`Buffer.from(arrayBuf)`] behaves like `new Uint8Array()` in this context. -```js +```mjs +import { Buffer } from 'buffer'; + +const arr = new Uint16Array(2); + +arr[0] = 5000; +arr[1] = 4000; + +// Copies the contents of `arr`. +const buf1 = Buffer.from(arr); + +// Shares memory with `arr`. +const buf2 = Buffer.from(arr.buffer); + +console.log(buf1); +// Prints: +console.log(buf2); +// Prints: + +arr[1] = 6000; + +console.log(buf1); +// Prints: +console.log(buf2); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const arr = new Uint16Array(2); arr[0] = 5000; @@ -249,7 +376,19 @@ When creating a `Buffer` using a [`TypedArray`][]'s `.buffer`, it is possible to use only a portion of the underlying [`ArrayBuffer`][] by passing in `byteOffset` and `length` parameters. -```js +```mjs +import { Buffer } from 'buffer'; + +const arr = new Uint16Array(20); +const buf = Buffer.from(arr.buffer, 0, 16); + +console.log(buf.length); +// Prints: 16 +``` + +```cjs +const { Buffer } = require('buffer'); + const arr = new Uint16Array(20); const buf = Buffer.from(arr.buffer, 0, 16); @@ -276,7 +415,23 @@ function: `Buffer` instances can be iterated over using `for..of` syntax: -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, 2, 3]); + +for (const b of buf) { + console.log(b); +} +// Prints: +// 1 +// 2 +// 3 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, 2, 3]); for (const b of buf) { @@ -378,11 +533,39 @@ destinations without transferring or immediately copying the data. The data contained by the `Blob` is copied only when the `arrayBuffer()` or `text()` methods are called. -```js -const { Blob } = require('buffer'); +```mjs +import { Blob, Buffer } from 'buffer'; +import { setTimeout as delay } from 'timers/promises'; + const blob = new Blob(['hello there']); + +const mc1 = new MessageChannel(); +const mc2 = new MessageChannel(); + +mc1.port1.onmessage = async ({ data }) => { + console.log(await data.arrayBuffer()); + mc1.port1.close(); +}; + +mc2.port1.onmessage = async ({ data }) => { + await delay(1000); + console.log(await data.arrayBuffer()); + mc2.port1.close(); +}; + +mc1.port2.postMessage(blob); +mc2.port2.postMessage(blob); + +// The Blob is still usable after posting. +data.text().then(console.log); +``` + +```cjs +const { Blob, Buffer } = require('buffer'); const { setTimeout: delay } = require('timers/promises'); +const blob = new Blob(['hello there']); + const mc1 = new MessageChannel(); const mc2 = new MessageChannel(); @@ -440,7 +623,18 @@ changes: Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the `Buffer` will be zero-filled. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.alloc(5); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.alloc(5); console.log(buf); @@ -454,7 +648,18 @@ is thrown. If `fill` is specified, the allocated `Buffer` will be initialized by calling [`buf.fill(fill)`][`buf.fill()`]. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.alloc(5, 'a'); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.alloc(5, 'a'); console.log(buf); @@ -464,7 +669,18 @@ console.log(buf); If both `fill` and `encoding` are specified, the allocated `Buffer` will be initialized by calling [`buf.fill(fill, encoding)`][`buf.fill()`]. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); console.log(buf); @@ -502,7 +718,23 @@ initialized*. The contents of the newly created `Buffer` are unknown and *may contain sensitive data*. Use [`Buffer.alloc()`][] instead to initialize `Buffer` instances with zeroes. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(10); + +console.log(buf); +// Prints (contents may vary): + +buf.fill(0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(10); console.log(buf); @@ -564,7 +796,29 @@ memory from a pool for an indeterminate amount of time, it may be appropriate to create an un-pooled `Buffer` instance using `Buffer.allocUnsafeSlow()` and then copying out the relevant bits. -```js +```mjs +import { Buffer } from 'buffer'; + +// Need to keep around a few small chunks of memory. +const store = []; + +socket.on('readable', () => { + let data; + while (null !== (data = readable.read())) { + // Allocate for retained data. + const sb = Buffer.allocUnsafeSlow(10); + + // Copy the data into the new allocation. + data.copy(sb, 0, 0, 10); + + store.push(sb); + } +}); +``` + +```cjs +const { Buffer } = require('buffer'); + // Need to keep around a few small chunks of memory. const store = []; @@ -612,7 +866,19 @@ For strings that contain non-base64/hex-encoded data (e.g. whitespace), the return value might be greater than the length of a `Buffer` created from the string. -```js +```mjs +import { Buffer } from 'buffer'; + +const str = '\u00bd + \u00bc = \u00be'; + +console.log(`${str}: ${str.length} characters, ` + + `${Buffer.byteLength(str, 'utf8')} bytes`); +// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes +``` + +```cjs +const { Buffer } = require('buffer'); + const str = '\u00bd + \u00bc = \u00be'; console.log(`${str}: ${str.length} characters, ` + @@ -642,7 +908,21 @@ Compares `buf1` to `buf2`, typically for the purpose of sorting arrays of `Buffer` instances. This is equivalent to calling [`buf1.compare(buf2)`][`buf.compare()`]. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from('1234'); +const buf2 = Buffer.from('0123'); +const arr = [buf1, buf2]; + +console.log(arr.sort(Buffer.compare)); +// Prints: [ , ] +// (This result is equal to: [buf2, buf1].) +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from('1234'); const buf2 = Buffer.from('0123'); const arr = [buf1, buf2]; @@ -680,7 +960,30 @@ If `totalLength` is provided, it is coerced to an unsigned integer. If the combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is truncated to `totalLength`. -```js +```mjs +import { Buffer } from 'buffer'; + +// Create a single `Buffer` from a list of three `Buffer` instances. + +const buf1 = Buffer.alloc(10); +const buf2 = Buffer.alloc(14); +const buf3 = Buffer.alloc(18); +const totalLength = buf1.length + buf2.length + buf3.length; + +console.log(totalLength); +// Prints: 42 + +const bufA = Buffer.concat([buf1, buf2, buf3], totalLength); + +console.log(bufA); +// Prints: +console.log(bufA.length); +// Prints: 42 +``` + +```cjs +const { Buffer } = require('buffer'); + // Create a single `Buffer` from a list of three `Buffer` instances. const buf1 = Buffer.alloc(10); @@ -712,15 +1015,24 @@ added: v5.10.0 Allocates a new `Buffer` using an `array` of bytes in the range `0` – `255`. Array entries outside that range will be truncated to fit into it. -```js +```mjs +import { Buffer } from 'buffer'; + // Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'. const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); ``` -A `TypeError` will be thrown if `array` is not an `Array` or another type -appropriate for `Buffer.from()` variants. +```cjs +const { Buffer } = require('buffer'); -`Buffer.from(array)` and [`Buffer.from(string)`][] may also use the internal +// Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'. +const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); +``` + +A `TypeError` will be thrown if `array` is not an `Array` or another type +appropriate for `Buffer.from()` variants. + +`Buffer.from(array)` and [`Buffer.from(string)`][] may also use the internal `Buffer` pool like [`Buffer.allocUnsafe()`][] does. ### Static method: `Buffer.from(arrayBuffer[, byteOffset[, length]])` @@ -740,7 +1052,30 @@ memory. For example, when passed a reference to the `.buffer` property of a [`TypedArray`][] instance, the newly created `Buffer` will share the same allocated memory as the [`TypedArray`][]'s underlying `ArrayBuffer`. -```js +```mjs +import { Buffer } from 'buffer'; + +const arr = new Uint16Array(2); + +arr[0] = 5000; +arr[1] = 4000; + +// Shares memory with `arr`. +const buf = Buffer.from(arr.buffer); + +console.log(buf); +// Prints: + +// Changing the original Uint16Array changes the Buffer also. +arr[1] = 6000; + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const arr = new Uint16Array(2); arr[0] = 5000; @@ -762,7 +1097,19 @@ console.log(buf); The optional `byteOffset` and `length` arguments specify a memory range within the `arrayBuffer` that will be shared by the `Buffer`. -```js +```mjs +import { Buffer } from 'buffer'; + +const ab = new ArrayBuffer(10); +const buf = Buffer.from(ab, 0, 2); + +console.log(buf.length); +// Prints: 2 +``` + +```cjs +const { Buffer } = require('buffer'); + const ab = new ArrayBuffer(10); const buf = Buffer.from(ab, 0, 2); @@ -779,7 +1126,21 @@ of memory that extends beyond the bounds of a `TypedArray` view. A new `Buffer` created using the `buffer` property of a `TypedArray` may extend beyond the range of the `TypedArray`: -```js +```mjs +import { Buffer } from 'buffer'; + +const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements +const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements +console.log(arrA.buffer === arrB.buffer); // true + +const buf = Buffer.from(arrB.buffer); +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements console.log(arrA.buffer === arrB.buffer); // true @@ -799,7 +1160,23 @@ added: v5.10.0 Copies the passed `buffer` data onto a new `Buffer` instance. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from('buffer'); +const buf2 = Buffer.from(buf1); + +buf1[0] = 0x61; + +console.log(buf1.toString()); +// Prints: auffer +console.log(buf2.toString()); +// Prints: buffer +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from('buffer'); const buf2 = Buffer.from(buf1); @@ -826,7 +1203,16 @@ added: v8.2.0 For objects whose `valueOf()` function returns a value not strictly equal to `object`, returns `Buffer.from(object.valueOf(), offsetOrEncoding, length)`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from(new String('this is a test')); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from(new String('this is a test')); // Prints: ``` @@ -834,7 +1220,22 @@ const buf = Buffer.from(new String('this is a test')); For objects that support `Symbol.toPrimitive`, returns `Buffer.from(object[Symbol.toPrimitive]('string'), offsetOrEncoding)`. -```js +```mjs +import { Buffer } from 'buffer'; + +class Foo { + [Symbol.toPrimitive]() { + return 'this is a test'; + } +} + +const buf = Buffer.from(new Foo(), 'utf8'); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + class Foo { [Symbol.toPrimitive]() { return 'this is a test'; @@ -859,7 +1260,23 @@ added: v5.10.0 Creates a new `Buffer` containing `string`. The `encoding` parameter identifies the character encoding to be used when converting `string` into bytes. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from('this is a tést'); +const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); + +console.log(buf1.toString()); +// Prints: this is a tést +console.log(buf2.toString()); +// Prints: this is a tést +console.log(buf1.toString('latin1')); +// Prints: this is a tést +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from('this is a tést'); const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); @@ -884,7 +1301,19 @@ added: v0.1.101 Returns `true` if `obj` is a `Buffer`, `false` otherwise. -```js +```mjs +import { Buffer } from 'buffer'; + +Buffer.isBuffer(Buffer.alloc(10)); // true +Buffer.isBuffer(Buffer.from('foo')); // true +Buffer.isBuffer('a string'); // false +Buffer.isBuffer([]); // false +Buffer.isBuffer(new Uint8Array(1024)); // false +``` + +```cjs +const { Buffer } = require('buffer'); + Buffer.isBuffer(Buffer.alloc(10)); // true Buffer.isBuffer(Buffer.from('foo')); // true Buffer.isBuffer('a string'); // false @@ -903,7 +1332,25 @@ added: v0.9.1 Returns `true` if `encoding` is the name of a supported character encoding, or `false` otherwise. -```js +```mjs +import { Buffer } from 'buffer'; + +console.log(Buffer.isEncoding('utf8')); +// Prints: true + +console.log(Buffer.isEncoding('hex')); +// Prints: true + +console.log(Buffer.isEncoding('utf/8')); +// Prints: false + +console.log(Buffer.isEncoding('')); +// Prints: false +``` + +```cjs +const { Buffer } = require('buffer'); + console.log(Buffer.isEncoding('utf8')); // Prints: true @@ -941,7 +1388,27 @@ access is the same as `Uint8Array`. In other words, `buf[index]` returns `buf[index] = value` does not modify the buffer if `index` is negative or `>= buf.length`. -```js +```mjs +import { Buffer } from 'buffer'; + +// Copy an ASCII string into a `Buffer` one byte at a time. +// (This only works for ASCII-only strings. In general, one should use +// `Buffer.from()` to perform this conversion.) + +const str = 'Node.js'; +const buf = Buffer.allocUnsafe(str.length); + +for (let i = 0; i < str.length; i++) { + buf[i] = str.charCodeAt(i); +} + +console.log(buf.toString('utf8')); +// Prints: Node.js +``` + +```cjs +const { Buffer } = require('buffer'); + // Copy an ASCII string into a `Buffer` one byte at a time. // (This only works for ASCII-only strings. In general, one should use // `Buffer.from()` to perform this conversion.) @@ -965,7 +1432,19 @@ console.log(buf.toString('utf8')); This `ArrayBuffer` is not guaranteed to correspond exactly to the original `Buffer`. See the notes on `buf.byteOffset` for details. -```js +```mjs +import { Buffer } from 'buffer'; + +const arrayBuffer = new ArrayBuffer(16); +const buffer = Buffer.from(arrayBuffer); + +console.log(buffer.buffer === arrayBuffer); +// Prints: true +``` + +```cjs +const { Buffer } = require('buffer'); + const arrayBuffer = new ArrayBuffer(16); const buffer = Buffer.from(arrayBuffer); @@ -988,7 +1467,21 @@ to the `Buffer` object itself. A common issue when creating a `TypedArray` object that shares its memory with a `Buffer` is that in this case one needs to specify the `byteOffset` correctly: -```js +```mjs +import { Buffer } from 'buffer'; + +// Create a buffer smaller than `Buffer.poolSize`. +const nodeBuffer = new Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + +// When casting the Node.js Buffer to an Int8Array, use the byteOffset +// to refer only to the part of `nodeBuffer.buffer` that contains the memory +// for `nodeBuffer`. +new Int8Array(nodeBuffer.buffer, nodeBuffer.byteOffset, nodeBuffer.length); +``` + +```cjs +const { Buffer } = require('buffer'); + // Create a buffer smaller than `Buffer.poolSize`. const nodeBuffer = new Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); @@ -1030,7 +1523,31 @@ Comparison is based on the actual sequence of bytes in each `Buffer`. * `1` is returned if `target` should come *before* `buf` when sorted. * `-1` is returned if `target` should come *after* `buf` when sorted. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from('ABC'); +const buf2 = Buffer.from('BCD'); +const buf3 = Buffer.from('ABCD'); + +console.log(buf1.compare(buf1)); +// Prints: 0 +console.log(buf1.compare(buf2)); +// Prints: -1 +console.log(buf1.compare(buf3)); +// Prints: -1 +console.log(buf2.compare(buf1)); +// Prints: 1 +console.log(buf2.compare(buf3)); +// Prints: 1 +console.log([buf1, buf2, buf3].sort(Buffer.compare)); +// Prints: [ , , ] +// (This result is equal to: [buf1, buf3, buf2].) +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('BCD'); const buf3 = Buffer.from('ABCD'); @@ -1054,7 +1571,23 @@ The optional `targetStart`, `targetEnd`, `sourceStart`, and `sourceEnd` arguments can be used to limit the comparison to specific ranges within `target` and `buf` respectively. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]); +const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]); + +console.log(buf1.compare(buf2, 5, 9, 0, 4)); +// Prints: 0 +console.log(buf1.compare(buf2, 0, 6, 4)); +// Prints: -1 +console.log(buf1.compare(buf2, 5, 6, 5)); +// Prints: 1 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]); const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]); @@ -1090,7 +1623,9 @@ memory region overlaps with `buf`. for all TypedArrays, including Node.js `Buffer`s, although it takes different function arguments. -```js +```mjs +import { Buffer } from 'buffer'; + // Create two `Buffer` instances. const buf1 = Buffer.allocUnsafe(26); const buf2 = Buffer.allocUnsafe(26).fill('!'); @@ -1109,7 +1644,49 @@ console.log(buf2.toString('ascii', 0, 25)); // Prints: !!!!!!!!qrst!!!!!!!!!!!!! ``` -```js +```cjs +const { Buffer } = require('buffer'); + +// Create two `Buffer` instances. +const buf1 = Buffer.allocUnsafe(26); +const buf2 = Buffer.allocUnsafe(26).fill('!'); + +for (let i = 0; i < 26; i++) { + // 97 is the decimal ASCII value for 'a'. + buf1[i] = i + 97; +} + +// Copy `buf1` bytes 16 through 19 into `buf2` starting at byte 8 of `buf2`. +buf1.copy(buf2, 8, 16, 20); +// This is equivalent to: +// buf2.set(buf1.subarray(16, 20), 8); + +console.log(buf2.toString('ascii', 0, 25)); +// Prints: !!!!!!!!qrst!!!!!!!!!!!!! +``` + +```mjs +import { Buffer } from 'buffer'; + +// Create a `Buffer` and copy data from one region to an overlapping region +// within the same `Buffer`. + +const buf = Buffer.allocUnsafe(26); + +for (let i = 0; i < 26; i++) { + // 97 is the decimal ASCII value for 'a'. + buf[i] = i + 97; +} + +buf.copy(buf, 0, 4, 10); + +console.log(buf.toString()); +// Prints: efghijghijklmnopqrstuvwxyz +``` + +```cjs +const { Buffer } = require('buffer'); + // Create a `Buffer` and copy data from one region to an overlapping region // within the same `Buffer`. @@ -1136,7 +1713,28 @@ added: v1.1.0 Creates and returns an [iterator][] of `[index, byte]` pairs from the contents of `buf`. -```js +```mjs +import { Buffer } from 'buffer'; + +// Log the entire contents of a `Buffer`. + +const buf = Buffer.from('buffer'); + +for (const pair of buf.entries()) { + console.log(pair); +} +// Prints: +// [0, 98] +// [1, 117] +// [2, 102] +// [3, 102] +// [4, 101] +// [5, 114] +``` + +```cjs +const { Buffer } = require('buffer'); + // Log the entire contents of a `Buffer`. const buf = Buffer.from('buffer'); @@ -1170,7 +1768,22 @@ Returns `true` if both `buf` and `otherBuffer` have exactly the same bytes, `false` otherwise. Equivalent to [`buf.compare(otherBuffer) === 0`][`buf.compare()`]. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from('ABC'); +const buf2 = Buffer.from('414243', 'hex'); +const buf3 = Buffer.from('ABCD'); + +console.log(buf1.equals(buf2)); +// Prints: true +console.log(buf1.equals(buf3)); +// Prints: false +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('414243', 'hex'); const buf3 = Buffer.from('ABCD'); @@ -1216,7 +1829,20 @@ changes: Fills `buf` with the specified `value`. If the `offset` and `end` are not given, the entire `buf` will be filled: -```js +```mjs +import { Buffer } from 'buffer'; + +// Fill a `Buffer` with the ASCII character 'h'. + +const b = Buffer.allocUnsafe(50).fill('h'); + +console.log(b.toString()); +// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +``` + +```cjs +const { Buffer } = require('buffer'); + // Fill a `Buffer` with the ASCII character 'h'. const b = Buffer.allocUnsafe(50).fill('h'); @@ -1232,17 +1858,43 @@ filled with `value & 255`. If the final write of a `fill()` operation falls on a multi-byte character, then only the bytes of that character that fit into `buf` are written: -```js +```mjs +import { Buffer } from 'buffer'; + // Fill a `Buffer` with character that takes up two bytes in UTF-8. console.log(Buffer.allocUnsafe(5).fill('\u0222')); // Prints: ``` -If `value` contains invalid characters, it is truncated; if no valid -fill data remains, an exception is thrown: +```cjs +const { Buffer } = require('buffer'); + +// Fill a `Buffer` with character that takes up two bytes in UTF-8. + +console.log(Buffer.allocUnsafe(5).fill('\u0222')); +// Prints: +``` + +If `value` contains invalid characters, it is truncated; if no valid +fill data remains, an exception is thrown: + +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(5); + +console.log(buf.fill('a')); +// Prints: +console.log(buf.fill('aazz', 'hex')); +// Prints: +console.log(buf.fill('zz', 'hex')); +// Throws an exception. +``` + +```cjs +const { Buffer } = require('buffer'); -```js const buf = Buffer.allocUnsafe(5); console.log(buf.fill('a')); @@ -1267,7 +1919,30 @@ added: v5.3.0 Equivalent to [`buf.indexOf() !== -1`][`buf.indexOf()`]. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('this is a buffer'); + +console.log(buf.includes('this')); +// Prints: true +console.log(buf.includes('is')); +// Prints: true +console.log(buf.includes(Buffer.from('a buffer'))); +// Prints: true +console.log(buf.includes(97)); +// Prints: true (97 is the decimal ASCII value for 'a') +console.log(buf.includes(Buffer.from('a buffer example'))); +// Prints: false +console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); +// Prints: true +console.log(buf.includes('this', 4)); +// Prints: false +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('this is a buffer'); console.log(buf.includes('this')); @@ -1319,7 +1994,35 @@ If `value` is: * a number, `value` will be interpreted as an unsigned 8-bit integer value between `0` and `255`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('this is a buffer'); + +console.log(buf.indexOf('this')); +// Prints: 0 +console.log(buf.indexOf('is')); +// Prints: 2 +console.log(buf.indexOf(Buffer.from('a buffer'))); +// Prints: 8 +console.log(buf.indexOf(97)); +// Prints: 8 (97 is the decimal ASCII value for 'a') +console.log(buf.indexOf(Buffer.from('a buffer example'))); +// Prints: -1 +console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8))); +// Prints: 8 + +const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'utf16le'); + +console.log(utf16Buffer.indexOf('\u03a3', 0, 'utf16le')); +// Prints: 4 +console.log(utf16Buffer.indexOf('\u03a3', -4, 'utf16le')); +// Prints: 6 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('this is a buffer'); console.log(buf.indexOf('this')); @@ -1351,7 +2054,27 @@ If `byteOffset` is not a number, it will be coerced to a number. If the result of coercion is `NaN` or `0`, then the entire buffer will be searched. This behavior matches [`String.prototype.indexOf()`][]. -```js +```mjs +import { Buffer } from 'buffer'; + +const b = Buffer.from('abcdef'); + +// Passing a value that's a number, but not a valid byte. +// Prints: 2, equivalent to searching for 99 or 'c'. +console.log(b.indexOf(99.9)); +console.log(b.indexOf(256 + 99)); + +// Passing a byteOffset that coerces to NaN or 0. +// Prints: 1, searching the whole buffer. +console.log(b.indexOf('b', undefined)); +console.log(b.indexOf('b', {})); +console.log(b.indexOf('b', null)); +console.log(b.indexOf('b', [])); +``` + +```cjs +const { Buffer } = require('buffer'); + const b = Buffer.from('abcdef'); // Passing a value that's a number, but not a valid byte. @@ -1380,7 +2103,26 @@ added: v1.1.0 Creates and returns an [iterator][] of `buf` keys (indices). -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('buffer'); + +for (const key of buf.keys()) { + console.log(key); +} +// Prints: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('buffer'); for (const key of buf.keys()) { @@ -1417,7 +2159,37 @@ changes: Identical to [`buf.indexOf()`][], except the last occurrence of `value` is found rather than the first occurrence. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('this buffer is a buffer'); + +console.log(buf.lastIndexOf('this')); +// Prints: 0 +console.log(buf.lastIndexOf('buffer')); +// Prints: 17 +console.log(buf.lastIndexOf(Buffer.from('buffer'))); +// Prints: 17 +console.log(buf.lastIndexOf(97)); +// Prints: 15 (97 is the decimal ASCII value for 'a') +console.log(buf.lastIndexOf(Buffer.from('yolo'))); +// Prints: -1 +console.log(buf.lastIndexOf('buffer', 5)); +// Prints: 5 +console.log(buf.lastIndexOf('buffer', 4)); +// Prints: -1 + +const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'utf16le'); + +console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'utf16le')); +// Prints: 6 +console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'utf16le')); +// Prints: 4 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('this buffer is a buffer'); console.log(buf.lastIndexOf('this')); @@ -1451,7 +2223,30 @@ If `byteOffset` is not a number, it will be coerced to a number. Any arguments that coerce to `NaN`, like `{}` or `undefined`, will search the whole buffer. This behavior matches [`String.prototype.lastIndexOf()`][]. -```js +```mjs +import { Buffer } from 'buffer'; + +const b = Buffer.from('abcdef'); + +// Passing a value that's a number, but not a valid byte. +// Prints: 2, equivalent to searching for 99 or 'c'. +console.log(b.lastIndexOf(99.9)); +console.log(b.lastIndexOf(256 + 99)); + +// Passing a byteOffset that coerces to NaN. +// Prints: 1, searching the whole buffer. +console.log(b.lastIndexOf('b', undefined)); +console.log(b.lastIndexOf('b', {})); + +// Passing a byteOffset that coerces to 0. +// Prints: -1, equivalent to passing 0. +console.log(b.lastIndexOf('b', null)); +console.log(b.lastIndexOf('b', [])); +``` + +```cjs +const { Buffer } = require('buffer'); + const b = Buffer.from('abcdef'); // Passing a value that's a number, but not a valid byte. @@ -1481,7 +2276,25 @@ added: v0.1.90 Returns the number of bytes in `buf`. -```js +```mjs +import { Buffer } from 'buffer'; + +// Create a `Buffer` and write a shorter string to it using UTF-8. + +const buf = Buffer.alloc(1234); + +console.log(buf.length); +// Prints: 1234 + +buf.write('some string', 0, 'utf8'); + +console.log(buf.length); +// Prints: 1234 +``` + +```cjs +const { Buffer } = require('buffer'); + // Create a `Buffer` and write a shorter string to it using UTF-8. const buf = Buffer.alloc(1234); @@ -1559,7 +2372,18 @@ Reads an unsigned, big-endian 64-bit integer from `buf` at the specified This function is also available under the `readBigUint64BE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); + +console.log(buf.readBigUInt64BE(0)); +// Prints: 4294967295n +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); console.log(buf.readBigUInt64BE(0)); @@ -1588,7 +2412,18 @@ Reads an unsigned, little-endian 64-bit integer from `buf` at the specified This function is also available under the `readBigUint64LE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); + +console.log(buf.readBigUInt64LE(0)); +// Prints: 18446744069414584320n +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); console.log(buf.readBigUInt64LE(0)); @@ -1611,7 +2446,18 @@ changes: Reads a 64-bit, big-endian double from `buf` at the specified `offset`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); + +console.log(buf.readDoubleBE(0)); +// Prints: 8.20788039913184e-304 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); console.log(buf.readDoubleBE(0)); @@ -1634,7 +2480,20 @@ changes: Reads a 64-bit, little-endian double from `buf` at the specified `offset`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); + +console.log(buf.readDoubleLE(0)); +// Prints: 5.447603722011605e-270 +console.log(buf.readDoubleLE(1)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); console.log(buf.readDoubleLE(0)); @@ -1659,7 +2518,18 @@ changes: Reads a 32-bit, big-endian float from `buf` at the specified `offset`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, 2, 3, 4]); + +console.log(buf.readFloatBE(0)); +// Prints: 2.387939260590663e-38 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, 2, 3, 4]); console.log(buf.readFloatBE(0)); @@ -1682,7 +2552,20 @@ changes: Reads a 32-bit, little-endian float from `buf` at the specified `offset`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, 2, 3, 4]); + +console.log(buf.readFloatLE(0)); +// Prints: 1.539989614439558e-36 +console.log(buf.readFloatLE(1)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, 2, 3, 4]); console.log(buf.readFloatLE(0)); @@ -1709,7 +2592,22 @@ Reads a signed 8-bit integer from `buf` at the specified `offset`. Integers read from a `Buffer` are interpreted as two's complement signed values. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([-1, 5]); + +console.log(buf.readInt8(0)); +// Prints: -1 +console.log(buf.readInt8(1)); +// Prints: 5 +console.log(buf.readInt8(2)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([-1, 5]); console.log(buf.readInt8(0)); @@ -1738,7 +2636,18 @@ Reads a signed, big-endian 16-bit integer from `buf` at the specified `offset`. Integers read from a `Buffer` are interpreted as two's complement signed values. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0, 5]); + +console.log(buf.readInt16BE(0)); +// Prints: 5 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0, 5]); console.log(buf.readInt16BE(0)); @@ -1764,7 +2673,20 @@ Reads a signed, little-endian 16-bit integer from `buf` at the specified Integers read from a `Buffer` are interpreted as two's complement signed values. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0, 5]); + +console.log(buf.readInt16LE(0)); +// Prints: 1280 +console.log(buf.readInt16LE(1)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0, 5]); console.log(buf.readInt16LE(0)); @@ -1791,7 +2713,18 @@ Reads a signed, big-endian 32-bit integer from `buf` at the specified `offset`. Integers read from a `Buffer` are interpreted as two's complement signed values. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0, 0, 0, 5]); + +console.log(buf.readInt32BE(0)); +// Prints: 5 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0, 0, 0, 5]); console.log(buf.readInt32BE(0)); @@ -1817,7 +2750,20 @@ Reads a signed, little-endian 32-bit integer from `buf` at the specified Integers read from a `Buffer` are interpreted as two's complement signed values. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0, 0, 0, 5]); + +console.log(buf.readInt32LE(0)); +// Prints: 83886080 +console.log(buf.readInt32LE(1)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0, 0, 0, 5]); console.log(buf.readInt32LE(0)); @@ -1846,7 +2792,22 @@ Reads `byteLength` number of bytes from `buf` at the specified `offset` and interprets the result as a big-endian, two's complement signed value supporting up to 48 bits of accuracy. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + +console.log(buf.readIntBE(0, 6).toString(16)); +// Prints: 1234567890ab +console.log(buf.readIntBE(1, 6).toString(16)); +// Throws ERR_OUT_OF_RANGE. +console.log(buf.readIntBE(1, 0).toString(16)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); console.log(buf.readIntBE(0, 6).toString(16)); @@ -1877,7 +2838,18 @@ Reads `byteLength` number of bytes from `buf` at the specified `offset` and interprets the result as a little-endian, two's complement signed value supporting up to 48 bits of accuracy. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + +console.log(buf.readIntLE(0, 6).toString(16)); +// Prints: -546f87a9cbee +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); console.log(buf.readIntLE(0, 6).toString(16)); @@ -1907,7 +2879,22 @@ Reads an unsigned 8-bit integer from `buf` at the specified `offset`. This function is also available under the `readUint8` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([1, -2]); + +console.log(buf.readUInt8(0)); +// Prints: 1 +console.log(buf.readUInt8(1)); +// Prints: 254 +console.log(buf.readUInt8(2)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([1, -2]); console.log(buf.readUInt8(0)); @@ -1942,7 +2929,20 @@ Reads an unsigned, big-endian 16-bit integer from `buf` at the specified This function is also available under the `readUint16BE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56]); + +console.log(buf.readUInt16BE(0).toString(16)); +// Prints: 1234 +console.log(buf.readUInt16BE(1).toString(16)); +// Prints: 3456 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56]); console.log(buf.readUInt16BE(0).toString(16)); @@ -1975,7 +2975,22 @@ Reads an unsigned, little-endian 16-bit integer from `buf` at the specified This function is also available under the `readUint16LE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56]); + +console.log(buf.readUInt16LE(0).toString(16)); +// Prints: 3412 +console.log(buf.readUInt16LE(1).toString(16)); +// Prints: 5634 +console.log(buf.readUInt16LE(2).toString(16)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56]); console.log(buf.readUInt16LE(0).toString(16)); @@ -2010,7 +3025,18 @@ Reads an unsigned, big-endian 32-bit integer from `buf` at the specified This function is also available under the `readUint32BE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); + +console.log(buf.readUInt32BE(0).toString(16)); +// Prints: 12345678 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); console.log(buf.readUInt32BE(0).toString(16)); @@ -2041,7 +3067,20 @@ Reads an unsigned, little-endian 32-bit integer from `buf` at the specified This function is also available under the `readUint32LE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); + +console.log(buf.readUInt32LE(0).toString(16)); +// Prints: 78563412 +console.log(buf.readUInt32LE(1).toString(16)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); console.log(buf.readUInt32LE(0).toString(16)); @@ -2077,7 +3116,20 @@ up to 48 bits of accuracy. This function is also available under the `readUintBE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + +console.log(buf.readUIntBE(0, 6).toString(16)); +// Prints: 1234567890ab +console.log(buf.readUIntBE(1, 6).toString(16)); +// Throws ERR_OUT_OF_RANGE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); console.log(buf.readUIntBE(0, 6).toString(16)); @@ -2113,7 +3165,18 @@ up to 48 bits of accuracy. This function is also available under the `readUintLE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); + +console.log(buf.readUIntLE(0, 6).toString(16)); +// Prints: ab9078563412 +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); console.log(buf.readUIntLE(0, 6).toString(16)); @@ -2141,7 +3204,33 @@ This method is inherited from [`TypedArray.prototype.subarray()`][]. Modifying the new `Buffer` slice will modify the memory in the original `Buffer` because the allocated memory of the two objects overlap. -```js +```mjs +import { Buffer } from 'buffer'; + +// Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte +// from the original `Buffer`. + +const buf1 = Buffer.allocUnsafe(26); + +for (let i = 0; i < 26; i++) { + // 97 is the decimal ASCII value for 'a'. + buf1[i] = i + 97; +} + +const buf2 = buf1.subarray(0, 3); + +console.log(buf2.toString('ascii', 0, buf2.length)); +// Prints: abc + +buf1[0] = 33; + +console.log(buf2.toString('ascii', 0, buf2.length)); +// Prints: !bc +``` + +```cjs +const { Buffer } = require('buffer'); + // Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte // from the original `Buffer`. @@ -2166,7 +3255,27 @@ console.log(buf2.toString('ascii', 0, buf2.length)); Specifying negative indexes causes the slice to be generated relative to the end of `buf` rather than the beginning. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('buffer'); + +console.log(buf.subarray(-6, -1).toString()); +// Prints: buffe +// (Equivalent to buf.subarray(0, 5).) + +console.log(buf.subarray(-6, -2).toString()); +// Prints: buff +// (Equivalent to buf.subarray(0, 4).) + +console.log(buf.subarray(-5, -2).toString()); +// Prints: uff +// (Equivalent to buf.subarray(1, 4).) +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('buffer'); console.log(buf.subarray(-6, -1).toString()); @@ -2212,7 +3321,23 @@ This method is not compatible with the `Uint8Array.prototype.slice()`, which is a superclass of `Buffer`. To copy the slice, use `Uint8Array.prototype.slice()`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('buffer'); + +const copiedBuf = Uint8Array.prototype.slice.call(buf); +copiedBuf[0]++; +console.log(copiedBuf.toString()); +// Prints: cuffer + +console.log(buf.toString()); +// Prints: buffer +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('buffer'); const copiedBuf = Uint8Array.prototype.slice.call(buf); @@ -2235,7 +3360,28 @@ Interprets `buf` as an array of unsigned 16-bit integers and swaps the byte order *in-place*. Throws [`ERR_INVALID_BUFFER_SIZE`][] if [`buf.length`][] is not a multiple of 2. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); + +console.log(buf1); +// Prints: + +buf1.swap16(); + +console.log(buf1); +// Prints: + +const buf2 = Buffer.from([0x1, 0x2, 0x3]); + +buf2.swap16(); +// Throws ERR_INVALID_BUFFER_SIZE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); console.log(buf1); @@ -2255,7 +3401,16 @@ buf2.swap16(); One convenient use of `buf.swap16()` is to perform a fast in-place conversion between UTF-16 little-endian and UTF-16 big-endian: -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('This is little-endian UTF-16', 'utf16le'); +buf.swap16(); // Convert to big-endian UTF-16 text. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from('This is little-endian UTF-16', 'utf16le'); buf.swap16(); // Convert to big-endian UTF-16 text. ``` @@ -2271,7 +3426,28 @@ Interprets `buf` as an array of unsigned 32-bit integers and swaps the byte order *in-place*. Throws [`ERR_INVALID_BUFFER_SIZE`][] if [`buf.length`][] is not a multiple of 4. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); + +console.log(buf1); +// Prints: + +buf1.swap32(); + +console.log(buf1); +// Prints: + +const buf2 = Buffer.from([0x1, 0x2, 0x3]); + +buf2.swap32(); +// Throws ERR_INVALID_BUFFER_SIZE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); console.log(buf1); @@ -2298,7 +3474,28 @@ added: v6.3.0 Interprets `buf` as an array of 64-bit numbers and swaps byte order *in-place*. Throws [`ERR_INVALID_BUFFER_SIZE`][] if [`buf.length`][] is not a multiple of 8. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); + +console.log(buf1); +// Prints: + +buf1.swap64(); + +console.log(buf1); +// Prints: + +const buf2 = Buffer.from([0x1, 0x2, 0x3]); + +buf2.swap64(); +// Throws ERR_INVALID_BUFFER_SIZE. +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); console.log(buf1); @@ -2328,7 +3525,28 @@ this function when stringifying a `Buffer` instance. `Buffer.from()` accepts objects in the format returned from this method. In particular, `Buffer.from(buf.toJSON())` works like `Buffer.from(buf)`. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); +const json = JSON.stringify(buf); + +console.log(json); +// Prints: {"type":"Buffer","data":[1,2,3,4,5]} + +const copy = JSON.parse(json, (key, value) => { + return value && value.type === 'Buffer' ? + Buffer.from(value) : + value; +}); + +console.log(copy); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json = JSON.stringify(buf); @@ -2365,7 +3583,34 @@ then each invalid byte is replaced with the replacement character `U+FFFD`. The maximum length of a string instance (in UTF-16 code units) is available as [`buffer.constants.MAX_STRING_LENGTH`][]. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf1 = Buffer.allocUnsafe(26); + +for (let i = 0; i < 26; i++) { + // 97 is the decimal ASCII value for 'a'. + buf1[i] = i + 97; +} + +console.log(buf1.toString('utf8')); +// Prints: abcdefghijklmnopqrstuvwxyz +console.log(buf1.toString('utf8', 0, 5)); +// Prints: abcde + +const buf2 = Buffer.from('tést'); + +console.log(buf2.toString('hex')); +// Prints: 74c3a97374 +console.log(buf2.toString('utf8', 0, 3)); +// Prints: té +console.log(buf2.toString(undefined, 0, 3)); +// Prints: té +``` + +```cjs +const { Buffer } = require('buffer'); + const buf1 = Buffer.allocUnsafe(26); for (let i = 0; i < 26; i++) { @@ -2395,10 +3640,40 @@ added: v1.1.0 * Returns: {Iterator} -Creates and returns an [iterator][] for `buf` values (bytes). This function is -called automatically when a `Buffer` is used in a `for..of` statement. +Creates and returns an [iterator][] for `buf` values (bytes). This function is +called automatically when a `Buffer` is used in a `for..of` statement. + +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.from('buffer'); + +for (const value of buf.values()) { + console.log(value); +} +// Prints: +// 98 +// 117 +// 102 +// 102 +// 101 +// 114 + +for (const value of buf) { + console.log(value); +} +// Prints: +// 98 +// 117 +// 102 +// 102 +// 101 +// 114 +``` + +```cjs +const { Buffer } = require('buffer'); -```js const buf = Buffer.from('buffer'); for (const value of buf.values()) { @@ -2442,7 +3717,27 @@ Writes `string` to `buf` at `offset` according to the character encoding in not contain enough space to fit the entire string, only part of `string` will be written. However, partially encoded characters will not be written. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.alloc(256); + +const len = buf.write('\u00bd + \u00bc = \u00be', 0); + +console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); +// Prints: 12 bytes: ½ + ¼ = ¾ + +const buffer = Buffer.alloc(10); + +const length = buffer.write('abcd', 8); + +console.log(`${length} bytes: ${buffer.toString('utf8', 8, 10)}`); +// Prints: 2 bytes : ab +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.alloc(256); const len = buf.write('\u00bd + \u00bc = \u00be', 0); @@ -2474,7 +3769,20 @@ Writes `value` to `buf` at the specified `offset` as big-endian. `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(8); + +buf.writeBigInt64BE(0x0102030405060708n, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(8); buf.writeBigInt64BE(0x0102030405060708n, 0); @@ -2499,7 +3807,20 @@ Writes `value` to `buf` at the specified `offset` as little-endian. `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(8); + +buf.writeBigInt64LE(0x0102030405060708n, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(8); buf.writeBigInt64LE(0x0102030405060708n, 0); @@ -2530,7 +3851,20 @@ Writes `value` to `buf` at the specified `offset` as big-endian. This function is also available under the `writeBigUint64BE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(8); + +buf.writeBigUInt64BE(0xdecafafecacefaden, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(8); buf.writeBigUInt64BE(0xdecafafecacefaden, 0); @@ -2559,7 +3893,20 @@ changes: Writes `value` to `buf` at the specified `offset` as little-endian -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(8); + +buf.writeBigUInt64LE(0xdecafafecacefaden, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(8); buf.writeBigUInt64LE(0xdecafafecacefaden, 0); @@ -2589,7 +3936,20 @@ Writes `value` to `buf` at the specified `offset` as big-endian. The `value` must be a JavaScript number. Behavior is undefined when `value` is anything other than a JavaScript number. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(8); + +buf.writeDoubleBE(123.456, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(8); buf.writeDoubleBE(123.456, 0); @@ -2617,7 +3977,20 @@ Writes `value` to `buf` at the specified `offset` as little-endian. The `value` must be a JavaScript number. Behavior is undefined when `value` is anything other than a JavaScript number. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(8); + +buf.writeDoubleLE(123.456, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(8); buf.writeDoubleLE(123.456, 0); @@ -2644,7 +4017,20 @@ changes: Writes `value` to `buf` at the specified `offset` as big-endian. Behavior is undefined when `value` is anything other than a JavaScript number. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeFloatBE(0xcafebabe, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeFloatBE(0xcafebabe, 0); @@ -2671,7 +4057,20 @@ changes: Writes `value` to `buf` at the specified `offset` as little-endian. Behavior is undefined when `value` is anything other than a JavaScript number. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeFloatLE(0xcafebabe, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeFloatLE(0xcafebabe, 0); @@ -2701,7 +4100,21 @@ a signed 8-bit integer. `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(2); + +buf.writeInt8(2, 0); +buf.writeInt8(-2, 1); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(2); buf.writeInt8(2, 0); @@ -2732,7 +4145,20 @@ anything other than a signed 16-bit integer. The `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(2); + +buf.writeInt16BE(0x0102, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(2); buf.writeInt16BE(0x0102, 0); @@ -2762,7 +4188,20 @@ anything other than a signed 16-bit integer. The `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(2); + +buf.writeInt16LE(0x0304, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(2); buf.writeInt16LE(0x0304, 0); @@ -2792,7 +4231,20 @@ anything other than a signed 32-bit integer. The `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeInt32BE(0x01020304, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeInt32BE(0x01020304, 0); @@ -2822,7 +4274,20 @@ anything other than a signed 32-bit integer. The `value` is interpreted and written as a two's complement signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeInt32LE(0x05060708, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeInt32LE(0x05060708, 0); @@ -2852,7 +4317,20 @@ Writes `byteLength` bytes of `value` to `buf` at the specified `offset` as big-endian. Supports up to 48 bits of accuracy. Behavior is undefined when `value` is anything other than a signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(6); + +buf.writeIntBE(0x1234567890ab, 0, 6); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(6); buf.writeIntBE(0x1234567890ab, 0, 6); @@ -2882,7 +4360,20 @@ Writes `byteLength` bytes of `value` to `buf` at the specified `offset` as little-endian. Supports up to 48 bits of accuracy. Behavior is undefined when `value` is anything other than a signed integer. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(6); + +buf.writeIntLE(0x1234567890ab, 0, 6); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(6); buf.writeIntLE(0x1234567890ab, 0, 6); @@ -2917,7 +4408,23 @@ other than an unsigned 8-bit integer. This function is also available under the `writeUint8` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeUInt8(0x3, 0); +buf.writeUInt8(0x4, 1); +buf.writeUInt8(0x23, 2); +buf.writeUInt8(0x42, 3); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeUInt8(0x3, 0); @@ -2955,7 +4462,21 @@ is anything other than an unsigned 16-bit integer. This function is also available under the `writeUint16BE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeUInt16BE(0xdead, 0); +buf.writeUInt16BE(0xbeef, 2); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeUInt16BE(0xdead, 0); @@ -2991,7 +4512,21 @@ anything other than an unsigned 16-bit integer. This function is also available under the `writeUint16LE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeUInt16LE(0xdead, 0); +buf.writeUInt16LE(0xbeef, 2); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeUInt16LE(0xdead, 0); @@ -3027,7 +4562,20 @@ is anything other than an unsigned 32-bit integer. This function is also available under the `writeUint32BE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeUInt32BE(0xfeedface, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeUInt32BE(0xfeedface, 0); @@ -3062,7 +4610,20 @@ anything other than an unsigned 32-bit integer. This function is also available under the `writeUint32LE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(4); + +buf.writeUInt32LE(0xfeedface, 0); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(4); buf.writeUInt32LE(0xfeedface, 0); @@ -3099,7 +4660,20 @@ when `value` is anything other than an unsigned integer. This function is also available under the `writeUintBE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(6); + +buf.writeUIntBE(0x1234567890ab, 0, 6); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(6); buf.writeUIntBE(0x1234567890ab, 0, 6); @@ -3136,7 +4710,20 @@ when `value` is anything other than an unsigned integer. This function is also available under the `writeUintLE` alias. -```js +```mjs +import { Buffer } from 'buffer'; + +const buf = Buffer.allocUnsafe(6); + +buf.writeUIntLE(0x1234567890ab, 0, 6); + +console.log(buf); +// Prints: +``` + +```cjs +const { Buffer } = require('buffer'); + const buf = Buffer.allocUnsafe(6); buf.writeUIntLE(0x1234567890ab, 0, 6); @@ -3382,10 +4969,18 @@ Encodings supported by `buffer.transcode()` are: `'ascii'`, `'utf8'`, The transcoding process will use substitution characters if a given byte sequence cannot be adequately represented in the target encoding. For instance: -```js -const buffer = require('buffer'); +```mjs +import { Buffer, transcode } from 'buffer'; + +const newBuf = transcode(Buffer.from('€'), 'utf8', 'ascii'); +console.log(newBuf.toString('ascii')); +// Prints: '?' +``` + +```cjs +const { Buffer, transcode } = require('buffer'); -const newBuf = buffer.transcode(Buffer.from('€'), 'utf8', 'ascii'); +const newBuf = transcode(Buffer.from('€'), 'utf8', 'ascii'); console.log(newBuf.toString('ascii')); // Prints: '?' ``` diff --git a/doc/api/cluster.md b/doc/api/cluster.md index d12c1f12d256d8..2b515ab82e3b6b 100644 --- a/doc/api/cluster.md +++ b/doc/api/cluster.md @@ -13,10 +13,42 @@ processes to handle the load. The cluster module allows easy creation of child processes that all share server ports. -```js +```mjs +import cluster from 'cluster'; +import http from 'http'; +import { cpus } from 'os'; +import process from 'process'; + +const numCPUs = cpus().length; + +if (cluster.isPrimary) { + console.log(`Primary ${process.pid} is running`); + + // Fork workers. + for (let i = 0; i < numCPUs; i++) { + cluster.fork(); + } + + cluster.on('exit', (worker, code, signal) => { + console.log(`worker ${worker.process.pid} died`); + }); +} else { + // Workers can share any TCP connection + // In this case it is an HTTP server + http.createServer((req, res) => { + res.writeHead(200); + res.end('hello world\n'); + }).listen(8000); + + console.log(`Worker ${process.pid} started`); +} +``` + +```cjs const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; +const process = require('process'); if (cluster.isPrimary) { console.log(`Primary ${process.pid} is running`); @@ -157,7 +189,24 @@ added: v0.11.2 Similar to the `cluster.on('exit')` event, but specific to this worker. -```js +```mjs +import cluster from 'cluster'; + +const worker = cluster.fork(); +worker.on('exit', (code, signal) => { + if (signal) { + console.log(`worker was killed by signal: ${signal}`); + } else if (code !== 0) { + console.log(`worker exited with error code: ${code}`); + } else { + console.log('worker success!'); + } +}); +``` + +```cjs +const cluster = require('cluster'); + const worker = cluster.fork(); worker.on('exit', (code, signal) => { if (signal) { @@ -179,7 +228,17 @@ added: v0.7.0 Similar to the `cluster.on('listening')` event, but specific to this worker. -```js +```mjs +import cluster from 'cluster'; + +cluster.fork().on('listening', (address) => { + // Worker is listening +}); +``` + +```cjs +const cluster = require('cluster'); + cluster.fork().on('listening', (address) => { // Worker is listening }); @@ -204,9 +263,54 @@ See [`process` event: `'message'`][]. Here is an example using the message system. It keeps a count in the primary process of the number of HTTP requests received by the workers: -```js +```mjs +import cluster from 'cluster'; +import http from 'http'; +import { cpus } from 'os'; +import process from 'process'; + +if (cluster.isPrimary) { + + // Keep track of http requests + let numReqs = 0; + setInterval(() => { + console.log(`numReqs = ${numReqs}`); + }, 1000); + + // Count requests + function messageHandler(msg) { + if (msg.cmd && msg.cmd === 'notifyRequest') { + numReqs += 1; + } + } + + // Start workers and listen for messages containing notifyRequest + const numCPUs = cpus().length; + for (let i = 0; i < numCPUs; i++) { + cluster.fork(); + } + + for (const id in cluster.workers) { + cluster.workers[id].on('message', messageHandler); + } + +} else { + + // Worker processes have a http server. + http.Server((req, res) => { + res.writeHead(200); + res.end('hello world\n'); + + // Notify primary about the request + process.send({ cmd: 'notifyRequest' }); + }).listen(8000); +} +``` + +```cjs const cluster = require('cluster'); const http = require('http'); +const process = require('process'); if (cluster.isPrimary) { @@ -387,10 +491,44 @@ added: v0.11.14 This function returns `true` if the worker's process has terminated (either because of exiting or being signaled). Otherwise, it returns `false`. -```js +```mjs +import cluster from 'cluster'; +import http from 'http'; +import { cpus } from 'os'; +import process from 'process'; + +const numCPUs = cpus().length; + +if (cluster.isPrimary) { + console.log(`Primary ${process.pid} is running`); + + // Fork workers. + for (let i = 0; i < numCPUs; i++) { + cluster.fork(); + } + + cluster.on('fork', (worker) => { + console.log('worker is dead:', worker.isDead()); + }); + + cluster.on('exit', (worker, code, signal) => { + console.log('worker is dead:', worker.isDead()); + }); +} else { + // Workers can share any TCP connection. In this case, it is an HTTP server. + http.createServer((req, res) => { + res.writeHead(200); + res.end(`Current process\n ${process.pid}`); + process.kill(process.pid); + }).listen(8000); +} +``` + +```cjs const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; +const process = require('process'); if (cluster.isPrimary) { console.log(`Primary ${process.pid} is running`); @@ -817,8 +955,25 @@ the `env` passed to [`.fork()`][]. The defaults above apply to the first call only; the defaults for later calls are the current values at the time of `cluster.setupPrimary()` is called. -```js +```mjs +import cluster from 'cluster'; + +cluster.setupPrimary({ + exec: 'worker.js', + args: ['--use', 'https'], + silent: true +}); +cluster.fork(); // https worker +cluster.setupPrimary({ + exec: 'worker.js', + args: ['--use', 'http'] +}); +cluster.fork(); // http worker +``` + +```cjs const cluster = require('cluster'); + cluster.setupPrimary({ exec: 'worker.js', args: ['--use', 'https'], @@ -843,7 +998,19 @@ added: v0.7.0 A reference to the current worker object. Not available in the primary process. -```js +```mjs +import cluster from 'cluster'; + +if (cluster.isPrimary) { + console.log('I am primary'); + cluster.fork(); + cluster.fork(); +} else if (cluster.isWorker) { + console.log(`I am worker #${cluster.worker.id}`); +} +``` + +```cjs const cluster = require('cluster'); if (cluster.isPrimary) { @@ -871,7 +1038,23 @@ _and_ exited. The order between these two events cannot be determined in advance. However, it is guaranteed that the removal from the `cluster.workers` list happens before last `'disconnect'` or `'exit'` event is emitted. -```js +```mjs +import cluster from 'cluster'; + +// Go through all workers +function eachWorker(callback) { + for (const id in cluster.workers) { + callback(cluster.workers[id]); + } +} +eachWorker((worker) => { + worker.send('big announcement to all workers'); +}); +``` + +```cjs +const cluster = require('cluster'); + // Go through all workers function eachWorker(callback) { for (const id in cluster.workers) { diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 8bd28d20b0c6ee..2f42643d440c6d 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -10,7 +10,7 @@ The `crypto` module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions. ```mjs -import { createHmac } from 'crypto'; +const { createHmac } = await import('crypto'); const secret = 'abcdefg'; const hash = createHmac('sha256', secret) @@ -162,7 +162,9 @@ changes: `false` otherwise. ```mjs +import { Buffer } from 'buffer'; const { Certificate } = await import('crypto'); + const spkac = getSpkacSomehow(); console.log(Certificate.verifySpkac(Buffer.from(spkac))); // Prints: true or false @@ -170,6 +172,8 @@ console.log(Certificate.verifySpkac(Buffer.from(spkac))); ```cjs const { Certificate } = require('crypto'); +const { Buffer } = require('buffer'); + const spkac = getSpkacSomehow(); console.log(Certificate.verifySpkac(Buffer.from(spkac))); // Prints: true or false @@ -268,7 +272,9 @@ added: v0.11.8 `false` otherwise. ```mjs +import { Buffer } from 'buffer'; const { Certificate } = await import('crypto'); + const cert = Certificate(); const spkac = getSpkacSomehow(); console.log(cert.verifySpkac(Buffer.from(spkac))); @@ -277,6 +283,8 @@ console.log(cert.verifySpkac(Buffer.from(spkac))); ```cjs const { Certificate } = require('crypto'); +const { Buffer } = require('buffer'); + const cert = Certificate(); const spkac = getSpkacSomehow(); console.log(cert.verifySpkac(Buffer.from(spkac))); @@ -385,7 +393,7 @@ import { const { scrypt, randomFill, - createCipheriv, + createCipheriv } = await import('crypto'); const algorithm = 'aes-192-cbc'; @@ -456,7 +464,7 @@ Example: Using the [`cipher.update()`][] and [`cipher.final()`][] methods: const { scrypt, randomFill, - createCipheriv, + createCipheriv } = await import('crypto'); const algorithm = 'aes-192-cbc'; @@ -626,9 +634,10 @@ directly using the `new` keyword. Example: Using `Decipher` objects as streams: ```mjs +import { Buffer } from 'buffer'; const { scryptSync, - createDecipheriv, + createDecipheriv } = await import('crypto'); const algorithm = 'aes-192-cbc'; @@ -665,6 +674,7 @@ const { scryptSync, createDecipheriv, } = require('crypto'); +const { Buffer } = require('buffer'); const algorithm = 'aes-192-cbc'; const password = 'Password used to generate key'; @@ -702,10 +712,10 @@ import { createReadStream, createWriteStream, } from 'fs'; - +import { Buffer } from 'buffer'; const { scryptSync, - createDecipheriv, + createDecipheriv } = await import('crypto'); const algorithm = 'aes-192-cbc'; @@ -728,11 +738,11 @@ const { createReadStream, createWriteStream, } = require('fs'); - const { scryptSync, createDecipheriv, } = require('crypto'); +const { Buffer } = require('buffer'); const algorithm = 'aes-192-cbc'; const password = 'Password used to generate key'; @@ -752,9 +762,10 @@ input.pipe(decipher).pipe(output); Example: Using the [`decipher.update()`][] and [`decipher.final()`][] methods: ```mjs +import { Buffer } from 'buffer'; const { scryptSync, - createDecipheriv, + createDecipheriv } = await import('crypto'); const algorithm = 'aes-192-cbc'; @@ -780,6 +791,7 @@ const { scryptSync, createDecipheriv, } = require('crypto'); +const { Buffer } = require('buffer'); const algorithm = 'aes-192-cbc'; const password = 'Password used to generate key'; @@ -942,7 +954,7 @@ Instances of the `DiffieHellman` class can be created using the import assert from 'assert'; const { - createDiffieHellman, + createDiffieHellman } = await import('crypto'); // Generate Alice's keys... @@ -1159,7 +1171,7 @@ Instances of the `ECDH` class can be created using the import assert from 'assert'; const { - createECDH, + createECDH } = await import('crypto'); // Generate Alice's keys... @@ -1234,7 +1246,7 @@ Example (uncompressing a key): ```mjs const { createECDH, - ECDH, + ECDH } = await import('crypto'); const ecdh = createECDH('secp256k1'); @@ -1400,7 +1412,7 @@ Example (obtaining a shared secret): ```mjs const { createECDH, - createHash, + createHash } = await import('crypto'); const alice = createECDH('secp256k1'); @@ -1473,7 +1485,7 @@ Example: Using `Hash` objects as streams: ```mjs const { - createHash, + createHash } = await import('crypto'); const hash = createHash('sha256'); @@ -1519,36 +1531,31 @@ Example: Using `Hash` and piped streams: ```mjs import { createReadStream } from 'fs'; +import { stdout } from 'process'; +const { createHash } = await import('crypto'); -const { - createHash, -} = await import('crypto'); const hash = createHash('sha256'); const input = createReadStream('test.js'); -input.pipe(hash).setEncoding('hex').pipe(process.stdout); +input.pipe(hash).setEncoding('hex').pipe(stdout); ``` ```cjs -const { - createReadStream, -} = require('fs'); - -const { - createHash, -} = require('crypto'); +const { createReadStream } = require('fs'); +const { createHash } = require('crypto'); +const { stdout } = require('process'); const hash = createHash('sha256'); const input = createReadStream('test.js'); -input.pipe(hash).setEncoding('hex').pipe(process.stdout); +input.pipe(hash).setEncoding('hex').pipe(stdout); ``` Example: Using the [`hash.update()`][] and [`hash.digest()`][] methods: ```mjs const { - createHash, + createHash } = await import('crypto'); const hash = createHash('sha256'); @@ -1593,7 +1600,7 @@ its [`hash.digest()`][] method has been called. ```mjs // Calculate a rolling hash. const { - createHash, + createHash } = await import('crypto'); const hash = createHash('sha256'); @@ -1688,7 +1695,7 @@ Example: Using `Hmac` objects as streams: ```mjs const { - createHmac, + createHmac } = await import('crypto'); const hmac = createHmac('sha256', 'a secret'); @@ -1734,37 +1741,37 @@ Example: Using `Hmac` and piped streams: ```mjs import { createReadStream } from 'fs'; - +import { stdout } from 'process'; const { - createHmac, + createHmac } = await import('crypto'); const hmac = createHmac('sha256', 'a secret'); const input = createReadStream('test.js'); -input.pipe(hmac).pipe(process.stdout); +input.pipe(hmac).pipe(stdout); ``` ```cjs const { createReadStream, } = require('fs'); - const { createHmac, } = require('crypto'); +const { stdout } = require('process'); const hmac = createHmac('sha256', 'a secret'); const input = createReadStream('test.js'); -input.pipe(hmac).pipe(process.stdout); +input.pipe(hmac).pipe(stdout); ``` Example: Using the [`hmac.update()`][] and [`hmac.digest()`][] methods: ```mjs const { - createHmac, + createHmac } = await import('crypto'); const hmac = createHmac('sha256', 'a secret'); @@ -1863,12 +1870,8 @@ added: v15.0.0 Example: Converting a `CryptoKey` instance to a `KeyObject`: ```mjs -const { - webcrypto: { - subtle, - }, - KeyObject, -} = await import('crypto'); +const { webcrypto, KeyObject } = await import('crypto'); +const { subtle } = webcrypto; const key = await subtle.generateKey({ name: 'HMAC', @@ -2058,7 +2061,7 @@ Example: Using `Sign` and [`Verify`][] objects as streams: const { generateKeyPairSync, createSign, - createVerify, + createVerify } = await import('crypto'); const { privateKey, publicKey } = generateKeyPairSync('ec', { @@ -2106,7 +2109,7 @@ Example: Using the [`sign.update()`][] and [`verify.update()`][] methods: const { generateKeyPairSync, createSign, - createVerify, + createVerify } = await import('crypto'); const { privateKey, publicKey } = generateKeyPairSync('rsa', { @@ -3026,12 +3029,12 @@ Example: generating the sha256 sum of a file import { createReadStream } from 'fs'; - +import { argv } from 'process'; const { - createHash, + createHash } = await import('crypto'); -const filename = process.argv[2]; +const filename = argv[2]; const hash = createHash('sha256'); @@ -3052,12 +3055,12 @@ input.on('readable', () => { const { createReadStream, } = require('fs'); - const { createHash, } = require('crypto'); +const { argv } = require('process'); -const filename = process.argv[2]; +const filename = argv[2]; const hash = createHash('sha256'); @@ -3112,12 +3115,12 @@ Example: generating the sha256 HMAC of a file import { createReadStream } from 'fs'; - +import { argv } from 'process'; const { - createHmac, + createHmac } = await import('crypto'); -const filename = process.argv[2]; +const filename = argv[2]; const hmac = createHmac('sha256', 'a secret'); @@ -3138,12 +3141,12 @@ input.on('readable', () => { const { createReadStream, } = require('fs'); - const { createHmac, } = require('crypto'); +const { argv } = require('process'); -const filename = process.argv[2]; +const filename = argv[2]; const hmac = createHmac('sha256', 'a secret'); @@ -3336,7 +3339,7 @@ Asynchronously generates a new random secret key of the given `length`. The ```mjs const { - generateKey, + generateKey } = await import('crypto'); generateKey('hmac', { length: 64 }, (err, key) => { @@ -3408,7 +3411,7 @@ It is recommended to encode public keys as `'spki'` and private keys as ```mjs const { - generateKeyPair, + generateKeyPair } = await import('crypto'); generateKeyPair('rsa', { @@ -3505,7 +3508,7 @@ and to keep the passphrase confidential. ```mjs const { - generateKeyPairSync, + generateKeyPairSync } = await import('crypto'); const { @@ -3573,7 +3576,7 @@ Synchronously generates a new random secret key of the given `length`. The ```mjs const { - generateKeySync, + generateKeySync } = await import('crypto'); const key = generateKeySync('hmac', 64); @@ -3710,7 +3713,7 @@ added: v0.9.3 ```mjs const { - getCiphers, + getCiphers } = await import('crypto'); console.log(getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...] @@ -3733,7 +3736,7 @@ added: v2.3.0 ```mjs const { - getCurves, + getCurves } = await import('crypto'); console.log(getCurves()); // ['Oakley-EC2N-3', 'Oakley-EC2N-4', ...] @@ -3770,7 +3773,7 @@ Example (obtaining a shared secret): ```mjs const { - getDiffieHellman, + getDiffieHellman } = await import('crypto'); const alice = getDiffieHellman('modp14'); const bob = getDiffieHellman('modp14'); @@ -3822,7 +3825,7 @@ added: v0.9.3 ```mjs const { - getHashes, + getHashes } = await import('crypto'); console.log(getHashes()); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...] @@ -3866,8 +3869,9 @@ be passed to the callback as an {ArrayBuffer}. An error will be thrown if any of the input aguments specify invalid values or types. ```mjs +import { Buffer } from 'buffer'; const { - hkdf, + hkdf } = await import('crypto'); hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => { @@ -3880,6 +3884,7 @@ hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => { const { hkdf, } = require('crypto'); +const { Buffer } = require('buffer'); hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => { if (err) throw err; @@ -3915,8 +3920,9 @@ An error will be thrown if any of the input aguments specify invalid values or types, or if the derived key cannot be generated. ```mjs +import { Buffer } from 'buffer'; const { - hkdfSync, + hkdfSync } = await import('crypto'); const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64); @@ -3927,6 +3933,7 @@ console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653' const { hkdfSync, } = require('crypto'); +const { Buffer } = require('buffer'); const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64); console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653' @@ -3992,7 +3999,7 @@ When passing strings for `password` or `salt`, please consider ```mjs const { - pbkdf2, + pbkdf2 } = await import('crypto'); pbkdf2('secret', 'salt', 100000, 64, 'sha512', (err, derivedKey) => { @@ -4017,7 +4024,7 @@ The `crypto.DEFAULT_ENCODING` property can be used to change the way the deprecated and use should be avoided. ```mjs -const crypto = await import('crypto'); +import crypto from 'crypto'; crypto.DEFAULT_ENCODING = 'hex'; crypto.pbkdf2('secret', 'salt', 100000, 512, 'sha512', (err, derivedKey) => { if (err) throw err; @@ -4089,7 +4096,7 @@ When passing strings for `password` or `salt`, please consider ```mjs const { - pbkdf2Sync, + pbkdf2Sync } = await import('crypto'); const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha512'); @@ -4110,7 +4117,7 @@ The `crypto.DEFAULT_ENCODING` property may be used to change the way the should be avoided. ```mjs -const crypto = await import('crypto'); +import crypto from 'crypto'; crypto.DEFAULT_ENCODING = 'hex'; const key = crypto.pbkdf2Sync('secret', 'salt', 100000, 512, 'sha512'); console.log(key); // '3745e48...aa39b34' @@ -4327,7 +4334,7 @@ If an error occurs, `err` will be an `Error` object; otherwise it is `null`. The ```mjs // Asynchronous const { - randomBytes, + randomBytes } = await import('crypto'); randomBytes(256, (err, buf) => { @@ -4355,7 +4362,7 @@ there is a problem generating the bytes. ```mjs // Synchronous const { - randomBytes, + randomBytes } = await import('crypto'); const buf = randomBytes(256); @@ -4411,9 +4418,8 @@ changes: Synchronous version of [`crypto.randomFill()`][]. ```mjs -const { - randomFillSync, -} = await import('crypto'); +import { Buffer } from 'buffer'; +const { randomFillSync } = await import('crypto'); const buf = Buffer.alloc(10); console.log(randomFillSync(buf).toString('hex')); @@ -4427,9 +4433,8 @@ console.log(buf.toString('hex')); ``` ```cjs -const { - randomFillSync, -} = require('crypto'); +const { randomFillSync } = require('crypto'); +const { Buffer } = require('buffer'); const buf = Buffer.alloc(10); console.log(randomFillSync(buf).toString('hex')); @@ -4446,9 +4451,8 @@ Any `ArrayBuffer`, `TypedArray` or `DataView` instance may be passed as `buffer`. ```mjs -const { - randomFillSync, -} = await import('crypto'); +import { Buffer } from 'buffer'; +const { randomFillSync } = await import('crypto'); const a = new Uint32Array(10); console.log(Buffer.from(randomFillSync(a).buffer, @@ -4463,9 +4467,8 @@ console.log(Buffer.from(randomFillSync(c)).toString('hex')); ``` ```cjs -const { - randomFillSync, -} = require('crypto'); +const { randomFillSync } = require('crypto'); +const { Buffer } = require('buffer'); const a = new Uint32Array(10); console.log(Buffer.from(randomFillSync(a).buffer, @@ -4504,9 +4507,8 @@ requires that a callback is passed in. If the `callback` function is not provided, an error will be thrown. ```mjs -const { - randomFill, -} = await import('crypto'); +import { Buffer } from 'buffer'; +const { randomFill } = await import('crypto'); const buf = Buffer.alloc(10); randomFill(buf, (err, buf) => { @@ -4527,9 +4529,8 @@ randomFill(buf, 5, 5, (err, buf) => { ``` ```cjs -const { - randomFill, -} = require('crypto'); +const { randomFill } = require('crypto'); +const { Buffer } = require('buffer'); const buf = Buffer.alloc(10); randomFill(buf, (err, buf) => { @@ -4559,9 +4560,8 @@ contains finite numbers only, they are not drawn from a uniform random distribution and have no meaningful lower or upper bounds. ```mjs -const { - randomFill, -} = await import('crypto'); +import { Buffer } from 'buffer'; +const { randomFill } = await import('crypto'); const a = new Uint32Array(10); randomFill(a, (err, buf) => { @@ -4585,9 +4585,8 @@ randomFill(c, (err, buf) => { ``` ```cjs -const { - randomFill, -} = require('crypto'); +const { randomFill } = require('crypto'); +const { Buffer } = require('buffer'); const a = new Uint32Array(10); randomFill(a, (err, buf) => { @@ -4642,7 +4641,7 @@ generated synchronously. ```mjs // Asynchronous const { - randomInt, + randomInt } = await import('crypto'); randomInt(3, (err, n) => { @@ -4666,7 +4665,7 @@ randomInt(3, (err, n) => { ```mjs // Synchronous const { - randomInt, + randomInt } = await import('crypto'); const n = randomInt(3); @@ -4686,7 +4685,7 @@ console.log(`Random number chosen from (0, 1, 2): ${n}`); ```mjs // With `min` argument const { - randomInt, + randomInt } = await import('crypto'); const n = randomInt(1, 7); @@ -4776,7 +4775,7 @@ or types. ```mjs const { - scrypt, + scrypt } = await import('crypto'); // Using the factory defaults. @@ -4856,7 +4855,7 @@ or types. ```mjs const { - scryptSync, + scryptSync } = await import('crypto'); // Using the factory defaults. @@ -5212,10 +5211,11 @@ mode must adhere to certain restrictions when using the cipher API: authentication tag. ```mjs +import { Buffer } from 'buffer'; const { createCipheriv, createDecipheriv, - randomBytes, + randomBytes } = await import('crypto'); const key = 'keykeykeykeykeykeykeykey'; @@ -5261,6 +5261,7 @@ const { createDecipheriv, randomBytes, } = require('crypto'); +const { Buffer } = require('buffer'); const key = 'keykeykeykeykeykeykeykey'; const nonce = randomBytes(12); diff --git a/doc/api/dgram.md b/doc/api/dgram.md index 8813f9bffaf384..365c30c9ae64a7 100644 --- a/doc/api/dgram.md +++ b/doc/api/dgram.md @@ -10,7 +10,30 @@ The `dgram` module provides an implementation of UDP datagram sockets. -```js +```mjs +import dgram from 'dgram'; + +const server = dgram.createSocket('udp4'); + +server.on('error', (err) => { + console.log(`server error:\n${err.stack}`); + server.close(); +}); + +server.on('message', (msg, rinfo) => { + console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); +}); + +server.on('listening', () => { + const address = server.address(); + console.log(`server listening ${address.address}:${address.port}`); +}); + +server.bind(41234); +// Prints: server listening 0.0.0.0:41234 +``` + +```cjs const dgram = require('dgram'); const server = dgram.createSocket('udp4'); @@ -123,9 +146,25 @@ When sharing a UDP socket across multiple `cluster` workers, the `socket.addMembership()` function must be called only once or an `EADDRINUSE` error will occur: -```js +```mjs +import cluster from 'cluster'; +import dgram from 'dgram'; + +if (cluster.isPrimary) { + cluster.fork(); // Works ok. + cluster.fork(); // Fails with EADDRINUSE. +} else { + const s = dgram.createSocket('udp4'); + s.bind(1234, () => { + s.addMembership('224.0.0.114'); + }); +} +``` + +```cjs const cluster = require('cluster'); const dgram = require('dgram'); + if (cluster.isPrimary) { cluster.fork(); // Works ok. cluster.fork(); // Fails with EADDRINUSE. @@ -205,7 +244,30 @@ attempting to bind with a closed socket), an [`Error`][] may be thrown. Example of a UDP server listening on port 41234: -```js +```mjs +import dgram from 'dgram'; + +const server = dgram.createSocket('udp4'); + +server.on('error', (err) => { + console.log(`server error:\n${err.stack}`); + server.close(); +}); + +server.on('message', (msg, rinfo) => { + console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); +}); + +server.on('listening', () => { + const address = server.address(); + console.log(`server listening ${address.address}:${address.port}`); +}); + +server.bind(41234); +// Prints: server listening 0.0.0.0:41234 +``` + +```cjs const dgram = require('dgram'); const server = dgram.createSocket('udp4'); @@ -480,8 +542,21 @@ This method throws [`ERR_SOCKET_BAD_PORT`][] if called on an unbound socket. Example of sending a UDP packet to a port on `localhost`; -```js +```mjs +import dgram from 'dgram'; +import { Buffer } from 'buffer'; + +const message = Buffer.from('Some bytes'); +const client = dgram.createSocket('udp4'); +client.send(message, 41234, 'localhost', (err) => { + client.close(); +}); +``` + +```cjs const dgram = require('dgram'); +const { Buffer } = require('buffer'); + const message = Buffer.from('Some bytes'); const client = dgram.createSocket('udp4'); client.send(message, 41234, 'localhost', (err) => { @@ -492,8 +567,22 @@ client.send(message, 41234, 'localhost', (err) => { Example of sending a UDP packet composed of multiple buffers to a port on `127.0.0.1`; -```js +```mjs +import dgram from 'dgram'; +import { Buffer } from 'buffer'; + +const buf1 = Buffer.from('Some '); +const buf2 = Buffer.from('bytes'); +const client = dgram.createSocket('udp4'); +client.send([buf1, buf2], 41234, (err) => { + client.close(); +}); +``` + +```cjs const dgram = require('dgram'); +const { Buffer } = require('buffer'); + const buf1 = Buffer.from('Some '); const buf2 = Buffer.from('bytes'); const client = dgram.createSocket('udp4'); @@ -510,8 +599,23 @@ however, sending multiple buffers is faster. Example of sending a UDP packet using a socket connected to a port on `localhost`: -```js +```mjs +import dgram from 'dgram'; +import { Buffer } from 'buffer'; + +const message = Buffer.from('Some bytes'); +const client = dgram.createSocket('udp4'); +client.connect(41234, 'localhost', (err) => { + client.send(message, (err) => { + client.close(); + }); +}); +``` + +```cjs const dgram = require('dgram'); +const { Buffer } = require('buffer'); + const message = Buffer.from('Some bytes'); const client = dgram.createSocket('udp4'); client.connect(41234, 'localhost', (err) => { diff --git a/doc/api/diagnostics_channel.md b/doc/api/diagnostics_channel.md index 7a22b2f56eec1d..ba02a5092c3731 100644 --- a/doc/api/diagnostics_channel.md +++ b/doc/api/diagnostics_channel.md @@ -11,7 +11,11 @@ to report arbitrary message data for diagnostics purposes. It can be accessed using: -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); ``` @@ -33,7 +37,27 @@ other modules. Following is a simple overview of the public API. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +// Get a reusable channel object +const channel = diagnostics_channel.channel('my-channel'); + +// Subscribe to the channel +channel.subscribe((message, name) => { + // Received data +}); + +// Check if the channel has an active subscriber +if (channel.hasSubscribers) { + // Publish data to the channel + channel.publish({ + some: 'data' + }); +} +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); // Get a reusable channel object @@ -64,7 +88,15 @@ the message you want to send might be expensive to prepare. This API is optional but helpful when trying to publish messages from very performance-sensitive code. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +if (diagnostics_channel.hasSubscribers('my-channel')) { + // There are subscribers, prepare and publish message +} +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); if (diagnostics_channel.hasSubscribers('my-channel')) { @@ -81,7 +113,13 @@ This is the primary entry-point for anyone wanting to interact with a named channel. It produces a channel object which is optimized to reduce overhead at publish time as much as possible. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +const channel = diagnostics_channel.channel('my-channel'); +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); @@ -107,7 +145,17 @@ the message you want to send might be expensive to prepare. This API is optional but helpful when trying to publish messages from very performance-sensitive code. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +const channel = diagnostics_channel.channel('my-channel'); + +if (channel.hasSubscribers) { + // There are subscribers, prepare and publish message +} +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); @@ -124,7 +172,17 @@ if (channel.hasSubscribers) { Publish a message to any subscribers to the channel. This will trigger message handlers synchronously so they will execute within the same context. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +const channel = diagnostics_channel.channel('my-channel'); + +channel.publish({ + some: 'message' +}); +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); @@ -144,7 +202,17 @@ Register a message handler to subscribe to this channel. This message handler will be run synchronously whenever a message is published to the channel. Any errors thrown in the message handler will trigger an [`'uncaughtException'`][]. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +const channel = diagnostics_channel.channel('my-channel'); + +channel.subscribe((message, name) => { + // Received data +}); +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); @@ -161,7 +229,21 @@ channel.subscribe((message, name) => { Remove a message handler previously registered to this channel with [`channel.subscribe(onMessage)`][]. -```js +```mjs +import diagnostics_channel from 'diagnostics_channel'; + +const channel = diagnostics_channel.channel('my-channel'); + +function onMessage(message, name) { + // Received data +} + +channel.subscribe(onMessage); + +channel.unsubscribe(onMessage); +``` + +```cjs const diagnostics_channel = require('diagnostics_channel'); const channel = diagnostics_channel.channel('my-channel'); diff --git a/doc/api/esm.md b/doc/api/esm.md index 40cb34ee90899b..534addc3330932 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -247,6 +247,7 @@ readFile('./foo.txt', (err, source) => { ```js import fs, { readFileSync } from 'fs'; import { syncBuiltinESMExports } from 'module'; +import { Buffer } from 'buffer'; fs.readFileSync = () => Buffer.from('Hello, ESM'); syncBuiltinESMExports(); @@ -819,8 +820,9 @@ globalThis.someInjectedProperty = 42; console.log('I just set some globals!'); const { createRequire } = getBuiltin('module'); +const { cwd } = getBuiltin('process'); -const require = createRequire(process.cwd() + '/'); +const require = createRequire(cwd() + '/'); // [...] `; } @@ -921,8 +923,9 @@ purposes. // coffeescript-loader.mjs import { URL, pathToFileURL } from 'url'; import CoffeeScript from 'coffeescript'; +import { cwd } from 'process'; -const baseURL = pathToFileURL(`${process.cwd()}/`).href; +const baseURL = pathToFileURL(`${cwd()}/`).href; // CoffeeScript files end in .coffee, .litcoffee or .coffee.md. const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; diff --git a/doc/api/fs.md b/doc/api/fs.md index b4f2c1e11a14b0..09b0d97c3de841 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1313,6 +1313,7 @@ to be written. ```mjs import { writeFile } from 'fs/promises'; +import { Buffer } from 'buffer'; try { const controller = new AbortController(); @@ -3951,6 +3952,7 @@ If `data` is a normal object, it must have an own `toString` function property. ```mjs import { writeFile } from 'fs'; +import { Buffer } from 'buffer'; const data = new Uint8Array(Buffer.from('Hello Node.js')); writeFile('message.txt', data, (err) => { @@ -3981,6 +3983,7 @@ to be written. ```mjs import { writeFile } from 'fs'; +import { Buffer } from 'buffer'; const controller = new AbortController(); const { signal } = controller; @@ -4002,6 +4005,7 @@ calling `fs.write()` like: ```mjs import { write } from 'fs'; +import { Buffer } from 'buffer'; write(fd, Buffer.from(data, options.encoding), callback); ``` @@ -6522,6 +6526,7 @@ Example using an absolute path on POSIX: ```mjs import { open } from 'fs/promises'; +import { Buffer } from 'buffer'; let fd; try { diff --git a/doc/api/process.md b/doc/api/process.md index 85e3bf5458a901..dbc6c8d57360a2 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -5,12 +5,15 @@ -The `process` object is a `global` that provides information about, and control -over, the current Node.js process. As a global, it is always available to -Node.js applications without using `require()`. It can also be explicitly -accessed using `require()`: +The `process` object provides information about, and control over, the current +Node.js process. While it is available as a global, it is recommended to +explicitly access it via require or import: -```js +```mjs +import process from 'process'; +``` + +```cjs const process = require('process'); ``` @@ -38,7 +41,28 @@ termination, such as calling [`process.exit()`][] or uncaught exceptions. The `'beforeExit'` should *not* be used as an alternative to the `'exit'` event unless the intention is to schedule additional work. -```js +```mjs +import process from 'process'; + +process.on('beforeExit', (code) => { + console.log('Process beforeExit event with code: ', code); +}); + +process.on('exit', (code) => { + console.log('Process exit event with code: ', code); +}); + +console.log('This message is displayed first.'); + +// Prints: +// This message is displayed first. +// Process beforeExit event with code: 0 +// Process exit event with code: 0 +``` + +```cjs +const process = require('process'); + process.on('beforeExit', (code) => { console.log('Process beforeExit event with code: ', code); }); @@ -84,7 +108,17 @@ The listener callback function is invoked with the exit code specified either by the [`process.exitCode`][] property, or the `exitCode` argument passed to the [`process.exit()`][] method. -```js +```mjs +import process from 'process'; + +process.on('exit', (code) => { + console.log(`About to exit with code: ${code}`); +}); +``` + +```cjs +const process = require('process'); + process.on('exit', (code) => { console.log(`About to exit with code: ${code}`); }); @@ -95,7 +129,19 @@ process will exit immediately after calling the `'exit'` event listeners causing any additional work still queued in the event loop to be abandoned. In the following example, for instance, the timeout will never occur: -```js +```mjs +import process from 'process'; + +process.on('exit', (code) => { + setTimeout(() => { + console.log('This will not run'); + }, 0); +}); +``` + +```cjs +const process = require('process'); + process.on('exit', (code) => { setTimeout(() => { console.log('This will not run'); @@ -148,7 +194,38 @@ This is useful for tracking potential errors in an application while using the the occurrence of this event does not necessarily indicate an error. For example, [`Promise.race()`][] can trigger a `'multipleResolves'` event. -```js +```mjs +import process from 'process'; + +process.on('multipleResolves', (type, promise, reason) => { + console.error(type, promise, reason); + setImmediate(() => process.exit(1)); +}); + +async function main() { + try { + return await new Promise((resolve, reject) => { + resolve('First call'); + resolve('Swallowed resolve'); + reject(new Error('Swallowed reject')); + }); + } catch { + throw new Error('Failed'); + } +} + +main().then(console.log); +// resolve: Promise { 'First call' } 'Swallowed resolve' +// reject: Promise { 'First call' } Error: Swallowed reject +// at Promise (*) +// at new Promise () +// at main (*) +// First call +``` + +```cjs +const process = require('process'); + process.on('multipleResolves', (type, promise, reason) => { console.error(type, promise, reason); setImmediate(() => process.exit(1)); @@ -206,7 +283,21 @@ In asynchronous code, the `'unhandledRejection'` event is emitted when the list of unhandled rejections grows, and the `'rejectionHandled'` event is emitted when the list of unhandled rejections shrinks. -```js +```mjs +import process from 'process'; + +const unhandledRejections = new Map(); +process.on('unhandledRejection', (reason, promise) => { + unhandledRejections.set(promise, reason); +}); +process.on('rejectionHandled', (promise) => { + unhandledRejections.delete(promise); +}); +``` + +```cjs +const process = require('process'); + const unhandledRejections = new Map(); process.on('unhandledRejection', (reason, promise) => { unhandledRejections.set(promise, reason); @@ -250,7 +341,29 @@ behavior. Alternatively, change the [`process.exitCode`][] in the provided exit code. Otherwise, in the presence of such handler the process will exit with 0. -```js +```mjs +import process from 'process'; + +process.on('uncaughtException', (err, origin) => { + fs.writeSync( + process.stderr.fd, + `Caught exception: ${err}\n` + + `Exception origin: ${origin}` + ); +}); + +setTimeout(() => { + console.log('This will still run.'); +}, 500); + +// Intentionally cause an exception, but don't catch it. +nonexistentFunc(); +console.log('This will not run.'); +``` + +```cjs +const process = require('process'); + process.on('uncaughtException', (err, origin) => { fs.writeSync( process.stderr.fd, @@ -321,7 +434,21 @@ Installing an `'uncaughtExceptionMonitor'` listener does not change the behavior once an `'uncaughtException'` event is emitted. The process will still crash if no `'uncaughtException'` listener is installed. -```js +```mjs +import process from 'process'; + +process.on('uncaughtExceptionMonitor', (err, origin) => { + MyMonitoringTool.logSync(err, origin); +}); + +// Intentionally cause an exception, but don't catch it. +nonexistentFunc(); +// Still crashes Node.js +``` + +```cjs +const process = require('process'); + process.on('uncaughtExceptionMonitor', (err, origin) => { MyMonitoringTool.logSync(err, origin); }); @@ -356,7 +483,22 @@ are propagated through a `Promise` chain. The `'unhandledRejection'` event is useful for detecting and keeping track of promises that were rejected whose rejections have not yet been handled. -```js +```mjs +import process from 'process'; + +process.on('unhandledRejection', (reason, promise) => { + console.log('Unhandled Rejection at:', promise, 'reason:', reason); + // Application specific logging, throwing an error, or other logic here +}); + +somePromise.then((res) => { + return reportToUser(JSON.pasre(res)); // Note the typo (`pasre`) +}); // No `.catch()` or `.then()` +``` + +```cjs +const process = require('process'); + process.on('unhandledRejection', (reason, promise) => { console.log('Unhandled Rejection at:', promise, 'reason:', reason); // Application specific logging, throwing an error, or other logic here @@ -370,7 +512,21 @@ somePromise.then((res) => { The following will also trigger the `'unhandledRejection'` event to be emitted: -```js +```mjs +import process from 'process'; + +function SomeResource() { + // Initially set the loaded status to a rejected promise + this.loaded = Promise.reject(new Error('Resource not yet loaded!')); +} + +const resource = new SomeResource(); +// no .catch or .then on resource.loaded for at least a turn +``` + +```cjs +const process = require('process'); + function SomeResource() { // Initially set the loaded status to a rejected promise this.loaded = Promise.reject(new Error('Resource not yet loaded!')); @@ -406,7 +562,19 @@ are not part of the normal Node.js and JavaScript error handling flow. Node.js can emit warnings whenever it detects bad coding practices that could lead to sub-optimal application performance, bugs, or security vulnerabilities. -```js +```mjs +import process from 'process'; + +process.on('warning', (warning) => { + console.warn(warning.name); // Print the warning name + console.warn(warning.message); // Print the warning message + console.warn(warning.stack); // Print the stack trace +}); +``` + +```cjs +const process = require('process'); + process.on('warning', (warning) => { console.warn(warning.name); // Print the warning name console.warn(warning.message); // Print the warning message @@ -511,7 +679,28 @@ The signal handler will receive the signal's name (`'SIGINT'`, The name of each event will be the uppercase common name for the signal (e.g. `'SIGINT'` for `SIGINT` signals). -```js +```mjs +import process from 'process'; + +// Begin reading from stdin so the process does not exit. +process.stdin.resume(); + +process.on('SIGINT', () => { + console.log('Received SIGINT. Press Control-D to exit.'); +}); + +// Using a single function to handle multiple signals +function handle(signal) { + console.log(`Received ${signal}`); +} + +process.on('SIGINT', handle); +process.on('SIGTERM', handle); +``` + +```cjs +const process = require('process'); + // Begin reading from stdin so the process does not exit. process.stdin.resume(); @@ -613,8 +802,21 @@ appear only *once*; each will begin with one or more dashes. Flags passed through to V8 will contain underscores instead of non-leading dashes: -```js -process.allowedNodeEnvironmentFlags.forEach((flag) => { +```mjs +import { allowedNodeEnvironmentFlags } from 'process'; + +allowedNodeEnvironmentFlags.forEach((flag) => { + // -r + // --inspect-brk + // --abort_on_uncaught_exception + // ... +}); +``` + +```cjs +const { allowedNodeEnvironmentFlags } = require('process'); + +allowedNodeEnvironmentFlags.forEach((flag) => { // -r // --inspect-brk // --abort_on_uncaught_exception @@ -641,7 +843,15 @@ The operating system CPU architecture for which the Node.js binary was compiled. Possible values are: `'arm'`, `'arm64'`, `'ia32'`, `'mips'`,`'mipsel'`, `'ppc'`, `'ppc64'`, `'s390'`, `'s390x'`, `'x32'`, and `'x64'`. -```js +```mjs +import { arch } from 'process'; + +console.log(`This processor architecture is ${arch}`); +``` + +```cjs +const { arch } = require('process'); + console.log(`This processor architecture is ${process.arch}`); ``` @@ -661,9 +871,20 @@ arguments. For example, assuming the following script for `process-args.js`: -```js +```mjs +import { argv } from 'process'; + +// print process.argv +argv.forEach((val, index) => { + console.log(`${index}: ${val}`); +}); +``` + +```cjs +const { argv } = require('process'); + // print process.argv -process.argv.forEach((val, index) => { +argv.forEach((val, index) => { console.log(`${index}: ${val}`); }); ``` @@ -753,11 +974,25 @@ The `process.chdir()` method changes the current working directory of the Node.js process or throws an exception if doing so fails (for instance, if the specified `directory` does not exist). -```js -console.log(`Starting directory: ${process.cwd()}`); +```mjs +import { chdir, cwd } from 'process'; + +console.log(`Starting directory: ${cwd()}`); try { - process.chdir('/tmp'); - console.log(`New directory: ${process.cwd()}`); + chdir('/tmp'); + console.log(`New directory: ${cwd()}`); +} catch (err) { + console.error(`chdir: ${err}`); +} +``` + +```cjs +const { chdir, cwd } = require('process'); + +console.log(`Starting directory: ${cwd()}`); +try { + chdir('/tmp'); + console.log(`New directory: ${cwd()}`); } catch (err) { console.error(`chdir: ${err}`); } @@ -855,15 +1090,31 @@ actual elapsed time if multiple CPU cores are performing work for this process. The result of a previous call to `process.cpuUsage()` can be passed as the argument to the function, to get a diff reading. -```js -const startUsage = process.cpuUsage(); +```mjs +import { cpuUsage } from 'process'; + +const startUsage = cpuUsage(); // { user: 38579, system: 6986 } // spin the CPU for 500 milliseconds const now = Date.now(); while (Date.now() - now < 500); -console.log(process.cpuUsage(startUsage)); +console.log(cpuUsage(startUsage)); +// { user: 514883, system: 11226 } +``` + +```cjs +const { cpuUsage } = require('process'); + +const startUsage = cpuUsage(); +// { user: 38579, system: 6986 } + +// spin the CPU for 500 milliseconds +const now = Date.now(); +while (Date.now() - now < 500); + +console.log(cpuUsage(startUsage)); // { user: 514883, system: 11226 } ``` @@ -877,8 +1128,16 @@ added: v0.1.8 The `process.cwd()` method returns the current working directory of the Node.js process. -```js -console.log(`Current directory: ${process.cwd()}`); +```mjs +import { cwd } from 'process'; + +console.log(`Current directory: ${cwd()}`); +``` + +```cjs +const { cwd } = require('process'); + +console.log(`Current directory: ${cwd()}`); ``` ## `process.debugPort` @@ -890,7 +1149,15 @@ added: v0.7.2 The port used by the Node.js debugger when enabled. -```js +```mjs +import process from 'process'; + +process.debugPort = 5858; +``` + +```cjs +const process = require('process'); + process.debugPort = 5858; ``` @@ -941,12 +1208,24 @@ that exports a `foo` function. All the symbols are loaded before the call returns, by passing the `RTLD_NOW` constant. In this example the constant is assumed to be available. -```js -const os = require('os'); -const path = require('path'); +```mjs +import { dlopen } from 'process'; +import { constants } from 'os'; +import { fileURLToPath } from 'url'; + +const module = { exports: {} }; +dlopen(module, fileURLToPath(new URL('local.node', import.meta.url)), + constants.dlopen.RTLD_NOW); +module.exports.foo(); +``` + +```cjs +const { dlopen } = require('process'); +const { constants } = require('os'); +const { join } = require('path'); + const module = { exports: {} }; -process.dlopen(module, path.join(__dirname, 'local.node'), - os.constants.dlopen.RTLD_NOW); +dlopen(module, join(__dirname, 'local.node'), constants.dlopen.RTLD_NOW); module.exports.foo(); ``` @@ -969,9 +1248,24 @@ The `process.emitWarning()` method can be used to emit custom or application specific process warnings. These can be listened for by adding a handler to the [`'warning'`][process_warning] event. -```js +```mjs +import { emitWarning } from 'process'; + +// Emit a warning with a code and additional detail. +emitWarning('Something happened!', { + code: 'MY_WARNING', + detail: 'This is some additional information' +}); +// Emits: +// (node:56338) [MY_WARNING] Warning: Something happened! +// This is some additional information +``` + +```cjs +const { emitWarning } = require('process'); + // Emit a warning with a code and additional detail. -process.emitWarning('Something happened!', { +emitWarning('Something happened!', { code: 'MY_WARNING', detail: 'This is some additional information' }); @@ -984,7 +1278,21 @@ In this example, an `Error` object is generated internally by `process.emitWarning()` and passed through to the [`'warning'`][process_warning] handler. -```js +```mjs +import process from 'process'; + +process.on('warning', (warning) => { + console.warn(warning.name); // 'Warning' + console.warn(warning.message); // 'Something happened!' + console.warn(warning.code); // 'MY_WARNING' + console.warn(warning.stack); // Stack trace + console.warn(warning.detail); // 'This is some additional information' +}); +``` + +```cjs +const process = require('process'); + process.on('warning', (warning) => { console.warn(warning.name); // 'Warning' console.warn(warning.message); // 'Something happened!' @@ -1013,19 +1321,48 @@ The `process.emitWarning()` method can be used to emit custom or application specific process warnings. These can be listened for by adding a handler to the [`'warning'`][process_warning] event. -```js +```mjs +import { emitWarning } from 'process'; + // Emit a warning using a string. -process.emitWarning('Something happened!'); +emitWarning('Something happened!'); // Emits: (node: 56338) Warning: Something happened! ``` -```js +```cjs +const { emitWarning } = require('process'); + +// Emit a warning using a string. +emitWarning('Something happened!'); +// Emits: (node: 56338) Warning: Something happened! +``` + +```mjs +import { emitWarning } from 'process'; + // Emit a warning using a string and a type. -process.emitWarning('Something Happened!', 'CustomWarning'); +emitWarning('Something Happened!', 'CustomWarning'); // Emits: (node:56338) CustomWarning: Something Happened! ``` -```js +```cjs +const { emitWarning } = require('process'); + +// Emit a warning using a string and a type. +emitWarning('Something Happened!', 'CustomWarning'); +// Emits: (node:56338) CustomWarning: Something Happened! +``` + +```mjs +import { emitWarning } from 'process'; + +emitWarning('Something happened!', 'CustomWarning', 'WARN001'); +// Emits: (node:56338) [WARN001] CustomWarning: Something happened! +``` + +```cjs +const { emitWarning } = require('process'); + process.emitWarning('Something happened!', 'CustomWarning', 'WARN001'); // Emits: (node:56338) [WARN001] CustomWarning: Something happened! ``` @@ -1034,7 +1371,20 @@ In each of the previous examples, an `Error` object is generated internally by `process.emitWarning()` and passed through to the [`'warning'`][process_warning] handler. -```js +```mjs +import process from 'process'; + +process.on('warning', (warning) => { + console.warn(warning.name); + console.warn(warning.message); + console.warn(warning.code); + console.warn(warning.stack); +}); +``` + +```cjs +const process = require('process'); + process.on('warning', (warning) => { console.warn(warning.name); console.warn(warning.message); @@ -1047,14 +1397,29 @@ If `warning` is passed as an `Error` object, it will be passed through to the `'warning'` event handler unmodified (and the optional `type`, `code` and `ctor` arguments will be ignored): -```js +```mjs +import { emitWarning } from 'process'; + // Emit a warning using an Error object. const myWarning = new Error('Something happened!'); // Use the Error name property to specify the type name myWarning.name = 'CustomWarning'; myWarning.code = 'WARN001'; -process.emitWarning(myWarning); +emitWarning(myWarning); +// Emits: (node:56338) [WARN001] CustomWarning: Something happened! +``` + +```cjs +const { emitWarning } = require('process'); + +// Emit a warning using an Error object. +const myWarning = new Error('Something happened!'); +// Use the Error name property to specify the type name +myWarning.name = 'CustomWarning'; +myWarning.code = 'WARN001'; + +emitWarning(myWarning); // Emits: (node:56338) [WARN001] CustomWarning: Something happened! ``` @@ -1080,11 +1445,28 @@ As a best practice, warnings should be emitted only once per process. To do so, it is recommended to place the `emitWarning()` behind a simple boolean flag as illustrated in the example below: -```js +```mjs +import { emitWarning } from 'process'; + function emitMyWarning() { if (!emitMyWarning.warned) { emitMyWarning.warned = true; - process.emitWarning('Only warn once!'); + emitWarning('Only warn once!'); + } +} +emitMyWarning(); +// Emits: (node: 56339) Warning: Only warn once! +emitMyWarning(); +// Emits nothing +``` + +```cjs +const { emitWarning } = require('process'); + +function emitMyWarning() { + if (!emitMyWarning.warned) { + emitMyWarning.warned = true; + emitWarning('Only warn once!'); } } emitMyWarning(); @@ -1141,38 +1523,81 @@ $ node -e 'process.env.foo = "bar"' && echo $foo While the following will: -```js -process.env.foo = 'bar'; -console.log(process.env.foo); +```mjs +import { env } from 'process'; + +env.foo = 'bar'; +console.log(env.foo); +``` + +```cjs +const { env } = require('process'); + +env.foo = 'bar'; +console.log(env.foo); ``` Assigning a property on `process.env` will implicitly convert the value to a string. **This behavior is deprecated.** Future versions of Node.js may throw an error when the value is not a string, number, or boolean. -```js -process.env.test = null; -console.log(process.env.test); +```mjs +import { env } from 'process'; + +env.test = null; +console.log(env.test); // => 'null' -process.env.test = undefined; -console.log(process.env.test); +env.test = undefined; +console.log(env.test); +// => 'undefined' +``` + +```cjs +const { env } = require('process'); + +env.test = null; +console.log(env.test); +// => 'null' +env.test = undefined; +console.log(env.test); // => 'undefined' ``` Use `delete` to delete a property from `process.env`. -```js -process.env.TEST = 1; -delete process.env.TEST; -console.log(process.env.TEST); +```mjs +import { env } from 'process'; + +env.TEST = 1; +delete env.TEST; +console.log(env.TEST); +// => undefined +``` + +```cjs +const { env } = require('process'); + +env.TEST = 1; +delete env.TEST; +console.log(env.TEST); // => undefined ``` On Windows operating systems, environment variables are case-insensitive. -```js -process.env.TEST = 1; -console.log(process.env.test); +```mjs +import { env } from 'process'; + +env.TEST = 1; +console.log(env.test); +// => 1 +``` + +```cjs +const { env } = require('process'); + +env.TEST = 1; +console.log(env.test); // => 1 ``` @@ -1248,8 +1673,16 @@ called. To exit with a 'failure' code: -```js -process.exit(1); +```mjs +import { exit } from 'process'; + +exit(1); +``` + +```cjs +const { exit } = require('process'); + +exit(1); ``` The shell that executed Node.js should see the exit code as `1`. @@ -1268,11 +1701,23 @@ For instance, the following example illustrates a *misuse* of the `process.exit()` method that could lead to data printed to stdout being truncated and lost: -```js +```mjs +import { exit } from 'process'; + // This is an example of what *not* to do: if (someConditionNotMet()) { printUsageToStdout(); - process.exit(1); + exit(1); +} +``` + +```cjs +const { exit } = require('process'); + +// This is an example of what *not* to do: +if (someConditionNotMet()) { + printUsageToStdout(); + exit(1); } ``` @@ -1285,7 +1730,20 @@ Rather than calling `process.exit()` directly, the code *should* set the `process.exitCode` and allow the process to exit naturally by avoiding scheduling any additional work for the event loop: -```js +```mjs +import process from 'process'; + +// How to properly set the exit code while letting +// the process exit gracefully. +if (someConditionNotMet()) { + printUsageToStdout(); + process.exitCode = 1; +} +``` + +```cjs +const process = require('process'); + // How to properly set the exit code while letting // the process exit gracefully. if (someConditionNotMet()) { @@ -1323,7 +1781,17 @@ added: v2.0.0 The `process.getegid()` method returns the numerical effective group identity of the Node.js process. (See getegid(2).) -```js +```mjs +import process from 'process'; + +if (process.getegid) { + console.log(`Current gid: ${process.getegid()}`); +} +``` + +```cjs +const process = require('process'); + if (process.getegid) { console.log(`Current gid: ${process.getegid()}`); } @@ -1342,7 +1810,17 @@ added: v2.0.0 The `process.geteuid()` method returns the numerical effective user identity of the process. (See geteuid(2).) -```js +```mjs +import process from 'process'; + +if (process.geteuid) { + console.log(`Current uid: ${process.geteuid()}`); +} +``` + +```cjs +const process = require('process'); + if (process.geteuid) { console.log(`Current uid: ${process.geteuid()}`); } @@ -1361,7 +1839,17 @@ added: v0.1.31 The `process.getgid()` method returns the numerical group identity of the process. (See getgid(2).) -```js +```mjs +import process from 'process'; + +if (process.getgid) { + console.log(`Current gid: ${process.getgid()}`); +} +``` + +```cjs +const process = require('process'); + if (process.getgid) { console.log(`Current gid: ${process.getgid()}`); } @@ -1381,7 +1869,17 @@ The `process.getgroups()` method returns an array with the supplementary group IDs. POSIX leaves it unspecified if the effective group ID is included but Node.js ensures it always is. -```js +```mjs +import process from 'process'; + +if (process.getgroups) { + console.log(process.getgroups()); // [ 16, 21, 297 ] +} +``` + +```cjs +const process = require('process'); + if (process.getgroups) { console.log(process.getgroups()); // [ 16, 21, 297 ] } @@ -1400,7 +1898,17 @@ added: v0.1.28 The `process.getuid()` method returns the numeric user identity of the process. (See getuid(2).) -```js +```mjs +import process from 'process'; + +if (process.getuid) { + console.log(`Current uid: ${process.getuid()}`); +} +``` + +```cjs +const process = require('process'); + if (process.getuid) { console.log(`Current uid: ${process.getuid()}`); } @@ -1446,13 +1954,31 @@ These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift. The primary use is for measuring performance between intervals: -```js +```mjs +import { hrtime } from 'process'; + +const NS_PER_SEC = 1e9; +const time = hrtime(); +// [ 1800216, 25 ] + +setTimeout(() => { + const diff = hrtime(time); + // [ 1, 552 ] + + console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`); + // Benchmark took 1000000552 nanoseconds +}, 1000); +``` + +```cjs +const { hrtime } = require('process'); + const NS_PER_SEC = 1e9; -const time = process.hrtime(); +const time = hrtime(); // [ 1800216, 25 ] setTimeout(() => { - const diff = process.hrtime(time); + const diff = hrtime(time); // [ 1, 552 ] console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`); @@ -1474,12 +2000,29 @@ Unlike [`process.hrtime()`][], it does not support an additional `time` argument since the difference can just be computed directly by subtraction of the two `bigint`s. -```js -const start = process.hrtime.bigint(); +```mjs +import { hrtime } from 'process'; + +const start = hrtime.bigint(); // 191051479007711n setTimeout(() => { - const end = process.hrtime.bigint(); + const end = hrtime.bigint(); + // 191052633396993n + + console.log(`Benchmark took ${end - start} nanoseconds`); + // Benchmark took 1154389282 nanoseconds +}, 1000); +``` + +```cjs +const { hrtime } = require('process'); + +const start = hrtime.bigint(); +// 191051479007711n + +setTimeout(() => { + const end = hrtime.bigint(); // 191052633396993n console.log(`Benchmark took ${end - start} nanoseconds`); @@ -1502,12 +2045,24 @@ access or the `CAP_SETGID` capability. Use care when dropping privileges: -```js -console.log(process.getgroups()); // [ 0 ] -process.initgroups('nodeuser', 1000); // switch user -console.log(process.getgroups()); // [ 27, 30, 46, 1000, 0 ] -process.setgid(1000); // drop root gid -console.log(process.getgroups()); // [ 27, 30, 46, 1000 ] +```mjs +import { getgroups, initgroups, setgid } from 'process'; + +console.log(getgroups()); // [ 0 ] +initgroups('nodeuser', 1000); // switch user +console.log(getgroups()); // [ 27, 30, 46, 1000, 0 ] +setgid(1000); // drop root gid +console.log(getgroups()); // [ 27, 30, 46, 1000 ] +``` + +```cjs +const { getgroups, initgroups, setgid } = require('process'); + +console.log(getgroups()); // [ 0 ] +initgroups('nodeuser', 1000); // switch user +console.log(getgroups()); // [ 27, 30, 46, 1000, 0 ] +setgid(1000); // drop root gid +console.log(getgroups()); // [ 27, 30, 46, 1000 ] ``` This function is only available on POSIX platforms (i.e. not Windows or @@ -1538,7 +2093,24 @@ Even though the name of this function is `process.kill()`, it is really just a signal sender, like the `kill` system call. The signal sent may do something other than kill the target process. -```js +```mjs +import process, { kill } from 'process'; + +process.on('SIGHUP', () => { + console.log('Got SIGHUP signal.'); +}); + +setTimeout(() => { + console.log('Exiting.'); + process.exit(0); +}, 100); + +kill(process.pid, 'SIGHUP'); +``` + +```cjs +const process = require('process'); + process.on('SIGHUP', () => { console.log('Got SIGHUP signal.'); }); @@ -1594,11 +2166,27 @@ changes: * `external` {integer} * `arrayBuffers` {integer} -Returns an object describing the memory usage of the Node.js process measured in -bytes. +Returns an object describing the memory usage of the Node.js process measured in +bytes. + +```mjs +import { memoryUsage } from 'process'; + +console.log(memoryUsage()); +// Prints: +// { +// rss: 4935680, +// heapTotal: 1826816, +// heapUsed: 650472, +// external: 49879, +// arrayBuffers: 9386 +// } +``` + +```cjs +const { memoryUsage } = require('process'); -```js -console.log(process.memoryUsage()); +console.log(memoryUsage()); // Prints: // { // rss: 4935680, @@ -1645,8 +2233,17 @@ process, including all C++ and JavaScript objects and code. This is the same value as the `rss` property provided by `process.memoryUsage()` but `process.memoryUsage.rss()` is faster. -```js -console.log(process.memoryUsage.rss()); +```mjs +import { memoryUsage } from 'process'; + +console.log(memoryUsage.rss()); +// 35655680 +``` + +```cjs +const { rss } = require('process'); + +console.log(memoryUsage.rss()); // 35655680 ``` @@ -1668,9 +2265,25 @@ completion and before the event loop is allowed to continue. It's possible to create an infinite loop if one were to recursively call `process.nextTick()`. See the [Event Loop][] guide for more background. -```js +```mjs +import { nextTick } from 'process'; + +console.log('start'); +nextTick(() => { + console.log('nextTick callback'); +}); +console.log('scheduled'); +// Output: +// start +// scheduled +// nextTick callback +``` + +```cjs +const { nextTick } = require('process'); + console.log('start'); -process.nextTick(() => { +nextTick(() => { console.log('nextTick callback'); }); console.log('scheduled'); @@ -1684,11 +2297,30 @@ This is important when developing APIs in order to give users the opportunity to assign event handlers *after* an object has been constructed but before any I/O has occurred: -```js +```mjs +import { nextTick } from 'process'; + +function MyThing(options) { + this.setupOptions(options); + + nextTick(() => { + this.startDoingStuff(); + }); +} + +const thing = new MyThing(); +thing.getReadyForStuff(); + +// thing.startDoingStuff() gets called now, not before. +``` + +```cjs +const { nextTick } = require('process'); + function MyThing(options) { this.setupOptions(options); - process.nextTick(() => { + nextTick(() => { this.startDoingStuff(); }); } @@ -1730,10 +2362,25 @@ It is not clear whether `foo()` or `bar()` will be called first. The following approach is much better: -```js +```mjs +import { nextTick } from 'process'; + +function definitelyAsync(arg, cb) { + if (arg) { + nextTick(cb); + return; + } + + fs.stat('file', cb); +} +``` + +```cjs +const { nextTick } = require('process'); + function definitelyAsync(arg, cb) { if (arg) { - process.nextTick(cb); + nextTick(cb); return; } @@ -1749,10 +2396,24 @@ execute the then, catch, and finally handlers of resolved promises. Within Node.js, every time the "next tick queue" is drained, the microtask queue is drained immediately after. -```js +```mjs +import { nextTick } from 'process'; + +Promise.resolve().then(() => console.log(2)); +queueMicrotask(() => console.log(3)); +nextTick(() => console.log(1)); +// Output: +// 1 +// 2 +// 3 +``` + +```cjs +const { nextTick } = require('process'); + Promise.resolve().then(() => console.log(2)); queueMicrotask(() => console.log(3)); -process.nextTick(() => console.log(1)); +nextTick(() => console.log(1)); // Output: // 1 // 2 @@ -1827,8 +2488,16 @@ added: v0.1.15 The `process.pid` property returns the PID of the process. -```js -console.log(`This process is pid ${process.pid}`); +```mjs +import { pid } from 'process'; + +console.log(`This process is pid ${pid}`); +``` + +```cjs +const { pid } = require('process'); + +console.log(`This process is pid ${pid}`); ``` ## `process.platform` @@ -1851,8 +2520,16 @@ Currently possible values are: * `'sunos'` * `'win32'` -```js -console.log(`This platform is ${process.platform}`); +```mjs +import { platform } from 'process'; + +console.log(`This platform is ${platform}`); +``` + +```cjs +const { platform } = require('process'); + +console.log(`This platform is ${platform}`); ``` The value `'android'` may also be returned if the Node.js is built on the @@ -1872,8 +2549,16 @@ added: The `process.ppid` property returns the PID of the parent of the current process. -```js -console.log(`The parent process is pid ${process.ppid}`); +```mjs +import { ppid } from 'process'; + +console.log(`The parent process is pid ${ppid}`); +``` + +```cjs +const { ppid } = require('process'); + +console.log(`The parent process is pid ${ppid}`); ``` ## `process.release` @@ -1958,8 +2643,16 @@ Write reports in a compact format, single-line JSON, more easily consumable by log processing systems than the default multi-line format designed for human consumption. -```js -console.log(`Reports are compact? ${process.report.compact}`); +```mjs +import { report } from 'process'; + +console.log(`Reports are compact? ${report.compact}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Reports are compact? ${report.compact}`); ``` ### `process.report.directory` @@ -1979,8 +2672,16 @@ Directory where the report is written. The default value is the empty string, indicating that reports are written to the current working directory of the Node.js process. -```js -console.log(`Report directory is ${process.report.directory}`); +```mjs +import { report } from 'process'; + +console.log(`Report directory is ${report.directory}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Report directory is ${report.directory}`); ``` ### `process.report.filename` @@ -2000,8 +2701,16 @@ Filename where the report is written. If set to the empty string, the output filename will be comprised of a timestamp, PID, and sequence number. The default value is the empty string. -```js -console.log(`Report filename is ${process.report.filename}`); +```mjs +import { report } from 'process'; + +console.log(`Report filename is ${report.filename}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Report filename is ${report.filename}`); ``` ### `process.report.getReport([err])` @@ -2022,8 +2731,21 @@ Returns a JavaScript Object representation of a diagnostic report for the running process. The report's JavaScript stack trace is taken from `err`, if present. -```js -const data = process.report.getReport(); +```mjs +import { report } from 'process'; + +const data = report.getReport(); +console.log(data.header.nodejsVersion); + +// Similar to process.report.writeReport() +import fs from 'fs'; +fs.writeFileSync('my-report.log', util.inspect(data), 'utf8'); +``` + +```cjs +const { report } = require('process'); + +const data = report.getReport(); console.log(data.header.nodejsVersion); // Similar to process.report.writeReport() @@ -2049,8 +2771,16 @@ changes: If `true`, a diagnostic report is generated on fatal errors, such as out of memory errors or failed C++ assertions. -```js -console.log(`Report on fatal error: ${process.report.reportOnFatalError}`); +```mjs +import { report } from 'process'; + +console.log(`Report on fatal error: ${report.reportOnFatalError}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Report on fatal error: ${report.reportOnFatalError}`); ``` ### `process.report.reportOnSignal` @@ -2069,8 +2799,16 @@ changes: If `true`, a diagnostic report is generated when the process receives the signal specified by `process.report.signal`. -```js -console.log(`Report on signal: ${process.report.reportOnSignal}`); +```mjs +import { report } from 'process'; + +console.log(`Report on signal: ${report.reportOnSignal}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Report on signal: ${report.reportOnSignal}`); ``` ### `process.report.reportOnUncaughtException` @@ -2088,8 +2826,16 @@ changes: If `true`, a diagnostic report is generated on uncaught exception. -```js -console.log(`Report on exception: ${process.report.reportOnUncaughtException}`); +```mjs +import { report } from 'process'; + +console.log(`Report on exception: ${report.reportOnUncaughtException}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Report on exception: ${report.reportOnUncaughtException}`); ``` ### `process.report.signal` @@ -2108,8 +2854,16 @@ changes: The signal used to trigger the creation of a diagnostic report. Defaults to `'SIGUSR2'`. -```js -console.log(`Report signal: ${process.report.signal}`); +```mjs +import { report } from 'process'; + +console.log(`Report signal: ${report.signal}`); +``` + +```cjs +const { report } = require('process'); + +console.log(`Report signal: ${report.signal}`); ``` ### `process.report.writeReport([filename][, err])` @@ -2135,8 +2889,16 @@ Writes a diagnostic report to a file. If `filename` is not provided, the default filename includes the date, time, PID, and a sequence number. The report's JavaScript stack trace is taken from `err`, if present. -```js -process.report.writeReport(); +```mjs +import { report } from 'process'; + +report.writeReport(); +``` + +```cjs +const { report } = require('process'); + +report.writeReport(); ``` Additional documentation is available in the [report documentation][]. @@ -2189,8 +2951,37 @@ added: v12.6.0 process becoming runnable or because the current process exceeded its time slice. This field is not supported on Windows. -```js -console.log(process.resourceUsage()); +```mjs +import { resourceUsage } from 'process'; + +console.log(resourceUsage()); +/* + Will output: + { + userCPUTime: 82872, + systemCPUTime: 4143, + maxRSS: 33164, + sharedMemorySize: 0, + unsharedDataSize: 0, + unsharedStackSize: 0, + minorPageFault: 2469, + majorPageFault: 0, + swappedOut: 0, + fsRead: 0, + fsWrite: 8, + ipcSent: 0, + ipcReceived: 0, + signalsCount: 0, + voluntaryContextSwitches: 79, + involuntaryContextSwitches: 1 + } +*/ +``` + +```cjs +const { resourceUsage } = require('process'); + +console.log(resourceUsage()); /* Will output: { @@ -2251,7 +3042,23 @@ The `process.setegid()` method sets the effective group identity of the process. name string. If a group name is specified, this method blocks while resolving the associated a numeric ID. -```js +```mjs +import process from 'process'; + +if (process.getegid && process.setegid) { + console.log(`Current gid: ${process.getegid()}`); + try { + process.setegid(501); + console.log(`New gid: ${process.getegid()}`); + } catch (err) { + console.log(`Failed to set gid: ${err}`); + } +} +``` + +```cjs +const process = require('process'); + if (process.getegid && process.setegid) { console.log(`Current gid: ${process.getegid()}`); try { @@ -2279,7 +3086,23 @@ The `process.seteuid()` method sets the effective user identity of the process. string. If a username is specified, the method blocks while resolving the associated numeric ID. -```js +```mjs +import process from 'process'; + +if (process.geteuid && process.seteuid) { + console.log(`Current uid: ${process.geteuid()}`); + try { + process.seteuid(501); + console.log(`New uid: ${process.geteuid()}`); + } catch (err) { + console.log(`Failed to set uid: ${err}`); + } +} +``` + +```cjs +const process = require('process'); + if (process.geteuid && process.seteuid) { console.log(`Current uid: ${process.geteuid()}`); try { @@ -2307,7 +3130,23 @@ setgid(2).) The `id` can be passed as either a numeric ID or a group name string. If a group name is specified, this method blocks while resolving the associated numeric ID. -```js +```mjs +import process from 'process'; + +if (process.getgid && process.setgid) { + console.log(`Current gid: ${process.getgid()}`); + try { + process.setgid(501); + console.log(`New gid: ${process.getgid()}`); + } catch (err) { + console.log(`Failed to set gid: ${err}`); + } +} +``` + +```cjs +const process = require('process'); + if (process.getgid && process.setgid) { console.log(`Current gid: ${process.getgid()}`); try { @@ -2336,7 +3175,22 @@ process to have `root` or the `CAP_SETGID` capability. The `groups` array can contain numeric group IDs, group names, or both. -```js +```mjs +import process from 'process'; + +if (process.getgroups && process.setgroups) { + try { + process.setgroups([501]); + console.log(process.getgroups()); // new groups + } catch (err) { + console.log(`Failed to set groups: ${err}`); + } +} +``` + +```cjs +const process = require('process'); + if (process.getgroups && process.setgroups) { try { process.setgroups([501]); @@ -2363,7 +3217,23 @@ setuid(2).) The `id` can be passed as either a numeric ID or a username string. If a username is specified, the method blocks while resolving the associated numeric ID. -```js +```mjs +import process from 'process'; + +if (process.getuid && process.setuid) { + console.log(`Current uid: ${process.getuid()}`); + try { + process.setuid(501); + console.log(`New uid: ${process.getuid()}`); + } catch (err) { + console.log(`Failed to set uid: ${err}`); + } +} +``` + +```cjs +const process = require('process'); + if (process.getuid && process.setuid) { console.log(`Current uid: ${process.getuid()}`); try { @@ -2462,8 +3332,16 @@ a [Writable][] stream. For example, to copy `process.stdin` to `process.stdout`: -```js -process.stdin.pipe(process.stdout); +```mjs +import { stdin, stdout } from 'process'; + +stdin.pipe(stdout); +``` + +```cjs +const { stdin, stdout } = require('process'); + +stdin.pipe(stdout); ``` `process.stdout` differs from other Node.js streams in important ways. See @@ -2622,9 +3500,21 @@ added: v0.1.19 `process.umask(mask)` sets the Node.js process's file mode creation mask. Child processes inherit the mask from the parent process. Returns the previous mask. -```js +```mjs +import { umask } from 'process'; + +const newmask = 0o022; +const oldmask = umask(newmask); +console.log( + `Changed umask from ${oldmask.toString(8)} to ${newmask.toString(8)}` +); +``` + +```cjs +const { umask } = require('process'); + const newmask = 0o022; -const oldmask = process.umask(newmask); +const oldmask = umask(newmask); console.log( `Changed umask from ${oldmask.toString(8)} to ${newmask.toString(8)}` ); @@ -2654,8 +3544,17 @@ added: v0.1.3 The `process.version` property contains the Node.js version string. -```js -console.log(`Version: ${process.version}`); +```mjs +import { version } from 'process'; + +console.log(`Version: ${version}`); +// Version: v14.8.0 +``` + +```cjs +const { version } = require('process'); + +console.log(`Version: ${version}`); // Version: v14.8.0 ``` @@ -2681,8 +3580,16 @@ Node.js and its dependencies. `process.versions.modules` indicates the current ABI version, which is increased whenever a C++ API changes. Node.js will refuse to load modules that were compiled against a different module ABI version. -```js -console.log(process.versions); +```mjs +import { versions } from 'process'; + +console.log(versions); +``` + +```cjs +const { versions } = require('process'); + +console.log(versions); ``` Will generate an object similar to: diff --git a/doc/api/wasi.md b/doc/api/wasi.md index d5213b9c9eb460..58c310edd82585 100644 --- a/doc/api/wasi.md +++ b/doc/api/wasi.md @@ -13,10 +13,11 @@ underlying operating system via a collection of POSIX-like functions. ```mjs import fs from 'fs'; import { WASI } from 'wasi'; +import { argv, env } from 'process'; const wasi = new WASI({ - args: process.argv, - env: process.env, + args: argv, + env, preopens: { '/sandbox': '/some/real/path/that/wasm/can/access' } @@ -33,9 +34,11 @@ wasi.start(instance); 'use strict'; const fs = require('fs'); const { WASI } = require('wasi'); +const { argv, env } = require('process'); + const wasi = new WASI({ - args: process.argv, - env: process.env, + args: argv, + env, preopens: { '/sandbox': '/some/real/path/that/wasm/can/access' }