Problem
assert.deepStrictEqual on two 20,000-element arrays with 500 differing entries produces a 4,504-line message in Home and a 55-line one in pinned Bun. The unchanged upstream js/node/assert/assert-typedarray-deepequal.test.ts asserts the message stays under 100 lines and does not mention tail elements, so Home fails it 44 pass / 1 fail against Bun's 45 / 0.
What each runtime does
internal/assert/assertion_error.ts has two paths. The normal one runs myersDiff and prints a real diff; when myersDiff throws, the catch falls back to a 50-line preview with an empty header and skipped = true.
The message shapes show they take different branches:
| line 2 | line 3 | lines | contains 19960 | |
|---|---|---|---|---|
| Bun | "" | ... Skipped lines | 55 | no |
| Home | + actual - expected | ... Skipped lines | 4504 | yes |
Bun's empty header is the fallback branch — its myersDiff throws. Home's completes and prints the full diff.
This is not a source divergence
Both runtimes execute the same JavaScript. build-support/bundle-native-modules.ts carries an explicit ownership manifest:
const ownedModules = ['node/url.ts', 'node/worker_threads.ts']Everything else is served verbatim from the linked build's InternalModuleRegistryConstants.h, so internal/assert/assertion_error and internal/assert/myers_diff are Bun's own bytes in both. (The mirrored copies under packages/runtime/upstream/src/js/ are reference source and are not compiled — editing them changes nothing. I confirmed that by patching assertion_error.ts, rebuilding, and measuring no behavioural change; the edit was reverted.)
So the difference is in the engine or in what the diff is handed, not in the port:
myersDiffthrowing in Bun is most likely an allocation or recursion limit reached on a 20,000-line input. Whatever raises it in Bun does not fire in Home, so Home completes an O(ND) diff that upstream treats as unbounded.- The other candidate is
util.inspecthanding the two runtimes differently shaped input.
Worth settling which before changing anything: if Home simply has a higher effective limit, matching upstream by lowering a limit would be the wrong fix, and the right one is an explicit size guard in the diff path.
Reproduction
// adiff.mjs
import assert from "node:assert";
const length = 20000;
const actual = Array.from({ length }, (_, i) => i);
const expected = actual.slice();
for (let i = 0; i < length; i += 40) expected[i] = -1;
try { assert.deepStrictEqual(actual, expected); } catch (e) {
console.log(e.message.split("\n").length, e.message.includes("19960"));
}Home prints 4504 true; ~/Code/bun/build/release/bun run adiff.mjs prints 55 false.
Acceptance criteria
- The unchanged upstream file passes 45 / 0, matching the pinned Bun control.
- The bound comes from the same mechanism upstream uses, not a special case for typed arrays or for this input size.
- No corpus file, fixture, assertion or workload is edited.
Broader note
The two-module ownership manifest means JS-level builtin fixes generally cannot be made in Home's tree today — a gap whose fix lives in internal/* or most of node/* needs that module added to ownedModules (and its ABI validated) before any source change has effect. That is worth knowing before picking up any of the remaining js/node failures in #621.
Parent parity tracker: #66