From 9df4fd2cfe58790966f44fd6f2a9946b4ed7ac4b Mon Sep 17 00:00:00 2001 From: Gopal Date: Sat, 29 Aug 2026 12:59:02 +0400 Subject: [PATCH] docs: standardize API code examples to ESM - Remove dual mjs/cjs code blocks from API documentation - Use single ```js blocks with ESM imports as the canonical form - Eliminates redundant documentation and reduces file size - Resolves nodejs/node#65536 Signed-off-by: Gopal --- doc/api/addons.md | 2 +- doc/api/assert.md | 780 +--------- doc/api/async_context.md | 255 +--- doc/api/async_hooks.md | 239 +-- doc/api/buffer.md | 1663 ++------------------- doc/api/child_process.md | 116 +- doc/api/cli.md | 17 +- doc/api/cluster.md | 175 +-- doc/api/console.md | 24 +- doc/api/crypto.md | 1143 +------------- doc/api/deprecations.md | 19 +- doc/api/dgram.md | 107 +- doc/api/diagnostics_channel.md | 451 +----- doc/api/dns.md | 125 +- doc/api/dtls.md | 14 +- doc/api/errors.md | 4 +- doc/api/esm.md | 2 +- doc/api/events.md | 670 +-------- doc/api/ffi.md | 35 +- doc/api/fs.md | 455 ++---- doc/api/globals.md | 25 +- doc/api/http.md | 358 +---- doc/api/http2.md | 685 +-------- doc/api/https.md | 158 +- doc/api/inspector.md | 18 +- doc/api/module.md | 247 +-- doc/api/modules.md | 14 +- doc/api/net.md | 72 +- doc/api/os.md | 6 +- doc/api/packages.md | 8 +- doc/api/path.md | 4 +- doc/api/perf_hooks.md | 345 +---- doc/api/process.md | 877 ++--------- doc/api/quic.md | 44 +- doc/api/readline.md | 148 +- doc/api/repl.md | 246 +-- doc/api/single-executable-applications.md | 2 +- doc/api/sqlite.md | 140 +- doc/api/stream.md | 152 +- doc/api/stream_iter.md | 634 +------- doc/api/string_decoder.md | 30 +- doc/api/test.md | 585 +------- doc/api/timers.md | 91 +- doc/api/tls.md | 108 +- doc/api/tracing.md | 93 +- doc/api/url.md | 127 +- doc/api/util.md | 708 +-------- doc/api/v8.md | 232 +-- doc/api/vfs.md | 18 +- doc/api/vm.md | 540 +------ doc/api/wasi.md | 27 +- doc/api/webcrypto.md | 2 +- doc/api/webstreams.md | 228 +-- doc/api/worker_threads.md | 432 +----- doc/api/zlib.md | 338 +---- 55 files changed, 1147 insertions(+), 12891 deletions(-) diff --git a/doc/api/addons.md b/doc/api/addons.md index 80d23a4cf48a..70e8dbaeee5f 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -451,7 +451,7 @@ both static `import` and dynamic `import()` to load binary addons. If we reuse the Hello World example from earlier, you could do: -```mjs +```js // hello.mjs import myAddon from './hello.node'; // N.B.: import {hello} from './hello.node' would not work diff --git a/doc/api/assert.md b/doc/api/assert.md index c33f4ba82336..2604537d5437 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -62,25 +62,17 @@ is thrown. To use strict assertion mode: -```mjs +```js import { strict as assert } from 'node:assert'; ``` -```cjs -const assert = require('node:assert').strict; -``` - -```mjs +```js import assert from 'node:assert/strict'; ``` -```cjs -const assert = require('node:assert/strict'); -``` - Example error diff: -```mjs +```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); @@ -99,25 +91,6 @@ assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // ] ``` -```cjs -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 @@ -134,18 +107,14 @@ Legacy assertion mode uses the [`==` operator][] in: To use legacy assertion mode: -```mjs +```js import assert from 'node:assert'; ``` -```cjs -const assert = require('node:assert'); -``` - Legacy assertion mode may have surprising results, especially when using [`assert.deepEqual()`][]: -```cjs +```js // WARNING: This does not throw an AssertionError in legacy assertion mode! assert.deepEqual(/a/gi, new Date()); ``` @@ -188,7 +157,7 @@ and: assertion error. * `operator` {string} Set to the passed in operator value. -```mjs +```js import assert from 'node:assert'; // Generate an AssertionError to compare the error message later: @@ -213,31 +182,6 @@ try { } ``` -```cjs -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.Assert` -```mjs +```js import assert from 'node:assert/strict'; assert.ok(true); @@ -1723,7 +1309,7 @@ assert.ok(0); -```cjs +```js const assert = require('node:assert/strict'); assert.ok(true); @@ -1758,7 +1344,7 @@ assert.ok(0); // assert.ok(0) ``` -```mjs +```js import assert from 'node:assert/strict'; // Using `assert()` works the same: @@ -1768,16 +1354,6 @@ assert(2 + 2 > 5); // assert(2 + 2 > 5) ``` -```cjs -const assert = require('node:assert'); - -// Using `assert()` works the same: -assert(2 + 2 > 5); -// AssertionError: The expression evaluated to a falsy value: -// -// assert(2 + 2 > 5) -``` - ## `assert.rejects(asyncFn[, error][, message])` -```cjs +```js let crypto; try { crypto = require('node:crypto'); @@ -62,7 +50,7 @@ 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: -```mjs +```js let crypto; try { crypto = await import('node:crypto'); @@ -226,7 +214,7 @@ repeatedly. Example: Reusing a [`KeyObject`][] across sign and verify operations: -```mjs +```js import { promisify } from 'node:util'; const { generateKeyPair, sign, verify } = await import('node:crypto'); @@ -241,7 +229,7 @@ verify(null, data, publicKey, signature); Example: Importing keys of various formats into [`KeyObject`][]s: -```mjs +```js import { promisify } from 'node:util'; const { createPrivateKey, createPublicKey, generateKeyPair, @@ -277,7 +265,7 @@ createPublicKey({ key: rawPub, format: 'raw-public', asymmetricKeyType: 'ed25519 Example: Passing key material directly to [`crypto.sign()`][] and [`crypto.verify()`][] without creating a [`KeyObject`][] first: -```mjs +```js import { promisify } from 'node:util'; const { generateKeyPair, sign, verify } = await import('node:crypto'); @@ -311,7 +299,7 @@ verify(null, data, { Example: For EC keys, the `namedCurve` option is required when importing raw keys: -```mjs +```js import { promisify } from 'node:util'; const { createPrivateKey, createPublicKey, generateKeyPair, sign, verify, @@ -361,7 +349,7 @@ verify('sha256', data, publicKey, signature); Example: Exporting raw seeds and importing them: -```mjs +```js import { promisify } from 'node:util'; const { createPrivateKey, decapsulate, encapsulate, generateKeyPair, @@ -415,7 +403,7 @@ changes: * Returns: {Buffer} The challenge component of the `spkac` data structure, which includes a public key and a challenge. -```mjs +```js const { Certificate } = await import('node:crypto'); const spkac = getSpkacSomehow(); const challenge = Certificate.exportChallenge(spkac); @@ -423,14 +411,6 @@ console.log(challenge.toString('utf8')); // Prints: the challenge as a UTF8 string ``` -```cjs -const { 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])` true - console.error(err.code); // --> 'ERR_INVALID_HTTP_TOKEN' - console.error(err.message); // --> 'Header name must be a valid HTTP token [""]' -} -``` - ## `http.validateHeaderValue(name, value)` true - console.error(err.code === 'ERR_HTTP_INVALID_HEADER_VALUE'); // --> true - console.error(err.message); // --> 'Invalid value "undefined" for header "x-my-header"' -} - -try { - validateHeaderValue('x-my-header', 'oʊmɪɡə'); -} catch (err) { - console.error(err instanceof TypeError); // --> true - console.error(err.code === 'ERR_INVALID_CHAR'); // --> true - console.error(err.message); // --> 'Invalid character in header content ["x-my-header"]' -} -``` - ## `http.setMaxIdleHTTPParsers(max)` -```cjs +```js const Point = require('./point.mjs'); console.log(Point); // [class Point] @@ -291,7 +291,7 @@ named exports, the module can make sure that the default export is an object wit named exports attached to it as properties. For example with the example above, `distance` can be attached to the default export, the `Point` class, as a static method. -```mjs +```js export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); } export default class Point { @@ -304,7 +304,7 @@ export { Point as 'module.exports' }; -```cjs +```js const Point = require('./point.mjs'); console.log(Point); // [class Point] diff --git a/doc/api/net.md b/doc/api/net.md index d0b0e34c6504..c159960a965e 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -14,14 +14,10 @@ TCP or [IPC][] servers ([`net.createServer()`][]) and clients It can be accessed using: -```mjs +```js import net from 'node:net'; ``` -```cjs -const net = require('node:net'); -``` - ## IPC support -```cjs +```js const { performance, PerformanceObserver, @@ -2802,7 +2542,7 @@ it means the time interval between starting the request and receiving the response, and for HTTP request, it means the time interval between receiving the request and sending the response: -```mjs +```js import { PerformanceObserver } from 'node:perf_hooks'; import { createServer, get } from 'node:http'; @@ -2823,30 +2563,9 @@ createServer((req, res) => { }); ``` -```cjs -const { PerformanceObserver } = require('node:perf_hooks'); -const http = require('node:http'); - -const obs = new PerformanceObserver((items) => { - items.getEntries().forEach((item) => { - console.log(item); - }); -}); - -obs.observe({ entryTypes: ['http'] }); - -const PORT = 8080; - -http.createServer((req, res) => { - res.end('ok'); -}).listen(PORT, () => { - http.get(`http://127.0.0.1:${PORT}`); -}); -``` - ### Measuring how long the `net.connect` (only for TCP) takes when the connection is successful -```mjs +```js import { PerformanceObserver } from 'node:perf_hooks'; import { connect, createServer } from 'node:net'; @@ -2864,26 +2583,9 @@ createServer((socket) => { }); ``` -```cjs -const { PerformanceObserver } = require('node:perf_hooks'); -const net = require('node:net'); -const obs = new PerformanceObserver((items) => { - items.getEntries().forEach((item) => { - console.log(item); - }); -}); -obs.observe({ entryTypes: ['net'] }); -const PORT = 8080; -net.createServer((socket) => { - socket.destroy(); -}).listen(PORT, () => { - net.connect(PORT); -}); -``` - ### Measuring how long the DNS takes when the request is successful -```mjs +```js import { PerformanceObserver } from 'node:perf_hooks'; import { lookup, promises } from 'node:dns'; @@ -2897,19 +2599,6 @@ lookup('localhost', () => {}); promises.resolve('localhost'); ``` -```cjs -const { PerformanceObserver } = require('node:perf_hooks'); -const dns = require('node:dns'); -const obs = new PerformanceObserver((items) => { - items.getEntries().forEach((item) => { - console.log(item); - }); -}); -obs.observe({ entryTypes: ['dns'] }); -dns.lookup('localhost', () => {}); -dns.promises.resolve('localhost'); -``` - [Async Hooks]: async_hooks.md [CBOR]: https://www.rfc-editor.org/rfc/rfc8949 [Cliff's delta]: https://en.wikipedia.org/wiki/Effect_size#Cliff's_delta diff --git a/doc/api/process.md b/doc/api/process.md index c237943b69f0..605c72bec8a2 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -9,13 +9,13 @@ The `process` object provides information about, and control over, the current Node.js process. -```mjs +```js import process from 'node:process'; ``` -```cjs +```js const process = require('node:process'); ``` @@ -44,7 +44,7 @@ termination, such as calling [`process.exit()`][] or uncaught exceptions. The `'beforeExit'` should _not_ be used as an alternative to the `'exit'` event unless the intention is to schedule additional work. -```mjs +```js import process from 'node:process'; process.on('beforeExit', (code) => { @@ -63,23 +63,6 @@ console.log('This message is displayed first.'); // Process exit event with code: 0 ``` -```cjs -process.on('beforeExit', (code) => { - console.log('Process beforeExit event with code: ', code); -}); - -process.on('exit', (code) => { - console.log('Process exit event with code: ', code); -}); - -console.log('This message is displayed first.'); - -// Prints: -// This message is displayed first. -// Process beforeExit event with code: 0 -// Process exit event with code: 0 -``` - ### Event: `'disconnect'` -```cjs +```js const { Writable } = require('node:stream'); class MyWritable extends Writable { @@ -3841,7 +3765,7 @@ class MyWritable extends Writable { -```mjs +```js import { Writable } from 'node:stream'; class MyWritable extends Writable { @@ -4518,7 +4442,7 @@ changes: -```cjs +```js const { Duplex } = require('node:stream'); class MyDuplex extends Duplex { @@ -4531,7 +4455,7 @@ class MyDuplex extends Duplex { -```mjs +```js import { Duplex } from 'node:stream'; class MyDuplex extends Duplex { @@ -4714,7 +4638,7 @@ output on the `Readable` side is not consumed. -```cjs +```js const { Transform } = require('node:stream'); class MyTransform extends Transform { @@ -4727,7 +4651,7 @@ class MyTransform extends Transform { -```mjs +```js import { Transform } from 'node:stream'; class MyTransform extends Transform { diff --git a/doc/api/stream_iter.md b/doc/api/stream_iter.md index c1ebacd3dfad..69a317ef49f8 100644 --- a/doc/api/stream_iter.md +++ b/doc/api/stream_iter.md @@ -18,7 +18,7 @@ functions or objects with a `transform` method. Data flows in **batches** ({Uint8Array\[]} per iteration) to amortize the cost of async operations. -```mjs +```js import { from, pull, text } from 'node:stream/iter'; import { compressGzip, decompressGzip } from 'node:zlib/iter'; @@ -28,21 +28,7 @@ const result = await text(pull(compressed, decompressGzip())); console.log(result); // 'Hello, world!' ``` -```cjs -const { from, pull, text } = require('node:stream/iter'); -const { compressGzip, decompressGzip } = require('node:zlib/iter'); - -async function run() { - // Compress and decompress a string - const compressed = pull(from('Hello, world!'), compressGzip()); - const result = await text(pull(compressed, decompressGzip())); - console.log(result); // 'Hello, world!' -} - -run().catch(console.error); -``` - -```mjs +```js import { open } from 'node:fs/promises'; import { text, pipeTo } from 'node:stream/iter'; import { compressGzip, decompressGzip } from 'node:zlib/iter'; @@ -58,26 +44,6 @@ const gz = await open('output.gz', 'r'); console.log(await text(gz.pull(decompressGzip(), { autoClose: true }))); ``` -```cjs -const { open } = require('node:fs/promises'); -const { text, pipeTo } = require('node:stream/iter'); -const { compressGzip, decompressGzip } = require('node:zlib/iter'); - -async function run() { - // Read a file, compress, write to another file - const src = await open('input.txt', 'r'); - const dst = await open('output.gz', 'w'); - await pipeTo(src.pull(), compressGzip(), dst.writer({ autoClose: true })); - await src.close(); - - // Read it back - const gz = await open('output.gz', 'r'); - console.log(await text(gz.pull(decompressGzip(), { autoClose: true }))); -} - -run().catch(console.error); -``` - ## Concepts ### Byte streams @@ -94,7 +60,7 @@ Each iteration yields a **batch** -- an {Array} of {Uint8Array} chunks across multiple chunks. A consumer that processes one chunk at a time can simply iterate the inner array: -```mjs +```js for await (const batch of source) { for (const chunk of batch) { handle(chunk); @@ -102,16 +68,6 @@ for await (const batch of source) { } ``` -```cjs -async function run() { - for await (const batch of source) { - for (const chunk of batch) { - handle(chunk); - } - } -} -``` - ### Transforms Transforms come in two forms: @@ -240,7 +196,7 @@ write at a time (yours), so you never hit the pending writes limit. Unawaited writes accumulate in the pending queue and throw once it overflows: -```mjs +```js import { push, text } from 'node:stream/iter'; const { writer, readable } = push({ budget: 16384 }); @@ -258,28 +214,6 @@ await writer.end(); console.log(await consuming); ``` -```cjs -const { push, text } = require('node:stream/iter'); - -async function run() { - const { writer, readable } = push({ budget: 16384 }); - - // Consumer must run concurrently -- without it, the first write - // that fills the buffer blocks the producer forever. - const consuming = text(readable); - - // GOOD: awaited writes. The producer waits for the consumer to - // make room when the buffer is full. - for (const item of dataset) { - await writer.write(item); - } - await writer.end(); - console.log(await consuming); -} - -run().catch(console.error); -``` - Forgetting to `await` will eventually throw: ```js @@ -302,7 +236,7 @@ This is the mode that existing Node.js classic streams and Web Streams default to. Use it when you control the producer and know it awaits properly, or when migrating code from those APIs. -```mjs +```js import { push, text } from 'node:stream/iter'; const { writer, readable } = push({ @@ -320,28 +254,6 @@ await writer.end(); console.log(await consuming); ``` -```cjs -const { push, text } = require('node:stream/iter'); - -async function run() { - const { writer, readable } = push({ - budget: 16384, - backpressure: 'unbounded', - }); - - const consuming = text(readable); - - // Safe -- awaited writes block until the consumer reads. - for (const item of dataset) { - await writer.write(item); - } - await writer.end(); - console.log(await consuming); -} - -run().catch(console.error); -``` - #### Drop-oldest Writes never wait. When the slots buffer is full, the oldest buffered @@ -349,7 +261,7 @@ chunk is evicted to make room for the incoming write. The consumer always sees the most recent data. Useful for live feeds, telemetry, or any scenario where stale data is less valuable than current data. -```mjs +```js import { push } from 'node:stream/iter'; // Keep only the most recent ~16 KB of readings @@ -359,16 +271,6 @@ const { writer, readable } = push({ }); ``` -```cjs -const { push } = require('node:stream/iter'); - -// Keep only the most recent ~16 KB of readings -const { writer, readable } = push({ - budget: 16384, - backpressure: 'drop-oldest', -}); -``` - #### Drop-newest Writes never wait. When the slots buffer is full, the incoming write is @@ -376,7 +278,7 @@ silently discarded. The consumer processes what is already buffered without being overwhelmed by new data. Useful for rate-limiting or shedding load under pressure. -```mjs +```js import { push } from 'node:stream/iter'; // Accept up to 16 KB of buffered data; discard anything beyond that @@ -386,16 +288,6 @@ const { writer, readable } = push({ }); ``` -```cjs -const { push } = require('node:stream/iter'); - -// Accept up to 16 KB of buffered data; discard anything beyond that -const { writer, readable } = push({ - budget: 16384, - backpressure: 'drop-newest', -}); -``` - ### Writer interface A writer is any object conforming to the Writer interface. Only `write()` is @@ -406,7 +298,7 @@ try-fallback pattern: attempt the fast synchronous path first, and fall back to the async version only when the synchronous call indicates it could not complete: -```mjs +```js if (!writer.writeSync(chunk)) await writer.write(chunk); if (!writer.writevSync(chunks)) await writer.writev(chunks); if (writer.endSync() < 0) await writer.end(); @@ -442,7 +334,7 @@ Synchronous variant of `writer.end()`. A return value of `-1` means closing has started but requires asynchronous draining. Use the try-fallback pattern to await completion: -```cjs +```js const result = writer.endSync(); if (result < 0) { writer.end(); @@ -499,7 +391,7 @@ Synchronous batch write. All functions are available both as named exports and as properties of the `Stream` namespace object: -```mjs +```js // Named exports import { from, pull, bytes, Stream } from 'node:stream/iter'; @@ -507,14 +399,6 @@ import { from, pull, bytes, Stream } from 'node:stream/iter'; Stream.from('hello'); ``` -```cjs -// Named exports -const { from, pull, bytes, Stream } = require('node:stream/iter'); - -// Namespace access -Stream.from('hello'); -``` - Including the `node:` prefix on the module specifier is optional. ## Sources @@ -541,7 +425,7 @@ Objects implementing `Symbol.for('Stream.toAsyncStreamable')` or precedence over the iteration protocols (`Symbol.asyncIterator`, `Symbol.iterator`). -```mjs +```js import { Buffer } from 'node:buffer'; import { from, text } from 'node:stream/iter'; @@ -549,18 +433,6 @@ console.log(await text(from('hello'))); // 'hello' console.log(await text(from(Buffer.from('hello')))); // 'hello' ``` -```cjs -const { Buffer } = require('node:buffer'); -const { from, text } = require('node:stream/iter'); - -async function run() { - console.log(await text(from('hello'))); // 'hello' - console.log(await text(from(Buffer.from('hello')))); // 'hello' -} - -run().catch(console.error); -``` - ### `fromSync(input)` The `defaultOptions` value allows customization of the default options used by -`util.inspect`. This is useful for functions like `console.log` or -`util.format` which implicitly call into `util.inspect`. It shall be set to an -object containing one or more valid [`util.inspect()`][] options. Setting -option properties directly is also supported. - -```mjs -import { inspect } from 'node:util'; -const arr = Array(156).fill(0); - -console.log(arr); // Logs the truncated array -inspect.defaultOptions.maxArrayLength = null; -console.log(arr); // logs the full array -``` +`util.inspect`. This is useful for functions like `console.log` or +`util.format` which implicitly call into `util.inspect`. It shall be set to an +object containing one or more valid [`util.inspect()`][] options. Setting +option properties directly is also supported. -```cjs -const { inspect } = require('node:util'); +```js +import { inspect } from 'node:util'; const arr = Array(156).fill(0); console.log(arr); // Logs the truncated array @@ -1721,43 +1389,30 @@ properties for each of these components. Creates a new `MIMEType` object by parsing the `input`. -```mjs +```js import { MIMEType } from 'node:util'; const myMIME = new MIMEType('text/plain'); ``` -```cjs -const { MIMEType } = require('node:util'); - -const myMIME = new MIMEType('text/plain'); -``` - A `TypeError` will be thrown if the `input` is not a valid MIME. Note that an effort will be made to coerce the given values into strings. For instance: -```mjs +```js import { MIMEType } from 'node:util'; const myMIME = new MIMEType({ toString: () => 'text/plain' }); console.log(String(myMIME)); // Prints: text/plain ``` -```cjs -const { MIMEType } = require('node:util'); -const myMIME = new MIMEType({ toString: () => 'text/plain' }); -console.log(String(myMIME)); -// Prints: text/plain -``` - ### `mime.type` * Type: {string} Gets and sets the type portion of the MIME. -```mjs +```js import { MIMEType } from 'node:util'; const myMIME = new MIMEType('text/javascript'); @@ -1770,26 +1425,13 @@ console.log(String(myMIME)); // Prints: application/javascript ``` -```cjs -const { MIMEType } = require('node:util'); - -const myMIME = new MIMEType('text/javascript'); -console.log(myMIME.type); -// Prints: text -myMIME.type = 'application'; -console.log(myMIME.type); -// Prints: application -console.log(String(myMIME)); -// Prints: application/javascript -``` - ### `mime.subtype` * Type: {string} Gets and sets the subtype portion of the MIME. -```mjs +```js import { MIMEType } from 'node:util'; const myMIME = new MIMEType('text/ecmascript'); @@ -1802,19 +1444,6 @@ console.log(String(myMIME)); // Prints: text/javascript ``` -```cjs -const { MIMEType } = require('node:util'); - -const myMIME = new MIMEType('text/ecmascript'); -console.log(myMIME.subtype); -// Prints: ecmascript -myMIME.subtype = 'javascript'; -console.log(myMIME.subtype); -// Prints: javascript -console.log(String(myMIME)); -// Prints: text/javascript -``` - ### `mime.essence` * Type: {string} @@ -1822,7 +1451,7 @@ console.log(String(myMIME)); Gets the essence of the MIME. This property is read only. Use `mime.type` or `mime.subtype` to alter the MIME. -```mjs +```js import { MIMEType } from 'node:util'; const myMIME = new MIMEType('text/javascript;key=value'); @@ -1835,19 +1464,6 @@ console.log(String(myMIME)); // Prints: application/javascript;key=value ``` -```cjs -const { MIMEType } = require('node:util'); - -const myMIME = new MIMEType('text/javascript;key=value'); -console.log(myMIME.essence); -// Prints: text/javascript -myMIME.type = 'application'; -console.log(myMIME.essence); -// Prints: application/javascript -console.log(String(myMIME)); -// Prints: application/javascript;key=value -``` - ### `mime.params` * Type: {MIMEParams} @@ -1874,7 +1490,7 @@ Alias for [`mime.toString()`][]. This method is automatically called when an `MIMEType` object is serialized with [`JSON.stringify()`][]. -```mjs +```js import { MIMEType } from 'node:util'; const myMIMES = [ @@ -1885,17 +1501,6 @@ console.log(JSON.stringify(myMIMES)); // Prints: ["image/png", "image/gif"] ``` -```cjs -const { MIMEType } = require('node:util'); - -const myMIMES = [ - new MIMEType('image/png'), - new MIMEType('image/gif'), -]; -console.log(JSON.stringify(myMIMES)); -// Prints: ["image/png", "image/gif"] -``` - ### `MIMEType.parse(string)` -```mjs +```js import foo from 'foo'; import source Foo from 'foo'; ``` @@ -1138,7 +941,7 @@ For example, given a source text: -```mjs +```js import foo from 'foo'; import fooAlias from 'foo'; import bar from './bar.js'; @@ -1198,7 +1001,7 @@ defined in the WebIDL specification. The purpose of synthetic modules is to provide a generic interface for exposing non-JavaScript sources to ECMAScript module graphs. -```mjs +```js import { SyntheticModule } from 'node:vm'; const source = '{ "a": 1 }'; @@ -1216,24 +1019,6 @@ const syntheticModule = new SyntheticModule(['default'], function() { })(); ``` -```cjs -const { SyntheticModule } = require('node:vm'); - -const source = '{ "a": 1 }'; -const syntheticModule = new SyntheticModule(['default'], function() { - const obj = JSON.parse(source); - this.setExport('default', obj); -}); - -// Use `syntheticModule` in linking -(async () => { - await syntheticModule.link(() => {}); - await syntheticModule.evaluate(); - - console.log('Default export:', syntheticModule.namespace.default); -})(); -``` - ### `new vm.SyntheticModule(exportNames, evaluateCallback[, options])` -```mjs +```js import { runInThisContext } from 'node:vm'; let localVar = 'initial value'; @@ -1964,7 +1658,7 @@ console.log(`evalResult: '${evalResult}', localVar: '${localVar}'`); -```cjs +```js const { runInThisContext } = require('node:vm'); let localVar = 'initial value'; @@ -1993,7 +1687,7 @@ In order to run a simple web server using the `node:http` module the code passed to the context must either call `require('node:http')` on its own, or have a reference to the `node:http` module passed to it. For instance: -```mjs +```js import { runInThisContext } from 'node:vm'; import { createRequire } from 'node:module'; @@ -2014,24 +1708,6 @@ const code = ` runInThisContext(code)(require); ``` -```cjs -const { runInThisContext } = require('node:vm'); - -const code = ` -((require) => { - const { createServer } = require('node:http'); - - createServer((request, response) => { - response.writeHead(200, { 'Content-Type': 'text/plain' }); - response.end('Hello World\\n'); - }).listen(8124); - - console.log('Server running at http://127.0.0.1:8124/'); -})`; - -runInThisContext(code)(require); -``` - The `require()` in the above case shares the state with the context it is passed from. This may introduce risks when untrusted code is executed, e.g. altering objects in the context in unwanted ways. @@ -2057,7 +1733,7 @@ The contextifying would introduce some quirks to the `globalThis` value in the c For example, it cannot be frozen, and it is not reference equal to the `contextObject` in the outer context. -```mjs +```js import { createContext, runInContext } from 'node:vm'; // An undefined `contextObject` option makes the global object contextified. @@ -2072,21 +1748,6 @@ try { console.log(runInContext('globalThis.foo = 1; foo;', context)); // 1 ``` -```cjs -const { createContext, runInContext } = require('node:vm'); - -// An undefined `contextObject` option makes the global object contextified. -const context = createContext(); -console.log(runInContext('globalThis', context) === context); // false -// A contextified global object cannot be frozen. -try { - runInContext('Object.freeze(globalThis);', context); -} catch (e) { - console.log(`${e.constructor.name}: ${e.message}`); // TypeError: Cannot freeze -} -console.log(runInContext('globalThis.foo = 1; foo;', context)); // 1 -``` - To create a context with an ordinary global object and get access to a global proxy in the outer context with fewer quirks, specify `vm.constants.DONT_CONTEXTIFY` as the `contextObject` argument. @@ -2098,7 +1759,7 @@ a context without wrapping its global object with another object in a Node.js-sp As a result, the `globalThis` value inside the new context would behave more closely to an ordinary one. -```mjs +```js import { createContext, runInContext, constants } from 'node:vm'; // Use vm.constants.DONT_CONTEXTIFY to freeze the global object. @@ -2111,25 +1772,12 @@ try { } ``` -```cjs -const { createContext, runInContext, constants } = require('node:vm'); - -// Use vm.constants.DONT_CONTEXTIFY to freeze the global object. -const context = createContext(constants.DONT_CONTEXTIFY); -runInContext('Object.freeze(globalThis);', context); -try { - runInContext('bar = 1; bar;', context); -} catch (e) { - console.log(`${e.constructor.name}: ${e.message}`); // ReferenceError: bar is not defined -} -``` - When `vm.constants.DONT_CONTEXTIFY` is used as the `contextObject` argument to [`vm.createContext()`][], the returned object is a proxy-like object to the global object in the newly created context with fewer Node.js-specific quirks. It is reference equal to the `globalThis` value in the new context, can be modified from outside the context, and can be used to access built-ins in the new context directly. -```mjs +```js import { createContext, runInContext, constants } from 'node:vm'; const context = createContext(constants.DONT_CONTEXTIFY); @@ -2153,30 +1801,6 @@ try { } ``` -```cjs -const { createContext, runInContext, constants } = require('node:vm'); - -const context = createContext(constants.DONT_CONTEXTIFY); - -// Returned object is reference equal to globalThis in the new context. -console.log(runInContext('globalThis', context) === context); // true - -// Can be used to access globals in the new context directly. -console.log(context.Array); // [Function: Array] -runInContext('foo = 1;', context); -console.log(context.foo); // 1 -context.bar = 1; -console.log(runInContext('bar;', context)); // 1 - -// Can be frozen and it affects the inner context. -Object.freeze(context); -try { - runInContext('baz = 1; baz;', context); -} catch (e) { - console.log(`${e.constructor.name}: ${e.message}`); // ReferenceError: baz is not defined -} -``` - ## Timeout interactions with asynchronous tasks and Promises `Promise`s and `async function`s can schedule tasks run by the JavaScript @@ -2189,7 +1813,7 @@ For example, the following code executed by `vm.runInNewContext()` with a timeout of 5 milliseconds schedules an infinite loop to run after a promise resolves. The scheduled loop is never interrupted by the timeout: -```mjs +```js import { runInNewContext } from 'node:vm'; function loop() { @@ -2206,27 +1830,10 @@ runInNewContext( console.log('done executing'); ``` -```cjs -const { runInNewContext } = require('node:vm'); - -function loop() { - console.log('entering loop'); - while (1) console.log(Date.now()); -} - -runInNewContext( - 'Promise.resolve().then(() => loop());', - { loop, console }, - { timeout: 5 }, -); -// This is printed *before* 'entering infinite loop' (!) -console.log('done executing'); -``` - This can be addressed by passing `microtaskMode: 'afterEvaluate'` to the code that creates the `Context`: -```mjs +```js import { runInNewContext } from 'node:vm'; function loop() { @@ -2240,20 +1847,6 @@ runInNewContext( ); ``` -```cjs -const { runInNewContext } = require('node:vm'); - -function loop() { - while (1) console.log(Date.now()); -} - -runInNewContext( - 'Promise.resolve().then(() => loop());', - { loop, console }, - { timeout: 5, microtaskMode: 'afterEvaluate' }, -); -``` - In this case, the microtask scheduled through `promise.then()` will be run before returning from `vm.runInNewContext()`, and will be interrupted by the `timeout` functionality. This applies only to code running in a @@ -2283,7 +1876,7 @@ the outer context. When the outer context `await` on the promise, the execution flow of the outer context is disrupted in a surprising way: the log statement is never executed. -```mjs +```js import { createContext, runInContext } from 'node:vm'; const inner_context = createContext({}, { microtaskMode: 'afterEvaluate' }); @@ -2303,28 +1896,6 @@ await inner_promise; console.log('this will NOT be printed'); ``` -```cjs -const { createContext, runInContext } = require('node:vm'); - -// runInContext() returns a Promise created in the inner context. -const inner_context = createContext({}, { microtaskMode: 'afterEvaluate' }); - -(async () => { - const inner_promise = runInContext('Promise.resolve()', inner_context); - - // As part of performing `await`, the JavaScript runtime must enqueue a task - // on the microtask queue of the context where `inner_promise` was created. - // A task is added on the inner microtask queue, but **it will not be run - // automatically**: this task will remain pending indefinitely. - // - // Since the outer microtask queue is empty, execution in the outer module - // falls through, and the log statement below is never executed. - await inner_promise; - - console.log('this will NOT be printed'); -})(); -``` - To successfully share promises between contexts with different microtask queues, it is necessary to ensure that tasks on the inner microtask queue will be run **whenever** the outer context enqueues a task on the inner microtask queue. @@ -2335,7 +1906,7 @@ module using this context. In our example, the normal execution flow can be restored by scheduling a second call to `runInContext()` _before_ `await inner_promise`. -```mjs +```js // Schedule `runInContext()` to manually drain the inner context microtask // queue; it will run after the `await` statement below. setImmediate(() => { @@ -2389,7 +1960,7 @@ be aware that the objects created by modules loaded from the main context are still from the main context and not `instanceof` built-in classes in the new context. -```cjs +```js const { Script, constants } = require('node:vm'); const script = new Script( 'import("node:fs").then(({readFile}) => readFile instanceof Function)', @@ -2400,7 +1971,7 @@ const script = new Script( script.runInNewContext().then(console.log); ``` -```mjs +```js import { Script, constants } from 'node:vm'; const script = new Script( @@ -2414,7 +1985,7 @@ script.runInNewContext().then(console.log); This option also allows the script or function to load user modules: -```mjs +```js import { Script, constants } from 'node:vm'; import { resolve } from 'node:path'; import { writeFileSync } from 'node:fs'; @@ -2442,34 +2013,6 @@ const script = new Script( script.runInThisContext().then(console.log); ``` -```cjs -const { Script, constants } = require('node:vm'); -const { resolve } = require('node:path'); -const { writeFileSync } = require('node:fs'); - -// Write test.js and test.txt to the directory where the current script -// being run is located. -writeFileSync(resolve(__dirname, 'test.mjs'), - 'export const filename = "./test.json";'); -writeFileSync(resolve(__dirname, 'test.json'), - '{"hello": "world"}'); - -// Compile a script that loads test.mjs and then test.json -// as if the script is placed in the same directory. -const script = new Script( - `(async function() { - const { filename } = await import('./test.mjs'); - return import(filename, { with: { type: 'json' } }) - })();`, - { - filename: resolve(__dirname, 'test-with-default.js'), - importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER, - }); - -// { default: { hello: 'world' } } -script.runInThisContext().then(console.log); -``` - There are a few caveats with loading user modules using the default loader from the main context: @@ -2516,7 +2059,7 @@ has the following signature: recommended in order to take advantage of error tracking, and to avoid issues with namespaces that contain `then` function exports. -```mjs +```js // This script must be run with --experimental-vm-modules. import { Script, SyntheticModule } from 'node:vm'; @@ -2535,27 +2078,6 @@ const result = await script.runInThisContext(); console.log(result); // { bar: { hello: 'world' } } ``` -```cjs -// This script must be run with --experimental-vm-modules. -const { Script, SyntheticModule } = require('node:vm'); - -(async function main() { - const script = new Script('import("foo.json", { with: { type: "json" } })', { - async importModuleDynamically(specifier, referrer, importAttributes) { - console.log(specifier); // 'foo.json' - console.log(referrer); // The compiled script - console.log(importAttributes); // { type: 'json' } - const m = new SyntheticModule(['bar'], () => { }); - await m.link(() => { }); - m.setExport('bar', { hello: 'world' }); - return m; - }, - }); - const result = await script.runInThisContext(); - console.log(result); // { bar: { hello: 'world' } } -})(); -``` - [Cyclic Module Record]: https://tc39.es/ecma262/#sec-cyclic-module-records [ECMAScript Module Loader]: esm.md#modules-ecmascript-modules [Evaluate() concrete method]: https://tc39.es/ecma262/#sec-moduleevaluation diff --git a/doc/api/wasi.md b/doc/api/wasi.md index 6f477a765daf..3fb347d4574a 100644 --- a/doc/api/wasi.md +++ b/doc/api/wasi.md @@ -15,7 +15,7 @@ The WASI API provides an implementation of the [WebAssembly System Interface][] specification. WASI gives WebAssembly applications access to the underlying operating system via a collection of POSIX-like functions. -```mjs +```js import { readFile } from 'node:fs/promises'; import { WASI } from 'node:wasi'; import { argv, env } from 'node:process'; @@ -37,31 +37,6 @@ const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject()); wasi.start(instance); ``` -```cjs -const { readFile } = require('node:fs/promises'); -const { WASI } = require('node:wasi'); -const { argv, env } = require('node:process'); -const { join } = require('node:path'); - -const wasi = new WASI({ - version: 'preview1', - args: argv, - env, - preopens: { - '/local': '/some/real/path/that/wasm/can/access', - }, -}); - -(async () => { - const wasm = await WebAssembly.compile( - await readFile(join(__dirname, 'demo.wasm')), - ); - const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject()); - - wasi.start(instance); -})(); -``` - To run the above example, create a new WebAssembly text format file named `demo.wat`: diff --git a/doc/api/webcrypto.md b/doc/api/webcrypto.md index 6e2acacd5854..ad3e2a1f71ca 100644 --- a/doc/api/webcrypto.md +++ b/doc/api/webcrypto.md @@ -453,7 +453,7 @@ This example derives a key from a password using Argon2, if available, or PBKDF2, otherwise; and then encrypts and decrypts some text with it using AES-OCB, if available, and AES-GCM, otherwise. -```mjs +```js const { SubtleCrypto, crypto } = globalThis; const password = 'correct horse battery staple'; diff --git a/doc/api/webstreams.md b/doc/api/webstreams.md index 45e87152b86b..57a54c2b068b 100644 --- a/doc/api/webstreams.md +++ b/doc/api/webstreams.md @@ -37,7 +37,7 @@ This example creates a simple `ReadableStream` that pushes the current `performance.now()` timestamp once every second forever. An async iterable is used to read the data from the stream. -```mjs +```js import { ReadableStream, } from 'node:stream/web'; @@ -63,34 +63,6 @@ for await (const value of stream) console.log(value); ``` -```cjs -const { - ReadableStream, -} = require('node:stream/web'); - -const { - setInterval: every, -} = require('node:timers/promises'); - -const { - performance, -} = require('node:perf_hooks'); - -const SECOND = 1000; - -const stream = new ReadableStream({ - async start(controller) { - for await (const _ of every(SECOND)) - controller.enqueue(performance.now()); - }, -}); - -(async () => { - for await (const value of stream) - console.log(value); -})(); -``` - ### Node.js streams interoperability Node.js streams can be converted to web streams and vice versa via the `toWeb` and `fromWeb` methods present on [`stream.Readable`][], [`stream.Writable`][] and [`stream.Duplex`][] objects. @@ -212,7 +184,7 @@ added: v16.5.0 * `mode` {string} `'byob'` or `undefined` * Returns: {ReadableStreamDefaultReader|ReadableStreamBYOBReader} -```mjs +```js import { ReadableStream } from 'node:stream/web'; const stream = new ReadableStream(); @@ -222,16 +194,6 @@ const reader = stream.getReader(); console.log(await reader.read()); ``` -```cjs -const { ReadableStream } = require('node:stream/web'); - -const stream = new ReadableStream(); - -const reader = stream.getReader(); - -reader.read().then(console.log); -``` - Causes the `readableStream.locked` to be `true`. #### `readableStream.pipeThrough(transform[, options])` @@ -267,7 +229,7 @@ pipeline is configured, `transform.readable` is returned. Causes the `readableStream.locked` to be `true` while the pipe operation is active. -```mjs +```js import { ReadableStream, TransformStream, @@ -292,33 +254,6 @@ for await (const chunk of transformedStream) // Prints: A ``` -```cjs -const { - ReadableStream, - TransformStream, -} = require('node:stream/web'); - -const stream = new ReadableStream({ - start(controller) { - controller.enqueue('a'); - }, -}); - -const transform = new TransformStream({ - transform(chunk, controller) { - controller.enqueue(chunk.toUpperCase()); - }, -}); - -const transformedStream = stream.pipeThrough(transform); - -(async () => { - for await (const chunk of transformedStream) - console.log(chunk); - // Prints: A -})(); -``` - #### `readableStream.pipeTo(destination[, options])`