Skip to solution
hardDSA

How does V8 Array copy-on-write optimization work for `toSorted`/`toReversed`/`toSpliced`/`with`?

224 views
01

Understand the problem

Question presented to candidate: "V8 has a well-known copy-on-write optimization for JavaScript arrays. Do the new ES2023 methods toSorted, toReversed, toSpliced, and with take advantage of that COW sharing to make their copy lazy, or do they always eagerly copy? Show me, do not just tell me."

What a strong answer should cover:

  • V8 genuinely has a copy-on-write (COW) backing-store optimization for arrays: when an array's element storage is marked COW (most commonly, a freshly-evaluated array literal), a shallow clone via slice() or spread [...arr] can share the exact same backing FixedArray instead of allocating a new one — verified directly by inspecting V8 internals.
  • The four ES2023 change-array-by-copy methods do NOT participate in that lazy sharing. Each one allocates a brand-new, non-COW backing store immediately at call time, verified directly — even with(index, value), which only changes a single element, does not share the other unchanged elements.
  • This makes sense once the two questions are separated: COW sharing is about WHEN a copy physically happens for methods that produce an array that starts out identical to the source. toSorted/toReversed/toSpliced/with all produce arrays that are already structurally different the moment they return, so there is nothing identical left to lazily share.
  • These four methods should be budgeted as a genuine O(n) allocation on every call, confirmed by direct benchmark: with() on a 20,000-element array costs essentially the same as a manual spread-then-assign copy.
  • Contrast with slice()/spread, which really can be near-free when the source is COW-eligible, verified via a real backing-store-address comparison before and after the call.

Clarifying questions expected:

  • "Are we talking about V8 specifically, or does the ECMAScript spec itself mandate a particular allocation strategy?" — the spec only mandates the observable result (an independent array); COW sharing is a pure V8 implementation detail other engines are free to implement differently.
  • "Does the source array's own origin matter — a literal versus something built with Array.from or map?" — worth naming that COW eligibility in V8 is tied to how the source array itself was created, not a universal property of every array.

Code / implementation expected: Yes — direct inspection of V8's internal backing-store pointers via --allow-natives-syntax and %DebugPrint, not a description from memory, plus a real benchmark comparing native with() against a manual copy.

v8arrayperformance
02

Attempt it yourself

Sketch your approach before reading the solution — that's what interviews test.

Nudge consolestandby

Stuck? Beam a request up — the console returns a conceptual nudge that guides your logic without spoiling the implementation.

03

Study the solution

Target Audience: Engineers preparing for JavaScript engine-internals interview questions. Difficulty: Hard

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. The V8-internals findings below were captured by running node with the --allow

Solution ready — 2 min read

Classified // press E to declassify

04

Run the code

JSCorrectness + real benchmark: none of the four methods mutate the source, and with() costs the same as a manual copy (run directly)
Reference: direct V8 internals proof via --allow-natives-syntax and %DebugPrint (run with: node --allow-natives-syntax file.js -- not runnable in the browser playground, this flag is Node/V8-CLI-only)
function backingStoreOf(label, arr) {
  console.log(`
---- ${label} ----`);
  eval("%DebugPrint(arr)"); // prints the real internal layout, including the backing FixedArray's address
}

const literalSrc = [3, 1, 2];
backingStoreOf("source (array literal)", literalSrc);
backingStoreOf("toSorted() result", literalSrc.toSorted());

const literalSrc2 = [1, 2, 3];
backingStoreOf("source (array literal)", literalSrc2);
backingStoreOf("slice() result", literalSrc2.slice());

// Run this file with: node --allow-natives-syntax this-file.js
// Then compare the "elements:" line's 0x... address and the [COW] tag
// between each "source" print and its corresponding result print.
05

Join the discussion

Discussion (0)

Sign in to join the discussion.

No responses yet. Be the first to share what you think.

Transmission complete // awaiting log

KEEP THE
STREAK ALIVE.

Dossier 159 of 165 decoded in the JavaScript track. One more won't hurt.

Back to track