From 4992ce29f2f931b84f91019cb7c85ee0ebe3320e Mon Sep 17 00:00:00 2001 From: Yarchik Date: Wed, 17 Jun 2026 15:57:53 +0100 Subject: [PATCH] fix: preserve a trailing hole in sparse arrays `Array.prototype.map` keeps holes, but joining the results drops a trailing one: `[1, ,]` (length 2) was serialized as `[1,]`, which is an array of length 1. So a sparse array ending in a hole came back shorter after `eval`. Append a separator when the last element is a hole to keep the length. --- src/array.ts | 7 ++++++- src/index.spec.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/array.ts b/src/array.ts index 5cd6e38..f129484 100644 --- a/src/array.ts +++ b/src/array.ts @@ -15,6 +15,11 @@ export const arrayToString: ToString = (array: any[], space, next) => { }) .join(space ? ",\n" : ","); + // A trailing hole is dropped by an array literal (`[1,]` has length `1`), so + // append a separator to preserve the array length on the round-trip. + const trailingHole = + array.length > 0 && !(array.length - 1 in array) ? "," : ""; + const eol = space && values ? "\n" : ""; - return `[${eol}${values}${eol}]`; + return `[${eol}${values}${trailingHole}${eol}]`; }; diff --git a/src/index.spec.ts b/src/index.spec.ts index e03d411..73b657e 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -101,6 +101,14 @@ describe("javascript-stringify", () => { describe("arrays", () => { it("should stringify as array shorthand", test([1, 2, 3], "[1,2,3]")); + it("should preserve a trailing hole", testRoundTrip("[1,,]")); + + it("should preserve multiple trailing holes", testRoundTrip("[1,,,]")); + + it("should preserve a leading hole", testRoundTrip("[,1]")); + + it("should preserve an interior hole", testRoundTrip("[1,,3]")); + it( "should indent elements", test([{ x: 10 }], "[\n\t{\n\t\tx: 10\n\t}\n]", "\t"),