From b97a6ce2ef31cb1476c8e25addb91271a1f931c9 Mon Sep 17 00:00:00 2001 From: Huanyi Xie <74809554+xiehuanyi@users.noreply.github.com> Date: Mon, 12 Oct 2026 00:21:58 +0300 Subject: [PATCH 1/2] fix(csv-stringify): preserve caller column definitions --- .../lib/api/normalize_columns.js | 8 +++---- packages/csv-stringify/test/option.columns.js | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/csv-stringify/lib/api/normalize_columns.js b/packages/csv-stringify/lib/api/normalize_columns.js index 53e4b2700..21fe74bcc 100644 --- a/packages/csv-stringify/lib/api/normalize_columns.js +++ b/packages/csv-stringify/lib/api/normalize_columns.js @@ -32,10 +32,10 @@ const normalize_columns = function (columns) { Error('Invalid column definition: property "key" is required'), ]; } - if (column.header === undefined) { - column.header = column.key; - } - newcolumns.push(column); + newcolumns.push({ + ...column, + header: column.header === undefined ? column.key : column.header, + }); } else { return [ Error("Invalid column definition: expect a string or an object"), diff --git a/packages/csv-stringify/test/option.columns.js b/packages/csv-stringify/test/option.columns.js index a83bd1dd1..88db052f8 100644 --- a/packages/csv-stringify/test/option.columns.js +++ b/packages/csv-stringify/test/option.columns.js @@ -1,8 +1,29 @@ import "should"; import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `columns`", function () { describe("definition", function () { + it("accepts frozen column definitions without adding a header", function () { + const column = Object.freeze({ key: "a" }); + const columns = Object.freeze([column]); + stringifySync([{ a: "value" }], { columns, header: true }).should.eql( + "a\nvalue\n", + ); + Object.keys(column).should.eql(["key"]); + }); + + it("does not mutate reusable column definitions", function () { + const column = { key: "a" }; + stringifySync([{ a: "first" }], { columns: [column], header: true }); + column.key = "b"; + stringifySync([{ b: "second" }], { + columns: [column], + header: true, + }).should.eql("b\nsecond\n"); + Object.keys(column).should.eql(["key"]); + }); + it("validates option types", function () { (() => { stringify([], { columns: true }, () => {}); From fcd9de7ab543498590fd88c2bb33b9cb1791338c Mon Sep 17 00:00:00 2001 From: Huanyi Xie <74809554+xiehuanyi@users.noreply.github.com> Date: Mon, 12 Oct 2026 00:36:11 +0300 Subject: [PATCH 2/2] fix(csv-stringify): retain structural column keys --- .../lib/api/normalize_columns.js | 1 + packages/csv-stringify/test/option.columns.js | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/csv-stringify/lib/api/normalize_columns.js b/packages/csv-stringify/lib/api/normalize_columns.js index 21fe74bcc..67722eae5 100644 --- a/packages/csv-stringify/lib/api/normalize_columns.js +++ b/packages/csv-stringify/lib/api/normalize_columns.js @@ -34,6 +34,7 @@ const normalize_columns = function (columns) { } newcolumns.push({ ...column, + key: column.key, header: column.header === undefined ? column.key : column.header, }); } else { diff --git a/packages/csv-stringify/test/option.columns.js b/packages/csv-stringify/test/option.columns.js index 88db052f8..b6894c737 100644 --- a/packages/csv-stringify/test/option.columns.js +++ b/packages/csv-stringify/test/option.columns.js @@ -13,6 +13,28 @@ describe("Option `columns`", function () { Object.keys(column).should.eql(["key"]); }); + const structuralColumns = [ + ["inherited", Object.create({ key: "a" })], + ["non-enumerable", Object.defineProperty({}, "key", { value: "a" })], + [ + "getter", + Object.create({ + get key() { + return "a"; + }, + }), + ], + ]; + for (const [name, column] of structuralColumns) { + it(`preserves a ${name} column key`, function () { + stringifySync([{ a: "value" }], { + columns: [column], + header: true, + }).should.eql("a\nvalue\n"); + Object.keys(column).should.eql([]); + }); + } + it("does not mutate reusable column definitions", function () { const column = { key: "a" }; stringifySync([{ a: "first" }], { columns: [column], header: true });