lib: add primitive fast path to structuredClone

Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/64190
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Guilherme Araújo authored and GitHub committed 2026-09-20 21:03:24 +00:00
1 parent ada8c5c9f8
commit bfb84d3eb1
3 files changed
+28 -1

No files matched your search

+6 -1
View File
@@ -4,7 +4,7 @@ const common = require('../common.js');
const assert = require('assert');
const bench = common.createBenchmark(main, {
type: ['string', 'object', 'arraybuffer'],
type: ['int', 'string', 'object', 'arraybuffer'],
n: [1e4],
});
@@ -12,6 +12,11 @@ function main({ n, type }) {
const data = [];
switch (type) {
case 'int':
for (let i = 0; i < n; ++i) {
data.push(i);
}
break;
case 'string':
for (let i = 0; i < n; ++i) {
data.push(new Date().toISOString());
+11
View File
@@ -103,6 +103,17 @@ function structuredClone(value, options) {
throw new ERR_MISSING_ARGS('The value argument must be specified');
}
// Fast path: primitives clone to themselves, so skip the native
// serialize/deserialize round-trip when no options were provided.
// Symbols are excluded. they are not cloneable and must throw below.
if (options === undefined &&
(value === null ||
(typeof value !== 'object' &&
typeof value !== 'function' &&
typeof value !== 'symbol'))) {
return value;
}
const idlOptions = webidl.converters.StructuredSerializeOptions(
options,
{
@@ -27,6 +27,17 @@ assert.strictEqual(structuredClone(undefined, null), undefined);
// Transfer can be null or undefined.
assert.strictEqual(structuredClone(undefined, { }), undefined);
// Primitives clone to themselves.
assert.strictEqual(structuredClone(null), null);
assert.strictEqual(structuredClone(1), 1);
assert.strictEqual(structuredClone('x'), 'x');
assert.strictEqual(structuredClone(true), true);
assert.strictEqual(structuredClone(10n), 10n);
// -0 is preserved.
assert.ok(Object.is(structuredClone(-0), -0));
// Symbols are not cloneable and must throw.
assert.throws(() => structuredClone(Symbol()), { name: 'DataCloneError' });
// Transferables or its subclasses should be received with its closest transferable superclass
for (const StreamClass of [ReadableStream, WritableStream, TransformStream]) {
const original = new StreamClass();