About this documentation#

Welcome to the official API reference documentation for Node.js!

Node.js is a JavaScript runtime built on the V8 JavaScript engine.

Contributing#

Report errors in this documentation in the issue tracker. See the contributing guide for directions on how to submit pull requests.

Stability index#

Throughout the documentation are indications of a section's stability. Some APIs are so proven and so relied upon that they are unlikely to ever change at all. Others are brand new and experimental, or known to be hazardous.

The stability indexes are as follows:

Stability: 0 - Deprecated. The feature may emit warnings. Backward compatibility is not guaranteed.

Stability: 1 - Experimental. The feature is not subject to semantic versioning rules. Non-backward compatible changes or removal may occur in any future release. Use of the feature is not recommended in production environments.

Experimental features are subdivided into stages:

  • 1.0 - Early development. Experimental features at this stage are unfinished and subject to substantial change.
  • 1.1 - Active development. Experimental features at this stage are nearing minimum viability.
  • 1.2 - Release candidate. Experimental features at this stage are hopefully ready to become stable. No further breaking changes are anticipated but may still occur in response to user feedback. We encourage user testing and feedback so that we can know that this feature is ready to be marked as stable.

Experimental features leave the experimental status typically either by graduating to stable, or are removed without a deprecation cycle.

Stability: 2 - Stable. Compatibility with the npm ecosystem is a high priority.

Stability: 3 - Legacy. Although this feature is unlikely to be removed and is still covered by semantic versioning guarantees, it is no longer actively maintained, and other alternatives are available.

Features are marked as legacy rather than being deprecated if their use does no harm, and they are widely relied upon within the npm ecosystem. Bugs found in legacy features are unlikely to be fixed.

Use caution when making use of Experimental features, particularly when authoring libraries. Users may not be aware that experimental features are being used. Bugs or behavior changes may surprise users when Experimental API modifications occur. To avoid surprises, use of an Experimental feature may need a command-line flag. Experimental features may also emit a warning.

Stability overview#

JSON output#

Every .html document has a corresponding .json document. This is for IDEs and other utilities that consume the documentation.

System calls and man pages#

Node.js functions which wrap a system call will document that. The docs link to the corresponding man pages which describe how the system call works.

Most Unix system calls have Windows analogues. Still, behavior differences may be unavoidable.

Usage and example#

Usage#

node [options] [V8 options] [script.js | -e "script" | - ] [arguments]

Please see the Command-line options document for more information.

Example#

An example of a web server written with Node.js which responds with 'Hello, World!':

Commands in this document start with $ or > to replicate how they would appear in a user's terminal. Do not include the $ and > characters. They are there to show the start of each command.

Lines that don't start with $ or > character show the output of the previous command.

First, make sure to have downloaded and installed Node.js. See Installing Node.js via package manager for further install information.

Now, create an empty project folder called projects, then navigate into it.

Linux and Mac:

mkdir ~/projects
cd ~/projects 

Windows CMD:

mkdir %USERPROFILE%\projects
cd %USERPROFILE%\projects 

Windows PowerShell:

mkdir $env:USERPROFILE\projects
cd $env:USERPROFILE\projects 

Next, create a new source file in the projects folder and call it hello-world.js.

Open hello-world.js in any preferred text editor and paste in the following content:

const http = require('node:http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
}); 

Save the file. Then, in the terminal window, to run the hello-world.js file, enter:

node hello-world.js 

Output like this should appear in the terminal:

Server running at http://127.0.0.1:3000/ 

Now, open any preferred web browser and visit http://127.0.0.1:3000.

If the browser displays the string Hello, World!, that indicates the server is working.

Assert#

Stability: 2 - Stable

Source Code: lib/assert.js

The node:assert module provides a set of assertion functions for verifying invariants.

Strict assertion mode#

In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, assert.deepEqual() will behave like assert.deepStrictEqual().

In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated.

To use strict assertion mode:

import { strict as assert } from 'node:assert';const assert = require('node:assert').strict;
import assert from 'node:assert/strict';const assert = require('node:assert/strict');

Example error diff:

import { strict as assert } from 'node:assert';

assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected ... Lines skipped
//
//   [
//     [
// ...
//       2,
// +     3
// -     '3'
//     ],
// ...
//     5
//   ]const assert = require('node:assert/strict');

assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected ... Lines skipped
//
//   [
//     [
// ...
//       2,
// +     3
// -     '3'
//     ],
// ...
//     5
//   ]

To deactivate the colors, use the NO_COLOR or NODE_DISABLE_COLORS environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty getColorDepth() documentation.

Legacy assertion mode#

Legacy assertion mode uses the == operator in:

To use legacy assertion mode:

import assert from 'node:assert';const assert = require('node:assert');

Legacy assertion mode may have surprising results, especially when using assert.deepEqual():

// WARNING: This does not throw an AssertionError in legacy assertion mode!
assert.deepEqual(/a/gi, new Date()); 

Class: assert.AssertionError[src]#

Indicates the failure of an assertion. All errors thrown by the node:assert module will be instances of the AssertionError class.

new assert.AssertionError(options)#

  • options <Object>
    • message <string> If provided, the error message is set to this value.
    • actual <any> The actual property on the error instance.
    • expected <any> The expected property on the error instance.
    • operator <string> The operator property on the error instance.
    • stackStartFn <Function> If provided, the generated stack trace omits frames before this function.

A subclass of <Error> that indicates the failure of an assertion.

All instances contain the built-in Error properties (message and name) and:

  • actual <any> Set to the actual argument for methods such as assert.strictEqual().
  • expected <any> Set to the expected value for methods such as assert.strictEqual().
  • generatedMessage <boolean> Indicates if the message was auto-generated (true) or not.
  • code <string> Value is always ERR_ASSERTION to show that the error is an assertion error.
  • operator <string> Set to the passed in operator value.
import assert from 'node:assert';

// Generate an AssertionError to compare the error message later:
const { message } = new assert.AssertionError({
  actual: 1,
  expected: 2,
  operator: 'strictEqual',
});

// Verify error output:
try {
  assert.strictEqual(1, 2);
} catch (err) {
  assert(err instanceof assert.AssertionError);
  assert.strictEqual(err.message, message);
  assert.strictEqual(err.name, 'AssertionError');
  assert.strictEqual(err.actual, 1);
  assert.strictEqual(err.expected, 2);
  assert.strictEqual(err.code, 'ERR_ASSERTION');
  assert.strictEqual(err.operator, 'strictEqual');
  assert.strictEqual(err.generatedMessage, true);
}const assert = require('node:assert');

// Generate an AssertionError to compare the error message later:
const { message } = new assert.AssertionError({
  actual: 1,
  expected: 2,
  operator: 'strictEqual',
});

// Verify error output:
try {
  assert.strictEqual(1, 2);
} catch (err) {
  assert(err instanceof assert.AssertionError);
  assert.strictEqual(err.message, message);
  assert.strictEqual(err.name, 'AssertionError');
  assert.strictEqual(err.actual, 1);
  assert.strictEqual(err.expected, 2);
  assert.strictEqual(err.code, 'ERR_ASSERTION');
  assert.strictEqual(err.operator, 'strictEqual');
  assert.strictEqual(err.generatedMessage, true);
}

Class: assert.CallTracker#

Stability: 0 - Deprecated

This feature is deprecated and will be removed in a future version. Please consider using alternatives such as the mock helper function.

new assert.CallTracker()#

Creates a new CallTracker object which can be used to track if functions were called a specific number of times. The tracker.verify() must be called for the verification to take place. The usual pattern would be to call it in a process.on('exit') handler.

import assert from 'node:assert';
import process from 'node:process';

const tracker = new assert.CallTracker();

function func() {}

// callsfunc() must be called exactly 1 time before tracker.verify().
const callsfunc = tracker.calls(func, 1);

callsfunc();

// Calls tracker.verify() and verifies if all tracker.calls() functions have
// been called exact times.
process.on('exit', () => {
  tracker.verify();
});const assert = require('node:assert');
const process = require('node:process');

const tracker = new assert.CallTracker();

function func() {}

// callsfunc() must be called exactly 1 time before tracker.verify().
const callsfunc = tracker.calls(func, 1);

callsfunc();

// Calls tracker.verify() and verifies if all tracker.calls() functions have
// been called exact times.
process.on('exit', () => {
  tracker.verify();
});

tracker.calls([fn][, exact])#

The wrapper function is expected to be called exactly exact times. If the function has not been called exactly exact times when tracker.verify() is called, then tracker.verify() will throw an error.

import assert from 'node:assert';

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}

// Returns a function that wraps func() that must be called exact times
// before tracker.verify().
const callsfunc = tracker.calls(func);const assert = require('node:assert');

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}

// Returns a function that wraps func() that must be called exact times
// before tracker.verify().
const callsfunc = tracker.calls(func);

tracker.getCalls(fn)#

import assert from 'node:assert';

const tracker = new assert.CallTracker();

function func() {}
const callsfunc = tracker.calls(func);
callsfunc(1, 2, 3);

assert.deepStrictEqual(tracker.getCalls(callsfunc),
                       [{ thisArg: undefined, arguments: [1, 2, 3] }]);const assert = require('node:assert');

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}
const callsfunc = tracker.calls(func);
callsfunc(1, 2, 3);

assert.deepStrictEqual(tracker.getCalls(callsfunc),
                       [{ thisArg: undefined, arguments: [1, 2, 3] }]);

tracker.report()#

  • Returns: <Array> An array of objects containing information about the wrapper functions returned by tracker.calls().
  • Object <Object>
    • message <string>
    • actual <number> The actual number of times the function was called.
    • expected <number> The number of times the function was expected to be called.
    • operator <string> The name of the function that is wrapped.
    • stack <Object> A stack trace of the function.

The arrays contains information about the expected and actual number of calls of the functions that have not been called the expected number of times.

import assert from 'node:assert';

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}

// Returns a function that wraps func() that must be called exact times
// before tracker.verify().
const callsfunc = tracker.calls(func, 2);

// Returns an array containing information on callsfunc()
console.log(tracker.report());
// [
//  {
//    message: 'Expected the func function to be executed 2 time(s) but was
//    executed 0 time(s).',
//    actual: 0,
//    expected: 2,
//    operator: 'func',
//    stack: stack trace
//  }
// ]const assert = require('node:assert');

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}

// Returns a function that wraps func() that must be called exact times
// before tracker.verify().
const callsfunc = tracker.calls(func, 2);

// Returns an array containing information on callsfunc()
console.log(tracker.report());
// [
//  {
//    message: 'Expected the func function to be executed 2 time(s) but was
//    executed 0 time(s).',
//    actual: 0,
//    expected: 2,
//    operator: 'func',
//    stack: stack trace
//  }
// ]

tracker.reset([fn])#

Reset calls of the call tracker. If a tracked function is passed as an argument, the calls will be reset for it. If no arguments are passed, all tracked functions will be reset.

import assert from 'node:assert';

const tracker = new assert.CallTracker();

function func() {}
const callsfunc = tracker.calls(func);

callsfunc();
// Tracker was called once
assert.strictEqual(tracker.getCalls(callsfunc).length, 1);

tracker.reset(callsfunc);
assert.strictEqual(tracker.getCalls(callsfunc).length, 0);const assert = require('node:assert');

const tracker = new assert.CallTracker();

function func() {}
const callsfunc = tracker.calls(func);

callsfunc();
// Tracker was called once
assert.strictEqual(tracker.getCalls(callsfunc).length, 1);

tracker.reset(callsfunc);
assert.strictEqual(tracker.getCalls(callsfunc).length, 0);

tracker.verify()#

Iterates through the list of functions passed to tracker.calls() and will throw an error for functions that have not been called the expected number of times.

import assert from 'node:assert';

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}

// Returns a function that wraps func() that must be called exact times
// before tracker.verify().
const callsfunc = tracker.calls(func, 2);

callsfunc();

// Will throw an error since callsfunc() was only called once.
tracker.verify();const assert = require('node:assert');

// Creates call tracker.
const tracker = new assert.CallTracker();

function func() {}

// Returns a function that wraps func() that must be called exact times
// before tracker.verify().
const callsfunc = tracker.calls(func, 2);

callsfunc();

// Will throw an error since callsfunc() was only called once.
tracker.verify();

assert(value[, message])#

An alias of assert.ok().

assert.deepEqual(actual, expected[, message])#

Strict assertion mode

An alias of assert.deepStrictEqual().

Legacy assertion mode

Stability: 3 - Legacy: Use assert.deepStrictEqual() instead.

Tests for deep equality between the actual and expected parameters. Consider using assert.deepStrictEqual() instead. assert.deepEqual() can have surprising results.

Deep equality means that the enumerable "own" properties of child objects are also recursively evaluated by the following rules.

Comparison details#

  • Primitive values are compared with the == operator, with the exception of <NaN>. It is treated as being identical in case both sides are <NaN>.
  • Type tags of objects should be the same.
  • Only enumerable "own" properties are considered.
  • <Error> names, messages, causes, and errors are always compared, even if these are not enumerable properties.
  • Object wrappers are compared both as objects and unwrapped values.
  • Object properties are compared unordered.
  • <Map> keys and <Set> items are compared unordered.
  • Recursion stops when both sides differ or either side encounters a circular reference.
  • Implementation does not test the [[Prototype]] of objects.
  • <Symbol> properties are not compared.
  • <WeakMap> and <WeakSet> comparison does not rely on their values but only on their instances.
  • <RegExp> lastIndex, flags, and source are always compared, even if these are not enumerable properties.

The following example does not throw an AssertionError because the primitives are compared using the == operator.

import assert from 'node:assert';
// WARNING: This does not throw an AssertionError!

assert.deepEqual('+00000000', false);const assert = require('node:assert');
// WARNING: This does not throw an AssertionError!

assert.deepEqual('+00000000', false);

"Deep" equality means that the enumerable "own" properties of child objects are evaluated also:

import assert from 'node:assert';

const obj1 = {
  a: {
    b: 1,
  },
};
const obj2 = {
  a: {
    b: 2,
  },
};
const obj3 = {
  a: {
    b: 1,
  },
};
const obj4 = { __proto__: obj1 };

assert.deepEqual(obj1, obj1);
// OK

// Values of b are different:
assert.deepEqual(obj1, obj2);
// AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }

assert.deepEqual(obj1, obj3);
// OK

// Prototypes are ignored:
assert.deepEqual(obj1, obj4);
// AssertionError: { a: { b: 1 } } deepEqual {}const assert = require('node:assert');

const obj1 = {
  a: {
    b: 1,
  },
};
const obj2 = {
  a: {
    b: 2,
  },
};
const obj3 = {
  a: {
    b: 1,
  },
};
const obj4 = { __proto__: obj1 };

assert.deepEqual(obj1, obj1);
// OK

// Values of b are different:
assert.deepEqual(obj1, obj2);
// AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }

assert.deepEqual(obj1, obj3);
// OK

// Prototypes are ignored:
assert.deepEqual(obj1, obj4);
// AssertionError: { a: { b: 1 } } deepEqual {}

If the values are not equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.deepStrictEqual(actual, expected[, message])#

Tests for deep equality between the actual and expected parameters. "Deep" equality means that the enumerable "own" properties of child objects are recursively evaluated also by the following rules.

Comparison details#

  • Primitive values are compared using Object.is().
  • Type tags of objects should be the same.
  • [[Prototype]] of objects are compared using the === operator.
  • Only enumerable "own" properties are considered.
  • <Error> names, messages, causes, and errors are always compared, even if these are not enumerable properties. errors is also compared.
  • Enumerable own <Symbol> properties are compared as well.
  • Object wrappers are compared both as objects and unwrapped values.
  • Object properties are compared unordered.
  • <Map> keys and <Set> items are compared unordered.
  • Recursion stops when both sides differ or either side encounters a circular reference.
  • <WeakMap> and <WeakSet> instances are not compared structurally. They are only equal if they reference the same object. Any comparison between different WeakMap or WeakSet instances will result in inequality, even if they contain the same entries.
  • <RegExp> lastIndex, flags, and source are always compared, even if these are not enumerable properties.
import assert from 'node:assert/strict';

// This fails because 1 !== '1'.
assert.deepStrictEqual({ a: 1 }, { a: '1' });
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
//   {
// +   a: 1
// -   a: '1'
//   }

// The following objects don't have own properties
const date = new Date();
const object = {};
const fakeDate = {};
Object.setPrototypeOf(fakeDate, Date.prototype);

// Different [[Prototype]]:
assert.deepStrictEqual(object, fakeDate);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + {}
// - Date {}

// Different type tags:
assert.deepStrictEqual(date, fakeDate);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 2018-04-26T00:49:08.604Z
// - Date {}

assert.deepStrictEqual(NaN, NaN);
// OK because Object.is(NaN, NaN) is true.

// Different unwrapped numbers:
assert.deepStrictEqual(new Number(1), new Number(2));
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + [Number: 1]
// - [Number: 2]

assert.deepStrictEqual(new String('foo'), Object('foo'));
// OK because the object and the string are identical when unwrapped.

assert.deepStrictEqual(-0, -0);
// OK

// Different zeros:
assert.deepStrictEqual(0, -0);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 0
// - -0

const symbol1 = Symbol();
const symbol2 = Symbol();
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol1]: 1 });
// OK, because it is the same symbol on both objects.

assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 });
// AssertionError [ERR_ASSERTION]: Inputs identical but not reference equal:
//
// {
//   Symbol(): 1
// }

const weakMap1 = new WeakMap();
const weakMap2 = new WeakMap();
const obj = {};

weakMap1.set(obj, 'value');
weakMap2.set(obj, 'value');

// Comparing different instances fails, even with same contents
assert.deepStrictEqual(weakMap1, weakMap2);
// AssertionError: Values have same structure but are not reference-equal:
//
// WeakMap {
//   <items unknown>
// }

// Comparing the same instance to itself succeeds
assert.deepStrictEqual(weakMap1, weakMap1);
// OK

const weakSet1 = new WeakSet();
const weakSet2 = new WeakSet();
weakSet1.add(obj);
weakSet2.add(obj);

// Comparing different instances fails, even with same contents
assert.deepStrictEqual(weakSet1, weakSet2);
// AssertionError: Values have same structure but are not reference-equal:
// + actual - expected
//
// WeakSet {
//   <items unknown>
// }

// Comparing the same instance to itself succeeds
assert.deepStrictEqual(weakSet1, weakSet1);
// OKconst assert = require('node:assert/strict');

// This fails because 1 !== '1'.
assert.deepStrictEqual({ a: 1 }, { a: '1' });
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
//   {
// +   a: 1
// -   a: '1'
//   }

// The following objects don't have own properties
const date = new Date();
const object = {};
const fakeDate = {};
Object.setPrototypeOf(fakeDate, Date.prototype);

// Different [[Prototype]]:
assert.deepStrictEqual(object, fakeDate);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + {}
// - Date {}

// Different type tags:
assert.deepStrictEqual(date, fakeDate);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 2018-04-26T00:49:08.604Z
// - Date {}

assert.deepStrictEqual(NaN, NaN);
// OK because Object.is(NaN, NaN) is true.

// Different unwrapped numbers:
assert.deepStrictEqual(new Number(1), new Number(2));
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + [Number: 1]
// - [Number: 2]

assert.deepStrictEqual(new String('foo'), Object('foo'));
// OK because the object and the string are identical when unwrapped.

assert.deepStrictEqual(-0, -0);
// OK

// Different zeros:
assert.deepStrictEqual(0, -0);
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 0
// - -0

const symbol1 = Symbol();
const symbol2 = Symbol();
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol1]: 1 });
// OK, because it is the same symbol on both objects.

assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 });
// AssertionError [ERR_ASSERTION]: Inputs identical but not reference equal:
//
// {
//   Symbol(): 1
// }

const weakMap1 = new WeakMap();
const weakMap2 = new WeakMap();
const obj = {};

weakMap1.set(obj, 'value');
weakMap2.set(obj, 'value');

// Comparing different instances fails, even with same contents
assert.deepStrictEqual(weakMap1, weakMap2);
// AssertionError: Values have same structure but are not reference-equal:
//
// WeakMap {
//   <items unknown>
// }

// Comparing the same instance to itself succeeds
assert.deepStrictEqual(weakMap1, weakMap1);
// OK

const weakSet1 = new WeakSet();
const weakSet2 = new WeakSet();
weakSet1.add(obj);
weakSet2.add(obj);

// Comparing different instances fails, even with same contents
assert.deepStrictEqual(weakSet1, weakSet2);
// AssertionError: Values have same structure but are not reference-equal:
// + actual - expected
//
// WeakSet {
//   <items unknown>
// }

// Comparing the same instance to itself succeeds
assert.deepStrictEqual(weakSet1, weakSet1);
// OK

If the values are not equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.doesNotMatch(string, regexp[, message])#

Expects the string input not to match the regular expression.

import assert from 'node:assert/strict';

assert.doesNotMatch('I will fail', /fail/);
// AssertionError [ERR_ASSERTION]: The input was expected to not match the ...

assert.doesNotMatch(123, /pass/);
// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string.

assert.doesNotMatch('I will pass', /different/);
// OKconst assert = require('node:assert/strict');

assert.doesNotMatch('I will fail', /fail/);
// AssertionError [ERR_ASSERTION]: The input was expected to not match the ...

assert.doesNotMatch(123, /pass/);
// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string.

assert.doesNotMatch('I will pass', /different/);
// OK

If the values do match, or if the string argument is of another type than string, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.doesNotReject(asyncFn[, error][, message])#

Awaits the asyncFn promise or, if asyncFn is a function, immediately calls the function and awaits the returned promise to complete. It will then check that the promise is not rejected.

If asyncFn is a function and it throws an error synchronously, assert.doesNotReject() will return a rejected Promise with that error. If the function does not return a promise, assert.doesNotReject() will return a rejected Promise with an ERR_INVALID_RETURN_VALUE error. In both cases the error handler is skipped.

Using assert.doesNotReject() is actually not useful because there is little benefit in catching a rejection and then rejecting it again. Instead, consider adding a comment next to the specific code path that should not reject and keep error messages as expressive as possible.

If specified, error can be a Class, <RegExp> or a validation function. See assert.throws() for more details.

Besides the async nature to await the completion behaves identically to assert.doesNotThrow().

import assert from 'node:assert/strict';

await assert.doesNotReject(
  async () => {
    throw new TypeError('Wrong value');
  },
  SyntaxError,
);const assert = require('node:assert/strict');

(async () => {
  await assert.doesNotReject(
    async () => {
      throw new TypeError('Wrong value');
    },
    SyntaxError,
  );
})();
import assert from 'node:assert/strict';

assert.doesNotReject(Promise.reject(new TypeError('Wrong value')))
  .then(() => {
    // ...
  });const assert = require('node:assert/strict');

assert.doesNotReject(Promise.reject(new TypeError('Wrong value')))
  .then(() => {
    // ...
  });

assert.doesNotThrow(fn[, error][, message])#

Asserts that the function fn does not throw an error.

Using assert.doesNotThrow() is actually not useful because there is no benefit in catching an error and then rethrowing it. Instead, consider adding a comment next to the specific code path that should not throw and keep error messages as expressive as possible.

When assert.doesNotThrow() is called, it will immediately call the fn function.

If an error is thrown and it is the same type as that specified by the error parameter, then an AssertionError is thrown. If the error is of a different type, or if the error parameter is undefined, the error is propagated back to the caller.

If specified, error can be a Class, <RegExp>, or a validation function. See assert.throws() for more details.

The following, for instance, will throw the <TypeError> because there is no matching error type in the assertion:

import assert from 'node:assert/strict';

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  SyntaxError,
);const assert = require('node:assert/strict');

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  SyntaxError,
);

However, the following will result in an AssertionError with the message 'Got unwanted exception...':

import assert from 'node:assert/strict';

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  TypeError,
);const assert = require('node:assert/strict');

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  TypeError,
);

If an AssertionError is thrown and a value is provided for the message parameter, the value of message will be appended to the AssertionError message:

import assert from 'node:assert/strict';

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  /Wrong value/,
  'Whoops',
);
// Throws: AssertionError: Got unwanted exception: Whoopsconst assert = require('node:assert/strict');

assert.doesNotThrow(
  () => {
    throw new TypeError('Wrong value');
  },
  /Wrong value/,
  'Whoops',
);
// Throws: AssertionError: Got unwanted exception: Whoops

assert.equal(actual, expected[, message])#

Strict assertion mode

An alias of assert.strictEqual().

Legacy assertion mode

Stability: 3 - Legacy: Use assert.strictEqual() instead.

Tests shallow, coercive equality between the actual and expected parameters using the == operator. NaN is specially handled and treated as being identical if both sides are NaN.

import assert from 'node:assert';

assert.equal(1, 1);
// OK, 1 == 1
assert.equal(1, '1');
// OK, 1 == '1'
assert.equal(NaN, NaN);
// OK

assert.equal(1, 2);
// AssertionError: 1 == 2
assert.equal({ a: { b: 1 } }, { a: { b: 1 } });
// AssertionError: { a: { b: 1 } } == { a: { b: 1 } }const assert = require('node:assert');

assert.equal(1, 1);
// OK, 1 == 1
assert.equal(1, '1');
// OK, 1 == '1'
assert.equal(NaN, NaN);
// OK

assert.equal(1, 2);
// AssertionError: 1 == 2
assert.equal({ a: { b: 1 } }, { a: { b: 1 } });
// AssertionError: { a: { b: 1 } } == { a: { b: 1 } }

If the values are not equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.fail([message])#

Throws an AssertionError with the provided error message or a default error message. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

import assert from 'node:assert/strict';

assert.fail();
// AssertionError [ERR_ASSERTION]: Failed

assert.fail('boom');
// AssertionError [ERR_ASSERTION]: boom

assert.fail(new TypeError('need array'));
// TypeError: need arrayconst assert = require('node:assert/strict');

assert.fail();
// AssertionError [ERR_ASSERTION]: Failed

assert.fail('boom');
// AssertionError [ERR_ASSERTION]: boom

assert.fail(new TypeError('need array'));
// TypeError: need array

Using assert.fail() with more than two arguments is possible but deprecated. See below for further details.

assert.fail(actual, expected[, message[, operator[, stackStartFn]]])#

Stability: 0 - Deprecated: Use assert.fail([message]) or other assert functions instead.

If message is falsy, the error message is set as the values of actual and expected separated by the provided operator. If just the two actual and expected arguments are provided, operator will default to '!='. If message is provided as third argument it will be used as the error message and the other arguments will be stored as properties on the thrown object. If stackStartFn is provided, all stack frames above that function will be removed from stacktrace (see Error.captureStackTrace). If no arguments are given, the default message Failed will be used.

import assert from 'node:assert/strict';

assert.fail('a', 'b');
// AssertionError [ERR_ASSERTION]: 'a' != 'b'

assert.fail(1, 2, undefined, '>');
// AssertionError [ERR_ASSERTION]: 1 > 2

assert.fail(1, 2, 'fail');
// AssertionError [ERR_ASSERTION]: fail

assert.fail(1, 2, 'whoops', '>');
// AssertionError [ERR_ASSERTION]: whoops

assert.fail(1, 2, new TypeError('need array'));
// TypeError: need arrayconst assert = require('node:assert/strict');

assert.fail('a', 'b');
// AssertionError [ERR_ASSERTION]: 'a' != 'b'

assert.fail(1, 2, undefined, '>');
// AssertionError [ERR_ASSERTION]: 1 > 2

assert.fail(1, 2, 'fail');
// AssertionError [ERR_ASSERTION]: fail

assert.fail(1, 2, 'whoops', '>');
// AssertionError [ERR_ASSERTION]: whoops

assert.fail(1, 2, new TypeError('need array'));
// TypeError: need array

In the last three cases actual, expected, and operator have no influence on the error message.

Example use of stackStartFn for truncating the exception's stacktrace:

import assert from 'node:assert/strict';

function suppressFrame() {
  assert.fail('a', 'b', undefined, '!==', suppressFrame);
}
suppressFrame();
// AssertionError [ERR_ASSERTION]: 'a' !== 'b'
//     at repl:1:1
//     at ContextifyScript.Script.runInThisContext (vm.js:44:33)
//     ...const assert = require('node:assert/strict');

function suppressFrame() {
  assert.fail('a', 'b', undefined, '!==', suppressFrame);
}
suppressFrame();
// AssertionError [ERR_ASSERTION]: 'a' !== 'b'
//     at repl:1:1
//     at ContextifyScript.Script.runInThisContext (vm.js:44:33)
//     ...

assert.ifError(value)#

Throws value if value is not undefined or null. This is useful when testing the error argument in callbacks. The stack trace contains all frames from the error passed to ifError() including the potential new frames for ifError() itself.

import assert from 'node:assert/strict';

assert.ifError(null);
// OK
assert.ifError(0);
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0
assert.ifError('error');
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 'error'
assert.ifError(new Error());
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error

// Create some random error frames.
let err;
(function errorFrame() {
  err = new Error('test error');
})();

(function ifErrorFrame() {
  assert.ifError(err);
})();
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error
//     at ifErrorFrame
//     at errorFrameconst assert = require('node:assert/strict');

assert.ifError(null);
// OK
assert.ifError(0);
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0
assert.ifError('error');
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 'error'
assert.ifError(new Error());
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error

// Create some random error frames.
let err;
(function errorFrame() {
  err = new Error('test error');
})();

(function ifErrorFrame() {
  assert.ifError(err);
})();
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error
//     at ifErrorFrame
//     at errorFrame

assert.match(string, regexp[, message])#

Expects the string input to match the regular expression.

import assert from 'node:assert/strict';

assert.match('I will fail', /pass/);
// AssertionError [ERR_ASSERTION]: The input did not match the regular ...

assert.match(123, /pass/);
// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string.

assert.match('I will pass', /pass/);
// OKconst assert = require('node:assert/strict');

assert.match('I will fail', /pass/);
// AssertionError [ERR_ASSERTION]: The input did not match the regular ...

assert.match(123, /pass/);
// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string.

assert.match('I will pass', /pass/);
// OK

If the values do not match, or if the string argument is of another type than string, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.notDeepEqual(actual, expected[, message])#

Strict assertion mode

An alias of assert.notDeepStrictEqual().

Legacy assertion mode

Tests for any deep inequality. Opposite of assert.deepEqual().

import assert from 'node:assert';

const obj1 = {
  a: {
    b: 1,
  },
};
const obj2 = {
  a: {
    b: 2,
  },
};
const obj3 = {
  a: {
    b: 1,
  },
};
const obj4 = { __proto__: obj1 };

assert.notDeepEqual(obj1, obj1);
// AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

assert.notDeepEqual(obj1, obj2);
// OK

assert.notDeepEqual(obj1, obj3);
// AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

assert.notDeepEqual(obj1, obj4);
// OKconst assert = require('node:assert');

const obj1 = {
  a: {
    b: 1,
  },
};
const obj2 = {
  a: {
    b: 2,
  },
};
const obj3 = {
  a: {
    b: 1,
  },
};
const obj4 = { __proto__: obj1 };

assert.notDeepEqual(obj1, obj1);
// AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

assert.notDeepEqual(obj1, obj2);
// OK

assert.notDeepEqual(obj1, obj3);
// AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }

assert.notDeepEqual(obj1, obj4);
// OK

If the values are deeply equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.notDeepStrictEqual(actual, expected[, message])#

Tests for deep strict inequality. Opposite of assert.deepStrictEqual().

import assert from 'node:assert/strict';

assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// OKconst assert = require('node:assert/strict');

assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
// OK

If the values are deeply and strictly equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.notEqual(actual, expected[, message])#

Strict assertion mode

An alias of assert.notStrictEqual().

Legacy assertion mode

Stability: 3 - Legacy: Use assert.notStrictEqual() instead.

Tests shallow, coercive inequality with the != operator. NaN is specially handled and treated as being identical if both sides are NaN.

import assert from 'node:assert';

assert.notEqual(1, 2);
// OK

assert.notEqual(1, 1);
// AssertionError: 1 != 1

assert.notEqual(1, '1');
// AssertionError: 1 != '1'const assert = require('node:assert');

assert.notEqual(1, 2);
// OK

assert.notEqual(1, 1);
// AssertionError: 1 != 1

assert.notEqual(1, '1');
// AssertionError: 1 != '1'

If the values are equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.notStrictEqual(actual, expected[, message])#

Tests strict inequality between the actual and expected parameters as determined by Object.is().

import assert from 'node:assert/strict';

assert.notStrictEqual(1, 2);
// OK

assert.notStrictEqual(1, 1);
// AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to:
//
// 1

assert.notStrictEqual(1, '1');
// OKconst assert = require('node:assert/strict');

assert.notStrictEqual(1, 2);
// OK

assert.notStrictEqual(1, 1);
// AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to:
//
// 1

assert.notStrictEqual(1, '1');
// OK

If the values are strictly equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.ok(value[, message])#

Tests if value is truthy. It is equivalent to assert.equal(!!value, true, message).

If value is not truthy, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError. If no arguments are passed in at all message will be set to the string: 'No value argument passed to `assert.ok()`'.

Be aware that in the repl the error message will be different to the one thrown in a file! See below for further details.

import assert from 'node:assert/strict';

assert.ok(true);
// OK
assert.ok(1);
// OK

assert.ok();
// AssertionError: No value argument passed to `assert.ok()`

assert.ok(false, 'it\'s false');
// AssertionError: it's false

// In the repl:
assert.ok(typeof 123 === 'string');
// AssertionError: false == true

// In a file (e.g. test.js):
assert.ok(typeof 123 === 'string');
// AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(typeof 123 === 'string')

assert.ok(false);
// AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(false)

assert.ok(0);
// AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(0)const assert = require('node:assert/strict');

assert.ok(true);
// OK
assert.ok(1);
// OK

assert.ok();
// AssertionError: No value argument passed to `assert.ok()`

assert.ok(false, 'it\'s false');
// AssertionError: it's false

// In the repl:
assert.ok(typeof 123 === 'string');
// AssertionError: false == true

// In a file (e.g. test.js):
assert.ok(typeof 123 === 'string');
// AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(typeof 123 === 'string')

assert.ok(false);
// AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(false)

assert.ok(0);
// AssertionError: The expression evaluated to a falsy value:
//
//   assert.ok(0)
import assert from 'node:assert/strict';

// Using `assert()` works the same:
assert(0);
// AssertionError: The expression evaluated to a falsy value:
//
//   assert(0)const assert = require('node:assert');

// Using `assert()` works the same:
assert(0);
// AssertionError: The expression evaluated to a falsy value:
//
//   assert(0)

assert.rejects(asyncFn[, error][, message])#

Awaits the asyncFn promise or, if asyncFn is a function, immediately calls the function and awaits the returned promise to complete. It will then check that the promise is rejected.

If asyncFn is a function and it throws an error synchronously, assert.rejects() will return a rejected Promise with that error. If the function does not return a promise, assert.rejects() will return a rejected Promise with an ERR_INVALID_RETURN_VALUE error. In both cases the error handler is skipped.

Besides the async nature to await the completion behaves identically to assert.throws().

If specified, error can be a Class, <RegExp>, a validation function, an object where each property will be tested for, or an instance of error where each property will be tested for including the non-enumerable message and name properties.

If specified, message will be the message provided by the AssertionError if the asyncFn fails to reject.

import assert from 'node:assert/strict';

await assert.rejects(
  async () => {
    throw new TypeError('Wrong value');
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
  },
);const assert = require('node:assert/strict');

(async () => {
  await assert.rejects(
    async () => {
      throw new TypeError('Wrong value');
    },
    {
      name: 'TypeError',
      message: 'Wrong value',
    },
  );
})();
import assert from 'node:assert/strict';

await assert.rejects(
  async () => {
    throw new TypeError('Wrong value');
  },
  (err) => {
    assert.strictEqual(err.name, 'TypeError');
    assert.strictEqual(err.message, 'Wrong value');
    return true;
  },
);const assert = require('node:assert/strict');

(async () => {
  await assert.rejects(
    async () => {
      throw new TypeError('Wrong value');
    },
    (err) => {
      assert.strictEqual(err.name, 'TypeError');
      assert.strictEqual(err.message, 'Wrong value');
      return true;
    },
  );
})();
import assert from 'node:assert/strict';

assert.rejects(
  Promise.reject(new Error('Wrong value')),
  Error,
).then(() => {
  // ...
});const assert = require('node:assert/strict');

assert.rejects(
  Promise.reject(new Error('Wrong value')),
  Error,
).then(() => {
  // ...
});

error cannot be a string. If a string is provided as the second argument, then error is assumed to be omitted and the string will be used for message instead. This can lead to easy-to-miss mistakes. Please read the example in assert.throws() carefully if using a string as the second argument gets considered.

assert.strictEqual(actual, expected[, message])#

Tests strict equality between the actual and expected parameters as determined by Object.is().

import assert from 'node:assert/strict';

assert.strictEqual(1, 2);
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
//
// 1 !== 2

assert.strictEqual(1, 1);
// OK

assert.strictEqual('Hello foobar', 'Hello World!');
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
// + actual - expected
//
// + 'Hello foobar'
// - 'Hello World!'
//          ^

const apples = 1;
const oranges = 2;
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2

assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
// TypeError: Inputs are not identicalconst assert = require('node:assert/strict');

assert.strictEqual(1, 2);
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
//
// 1 !== 2

assert.strictEqual(1, 1);
// OK

assert.strictEqual('Hello foobar', 'Hello World!');
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
// + actual - expected
//
// + 'Hello foobar'
// - 'Hello World!'
//          ^

const apples = 1;
const oranges = 2;
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2

assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
// TypeError: Inputs are not identical

If the values are not strictly equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of <Error> then it will be thrown instead of the AssertionError.

assert.throws(fn[, error][, message])#

Expects the function fn to throw an error.

If specified, error can be a Class, <RegExp>, a validation function, a validation object where each property will be tested for strict deep equality, or an instance of error where each property will be tested for strict deep equality including the non-enumerable message and name properties. When using an object, it is also possible to use a regular expression, when validating against a string property. See below for examples.

If specified, message will be appended to the message provided by the AssertionError if the fn call fails to throw or in case the error validation fails.

Custom validation object/error instance:

import assert from 'node:assert/strict';

const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
  nested: true,
  baz: 'text',
};
err.reg = /abc/i;

assert.throws(
  () => {
    throw err;
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
    info: {
      nested: true,
      baz: 'text',
    },
    // Only properties on the validation object will be tested for.
    // Using nested objects requires all properties to be present. Otherwise
    // the validation is going to fail.
  },
);

// Using regular expressions to validate error properties:
assert.throws(
  () => {
    throw err;
  },
  {
    // The `name` and `message` properties are strings and using regular
    // expressions on those will match against the string. If they fail, an
    // error is thrown.
    name: /^TypeError$/,
    message: /Wrong/,
    foo: 'bar',
    info: {
      nested: true,
      // It is not possible to use regular expressions for nested properties!
      baz: 'text',
    },
    // The `reg` property contains a regular expression and only if the
    // validation object contains an identical regular expression, it is going
    // to pass.
    reg: /abc/i,
  },
);

// Fails due to the different `message` and `name` properties:
assert.throws(
  () => {
    const otherErr = new Error('Not found');
    // Copy all enumerable properties from `err` to `otherErr`.
    for (const [key, value] of Object.entries(err)) {
      otherErr[key] = value;
    }
    throw otherErr;
  },
  // The error's `message` and `name` properties will also be checked when using
  // an error as validation object.
  err,
);const assert = require('node:assert/strict');

const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
  nested: true,
  baz: 'text',
};
err.reg = /abc/i;

assert.throws(
  () => {
    throw err;
  },
  {
    name: 'TypeError',
    message: 'Wrong value',
    info: {
      nested: true,
      baz: 'text',
    },
    // Only properties on the validation object will be tested for.
    // Using nested objects requires all properties to be present. Otherwise
    // the validation is going to fail.
  },
);

// Using regular expressions to validate error properties:
assert.throws(
  () => {
    throw err;
  },
  {
    // The `name` and `message` properties are strings and using regular
    // expressions on those will match against the string. If they fail, an
    // error is thrown.
    name: /^TypeError$/,
    message: /Wrong/,
    foo: 'bar',
    info: {
      nested: true,
      // It is not possible to use regular expressions for nested properties!
      baz: 'text',
    },
    // The `reg` property contains a regular expression and only if the
    // validation object contains an identical regular expression, it is going
    // to pass.
    reg: /abc/i,
  },
);

// Fails due to the different `message` and `name` properties:
assert.throws(
  () => {
    const otherErr = new Error('Not found');
    // Copy all enumerable properties from `err` to `otherErr`.
    for (const [key, value] of Object.entries(err)) {
      otherErr[key] = value;
    }
    throw otherErr;
  },
  // The error's `message` and `name` properties will also be checked when using
  // an error as validation object.
  err,
);

Validate instanceof using constructor:

import assert from 'node:assert/strict';

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  Error,
);const assert = require('node:assert/strict');

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  Error,
);

Validate error message using <RegExp>:

Using a regular expression runs .toString on the error object, and will therefore also include the error name.

import assert from 'node:assert/strict';

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  /^Error: Wrong value$/,
);const assert = require('node:assert/strict');

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  /^Error: Wrong value$/,
);

Custom error validation:

The function must return true to indicate all internal validations passed. It will otherwise fail with an AssertionError.

import assert from 'node:assert/strict';

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  (err) => {
    assert(err instanceof Error);
    assert(/value/.test(err));
    // Avoid returning anything from validation functions besides `true`.
    // Otherwise, it's not clear what part of the validation failed. Instead,
    // throw an error about the specific validation that failed (as done in this
    // example) and add as much helpful debugging information to that error as
    // possible.
    return true;
  },
  'unexpected error',
);const assert = require('node:assert/strict');

assert.throws(
  () => {
    throw new Error('Wrong value');
  },
  (err) => {
    assert(err instanceof Error);
    assert(/value/.test(err));
    // Avoid returning anything from validation functions besides `true`.
    // Otherwise, it's not clear what part of the validation failed. Instead,
    // throw an error about the specific validation that failed (as done in this
    // example) and add as much helpful debugging information to that error as
    // possible.
    return true;
  },
  'unexpected error',
);

error cannot be a string. If a string is provided as the second argument, then error is assumed to be omitted and the string will be used for message instead. This can lead to easy-to-miss mistakes. Using the same message as the thrown error message is going to result in an ERR_AMBIGUOUS_ARGUMENT error. Please read the example below carefully if using a string as the second argument gets considered:

import assert from 'node:assert/strict';

function throwingFirst() {
  throw new Error('First');
}

function throwingSecond() {
  throw new Error('Second');
}

function notThrowing() {}

// The second argument is a string and the input function threw an Error.
// The first case will not throw as it does not match for the error message
// thrown by the input function!
assert.throws(throwingFirst, 'Second');
// In the next example the message has no benefit over the message from the
// error and since it is not clear if the user intended to actually match
// against the error message, Node.js throws an `ERR_AMBIGUOUS_ARGUMENT` error.
assert.throws(throwingSecond, 'Second');
// TypeError [ERR_AMBIGUOUS_ARGUMENT]

// The string is only used (as message) in case the function does not throw:
assert.throws(notThrowing, 'Second');
// AssertionError [ERR_ASSERTION]: Missing expected exception: Second

// If it was intended to match for the error message do this instead:
// It does not throw because the error messages match.
assert.throws(throwingSecond, /Second$/);

// If the error message does not match, an AssertionError is thrown.
assert.throws(throwingFirst, /Second$/);
// AssertionError [ERR_ASSERTION]const assert = require('node:assert/strict');

function throwingFirst() {
  throw new Error('First');
}

function throwingSecond() {
  throw new Error('Second');
}

function notThrowing() {}

// The second argument is a string and the input function threw an Error.
// The first case will not throw as it does not match for the error message
// thrown by the input function!
assert.throws(throwingFirst, 'Second');
// In the next example the message has no benefit over the message from the
// error and since it is not clear if the user intended to actually match
// against the error message, Node.js throws an `ERR_AMBIGUOUS_ARGUMENT` error.
assert.throws(throwingSecond, 'Second');
// TypeError [ERR_AMBIGUOUS_ARGUMENT]

// The string is only used (as message) in case the function does not throw:
assert.throws(notThrowing, 'Second');
// AssertionError [ERR_ASSERTION]: Missing expected exception: Second

// If it was intended to match for the error message do this instead:
// It does not throw because the error messages match.
assert.throws(throwingSecond, /Second$/);

// If the error message does not match, an AssertionError is thrown.
assert.throws(throwingFirst, /Second$/);
// AssertionError [ERR_ASSERTION]

Due to the confusing error-prone notation, avoid a string as the second argument.

assert.partialDeepStrictEqual(actual, expected[, message])#

Tests for partial deep equality between the actual and expected parameters. "Deep" equality means that the enumerable "own" properties of child objects are recursively evaluated also by the following rules. "Partial" equality means that only properties that exist on the expected parameter are going to be compared.

This method always passes the same test cases as assert.deepStrictEqual(), behaving as a super set of it.

Comparison details#

  • Primitive values are compared using Object.is().
  • Type tags of objects should be the same.
  • [[Prototype]] of objects are not compared.
  • Only enumerable "own" properties are considered.
  • <Error> names, messages, causes, and errors are always compared, even if these are not enumerable properties. errors is also compared.
  • Enumerable own <Symbol> properties are compared as well.
  • Object wrappers are compared both as objects and unwrapped values.
  • Object properties are compared unordered.
  • <Map> keys and <Set> items are compared unordered.
  • Recursion stops when both sides differ or both sides encounter a circular reference.
  • <WeakMap> and <WeakSet> instances are not compared structurally. They are only equal if they reference the same object. Any comparison between different WeakMap or WeakSet instances will result in inequality, even if they contain the same entries.
  • <RegExp> lastIndex, flags, and source are always compared, even if these are not enumerable properties.
  • Holes in sparse arrays are ignored.
import assert from 'node:assert';

assert.partialDeepStrictEqual(
  { a: { b: { c: 1 } } },
  { a: { b: { c: 1 } } },
);
// OK

assert.partialDeepStrictEqual(
  { a: 1, b: 2, c: 3 },
  { b: 2 },
);
// OK

assert.partialDeepStrictEqual(
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [4, 5, 8],
);
// OK

assert.partialDeepStrictEqual(
  new Set([{ a: 1 }, { b: 1 }]),
  new Set([{ a: 1 }]),
);
// OK

assert.partialDeepStrictEqual(
  new Map([['key1', 'value1'], ['key2', 'value2']]),
  new Map([['key2', 'value2']]),
);
// OK

assert.partialDeepStrictEqual(123n, 123n);
// OK

assert.partialDeepStrictEqual(
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [5, 4, 8],
);
// AssertionError

assert.partialDeepStrictEqual(
  { a: 1 },
  { a: 1, b: 2 },
);
// AssertionError

assert.partialDeepStrictEqual(
  { a: { b: 2 } },
  { a: { b: '2' } },
);
// AssertionErrorconst assert = require('node:assert');

assert.partialDeepStrictEqual(
  { a: { b: { c: 1 } } },
  { a: { b: { c: 1 } } },
);
// OK

assert.partialDeepStrictEqual(
  { a: 1, b: 2, c: 3 },
  { b: 2 },
);
// OK

assert.partialDeepStrictEqual(
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [4, 5, 8],
);
// OK

assert.partialDeepStrictEqual(
  new Set([{ a: 1 }, { b: 1 }]),
  new Set([{ a: 1 }]),
);
// OK

assert.partialDeepStrictEqual(
  new Map([['key1', 'value1'], ['key2', 'value2']]),
  new Map([['key2', 'value2']]),
);
// OK

assert.partialDeepStrictEqual(123n, 123n);
// OK

assert.partialDeepStrictEqual(
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [5, 4, 8],
);
// AssertionError

assert.partialDeepStrictEqual(
  { a: 1 },
  { a: 1, b: 2 },
);
// AssertionError

assert.partialDeepStrictEqual(
  { a: { b: 2 } },
  { a: { b: '2' } },
);
// AssertionError

Asynchronous context tracking#

Stability: 2 - Stable

Source Code: lib/async_hooks.js

Introduction#

These classes are used to associate state and propagate it throughout callbacks and promise chains. They allow storing data throughout the lifetime of a web request or any other asynchronous duration. It is similar to thread-local storage in other languages.

The AsyncLocalStorage and AsyncResource classes are part of the node:async_hooks module:

import { AsyncLocalStorage, AsyncResource } from 'node:async_hooks';const { AsyncLocalStorage, AsyncResource } = require('node:async_hooks');

Class: AsyncLocalStorage#

This class creates stores that stay coherent through asynchronous operations.

While you can create your own implementation on top of the node:async_hooks module, AsyncLocalStorage should be preferred as it is a performant and memory safe implementation that involves significant optimizations that are non-obvious to implement.

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.

import http from 'node:http';
import { AsyncLocalStorage } from 'node: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
//   0: finish
//   1: start
//   1: finishconst http = require('node:http');
const { AsyncLocalStorage } = require('node: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
//   0: finish
//   1: start
//   1: finish

Each instance of AsyncLocalStorage maintains an independent storage context. Multiple instances can safely exist simultaneously without risk of interfering with each other's data.

new AsyncLocalStorage([options])#

  • options <Object>
    • defaultValue <any> The default value to be used when no store is provided.
    • name <string> A name for the AsyncLocalStorage value.

Creates a new instance of AsyncLocalStorage. Store is only provided within a run() call or after an enterWith() call.

Static method: AsyncLocalStorage.bind(fn)#

  • fn <Function> The function to bind to the current execution context.
  • Returns: <Function> A new function that calls fn within the captured execution context.

Binds the given function to the current execution context.

Static method: AsyncLocalStorage.snapshot()#

  • Returns: <Function> A new function with the signature (fn: (...args) : R, ...args) : R.

Captures the current execution context and returns a function that accepts a function as an argument. Whenever the returned function is called, it calls the function passed to it within the captured context.

const asyncLocalStorage = new AsyncLocalStorage();
const runInAsyncScope = asyncLocalStorage.run(123, () => AsyncLocalStorage.snapshot());
const result = asyncLocalStorage.run(321, () => runInAsyncScope(() => asyncLocalStorage.getStore()));
console.log(result);  // returns 123 

AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple async context tracking purposes, for example:

class Foo {
  #runInAsyncScope = AsyncLocalStorage.snapshot();

  get() { return this.#runInAsyncScope(() => asyncLocalStorage.getStore()); }
}

const foo = asyncLocalStorage.run(123, () => new Foo());
console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123 

asyncLocalStorage.disable()#

Stability: 1 - Experimental

Disables the instance of AsyncLocalStorage. All subsequent calls to asyncLocalStorage.getStore() will return undefined until asyncLocalStorage.run() or asyncLocalStorage.enterWith() is called again.

When calling asyncLocalStorage.disable(), all current contexts linked to the instance will be exited.

Calling asyncLocalStorage.disable() is required before the asyncLocalStorage can be garbage collected. This does not apply to stores provided by the asyncLocalStorage, as those objects are garbage collected along with the corresponding async resources.

Use this method when the asyncLocalStorage is not in use anymore in the current process.

asyncLocalStorage.getStore()#

Returns the current store. If called outside of an asynchronous context initialized by calling asyncLocalStorage.run() or asyncLocalStorage.enterWith(), it returns undefined.

asyncLocalStorage.enterWith(store)#

Stability: 1 - Experimental

Transitions into the context for the remainder of the current synchronous execution and then persists the store through any following asynchronous calls.

Example:

const store = { id: 1 };
// Replaces previous store with the given store object
asyncLocalStorage.enterWith(store);
asyncLocalStorage.getStore(); // Returns the store object
someAsyncOperation(() => {
  asyncLocalStorage.getStore(); // Returns the same object
}); 

This transition will continue for the entire synchronous execution. This means that if, for example, the context is entered within an event handler subsequent event handlers will also run within that context unless specifically bound to another context with an AsyncResource. That is why run() should be preferred over enterWith() unless there are strong reasons to use the latter method.

const store = { id: 1 };

emitter.on('my-event', () => {
  asyncLocalStorage.enterWith(store);
});
emitter.on('my-event', () => {
  asyncLocalStorage.getStore(); // Returns the same object
});

asyncLocalStorage.getStore(); // Returns undefined
emitter.emit('my-event');
asyncLocalStorage.getStore(); // Returns the same object 

asyncLocalStorage.name#

The name of the AsyncLocalStorage instance if provided.

asyncLocalStorage.run(store, callback[, ...args])#

Runs a function synchronously within a context and returns its return value. The store is not accessible outside of the callback function. The store is accessible to any asynchronous operations created within the callback.

The optional args are passed to the callback function.

If the callback function throws an error, the error is thrown by run() too. The stacktrace is not impacted by this call and the context is exited.

Example:

const store = { id: 2 };
try {
  asyncLocalStorage.run(store, () => {
    asyncLocalStorage.getStore(); // Returns the store object
    setTimeout(() => {
      asyncLocalStorage.getStore(); // Returns the store object
    }, 200);
    throw new Error();
  });
} catch (e) {
  asyncLocalStorage.getStore(); // Returns undefined
  // The error will be caught here
} 

asyncLocalStorage.exit(callback[, ...args])#

Stability: 1 - Experimental

Runs a function synchronously outside of a context and returns its return value. The store is not accessible within the callback function or the asynchronous operations created within the callback. Any getStore() call done within the callback function will always return undefined.

The optional args are passed to the callback function.

If the callback function throws an error, the error is thrown by exit() too. The stacktrace is not impacted by this call and the context is re-entered.

Example:

// Within a call to run
try {
  asyncLocalStorage.getStore(); // Returns the store object or value
  asyncLocalStorage.exit(() => {
    asyncLocalStorage.getStore(); // Returns undefined
    throw new Error();
  });
} catch (e) {
  asyncLocalStorage.getStore(); // Returns the same object or value
  // The error will be caught here
} 

Usage with async/await#

If, within an async function, only one await call is to run within a context, the following pattern should be used:

async function fn() {
  await asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set('key', value);
    return foo(); // The return value of foo will be awaited
  });
} 

In this example, the store is only available in the callback function and the functions called by foo. Outside of run, calling getStore will return undefined.

Troubleshooting: Context loss#

In most cases, AsyncLocalStorage works without issues. In rare situations, the current store is lost in one of the asynchronous operations.

If your code is callback-based, it is enough to promisify it with util.promisify() so it starts working with native promises.

If you need to use a callback-based API or your code assumes a custom thenable implementation, use the AsyncResource class to associate the asynchronous operation with the correct execution context. Find the function call responsible for the context loss by logging the content of asyncLocalStorage.getStore() after the calls you suspect are responsible for the loss. When the code logs undefined, the last callback called is probably responsible for the context loss.

Class: AsyncResource#

The class AsyncResource is designed to be extended by the embedder's async resources. Using this, users can easily trigger the lifetime events of their own resources.

The init hook will trigger when an AsyncResource is instantiated.

The following is an overview of the AsyncResource API.

import { AsyncResource, executionAsyncId } from 'node: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();const { AsyncResource, executionAsyncId } = require('node: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();

new AsyncResource(type[, options])#

  • type <string> The type of async event.
  • options <Object>
    • triggerAsyncId <number> The ID of the execution context that created this async event. Default: executionAsyncId().
    • requireManualDestroy <boolean> If set to true, disables emitDestroy when the object is garbage collected. This usually does not need to be set (even if emitDestroy is called manually), unless the resource's asyncId is retrieved and the sensitive API's emitDestroy is called with it. When set to false, the emitDestroy call on garbage collection will only take place if there is at least one active destroy hook. Default: false.

Example usage:

class DBQuery extends AsyncResource {
  constructor(db) {
    super('DBQuery');
    this.db = db;
  }

  getInfo(query, callback) {
    this.db.get(query, (err, data) => {
      this.runInAsyncScope(callback, null, err, data);
    });
  }

  close() {
    this.db = null;
    this.emitDestroy();
  }
} 

Static method: AsyncResource.bind(fn[, type[, thisArg]])#

  • fn <Function> The function to bind to the current execution context.
  • type <string> An optional name to associate with the underlying AsyncResource.
  • thisArg <any>

Binds the given function to the current execution context.

asyncResource.bind(fn[, thisArg])#

  • fn <Function> The function to bind to the current AsyncResource.
  • thisArg <any>

Binds the given function to execute to this AsyncResource's scope.

asyncResource.runInAsyncScope(fn[, thisArg, ...args])#

  • fn <Function> The function to call in the execution context of this async resource.
  • thisArg <any> The receiver to be used for the function call.
  • ...args <any> Optional arguments to pass to the function.

Call the provided function with the provided arguments in the execution context of the async resource. This will establish the context, trigger the AsyncHooks before callbacks, call the function, trigger the AsyncHooks after callbacks, and then restore the original execution context.

asyncResource.emitDestroy()#

Call all destroy hooks. This should only ever be called once. An error will be thrown if it is called more than once. This must be manually called. If the resource is left to be collected by the GC then the destroy hooks will never be called.

asyncResource.asyncId()#

  • Returns: <number> The unique asyncId assigned to the resource.

asyncResource.triggerAsyncId()#

  • Returns: <number> The same triggerAsyncId that is passed to the AsyncResource constructor.

Using AsyncResource for a Worker thread pool#

The following example shows how to use the AsyncResource class to properly provide async tracking for a Worker pool. Other resource pools, such as 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:

import { parentPort } from 'node:worker_threads';
parentPort.on('message', (task) => {
  parentPort.postMessage(task.a + task.b);
});const { parentPort } = require('node:worker_threads');
parentPort.on('message', (task) => {
  parentPort.postMessage(task.a + task.b);
});

a Worker pool around it could use the following structure:

import { AsyncResource } from 'node:async_hooks';
import { EventEmitter } from 'node:events';
import { Worker } from 'node: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_processor.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();
  }
}const { AsyncResource } = require('node:async_hooks');
const { EventEmitter } = require('node:events');
const path = require('node:path');
const { Worker } = require('node: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.
  }
}

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(path.resolve(__dirname, 'task_processor.js'));
    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();
  }
}

module.exports = WorkerPool;

Without the explicit tracking added by the WorkerPoolTaskInfo objects, it would appear that the callbacks are associated with the individual Worker objects. However, the creation of the Workers is not associated with the creation of the tasks and does not provide information about when tasks were scheduled.

This pool could be used as follows:

import WorkerPool from './worker_pool.js';
import os from 'node:os';

const pool = new WorkerPool(os.availableParallelism());

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();
  });
}const WorkerPool = require('./worker_pool.js');
const os = require('node:os');

const pool = new WorkerPool(os.availableParallelism());

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();
  });
}

Integrating AsyncResource with EventEmitter#

Event listeners triggered by an EventEmitter may be run in a different execution context than the one that was active when eventEmitter.on() was called.

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.

import { createServer } from 'node:http';
import { AsyncResource, executionAsyncId } from 'node: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);const { createServer } = require('node:http');
const { AsyncResource, executionAsyncId } = require('node: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);

Async hooks#

Stability: 1 - Experimental. Please migrate away from this API, if you can. We do not recommend using the createHook, AsyncHook, and executionAsyncResource APIs as they have usability issues, safety risks, and performance implications. Async context tracking use cases are better served by the stable AsyncLocalStorage API. If you have a use case for createHook, AsyncHook, or executionAsyncResource beyond the context tracking need solved by AsyncLocalStorage or diagnostics data currently provided by Diagnostics Channel, please open an issue at https://github.com/nodejs/node/issues describing your use case so we can create a more purpose-focused API.

Source Code: lib/async_hooks.js

We strongly discourage the use of the async_hooks API. Other APIs that can cover most of its use cases include:

The node:async_hooks module provides an API to track asynchronous resources. It can be accessed using:

import async_hooks from 'node:async_hooks';const async_hooks = require('node:async_hooks');

Terminology#

An asynchronous resource represents an object with an associated callback. This callback may be called multiple times, such as the 'connection' event in net.createServer(), or just a single time like in fs.open(). A resource can also be closed before the callback is called. AsyncHook does not explicitly distinguish between these different cases but will represent them as the abstract concept that is a resource.

If Workers are used, each thread has an independent async_hooks interface, and each thread will use a new set of async IDs.

Overview#

Following is a simple overview of the public API.

import async_hooks from 'node: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) { }const async_hooks = require('node: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) { }

async_hooks.createHook(callbacks)#

Registers functions to be called for different lifetime events of each async operation.

The callbacks init()/before()/after()/destroy() are called for the respective asynchronous event during a resource's lifetime.

All callbacks are optional. For example, if only resource cleanup needs to 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.

import { createHook } from 'node:async_hooks';

const asyncHook = createHook({
  init(asyncId, type, triggerAsyncId, resource) { },
  destroy(asyncId) { },
});const async_hooks = require('node:async_hooks');

const asyncHook = async_hooks.createHook({
  init(asyncId, type, triggerAsyncId, resource) { },
  destroy(asyncId) { },
});

The callbacks will be inherited via the prototype chain:

class MyAsyncCallbacks {
  init(asyncId, type, triggerAsyncId, resource) { }
  destroy(asyncId) {}
}

class MyAddedCallbacks extends MyAsyncCallbacks {
  before(asyncId) { }
  after(asyncId) { }
}

const asyncHook = async_hooks.createHook(new MyAddedCallbacks()); 

Because promises are asynchronous resources whose lifecycle is tracked via the async hooks mechanism, the init(), before(), after(), and destroy() callbacks must not be async functions that return promises.

Error handling#

If any AsyncHook callbacks throw, the application will print the stack trace and exit. The exit path does follow that of an uncaught exception, but all 'uncaughtException' listeners are removed, thus forcing the process to exit. The 'exit' callbacks will still be called unless the application is run with --abort-on-uncaught-exception, in which case a stack trace will be printed and the application exits, leaving a core file.

The reason for this error handling behavior is that these callbacks are running at potentially volatile points in an object's lifetime, for example during class construction and destruction. Because of this, it is deemed necessary to bring down the process quickly in order to prevent an unintentional abort in the future. This is subject to change in the future if a comprehensive analysis is performed to ensure an exception can follow the normal control flow without unintentional side effects.

Printing in AsyncHook callbacks#

Because printing to the console is an asynchronous operation, console.log() will cause AsyncHook callbacks to be called. Using console.log() or similar asynchronous operations inside an AsyncHook callback function will cause an infinite recursion. An easy solution to this when debugging is to use a synchronous logging operation such as fs.writeFileSync(file, msg, flag). This will print to the file and will not invoke AsyncHook recursively because it is synchronous.

import { writeFileSync } from 'node:fs';
import { format } from 'node:util';

function debug(...args) {
  // Use a function like this one when debugging inside an AsyncHook callback
  writeFileSync('log.out', `${format(...args)}\n`, { flag: 'a' });
}const fs = require('node:fs');
const util = require('node:util');

function debug(...args) {
  // Use a function like this one when debugging inside an AsyncHook callback
  fs.writeFileSync('log.out', `${util.format(...args)}\n`, { flag: 'a' });
}

If an asynchronous operation is needed for logging, it is possible to keep track of what caused the asynchronous operation using the information provided by AsyncHook itself. The logging should then be skipped when it was the logging itself that caused the AsyncHook callback to be called. By doing this, the otherwise infinite recursion is broken.

Class: AsyncHook#

The class AsyncHook exposes an interface for tracking lifetime events of asynchronous operations.

asyncHook.enable()#

Enable the callbacks for a given AsyncHook instance. If no callbacks are 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.

import { createHook } from 'node:async_hooks';

const hook = createHook(callbacks).enable();const async_hooks = require('node:async_hooks');

const hook = async_hooks.createHook(callbacks).enable();

asyncHook.disable()#

Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.

For API consistency disable() also returns the AsyncHook instance.

Hook callbacks#

Key events in the lifetime of asynchronous events have been categorized into four areas: instantiation, before/after the callback is called, and when the instance is destroyed.

init(asyncId, type, triggerAsyncId, resource)#
  • asyncId <number> A unique ID for the async resource.
  • type <string> The type of the async resource.
  • triggerAsyncId <number> The unique ID of the async resource in whose execution context this async resource was created.
  • resource <Object> Reference to the resource representing the async operation, needs to be released during destroy.

Called when a class is constructed that has the possibility to emit an asynchronous event. This does not mean the instance must call before/after before destroy is called, only that the possibility exists.

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.

import { createServer } from 'node:net';

createServer().listen(function() { this.close(); });
// OR
clearTimeout(setTimeout(() => {}, 10));require('node:net').createServer().listen(function() { this.close(); });
// OR
clearTimeout(setTimeout(() => {}, 10));

Every new resource is assigned an ID that is unique within the scope of the current Node.js instance.

type#

The type is a string identifying the type of resource that caused init to be called. Generally, it will correspond to the name of the resource's constructor.

The type of resources created by Node.js itself can change in any Node.js release. Valid values include TLSWRAP, TCPWRAP, TCPSERVERWRAP, GETADDRINFOREQWRAP, FSREQCALLBACK, Microtask, and Timeout. Inspect the source code of the Node.js version used to get the full list.

Furthermore users of AsyncResource create async resources independent of Node.js itself.

There is also the PROMISE resource type, which is used to track Promise instances and asynchronous work scheduled by them.

Users are able to define their own type when using the public embedder API.

It is possible to have type name collisions. Embedders are encouraged to use unique prefixes, such as the npm package name, to prevent collisions when listening to the hooks.

triggerAsyncId#

triggerAsyncId is the asyncId of the resource that caused (or "triggered") the new resource to initialize and that caused init to call. This is different from async_hooks.executionAsyncId() that only shows when a resource was created, while triggerAsyncId shows why a resource was created.

The following is a simple demonstration of triggerAsyncId:

import { createHook, executionAsyncId } from 'node:async_hooks';
import { stdout } from 'node:process';
import net from 'node:net';
import fs from 'node:fs';

createHook({
  init(asyncId, type, triggerAsyncId) {
    const eid = executionAsyncId();
    fs.writeSync(
      stdout.fd,
      `${type}(${asyncId}): trigger: ${triggerAsyncId} execution: ${eid}\n`);
  },
}).enable();

net.createServer((conn) => {}).listen(8080);const { createHook, executionAsyncId } = require('node:async_hooks');
const { stdout } = require('node:process');
const net = require('node:net');
const fs = require('node:fs');

createHook({
  init(asyncId, type, triggerAsyncId) {
    const eid = executionAsyncId();
    fs.writeSync(
      stdout.fd,
      `${type}(${asyncId}): trigger: ${triggerAsyncId} execution: ${eid}\n`);
  },
}).enable();

net.createServer((conn) => {}).listen(8080);

Output when hitting the server with nc localhost 8080:

TCPSERVERWRAP(5): trigger: 1 execution: 1
TCPWRAP(7): trigger: 5 execution: 0 

The TCPSERVERWRAP is the server which receives the connections.

The TCPWRAP is the new connection from the client. When a new connection is made, the TCPWrap instance is immediately constructed. This happens outside of any JavaScript stack. (An executionAsyncId() of 0 means that it is being executed from C++ with no JavaScript stack above it.) With only that information, it would be impossible to link resources together in terms of what caused them to be created, so triggerAsyncId is given the task of propagating what resource is responsible for the new resource's existence.

resource#

resource is an object that represents the actual async resource that has been initialized. The API to access the object may be specified by the creator of the resource. Resources created by Node.js itself are internal and may change at any time. Therefore no API is specified for these.

In some cases the resource object is reused for performance reasons, it is thus not safe to use it as a key in a WeakMap or add properties to it.

Asynchronous context example#

The context tracking use case is covered by the stable API AsyncLocalStorage. This example only illustrates async hooks operation but AsyncLocalStorage fits better to this use case.

The following is an example with additional information about the calls to init between the before and after calls, specifically what the callback to listen() will look like. The output formatting is slightly more elaborate to make calling context easier to see.

import async_hooks from 'node:async_hooks';
import fs from 'node:fs';
import net from 'node:net';
import { stdout } from 'node:process';
const { fd } = stdout;

let indent = 0;
async_hooks.createHook({
  init(asyncId, type, triggerAsyncId) {
    const eid = async_hooks.executionAsyncId();
    const indentStr = ' '.repeat(indent);
    fs.writeSync(
      fd,
      `${indentStr}${type}(${asyncId}):` +
      ` trigger: ${triggerAsyncId} execution: ${eid}\n`);
  },
  before(asyncId) {
    const indentStr = ' '.repeat(indent);
    fs.writeSync(fd, `${indentStr}before:  ${asyncId}\n`);
    indent += 2;
  },
  after(asyncId) {
    indent -= 2;
    const indentStr = ' '.repeat(indent);
    fs.writeSync(fd, `${indentStr}after:  ${asyncId}\n`);
  },
  destroy(asyncId) {
    const indentStr = ' '.repeat(indent);
    fs.writeSync(fd, `${indentStr}destroy:  ${asyncId}\n`);
  },
}).enable();

net.createServer(() => {}).listen(8080, () => {
  // Let's wait 10ms before logging the server started.
  setTimeout(() => {
    console.log('>>>', async_hooks.executionAsyncId());
  }, 10);
});const async_hooks = require('node:async_hooks');
const fs = require('node:fs');
const net = require('node:net');
const { fd } = process.stdout;

let indent = 0;
async_hooks.createHook({
  init(asyncId, type, triggerAsyncId) {
    const eid = async_hooks.executionAsyncId();
    const indentStr = ' '.repeat(indent);
    fs.writeSync(
      fd,
      `${indentStr}${type}(${asyncId}):` +
      ` trigger: ${triggerAsyncId} execution: ${eid}\n`);
  },
  before(asyncId) {
    const indentStr = ' '.repeat(indent);
    fs.writeSync(fd, `${indentStr}before:  ${asyncId}\n`);
    indent += 2;
  },
  after(asyncId) {
    indent -= 2;
    const indentStr = ' '.repeat(indent);
    fs.writeSync(fd, `${indentStr}after:  ${asyncId}\n`);
  },
  destroy(asyncId) {
    const indentStr = ' '.repeat(indent);
    fs.writeSync(fd, `${indentStr}destroy:  ${asyncId}\n`);
  },
}).enable();

net.createServer(() => {}).listen(8080, () => {
  // Let's wait 10ms before logging the server started.
  setTimeout(() => {
    console.log('>>>', async_hooks.executionAsyncId());
  }, 10);
});

Output from only starting the server:

TCPSERVERWRAP(5): trigger: 1 execution: 1
TickObject(6): trigger: 5 execution: 1
before:  6
  Timeout(7): trigger: 6 execution: 6
after:   6
destroy: 6
before:  7
>>> 7
  TickObject(8): trigger: 7 execution: 7
after:   7
before:  8
after:   8 

As illustrated in the example, executionAsyncId() and execution each specify the value of the current execution context; which is delineated by calls to before and after.

Only using execution to graph resource allocation results in the following:

  root(1)
     ^
     |
TickObject(6)
     ^
     |
 Timeout(7) 

The TCPSERVERWRAP is not part of this graph, even though it was the reason for console.log() being called. This is because binding to a port without a host name is a synchronous operation, but to maintain a completely asynchronous API the user's callback is placed in a process.nextTick(). Which is why TickObject is present in the output and is a 'parent' for .listen() callback.

The graph only shows when a resource was created, not why, so to track the why use triggerAsyncId. Which can be represented with the following graph:

 bootstrap(1)
     |
     ˅
TCPSERVERWRAP(5)
     |
     ˅
 TickObject(6)
     |
     ˅
  Timeout(7) 
before(asyncId)#

When an asynchronous operation is initiated (such as a TCP server receiving a new connection) or completes (such as writing data to disk) a callback is called to notify the user. The before callback is called just before said callback is executed. asyncId is the unique identifier assigned to the resource about to execute the callback.

The before callback will be called 0 to N times. The before callback will typically be called 0 times if the asynchronous operation was cancelled or, for example, if no connections are received by a TCP server. Persistent asynchronous resources like a TCP server will typically call the before callback multiple times, while other operations like fs.open() will call it only once.

after(asyncId)#

Called immediately after the callback specified in before is completed.

If an uncaught exception occurs during execution of the callback, then after will run after the 'uncaughtException' event is emitted or a domain's handler runs.

destroy(asyncId)#

Called after the resource corresponding to asyncId is destroyed. It is also called asynchronously from the embedder API emitDestroy().

Some resources depend on garbage collection for cleanup, so if a reference is made to the resource object passed to init it is possible that destroy will never be called, causing a memory leak in the application. If the resource does not depend on garbage collection, then this will not be an issue.

Using the destroy hook results in additional overhead because it enables tracking of Promise instances via the garbage collector.

promiseResolve(asyncId)#

Called when the resolve function passed to the Promise constructor is invoked (either directly or through other means of resolving a promise).

resolve() does not do any observable synchronous work.

The Promise is not necessarily fulfilled or rejected at this point if the Promise was resolved by assuming the state of another Promise.

new Promise((resolve) => resolve(true)).then((a) => {}); 

calls the following callbacks:

init for PROMISE with id 5, trigger id: 1
  promise resolve 5      # corresponds to resolve(true)
init for PROMISE with id 6, trigger id: 5  # the Promise returned by then()
  before 6               # the then() callback is entered
  promise resolve 6      # the then() callback resolves the promise by returning
  after 6 

async_hooks.executionAsyncResource()#

  • Returns: <Object> The resource representing the current execution. Useful to store data within the resource.

Resource objects returned by executionAsyncResource() are most often internal Node.js handle objects with undocumented APIs. Using any functions or properties on the object is likely to crash your application and should be avoided.

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.

import { open } from 'node:fs';
import { executionAsyncId, executionAsyncResource } from 'node:async_hooks';

console.log(executionAsyncId(), executionAsyncResource());  // 1 {}
open(new URL(import.meta.url), 'r', (err, fd) => {
  console.log(executionAsyncId(), executionAsyncResource());  // 7 FSReqWrap
});const { open } = require('node:fs');
const { executionAsyncId, executionAsyncResource } = require('node:async_hooks');

console.log(executionAsyncId(), executionAsyncResource());  // 1 {}
open(__filename, 'r', (err, fd) => {
  console.log(executionAsyncId(), executionAsyncResource());  // 7 FSReqWrap
});

This can be used to implement continuation local storage without the use of a tracking Map to store the metadata:

import { createServer } from 'node:http';
import {
  executionAsyncId,
  executionAsyncResource,
  createHook,
} from 'node: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);const { createServer } = require('node:http');
const {
  executionAsyncId,
  executionAsyncResource,
  createHook,
} = require('node: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);

async_hooks.executionAsyncId()#

  • Returns: <number> The asyncId of the current execution context. Useful to track when something calls.
import { executionAsyncId } from 'node:async_hooks';
import fs from 'node:fs';

console.log(executionAsyncId());  // 1 - bootstrap
const path = '.';
fs.open(path, 'r', (err, fd) => {
  console.log(executionAsyncId());  // 6 - open()
});const async_hooks = require('node:async_hooks');
const fs = require('node:fs');

console.log(async_hooks.executionAsyncId());  // 1 - bootstrap
const path = '.';
fs.open(path, 'r', (err, fd) => {
  console.log(async_hooks.executionAsyncId());  // 6 - open()
});

The ID returned from executionAsyncId() is related to execution timing, not causality (which is covered by triggerAsyncId()):

const server = net.createServer((conn) => {
  // Returns the ID of the server, not of the new connection, because the
  // callback runs in the execution scope of the server's MakeCallback().
  async_hooks.executionAsyncId();

}).listen(port, () => {
  // Returns the ID of a TickObject (process.nextTick()) because all
  // callbacks passed to .listen() are wrapped in a nextTick().
  async_hooks.executionAsyncId();
}); 

Promise contexts may not get precise executionAsyncIds by default. See the section on promise execution tracking.

async_hooks.triggerAsyncId()#

  • Returns: <number> The ID of the resource responsible for calling the callback that is currently being executed.
const server = net.createServer((conn) => {
  // The resource that caused (or triggered) this callback to be called
  // was that of the new connection. Thus the return value of triggerAsyncId()
  // is the asyncId of "conn".
  async_hooks.triggerAsyncId();

}).listen(port, () => {
  // Even though all callbacks passed to .listen() are wrapped in a nextTick()
  // the callback itself exists because the call to the server's .listen()
  // was made. So the return value would be the ID of the server.
  async_hooks.triggerAsyncId();
}); 

Promise contexts may not get valid triggerAsyncIds by default. See the section on promise execution tracking.

async_hooks.asyncWrapProviders#

  • Returns: A map of provider types to the corresponding numeric id. This map contains all the event types that might be emitted by the async_hooks.init() event.

This feature suppresses the deprecated usage of process.binding('async_wrap').Providers. See: DEP0111

Promise execution tracking#

By default, promise executions are not assigned asyncIds due to the relatively expensive nature of the promise introspection API 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.

import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';

Promise.resolve(1729).then(() => {
  console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 1 tid 0const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');

Promise.resolve(1729).then(() => {
  console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 1 tid 0

Observe that the then() callback claims to have executed in the context of the outer scope even though there was an asynchronous hop involved. Also, the triggerAsyncId value is 0, which means that we are missing context about the resource that caused (triggered) the then() callback to be executed.

Installing async hooks via async_hooks.createHook enables promise execution tracking:

import { createHook, executionAsyncId, triggerAsyncId } from 'node:async_hooks';
createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled.
Promise.resolve(1729).then(() => {
  console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 7 tid 6const { createHook, executionAsyncId, triggerAsyncId } = require('node: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

In this example, adding any actual hook function enabled the tracking of promises. There are two promises in the example above; the promise created by Promise.resolve() and the promise returned by the call to then(). In the example above, the first promise got the asyncId 6 and the latter got asyncId 7. During the execution of the then() callback, we are executing in the context of promise with asyncId 7. This promise was triggered by async resource 6.

Another subtlety with promises is that before and after callbacks are run only on chained promises. That means promises not created by then()/catch() will not have the before and after callbacks fired on them. For more details see the details of the V8 PromiseHooks API.

JavaScript embedder API#

Library developers that handle their own asynchronous resources performing tasks like I/O, connection pooling, or managing callback queues may use the AsyncResource JavaScript API so that all the appropriate callbacks are called.

Class: AsyncResource#

The documentation for this class has moved AsyncResource.

Class: AsyncLocalStorage#

The documentation for this class has moved AsyncLocalStorage.

Buffer#

Stability: 2 - Stable

Source Code: lib/buffer.js

Buffer objects are used to represent a fixed-length sequence of bytes. Many Node.js APIs support Buffers.

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 Buffers are supported as well.

While the Buffer class is available within the global scope, it is still recommended to explicitly reference it via an import or require statement.

import { Buffer } from 'node: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');const { Buffer } = require('node: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');

Buffers and character encodings#

When converting between Buffers and strings, a character encoding may be specified. If no character encoding is specified, UTF-8 will be used as the default.

import { Buffer } from 'node: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: <Buffer 66 68 71 77 68 67 61 64 73>
console.log(Buffer.from('fhqwhgads', 'utf16le'));
// Prints: <Buffer 66 00 68 00 71 00 77 00 68 00 67 00 61 00 64 00 73 00>const { Buffer } = require('node: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: <Buffer 66 68 71 77 68 67 61 64 73>
console.log(Buffer.from('fhqwhgads', 'utf16le'));
// Prints: <Buffer 66 00 68 00 71 00 77 00 68 00 67 00 61 00 64 00 73 00>

Node.js buffers accept all case variations of encoding strings that they receive. For example, UTF-8 can be specified as 'utf8', 'UTF8', or 'uTf8'.

The character encodings currently supported by Node.js are the following:

  • 'utf8' (alias: 'utf-8'): Multi-byte encoded Unicode characters. Many web pages and other document formats use UTF-8. This is the default character encoding. When decoding a Buffer into a string that does not exclusively contain valid UTF-8 data, the Unicode replacement character U+FFFD � will be used to represent those errors.

  • 'utf16le' (alias: 'utf-16le'): Multi-byte encoded Unicode characters. Unlike 'utf8', each character in the string will be encoded using either 2 or 4 bytes. Node.js only supports the little-endian variant of UTF-16.

  • 'latin1': Latin-1 stands for ISO-8859-1. This character encoding only supports the Unicode characters from U+0000 to U+00FF. Each character is encoded using a single byte. Characters that do not fit into that range are truncated and will be mapped to characters in that range.

Converting a Buffer into a string using one of the above is referred to as decoding, and converting a string into a Buffer is referred to as encoding.

Node.js also supports the following binary-to-text encodings. For binary-to-text encodings, the naming convention is reversed: Converting a Buffer into a string is typically referred to as encoding, and converting a string into a Buffer as decoding.

  • 'base64': Base64 encoding. When creating a Buffer from a string, this encoding will also correctly accept "URL and Filename Safe Alphabet" as specified in RFC 4648, Section 5. Whitespace characters such as spaces, tabs, and new lines contained within the base64-encoded string are ignored.

  • 'base64url': base64url encoding as specified in RFC 4648, Section 5. When creating a Buffer from a string, this encoding will also correctly accept regular base64-encoded strings. When encoding a Buffer to a string, this encoding will omit padding.

  • 'hex': Encode each byte as two hexadecimal characters. Data truncation may occur when decoding strings that do not exclusively consist of an even number of hexadecimal characters. See below for an example.

The following legacy character encodings are also supported:

  • 'ascii': For 7-bit ASCII data only. When encoding a string into a Buffer, this is equivalent to using 'latin1'. When decoding a Buffer into a string, using this encoding will additionally unset the highest bit of each byte before decoding as 'latin1'. Generally, there should be no reason to use this encoding, as 'utf8' (or, if the data is known to always be ASCII-only, 'latin1') will be a better choice when encoding or decoding ASCII-only text. It is only provided for legacy compatibility.

  • 'binary': Alias for 'latin1'. The name of this encoding can be very misleading, as all of the encodings listed here convert between strings and binary data. For converting between strings and Buffers, typically 'utf8' is the right choice.

  • 'ucs2', 'ucs-2': Aliases of 'utf16le'. UCS-2 used to refer to a variant 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.

import { Buffer } from 'node:buffer';

Buffer.from('1ag123', 'hex');
// Prints <Buffer 1a>, data truncated when first non-hexadecimal value
// ('g') encountered.

Buffer.from('1a7', 'hex');
// Prints <Buffer 1a>, data truncated when data ends in single digit ('7').

Buffer.from('1634', 'hex');
// Prints <Buffer 16 34>, all data represented.const { Buffer } = require('node:buffer');

Buffer.from('1ag123', 'hex');
// Prints <Buffer 1a>, data truncated when first non-hexadecimal value
// ('g') encountered.

Buffer.from('1a7', 'hex');
// Prints <Buffer 1a>, data truncated when data ends in single digit ('7').

Buffer.from('1634', 'hex');
// Prints <Buffer 16 34>, all data represented.

Modern Web browsers follow the WHATWG Encoding Standard which aliases both 'latin1' and 'ISO-8859-1' to 'win-1252'. This means that while doing something like http.get(), if the returned charset is one of those listed in the WHATWG specification it is possible that the server actually returned 'win-1252'-encoded data, and using 'latin1' encoding may incorrectly decode the characters.

Buffers and TypedArrays#

Buffer instances are also JavaScript <Uint8Array> and <TypedArray> instances. All <TypedArray> methods are available on Buffers. There are, however, subtle incompatibilities between the Buffer API and the <TypedArray> API.

In particular:

There are two ways to create new <TypedArray> instances from a Buffer:

  • Passing a Buffer to a <TypedArray> constructor will copy the Buffer's contents, interpreted as an array of integers, and not as a byte sequence of the target type.
import { Buffer } from 'node:buffer';

const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);

console.log(uint32array);

// Prints: Uint32Array(4) [ 1, 2, 3, 4 ]const { Buffer } = require('node:buffer');

const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);

console.log(uint32array);

// Prints: Uint32Array(4) [ 1, 2, 3, 4 ]
import { Buffer } from 'node: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 ]const { Buffer } = require('node: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 ]

It is possible to create a new Buffer that shares the same allocated memory as a <TypedArray> instance by using the TypedArray object's .buffer property in the same way. Buffer.from() behaves like new Uint8Array() in this context.

import { Buffer } from 'node: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: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 a0 0f>

arr[1] = 6000;

console.log(buf1);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 70 17>const { Buffer } = require('node: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: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 a0 0f>

arr[1] = 6000;

console.log(buf1);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 70 17>

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.

import { Buffer } from 'node:buffer';

const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);

console.log(buf.length);
// Prints: 16const { Buffer } = require('node:buffer');

const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);

console.log(buf.length);
// Prints: 16

The Buffer.from() and TypedArray.from() have different signatures and implementations. Specifically, the <TypedArray> variants accept a second argument that is a mapping function that is invoked on every element of the typed array:

  • TypedArray.from(source[, mapFn[, thisArg]])

The Buffer.from() method, however, does not support the use of a mapping function:

Buffers and iteration#

Buffer instances can be iterated over using for..of syntax:

import { Buffer } from 'node:buffer';

const buf = Buffer.from([1, 2, 3]);

for (const b of buf) {
  console.log(b);
}
// Prints:
//   1
//   2
//   3const { Buffer } = require('node:buffer');

const buf = Buffer.from([1, 2, 3]);

for (const b of buf) {
  console.log(b);
}
// Prints:
//   1
//   2
//   3

Additionally, the buf.values(), buf.keys(), and buf.entries() methods can be used to create iterators.

Class: Blob#

A Blob encapsulates immutable, raw data that can be safely shared across multiple worker threads.

new buffer.Blob([sources[, options]])#

Creates a new Blob object containing a concatenation of the given sources.

<ArrayBuffer>, <TypedArray>, <DataView>, and <Buffer> sources are copied into the 'Blob' and can therefore be safely modified after the 'Blob' is created.

String sources are encoded as UTF-8 byte sequences and copied into the Blob. Unmatched surrogate pairs within each string part will be replaced by Unicode U+FFFD replacement characters.

blob.arrayBuffer()#

Returns a promise that fulfills with an <ArrayBuffer> containing a copy of the Blob data.

blob.bytes()#

The blob.bytes() method returns the byte of the Blob object as a Promise<Uint8Array>.

const blob = new Blob(['hello']);
blob.bytes().then((bytes) => {
  console.log(bytes); // Outputs: Uint8Array(5) [ 104, 101, 108, 108, 111 ]
}); 

blob.size#

The total size of the Blob in bytes.

blob.slice([start[, end[, type]]])#

Creates and returns a new Blob containing a subset of this Blob objects data. The original Blob is not altered.

blob.stream()#

Returns a new ReadableStream that allows the content of the Blob to be read.

blob.text()#

Returns a promise that fulfills with the contents of the Blob decoded as a UTF-8 string.

blob.type#

The content-type of the Blob.

Blob objects and MessageChannel#

Once a <Blob> object is created, it can be sent via MessagePort to multiple 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.

import { Blob } from 'node:buffer';
import { setTimeout as delay } from 'node: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.
blob.text().then(console.log);const { Blob } = require('node:buffer');
const { setTimeout: delay } = require('node: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.
blob.text().then(console.log);

Class: Buffer#

The Buffer class is a global type for dealing with binary data directly. It can be constructed in a variety of ways.

Static method: Buffer.alloc(size[, fill[, encoding]])#

Allocates a new Buffer of size bytes. If fill is undefined, the Buffer will be zero-filled.

import { Buffer } from 'node:buffer';

const buf = Buffer.alloc(5);

console.log(buf);
// Prints: <Buffer 00 00 00 00 00>const { Buffer } = require('node:buffer');

const buf = Buffer.alloc(5);

console.log(buf);
// Prints: <Buffer 00 00 00 00 00>

If size is larger than buffer.constants.MAX_LENGTH or smaller than 0, ERR_OUT_OF_RANGE is thrown.

If fill is specified, the allocated Buffer will be initialized by calling buf.fill(fill).

import { Buffer } from 'node:buffer';

const buf = Buffer.alloc(5, 'a');

console.log(buf);
// Prints: <Buffer 61 61 61 61 61>const { Buffer } = require('node:buffer');

const buf = Buffer.alloc(5, 'a');

console.log(buf);
// Prints: <Buffer 61 61 61 61 61>

If both fill and encoding are specified, the allocated Buffer will be initialized by calling buf.fill(fill, encoding).

import { Buffer } from 'node:buffer';

const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');

console.log(buf);
// Prints: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>const { Buffer } = require('node:buffer');

const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');

console.log(buf);
// Prints: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>

Calling Buffer.alloc() can be measurably slower than the alternative Buffer.allocUnsafe() but ensures that the newly created Buffer instance contents will never contain sensitive data from previous allocations, including data that might not have been allocated for Buffers.

A TypeError will be thrown if size is not a number.

Static method: Buffer.allocUnsafe(size)#

Allocates a new Buffer of size bytes. If size is larger than buffer.constants.MAX_LENGTH or smaller than 0, ERR_OUT_OF_RANGE is thrown.

The underlying memory for Buffer instances created in this way is not 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.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(10);

console.log(buf);
// Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32>

buf.fill(0);

console.log(buf);
// Prints: <Buffer 00 00 00 00 00 00 00 00 00 00>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(10);

console.log(buf);
// Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32>

buf.fill(0);

console.log(buf);
// Prints: <Buffer 00 00 00 00 00 00 00 00 00 00>

A TypeError will be thrown if size is not a number.

The Buffer module pre-allocates an internal Buffer instance of size Buffer.poolSize that is used as a pool for the fast allocation of new Buffer instances created using Buffer.allocUnsafe(), Buffer.from(array), Buffer.from(string), and Buffer.concat() only when size is less than Buffer.poolSize >>> 1 (floor of Buffer.poolSize divided by two).

Use of this pre-allocated internal memory pool is a key difference between calling Buffer.alloc(size, fill) vs. Buffer.allocUnsafe(size).fill(fill). Specifically, Buffer.alloc(size, fill) will never use the internal Buffer pool, while Buffer.allocUnsafe(size).fill(fill) will use the internal Buffer pool if size is less than or equal to half Buffer.poolSize. The difference is subtle but can be important when an application requires the additional performance that Buffer.allocUnsafe() provides.

Static method: Buffer.allocUnsafeSlow(size)#

Allocates a new Buffer of size bytes. If size is larger than buffer.constants.MAX_LENGTH or smaller than 0, ERR_OUT_OF_RANGE is thrown. A zero-length Buffer is created if size is 0.

The underlying memory for Buffer instances created in this way is not initialized. The contents of the newly created Buffer are unknown and may contain sensitive data. Use buf.fill(0) to initialize such Buffer instances with zeroes.

When using Buffer.allocUnsafe() to allocate new Buffer instances, allocations less than Buffer.poolSize >>> 1 (4KiB when default poolSize is used) are sliced from a single pre-allocated Buffer. This allows applications to avoid the garbage collection overhead of creating many individually allocated Buffer instances. This approach improves both performance and memory usage by eliminating the need to track and clean up as many individual ArrayBuffer objects.

However, in the case where a developer may need to retain a small chunk of 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.

import { Buffer } from 'node: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);
  }
});const { Buffer } = require('node: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);
  }
});

A TypeError will be thrown if size is not a number.

Static method: Buffer.byteLength(string[, encoding])#

Returns the byte length of a string when encoded using encoding. This is not the same as String.prototype.length, which does not account for the encoding that is used to convert the string into bytes.

For 'base64', 'base64url', and 'hex', this function assumes valid input. 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.

import { Buffer } from 'node:buffer';

const str = '\u00bd + \u00bc = \u00be';

console.log(`${str}: ${str.length} characters, ` +
            `${Buffer.byteLength(str, 'utf8')} bytes`);
// Prints: ½ + ¼ = ¾: 9 characters, 12 bytesconst { Buffer } = require('node:buffer');

const str = '\u00bd + \u00bc = \u00be';

console.log(`${str}: ${str.length} characters, ` +
            `${Buffer.byteLength(str, 'utf8')} bytes`);
// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes

When string is a <Buffer> | <DataView> | <TypedArray> | <ArrayBuffer> | <SharedArrayBuffer>, the byte length as reported by .byteLength is returned.

Static method: Buffer.compare(buf1, buf2)#

Compares buf1 to buf2, typically for the purpose of sorting arrays of Buffer instances. This is equivalent to calling buf1.compare(buf2).

import { Buffer } from 'node:buffer';

const buf1 = Buffer.from('1234');
const buf2 = Buffer.from('0123');
const arr = [buf1, buf2];

console.log(arr.sort(Buffer.compare));
// Prints: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ]
// (This result is equal to: [buf2, buf1].)const { Buffer } = require('node:buffer');

const buf1 = Buffer.from('1234');
const buf2 = Buffer.from('0123');
const arr = [buf1, buf2];

console.log(arr.sort(Buffer.compare));
// Prints: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ]
// (This result is equal to: [buf2, buf1].)

Static method: Buffer.concat(list[, totalLength])#

Returns a new Buffer which is the result of concatenating all the Buffer instances in the list together.

If the list has no items, or if the totalLength is 0, then a new zero-length Buffer is returned.

If totalLength is not provided, it is calculated from the Buffer instances in list by adding their lengths.

If totalLength is provided, it is coerced to an unsigned integer. If the combined length of the Buffers in list exceeds totalLength, the result is truncated to totalLength. If the combined length of the Buffers in list is less than totalLength, the remaining space is filled with zeros.

import { Buffer } from 'node: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: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42const { Buffer } = require('node: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: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42

Buffer.concat() may also use the internal Buffer pool like Buffer.allocUnsafe() does.

Static method: Buffer.copyBytesFrom(view[, offset[, length]])#

Copies the underlying memory of view into a new Buffer.

const u16 = new Uint16Array([0, 0xffff]);
const buf = Buffer.copyBytesFrom(u16, 1, 1);
u16[1] = 0;
console.log(buf.length); // 2
console.log(buf[0]); // 255
console.log(buf[1]); // 255 

Static method: Buffer.from(array)#

Allocates a new Buffer using an array of bytes in the range 0255. Array entries outside that range will be truncated to fit into it.

import { Buffer } from 'node:buffer';

// Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'.
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);const { Buffer } = require('node:buffer');

// Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'.
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);

If array is an Array-like object (that is, one with a length property of type number), it is treated as if it is an array, unless it is a Buffer or a Uint8Array. This means all other TypedArray variants get treated as an Array. To create a Buffer from the bytes backing a TypedArray, use Buffer.copyBytesFrom().

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]])#

This creates a view of the <ArrayBuffer> without copying the underlying 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.

import { Buffer } from 'node: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: <Buffer 88 13 a0 0f>

// Changing the original Uint16Array changes the Buffer also.
arr[1] = 6000;

console.log(buf);
// Prints: <Buffer 88 13 70 17>const { Buffer } = require('node: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: <Buffer 88 13 a0 0f>

// Changing the original Uint16Array changes the Buffer also.
arr[1] = 6000;

console.log(buf);
// Prints: <Buffer 88 13 70 17>

The optional byteOffset and length arguments specify a memory range within the arrayBuffer that will be shared by the Buffer.

import { Buffer } from 'node:buffer';

const ab = new ArrayBuffer(10);
const buf = Buffer.from(ab, 0, 2);

console.log(buf.length);
// Prints: 2const { Buffer } = require('node:buffer');

const ab = new ArrayBuffer(10);
const buf = Buffer.from(ab, 0, 2);

console.log(buf.length);
// Prints: 2

A TypeError will be thrown if arrayBuffer is not an <ArrayBuffer> or a <SharedArrayBuffer> or another type appropriate for Buffer.from() variants.

It is important to remember that a backing ArrayBuffer can cover a range 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:

import { Buffer } from 'node: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: <Buffer 63 64 65 66>const { Buffer } = require('node: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: <Buffer 63 64 65 66>

Static method: Buffer.from(buffer)#

Copies the passed buffer data onto a new Buffer instance.

import { Buffer } from 'node: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: bufferconst { Buffer } = require('node: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

A TypeError will be thrown if buffer is not a Buffer or another type appropriate for Buffer.from() variants.

Static method: Buffer.from(object[, offsetOrEncoding[, length]])#

For objects whose valueOf() function returns a value not strictly equal to object, returns Buffer.from(object.valueOf(), offsetOrEncoding, length).

import { Buffer } from 'node:buffer';

const buf = Buffer.from(new String('this is a test'));
// Prints: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>const { Buffer } = require('node:buffer');

const buf = Buffer.from(new String('this is a test'));
// Prints: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>

For objects that support Symbol.toPrimitive, returns Buffer.from(object[Symbol.toPrimitive]('string'), offsetOrEncoding).

import { Buffer } from 'node:buffer';

class Foo {
  [Symbol.toPrimitive]() {
    return 'this is a test';
  }
}

const buf = Buffer.from(new Foo(), 'utf8');
// Prints: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>const { Buffer } = require('node:buffer');

class Foo {
  [Symbol.toPrimitive]() {
    return 'this is a test';
  }
}

const buf = Buffer.from(new Foo(), 'utf8');
// Prints: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>

A TypeError will be thrown if object does not have the mentioned methods or is not of another type appropriate for Buffer.from() variants.

Static method: Buffer.from(string[, encoding])#

Creates a new Buffer containing string. The encoding parameter identifies the character encoding to be used when converting string into bytes.

import { Buffer } from 'node: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éstconst { Buffer } = require('node: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

A TypeError will be thrown if string is not a string or another type appropriate for Buffer.from() variants.

Buffer.from(string) may also use the internal Buffer pool like Buffer.allocUnsafe() does.

Static method: Buffer.isBuffer(obj)#

Returns true if obj is a Buffer, false otherwise.

import { Buffer } from 'node: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)); // falseconst { Buffer } = require('node: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

Static method: Buffer.isEncoding(encoding)#

Returns true if encoding is the name of a supported character encoding, or false otherwise.

import { Buffer } from 'node: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: falseconst { Buffer } = require('node: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

Class property: Buffer.poolSize#

This is the size (in bytes) of pre-allocated internal Buffer instances used for pooling. This value may be modified.

buf[index]#

The index operator [index] can be used to get and set the octet at position index in buf. The values refer to individual bytes, so the legal value range is between 0x00 and 0xFF (hex) or 0 and 255 (decimal).

This operator is inherited from Uint8Array, so its behavior on out-of-bounds access is the same as Uint8Array. In other words, buf[index] returns undefined when index is negative or greater or equal to buf.length, and buf[index] = value does not modify the buffer if index is negative or >= buf.length.

import { Buffer } from 'node: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.jsconst { Buffer } = require('node: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

buf.buffer#

  • <ArrayBuffer> The underlying ArrayBuffer object based on which this Buffer object is created.

This ArrayBuffer is not guaranteed to correspond exactly to the original Buffer. See the notes on buf.byteOffset for details.

import { Buffer } from 'node:buffer';

const arrayBuffer = new ArrayBuffer(16);
const buffer = Buffer.from(arrayBuffer);

console.log(buffer.buffer === arrayBuffer);
// Prints: trueconst { Buffer } = require('node:buffer');

const arrayBuffer = new ArrayBuffer(16);
const buffer = Buffer.from(arrayBuffer);

console.log(buffer.buffer === arrayBuffer);
// Prints: true

buf.byteOffset#

  • <integer> The byteOffset of the Buffer's underlying ArrayBuffer object.

When setting byteOffset in Buffer.from(ArrayBuffer, byteOffset, length), or sometimes when allocating a Buffer smaller than Buffer.poolSize, the buffer does not start from a zero offset on the underlying ArrayBuffer.

This can cause problems when accessing the underlying ArrayBuffer directly using buf.buffer, as other parts of the ArrayBuffer may be unrelated 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:

import { Buffer } from 'node:buffer';

// Create a buffer smaller than `Buffer.poolSize`.
const nodeBuffer = 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);const { Buffer } = require('node:buffer');

// Create a buffer smaller than `Buffer.poolSize`.
const nodeBuffer = 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);

buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])#

  • target <Buffer> | <Uint8Array> A Buffer or <Uint8Array> with which to compare buf.
  • targetStart <integer> The offset within target at which to begin comparison. Default: 0.
  • targetEnd <integer> The offset within target at which to end comparison (not inclusive). Default: target.length.
  • sourceStart <integer> The offset within buf at which to begin comparison. Default: 0.
  • sourceEnd <integer> The offset within buf at which to end comparison (not inclusive). Default: buf.length.
  • Returns: <integer>

Compares buf with target and returns a number indicating whether buf comes before, after, or is the same as target in sort order. Comparison is based on the actual sequence of bytes in each Buffer.

  • 0 is returned if target is the same as buf
  • 1 is returned if target should come before buf when sorted.
  • -1 is returned if target should come after buf when sorted.
import { Buffer } from 'node: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: [ <Buffer 41 42 43>, <Buffer 41 42 43 44>, <Buffer 42 43 44> ]
// (This result is equal to: [buf1, buf3, buf2].)const { Buffer } = require('node: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: [ <Buffer 41 42 43>, <Buffer 41 42 43 44>, <Buffer 42 43 44> ]
// (This result is equal to: [buf1, buf3, buf2].)

The optional targetStart, targetEnd, sourceStart, and sourceEnd arguments can be used to limit the comparison to specific ranges within target and buf respectively.

import { Buffer } from 'node: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: 1const { Buffer } = require('node: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

ERR_OUT_OF_RANGE is thrown if targetStart < 0, sourceStart < 0, targetEnd > target.byteLength, or sourceEnd > source.byteLength.

buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])#

  • target <Buffer> | <Uint8Array> A Buffer or <Uint8Array> to copy into.
  • targetStart <integer> The offset within target at which to begin writing. Default: 0.
  • sourceStart <integer> The offset within buf from which to begin copying. Default: 0.
  • sourceEnd <integer> The offset within buf at which to stop copying (not inclusive). Default: buf.length.
  • Returns: <integer> The number of bytes copied.

Copies data from a region of buf to a region in target, even if the target memory region overlaps with buf.

TypedArray.prototype.set() performs the same operation, and is available for all TypedArrays, including Node.js Buffers, although it takes different function arguments.

import { Buffer } from 'node: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!!!!!!!!!!!!!const { Buffer } = require('node: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!!!!!!!!!!!!!
import { Buffer } from 'node: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: efghijghijklmnopqrstuvwxyzconst { Buffer } = require('node: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

buf.entries()#

Creates and returns an iterator of [index, byte] pairs from the contents of buf.

import { Buffer } from 'node: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]const { Buffer } = require('node: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]

buf.equals(otherBuffer)#

Returns true if both buf and otherBuffer have exactly the same bytes, false otherwise. Equivalent to buf.compare(otherBuffer) === 0.

import { Buffer } from 'node: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: falseconst { Buffer } = require('node: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

buf.fill(value[, offset[, end]][, encoding])#

  • value <string> | <Buffer> | <Uint8Array> | <integer> The value with which to fill buf. Empty value (string, Uint8Array, Buffer) is coerced to 0.
  • offset <integer> Number of bytes to skip before starting to fill buf. Default: 0.
  • end <integer> Where to stop filling buf (not inclusive). Default: buf.length.
  • encoding <string> The encoding for value if value is a string. Default: 'utf8'.
  • Returns: <Buffer> A reference to buf.

Fills buf with the specified value. If the offset and end are not given, the entire buf will be filled:

import { Buffer } from 'node:buffer';

// Fill a `Buffer` with the ASCII character 'h'.

const b = Buffer.allocUnsafe(50).fill('h');

console.log(b.toString());
// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

// Fill a buffer with empty string
const c = Buffer.allocUnsafe(5).fill('');

console.log(c.fill(''));
// Prints: <Buffer 00 00 00 00 00>const { Buffer } = require('node:buffer');

// Fill a `Buffer` with the ASCII character 'h'.

const b = Buffer.allocUnsafe(50).fill('h');

console.log(b.toString());
// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

// Fill a buffer with empty string
const c = Buffer.allocUnsafe(5).fill('');

console.log(c.fill(''));
// Prints: <Buffer 00 00 00 00 00>

value is coerced to a uint32 value if it is not a string, Buffer, or integer. If the resulting integer is greater than 255 (decimal), buf will be 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:

import { Buffer } from 'node:buffer';

// Fill a `Buffer` with character that takes up two bytes in UTF-8.

console.log(Buffer.allocUnsafe(5).fill('\u0222'));
// Prints: <Buffer c8 a2 c8 a2 c8>const { Buffer } = require('node:buffer');

// Fill a `Buffer` with character that takes up two bytes in UTF-8.

console.log(Buffer.allocUnsafe(5).fill('\u0222'));
// Prints: <Buffer c8 a2 c8 a2 c8>

If value contains invalid characters, it is truncated; if no valid fill data remains, an exception is thrown:

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(5);

console.log(buf.fill('a'));
// Prints: <Buffer 61 61 61 61 61>
console.log(buf.fill('aazz', 'hex'));
// Prints: <Buffer aa aa aa aa aa>
console.log(buf.fill('zz', 'hex'));
// Throws an exception.const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(5);

console.log(buf.fill('a'));
// Prints: <Buffer 61 61 61 61 61>
console.log(buf.fill('aazz', 'hex'));
// Prints: <Buffer aa aa aa aa aa>
console.log(buf.fill('zz', 'hex'));
// Throws an exception.

buf.includes(value[, byteOffset][, encoding])#

  • value <string> | <Buffer> | <Uint8Array> | <integer> What to search for.
  • byteOffset <integer> Where to begin searching in buf. If negative, then offset is calculated from the end of buf. Default: 0.
  • encoding <string> If value is a string, this is its encoding. Default: 'utf8'.
  • Returns: <boolean> true if value was found in buf, false otherwise.

Equivalent to buf.indexOf() !== -1.

import { Buffer } from 'node: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: falseconst { Buffer } = require('node: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

buf.indexOf(value[, byteOffset][, encoding])#

  • value <string> | <Buffer> | <Uint8Array> | <integer> What to search for.
  • byteOffset <integer> Where to begin searching in buf. If negative, then offset is calculated from the end of buf. Default: 0.
  • encoding <string> If value is a string, this is the encoding used to determine the binary representation of the string that will be searched for in buf. Default: 'utf8'.
  • Returns: <integer> The index of the first occurrence of value in buf, or -1 if buf does not contain value.

If value is:

  • a string, value is interpreted according to the character encoding in encoding.
  • a Buffer or <Uint8Array>, value will be used in its entirety. To compare a partial Buffer, use buf.subarray.
  • a number, value will be interpreted as an unsigned 8-bit integer value between 0 and 255.
import { Buffer } from 'node: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: 6const { Buffer } = require('node: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

If value is not a string, number, or Buffer, this method will throw a TypeError. If value is a number, it will be coerced to a valid byte value, an integer between 0 and 255.

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().

import { Buffer } from 'node: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', []));const { Buffer } = require('node: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', []));

If value is an empty string or empty Buffer and byteOffset is less than buf.length, byteOffset will be returned. If value is empty and byteOffset is at least buf.length, buf.length will be returned.

buf.keys()#

Creates and returns an iterator of buf keys (indexes).

import { Buffer } from 'node:buffer';

const buf = Buffer.from('buffer');

for (const key of buf.keys()) {
  console.log(key);
}
// Prints:
//   0
//   1
//   2
//   3
//   4
//   5const { Buffer } = require('node:buffer');

const buf = Buffer.from('buffer');

for (const key of buf.keys()) {
  console.log(key);
}
// Prints:
//   0
//   1
//   2
//   3
//   4
//   5

buf.lastIndexOf(value[, byteOffset][, encoding])#

  • value <string> | <Buffer> | <Uint8Array> | <integer> What to search for.
  • byteOffset <integer> Where to begin searching in buf. If negative, then offset is calculated from the end of buf. Default: buf.length - 1.
  • encoding <string> If value is a string, this is the encoding used to determine the binary representation of the string that will be searched for in buf. Default: 'utf8'.
  • Returns: <integer> The index of the last occurrence of value in buf, or -1 if buf does not contain value.

Identical to buf.indexOf(), except the last occurrence of value is found rather than the first occurrence.

import { Buffer } from 'node: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: 4const { Buffer } = require('node: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

If value is not a string, number, or Buffer, this method will throw a TypeError. If value is a number, it will be coerced to a valid byte value, an integer between 0 and 255.

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().

import { Buffer } from 'node: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', []));const { Buffer } = require('node: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', []));

If value is an empty string or empty Buffer, byteOffset will be returned.

buf.length#

Returns the number of bytes in buf.

import { Buffer } from 'node: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: 1234const { Buffer } = require('node: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

buf.parent#

Stability: 0 - Deprecated: Use buf.buffer instead.

The buf.parent property is a deprecated alias for buf.buffer.

buf.readBigInt64BE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <bigint>

Reads a signed, big-endian 64-bit integer from buf at the specified offset.

Integers read from a Buffer are interpreted as two's complement signed values.

buf.readBigInt64LE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <bigint>

Reads a signed, little-endian 64-bit integer from buf at the specified offset.

Integers read from a Buffer are interpreted as two's complement signed values.

buf.readBigUInt64BE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <bigint>

Reads an unsigned, big-endian 64-bit integer from buf at the specified offset.

This function is also available under the readBigUint64BE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]);

console.log(buf.readBigUInt64BE(0));
// Prints: 4294967295nconst { Buffer } = require('node:buffer');

const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]);

console.log(buf.readBigUInt64BE(0));
// Prints: 4294967295n

buf.readBigUInt64LE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <bigint>

Reads an unsigned, little-endian 64-bit integer from buf at the specified offset.

This function is also available under the readBigUint64LE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]);

console.log(buf.readBigUInt64LE(0));
// Prints: 18446744069414584320nconst { Buffer } = require('node:buffer');

const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]);

console.log(buf.readBigUInt64LE(0));
// Prints: 18446744069414584320n

buf.readDoubleBE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <number>

Reads a 64-bit, big-endian double from buf at the specified offset.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);

console.log(buf.readDoubleBE(0));
// Prints: 8.20788039913184e-304const { Buffer } = require('node:buffer');

const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);

console.log(buf.readDoubleBE(0));
// Prints: 8.20788039913184e-304

buf.readDoubleLE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <number>

Reads a 64-bit, little-endian double from buf at the specified offset.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readFloatBE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <number>

Reads a 32-bit, big-endian float from buf at the specified offset.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([1, 2, 3, 4]);

console.log(buf.readFloatBE(0));
// Prints: 2.387939260590663e-38const { Buffer } = require('node:buffer');

const buf = Buffer.from([1, 2, 3, 4]);

console.log(buf.readFloatBE(0));
// Prints: 2.387939260590663e-38

buf.readFloatLE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <number>

Reads a 32-bit, little-endian float from buf at the specified offset.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readInt8([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 1. Default: 0.
  • Returns: <integer>

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.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readInt16BE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer>

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0, 5]);

console.log(buf.readInt16BE(0));
// Prints: 5const { Buffer } = require('node:buffer');

const buf = Buffer.from([0, 5]);

console.log(buf.readInt16BE(0));
// Prints: 5

buf.readInt16LE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer>

Reads a signed, little-endian 16-bit integer from buf at the specified offset.

Integers read from a Buffer are interpreted as two's complement signed values.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0, 5]);

console.log(buf.readInt16LE(0));
// Prints: 1280
console.log(buf.readInt16LE(1));
// Throws ERR_OUT_OF_RANGE.const { Buffer } = require('node:buffer');

const buf = Buffer.from([0, 5]);

console.log(buf.readInt16LE(0));
// Prints: 1280
console.log(buf.readInt16LE(1));
// Throws ERR_OUT_OF_RANGE.

buf.readInt32BE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer>

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0, 0, 0, 5]);

console.log(buf.readInt32BE(0));
// Prints: 5const { Buffer } = require('node:buffer');

const buf = Buffer.from([0, 0, 0, 5]);

console.log(buf.readInt32BE(0));
// Prints: 5

buf.readInt32LE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer>

Reads a signed, little-endian 32-bit integer from buf at the specified offset.

Integers read from a Buffer are interpreted as two's complement signed values.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readIntBE(offset, byteLength)#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to read. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer>

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.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readIntLE(offset, byteLength)#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to read. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer>

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readIntLE(0, 6).toString(16));
// Prints: -546f87a9cbeeconst { Buffer } = require('node:buffer');

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readIntLE(0, 6).toString(16));
// Prints: -546f87a9cbee

buf.readUInt8([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 1. Default: 0.
  • Returns: <integer>

Reads an unsigned 8-bit integer from buf at the specified offset.

This function is also available under the readUint8 alias.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readUInt16BE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer>

Reads an unsigned, big-endian 16-bit integer from buf at the specified offset.

This function is also available under the readUint16BE alias.

import { Buffer } from 'node: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: 3456const { Buffer } = require('node: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

buf.readUInt16LE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer>

Reads an unsigned, little-endian 16-bit integer from buf at the specified offset.

This function is also available under the readUint16LE alias.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readUInt32BE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer>

Reads an unsigned, big-endian 32-bit integer from buf at the specified offset.

This function is also available under the readUint32BE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]);

console.log(buf.readUInt32BE(0).toString(16));
// Prints: 12345678const { Buffer } = require('node:buffer');

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]);

console.log(buf.readUInt32BE(0).toString(16));
// Prints: 12345678

buf.readUInt32LE([offset])#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer>

Reads an unsigned, little-endian 32-bit integer from buf at the specified offset.

This function is also available under the readUint32LE alias.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readUIntBE(offset, byteLength)#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to read. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer>

Reads byteLength number of bytes from buf at the specified offset and interprets the result as an unsigned big-endian integer supporting up to 48 bits of accuracy.

This function is also available under the readUintBE alias.

import { Buffer } from 'node: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.const { Buffer } = require('node: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.

buf.readUIntLE(offset, byteLength)#

  • offset <integer> Number of bytes to skip before starting to read. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to read. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer>

Reads byteLength number of bytes from buf at the specified offset and interprets the result as an unsigned, little-endian integer supporting up to 48 bits of accuracy.

This function is also available under the readUintLE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readUIntLE(0, 6).toString(16));
// Prints: ab9078563412const { Buffer } = require('node:buffer');

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readUIntLE(0, 6).toString(16));
// Prints: ab9078563412

buf.subarray([start[, end]])#

Returns a new Buffer that references the same memory as the original, but offset and cropped by the start and end indexes.

Specifying end greater than buf.length will return the same result as that of end equal to buf.length.

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.

import { Buffer } from 'node: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: !bcconst { Buffer } = require('node: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

Specifying negative indexes causes the slice to be generated relative to the end of buf rather than the beginning.

import { Buffer } from 'node: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).)const { Buffer } = require('node: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).)

buf.slice([start[, end]])#

Stability: 0 - Deprecated: Use buf.subarray instead.

Returns a new Buffer that references the same memory as the original, but offset and cropped by the start and end indexes.

This method is not compatible with the Uint8Array.prototype.slice(), which is a superclass of Buffer. To copy the slice, use Uint8Array.prototype.slice().

import { Buffer } from 'node: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

// With buf.slice(), the original buffer is modified.
const notReallyCopiedBuf = buf.slice();
notReallyCopiedBuf[0]++;
console.log(notReallyCopiedBuf.toString());
// Prints: cuffer
console.log(buf.toString());
// Also prints: cuffer (!)const { Buffer } = require('node: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

// With buf.slice(), the original buffer is modified.
const notReallyCopiedBuf = buf.slice();
notReallyCopiedBuf[0]++;
console.log(notReallyCopiedBuf.toString());
// Prints: cuffer
console.log(buf.toString());
// Also prints: cuffer (!)

buf.swap16()#

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.

import { Buffer } from 'node:buffer';

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap16();

console.log(buf1);
// Prints: <Buffer 02 01 04 03 06 05 08 07>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap16();
// Throws ERR_INVALID_BUFFER_SIZE.const { Buffer } = require('node:buffer');

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap16();

console.log(buf1);
// Prints: <Buffer 02 01 04 03 06 05 08 07>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap16();
// Throws ERR_INVALID_BUFFER_SIZE.

One convenient use of buf.swap16() is to perform a fast in-place conversion between UTF-16 little-endian and UTF-16 big-endian:

import { Buffer } from 'node:buffer';

const buf = Buffer.from('This is little-endian UTF-16', 'utf16le');
buf.swap16(); // Convert to big-endian UTF-16 text.const { Buffer } = require('node:buffer');

const buf = Buffer.from('This is little-endian UTF-16', 'utf16le');
buf.swap16(); // Convert to big-endian UTF-16 text.

buf.swap32()#

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.

import { Buffer } from 'node:buffer';

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap32();

console.log(buf1);
// Prints: <Buffer 04 03 02 01 08 07 06 05>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap32();
// Throws ERR_INVALID_BUFFER_SIZE.const { Buffer } = require('node:buffer');

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap32();

console.log(buf1);
// Prints: <Buffer 04 03 02 01 08 07 06 05>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap32();
// Throws ERR_INVALID_BUFFER_SIZE.

buf.swap64()#

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.

import { Buffer } from 'node:buffer';

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap64();

console.log(buf1);
// Prints: <Buffer 08 07 06 05 04 03 02 01>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap64();
// Throws ERR_INVALID_BUFFER_SIZE.const { Buffer } = require('node:buffer');

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap64();

console.log(buf1);
// Prints: <Buffer 08 07 06 05 04 03 02 01>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap64();
// Throws ERR_INVALID_BUFFER_SIZE.

buf.toJSON()#

Returns a JSON representation of buf. JSON.stringify() implicitly calls 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).

import { Buffer } from 'node: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: <Buffer 01 02 03 04 05>const { Buffer } = require('node: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: <Buffer 01 02 03 04 05>

buf.toString([encoding[, start[, end]]])#

  • encoding <string> The character encoding to use. Default: 'utf8'.
  • start <integer> The byte offset to start decoding at. Default: 0.
  • end <integer> The byte offset to stop decoding at (not inclusive). Default: buf.length.
  • Returns: <string>

Decodes buf to a string according to the specified character encoding in encoding. start and end may be passed to decode only a subset of buf.

If encoding is 'utf8' and a byte sequence in the input is not valid UTF-8, 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.

import { Buffer } from 'node: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éconst { Buffer } = require('node: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é

buf.values()#

Creates and returns an iterator for buf values (bytes). This function is called automatically when a Buffer is used in a for..of statement.

import { Buffer } from 'node: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
//   114const { Buffer } = require('node: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

buf.write(string[, offset[, length]][, encoding])#

  • string <string> String to write to buf.
  • offset <integer> Number of bytes to skip before starting to write string. Default: 0.
  • length <integer> Maximum number of bytes to write (written bytes will not exceed buf.length - offset). Default: buf.length - offset.
  • encoding <string> The character encoding of string. Default: 'utf8'.
  • Returns: <integer> Number of bytes written.

Writes string to buf at offset according to the character encoding in encoding. The length parameter is the number of bytes to write. If buf did not contain enough space to fit the entire string, only part of string will be written. However, partially encoded characters will not be written.

import { Buffer } from 'node: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 : abconst { Buffer } = require('node: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

buf.writeBigInt64BE(value[, offset])#

  • value <bigint> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian.

value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64BE(0x0102030405060708n, 0);

console.log(buf);
// Prints: <Buffer 01 02 03 04 05 06 07 08>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64BE(0x0102030405060708n, 0);

console.log(buf);
// Prints: <Buffer 01 02 03 04 05 06 07 08>

buf.writeBigInt64LE(value[, offset])#

  • value <bigint> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian.

value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64LE(0x0102030405060708n, 0);

console.log(buf);
// Prints: <Buffer 08 07 06 05 04 03 02 01>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64LE(0x0102030405060708n, 0);

console.log(buf);
// Prints: <Buffer 08 07 06 05 04 03 02 01>

buf.writeBigUInt64BE(value[, offset])#

  • value <bigint> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian.

This function is also available under the writeBigUint64BE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64BE(0xdecafafecacefaden, 0);

console.log(buf);
// Prints: <Buffer de ca fa fe ca ce fa de>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64BE(0xdecafafecacefaden, 0);

console.log(buf);
// Prints: <Buffer de ca fa fe ca ce fa de>

buf.writeBigUInt64LE(value[, offset])#

  • value <bigint> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy: 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64LE(0xdecafafecacefaden, 0);

console.log(buf);
// Prints: <Buffer de fa ce ca fe fa ca de>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64LE(0xdecafafecacefaden, 0);

console.log(buf);
// Prints: <Buffer de fa ce ca fe fa ca de>

This function is also available under the writeBigUint64LE alias.

buf.writeDoubleBE(value[, offset])#

  • value <number> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleBE(123.456, 0);

console.log(buf);
// Prints: <Buffer 40 5e dd 2f 1a 9f be 77>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleBE(123.456, 0);

console.log(buf);
// Prints: <Buffer 40 5e dd 2f 1a 9f be 77>

buf.writeDoubleLE(value[, offset])#

  • value <number> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 8. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleLE(123.456, 0);

console.log(buf);
// Prints: <Buffer 77 be 9f 1a 2f dd 5e 40>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleLE(123.456, 0);

console.log(buf);
// Prints: <Buffer 77 be 9f 1a 2f dd 5e 40>

buf.writeFloatBE(value[, offset])#

  • value <number> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian. Behavior is undefined when value is anything other than a JavaScript number.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeFloatBE(0xcafebabe, 0);

console.log(buf);
// Prints: <Buffer 4f 4a fe bb>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeFloatBE(0xcafebabe, 0);

console.log(buf);
// Prints: <Buffer 4f 4a fe bb>

buf.writeFloatLE(value[, offset])#

  • value <number> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian. Behavior is undefined when value is anything other than a JavaScript number.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeFloatLE(0xcafebabe, 0);

console.log(buf);
// Prints: <Buffer bb fe 4a 4f>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeFloatLE(0xcafebabe, 0);

console.log(buf);
// Prints: <Buffer bb fe 4a 4f>

buf.writeInt8(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 1. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset. value must be a valid signed 8-bit integer. Behavior is undefined when value is anything other than a signed 8-bit integer.

value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(2);

buf.writeInt8(2, 0);
buf.writeInt8(-2, 1);

console.log(buf);
// Prints: <Buffer 02 fe>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(2);

buf.writeInt8(2, 0);
buf.writeInt8(-2, 1);

console.log(buf);
// Prints: <Buffer 02 fe>

buf.writeInt16BE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian. The value must be a valid signed 16-bit integer. Behavior is undefined when value is anything other than a signed 16-bit integer.

The value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(2);

buf.writeInt16BE(0x0102, 0);

console.log(buf);
// Prints: <Buffer 01 02>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(2);

buf.writeInt16BE(0x0102, 0);

console.log(buf);
// Prints: <Buffer 01 02>

buf.writeInt16LE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian. The value must be a valid signed 16-bit integer. Behavior is undefined when value is anything other than a signed 16-bit integer.

The value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(2);

buf.writeInt16LE(0x0304, 0);

console.log(buf);
// Prints: <Buffer 04 03>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(2);

buf.writeInt16LE(0x0304, 0);

console.log(buf);
// Prints: <Buffer 04 03>

buf.writeInt32BE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian. The value must be a valid signed 32-bit integer. Behavior is undefined when value is anything other than a signed 32-bit integer.

The value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeInt32BE(0x01020304, 0);

console.log(buf);
// Prints: <Buffer 01 02 03 04>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeInt32BE(0x01020304, 0);

console.log(buf);
// Prints: <Buffer 01 02 03 04>

buf.writeInt32LE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian. The value must be a valid signed 32-bit integer. Behavior is undefined when value is anything other than a signed 32-bit integer.

The value is interpreted and written as a two's complement signed integer.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeInt32LE(0x05060708, 0);

console.log(buf);
// Prints: <Buffer 08 07 06 05>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeInt32LE(0x05060708, 0);

console.log(buf);
// Prints: <Buffer 08 07 06 05>

buf.writeIntBE(value, offset, byteLength)#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to write. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer> offset plus the number of bytes written.

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(6);

buf.writeIntBE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer 12 34 56 78 90 ab>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(6);

buf.writeIntBE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer 12 34 56 78 90 ab>

buf.writeIntLE(value, offset, byteLength)#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to write. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer> offset plus the number of bytes written.

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.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(6);

buf.writeIntLE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer ab 90 78 56 34 12>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(6);

buf.writeIntLE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer ab 90 78 56 34 12>

buf.writeUInt8(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 1. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset. value must be a valid unsigned 8-bit integer. Behavior is undefined when value is anything other than an unsigned 8-bit integer.

This function is also available under the writeUint8 alias.

import { Buffer } from 'node: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: <Buffer 03 04 23 42>const { Buffer } = require('node: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: <Buffer 03 04 23 42>

buf.writeUInt16BE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian. The value must be a valid unsigned 16-bit integer. Behavior is undefined when value is anything other than an unsigned 16-bit integer.

This function is also available under the writeUint16BE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16BE(0xdead, 0);
buf.writeUInt16BE(0xbeef, 2);

console.log(buf);
// Prints: <Buffer de ad be ef>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16BE(0xdead, 0);
buf.writeUInt16BE(0xbeef, 2);

console.log(buf);
// Prints: <Buffer de ad be ef>

buf.writeUInt16LE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 2. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian. The value must be a valid unsigned 16-bit integer. Behavior is undefined when value is anything other than an unsigned 16-bit integer.

This function is also available under the writeUint16LE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16LE(0xdead, 0);
buf.writeUInt16LE(0xbeef, 2);

console.log(buf);
// Prints: <Buffer ad de ef be>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16LE(0xdead, 0);
buf.writeUInt16LE(0xbeef, 2);

console.log(buf);
// Prints: <Buffer ad de ef be>

buf.writeUInt32BE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as big-endian. The value must be a valid unsigned 32-bit integer. Behavior is undefined when value is anything other than an unsigned 32-bit integer.

This function is also available under the writeUint32BE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32BE(0xfeedface, 0);

console.log(buf);
// Prints: <Buffer fe ed fa ce>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32BE(0xfeedface, 0);

console.log(buf);
// Prints: <Buffer fe ed fa ce>

buf.writeUInt32LE(value[, offset])#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - 4. Default: 0.
  • Returns: <integer> offset plus the number of bytes written.

Writes value to buf at the specified offset as little-endian. The value must be a valid unsigned 32-bit integer. Behavior is undefined when value is anything other than an unsigned 32-bit integer.

This function is also available under the writeUint32LE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32LE(0xfeedface, 0);

console.log(buf);
// Prints: <Buffer ce fa ed fe>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32LE(0xfeedface, 0);

console.log(buf);
// Prints: <Buffer ce fa ed fe>

buf.writeUIntBE(value, offset, byteLength)#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to write. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer> offset plus the number of bytes written.

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 an unsigned integer.

This function is also available under the writeUintBE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(6);

buf.writeUIntBE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer 12 34 56 78 90 ab>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(6);

buf.writeUIntBE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer 12 34 56 78 90 ab>

buf.writeUIntLE(value, offset, byteLength)#

  • value <integer> Number to be written to buf.
  • offset <integer> Number of bytes to skip before starting to write. Must satisfy 0 <= offset <= buf.length - byteLength.
  • byteLength <integer> Number of bytes to write. Must satisfy 0 < byteLength <= 6.
  • Returns: <integer> offset plus the number of bytes written.

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 an unsigned integer.

This function is also available under the writeUintLE alias.

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(6);

buf.writeUIntLE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer ab 90 78 56 34 12>const { Buffer } = require('node:buffer');

const buf = Buffer.allocUnsafe(6);

buf.writeUIntLE(0x1234567890ab, 0, 6);

console.log(buf);
// Prints: <Buffer ab 90 78 56 34 12>

new Buffer(array)#

Stability: 0 - Deprecated: Use Buffer.from(array) instead.

See Buffer.from(array).

new Buffer(arrayBuffer[, byteOffset[, length]])#

See Buffer.from(arrayBuffer[, byteOffset[, length]]).

new Buffer(buffer)#

Stability: 0 - Deprecated: Use Buffer.from(buffer) instead.

See Buffer.from(buffer).

new Buffer(size)#

Stability: 0 - Deprecated: Use Buffer.alloc() instead (also see Buffer.allocUnsafe()).

  • size <integer> The desired length of the new Buffer.

See Buffer.alloc() and Buffer.allocUnsafe(). This variant of the constructor is equivalent to Buffer.alloc().

new Buffer(string[, encoding])#

  • string <string> String to encode.
  • encoding <string> The encoding of string. Default: 'utf8'.

See Buffer.from(string[, encoding]).

Class: File#

A <File> provides information about files.

new buffer.File(sources, fileName[, options])#

file.name#

The name of the File.

file.lastModified#

The last modified date of the File.

node:buffer module APIs#

While, the Buffer object is available as a global, there are additional Buffer-related APIs that are available only via the node:buffer module accessed using require('node:buffer').

buffer.atob(data)#

Stability: 3 - Legacy. Use Buffer.from(data, 'base64') instead.

  • data <any> The Base64-encoded input string.

Decodes a string of Base64-encoded data into bytes, and encodes those bytes into a string using Latin-1 (ISO-8859-1).

The data may be any JavaScript-value that can be coerced into a string.

This function is only provided for compatibility with legacy web platform APIs and should never be used in new code, because they use strings to represent binary data and predate the introduction of typed arrays in JavaScript. For code running using Node.js APIs, converting between base64-encoded strings and binary data should be performed using Buffer.from(str, 'base64') and buf.toString('base64').

buffer.btoa(data)#

Stability: 3 - Legacy. Use buf.toString('base64') instead.

  • data <any> An ASCII (Latin1) string.

Decodes a string into bytes using Latin-1 (ISO-8859), and encodes those bytes into a string using Base64.

The data may be any JavaScript-value that can be coerced into a string.

This function is only provided for compatibility with legacy web platform APIs and should never be used in new code, because they use strings to represent binary data and predate the introduction of typed arrays in JavaScript. For code running using Node.js APIs, converting between base64-encoded strings and binary data should be performed using Buffer.from(str, 'base64') and buf.toString('base64').

buffer.isAscii(input)#

This function returns true if input contains only valid ASCII-encoded data, including the case in which input is empty.

Throws if the input is a detached array buffer.

buffer.isUtf8(input)#

This function returns true if input contains only valid UTF-8-encoded data, including the case in which input is empty.

Throws if the input is a detached array buffer.

buffer.INSPECT_MAX_BYTES#

Returns the maximum number of bytes that will be returned when buf.inspect() is called. This can be overridden by user modules. See util.inspect() for more details on buf.inspect() behavior.

buffer.kMaxLength#

  • <integer> The largest size allowed for a single Buffer instance.

An alias for buffer.constants.MAX_LENGTH.

buffer.kStringMaxLength#

  • <integer> The largest length allowed for a single string instance.

An alias for buffer.constants.MAX_STRING_LENGTH.

buffer.resolveObjectURL(id)#

  • id <string> A 'blob:nodedata:... URL string returned by a prior call to URL.createObjectURL().
  • Returns: <Blob>

Resolves a 'blob:nodedata:...' an associated <Blob> object registered using a prior call to URL.createObjectURL().

buffer.transcode(source, fromEnc, toEnc)#

Re-encodes the given Buffer or Uint8Array instance from one character encoding to another. Returns a new Buffer instance.

Throws if the fromEnc or toEnc specify invalid character encodings or if conversion from fromEnc to toEnc is not permitted.

Encodings supported by buffer.transcode() are: 'ascii', 'utf8', 'utf16le', 'ucs2', 'latin1', and 'binary'.

The transcoding process will use substitution characters if a given byte sequence cannot be adequately represented in the target encoding. For instance:

import { Buffer, transcode } from 'node:buffer';

const newBuf = transcode(Buffer.from('€'), 'utf8', 'ascii');
console.log(newBuf.toString('ascii'));
// Prints: '?'const { Buffer, transcode } = require('node:buffer');

const newBuf = transcode(Buffer.from('€'), 'utf8', 'ascii');
console.log(newBuf.toString('ascii'));
// Prints: '?'

Because the Euro () sign is not representable in US-ASCII, it is replaced with ? in the transcoded Buffer.

Class: SlowBuffer#

Stability: 0 - Deprecated: Use Buffer.allocUnsafeSlow() instead.

See Buffer.allocUnsafeSlow(). This was never a class in the sense that the constructor always returned a Buffer instance, rather than a SlowBuffer instance.

new SlowBuffer(size)#
  • size <integer> The desired length of the new SlowBuffer.

See Buffer.allocUnsafeSlow().

Buffer constants#

buffer.constants.MAX_LENGTH#
  • <integer> The largest size allowed for a single Buffer instance.

On 32-bit architectures, this value currently is 230 - 1 (about 1 GiB).

On 64-bit architectures, this value currently is 253 - 1 (about 8 PiB).

It reflects v8::TypedArray::kMaxLength under the hood.

This value is also available as buffer.kMaxLength.

buffer.constants.MAX_STRING_LENGTH#
  • <integer> The largest length allowed for a single string instance.

Represents the largest length that a string primitive can have, counted in UTF-16 code units.

This value may depend on the JS engine that is being used.

Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe()#

In versions of Node.js prior to 6.0.0, Buffer instances were created using the Buffer constructor function, which allocates the returned Buffer differently based on what arguments are provided:

  • Passing a number as the first argument to Buffer() (e.g. new Buffer(10)) allocates a new Buffer object of the specified size. Prior to Node.js 8.0.0, the memory allocated for such Buffer instances is not initialized and can contain sensitive data. Such Buffer instances must be subsequently initialized by using either buf.fill(0) or by writing to the entire Buffer before reading data from the Buffer. While this behavior is intentional to improve performance, development experience has demonstrated that a more explicit distinction is required between creating a fast-but-uninitialized Buffer versus creating a slower-but-safer Buffer. Since Node.js 8.0.0, Buffer(num) and new Buffer(num) return a Buffer with initialized memory.
  • Passing a string, array, or Buffer as the first argument copies the passed object's data into the Buffer.
  • Passing an <ArrayBuffer> or a <SharedArrayBuffer> returns a Buffer that shares allocated memory with the given array buffer.

Because the behavior of new Buffer() is different depending on the type of the first argument, security and reliability issues can be inadvertently introduced into applications when argument validation or Buffer initialization is not performed.

For example, if an attacker can cause an application to receive a number where a string is expected, the application may call new Buffer(100) instead of new Buffer("100"), leading it to allocate a 100 byte buffer instead of allocating a 3 byte buffer with content "100". This is commonly possible using JSON API calls. Since JSON distinguishes between numeric and string types, it allows injection of numbers where a naively written application that does not validate its input sufficiently might expect to always receive a string. Before Node.js 8.0.0, the 100 byte buffer might contain arbitrary pre-existing in-memory data, so may be used to expose in-memory secrets to a remote attacker. Since Node.js 8.0.0, exposure of memory cannot occur because the data is zero-filled. However, other attacks are still possible, such as causing very large buffers to be allocated by the server, leading to performance degradation or crashing on memory exhaustion.

To make the creation of Buffer instances more reliable and less error-prone, the various forms of the new Buffer() constructor have been deprecated and replaced by separate Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe() methods.

Developers should migrate all existing uses of the new Buffer() constructors to one of these new APIs.

Buffer instances returned by Buffer.allocUnsafe(), Buffer.from(string), Buffer.concat() and Buffer.from(array) may be allocated off a shared internal memory pool if size is less than or equal to half Buffer.poolSize. Instances returned by Buffer.allocUnsafeSlow() never use the shared internal memory pool.

The --zero-fill-buffers command-line option#

Node.js can be started using the --zero-fill-buffers command-line option to cause all newly-allocated Buffer instances to be zero-filled upon creation by default. Without the option, buffers created with Buffer.allocUnsafe(), Buffer.allocUnsafeSlow(), and new SlowBuffer(size) are not zero-filled. Use of this flag can have a measurable negative impact on performance. Use the --zero-fill-buffers option only when necessary to enforce that newly allocated Buffer instances cannot contain old data that is potentially sensitive.

$ node --zero-fill-buffers
> Buffer.allocUnsafe(5);
<Buffer 00 00 00 00 00> 

What makes Buffer.allocUnsafe() and Buffer.allocUnsafeSlow() "unsafe"?#

When calling Buffer.allocUnsafe() and Buffer.allocUnsafeSlow(), the segment of allocated memory is uninitialized (it is not zeroed-out). While this design makes the allocation of memory quite fast, the allocated segment of memory might contain old data that is potentially sensitive. Using a Buffer created by Buffer.allocUnsafe() without completely overwriting the memory can allow this old data to be leaked when the Buffer memory is read.

While there are clear performance advantages to using Buffer.allocUnsafe(), extra care must be taken in order to avoid introducing security vulnerabilities into an application.

C++ addons#

Addons are dynamically-linked shared objects written in C++. The require() function can load addons as ordinary Node.js modules. Addons provide an interface between JavaScript and C/C++ libraries.

There are three options for implementing addons:

Unless there is a need for direct access to functionality which is not
exposed by Node-API, use Node-API. Refer to C/C++ addons with Node-API for more information on Node-API.

When not using Node-API, implementing addons becomes more complex, requiring
knowledge of multiple components and APIs:

  • V8: the C++ library Node.js uses to provide the JavaScript implementation. It provides the mechanisms for creating objects, calling functions, etc. The V8's API is documented mostly in the v8.h header file (deps/v8/include/v8.h in the Node.js source tree), and is also available online.

  • libuv: The C library that implements the Node.js event loop, its worker threads and all of the asynchronous behaviors of the platform. It also serves as a cross-platform abstraction library, giving easy, POSIX-like access across all major operating systems to many common system tasks, such as interacting with the file system, sockets, timers, and system events. libuv also provides a threading abstraction similar to POSIX threads for more sophisticated asynchronous addons that need to move beyond the standard event loop. Addon authors should avoid blocking the event loop with I/O or other time-intensive tasks by offloading work via libuv to non-blocking system operations, worker threads, or a custom use of libuv threads.

  • Internal Node.js libraries: Node.js itself exports C++ APIs that addons can use, the most important of which is the node::ObjectWrap class.

  • Other statically linked libraries (including OpenSSL): These other libraries are located in the deps/ directory in the Node.js source tree. Only the libuv, OpenSSL, V8, and zlib symbols are purposefully re-exported by Node.js and may be used to various extents by addons. See Linking to libraries included with Node.js for additional information.

All of the following examples are available for download and may be used as the starting-point for an addon.

Hello world#

This "Hello world" example is a simple addon, written in C++, that is the equivalent of the following JavaScript code:

module.exports.hello = () => 'world'; 

First, create the file hello.cc:

// hello.cc
#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(
      isolate, "world", NewStringType::kNormal).ToLocalChecked());
}

void Initialize(Local<Object> exports) {
  NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)

}  // namespace demo 

All Node.js addons must export an initialization function following the pattern:

void Initialize(Local<Object> exports);
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) 

There is no semi-colon after NODE_MODULE as it's not a function (see node.h).

The module_name must match the filename of the final binary (excluding the .node suffix).

In the hello.cc example, then, the initialization function is Initialize and the addon module name is addon.

When building addons with node-gyp, using the macro NODE_GYP_MODULE_NAME as the first parameter of NODE_MODULE() will ensure that the name of the final binary will be passed to NODE_MODULE().

Addons defined with NODE_MODULE() can not be loaded in multiple contexts or multiple threads at the same time.

Context-aware addons#

There are environments in which Node.js addons may need to be loaded multiple times in multiple contexts. For example, the Electron runtime runs multiple instances of Node.js in a single process. Each instance will have its own require() cache, and thus each instance will need a native addon to behave correctly when loaded via require(). This means that the addon must support multiple initializations.

A context-aware addon can be constructed by using the macro NODE_MODULE_INITIALIZER, which expands to the name of a function which Node.js will expect to find when it loads an addon. An addon can thus be initialized as in the following example:

using namespace v8;

extern "C" NODE_MODULE_EXPORT void
NODE_MODULE_INITIALIZER(Local<Object> exports,
                        Local<Value> module,
                        Local<Context> context) {
  /* Perform addon initialization steps here. */
} 

Another option is to use the macro NODE_MODULE_INIT(), which will also construct a context-aware addon. Unlike NODE_MODULE(), which is used to construct an addon around a given addon initializer function, NODE_MODULE_INIT() serves as the declaration of such an initializer to be followed by a function body.

The following three variables may be used inside the function body following an invocation of NODE_MODULE_INIT():

  • Local<Object> exports,
  • Local<Value> module, and
  • Local<Context> context

Building a context-aware addon requires careful management of global static data to ensure stability and correctness. Since the addon may be loaded multiple times, potentially even from different threads, any global static data stored in the addon must be properly protected, and must not contain any persistent references to JavaScript objects. The reason for this is that JavaScript objects are only valid in one context, and will likely cause a crash when accessed from the wrong context or from a different thread than the one on which they were created.

The context-aware addon can be structured to avoid global static data by performing the following steps:

  • Define a class which will hold per-addon-instance data and which has a static member of the form
    static void DeleteInstance(void* data) {
      // Cast `data` to an instance of the class and delete it.
    } 
  • Heap-allocate an instance of this class in the addon initializer. This can be accomplished using the new keyword.
  • Call node::AddEnvironmentCleanupHook(), passing it the above-created instance and a pointer to DeleteInstance(). This will ensure the instance is deleted when the environment is torn down.
  • Store the instance of the class in a v8::External, and
  • Pass the v8::External to all methods exposed to JavaScript by passing it to v8::FunctionTemplate::New() or v8::Function::New() which creates the native-backed JavaScript functions. The third parameter of v8::FunctionTemplate::New() or v8::Function::New() accepts the v8::External and makes it available in the native callback using the v8::FunctionCallbackInfo::Data() method.

This will ensure that the per-addon-instance data reaches each binding that can be called from JavaScript. The per-addon-instance data must also be passed into any asynchronous callbacks the addon may create.

The following example illustrates the implementation of a context-aware addon:

#include <node.h>

using namespace v8;

class AddonData {
 public:
  explicit AddonData(Isolate* isolate):
      call_count(0) {
    // Ensure this per-addon-instance data is deleted at environment cleanup.
    node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
  }

  // Per-addon data.
  int call_count;

  static void DeleteInstance(void* data) {
    delete static_cast<AddonData*>(data);
  }
};

static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
  // Retrieve the per-addon-instance data.
  AddonData* data =
      reinterpret_cast<AddonData*>(info.Data().As<External>()->Value());
  data->call_count++;
  info.GetReturnValue().Set((double)data->call_count);
}

// Initialize this addon to be context-aware.
NODE_MODULE_INIT(/* exports, module, context */) {
  Isolate* isolate = context->GetIsolate();

  // Create a new instance of `AddonData` for this instance of the addon and
  // tie its life cycle to that of the Node.js environment.
  AddonData* data = new AddonData(isolate);

  // Wrap the data in a `v8::External` so we can pass it to the method we
  // expose.
  Local<External> external = External::New(isolate, data);

  // Expose the method `Method` to JavaScript, and make sure it receives the
  // per-addon-instance data we created above by passing `external` as the
  // third parameter to the `FunctionTemplate` constructor.
  exports->Set(context,
               String::NewFromUtf8(isolate, "method").ToLocalChecked(),
               FunctionTemplate::New(isolate, Method, external)
                  ->GetFunction(context).ToLocalChecked()).FromJust();
} 
Worker support#

In order to be loaded from multiple Node.js environments, such as a main thread and a Worker thread, an add-on needs to either:

  • Be an Node-API addon, or
  • Be declared as context-aware using NODE_MODULE_INIT() as described above

In order to support Worker threads, addons need to clean up any resources they may have allocated when such a thread exits. This can be achieved through the usage of the AddEnvironmentCleanupHook() function:

void AddEnvironmentCleanupHook(v8::Isolate* isolate,
                               void (*fun)(void* arg),
                               void* arg); 

This function adds a hook that will run before a given Node.js instance shuts down. If necessary, such hooks can be removed before they are run using RemoveEnvironmentCleanupHook(), which has the same signature. Callbacks are run in last-in first-out order.

If necessary, there is an additional pair of AddEnvironmentCleanupHook() and RemoveEnvironmentCleanupHook() overloads, where the cleanup hook takes a callback function. This can be used for shutting down asynchronous resources, such as any libuv handles registered by the addon.

The following addon.cc uses AddEnvironmentCleanupHook:

// addon.cc
#include <node.h>
#include <assert.h>
#include <stdlib.h>

using node::AddEnvironmentCleanupHook;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;

// Note: In a real-world application, do not rely on static/global data.
static char cookie[] = "yum yum";
static int cleanup_cb1_called = 0;
static int cleanup_cb2_called = 0;

static void cleanup_cb1(void* arg) {
  Isolate* isolate = static_cast<Isolate*>(arg);
  HandleScope scope(isolate);
  Local<Object> obj = Object::New(isolate);
  assert(!obj.IsEmpty());  // assert VM is still alive
  assert(obj->IsObject());
  cleanup_cb1_called++;
}

static void cleanup_cb2(void* arg) {
  assert(arg == static_cast<void*>(cookie));
  cleanup_cb2_called++;
}

static void sanity_check(void*) {
  assert(cleanup_cb1_called == 1);
  assert(cleanup_cb2_called == 1);
}

// Initialize this addon to be context-aware.
NODE_MODULE_INIT(/* exports, module, context */) {
  Isolate* isolate = context->GetIsolate();

  AddEnvironmentCleanupHook(isolate, sanity_check, nullptr);
  AddEnvironmentCleanupHook(isolate, cleanup_cb2, cookie);
  AddEnvironmentCleanupHook(isolate, cleanup_cb1, isolate);
} 

Test in JavaScript by running:

// test.js
require('./build/Release/addon'); 

Building#

Once the source code has been written, it must be compiled into the binary addon.node file. To do so, create a file called binding.gyp in the top-level of the project describing the build configuration of the module using a JSON-like format. This file is used by node-gyp, a tool written specifically to compile Node.js addons.

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "hello.cc" ]
    }
  ]
} 

A version of the node-gyp utility is bundled and distributed with Node.js as part of npm. This version is not made directly available for developers to use and is intended only to support the ability to use the npm install command to compile and install addons. Developers who wish to use node-gyp directly can install it using the command npm install -g node-gyp. See the node-gyp installation instructions for more information, including platform-specific requirements.

Once the binding.gyp file has been created, use node-gyp configure to generate the appropriate project build files for the current platform. This will generate either a Makefile (on Unix platforms) or a vcxproj file (on Windows) in the build/ directory.

Next, invoke the node-gyp build command to generate the compiled addon.node file. This will be put into the build/Release/ directory.

When using npm install to install a Node.js addon, npm uses its own bundled version of node-gyp to perform this same set of actions, generating a compiled version of the addon for the user's platform on demand.

Once built, the binary addon can be used from within Node.js by pointing require() to the built addon.node module:

// hello.js
const addon = require('./build/Release/addon');

console.log(addon.hello());
// Prints: 'world' 

Because the exact path to the compiled addon binary can vary depending on how it is compiled (i.e. sometimes it may be in ./build/Debug/), addons can use the bindings package to load the compiled module.

While the bindings package implementation is more sophisticated in how it locates addon modules, it is essentially using a try…catch pattern similar to:

try {
  return require('./build/Release/addon.node');
} catch (err) {
  return require('./build/Debug/addon.node');
} 

Linking to libraries included with Node.js#

Node.js uses statically linked libraries such as V8, libuv, and OpenSSL. All addons are required to link to V8 and may link to any of the other dependencies as well. Typically, this is as simple as including the appropriate #include <...> statements (e.g. #include <v8.h>) and node-gyp will locate the appropriate headers automatically. However, there are a few caveats to be aware of:

  • When node-gyp runs, it will detect the specific release version of Node.js and download either the full source tarball or just the headers. If the full source is downloaded, addons will have complete access to the full set of Node.js dependencies. However, if only the Node.js headers are downloaded, then only the symbols exported by Node.js will be available.

  • node-gyp can be run using the --nodedir flag pointing at a local Node.js source image. Using this option, the addon will have access to the full set of dependencies.

Loading addons using require()#

The filename extension of the compiled addon binary is .node (as opposed to .dll or .so). The require() function is written to look for files with the .node file extension and initialize those as dynamically-linked libraries.

When calling require(), the .node extension can usually be omitted and Node.js will still find and initialize the addon. One caveat, however, is that Node.js will first attempt to locate and load modules or JavaScript files that happen to share the same base name. For instance, if there is a file addon.js in the same directory as the binary addon.node, then require('addon') will give precedence to the addon.js file and load it instead.

Native abstractions for Node.js#

Each of the examples illustrated in this document directly use the Node.js and V8 APIs for implementing addons. The V8 API can, and has, changed dramatically from one V8 release to the next (and one major Node.js release to the next). With each change, addons may need to be updated and recompiled in order to continue functioning. The Node.js release schedule is designed to minimize the frequency and impact of such changes but there is little that Node.js can do to ensure stability of the V8 APIs.

The Native Abstractions for Node.js (or nan) provide a set of tools that addon developers are recommended to use to keep compatibility between past and future releases of V8 and Node.js. See the nan examples for an illustration of how it can be used.

Node-API#

Stability: 2 - Stable

Node-API is an API for building native addons. It is independent from the underlying JavaScript runtime (e.g. V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js. It is intended to insulate addons from changes in the underlying JavaScript engine and allow modules compiled for one version to run on later versions of Node.js without recompilation. Addons are built/packaged with the same approach/tools outlined in this document (node-gyp, etc.). The only difference is the set of APIs that are used by the native code. Instead of using the V8 or Native Abstractions for Node.js APIs, the functions available in the Node-API are used.

Creating and maintaining an addon that benefits from the ABI stability provided by Node-API carries with it certain implementation considerations.

To use Node-API in the above "Hello world" example, replace the content of hello.cc with the following. All other instructions remain the same.

// hello.cc using Node-API
#include <node_api.h>

namespace demo {

napi_value Method(napi_env env, napi_callback_info args) {
  napi_value greeting;
  napi_status status;

  status = napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &greeting);
  if (status != napi_ok) return nullptr;
  return greeting;
}

napi_value init(napi_env env, napi_value exports) {
  napi_status status;
  napi_value fn;

  status = napi_create_function(env, nullptr, 0, Method, nullptr, &fn);
  if (status != napi_ok) return nullptr;

  status = napi_set_named_property(env, exports, "hello", fn);
  if (status != napi_ok) return nullptr;
  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, init)

}  // namespace demo 

The functions available and how to use them are documented in C/C++ addons with Node-API.

Addon examples#

Following are some example addons intended to help developers get started. The examples use the V8 APIs. Refer to the online V8 reference for help with the various V8 calls, and V8's Embedder's Guide for an explanation of several concepts used such as handles, scopes, function templates, etc.

Each of these examples using the following binding.gyp file:

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "addon.cc" ]
    }
  ]
} 

In cases where there is more than one .cc file, simply add the additional filename to the sources array:

"sources": ["addon.cc", "myexample.cc"] 

Once the binding.gyp file is ready, the example addons can be configured and built using node-gyp:

node-gyp configure build 

Function arguments#

Addons will typically expose objects and functions that can be accessed from JavaScript running within Node.js. When functions are invoked from JavaScript, the input arguments and return value must be mapped to and from the C/C++ code.

The following example illustrates how to read function arguments passed from JavaScript and how to return a result:

// addon.cc
#include <node.h>

namespace demo {

using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

// This is the implementation of the "add" method
// Input arguments are passed using the
// const FunctionCallbackInfo<Value>& args struct
void Add(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  // Check the number of arguments passed.
  if (args.Length() < 2) {
    // Throw an Error that is passed back to JavaScript
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate,
                            "Wrong number of arguments").ToLocalChecked()));
    return;
  }

  // Check the argument types
  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate,
                            "Wrong arguments").ToLocalChecked()));
    return;
  }

  // Perform the operation
  double value =
      args[0].As<Number>()->Value() + args[1].As<Number>()->Value();
  Local<Number> num = Number::New(isolate, value);

  // Set the return value (using the passed in
  // FunctionCallbackInfo<Value>&)
  args.GetReturnValue().Set(num);
}

void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "add", Add);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

}  // namespace demo 

Once compiled, the example addon can be required and used from within Node.js:

// test.js
const addon = require('./build/Release/addon');

console.log('This should be eight:', addon.add(3, 5)); 

Callbacks#

It is common practice within addons to pass JavaScript functions to a C++ function and execute them from there. The following example illustrates how to invoke such callbacks:

// addon.cc
#include <node.h>

namespace demo {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Null;
using v8::Object;
using v8::String;
using v8::Value;

void RunCallback(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Local<Function> cb = Local<Function>::Cast(args[0]);
  const unsigned argc = 1;
  Local<Value> argv[argc] = {
      String::NewFromUtf8(isolate,
                          "hello world").ToLocalChecked() };
  cb->Call(context, Null(isolate), argc, argv).ToLocalChecked();
}

void Init(Local<Object> exports, Local<Object> module) {
  NODE_SET_METHOD(module, "exports", RunCallback);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

}  // namespace demo 

This example uses a two-argument form of Init() that receives the full module object as the second argument. This allows the addon to completely overwrite exports with a single function instead of adding the function as a property of exports.

To test it, run the following JavaScript:

// test.js
const addon = require('./build/Release/addon');

addon((msg) => {
  console.log(msg);
// Prints: 'hello world'
}); 

In this example, the callback function is invoked synchronously.

Object factory#

Addons can create and return new objects from within a C++ function as illustrated in the following example. An object is created and returned with a property msg that echoes the string passed to createObject():

// addon.cc
#include <node.h>

namespace demo {

using v8::Context;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void CreateObject(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  Local<Object> obj = Object::New(isolate);
  obj->Set(context,
           String::NewFromUtf8(isolate,
                               "msg").ToLocalChecked(),
                               args[0]->ToString(context).ToLocalChecked())
           .FromJust();

  args.GetReturnValue().Set(obj);
}

void Init(Local<Object> exports, Local<Object> module) {
  NODE_SET_METHOD(module, "exports", CreateObject);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

}  // namespace demo 

To test it in JavaScript:

// test.js
const addon = require('./build/Release/addon');

const obj1 = addon('hello');
const obj2 = addon('world');
console.log(obj1.msg, obj2.msg);
// Prints: 'hello world' 

Function factory#

Another common scenario is creating JavaScript functions that wrap C++ functions and returning those back to JavaScript:

// addon.cc
#include <node.h>

namespace demo {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void MyFunction(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(
      isolate, "hello world").ToLocalChecked());
}

void CreateFunction(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  Local<Context> context = isolate->GetCurrentContext();
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, MyFunction);
  Local<Function> fn = tpl->GetFunction(context).ToLocalChecked();

  // omit this to make it anonymous
  fn->SetName(String::NewFromUtf8(
      isolate, "theFunction").ToLocalChecked());

  args.GetReturnValue().Set(fn);
}

void Init(Local<Object> exports, Local<Object> module) {
  NODE_SET_METHOD(module, "exports", CreateFunction);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

}  // namespace demo 

To test:

// test.js
const addon = require('./build/Release/addon');

const fn = addon();
console.log(fn());
// Prints: 'hello world' 

Wrapping C++ objects#

It is also possible to wrap C++ objects/classes in a way that allows new instances to be created using the JavaScript new operator:

// addon.cc
#include <node.h>
#include "myobject.h"

namespace demo {

using v8::Local;
using v8::Object;

void InitAll(Local<Object> exports) {
  MyObject::Init(exports);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)

}  // namespace demo 

Then, in myobject.h, the wrapper class inherits from node::ObjectWrap:

// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <node.h>
#include <node_object_wrap.h>

namespace demo {

class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Local<v8::Object> exports);

 private:
  explicit MyObject(double value = 0);
  ~MyObject();

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);

  double value_;
};

}  // namespace demo

#endif 

In myobject.cc, implement the various methods that are to be exposed. In the following code, the method plusOne() is exposed by adding it to the constructor's prototype:

// myobject.cc
#include "myobject.h"

namespace demo {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::String;
using v8::Value;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(Local<Object> exports) {
  Isolate* isolate = exports->GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  Local<ObjectTemplate> addon_data_tpl = ObjectTemplate::New(isolate);
  addon_data_tpl->SetInternalFieldCount(1);  // 1 field for the MyObject::New()
  Local<Object> addon_data =
      addon_data_tpl->NewInstance(context).ToLocalChecked();

  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New, addon_data);
  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);

  Local<Function> constructor = tpl->GetFunction(context).ToLocalChecked();
  addon_data->SetInternalField(0, constructor);
  exports->Set(context, String::NewFromUtf8(
      isolate, "MyObject").ToLocalChecked(),
      constructor).FromJust();
}

void MyObject::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    double value = args[0]->IsUndefined() ?
        0 : args[0]->NumberValue(context).FromMaybe(0);
    MyObject* obj = new MyObject(value);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 1;
    Local<Value> argv[argc] = { args[0] };
    Local<Function> cons =
        args.Data().As<Object>()->GetInternalField(0)
            .As<Value>().As<Function>();
    Local<Object> result =
        cons->NewInstance(context, argc, argv).ToLocalChecked();
    args.GetReturnValue().Set(result);
  }
}

void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
  obj->value_ += 1;

  args.GetReturnValue().Set(Number::New(isolate, obj->value_));
}

}  // namespace demo 

To build this example, the myobject.cc file must be added to the binding.gyp:

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [
        "addon.cc",
        "myobject.cc"
      ]
    }
  ]
} 

Test it with:

// test.js
const addon = require('./build/Release/addon');

const obj = new addon.MyObject(10);
console.log(obj.plusOne());
// Prints: 11
console.log(obj.plusOne());
// Prints: 12
console.log(obj.plusOne());
// Prints: 13 

The destructor for a wrapper object will run when the object is garbage-collected. For destructor testing, there are command-line flags that can be used to make it possible to force garbage collection. These flags are provided by the underlying V8 JavaScript engine. They are subject to change or removal at any time. They are not documented by Node.js or V8, and they should never be used outside of testing.

During shutdown of the process or worker threads destructors are not called by the JS engine. Therefore it's the responsibility of the user to track these objects and ensure proper destruction to avoid resource leaks.

Factory of wrapped objects#

Alternatively, it is possible to use a factory pattern to avoid explicitly creating object instances using the JavaScript new operator:

const obj = addon.createObject();
// instead of:
// const obj = new addon.Object(); 

First, the createObject() method is implemented in addon.cc:

// addon.cc
#include <node.h>
#include "myobject.h"

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void CreateObject(const FunctionCallbackInfo<Value>& args) {
  MyObject::NewInstance(args);
}

void InitAll(Local<Object> exports, Local<Object> module) {
  MyObject::Init(exports->GetIsolate());

  NODE_SET_METHOD(module, "exports", CreateObject);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)

}  // namespace demo 

In myobject.h, the static method NewInstance() is added to handle instantiating the object. This method takes the place of using new in JavaScript:

// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <node.h>
#include <node_object_wrap.h>

namespace demo {

class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Isolate* isolate);
  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);

 private:
  explicit MyObject(double value = 0);
  ~MyObject();

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
  static v8::Global<v8::Function> constructor;
  double value_;
};

}  // namespace demo

#endif 

The implementation in myobject.cc is similar to the previous example:

// myobject.cc
#include <node.h>
#include "myobject.h"

namespace demo {

using node::AddEnvironmentCleanupHook;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Global;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

// Warning! This is not thread-safe, this addon cannot be used for worker
// threads.
Global<Function> MyObject::constructor;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(Isolate* isolate) {
  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);

  Local<Context> context = isolate->GetCurrentContext();
  constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());

  AddEnvironmentCleanupHook(isolate, [](void*) {
    constructor.Reset();
  }, nullptr);
}

void MyObject::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    double value = args[0]->IsUndefined() ?
        0 : args[0]->NumberValue(context).FromMaybe(0);
    MyObject* obj = new MyObject(value);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 1;
    Local<Value> argv[argc] = { args[0] };
    Local<Function> cons = Local<Function>::New(isolate, constructor);
    Local<Object> instance =
        cons->NewInstance(context, argc, argv).ToLocalChecked();
    args.GetReturnValue().Set(instance);
  }
}

void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  const unsigned argc = 1;
  Local<Value> argv[argc] = { args[0] };
  Local<Function> cons = Local<Function>::New(isolate, constructor);
  Local<Context> context = isolate->GetCurrentContext();
  Local<Object> instance =
      cons->NewInstance(context, argc, argv).ToLocalChecked();

  args.GetReturnValue().Set(instance);
}

void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
  obj->value_ += 1;

  args.GetReturnValue().Set(Number::New(isolate, obj->value_));
}

}  // namespace demo 

Once again, to build this example, the myobject.cc file must be added to the binding.gyp:

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [
        "addon.cc",
        "myobject.cc"
      ]
    }
  ]
} 

Test it with:

// test.js
const createObject = require('./build/Release/addon');

const obj = createObject(10);
console.log(obj.plusOne());
// Prints: 11
console.log(obj.plusOne());
// Prints: 12
console.log(obj.plusOne());
// Prints: 13

const obj2 = createObject(20);
console.log(obj2.plusOne());
// Prints: 21
console.log(obj2.plusOne());
// Prints: 22
console.log(obj2.plusOne());
// Prints: 23 

Passing wrapped objects around#

In addition to wrapping and returning C++ objects, it is possible to pass wrapped objects around by unwrapping them with the Node.js helper function node::ObjectWrap::Unwrap. The following examples shows a function add() that can take two MyObject objects as input arguments:

// addon.cc
#include <node.h>
#include <node_object_wrap.h>
#include "myobject.h"

namespace demo {

using v8::Context;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

void CreateObject(const FunctionCallbackInfo<Value>& args) {
  MyObject::NewInstance(args);
}

void Add(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(
      args[0]->ToObject(context).ToLocalChecked());
  MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
      args[1]->ToObject(context).ToLocalChecked());

  double sum = obj1->value() + obj2->value();
  args.GetReturnValue().Set(Number::New(isolate, sum));
}

void InitAll(Local<Object> exports) {
  MyObject::Init(exports->GetIsolate());

  NODE_SET_METHOD(exports, "createObject", CreateObject);
  NODE_SET_METHOD(exports, "add", Add);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)

}  // namespace demo 

In myobject.h, a new public method is added to allow access to private values after unwrapping the object.

// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <node.h>
#include <node_object_wrap.h>

namespace demo {

class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Isolate* isolate);
  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
  inline double value() const { return value_; }

 private:
  explicit MyObject(double value = 0);
  ~MyObject();

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static v8::Global<v8::Function> constructor;
  double value_;
};

}  // namespace demo

#endif 

The implementation of myobject.cc remains similar to the previous version:

// myobject.cc
#include <node.h>
#include "myobject.h"

namespace demo {

using node::AddEnvironmentCleanupHook;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Global;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

// Warning! This is not thread-safe, this addon cannot be used for worker
// threads.
Global<Function> MyObject::constructor;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(Isolate* isolate) {
  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  Local<Context> context = isolate->GetCurrentContext();
  constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());

  AddEnvironmentCleanupHook(isolate, [](void*) {
    constructor.Reset();
  }, nullptr);
}

void MyObject::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    double value = args[0]->IsUndefined() ?
        0 : args[0]->NumberValue(context).FromMaybe(0);
    MyObject* obj = new MyObject(value);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 1;
    Local<Value> argv[argc] = { args[0] };
    Local<Function> cons = Local<Function>::New(isolate, constructor);
    Local<Object> instance =
        cons->NewInstance(context, argc, argv).ToLocalChecked();
    args.GetReturnValue().Set(instance);
  }
}

void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  const unsigned argc = 1;
  Local<Value> argv[argc] = { args[0] };
  Local<Function> cons = Local<Function>::New(isolate, constructor);
  Local<Context> context = isolate->GetCurrentContext();
  Local<Object> instance =
      cons->NewInstance(context, argc, argv).ToLocalChecked();

  args.GetReturnValue().Set(instance);
}

}  // namespace demo 

Test it with:

// test.js
const addon = require('./build/Release/addon');

const obj1 = addon.createObject(10);
const obj2 = addon.createObject(20);
const result = addon.add(obj1, obj2);

console.log(result);
// Prints: 30 

Node-API#

Stability: 2 - Stable

Node-API (formerly N-API) is an API for building native Addons. It is independent from the underlying JavaScript runtime (for example, V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js. It is intended to insulate addons from changes in the underlying JavaScript engine and allow modules compiled for one major version to run on later major versions of Node.js without recompilation. The ABI Stability guide provides a more in-depth explanation.

Addons are built/packaged with the same approach/tools outlined in the section titled C++ Addons. The only difference is the set of APIs that are used by the native code. Instead of using the V8 or Native Abstractions for Node.js APIs, the functions available in Node-API are used.

APIs exposed by Node-API are generally used to create and manipulate JavaScript values. Concepts and operations generally map to ideas specified in the ECMA-262 Language Specification. The APIs have the following properties:

  • All Node-API calls return a status code of type napi_status. This status indicates whether the API call succeeded or failed.
  • The API's return value is passed via an out parameter.
  • All JavaScript values are abstracted behind an opaque type named napi_value.
  • In case of an error status code, additional information can be obtained using napi_get_last_error_info. More information can be found in the error handling section Error handling.

Node-API is a C API that ensures ABI stability across Node.js versions and different compiler levels. A C++ API can be easier to use. To support using C++, the project maintains a C++ wrapper module called node-addon-api. This wrapper provides an inlinable C++ API. Binaries built with node-addon-api will depend on the symbols for the Node-API C-based functions exported by Node.js. node-addon-api is a more efficient way to write code that calls Node-API. Take, for example, the following node-addon-api code. The first section shows the node-addon-api code and the second section shows what actually gets used in the addon.

Object obj = Object::New(env);
obj["foo"] = String::New(env, "bar"); 
napi_status status;
napi_value object, string;
status = napi_create_object(env, &object);
if (status != napi_ok) {
  napi_throw_error(env, ...);
  return;
}

status = napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, &string);
if (status != napi_ok) {
  napi_throw_error(env, ...);
  return;
}

status = napi_set_named_property(env, object, "foo", string);
if (status != napi_ok) {
  napi_throw_error(env, ...);
  return;
} 

The end result is that the addon only uses the exported C APIs. As a result, it still gets the benefits of the ABI stability provided by the C API.

When using node-addon-api instead of the C APIs, start with the API docs for node-addon-api.

The Node-API Resource offers an excellent orientation and tips for developers just getting started with Node-API and node-addon-api. Additional media resources can be found on the Node-API Media page.

Implications of ABI stability#

Although Node-API provides an ABI stability guarantee, other parts of Node.js do not, and any external libraries used from the addon may not. In particular, none of the following APIs provide an ABI stability guarantee across major versions:

  • the Node.js C++ APIs available via any of

    #include <node.h>
    #include <node_buffer.h>
    #include <node_version.h>
    #include <node_object_wrap.h> 
  • the libuv APIs which are also included with Node.js and available via

    #include <uv.h> 
  • the V8 API available via

    #include <v8.h> 

Thus, for an addon to remain ABI-compatible across Node.js major versions, it must use Node-API exclusively by restricting itself to using

#include <node_api.h> 

and by checking, for all external libraries that it uses, that the external library makes ABI stability guarantees similar to Node-API.

Building#

Unlike modules written in JavaScript, developing and deploying Node.js native addons using Node-API requires an additional set of tools. Besides the basic tools required to develop for Node.js, the native addon developer requires a toolchain that can compile C and C++ code into a binary. In addition, depending upon how the native addon is deployed, the user of the native addon will also need to have a C/C++ toolchain installed.

For Linux developers, the necessary C/C++ toolchain packages are readily available. GCC is widely used in the Node.js community to build and test across a variety of platforms. For many developers, the LLVM compiler infrastructure is also a good choice.

For Mac developers, Xcode offers all the required compiler tools. However, it is not necessary to install the entire Xcode IDE. The following command installs the necessary toolchain:

xcode-select --install 

For Windows developers, Visual Studio offers all the required compiler tools. However, it is not necessary to install the entire Visual Studio IDE. The following command installs the necessary toolchain:

npm install --global windows-build-tools 

The sections below describe the additional tools available for developing and deploying Node.js native addons.

Build tools#

Both the tools listed here require that users of the native addon have a C/C++ toolchain installed in order to successfully install the native addon.

node-gyp#

node-gyp is a build system based on the gyp-next fork of Google's GYP tool and comes bundled with npm. GYP, and therefore node-gyp, requires that Python be installed.

Historically, node-gyp has been the tool of choice for building native addons. It has widespread adoption and documentation. However, some developers have run into limitations in node-gyp.

CMake.js#

CMake.js is an alternative build system based on CMake.

CMake.js is a good choice for projects that already use CMake or for developers affected by limitations in node-gyp. build_with_cmake is an example of a CMake-based native addon project.

Uploading precompiled binaries#

The three tools listed here permit native addon developers and maintainers to create and upload binaries to public or private servers. These tools are typically integrated with CI/CD build systems like Travis CI and AppVeyor to build and upload binaries for a variety of platforms and architectures. These binaries are then available for download by users who do not need to have a C/C++ toolchain installed.

node-pre-gyp#

node-pre-gyp is a tool based on node-gyp that adds the ability to upload binaries to a server of the developer's choice. node-pre-gyp has particularly good support for uploading binaries to Amazon S3.

prebuild#

prebuild is a tool that supports builds using either node-gyp or CMake.js. Unlike node-pre-gyp which supports a variety of servers, prebuild uploads binaries only to GitHub releases. prebuild is a good choice for GitHub projects using CMake.js.

prebuildify#

prebuildify is a tool based on node-gyp. The advantage of prebuildify is that the built binaries are bundled with the native addon when it's uploaded to npm. The binaries are downloaded from npm and are immediately available to the module user when the native addon is installed.

Usage#

In order to use the Node-API functions, include the file node_api.h which is located in the src directory in the node development tree:

#include <node_api.h> 

This will opt into the default NAPI_VERSION for the given release of Node.js. In order to ensure compatibility with specific versions of Node-API, the version can be specified explicitly when including the header:

#define NAPI_VERSION 3
#include <node_api.h> 

This restricts the Node-API surface to just the functionality that was available in the specified (and earlier) versions.

Some of the Node-API surface is experimental and requires explicit opt-in:

#define NAPI_EXPERIMENTAL
#include <node_api.h> 

In this case the entire API surface, including any experimental APIs, will be available to the module code.

Occasionally, experimental features are introduced that affect already-released and stable APIs. These features can be disabled by an opt-out:

#define NAPI_EXPERIMENTAL
#define NODE_API_EXPERIMENTAL_<FEATURE_NAME>_OPT_OUT
#include <node_api.h> 

where <FEATURE_NAME> is the name of an experimental feature that affects both experimental and stable APIs.

Node-API version matrix#

Up until version 9, Node-API versions were additive and versioned independently from Node.js. This meant that any version was an extension to the previous version in that it had all of the APIs from the previous version with some additions. Each Node.js version only supported a single Node-API version. For example v18.15.0 supports only Node-API version 8. ABI stability was achieved because 8 was a strict superset of all previous versions.

As of version 9, while Node-API versions continue to be versioned independently an add-on that ran with Node-API version 9 may need code updates to run with Node-API version 10. ABI stability is maintained, however, because Node.js versions that support Node-API versions higher than 8 will support all versions between 8 and the highest version they support and will default to providing the version 8 APIs unless an add-on opts into a higher Node-API version. This approach provides the flexibility of better optimizing existing Node-API functions while maintaining ABI stability. Existing add-ons can continue to run without recompilation using an earlier version of Node-API. If an add-on needs functionality from a newer Node-API version, changes to existing code and recompilation will be needed to use those new functions anyway.

In versions of Node.js that support Node-API version 9 and later, defining NAPI_VERSION=X and using the existing add-on initialization macros will bake in the requested Node-API version that will be used at runtime into the add-on. If NAPI_VERSION is not set it will default to 8.

This table may not be up to date in older streams, the most up to date information is in the latest API documentation in: Node-API version matrix

Node-API version Supported In
10 v22.14.0+, 23.6.0+ and all later versions
9 v18.17.0+, 20.3.0+, 21.0.0 and all later versions
8 v12.22.0+, v14.17.0+, v15.12.0+, 16.0.0 and all later versions
7 v10.23.0+, v12.19.0+, v14.12.0+, 15.0.0 and all later versions
6 v10.20.0+, v12.17.0+, 14.0.0 and all later versions
5 v10.17.0+, v12.11.0+, 13.0.0 and all later versions
4 v10.16.0+, v11.8.0+, 12.0.0 and all later versions
3 v6.14.2*, 8.11.2+, v9.11.0+*, 10.0.0 and all later versions
2 v8.10.0+*, v9.3.0+*, 10.0.0 and all later versions
1 v8.6.0+**, v9.0.0+*, 10.0.0 and all later versions

* Node-API was experimental.

** Node.js 8.0.0 included Node-API as experimental. It was released as Node-API version 1 but continued to evolve until Node.js 8.6.0. The API is different in versions prior to Node.js 8.6.0. We recommend Node-API version 3 or later.

Each API documented for Node-API will have a header named added in:, and APIs which are stable will have the additional header Node-API version:. APIs are directly usable when using a Node.js version which supports the Node-API version shown in Node-API version: or higher. When using a Node.js version that does not support the Node-API version: listed or if there is no Node-API version: listed, then the API will only be available if #define NAPI_EXPERIMENTAL precedes the inclusion of node_api.h or js_native_api.h. If an API appears not to be available on a version of Node.js which is later than the one shown in added in: then this is most likely the reason for the apparent absence.

The Node-APIs associated strictly with accessing ECMAScript features from native code can be found separately in js_native_api.h and js_native_api_types.h. The APIs defined in these headers are included in node_api.h and node_api_types.h. The headers are structured in this way in order to allow implementations of Node-API outside of Node.js. For those implementations the Node.js specific APIs may not be applicable.

The Node.js-specific parts of an addon can be separated from the code that exposes the actual functionality to the JavaScript environment so that the latter may be used with multiple implementations of Node-API. In the example below, addon.c and addon.h refer only to js_native_api.h. This ensures that addon.c can be reused to compile against either the Node.js implementation of Node-API or any implementation of Node-API outside of Node.js.

addon_node.c is a separate file that contains the Node.js specific entry point to the addon and which instantiates the addon by calling into addon.c when the addon is loaded into a Node.js environment.

// addon.h
#ifndef _ADDON_H_
#define _ADDON_H_
#include <js_native_api.h>
napi_value create_addon(napi_env env);
#endif  // _ADDON_H_ 
// addon.c
#include "addon.h"

#define NODE_API_CALL(env, call)                                  \
  do {                                                            \
    napi_status status = (call);                                  \
    if (status != napi_ok) {                                      \
      const napi_extended_error_info* error_info = NULL;          \
      napi_get_last_error_info((env), &error_info);               \
      const char* err_message = error_info->error_message;        \
      bool is_pending;                                            \
      napi_is_exception_pending((env), &is_pending);              \
      /* If an exception is already pending, don't rethrow it */  \
      if (!is_pending) {                                          \
        const char* message = (err_message == NULL)               \
            ? "empty error message"                               \
            : err_message;                                        \
        napi_throw_error((env), NULL, message);                   \
      }                                                           \
      return NULL;                                                \
    }                                                             \
  } while(0)

static napi_value
DoSomethingUseful(napi_env env, napi_callback_info info) {
  // Do something useful.
  return NULL;
}

napi_value create_addon(napi_env env) {
  napi_value result;
  NODE_API_CALL(env, napi_create_object(env, &result));

  napi_value exported_function;
  NODE_API_CALL(env, napi_create_function(env,
                                          "doSomethingUseful",
                                          NAPI_AUTO_LENGTH,
                                          DoSomethingUseful,
                                          NULL,
                                          &exported_function));

  NODE_API_CALL(env, napi_set_named_property(env,
                                             result,
                                             "doSomethingUseful",
                                             exported_function));

  return result;
} 
// addon_node.c
#include <node_api.h>
#include "addon.h"

NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
  // This function body is expected to return a `napi_value`.
  // The variables `napi_env env` and `napi_value exports` may be used within
  // the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
  return create_addon(env);
} 

Environment life cycle APIs#

Section 8.7 of the ECMAScript Language Specification defines the concept of an "Agent" as a self-contained environment in which JavaScript code runs. Multiple such Agents may be started and terminated either concurrently or in sequence by the process.

A Node.js environment corresponds to an ECMAScript Agent. In the main process, an environment is created at startup, and additional environments can be created on separate threads to serve as worker threads. When Node.js is embedded in another application, the main thread of the application may also construct and destroy a Node.js environment multiple times during the life cycle of the application process such that each Node.js environment created by the application may, in turn, during its life cycle create and destroy additional environments as worker threads.

From the perspective of a native addon this means that the bindings it provides may be called multiple times, from multiple contexts, and even concurrently from multiple threads.

Native addons may need to allocate global state which they use during their life cycle of an Node.js environment such that the state can be unique to each instance of the addon.

To this end, Node-API provides a way to associate data such that its life cycle is tied to the life cycle of a Node.js environment.

napi_set_instance_data#

napi_status napi_set_instance_data(node_api_basic_env env,
                                   void* data,
                                   napi_finalize finalize_cb,
                                   void* finalize_hint); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] data: The data item to make available to bindings of this instance.
  • [in] finalize_cb: The function to call when the environment is being torn down. The function receives data so that it might free it. napi_finalize provides more details.
  • [in] finalize_hint: Optional hint to pass to the finalize callback during collection.

Returns napi_ok if the API succeeded.

This API associates data with the currently running Node.js environment. data can later be retrieved using napi_get_instance_data(). Any existing data associated with the currently running Node.js environment which was set by means of a previous call to napi_set_instance_data() will be overwritten. If a finalize_cb was provided by the previous call, it will not be called.

napi_get_instance_data#

napi_status napi_get_instance_data(node_api_basic_env env,
                                   void** data); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [out] data: The data item that was previously associated with the currently running Node.js environment by a call to napi_set_instance_data().

Returns napi_ok if the API succeeded.

This API retrieves data that was previously associated with the currently running Node.js environment via napi_set_instance_data(). If no data is set, the call will succeed and data will be set to NULL.

Basic Node-API data types#

Node-API exposes the following fundamental data types as abstractions that are consumed by the various APIs. These APIs should be treated as opaque, introspectable only with other Node-API calls.

napi_status#

Integral status code indicating the success or failure of a Node-API call. Currently, the following status codes are supported.

typedef enum {
  napi_ok,
  napi_invalid_arg,
  napi_object_expected,
  napi_string_expected,
  napi_name_expected,
  napi_function_expected,
  napi_number_expected,
  napi_boolean_expected,
  napi_array_expected,
  napi_generic_failure,
  napi_pending_exception,
  napi_cancelled,
  napi_escape_called_twice,
  napi_handle_scope_mismatch,
  napi_callback_scope_mismatch,
  napi_queue_full,
  napi_closing,
  napi_bigint_expected,
  napi_date_expected,
  napi_arraybuffer_expected,
  napi_detachable_arraybuffer_expected,
  napi_would_deadlock,  /* unused */
  napi_no_external_buffers_allowed,
  napi_cannot_run_js
} napi_status; 

If additional information is required upon an API returning a failed status, it can be obtained by calling napi_get_last_error_info.

napi_extended_error_info#

typedef struct {
  const char* error_message;
  void* engine_reserved;
  uint32_t engine_error_code;
  napi_status error_code;
} napi_extended_error_info; 
  • error_message: UTF8-encoded string containing a VM-neutral description of the error.
  • engine_reserved: Reserved for VM-specific error details. This is currently not implemented for any VM.
  • engine_error_code: VM-specific error code. This is currently not implemented for any VM.
  • error_code: The Node-API status code that originated with the last error.

See the Error handling section for additional information.

napi_env#

napi_env is used to represent a context that the underlying Node-API implementation can use to persist VM-specific state. This structure is passed to native functions when they're invoked, and it must be passed back when making Node-API calls. Specifically, the same napi_env that was passed in when the initial native function was called must be passed to any subsequent nested Node-API calls. Caching the napi_env for the purpose of general reuse, and passing the napi_env between instances of the same addon running on different Worker threads is not allowed. The napi_env becomes invalid when an instance of a native addon is unloaded. Notification of this event is delivered through the callbacks given to napi_add_env_cleanup_hook and napi_set_instance_data.

node_api_basic_env#

Stability: 1 - Experimental

This variant of napi_env is passed to synchronous finalizers (node_api_basic_finalize). There is a subset of Node-APIs which accept a parameter of type node_api_basic_env as their first argument. These APIs do not access the state of the JavaScript engine and are thus safe to call from synchronous finalizers. Passing a parameter of type napi_env to these APIs is allowed, however, passing a parameter of type node_api_basic_env to APIs that access the JavaScript engine state is not allowed. Attempting to do so without a cast will produce a compiler warning or an error when add-ons are compiled with flags which cause them to emit warnings and/or errors when incorrect pointer types are passed into a function. Calling such APIs from a synchronous finalizer will ultimately result in the termination of the application.

napi_value#

This is an opaque pointer that is used to represent a JavaScript value.

napi_threadsafe_function#

This is an opaque pointer that represents a JavaScript function which can be called asynchronously from multiple threads via napi_call_threadsafe_function().

napi_threadsafe_function_release_mode#

A value to be given to napi_release_threadsafe_function() to indicate whether the thread-safe function is to be closed immediately (napi_tsfn_abort) or merely released (napi_tsfn_release) and thus available for subsequent use via napi_acquire_threadsafe_function() and napi_call_threadsafe_function().

typedef enum {
  napi_tsfn_release,
  napi_tsfn_abort
} napi_threadsafe_function_release_mode; 

napi_threadsafe_function_call_mode#

A value to be given to napi_call_threadsafe_function() to indicate whether the call should block whenever the queue associated with the thread-safe function is full.

typedef enum {
  napi_tsfn_nonblocking,
  napi_tsfn_blocking
} napi_threadsafe_function_call_mode; 

Node-API memory management types#

napi_handle_scope#

This is an abstraction used to control and modify the lifetime of objects created within a particular scope. In general, Node-API values are created within the context of a handle scope. When a native method is called from JavaScript, a default handle scope will exist. If the user does not explicitly create a new handle scope, Node-API values will be created in the default handle scope. For any invocations of code outside the execution of a native method (for instance, during a libuv callback invocation), the module is required to create a scope before invoking any functions that can result in the creation of JavaScript values.

Handle scopes are created using napi_open_handle_scope and are destroyed using napi_close_handle_scope. Closing the scope can indicate to the GC that all napi_values created during the lifetime of the handle scope are no longer referenced from the current stack frame.

For more details, review the Object lifetime management.

napi_escapable_handle_scope#

Escapable handle scopes are a special type of handle scope to return values created within a particular handle scope to a parent scope.

napi_ref#

This is the abstraction to use to reference a napi_value. This allows for users to manage the lifetimes of JavaScript values, including defining their minimum lifetimes explicitly.

For more details, review the Object lifetime management.

napi_type_tag#

A 128-bit value stored as two unsigned 64-bit integers. It serves as a UUID with which JavaScript objects or externals can be "tagged" in order to ensure that they are of a certain type. This is a stronger check than napi_instanceof, because the latter can report a false positive if the object's prototype has been manipulated. Type-tagging is most useful in conjunction with napi_wrap because it ensures that the pointer retrieved from a wrapped object can be safely cast to the native type corresponding to the type tag that had been previously applied to the JavaScript object.

typedef struct {
  uint64_t lower;
  uint64_t upper;
} napi_type_tag; 
napi_async_cleanup_hook_handle#

An opaque value returned by napi_add_async_cleanup_hook. It must be passed to napi_remove_async_cleanup_hook when the chain of asynchronous cleanup events completes.

Node-API callback types#

napi_callback_info#

Opaque datatype that is passed to a callback function. It can be used for getting additional information about the context in which the callback was invoked.

napi_callback#

Function pointer type for user-provided native functions which are to be exposed to JavaScript via Node-API. Callback functions should satisfy the following signature:

typedef napi_value (*napi_callback)(napi_env, napi_callback_info); 

Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside a napi_callback is not necessary.

node_api_basic_finalize#

Stability: 1 - Experimental

Function pointer type for add-on provided functions that allow the user to be notified when externally-owned data is ready to be cleaned up because the object it was associated with has been garbage-collected. The user must provide a function satisfying the following signature which would get called upon the object's collection. Currently, node_api_basic_finalize can be used for finding out when objects that have external data are collected.

typedef void (*node_api_basic_finalize)(node_api_basic_env env,
                                      void* finalize_data,
                                      void* finalize_hint); 

Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside the function body is not necessary.

Since these functions may be called while the JavaScript engine is in a state where it cannot execute JavaScript code, only Node-APIs which accept a node_api_basic_env as their first parameter may be called. node_api_post_finalizer can be used to schedule Node-API calls that require access to the JavaScript engine's state to run after the current garbage collection cycle has completed.

In the case of node_api_create_external_string_latin1 and node_api_create_external_string_utf16 the env parameter may be null, because external strings can be collected during the latter part of environment shutdown.

Change History:

  • experimental (NAPI_EXPERIMENTAL):

    Only Node-API calls that accept a node_api_basic_env as their first parameter may be called, otherwise the application will be terminated with an appropriate error message. This feature can be turned off by defining NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT.

napi_finalize#

Function pointer type for add-on provided function that allow the user to schedule a group of calls to Node-APIs in response to a garbage collection event, after the garbage collection cycle has completed. These function pointers can be used with node_api_post_finalizer.

typedef void (*napi_finalize)(napi_env env,
                              void* finalize_data,
                              void* finalize_hint); 

Change History:

  • experimental (NAPI_EXPERIMENTAL is defined):

    A function of this type may no longer be used as a finalizer, except with node_api_post_finalizer. node_api_basic_finalize must be used instead. This feature can be turned off by defining NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT.

napi_async_execute_callback#

Function pointer used with functions that support asynchronous operations. Callback functions must satisfy the following signature:

typedef void (*napi_async_execute_callback)(napi_env env, void* data); 

Implementations of this function must avoid making Node-API calls that execute JavaScript or interact with JavaScript objects. Node-API calls should be in the napi_async_complete_callback instead. Do not use the napi_env parameter as it will likely result in execution of JavaScript.

napi_async_complete_callback#

Function pointer used with functions that support asynchronous operations. Callback functions must satisfy the following signature:

typedef void (*napi_async_complete_callback)(napi_env env,
                                             napi_status status,
                                             void* data); 

Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside the function body is not necessary.

napi_threadsafe_function_call_js#

Function pointer used with asynchronous thread-safe function calls. The callback will be called on the main thread. Its purpose is to use a data item arriving via the queue from one of the secondary threads to construct the parameters necessary for a call into JavaScript, usually via napi_call_function, and then make the call into JavaScript.

The data arriving from the secondary thread via the queue is given in the data parameter and the JavaScript function to call is given in the js_callback parameter.

Node-API sets up the environment prior to calling this callback, so it is sufficient to call the JavaScript function via napi_call_function rather than via napi_make_callback.

Callback functions must satisfy the following signature:

typedef void (*napi_threadsafe_function_call_js)(napi_env env,
                                                 napi_value js_callback,
                                                 void* context,
                                                 void* data); 
  • [in] env: The environment to use for API calls, or NULL if the thread-safe function is being torn down and data may need to be freed.
  • [in] js_callback: The JavaScript function to call, or NULL if the thread-safe function is being torn down and data may need to be freed. It may also be NULL if the thread-safe function was created without js_callback.
  • [in] context: The optional data with which the thread-safe function was created.
  • [in] data: Data created by the secondary thread. It is the responsibility of the callback to convert this native data to JavaScript values (with Node-API functions) that can be passed as parameters when js_callback is invoked. This pointer is managed entirely by the threads and this callback. Thus this callback should free the data.

Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside the function body is not necessary.

napi_cleanup_hook#

Function pointer used with napi_add_env_cleanup_hook. It will be called when the environment is being torn down.

Callback functions must satisfy the following signature:

typedef void (*napi_cleanup_hook)(void* data); 
napi_async_cleanup_hook#

Function pointer used with napi_add_async_cleanup_hook. It will be called when the environment is being torn down.

Callback functions must satisfy the following signature:

typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
                                        void* data); 

The body of the function should initiate the asynchronous cleanup actions at the end of which handle must be passed in a call to napi_remove_async_cleanup_hook.

Error handling#

Node-API uses both return values and JavaScript exceptions for error handling. The following sections explain the approach for each case.

Return values#

All of the Node-API functions share the same error handling pattern. The return type of all API functions is napi_status.

The return value will be napi_ok if the request was successful and no uncaught JavaScript exception was thrown. If an error occurred AND an exception was thrown, the napi_status value for the error will be returned. If an exception was thrown, and no error occurred, napi_pending_exception will be returned.

In cases where a return value other than napi_ok or napi_pending_exception is returned, napi_is_exception_pending must be called to check if an exception is pending. See the section on exceptions for more details.

The full set of possible napi_status values is defined in napi_api_types.h.

The napi_status return value provides a VM-independent representation of the error which occurred. In some cases it is useful to be able to get more detailed information, including a string representing the error as well as VM (engine)-specific information.

In order to retrieve this information napi_get_last_error_info is provided which returns a napi_extended_error_info structure. The format of the napi_extended_error_info structure is as follows:

typedef struct napi_extended_error_info {
  const char* error_message;
  void* engine_reserved;
  uint32_t engine_error_code;
  napi_status error_code;
}; 
  • error_message: Textual representation of the error that occurred.
  • engine_reserved: Opaque handle reserved for engine use only.
  • engine_error_code: VM specific error code.
  • error_code: Node-API status code for the last error.

napi_get_last_error_info returns the information for the last Node-API call that was made.

Do not rely on the content or format of any of the extended information as it is not subject to SemVer and may change at any time. It is intended only for logging purposes.

napi_get_last_error_info#
napi_status
napi_get_last_error_info(node_api_basic_env env,
                         const napi_extended_error_info** result); 
  • [in] env: The environment that the API is invoked under.
  • [out] result: The napi_extended_error_info structure with more information about the error.

Returns napi_ok if the API succeeded.

This API retrieves a napi_extended_error_info structure with information about the last error that occurred.

The content of the napi_extended_error_info returned is only valid up until a Node-API function is called on the same env. This includes a call to napi_is_exception_pending so it may often be necessary to make a copy of the information so that it can be used later. The pointer returned in error_message points to a statically-defined string so it is safe to use that pointer if you have copied it out of the error_message field (which will be overwritten) before another Node-API function was called.

Do not rely on the content or format of any of the extended information as it is not subject to SemVer and may change at any time. It is intended only for logging purposes.

This API can be called even if there is a pending JavaScript exception.

Exceptions#

Any Node-API function call may result in a pending JavaScript exception. This is the case for any of the API functions, even those that may not cause the execution of JavaScript.

If the napi_status returned by a function is napi_ok then no exception is pending and no additional action is required. If the napi_status returned is anything other than napi_ok or napi_pending_exception, in order to try to recover and continue instead of simply returning immediately, napi_is_exception_pending must be called in order to determine if an exception is pending or not.

In many cases when a Node-API function is called and an exception is already pending, the function will return immediately with a napi_status of napi_pending_exception. However, this is not the case for all functions. Node-API allows a subset of the functions to be called to allow for some minimal cleanup before returning to JavaScript. In that case, napi_status will reflect the status for the function. It will not reflect previous pending exceptions. To avoid confusion, check the error status after every function call.

When an exception is pending one of two approaches can be employed.

The first approach is to do any appropriate cleanup and then return so that execution will return to JavaScript. As part of the transition back to JavaScript, the exception will be thrown at the point in the JavaScript code where the native method was invoked. The behavior of most Node-API calls is unspecified while an exception is pending, and many will simply return napi_pending_exception, so do as little as possible and then return to JavaScript where the exception can be handled.

The second approach is to try to handle the exception. There will be cases where the native code can catch the exception, take the appropriate action, and then continue. This is only recommended in specific cases where it is known that the exception can be safely handled. In these cases napi_get_and_clear_last_exception can be used to get and clear the exception. On success, result will contain the handle to the last JavaScript Object thrown. If it is determined, after retrieving the exception, the exception cannot be handled after all it can be re-thrown it with napi_throw where error is the JavaScript value to be thrown.

The following utility functions are also available in case native code needs to throw an exception or determine if a napi_value is an instance of a JavaScript Error object: napi_throw_error, napi_throw_type_error, napi_throw_range_error, node_api_throw_syntax_error and napi_is_error.

The following utility functions are also available in case native code needs to create an Error object: napi_create_error, napi_create_type_error, napi_create_range_error and node_api_create_syntax_error, where result is the napi_value that refers to the newly created JavaScript Error object.

The Node.js project is adding error codes to all of the errors generated internally. The goal is for applications to use these error codes for all error checking. The associated error messages will remain, but will only be meant to be used for logging and display with the expectation that the message can change without SemVer applying. In order to support this model with Node-API, both in internal functionality and for module specific functionality (as its good practice), the throw_ and create_ functions take an optional code parameter which is the string for the code to be added to the error object. If the optional parameter is NULL then no code will be associated with the error. If a code is provided, the name associated with the error is also updated to be:

originalName [code] 

where originalName is the original name associated with the error and code is the code that was provided. For example, if the code is 'ERR_ERROR_1' and a TypeError is being created the name will be:

TypeError [ERR_ERROR_1] 
napi_throw#
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error); 
  • [in] env: The environment that the API is invoked under.
  • [in] error: The JavaScript value to be thrown.

Returns napi_ok if the API succeeded.

This API throws the JavaScript value provided.

napi_throw_error#
NAPI_EXTERN napi_status napi_throw_error(napi_env env,
                                         const char* code,
                                         const char* msg); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional error code to be set on the error.
  • [in] msg: C string representing the text to be associated with the error.

Returns napi_ok if the API succeeded.

This API throws a JavaScript Error with the text provided.

napi_throw_type_error#
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
                                              const char* code,
                                              const char* msg); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional error code to be set on the error.
  • [in] msg: C string representing the text to be associated with the error.

Returns napi_ok if the API succeeded.

This API throws a JavaScript TypeError with the text provided.

napi_throw_range_error#
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
                                               const char* code,
                                               const char* msg); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional error code to be set on the error.
  • [in] msg: C string representing the text to be associated with the error.

Returns napi_ok if the API succeeded.

This API throws a JavaScript RangeError with the text provided.

node_api_throw_syntax_error#
NAPI_EXTERN napi_status node_api_throw_syntax_error(napi_env env,
                                                    const char* code,
                                                    const char* msg); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional error code to be set on the error.
  • [in] msg: C string representing the text to be associated with the error.

Returns napi_ok if the API succeeded.

This API throws a JavaScript SyntaxError with the text provided.

napi_is_error#
NAPI_EXTERN napi_status napi_is_error(napi_env env,
                                      napi_value value,
                                      bool* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The napi_value to be checked.
  • [out] result: Boolean value that is set to true if napi_value represents an error, false otherwise.

Returns napi_ok if the API succeeded.

This API queries a napi_value to check if it represents an error object.

napi_create_error#
NAPI_EXTERN napi_status napi_create_error(napi_env env,
                                          napi_value code,
                                          napi_value msg,
                                          napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional napi_value with the string for the error code to be associated with the error.
  • [in] msg: napi_value that references a JavaScript string to be used as the message for the Error.
  • [out] result: napi_value representing the error created.

Returns napi_ok if the API succeeded.

This API returns a JavaScript Error with the text provided.

napi_create_type_error#
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
                                               napi_value code,
                                               napi_value msg,
                                               napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional napi_value with the string for the error code to be associated with the error.
  • [in] msg: napi_value that references a JavaScript string to be used as the message for the Error.
  • [out] result: napi_value representing the error created.

Returns napi_ok if the API succeeded.

This API returns a JavaScript TypeError with the text provided.

napi_create_range_error#
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
                                                napi_value code,
                                                napi_value msg,
                                                napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional napi_value with the string for the error code to be associated with the error.
  • [in] msg: napi_value that references a JavaScript string to be used as the message for the Error.
  • [out] result: napi_value representing the error created.

Returns napi_ok if the API succeeded.

This API returns a JavaScript RangeError with the text provided.

node_api_create_syntax_error#
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
                                                     napi_value code,
                                                     napi_value msg,
                                                     napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] code: Optional napi_value with the string for the error code to be associated with the error.
  • [in] msg: napi_value that references a JavaScript string to be used as the message for the Error.
  • [out] result: napi_value representing the error created.

Returns napi_ok if the API succeeded.

This API returns a JavaScript SyntaxError with the text provided.

napi_get_and_clear_last_exception#
napi_status napi_get_and_clear_last_exception(napi_env env,
                                              napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [out] result: The exception if one is pending, NULL otherwise.

Returns napi_ok if the API succeeded.

This API can be called even if there is a pending JavaScript exception.

napi_is_exception_pending#
napi_status napi_is_exception_pending(napi_env env, bool* result); 
  • [in] env: The environment that the API is invoked under.
  • [out] result: Boolean value that is set to true if an exception is pending.

Returns napi_ok if the API succeeded.

This API can be called even if there is a pending JavaScript exception.

napi_fatal_exception#
napi_status napi_fatal_exception(napi_env env, napi_value err); 
  • [in] env: The environment that the API is invoked under.
  • [in] err: The error that is passed to 'uncaughtException'.

Trigger an 'uncaughtException' in JavaScript. Useful if an async callback throws an exception with no way to recover.

Fatal errors#

In the event of an unrecoverable error in a native addon, a fatal error can be thrown to immediately terminate the process.

napi_fatal_error#
NAPI_NO_RETURN void napi_fatal_error(const char* location,
                                     size_t location_len,
                                     const char* message,
                                     size_t message_len); 
  • [in] location: Optional location at which the error occurred.
  • [in] location_len: The length of the location in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [in] message: The message associated with the error.
  • [in] message_len: The length of the message in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.

The function call does not return, the process will be terminated.

This API can be called even if there is a pending JavaScript exception.

Object lifetime management#

As Node-API calls are made, handles to objects in the heap for the underlying VM may be returned as napi_values. These handles must hold the objects 'live' until they are no longer required by the native code, otherwise the objects could be collected before the native code was finished using them.

As object handles are returned they are associated with a 'scope'. The lifespan for the default scope is tied to the lifespan of the native method call. The result is that, by default, handles remain valid and the objects associated with these handles will be held live for the lifespan of the native method call.

In many cases, however, it is necessary that the handles remain valid for either a shorter or longer lifespan than that of the native method. The sections which follow describe the Node-API functions that can be used to change the handle lifespan from the default.

Making handle lifespan shorter than that of the native method#

It is often necessary to make the lifespan of handles shorter than the lifespan of a native method. For example, consider a native method that has a loop which iterates through the elements in a large array:

for (int i = 0; i < 1000000; i++) {
  napi_value result;
  napi_status status = napi_get_element(env, object, i, &result);
  if (status != napi_ok) {
    break;
  }
  // do something with element
} 

This would result in a large number of handles being created, consuming substantial resources. In addition, even though the native code could only use the most recent handle, all of the associated objects would also be kept alive since they all share the same scope.

To handle this case, Node-API provides the ability to establish a new 'scope' to which newly created handles will be associated. Once those handles are no longer required, the scope can be 'closed' and any handles associated with the scope are invalidated. The methods available to open/close scopes are napi_open_handle_scope and napi_close_handle_scope.

Node-API only supports a single nested hierarchy of scopes. There is only one active scope at any time, and all new handles will be associated with that scope while it is active. Scopes must be closed in the reverse order from which they are opened. In addition, all scopes created within a native method must be closed before returning from that method.

Taking the earlier example, adding calls to napi_open_handle_scope and napi_close_handle_scope would ensure that at most a single handle is valid throughout the execution of the loop:

for (int i = 0; i < 1000000; i++) {
  napi_handle_scope scope;
  napi_status status = napi_open_handle_scope(env, &scope);
  if (status != napi_ok) {
    break;
  }
  napi_value result;
  status = napi_get_element(env, object, i, &result);
  if (status != napi_ok) {
    break;
  }
  // do something with element
  status = napi_close_handle_scope(env, scope);
  if (status != napi_ok) {
    break;
  }
} 

When nesting scopes, there are cases where a handle from an inner scope needs to live beyond the lifespan of that scope. Node-API supports an 'escapable scope' in order to support this case. An escapable scope allows one handle to be 'promoted' so that it 'escapes' the current scope and the lifespan of the handle changes from the current scope to that of the outer scope.

The methods available to open/close escapable scopes are napi_open_escapable_handle_scope and napi_close_escapable_handle_scope.

The request to promote a handle is made through napi_escape_handle which can only be called once.

napi_open_handle_scope#
NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env,
                                               napi_handle_scope* result); 
  • [in] env: The environment that the API is invoked under.
  • [out] result: napi_value representing the new scope.

Returns napi_ok if the API succeeded.

This API opens a new scope.

napi_close_handle_scope#
NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env,
                                                napi_handle_scope scope); 
  • [in] env: The environment that the API is invoked under.
  • [in] scope: napi_value representing the scope to be closed.

Returns napi_ok if the API succeeded.

This API closes the scope passed in. Scopes must be closed in the reverse order from which they were created.

This API can be called even if there is a pending JavaScript exception.

napi_open_escapable_handle_scope#
NAPI_EXTERN napi_status
    napi_open_escapable_handle_scope(napi_env env,
                                     napi_handle_scope* result); 
  • [in] env: The environment that the API is invoked under.
  • [out] result: napi_value representing the new scope.

Returns napi_ok if the API succeeded.

This API opens a new scope from which one object can be promoted to the outer scope.

napi_close_escapable_handle_scope#
NAPI_EXTERN napi_status
    napi_close_escapable_handle_scope(napi_env env,
                                      napi_handle_scope scope); 
  • [in] env: The environment that the API is invoked under.
  • [in] scope: napi_value representing the scope to be closed.

Returns napi_ok if the API succeeded.

This API closes the scope passed in. Scopes must be closed in the reverse order from which they were created.

This API can be called even if there is a pending JavaScript exception.

napi_escape_handle#
napi_status napi_escape_handle(napi_env env,
                               napi_escapable_handle_scope scope,
                               napi_value escapee,
                               napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] scope: napi_value representing the current scope.
  • [in] escapee: napi_value representing the JavaScript Object to be escaped.
  • [out] result: napi_value representing the handle to the escaped Object in the outer scope.

Returns napi_ok if the API succeeded.

This API promotes the handle to the JavaScript object so that it is valid for the lifetime of the outer scope. It can only be called once per scope. If it is called more than once an error will be returned.

This API can be called even if there is a pending JavaScript exception.

References to values with a lifespan longer than that of the native method#

In some cases, an addon will need to be able to create and reference values with a lifespan longer than that of a single native method invocation. For example, to create a constructor and later use that constructor in a request to create instances, it must be possible to reference the constructor object across many different instance creation requests. This would not be possible with a normal handle returned as a napi_value as described in the earlier section. The lifespan of a normal handle is managed by scopes and all scopes must be closed before the end of a native method.

Node-API provides methods for creating persistent references to values. Currently Node-API only allows references to be created for a limited set of value types, including object, external, function, and symbol.

Each reference has an associated count with a value of 0 or higher, which determines whether the reference will keep the corresponding value alive. References with a count of 0 do not prevent values from being collected. Values of object (object, function, external) and symbol types are becoming 'weak' references and can still be accessed while they are not collected. Any count greater than 0 will prevent the values from being collected.

Symbol values have different flavors. The true weak reference behavior is only supported by local symbols created with the napi_create_symbol function or the JavaScript Symbol() constructor calls. Globally registered symbols created with the node_api_symbol_for function or JavaScript Symbol.for() function calls remain always strong references because the garbage collector does not collect them. The same is true for well-known symbols such as Symbol.iterator. They are also never collected by the garbage collector.

References can be created with an initial reference count. The count can then be modified through napi_reference_ref and napi_reference_unref. If an object is collected while the count for a reference is 0, all subsequent calls to get the object associated with the reference napi_get_reference_value will return NULL for the returned napi_value. An attempt to call napi_reference_ref for a reference whose object has been collected results in an error.

References must be deleted once they are no longer required by the addon. When a reference is deleted, it will no longer prevent the corresponding object from being collected. Failure to delete a persistent reference results in a 'memory leak' with both the native memory for the persistent reference and the corresponding object on the heap being retained forever.

There can be multiple persistent references created which refer to the same object, each of which will either keep the object live or not based on its individual count. Multiple persistent references to the same object can result in unexpectedly keeping alive native memory. The native structures for a persistent reference must be kept alive until finalizers for the referenced object are executed. If a new persistent reference is created for the same object, the finalizers for that object will not be run and the native memory pointed by the earlier persistent reference will not be freed. This can be avoided by calling napi_delete_reference in addition to napi_reference_unref when possible.

Change History:

  • Version 10 (NAPI_VERSION is defined as 10 or higher):

    References can be created for all value types. The new supported value types do not support weak reference semantic and the values of these types are released when the reference count becomes 0 and cannot be accessed from the reference anymore.

napi_create_reference#
NAPI_EXTERN napi_status napi_create_reference(napi_env env,
                                              napi_value value,
                                              uint32_t initial_refcount,
                                              napi_ref* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The napi_value for which a reference is being created.
  • [in] initial_refcount: Initial reference count for the new reference.
  • [out] result: napi_ref pointing to the new reference.

Returns napi_ok if the API succeeded.

This API creates a new reference with the specified reference count to the value passed in.

napi_delete_reference#
NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref); 
  • [in] env: The environment that the API is invoked under.
  • [in] ref: napi_ref to be deleted.

Returns napi_ok if the API succeeded.

This API deletes the reference passed in.

This API can be called even if there is a pending JavaScript exception.

napi_reference_ref#
NAPI_EXTERN napi_status napi_reference_ref(napi_env env,
                                           napi_ref ref,
                                           uint32_t* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] ref: napi_ref for which the reference count will be incremented.
  • [out] result: The new reference count.

Returns napi_ok if the API succeeded.

This API increments the reference count for the reference passed in and returns the resulting reference count.

napi_reference_unref#
NAPI_EXTERN napi_status napi_reference_unref(napi_env env,
                                             napi_ref ref,
                                             uint32_t* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] ref: napi_ref for which the reference count will be decremented.
  • [out] result: The new reference count.

Returns napi_ok if the API succeeded.

This API decrements the reference count for the reference passed in and returns the resulting reference count.

napi_get_reference_value#
NAPI_EXTERN napi_status napi_get_reference_value(napi_env env,
                                                 napi_ref ref,
                                                 napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] ref: The napi_ref for which the corresponding value is being requested.
  • [out] result: The napi_value referenced by the napi_ref.

Returns napi_ok if the API succeeded.

If still valid, this API returns the napi_value representing the JavaScript value associated with the napi_ref. Otherwise, result will be NULL.

Cleanup on exit of the current Node.js environment#

While a Node.js process typically releases all its resources when exiting, embedders of Node.js, or future Worker support, may require addons to register clean-up hooks that will be run once the current Node.js environment exits.

Node-API provides functions for registering and un-registering such callbacks. When those callbacks are run, all resources that are being held by the addon should be freed up.

napi_add_env_cleanup_hook#
NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_basic_env env,
                                                  napi_cleanup_hook fun,
                                                  void* arg); 

Registers fun as a function to be run with the arg parameter once the current Node.js environment exits.

A function can safely be specified multiple times with different arg values. In that case, it will be called multiple times as well. Providing the same fun and arg values multiple times is not allowed and will lead the process to abort.

The hooks will be called in reverse order, i.e. the most recently added one will be called first.

Removing this hook can be done by using napi_remove_env_cleanup_hook. Typically, that happens when the resource for which this hook was added is being torn down anyway.

For asynchronous cleanup, napi_add_async_cleanup_hook is available.

napi_remove_env_cleanup_hook#
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_basic_env env,
                                                     void (*fun)(void* arg),
                                                     void* arg); 

Unregisters fun as a function to be run with the arg parameter once the current Node.js environment exits. Both the argument and the function value need to be exact matches.

The function must have originally been registered with napi_add_env_cleanup_hook, otherwise the process will abort.

napi_add_async_cleanup_hook#
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
    node_api_basic_env env,
    napi_async_cleanup_hook hook,
    void* arg,
    napi_async_cleanup_hook_handle* remove_handle); 
  • [in] env: The environment that the API is invoked under.
  • [in] hook: The function pointer to call at environment teardown.
  • [in] arg: The pointer to pass to hook when it gets called.
  • [out] remove_handle: Optional handle that refers to the asynchronous cleanup hook.

Registers hook, which is a function of type napi_async_cleanup_hook, as a function to be run with the remove_handle and arg parameters once the current Node.js environment exits.

Unlike napi_add_env_cleanup_hook, the hook is allowed to be asynchronous.

Otherwise, behavior generally matches that of napi_add_env_cleanup_hook.

If remove_handle is not NULL, an opaque value will be stored in it that must later be passed to napi_remove_async_cleanup_hook, regardless of whether the hook has already been invoked. Typically, that happens when the resource for which this hook was added is being torn down anyway.

napi_remove_async_cleanup_hook#
NAPI_EXTERN napi_status napi_remove_async_cleanup_hook(
    napi_async_cleanup_hook_handle remove_handle); 

Unregisters the cleanup hook corresponding to remove_handle. This will prevent the hook from being executed, unless it has already started executing. This must be called on any napi_async_cleanup_hook_handle value obtained from napi_add_async_cleanup_hook.

Finalization on the exit of the Node.js environment#

The Node.js environment may be torn down at an arbitrary time as soon as possible with JavaScript execution disallowed, like on the request of worker.terminate(). When the environment is being torn down, the registered napi_finalize callbacks of JavaScript objects, thread-safe functions and environment instance data are invoked immediately and independently.

The invocation of napi_finalize callbacks is scheduled after the manually registered cleanup hooks. In order to ensure a proper order of addon finalization during environment shutdown to avoid use-after-free in the napi_finalize callback, addons should register a cleanup hook with napi_add_env_cleanup_hook and napi_add_async_cleanup_hook to manually release the allocated resource in a proper order.

Module registration#

Node-API modules are registered in a manner similar to other modules except that instead of using the NODE_MODULE macro the following is used:

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 

The next difference is the signature for the Init method. For a Node-API module it is as follows:

napi_value Init(napi_env env, napi_value exports); 

The return value from Init is treated as the exports object for the module. The Init method is passed an empty object via the exports parameter as a convenience. If Init returns NULL, the parameter passed as exports is exported by the module. Node-API modules cannot modify the module object but can specify anything as the exports property of the module.

To add the method hello as a function so that it can be called as a method provided by the addon:

napi_value Init(napi_env env, napi_value exports) {
  napi_status status;
  napi_property_descriptor desc = {
    "hello",
    NULL,
    Method,
    NULL,
    NULL,
    NULL,
    napi_writable | napi_enumerable | napi_configurable,
    NULL
  };
  status = napi_define_properties(env, exports, 1, &desc);
  if (status != napi_ok) return NULL;
  return exports;
} 

To set a function to be returned by the require() for the addon:

napi_value Init(napi_env env, napi_value exports) {
  napi_value method;
  napi_status status;
  status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method);
  if (status != napi_ok) return NULL;
  return method;
} 

To define a class so that new instances can be created (often used with Object wrap):

// NOTE: partial example, not all referenced code is included
napi_value Init(napi_env env, napi_value exports) {
  napi_status status;
  napi_property_descriptor properties[] = {
    { "value", NULL, NULL, GetValue, SetValue, NULL, napi_writable | napi_configurable, NULL },
    DECLARE_NAPI_METHOD("plusOne", PlusOne),
    DECLARE_NAPI_METHOD("multiply", Multiply),
  };

  napi_value cons;
  status =
      napi_define_class(env, "MyObject", New, NULL, 3, properties, &cons);
  if (status != napi_ok) return NULL;

  status = napi_create_reference(env, cons, 1, &constructor);
  if (status != napi_ok) return NULL;

  status = napi_set_named_property(env, exports, "MyObject", cons);
  if (status != napi_ok) return NULL;

  return exports;
} 

You can also use the NAPI_MODULE_INIT macro, which acts as a shorthand for NAPI_MODULE and defining an Init function:

NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
  napi_value answer;
  napi_status result;

  status = napi_create_int64(env, 42, &answer);
  if (status != napi_ok) return NULL;

  status = napi_set_named_property(env, exports, "answer", answer);
  if (status != napi_ok) return NULL;

  return exports;
} 

The parameters env and exports are provided to the body of the NAPI_MODULE_INIT macro.

All Node-API addons are context-aware, meaning they may be loaded multiple times. There are a few design considerations when declaring such a module. The documentation on context-aware addons provides more details.

The variables env and exports will be available inside the function body following the macro invocation.

For more details on setting properties on objects, see the section on Working with JavaScript properties.

For more details on building addon modules in general, refer to the existing API.

Working with JavaScript values#

Node-API exposes a set of APIs to create all types of JavaScript values. Some of these types are documented under Section 6 of the ECMAScript Language Specification.

Fundamentally, these APIs are used to do one of the following:

  1. Create a new JavaScript object
  2. Convert from a primitive C type to a Node-API value
  3. Convert from Node-API value to a primitive C type
  4. Get global instances including undefined and null

Node-API values are represented by the type napi_value. Any Node-API call that requires a JavaScript value takes in a napi_value. In some cases, the API does check the type of the napi_value up-front. However, for better performance, it's better for the caller to make sure that the napi_value in question is of the JavaScript type expected by the API.

Enum types#

napi_key_collection_mode#
typedef enum {
  napi_key_include_prototypes,
  napi_key_own_only
} napi_key_collection_mode; 

Describes the Keys/Properties filter enums:

napi_key_collection_mode limits the range of collected properties.

napi_key_own_only limits the collected properties to the given object only. napi_key_include_prototypes will include all keys of the objects's prototype chain as well.

napi_key_filter#
typedef enum {
  napi_key_all_properties = 0,
  napi_key_writable = 1,
  napi_key_enumerable = 1 << 1,
  napi_key_configurable = 1 << 2,
  napi_key_skip_strings = 1 << 3,
  napi_key_skip_symbols = 1 << 4
} napi_key_filter; 

Property filter bits. They can be or'ed to build a composite filter.

napi_key_conversion#
typedef enum {
  napi_key_keep_numbers,
  napi_key_numbers_to_strings
} napi_key_conversion; 

napi_key_numbers_to_strings will convert integer indexes to strings. napi_key_keep_numbers will return numbers for integer indexes.

napi_valuetype#
typedef enum {
  // ES6 types (corresponds to typeof)
  napi_undefined,
  napi_null,
  napi_boolean,
  napi_number,
  napi_string,
  napi_symbol,
  napi_object,
  napi_function,
  napi_external,
  napi_bigint,
} napi_valuetype; 

Describes the type of a napi_value. This generally corresponds to the types described in Section 6.1 of the ECMAScript Language Specification. In addition to types in that section, napi_valuetype can also represent Functions and Objects with external data.

A JavaScript value of type napi_external appears in JavaScript as a plain object such that no properties can be set on it, and no prototype.

napi_typedarray_type#
typedef enum {
  napi_int8_array,
  napi_uint8_array,
  napi_uint8_clamped_array,
  napi_int16_array,
  napi_uint16_array,
  napi_int32_array,
  napi_uint32_array,
  napi_float32_array,
  napi_float64_array,
  napi_bigint64_array,
  napi_biguint64_array,
} napi_typedarray_type; 

This represents the underlying binary scalar datatype of the TypedArray. Elements of this enum correspond to Section 22.2 of the ECMAScript Language Specification.

Object creation functions#

napi_create_array#
napi_status napi_create_array(napi_env env, napi_value* result) 
  • [in] env: The environment that the Node-API call is invoked under.
  • [out] result: A napi_value representing a JavaScript Array.

Returns napi_ok if the API succeeded.

This API returns a Node-API value corresponding to a JavaScript Array type. JavaScript arrays are described in Section 22.1 of the ECMAScript Language Specification.

napi_create_array_with_length#
napi_status napi_create_array_with_length(napi_env env,
                                          size_t length,
                                          napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] length: The initial length of the Array.
  • [out] result: A napi_value representing a JavaScript Array.

Returns napi_ok if the API succeeded.

This API returns a Node-API value corresponding to a JavaScript Array type. The Array's length property is set to the passed-in length parameter. However, the underlying buffer is not guaranteed to be pre-allocated by the VM when the array is created. That behavior is left to the underlying VM implementation. If the buffer must be a contiguous block of memory that can be directly read and/or written via C, consider using napi_create_external_arraybuffer.

JavaScript arrays are described in Section 22.1 of the ECMAScript Language Specification.

napi_create_arraybuffer#
napi_status napi_create_arraybuffer(napi_env env,
                                    size_t byte_length,
                                    void** data,
                                    napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] length: The length in bytes of the array buffer to create.
  • [out] data: Pointer to the underlying byte buffer of the ArrayBuffer. data can optionally be ignored by passing NULL.
  • [out] result: A napi_value representing a JavaScript ArrayBuffer.

Returns napi_ok if the API succeeded.

This API returns a Node-API value corresponding to a JavaScript ArrayBuffer. ArrayBuffers are used to represent fixed-length binary data buffers. They are normally used as a backing-buffer for TypedArray objects. The ArrayBuffer allocated will have an underlying byte buffer whose size is determined by the length parameter that's passed in. The underlying buffer is optionally returned back to the caller in case the caller wants to directly manipulate the buffer. This buffer can only be written to directly from native code. To write to this buffer from JavaScript, a typed array or DataView object would need to be created.

JavaScript ArrayBuffer objects are described in Section 24.1 of the ECMAScript Language Specification.

napi_create_buffer#
napi_status napi_create_buffer(napi_env env,
                               size_t size,
                               void** data,
                               napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] size: Size in bytes of the underlying buffer.
  • [out] data: Raw pointer to the underlying buffer. data can optionally be ignored by passing NULL.
  • [out] result: A napi_value representing a node::Buffer.

Returns napi_ok if the API succeeded.

This API allocates a node::Buffer object. While this is still a fully-supported data structure, in most cases using a TypedArray will suffice.

napi_create_buffer_copy#
napi_status napi_create_buffer_copy(napi_env env,
                                    size_t length,
                                    const void* data,
                                    void** result_data,
                                    napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] size: Size in bytes of the input buffer (should be the same as the size of the new buffer).
  • [in] data: Raw pointer to the underlying buffer to copy from.
  • [out] result_data: Pointer to the new Buffer's underlying data buffer. result_data can optionally be ignored by passing NULL.
  • [out] result: A napi_value representing a node::Buffer.

Returns napi_ok if the API succeeded.

This API allocates a node::Buffer object and initializes it with data copied from the passed-in buffer. While this is still a fully-supported data structure, in most cases using a TypedArray will suffice.

napi_create_date#
napi_status napi_create_date(napi_env env,
                             double time,
                             napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] time: ECMAScript time value in milliseconds since 01 January, 1970 UTC.
  • [out] result: A napi_value representing a JavaScript Date.

Returns napi_ok if the API succeeded.

This API does not observe leap seconds; they are ignored, as ECMAScript aligns with POSIX time specification.

This API allocates a JavaScript Date object.

JavaScript Date objects are described in Section 20.3 of the ECMAScript Language Specification.

napi_create_external#
napi_status napi_create_external(napi_env env,
                                 void* data,
                                 napi_finalize finalize_cb,
                                 void* finalize_hint,
                                 napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] data: Raw pointer to the external data.
  • [in] finalize_cb: Optional callback to call when the external value is being collected. napi_finalize provides more details.
  • [in] finalize_hint: Optional hint to pass to the finalize callback during collection.
  • [out] result: A napi_value representing an external value.

Returns napi_ok if the API succeeded.

This API allocates a JavaScript value with external data attached to it. This is used to pass external data through JavaScript code, so it can be retrieved later by native code using napi_get_value_external.

The API adds a napi_finalize callback which will be called when the JavaScript object just created has been garbage collected.

The created value is not an object, and therefore does not support additional properties. It is considered a distinct value type: calling napi_typeof() with an external value yields napi_external.

napi_create_external_arraybuffer#
napi_status
napi_create_external_arraybuffer(napi_env env,
                                 void* external_data,
                                 size_t byte_length,
                                 napi_finalize finalize_cb,
                                 void* finalize_hint,
                                 napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] external_data: Pointer to the underlying byte buffer of the ArrayBuffer.
  • [in] byte_length: The length in bytes of the underlying buffer.
  • [in] finalize_cb: Optional callback to call when the ArrayBuffer is being collected. napi_finalize provides more details.
  • [in] finalize_hint: Optional hint to pass to the finalize callback during collection.
  • [out] result: A napi_value representing a JavaScript ArrayBuffer.

Returns napi_ok if the API succeeded.

Some runtimes other than Node.js have dropped support for external buffers. On runtimes other than Node.js this method may return napi_no_external_buffers_allowed to indicate that external buffers are not supported. One such runtime is Electron as described in this issue electron/issues/35801.

In order to maintain broadest compatibility with all runtimes you may define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED in your addon before includes for the node-api headers. Doing so will hide the 2 functions that create external buffers. This will ensure a compilation error occurs if you accidentally use one of these methods.

This API returns a Node-API value corresponding to a JavaScript ArrayBuffer. The underlying byte buffer of the ArrayBuffer is externally allocated and managed. The caller must ensure that the byte buffer remains valid until the finalize callback is called.

The API adds a napi_finalize callback which will be called when the JavaScript object just created has been garbage collected.

JavaScript ArrayBuffers are described in Section 24.1 of the ECMAScript Language Specification.

napi_create_external_buffer#
napi_status napi_create_external_buffer(napi_env env,
                                        size_t length,
                                        void* data,
                                        napi_finalize finalize_cb,
                                        void* finalize_hint,
                                        napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] length: Size in bytes of the input buffer (should be the same as the size of the new buffer).
  • [in] data: Raw pointer to the underlying buffer to expose to JavaScript.
  • [in] finalize_cb: Optional callback to call when the ArrayBuffer is being collected. napi_finalize provides more details.
  • [in] finalize_hint: Optional hint to pass to the finalize callback during collection.
  • [out] result: A napi_value representing a node::Buffer.

Returns napi_ok if the API succeeded.

Some runtimes other than Node.js have dropped support for external buffers. On runtimes other than Node.js this method may return napi_no_external_buffers_allowed to indicate that external buffers are not supported. One such runtime is Electron as described in this issue electron/issues/35801.

In order to maintain broadest compatibility with all runtimes you may define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED in your addon before includes for the node-api headers. Doing so will hide the 2 functions that create external buffers. This will ensure a compilation error occurs if you accidentally use one of these methods.

This API allocates a node::Buffer object and initializes it with data backed by the passed in buffer. While this is still a fully-supported data structure, in most cases using a TypedArray will suffice.

The API adds a napi_finalize callback which will be called when the JavaScript object just created has been garbage collected.

For Node.js >=4 Buffers are Uint8Arrays.

napi_create_object#
napi_status napi_create_object(napi_env env, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [out] result: A napi_value representing a JavaScript Object.

Returns napi_ok if the API succeeded.

This API allocates a default JavaScript Object. It is the equivalent of doing new Object() in JavaScript.

The JavaScript Object type is described in Section 6.1.7 of the ECMAScript Language Specification.

napi_create_symbol#
napi_status napi_create_symbol(napi_env env,
                               napi_value description,
                               napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] description: Optional napi_value which refers to a JavaScript string to be set as the description for the symbol.
  • [out] result: A napi_value representing a JavaScript symbol.

Returns napi_ok if the API succeeded.

This API creates a JavaScript symbol value from a UTF8-encoded C string.

The JavaScript symbol type is described in Section 19.4 of the ECMAScript Language Specification.

node_api_symbol_for#
napi_status node_api_symbol_for(napi_env env,
                                const char* utf8description,
                                size_t length,
                                napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] utf8description: UTF-8 C string representing the text to be used as the description for the symbol.
  • [in] length: The length of the description string in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing a JavaScript symbol.

Returns napi_ok if the API succeeded.

This API searches in the global registry for an existing symbol with the given description. If the symbol already exists it will be returned, otherwise a new symbol will be created in the registry.

The JavaScript symbol type is described in Section 19.4 of the ECMAScript Language Specification.

napi_create_typedarray#
napi_status napi_create_typedarray(napi_env env,
                                   napi_typedarray_type type,
                                   size_t length,
                                   napi_value arraybuffer,
                                   size_t byte_offset,
                                   napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] type: Scalar datatype of the elements within the TypedArray.
  • [in] length: Number of elements in the TypedArray.
  • [in] arraybuffer: ArrayBuffer underlying the typed array.
  • [in] byte_offset: The byte offset within the ArrayBuffer from which to start projecting the TypedArray.
  • [out] result: A napi_value representing a JavaScript TypedArray.

Returns napi_ok if the API succeeded.

This API creates a JavaScript TypedArray object over an existing ArrayBuffer. TypedArray objects provide an array-like view over an underlying data buffer where each element has the same underlying binary scalar datatype.

It's required that (length * size_of_element) + byte_offset should be <= the size in bytes of the array passed in. If not, a RangeError exception is raised.

JavaScript TypedArray objects are described in Section 22.2 of the ECMAScript Language Specification.

node_api_create_buffer_from_arraybuffer#
napi_status NAPI_CDECL node_api_create_buffer_from_arraybuffer(napi_env env,
                                                              napi_value arraybuffer,
                                                              size_t byte_offset,
                                                              size_t byte_length,
                                                              napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] arraybuffer: The ArrayBuffer from which the buffer will be created.
  • [in] byte_offset: The byte offset within the ArrayBuffer from which to start creating the buffer.
  • [in] byte_length: The length in bytes of the buffer to be created from the ArrayBuffer.
  • [out] result: A napi_value representing the created JavaScript Buffer object.

Returns napi_ok if the API succeeded.

This API creates a JavaScript Buffer object from an existing ArrayBuffer. The Buffer object is a Node.js-specific class that provides a way to work with binary data directly in JavaScript.

The byte range [byte_offset, byte_offset + byte_length) must be within the bounds of the ArrayBuffer. If byte_offset + byte_length exceeds the size of the ArrayBuffer, a RangeError exception is raised.

napi_create_dataview#
napi_status napi_create_dataview(napi_env env,
                                 size_t byte_length,
                                 napi_value arraybuffer,
                                 size_t byte_offset,
                                 napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] length: Number of elements in the DataView.
  • [in] arraybuffer: ArrayBuffer underlying the DataView.
  • [in] byte_offset: The byte offset within the ArrayBuffer from which to start projecting the DataView.
  • [out] result: A napi_value representing a JavaScript DataView.

Returns napi_ok if the API succeeded.

This API creates a JavaScript DataView object over an existing ArrayBuffer. DataView objects provide an array-like view over an underlying data buffer, but one which allows items of different size and type in the ArrayBuffer.

It is required that byte_length + byte_offset is less than or equal to the size in bytes of the array passed in. If not, a RangeError exception is raised.

JavaScript DataView objects are described in Section 24.3 of the ECMAScript Language Specification.

Functions to convert from C types to Node-API#

napi_create_int32#
napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: Integer value to be represented in JavaScript.
  • [out] result: A napi_value representing a JavaScript number.

Returns napi_ok if the API succeeded.

This API is used to convert from the C int32_t type to the JavaScript number type.

The JavaScript number type is described in Section 6.1.6 of the ECMAScript Language Specification.

napi_create_uint32#
napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: Unsigned integer value to be represented in JavaScript.
  • [out] result: A napi_value representing a JavaScript number.

Returns napi_ok if the API succeeded.

This API is used to convert from the C uint32_t type to the JavaScript number type.

The JavaScript number type is described in Section 6.1.6 of the ECMAScript Language Specification.

napi_create_int64#
napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: Integer value to be represented in JavaScript.
  • [out] result: A napi_value representing a JavaScript number.

Returns napi_ok if the API succeeded.

This API is used to convert from the C int64_t type to the JavaScript number type.

The JavaScript number type is described in Section 6.1.6 of the ECMAScript Language Specification. Note the complete range of int64_t cannot be represented with full precision in JavaScript. Integer values outside the range of Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) will lose precision.

napi_create_double#
napi_status napi_create_double(napi_env env, double value, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: Double-precision value to be represented in JavaScript.
  • [out] result: A napi_value representing a JavaScript number.

Returns napi_ok if the API succeeded.

This API is used to convert from the C double type to the JavaScript number type.

The JavaScript number type is described in Section 6.1.6 of the ECMAScript Language Specification.

napi_create_bigint_int64#
napi_status napi_create_bigint_int64(napi_env env,
                                     int64_t value,
                                     napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: Integer value to be represented in JavaScript.
  • [out] result: A napi_value representing a JavaScript BigInt.

Returns napi_ok if the API succeeded.

This API converts the C int64_t type to the JavaScript BigInt type.

napi_create_bigint_uint64#
napi_status napi_create_bigint_uint64(napi_env env,
                                      uint64_t value,
                                      napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: Unsigned integer value to be represented in JavaScript.
  • [out] result: A napi_value representing a JavaScript BigInt.

Returns napi_ok if the API succeeded.

This API converts the C uint64_t type to the JavaScript BigInt type.

napi_create_bigint_words#
napi_status napi_create_bigint_words(napi_env env,
                                     int sign_bit,
                                     size_t word_count,
                                     const uint64_t* words,
                                     napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] sign_bit: Determines if the resulting BigInt will be positive or negative.
  • [in] word_count: The length of the words array.
  • [in] words: An array of uint64_t little-endian 64-bit words.
  • [out] result: A napi_value representing a JavaScript BigInt.

Returns napi_ok if the API succeeded.

This API converts an array of unsigned 64-bit words into a single BigInt value.

The resulting BigInt is calculated as: (–1)sign_bit (words[0] × (264)0 + words[1] × (264)1 + …)

napi_create_string_latin1#
napi_status napi_create_string_latin1(napi_env env,
                                      const char* str,
                                      size_t length,
                                      napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing an ISO-8859-1-encoded string.
  • [in] length: The length of the string in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing a JavaScript string.

Returns napi_ok if the API succeeded.

This API creates a JavaScript string value from an ISO-8859-1-encoded C string. The native string is copied.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

node_api_create_external_string_latin1#
napi_status
node_api_create_external_string_latin1(napi_env env,
                                       char* str,
                                       size_t length,
                                       napi_finalize finalize_callback,
                                       void* finalize_hint,
                                       napi_value* result,
                                       bool* copied); 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing an ISO-8859-1-encoded string.
  • [in] length: The length of the string in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [in] finalize_callback: The function to call when the string is being collected. The function will be called with the following parameters:
    • [in] env: The environment in which the add-on is running. This value may be null if the string is being collected as part of the termination of the worker or the main Node.js instance.
    • [in] data: This is the value str as a void* pointer.
    • [in] finalize_hint: This is the value finalize_hint that was given to the API. napi_finalize provides more details. This parameter is optional. Passing a null value means that the add-on doesn't need to be notified when the corresponding JavaScript string is collected.
  • [in] finalize_hint: Optional hint to pass to the finalize callback during collection.
  • [out] result: A napi_value representing a JavaScript string.
  • [out] copied: Whether the string was copied. If it was, the finalizer will already have been invoked to destroy str.

Returns napi_ok if the API succeeded.

This API creates a JavaScript string value from an ISO-8859-1-encoded C string. The native string may not be copied and must thus exist for the entire life cycle of the JavaScript value.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

napi_create_string_utf16#
napi_status napi_create_string_utf16(napi_env env,
                                     const char16_t* str,
                                     size_t length,
                                     napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing a UTF16-LE-encoded string.
  • [in] length: The length of the string in two-byte code units, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing a JavaScript string.

Returns napi_ok if the API succeeded.

This API creates a JavaScript string value from a UTF16-LE-encoded C string. The native string is copied.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

node_api_create_external_string_utf16#
napi_status
node_api_create_external_string_utf16(napi_env env,
                                      char16_t* str,
                                      size_t length,
                                      napi_finalize finalize_callback,
                                      void* finalize_hint,
                                      napi_value* result,
                                      bool* copied); 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing a UTF16-LE-encoded string.
  • [in] length: The length of the string in two-byte code units, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [in] finalize_callback: The function to call when the string is being collected. The function will be called with the following parameters:
    • [in] env: The environment in which the add-on is running. This value may be null if the string is being collected as part of the termination of the worker or the main Node.js instance.
    • [in] data: This is the value str as a void* pointer.
    • [in] finalize_hint: This is the value finalize_hint that was given to the API. napi_finalize provides more details. This parameter is optional. Passing a null value means that the add-on doesn't need to be notified when the corresponding JavaScript string is collected.
  • [in] finalize_hint: Optional hint to pass to the finalize callback during collection.
  • [out] result: A napi_value representing a JavaScript string.
  • [out] copied: Whether the string was copied. If it was, the finalizer will already have been invoked to destroy str.

Returns napi_ok if the API succeeded.

This API creates a JavaScript string value from a UTF16-LE-encoded C string. The native string may not be copied and must thus exist for the entire life cycle of the JavaScript value.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

napi_create_string_utf8#
napi_status napi_create_string_utf8(napi_env env,
                                    const char* str,
                                    size_t length,
                                    napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing a UTF8-encoded string.
  • [in] length: The length of the string in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing a JavaScript string.

Returns napi_ok if the API succeeded.

This API creates a JavaScript string value from a UTF8-encoded C string. The native string is copied.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

Functions to create optimized property keys#

Many JavaScript engines including V8 use internalized strings as keys to set and get property values. They typically use a hash table to create and lookup such strings. While it adds some cost per key creation, it improves the performance after that by enabling comparison of string pointers instead of the whole strings.

If a new JavaScript string is intended to be used as a property key, then for some JavaScript engines it will be more efficient to use the functions in this section. Otherwise, use the napi_create_string_utf8 or node_api_create_external_string_utf8 series functions as there may be additional overhead in creating/storing strings with the property key creation methods.

node_api_create_property_key_latin1#
napi_status NAPI_CDECL node_api_create_property_key_latin1(napi_env env,
                                                           const char* str,
                                                           size_t length,
                                                           napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing an ISO-8859-1-encoded string.
  • [in] length: The length of the string in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing an optimized JavaScript string to be used as a property key for objects.

Returns napi_ok if the API succeeded.

This API creates an optimized JavaScript string value from an ISO-8859-1-encoded C string to be used as a property key for objects. The native string is copied. In contrast with napi_create_string_latin1, subsequent calls to this function with the same str pointer may benefit from a speedup in the creation of the requested napi_value, depending on the engine.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

node_api_create_property_key_utf16#
napi_status NAPI_CDECL node_api_create_property_key_utf16(napi_env env,
                                                          const char16_t* str,
                                                          size_t length,
                                                          napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing a UTF16-LE-encoded string.
  • [in] length: The length of the string in two-byte code units, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing an optimized JavaScript string to be used as a property key for objects.

Returns napi_ok if the API succeeded.

This API creates an optimized JavaScript string value from a UTF16-LE-encoded C string to be used as a property key for objects. The native string is copied.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

node_api_create_property_key_utf8#
napi_status NAPI_CDECL node_api_create_property_key_utf8(napi_env env,
                                                         const char* str,
                                                         size_t length,
                                                         napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] str: Character buffer representing a UTF8-encoded string.
  • [in] length: The length of the string in two-byte code units, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [out] result: A napi_value representing an optimized JavaScript string to be used as a property key for objects.

Returns napi_ok if the API succeeded.

This API creates an optimized JavaScript string value from a UTF8-encoded C string to be used as a property key for objects. The native string is copied.

The JavaScript string type is described in Section 6.1.4 of the ECMAScript Language Specification.

Functions to convert from Node-API to C types#

napi_get_array_length#
napi_status napi_get_array_length(napi_env env,
                                  napi_value value,
                                  uint32_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing the JavaScript Array whose length is being queried.
  • [out] result: uint32 representing length of the array.

Returns napi_ok if the API succeeded.

This API returns the length of an array.

Array length is described in Section 22.1.4.1 of the ECMAScript Language Specification.

napi_get_arraybuffer_info#
napi_status napi_get_arraybuffer_info(napi_env env,
                                      napi_value arraybuffer,
                                      void** data,
                                      size_t* byte_length) 
  • [in] env: The environment that the API is invoked under.
  • [in] arraybuffer: napi_value representing the ArrayBuffer being queried.
  • [out] data: The underlying data buffer of the ArrayBuffer. If byte_length is 0, this may be NULL or any other pointer value.
  • [out] byte_length: Length in bytes of the underlying data buffer.

Returns napi_ok if the API succeeded.

This API is used to retrieve the underlying data buffer of an ArrayBuffer and its length.

WARNING: Use caution while using this API. The lifetime of the underlying data buffer is managed by the ArrayBuffer even after it's returned. A possible safe way to use this API is in conjunction with napi_create_reference, which can be used to guarantee control over the lifetime of the ArrayBuffer. It's also safe to use the returned data buffer within the same callback as long as there are no calls to other APIs that might trigger a GC.

napi_get_buffer_info#
napi_status napi_get_buffer_info(napi_env env,
                                 napi_value value,
                                 void** data,
                                 size_t* length) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing the node::Buffer or Uint8Array being queried.
  • [out] data: The underlying data buffer of the node::Buffer or Uint8Array. If length is 0, this may be NULL or any other pointer value.
  • [out] length: Length in bytes of the underlying data buffer.

Returns napi_ok if the API succeeded.

This method returns the identical data and byte_length as napi_get_typedarray_info. And napi_get_typedarray_info accepts a node::Buffer (a Uint8Array) as the value too.

This API is used to retrieve the underlying data buffer of a node::Buffer and its length.

Warning: Use caution while using this API since the underlying data buffer's lifetime is not guaranteed if it's managed by the VM.

napi_get_prototype#
napi_status napi_get_prototype(napi_env env,
                               napi_value object,
                               napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] object: napi_value representing JavaScript Object whose prototype to return. This returns the equivalent of Object.getPrototypeOf (which is not the same as the function's prototype property).
  • [out] result: napi_value representing prototype of the given object.

Returns napi_ok if the API succeeded.

napi_get_typedarray_info#
napi_status napi_get_typedarray_info(napi_env env,
                                     napi_value typedarray,
                                     napi_typedarray_type* type,
                                     size_t* length,
                                     void** data,
                                     napi_value* arraybuffer,
                                     size_t* byte_offset) 
  • [in] env: The environment that the API is invoked under.
  • [in] typedarray: napi_value representing the TypedArray whose properties to query.
  • [out] type: Scalar datatype of the elements within the TypedArray.
  • [out] length: The number of elements in the TypedArray.
  • [out] data: The data buffer underlying the TypedArray adjusted by the byte_offset value so that it points to the first element in the TypedArray. If the length of the array is 0, this may be NULL or any other pointer value.
  • [out] arraybuffer: The ArrayBuffer underlying the TypedArray.
  • [out] byte_offset: The byte offset within the underlying native array at which the first element of the arrays is located. The value for the data parameter has already been adjusted so that data points to the first element in the array. Therefore, the first byte of the native array would be at data - byte_offset.

Returns napi_ok if the API succeeded.

This API returns various properties of a typed array.

Any of the out parameters may be NULL if that property is unneeded.

Warning: Use caution while using this API since the underlying data buffer is managed by the VM.

napi_get_dataview_info#
napi_status napi_get_dataview_info(napi_env env,
                                   napi_value dataview,
                                   size_t* byte_length,
                                   void** data,
                                   napi_value* arraybuffer,
                                   size_t* byte_offset) 
  • [in] env: The environment that the API is invoked under.
  • [in] dataview: napi_value representing the DataView whose properties to query.
  • [out] byte_length: Number of bytes in the DataView.
  • [out] data: The data buffer underlying the DataView. If byte_length is 0, this may be NULL or any other pointer value.
  • [out] arraybuffer: ArrayBuffer underlying the DataView.
  • [out] byte_offset: The byte offset within the data buffer from which to start projecting the DataView.

Returns napi_ok if the API succeeded.

Any of the out parameters may be NULL if that property is unneeded.

This API returns various properties of a DataView.

napi_get_date_value#
napi_status napi_get_date_value(napi_env env,
                                napi_value value,
                                double* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing a JavaScript Date.
  • [out] result: Time value as a double represented as milliseconds since midnight at the beginning of 01 January, 1970 UTC.

This API does not observe leap seconds; they are ignored, as ECMAScript aligns with POSIX time specification.

Returns napi_ok if the API succeeded. If a non-date napi_value is passed in it returns napi_date_expected.

This API returns the C double primitive of time value for the given JavaScript Date.

napi_get_value_bool#
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript Boolean.
  • [out] result: C boolean primitive equivalent of the given JavaScript Boolean.

Returns napi_ok if the API succeeded. If a non-boolean napi_value is passed in it returns napi_boolean_expected.

This API returns the C boolean primitive equivalent of the given JavaScript Boolean.

napi_get_value_double#
napi_status napi_get_value_double(napi_env env,
                                  napi_value value,
                                  double* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript number.
  • [out] result: C double primitive equivalent of the given JavaScript number.

Returns napi_ok if the API succeeded. If a non-number napi_value is passed in it returns napi_number_expected.

This API returns the C double primitive equivalent of the given JavaScript number.

napi_get_value_bigint_int64#
napi_status napi_get_value_bigint_int64(napi_env env,
                                        napi_value value,
                                        int64_t* result,
                                        bool* lossless); 
  • [in] env: The environment that the API is invoked under
  • [in] value: napi_value representing JavaScript BigInt.
  • [out] result: C int64_t primitive equivalent of the given JavaScript BigInt.
  • [out] lossless: Indicates whether the BigInt value was converted losslessly.

Returns napi_ok if the API succeeded. If a non-BigInt is passed in it returns napi_bigint_expected.

This API returns the C int64_t primitive equivalent of the given JavaScript BigInt. If needed it will truncate the value, setting lossless to false.

napi_get_value_bigint_uint64#
napi_status napi_get_value_bigint_uint64(napi_env env,
                                        napi_value value,
                                        uint64_t* result,
                                        bool* lossless); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript BigInt.
  • [out] result: C uint64_t primitive equivalent of the given JavaScript BigInt.
  • [out] lossless: Indicates whether the BigInt value was converted losslessly.

Returns napi_ok if the API succeeded. If a non-BigInt is passed in it returns napi_bigint_expected.

This API returns the C uint64_t primitive equivalent of the given JavaScript BigInt. If needed it will truncate the value, setting lossless to false.

napi_get_value_bigint_words#
napi_status napi_get_value_bigint_words(napi_env env,
                                        napi_value value,
                                        int* sign_bit,
                                        size_t* word_count,
                                        uint64_t* words); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript BigInt.
  • [out] sign_bit: Integer representing if the JavaScript BigInt is positive or negative.
  • [in/out] word_count: Must be initialized to the length of the words array. Upon return, it will be set to the actual number of words that would be needed to store this BigInt.
  • [out] words: Pointer to a pre-allocated 64-bit word array.

Returns napi_ok if the API succeeded.

This API converts a single BigInt value into a sign bit, 64-bit little-endian array, and the number of elements in the array. sign_bit and words may be both set to NULL, in order to get only word_count.

napi_get_value_external#
napi_status napi_get_value_external(napi_env env,
                                    napi_value value,
                                    void** result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript external value.
  • [out] result: Pointer to the data wrapped by the JavaScript external value.

Returns napi_ok if the API succeeded. If a non-external napi_value is passed in it returns napi_invalid_arg.

This API retrieves the external data pointer that was previously passed to napi_create_external().

napi_get_value_int32#
napi_status napi_get_value_int32(napi_env env,
                                 napi_value value,
                                 int32_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript number.
  • [out] result: C int32 primitive equivalent of the given JavaScript number.

Returns napi_ok if the API succeeded. If a non-number napi_value is passed in napi_number_expected.

This API returns the C int32 primitive equivalent of the given JavaScript number.

If the number exceeds the range of the 32 bit integer, then the result is truncated to the equivalent of the bottom 32 bits. This can result in a large positive number becoming a negative number if the value is > 231 - 1.

Non-finite number values (NaN, +Infinity, or -Infinity) set the result to zero.

napi_get_value_int64#
napi_status napi_get_value_int64(napi_env env,
                                 napi_value value,
                                 int64_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript number.
  • [out] result: C int64 primitive equivalent of the given JavaScript number.

Returns napi_ok if the API succeeded. If a non-number napi_value is passed in it returns napi_number_expected.

This API returns the C int64 primitive equivalent of the given JavaScript number.

number values outside the range of Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) will lose precision.

Non-finite number values (NaN, +Infinity, or -Infinity) set the result to zero.

napi_get_value_string_latin1#
napi_status napi_get_value_string_latin1(napi_env env,
                                         napi_value value,
                                         char* buf,
                                         size_t bufsize,
                                         size_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript string.
  • [in] buf: Buffer to write the ISO-8859-1-encoded string into. If NULL is passed in, the length of the string in bytes and excluding the null terminator is returned in result.
  • [in] bufsize: Size of the destination buffer. When this value is insufficient, the returned string is truncated and null-terminated. If this value is zero, then the string is not returned and no changes are done to the buffer.
  • [out] result: Number of bytes copied into the buffer, excluding the null terminator.

Returns napi_ok if the API succeeded. If a non-string napi_value is passed in it returns napi_string_expected.

This API returns the ISO-8859-1-encoded string corresponding the value passed in.

napi_get_value_string_utf8#
napi_status napi_get_value_string_utf8(napi_env env,
                                       napi_value value,
                                       char* buf,
                                       size_t bufsize,
                                       size_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript string.
  • [in] buf: Buffer to write the UTF8-encoded string into. If NULL is passed in, the length of the string in bytes and excluding the null terminator is returned in result.
  • [in] bufsize: Size of the destination buffer. When this value is insufficient, the returned string is truncated and null-terminated. If this value is zero, then the string is not returned and no changes are done to the buffer.
  • [out] result: Number of bytes copied into the buffer, excluding the null terminator.

Returns napi_ok if the API succeeded. If a non-string napi_value is passed in it returns napi_string_expected.

This API returns the UTF8-encoded string corresponding the value passed in.

napi_get_value_string_utf16#
napi_status napi_get_value_string_utf16(napi_env env,
                                        napi_value value,
                                        char16_t* buf,
                                        size_t bufsize,
                                        size_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript string.
  • [in] buf: Buffer to write the UTF16-LE-encoded string into. If NULL is passed in, the length of the string in 2-byte code units and excluding the null terminator is returned.
  • [in] bufsize: Size of the destination buffer. When this value is insufficient, the returned string is truncated and null-terminated. If this value is zero, then the string is not returned and no changes are done to the buffer.
  • [out] result: Number of 2-byte code units copied into the buffer, excluding the null terminator.

Returns napi_ok if the API succeeded. If a non-string napi_value is passed in it returns napi_string_expected.

This API returns the UTF16-encoded string corresponding the value passed in.

napi_get_value_uint32#
napi_status napi_get_value_uint32(napi_env env,
                                  napi_value value,
                                  uint32_t* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: napi_value representing JavaScript number.
  • [out] result: C primitive equivalent of the given napi_value as a uint32_t.

Returns napi_ok if the API succeeded. If a non-number napi_value is passed in it returns napi_number_expected.

This API returns the C primitive equivalent of the given napi_value as a uint32_t.

Functions to get global instances#

napi_get_boolean#
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The value of the boolean to retrieve.
  • [out] result: napi_value representing JavaScript Boolean singleton to retrieve.

Returns napi_ok if the API succeeded.

This API is used to return the JavaScript singleton object that is used to represent the given boolean value.

napi_get_global#
napi_status napi_get_global(napi_env env, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [out] result: napi_value representing JavaScript global object.

Returns napi_ok if the API succeeded.

This API returns the global object.

napi_get_null#
napi_status napi_get_null(napi_env env, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [out] result: napi_value representing JavaScript null object.

Returns napi_ok if the API succeeded.

This API returns the null object.

napi_get_undefined#
napi_status napi_get_undefined(napi_env env, napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [out] result: napi_value representing JavaScript Undefined value.

Returns napi_ok if the API succeeded.

This API returns the Undefined object.

Working with JavaScript values and abstract operations#

Node-API exposes a set of APIs to perform some abstract operations on JavaScript values. Some of these operations are documented under Section 7 of the ECMAScript Language Specification.

These APIs support doing one of the following:

  1. Coerce JavaScript values to specific JavaScript types (such as number or string).
  2. Check the type of a JavaScript value.
  3. Check for equality between two JavaScript values.

napi_coerce_to_bool#

napi_status napi_coerce_to_bool(napi_env env,
                                napi_value value,
                                napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to coerce.
  • [out] result: napi_value representing the coerced JavaScript Boolean.

Returns napi_ok if the API succeeded.

This API implements the abstract operation ToBoolean() as defined in Section 7.1.2 of the ECMAScript Language Specification.

napi_coerce_to_number#

napi_status napi_coerce_to_number(napi_env env,
                                  napi_value value,
                                  napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to coerce.
  • [out] result: napi_value representing the coerced JavaScript number.

Returns napi_ok if the API succeeded.

This API implements the abstract operation ToNumber() as defined in Section 7.1.3 of the ECMAScript Language Specification. This function potentially runs JS code if the passed-in value is an object.

napi_coerce_to_object#

napi_status napi_coerce_to_object(napi_env env,
                                  napi_value value,
                                  napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to coerce.
  • [out] result: napi_value representing the coerced JavaScript Object.

Returns napi_ok if the API succeeded.

This API implements the abstract operation ToObject() as defined in Section 7.1.13 of the ECMAScript Language Specification.

napi_coerce_to_string#

napi_status napi_coerce_to_string(napi_env env,
                                  napi_value value,
                                  napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to coerce.
  • [out] result: napi_value representing the coerced JavaScript string.

Returns napi_ok if the API succeeded.

This API implements the abstract operation ToString() as defined in Section 7.1.13 of the ECMAScript Language Specification. This function potentially runs JS code if the passed-in value is an object.

napi_typeof#

napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value whose type to query.
  • [out] result: The type of the JavaScript value.

Returns napi_ok if the API succeeded.

  • napi_invalid_arg if the type of value is not a known ECMAScript type and value is not an External value.

This API represents behavior similar to invoking the typeof Operator on the object as defined in Section 12.5.5 of the ECMAScript Language Specification. However, there are some differences:

  1. It has support for detecting an External value.
  2. It detects null as a separate type, while ECMAScript typeof would detect object.

If value has a type that is invalid, an error is returned.

napi_instanceof#

napi_status napi_instanceof(napi_env env,
                            napi_value object,
                            napi_value constructor,
                            bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] object: The JavaScript value to check.
  • [in] constructor: The JavaScript function object of the constructor function to check against.
  • [out] result: Boolean that is set to true if object instanceof constructor is true.

Returns napi_ok if the API succeeded.

This API represents invoking the instanceof Operator on the object as defined in Section 12.10.4 of the ECMAScript Language Specification.

napi_is_array#

napi_status napi_is_array(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given object is an array.

Returns napi_ok if the API succeeded.

This API represents invoking the IsArray operation on the object as defined in Section 7.2.2 of the ECMAScript Language Specification.

napi_is_arraybuffer#

napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given object is an ArrayBuffer.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in is an array buffer.

napi_is_buffer#

napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given napi_value represents a node::Buffer or Uint8Array object.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in is a buffer or Uint8Array. napi_is_typedarray should be preferred if the caller needs to check if the value is a Uint8Array.

napi_is_date#

napi_status napi_is_date(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given napi_value represents a JavaScript Date object.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in is a date.

napi_is_error#

napi_status napi_is_error(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given napi_value represents an Error object.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in is an Error.

napi_is_typedarray#

napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given napi_value represents a TypedArray.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in is a typed array.

napi_is_dataview#

napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The JavaScript value to check.
  • [out] result: Whether the given napi_value represents a DataView.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in is a DataView.

napi_strict_equals#

napi_status napi_strict_equals(napi_env env,
                               napi_value lhs,
                               napi_value rhs,
                               bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] lhs: The JavaScript value to check.
  • [in] rhs: The JavaScript value to check against.
  • [out] result: Whether the two napi_value objects are equal.

Returns napi_ok if the API succeeded.

This API represents the invocation of the Strict Equality algorithm as defined in Section 7.2.14 of the ECMAScript Language Specification.

napi_detach_arraybuffer#

napi_status napi_detach_arraybuffer(napi_env env,
                                    napi_value arraybuffer) 
  • [in] env: The environment that the API is invoked under.
  • [in] arraybuffer: The JavaScript ArrayBuffer to be detached.

Returns napi_ok if the API succeeded. If a non-detachable ArrayBuffer is passed in it returns napi_detachable_arraybuffer_expected.

Generally, an ArrayBuffer is non-detachable if it has been detached before. The engine may impose additional conditions on whether an ArrayBuffer is detachable. For example, V8 requires that the ArrayBuffer be external, that is, created with napi_create_external_arraybuffer.

This API represents the invocation of the ArrayBuffer detach operation as defined in Section 24.1.1.3 of the ECMAScript Language Specification.

napi_is_detached_arraybuffer#

napi_status napi_is_detached_arraybuffer(napi_env env,
                                         napi_value arraybuffer,
                                         bool* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] arraybuffer: The JavaScript ArrayBuffer to be checked.
  • [out] result: Whether the arraybuffer is detached.

Returns napi_ok if the API succeeded.

The ArrayBuffer is considered detached if its internal data is null.

This API represents the invocation of the ArrayBuffer IsDetachedBuffer operation as defined in Section 24.1.1.2 of the ECMAScript Language Specification.

Working with JavaScript properties#

Node-API exposes a set of APIs to get and set properties on JavaScript objects. Some of these types are documented under Section 7 of the ECMAScript Language Specification.

Properties in JavaScript are represented as a tuple of a key and a value. Fundamentally, all property keys in Node-API can be represented in one of the following forms:

  • Named: a simple UTF8-encoded string
  • Integer-Indexed: an index value represented by uint32_t
  • JavaScript value: these are represented in Node-API by napi_value. This can be a napi_value representing a string, number, or symbol.

Node-API values are represented by the type napi_value. Any Node-API call that requires a JavaScript value takes in a napi_value. However, it's the caller's responsibility to make sure that the napi_value in question is of the JavaScript type expected by the API.

The APIs documented in this section provide a simple interface to get and set properties on arbitrary JavaScript objects represented by napi_value.

For instance, consider the following JavaScript code snippet:

const obj = {};
obj.myProp = 123; 

The equivalent can be done using Node-API values with the following snippet:

napi_status status = napi_generic_failure;

// const obj = {}
napi_value obj, value;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;

// Create a napi_value for 123
status = napi_create_int32(env, 123, &value);
if (status != napi_ok) return status;

// obj.myProp = 123
status = napi_set_named_property(env, obj, "myProp", value);
if (status != napi_ok) return status; 

Indexed properties can be set in a similar manner. Consider the following JavaScript snippet:

const arr = [];
arr[123] = 'hello'; 

The equivalent can be done using Node-API values with the following snippet:

napi_status status = napi_generic_failure;

// const arr = [];
napi_value arr, value;
status = napi_create_array(env, &arr);
if (status != napi_ok) return status;

// Create a napi_value for 'hello'
status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &value);
if (status != napi_ok) return status;

// arr[123] = 'hello';
status = napi_set_element(env, arr, 123, value);
if (status != napi_ok) return status; 

Properties can be retrieved using the APIs described in this section. Consider the following JavaScript snippet:

const arr = [];
const value = arr[123]; 

The following is the approximate equivalent of the Node-API counterpart:

napi_status status = napi_generic_failure;

// const arr = []
napi_value arr, value;
status = napi_create_array(env, &arr);
if (status != napi_ok) return status;

// const value = arr[123]
status = napi_get_element(env, arr, 123, &value);
if (status != napi_ok) return status; 

Finally, multiple properties can also be defined on an object for performance reasons. Consider the following JavaScript:

const obj = {};
Object.defineProperties(obj, {
  'foo': { value: 123, writable: true, configurable: true, enumerable: true },
  'bar': { value: 456, writable: true, configurable: true, enumerable: true },
}); 

The following is the approximate equivalent of the Node-API counterpart:

napi_status status = napi_status_generic_failure;

// const obj = {};
napi_value obj;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;

// Create napi_values for 123 and 456
napi_value fooValue, barValue;
status = napi_create_int32(env, 123, &fooValue);
if (status != napi_ok) return status;
status = napi_create_int32(env, 456, &barValue);
if (status != napi_ok) return status;

// Set the properties
napi_property_descriptor descriptors[] = {
  { "foo", NULL, NULL, NULL, NULL, fooValue, napi_writable | napi_configurable, NULL },
  { "bar", NULL, NULL, NULL, NULL, barValue, napi_writable | napi_configurable, NULL }
}
status = napi_define_properties(env,
                                obj,
                                sizeof(descriptors) / sizeof(descriptors[0]),
                                descriptors);
if (status != napi_ok) return status; 

Structures#

napi_property_attributes#
typedef enum {
  napi_default = 0,
  napi_writable = 1 << 0,
  napi_enumerable = 1 << 1,
  napi_configurable = 1 << 2,

  // Used with napi_define_class to distinguish static properties
  // from instance properties. Ignored by napi_define_properties.
  napi_static = 1 << 10,

  // Default for class methods.
  napi_default_method = napi_writable | napi_configurable,

  // Default for object properties, like in JS obj[prop].
  napi_default_jsproperty = napi_writable |
                          napi_enumerable |
                          napi_configurable,
} napi_property_attributes; 

napi_property_attributes are flags used to control the behavior of properties set on a JavaScript object. Other than napi_static they correspond to the attributes listed in Section 6.1.7.1 of the ECMAScript Language Specification. They can be one or more of the following bitflags:

  • napi_default: No explicit attributes are set on the property. By default, a property is read only, not enumerable and not configurable.
  • napi_writable: The property is writable.
  • napi_enumerable: The property is enumerable.
  • napi_configurable: The property is configurable as defined in Section 6.1.7.1 of the ECMAScript Language Specification.
  • napi_static: The property will be defined as a static property on a class as opposed to an instance property, which is the default. This is used only by napi_define_class. It is ignored by napi_define_properties.
  • napi_default_method: Like a method in a JS class, the property is configurable and writeable, but not enumerable.
  • napi_default_jsproperty: Like a property set via assignment in JavaScript, the property is writable, enumerable, and configurable.
napi_property_descriptor#
typedef struct {
  // One of utf8name or name should be NULL.
  const char* utf8name;
  napi_value name;

  napi_callback method;
  napi_callback getter;
  napi_callback setter;
  napi_value value;

  napi_property_attributes attributes;
  void* data;
} napi_property_descriptor; 
  • utf8name: Optional string describing the key for the property, encoded as UTF8. One of utf8name or name must be provided for the property.
  • name: Optional napi_value that points to a JavaScript string or symbol to be used as the key for the property. One of utf8name or name must be provided for the property.
  • value: The value that's retrieved by a get access of the property if the property is a data property. If this is passed in, set getter, setter, method and data to NULL (since these members won't be used).
  • getter: A function to call when a get access of the property is performed. If this is passed in, set value and method to NULL (since these members won't be used). The given function is called implicitly by the runtime when the property is accessed from JavaScript code (or if a get on the property is performed using a Node-API call). napi_callback provides more details.
  • setter: A function to call when a set access of the property is performed. If this is passed in, set value and method to NULL (since these members won't be used). The given function is called implicitly by the runtime when the property is set from JavaScript code (or if a set on the property is performed using a Node-API call). napi_callback provides more details.
  • method: Set this to make the property descriptor object's value property to be a JavaScript function represented by method. If this is passed in, set value, getter and setter to NULL (since these members won't be used). napi_callback provides more details.
  • attributes: The attributes associated with the particular property. See napi_property_attributes.
  • data: The callback data passed into method, getter and setter if this function is invoked.

Functions#

napi_get_property_names#
napi_status napi_get_property_names(napi_env env,
                                    napi_value object,
                                    napi_value* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to retrieve the properties.
  • [out] result: A napi_value representing an array of JavaScript values that represent the property names of the object. The API can be used to iterate over result using napi_get_array_length and napi_get_element.

Returns napi_ok if the API succeeded.

This API returns the names of the enumerable properties of object as an array of strings. The properties of object whose key is a symbol will not be included.

napi_get_all_property_names#
napi_get_all_property_names(napi_env env,
                            napi_value object,
                            napi_key_collection_mode key_mode,
                            napi_key_filter key_filter,
                            napi_key_conversion key_conversion,
                            napi_value* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to retrieve the properties.
  • [in] key_mode: Whether to retrieve prototype properties as well.
  • [in] key_filter: Which properties to retrieve (enumerable/readable/writable).
  • [in] key_conversion: Whether to convert numbered property keys to strings.
  • [out] result: A napi_value representing an array of JavaScript values that represent the property names of the object. napi_get_array_length and napi_get_element can be used to iterate over result.

Returns napi_ok if the API succeeded.

This API returns an array containing the names of the available properties of this object.

napi_set_property#
napi_status napi_set_property(napi_env env,
                              napi_value object,
                              napi_value key,
                              napi_value value); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object on which to set the property.
  • [in] key: The name of the property to set.
  • [in] value: The property value.

Returns napi_ok if the API succeeded.

This API set a property on the Object passed in.

napi_get_property#
napi_status napi_get_property(napi_env env,
                              napi_value object,
                              napi_value key,
                              napi_value* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to retrieve the property.
  • [in] key: The name of the property to retrieve.
  • [out] result: The value of the property.

Returns napi_ok if the API succeeded.

This API gets the requested property from the Object passed in.

napi_has_property#
napi_status napi_has_property(napi_env env,
                              napi_value object,
                              napi_value key,
                              bool* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to query.
  • [in] key: The name of the property whose existence to check.
  • [out] result: Whether the property exists on the object or not.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in has the named property.

napi_delete_property#
napi_status napi_delete_property(napi_env env,
                                 napi_value object,
                                 napi_value key,
                                 bool* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to query.
  • [in] key: The name of the property to delete.
  • [out] result: Whether the property deletion succeeded or not. result can optionally be ignored by passing NULL.

Returns napi_ok if the API succeeded.

This API attempts to delete the key own property from object.

napi_has_own_property#
napi_status napi_has_own_property(napi_env env,
                                  napi_value object,
                                  napi_value key,
                                  bool* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to query.
  • [in] key: The name of the own property whose existence to check.
  • [out] result: Whether the own property exists on the object or not.

Returns napi_ok if the API succeeded.

This API checks if the Object passed in has the named own property. key must be a string or a symbol, or an error will be thrown. Node-API will not perform any conversion between data types.

napi_set_named_property#
napi_status napi_set_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8Name,
                                    napi_value value); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object on which to set the property.
  • [in] utf8Name: The name of the property to set.
  • [in] value: The property value.

Returns napi_ok if the API succeeded.

This method is equivalent to calling napi_set_property with a napi_value created from the string passed in as utf8Name.

napi_get_named_property#
napi_status napi_get_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8Name,
                                    napi_value* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to retrieve the property.
  • [in] utf8Name: The name of the property to get.
  • [out] result: The value of the property.

Returns napi_ok if the API succeeded.

This method is equivalent to calling napi_get_property with a napi_value created from the string passed in as utf8Name.

napi_has_named_property#
napi_status napi_has_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8Name,
                                    bool* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to query.
  • [in] utf8Name: The name of the property whose existence to check.
  • [out] result: Whether the property exists on the object or not.

Returns napi_ok if the API succeeded.

This method is equivalent to calling napi_has_property with a napi_value created from the string passed in as utf8Name.

napi_set_element#
napi_status napi_set_element(napi_env env,
                             napi_value object,
                             uint32_t index,
                             napi_value value); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to set the properties.
  • [in] index: The index of the property to set.
  • [in] value: The property value.

Returns napi_ok if the API succeeded.

This API sets an element on the Object passed in.

napi_get_element#
napi_status napi_get_element(napi_env env,
                             napi_value object,
                             uint32_t index,
                             napi_value* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to retrieve the property.
  • [in] index: The index of the property to get.
  • [out] result: The value of the property.

Returns napi_ok if the API succeeded.

This API gets the element at the requested index.

napi_has_element#
napi_status napi_has_element(napi_env env,
                             napi_value object,
                             uint32_t index,
                             bool* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to query.
  • [in] index: The index of the property whose existence to check.
  • [out] result: Whether the property exists on the object or not.

Returns napi_ok if the API succeeded.

This API returns if the Object passed in has an element at the requested index.

napi_delete_element#
napi_status napi_delete_element(napi_env env,
                                napi_value object,
                                uint32_t index,
                                bool* result); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to query.
  • [in] index: The index of the property to delete.
  • [out] result: Whether the element deletion succeeded or not. result can optionally be ignored by passing NULL.

Returns napi_ok if the API succeeded.

This API attempts to delete the specified index from object.

napi_define_properties#
napi_status napi_define_properties(napi_env env,
                                   napi_value object,
                                   size_t property_count,
                                   const napi_property_descriptor* properties); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object from which to retrieve the properties.
  • [in] property_count: The number of elements in the properties array.
  • [in] properties: The array of property descriptors.

Returns napi_ok if the API succeeded.

This method allows the efficient definition of multiple properties on a given object. The properties are defined using property descriptors (see napi_property_descriptor). Given an array of such property descriptors, this API will set the properties on the object one at a time, as defined by DefineOwnProperty() (described in Section 9.1.6 of the ECMA-262 specification).

napi_object_freeze#
napi_status napi_object_freeze(napi_env env,
                               napi_value object); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to freeze.

Returns napi_ok if the API succeeded.

This method freezes a given object. This prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. It also prevents the object's prototype from being changed. This is described in Section 19.1.2.6 of the ECMA-262 specification.

napi_object_seal#
napi_status napi_object_seal(napi_env env,
                             napi_value object); 
  • [in] env: The environment that the Node-API call is invoked under.
  • [in] object: The object to seal.

Returns napi_ok if the API succeeded.

This method seals a given object. This prevents new properties from being added to it, as well as marking all existing properties as non-configurable. This is described in Section 19.1.2.20 of the ECMA-262 specification.

Working with JavaScript functions#

Node-API provides a set of APIs that allow JavaScript code to call back into native code. Node-APIs that support calling back into native code take in a callback functions represented by the napi_callback type. When the JavaScript VM calls back to native code, the napi_callback function provided is invoked. The APIs documented in this section allow the callback function to do the following:

  • Get information about the context in which the callback was invoked.
  • Get the arguments passed into the callback.
  • Return a napi_value back from the callback.

Additionally, Node-API provides a set of functions which allow calling JavaScript functions from native code. One can either call a function like a regular JavaScript function call, or as a constructor function.

Any non-NULL data which is passed to this API via the data field of the napi_property_descriptor items can be associated with object and freed whenever object is garbage-collected by passing both object and the data to napi_add_finalizer.

napi_call_function#

NAPI_EXTERN napi_status napi_call_function(napi_env env,
                                           napi_value recv,
                                           napi_value func,
                                           size_t argc,
                                           const napi_value* argv,
                                           napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] recv: The this value passed to the called function.
  • [in] func: napi_value representing the JavaScript function to be invoked.
  • [in] argc: The count of elements in the argv array.
  • [in] argv: Array of napi_values representing JavaScript values passed in as arguments to the function.
  • [out] result: napi_value representing the JavaScript object returned.

Returns napi_ok if the API succeeded.

This method allows a JavaScript function object to be called from a native add-on. This is the primary mechanism of calling back from the add-on's native code into JavaScript. For the special case of calling into JavaScript after an async operation, see napi_make_callback.

A sample use case might look as follows. Consider the following JavaScript snippet:

function AddTwo(num) {
  return num + 2;
}
global.AddTwo = AddTwo; 

Then, the above function can be invoked from a native add-on using the following code:

// Get the function named "AddTwo" on the global object
napi_value global, add_two, arg;
napi_status status = napi_get_global(env, &global);
if (status != napi_ok) return;

status = napi_get_named_property(env, global, "AddTwo", &add_two);
if (status != napi_ok) return;

// const arg = 1337
status = napi_create_int32(env, 1337, &arg);
if (status != napi_ok) return;

napi_value* argv = &arg;
size_t argc = 1;

// AddTwo(arg);
napi_value return_val;
status = napi_call_function(env, global, add_two, argc, argv, &return_val);
if (status != napi_ok) return;

// Convert the result back to a native type
int32_t result;
status = napi_get_value_int32(env, return_val, &result);
if (status != napi_ok) return; 

napi_create_function#

napi_status napi_create_function(napi_env env,
                                 const char* utf8name,
                                 size_t length,
                                 napi_callback cb,
                                 void* data,
                                 napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] utf8Name: Optional name of the function encoded as UTF8. This is visible within JavaScript as the new function object's name property.
  • [in] length: The length of the utf8name in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [in] cb: The native function which should be called when this function object is invoked. napi_callback provides more details.
  • [in] data: User-provided data context. This will be passed back into the function when invoked later.
  • [out] result: napi_value representing the JavaScript function object for the newly created function.

Returns napi_ok if the API succeeded.

This API allows an add-on author to create a function object in native code. This is the primary mechanism to allow calling into the add-on's native code from JavaScript.

The newly created function is not automatically visible from script after this call. Instead, a property must be explicitly set on any object that is visible to JavaScript, in order for the function to be accessible from script.

In order to expose a function as part of the add-on's module exports, set the newly created function on the exports object. A sample module might look as follows:

napi_value SayHello(napi_env env, napi_callback_info info) {
  printf("Hello\n");
  return NULL;
}

napi_value Init(napi_env env, napi_value exports) {
  napi_status status;

  napi_value fn;
  status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn);
  if (status != napi_ok) return NULL;

  status = napi_set_named_property(env, exports, "sayHello", fn);
  if (status != napi_ok) return NULL;

  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 

Given the above code, the add-on can be used from JavaScript as follows:

const myaddon = require('./addon');
myaddon.sayHello(); 

The string passed to require() is the name of the target in binding.gyp responsible for creating the .node file.

Any non-NULL data which is passed to this API via the data parameter can be associated with the resulting JavaScript function (which is returned in the result parameter) and freed whenever the function is garbage-collected by passing both the JavaScript function and the data to napi_add_finalizer.

JavaScript Functions are described in Section 19.2 of the ECMAScript Language Specification.

napi_get_cb_info#

napi_status napi_get_cb_info(napi_env env,
                             napi_callback_info cbinfo,
                             size_t* argc,
                             napi_value* argv,
                             napi_value* thisArg,
                             void** data) 
  • [in] env: The environment that the API is invoked under.
  • [in] cbinfo: The callback info passed into the callback function.
  • [in-out] argc: Specifies the length of the provided argv array and receives the actual count of arguments. argc can optionally be ignored by passing NULL.
  • [out] argv: C array of napi_values to which the arguments will be copied. If there are more arguments than the provided count, only the requested number of arguments are copied. If there are fewer arguments provided than claimed, the rest of argv is filled with napi_value values that represent undefined. argv can optionally be ignored by passing NULL.
  • [out] thisArg: Receives the JavaScript this argument for the call. thisArg can optionally be ignored by passing NULL.
  • [out] data: Receives the data pointer for the callback. data can optionally be ignored by passing NULL.

Returns napi_ok if the API succeeded.

This method is used within a callback function to retrieve details about the call like the arguments and the this pointer from a given callback info.

napi_get_new_target#

napi_status napi_get_new_target(napi_env env,
                                napi_callback_info cbinfo,
                                napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] cbinfo: The callback info passed into the callback function.
  • [out] result: The new.target of the constructor call.

Returns napi_ok if the API succeeded.

This API returns the new.target of the constructor call. If the current callback is not a constructor call, the result is NULL.

napi_new_instance#

napi_status napi_new_instance(napi_env env,
                              napi_value cons,
                              size_t argc,
                              napi_value* argv,
                              napi_value* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] cons: napi_value representing the JavaScript function to be invoked as a constructor.
  • [in] argc: The count of elements in the argv array.
  • [in] argv: Array of JavaScript values as napi_value representing the arguments to the constructor. If argc is zero this parameter may be omitted by passing in NULL.
  • [out] result: napi_value representing the JavaScript object returned, which in this case is the constructed object.

This method is used to instantiate a new JavaScript value using a given napi_value that represents the constructor for the object. For example, consider the following snippet:

function MyObject(param) {
  this.param = param;
}

const arg = 'hello';
const value = new MyObject(arg); 

The following can be approximated in Node-API using the following snippet:

// Get the constructor function MyObject
napi_value global, constructor, arg, value;
napi_status status = napi_get_global(env, &global);
if (status != napi_ok) return;

status = napi_get_named_property(env, global, "MyObject", &constructor);
if (status != napi_ok) return;

// const arg = "hello"
status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &arg);
if (status != napi_ok) return;

napi_value* argv = &arg;
size_t argc = 1;

// const value = new MyObject(arg)
status = napi_new_instance(env, constructor, argc, argv, &value); 

Returns napi_ok if the API succeeded.

Object wrap#

Node-API offers a way to "wrap" C++ classes and instances so that the class constructor and methods can be called from JavaScript.

  1. The napi_define_class API defines a JavaScript class with constructor, static properties and methods, and instance properties and methods that correspond to the C++ class.
  2. When JavaScript code invokes the constructor, the constructor callback uses napi_wrap to wrap a new C++ instance in a JavaScript object, then returns the wrapper object.
  3. When JavaScript code invokes a method or property accessor on the class, the corresponding napi_callback C++ function is invoked. For an instance callback, napi_unwrap obtains the C++ instance that is the target of the call.

For wrapped objects it may be difficult to distinguish between a function called on a class prototype and a function called on an instance of a class. A common pattern used to address this problem is to save a persistent reference to the class constructor for later instanceof checks.

napi_value MyClass_constructor = NULL;
status = napi_get_reference_value(env, MyClass::es_constructor, &MyClass_constructor);
assert(napi_ok == status);
bool is_instance = false;
status = napi_instanceof(env, es_this, MyClass_constructor, &is_instance);
assert(napi_ok == status);
if (is_instance) {
  // napi_unwrap() ...
} else {
  // otherwise...
} 

The reference must be freed once it is no longer needed.

There are occasions where napi_instanceof() is insufficient for ensuring that a JavaScript object is a wrapper for a certain native type. This is the case especially when wrapped JavaScript objects are passed back into the addon via static methods rather than as the this value of prototype methods. In such cases there is a chance that they may be unwrapped incorrectly.

const myAddon = require('./build/Release/my_addon.node');

// `openDatabase()` returns a JavaScript object that wraps a native database
// handle.
const dbHandle = myAddon.openDatabase();

// `query()` returns a JavaScript object that wraps a native query handle.
const queryHandle = myAddon.query(dbHandle, 'Gimme ALL the things!');

// There is an accidental error in the line below. The first parameter to
// `myAddon.queryHasRecords()` should be the database handle (`dbHandle`), not
// the query handle (`query`), so the correct condition for the while-loop
// should be
//
// myAddon.queryHasRecords(dbHandle, queryHandle)
//
while (myAddon.queryHasRecords(queryHandle, dbHandle)) {
  // retrieve records
} 

In the above example myAddon.queryHasRecords() is a method that accepts two arguments. The first is a database handle and the second is a query handle. Internally, it unwraps the first argument and casts the resulting pointer to a native database handle. It then unwraps the second argument and casts the resulting pointer to a query handle. If the arguments are passed in the wrong order, the casts will work, however, there is a good chance that the underlying database operation will fail, or will even cause an invalid memory access.

To ensure that the pointer retrieved from the first argument is indeed a pointer to a database handle and, similarly, that the pointer retrieved from the second argument is indeed a pointer to a query handle, the implementation of queryHasRecords() has to perform a type validation. Retaining the JavaScript class constructor from which the database handle was instantiated and the constructor from which the query handle was instantiated in napi_refs can help, because napi_instanceof() can then be used to ensure that the instances passed into queryHashRecords() are indeed of the correct type.

Unfortunately, napi_instanceof() does not protect against prototype manipulation. For example, the prototype of the database handle instance can be set to the prototype of the constructor for query handle instances. In this case, the database handle instance can appear as a query handle instance, and it will pass the napi_instanceof() test for a query handle instance, while still containing a pointer to a database handle.

To this end, Node-API provides type-tagging capabilities.

A type tag is a 128-bit integer unique to the addon. Node-API provides the napi_type_tag structure for storing a type tag. When such a value is passed along with a JavaScript object or external stored in a napi_value to napi_type_tag_object(), the JavaScript object will be "marked" with the type tag. The "mark" is invisible on the JavaScript side. When a JavaScript object arrives into a native binding, napi_check_object_type_tag() can be used along with the original type tag to determine whether the JavaScript object was previously "marked" with the type tag. This creates a type-checking capability of a higher fidelity than napi_instanceof() can provide, because such type- tagging survives prototype manipulation and addon unloading/reloading.

Continuing the above example, the following skeleton addon implementation illustrates the use of napi_type_tag_object() and napi_check_object_type_tag().

// This value is the type tag for a database handle. The command
//
//   uuidgen | sed -r -e 's/-//g' -e 's/(.{16})(.*)/0x\1, 0x\2/'
//
// can be used to obtain the two values with which to initialize the structure.
static const napi_type_tag DatabaseHandleTypeTag = {
  0x1edf75a38336451d, 0xa5ed9ce2e4c00c38
};

// This value is the type tag for a query handle.
static const napi_type_tag QueryHandleTypeTag = {
  0x9c73317f9fad44a3, 0x93c3920bf3b0ad6a
};

static napi_value
openDatabase(napi_env env, napi_callback_info info) {
  napi_status status;
  napi_value result;

  // Perform the underlying action which results in a database handle.
  DatabaseHandle* dbHandle = open_database();

  // Create a new, empty JS object.
  status = napi_create_object(env, &result);
  if (status != napi_ok) return NULL;

  // Tag the object to indicate that it holds a pointer to a `DatabaseHandle`.
  status = napi_type_tag_object(env, result, &DatabaseHandleTypeTag);
  if (status != napi_ok) return NULL;

  // Store the pointer to the `DatabaseHandle` structure inside the JS object.
  status = napi_wrap(env, result, dbHandle, NULL, NULL, NULL);
  if (status != napi_ok) return NULL;

  return result;
}

// Later when we receive a JavaScript object purporting to be a database handle
// we can use `napi_check_object_type_tag()` to ensure that it is indeed such a
// handle.

static napi_value
query(napi_env env, napi_callback_info info) {
  napi_status status;
  size_t argc = 2;
  napi_value argv[2];
  bool is_db_handle;

  status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
  if (status != napi_ok) return NULL;

  // Check that the object passed as the first parameter has the previously
  // applied tag.
  status = napi_check_object_type_tag(env,
                                      argv[0],
                                      &DatabaseHandleTypeTag,
                                      &is_db_handle);
  if (status != napi_ok) return NULL;

  // Throw a `TypeError` if it doesn't.
  if (!is_db_handle) {
    // Throw a TypeError.
    return NULL;
  }
} 

napi_define_class#

napi_status napi_define_class(napi_env env,
                              const char* utf8name,
                              size_t length,
                              napi_callback constructor,
                              void* data,
                              size_t property_count,
                              const napi_property_descriptor* properties,
                              napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] utf8name: Name of the JavaScript constructor function. For clarity, it is recommended to use the C++ class name when wrapping a C++ class.
  • [in] length: The length of the utf8name in bytes, or NAPI_AUTO_LENGTH if it is null-terminated.
  • [in] constructor: Callback function that handles constructing instances of the class. When wrapping a C++ class, this method must be a static member with the napi_callback signature. A C++ class constructor cannot be used. napi_callback provides more details.
  • [in] data: Optional data to be passed to the constructor callback as the data property of the callback info.
  • [in] property_count: Number of items in the properties array argument.
  • [in] properties: Array of property descriptors describing static and instance data properties, accessors, and methods on the class See napi_property_descriptor.
  • [out] result: A napi_value representing the constructor function for the class.

Returns napi_ok if the API succeeded.

Defines a JavaScript class, including:

  • A JavaScript constructor function that has the class name. When wrapping a corresponding C++ class, the callback passed via constructor can be used to instantiate a new C++ class instance, which can then be placed inside the JavaScript object instance being constructed using napi_wrap.
  • Properties on the constructor function whose implementation can call corresponding static data properties, accessors, and methods of the C++ class (defined by property descriptors with the napi_static attribute).
  • Properties on the constructor function's prototype object. When wrapping a C++ class, non-static data properties, accessors, and methods of the C++ class can be called from the static functions given in the property descriptors without the napi_static attribute after retrieving the C++ class instance placed inside the JavaScript object instance by using napi_unwrap.

When wrapping a C++ class, the C++ constructor callback passed via constructor should be a static method on the class that calls the actual class constructor, then wraps the new C++ instance in a JavaScript object, and returns the wrapper object. See napi_wrap for details.

The JavaScript constructor function returned from napi_define_class is often saved and used later to construct new instances of the class from native code, and/or to check whether provided values are instances of the class. In that case, to prevent the function value from being garbage-collected, a strong persistent reference to it can be created using napi_create_reference, ensuring that the reference count is kept >= 1.

Any non-NULL data which is passed to this API via the data parameter or via the data field of the napi_property_descriptor array items can be associated with the resulting JavaScript constructor (which is returned in the result parameter) and freed whenever the class is garbage-collected by passing both the JavaScript function and the data to napi_add_finalizer.

napi_wrap#

napi_status napi_wrap(napi_env env,
                      napi_value js_object,
                      void* native_object,
                      napi_finalize finalize_cb,
                      void* finalize_hint,
                      napi_ref* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] js_object: The JavaScript object that will be the wrapper for the native object.
  • [in] native_object: The native instance that will be wrapped in the JavaScript object.
  • [in] finalize_cb: Optional native callback that can be used to free the native instance when the JavaScript object has been garbage-collected. napi_finalize provides more details.
  • [in] finalize_hint: Optional contextual hint that is passed to the finalize callback.
  • [out] result: Optional reference to the wrapped object.

Returns napi_ok if the API succeeded.

Wraps a native instance in a JavaScript object. The native instance can be retrieved later using napi_unwrap().

When JavaScript code invokes a constructor for a class that was defined using napi_define_class(), the napi_callback for the constructor is invoked. After constructing an instance of the native class, the callback must then call napi_wrap() to wrap the newly constructed instance in the already-created JavaScript object that is the this argument to the constructor callback. (That this object was created from the constructor function's prototype, so it already has definitions of all the instance properties and methods.)

Typically when wrapping a class instance, a finalize callback should be provided that simply deletes the native instance that is received as the data argument to the finalize callback.

The optional returned reference is initially a weak reference, meaning it has a reference count of 0. Typically this reference count would be incremented temporarily during async operations that require the instance to remain valid.

Caution: The optional returned reference (if obtained) should be deleted via napi_delete_reference ONLY in response to the finalize callback invocation. If it is deleted before then, then the finalize callback may never be invoked. Therefore, when obtaining a reference a finalize callback is also required in order to enable correct disposal of the reference.

Finalizer callbacks may be deferred, leaving a window where the object has been garbage collected (and the weak reference is invalid) but the finalizer hasn't been called yet. When using napi_get_reference_value() on weak references returned by napi_wrap(), you should still handle an empty result.

Calling napi_wrap() a second time on an object will return an error. To associate another native instance with the object, use napi_remove_wrap() first.

napi_unwrap#

napi_status napi_unwrap(napi_env env,
                        napi_value js_object,
                        void** result); 
  • [in] env: The environment that the API is invoked under.
  • [in] js_object: The object associated with the native instance.
  • [out] result: Pointer to the wrapped native instance.

Returns napi_ok if the API succeeded.

Retrieves a native instance that was previously wrapped in a JavaScript object using napi_wrap().

When JavaScript code invokes a method or property accessor on the class, the corresponding napi_callback is invoked. If the callback is for an instance method or accessor, then the this argument to the callback is the wrapper object; the wrapped C++ instance that is the target of the call can be obtained then by calling napi_unwrap() on the wrapper object.

napi_remove_wrap#

napi_status napi_remove_wrap(napi_env env,
                             napi_value js_object,
                             void** result); 
  • [in] env: The environment that the API is invoked under.
  • [in] js_object: The object associated with the native instance.
  • [out] result: Pointer to the wrapped native instance.

Returns napi_ok if the API succeeded.

Retrieves a native instance that was previously wrapped in the JavaScript object js_object using napi_wrap() and removes the wrapping. If a finalize callback was associated with the wrapping, it will no longer be called when the JavaScript object becomes garbage-collected.

napi_type_tag_object#

napi_status napi_type_tag_object(napi_env env,
                                 napi_value js_object,
                                 const napi_type_tag* type_tag); 
  • [in] env: The environment that the API is invoked under.
  • [in] js_object: The JavaScript object or external to be marked.
  • [in] type_tag: The tag with which the object is to be marked.

Returns napi_ok if the API succeeded.

Associates the value of the type_tag pointer with the JavaScript object or external. napi_check_object_type_tag() can then be used to compare the tag that was attached to the object with one owned by the addon to ensure that the object has the right type.

If the object already has an associated type tag, this API will return napi_invalid_arg.

napi_check_object_type_tag#

napi_status napi_check_object_type_tag(napi_env env,
                                       napi_value js_object,
                                       const napi_type_tag* type_tag,
                                       bool* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] js_object: The JavaScript object or external whose type tag to examine.
  • [in] type_tag: The tag with which to compare any tag found on the object.
  • [out] result: Whether the type tag given matched the type tag on the object. false is also returned if no type tag was found on the object.

Returns napi_ok if the API succeeded.

Compares the pointer given as type_tag with any that can be found on js_object. If no tag is found on js_object or, if a tag is found but it does not match type_tag, then result is set to false. If a tag is found and it matches type_tag, then result is set to true.

napi_add_finalizer#

napi_status napi_add_finalizer(napi_env env,
                               napi_value js_object,
                               void* finalize_data,
                               node_api_basic_finalize finalize_cb,
                               void* finalize_hint,
                               napi_ref* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] js_object: The JavaScript object to which the native data will be attached.
  • [in] finalize_data: Optional data to be passed to finalize_cb.
  • [in] finalize_cb: Native callback that will be used to free the native data when the JavaScript object has been garbage-collected. napi_finalize provides more details.
  • [in] finalize_hint: Optional contextual hint that is passed to the finalize callback.
  • [out] result: Optional reference to the JavaScript object.

Returns napi_ok if the API succeeded.

Adds a napi_finalize callback which will be called when the JavaScript object in js_object has been garbage-collected.

This API can be called multiple times on a single JavaScript object.

Caution: The optional returned reference (if obtained) should be deleted via napi_delete_reference ONLY in response to the finalize callback invocation. If it is deleted before then, then the finalize callback may never be invoked. Therefore, when obtaining a reference a finalize callback is also required in order to enable correct disposal of the reference.

node_api_post_finalizer#

Stability: 1 - Experimental

napi_status node_api_post_finalizer(node_api_basic_env env,
                                    napi_finalize finalize_cb,
                                    void* finalize_data,
                                    void* finalize_hint); 
  • [in] env: The environment that the API is invoked under.
  • [in] finalize_cb: Native callback that will be used to free the native data when the JavaScript object has been garbage-collected. napi_finalize provides more details.
  • [in] finalize_data: Optional data to be passed to finalize_cb.
  • [in] finalize_hint: Optional contextual hint that is passed to the finalize callback.

Returns napi_ok if the API succeeded.

Schedules a napi_finalize callback to be called asynchronously in the event loop.

Normally, finalizers are called while the GC (garbage collector) collects objects. At that point calling any Node-API that may cause changes in the GC state will be disabled and will crash Node.js.

node_api_post_finalizer helps to work around this limitation by allowing the add-on to defer calls to such Node-APIs to a point in time outside of the GC finalization.

Simple asynchronous operations#

Addon modules often need to leverage async helpers from libuv as part of their implementation. This allows them to schedule work to be executed asynchronously so that their methods can return in advance of the work being completed. This allows them to avoid blocking overall execution of the Node.js application.

Node-API provides an ABI-stable interface for these supporting functions which covers the most common asynchronous use cases.

Node-API defines the napi_async_work structure which is used to manage asynchronous workers. Instances are created/deleted with napi_create_async_work and napi_delete_async_work.

The execute and complete callbacks are functions that will be invoked when the executor is ready to execute and when it completes its task respectively.

The execute function should avoid making any Node-API calls that could result in the execution of JavaScript or interaction with JavaScript objects. Most often, any code that needs to make Node-API calls should be made in complete callback instead. Avoid using the napi_env parameter in the execute callback as it will likely execute JavaScript.

These functions implement the following interfaces:

typedef void (*napi_async_execute_callback)(napi_env env,
                                            void* data);
typedef void (*napi_async_complete_callback)(napi_env env,
                                             napi_status status,
                                             void* data); 

When these methods are invoked, the data parameter passed will be the addon-provided void* data that was passed into the napi_create_async_work call.

Once created the async worker can be queued for execution using the napi_queue_async_work function:

napi_status napi_queue_async_work(node_api_basic_env env,
                                  napi_async_work work); 

napi_cancel_async_work can be used if the work needs to be cancelled before the work has started execution.

After calling napi_cancel_async_work, the complete callback will be invoked with a status value of napi_cancelled. The work should not be deleted before the complete callback invocation, even when it was cancelled.

napi_create_async_work#

napi_status napi_create_async_work(napi_env env,
                                   napi_value async_resource,
                                   napi_value async_resource_name,
                                   napi_async_execute_callback execute,
                                   napi_async_complete_callback complete,
                                   void* data,
                                   napi_async_work* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] async_resource: An optional object associated with the async work that will be passed to possible async_hooks init hooks.
  • [in] async_resource_name: Identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API.
  • [in] execute: The native function which should be called to execute the logic asynchronously. The given function is called from a worker pool thread and can execute in parallel with the main event loop thread.
  • [in] complete: The native function which will be called when the asynchronous logic is completed or is cancelled. The given function is called from the main event loop thread. napi_async_complete_callback provides more details.
  • [in] data: User-provided data context. This will be passed back into the execute and complete functions.
  • [out] result: napi_async_work* which is the handle to the newly created async work.

Returns napi_ok if the API succeeded.

This API allocates a work object that is used to execute logic asynchronously. It should be freed using napi_delete_async_work once the work is no longer required.

async_resource_name should be a null-terminated, UTF-8-encoded string.

The async_resource_name identifier is provided by the user and should be representative of the type of async work being performed. It is also recommended to apply namespacing to the identifier, e.g. by including the module name. See the async_hooks documentation for more information.

napi_delete_async_work#

napi_status napi_delete_async_work(napi_env env,
                                   napi_async_work work); 
  • [in] env: The environment that the API is invoked under.
  • [in] work: The handle returned by the call to napi_create_async_work.

Returns napi_ok if the API succeeded.

This API frees a previously allocated work object.

This API can be called even if there is a pending JavaScript exception.

napi_queue_async_work#

napi_status napi_queue_async_work(node_api_basic_env env,
                                  napi_async_work work); 
  • [in] env: The environment that the API is invoked under.
  • [in] work: The handle returned by the call to napi_create_async_work.

Returns napi_ok if the API succeeded.

This API requests that the previously allocated work be scheduled for execution. Once it returns successfully, this API must not be called again with the same napi_async_work item or the result will be undefined.

napi_cancel_async_work#

napi_status napi_cancel_async_work(node_api_basic_env env,
                                   napi_async_work work); 
  • [in] env: The environment that the API is invoked under.
  • [in] work: The handle returned by the call to napi_create_async_work.

Returns napi_ok if the API succeeded.

This API cancels queued work if it has not yet been started. If it has already started executing, it cannot be cancelled and napi_generic_failure will be returned. If successful, the complete callback will be invoked with a status value of napi_cancelled. The work should not be deleted before the complete callback invocation, even if it has been successfully cancelled.

This API can be called even if there is a pending JavaScript exception.

Custom asynchronous operations#

The simple asynchronous work APIs above may not be appropriate for every scenario. When using any other asynchronous mechanism, the following APIs are necessary to ensure an asynchronous operation is properly tracked by the runtime.

napi_async_init#

napi_status napi_async_init(napi_env env,
                            napi_value async_resource,
                            napi_value async_resource_name,
                            napi_async_context* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] async_resource: Object associated with the async work that will be passed to possible async_hooks init hooks and can be accessed by async_hooks.executionAsyncResource().
  • [in] async_resource_name: Identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API.
  • [out] result: The initialized async context.

Returns napi_ok if the API succeeded.

The async_resource object needs to be kept alive until napi_async_destroy to keep async_hooks related API acts correctly. In order to retain ABI compatibility with previous versions, napi_async_contexts are not maintaining the strong reference to the async_resource objects to avoid introducing causing memory leaks. However, if the async_resource is garbage collected by JavaScript engine before the napi_async_context was destroyed by napi_async_destroy, calling napi_async_context related APIs like napi_open_callback_scope and napi_make_callback can cause problems like loss of async context when using the AsyncLocalStorage API.

In order to retain ABI compatibility with previous versions, passing NULL for async_resource does not result in an error. However, this is not recommended as this will result in undesirable behavior with async_hooks init hooks and async_hooks.executionAsyncResource() as the resource is now required by the underlying async_hooks implementation in order to provide the linkage between async callbacks.

napi_async_destroy#

napi_status napi_async_destroy(napi_env env,
                               napi_async_context async_context); 
  • [in] env: The environment that the API is invoked under.
  • [in] async_context: The async context to be destroyed.

Returns napi_ok if the API succeeded.

This API can be called even if there is a pending JavaScript exception.

napi_make_callback#

NAPI_EXTERN napi_status napi_make_callback(napi_env env,
                                           napi_async_context async_context,
                                           napi_value recv,
                                           napi_value func,
                                           size_t argc,
                                           const napi_value* argv,
                                           napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] async_context: Context for the async operation that is invoking the callback. This should normally be a value previously obtained from napi_async_init. In order to retain ABI compatibility with previous versions, passing NULL for async_context does not result in an error. However, this results in incorrect operation of async hooks. Potential issues include loss of async context when using the AsyncLocalStorage API.
  • [in] recv: The this value passed to the called function.
  • [in] func: napi_value representing the JavaScript function to be invoked.
  • [in] argc: The count of elements in the argv array.
  • [in] argv: Array of JavaScript values as napi_value representing the arguments to the function. If argc is zero this parameter may be omitted by passing in NULL.
  • [out] result: napi_value representing the JavaScript object returned.

Returns napi_ok if the API succeeded.

This method allows a JavaScript function object to be called from a native add-on. This API is similar to napi_call_function. However, it is used to call from native code back into JavaScript after returning from an async operation (when there is no other script on the stack). It is a fairly simple wrapper around node::MakeCallback.

Note it is not necessary to use napi_make_callback from within a napi_async_complete_callback; in that situation the callback's async context has already been set up, so a direct call to napi_call_function is sufficient and appropriate. Use of the napi_make_callback function may be required when implementing custom async behavior that does not use napi_create_async_work.

Any process.nextTicks or Promises scheduled on the microtask queue by JavaScript during the callback are ran before returning back to C/C++.

napi_open_callback_scope#

NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env,
                                                 napi_value resource_object,
                                                 napi_async_context context,
                                                 napi_callback_scope* result) 
  • [in] env: The environment that the API is invoked under.
  • [in] resource_object: An object associated with the async work that will be passed to possible async_hooks init hooks. This parameter has been deprecated and is ignored at runtime. Use the async_resource parameter in napi_async_init instead.
  • [in] context: Context for the async operation that is invoking the callback. This should be a value previously obtained from napi_async_init.
  • [out] result: The newly created scope.

There are cases (for example, resolving promises) where it is necessary to have the equivalent of the scope associated with a callback in place when making certain Node-API calls. If there is no other script on the stack the napi_open_callback_scope and napi_close_callback_scope functions can be used to open/close the required scope.

napi_close_callback_scope#

NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env,
                                                  napi_callback_scope scope) 
  • [in] env: The environment that the API is invoked under.
  • [in] scope: The scope to be closed.

This API can be called even if there is a pending JavaScript exception.

Version management#

napi_get_node_version#

typedef struct {
  uint32_t major;
  uint32_t minor;
  uint32_t patch;
  const char* release;
} napi_node_version;

napi_status napi_get_node_version(node_api_basic_env env,
                                  const napi_node_version** version); 
  • [in] env: The environment that the API is invoked under.
  • [out] version: A pointer to version information for Node.js itself.

Returns napi_ok if the API succeeded.

This function fills the version struct with the major, minor, and patch version of Node.js that is currently running, and the release field with the value of process.release.name.

The returned buffer is statically allocated and does not need to be freed.

napi_get_version#

napi_status napi_get_version(node_api_basic_env env,
                             uint32_t* result); 
  • [in] env: The environment that the API is invoked under.
  • [out] result: The highest version of Node-API supported.

Returns napi_ok if the API succeeded.

This API returns the highest Node-API version supported by the Node.js runtime. Node-API is planned to be additive such that newer releases of Node.js may support additional API functions. In order to allow an addon to use a newer function when running with versions of Node.js that support it, while providing fallback behavior when running with Node.js versions that don't support it:

  • Call napi_get_version() to determine if the API is available.
  • If available, dynamically load a pointer to the function using uv_dlsym().
  • Use the dynamically loaded pointer to invoke the function.
  • If the function is not available, provide an alternate implementation that does not use the function.

Memory management#

napi_adjust_external_memory#

NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_basic_env env,
                                                    int64_t change_in_bytes,
                                                    int64_t* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] change_in_bytes: The change in externally allocated memory that is kept alive by JavaScript objects.
  • [out] result: The adjusted value. This value should reflect the total amount of external memory with the given change_in_bytes included. The absolute value of the returned value should not be depended on. For example, implementations may use a single counter for all addons, or a counter for each addon.

Returns napi_ok if the API succeeded.

This function gives the runtime an indication of the amount of externally allocated memory that is kept alive by JavaScript objects (i.e. a JavaScript object that points to its own memory allocated by a native addon). Registering externally allocated memory may, but is not guaranteed to, trigger global garbage collections more often than it would otherwise.

This function is expected to be called in a manner such that an addon does not decrease the external memory more than it has increased the external memory.

Promises#

Node-API provides facilities for creating Promise objects as described in Section 25.4 of the ECMA specification. It implements promises as a pair of objects. When a promise is created by napi_create_promise(), a "deferred" object is created and returned alongside the Promise. The deferred object is bound to the created Promise and is the only means to resolve or reject the Promise using napi_resolve_deferred() or napi_reject_deferred(). The deferred object that is created by napi_create_promise() is freed by napi_resolve_deferred() or napi_reject_deferred(). The Promise object may be returned to JavaScript where it can be used in the usual fashion.

For example, to create a promise and pass it to an asynchronous worker:

napi_deferred deferred;
napi_value promise;
napi_status status;

// Create the promise.
status = napi_create_promise(env, &deferred, &promise);
if (status != napi_ok) return NULL;

// Pass the deferred to a function that performs an asynchronous action.
do_something_asynchronous(deferred);

// Return the promise to JS
return promise; 

The above function do_something_asynchronous() would perform its asynchronous action and then it would resolve or reject the deferred, thereby concluding the promise and freeing the deferred:

napi_deferred deferred;
napi_value undefined;
napi_status status;

// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;

// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (asynchronous_action_succeeded) {
  status = napi_resolve_deferred(env, deferred, undefined);
} else {
  status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;

// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL; 

napi_create_promise#

napi_status napi_create_promise(napi_env env,
                                napi_deferred* deferred,
                                napi_value* promise); 
  • [in] env: The environment that the API is invoked under.
  • [out] deferred: A newly created deferred object which can later be passed to napi_resolve_deferred() or napi_reject_deferred() to resolve resp. reject the associated promise.
  • [out] promise: The JavaScript promise associated with the deferred object.

Returns napi_ok if the API succeeded.

This API creates a deferred object and a JavaScript promise.

napi_resolve_deferred#

napi_status napi_resolve_deferred(napi_env env,
                                  napi_deferred deferred,
                                  napi_value resolution); 
  • [in] env: The environment that the API is invoked under.
  • [in] deferred: The deferred object whose associated promise to resolve.
  • [in] resolution: The value with which to resolve the promise.

This API resolves a JavaScript promise by way of the deferred object with which it is associated. Thus, it can only be used to resolve JavaScript promises for which the corresponding deferred object is available. This effectively means that the promise must have been created using napi_create_promise() and the deferred object returned from that call must have been retained in order to be passed to this API.

The deferred object is freed upon successful completion.

napi_reject_deferred#

napi_status napi_reject_deferred(napi_env env,
                                 napi_deferred deferred,
                                 napi_value rejection); 
  • [in] env: The environment that the API is invoked under.
  • [in] deferred: The deferred object whose associated promise to resolve.
  • [in] rejection: The value with which to reject the promise.

This API rejects a JavaScript promise by way of the deferred object with which it is associated. Thus, it can only be used to reject JavaScript promises for which the corresponding deferred object is available. This effectively means that the promise must have been created using napi_create_promise() and the deferred object returned from that call must have been retained in order to be passed to this API.

The deferred object is freed upon successful completion.

napi_is_promise#

napi_status napi_is_promise(napi_env env,
                            napi_value value,
                            bool* is_promise); 
  • [in] env: The environment that the API is invoked under.
  • [in] value: The value to examine
  • [out] is_promise: Flag indicating whether promise is a native promise object (that is, a promise object created by the underlying engine).

Script execution#

Node-API provides an API for executing a string containing JavaScript using the underlying JavaScript engine.

napi_run_script#

NAPI_EXTERN napi_status napi_run_script(napi_env env,
                                        napi_value script,
                                        napi_value* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] script: A JavaScript string containing the script to execute.
  • [out] result: The value resulting from having executed the script.

This function executes a string of JavaScript code and returns its result with the following caveats:

  • Unlike eval, this function does not allow the script to access the current lexical scope, and therefore also does not allow to access the module scope, meaning that pseudo-globals such as require will not be available.
  • The script can access the global scope. Function and var declarations in the script will be added to the global object. Variable declarations made using let and const will be visible globally, but will not be added to the global object.
  • The value of this is global within the script.

libuv event loop#

Node-API provides a function for getting the current event loop associated with a specific napi_env.

napi_get_uv_event_loop#

NAPI_EXTERN napi_status napi_get_uv_event_loop(node_api_basic_env env,
                                               struct uv_loop_s** loop); 
  • [in] env: The environment that the API is invoked under.
  • [out] loop: The current libuv loop instance.

Note: While libuv has been relatively stable over time, it does not provide an ABI stability guarantee. Use of this function should be avoided. Its use may result in an addon that does not work across Node.js versions. asynchronous-thread-safe-function-calls are an alternative for many use cases.

Asynchronous thread-safe function calls#

JavaScript functions can normally only be called from a native addon's main thread. If an addon creates additional threads, then Node-API functions that require a napi_env, napi_value, or napi_ref must not be called from those threads.

When an addon has additional threads and JavaScript functions need to be invoked based on the processing completed by those threads, those threads must communicate with the addon's main thread so that the main thread can invoke the JavaScript function on their behalf. The thread-safe function APIs provide an easy way to do this.

These APIs provide the type napi_threadsafe_function as well as APIs to create, destroy, and call objects of this type. napi_create_threadsafe_function() creates a persistent reference to a napi_value that holds a JavaScript function which can be called from multiple threads. The calls happen asynchronously. This means that values with which the JavaScript callback is to be called will be placed in a queue, and, for each value in the queue, a call will eventually be made to the JavaScript function.

Upon creation of a napi_threadsafe_function a napi_finalize callback can be provided. This callback will be invoked on the main thread when the thread-safe function is about to be destroyed. It receives the context and the finalize data given during construction, and provides an opportunity for cleaning up after the threads e.g. by calling uv_thread_join(). Aside from the main loop thread, no threads should be using the thread-safe function after the finalize callback completes.

The context given during the call to napi_create_threadsafe_function() can be retrieved from any thread with a call to napi_get_threadsafe_function_context().

Calling a thread-safe function#

napi_call_threadsafe_function() can be used for initiating a call into JavaScript. napi_call_threadsafe_function() accepts a parameter which controls whether the API behaves blockingly. If set to napi_tsfn_nonblocking, the API behaves non-blockingly, returning napi_queue_full if the queue was full, preventing data from being successfully added to the queue. If set to napi_tsfn_blocking, the API blocks until space becomes available in the queue. napi_call_threadsafe_function() never blocks if the thread-safe function was created with a maximum queue size of 0.

napi_call_threadsafe_function() should not be called with napi_tsfn_blocking from a JavaScript thread, because, if the queue is full, it may cause the JavaScript thread to deadlock.

The actual call into JavaScript is controlled by the callback given via the call_js_cb parameter. call_js_cb is invoked on the main thread once for each value that was placed into the queue by a successful call to napi_call_threadsafe_function(). If such a callback is not given, a default callback will be used, and the resulting JavaScript call will have no arguments. The call_js_cb callback receives the JavaScript function to call as a napi_value in its parameters, as well as the void* context pointer used when creating the napi_threadsafe_function, and the next data pointer that was created by one of the secondary threads. The callback can then use an API such as napi_call_function() to call into JavaScript.

The callback may also be invoked with env and call_js_cb both set to NULL to indicate that calls into JavaScript are no longer possible, while items remain in the queue that may need to be freed. This normally occurs when the Node.js process exits while there is a thread-safe function still active.

It is not necessary to call into JavaScript via napi_make_callback() because Node-API runs call_js_cb in a context appropriate for callbacks.

Zero or more queued items may be invoked in each tick of the event loop. Applications should not depend on a specific behavior other than progress in invoking callbacks will be made and events will be invoked as time moves forward.

Reference counting of thread-safe functions#

Threads can be added to and removed from a napi_threadsafe_function object during its existence. Thus, in addition to specifying an initial number of threads upon creation, napi_acquire_threadsafe_function can be called to indicate that a new thread will start making use of the thread-safe function. Similarly, napi_release_threadsafe_function can be called to indicate that an existing thread will stop making use of the thread-safe function.

napi_threadsafe_function objects are destroyed when every thread which uses the object has called napi_release_threadsafe_function() or has received a return status of napi_closing in response to a call to napi_call_threadsafe_function. The queue is emptied before the napi_threadsafe_function is destroyed. napi_release_threadsafe_function() should be the last API call made in conjunction with a given napi_threadsafe_function, because after the call completes, there is no guarantee that the napi_threadsafe_function is still allocated. For the same reason, do not use a thread-safe function after receiving a return value of napi_closing in response to a call to napi_call_threadsafe_function. Data associated with the napi_threadsafe_function can be freed in its napi_finalize callback which was passed to napi_create_threadsafe_function(). The parameter initial_thread_count of napi_create_threadsafe_function marks the initial number of acquisitions of the thread-safe functions, instead of calling napi_acquire_threadsafe_function multiple times at creation.

Once the number of threads making use of a napi_threadsafe_function reaches zero, no further threads can start making use of it by calling napi_acquire_threadsafe_function(). In fact, all subsequent API calls associated with it, except napi_release_threadsafe_function(), will return an error value of napi_closing.

The thread-safe function can be "aborted" by giving a value of napi_tsfn_abort to napi_release_threadsafe_function(). This will cause all subsequent APIs associated with the thread-safe function except napi_release_threadsafe_function() to return napi_closing even before its reference count reaches zero. In particular, napi_call_threadsafe_function() will return napi_closing, thus informing the threads that it is no longer possible to make asynchronous calls to the thread-safe function. This can be used as a criterion for terminating the thread. Upon receiving a return value of napi_closing from napi_call_threadsafe_function() a thread must not use the thread-safe function anymore because it is no longer guaranteed to be allocated.

Deciding whether to keep the process running#

Similarly to libuv handles, thread-safe functions can be "referenced" and "unreferenced". A "referenced" thread-safe function will cause the event loop on the thread on which it is created to remain alive until the thread-safe function is destroyed. In contrast, an "unreferenced" thread-safe function will not prevent the event loop from exiting. The APIs napi_ref_threadsafe_function and napi_unref_threadsafe_function exist for this purpose.

Neither does napi_unref_threadsafe_function mark the thread-safe functions as able to be destroyed nor does napi_ref_threadsafe_function prevent it from being destroyed.

napi_create_threadsafe_function#

NAPI_EXTERN napi_status
napi_create_threadsafe_function(napi_env env,
                                napi_value func,
                                napi_value async_resource,
                                napi_value async_resource_name,
                                size_t max_queue_size,
                                size_t initial_thread_count,
                                void* thread_finalize_data,
                                napi_finalize thread_finalize_cb,
                                void* context,
                                napi_threadsafe_function_call_js call_js_cb,
                                napi_threadsafe_function* result); 
  • [in] env: The environment that the API is invoked under.
  • [in] func: An optional JavaScript function to call from another thread. It must be provided if NULL is passed to call_js_cb.
  • [in] async_resource: An optional object associated with the async work that will be passed to possible async_hooks init hooks.
  • [in] async_resource_name: A JavaScript string to provide an identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API.
  • [in] max_queue_size: Maximum size of the queue. 0 for no limit.
  • [in] initial_thread_count: The initial number of acquisitions, i.e. the initial number of threads, including the main thread, which will be making use of this function.
  • [in] thread_finalize_data: Optional data to be passed to thread_finalize_cb.
  • [in] thread_finalize_cb: Optional function to call when the napi_threadsafe_function is being destroyed.
  • [in] context: Optional data to attach to the resulting napi_threadsafe_function.
  • [in] call_js_cb: Optional callback which calls the JavaScript function in response to a call on a different thread. This callback will be called on the main thread. If not given, the JavaScript function will be called with no parameters and with undefined as its this value. napi_threadsafe_function_call_js provides more details.
  • [out] result: The asynchronous thread-safe JavaScript function.

Change History:

  • Version 10 (NAPI_VERSION is defined as 10 or higher):

    Uncaught exceptions thrown in call_js_cb are handled with the 'uncaughtException' event, instead of being ignored.

napi_get_threadsafe_function_context#

NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
                                     void** result); 
  • [in] func: The thread-safe function for which to retrieve the context.
  • [out] result: The location where to store the context.

This API may be called from any thread which makes use of func.

napi_call_threadsafe_function#

NAPI_EXTERN napi_status
napi_call_threadsafe_function(napi_threadsafe_function func,
                              void* data,
                              napi_threadsafe_function_call_mode is_blocking); 
  • [in] func: The asynchronous thread-safe JavaScript function to invoke.
  • [in] data: Data to send into JavaScript via the callback call_js_cb provided during the creation of the thread-safe JavaScript function.
  • [in] is_blocking: Flag whose value can be either napi_tsfn_blocking to indicate that the call should block if the queue is full or napi_tsfn_nonblocking to indicate that the call should return immediately with a status of napi_queue_full whenever the queue is full.

This API should not be called with napi_tsfn_blocking from a JavaScript thread, because, if the queue is full, it may cause the JavaScript thread to deadlock.

This API will return napi_closing if napi_release_threadsafe_function() was called with abort set to napi_tsfn_abort from any thread. The value is only added to the queue if the API returns napi_ok.

This API may be called from any thread which makes use of func.

napi_acquire_threadsafe_function#

NAPI_EXTERN napi_status
napi_acquire_threadsafe_function(napi_threadsafe_function func); 
  • [in] func: The asynchronous thread-safe JavaScript function to start making use of.

A thread should call this API before passing func to any other thread-safe function APIs to indicate that it will be making use of func. This prevents func from being destroyed when all other threads have stopped making use of it.

This API may be called from any thread which will start making use of func.

napi_release_threadsafe_function#

NAPI_EXTERN napi_status
napi_release_threadsafe_function(napi_threadsafe_function func,
                                 napi_threadsafe_function_release_mode mode); 
  • [in] func: The asynchronous thread-safe JavaScript function whose reference count to decrement.
  • [in] mode: Flag whose value can be either napi_tsfn_release to indicate that the current thread will make no further calls to the thread-safe function, or napi_tsfn_abort to indicate that in addition to the current thread, no other thread should make any further calls to the thread-safe function. If set to napi_tsfn_abort, further calls to napi_call_threadsafe_function() will return napi_closing, and no further values will be placed in the queue.

A thread should call this API when it stops making use of func. Passing func to any thread-safe APIs after having called this API has undefined results, as func may have been destroyed.

This API may be called from any thread which will stop making use of func.

napi_ref_threadsafe_function#

NAPI_EXTERN napi_status
napi_ref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function func); 
  • [in] env: The environment that the API is invoked under.
  • [in] func: The thread-safe function to reference.

This API is used to indicate that the event loop running on the main thread should not exit until func has been destroyed. Similar to uv_ref it is also idempotent.

Neither does napi_unref_threadsafe_function mark the thread-safe functions as able to be destroyed nor does napi_ref_threadsafe_function prevent it from being destroyed. napi_acquire_threadsafe_function and napi_release_threadsafe_function are available for that purpose.

This API may only be called from the main thread.

napi_unref_threadsafe_function#

NAPI_EXTERN napi_status
napi_unref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function func); 
  • [in] env: The environment that the API is invoked under.
  • [in] func: The thread-safe function to unreference.

This API is used to indicate that the event loop running on the main thread may exit before func is destroyed. Similar to uv_unref it is also idempotent.

This API may only be called from the main thread.

Miscellaneous utilities#

node_api_get_module_file_name#

NAPI_EXTERN napi_status
node_api_get_module_file_name(node_api_basic_env env, const char** result);
 
  • [in] env: The environment that the API is invoked under.
  • [out] result: A URL containing the absolute path of the location from which the add-on was loaded. For a file on the local file system it will start with file://. The string is null-terminated and owned by env and must thus not be modified or freed.

result may be an empty string if the add-on loading process fails to establish the add-on's file name during loading.

C++ embedder API#

Node.js provides a number of C++ APIs that can be used to execute JavaScript in a Node.js environment from other C++ software.

The documentation for these APIs can be found in src/node.h in the Node.js source tree. In addition to the APIs exposed by Node.js, some required concepts are provided by the V8 embedder API.

Because using Node.js as an embedded library is different from writing code that is executed by Node.js, breaking changes do not follow typical Node.js deprecation policy and may occur on each semver-major release without prior warning.

Example embedding application#

The following sections will provide an overview over how to use these APIs to create an application from scratch that will perform the equivalent of node -e <code>, i.e. that will take a piece of JavaScript and run it in a Node.js-specific environment.

The full code can be found in the Node.js source tree.

Setting up a per-process state#

Node.js requires some per-process state management in order to run:

  • Arguments parsing for Node.js CLI options,
  • V8 per-process requirements, such as a v8::Platform instance.

The following example shows how these can be set up. Some class names are from the node and v8 C++ namespaces, respectively.

int main(int argc, char** argv) {
  argv = uv_setup_args(argc, argv);
  std::vector<std::string> args(argv, argv + argc);
  // Parse Node.js CLI options, and print any errors that have occurred while
  // trying to parse them.
  std::unique_ptr<node::InitializationResult> result =
      node::InitializeOncePerProcess(args, {
        node::ProcessInitializationFlags::kNoInitializeV8,
        node::ProcessInitializationFlags::kNoInitializeNodeV8Platform
      });

  for (const std::string& error : result->errors())
    fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str());
  if (result->early_return() != 0) {
    return result->exit_code();
  }

  // Create a v8::Platform instance. `MultiIsolatePlatform::Create()` is a way
  // to create a v8::Platform instance that Node.js can use when creating
  // Worker threads. When no `MultiIsolatePlatform` instance is present,
  // Worker threads are disabled.
  std::unique_ptr<MultiIsolatePlatform> platform =
      MultiIsolatePlatform::Create(4);
  V8::InitializePlatform(platform.get());
  V8::Initialize();

  // See below for the contents of this function.
  int ret = RunNodeInstance(
      platform.get(), result->args(), result->exec_args());

  V8::Dispose();
  V8::DisposePlatform();

  node::TearDownOncePerProcess();
  return ret;
} 

Setting up a per-instance state#

Node.js has a concept of a “Node.js instance”, that is commonly being referred to as node::Environment. Each node::Environment is associated with:

  • Exactly one v8::Isolate, i.e. one JS Engine instance,
  • Exactly one uv_loop_t, i.e. one event loop,
  • A number of v8::Contexts, but exactly one main v8::Context, and
  • One node::IsolateData instance that contains information that could be shared by multiple node::Environments. The embedder should make sure that node::IsolateData is shared only among node::Environments that use the same v8::Isolate, Node.js does not perform this check.

In order to set up a v8::Isolate, an v8::ArrayBuffer::Allocator needs to be provided. One possible choice is the default Node.js allocator, which can be created through node::ArrayBufferAllocator::Create(). Using the Node.js allocator allows minor performance optimizations when addons use the Node.js C++ Buffer API, and is required in order to track ArrayBuffer memory in process.memoryUsage().

Additionally, each v8::Isolate that is used for a Node.js instance needs to be registered and unregistered with the MultiIsolatePlatform instance, if one is being used, in order for the platform to know which event loop to use for tasks scheduled by the v8::Isolate.

The node::NewIsolate() helper function creates a v8::Isolate, sets it up with some Node.js-specific hooks (e.g. the Node.js error handler), and registers it with the platform automatically.

int RunNodeInstance(MultiIsolatePlatform* platform,
                    const std::vector<std::string>& args,
                    const std::vector<std::string>& exec_args) {
  int exit_code = 0;

  // Setup up a libuv event loop, v8::Isolate, and Node.js Environment.
  std::vector<std::string> errors;
  std::unique_ptr<CommonEnvironmentSetup> setup =
      CommonEnvironmentSetup::Create(platform, &errors, args, exec_args);
  if (!setup) {
    for (const std::string& err : errors)
      fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str());
    return 1;
  }

  Isolate* isolate = setup->isolate();
  Environment* env = setup->env();

  {
    Locker locker(isolate);
    Isolate::Scope isolate_scope(isolate);
    HandleScope handle_scope(isolate);
    // The v8::Context needs to be entered when node::CreateEnvironment() and
    // node::LoadEnvironment() are being called.
    Context::Scope context_scope(setup->context());

    // Set up the Node.js instance for execution, and run code inside of it.
    // There is also a variant that takes a callback and provides it with
    // the `require` and `process` objects, so that it can manually compile
    // and run scripts as needed.
    // The `require` function inside this script does *not* access the file
    // system, and can only load built-in Node.js modules.
    // `module.createRequire()` is being used to create one that is able to
    // load files from the disk, and uses the standard CommonJS file loader
    // instead of the internal-only `require` function.
    MaybeLocal<Value> loadenv_ret = node::LoadEnvironment(
        env,
        "const publicRequire ="
        "  require('node:module').createRequire(process.cwd() + '/');"
        "globalThis.require = publicRequire;"
        "require('node:vm').runInThisContext(process.argv[1]);");

    if (loadenv_ret.IsEmpty())  // There has been a JS exception.
      return 1;

    exit_code = node::SpinEventLoop(env).FromMaybe(1);

    // node::Stop() can be used to explicitly stop the event loop and keep
    // further JavaScript from running. It can be called from any thread,
    // and will act like worker.terminate() if called from another thread.
    node::Stop(env);
  }

  return exit_code;
} 

Child process#

Stability: 2 - Stable

Source Code: lib/child_process.js

The node:child_process module provides the ability to spawn subprocesses in a manner that is similar, but not identical, to popen(3). This capability is primarily provided by the child_process.spawn() function:

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});import { spawn } from 'node:child_process';
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

By default, pipes for stdin, stdout, and stderr are established between the parent Node.js process and the spawned subprocess. These pipes have limited (and platform-specific) capacity. If the subprocess writes to stdout in excess of that limit without the output being captured, the subprocess blocks waiting for the pipe buffer to accept more data. This is identical to the behavior of pipes in the shell. Use the { stdio: 'ignore' } option if the output will not be consumed.

The command lookup is performed using the options.env.PATH environment variable if env is in the options object. Otherwise, process.env.PATH is used. If options.env is set without PATH, lookup on Unix is performed on a default search path search of /usr/bin:/bin (see your operating system's manual for execvpe/execvp), on Windows the current processes environment variable PATH is used.

On Windows, environment variables are case-insensitive. Node.js lexicographically sorts the env keys and uses the first one that case-insensitively matches. Only first (in lexicographic order) entry will be passed to the subprocess. This might lead to issues on Windows when passing objects to the env option that have multiple variants of the same key, such as PATH and Path.

The child_process.spawn() method spawns the child process asynchronously, without blocking the Node.js event loop. The child_process.spawnSync() function provides equivalent functionality in a synchronous manner that blocks the event loop until the spawned process either exits or is terminated.

For convenience, the node:child_process module provides a handful of synchronous and asynchronous alternatives to child_process.spawn() and child_process.spawnSync(). Each of these alternatives are implemented on top of child_process.spawn() or child_process.spawnSync().

For certain use cases, such as automating shell scripts, the synchronous counterparts may be more convenient. In many cases, however, the synchronous methods can have significant impact on performance due to stalling the event loop while spawned processes complete.

Asynchronous process creation#

The child_process.spawn(), child_process.fork(), child_process.exec(), and child_process.execFile() methods all follow the idiomatic asynchronous programming pattern typical of other Node.js APIs.

Each of the methods returns a ChildProcess instance. These objects implement the Node.js EventEmitter API, allowing the parent process to register listener functions that are called when certain events occur during the life cycle of the child process.

The child_process.exec() and child_process.execFile() methods additionally allow for an optional callback function to be specified that is invoked when the child process terminates.

Spawning .bat and .cmd files on Windows#

The importance of the distinction between child_process.exec() and child_process.execFile() can vary based on platform. On Unix-type operating systems (Unix, Linux, macOS) child_process.execFile() can be more efficient because it does not spawn a shell by default. On Windows, however, .bat and .cmd files are not executable on their own without a terminal, and therefore cannot be launched using child_process.execFile(). When running on Windows, .bat and .cmd files can be invoked using child_process.spawn() with the shell option set, with child_process.exec(), or by spawning cmd.exe and passing the .bat or .cmd file as an argument (which is what the shell option and child_process.exec() do). In any case, if the script filename contains spaces it needs to be quoted.

// OR...
const { exec, spawn } = require('node:child_process');

exec('my.bat', (err, stdout, stderr) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(stdout);
});

// Script with spaces in the filename:
const bat = spawn('"my script.cmd" a b', { shell: true });
// or:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
  // ...
});// OR...
import { exec, spawn } from 'node:child_process';

exec('my.bat', (err, stdout, stderr) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(stdout);
});

// Script with spaces in the filename:
const bat = spawn('"my script.cmd" a b', { shell: true });
// or:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
  // ...
});

child_process.exec(command[, options][, callback])#

Spawns a shell then executes the command within that shell, buffering any generated output. The command string passed to the exec function is processed directly by the shell and special characters (vary based on shell) need to be dealt with accordingly:

const { exec } = require('node:child_process');

exec('"/path/to/test file/test.sh" arg1 arg2');
// Double quotes are used so that the space in the path is not interpreted as
// a delimiter of multiple arguments.

exec('echo "The \\$HOME variable is $HOME"');
// The $HOME variable is escaped in the first instance, but not in the second.import { exec } from 'node:child_process';

exec('"/path/to/test file/test.sh" arg1 arg2');
// Double quotes are used so that the space in the path is not interpreted as
// a delimiter of multiple arguments.

exec('echo "The \\$HOME variable is $HOME"');
// The $HOME variable is escaped in the first instance, but not in the second.

Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

If a callback function is provided, it is called with the arguments (error, stdout, stderr). On success, error will be null. On error, error will be an instance of Error. The error.code property will be the exit code of the process. By convention, any exit code other than 0 indicates an error. error.signal will be the signal that terminated the process.

The stdout and stderr arguments passed to the callback will contain the stdout and stderr output of the child process. By default, Node.js will decode the output as UTF-8 and pass strings to the callback. The encoding option can be used to specify the character encoding used to decode the stdout and stderr output. If encoding is 'buffer', or an unrecognized character encoding, Buffer objects will be passed to the callback instead.

const { exec } = require('node:child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});import { exec } from 'node:child_process';
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});

If timeout is greater than 0, the parent process will send the signal identified by the killSignal property (the default is 'SIGTERM') if the child process runs longer than timeout milliseconds.

Unlike the exec(3) POSIX system call, child_process.exec() does not replace the existing process and uses a shell to execute the command.

If this method is invoked as its util.promisify()ed version, it returns a Promise for an Object with stdout and stderr properties. The returned ChildProcess instance is attached to the Promise as a child property. In case of an error (including any error resulting in an exit code other than 0), a rejected promise is returned, with the same error object given in the callback, but with two additional properties stdout and stderr.

const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.error('stderr:', stderr);
}
lsExample();import { promisify } from 'node:util';
import child_process from 'node:child_process';
const exec = promisify(child_process.exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.error('stderr:', stderr);
}
lsExample();

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { exec } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = exec('grep ssh', { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();import { exec } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const child = exec('grep ssh', { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();

child_process.execFile(file[, args][, options][, callback])#

The child_process.execFile() function is similar to child_process.exec() except that it does not spawn a shell by default. Rather, the specified executable file is spawned directly as a new process making it slightly more efficient than child_process.exec().

The same options as child_process.exec() are supported. Since a shell is not spawned, behaviors such as I/O redirection and file globbing are not supported.

const { execFile } = require('node:child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});import { execFile } from 'node:child_process';
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});

The stdout and stderr arguments passed to the callback will contain the stdout and stderr output of the child process. By default, Node.js will decode the output as UTF-8 and pass strings to the callback. The encoding option can be used to specify the character encoding used to decode the stdout and stderr output. If encoding is 'buffer', or an unrecognized character encoding, Buffer objects will be passed to the callback instead.

If this method is invoked as its util.promisify()ed version, it returns a Promise for an Object with stdout and stderr properties. The returned ChildProcess instance is attached to the Promise as a child property. In case of an error (including any error resulting in an exit code other than 0), a rejected promise is returned, with the same error object given in the callback, but with two additional properties stdout and stderr.

const util = require('node:util');
const execFile = util.promisify(require('node:child_process').execFile);
async function getVersion() {
  const { stdout } = await execFile('node', ['--version']);
  console.log(stdout);
}
getVersion();import { promisify } from 'node:util';
import child_process from 'node:child_process';
const execFile = promisify(child_process.execFile);
async function getVersion() {
  const { stdout } = await execFile('node', ['--version']);
  console.log(stdout);
}
getVersion();

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { execFile } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = execFile('node', ['--version'], { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();import { execFile } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const child = execFile('node', ['--version'], { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();

child_process.fork(modulePath[, args][, options])#

  • modulePath <string> | <URL> The module to run in the child.
  • args <string[]> List of string arguments.
  • options <Object>
    • cwd <string> | <URL> Current working directory of the child process.
    • detached <boolean> Prepare child process to run independently of its parent process. Specific behavior depends on the platform (see options.detached).
    • env <Object> Environment key-value pairs. Default: process.env.
    • execPath <string> Executable used to create the child process.
    • execArgv <string[]> List of string arguments passed to the executable. Default: process.execArgv.
    • gid <number> Sets the group identity of the process (see setgid(2)).
    • serialization <string> Specify the kind of serialization used for sending messages between processes. Possible values are 'json' and 'advanced'. See Advanced serialization for more details. Default: 'json'.
    • signal <AbortSignal> Allows closing the child process using an AbortSignal.
    • killSignal <string> | <integer> The signal value to be used when the spawned process will be killed by timeout or abort signal. Default: 'SIGTERM'.
    • silent <boolean> If true, stdin, stdout, and stderr of the child process will be piped to the parent process, otherwise they will be inherited from the parent process, see the 'pipe' and 'inherit' options for child_process.spawn()'s stdio for more details. Default: false.
    • stdio <Array> | <string> See child_process.spawn()'s stdio. When this option is provided, it overrides silent. If the array variant is used, it must contain exactly one item with value 'ipc' or an error will be thrown. For instance [0, 1, 2, 'ipc'].
    • uid <number> Sets the user identity of the process (see setuid(2)).
    • windowsVerbatimArguments <boolean> No quoting or escaping of arguments is done on Windows. Ignored on Unix. Default: false.
    • timeout <number> In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
  • Returns: <ChildProcess>

The child_process.fork() method is a special case of child_process.spawn() used specifically to spawn new Node.js processes. Like child_process.spawn(), a ChildProcess object is returned. The returned ChildProcess will have an additional communication channel built-in that allows messages to be passed back and forth between the parent and child. See subprocess.send() for details.

Keep in mind that spawned Node.js child processes are independent of the parent with exception of the IPC communication channel that is established between the two. Each process has its own memory, with their own V8 instances. Because of the additional resource allocations required, spawning a large number of child Node.js processes is not recommended.

By default, child_process.fork() will spawn new Node.js instances using the process.execPath of the parent process. The execPath property in the options object allows for an alternative execution path to be used.

Node.js processes launched with a custom execPath will communicate with the parent process using the file descriptor (fd) identified using the environment variable NODE_CHANNEL_FD on the child process.

Unlike the fork(2) POSIX system call, child_process.fork() does not clone the current process.

The shell option available in child_process.spawn() is not supported by child_process.fork() and will be ignored if set.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { fork } = require('node:child_process');
const process = require('node:process');

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Hello from ${process.argv[2]}!`);
  }, 1_000);
} else {
  const controller = new AbortController();
  const { signal } = controller;
  const child = fork(__filename, ['child'], { signal });
  child.on('error', (err) => {
    // This will be called with err being an AbortError if the controller aborts
  });
  controller.abort(); // Stops the child process
}import { fork } from 'node:child_process';
import process from 'node:process';

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Hello from ${process.argv[2]}!`);
  }, 1_000);
} else {
  const controller = new AbortController();
  const { signal } = controller;
  const child = fork(import.meta.url, ['child'], { signal });
  child.on('error', (err) => {
    // This will be called with err being an AbortError if the controller aborts
  });
  controller.abort(); // Stops the child process
}

child_process.spawn(command[, args][, options])#

  • command <string> The command to run.
  • args <string[]> List of string arguments.
  • options <Object>
    • cwd <string> | <URL> Current working directory of the child process.
    • env <Object> Environment key-value pairs. Default: process.env.
    • argv0 <string> Explicitly set the value of argv[0] sent to the child process. This will be set to command if not specified.
    • stdio <Array> | <string> Child's stdio configuration (see options.stdio).
    • detached <boolean> Prepare child process to run independently of its parent process. Specific behavior depends on the platform (see options.detached).
    • uid <number> Sets the user identity of the process (see setuid(2)).
    • gid <number> Sets the group identity of the process (see setgid(2)).
    • serialization <string> Specify the kind of serialization used for sending messages between processes. Possible values are 'json' and 'advanced'. See Advanced serialization for more details. Default: 'json'.
    • shell <boolean> | <string> If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.env.ComSpec on Windows. A different shell can be specified as a string. See Shell requirements and Default Windows shell. Default: false (no shell).
    • windowsVerbatimArguments <boolean> No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD. Default: false.
    • windowsHide <boolean> Hide the subprocess console window that would normally be created on Windows systems. Default: false.
    • signal <AbortSignal> allows aborting the child process using an AbortSignal.
    • timeout <number> In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
    • killSignal <string> | <integer> The signal value to be used when the spawned process will be killed by timeout or abort signal. Default: 'SIGTERM'.
  • Returns: <ChildProcess>

The child_process.spawn() method spawns a new process using the given command, with command-line arguments in args. If omitted, args defaults to an empty array.

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

A third argument may be used to specify additional options, with these defaults:

const defaults = {
  cwd: undefined,
  env: process.env,
}; 

Use cwd to specify the working directory from which the process is spawned. If not given, the default is to inherit the current working directory. If given, but the path does not exist, the child process emits an ENOENT error and exits immediately. ENOENT is also emitted when the command does not exist.

Use env to specify environment variables that will be visible to the new process, the default is process.env.

undefined values in env will be ignored.

Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});import { spawn } from 'node:child_process';
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

Example: A very elaborate way to run ps ax | grep ssh

const { spawn } = require('node:child_process');
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);

ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

ps.stderr.on('data', (data) => {
  console.error(`ps stderr: ${data}`);
});

ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps process exited with code ${code}`);
  }
  grep.stdin.end();
});

grep.stdout.on('data', (data) => {
  console.log(data.toString());
});

grep.stderr.on('data', (data) => {
  console.error(`grep stderr: ${data}`);
});

grep.on('close', (code) => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`);
  }
});import { spawn } from 'node:child_process';
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);

ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

ps.stderr.on('data', (data) => {
  console.error(`ps stderr: ${data}`);
});

ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps process exited with code ${code}`);
  }
  grep.stdin.end();
});

grep.stdout.on('data', (data) => {
  console.log(data.toString());
});

grep.stderr.on('data', (data) => {
  console.error(`grep stderr: ${data}`);
});

grep.on('close', (code) => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`);
  }
});

Example of checking for failed spawn:

const { spawn } = require('node:child_process');
const subprocess = spawn('bad_command');

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});import { spawn } from 'node:child_process';
const subprocess = spawn('bad_command');

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});

Certain platforms (macOS, Linux) will use the value of argv[0] for the process title while others (Windows, SunOS) will use command.

Node.js overwrites argv[0] with process.execPath on startup, so process.argv[0] in a Node.js child process will not match the argv0 parameter passed to spawn from the parent. Retrieve it with the process.argv0 property instead.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { spawn } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
  // This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child processimport { spawn } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
  // This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process
options.detached#

On Windows, setting options.detached to true makes it possible for the child process to continue running after the parent exits. The child process will have its own console window. Once enabled for a child process, it cannot be disabled.

On non-Windows platforms, if options.detached is set to true, the child process will be made the leader of a new process group and session. Child processes may continue running after the parent exits regardless of whether they are detached or not. See setsid(2) for more information.

By default, the parent will wait for the detached child process to exit. To prevent the parent process from waiting for a given subprocess to exit, use the subprocess.unref() method. Doing so will cause the parent process' event loop to not include the child process in its reference count, allowing the parent process to exit independently of the child process, unless there is an established IPC channel between the child and the parent processes.

When using the detached option to start a long-running process, the process will not stay running in the background after the parent exits unless it is provided with a stdio configuration that is not connected to the parent. If the parent process' stdio is inherited, the child process will remain attached to the controlling terminal.

Example of a long-running process, by detaching and also ignoring its parent stdio file descriptors, in order to ignore the parent's termination:

const { spawn } = require('node:child_process');
const process = require('node:process');

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();import { spawn } from 'node:child_process';
import process from 'node:process';

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();

Alternatively one can redirect the child process' output into files:

const { openSync } = require('node:fs');
const { spawn } = require('node:child_process');
const out = openSync('./out.log', 'a');
const err = openSync('./out.log', 'a');

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: [ 'ignore', out, err ],
});

subprocess.unref();import { openSync } from 'node:fs';
import { spawn } from 'node:child_process';
const out = openSync('./out.log', 'a');
const err = openSync('./out.log', 'a');

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: [ 'ignore', out, err ],
});

subprocess.unref();
options.stdio#

The options.stdio option is used to configure the pipes that are established between the parent and child process. By default, the child's stdin, stdout, and stderr are redirected to corresponding subprocess.stdin, subprocess.stdout, and subprocess.stderr streams on the ChildProcess object. This is equivalent to setting the options.stdio equal to ['pipe', 'pipe', 'pipe'].

For convenience, options.stdio may be one of the following strings:

  • 'pipe': equivalent to ['pipe', 'pipe', 'pipe'] (the default)
  • 'overlapped': equivalent to ['overlapped', 'overlapped', 'overlapped']
  • 'ignore': equivalent to ['ignore', 'ignore', 'ignore']
  • 'inherit': equivalent to ['inherit', 'inherit', 'inherit'] or [0, 1, 2]

Otherwise, the value of options.stdio is an array where each index corresponds to an fd in the child. The fds 0, 1, and 2 correspond to stdin, stdout, and stderr, respectively. Additional fds can be specified to create additional pipes between the parent and child. The value is one of the following:

  1. 'pipe': Create a pipe between the child process and the parent process. The parent end of the pipe is exposed to the parent as a property on the child_process object as subprocess.stdio[fd]. Pipes created for fds 0, 1, and 2 are also available as subprocess.stdin, subprocess.stdout and subprocess.stderr, respectively. These are not actual Unix pipes and therefore the child process can not use them by their descriptor files, e.g. /dev/fd/2 or /dev/stdout.

  2. 'overlapped': Same as 'pipe' except that the FILE_FLAG_OVERLAPPED flag is set on the handle. This is necessary for overlapped I/O on the child process's stdio handles. See the docs for more details. This is exactly the same as 'pipe' on non-Windows systems.

  3. 'ipc': Create an IPC channel for passing messages/file descriptors between parent and child. A ChildProcess may have at most one IPC stdio file descriptor. Setting this option enables the subprocess.send() method. If the child process is a Node.js instance, the presence of an IPC channel will enable process.send() and process.disconnect() methods, as well as 'disconnect' and 'message' events within the child process.

    Accessing the IPC channel fd in any way other than process.send() or using the IPC channel with a child process that is not a Node.js instance is not supported.

  4. 'ignore': Instructs Node.js to ignore the fd in the child. While Node.js will always open fds 0, 1, and 2 for the processes it spawns, setting the fd to 'ignore' will cause Node.js to open /dev/null and attach it to the child's fd.

  5. 'inherit': Pass through the corresponding stdio stream to/from the parent process. In the first three positions, this is equivalent to process.stdin, process.stdout, and process.stderr, respectively. In any other position, equivalent to 'ignore'.

  6. <Stream> object: Share a readable or writable stream that refers to a tty, file, socket, or a pipe with the child process. The stream's underlying file descriptor is duplicated in the child process to the fd that corresponds to the index in the stdio array. The stream must have an underlying descriptor (file streams do not start until the 'open' event has occurred). NOTE: While it is technically possible to pass stdin as a writable or stdout/stderr as readable, it is not recommended. Readable and writable streams are designed with distinct behaviors, and using them incorrectly (e.g., passing a readable stream where a writable stream is expected) can lead to unexpected results or errors. This practice is discouraged as it may result in undefined behavior or dropped callbacks if the stream encounters errors. Always ensure that stdin is used as writable and stdout/stderr as readable to maintain the intended flow of data between the parent and child processes.

  7. Positive integer: The integer value is interpreted as a file descriptor that is open in the parent process. It is shared with the child process, similar to how <Stream> objects can be shared. Passing sockets is not supported on Windows.

  8. null, undefined: Use default value. For stdio fds 0, 1, and 2 (in other words, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the default is 'ignore'.

const { spawn } = require('node:child_process');
const process = require('node:process');

// Child will use parent's stdios.
spawn('prg', [], { stdio: 'inherit' });

// Spawn child sharing only stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });import { spawn } from 'node:child_process';
import process from 'node:process';

// Child will use parent's stdios.
spawn('prg', [], { stdio: 'inherit' });

// Spawn child sharing only stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

It is worth noting that when an IPC channel is established between the parent and child processes, and the child process is a Node.js instance, the child process is launched with the IPC channel unreferenced (using unref()) until the child process registers an event handler for the 'disconnect' event or the 'message' event. This allows the child process to exit normally without the process being held open by the open IPC channel. See also: child_process.exec() and child_process.fork().

Synchronous process creation#

The child_process.spawnSync(), child_process.execSync(), and child_process.execFileSync() methods are synchronous and will block the Node.js event loop, pausing execution of any additional code until the spawned process exits.

Blocking calls like these are mostly useful for simplifying general-purpose scripting tasks and for simplifying the loading/processing of application configuration at startup.

child_process.execFileSync(file[, args][, options])#

  • file <string> The name or path of the executable file to run.
  • args <string[]> List of string arguments.
  • options <Object>
    • cwd <string> | <URL> Current working directory of the child process.
    • input <string> | <Buffer> | <TypedArray> | <DataView> The value which will be passed as stdin to the spawned process. If stdio[0] is set to 'pipe', Supplying this value will override stdio[0].
    • stdio <string> | <Array> Child's stdio configuration. See child_process.spawn()'s stdio. stderr by default will be output to the parent process' stderr unless stdio is specified. Default: 'pipe'.
    • env <Object> Environment key-value pairs. Default: process.env.
    • uid <number> Sets the user identity of the process (see setuid(2)).
    • gid <number> Sets the group identity of the process (see setgid(2)).
    • timeout <number> In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
    • killSignal <string> | <integer> The signal value to be used when the spawned process will be killed. Default: 'SIGTERM'.
    • maxBuffer <number> Largest amount of data in bytes allowed on stdout or stderr. If exceeded, the child process is terminated. See caveat at maxBuffer and Unicode. Default: 1024 * 1024.
    • encoding <string> The encoding used for all stdio inputs and outputs. Default: 'buffer'.
    • windowsHide <boolean> Hide the subprocess console window that would normally be created on Windows systems. Default: false.
    • shell <boolean> | <string> If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.env.ComSpec on Windows. A different shell can be specified as a string. See Shell requirements and Default Windows shell. Default: false (no shell).
  • Returns: <Buffer> | <string> The stdout from the command.

The child_process.execFileSync() method is generally identical to child_process.execFile() with the exception that the method will not return until the child process has fully closed. When a timeout has been encountered and killSignal is sent, the method won't return until the process has completely exited.

If the child process intercepts and handles the SIGTERM signal and does not exit, the parent process will still wait until the child process has exited.

If the process times out or has a non-zero exit code, this method will throw an Error that will include the full result of the underlying child_process.spawnSync().

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

const { execFileSync } = require('node:child_process');

try {
  const stdout = execFileSync('my-script.sh', ['my-arg'], {
    // Capture stdout and stderr from child process. Overrides the
    // default behavior of streaming child stderr to the parent stderr
    stdio: 'pipe',

    // Use utf8 encoding for stdio pipes
    encoding: 'utf8',
  });

  console.log(stdout);
} catch (err) {
  if (err.code) {
    // Spawning child process failed
    console.error(err.code);
  } else {
    // Child was spawned but exited with non-zero exit code
    // Error contains any stdout and stderr from the child
    const { stdout, stderr } = err;

    console.error({ stdout, stderr });
  }
}import { execFileSync } from 'node:child_process';

try {
  const stdout = execFileSync('my-script.sh', ['my-arg'], {
    // Capture stdout and stderr from child process. Overrides the
    // default behavior of streaming child stderr to the parent stderr
    stdio: 'pipe',

    // Use utf8 encoding for stdio pipes
    encoding: 'utf8',
  });

  console.log(stdout);
} catch (err) {
  if (err.code) {
    // Spawning child process failed
    console.error(err.code);
  } else {
    // Child was spawned but exited with non-zero exit code
    // Error contains any stdout and stderr from the child
    const { stdout, stderr } = err;

    console.error({ stdout, stderr });
  }
}

child_process.execSync(command[, options])#

  • command <string> The command to run.
  • options <Object>
    • cwd <string> | <URL> Current working directory of the child process.
    • input <string> | <Buffer> | <TypedArray> | <DataView> The value which will be passed as stdin to the spawned process. If stdio[0] is set to 'pipe', Supplying this value will override stdio[0].
    • stdio <string> | <Array> Child's stdio configuration. See child_process.spawn()'s stdio. stderr by default will be output to the parent process' stderr unless stdio is specified. Default: 'pipe'.
    • env <Object> Environment key-value pairs. Default: process.env.
    • shell <string> Shell to execute the command with. See Shell requirements and Default Windows shell. Default: '/bin/sh' on Unix, process.env.ComSpec on Windows.
    • uid <number> Sets the user identity of the process. (See setuid(2)).
    • gid <number> Sets the group identity of the process. (See setgid(2)).
    • timeout <number> In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
    • killSignal <string> | <integer> The signal value to be used when the spawned process will be killed. Default: 'SIGTERM'.
    • maxBuffer <number> Largest amount of data in bytes allowed on stdout or stderr. If exceeded, the child process is terminated and any output is truncated. See caveat at maxBuffer and Unicode. Default: 1024 * 1024.
    • encoding <string> The encoding used for all stdio inputs and outputs. Default: 'buffer'.
    • windowsHide <boolean> Hide the subprocess console window that would normally be created on Windows systems. Default: false.
  • Returns: <Buffer> | <string> The stdout from the command.

The child_process.execSync() method is generally identical to child_process.exec() with the exception that the method will not return until the child process has fully closed. When a timeout has been encountered and killSignal is sent, the method won't return until the process has completely exited. If the child process intercepts and handles the SIGTERM signal and doesn't exit, the parent process will wait until the child process has exited.

If the process times out or has a non-zero exit code, this method will throw. The Error object will contain the entire result from child_process.spawnSync().

Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

child_process.spawnSync(command[, args][, options])#

  • command <string> The command to run.
  • args <string[]> List of string arguments.
  • options <Object>
    • cwd <string> | <URL> Current working directory of the child process.
    • input <string> | <Buffer> | <TypedArray> | <DataView> The value which will be passed as stdin to the spawned process. If stdio[0] is set to 'pipe', Supplying this value will override stdio[0].
    • argv0 <string> Explicitly set the value of argv[0] sent to the child process. This will be set to command if not specified.
    • stdio <string> | <Array> Child's stdio configuration. See child_process.spawn()'s stdio. Default: 'pipe'.
    • env <Object> Environment key-value pairs. Default: process.env.
    • uid <number> Sets the user identity of the process (see setuid(2)).
    • gid <number> Sets the group identity of the process (see setgid(2)).
    • timeout <number> In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
    • killSignal <string> | <integer> The signal value to be used when the spawned process will be killed. Default: 'SIGTERM'.
    • maxBuffer <number> Largest amount of data in bytes allowed on stdout or stderr. If exceeded, the child process is terminated and any output is truncated. See caveat at maxBuffer and Unicode. Default: 1024 * 1024.
    • encoding <string> The encoding used for all stdio inputs and outputs. Default: 'buffer'.
    • shell <boolean> | <string> If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.env.ComSpec on Windows. A different shell can be specified as a string. See Shell requirements and Default Windows shell. Default: false (no shell).
    • windowsVerbatimArguments <boolean> No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD. Default: false.
    • windowsHide <boolean> Hide the subprocess console window that would normally be created on Windows systems. Default: false.
  • Returns: <Object>
    • pid <number> Pid of the child process.
    • output <Array> Array of results from stdio output.
    • stdout <Buffer> | <string> The contents of output[1].
    • stderr <Buffer> | <string> The contents of output[2].
    • status <number> | <null> The exit code of the subprocess, or null if the subprocess terminated due to a signal.
    • signal <string> | <null> The signal used to kill the subprocess, or null if the subprocess did not terminate due to a signal.
    • error <Error> The error object if the child process failed or timed out.

The child_process.spawnSync() method is generally identical to child_process.spawn() with the exception that the function will not return until the child process has fully closed. When a timeout has been encountered and killSignal is sent, the method won't return until the process has completely exited. If the process intercepts and handles the SIGTERM signal and doesn't exit, the parent process will wait until the child process has exited.

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

Class: ChildProcess#

Instances of the ChildProcess represent spawned child processes.

Instances of ChildProcess are not intended to be created directly. Rather, use the child_process.spawn(), child_process.exec(), child_process.execFile(), or child_process.fork() methods to create instances of ChildProcess.

Event: 'close'#

  • code <number> The exit code if the child process exited on its own.
  • signal <string> The signal by which the child process was terminated.

The 'close' event is emitted after a process has ended and the stdio streams of a child process have been closed. This is distinct from the 'exit' event, since multiple processes might share the same stdio streams. The 'close' event will always emit after 'exit' was already emitted, or 'error' if the child process failed to spawn.

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process close all stdio with code ${code}`);
});

ls.on('exit', (code) => {
  console.log(`child process exited with code ${code}`);
});import { spawn } from 'node:child_process';
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process close all stdio with code ${code}`);
});

ls.on('exit', (code) => {
  console.log(`child process exited with code ${code}`);
});

Event: 'disconnect'#

The 'disconnect' event is emitted after calling the subprocess.disconnect() method in parent process or process.disconnect() in child process. After disconnecting it is no longer possible to send or receive messages, and the subprocess.connected property is false.

Event: 'error'#

The 'error' event is emitted whenever:

  • The process could not be spawned.
  • The process could not be killed.
  • Sending a message to the child process failed.
  • The child process was aborted via the signal option.

The 'exit' event may or may not fire after an error has occurred. When listening to both the 'exit' and 'error' events, guard against accidentally invoking handler functions multiple times.

See also subprocess.kill() and subprocess.send().

Event: 'exit'#

  • code <number> The exit code if the child process exited on its own.
  • signal <string> The signal by which the child process was terminated.

The 'exit' event is emitted after the child process ends. If the process exited, code is the final exit code of the process, otherwise null. If the process terminated due to receipt of a signal, signal is the string name of the signal, otherwise null. One of the two will always be non-null.

When the 'exit' event is triggered, child process stdio streams might still be open.

Node.js establishes signal handlers for SIGINT and SIGTERM and Node.js processes will not terminate immediately due to receipt of those signals. Rather, Node.js will perform a sequence of cleanup actions and then will re-raise the handled signal.

See waitpid(2).

Event: 'message'#

The 'message' event is triggered when a child process uses process.send() to send messages.

The message goes through serialization and parsing. The resulting message might not be the same as what is originally sent.

If the serialization option was set to 'advanced' used when spawning the child process, the message argument can contain data that JSON is not able to represent. See Advanced serialization for more details.

Event: 'spawn'#

The 'spawn' event is emitted once the child process has spawned successfully. If the child process does not spawn successfully, the 'spawn' event is not emitted and the 'error' event is emitted instead.

If emitted, the 'spawn' event comes before all other events and before any data is received via stdout or stderr.

The 'spawn' event will fire regardless of whether an error occurs within the spawned process. For example, if bash some-command spawns successfully, the 'spawn' event will fire, though bash may fail to spawn some-command. This caveat also applies when using { shell: true }.

subprocess.channel#

  • <Object> A pipe representing the IPC channel to the child process.

The subprocess.channel property is a reference to the child's IPC channel. If no IPC channel exists, this property is undefined.

subprocess.channel.ref()#

This method makes the IPC channel keep the event loop of the parent process running if .unref() has been called before.

subprocess.channel.unref()#

This method makes the IPC channel not keep the event loop of the parent process running, and lets it finish even while the channel is open.

subprocess.connected#

  • <boolean> Set to false after subprocess.disconnect() is called.

The subprocess.connected property indicates whether it is still possible to send and receive messages from a child process. When subprocess.connected is false, it is no longer possible to send or receive messages.

subprocess.disconnect()#

Closes the IPC channel between parent and child processes, allowing the child process to exit gracefully once there are no other connections keeping it alive. After calling this method the subprocess.connected and process.connected properties in both the parent and child processes (respectively) will be set to false, and it will be no longer possible to pass messages between the processes.

The 'disconnect' event will be emitted when there are no messages in the process of being received. This will most often be triggered immediately after calling subprocess.disconnect().

When the child process is a Node.js instance (e.g. spawned using child_process.fork()), the process.disconnect() method can be invoked within the child process to close the IPC channel as well.

subprocess.exitCode#

The subprocess.exitCode property indicates the exit code of the child process. If the child process is still running, the field will be null.

subprocess.kill([signal])#

The subprocess.kill() method sends a signal to the child process. If no argument is given, the process will be sent the 'SIGTERM' signal. See signal(7) for a list of available signals. This function returns true if kill(2) succeeds, and false otherwise.

const { spawn } = require('node:child_process');
const grep = spawn('grep', ['ssh']);

grep.on('close', (code, signal) => {
  console.log(
    `child process terminated due to receipt of signal ${signal}`);
});

// Send SIGHUP to process.
grep.kill('SIGHUP');import { spawn } from 'node:child_process';
const grep = spawn('grep', ['ssh']);

grep.on('close', (code, signal) => {
  console.log(
    `child process terminated due to receipt of signal ${signal}`);
});

// Send SIGHUP to process.
grep.kill('SIGHUP');

The ChildProcess object may emit an 'error' event if the signal cannot be delivered. Sending a signal to a child process that has already exited is not an error but may have unforeseen consequences. Specifically, if the process identifier (PID) has been reassigned to another process, the signal will be delivered to that process instead which can have unexpected results.

While the function is called kill, the signal delivered to the child process may not actually terminate the process.

See kill(2) for reference.

On Windows, where POSIX signals do not exist, the signal argument will be ignored except for 'SIGKILL', 'SIGTERM', 'SIGINT' and 'SIGQUIT', and the process will always be killed forcefully and abruptly (similar to 'SIGKILL'). See Signal Events for more details.

On Linux, child processes of child processes will not be terminated when attempting to kill their parent. This is likely to happen when running a new process in a shell or with the use of the shell option of ChildProcess:

const { spawn } = require('node:child_process');

const subprocess = spawn(
  'sh',
  [
    '-c',
    `node -e "setInterval(() => {
      console.log(process.pid, 'is alive')
    }, 500);"`,
  ], {
    stdio: ['inherit', 'inherit', 'inherit'],
  },
);

setTimeout(() => {
  subprocess.kill(); // Does not terminate the Node.js process in the shell.
}, 2000);import { spawn } from 'node:child_process';

const subprocess = spawn(
  'sh',
  [
    '-c',
    `node -e "setInterval(() => {
      console.log(process.pid, 'is alive')
    }, 500);"`,
  ], {
    stdio: ['inherit', 'inherit', 'inherit'],
  },
);

setTimeout(() => {
  subprocess.kill(); // Does not terminate the Node.js process in the shell.
}, 2000);

subprocess[Symbol.dispose]()#

Stability: 1 - Experimental

Calls subprocess.kill() with 'SIGTERM'.

subprocess.killed#

  • <boolean> Set to true after subprocess.kill() is used to successfully send a signal to the child process.

The subprocess.killed property indicates whether the child process successfully received a signal from subprocess.kill(). The killed property does not indicate that the child process has been terminated.

subprocess.pid#

Returns the process identifier (PID) of the child process. If the child process fails to spawn due to errors, then the value is undefined and error is emitted.

const { spawn } = require('node:child_process');
const grep = spawn('grep', ['ssh']);

console.log(`Spawned child pid: ${grep.pid}`);
grep.stdin.end();import { spawn } from 'node:child_process';
const grep = spawn('grep', ['ssh']);

console.log(`Spawned child pid: ${grep.pid}`);
grep.stdin.end();

subprocess.ref()#

Calling subprocess.ref() after making a call to subprocess.unref() will restore the removed reference count for the child process, forcing the parent process to wait for the child process to exit before exiting itself.

const { spawn } = require('node:child_process');
const process = require('node:process');

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();
subprocess.ref();import { spawn } from 'node:child_process';
import process from 'node:process';

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();
subprocess.ref();

subprocess.send(message[, sendHandle[, options]][, callback])#

  • message <Object>
  • sendHandle <Handle> | <undefined> undefined, or a net.Socket, net.Server, or dgram.Socket object.
  • options <Object> The options argument, if present, is an object used to parameterize the sending of certain types of handles. options supports the following properties:
    • keepOpen <boolean> A value that can be used when passing instances of net.Socket. When true, the socket is kept open in the sending process. Default: false.
  • callback <Function>
  • Returns: <boolean>

When an IPC channel has been established between the parent and child processes ( i.e. when using child_process.fork()), the subprocess.send() method can be used to send messages to the child process. When the child process is a Node.js instance, these messages can be received via the 'message' event.

The message goes through serialization and parsing. The resulting message might not be the same as what is originally sent.

For example, in the parent script:

const { fork } = require('node:child_process');
const forkedProcess = fork(`${__dirname}/sub.js`);

forkedProcess.on('message', (message) => {
  console.log('PARENT got message:', message);
});

// Causes the child to print: CHILD got message: { hello: 'world' }
forkedProcess.send({ hello: 'world' });import { fork } from 'node:child_process';
const forkedProcess = fork(`${import.meta.dirname}/sub.js`);

forkedProcess.on('message', (message) => {
  console.log('PARENT got message:', message);
});

// Causes the child to print: CHILD got message: { hello: 'world' }
forkedProcess.send({ hello: 'world' });

And then the child script, 'sub.js' might look like this:

process.on('message', (message) => {
  console.log('CHILD got message:', message);
});

// Causes the parent to print: PARENT got message: { foo: 'bar', baz: null }
process.send({ foo: 'bar', baz: NaN }); 

Child Node.js processes will have a process.send() method of their own that allows the child process to send messages back to the parent process.

There is a special case when sending a {cmd: 'NODE_foo'} message. Messages containing a NODE_ prefix in the cmd property are reserved for use within Node.js core and will not be emitted in the child's 'message' event. Rather, such messages are emitted using the 'internalMessage' event and are consumed internally by Node.js. Applications should avoid using such messages or listening for 'internalMessage' events as it is subject to change without notice.

The optional sendHandle argument that may be passed to subprocess.send() is for passing a TCP server or socket object to the child process. The child process will receive the object as the second argument passed to the callback function registered on the 'message' event. Any data that is received and buffered in the socket will not be sent to the child. Sending IPC sockets is not supported on Windows.

The optional callback is a function that is invoked after the message is sent but before the child process may have received it. The function is called with a single argument: null on success, or an Error object on failure.

If no callback function is provided and the message cannot be sent, an 'error' event will be emitted by the ChildProcess object. This can happen, for instance, when the child process has already exited.

subprocess.send() will return false if the channel has closed or when the backlog of unsent messages exceeds a threshold that makes it unwise to send more. Otherwise, the method returns true. The callback function can be used to implement flow control.

Example: sending a server object#

The sendHandle argument can be used, for instance, to pass the handle of a TCP server object to the child process as illustrated in the example below:

const { fork } = require('node:child_process');
const { createServer } = require('node:net');

const subprocess = fork('subprocess.js');

// Open up the server object and send the handle.
const server = createServer();
server.on('connection', (socket) => {
  socket.end('handled by parent');
});
server.listen(1337, () => {
  subprocess.send('server', server);
});import { fork } from 'node:child_process';
import { createServer } from 'node:net';

const subprocess = fork('subprocess.js');

// Open up the server object and send the handle.
const server = createServer();
server.on('connection', (socket) => {
  socket.end('handled by parent');
});
server.listen(1337, () => {
  subprocess.send('server', server);
});

The child process would then receive the server object as:

process.on('message', (m, server) => {
  if (m === 'server') {
    server.on('connection', (socket) => {
      socket.end('handled by child');
    });
  }
}); 

Once the server is now shared between the parent and child, some connections can be handled by the parent and some by the child.

While the example above uses a server created using the node:net module, node:dgram module servers use exactly the same workflow with the exceptions of listening on a 'message' event instead of 'connection' and using server.bind() instead of server.listen(). This is, however, only supported on Unix platforms.

Example: sending a socket object#

Similarly, the sendHandler argument can be used to pass the handle of a socket to the child process. The example below spawns two children that each handle connections with "normal" or "special" priority:

const { fork } = require('node:child_process');
const { createServer } = require('node:net');

const normal = fork('subprocess.js', ['normal']);
const special = fork('subprocess.js', ['special']);

// Open up the server and send sockets to child. Use pauseOnConnect to prevent
// the sockets from being read before they are sent to the child process.
const server = createServer({ pauseOnConnect: true });
server.on('connection', (socket) => {

  // If this is special priority...
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket);
    return;
  }
  // This is normal priority.
  normal.send('socket', socket);
});
server.listen(1337);import { fork } from 'node:child_process';
import { createServer } from 'node:net';

const normal = fork('subprocess.js', ['normal']);
const special = fork('subprocess.js', ['special']);

// Open up the server and send sockets to child. Use pauseOnConnect to prevent
// the sockets from being read before they are sent to the child process.
const server = createServer({ pauseOnConnect: true });
server.on('connection', (socket) => {

  // If this is special priority...
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket);
    return;
  }
  // This is normal priority.
  normal.send('socket', socket);
});
server.listen(1337);

The subprocess.js would receive the socket handle as the second argument passed to the event callback function:

process.on('message', (m, socket) => {
  if (m === 'socket') {
    if (socket) {
      // Check that the client socket exists.
      // It is possible for the socket to be closed between the time it is
      // sent and the time it is received in the child process.
      socket.end(`Request handled with ${process.argv[2]} priority`);
    }
  }
}); 

Do not use .maxConnections on a socket that has been passed to a subprocess. The parent cannot track when the socket is destroyed.

Any 'message' handlers in the subprocess should verify that socket exists, as the connection may have been closed during the time it takes to send the connection to the child.

subprocess.signalCode#

The subprocess.signalCode property indicates the signal received by the child process if any, else null.

subprocess.spawnargs#

The subprocess.spawnargs property represents the full list of command-line arguments the child process was launched with.

subprocess.spawnfile#

The subprocess.spawnfile property indicates the executable file name of the child process that is launched.

For child_process.fork(), its value will be equal to process.execPath. For child_process.spawn(), its value will be the name of the executable file. For child_process.exec(), its value will be the name of the shell in which the child process is launched.

subprocess.stderr#

A Readable Stream that represents the child process's stderr.

If the child process was spawned with stdio[2] set to anything other than 'pipe', then this will be null.

subprocess.stderr is an alias for subprocess.stdio[2]. Both properties will refer to the same value.

The subprocess.stderr property can be null or undefined if the child process could not be successfully spawned.

subprocess.stdin#

A Writable Stream that represents the child process's stdin.

If a child process waits to read all of its input, the child process will not continue until this stream has been closed via end().

If the child process was spawned with stdio[0] set to anything other than 'pipe', then this will be null.

subprocess.stdin is an alias for subprocess.stdio[0]. Both properties will refer to the same value.

The subprocess.stdin property can be null or undefined if the child process could not be successfully spawned.

subprocess.stdio#

A sparse array of pipes to the child process, corresponding with positions in the stdio option passed to child_process.spawn() that have been set to the value 'pipe'. subprocess.stdio[0], subprocess.stdio[1], and subprocess.stdio[2] are also available as subprocess.stdin, subprocess.stdout, and subprocess.stderr, respectively.

In the following example, only the child's fd 1 (stdout) is configured as a pipe, so only the parent's subprocess.stdio[1] is a stream, all other values in the array are null.

const assert = require('node:assert');
const fs = require('node:fs');
const child_process = require('node:child_process');

const subprocess = child_process.spawn('ls', {
  stdio: [
    0, // Use parent's stdin for child.
    'pipe', // Pipe child's stdout to parent.
    fs.openSync('err.out', 'w'), // Direct child's stderr to a file.
  ],
});

assert.strictEqual(subprocess.stdio[0], null);
assert.strictEqual(subprocess.stdio[0], subprocess.stdin);

assert(subprocess.stdout);
assert.strictEqual(subprocess.stdio[1], subprocess.stdout);

assert.strictEqual(subprocess.stdio[2], null);
assert.strictEqual(subprocess.stdio[2], subprocess.stderr);import assert from 'node:assert';
import fs from 'node:fs';
import child_process from 'node:child_process';

const subprocess = child_process.spawn('ls', {
  stdio: [
    0, // Use parent's stdin for child.
    'pipe', // Pipe child's stdout to parent.
    fs.openSync('err.out', 'w'), // Direct child's stderr to a file.
  ],
});

assert.strictEqual(subprocess.stdio[0], null);
assert.strictEqual(subprocess.stdio[0], subprocess.stdin);

assert(subprocess.stdout);
assert.strictEqual(subprocess.stdio[1], subprocess.stdout);

assert.strictEqual(subprocess.stdio[2], null);
assert.strictEqual(subprocess.stdio[2], subprocess.stderr);

The subprocess.stdio property can be undefined if the child process could not be successfully spawned.

subprocess.stdout#

A Readable Stream that represents the child process's stdout.

If the child process was spawned with stdio[1] set to anything other than 'pipe', then this will be null.

subprocess.stdout is an alias for subprocess.stdio[1]. Both properties will refer to the same value.

const { spawn } = require('node:child_process');

const subprocess = spawn('ls');

subprocess.stdout.on('data', (data) => {
  console.log(`Received chunk ${data}`);
});import { spawn } from 'node:child_process';

const subprocess = spawn('ls');

subprocess.stdout.on('data', (data) => {
  console.log(`Received chunk ${data}`);
});

The subprocess.stdout property can be null or undefined if the child process could not be successfully spawned.

subprocess.unref()#

By default, the parent process will wait for the detached child process to exit. To prevent the parent process from waiting for a given subprocess to exit, use the subprocess.unref() method. Doing so will cause the parent's event loop to not include the child process in its reference count, allowing the parent to exit independently of the child, unless there is an established IPC channel between the child and the parent processes.

const { spawn } = require('node:child_process');
const process = require('node:process');

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();import { spawn } from 'node:child_process';
import process from 'node:process';

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();

maxBuffer and Unicode#

The maxBuffer option specifies the largest number of bytes allowed on stdout or stderr. If this value is exceeded, then the child process is terminated. This impacts output that includes multibyte character encodings such as UTF-8 or UTF-16. For instance, console.log('中文测试') will send 13 UTF-8 encoded bytes to stdout although there are only 4 characters.

Shell requirements#

The shell should understand the -c switch. If the shell is 'cmd.exe', it should understand the /d /s /c switches and command-line parsing should be compatible.

Default Windows shell#

Although Microsoft specifies %COMSPEC% must contain the path to 'cmd.exe' in the root environment, child processes are not always subject to the same requirement. Thus, in child_process functions where a shell can be spawned, 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable.

Advanced serialization#

Child processes support a serialization mechanism for IPC that is based on the serialization API of the node:v8 module, based on the HTML structured clone algorithm. This is generally more powerful and supports more built-in JavaScript object types, such as BigInt, Map and Set, ArrayBuffer and TypedArray, Buffer, Error, RegExp etc.

However, this format is not a full superset of JSON, and e.g. properties set on objects of such built-in types will not be passed on through the serialization step. Additionally, performance may not be equivalent to that of JSON, depending on the structure of the passed data. Therefore, this feature requires opting in by setting the serialization option to 'advanced' when calling child_process.spawn() or child_process.fork().

Cluster#

Stability: 2 - Stable

Source Code: lib/cluster.js

Clusters of Node.js processes can be used to run multiple instances of Node.js that can distribute workloads among their application threads. When process isolation is not needed, use the worker_threads module instead, which allows running multiple application threads within a single Node.js instance.

The cluster module allows easy creation of child processes that all share server ports.

import cluster from 'node:cluster';
import http from 'node:http';
import { availableParallelism } from 'node:os';
import process from 'node:process';

const numCPUs = availableParallelism();

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`);
}const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').availableParallelism();
const process = require('node:process');

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`);
}

Running Node.js will now share port 8000 between the workers:

$ node server.js
Primary 3596 is running
Worker 4324 started
Worker 4520 started
Worker 6056 started
Worker 5644 started 

On Windows, it is not yet possible to set up a named pipe server in a worker.

How it works#

The worker processes are spawned using the child_process.fork() method, so that they can communicate with the parent via IPC and pass server handles back and forth.

The cluster module supports two methods of distributing incoming connections.

The first one (and the default one on all platforms except Windows) is the round-robin approach, where the primary process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process.

The second approach is where the primary process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly.

The second approach should, in theory, give the best performance. In practice however, distribution tends to be very unbalanced due to operating system scheduler vagaries. Loads have been observed where over 70% of all connections ended up in just two processes, out of a total of eight.

Because server.listen() hands off most of the work to the primary process, there are three cases where the behavior between a normal Node.js process and a cluster worker differs:

  1. server.listen({fd: 7}) Because the message is passed to the primary, file descriptor 7 in the parent will be listened on, and the handle passed to the worker, rather than listening to the worker's idea of what the number 7 file descriptor references.
  2. server.listen(handle) Listening on handles explicitly will cause the worker to use the supplied handle, rather than talk to the primary process.
  3. server.listen(0) Normally, this will cause servers to listen on a random port. However, in a cluster, each worker will receive the same "random" port each time they do listen(0). In essence, the port is random the first time, but predictable thereafter. To listen on a unique port, generate a port number based on the cluster worker ID.

Node.js does not provide routing logic. It is therefore important to design an application such that it does not rely too heavily on in-memory data objects for things like sessions and login.

Because workers are all separate processes, they can be killed or re-spawned depending on a program's needs, without affecting other workers. As long as there are some workers still alive, the server will continue to accept connections. If no workers are alive, existing connections will be dropped and new connections will be refused. Node.js does not automatically manage the number of workers, however. It is the application's responsibility to manage the worker pool based on its own needs.

Although a primary use case for the node:cluster module is networking, it can also be used for other use cases requiring worker processes.

Class: Worker#

A Worker object contains all public information and method about a worker. In the primary it can be obtained using cluster.workers. In a worker it can be obtained using cluster.worker.

Event: 'disconnect'#

Similar to the cluster.on('disconnect') event, but specific to this worker.

cluster.fork().on('disconnect', () => {
  // Worker has disconnected
}); 

Event: 'error'#

This event is the same as the one provided by child_process.fork().

Within a worker, process.on('error') may also be used.

Event: 'exit'#

  • code <number> The exit code, if it exited normally.
  • signal <string> The name of the signal (e.g. 'SIGHUP') that caused the process to be killed.

Similar to the cluster.on('exit') event, but specific to this worker.

import cluster from 'node:cluster';

if (cluster.isPrimary) {
  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!');
    }
  });
}const cluster = require('node:cluster');

if (cluster.isPrimary) {
  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!');
    }
  });
}

Event: 'listening'#

Similar to the cluster.on('listening') event, but specific to this worker.

cluster.fork().on('listening', (address) => {
  // Worker is listening
});cluster.fork().on('listening', (address) => {
  // Worker is listening
});

It is not emitted in the worker.

Event: 'message'#

Similar to the 'message' event of cluster, but specific to this worker.

Within a worker, process.on('message') may also be used.

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:

import cluster from 'node:cluster';
import http from 'node:http';
import { availableParallelism } from 'node:os';
import process from 'node: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 = availableParallelism();
  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);
}const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').availableParallelism();
const process = require('node: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
  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);
}

Event: 'online'#

Similar to the cluster.on('online') event, but specific to this worker.

cluster.fork().on('online', () => {
  // Worker is online
}); 

It is not emitted in the worker.

worker.disconnect()#

In a worker, this function will close all servers, wait for the 'close' event on those servers, and then disconnect the IPC channel.

In the primary, an internal message is sent to the worker causing it to call .disconnect() on itself.

Causes .exitedAfterDisconnect to be set.

After a server is closed, it will no longer accept new connections, but connections may be accepted by any other listening worker. Existing connections will be allowed to close as usual. When no more connections exist, see server.close(), the IPC channel to the worker will close allowing it to die gracefully.

The above applies only to server connections, client connections are not automatically closed by workers, and disconnect does not wait for them to close before exiting.

In a worker, process.disconnect exists, but it is not this function; it is disconnect().

Because long living server connections may block workers from disconnecting, it may be useful to send a message, so application specific actions may be taken to close them. It also may be useful to implement a timeout, killing a worker if the 'disconnect' event has not been emitted after some time.

if (cluster.isPrimary) {
  const worker = cluster.fork();
  let timeout;

  worker.on('listening', (address) => {
    worker.send('shutdown');
    worker.disconnect();
    timeout = setTimeout(() => {
      worker.kill();
    }, 2000);
  });

  worker.on('disconnect', () => {
    clearTimeout(timeout);
  });

} else if (cluster.isWorker) {
  const net = require('node:net');
  const server = net.createServer((socket) => {
    // Connections never end
  });

  server.listen(8000);

  process.on('message', (msg) => {
    if (msg === 'shutdown') {
      // Initiate graceful close of any connections to server
    }
  });
} 

worker.exitedAfterDisconnect#

This property is true if the worker exited due to .disconnect(). If the worker exited any other way, it is false. If the worker has not exited, it is undefined.

The boolean worker.exitedAfterDisconnect allows distinguishing between voluntary and accidental exit, the primary may choose not to respawn a worker based on this value.

cluster.on('exit', (worker, code, signal) => {
  if (worker.exitedAfterDisconnect === true) {
    console.log('Oh, it was just voluntary – no need to worry');
  }
});

// kill worker
worker.kill(); 

worker.id#

Each new worker is given its own unique id, this id is stored in the id.

While a worker is alive, this is the key that indexes it in cluster.workers.

worker.isConnected()#

This function returns true if the worker is connected to its primary via its IPC channel, false otherwise. A worker is connected to its primary after it has been created. It is disconnected after the 'disconnect' event is emitted.

worker.isDead()#

This function returns true if the worker's process has terminated (either because of exiting or being signaled). Otherwise, it returns false.

import cluster from 'node:cluster';
import http from 'node:http';
import { availableParallelism } from 'node:os';
import process from 'node:process';

const numCPUs = availableParallelism();

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);
}const cluster = require('node:cluster');
const http = require('node:http');
const numCPUs = require('node:os').availableParallelism();
const process = require('node:process');

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);
}

worker.kill([signal])#

  • signal <string> Name of the kill signal to send to the worker process. Default: 'SIGTERM'

This function will kill the worker. In the primary worker, it does this by disconnecting the worker.process, and once disconnected, killing with signal. In the worker, it does it by killing the process with signal.

The kill() function kills the worker process without waiting for a graceful disconnect, it has the same behavior as worker.process.kill().

This method is aliased as worker.destroy() for backwards compatibility.

In a worker, process.kill() exists, but it is not this function; it is kill().

worker.process#

All workers are created using child_process.fork(), the returned object from this function is stored as .process. In a worker, the global process is stored.

See: Child Process module.

Workers will call process.exit(0) if the 'disconnect' event occurs on process and .exitedAfterDisconnect is not true. This protects against accidental disconnection.

worker.send(message[, sendHandle[, options]][, callback])#

  • message <Object>
  • sendHandle <Handle>
  • options <Object> The options argument, if present, is an object used to parameterize the sending of certain types of handles. options supports the following properties:
    • keepOpen <boolean> A value that can be used when passing instances of net.Socket. When true, the socket is kept open in the sending process. Default: false.
  • callback <Function>
  • Returns: <boolean>

Send a message to a worker or primary, optionally with a handle.

In the primary, this sends a message to a specific worker. It is identical to ChildProcess.send().

In a worker, this sends a message to the primary. It is identical to process.send().

This example will echo back all messages from the primary:

if (cluster.isPrimary) {
  const worker = cluster.fork();
  worker.send('hi there');

} else if (cluster.isWorker) {
  process.on('message', (msg) => {
    process.send(msg);
  });
} 

Event: 'disconnect'#

Emitted after the worker IPC channel has disconnected. This can occur when a worker exits gracefully, is killed, or is disconnected manually (such as with worker.disconnect()).

There may be a delay between the 'disconnect' and 'exit' events. These events can be used to detect if the process is stuck in a cleanup or if there are long-living connections.

cluster.on('disconnect', (worker) => {
  console.log(`The worker #${worker.id} has disconnected`);
}); 

Event: 'exit'#

  • worker <cluster.Worker>
  • code <number> The exit code, if it exited normally.
  • signal <string> The name of the signal (e.g. 'SIGHUP') that caused the process to be killed.

When any of the workers die the cluster module will emit the 'exit' event.

This can be used to restart the worker by calling .fork() again.

cluster.on('exit', (worker, code, signal) => {
  console.log('worker %d died (%s). restarting...',
              worker.process.pid, signal || code);
  cluster.fork();
}); 

See child_process event: 'exit'.

Event: 'fork'#

When a new worker is forked the cluster module will emit a 'fork' event. This can be used to log worker activity, and create a custom timeout.

const timeouts = [];
function errorMsg() {
  console.error('Something must be wrong with the connection ...');
}

cluster.on('fork', (worker) => {
  timeouts[worker.id] = setTimeout(errorMsg, 2000);
});
cluster.on('listening', (worker, address) => {
  clearTimeout(timeouts[worker.id]);
});
cluster.on('exit', (worker, code, signal) => {
  clearTimeout(timeouts[worker.id]);
  errorMsg();
}); 

Event: 'listening'#

After calling listen() from a worker, when the 'listening' event is emitted on the server, a 'listening' event will also be emitted on cluster in the primary.

The event handler is executed with two arguments, the worker contains the worker object and the address object contains the following connection properties: address, port, and addressType. This is very useful if the worker is listening on more than one address.

cluster.on('listening', (worker, address) => {
  console.log(
    `A worker is now connected to ${address.address}:${address.port}`);
}); 

The addressType is one of:

  • 4 (TCPv4)
  • 6 (TCPv6)
  • -1 (Unix domain socket)
  • 'udp4' or 'udp6' (UDPv4 or UDPv6)

Event: 'message'#

Emitted when the cluster primary receives a message from any worker.

See child_process event: 'message'.

Event: 'online'#

After forking a new worker, the worker should respond with an online message. When the primary receives an online message it will emit this event. The difference between 'fork' and 'online' is that fork is emitted when the primary forks a worker, and 'online' is emitted when the worker is running.

cluster.on('online', (worker) => {
  console.log('Yay, the worker responded after it was forked');
}); 

Event: 'setup'#

Emitted every time .setupPrimary() is called.

The settings object is the cluster.settings object at the time .setupPrimary() was called and is advisory only, since multiple calls to .setupPrimary() can be made in a single tick.

If accuracy is important, use cluster.settings.

cluster.disconnect([callback])#

  • callback <Function> Called when all workers are disconnected and handles are closed.

Calls .disconnect() on each worker in cluster.workers.

When they are disconnected all internal handles will be closed, allowing the primary process to die gracefully if no other event is waiting.

The method takes an optional callback argument which will be called when finished.

This can only be called from the primary process.

cluster.fork([env])#

Spawn a new worker process.

This can only be called from the primary process.

cluster.isMaster#

Stability: 0 - Deprecated

Deprecated alias for cluster.isPrimary.

cluster.isPrimary#

True if the process is a primary. This is determined by the process.env.NODE_UNIQUE_ID. If process.env.NODE_UNIQUE_ID is undefined, then isPrimary is true.

cluster.isWorker#

True if the process is not a primary (it is the negation of cluster.isPrimary).

cluster.schedulingPolicy#

The scheduling policy, either cluster.SCHED_RR for round-robin or cluster.SCHED_NONE to leave it to the operating system. This is a global setting and effectively frozen once either the first worker is spawned, or .setupPrimary() is called, whichever comes first.

SCHED_RR is the default on all operating systems except Windows. Windows will change to SCHED_RR once libuv is able to effectively distribute IOCP handles without incurring a large performance hit.

cluster.schedulingPolicy can also be set through the NODE_CLUSTER_SCHED_POLICY environment variable. Valid values are 'rr' and 'none'.

cluster.settings#

  • <Object>
    • execArgv <string[]> List of string arguments passed to the Node.js executable. Default: process.execArgv.
    • exec <string> File path to worker file. Default: process.argv[1].
    • args <string[]> String arguments passed to worker. Default: process.argv.slice(2).
    • cwd <string> Current working directory of the worker process. Default: undefined (inherits from parent process).
    • serialization <string> Specify the kind of serialization used for sending messages between processes. Possible values are 'json' and 'advanced'. See Advanced serialization for child_process for more details. Default: false.
    • silent <boolean> Whether or not to send output to parent's stdio. Default: false.
    • stdio <Array> Configures the stdio of forked processes. Because the cluster module relies on IPC to function, this configuration must contain an 'ipc' entry. When this option is provided, it overrides silent. See child_process.spawn()'s stdio.
    • uid <number> Sets the user identity of the process. (See setuid(2).)
    • gid <number> Sets the group identity of the process. (See setgid(2).)
    • inspectPort <number> | <Function> Sets inspector port of worker. This can be a number, or a function that takes no arguments and returns a number. By default each worker gets its own port, incremented from the primary's process.debugPort.
    • windowsHide <boolean> Hide the forked processes console window that would normally be created on Windows systems. Default: false.

After calling .setupPrimary() (or .fork()) this settings object will contain the settings, including the default values.

This object is not intended to be changed or set manually.

cluster.setupMaster([settings])#

Stability: 0 - Deprecated

Deprecated alias for .setupPrimary().

cluster.setupPrimary([settings])#

setupPrimary is used to change the default 'fork' behavior. Once called, the settings will be present in cluster.settings.

Any settings changes only affect future calls to .fork() and have no effect on workers that are already running.

The only attribute of a worker that cannot be set via .setupPrimary() is 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.

import cluster from 'node: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 workerconst cluster = require('node: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

This can only be called from the primary process.

cluster.worker#

A reference to the current worker object. Not available in the primary process.

import cluster from 'node: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}`);
}const cluster = require('node: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}`);
}

cluster.workers#

A hash that stores the active worker objects, keyed by id field. This makes it easy to loop through all the workers. It is only available in the primary process.

A worker is removed from cluster.workers after the worker has disconnected 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 the last 'disconnect' or 'exit' event is emitted.

import cluster from 'node:cluster';

for (const worker of Object.values(cluster.workers)) {
  worker.send('big announcement to all workers');
}const cluster = require('node:cluster');

for (const worker of Object.values(cluster.workers)) {
  worker.send('big announcement to all workers');
}

Command-line API#

Node.js comes with a variety of CLI options. These options expose built-in debugging, multiple ways to execute scripts, and other helpful runtime options.

To view this documentation as a manual page in a terminal, run man node.

Synopsis#

node [options] [V8 options] [<program-entry-point> | -e "script" | -] [--] [arguments]

node inspect [<program-entry-point> | -e "script" | <host>:<port>] …

node --v8-options

Execute without arguments to start the REPL.

For more info about node inspect, see the debugger documentation.

Program entry point#

The program entry point is a specifier-like string. If the string is not an absolute path, it's resolved as a relative path from the current working directory. That path is then resolved by CommonJS module loader. If no corresponding file is found, an error is thrown.

If a file is found, its path will be passed to the ES module loader under any of the following conditions:

  • The program was started with a command-line flag that forces the entry point to be loaded with ECMAScript module loader, such as --import.
  • The file has an .mjs or .wasm (with --experimental-wasm-modules) extension.
  • The file does not have a .cjs extension, and the nearest parent package.json file contains a top-level "type" field with a value of "module".

Otherwise, the file is loaded using the CommonJS module loader. See Modules loaders for more details.

ECMAScript modules loader entry point caveat#

When loading, the ES module loader loads the program entry point, the node command will accept as input only files with .js, .mjs, or .cjs extensions. With the following flags, additional file extensions are enabled:

Options#

Stability: 2 - Stable

All options, including V8 options, allow words to be separated by both dashes (-) or underscores (_). For example, --pending-deprecation is equivalent to --pending_deprecation.

If an option that takes a single value (such as --max-http-header-size) is passed more than once, then the last passed value is used. Options from the command line take precedence over options passed through the NODE_OPTIONS environment variable.

-#

Alias for stdin. Analogous to the use of - in other command-line utilities, meaning that the script is read from stdin, and the rest of the options are passed to that script.

--#

Indicate the end of node options. Pass the rest of the arguments to the script. If no script filename or eval/print script is supplied prior to this, then the next argument is used as a script filename.

--abort-on-uncaught-exception#

Aborting instead of exiting causes a core file to be generated for post-mortem analysis using a debugger (such as lldb, gdb, and mdb).

If this flag is passed, the behavior can still be set to not abort through process.setUncaughtExceptionCaptureCallback() (and through usage of the node:domain module that uses it).

--allow-addons#

Stability: 1.1 - Active development

When using the Permission Model, the process will not be able to use native addons by default. Attempts to do so will throw an ERR_DLOPEN_DISABLED unless the user explicitly passes the --allow-addons flag when starting Node.js.

Example:

// Attempt to require an native addon
require('nodejs-addon-example'); 
$ node --permission --allow-fs-read=* index.js
node:internal/modules/cjs/loader:1319
  return process.dlopen(module, path.toNamespacedPath(filename));
                 ^

Error: Cannot load native addon because loading addons is disabled.
    at Module._extensions..node (node:internal/modules/cjs/loader:1319:18)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12)
    at Module.require (node:internal/modules/cjs/loader:1115:19)
    at require (node:internal/modules/helpers:130:18)
    at Object.<anonymous> (/home/index.js:1:15)
    at Module._compile (node:internal/modules/cjs/loader:1233:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1287:10)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12) {
  code: 'ERR_DLOPEN_DISABLED'
} 

--allow-child-process#

Stability: 1.1 - Active development

When using the Permission Model, the process will not be able to spawn any child process by default. Attempts to do so will throw an ERR_ACCESS_DENIED unless the user explicitly passes the --allow-child-process flag when starting Node.js.

Example:

const childProcess = require('node:child_process');
// Attempt to bypass the permission
childProcess.spawn('node', ['-e', 'require("fs").writeFileSync("/new-file", "example")']); 
$ node --permission --allow-fs-read=* index.js
node:internal/child_process:388
  const err = this._handle.spawn(options);
                           ^
Error: Access to this API has been restricted
    at ChildProcess.spawn (node:internal/child_process:388:28)
    at node:internal/main/run_main_module:17:47 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'ChildProcess'
} 

Unlike child_process.spawn, the child_process.fork API copies the execution arguments from the parent process. This means that if you start Node.js with the Permission Model enabled and include the --allow-child-process flag, calling child_process.fork() will propagate all Permission Model flags to the child process.

--allow-fs-read#

This flag configures file system read permissions using the Permission Model.

The valid arguments for the --allow-fs-read flag are:

  • * - To allow all FileSystemRead operations.
  • Multiple paths can be allowed using multiple --allow-fs-read flags. Example --allow-fs-read=/folder1/ --allow-fs-read=/folder1/

Examples can be found in the File System Permissions documentation.

The initializer module also needs to be allowed. Consider the following example:

$ node --permission index.js

Error: Access to this API has been restricted
    at node:internal/main/run_main_module:23:47 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'FileSystemRead',
  resource: '/Users/rafaelgss/repos/os/node/index.js'
} 

The process needs to have access to the index.js module:

node --permission --allow-fs-read=/path/to/index.js index.js 

--allow-fs-write#

This flag configures file system write permissions using the Permission Model.

The valid arguments for the --allow-fs-write flag are:

  • * - To allow all FileSystemWrite operations.
  • Multiple paths can be allowed using multiple --allow-fs-write flags. Example --allow-fs-write=/folder1/ --allow-fs-write=/folder1/

Paths delimited by comma (,) are no longer allowed. When passing a single flag with a comma a warning will be displayed.

Examples can be found in the File System Permissions documentation.

--allow-wasi#

Stability: 1.1 - Active development

When using the Permission Model, the process will not be capable of creating any WASI instances by default. For security reasons, the call will throw an ERR_ACCESS_DENIED unless the user explicitly passes the flag --allow-wasi in the main Node.js process.

Example:

const { WASI } = require('node:wasi');
// Attempt to bypass the permission
new WASI({
  version: 'preview1',
  // Attempt to mount the whole filesystem
  preopens: {
    '/': '/',
  },
}); 
$ node --permission --allow-fs-read=* index.js

Error: Access to this API has been restricted
    at node:internal/main/run_main_module:30:49 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'WASI',
} 

--allow-worker#

Stability: 1.1 - Active development

When using the Permission Model, the process will not be able to create any worker threads by default. For security reasons, the call will throw an ERR_ACCESS_DENIED unless the user explicitly pass the flag --allow-worker in the main Node.js process.

Example:

const { Worker } = require('node:worker_threads');
// Attempt to bypass the permission
new Worker(__filename); 
$ node --permission --allow-fs-read=* index.js

Error: Access to this API has been restricted
    at node:internal/main/run_main_module:17:47 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'WorkerThreads'
} 

--build-snapshot#

Stability: 1 - Experimental

Generates a snapshot blob when the process exits and writes it to disk, which can be loaded later with --snapshot-blob.

When building the snapshot, if --snapshot-blob is not specified, the generated blob will be written, by default, to snapshot.blob in the current working directory. Otherwise it will be written to the path specified by --snapshot-blob.

$ echo "globalThis.foo = 'I am from the snapshot'" > snapshot.js

# Run snapshot.js to initialize the application and snapshot the
# state of it into snapshot.blob.
$ node --snapshot-blob snapshot.blob --build-snapshot snapshot.js

$ echo "console.log(globalThis.foo)" > index.js

# Load the generated snapshot and start the application from index.js.
$ node --snapshot-blob snapshot.blob index.js
I am from the snapshot 

The v8.startupSnapshot API can be used to specify an entry point at snapshot building time, thus avoiding the need of an additional entry script at deserialization time:

$ echo "require('v8').startupSnapshot.setDeserializeMainFunction(() => console.log('I am from the snapshot'))" > snapshot.js
$ node --snapshot-blob snapshot.blob --build-snapshot snapshot.js
$ node --snapshot-blob snapshot.blob
I am from the snapshot 

For more information, check out the v8.startupSnapshot API documentation.

Currently the support for run-time snapshot is experimental in that:

  1. User-land modules are not yet supported in the snapshot, so only one single file can be snapshotted. Users can bundle their applications into a single script with their bundler of choice before building a snapshot, however.
  2. Only a subset of the built-in modules work in the snapshot, though the Node.js core test suite checks that a few fairly complex applications can be snapshotted. Support for more modules are being added. If any crashes or buggy behaviors occur when building a snapshot, please file a report in the Node.js issue tracker and link to it in the tracking issue for user-land snapshots.

--build-snapshot-config#

Stability: 1 - Experimental

Specifies the path to a JSON configuration file which configures snapshot creation behavior.

The following options are currently supported:

  • builder <string> Required. Provides the name to the script that is executed before building the snapshot, as if --build-snapshot had been passed with builder as the main script name.
  • withoutCodeCache <boolean> Optional. Including the code cache reduces the time spent on compiling functions included in the snapshot at the expense of a bigger snapshot size and potentially breaking portability of the snapshot.

When using this flag, additional script files provided on the command line will not be executed and instead be interpreted as regular command line arguments.

-c, --check#

Syntax check the script without executing.

--completion-bash#

Print source-able bash completion script for Node.js.

node --completion-bash > node_bash_completion
source node_bash_completion 

-C condition, --conditions=condition#

Provide custom conditional exports resolution conditions.

Any number of custom string condition names are permitted.

The default Node.js conditions of "node", "default", "import", and "require" will always apply as defined.

For example, to run a module with "development" resolutions:

node -C development app.js 

--cpu-prof#

Starts the V8 CPU profiler on start up, and writes the CPU profile to disk before exit.

If --cpu-prof-dir is not specified, the generated profile is placed in the current working directory.

If --cpu-prof-name is not specified, the generated profile is named CPU.${yyyymmdd}.${hhmmss}.${pid}.${tid}.${seq}.cpuprofile.

$ node --cpu-prof index.js
$ ls *.cpuprofile
CPU.20190409.202950.15293.0.0.cpuprofile 

If --cpu-prof-name is specified, the provided value will be used as-is; patterns such as ${hhmmss} or ${pid} are not supported.

$ node --cpu-prof --cpu-prof-name 'CPU.${pid}.cpuprofile' index.js
$ ls *.cpuprofile
'CPU.${pid}.cpuprofile' 

--cpu-prof-dir#

Specify the directory where the CPU profiles generated by --cpu-prof will be placed.

The default value is controlled by the --diagnostic-dir command-line option.

--cpu-prof-interval#

Specify the sampling interval in microseconds for the CPU profiles generated by --cpu-prof. The default is 1000 microseconds.

--cpu-prof-name#

Specify the file name of the CPU profile generated by --cpu-prof.

--diagnostic-dir=directory#

Set the directory to which all diagnostic output files are written. Defaults to current working directory.

Affects the default output directory of:

--disable-proto=mode#

Disable the Object.prototype.__proto__ property. If mode is delete, the property is removed entirely. If mode is throw, accesses to the property throw an exception with the code ERR_PROTO_ACCESS.

--disable-sigusr1#

Stability: 1.2 - Release candidate

Disable the ability of starting a debugging session by sending a SIGUSR1 signal to the process.

--disable-warning=code-or-type#

Stability: 1.1 - Active development

Disable specific process warnings by code or type.

Warnings emitted from process.emitWarning() may contain a code and a type. This option will not-emit warnings that have a matching code or type.

List of deprecation warnings.

The Node.js core warning types are: DeprecationWarning and ExperimentalWarning

For example, the following script will not emit DEP0025 require('node:sys') when executed with node --disable-warning=DEP0025:

import sys from 'node:sys';const sys = require('node:sys');

For example, the following script will emit the DEP0025 require('node:sys'), but not any Experimental Warnings (such as ExperimentalWarning: vm.measureMemory is an experimental feature in <=v21) when executed with node --disable-warning=ExperimentalWarning:

import sys from 'node:sys';
import vm from 'node:vm';

vm.measureMemory();const sys = require('node:sys');
const vm = require('node:vm');

vm.measureMemory();

--disable-wasm-trap-handler#

By default, Node.js enables trap-handler-based WebAssembly bound checks. As a result, V8 does not need to insert inline bound checks int the code compiled from WebAssembly which may speedup WebAssembly execution significantly, but this optimization requires allocating a big virtual memory cage (currently 10GB). If the Node.js process does not have access to a large enough virtual memory address space due to system configurations or hardware limitations, users won't be able to run any WebAssembly that involves allocation in this virtual memory cage and will see an out-of-memory error.

$ ulimit -v 5000000
$ node -p "new WebAssembly.Memory({ initial: 10, maximum: 100 });"
[eval]:1
new WebAssembly.Memory({ initial: 10, maximum: 100 });
^

RangeError: WebAssembly.Memory(): could not allocate memory
    at [eval]:1:1
    at runScriptInThisContext (node:internal/vm:209:10)
    at node:internal/process/execution:118:14
    at [eval]-wrapper:6:24
    at runScript (node:internal/process/execution:101:62)
    at evalScript (node:internal/process/execution:136:3)
    at node:internal/main/eval_string:49:3
 

--disable-wasm-trap-handler disables this optimization so that users can at least run WebAssembly (with less optimal performance) when the virtual memory address space available to their Node.js process is lower than what the V8 WebAssembly memory cage needs.

--disallow-code-generation-from-strings#

Make built-in language features like eval and new Function that generate code from strings throw an exception instead. This does not affect the Node.js node:vm module.

--dns-result-order=order#

Set the default value of order in dns.lookup() and dnsPromises.lookup(). The value could be:

  • ipv4first: sets default order to ipv4first.
  • ipv6first: sets default order to ipv6first.
  • verbatim: sets default order to verbatim.

The default is verbatim and dns.setDefaultResultOrder() have higher priority than --dns-result-order.

--enable-fips#

Enable FIPS-compliant crypto at startup. (Requires Node.js to be built against FIPS-compatible OpenSSL.)

--enable-network-family-autoselection#

Enables the family autoselection algorithm unless connection options explicitly disables it.

--enable-source-maps#

Enable Source Map v3 support for stack traces.

When using a transpiler, such as TypeScript, stack traces thrown by an application reference the transpiled code, not the original source position. --enable-source-maps enables caching of Source Maps and makes a best effort to report stack traces relative to the original source file.

Overriding Error.prepareStackTrace may prevent --enable-source-maps from modifying the stack trace. Call and return the results of the original Error.prepareStackTrace in the overriding function to modify the stack trace with source maps.

const originalPrepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = (error, trace) => {
  // Modify error and trace and format stack trace with
  // original Error.prepareStackTrace.
  return originalPrepareStackTrace(error, trace);
}; 

Note, enabling source maps can introduce latency to your application when Error.stack is accessed. If you access Error.stack frequently in your application, take into account the performance implications of --enable-source-maps.

--entry-url#

Stability: 1 - Experimental

When present, Node.js will interpret the entry point as a URL, rather than a path.

Follows ECMAScript module resolution rules.

Any query parameter or hash in the URL will be accessible via import.meta.url.

node --entry-url 'file:///path/to/file.js?queryparams=work#and-hashes-too'
node --entry-url 'file.ts?query#hash'
node --entry-url 'data:text/javascript,console.log("Hello")' 

--env-file-if-exists=config#

Stability: 1.1 - Active development

Behavior is the same as --env-file, but an error is not thrown if the file does not exist.

--env-file=config#

Stability: 1.1 - Active development

Loads environment variables from a file relative to the current directory, making them available to applications on process.env. The environment variables which configure Node.js, such as NODE_OPTIONS, are parsed and applied. If the same variable is defined in the environment and in the file, the value from the environment takes precedence.

You can pass multiple --env-file arguments. Subsequent files override pre-existing variables defined in previous files.

An error is thrown if the file does not exist.

node --env-file=.env --env-file=.development.env index.js 

The format of the file should be one line per key-value pair of environment variable name and value separated by =:

PORT=3000 

Any text after a # is treated as a comment:

# This is a comment
PORT=3000 # This is also a comment 

Values can start and end with the following quotes: `, " or '. They are omitted from the values.

USERNAME="nodejs" # will result in `nodejs` as the value. 

Multi-line values are supported:

MULTI_LINE="THIS IS
A MULTILINE"
# will result in `THIS IS\nA MULTILINE` as the value. 

Export keyword before a key is ignored:

export USERNAME="nodejs" # will result in `nodejs` as the value. 

If you want to load environment variables from a file that may not exist, you can use the --env-file-if-exists flag instead.

-e, --eval "script"#

Evaluate the following argument as JavaScript. The modules which are predefined in the REPL can also be used in script.

On Windows, using cmd.exe a single quote will not work correctly because it only recognizes double " for quoting. In Powershell or Git bash, both ' and " are usable.

It is possible to run code containing inline types unless the --no-experimental-strip-types flag is provided.

--experimental-addon-modules#

Stability: 1.0 - Early development

Enable experimental import support for .node addons.

--experimental-config-file=config#

Stability: 1.0 - Early development

If present, Node.js will look for a configuration file at the specified path. Node.js will read the configuration file and apply the settings. The configuration file should be a JSON file with the following structure. vX.Y.Z in the $schema must be replaced with the version of Node.js you are using.

{
  "$schema": "https://nodejs.org/dist/vX.Y.Z/docs/node-config-schema.json",
  "nodeOptions": {
    "import": [
      "amaro/strip"
    ],
    "watch-path": "src",
    "watch-preserve-output": true
  }
} 

In the nodeOptions field, only flags that are allowed in NODE_OPTIONS are supported. No-op flags are not supported. Not all V8 flags are currently supported.

It is possible to use the official JSON schema to validate the configuration file, which may vary depending on the Node.js version. Each key in the configuration file corresponds to a flag that can be passed as a command-line argument. The value of the key is the value that would be passed to the flag.

For example, the configuration file above is equivalent to the following command-line arguments:

node --import amaro/strip --watch-path=src --watch-preserve-output 

The priority in configuration is as follows:

  1. NODE_OPTIONS and command-line options
  2. Configuration file
  3. Dotenv NODE_OPTIONS

Values in the configuration file will not override the values in the environment variables and command-line options, but will override the values in the NODE_OPTIONS env file parsed by the --env-file flag.

If duplicate keys are present in the configuration file, only the first key will be used.

The configuration parser will throw an error if the configuration file contains unknown keys or keys that cannot used in NODE_OPTIONS.

Node.js will not sanitize or perform validation on the user-provided configuration, so NEVER use untrusted configuration files.

--experimental-default-config-file#

Stability: 1.0 - Early development

If the --experimental-default-config-file flag is present, Node.js will look for a node.config.json file in the current working directory and load it as a as configuration file.

--experimental-eventsource#

Enable exposition of EventSource Web API on the global scope.

--experimental-import-meta-resolve#

Enable experimental import.meta.resolve() parent URL support, which allows passing a second parentURL argument for contextual resolution.

Previously gated the entire import.meta.resolve feature.

--experimental-loader=module#

This flag is discouraged and may be removed in a future version of Node.js. Please use --import with register() instead.

Specify the module containing exported module customization hooks. module may be any string accepted as an import specifier.

This feature requires --allow-worker if used with the Permission Model.

--experimental-network-inspection#

Stability: 1 - Experimental

Enable experimental support for the network inspection with Chrome DevTools.

--experimental-print-required-tla#

If the ES module being require()'d contains top-level await, this flag allows Node.js to evaluate the module, try to locate the top-level awaits, and print their location to help users find them.

--experimental-require-module#

Stability: 1.1 - Active Development

Supports loading a synchronous ES module graph in require().

See Loading ECMAScript modules using require().

--experimental-sea-config#

Stability: 1 - Experimental

Use this flag to generate a blob that can be injected into the Node.js binary to produce a single executable application. See the documentation about this configuration for details.

--experimental-shadow-realm#

Use this flag to enable ShadowRealm support.

--experimental-test-coverage#

When used in conjunction with the node:test module, a code coverage report is generated as part of the test runner output. If no tests are run, a coverage report is not generated. See the documentation on collecting code coverage from tests for more details.

--experimental-test-module-mocks#

Stability: 1.0 - Early development

Enable module mocking in the test runner.

This feature requires --allow-worker if used with the Permission Model.

--experimental-transform-types#

Stability: 1.2 - Release candidate

Enables the transformation of TypeScript-only syntax into JavaScript code. Implies --enable-source-maps.

--experimental-vm-modules#

Enable experimental ES Module support in the node:vm module.

--experimental-wasi-unstable-preview1#

Enable experimental WebAssembly System Interface (WASI) support.

--experimental-wasm-modules#

Enable experimental WebAssembly module support.

--experimental-webstorage#

Enable experimental Web Storage support.

--experimental-worker-inspection#

Stability: 1.1 - Active Development

Enable experimental support for the worker inspection with Chrome DevTools.

--expose-gc#

Stability: 1 - Experimental. This flag is inherited from V8 and is subject to change upstream.

This flag will expose the gc extension from V8.

if (globalThis.gc) {
  globalThis.gc();
} 

--force-context-aware#

Disable loading native addons that are not context-aware.

--force-fips#

Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.) (Same requirements as --enable-fips.)

--force-node-api-uncaught-exceptions-policy#

Enforces uncaughtException event on Node-API asynchronous callbacks.

To prevent from an existing add-on from crashing the process, this flag is not enabled by default. In the future, this flag will be enabled by default to enforce the correct behavior.

--frozen-intrinsics#

Stability: 1 - Experimental

Enable experimental frozen intrinsics like Array and Object.

Only the root context is supported. There is no guarantee that globalThis.Array is indeed the default intrinsic reference. Code may break under this flag.

To allow polyfills to be added, --require and --import both run before freezing intrinsics.

--heap-prof#

Starts the V8 heap profiler on start up, and writes the heap profile to disk before exit.

If --heap-prof-dir is not specified, the generated profile is placed in the current working directory.

If --heap-prof-name is not specified, the generated profile is named Heap.${yyyymmdd}.${hhmmss}.${pid}.${tid}.${seq}.heapprofile.

$ node --heap-prof index.js
$ ls *.heapprofile
Heap.20190409.202950.15293.0.001.heapprofile 

--heap-prof-dir#

Specify the directory where the heap profiles generated by --heap-prof will be placed.

The default value is controlled by the --diagnostic-dir command-line option.

--heap-prof-interval#

Specify the average sampling interval in bytes for the heap profiles generated by --heap-prof. The default is 512 * 1024 bytes.

--heap-prof-name#

Specify the file name of the heap profile generated by --heap-prof.

--heapsnapshot-near-heap-limit=max_count#

Stability: 1 - Experimental

Writes a V8 heap snapshot to disk when the V8 heap usage is approaching the heap limit. count should be a non-negative integer (in which case Node.js will write no more than max_count snapshots to disk).

When generating snapshots, garbage collection may be triggered and bring the heap usage down. Therefore multiple snapshots may be written to disk before the Node.js instance finally runs out of memory. These heap snapshots can be compared to determine what objects are being allocated during the time consecutive snapshots are taken. It's not guaranteed that Node.js will write exactly max_count snapshots to disk, but it will try its best to generate at least one and up to max_count snapshots before the Node.js instance runs out of memory when max_count is greater than 0.

Generating V8 snapshots takes time and memory (both memory managed by the V8 heap and native memory outside the V8 heap). The bigger the heap is, the more resources it needs. Node.js will adjust the V8 heap to accommodate the additional V8 heap memory overhead, and try its best to avoid using up all the memory available to the process. When the process uses more memory than the system deems appropriate, the process may be terminated abruptly by the system, depending on the system configuration.

$ node --max-old-space-size=100 --heapsnapshot-near-heap-limit=3 index.js
Wrote snapshot to Heap.20200430.100036.49580.0.001.heapsnapshot
Wrote snapshot to Heap.20200430.100037.49580.0.002.heapsnapshot
Wrote snapshot to Heap.20200430.100038.49580.0.003.heapsnapshot

<--- Last few GCs --->

[49580:0x110000000]     4826 ms: Mark-sweep 130.6 (147.8) -> 130.5 (147.8) MB, 27.4 / 0.0 ms  (average mu = 0.126, current mu = 0.034) allocation failure scavenge might not succeed
[49580:0x110000000]     4845 ms: Mark-sweep 130.6 (147.8) -> 130.6 (147.8) MB, 18.8 / 0.0 ms  (average mu = 0.088, current mu = 0.031) allocation failure scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
.... 

--heapsnapshot-signal=signal#

Enables a signal handler that causes the Node.js process to write a heap dump when the specified signal is received. signal must be a valid signal name. Disabled by default.

$ node --heapsnapshot-signal=SIGUSR2 index.js &
$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
node         1  5.5  6.1 787252 247004 ?       Ssl  16:43   0:02 node --heapsnapshot-signal=SIGUSR2 index.js
$ kill -USR2 1
$ ls
Heap.20190718.133405.15554.0.001.heapsnapshot 

-h, --help#

Print node command-line options. The output of this option is less detailed than this document.

--icu-data-dir=file#

Specify ICU data load path. (Overrides NODE_ICU_DATA.)

--import=module#

Stability: 1 - Experimental

Preload the specified module at startup. If the flag is provided several times, each module will be executed sequentially in the order they appear, starting with the ones provided in NODE_OPTIONS.

Follows ECMAScript module resolution rules. Use --require to load a CommonJS module. Modules preloaded with --require will run before modules preloaded with --import.

Modules are preloaded into the main thread as well as any worker threads, forked processes, or clustered processes.

--input-type=type#

This configures Node.js to interpret --eval or STDIN input as CommonJS or as an ES module. Valid values are "commonjs", "module", "module-typescript" and "commonjs-typescript". The "-typescript" values are not available with the flag --no-experimental-strip-types. The default is no value, or "commonjs" if --no-experimental-detect-module is passed.

If --input-type is not provided, Node.js will try to detect the syntax with the following steps:

  1. Run the input as CommonJS.
  2. If step 1 fails, run the input as an ES module.
  3. If step 2 fails with a SyntaxError, strip the types.
  4. If step 3 fails with an error code ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX or ERR_INVALID_TYPESCRIPT_SYNTAX, throw the error from step 2, including the TypeScript error in the message, else run as CommonJS.
  5. If step 4 fails, run the input as an ES module.

To avoid the delay of multiple syntax detection passes, the --input-type=type flag can be used to specify how the --eval input should be interpreted.

The REPL does not support this option. Usage of --input-type=module with --print will throw an error, as --print does not support ES module syntax.

--insecure-http-parser#

Enable leniency flags on the HTTP parser. This may allow interoperability with non-conformant HTTP implementations.

When enabled, the parser will accept the following:

  • Invalid HTTP headers values.
  • Invalid HTTP versions.
  • Allow message containing both Transfer-Encoding and Content-Length headers.
  • Allow extra data after message when Connection: close is present.
  • Allow extra transfer encodings after chunked has been provided.
  • Allow \n to be used as token separator instead of \r\n.
  • Allow \r\n not to be provided after a chunk.
  • Allow spaces to be present after a chunk size and before \r\n.

All the above will expose your application to request smuggling or poisoning attack. Avoid using this option.

Warning: binding inspector to a public IP:port combination is insecure#

Binding the inspector to a public IP (including 0.0.0.0) with an open port is insecure, as it allows external hosts to connect to the inspector and perform a remote code execution attack.

If specifying a host, make sure that either:

  • The host is not accessible from public networks.
  • A firewall disallows unwanted connections on the port.

More specifically, --inspect=0.0.0.0 is insecure if the port (9229 by default) is not firewall-protected.

See the debugging security implications section for more information.

--inspect-brk[=[host:]port]#

Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229. If port 0 is specified, a random available port will be used.

See V8 Inspector integration for Node.js for further explanation on Node.js debugger.

--inspect-port=[host:]port#

Set the host:port to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Except when --disable-sigusr1 is passed.

Default host is 127.0.0.1. If port 0 is specified, a random available port will be used.

See the security warning below regarding the host parameter usage.

--inspect-publish-uid=stderr,http#

Specify ways of the inspector web socket url exposure.

By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.

--inspect-wait[=[host:]port]#

Activate inspector on host:port and wait for debugger to be attached. Default host:port is 127.0.0.1:9229. If port 0 is specified, a random available port will be used.

See V8 Inspector integration for Node.js for further explanation on Node.js debugger.

--inspect[=[host:]port]#

Activate inspector on host:port. Default is 127.0.0.1:9229. If port 0 is specified, a random available port will be used.

V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Node.js instances. The tools attach to Node.js instances via a tcp port and communicate using the Chrome DevTools Protocol. See V8 Inspector integration for Node.js for further explanation on Node.js debugger.

-i, --interactive#

Opens the REPL even if stdin does not appear to be a terminal.

--jitless#

Stability: 1 - Experimental. This flag is inherited from V8 and is subject to change upstream.

Disable runtime allocation of executable memory. This may be required on some platforms for security reasons. It can also reduce attack surface on other platforms, but the performance impact may be severe.

--localstorage-file=file#

The file used to store localStorage data. If the file does not exist, it is created the first time localStorage is accessed. The same file may be shared between multiple Node.js processes concurrently. This flag is a no-op unless Node.js is started with the --experimental-webstorage flag.

--max-http-header-size=size#

Specify the maximum size, in bytes, of HTTP headers. Defaults to 16 KiB.

--napi-modules#

This option is a no-op. It is kept for compatibility.

--network-family-autoselection-attempt-timeout#

Sets the default value for the network family autoselection attempt timeout. For more information, see net.getDefaultAutoSelectFamilyAttemptTimeout().

--no-addons#

Disable the node-addons exports condition as well as disable loading native addons. When --no-addons is specified, calling process.dlopen or requiring a native C++ addon will fail and throw an exception.

--no-async-context-frame#

Disables the use of AsyncLocalStorage backed by AsyncContextFrame and uses the prior implementation which relied on async_hooks. The previous model is retained for compatibility with Electron and for cases where the context flow may differ. However, if a difference in flow is found please report it.

--no-deprecation#

Silence deprecation warnings.

--no-experimental-detect-module#

Disable using syntax detection to determine module type.

--no-experimental-global-navigator#

Stability: 1 - Experimental

Disable exposition of Navigator API on the global scope.

--no-experimental-repl-await#

Use this flag to disable top-level await in REPL.

--no-experimental-require-module#

Stability: 1.1 - Active Development

Disable support for loading a synchronous ES module graph in require().

See Loading ECMAScript modules using require().

--no-experimental-sqlite#

Disable the experimental node:sqlite module.

--no-experimental-strip-types#

Stability: 1.2 - Release candidate

Disable experimental type-stripping for TypeScript files. For more information, see the TypeScript type-stripping documentation.

--no-experimental-websocket#

Disable exposition of WebSocket on the global scope.

--no-extra-info-on-fatal-exception#

Hide extra information on fatal exception that causes exit.

--no-force-async-hooks-checks#

Disables runtime checks for async_hooks. These will still be enabled dynamically when async_hooks is enabled.

--no-global-search-paths#

Do not search modules from global paths like $HOME/.node_modules and $NODE_PATH.

--no-network-family-autoselection#

Disables the family autoselection algorithm unless connection options explicitly enables it.

--no-warnings#

Silence all process warnings (including deprecations).

--node-memory-debug#

Enable extra debug checks for memory leaks in Node.js internals. This is usually only useful for developers debugging Node.js itself.

--openssl-config=file#

Load an OpenSSL configuration file on startup. Among other uses, this can be used to enable FIPS-compliant crypto if Node.js is built against FIPS-enabled OpenSSL.

--openssl-legacy-provider#

Enable OpenSSL 3.0 legacy provider. For more information please see OSSL_PROVIDER-legacy.

--openssl-shared-config#

Enable OpenSSL default configuration section, openssl_conf to be read from the OpenSSL configuration file. The default configuration file is named openssl.cnf but this can be changed using the environment variable OPENSSL_CONF, or by using the command line option --openssl-config. The location of the default OpenSSL configuration file depends on how OpenSSL is being linked to Node.js. Sharing the OpenSSL configuration may have unwanted implications and it is recommended to use a configuration section specific to Node.js which is nodejs_conf and is default when this option is not used.

--pending-deprecation#

Emit pending deprecation warnings.

Pending deprecations are generally identical to a runtime deprecation with the notable exception that they are turned off by default and will not be emitted unless either the --pending-deprecation command-line flag, or the NODE_PENDING_DEPRECATION=1 environment variable, is set. Pending deprecations are used to provide a kind of selective "early warning" mechanism that developers may leverage to detect deprecated API usage.

--permission#

Enable the Permission Model for current process. When enabled, the following permissions are restricted:

--preserve-symlinks#

Instructs the module loader to preserve symbolic links when resolving and caching modules.

By default, when Node.js loads a module from a path that is symbolically linked to a different on-disk location, Node.js will dereference the link and use the actual on-disk "real path" of the module as both an identifier and as a root path to locate other dependency modules. In most cases, this default behavior is acceptable. However, when using symbolically linked peer dependencies, as illustrated in the example below, the default behavior causes an exception to be thrown if moduleA attempts to require moduleB as a peer dependency:

{appDir}
 ├── app
 │   ├── index.js
 │   └── node_modules
 │       ├── moduleA -> {appDir}/moduleA
 │       └── moduleB
 │           ├── index.js
 │           └── package.json
 └── moduleA
     ├── index.js
     └── package.json 

The --preserve-symlinks command-line flag instructs Node.js to use the symlink path for modules as opposed to the real path, allowing symbolically linked peer dependencies to be found.

Note, however, that using --preserve-symlinks can have other side effects. Specifically, symbolically linked native modules can fail to load if those are linked from more than one location in the dependency tree (Node.js would see those as two separate modules and would attempt to load the module multiple times, causing an exception to be thrown).

The --preserve-symlinks flag does not apply to the main module, which allows node --preserve-symlinks node_module/.bin/<foo> to work. To apply the same behavior for the main module, also use --preserve-symlinks-main.

--preserve-symlinks-main#

Instructs the module loader to preserve symbolic links when resolving and caching the main module (require.main).

This flag exists so that the main module can be opted-in to the same behavior that --preserve-symlinks gives to all other imports; they are separate flags, however, for backward compatibility with older Node.js versions.

--preserve-symlinks-main does not imply --preserve-symlinks; use --preserve-symlinks-main in addition to --preserve-symlinks when it is not desirable to follow symlinks before resolving relative paths.

See --preserve-symlinks for more information.

-p, --print "script"#

Identical to -e but prints the result.

--prof#

Generate V8 profiler output.

--prof-process#

Process V8 profiler output generated using the V8 option --prof.

--redirect-warnings=file#

Write process warnings to the given file instead of printing to stderr. The file will be created if it does not exist, and will be appended to if it does. If an error occurs while attempting to write the warning to the file, the warning will be written to stderr instead.

The file name may be an absolute path. If it is not, the default directory it will be written to is controlled by the --diagnostic-dir command-line option.

--report-compact#

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.

--report-dir=directory, report-directory=directory#

Location at which the report will be generated.

--report-exclude-env#

When --report-exclude-env is passed the diagnostic report generated will not contain the environmentVariables data.

--report-exclude-network#

Exclude header.networkInterfaces from the diagnostic report. By default this is not set and the network interfaces are included.

--report-filename=filename#

Name of the file to which the report will be written.

If the filename is set to 'stdout' or 'stderr', the report is written to the stdout or stderr of the process respectively.

--report-on-fatalerror#

Enables the report to be triggered on fatal errors (internal errors within the Node.js runtime such as out of memory) that lead to termination of the application. Useful to inspect various diagnostic data elements such as heap, stack, event loop state, resource consumption etc. to reason about the fatal error.

--report-on-signal#

Enables report to be generated upon receiving the specified (or predefined) signal to the running Node.js process. The signal to trigger the report is specified through --report-signal.

--report-signal=signal#

Sets or resets the signal for report generation (not supported on Windows). Default signal is SIGUSR2.

--report-uncaught-exception#

Enables report to be generated when the process exits due to an uncaught exception. Useful when inspecting the JavaScript stack in conjunction with native stack and other runtime environment data.

-r, --require module#

Preload the specified module at startup.

Follows require()'s module resolution rules. module may be either a path to a file, or a node module name.

Modules preloaded with --require will run before modules preloaded with --import.

Modules are preloaded into the main thread as well as any worker threads, forked processes, or clustered processes.

--run#

This runs a specified command from a package.json's "scripts" object. If a missing "command" is provided, it will list the available scripts.

--run will traverse up to the root directory and finds a package.json file to run the command from.

--run prepends ./node_modules/.bin for each ancestor of the current directory, to the PATH in order to execute the binaries from different folders where multiple node_modules directories are present, if ancestor-folder/node_modules/.bin is a directory.

--run executes the command in the directory containing the related package.json.

For example, the following command will run the test script of the package.json in the current folder:

$ node --run test 

You can also pass arguments to the command. Any argument after -- will be appended to the script:

$ node --run test -- --verbose 
Intentional limitations#

node --run is not meant to match the behaviors of npm run or of the run commands of other package managers. The Node.js implementation is intentionally more limited, in order to focus on top performance for the most common use cases. Some features of other run implementations that are intentionally excluded are:

  • Running pre or post scripts in addition to the specified script.
  • Defining package manager-specific environment variables.
Environment variables#

The following environment variables are set when running a script with --run:

  • NODE_RUN_SCRIPT_NAME: The name of the script being run. For example, if --run is used to run test, the value of this variable will be test.
  • NODE_RUN_PACKAGE_JSON_PATH: The path to the package.json that is being processed.

--secure-heap-min=n#

When using --secure-heap, the --secure-heap-min flag specifies the minimum allocation from the secure heap. The minimum value is 2. The maximum value is the lesser of --secure-heap or 2147483647. The value given must be a power of two.

--secure-heap=n#

Initializes an OpenSSL secure heap of n bytes. When initialized, the secure heap is used for selected types of allocations within OpenSSL during key generation and other operations. This is useful, for instance, to prevent sensitive information from leaking due to pointer overruns or underruns.

The secure heap is a fixed size and cannot be resized at runtime so, if used, it is important to select a large enough heap to cover all application uses.

The heap size given must be a power of two. Any value less than 2 will disable the secure heap.

The secure heap is disabled by default.

The secure heap is not available on Windows.

See CRYPTO_secure_malloc_init for more details.

--snapshot-blob=path#

Stability: 1 - Experimental

When used with --build-snapshot, --snapshot-blob specifies the path where the generated snapshot blob is written to. If not specified, the generated blob is written to snapshot.blob in the current working directory.

When used without --build-snapshot, --snapshot-blob specifies the path to the blob that is used to restore the application state.

When loading a snapshot, Node.js checks that:

  1. The version, architecture, and platform of the running Node.js binary are exactly the same as that of the binary that generates the snapshot.
  2. The V8 flags and CPU features are compatible with that of the binary that generates the snapshot.

If they don't match, Node.js refuses to load the snapshot and exits with status code 1.

--test#

Starts the Node.js command line test runner. This flag cannot be combined with --watch-path, --check, --eval, --interactive, or the inspector. See the documentation on running tests from the command line for more details.

--test-concurrency#

The maximum number of test files that the test runner CLI will execute concurrently. If --test-isolation is set to 'none', this flag is ignored and concurrency is one. Otherwise, concurrency defaults to os.availableParallelism() - 1.

--test-coverage-branches=threshold#

Stability: 1 - Experimental

Require a minimum percent of covered branches. If code coverage does not reach the threshold specified, the process will exit with code 1.

--test-coverage-exclude#

Stability: 1 - Experimental

Excludes specific files from code coverage using a glob pattern, which can match both absolute and relative file paths.

This option may be specified multiple times to exclude multiple glob patterns.

If both --test-coverage-exclude and --test-coverage-include are provided, files must meet both criteria to be included in the coverage report.

By default all the matching test files are excluded from the coverage report. Specifying this option will override the default behavior.

--test-coverage-functions=threshold#

Stability: 1 - Experimental

Require a minimum percent of covered functions. If code coverage does not reach the threshold specified, the process will exit with code 1.

--test-coverage-include#

Stability: 1 - Experimental

Includes specific files in code coverage using a glob pattern, which can match both absolute and relative file paths.

This option may be specified multiple times to include multiple glob patterns.

If both --test-coverage-exclude and --test-coverage-include are provided, files must meet both criteria to be included in the coverage report.

--test-coverage-lines=threshold#

Stability: 1 - Experimental

Require a minimum percent of covered lines. If code coverage does not reach the threshold specified, the process will exit with code 1.

--test-force-exit#

Configures the test runner to exit the process once all known tests have finished executing even if the event loop would otherwise remain active.

--test-global-setup=module#

Stability: 1.0 - Early development

Specify a module that will be evaluated before all tests are executed and can be used to setup global state or fixtures for tests.

See the documentation on global setup and teardown for more details.

--test-isolation=mode#

Configures the type of test isolation used in the test runner. When mode is 'process', each test file is run in a separate child process. When mode is 'none', all test files run in the same process as the test runner. The default isolation mode is 'process'. This flag is ignored if the --test flag is not present. See the test runner execution model section for more information.

--test-name-pattern#

A regular expression that configures the test runner to only execute tests whose name matches the provided pattern. See the documentation on filtering tests by name for more details.

If both --test-name-pattern and --test-skip-pattern are supplied, tests must satisfy both requirements in order to be executed.

--test-only#

Configures the test runner to only execute top level tests that have the only option set. This flag is not necessary when test isolation is disabled.

--test-reporter#

A test reporter to use when running tests. See the documentation on test reporters for more details.

--test-reporter-destination#

The destination for the corresponding test reporter. See the documentation on test reporters for more details.

--test-shard#

Test suite shard to execute in a format of <index>/<total>, where

index is a positive integer, index of divided parts total is a positive integer, total of divided part This command will divide all tests files into total equal parts, and will run only those that happen to be in an index part.

For example, to split your tests suite into three parts, use this:

node --test --test-shard=1/3
node --test --test-shard=2/3
node --test --test-shard=3/3 

--test-skip-pattern#

A regular expression that configures the test runner to skip tests whose name matches the provided pattern. See the documentation on filtering tests by name for more details.

If both --test-name-pattern and --test-skip-pattern are supplied, tests must satisfy both requirements in order to be executed.

--test-timeout#

A number of milliseconds the test execution will fail after. If unspecified, subtests inherit this value from their parent. The default value is Infinity.

--test-update-snapshots#

Regenerates the snapshot files used by the test runner for snapshot testing.

--throw-deprecation#

Throw errors for deprecations.

--title=title#

Set process.title on startup.

--tls-cipher-list=list#

Specify an alternative default TLS cipher list. Requires Node.js to be built with crypto support (default).

--tls-keylog=file#

Log TLS key material to a file. The key material is in NSS SSLKEYLOGFILE format and can be used by software (such as Wireshark) to decrypt the TLS traffic.

--tls-max-v1.2#

Set tls.DEFAULT_MAX_VERSION to 'TLSv1.2'. Use to disable support for TLSv1.3.

--tls-max-v1.3#

Set default tls.DEFAULT_MAX_VERSION to 'TLSv1.3'. Use to enable support for TLSv1.3.

--tls-min-v1.0#

Set default tls.DEFAULT_MIN_VERSION to 'TLSv1'. Use for compatibility with old TLS clients or servers.

--tls-min-v1.1#

Set default tls.DEFAULT_MIN_VERSION to 'TLSv1.1'. Use for compatibility with old TLS clients or servers.

--tls-min-v1.2#

Set default tls.DEFAULT_MIN_VERSION to 'TLSv1.2'. This is the default for 12.x and later, but the option is supported for compatibility with older Node.js versions.

--tls-min-v1.3#

Set default tls.DEFAULT_MIN_VERSION to 'TLSv1.3'. Use to disable support for TLSv1.2, which is not as secure as TLSv1.3.

--trace-deprecation#

Print stack traces for deprecations.

--trace-env#

Print information about any access to environment variables done in the current Node.js instance to stderr, including:

  • The environment variable reads that Node.js does internally.
  • Writes in the form of process.env.KEY = "SOME VALUE".
  • Reads in the form of process.env.KEY.
  • Definitions in the form of Object.defineProperty(process.env, 'KEY', {...}).
  • Queries in the form of Object.hasOwn(process.env, 'KEY'), process.env.hasOwnProperty('KEY') or 'KEY' in process.env.
  • Deletions in the form of delete process.env.KEY.
  • Enumerations inf the form of ...process.env or Object.keys(process.env).

Only the names of the environment variables being accessed are printed. The values are not printed.

To print the stack trace of the access, use --trace-env-js-stack and/or --trace-env-native-stack.

--trace-env-js-stack#

In addition to what --trace-env does, this prints the JavaScript stack trace of the access.

--trace-env-native-stack#

In addition to what --trace-env does, this prints the native stack trace of the access.

--trace-event-categories#

A comma separated list of categories that should be traced when trace event tracing is enabled using --trace-events-enabled.

--trace-event-file-pattern#

Template string specifying the filepath for the trace event data, it supports ${rotation} and ${pid}.

--trace-events-enabled#

Enables the collection of trace event tracing information.

--trace-exit#

Prints a stack trace whenever an environment is exited proactively, i.e. invoking process.exit().

--trace-require-module=mode#

Prints information about usage of Loading ECMAScript modules using require().

When mode is all, all usage is printed. When mode is no-node-modules, usage from the node_modules folder is excluded.

--trace-sigint#

Prints a stack trace on SIGINT.

--trace-sync-io#

Prints a stack trace whenever synchronous I/O is detected after the first turn of the event loop.

--trace-tls#

Prints TLS packet trace information to stderr. This can be used to debug TLS connection problems.

--trace-uncaught#

Print stack traces for uncaught exceptions; usually, the stack trace associated with the creation of an Error is printed, whereas this makes Node.js also print the stack trace associated with throwing the value (which does not need to be an Error instance).

Enabling this option may affect garbage collection behavior negatively.

--trace-warnings#

Print stack traces for process warnings (including deprecations).

--track-heap-objects#

Track heap object allocations for heap snapshots.

--unhandled-rejections=mode#

Using this flag allows to change what should happen when an unhandled rejection occurs. One of the following modes can be chosen:

  • throw: Emit unhandledRejection. If this hook is not set, raise the unhandled rejection as an uncaught exception. This is the default.
  • strict: Raise the unhandled rejection as an uncaught exception. If the exception is handled, unhandledRejection is emitted.
  • warn: Always trigger a warning, no matter if the unhandledRejection hook is set or not but do not print the deprecation warning.
  • warn-with-error-code: Emit unhandledRejection. If this hook is not set, trigger a warning, and set the process exit code to 1.
  • none: Silence all warnings.

If a rejection happens during the command line entry point's ES module static loading phase, it will always raise it as an uncaught exception.

--use-bundled-ca, --use-openssl-ca#

Use bundled Mozilla CA store as supplied by current Node.js version or use OpenSSL's default CA store. The default store is selectable at build-time.

The bundled CA store, as supplied by Node.js, is a snapshot of Mozilla CA store that is fixed at release time. It is identical on all supported platforms.

Using OpenSSL store allows for external modifications of the store. For most Linux and BSD distributions, this store is maintained by the distribution maintainers and system administrators. OpenSSL CA store location is dependent on configuration of the OpenSSL library but this can be altered at runtime using environment variables.

See SSL_CERT_DIR and SSL_CERT_FILE.

--use-largepages=mode#

Re-map the Node.js static code to large memory pages at startup. If supported on the target system, this will cause the Node.js static code to be moved onto 2 MiB pages instead of 4 KiB pages.

The following values are valid for mode:

  • off: No mapping will be attempted. This is the default.
  • on: If supported by the OS, mapping will be attempted. Failure to map will be ignored and a message will be printed to standard error.
  • silent: If supported by the OS, mapping will be attempted. Failure to map will be ignored and will not be reported.

--use-system-ca#

Node.js uses the trusted CA certificates present in the system store along with the --use-bundled-ca option and the NODE_EXTRA_CA_CERTS environment variable. On platforms other than Windows and macOS, this loads certificates from the directory and file trusted by OpenSSL, similar to --use-openssl-ca, with the difference being that it caches the certificates after first load.

On Windows and macOS, the certificate trust policy is planned to follow Chromium's policy for locally trusted certificates:

On macOS, the following settings are respected:

  • Default and System Keychains
    • Trust:
      • Any certificate where the “When using this certificate” flag is set to “Always Trust” or
      • Any certificate where the “Secure Sockets Layer (SSL)” flag is set to “Always Trust.”
    • Distrust:
      • Any certificate where the “When using this certificate” flag is set to “Never Trust” or
      • Any certificate where the “Secure Sockets Layer (SSL)” flag is set to “Never Trust.”

On Windows, the following settings are respected (unlike Chromium's policy, distrust and intermediate CA are not currently supported):

  • Local Machine (accessed via certlm.msc)
    • Trust:
      • Trusted Root Certification Authorities
      • Trusted People
      • Enterprise Trust -> Enterprise -> Trusted Root Certification Authorities
      • Enterprise Trust -> Enterprise -> Trusted People
      • Enterprise Trust -> Group Policy -> Trusted Root Certification Authorities
      • Enterprise Trust -> Group Policy -> Trusted People
  • Current User (accessed via certmgr.msc)
    • Trust:
      • Trusted Root Certification Authorities
      • Enterprise Trust -> Group Policy -> Trusted Root Certification Authorities

On Windows and macOS, Node.js would check that the user settings for the certificates do not forbid them for TLS server authentication before using them.

On other systems, Node.js loads certificates from the default certificate file (typically /etc/ssl/cert.pem) and default certificate directory (typically /etc/ssl/certs) that the version of OpenSSL that Node.js links to respects. This typically works with the convention on major Linux distributions and other Unix-like systems. If the overriding OpenSSL environment variables (typically SSL_CERT_FILE and SSL_CERT_DIR, depending on the configuration of the OpenSSL that Node.js links to) are set, the specified paths will be used to load certificates instead. These environment variables can be used as workarounds if the conventional paths used by the version of OpenSSL Node.js links to are not consistent with the system configuration that the users have for some reason.

--v8-options#

Print V8 command-line options.

--v8-pool-size=num#

Set V8's thread pool size which will be used to allocate background jobs.

If set to 0 then Node.js will choose an appropriate size of the thread pool based on an estimate of the amount of parallelism.

The amount of parallelism refers to the number of computations that can be carried out simultaneously in a given machine. In general, it's the same as the amount of CPUs, but it may diverge in environments such as VMs or containers.

-v, --version#

Print node's version.

--watch#

Starts Node.js in watch mode. When in watch mode, changes in the watched files cause the Node.js process to restart. By default, watch mode will watch the entry point and any required or imported module. Use --watch-path to specify what paths to watch.

This flag cannot be combined with --check, --eval, --interactive, or the REPL.

node --watch index.js 

--watch-path#

Starts Node.js in watch mode and specifies what paths to watch. When in watch mode, changes in the watched paths cause the Node.js process to restart. This will turn off watching of required or imported modules, even when used in combination with --watch.

This flag cannot be combined with --check, --eval, --interactive, --test, or the REPL.

node --watch-path=./src --watch-path=./tests index.js 

This option is only supported on macOS and Windows. An ERR_FEATURE_UNAVAILABLE_ON_PLATFORM exception will be thrown when the option is used on a platform that does not support it.

--watch-preserve-output#

Disable the clearing of the console when watch mode restarts the process.

node --watch --watch-preserve-output test.js 

--zero-fill-buffers#

Automatically zero-fills all newly allocated Buffer and SlowBuffer instances.

Environment variables#

Stability: 2 - Stable

FORCE_COLOR=[1, 2, 3]#

The FORCE_COLOR environment variable is used to enable ANSI colorized output. The value may be:

  • 1, true, or the empty string '' indicate 16-color support,
  • 2 to indicate 256-color support, or
  • 3 to indicate 16 million-color support.

When FORCE_COLOR is used and set to a supported value, both the NO_COLOR, and NODE_DISABLE_COLORS environment variables are ignored.

Any other value will result in colorized output being disabled.

NODE_COMPILE_CACHE=dir#

Stability: 1.1 - Active Development

Enable the module compile cache for the Node.js instance. See the documentation of module compile cache for details.

NODE_DEBUG=module[,…]#

','-separated list of core modules that should print debug information.

NODE_DEBUG_NATIVE=module[,…]#

','-separated list of core C++ modules that should print debug information.

NODE_DISABLE_COLORS=1#

When set, colors will not be used in the REPL.

NODE_DISABLE_COMPILE_CACHE=1#

Stability: 1.1 - Active Development

Disable the module compile cache for the Node.js instance. See the documentation of module compile cache for details.

NODE_EXTRA_CA_CERTS=file#

When set, the well known "root" CAs (like VeriSign) will be extended with the extra certificates in file. The file should consist of one or more trusted certificates in PEM format. A message will be emitted (once) with process.emitWarning() if the file is missing or malformed, but any errors are otherwise ignored.

Neither the well known nor extra certificates are used when the ca options property is explicitly specified for a TLS or HTTPS client or server.

This environment variable is ignored when node runs as setuid root or has Linux file capabilities set.

The NODE_EXTRA_CA_CERTS environment variable is only read when the Node.js process is first launched. Changing the value at runtime using process.env.NODE_EXTRA_CA_CERTS has no effect on the current process.

NODE_ICU_DATA=file#

Data path for ICU (Intl object) data. Will extend linked-in data when compiled with small-icu support.

NODE_NO_WARNINGS=1#

When set to 1, process warnings are silenced.

NODE_OPTIONS=options...#

A space-separated list of command-line options. options... are interpreted before command-line options, so command-line options will override or compound after anything in options.... Node.js will exit with an error if an option that is not allowed in the environment is used, such as -p or a script file.

If an option value contains a space, it can be escaped using double quotes:

NODE_OPTIONS='--require "./my path/file.js"' 

A singleton flag passed as a command-line option will override the same flag passed into NODE_OPTIONS:

# The inspector will be available on port 5555
NODE_OPTIONS='--inspect=localhost:4444' node --inspect=localhost:5555 

A flag that can be passed multiple times will be treated as if its NODE_OPTIONS instances were passed first, and then its command-line instances afterwards:

NODE_OPTIONS='--require "./a.js"' node --require "./b.js"
# is equivalent to:
node --require "./a.js" --require "./b.js" 

Node.js options that are allowed are in the following list. If an option supports both --XX and --no-XX variants, they are both supported but only one is included in the list below.

  • --allow-addons
  • --allow-child-process
  • --allow-fs-read
  • --allow-fs-write
  • --allow-wasi
  • --allow-worker
  • --conditions, -C
  • --cpu-prof-dir
  • --cpu-prof-interval
  • --cpu-prof-name
  • --cpu-prof
  • --diagnostic-dir
  • --disable-proto
  • --disable-sigusr1
  • --disable-warning
  • --disable-wasm-trap-handler
  • --dns-result-order
  • --enable-fips
  • --enable-network-family-autoselection
  • --enable-source-maps
  • --entry-url
  • --experimental-abortcontroller
  • --experimental-addon-modules
  • --experimental-detect-module
  • --experimental-eventsource
  • --experimental-import-meta-resolve
  • --experimental-json-modules
  • --experimental-loader
  • --experimental-modules
  • --experimental-print-required-tla
  • --experimental-require-module
  • --experimental-shadow-realm
  • --experimental-specifier-resolution
  • --experimental-test-isolation
  • --experimental-top-level-await
  • --experimental-transform-types
  • --experimental-vm-modules
  • --experimental-wasi-unstable-preview1
  • --experimental-wasm-modules
  • --experimental-webstorage
  • --force-context-aware
  • --force-fips
  • --force-node-api-uncaught-exceptions-policy
  • --frozen-intrinsics
  • --heap-prof-dir
  • --heap-prof-interval
  • --heap-prof-name
  • --heap-prof
  • --heapsnapshot-near-heap-limit
  • --heapsnapshot-signal
  • --http-parser
  • --icu-data-dir
  • --import
  • --input-type
  • --insecure-http-parser
  • --inspect-brk
  • --inspect-port, --debug-port
  • --inspect-publish-uid
  • --inspect-wait
  • --inspect
  • --localstorage-file
  • --max-http-header-size
  • --napi-modules
  • --network-family-autoselection-attempt-timeout
  • --no-addons
  • --no-async-context-frame
  • --no-deprecation
  • --no-experimental-global-navigator
  • --no-experimental-repl-await
  • --no-experimental-sqlite
  • --no-experimental-strip-types
  • --no-experimental-websocket
  • --no-extra-info-on-fatal-exception
  • --no-force-async-hooks-checks
  • --no-global-search-paths
  • --no-network-family-autoselection
  • --no-warnings
  • --node-memory-debug
  • --openssl-config
  • --openssl-legacy-provider
  • --openssl-shared-config
  • --pending-deprecation
  • --permission
  • --preserve-symlinks-main
  • --preserve-symlinks
  • --prof-process
  • --redirect-warnings
  • --report-compact
  • --report-dir, --report-directory
  • --report-exclude-env
  • --report-exclude-network
  • --report-filename
  • --report-on-fatalerror
  • --report-on-signal
  • --report-signal
  • --report-uncaught-exception
  • --require, -r
  • --secure-heap-min
  • --secure-heap
  • --snapshot-blob
  • --test-coverage-branches
  • --test-coverage-exclude
  • --test-coverage-functions
  • --test-coverage-include
  • --test-coverage-lines
  • --test-global-setup
  • --test-isolation
  • --test-name-pattern
  • --test-only
  • --test-reporter-destination
  • --test-reporter
  • --test-shard
  • --test-skip-pattern
  • --throw-deprecation
  • --title
  • --tls-cipher-list
  • --tls-keylog
  • --tls-max-v1.2
  • --tls-max-v1.3
  • --tls-min-v1.0
  • --tls-min-v1.1
  • --tls-min-v1.2
  • --tls-min-v1.3
  • --trace-deprecation
  • --trace-env-js-stack
  • --trace-env-native-stack
  • --trace-env
  • --trace-event-categories
  • --trace-event-file-pattern
  • --trace-events-enabled
  • --trace-exit
  • --trace-require-module
  • --trace-sigint
  • --trace-sync-io
  • --trace-tls
  • --trace-uncaught
  • --trace-warnings
  • --track-heap-objects
  • --unhandled-rejections
  • --use-bundled-ca
  • --use-largepages
  • --use-openssl-ca
  • --use-system-ca
  • --v8-pool-size
  • --watch-path
  • --watch-preserve-output
  • --watch
  • --zero-fill-buffers

V8 options that are allowed are:

  • --abort-on-uncaught-exception
  • --disallow-code-generation-from-strings
  • --enable-etw-stack-walking
  • --expose-gc
  • --interpreted-frames-native-stack
  • --jitless
  • --max-old-space-size
  • --max-semi-space-size
  • --perf-basic-prof-only-functions
  • --perf-basic-prof
  • --perf-prof-unwinding-info
  • --perf-prof
  • --stack-trace-limit

--perf-basic-prof-only-functions, --perf-basic-prof, --perf-prof-unwinding-info, and --perf-prof are only available on Linux.

--enable-etw-stack-walking is only available on Windows.

NODE_PATH=path[:…]#

':'-separated list of directories prefixed to the module search path.

On Windows, this is a ';'-separated list instead.

NODE_PENDING_DEPRECATION=1#

When set to 1, emit pending deprecation warnings.

Pending deprecations are generally identical to a runtime deprecation with the notable exception that they are turned off by default and will not be emitted unless either the --pending-deprecation command-line flag, or the NODE_PENDING_DEPRECATION=1 environment variable, is set. Pending deprecations are used to provide a kind of selective "early warning" mechanism that developers may leverage to detect deprecated API usage.

NODE_PENDING_PIPE_INSTANCES=instances#

Set the number of pending pipe instance handles when the pipe server is waiting for connections. This setting applies to Windows only.

NODE_PRESERVE_SYMLINKS=1#

When set to 1, instructs the module loader to preserve symbolic links when resolving and caching modules.

NODE_REDIRECT_WARNINGS=file#

When set, process warnings will be emitted to the given file instead of printing to stderr. The file will be created if it does not exist, and will be appended to if it does. If an error occurs while attempting to write the warning to the file, the warning will be written to stderr instead. This is equivalent to using the --redirect-warnings=file command-line flag.

NODE_REPL_EXTERNAL_MODULE=file#

Path to a Node.js module which will be loaded in place of the built-in REPL. Overriding this value to an empty string ('') will use the built-in REPL.

NODE_REPL_HISTORY=file#

Path to the file used to store the persistent REPL history. The default path is ~/.node_repl_history, which is overridden by this variable. Setting the value to an empty string ('' or ' ') disables persistent REPL history.

NODE_SKIP_PLATFORM_CHECK=value#

If value equals '1', the check for a supported platform is skipped during Node.js startup. Node.js might not execute correctly. Any issues encountered on unsupported platforms will not be fixed.

NODE_TEST_CONTEXT=value#

If value equals 'child', test reporter options will be overridden and test output will be sent to stdout in the TAP format. If any other value is provided, Node.js makes no guarantees about the reporter format used or its stability.

NODE_TLS_REJECT_UNAUTHORIZED=value#

If value equals '0', certificate validation is disabled for TLS connections. This makes TLS, and HTTPS by extension, insecure. The use of this environment variable is strongly discouraged.

NODE_USE_ENV_PROXY=1#

Stability: 1.1 - Active Development

When enabled, Node.js parses the HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables during startup, and tunnels requests over the specified proxy.

This currently only affects requests sent over fetch(). Support for other built-in http and https methods is under way.

NODE_V8_COVERAGE=dir#

When set, Node.js will begin outputting V8 JavaScript code coverage and Source Map data to the directory provided as an argument (coverage information is written as JSON to files with a coverage prefix).

NODE_V8_COVERAGE will automatically propagate to subprocesses, making it easier to instrument applications that call the child_process.spawn() family of functions. NODE_V8_COVERAGE can be set to an empty string, to prevent propagation.

Coverage output#

Coverage is output as an array of ScriptCoverage objects on the top-level key result:

{
  "result": [
    {
      "scriptId": "67",
      "url": "internal/tty.js",
      "functions": []
    }
  ]
} 
Source map cache#

Stability: 1 - Experimental

If found, source map data is appended to the top-level key source-map-cache on the JSON coverage object.

source-map-cache is an object with keys representing the files source maps were extracted from, and values which include the raw source-map URL (in the key url), the parsed Source Map v3 information (in the key data), and the line lengths of the source file (in the key lineLengths).

{
  "result": [
    {
      "scriptId": "68",
      "url": "file:///absolute/path/to/source.js",
      "functions": []
    }
  ],
  "source-map-cache": {
    "file:///absolute/path/to/source.js": {
      "url": "./path-to-map.json",
      "data": {
        "version": 3,
        "sources": [
          "file:///absolute/path/to/original.js"
        ],
        "names": [
          "Foo",
          "console",
          "info"
        ],
        "mappings": "MAAMA,IACJC,YAAaC",
        "sourceRoot": "./"
      },
      "lineLengths": [
        13,
        62,
        38,
        27
      ]
    }
  }
} 

NO_COLOR=<any>#

NO_COLOR is an alias for NODE_DISABLE_COLORS. The value of the environment variable is arbitrary.

OPENSSL_CONF=file#

Load an OpenSSL configuration file on startup. Among other uses, this can be used to enable FIPS-compliant crypto if Node.js is built with ./configure --openssl-fips.

If the --openssl-config command-line option is used, the environment variable is ignored.

SSL_CERT_DIR=dir#

If --use-openssl-ca is enabled, or if --use-system-ca is enabled on platforms other than macOS and Windows, this overrides and sets OpenSSL's directory containing trusted certificates.

Be aware that unless the child environment is explicitly set, this environment variable will be inherited by any child processes, and if they use OpenSSL, it may cause them to trust the same CAs as node.

SSL_CERT_FILE=file#

If --use-openssl-ca is enabled, or if --use-system-ca is enabled on platforms other than macOS and Windows, this overrides and sets OpenSSL's file containing trusted certificates.

Be aware that unless the child environment is explicitly set, this environment variable will be inherited by any child processes, and if they use OpenSSL, it may cause them to trust the same CAs as node.

TZ#

The TZ environment variable is used to specify the timezone configuration.

While Node.js does not support all of the various ways that TZ is handled in other environments, it does support basic timezone IDs (such as 'Etc/UTC', 'Europe/Paris', or 'America/New_York'). It may support a few other abbreviations or aliases, but these are strongly discouraged and not guaranteed.

$ TZ=Europe/Dublin node -pe "new Date().toString()"
Wed May 12 2021 20:30:48 GMT+0100 (Irish Standard Time) 

UV_THREADPOOL_SIZE=size#

Set the number of threads used in libuv's threadpool to size threads.

Asynchronous system APIs are used by Node.js whenever possible, but where they do not exist, libuv's threadpool is used to create asynchronous node APIs based on synchronous system APIs. Node.js APIs that use the threadpool are:

  • all fs APIs, other than the file watcher APIs and those that are explicitly synchronous
  • asynchronous crypto APIs such as crypto.pbkdf2(), crypto.scrypt(), crypto.randomBytes(), crypto.randomFill(), crypto.generateKeyPair()
  • dns.lookup()
  • all zlib APIs, other than those that are explicitly synchronous

Because libuv's threadpool has a fixed size, it means that if for whatever reason any of these APIs takes a long time, other (seemingly unrelated) APIs that run in libuv's threadpool will experience degraded performance. In order to mitigate this issue, one potential solution is to increase the size of libuv's threadpool by setting the 'UV_THREADPOOL_SIZE' environment variable to a value greater than 4 (its current default value). However, setting this from inside the process using process.env.UV_THREADPOOL_SIZE=size is not guranteed to work as the threadpool would have been created as part of the runtime initialisation much before user code is run. For more information, see the libuv threadpool documentation.

Useful V8 options#

V8 has its own set of CLI options. Any V8 CLI option that is provided to node will be passed on to V8 to handle. V8's options have no stability guarantee. The V8 team themselves don't consider them to be part of their formal API, and reserve the right to change them at any time. Likewise, they are not covered by the Node.js stability guarantees. Many of the V8 options are of interest only to V8 developers. Despite this, there is a small set of V8 options that are widely applicable to Node.js, and they are documented here:

--abort-on-uncaught-exception#

--disallow-code-generation-from-strings#

--enable-etw-stack-walking#

--expose-gc#

--harmony-shadow-realm#

--interpreted-frames-native-stack#

--jitless#

--max-old-space-size=SIZE (in MiB)#

Sets the max memory size of V8's old memory section. As memory consumption approaches the limit, V8 will spend more time on garbage collection in an effort to free unused memory.

On a machine with 2 GiB of memory, consider setting this to 1536 (1.5 GiB) to leave some memory for other uses and avoid swapping.

node --max-old-space-size=1536 index.js 

--max-semi-space-size=SIZE (in MiB)#

Sets the maximum semi-space size for V8's scavenge garbage collector in MiB (mebibytes). Increasing the max size of a semi-space may improve throughput for Node.js at the cost of more memory consumption.

Since the young generation size of the V8 heap is three times (see YoungGenerationSizeFromSemiSpaceSize in V8) the size of the semi-space, an increase of 1 MiB to semi-space applies to each of the three individual semi-spaces and causes the heap size to increase by 3 MiB. The throughput improvement depends on your workload (see #42511).

The default value depends on the memory limit. For example, on 64-bit systems with a memory limit of 512 MiB, the max size of a semi-space defaults to 1 MiB. For memory limits up to and including 2GiB, the default max size of a semi-space will be less than 16 MiB on 64-bit systems.

To get the best configuration for your application, you should try different max-semi-space-size values when running benchmarks for your application.

For example, benchmark on a 64-bit systems:

for MiB in 16 32 64 128; do
    node --max-semi-space-size=$MiB index.js
done 

--perf-basic-prof#

--perf-basic-prof-only-functions#

--perf-prof#

--perf-prof-unwinding-info#

--prof#

--security-revert#

--stack-trace-limit=limit#

The maximum number of stack frames to collect in an error's stack trace. Setting it to 0 disables stack trace collection. The default value is 10.

node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12 

Console#

Stability: 2 - Stable

Source Code: lib/console.js

The node:console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error(), and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without calling require('node:console').

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. Programs that desire to depend on the synchronous / asynchronous behavior of the console functions should first figure out the nature of console's backing stream. This is because the stream is dependent on the underlying platform and standard stream configuration of the current process. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr 

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err 

Class: Console#

The Console class can be used to create a simple logger with configurable output streams and can be accessed using either require('node:console').Console or console.Console (or their destructured counterparts):

import { Console } from 'node:console';const { Console } = require('node:console');
const { Console } = console; 

new Console(stdout[, stderr][, ignoreErrors])#

new Console(options)#

  • options <Object>
    • stdout <stream.Writable>
    • stderr <stream.Writable>
    • ignoreErrors <boolean> Ignore errors when writing to the underlying streams. Default: true.
    • colorMode <boolean> | <string> Set color support for this Console instance. Setting to true enables coloring while inspecting values. Setting to false disables coloring while inspecting values. Setting to 'auto' makes color support depend on the value of the isTTY property and the value returned by getColorDepth() on the respective stream. This option can not be used, if inspectOptions.colors is set as well. Default: 'auto'.
    • inspectOptions <Object> Specifies options that are passed along to util.inspect().
    • groupIndentation <number> Set group indentation. Default: 2.

Creates a new Console with one or two writable stream instances. stdout is a writable stream to print log or info output. stderr is used for warning or error output. If stderr is not provided, stdout is used for stderr.

import { createWriteStream } from 'node:fs';
import { Console } from 'node:console';
// Alternatively
// const { Console } = console;

const output = createWriteStream('./stdout.log');
const errorOutput = createWriteStream('./stderr.log');
// Custom simple logger
const logger = new Console({ stdout: output, stderr: errorOutput });
// use it like console
const count = 5;
logger.log('count: %d', count);
// In stdout.log: count 5const fs = require('node:fs');
const { Console } = require('node:console');
// Alternatively
// const { Console } = console;

const output = fs.createWriteStream('./stdout.log');
const errorOutput = fs.createWriteStream('./stderr.log');
// Custom simple logger
const logger = new Console({ stdout: output, stderr: errorOutput });
// use it like console
const count = 5;
logger.log('count: %d', count);
// In stdout.log: count 5

The global console is a special Console whose output is sent to process.stdout and process.stderr. It is equivalent to calling:

new Console({ stdout: process.stdout, stderr: process.stderr }); 

console.assert(value[, ...message])#

  • value <any> The value tested for being truthy.
  • ...message <any> All arguments besides value are used as error message.

console.assert() writes a message if value is falsy or omitted. It only writes a message and does not otherwise affect execution. The output always starts with "Assertion failed". If provided, message is formatted using util.format().

If value is truthy, nothing happens.

console.assert(true, 'does nothing');

console.assert(false, 'Whoops %s work', 'didn\'t');
// Assertion failed: Whoops didn't work

console.assert();
// Assertion failed 

console.clear()#

When stdout is a TTY, calling console.clear() will attempt to clear the TTY. When stdout is not a TTY, this method does nothing.

The specific operation of console.clear() can vary across operating systems and terminal types. For most Linux operating systems, console.clear() operates similarly to the clear shell command. On Windows, console.clear() will clear only the output in the current terminal viewport for the Node.js binary.

console.count([label])#

  • label <string> The display label for the counter. Default: 'default'.

Maintains an internal counter specific to label and outputs to stdout the number of times console.count() has been called with the given label.

> console.count()
default: 1
undefined
> console.count('default')
default: 2
undefined
> console.count('abc')
abc: 1
undefined
> console.count('xyz')
xyz: 1
undefined
> console.count('abc')
abc: 2
undefined
> console.count()
default: 3
undefined
> 

console.countReset([label])#

  • label <string> The display label for the counter. Default: 'default'.

Resets the internal counter specific to label.

> console.count('abc');
abc: 1
undefined
> console.countReset('abc');
undefined
> console.count('abc');
abc: 1
undefined
> 

console.debug(data[, ...args])#

The console.debug() function is an alias for console.log().

console.dir(obj[, options])#

  • obj <any>
  • options <Object>
    • showHidden <boolean> If true then the object's non-enumerable and symbol properties will be shown too. Default: false.
    • depth <number> Tells util.inspect() how many times to recurse while formatting the object. This is useful for inspecting large complicated objects. To make it recurse indefinitely, pass null. Default: 2.
    • colors <boolean> If true, then the output will be styled with ANSI color codes. Colors are customizable; see customizing util.inspect() colors. Default: false.

Uses util.inspect() on obj and prints the resulting string to stdout. This function bypasses any custom inspect() function defined on obj.

console.dirxml(...data)#

This method calls console.log() passing it the arguments received. This method does not produce any XML formatting.

console.error([data][, ...args])#

Prints to stderr with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr 

If formatting elements (e.g. %d) are not found in the first string then util.inspect() is called on each argument and the resulting string values are concatenated. See util.format() for more information.

console.group([...label])#

Increases indentation of subsequent lines by spaces for groupIndentation length.

If one or more labels are provided, those are printed first without the additional indentation.

console.groupCollapsed()#

An alias for console.group().

console.groupEnd()#

Decreases indentation of subsequent lines by spaces for groupIndentation length.

console.info([data][, ...args])#

The console.info() function is an alias for console.log().

console.log([data][, ...args])#

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout 

See util.format() for more information.

console.table(tabularData[, properties])#

  • tabularData <any>
  • properties <string[]> Alternate properties for constructing the table.

Try to construct a table with the columns of the properties of tabularData (or use properties) and rows of tabularData and log it. Falls back to just logging the argument if it can't be parsed as tabular.

// These can't be parsed as tabular data
console.table(Symbol());
// Symbol()

console.table(undefined);
// undefined

console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]);
// ┌─────────┬─────┬─────┐
// │ (index) │ a   │ b   │
// ├─────────┼─────┼─────┤
// │ 0       │ 1   │ 'Y' │
// │ 1       │ 'Z' │ 2   │
// └─────────┴─────┴─────┘

console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']);
// ┌─────────┬─────┐
// │ (index) │ a   │
// ├─────────┼─────┤
// │ 0       │ 1   │
// │ 1       │ 'Z' │
// └─────────┴─────┘ 

console.time([label])#

Starts a timer that can be used to compute the duration of an operation. Timers are identified by a unique label. Use the same label when calling console.timeEnd() to stop the timer and output the elapsed time in suitable time units to stdout. For example, if the elapsed time is 3869ms, console.timeEnd() displays "3.869s".

console.timeEnd([label])#

Stops a timer that was previously started by calling console.time() and prints the result to stdout:

console.time('bunch-of-stuff');
// Do a bunch of stuff.
console.timeEnd('bunch-of-stuff');
// Prints: bunch-of-stuff: 225.438ms 

console.timeLog([label][, ...data])#

For a timer that was previously started by calling console.time(), prints the elapsed time and other data arguments to stdout:

console.time('process');
const value = expensiveProcess1(); // Returns 42
console.timeLog('process', value);
// Prints "process: 365.227ms 42".
doExpensiveProcess2(value);
console.timeEnd('process'); 

console.trace([message][, ...args])#

Prints to stderr the string 'Trace: ', followed by the util.format() formatted message and stack trace to the current position in the code.

console.trace('Show me');
// Prints: (stack trace will vary based on where trace is called)
//  Trace: Show me
//    at repl:2:9
//    at REPLServer.defaultEval (repl.js:248:27)
//    at bound (domain.js:287:14)
//    at REPLServer.runBound [as eval] (domain.js:300:12)
//    at REPLServer.<anonymous> (repl.js:412:12)
//    at emitOne (events.js:82:20)
//    at REPLServer.emit (events.js:169:7)
//    at REPLServer.Interface._onLine (readline.js:210:10)
//    at REPLServer.Interface._line (readline.js:549:8)
//    at REPLServer.Interface._ttyWrite (readline.js:826:14) 

console.warn([data][, ...args])#

The console.warn() function is an alias for console.error().

Inspector only methods#

The following methods are exposed by the V8 engine in the general API but do not display anything unless used in conjunction with the inspector (--inspect flag).

console.profile([label])#

This method does not display anything unless used in the inspector. The console.profile() method starts a JavaScript CPU profile with an optional label until console.profileEnd() is called. The profile is then added to the Profile panel of the inspector.

console.profile('MyLabel');
// Some code
console.profileEnd('MyLabel');
// Adds the profile 'MyLabel' to the Profiles panel of the inspector. 

console.profileEnd([label])#

This method does not display anything unless used in the inspector. Stops the current JavaScript CPU profiling session if one has been started and prints the report to the Profiles panel of the inspector. See console.profile() for an example.

If this method is called without a label, the most recently started profile is stopped.

console.timeStamp([label])#

This method does not display anything unless used in the inspector. The console.timeStamp() method adds an event with the label 'label' to the Timeline panel of the inspector.

Crypto#

Stability: 2 - Stable

Source Code: lib/crypto.js

The node:crypto module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions.

const { createHmac } = await import('node:crypto');

const secret = 'abcdefg';
const hash = createHmac('sha256', secret)
               .update('I love cupcakes')
               .digest('hex');
console.log(hash);
// Prints:
//   c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658econst { createHmac } = require('node:crypto');

const secret = 'abcdefg';
const hash = createHmac('sha256', secret)
               .update('I love cupcakes')
               .digest('hex');
console.log(hash);
// Prints:
//   c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e

Determining if crypto support is unavailable#

It is possible for Node.js to be built without including support for the node:crypto module. In such cases, attempting to import from crypto or calling require('node:crypto') will result in an error being thrown.

When using CommonJS, the error thrown can be caught using try/catch:

let crypto;
try {
  crypto = require('node:crypto');
} catch (err) {
  console.error('crypto support is disabled!');
} 

When using the lexical ESM import keyword, the error can only be caught if a handler for process.on('uncaughtException') is registered before any attempt to load the module is made (using, for instance, a preload module).

When using ESM, if there is a chance that the code may be run on a build of Node.js where crypto support is not enabled, consider using the import() function instead of the lexical import keyword:

let crypto;
try {
  crypto = await import('node:crypto');
} catch (err) {
  console.error('crypto support is disabled!');
} 

Class: Certificate#

SPKAC is a Certificate Signing Request mechanism originally implemented by Netscape and was specified formally as part of HTML5's keygen element.

<keygen> is deprecated since HTML 5.2 and new projects should not use this element anymore.

The node:crypto module provides the Certificate class for working with SPKAC data. The most common usage is handling output generated by the HTML5 <keygen> element. Node.js uses OpenSSL's SPKAC implementation internally.

Static method: Certificate.exportChallenge(spkac[, encoding])#

const { Certificate } = await import('node:crypto');
const spkac = getSpkacSomehow();
const challenge = Certificate.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 stringconst { Certificate } = require('node:crypto');
const spkac = getSpkacSomehow();
const challenge = Certificate.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 string

Static method: Certificate.exportPublicKey(spkac[, encoding])#

const { Certificate } = await import('node:crypto');
const spkac = getSpkacSomehow();
const publicKey = Certificate.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>const { Certificate } = require('node:crypto');
const spkac = getSpkacSomehow();
const publicKey = Certificate.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>

Static method: Certificate.verifySpkac(spkac[, encoding])#

import { Buffer } from 'node:buffer';
const { Certificate } = await import('node:crypto');

const spkac = getSpkacSomehow();
console.log(Certificate.verifySpkac(Buffer.from(spkac)));
// Prints: true or falseconst { Buffer } = require('node:buffer');
const { Certificate } = require('node:crypto');

const spkac = getSpkacSomehow();
console.log(Certificate.verifySpkac(Buffer.from(spkac)));
// Prints: true or false

Legacy API#

Stability: 0 - Deprecated

As a legacy interface, it is possible to create new instances of the crypto.Certificate class as illustrated in the examples below.

new crypto.Certificate()#

Instances of the Certificate class can be created using the new keyword or by calling crypto.Certificate() as a function:

const { Certificate } = await import('node:crypto');

const cert1 = new Certificate();
const cert2 = Certificate();const { Certificate } = require('node:crypto');

const cert1 = new Certificate();
const cert2 = Certificate();
certificate.exportChallenge(spkac[, encoding])#
const { Certificate } = await import('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const challenge = cert.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 stringconst { Certificate } = require('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const challenge = cert.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 string
certificate.exportPublicKey(spkac[, encoding])#
const { Certificate } = await import('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const publicKey = cert.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>const { Certificate } = require('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const publicKey = cert.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>
certificate.verifySpkac(spkac[, encoding])#
import { Buffer } from 'node:buffer';
const { Certificate } = await import('node:crypto');

const cert = Certificate();
const spkac = getSpkacSomehow();
console.log(cert.verifySpkac(Buffer.from(spkac)));
// Prints: true or falseconst { Buffer } = require('node:buffer');
const { Certificate } = require('node:crypto');

const cert = Certificate();
const spkac = getSpkacSomehow();
console.log(cert.verifySpkac(Buffer.from(spkac)));
// Prints: true or false

Class: Cipheriv#

Instances of the Cipheriv class are used to encrypt data. The class can be used in one of two ways:

  • As a stream that is both readable and writable, where plain unencrypted data is written to produce encrypted data on the readable side, or
  • Using the cipher.update() and cipher.final() methods to produce the encrypted data.

The crypto.createCipheriv() method is used to create Cipheriv instances. Cipheriv objects are not to be created directly using the new keyword.

Example: Using Cipheriv objects as streams:

const {
  scrypt,
  randomFill,
  createCipheriv,
} = await import('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';

// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
  if (err) throw err;
  // Then, we'll generate a random initialization vector
  randomFill(new Uint8Array(16), (err, iv) => {
    if (err) throw err;

    // Once we have the key and iv, we can create and use the cipher...
    const cipher = createCipheriv(algorithm, key, iv);

    let encrypted = '';
    cipher.setEncoding('hex');

    cipher.on('data', (chunk) => encrypted += chunk);
    cipher.on('end', () => console.log(encrypted));

    cipher.write('some clear text data');
    cipher.end();
  });
});const {
  scrypt,
  randomFill,
  createCipheriv,
} = require('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';

// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
  if (err) throw err;
  // Then, we'll generate a random initialization vector
  randomFill(new Uint8Array(16), (err, iv) => {
    if (err) throw err;

    // Once we have the key and iv, we can create and use the cipher...
    const cipher = createCipheriv(algorithm, key, iv);

    let encrypted = '';
    cipher.setEncoding('hex');

    cipher.on('data', (chunk) => encrypted += chunk);
    cipher.on('end', () => console.log(encrypted));

    cipher.write('some clear text data');
    cipher.end();
  });
});

Example: Using Cipheriv and piped streams:

import {
  createReadStream,
  createWriteStream,
} from 'node:fs';

import {
  pipeline,
} from 'node:stream';

const {
  scrypt,
  randomFill,
  createCipheriv,
} = await import('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';

// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
  if (err) throw err;
  // Then, we'll generate a random initialization vector
  randomFill(new Uint8Array(16), (err, iv) => {
    if (err) throw err;

    const cipher = createCipheriv(algorithm, key, iv);

    const input = createReadStream('test.js');
    const output = createWriteStream('test.enc');

    pipeline(input, cipher, output, (err) => {
      if (err) throw err;
    });
  });
});const {
  createReadStream,
  createWriteStream,
} = require('node:fs');

const {
  pipeline,
} = require('node:stream');

const {
  scrypt,
  randomFill,
  createCipheriv,
} = require('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';

// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
  if (err) throw err;
  // Then, we'll generate a random initialization vector
  randomFill(new Uint8Array(16), (err, iv) => {
    if (err) throw err;

    const cipher = createCipheriv(algorithm, key, iv);

    const input = createReadStream('test.js');
    const output = createWriteStream('test.enc');

    pipeline(input, cipher, output, (err) => {
      if (err) throw err;
    });
  });
});

Example: Using the cipher.update() and cipher.final() methods:

const {
  scrypt,
  randomFill,
  createCipheriv,
} = await import('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';

// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
  if (err) throw err;
  // Then, we'll generate a random initialization vector
  randomFill(new Uint8Array(16), (err, iv) => {
    if (err) throw err;

    const cipher = createCipheriv(algorithm, key, iv);

    let encrypted = cipher.update('some clear text data', 'utf8', 'hex');
    encrypted += cipher.final('hex');
    console.log(encrypted);
  });
});const {
  scrypt,
  randomFill,
  createCipheriv,
} = require('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';

// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
  if (err) throw err;
  // Then, we'll generate a random initialization vector
  randomFill(new Uint8Array(16), (err, iv) => {
    if (err) throw err;

    const cipher = createCipheriv(algorithm, key, iv);

    let encrypted = cipher.update('some clear text data', 'utf8', 'hex');
    encrypted += cipher.final('hex');
    console.log(encrypted);
  });
});

cipher.final([outputEncoding])#

  • outputEncoding <string> The encoding of the return value.
  • Returns: <Buffer> | <string> Any remaining enciphered contents. If outputEncoding is specified, a string is returned. If an outputEncoding is not provided, a Buffer is returned.

Once the cipher.final() method has been called, the Cipheriv object can no longer be used to encrypt data. Attempts to call cipher.final() more than once will result in an error being thrown.

cipher.getAuthTag()#

  • Returns: <Buffer> When using an authenticated encryption mode (GCM, CCM, OCB, and chacha20-poly1305 are currently supported), the cipher.getAuthTag() method returns a Buffer containing the authentication tag that has been computed from the given data.

The cipher.getAuthTag() method should only be called after encryption has been completed using the cipher.final() method.

If the authTagLength option was set during the cipher instance's creation, this function will return exactly authTagLength bytes.

cipher.setAAD(buffer[, options])#

When using an authenticated encryption mode (GCM, CCM, OCB, and chacha20-poly1305 are currently supported), the cipher.setAAD() method sets the value used for the additional authenticated data (AAD) input parameter.

The plaintextLength option is optional for GCM and OCB. When using CCM, the plaintextLength option must be specified and its value must match the length of the plaintext in bytes. See CCM mode.

The cipher.setAAD() method must be called before cipher.update().

cipher.setAutoPadding([autoPadding])#

  • autoPadding <boolean> Default: true
  • Returns: <Cipheriv> The same Cipheriv instance for method chaining.

When using block encryption algorithms, the Cipheriv class will automatically add padding to the input data to the appropriate block size. To disable the default padding call cipher.setAutoPadding(false).

When autoPadding is false, the length of the entire input data must be a multiple of the cipher's block size or cipher.final() will throw an error. Disabling automatic padding is useful for non-standard padding, for instance using 0x0 instead of PKCS padding.

The cipher.setAutoPadding() method must be called before cipher.final().

cipher.update(data[, inputEncoding][, outputEncoding])#

Updates the cipher with data. If the inputEncoding argument is given, the data argument is a string using the specified encoding. If the inputEncoding argument is not given, data must be a Buffer, TypedArray, or DataView. If data is a Buffer, TypedArray, or DataView, then inputEncoding is ignored.

The outputEncoding specifies the output format of the enciphered data. If the outputEncoding is specified, a string using the specified encoding is returned. If no outputEncoding is provided, a Buffer is returned.

The cipher.update() method can be called multiple times with new data until cipher.final() is called. Calling cipher.update() after cipher.final() will result in an error being thrown.

Class: Decipheriv#

Instances of the Decipheriv class are used to decrypt data. The class can be used in one of two ways:

  • As a stream that is both readable and writable, where plain encrypted data is written to produce unencrypted data on the readable side, or
  • Using the decipher.update() and decipher.final() methods to produce the unencrypted data.

The crypto.createDecipheriv() method is used to create Decipheriv instances. Decipheriv objects are not to be created directly using the new keyword.

Example: Using Decipheriv objects as streams:

import { Buffer } from 'node:buffer';
const {
  scryptSync,
  createDecipheriv,
} = await import('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Key length is dependent on the algorithm. In this case for aes192, it is
// 24 bytes (192 bits).
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

const decipher = createDecipheriv(algorithm, key, iv);

let decrypted = '';
decipher.on('readable', () => {
  let chunk;
  while (null !== (chunk = decipher.read())) {
    decrypted += chunk.toString('utf8');
  }
});
decipher.on('end', () => {
  console.log(decrypted);
  // Prints: some clear text data
});

// Encrypted with same algorithm, key and iv.
const encrypted =
  'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
decipher.write(encrypted, 'hex');
decipher.end();const {
  scryptSync,
  createDecipheriv,
} = require('node:crypto');
const { Buffer } = require('node:buffer');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Key length is dependent on the algorithm. In this case for aes192, it is
// 24 bytes (192 bits).
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

const decipher = createDecipheriv(algorithm, key, iv);

let decrypted = '';
decipher.on('readable', () => {
  let chunk;
  while (null !== (chunk = decipher.read())) {
    decrypted += chunk.toString('utf8');
  }
});
decipher.on('end', () => {
  console.log(decrypted);
  // Prints: some clear text data
});

// Encrypted with same algorithm, key and iv.
const encrypted =
  'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
decipher.write(encrypted, 'hex');
decipher.end();

Example: Using Decipheriv and piped streams:

import {
  createReadStream,
  createWriteStream,
} from 'node:fs';
import { Buffer } from 'node:buffer';
const {
  scryptSync,
  createDecipheriv,
} = await import('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

const decipher = createDecipheriv(algorithm, key, iv);

const input = createReadStream('test.enc');
const output = createWriteStream('test.js');

input.pipe(decipher).pipe(output);const {
  createReadStream,
  createWriteStream,
} = require('node:fs');
const {
  scryptSync,
  createDecipheriv,
} = require('node:crypto');
const { Buffer } = require('node:buffer');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

const decipher = createDecipheriv(algorithm, key, iv);

const input = createReadStream('test.enc');
const output = createWriteStream('test.js');

input.pipe(decipher).pipe(output);

Example: Using the decipher.update() and decipher.final() methods:

import { Buffer } from 'node:buffer';
const {
  scryptSync,
  createDecipheriv,
} = await import('node:crypto');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

const decipher = createDecipheriv(algorithm, key, iv);

// Encrypted using same algorithm, key and iv.
const encrypted =
  'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
// Prints: some clear text dataconst {
  scryptSync,
  createDecipheriv,
} = require('node:crypto');
const { Buffer } = require('node:buffer');

const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.

const decipher = createDecipheriv(algorithm, key, iv);

// Encrypted using same algorithm, key and iv.
const encrypted =
  'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
// Prints: some clear text data

decipher.final([outputEncoding])#

  • outputEncoding <string> The encoding of the return value.
  • Returns: <Buffer> | <string> Any remaining deciphered contents. If outputEncoding is specified, a string is returned. If an outputEncoding is not provided, a Buffer is returned.

Once the decipher.final() method has been called, the Decipheriv object can no longer be used to decrypt data. Attempts to call decipher.final() more than once will result in an error being thrown.

decipher.setAAD(buffer[, options])#

When using an authenticated encryption mode (GCM, CCM, OCB, and chacha20-poly1305 are currently supported), the decipher.setAAD() method sets the value used for the additional authenticated data (AAD) input parameter.

The options argument is optional for GCM. When using CCM, the plaintextLength option must be specified and its value must match the length of the ciphertext in bytes. See CCM mode.

The decipher.setAAD() method must be called before decipher.update().

When passing a string as the buffer, please consider caveats when using strings as inputs to cryptographic APIs.

decipher.setAuthTag(buffer[, encoding])#

When using an authenticated encryption mode (GCM, CCM, OCB, and chacha20-poly1305 are currently supported), the decipher.setAuthTag() method is used to pass in the received authentication tag. If no tag is provided, or if the cipher text has been tampered with, decipher.final() will throw, indicating that the cipher text should be discarded due to failed authentication. If the tag length is invalid according to NIST SP 800-38D or does not match the value of the authTagLength option, decipher.setAuthTag() will throw an error.

The decipher.setAuthTag() method must be called before decipher.update() for CCM mode or before decipher.final() for GCM and OCB modes and chacha20-poly1305. decipher.setAuthTag() can only be called once.

When passing a string as the authentication tag, please consider caveats when using strings as inputs to cryptographic APIs.

decipher.setAutoPadding([autoPadding])#

When data has been encrypted without standard block padding, calling decipher.setAutoPadding(false) will disable automatic padding to prevent decipher.final() from checking for and removing padding.

Turning auto padding off will only work if the input data's length is a multiple of the ciphers block size.

The decipher.setAutoPadding() method must be called before decipher.final().

decipher.update(data[, inputEncoding][, outputEncoding])#

Updates the decipher with data. If the inputEncoding argument is given, the data argument is a string using the specified encoding. If the inputEncoding argument is not given, data must be a Buffer. If data is a Buffer then inputEncoding is ignored.

The outputEncoding specifies the output format of the enciphered data. If the outputEncoding is specified, a string using the specified encoding is returned. If no outputEncoding is provided, a Buffer is returned.

The decipher.update() method can be called multiple times with new data until decipher.final() is called. Calling decipher.update() after decipher.final() will result in an error being thrown.

Even if the underlying cipher implements authentication, the authenticity and integrity of the plaintext returned from this function may be uncertain at this time. For authenticated encryption algorithms, authenticity is generally only established when the application calls decipher.final().

Class: DiffieHellman#

The DiffieHellman class is a utility for creating Diffie-Hellman key exchanges.

Instances of the DiffieHellman class can be created using the crypto.createDiffieHellman() function.

import assert from 'node:assert';

const {
  createDiffieHellman,
} = await import('node:crypto');

// Generate Alice's keys...
const alice = createDiffieHellman(2048);
const aliceKey = alice.generateKeys();

// Generate Bob's keys...
const bob = createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();

// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);

// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));const assert = require('node:assert');

const {
  createDiffieHellman,
} = require('node:crypto');

// Generate Alice's keys...
const alice = createDiffieHellman(2048);
const aliceKey = alice.generateKeys();

// Generate Bob's keys...
const bob = createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();

// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);

// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));

diffieHellman.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])#

Computes the shared secret using otherPublicKey as the other party's public key and returns the computed shared secret. The supplied key is interpreted using the specified inputEncoding, and secret is encoded using specified outputEncoding. If the inputEncoding is not provided, otherPublicKey is expected to be a Buffer, TypedArray, or DataView.

If outputEncoding is given a string is returned; otherwise, a Buffer is returned.

diffieHellman.generateKeys([encoding])#

Generates private and public Diffie-Hellman key values unless they have been generated or computed already, and returns the public key in the specified encoding. This key should be transferred to the other party. If encoding is provided a string is returned; otherwise a Buffer is returned.

This function is a thin wrapper around DH_generate_key(). In particular, once a private key has been generated or set, calling this function only updates the public key but does not generate a new private key.

diffieHellman.getGenerator([encoding])#

Returns the Diffie-Hellman generator in the specified encoding. If encoding is provided a string is returned; otherwise a Buffer is returned.

diffieHellman.getPrime([encoding])#

Returns the Diffie-Hellman prime in the specified encoding. If encoding is provided a string is returned; otherwise a Buffer is returned.

diffieHellman.getPrivateKey([encoding])#

Returns the Diffie-Hellman private key in the specified encoding. If encoding is provided a string is returned; otherwise a Buffer is returned.

diffieHellman.getPublicKey([encoding])#

Returns the Diffie-Hellman public key in the specified encoding. If encoding is provided a string is returned; otherwise a Buffer is returned.

diffieHellman.setPrivateKey(privateKey[, encoding])#

Sets the Diffie-Hellman private key. If the encoding argument is provided, privateKey is expected to be a string. If no encoding is provided, privateKey is expected to be a Buffer, TypedArray, or DataView.

This function does not automatically compute the associated public key. Either diffieHellman.setPublicKey() or diffieHellman.generateKeys() can be used to manually provide the public key or to automatically derive it.

diffieHellman.setPublicKey(publicKey[, encoding])#

Sets the Diffie-Hellman public key. If the encoding argument is provided, publicKey is expected to be a string. If no encoding is provided, publicKey is expected to be a Buffer, TypedArray, or DataView.

diffieHellman.verifyError#

A bit field containing any warnings and/or errors resulting from a check performed during initialization of the DiffieHellman object.

The following values are valid for this property (as defined in node:constants module):

  • DH_CHECK_P_NOT_SAFE_PRIME
  • DH_CHECK_P_NOT_PRIME
  • DH_UNABLE_TO_CHECK_GENERATOR
  • DH_NOT_SUITABLE_GENERATOR

Class: DiffieHellmanGroup#

The DiffieHellmanGroup class takes a well-known modp group as its argument. It works the same as DiffieHellman, except that it does not allow changing its keys after creation. In other words, it does not implement setPublicKey() or setPrivateKey() methods.

const { createDiffieHellmanGroup } = await import('node:crypto');
const dh = createDiffieHellmanGroup('modp16');const { createDiffieHellmanGroup } = require('node:crypto');
const dh = createDiffieHellmanGroup('modp16');

The following groups are supported:

  • 'modp14' (2048 bits, RFC 3526 Section 3)
  • 'modp15' (3072 bits, RFC 3526 Section 4)
  • 'modp16' (4096 bits, RFC 3526 Section 5)
  • 'modp17' (6144 bits, RFC 3526 Section 6)
  • 'modp18' (8192 bits, RFC 3526 Section 7)

The following groups are still supported but deprecated (see Caveats):

  • 'modp1' (768 bits, RFC 2409 Section 6.1)
  • 'modp2' (1024 bits, RFC 2409 Section 6.2)
  • 'modp5' (1536 bits, RFC 3526 Section 2)

These deprecated groups might be removed in future versions of Node.js.

Class: ECDH#

The ECDH class is a utility for creating Elliptic Curve Diffie-Hellman (ECDH) key exchanges.

Instances of the ECDH class can be created using the crypto.createECDH() function.

import assert from 'node:assert';

const {
  createECDH,
} = await import('node:crypto');

// Generate Alice's keys...
const alice = createECDH('secp521r1');
const aliceKey = alice.generateKeys();

// Generate Bob's keys...
const bob = createECDH('secp521r1');
const bobKey = bob.generateKeys();

// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);

assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
// OKconst assert = require('node:assert');

const {
  createECDH,
} = require('node:crypto');

// Generate Alice's keys...
const alice = createECDH('secp521r1');
const aliceKey = alice.generateKeys();

// Generate Bob's keys...
const bob = createECDH('secp521r1');
const bobKey = bob.generateKeys();

// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);

assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
// OK

Static method: ECDH.convertKey(key, curve[, inputEncoding[, outputEncoding[, format]]])#

Converts the EC Diffie-Hellman public key specified by key and curve to the format specified by format. The format argument specifies point encoding and can be 'compressed', 'uncompressed' or 'hybrid'. The supplied key is interpreted using the specified inputEncoding, and the returned key is encoded using the specified outputEncoding.

Use crypto.getCurves() to obtain a list of available curve names. On recent OpenSSL releases, openssl ecparam -list_curves will also display the name and description of each available elliptic curve.

If format is not specified the point will be returned in 'uncompressed' format.

If the inputEncoding is not provided, key is expected to be a Buffer, TypedArray, or DataView.

Example (uncompressing a key):

const {
  createECDH,
  ECDH,
} = await import('node:crypto');

const ecdh = createECDH('secp256k1');
ecdh.generateKeys();

const compressedKey = ecdh.getPublicKey('hex', 'compressed');

const uncompressedKey = ECDH.convertKey(compressedKey,
                                        'secp256k1',
                                        'hex',
                                        'hex',
                                        'uncompressed');

// The converted key and the uncompressed public key should be the same
console.log(uncompressedKey === ecdh.getPublicKey('hex'));const {
  createECDH,
  ECDH,
} = require('node:crypto');

const ecdh = createECDH('secp256k1');
ecdh.generateKeys();

const compressedKey = ecdh.getPublicKey('hex', 'compressed');

const uncompressedKey = ECDH.convertKey(compressedKey,
                                        'secp256k1',
                                        'hex',
                                        'hex',
                                        'uncompressed');

// The converted key and the uncompressed public key should be the same
console.log(uncompressedKey === ecdh.getPublicKey('hex'));

ecdh.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])#

Computes the shared secret using otherPublicKey as the other party's public key and returns the computed shared secret. The supplied key is interpreted using specified inputEncoding, and the returned secret is encoded using the specified outputEncoding. If the inputEncoding is not provided, otherPublicKey is expected to be a Buffer, TypedArray, or DataView.

If outputEncoding is given a string will be returned; otherwise a Buffer is returned.

ecdh.computeSecret will throw an ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY error when otherPublicKey lies outside of the elliptic curve. Since otherPublicKey is usually supplied from a remote user over an insecure network, be sure to handle this exception accordingly.

ecdh.generateKeys([encoding[, format]])#

Generates private and public EC Diffie-Hellman key values, and returns the public key in the specified format and encoding. This key should be transferred to the other party.

The format argument specifies point encoding and can be 'compressed' or 'uncompressed'. If format is not specified, the point will be returned in 'uncompressed' format.

If encoding is provided a string is returned; otherwise a Buffer is returned.

ecdh.getPrivateKey([encoding])#

If encoding is specified, a string is returned; otherwise a Buffer is returned.

ecdh.getPublicKey([encoding][, format])#

The format argument specifies point encoding and can be 'compressed' or 'uncompressed'. If format is not specified the point will be returned in 'uncompressed' format.

If encoding is specified, a string is returned; otherwise a Buffer is returned.

ecdh.setPrivateKey(privateKey[, encoding])#

Sets the EC Diffie-Hellman private key. If encoding is provided, privateKey is expected to be a string; otherwise privateKey is expected to be a Buffer, TypedArray, or DataView.

If privateKey is not valid for the curve specified when the ECDH object was created, an error is thrown. Upon setting the private key, the associated public point (key) is also generated and set in the ECDH object.

ecdh.setPublicKey(publicKey[, encoding])#

Stability: 0 - Deprecated

Sets the EC Diffie-Hellman public key. If encoding is provided publicKey is expected to be a string; otherwise a Buffer, TypedArray, or DataView is expected.

There is not normally a reason to call this method because ECDH only requires a private key and the other party's public key to compute the shared secret. Typically either ecdh.generateKeys() or ecdh.setPrivateKey() will be called. The ecdh.setPrivateKey() method attempts to generate the public point/key associated with the private key being set.

Example (obtaining a shared secret):

const {
  createECDH,
  createHash,
} = await import('node:crypto');

const alice = createECDH('secp256k1');
const bob = createECDH('secp256k1');

// This is a shortcut way of specifying one of Alice's previous private
// keys. It would be unwise to use such a predictable private key in a real
// application.
alice.setPrivateKey(
  createHash('sha256').update('alice', 'utf8').digest(),
);

// Bob uses a newly generated cryptographically strong
// pseudorandom key pair
bob.generateKeys();

const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

// aliceSecret and bobSecret should be the same shared secret value
console.log(aliceSecret === bobSecret);const {
  createECDH,
  createHash,
} = require('node:crypto');

const alice = createECDH('secp256k1');
const bob = createECDH('secp256k1');

// This is a shortcut way of specifying one of Alice's previous private
// keys. It would be unwise to use such a predictable private key in a real
// application.
alice.setPrivateKey(
  createHash('sha256').update('alice', 'utf8').digest(),
);

// Bob uses a newly generated cryptographically strong
// pseudorandom key pair
bob.generateKeys();

const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

// aliceSecret and bobSecret should be the same shared secret value
console.log(aliceSecret === bobSecret);

Class: Hash#

The Hash class is a utility for creating hash digests of data. It can be used in one of two ways:

  • As a stream that is both readable and writable, where data is written to produce a computed hash digest on the readable side, or
  • Using the hash.update() and hash.digest() methods to produce the computed hash.

The crypto.createHash() method is used to create Hash instances. Hash objects are not to be created directly using the new keyword.

Example: Using Hash objects as streams:

const {
  createHash,
} = await import('node:crypto');

const hash = createHash('sha256');

hash.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = hash.read();
  if (data) {
    console.log(data.toString('hex'));
    // Prints:
    //   6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
  }
});

hash.write('some data to hash');
hash.end();const {
  createHash,
} = require('node:crypto');

const hash = createHash('sha256');

hash.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = hash.read();
  if (data) {
    console.log(data.toString('hex'));
    // Prints:
    //   6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
  }
});

hash.write('some data to hash');
hash.end();

Example: Using Hash and piped streams:

import { createReadStream } from 'node:fs';
import { stdout } from 'node:process';
const { createHash } = await import('node:crypto');

const hash = createHash('sha256');

const input = createReadStream('test.js');
input.pipe(hash).setEncoding('hex').pipe(stdout);const { createReadStream } = require('node:fs');
const { createHash } = require('node:crypto');
const { stdout } = require('node:process');

const hash = createHash('sha256');

const input = createReadStream('test.js');
input.pipe(hash).setEncoding('hex').pipe(stdout);

Example: Using the hash.update() and hash.digest() methods:

const {
  createHash,
} = await import('node:crypto');

const hash = createHash('sha256');

hash.update('some data to hash');
console.log(hash.digest('hex'));
// Prints:
//   6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50const {
  createHash,
} = require('node:crypto');

const hash = createHash('sha256');

hash.update('some data to hash');
console.log(hash.digest('hex'));
// Prints:
//   6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50

hash.copy([options])#

Creates a new Hash object that contains a deep copy of the internal state of the current Hash object.

The optional options argument controls stream behavior. For XOF hash functions such as 'shake256', the outputLength option can be used to specify the desired output length in bytes.

An error is thrown when an attempt is made to copy the Hash object after its hash.digest() method has been called.

// Calculate a rolling hash.
const {
  createHash,
} = await import('node:crypto');

const hash = createHash('sha256');

hash.update('one');
console.log(hash.copy().digest('hex'));

hash.update('two');
console.log(hash.copy().digest('hex'));

hash.update('three');
console.log(hash.copy().digest('hex'));

// Etc.// Calculate a rolling hash.
const {
  createHash,
} = require('node:crypto');

const hash = createHash('sha256');

hash.update('one');
console.log(hash.copy().digest('hex'));

hash.update('two');
console.log(hash.copy().digest('hex'));

hash.update('three');
console.log(hash.copy().digest('hex'));

// Etc.

hash.digest([encoding])#

Calculates the digest of all of the data passed to be hashed (using the hash.update() method). If encoding is provided a string will be returned; otherwise a Buffer is returned.

The Hash object can not be used again after hash.digest() method has been called. Multiple calls will cause an error to be thrown.

hash.update(data[, inputEncoding])#

Updates the hash content with the given data, the encoding of which is given in inputEncoding. If encoding is not provided, and the data is a string, an encoding of 'utf8' is enforced. If data is a Buffer, TypedArray, or DataView, then inputEncoding is ignored.

This can be called many times with new data as it is streamed.

Class: Hmac#

The Hmac class is a utility for creating cryptographic HMAC digests. It can be used in one of two ways:

  • As a stream that is both readable and writable, where data is written to produce a computed HMAC digest on the readable side, or
  • Using the hmac.update() and hmac.digest() methods to produce the computed HMAC digest.

The crypto.createHmac() method is used to create Hmac instances. Hmac objects are not to be created directly using the new keyword.

Example: Using Hmac objects as streams:

const {
  createHmac,
} = await import('node:crypto');

const hmac = createHmac('sha256', 'a secret');

hmac.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = hmac.read();
  if (data) {
    console.log(data.toString('hex'));
    // Prints:
    //   7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e
  }
});

hmac.write('some data to hash');
hmac.end();const {
  createHmac,
} = require('node:crypto');

const hmac = createHmac('sha256', 'a secret');

hmac.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = hmac.read();
  if (data) {
    console.log(data.toString('hex'));
    // Prints:
    //   7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e
  }
});

hmac.write('some data to hash');
hmac.end();

Example: Using Hmac and piped streams:

import { createReadStream } from 'node:fs';
import { stdout } from 'node:process';
const {
  createHmac,
} = await import('node:crypto');

const hmac = createHmac('sha256', 'a secret');

const input = createReadStream('test.js');
input.pipe(hmac).pipe(stdout);const {
  createReadStream,
} = require('node:fs');
const {
  createHmac,
} = require('node:crypto');
const { stdout } = require('node:process');

const hmac = createHmac('sha256', 'a secret');

const input = createReadStream('test.js');
input.pipe(hmac).pipe(stdout);

Example: Using the hmac.update() and hmac.digest() methods:

const {
  createHmac,
} = await import('node:crypto');

const hmac = createHmac('sha256', 'a secret');

hmac.update('some data to hash');
console.log(hmac.digest('hex'));
// Prints:
//   7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77econst {
  createHmac,
} = require('node:crypto');

const hmac = createHmac('sha256', 'a secret');

hmac.update('some data to hash');
console.log(hmac.digest('hex'));
// Prints:
//   7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e

hmac.digest([encoding])#

Calculates the HMAC digest of all of the data passed using hmac.update(). If encoding is provided a string is returned; otherwise a Buffer is returned;

The Hmac object can not be used again after hmac.digest() has been called. Multiple calls to hmac.digest() will result in an error being thrown.

hmac.update(data[, inputEncoding])#

Updates the Hmac content with the given data, the encoding of which is given in inputEncoding. If encoding is not provided, and the data is a string, an encoding of 'utf8' is enforced. If data is a Buffer, TypedArray, or DataView, then inputEncoding is ignored.

This can be called many times with new data as it is streamed.

Class: KeyObject#

Node.js uses a KeyObject class to represent a symmetric or asymmetric key, and each kind of key exposes different functions. The crypto.createSecretKey(), crypto.createPublicKey() and crypto.createPrivateKey() methods are used to create KeyObject instances. KeyObject objects are not to be created directly using the new keyword.

Most applications should consider using the new KeyObject API instead of passing keys as strings or Buffers due to improved security features.

KeyObject instances can be passed to other threads via postMessage(). The receiver obtains a cloned KeyObject, and the KeyObject does not need to be listed in the transferList argument.

Static method: KeyObject.from(key)#

Example: Converting a CryptoKey instance to a KeyObject:

const { KeyObject } = await import('node:crypto');
const { subtle } = globalThis.crypto;

const key = await subtle.generateKey({
  name: 'HMAC',
  hash: 'SHA-256',
  length: 256,
}, true, ['sign', 'verify']);

const keyObject = KeyObject.from(key);
console.log(keyObject.symmetricKeySize);
// Prints: 32 (symmetric key size in bytes)const { KeyObject } = require('node:crypto');
const { subtle } = globalThis.crypto;

(async function() {
  const key = await subtle.generateKey({
    name: 'HMAC',
    hash: 'SHA-256',
    length: 256,
  }, true, ['sign', 'verify']);

  const keyObject = KeyObject.from(key);
  console.log(keyObject.symmetricKeySize);
  // Prints: 32 (symmetric key size in bytes)
})();

keyObject.asymmetricKeyDetails#

  • <Object>
    • modulusLength: <number> Key size in bits (RSA, DSA).
    • publicExponent: <bigint> Public exponent (RSA).
    • hashAlgorithm: <string> Name of the message digest (RSA-PSS).
    • mgf1HashAlgorithm: <string> Name of the message digest used by MGF1 (RSA-PSS).
    • saltLength: <number> Minimal salt length in bytes (RSA-PSS).
    • divisorLength: <number> Size of q in bits (DSA).
    • namedCurve: <string> Name of the curve (EC).

This property exists only on asymmetric keys. Depending on the type of the key, this object contains information about the key. None of the information obtained through this property can be used to uniquely identify a key or to compromise the security of the key.

For RSA-PSS keys, if the key material contains a RSASSA-PSS-params sequence, the hashAlgorithm, mgf1HashAlgorithm, and saltLength properties will be set.

Other key details might be exposed via this API using additional attributes.

keyObject.asymmetricKeyType#

For asymmetric keys, this property represents the type of the key. Supported key types are:

  • 'rsa' (OID 1.2.840.113549.1.1.1)
  • 'rsa-pss' (OID 1.2.840.113549.1.1.10)
  • 'dsa' (OID 1.2.840.10040.4.1)
  • 'ec' (OID 1.2.840.10045.2.1)
  • 'x25519' (OID 1.3.101.110)
  • 'x448' (OID 1.3.101.111)
  • 'ed25519' (OID 1.3.101.112)
  • 'ed448' (OID 1.3.101.113)
  • 'dh' (OID 1.2.840.113549.1.3.1)

This property is undefined for unrecognized KeyObject types and symmetric keys.

keyObject.equals(otherKeyObject)#

Returns true or false depending on whether the keys have exactly the same type, value, and parameters. This method is not constant time.

keyObject.export([options])#

For symmetric keys, the following encoding options can be used:

  • format: <string> Must be 'buffer' (default) or 'jwk'.

For public keys, the following encoding options can be used:

  • type: <string> Must be one of 'pkcs1' (RSA only) or 'spki'.
  • format: <string> Must be 'pem', 'der', or 'jwk'.

For private keys, the following encoding options can be used:

  • type: <string> Must be one of 'pkcs1' (RSA only), 'pkcs8' or 'sec1' (EC only).
  • format: <string> Must be 'pem', 'der', or 'jwk'.
  • cipher: <string> If specified, the private key will be encrypted with the given cipher and passphrase using PKCS#5 v2.0 password based encryption.
  • passphrase: <string> | <Buffer> The passphrase to use for encryption, see cipher.

The result type depends on the selected encoding format, when PEM the result is a string, when DER it will be a buffer containing the data encoded as DER, when JWK it will be an object.

When JWK encoding format was selected, all other encoding options are ignored.

PKCS#1, SEC1, and PKCS#8 type keys can be encrypted by using a combination of the cipher and format options. The PKCS#8 type can be used with any format to encrypt any key algorithm (RSA, EC, or DH) by specifying a cipher. PKCS#1 and SEC1 can only be encrypted by specifying a cipher when the PEM format is used. For maximum compatibility, use PKCS#8 for encrypted private keys. Since PKCS#8 defines its own encryption mechanism, PEM-level encryption is not supported when encrypting a PKCS#8 key. See RFC 5208 for PKCS#8 encryption and RFC 1421 for PKCS#1 and SEC1 encryption.

keyObject.symmetricKeySize#

For secret keys, this property represents the size of the key in bytes. This property is undefined for asymmetric keys.

keyObject.toCryptoKey(algorithm, extractable, keyUsages)#

Converts a KeyObject instance to a CryptoKey.

keyObject.type#

Depending on the type of this KeyObject, this property is either 'secret' for secret (symmetric) keys, 'public' for public (asymmetric) keys or 'private' for private (asymmetric) keys.

Class: Sign#

The Sign class is a utility for generating signatures. It can be used in one of two ways:

  • As a writable stream, where data to be signed is written and the sign.sign() method is used to generate and return the signature, or
  • Using the sign.update() and sign.sign() methods to produce the signature.

The crypto.createSign() method is used to create Sign instances. The argument is the string name of the hash function to use. Sign objects are not to be created directly using the new keyword.

Example: Using Sign and Verify objects as streams:

const {
  generateKeyPairSync,
  createSign,
  createVerify,
} = await import('node:crypto');

const { privateKey, publicKey } = generateKeyPairSync('ec', {
  namedCurve: 'sect239k1',
});

const sign = createSign('SHA256');
sign.write('some data to sign');
sign.end();
const signature = sign.sign(privateKey, 'hex');

const verify = createVerify('SHA256');
verify.write('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature, 'hex'));
// Prints: trueconst {
  generateKeyPairSync,
  createSign,
  createVerify,
} = require('node:crypto');

const { privateKey, publicKey } = generateKeyPairSync('ec', {
  namedCurve: 'sect239k1',
});

const sign = createSign('SHA256');
sign.write('some data to sign');
sign.end();
const signature = sign.sign(privateKey, 'hex');

const verify = createVerify('SHA256');
verify.write('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature, 'hex'));
// Prints: true

Example: Using the sign.update() and verify.update() methods:

const {
  generateKeyPairSync,
  createSign,
  createVerify,
} = await import('node:crypto');

const { privateKey, publicKey } = generateKeyPairSync('rsa', {
  modulusLength: 2048,
});

const sign = createSign('SHA256');
sign.update('some data to sign');
sign.end();
const signature = sign.sign(privateKey);

const verify = createVerify('SHA256');
verify.update('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature));
// Prints: trueconst {
  generateKeyPairSync,
  createSign,
  createVerify,
} = require('node:crypto');

const { privateKey, publicKey } = generateKeyPairSync('rsa', {
  modulusLength: 2048,
});

const sign = createSign('SHA256');
sign.update('some data to sign');
sign.end();
const signature = sign.sign(privateKey);

const verify = createVerify('SHA256');
verify.update('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature));
// Prints: true

sign.sign(privateKey[, outputEncoding])#

Calculates the signature on all the data passed through using either sign.update() or sign.write().

If privateKey is not a KeyObject, this function behaves as if privateKey had been passed to crypto.createPrivateKey(). If it is an object, the following additional properties can be passed:

  • dsaEncoding <string> For DSA and ECDSA, this option specifies the format of the generated signature. It can be one of the following:

    • 'der' (default): DER-encoded ASN.1 signature structure encoding (r, s).
    • 'ieee-p1363': Signature format r || s as proposed in IEEE-P1363.
  • padding <integer> Optional padding value for RSA, one of the following:

    • crypto.constants.RSA_PKCS1_PADDING (default)
    • crypto.constants.RSA_PKCS1_PSS_PADDING

    RSA_PKCS1_PSS_PADDING will use MGF1 with the same hash function used to sign the message as specified in section 3.1 of RFC 4055, unless an MGF1 hash function has been specified as part of the key in compliance with section 3.3 of RFC 4055.

  • saltLength <integer> Salt length for when padding is RSA_PKCS1_PSS_PADDING. The special value crypto.constants.RSA_PSS_SALTLEN_DIGEST sets the salt length to the digest size, crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN (default) sets it to the maximum permissible value.

If outputEncoding is provided a string is returned; otherwise a Buffer is returned.

The Sign object can not be again used after sign.sign() method has been called. Multiple calls to sign.sign() will result in an error being thrown.

sign.update(data[, inputEncoding])#

Updates the Sign content with the given data, the encoding of which is given in inputEncoding. If encoding is not provided, and the data is a string, an encoding of 'utf8' is enforced. If data is a Buffer, TypedArray, or DataView, then inputEncoding is ignored.

This can be called many times with new data as it is streamed.

Class: Verify#

The Verify class is a utility for verifying signatures. It can be used in one of two ways:

The crypto.createVerify() method is used to create Verify instances. Verify objects are not to be created directly using the new keyword.

See Sign for examples.

verify.update(data[, inputEncoding])#

Updates the Verify content with the given data, the encoding of which is given in inputEncoding. If inputEncoding is not provided, and the data is a string, an encoding of 'utf8' is enforced. If data is a Buffer, TypedArray, or DataView, then inputEncoding is ignored.

This can be called many times with new data as it is streamed.

verify.verify(object, signature[, signatureEncoding])#

Verifies the provided data using the given object and signature.

If object is not a KeyObject, this function behaves as if object had been passed to crypto.createPublicKey(). If it is an object, the following additional properties can be passed:

  • dsaEncoding <string> For DSA and ECDSA, this option specifies the format of the signature. It can be one of the following:

    • 'der' (default): DER-encoded ASN.1 signature structure encoding (r, s).
    • 'ieee-p1363': Signature format r || s as proposed in IEEE-P1363.
  • padding <integer> Optional padding value for RSA, one of the following:

    • crypto.constants.RSA_PKCS1_PADDING (default)
    • crypto.constants.RSA_PKCS1_PSS_PADDING

    RSA_PKCS1_PSS_PADDING will use MGF1 with the same hash function used to verify the message as specified in section 3.1 of RFC 4055, unless an MGF1 hash function has been specified as part of the key in compliance with section 3.3 of RFC 4055.

  • saltLength <integer> Salt length for when padding is RSA_PKCS1_PSS_PADDING. The special value crypto.constants.RSA_PSS_SALTLEN_DIGEST sets the salt length to the digest size, crypto.constants.RSA_PSS_SALTLEN_AUTO (default) causes it to be determined automatically.

The signature argument is the previously calculated signature for the data, in the signatureEncoding. If a signatureEncoding is specified, the signature is expected to be a string; otherwise signature is expected to be a Buffer, TypedArray, or DataView.

The verify object can not be used again after verify.verify() has been called. Multiple calls to verify.verify() will result in an error being thrown.

Because public keys can be derived from private keys, a private key may be passed instead of a public key.

Class: X509Certificate#

Encapsulates an X509 certificate and provides read-only access to its information.

const { X509Certificate } = await import('node:crypto');

const x509 = new X509Certificate('{... pem encoded cert ...}');

console.log(x509.subject);const { X509Certificate } = require('node:crypto');

const x509 = new X509Certificate('{... pem encoded cert ...}');

console.log(x509.subject);

new X509Certificate(buffer)#

x509.ca#

  • Type: <boolean> Will be true if this is a Certificate Authority (CA) certificate.

x509.checkEmail(email[, options])#

Checks whether the certificate matches the given email address.

If the 'subject' option is undefined or set to 'default', the certificate subject is only considered if the subject alternative name extension either does not exist or does not contain any email addresses.

If the 'subject' option is set to 'always' and if the subject alternative name extension either does not exist or does not contain a matching email address, the certificate subject is considered.

If the 'subject' option is set to 'never', the certificate subject is never considered, even if the certificate contains no subject alternative names.

x509.checkHost(name[, options])#

Checks whether the certificate matches the given host name.

If the certificate matches the given host name, the matching subject name is returned. The returned name might be an exact match (e.g., foo.example.com) or it might contain wildcards (e.g., *.example.com). Because host name comparisons are case-insensitive, the returned subject name might also differ from the given name in capitalization.

If the 'subject' option is undefined or set to 'default', the certificate subject is only considered if the subject alternative name extension either does not exist or does not contain any DNS names. This behavior is consistent with RFC 2818 ("HTTP Over TLS").

If the 'subject' option is set to 'always' and if the subject alternative name extension either does not exist or does not contain a matching DNS name, the certificate subject is considered.

If the 'subject' option is set to 'never', the certificate subject is never considered, even if the certificate contains no subject alternative names.

x509.checkIP(ip)#

Checks whether the certificate matches the given IP address (IPv4 or IPv6).

Only RFC 5280 iPAddress subject alternative names are considered, and they must match the given ip address exactly. Other subject alternative names as well as the subject field of the certificate are ignored.

x509.checkIssued(otherCert)#

Checks whether this certificate was issued by the given otherCert.

x509.checkPrivateKey(privateKey)#

Checks whether the public key for this certificate is consistent with the given private key.

x509.extKeyUsage#

An array detailing the key extended usages for this certificate.

x509.fingerprint#

The SHA-1 fingerprint of this certificate.

Because SHA-1 is cryptographically broken and because the security of SHA-1 is significantly worse than that of algorithms that are commonly used to sign certificates, consider using x509.fingerprint256 instead.

x509.fingerprint256#

The SHA-256 fingerprint of this certificate.

x509.fingerprint512#

The SHA-512 fingerprint of this certificate.

Because computing the SHA-256 fingerprint is usually faster and because it is only half the size of the SHA-512 fingerprint, x509.fingerprint256 may be a better choice. While SHA-512 presumably provides a higher level of security in general, the security of SHA-256 matches that of most algorithms that are commonly used to sign certificates.

x509.infoAccess#

A textual representation of the certificate's authority information access extension.

This is a line feed separated list of access descriptions. Each line begins with the access method and the kind of the access location, followed by a colon and the value associated with the access location.

After the prefix denoting the access method and the kind of the access location, the remainder of each line might be enclosed in quotes to indicate that the value is a JSON string literal. For backward compatibility, Node.js only uses JSON string literals within this property when necessary to avoid ambiguity. Third-party code should be prepared to handle both possible entry formats.

x509.issuer#

The issuer identification included in this certificate.

x509.issuerCertificate#

The issuer certificate or undefined if the issuer certificate is not available.

x509.publicKey#

The public key <KeyObject> for this certificate.

x509.raw#

A Buffer containing the DER encoding of this certificate.

x509.serialNumber#

The serial number of this certificate.

Serial numbers are assigned by certificate authorities and do not uniquely identify certificates. Consider using x509.fingerprint256 as a unique identifier instead.

x509.subject#

The complete subject of this certificate.

x509.subjectAltName#

The subject alternative name specified for this certificate.

This is a comma-separated list of subject alternative names. Each entry begins with a string identifying the kind of the subject alternative name followed by a colon and the value associated with the entry.

Earlier versions of Node.js incorrectly assumed that it is safe to split this property at the two-character sequence ', ' (see CVE-2021-44532). However, both malicious and legitimate certificates can contain subject alternative names that include this sequence when represented as a string.

After the prefix denoting the type of the entry, the remainder of each entry might be enclosed in quotes to indicate that the value is a JSON string literal. For backward compatibility, Node.js only uses JSON string literals within this property when necessary to avoid ambiguity. Third-party code should be prepared to handle both possible entry formats.

x509.toJSON()#

There is no standard JSON encoding for X509 certificates. The toJSON() method returns a string containing the PEM encoded certificate.

x509.toLegacyObject()#

Returns information about this certificate using the legacy certificate object encoding.

x509.toString()#

Returns the PEM-encoded certificate.

x509.validFrom#

The date/time from which this certificate is valid.

x509.validFromDate#

The date/time from which this certificate is valid, encapsulated in a Date object.

x509.validTo#

The date/time until which this certificate is valid.

x509.validToDate#

The date/time until which this certificate is valid, encapsulated in a Date object.

x509.verify(publicKey)#

Verifies that this certificate was signed by the given public key. Does not perform any other validation checks on the certificate.

node:crypto module methods and properties#

crypto.checkPrime(candidate[, options], callback)#

  • candidate <ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint> A possible prime encoded as a sequence of big endian octets of arbitrary length.
  • options <Object>
    • checks <number> The number of Miller-Rabin probabilistic primality iterations to perform. When the value is 0 (zero), a number of checks is used that yields a false positive rate of at most 2-64 for random input. Care must be used when selecting a number of checks. Refer to the OpenSSL documentation for the BN_is_prime_ex function nchecks options for more details. Default: 0
  • callback <Function>
    • err <Error> Set to an <Error> object if an error occurred during check.
    • result <boolean> true if the candidate is a prime with an error probability less than 0.25 ** options.checks.

Checks the primality of the candidate.

crypto.checkPrimeSync(candidate[, options])#

  • candidate <ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint> A possible prime encoded as a sequence of big endian octets of arbitrary length.
  • options <Object>
    • checks <number> The number of Miller-Rabin probabilistic primality iterations to perform. When the value is 0 (zero), a number of checks is used that yields a false positive rate of at most 2-64 for random input. Care must be used when selecting a number of checks. Refer to the OpenSSL documentation for the BN_is_prime_ex function nchecks options for more details. Default: 0
  • Returns: <boolean> true if the candidate is a prime with an error probability less than 0.25 ** options.checks.

Checks the primality of the candidate.

crypto.constants#

An object containing commonly used constants for crypto and security related operations. The specific constants currently defined are described in Crypto constants.

crypto.createCipheriv(algorithm, key, iv[, options])#

Creates and returns a Cipheriv object, with the given algorithm, key and initialization vector (iv).

The options argument controls stream behavior and is optional except when a cipher in CCM or OCB mode (e.g. 'aes-128-ccm') is used. In that case, the authTagLength option is required and specifies the length of the authentication tag in bytes, see CCM mode. In GCM mode, the authTagLength option is not required but can be used to set the length of the authentication tag that will be returned by getAuthTag() and defaults to 16 bytes. For chacha20-poly1305, the authTagLength option defaults to 16 bytes.

The algorithm is dependent on OpenSSL, examples are 'aes192', etc. On recent OpenSSL releases, openssl list -cipher-algorithms will display the available cipher algorithms.

The key is the raw key used by the algorithm and iv is an initialization vector. Both arguments must be 'utf8' encoded strings, Buffers, TypedArray, or DataViews. The key may optionally be a KeyObject of type secret. If the cipher does not need an initialization vector, iv may be null.

When passing strings for key or iv, please consider caveats when using strings as inputs to cryptographic APIs.

Initialization vectors should be unpredictable and unique; ideally, they will be cryptographically random. They do not have to be secret: IVs are typically just added to ciphertext messages unencrypted. It may sound contradictory that something has to be unpredictable and unique, but does not have to be secret; remember that an attacker must not be able to predict ahead of time what a given IV will be.

crypto.createDecipheriv(algorithm, key, iv[, options])#

Creates and returns a Decipheriv object that uses the given algorithm, key and initialization vector (iv).

The options argument controls stream behavior and is optional except when a cipher in CCM or OCB mode (e.g. 'aes-128-ccm') is used. In that case, the authTagLength option is required and specifies the length of the authentication tag in bytes, see CCM mode. For AES-GCM and chacha20-poly1305, the authTagLength option defaults to 16 bytes and must be set to a different value if a different length is used.

The algorithm is dependent on OpenSSL, examples are 'aes192', etc. On recent OpenSSL releases, openssl list -cipher-algorithms will display the available cipher algorithms.

The key is the raw key used by the algorithm and iv is an initialization vector. Both arguments must be 'utf8' encoded strings, Buffers, TypedArray, or DataViews. The key may optionally be a KeyObject of type secret. If the cipher does not need an initialization vector, iv may be null.

When passing strings for key or iv, please consider caveats when using strings as inputs to cryptographic APIs.

Initialization vectors should be unpredictable and unique; ideally, they will be cryptographically random. They do not have to be secret: IVs are typically just added to ciphertext messages unencrypted. It may sound contradictory that something has to be unpredictable and unique, but does not have to be secret; remember that an attacker must not be able to predict ahead of time what a given IV will be.

crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding])#

Creates a DiffieHellman key exchange object using the supplied prime and an optional specific generator.

The generator argument can be a number, string, or Buffer. If generator is not specified, the value 2 is used.

If primeEncoding is specified, prime is expected to be a string; otherwise a Buffer, TypedArray, or DataView is expected.

If generatorEncoding is specified, generator is expected to be a string; otherwise a number, Buffer, TypedArray, or DataView is expected.

crypto.createDiffieHellman(primeLength[, generator])#

Creates a DiffieHellman key exchange object and generates a prime of primeLength bits using an optional specific numeric generator. If generator is not specified, the value 2 is used.

crypto.createDiffieHellmanGroup(name)#

An alias for crypto.getDiffieHellman()

crypto.createECDH(curveName)#

Creates an Elliptic Curve Diffie-Hellman (ECDH) key exchange object using a predefined curve specified by the curveName string. Use crypto.getCurves() to obtain a list of available curve names. On recent OpenSSL releases, openssl ecparam -list_curves will also display the name and description of each available elliptic curve.

crypto.createHash(algorithm[, options])#

Creates and returns a Hash object that can be used to generate hash digests using the given algorithm. Optional options argument controls stream behavior. For XOF hash functions such as 'shake256', the outputLength option can be used to specify the desired output length in bytes.

The algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are 'sha256', 'sha512', etc. On recent releases of OpenSSL, openssl list -digest-algorithms will display the available digest algorithms.

Example: generating the sha256 sum of a file

import {
  createReadStream,
} from 'node:fs';
import { argv } from 'node:process';
const {
  createHash,
} = await import('node:crypto');

const filename = argv[2];

const hash = createHash('sha256');

const input = createReadStream(filename);
input.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = input.read();
  if (data)
    hash.update(data);
  else {
    console.log(`${hash.digest('hex')} ${filename}`);
  }
});const {
  createReadStream,
} = require('node:fs');
const {
  createHash,
} = require('node:crypto');
const { argv } = require('node:process');

const filename = argv[2];

const hash = createHash('sha256');

const input = createReadStream(filename);
input.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = input.read();
  if (data)
    hash.update(data);
  else {
    console.log(`${hash.digest('hex')} ${filename}`);
  }
});

crypto.createHmac(algorithm, key[, options])#

Creates and returns an Hmac object that uses the given algorithm and key. Optional options argument controls stream behavior.

The algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are 'sha256', 'sha512', etc. On recent releases of OpenSSL, openssl list -digest-algorithms will display the available digest algorithms.

The key is the HMAC key used to generate the cryptographic HMAC hash. If it is a KeyObject, its type must be secret. If it is a string, please consider caveats when using strings as inputs to cryptographic APIs. If it was obtained from a cryptographically secure source of entropy, such as crypto.randomBytes() or crypto.generateKey(), its length should not exceed the block size of algorithm (e.g., 512 bits for SHA-256).

Example: generating the sha256 HMAC of a file

import {
  createReadStream,
} from 'node:fs';
import { argv } from 'node:process';
const {
  createHmac,
} = await import('node:crypto');

const filename = argv[2];

const hmac = createHmac('sha256', 'a secret');

const input = createReadStream(filename);
input.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = input.read();
  if (data)
    hmac.update(data);
  else {
    console.log(`${hmac.digest('hex')} ${filename}`);
  }
});const {
  createReadStream,
} = require('node:fs');
const {
  createHmac,
} = require('node:crypto');
const { argv } = require('node:process');

const filename = argv[2];

const hmac = createHmac('sha256', 'a secret');

const input = createReadStream(filename);
input.on('readable', () => {
  // Only one element is going to be produced by the
  // hash stream.
  const data = input.read();
  if (data)
    hmac.update(data);
  else {
    console.log(`${hmac.digest('hex')} ${filename}`);
  }
});

crypto.createPrivateKey(key)#

Creates and returns a new key object containing a private key. If key is a string or Buffer, format is assumed to be 'pem'; otherwise, key must be an object with the properties described above.

If the private key is encrypted, a passphrase must be specified. The length of the passphrase is limited to 1024 bytes.

crypto.createPublicKey(key)#

Creates and returns a new key object containing a public key. If key is a string or Buffer, format is assumed to be 'pem'; if key is a KeyObject with type 'private', the public key is derived from the given private key; otherwise, key must be an object with the properties described above.

If the format is 'pem', the 'key' may also be an X.509 certificate.

Because public keys can be derived from private keys, a private key may be passed instead of a public key. In that case, this function behaves as if crypto.createPrivateKey() had been called, except that the type of the returned KeyObject will be 'public' and that the private key cannot be extracted from the returned KeyObject. Similarly, if a KeyObject with type 'private' is given, a new KeyObject with type 'public' will be returned and it will be impossible to extract the private key from the returned object.

crypto.createSecretKey(key[, encoding])#

Creates and returns a new key object containing a secret key for symmetric encryption or Hmac.

crypto.createSign(algorithm[, options])#

Creates and returns a Sign object that uses the given algorithm. Use crypto.getHashes() to obtain the names of the available digest algorithms. Optional options argument controls the stream.Writable behavior.

In some cases, a Sign instance can be created using the name of a signature algorithm, such as 'RSA-SHA256', instead of a digest algorithm. This will use the corresponding digest algorithm. This does not work for all signature algorithms, such as 'ecdsa-with-SHA256', so it is best to always use digest algorithm names.

crypto.createVerify(algorithm[, options])#

Creates and returns a Verify object that uses the given algorithm. Use crypto.getHashes() to obtain an array of names of the available signing algorithms. Optional options argument controls the stream.Writable behavior.

In some cases, a Verify instance can be created using the name of a signature algorithm, such as 'RSA-SHA256', instead of a digest algorithm. This will use the corresponding digest algorithm. This does not work for all signature algorithms, such as 'ecdsa-with-SHA256', so it is best to always use digest algorithm names.

crypto.diffieHellman(options[, callback])#

Computes the Diffie-Hellman secret based on a privateKey and a publicKey. Both keys must have the same asymmetricKeyType, which must be one of 'dh' (for Diffie-Hellman), 'ec', 'x448', or 'x25519' (for ECDH).

If the callback function is provided this function uses libuv's threadpool.

crypto.fips#

Stability: 0 - Deprecated

Property for checking and controlling whether a FIPS compliant crypto provider is currently in use. Setting to true requires a FIPS build of Node.js.

This property is deprecated. Please use crypto.setFips() and crypto.getFips() instead.

crypto.generateKey(type, options, callback)#

  • type: <string> The intended use of the generated secret key. Currently accepted values are 'hmac' and 'aes'.
  • options: <Object>
    • length: <number> The bit length of the key to generate. This must be a value greater than 0.
      • If type is 'hmac', the minimum is 8, and the maximum length is 231-1. If the value is not a multiple of 8, the generated key will be truncated to Math.floor(length / 8).
      • If type is 'aes', the length must be one of 128, 192, or 256.
  • callback: <Function>

Asynchronously generates a new random secret key of the given length. The type will determine which validations will be performed on the length.

const {
  generateKey,
} = await import('node:crypto');

generateKey('hmac', { length: 512 }, (err, key) => {
  if (err) throw err;
  console.log(key.export().toString('hex'));  // 46e..........620
});const {
  generateKey,
} = require('node:crypto');

generateKey('hmac', { length: 512 }, (err, key) => {
  if (err) throw err;
  console.log(key.export().toString('hex'));  // 46e..........620
});

The size of a generated HMAC key should not exceed the block size of the underlying hash function. See crypto.createHmac() for more information.

crypto.generateKeyPair(type, options, callback)#

Generates a new asymmetric key pair of the given type. RSA, RSA-PSS, DSA, EC, Ed25519, Ed448, X25519, X448, and DH are currently supported.

If a publicKeyEncoding or privateKeyEncoding was specified, this function behaves as if keyObject.export() had been called on its result. Otherwise, the respective part of the key is returned as a KeyObject.

It is recommended to encode public keys as 'spki' and private keys as 'pkcs8' with encryption for long-term storage:

const {
  generateKeyPair,
} = await import('node:crypto');

generateKeyPair('rsa', {
  modulusLength: 4096,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem',
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
    cipher: 'aes-256-cbc',
    passphrase: 'top secret',
  },
}, (err, publicKey, privateKey) => {
  // Handle errors and use the generated key pair.
});const {
  generateKeyPair,
} = require('node:crypto');

generateKeyPair('rsa', {
  modulusLength: 4096,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem',
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
    cipher: 'aes-256-cbc',
    passphrase: 'top secret',
  },
}, (err, publicKey, privateKey) => {
  // Handle errors and use the generated key pair.
});

On completion, callback will be called with err set to undefined and publicKey / privateKey representing the generated key pair.

If this method is invoked as its util.promisify()ed version, it returns a Promise for an Object with publicKey and privateKey properties.

crypto.generateKeyPairSync(type, options)#

Generates a new asymmetric key pair of the given type. RSA, RSA-PSS, DSA, EC, Ed25519, Ed448, X25519, X448, and DH are currently supported.

If a publicKeyEncoding or privateKeyEncoding was specified, this function behaves as if keyObject.export() had been called on its result. Otherwise, the respective part of the key is returned as a KeyObject.

When encoding public keys, it is recommended to use 'spki'. When encoding private keys, it is recommended to use 'pkcs8' with a strong passphrase, and to keep the passphrase confidential.

const {
  generateKeyPairSync,
} = await import('node:crypto');

const {
  publicKey,
  privateKey,
} = generateKeyPairSync('rsa', {
  modulusLength: 4096,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem',
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
    cipher: 'aes-256-cbc',
    passphrase: 'top secret',
  },
});const {
  generateKeyPairSync,
} = require('node:crypto');

const {
  publicKey,
  privateKey,
} = generateKeyPairSync('rsa', {
  modulusLength: 4096,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem',
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
    cipher: 'aes-256-cbc',
    passphrase: 'top secret',
  },
});

The return value { publicKey, privateKey } represents the generated key pair. When PEM encoding was selected, the respective key will be a string, otherwise it will be a buffer containing the data encoded as DER.

crypto.generateKeySync(type, options)#

  • type: <string> The intended use of the generated secret key. Currently accepted values are 'hmac' and 'aes'.
  • options: <Object>
    • length: <number> The bit length of the key to generate.
      • If type is 'hmac', the minimum is 8, and the maximum length is 231-1. If the value is not a multiple of 8, the generated key will be truncated to Math.floor(length / 8).
      • If type is 'aes', the length must be one of 128, 192, or 256.
  • Returns: <KeyObject>

Synchronously generates a new random secret key of the given length. The type will determine which validations will be performed on the length.

const {
  generateKeySync,
} = await import('node:crypto');

const key = generateKeySync('hmac', { length: 512 });
console.log(key.export().toString('hex'));  // e89..........41econst {
  generateKeySync,
} = require('node:crypto');

const key = generateKeySync('hmac', { length: 512 });
console.log(key.export().toString('hex'));  // e89..........41e

The size of a generated HMAC key should not exceed the block size of the underlying hash function. See crypto.createHmac() for more information.

crypto.generatePrime(size[, options], callback)#

Generates a pseudorandom prime of size bits.

If options.safe is true, the prime will be a safe prime -- that is, (prime - 1) / 2 will also be a prime.

The options.add and options.rem parameters can be used to enforce additional requirements, e.g., for Diffie-Hellman:

  • If options.add and options.rem are both set, the prime will satisfy the condition that prime % add = rem.
  • If only options.add is set and options.safe is not true, the prime will satisfy the condition that prime % add = 1.
  • If only options.add is set and options.safe is set to true, the prime will instead satisfy the condition that prime % add = 3. This is necessary because prime % add = 1 for options.add > 2 would contradict the condition enforced by options.safe.
  • options.rem is ignored if options.add is not given.

Both options.add and options.rem must be encoded as big-endian sequences if given as an ArrayBuffer, SharedArrayBuffer, TypedArray, Buffer, or DataView.

By default, the prime is encoded as a big-endian sequence of octets in an <ArrayBuffer>. If the bigint option is true, then a <bigint> is provided.

The size of the prime will have a direct impact on how long it takes to generate the prime. The larger the size, the longer it will take. Because we use OpenSSL's BN_generate_prime_ex function, which provides only minimal control over our ability to interrupt the generation process, it is not recommended to generate overly large primes, as doing so may make the process unresponsive.

crypto.generatePrimeSync(size[, options])#

Generates a pseudorandom prime of size bits.

If options.safe is true, the prime will be a safe prime -- that is, (prime - 1) / 2 will also be a prime.

The options.add and options.rem parameters can be used to enforce additional requirements, e.g., for Diffie-Hellman:

  • If options.add and options.rem are both set, the prime will satisfy the condition that prime % add = rem.
  • If only options.add is set and options.safe is not true, the prime will satisfy the condition that prime % add = 1.
  • If only options.add is set and options.safe is set to true, the prime will instead satisfy the condition that prime % add = 3. This is necessary because prime % add = 1 for options.add > 2 would contradict the condition enforced by options.safe.
  • options.rem is ignored if options.add is not given.

Both options.add and options.rem must be encoded as big-endian sequences if given as an ArrayBuffer, SharedArrayBuffer, TypedArray, Buffer, or DataView.

By default, the prime is encoded as a big-endian sequence of octets in an <ArrayBuffer>. If the bigint option is true, then a <bigint> is provided.

The size of the prime will have a direct impact on how long it takes to generate the prime. The larger the size, the longer it will take. Because we use OpenSSL's BN_generate_prime_ex function, which provides only minimal control over our ability to interrupt the generation process, it is not recommended to generate overly large primes, as doing so may make the process unresponsive.

crypto.getCipherInfo(nameOrNid[, options])#

  • nameOrNid: <string> | <number> The name or nid of the cipher to query.
  • options: <Object>
  • Returns: <Object>
    • name <string> The name of the cipher
    • nid <number> The nid of the cipher
    • blockSize <number> The block size of the cipher in bytes. This property is omitted when mode is 'stream'.
    • ivLength <number> The expected or default initialization vector length in bytes. This property is omitted if the cipher does not use an initialization vector.
    • keyLength <number> The expected or default key length in bytes.
    • mode <string> The cipher mode. One of 'cbc', 'ccm', 'cfb', 'ctr', 'ecb', 'gcm', 'ocb', 'ofb', 'stream', 'wrap', 'xts'.

Returns information about a given cipher.

Some ciphers accept variable length keys and initialization vectors. By default, the crypto.getCipherInfo() method will return the default values for these ciphers. To test if a given key length or iv length is acceptable for given cipher, use the keyLength and ivLength options. If the given values are unacceptable, undefined will be returned.

crypto.getCiphers()#

  • Returns: <string[]> An array with the names of the supported cipher algorithms.
const {
  getCiphers,
} = await import('node:crypto');

console.log(getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...]const {
  getCiphers,
} = require('node:crypto');

console.log(getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...]

crypto.getCurves()#

  • Returns: <string[]> An array with the names of the supported elliptic curves.
const {
  getCurves,
} = await import('node:crypto');

console.log(getCurves()); // ['Oakley-EC2N-3', 'Oakley-EC2N-4', ...]const {
  getCurves,
} = require('node:crypto');

console.log(getCurves()); // ['Oakley-EC2N-3', 'Oakley-EC2N-4', ...]

crypto.getDiffieHellman(groupName)#

Creates a predefined DiffieHellmanGroup key exchange object. The supported groups are listed in the documentation for DiffieHellmanGroup.

The returned object mimics the interface of objects created by crypto.createDiffieHellman(), but will not allow changing the keys (with diffieHellman.setPublicKey(), for example). The advantage of using this method is that the parties do not have to generate nor exchange a group modulus beforehand, saving both processor and communication time.

Example (obtaining a shared secret):

const {
  getDiffieHellman,
} = await import('node:crypto');
const alice = getDiffieHellman('modp14');
const bob = getDiffieHellman('modp14');

alice.generateKeys();
bob.generateKeys();

const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

/* aliceSecret and bobSecret should be the same */
console.log(aliceSecret === bobSecret);const {
  getDiffieHellman,
} = require('node:crypto');

const alice = getDiffieHellman('modp14');
const bob = getDiffieHellman('modp14');

alice.generateKeys();
bob.generateKeys();

const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

/* aliceSecret and bobSecret should be the same */
console.log(aliceSecret === bobSecret);

crypto.getFips()#

  • Returns: <number> 1 if and only if a FIPS compliant crypto provider is currently in use, 0 otherwise. A future semver-major release may change the return type of this API to a <boolean>.

crypto.getHashes()#

  • Returns: <string[]> An array of the names of the supported hash algorithms, such as 'RSA-SHA256'. Hash algorithms are also called "digest" algorithms.
const {
  getHashes,
} = await import('node:crypto');

console.log(getHashes()); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...]const {
  getHashes,
} = require('node:crypto');

console.log(getHashes()); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...]

crypto.getRandomValues(typedArray)#

A convenient alias for crypto.webcrypto.getRandomValues(). This implementation is not compliant with the Web Crypto spec, to write web-compatible code use crypto.webcrypto.getRandomValues() instead.

crypto.hash(algorithm, data[, outputEncoding])#

Stability: 1.2 - Release candidate

A utility for creating one-shot hash digests of data. It can be faster than the object-based crypto.createHash() when hashing a smaller amount of data (<= 5MB) that's readily available. If the data can be big or if it is streamed, it's still recommended to use crypto.createHash() instead.

The algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are 'sha256', 'sha512', etc. On recent releases of OpenSSL, openssl list -digest-algorithms will display the available digest algorithms.

Example:

const crypto = require('node:crypto');
const { Buffer } = require('node:buffer');

// Hashing a string and return the result as a hex-encoded string.
const string = 'Node.js';
// 10b3493287f831e81a438811a1ffba01f8cec4b7
console.log(crypto.hash('sha1', string));

// Encode a base64-encoded string into a Buffer, hash it and return
// the result as a buffer.
const base64 = 'Tm9kZS5qcw==';
// <Buffer 10 b3 49 32 87 f8 31 e8 1a 43 88 11 a1 ff ba 01 f8 ce c4 b7>
console.log(crypto.hash('sha1', Buffer.from(base64, 'base64'), 'buffer'));import crypto from 'node:crypto';
import { Buffer } from 'node:buffer';

// Hashing a string and return the result as a hex-encoded string.
const string = 'Node.js';
// 10b3493287f831e81a438811a1ffba01f8cec4b7
console.log(crypto.hash('sha1', string));

// Encode a base64-encoded string into a Buffer, hash it and return
// the result as a buffer.
const base64 = 'Tm9kZS5qcw==';
// <Buffer 10 b3 49 32 87 f8 31 e8 1a 43 88 11 a1 ff ba 01 f8 ce c4 b7>
console.log(crypto.hash('sha1', Buffer.from(base64, 'base64'), 'buffer'));

crypto.hkdf(digest, ikm, salt, info, keylen, callback)#

HKDF is a simple key derivation function defined in RFC 5869. The given ikm, salt and info are used with the digest to derive a key of keylen bytes.

The supplied callback function is called with two arguments: err and derivedKey. If an errors occurs while deriving the key, err will be set; otherwise err will be null. The successfully generated derivedKey will be passed to the callback as an <ArrayBuffer>. An error will be thrown if any of the input arguments specify invalid values or types.

import { Buffer } from 'node:buffer';
const {
  hkdf,
} = await import('node:crypto');

hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {
  if (err) throw err;
  console.log(Buffer.from(derivedKey).toString('hex'));  // '24156e2...5391653'
});const {
  hkdf,
} = require('node:crypto');
const { Buffer } = require('node:buffer');

hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {
  if (err) throw err;
  console.log(Buffer.from(derivedKey).toString('hex'));  // '24156e2...5391653'
});

crypto.hkdfSync(digest, ikm, salt, info, keylen)#

Provides a synchronous HKDF key derivation function as defined in RFC 5869. The given ikm, salt and info are used with the digest to derive a key of keylen bytes.

The successfully generated derivedKey will be returned as an <ArrayBuffer>.

An error will be thrown if any of the input arguments specify invalid values or types, or if the derived key cannot be generated.

import { Buffer } from 'node:buffer';
const {
  hkdfSync,
} = await import('node:crypto');

const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64);
console.log(Buffer.from(derivedKey).toString('hex'));  // '24156e2...5391653'const {
  hkdfSync,
} = require('node:crypto');
const { Buffer } = require('node:buffer');

const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64);
console.log(Buffer.from(derivedKey).toString('hex'));  // '24156e2...5391653'

crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)#

Provides an asynchronous Password-Based Key Derivation Function 2 (PBKDF2) implementation. A selected HMAC digest algorithm specified by digest is applied to derive a key of the requested byte length (keylen) from the password, salt and iterations.

The supplied callback function is called with two arguments: err and derivedKey. If an error occurs while deriving the key, err will be set; otherwise err will be null. By default, the successfully generated derivedKey will be passed to the callback as a Buffer. An error will be thrown if any of the input arguments specify invalid values or types.

The iterations argument must be a number set as high as possible. The higher the number of iterations, the more secure the derived key will be, but will take a longer amount of time to complete.

The salt should be as unique as possible. It is recommended that a salt is random and at least 16 bytes long. See NIST SP 800-132 for details.

When passing strings for password or salt, please consider caveats when using strings as inputs to cryptographic APIs.

const {
  pbkdf2,
} = await import('node:crypto');

pbkdf2('secret', 'salt', 100000, 64, 'sha512', (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...08d59ae'
});const {
  pbkdf2,
} = require('node:crypto');

pbkdf2('secret', 'salt', 100000, 64, 'sha512', (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...08d59ae'
});

An array of supported digest functions can be retrieved using crypto.getHashes().

This API uses libuv's threadpool, which can have surprising and negative performance implications for some applications; see the UV_THREADPOOL_SIZE documentation for more information.

crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)#

Provides a synchronous Password-Based Key Derivation Function 2 (PBKDF2) implementation. A selected HMAC digest algorithm specified by digest is applied to derive a key of the requested byte length (keylen) from the password, salt and iterations.

If an error occurs an Error will be thrown, otherwise the derived key will be returned as a Buffer.

The iterations argument must be a number set as high as possible. The higher the number of iterations, the more secure the derived key will be, but will take a longer amount of time to complete.

The salt should be as unique as possible. It is recommended that a salt is random and at least 16 bytes long. See NIST SP 800-132 for details.

When passing strings for password or salt, please consider caveats when using strings as inputs to cryptographic APIs.

const {
  pbkdf2Sync,
} = await import('node:crypto');

const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha512');
console.log(key.toString('hex'));  // '3745e48...08d59ae'const {
  pbkdf2Sync,
} = require('node:crypto');

const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha512');
console.log(key.toString('hex'));  // '3745e48...08d59ae'

An array of supported digest functions can be retrieved using crypto.getHashes().

crypto.privateDecrypt(privateKey, buffer)#

Decrypts buffer with privateKey. buffer was previously encrypted using the corresponding public key, for example using crypto.publicEncrypt().

If privateKey is not a KeyObject, this function behaves as if privateKey had been passed to crypto.createPrivateKey(). If it is an object, the padding property can be passed. Otherwise, this function uses RSA_PKCS1_OAEP_PADDING.

Using crypto.constants.RSA_PKCS1_PADDING in crypto.privateDecrypt() requires OpenSSL to support implicit rejection (rsa_pkcs1_implicit_rejection). If the version of OpenSSL used by Node.js does not support this feature, attempting to use RSA_PKCS1_PADDING will fail.

crypto.privateEncrypt(privateKey, buffer)#

Encrypts buffer with privateKey. The returned data can be decrypted using the corresponding public key, for example using crypto.publicDecrypt().

If privateKey is not a KeyObject, this function behaves as if privateKey had been passed to crypto.createPrivateKey(). If it is an object, the padding property can be passed. Otherwise, this function uses RSA_PKCS1_PADDING.

crypto.publicDecrypt(key, buffer)#

Decrypts buffer with key.buffer was previously encrypted using the corresponding private key, for example using crypto.privateEncrypt().

If key is not a KeyObject, this function behaves as if key had been passed to crypto.createPublicKey(). If it is an object, the padding property can be passed. Otherwise, this function uses RSA_PKCS1_PADDING.

Because RSA public keys can be derived from private keys, a private key may be passed instead of a public key.

crypto.publicEncrypt(key, buffer)#

Encrypts the content of buffer with key and returns a new Buffer with encrypted content. The returned data can be decrypted using the corresponding private key, for example using crypto.privateDecrypt().

If key is not a KeyObject, this function behaves as if key had been passed to crypto.createPublicKey(). If it is an object, the padding property can be passed. Otherwise, this function uses RSA_PKCS1_OAEP_PADDING.

Because RSA public keys can be derived from private keys, a private key may be passed instead of a public key.

crypto.randomBytes(size[, callback])#

Generates cryptographically strong pseudorandom data. The size argument is a number indicating the number of bytes to generate.

If a callback function is provided, the bytes are generated asynchronously and the callback function is invoked with two arguments: err and buf. If an error occurs, err will be an Error object; otherwise it is null. The buf argument is a Buffer containing the generated bytes.

// Asynchronous
const {
  randomBytes,
} = await import('node:crypto');

randomBytes(256, (err, buf) => {
  if (err) throw err;
  console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);
});// Asynchronous
const {
  randomBytes,
} = require('node:crypto');

randomBytes(256, (err, buf) => {
  if (err) throw err;
  console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);
});

If the callback function is not provided, the random bytes are generated synchronously and returned as a Buffer. An error will be thrown if there is a problem generating the bytes.

// Synchronous
const {
  randomBytes,
} = await import('node:crypto');

const buf = randomBytes(256);
console.log(
  `${buf.length} bytes of random data: ${buf.toString('hex')}`);// Synchronous
const {
  randomBytes,
} = require('node:crypto');

const buf = randomBytes(256);
console.log(
  `${buf.length} bytes of random data: ${buf.toString('hex')}`);

The crypto.randomBytes() method will not complete until there is sufficient entropy available. This should normally never take longer than a few milliseconds. The only time when generating the random bytes may conceivably block for a longer period of time is right after boot, when the whole system is still low on entropy.

This API uses libuv's threadpool, which can have surprising and negative performance implications for some applications; see the UV_THREADPOOL_SIZE documentation for more information.

The asynchronous version of crypto.randomBytes() is carried out in a single threadpool request. To minimize threadpool task length variation, partition large randomBytes requests when doing so as part of fulfilling a client request.

crypto.randomFill(buffer[, offset][, size], callback)#

This function is similar to crypto.randomBytes() but requires the first argument to be a Buffer that will be filled. It also requires that a callback is passed in.

If the callback function is not provided, an error will be thrown.

import { Buffer } from 'node:buffer';
const { randomFill } = await import('node:crypto');

const buf = Buffer.alloc(10);
randomFill(buf, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});

randomFill(buf, 5, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});

// The above is equivalent to the following:
randomFill(buf, 5, 5, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});const { randomFill } = require('node:crypto');
const { Buffer } = require('node:buffer');

const buf = Buffer.alloc(10);
randomFill(buf, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});

randomFill(buf, 5, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});

// The above is equivalent to the following:
randomFill(buf, 5, 5, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});

Any ArrayBuffer, TypedArray, or DataView instance may be passed as buffer.

While this includes instances of Float32Array and Float64Array, this function should not be used to generate random floating-point numbers. The result may contain +Infinity, -Infinity, and NaN, and even if the array contains finite numbers only, they are not drawn from a uniform random distribution and have no meaningful lower or upper bounds.

import { Buffer } from 'node:buffer';
const { randomFill } = await import('node:crypto');

const a = new Uint32Array(10);
randomFill(a, (err, buf) => {
  if (err) throw err;
  console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
    .toString('hex'));
});

const b = new DataView(new ArrayBuffer(10));
randomFill(b, (err, buf) => {
  if (err) throw err;
  console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
    .toString('hex'));
});

const c = new ArrayBuffer(10);
randomFill(c, (err, buf) => {
  if (err) throw err;
  console.log(Buffer.from(buf).toString('hex'));
});const { randomFill } = require('node:crypto');
const { Buffer } = require('node:buffer');

const a = new Uint32Array(10);
randomFill(a, (err, buf) => {
  if (err) throw err;
  console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
    .toString('hex'));
});

const b = new DataView(new ArrayBuffer(10));
randomFill(b, (err, buf) => {
  if (err) throw err;
  console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
    .toString('hex'));
});

const c = new ArrayBuffer(10);
randomFill(c, (err, buf) => {
  if (err) throw err;
  console.log(Buffer.from(buf).toString('hex'));
});

This API uses libuv's threadpool, which can have surprising and negative performance implications for some applications; see the UV_THREADPOOL_SIZE documentation for more information.

The asynchronous version of crypto.randomFill() is carried out in a single threadpool request. To minimize threadpool task length variation, partition large randomFill requests when doing so as part of fulfilling a client request.

crypto.randomFillSync(buffer[, offset][, size])#

Synchronous version of crypto.randomFill().

import { Buffer } from 'node:buffer';
const { randomFillSync } = await import('node:crypto');

const buf = Buffer.alloc(10);
console.log(randomFillSync(buf).toString('hex'));

randomFillSync(buf, 5);
console.log(buf.toString('hex'));

// The above is equivalent to the following:
randomFillSync(buf, 5, 5);
console.log(buf.toString('hex'));const { randomFillSync } = require('node:crypto');
const { Buffer } = require('node:buffer');

const buf = Buffer.alloc(10);
console.log(randomFillSync(buf).toString('hex'));

randomFillSync(buf, 5);
console.log(buf.toString('hex'));

// The above is equivalent to the following:
randomFillSync(buf, 5, 5);
console.log(buf.toString('hex'));

Any ArrayBuffer, TypedArray or DataView instance may be passed as buffer.

import { Buffer } from 'node:buffer';
const { randomFillSync } = await import('node:crypto');

const a = new Uint32Array(10);
console.log(Buffer.from(randomFillSync(a).buffer,
                        a.byteOffset, a.byteLength).toString('hex'));

const b = new DataView(new ArrayBuffer(10));
console.log(Buffer.from(randomFillSync(b).buffer,
                        b.byteOffset, b.byteLength).toString('hex'));

const c = new ArrayBuffer(10);
console.log(Buffer.from(randomFillSync(c)).toString('hex'));const { randomFillSync } = require('node:crypto');
const { Buffer } = require('node:buffer');

const a = new Uint32Array(10);
console.log(Buffer.from(randomFillSync(a).buffer,
                        a.byteOffset, a.byteLength).toString('hex'));

const b = new DataView(new ArrayBuffer(10));
console.log(Buffer.from(randomFillSync(b).buffer,
                        b.byteOffset, b.byteLength).toString('hex'));

const c = new ArrayBuffer(10);
console.log(Buffer.from(randomFillSync(c)).toString('hex'));

crypto.randomInt([min, ]max[, callback])#

  • min <integer> Start of random range (inclusive). Default: 0.
  • max <integer> End of random range (exclusive).
  • callback <Function> function(err, n) {}.

Return a random integer n such that min <= n < max. This implementation avoids modulo bias.

The range (max - min) must be less than 248. min and max must be safe integers.

If the callback function is not provided, the random integer is generated synchronously.

// Asynchronous
const {
  randomInt,
} = await import('node:crypto');

randomInt(3, (err, n) => {
  if (err) throw err;
  console.log(`Random number chosen from (0, 1, 2): ${n}`);
});// Asynchronous
const {
  randomInt,
} = require('node:crypto');

randomInt(3, (err, n) => {
  if (err) throw err;
  console.log(`Random number chosen from (0, 1, 2): ${n}`);
});
// Synchronous
const {
  randomInt,
} = await import('node:crypto');

const n = randomInt(3);
console.log(`Random number chosen from (0, 1, 2): ${n}`);// Synchronous
const {
  randomInt,
} = require('node:crypto');

const n = randomInt(3);
console.log(`Random number chosen from (0, 1, 2): ${n}`);
// With `min` argument
const {
  randomInt,
} = await import('node:crypto');

const n = randomInt(1, 7);
console.log(`The dice rolled: ${n}`);// With `min` argument
const {
  randomInt,
} = require('node:crypto');

const n = randomInt(1, 7);
console.log(`The dice rolled: ${n}`);

crypto.randomUUID([options])#

  • options <Object>
    • disableEntropyCache <boolean> By default, to improve performance, Node.js generates and caches enough random data to generate up to 128 random UUIDs. To generate a UUID without using the cache, set disableEntropyCache to true. Default: false.
  • Returns: <string>

Generates a random RFC 4122 version 4 UUID. The UUID is generated using a cryptographic pseudorandom number generator.

crypto.scrypt(password, salt, keylen[, options], callback)#

Provides an asynchronous scrypt implementation. Scrypt is a password-based key derivation function that is designed to be expensive computationally and memory-wise in order to make brute-force attacks unrewarding.

The salt should be as unique as possible. It is recommended that a salt is random and at least 16 bytes long. See NIST SP 800-132 for details.

When passing strings for password or salt, please consider caveats when using strings as inputs to cryptographic APIs.

The callback function is called with two arguments: err and derivedKey. err is an exception object when key derivation fails, otherwise err is null. derivedKey is passed to the callback as a Buffer.

An exception is thrown when any of the input arguments specify invalid values or types.

const {
  scrypt,
} = await import('node:crypto');

// Using the factory defaults.
scrypt('password', 'salt', 64, (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...08d59ae'
});
// Using a custom N parameter. Must be a power of two.
scrypt('password', 'salt', 64, { N: 1024 }, (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...aa39b34'
});const {
  scrypt,
} = require('node:crypto');

// Using the factory defaults.
scrypt('password', 'salt', 64, (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...08d59ae'
});
// Using a custom N parameter. Must be a power of two.
scrypt('password', 'salt', 64, { N: 1024 }, (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...aa39b34'
});

crypto.scryptSync(password, salt, keylen[, options])#

Provides a synchronous scrypt implementation. Scrypt is a password-based key derivation function that is designed to be expensive computationally and memory-wise in order to make brute-force attacks unrewarding.

The salt should be as unique as possible. It is recommended that a salt is random and at least 16 bytes long. See NIST SP 800-132 for details.

When passing strings for password or salt, please consider caveats when using strings as inputs to cryptographic APIs.

An exception is thrown when key derivation fails, otherwise the derived key is returned as a Buffer.

An exception is thrown when any of the input arguments specify invalid values or types.

const {
  scryptSync,
} = await import('node:crypto');
// Using the factory defaults.

const key1 = scryptSync('password', 'salt', 64);
console.log(key1.toString('hex'));  // '3745e48...08d59ae'
// Using a custom N parameter. Must be a power of two.
const key2 = scryptSync('password', 'salt', 64, { N: 1024 });
console.log(key2.toString('hex'));  // '3745e48...aa39b34'const {
  scryptSync,
} = require('node:crypto');
// Using the factory defaults.

const key1 = scryptSync('password', 'salt', 64);
console.log(key1.toString('hex'));  // '3745e48...08d59ae'
// Using a custom N parameter. Must be a power of two.
const key2 = scryptSync('password', 'salt', 64, { N: 1024 });
console.log(key2.toString('hex'));  // '3745e48...aa39b34'

crypto.secureHeapUsed()#

  • Returns: <Object>
    • total <number> The total allocated secure heap size as specified using the --secure-heap=n command-line flag.
    • min <number> The minimum allocation from the secure heap as specified using the --secure-heap-min command-line flag.
    • used <number> The total number of bytes currently allocated from the secure heap.
    • utilization <number> The calculated ratio of used to total allocated bytes.

crypto.setEngine(engine[, flags])#

Load and set the engine for some or all OpenSSL functions (selected by flags). Support for custom engines in OpenSSL is deprecated from OpenSSL 3.

engine could be either an id or a path to the engine's shared library.

The optional flags argument uses ENGINE_METHOD_ALL by default. The flags is a bit field taking one of or a mix of the following flags (defined in crypto.constants):

  • crypto.constants.ENGINE_METHOD_RSA
  • crypto.constants.ENGINE_METHOD_DSA
  • crypto.constants.ENGINE_METHOD_DH
  • crypto.constants.ENGINE_METHOD_RAND
  • crypto.constants.ENGINE_METHOD_EC
  • crypto.constants.ENGINE_METHOD_CIPHERS
  • crypto.constants.ENGINE_METHOD_DIGESTS
  • crypto.constants.ENGINE_METHOD_PKEY_METHS
  • crypto.constants.ENGINE_METHOD_PKEY_ASN1_METHS
  • crypto.constants.ENGINE_METHOD_ALL
  • crypto.constants.ENGINE_METHOD_NONE

crypto.setFips(bool)#

Enables the FIPS compliant crypto provider in a FIPS-enabled Node.js build. Throws an error if FIPS mode is not available.

crypto.sign(algorithm, data, key[, callback])#

Calculates and returns the signature for data using the given private key and algorithm. If algorithm is null or undefined, then the algorithm is dependent upon the key type (especially Ed25519 and Ed448).

If key is not a KeyObject, this function behaves as if key had been passed to crypto.createPrivateKey(). If it is an object, the following additional properties can be passed:

  • dsaEncoding <string> For DSA and ECDSA, this option specifies the format of the generated signature. It can be one of the following:

    • 'der' (default): DER-encoded ASN.1 signature structure encoding (r, s).
    • 'ieee-p1363': Signature format r || s as proposed in IEEE-P1363.
  • padding <integer> Optional padding value for RSA, one of the following:

    • crypto.constants.RSA_PKCS1_PADDING (default)
    • crypto.constants.RSA_PKCS1_PSS_PADDING

    RSA_PKCS1_PSS_PADDING will use MGF1 with the same hash function used to sign the message as specified in section 3.1 of RFC 4055.

  • saltLength <integer> Salt length for when padding is RSA_PKCS1_PSS_PADDING. The special value crypto.constants.RSA_PSS_SALTLEN_DIGEST sets the salt length to the digest size, crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN (default) sets it to the maximum permissible value.

If the callback function is provided this function uses libuv's threadpool.

crypto.subtle#

A convenient alias for crypto.webcrypto.subtle.

crypto.timingSafeEqual(a, b)#

This function compares the underlying bytes that represent the given ArrayBuffer, TypedArray, or DataView instances using a constant-time algorithm.

This function does not leak timing information that would allow an attacker to guess one of the values. This is suitable for comparing HMAC digests or secret values like authentication cookies or capability urls.

a and b must both be Buffers, TypedArrays, or DataViews, and they must have the same byte length. An error is thrown if a and b have different byte lengths.

If at least one of a and b is a TypedArray with more than one byte per entry, such as Uint16Array, the result will be computed using the platform byte order.

When both of the inputs are Float32Arrays or Float64Arrays, this function might return unexpected results due to IEEE 754 encoding of floating-point numbers. In particular, neither x === y nor Object.is(x, y) implies that the byte representations of two floating-point numbers x and y are equal.

Use of crypto.timingSafeEqual does not guarantee that the surrounding code is timing-safe. Care should be taken to ensure that the surrounding code does not introduce timing vulnerabilities.

crypto.verify(algorithm, data, key, signature[, callback])#

Verifies the given signature for data using the given key and algorithm. If algorithm is null or undefined, then the algorithm is dependent upon the key type (especially Ed25519 and Ed448).

If key is not a KeyObject, this function behaves as if key had been passed to crypto.createPublicKey(). If it is an object, the following additional properties can be passed:

  • dsaEncoding <string> For DSA and ECDSA, this option specifies the format of the signature. It can be one of the following:

    • 'der' (default): DER-encoded ASN.1 signature structure encoding (r, s).
    • 'ieee-p1363': Signature format r || s as proposed in IEEE-P1363.
  • padding <integer> Optional padding value for RSA, one of the following:

    • crypto.constants.RSA_PKCS1_PADDING (default)
    • crypto.constants.RSA_PKCS1_PSS_PADDING

    RSA_PKCS1_PSS_PADDING will use MGF1 with the same hash function used to sign the message as specified in section 3.1 of RFC 4055.

  • saltLength <integer> Salt length for when padding is RSA_PKCS1_PSS_PADDING. The special value crypto.constants.RSA_PSS_SALTLEN_DIGEST sets the salt length to the digest size, crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN (default) sets it to the maximum permissible value.

The signature argument is the previously calculated signature for the data.

Because public keys can be derived from private keys, a private key or a public key may be passed for key.

If the callback function is provided this function uses libuv's threadpool.

crypto.webcrypto#

Type: <Crypto> An implementation of the Web Crypto API standard.

See the Web Crypto API documentation for details.

Notes#

Using strings as inputs to cryptographic APIs#

For historical reasons, many cryptographic APIs provided by Node.js accept strings as inputs where the underlying cryptographic algorithm works on byte sequences. These instances include plaintexts, ciphertexts, symmetric keys, initialization vectors, passphrases, salts, authentication tags, and additional authenticated data.

When passing strings to cryptographic APIs, consider the following factors.

  • Not all byte sequences are valid UTF-8 strings. Therefore, when a byte sequence of length n is derived from a string, its entropy is generally lower than the entropy of a random or pseudorandom n byte sequence. For example, no UTF-8 string will result in the byte sequence c0 af. Secret keys should almost exclusively be random or pseudorandom byte sequences.

  • Similarly, when converting random or pseudorandom byte sequences to UTF-8 strings, subsequences that do not represent valid code points may be replaced by the Unicode replacement character (U+FFFD). The byte representation of the resulting Unicode string may, therefore, not be equal to the byte sequence that the string was created from.

    const original = [0xc0, 0xaf];
    const bytesAsString = Buffer.from(original).toString('utf8');
    const stringAsBytes = Buffer.from(bytesAsString, 'utf8');
    console.log(stringAsBytes);
    // Prints '<Buffer ef bf bd ef bf bd>'. 

    The outputs of ciphers, hash functions, signature algorithms, and key derivation functions are pseudorandom byte sequences and should not be used as Unicode strings.

  • When strings are obtained from user input, some Unicode characters can be represented in multiple equivalent ways that result in different byte sequences. For example, when passing a user passphrase to a key derivation function, such as PBKDF2 or scrypt, the result of the key derivation function depends on whether the string uses composed or decomposed characters. Node.js does not normalize character representations. Developers should consider using String.prototype.normalize() on user inputs before passing them to cryptographic APIs.

Legacy streams API (prior to Node.js 0.10)#

The Crypto module was added to Node.js before there was the concept of a unified Stream API, and before there were Buffer objects for handling binary data. As such, many crypto classes have methods not typically found on other Node.js classes that implement the streams API (e.g. update(), final(), or digest()). Also, many methods accepted and returned 'latin1' encoded strings by default rather than Buffers. This default was changed after Node.js v0.8 to use Buffer objects by default instead.

Support for weak or compromised algorithms#

The node:crypto module still supports some algorithms which are already compromised and are not recommended for use. The API also allows the use of ciphers and hashes with a small key size that are too weak for safe use.

Users should take full responsibility for selecting the crypto algorithm and key size according to their security requirements.

Based on the recommendations of NIST SP 800-131A:

  • MD5 and SHA-1 are no longer acceptable where collision resistance is required such as digital signatures.
  • The key used with RSA, DSA, and DH algorithms is recommended to have at least 2048 bits and that of the curve of ECDSA and ECDH at least 224 bits, to be safe to use for several years.
  • The DH groups of modp1, modp2 and modp5 have a key size smaller than 2048 bits and are not recommended.

See the reference for other recommendations and details.

Some algorithms that have known weaknesses and are of little relevance in practice are only available through the legacy provider, which is not enabled by default.

CCM mode#

CCM is one of the supported AEAD algorithms. Applications which use this mode must adhere to certain restrictions when using the cipher API:

  • The authentication tag length must be specified during cipher creation by setting the authTagLength option and must be one of 4, 6, 8, 10, 12, 14 or 16 bytes.
  • The length of the initialization vector (nonce) N must be between 7 and 13 bytes (7 ≤ N ≤ 13).
  • The length of the plaintext is limited to 2 ** (8 * (15 - N)) bytes.
  • When decrypting, the authentication tag must be set via setAuthTag() before calling update(). Otherwise, decryption will fail and final() will throw an error in compliance with section 2.6 of RFC 3610.
  • Using stream methods such as write(data), end(data) or pipe() in CCM mode might fail as CCM cannot handle more than one chunk of data per instance.
  • When passing additional authenticated data (AAD), the length of the actual message in bytes must be passed to setAAD() via the plaintextLength option. Many crypto libraries include the authentication tag in the ciphertext, which means that they produce ciphertexts of the length plaintextLength + authTagLength. Node.js does not include the authentication tag, so the ciphertext length is always plaintextLength. This is not necessary if no AAD is used.
  • As CCM processes the whole message at once, update() must be called exactly once.
  • Even though calling update() is sufficient to encrypt/decrypt the message, applications must call final() to compute or verify the authentication tag.
import { Buffer } from 'node:buffer';
const {
  createCipheriv,
  createDecipheriv,
  randomBytes,
} = await import('node:crypto');

const key = 'keykeykeykeykeykeykeykey';
const nonce = randomBytes(12);

const aad = Buffer.from('0123456789', 'hex');

const cipher = createCipheriv('aes-192-ccm', key, nonce, {
  authTagLength: 16,
});
const plaintext = 'Hello world';
cipher.setAAD(aad, {
  plaintextLength: Buffer.byteLength(plaintext),
});
const ciphertext = cipher.update(plaintext, 'utf8');
cipher.final();
const tag = cipher.getAuthTag();

// Now transmit { ciphertext, nonce, tag }.

const decipher = createDecipheriv('aes-192-ccm', key, nonce, {
  authTagLength: 16,
});
decipher.setAuthTag(tag);
decipher.setAAD(aad, {
  plaintextLength: ciphertext.length,
});
const receivedPlaintext = decipher.update(ciphertext, null, 'utf8');

try {
  decipher.final();
} catch (err) {
  throw new Error('Authentication failed!', { cause: err });
}

console.log(receivedPlaintext);const { Buffer } = require('node:buffer');
const {
  createCipheriv,
  createDecipheriv,
  randomBytes,
} = require('node:crypto');

const key = 'keykeykeykeykeykeykeykey';
const nonce = randomBytes(12);

const aad = Buffer.from('0123456789', 'hex');

const cipher = createCipheriv('aes-192-ccm', key, nonce, {
  authTagLength: 16,
});
const plaintext = 'Hello world';
cipher.setAAD(aad, {
  plaintextLength: Buffer.byteLength(plaintext),
});
const ciphertext = cipher.update(plaintext, 'utf8');
cipher.final();
const tag = cipher.getAuthTag();

// Now transmit { ciphertext, nonce, tag }.

const decipher = createDecipheriv('aes-192-ccm', key, nonce, {
  authTagLength: 16,
});
decipher.setAuthTag(tag);
decipher.setAAD(aad, {
  plaintextLength: ciphertext.length,
});
const receivedPlaintext = decipher.update(ciphertext, null, 'utf8');

try {
  decipher.final();
} catch (err) {
  throw new Error('Authentication failed!', { cause: err });
}

console.log(receivedPlaintext);

FIPS mode#

When using OpenSSL 3, Node.js supports FIPS 140-2 when used with an appropriate OpenSSL 3 provider, such as the FIPS provider from OpenSSL 3 which can be installed by following the instructions in OpenSSL's FIPS README file.

For FIPS support in Node.js you will need:

  • A correctly installed OpenSSL 3 FIPS provider.
  • An OpenSSL 3 FIPS module configuration file.
  • An OpenSSL 3 configuration file that references the FIPS module configuration file.

Node.js will need to be configured with an OpenSSL configuration file that points to the FIPS provider. An example configuration file looks like this:

nodejs_conf = nodejs_init

.include /<absolute path>/fipsmodule.cnf

[nodejs_init]
providers = provider_sect

[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1 

where fipsmodule.cnf is the FIPS module configuration file generated from the FIPS provider installation step:

openssl fipsinstall 

Set the OPENSSL_CONF environment variable to point to your configuration file and OPENSSL_MODULES to the location of the FIPS provider dynamic library. e.g.

export OPENSSL_CONF=/<path to configuration file>/nodejs.cnf
export OPENSSL_MODULES=/<path to openssl lib>/ossl-modules 

FIPS mode can then be enabled in Node.js either by:

  • Starting Node.js with --enable-fips or --force-fips command line flags.
  • Programmatically calling crypto.setFips(true).

Optionally FIPS mode can be enabled in Node.js via the OpenSSL configuration file. e.g.

nodejs_conf = nodejs_init

.include /<absolute path>/fipsmodule.cnf

[nodejs_init]
providers = provider_sect
alg_section = algorithm_sect

[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1

[algorithm_sect]
default_properties = fips=yes 

Crypto constants#

The following constants exported by crypto.constants apply to various uses of the node:crypto, node:tls, and node:https modules and are generally specific to OpenSSL.

OpenSSL options#

See the list of SSL OP Flags for details.

Constant Description
SSL_OP_ALL Applies multiple bug workarounds within OpenSSL. See https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html for detail.
SSL_OP_ALLOW_NO_DHE_KEX Instructs OpenSSL to allow a non-[EC]DHE-based key exchange mode for TLS v1.3
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION Allows legacy insecure renegotiation between OpenSSL and unpatched clients or servers. See https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html.
SSL_OP_CIPHER_SERVER_PREFERENCE Attempts to use the server's preferences instead of the client's when selecting a cipher. Behavior depends on protocol version. See https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html.
SSL_OP_CISCO_ANYCONNECT Instructs OpenSSL to use Cisco's version identifier of DTLS_BAD_VER.
SSL_OP_COOKIE_EXCHANGE Instructs OpenSSL to turn on cookie exchange.
SSL_OP_CRYPTOPRO_TLSEXT_BUG Instructs OpenSSL to add server-hello extension from an early version of the cryptopro draft.
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS Instructs OpenSSL to disable a SSL 3.0/TLS 1.0 vulnerability workaround added in OpenSSL 0.9.6d.
SSL_OP_LEGACY_SERVER_CONNECT Allows initial connection to servers that do not support RI.
SSL_OP_NO_COMPRESSION Instructs OpenSSL to disable support for SSL/TLS compression.
SSL_OP_NO_ENCRYPT_THEN_MAC Instructs OpenSSL to disable encrypt-then-MAC.
SSL_OP_NO_QUERY_MTU
SSL_OP_NO_RENEGOTIATION Instructs OpenSSL to disable renegotiation.
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION Instructs OpenSSL to always start a new session when performing renegotiation.
SSL_OP_NO_SSLv2 Instructs OpenSSL to turn off SSL v2
SSL_OP_NO_SSLv3 Instructs OpenSSL to turn off SSL v3
SSL_OP_NO_TICKET Instructs OpenSSL to disable use of RFC4507bis tickets.
SSL_OP_NO_TLSv1 Instructs OpenSSL to turn off TLS v1
SSL_OP_NO_TLSv1_1 Instructs OpenSSL to turn off TLS v1.1
SSL_OP_NO_TLSv1_2 Instructs OpenSSL to turn off TLS v1.2
SSL_OP_NO_TLSv1_3 Instructs OpenSSL to turn off TLS v1.3
SSL_OP_PRIORITIZE_CHACHA Instructs OpenSSL server to prioritize ChaCha20-Poly1305 when the client does. This option has no effect if SSL_OP_CIPHER_SERVER_PREFERENCE is not enabled.
SSL_OP_TLS_ROLLBACK_BUG Instructs OpenSSL to disable version rollback attack detection.

OpenSSL engine constants#

Constant Description
ENGINE_METHOD_RSA Limit engine usage to RSA
ENGINE_METHOD_DSA Limit engine usage to DSA
ENGINE_METHOD_DH Limit engine usage to DH
ENGINE_METHOD_RAND Limit engine usage to RAND
ENGINE_METHOD_EC Limit engine usage to EC
ENGINE_METHOD_CIPHERS Limit engine usage to CIPHERS
ENGINE_METHOD_DIGESTS Limit engine usage to DIGESTS
ENGINE_METHOD_PKEY_METHS Limit engine usage to PKEY_METHS
ENGINE_METHOD_PKEY_ASN1_METHS Limit engine usage to PKEY_ASN1_METHS
ENGINE_METHOD_ALL
ENGINE_METHOD_NONE

Other OpenSSL constants#

Constant Description
DH_CHECK_P_NOT_SAFE_PRIME
DH_CHECK_P_NOT_PRIME
DH_UNABLE_TO_CHECK_GENERATOR
DH_NOT_SUITABLE_GENERATOR
RSA_PKCS1_PADDING
RSA_SSLV23_PADDING
RSA_NO_PADDING
RSA_PKCS1_OAEP_PADDING
RSA_X931_PADDING
RSA_PKCS1_PSS_PADDING
RSA_PSS_SALTLEN_DIGEST Sets the salt length for RSA_PKCS1_PSS_PADDING to the digest size when signing or verifying.
RSA_PSS_SALTLEN_MAX_SIGN Sets the salt length for RSA_PKCS1_PSS_PADDING to the maximum permissible value when signing data.
RSA_PSS_SALTLEN_AUTO Causes the salt length for RSA_PKCS1_PSS_PADDING to be determined automatically when verifying a signature.
POINT_CONVERSION_COMPRESSED
POINT_CONVERSION_UNCOMPRESSED
POINT_CONVERSION_HYBRID

Node.js crypto constants#

Constant Description
defaultCoreCipherList Specifies the built-in default cipher list used by Node.js.
defaultCipherList Specifies the active default cipher list used by the current Node.js process.

Debugger#

Stability: 2 - Stable

Node.js includes a command-line debugging utility. The Node.js debugger client is not a full-featured debugger, but simple stepping and inspection are possible.

To use it, start Node.js with the inspect argument followed by the path to the script to debug.

$ node inspect myscript.js
< Debugger listening on ws://127.0.0.1:9229/621111f9-ffcb-4e82-b718-48a145fa5db8
< For help, see: https://nodejs.org/en/docs/inspector
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
 ok
Break on start in myscript.js:2
  1 // myscript.js
> 2 global.x = 5;
  3 setTimeout(() => {
  4   debugger;
debug> 

The debugger automatically breaks on the first executable line. To instead run until the first breakpoint (specified by a debugger statement), set the NODE_INSPECT_RESUME_ON_START environment variable to 1.

$ cat myscript.js
// myscript.js
global.x = 5;
setTimeout(() => {
  debugger;
  console.log('world');
}, 1000);
console.log('hello');
$ NODE_INSPECT_RESUME_ON_START=1 node inspect myscript.js
< Debugger listening on ws://127.0.0.1:9229/f1ed133e-7876-495b-83ae-c32c6fc319c2
< For help, see: https://nodejs.org/en/docs/inspector
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
< hello
<
break in myscript.js:4
  2 global.x = 5;
  3 setTimeout(() => {
> 4   debugger;
  5   console.log('world');
  6 }, 1000);
debug> next
break in myscript.js:5
  3 setTimeout(() => {
  4   debugger;
> 5   console.log('world');
  6 }, 1000);
  7 console.log('hello');
debug> repl
Press Ctrl+C to leave debug repl
> x
5
> 2 + 2
4
debug> next
< world
<
break in myscript.js:6
  4   debugger;
  5   console.log('world');
> 6 }, 1000);
  7 console.log('hello');
  8
debug> .exit
$ 

The repl command allows code to be evaluated remotely. The next command steps to the next line. Type help to see what other commands are available.

Pressing enter without typing a command will repeat the previous debugger command.

Watchers#

It is possible to watch expression and variable values while debugging. On every breakpoint, each expression from the watchers list will be evaluated in the current context and displayed immediately before the breakpoint's source code listing.

To begin watching an expression, type watch('my_expression'). The command watchers will print the active watchers. To remove a watcher, type unwatch('my_expression').

Command reference#

Stepping#

  • cont, c: Continue execution
  • next, n: Step next
  • step, s: Step in
  • out, o: Step out
  • pause: Pause running code (like pause button in Developer Tools)

Breakpoints#

  • setBreakpoint(), sb(): Set breakpoint on current line
  • setBreakpoint(line), sb(line): Set breakpoint on specific line
  • setBreakpoint('fn()'), sb(...): Set breakpoint on a first statement in function's body
  • setBreakpoint('script.js', 1), sb(...): Set breakpoint on first line of script.js
  • setBreakpoint('script.js', 1, 'num < 4'), sb(...): Set conditional breakpoint on first line of script.js that only breaks when num < 4 evaluates to true
  • clearBreakpoint('script.js', 1), cb(...): Clear breakpoint in script.js on line 1

It is also possible to set a breakpoint in a file (module) that is not loaded yet:

$ node inspect main.js
< Debugger listening on ws://127.0.0.1:9229/48a5b28a-550c-471b-b5e1-d13dd7165df9
< For help, see: https://nodejs.org/en/docs/inspector
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
Break on start in main.js:1
> 1 const mod = require('./mod.js');
  2 mod.hello();
  3 mod.hello();
debug> setBreakpoint('mod.js', 22)
Warning: script 'mod.js' was not loaded yet.
debug> c
break in mod.js:22
 20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
 21
>22 exports.hello = function() {
 23   return 'hello from module';
 24 };
debug> 

It is also possible to set a conditional breakpoint that only breaks when a given expression evaluates to true:

$ node inspect main.js
< Debugger listening on ws://127.0.0.1:9229/ce24daa8-3816-44d4-b8ab-8273c8a66d35
< For help, see: https://nodejs.org/en/docs/inspector
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
Break on start in main.js:7
  5 }
  6
> 7 addOne(10);
  8 addOne(-1);
  9
debug> setBreakpoint('main.js', 4, 'num < 0')
  1 'use strict';
  2
  3 function addOne(num) {
> 4   return num + 1;
  5 }
  6
  7 addOne(10);
  8 addOne(-1);
  9
debug> cont
break in main.js:4
  2
  3 function addOne(num) {
> 4   return num + 1;
  5 }
  6
debug> exec('num')
-1
debug> 

Information#

  • backtrace, bt: Print backtrace of current execution frame
  • list(5): List scripts source code with 5 line context (5 lines before and after)
  • watch(expr): Add expression to watch list
  • unwatch(expr): Remove expression from watch list
  • unwatch(index): Remove expression at specific index from watch list
  • watchers: List all watchers and their values (automatically listed on each breakpoint)
  • repl: Open debugger's repl for evaluation in debugging script's context
  • exec expr, p expr: Execute an expression in debugging script's context and print its value
  • profile: Start CPU profiling session
  • profileEnd: Stop current CPU profiling session
  • profiles: List all completed CPU profiling sessions
  • profiles[n].save(filepath = 'node.cpuprofile'): Save CPU profiling session to disk as JSON
  • takeHeapSnapshot(filepath = 'node.heapsnapshot'): Take a heap snapshot and save to disk as JSON

Execution control#

  • run: Run script (automatically runs on debugger's start)
  • restart: Restart script
  • kill: Kill script

Various#

  • scripts: List all loaded scripts
  • version: Display V8's version

Advanced usage#

V8 inspector integration for Node.js#

V8 Inspector integration allows attaching Chrome DevTools to Node.js instances for debugging and profiling. It uses the Chrome DevTools Protocol.

V8 Inspector can be enabled by passing the --inspect flag when starting a Node.js application. It is also possible to supply a custom port with that flag, e.g. --inspect=9222 will accept DevTools connections on port 9222.

Using the --inspect flag will execute the code immediately before debugger is connected. This means that the code will start running before you can start debugging, which might not be ideal if you want to debug from the very beginning.

In such cases, you have two alternatives:

  1. --inspect-wait flag: This flag will wait for debugger to be attached before executing the code. This allows you to start debugging right from the beginning of the execution.
  2. --inspect-brk flag: Unlike --inspect, this flag will break on the first line of the code as soon as debugger is attached. This is useful when you want to debug the code step by step from the very beginning, without any code execution prior to debugging.

So, when deciding between --inspect, --inspect-wait, and --inspect-brk, consider whether you want the code to start executing immediately, wait for debugger to be attached before execution, or break on the first line for step-by-step debugging.

$ node --inspect index.js
Debugger listening on ws://127.0.0.1:9229/dc9010dd-f8b8-4ac5-a510-c1a114ec7d29
For help, see: https://nodejs.org/en/docs/inspector 

(In the example above, the UUID dc9010dd-f8b8-4ac5-a510-c1a114ec7d29 at the end of the URL is generated on the fly, it varies in different debugging sessions.)

If the Chrome browser is older than 66.0.3345.0, use inspector.html instead of js_app.html in the above URL.

Chrome DevTools doesn't support debugging worker threads yet. ndb can be used to debug them.

Deprecated APIs#

Node.js APIs might be deprecated for any of the following reasons:

  • Use of the API is unsafe.
  • An improved alternative API is available.
  • Breaking changes to the API are expected in a future major release.

Node.js uses four kinds of deprecations:

  • Documentation-only
  • Application (non-node_modules code only)
  • Runtime (all code)
  • End-of-Life

A Documentation-only deprecation is one that is expressed only within the Node.js API docs. These generate no side-effects while running Node.js. Some Documentation-only deprecations trigger a runtime warning when launched with --pending-deprecation flag (or its alternative, NODE_PENDING_DEPRECATION=1 environment variable), similarly to Runtime deprecations below. Documentation-only deprecations that support that flag are explicitly labeled as such in the list of Deprecated APIs.

An Application deprecation for only non-node_modules code will, by default, generate a process warning that will be printed to stderr the first time the deprecated API is used in code that's not loaded from node_modules. When the --throw-deprecation command-line flag is used, a Runtime deprecation will cause an error to be thrown. When --pending-deprecation is used, warnings will also be emitted for code loaded from node_modules.

A runtime deprecation for all code is similar to the runtime deprecation for non-node_modules code, except that it also emits a warning for code loaded from node_modules.

An End-of-Life deprecation is used when functionality is or will soon be removed from Node.js.

Revoking deprecations#

Occasionally, the deprecation of an API might be reversed. In such situations, this document will be updated with information relevant to the decision. However, the deprecation identifier will not be modified.

List of deprecated APIs#

DEP0001: http.OutgoingMessage.prototype.flush#

Type: End-of-Life

OutgoingMessage.prototype.flush() has been removed. Use OutgoingMessage.prototype.flushHeaders() instead.

DEP0002: require('_linklist')#

Type: End-of-Life

The _linklist module is deprecated. Please use a userland alternative.

DEP0003: _writableState.buffer#

Type: End-of-Life

The _writableState.buffer has been removed. Use _writableState.getBuffer() instead.

DEP0004: CryptoStream.prototype.readyState#

Type: End-of-Life

The CryptoStream.prototype.readyState property was removed.

DEP0005: Buffer() constructor#

Type: Application (non-node_modules code only)

The Buffer() function and new Buffer() constructor are deprecated due to API usability issues that can lead to accidental security issues.

As an alternative, use one of the following methods of constructing Buffer objects:

Without --pending-deprecation, runtime warnings occur only for code not in node_modules. This means there will not be deprecation warnings for Buffer() usage in dependencies. With --pending-deprecation, a runtime warning results no matter where the Buffer() usage occurs.

DEP0006: child_process options.customFds#

Type: End-of-Life

Within the child_process module's spawn(), fork(), and exec() methods, the options.customFds option is deprecated. The options.stdio option should be used instead.

DEP0007: Replace cluster worker.suicide with worker.exitedAfterDisconnect#

Type: End-of-Life

In an earlier version of the Node.js cluster, a boolean property with the name suicide was added to the Worker object. The intent of this property was to provide an indication of how and why the Worker instance exited. In Node.js 6.0.0, the old property was deprecated and replaced with a new worker.exitedAfterDisconnect property. The old property name did not precisely describe the actual semantics and was unnecessarily emotion-laden.

DEP0008: require('node:constants')#

Type: Documentation-only

The node:constants module is deprecated. When requiring access to constants relevant to specific Node.js builtin modules, developers should instead refer to the constants property exposed by the relevant module. For instance, require('node:fs').constants and require('node:os').constants.

DEP0009: crypto.pbkdf2 without digest#

Type: End-of-Life

Use of the crypto.pbkdf2() API without specifying a digest was deprecated in Node.js 6.0 because the method defaulted to using the non-recommended 'SHA1' digest. Previously, a deprecation warning was printed. Starting in Node.js 8.0.0, calling crypto.pbkdf2() or crypto.pbkdf2Sync() with digest set to undefined will throw a TypeError.

Beginning in Node.js v11.0.0, calling these functions with digest set to null would print a deprecation warning to align with the behavior when digest is undefined.

Now, however, passing either undefined or null will throw a TypeError.

DEP0010: crypto.createCredentials#

Type: End-of-Life

The crypto.createCredentials() API was removed. Please use tls.createSecureContext() instead.

DEP0011: crypto.Credentials#

Type: End-of-Life

The crypto.Credentials class was removed. Please use tls.SecureContext instead.

DEP0012: Domain.dispose#

Type: End-of-Life

Domain.dispose() has been removed. Recover from failed I/O actions explicitly via error event handlers set on the domain instead.

DEP0013: fs asynchronous function without callback#

Type: End-of-Life

Calling an asynchronous function without a callback throws a TypeError in Node.js 10.0.0 onwards. See https://github.com/nodejs/node/pull/12562.

DEP0014: fs.read legacy String interface#

Type: End-of-Life

The fs.read() legacy String interface is deprecated. Use the Buffer API as mentioned in the documentation instead.

DEP0015: fs.readSync legacy String interface#

Type: End-of-Life

The fs.readSync() legacy String interface is deprecated. Use the Buffer API as mentioned in the documentation instead.

DEP0016: GLOBAL/root#

Type: End-of-Life

The GLOBAL and root aliases for the global property were deprecated in Node.js 6.0.0 and have since been removed.

DEP0017: Intl.v8BreakIterator#

Type: End-of-Life

Intl.v8BreakIterator was a non-standard extension and has been removed. See Intl.Segmenter.

DEP0018: Unhandled promise rejections#

Type: End-of-Life

Unhandled promise rejections are deprecated. By default, promise rejections that are not handled terminate the Node.js process with a non-zero exit code. To change the way Node.js treats unhandled rejections, use the --unhandled-rejections command-line option.

DEP0019: require('.') resolved outside directory#

Type: End-of-Life

In certain cases, require('.') could resolve outside the package directory. This behavior has been removed.

DEP0020: Server.connections#

Type: End-of-Life

The Server.connections property was deprecated in Node.js v0.9.7 and has been removed. Please use the Server.getConnections() method instead.

DEP0021: Server.listenFD#

Type: End-of-Life

The Server.listenFD() method was deprecated and removed. Please use Server.listen({fd: <number>}) instead.

DEP0022: os.tmpDir()#

Type: End-of-Life

The os.tmpDir() API was deprecated in Node.js 7.0.0 and has since been removed. Please use os.tmpdir() instead.

DEP0023: os.getNetworkInterfaces()#

Type: End-of-Life

The os.getNetworkInterfaces() method is deprecated. Please use the os.networkInterfaces() method instead.

DEP0024: REPLServer.prototype.convertToContext()#

Type: End-of-Life

The REPLServer.prototype.convertToContext() API has been removed.

DEP0025: require('node:sys')#

Type: Runtime

The node:sys module is deprecated. Please use the util module instead.

DEP0026: util.print()#

Type: End-of-Life

util.print() has been removed. Please use console.log() instead.

DEP0027: util.puts()#

Type: End-of-Life

util.puts() has been removed. Please use console.log() instead.

DEP0028: util.debug()#

Type: End-of-Life

util.debug() has been removed. Please use console.error() instead.

DEP0029: util.error()#

Type: End-of-Life

util.error() has been removed. Please use console.error() instead.

DEP0030: SlowBuffer#

Type: Runtime

The SlowBuffer class is deprecated. Please use Buffer.allocUnsafeSlow(size) instead.

DEP0031: ecdh.setPublicKey()#

Type: Documentation-only

The ecdh.setPublicKey() method is now deprecated as its inclusion in the API is not useful.

DEP0032: node:domain module#

Type: Documentation-only

The domain module is deprecated and should not be used.

DEP0033: EventEmitter.listenerCount()#

Type: Documentation-only

The events.listenerCount(emitter, eventName) API is deprecated. Please use emitter.listenerCount(eventName) instead.

DEP0034: fs.exists(path, callback)#

Type: Documentation-only

The fs.exists(path, callback) API is deprecated. Please use fs.stat() or fs.access() instead.

DEP0035: fs.lchmod(path, mode, callback)#

Type: Documentation-only

The fs.lchmod(path, mode, callback) API is deprecated.

DEP0036: fs.lchmodSync(path, mode)#

Type: Documentation-only

The fs.lchmodSync(path, mode) API is deprecated.

DEP0037: fs.lchown(path, uid, gid, callback)#

Type: Deprecation revoked

The fs.lchown(path, uid, gid, callback) API was deprecated. The deprecation was revoked because the requisite supporting APIs were added in libuv.

DEP0038: fs.lchownSync(path, uid, gid)#

Type: Deprecation revoked

The fs.lchownSync(path, uid, gid) API was deprecated. The deprecation was revoked because the requisite supporting APIs were added in libuv.

DEP0039: require.extensions#

Type: Documentation-only

The require.extensions property is deprecated.

DEP0040: node:punycode module#

Type: Runtime

The punycode module is deprecated. Please use a userland alternative instead.

DEP0041: NODE_REPL_HISTORY_FILE environment variable#

Type: End-of-Life

The NODE_REPL_HISTORY_FILE environment variable was removed. Please use NODE_REPL_HISTORY instead.

DEP0042: tls.CryptoStream#

Type: End-of-Life

The tls.CryptoStream class was removed. Please use tls.TLSSocket instead.

DEP0043: tls.SecurePair#

Type: End-of-Life

The tls.SecurePair class is deprecated. Please use tls.TLSSocket instead.

DEP0044: util.isArray()#

Type: Runtime

The util.isArray() API is deprecated. Please use Array.isArray() instead.

DEP0045: util.isBoolean()#

Type: End-of-Life

The util.isBoolean() API has been removed. Please use typeof arg === 'boolean' instead.

DEP0046: util.isBuffer()#

Type: End-of-Life

The util.isBuffer() API has been removed. Please use Buffer.isBuffer() instead.

DEP0047: util.isDate()#

Type: End-of-Life

The util.isDate() API has been removed. Please use arg instanceof Date instead.

DEP0048: util.isError()#

Type: End-of-Life

The util.isError() API has been removed. Please use Object.prototype.toString(arg) === '[object Error]' || arg instanceof Error instead.

DEP0049: util.isFunction()#

Type: End-of-Life

The util.isFunction() API has been removed. Please use typeof arg === 'function' instead.

DEP0050: util.isNull()#

Type: End-of-Life

The util.isNull() API has been removed. Please use arg === null instead.

DEP0051: util.isNullOrUndefined()#

Type: End-of-Life

The util.isNullOrUndefined() API has been removed. Please use arg === null || arg === undefined instead.

DEP0052: util.isNumber()#

Type: End-of-Life

The util.isNumber() API has been removed. Please use typeof arg === 'number' instead.

DEP0053: util.isObject()#

Type: End-of-Life

The util.isObject() API has been removed. Please use arg && typeof arg === 'object' instead.

DEP0054: util.isPrimitive()#

Type: End-of-Life

The util.isPrimitive() API has been removed. Please use arg === null || (typeof arg !=='object' && typeof arg !== 'function') instead.

DEP0055: util.isRegExp()#

Type: End-of-Life

The util.isRegExp() API has been removed. Please use arg instanceof RegExp instead.

DEP0056: util.isString()#

Type: End-of-Life

The util.isString() API has been removed. Please use typeof arg === 'string' instead.

DEP0057: util.isSymbol()#

Type: End-of-Life

The util.isSymbol() API has been removed. Please use typeof arg === 'symbol' instead.

DEP0058: util.isUndefined()#

Type: End-of-Life

The util.isUndefined() API has been removed. Please use arg === undefined instead.

DEP0059: util.log()#

Type: End-of-Life

The util.log() API has been removed because it's an unmaintained legacy API that was exposed to user land by accident. Instead, consider the following alternatives based on your specific needs:

  • Third-Party Logging Libraries

  • Use console.log(new Date().toLocaleString(), message)

By adopting one of these alternatives, you can transition away from util.log() and choose a logging strategy that aligns with the specific requirements and complexity of your application.

DEP0060: util._extend()#

Type: Runtime

The util._extend() API is deprecated because it's an unmaintained legacy API that was exposed to user land by accident. Please use target = Object.assign(target, source) instead.

DEP0061: fs.SyncWriteStream#

Type: End-of-Life

The fs.SyncWriteStream class was never intended to be a publicly accessible API and has been removed. No alternative API is available. Please use a userland alternative.

DEP0062: node --debug#

Type: End-of-Life

--debug activates the legacy V8 debugger interface, which was removed as of V8 5.8. It is replaced by Inspector which is activated with --inspect instead.

DEP0063: ServerResponse.prototype.writeHeader()#

Type: Documentation-only

The node:http module ServerResponse.prototype.writeHeader() API is deprecated. Please use ServerResponse.prototype.writeHead() instead.

The ServerResponse.prototype.writeHeader() method was never documented as an officially supported API.

DEP0064: tls.createSecurePair()#

Type: End-of-Life

The tls.createSecurePair() API was deprecated in documentation in Node.js 0.11.3. Users should use tls.Socket instead.

DEP0065: repl.REPL_MODE_MAGIC and NODE_REPL_MODE=magic#

Type: End-of-Life

The node:repl module's REPL_MODE_MAGIC constant, used for replMode option, has been removed. Its behavior has been functionally identical to that of REPL_MODE_SLOPPY since Node.js 6.0.0, when V8 5.0 was imported. Please use REPL_MODE_SLOPPY instead.

The NODE_REPL_MODE environment variable is used to set the underlying replMode of an interactive node session. Its value, magic, is also removed. Please use sloppy instead.

DEP0066: OutgoingMessage.prototype._headers, OutgoingMessage.prototype._headerNames#

Type: End-of-Life

The node:http module OutgoingMessage.prototype._headers and OutgoingMessage.prototype._headerNames properties are deprecated. Use one of the public methods (e.g. OutgoingMessage.prototype.getHeader(), OutgoingMessage.prototype.getHeaders(), OutgoingMessage.prototype.getHeaderNames(), OutgoingMessage.prototype.getRawHeaderNames(), OutgoingMessage.prototype.hasHeader(), OutgoingMessage.prototype.removeHeader(), OutgoingMessage.prototype.setHeader()) for working with outgoing headers.

The OutgoingMessage.prototype._headers and OutgoingMessage.prototype._headerNames properties were never documented as officially supported properties.

DEP0067: OutgoingMessage.prototype._renderHeaders#

Type: Documentation-only

The node:http module OutgoingMessage.prototype._renderHeaders() API is deprecated.

The OutgoingMessage.prototype._renderHeaders property was never documented as an officially supported API.

DEP0068: node debug#

Type: End-of-Life

node debug corresponds to the legacy CLI debugger which has been replaced with a V8-inspector based CLI debugger available through node inspect.

DEP0069: vm.runInDebugContext(string)#

Type: End-of-Life

DebugContext has been removed in V8 and is not available in Node.js 10+.

DebugContext was an experimental API.

DEP0070: async_hooks.currentId()#

Type: End-of-Life

async_hooks.currentId() was renamed to async_hooks.executionAsyncId() for clarity.

This change was made while async_hooks was an experimental API.

DEP0071: async_hooks.triggerId()#

Type: End-of-Life

async_hooks.triggerId() was renamed to async_hooks.triggerAsyncId() for clarity.

This change was made while async_hooks was an experimental API.

DEP0072: async_hooks.AsyncResource.triggerId()#

Type: End-of-Life

async_hooks.AsyncResource.triggerId() was renamed to async_hooks.AsyncResource.triggerAsyncId() for clarity.

This change was made while async_hooks was an experimental API.

DEP0073: Several internal properties of net.Server#

Type: End-of-Life

Accessing several internal, undocumented properties of net.Server instances with inappropriate names is deprecated.

As the original API was undocumented and not generally useful for non-internal code, no replacement API is provided.

DEP0074: REPLServer.bufferedCommand#

Type: End-of-Life

The REPLServer.bufferedCommand property was deprecated in favor of REPLServer.clearBufferedCommand().

DEP0075: REPLServer.parseREPLKeyword()#

Type: End-of-Life

REPLServer.parseREPLKeyword() was removed from userland visibility.

DEP0076: tls.parseCertString()#

Type: End-of-Life

tls.parseCertString() was a trivial parsing helper that was made public by mistake. While it was supposed to parse certificate subject and issuer strings, it never handled multi-value Relative Distinguished Names correctly.

Earlier versions of this document suggested using querystring.parse() as an alternative to tls.parseCertString(). However, querystring.parse() also does not handle all certificate subjects correctly and should not be used.

DEP0077: Module._debug()#

Type: Runtime

Module._debug() is deprecated.

The Module._debug() function was never documented as an officially supported API.

DEP0078: REPLServer.turnOffEditorMode()#

Type: End-of-Life

REPLServer.turnOffEditorMode() was removed from userland visibility.

DEP0079: Custom inspection function on objects via .inspect()#

Type: End-of-Life

Using a property named inspect on an object to specify a custom inspection function for util.inspect() is deprecated. Use util.inspect.custom instead. For backward compatibility with Node.js prior to version 6.4.0, both can be specified.

DEP0080: path._makeLong()#

Type: Documentation-only

The internal path._makeLong() was not intended for public use. However, userland modules have found it useful. The internal API is deprecated and replaced with an identical, public path.toNamespacedPath() method.

DEP0081: fs.truncate() using a file descriptor#

Type: End-of-Life

fs.truncate() fs.truncateSync() usage with a file descriptor is deprecated. Please use fs.ftruncate() or fs.ftruncateSync() to work with file descriptors.

DEP0082: REPLServer.prototype.memory()#

Type: End-of-Life

REPLServer.prototype.memory() is only necessary for the internal mechanics of the REPLServer itself. Do not use this function.

DEP0083: Disabling ECDH by setting ecdhCurve to false#

Type: End-of-Life

The ecdhCurve option to tls.createSecureContext() and tls.TLSSocket could be set to false to disable ECDH entirely on the server only. This mode was deprecated in preparation for migrating to OpenSSL 1.1.0 and consistency with the client and is now unsupported. Use the ciphers parameter instead.

DEP0084: requiring bundled internal dependencies#

Type: End-of-Life

Since Node.js versions 4.4.0 and 5.2.0, several modules only intended for internal usage were mistakenly exposed to user code through require(). These modules were:

  • v8/tools/codemap
  • v8/tools/consarray
  • v8/tools/csvparser
  • v8/tools/logreader
  • v8/tools/profile_view
  • v8/tools/profile
  • v8/tools/SourceMap
  • v8/tools/splaytree
  • v8/tools/tickprocessor-driver
  • v8/tools/tickprocessor
  • node-inspect/lib/_inspect (from 7.6.0)
  • node-inspect/lib/internal/inspect_client (from 7.6.0)
  • node-inspect/lib/internal/inspect_repl (from 7.6.0)

The v8/* modules do not have any exports, and if not imported in a specific order would in fact throw errors. As such there are virtually no legitimate use cases for importing them through require().

On the other hand, node-inspect can be installed locally through a package manager, as it is published on the npm registry under the same name. No source code modification is necessary if that is done.

DEP0085: AsyncHooks sensitive API#

Type: End-of-Life

The AsyncHooks sensitive API was never documented and had various minor issues. Use the AsyncResource API instead. See https://github.com/nodejs/node/issues/15572.

DEP0086: Remove runInAsyncIdScope#

Type: End-of-Life

runInAsyncIdScope doesn't emit the 'before' or 'after' event and can thus cause a lot of issues. See https://github.com/nodejs/node/issues/14328.

DEP0089: require('node:assert')#

Type: Deprecation revoked

Importing assert directly was not recommended as the exposed functions use loose equality checks. The deprecation was revoked because use of the node:assert module is not discouraged, and the deprecation caused developer confusion.

DEP0090: Invalid GCM authentication tag lengths#

Type: End-of-Life

Node.js used to support all GCM authentication tag lengths which are accepted by OpenSSL when calling decipher.setAuthTag(). Beginning with Node.js v11.0.0, only authentication tag lengths of 128, 120, 112, 104, 96, 64, and 32 bits are allowed. Authentication tags of other lengths are invalid per NIST SP 800-38D.

DEP0091: crypto.DEFAULT_ENCODING#

Type: End-of-Life

The crypto.DEFAULT_ENCODING property only existed for compatibility with Node.js releases prior to versions 0.9.3 and has been removed.

DEP0092: Top-level this bound to module.exports#

Type: Documentation-only

Assigning properties to the top-level this as an alternative to module.exports is deprecated. Developers should use exports or module.exports instead.

DEP0093: crypto.fips is deprecated and replaced#

Type: Runtime

The crypto.fips property is deprecated. Please use crypto.setFips() and crypto.getFips() instead.

DEP0094: Using assert.fail() with more than one argument#

Type: Runtime

Using assert.fail() with more than one argument is deprecated. Use assert.fail() with only one argument or use a different node:assert module method.

DEP0095: timers.enroll()#

Type: End-of-Life

timers.enroll() has been removed. Please use the publicly documented setTimeout() or setInterval() instead.

DEP0096: timers.unenroll()#

Type: End-of-Life

timers.unenroll() has been removed. Please use the publicly documented clearTimeout() or clearInterval() instead.

DEP0097: MakeCallback with domain property#

Type: Runtime

Users of MakeCallback that add the domain property to carry context, should start using the async_context variant of MakeCallback or CallbackScope, or the high-level AsyncResource class.

DEP0098: AsyncHooks embedder AsyncResource.emitBefore and AsyncResource.emitAfter APIs#

Type: End-of-Life

The embedded API provided by AsyncHooks exposes .emitBefore() and .emitAfter() methods which are very easy to use incorrectly which can lead to unrecoverable errors.

Use asyncResource.runInAsyncScope() API instead which provides a much safer, and more convenient, alternative. See https://github.com/nodejs/node/pull/18513.

DEP0099: Async context-unaware node::MakeCallback C++ APIs#

Type: Compile-time

Certain versions of node::MakeCallback APIs available to native addons are deprecated. Please use the versions of the API that accept an async_context parameter.

DEP0100: process.assert()#

Type: End-of-Life

process.assert() is deprecated. Please use the assert module instead.

This was never a documented feature.

DEP0101: --with-lttng#

Type: End-of-Life

The --with-lttng compile-time option has been removed.

DEP0102: Using noAssert in Buffer#(read|write) operations#

Type: End-of-Life

Using the noAssert argument has no functionality anymore. All input is verified regardless of the value of noAssert. Skipping the verification could lead to hard-to-find errors and crashes.

DEP0103: process.binding('util').is[...] typechecks#

Type: Documentation-only (supports --pending-deprecation)

Using process.binding() in general should be avoided. The type checking methods in particular can be replaced by using util.types.

This deprecation has been superseded by the deprecation of the process.binding() API (DEP0111).

DEP0104: process.env string coercion#

Type: Documentation-only (supports --pending-deprecation)

When assigning a non-string property to process.env, the assigned value is implicitly converted to a string. This behavior is deprecated if the assigned value is not a string, boolean, or number. In the future, such assignment might result in a thrown error. Please convert the property to a string before assigning it to process.env.

DEP0105: decipher.finaltol#

Type: End-of-Life

decipher.finaltol() has never been documented and was an alias for decipher.final(). This API has been removed, and it is recommended to use decipher.final() instead.

DEP0106: crypto.createCipher and crypto.createDecipher#

Type: End-of-Life

crypto.createCipher() and crypto.createDecipher() have been removed as they use a weak key derivation function (MD5 with no salt) and static initialization vectors. It is recommended to derive a key using crypto.pbkdf2() or crypto.scrypt() with random salts and to use crypto.createCipheriv() and crypto.createDecipheriv() to obtain the Cipheriv and Decipheriv objects respectively.

DEP0107: tls.convertNPNProtocols()#

Type: End-of-Life

This was an undocumented helper function not intended for use outside Node.js core and obsoleted by the removal of NPN (Next Protocol Negotiation) support.

DEP0108: zlib.bytesRead#

Type: End-of-Life

Deprecated alias for zlib.bytesWritten. This original name was chosen because it also made sense to interpret the value as the number of bytes read by the engine, but is inconsistent with other streams in Node.js that expose values under these names.

DEP0109: http, https, and tls support for invalid URLs#

Type: End-of-Life

Some previously supported (but strictly invalid) URLs were accepted through the http.request(), http.get(), https.request(), https.get(), and tls.checkServerIdentity() APIs because those were accepted by the legacy url.parse() API. The mentioned APIs now use the WHATWG URL parser that requires strictly valid URLs. Passing an invalid URL is deprecated and support will be removed in the future.

DEP0110: vm.Script cached data#

Type: Documentation-only

The produceCachedData option is deprecated. Use script.createCachedData() instead.

DEP0111: process.binding()#

Type: Documentation-only (supports --pending-deprecation)

process.binding() is for use by Node.js internal code only.

While process.binding() has not reached End-of-Life status in general, it is unavailable when the permission model is enabled.

DEP0112: dgram private APIs#

Type: Runtime

The node:dgram module previously contained several APIs that were never meant to accessed outside of Node.js core: Socket.prototype._handle, Socket.prototype._receiving, Socket.prototype._bindState, Socket.prototype._queue, Socket.prototype._reuseAddr, Socket.prototype._healthCheck(), Socket.prototype._stopReceiving(), and dgram._createSocketHandle().

DEP0113: Cipher.setAuthTag(), Decipher.getAuthTag()#

Type: End-of-Life

Cipher.setAuthTag() and Decipher.getAuthTag() are no longer available. They were never documented and would throw when called.

DEP0114: crypto._toBuf()#

Type: End-of-Life

The crypto._toBuf() function was not designed to be used by modules outside of Node.js core and was removed.

DEP0115: crypto.prng(), crypto.pseudoRandomBytes(), crypto.rng()#

Type: Documentation-only (supports --pending-deprecation)

In recent versions of Node.js, there is no difference between crypto.randomBytes() and crypto.pseudoRandomBytes(). The latter is deprecated along with the undocumented aliases crypto.prng() and crypto.rng() in favor of crypto.randomBytes() and might be removed in a future release.

DEP0116: Legacy URL API#

Type: Deprecation revoked

The legacy URL API is deprecated. This includes url.format(), url.parse(), url.resolve(), and the legacy urlObject. Please use the WHATWG URL API instead.

DEP0117: Native crypto handles#

Type: End-of-Life

Previous versions of Node.js exposed handles to internal native objects through the _handle property of the Cipher, Decipher, DiffieHellman, DiffieHellmanGroup, ECDH, Hash, Hmac, Sign, and Verify classes. The _handle property has been removed because improper use of the native object can lead to crashing the application.

DEP0118: dns.lookup() support for a falsy host name#

Type: Runtime

Previous versions of Node.js supported dns.lookup() with a falsy host name like dns.lookup(false) due to backward compatibility. This behavior is undocumented and is thought to be unused in real world apps. It will become an error in future versions of Node.js.

DEP0119: process.binding('uv').errname() private API#

Type: Documentation-only (supports --pending-deprecation)

process.binding('uv').errname() is deprecated. Please use util.getSystemErrorName() instead.

DEP0120: Windows Performance Counter support#

Type: End-of-Life

Windows Performance Counter support has been removed from Node.js. The undocumented COUNTER_NET_SERVER_CONNECTION(), COUNTER_NET_SERVER_CONNECTION_CLOSE(), COUNTER_HTTP_SERVER_REQUEST(), COUNTER_HTTP_SERVER_RESPONSE(), COUNTER_HTTP_CLIENT_REQUEST(), and COUNTER_HTTP_CLIENT_RESPONSE() functions have been deprecated.

DEP0121: net._setSimultaneousAccepts()#

Type: End-of-Life

The undocumented net._setSimultaneousAccepts() function was originally intended for debugging and performance tuning when using the node:child_process and node:cluster modules on Windows. The function is not generally useful and is being removed. See discussion here: https://github.com/nodejs/node/issues/18391

DEP0122: tls Server.prototype.setOptions()#

Type: End-of-Life

Please use Server.prototype.setSecureContext() instead.

DEP0123: setting the TLS ServerName to an IP address#

Type: Runtime

Setting the TLS ServerName to an IP address is not permitted by RFC 6066. This will be ignored in a future version.

DEP0124: using REPLServer.rli#

Type: End-of-Life

This property is a reference to the instance itself.

DEP0125: require('node:_stream_wrap')#

Type: Runtime

The node:_stream_wrap module is deprecated.

DEP0126: timers.active()#

Type: End-of-Life

The previously undocumented timers.active() has been removed. Please use the publicly documented timeout.refresh() instead. If re-referencing the timeout is necessary, timeout.ref() can be used with no performance impact since Node.js 10.

DEP0127: timers._unrefActive()#

Type: End-of-Life

The previously undocumented and "private" timers._unrefActive() has been removed. Please use the publicly documented timeout.refresh() instead. If unreferencing the timeout is necessary, timeout.unref() can be used with no performance impact since Node.js 10.

DEP0128: modules with an invalid main entry and an index.js file#

Type: Runtime

Modules that have an invalid main entry (e.g., ./does-not-exist.js) and also have an index.js file in the top level directory will resolve the index.js file. That is deprecated and is going to throw an error in future Node.js versions.

DEP0129: ChildProcess._channel#

Type: Runtime

The _channel property of child process objects returned by spawn() and similar functions is not intended for public use. Use ChildProcess.channel instead.

DEP0130: Module.createRequireFromPath()#

Type: End-of-Life

Use module.createRequire() instead.

DEP0131: Legacy HTTP parser#

Type: End-of-Life

The legacy HTTP parser, used by default in versions of Node.js prior to 12.0.0, is deprecated and has been removed in v13.0.0. Prior to v13.0.0, the --http-parser=legacy command-line flag could be used to revert to using the legacy parser.

DEP0132: worker.terminate() with callback#

Type: Runtime

Passing a callback to worker.terminate() is deprecated. Use the returned Promise instead, or a listener to the worker's 'exit' event.

DEP0133: http connection#

Type: Documentation-only

Prefer response.socket over response.connection and request.socket over request.connection.

DEP0134: process._tickCallback#

Type: Documentation-only (supports --pending-deprecation)

The process._tickCallback property was never documented as an officially supported API.

DEP0135: WriteStream.open() and ReadStream.open() are internal#

Type: Runtime

WriteStream.open() and ReadStream.open() are undocumented internal APIs that do not make sense to use in userland. File streams should always be opened through their corresponding factory methods fs.createWriteStream() and fs.createReadStream()) or by passing a file descriptor in options.

DEP0136: http finished#

Type: Documentation-only

response.finished indicates whether response.end() has been called, not whether 'finish' has been emitted and the underlying data is flushed.

Use response.writableFinished or response.writableEnded accordingly instead to avoid the ambiguity.

To maintain existing behavior response.finished should be replaced with response.writableEnded.

DEP0137: Closing fs.FileHandle on garbage collection#

Type: Runtime

Allowing a fs.FileHandle object to be closed on garbage collection is deprecated. In the future, doing so might result in a thrown error that will terminate the process.

Please ensure that all fs.FileHandle objects are explicitly closed using FileHandle.prototype.close() when the fs.FileHandle is no longer needed:

const fsPromises = require('node:fs').promises;
async function openAndClose() {
  let filehandle;
  try {
    filehandle = await fsPromises.open('thefile.txt', 'r');
  } finally {
    if (filehandle !== undefined)
      await filehandle.close();
  }
} 

DEP0138: process.mainModule#

Type: Documentation-only

process.mainModule is a CommonJS-only feature while process global object is shared with non-CommonJS environment. Its use within ECMAScript modules is unsupported.

It is deprecated in favor of require.main, because it serves the same purpose and is only available on CommonJS environment.

DEP0139: process.umask() with no arguments#

Type: Documentation-only

Calling process.umask() with no argument causes the process-wide umask to be written twice. This introduces a race condition between threads, and is a potential security vulnerability. There is no safe, cross-platform alternative API.

DEP0140: Use request.destroy() instead of request.abort()#

Type: Documentation-only

Use request.destroy() instead of request.abort().

DEP0141: repl.inputStream and repl.outputStream#

Type: Documentation-only (supports --pending-deprecation)

The node:repl module exported the input and output stream twice. Use .input instead of .inputStream and .output instead of .outputStream.

DEP0142: repl._builtinLibs#

Type: Documentation-only (supports --pending-deprecation)

The node:repl module exports a _builtinLibs property that contains an array of built-in modules. It was incomplete so far and instead it's better to rely upon require('node:module').builtinModules.

DEP0143: Transform._transformState#

Type: Runtime

Transform._transformState will be removed in future versions where it is no longer required due to simplification of the implementation.

DEP0144: module.parent#

Type: Documentation-only (supports --pending-deprecation)

A CommonJS module can access the first module that required it using module.parent. This feature is deprecated because it does not work consistently in the presence of ECMAScript modules and because it gives an inaccurate representation of the CommonJS module graph.

Some modules use it to check if they are the entry point of the current process. Instead, it is recommended to compare require.main and module:

if (require.main === module) {
  // Code section that will run only if current file is the entry point.
} 

When looking for the CommonJS modules that have required the current one, require.cache and module.children can be used:

const moduleParents = Object.values(require.cache)
  .filter((m) => m.children.includes(module)); 

DEP0145: socket.bufferSize#

Type: Documentation-only

socket.bufferSize is just an alias for writable.writableLength.

DEP0146: new crypto.Certificate()#

Type: Documentation-only

The crypto.Certificate() constructor is deprecated. Use static methods of crypto.Certificate() instead.

DEP0147: fs.rmdir(path, { recursive: true })#

Type: Runtime

In future versions of Node.js, recursive option will be ignored for fs.rmdir, fs.rmdirSync, and fs.promises.rmdir.

Use fs.rm(path, { recursive: true, force: true }), fs.rmSync(path, { recursive: true, force: true }) or fs.promises.rm(path, { recursive: true, force: true }) instead.

DEP0148: Folder mappings in "exports" (trailing "/")#

Type: End-of-Life

Using a trailing "/" to define subpath folder mappings in the subpath exports or subpath imports fields is no longer supported. Use subpath patterns instead.

DEP0149: http.IncomingMessage#connection#

Type: Documentation-only

Prefer message.socket over message.connection.

DEP0150: Changing the value of process.config#

Type: End-of-Life

The process.config property provides access to Node.js compile-time settings. However, the property is mutable and therefore subject to tampering. The ability to change the value will be removed in a future version of Node.js.

DEP0151: Main index lookup and extension searching#

Type: Runtime

Previously, index.js and extension searching lookups would apply to import 'pkg' main entry point resolution, even when resolving ES modules.

With this deprecation, all ES module main entry point resolutions require an explicit "exports" or "main" entry with the exact file extension.

DEP0152: Extension PerformanceEntry properties#

Type: Runtime

The 'gc', 'http2', and 'http' <PerformanceEntry> object types have additional properties assigned to them that provide additional information. These properties are now available within the standard detail property of the PerformanceEntry object. The existing accessors have been deprecated and should no longer be used.

DEP0153: dns.lookup and dnsPromises.lookup options type coercion#

Type: End-of-Life

Using a non-nullish non-integer value for family option, a non-nullish non-number value for hints option, a non-nullish non-boolean value for all option, or a non-nullish non-boolean value for verbatim option in dns.lookup() and dnsPromises.lookup() throws an ERR_INVALID_ARG_TYPE error.

DEP0154: RSA-PSS generate key pair options#

Type: Runtime

The 'hash' and 'mgf1Hash' options are replaced with 'hashAlgorithm' and 'mgf1HashAlgorithm'.

DEP0155: Trailing slashes in pattern specifier resolutions#

Type: Runtime

The remapping of specifiers ending in "/" like import 'pkg/x/' is deprecated for package "exports" and "imports" pattern resolutions.

DEP0156: .aborted property and 'abort', 'aborted' event in http#

Type: Documentation-only

Move to <Stream> API instead, as the http.ClientRequest, http.ServerResponse, and http.IncomingMessage are all stream-based. Check stream.destroyed instead of the .aborted property, and listen for 'close' instead of 'abort', 'aborted' event.

The .aborted property and 'abort' event are only useful for detecting .abort() calls. For closing a request early, use the Stream .destroy([error]) then check the .destroyed property and 'close' event should have the same effect. The receiving end should also check the readable.readableEnded value on http.IncomingMessage to get whether it was an aborted or graceful destroy.

DEP0157: Thenable support in streams#

Type: End-of-Life

An undocumented feature of Node.js streams was to support thenables in implementation methods. This is now deprecated, use callbacks instead and avoid use of async function for streams implementation methods.

This feature caused users to encounter unexpected problems where the user implements the function in callback style but uses e.g. an async method which would cause an error since mixing promise and callback semantics is not valid.

const w = new Writable({
  async final(callback) {
    await someOp();
    callback();
  },
}); 

DEP0158: buffer.slice(start, end)#

Type: Documentation-only

This method was deprecated because it is not compatible with Uint8Array.prototype.slice(), which is a superclass of Buffer.

Use buffer.subarray which does the same thing instead.

DEP0159: ERR_INVALID_CALLBACK#

Type: End-of-Life

This error code was removed due to adding more confusion to the errors used for value type validation.

DEP0160: process.on('multipleResolves', handler)#

Type: Runtime

This event was deprecated because it did not work with V8 promise combinators which diminished its usefulness.

DEP0161: process._getActiveRequests() and process._getActiveHandles()#

Type: Documentation-only

The process._getActiveHandles() and process._getActiveRequests() functions are not intended for public use and can be removed in future releases.

Use process.getActiveResourcesInfo() to get a list of types of active resources and not the actual references.

DEP0162: fs.write(), fs.writeFileSync() coercion to string#

Type: End-of-Life

Implicit coercion of objects with own toString property, passed as second parameter in fs.write(), fs.writeFile(), fs.appendFile(), fs.writeFileSync(), and fs.appendFileSync() is deprecated. Convert them to primitive strings.

DEP0163: channel.subscribe(onMessage), channel.unsubscribe(onMessage)#

Type: Documentation-only

These methods were deprecated because they can be used in a way which does not hold the channel reference alive long enough to receive the events.

Use diagnostics_channel.subscribe(name, onMessage) or diagnostics_channel.unsubscribe(name, onMessage) which does the same thing instead.

DEP0164: process.exit(code), process.exitCode coercion to integer#

Type: End-of-Life

Values other than undefined, null, integer numbers, and integer strings (e.g., '1') are deprecated as value for the code parameter in process.exit() and as value to assign to process.exitCode.

DEP0165: --trace-atomics-wait#

Type: End-of-Life

The --trace-atomics-wait flag has been removed because it uses the V8 hook SetAtomicsWaitCallback, that will be removed in a future V8 release.

DEP0166: Double slashes in imports and exports targets#

Type: Runtime

Package imports and exports targets mapping into paths including a double slash (of "/" or "\") are deprecated and will fail with a resolution validation error in a future release. This same deprecation also applies to pattern matches starting or ending in a slash.

DEP0167: Weak DiffieHellmanGroup instances (modp1, modp2, modp5)#

Type: Documentation-only

The well-known MODP groups modp1, modp2, and modp5 are deprecated because they are not secure against practical attacks. See RFC 8247 Section 2.4 for details.

These groups might be removed in future versions of Node.js. Applications that rely on these groups should evaluate using stronger MODP groups instead.

DEP0168: Unhandled exception in Node-API callbacks#

Type: Runtime

The implicit suppression of uncaught exceptions in Node-API callbacks is now deprecated.

Set the flag --force-node-api-uncaught-exceptions-policy to force Node.js to emit an 'uncaughtException' event if the exception is not handled in Node-API callbacks.

DEP0169: Insecure url.parse()#

Type: Application (non-node_modules code only)

url.parse() behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for url.parse() vulnerabilities.

DEP0170: Invalid port when using url.parse()#

Type: Runtime

url.parse() accepts URLs with ports that are not numbers. This behavior might result in host name spoofing with unexpected input. These URLs will throw an error in future versions of Node.js, as the WHATWG URL API does already.

DEP0171: Setters for http.IncomingMessage headers and trailers#

Type: Documentation-only

In a future version of Node.js, message.headers, message.headersDistinct, message.trailers, and message.trailersDistinct will be read-only.

DEP0172: The asyncResource property of AsyncResource bound functions#

Type: Runtime

In a future version of Node.js, the asyncResource property will no longer be added when a function is bound to an AsyncResource.

DEP0173: the assert.CallTracker class#

Type: Runtime

In a future version of Node.js, assert.CallTracker, will be removed. Consider using alternatives such as the mock helper function.

DEP0174: calling promisify on a function that returns a Promise#

Type: Runtime

Calling util.promisify on a function that returns a Promise will ignore the result of said promise, which can lead to unhandled promise rejections.

DEP0175: util.toUSVString#

Type: Documentation-only

The util.toUSVString() API is deprecated. Please use String.prototype.toWellFormed instead.

DEP0176: fs.F_OK, fs.R_OK, fs.W_OK, fs.X_OK#

Type: Runtime

F_OK, R_OK, W_OK and X_OK getters exposed directly on node:fs are deprecated. Get them from fs.constants or fs.promises.constants instead.

DEP0177: util.types.isWebAssemblyCompiledModule#

Type: End-of-Life

The util.types.isWebAssemblyCompiledModule API has been removed. Please use value instanceof WebAssembly.Module instead.

DEP0178: dirent.path#

Type: End-of-Life

The dirent.path property has been removed due to its lack of consistency across release lines. Please use dirent.parentPath instead.

DEP0179: Hash constructor#

Type: Runtime

Calling Hash class directly with Hash() or new Hash() is deprecated due to being internals, not intended for public use. Please use the crypto.createHash() method to create Hash instances.

DEP0180: fs.Stats constructor#

Type: Runtime

Calling fs.Stats class directly with Stats() or new Stats() is deprecated due to being internals, not intended for public use.

DEP0181: Hmac constructor#

Type: Runtime

Calling Hmac class directly with Hmac() or new Hmac() is deprecated due to being internals, not intended for public use. Please use the crypto.createHmac() method to create Hmac instances.

DEP0182: Short GCM authentication tags without explicit authTagLength#

Type: Runtime

Applications that intend to use authentication tags that are shorter than the default authentication tag length must set the authTagLength option of the crypto.createDecipheriv() function to the appropriate length.

For ciphers in GCM mode, the decipher.setAuthTag() function accepts authentication tags of any valid length (see DEP0090). This behavior is deprecated to better align with recommendations per NIST SP 800-38D.

DEP0183: OpenSSL engine-based APIs#

Type: Documentation-only

OpenSSL 3 has deprecated support for custom engines with a recommendation to switch to its new provider model. The clientCertEngine option for https.request(), tls.createSecureContext(), and tls.createServer(); the privateKeyEngine and privateKeyIdentifier for tls.createSecureContext(); and crypto.setEngine() all depend on this functionality from OpenSSL.

DEP0184: Instantiating node:zlib classes without new#

Type: Runtime

Instantiating classes without the new qualifier exported by the node:zlib module is deprecated. It is recommended to use the new qualifier instead. This applies to all Zlib classes, such as Deflate, DeflateRaw, Gunzip, Inflate, InflateRaw, Unzip, and Zlib.

DEP0185: Instantiating node:repl classes without new#

Type: Runtime

Instantiating classes without the new qualifier exported by the node:repl module is deprecated. It is recommended to use the new qualifier instead. This applies to all REPL classes, including REPLServer and Recoverable.

DEP0187: Passing invalid argument types to fs.existsSync#

Type: Runtime

Passing non-supported argument types is deprecated and, instead of returning false, will throw an error in a future version.

DEP0188: process.features.ipv6 and process.features.uv#

Type: Documentation-only

These properties are unconditionally true. Any checks based on these properties are redundant.

DEP0189: process.features.tls_*#

Type: Documentation-only

process.features.tls_alpn, process.features.tls_ocsp, and process.features.tls_sni are deprecated, as their values are guaranteed to be identical to that of process.features.tls.

DEP0190: Passing args to node:child_process execFile/spawn with shell option true#

Type: Runtime

When an args array is passed to