From 689fa7e481ac61e4e01228f689aa45fc4a4696a8 Mon Sep 17 00:00:00 2001 From: kirisue <100792373+kirisue@users.noreply.github.com> Date: Sat, 26 Sep 2026 11:05:09 -0600 Subject: [PATCH 1/3] fix(stringify): reject invalid values in cast option objects --- packages/csv-stringify/lib/api/index.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/csv-stringify/lib/api/index.js b/packages/csv-stringify/lib/api/index.js index 4f932fb3..1fb77be2 100644 --- a/packages/csv-stringify/lib/api/index.js +++ b/packages/csv-stringify/lib/api/index.js @@ -161,12 +161,11 @@ const stringifier = function (options, state, info) { value !== undefined && value !== null ) { - if (err) - return [ - Error( - `Invalid Casting Value: returned value must return a string, null or undefined, got ${JSON.stringify(value)}`, - ), - ]; + return [ + Error( + `Invalid Casting Value: returned value must return a string, null or undefined, got ${JSON.stringify(value)}`, + ), + ]; } // Merge global options with the ones returned by cast options = { ...this.options, ...options }; From 0851ae5b424f312dc0ba7b1fb0b174678bf20e7a Mon Sep 17 00:00:00 2001 From: kirisue <100792373+kirisue@users.noreply.github.com> Date: Sat, 26 Sep 2026 11:06:34 -0600 Subject: [PATCH 2/3] test(stringify): cover invalid values in cast options --- packages/csv-stringify/test/option.cast.js | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/csv-stringify/test/option.cast.js b/packages/csv-stringify/test/option.cast.js index 643c3c24..de27e369 100644 --- a/packages/csv-stringify/test/option.cast.js +++ b/packages/csv-stringify/test/option.cast.js @@ -1,5 +1,7 @@ import "should"; +import assert from "node:assert"; import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `cast`", function () { describe("udf", function () { @@ -22,6 +24,49 @@ describe("Option `cast`", function () { }); describe("info object", function () { + for (const value of [0, false]) { + const message = `Invalid Casting Value: returned value must return a string, null or undefined, got ${JSON.stringify(value)}`; + + it(`reject invalid value ${JSON.stringify(value)} in the callback API`, function (next) { + stringify( + [["input"]], + { cast: { string: () => ({ value }) } }, + (err) => { + if (!err) + return next(Error("Expected an invalid casting value error")); + err.message.should.eql(message); + next(); + }, + ); + }); + + it(`reject invalid value ${JSON.stringify(value)} in the sync API`, function () { + assert.throws( + () => + stringifySync([["input"]], { cast: { string: () => ({ value }) } }), + { message }, + ); + }); + } + + it("accept string, null and undefined values in cast options", function (next) { + stringify( + [["empty", "null", "undefined", "text"]], + { + cast: { + string: (value, context) => ({ + value: ["", null, undefined, "text"][context.index], + }), + }, + }, + (err, data) => { + if (err) return next(err); + data.should.eql(",,,text\n"); + next(); + }, + ); + }); + it("validate and normalize local options", function (next) { stringify( [["invalid cast"]], From 44f53d8c6877e883987370d914a34befffa7fc76 Mon Sep 17 00:00:00 2001 From: David Worms Date: Mon, 28 Sep 2026 21:58:44 +0200 Subject: [PATCH 3/3] test(csv-parse): minor organisation (cherry picked from commit 24ce50d071d9e2cd023a53d3968e819f69b9a309) --- packages/csv-stringify/test/option.cast.js | 27 +++------------------- packages/csv-stringify/test/option.cast.ts | 18 +++++++++++++++ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/packages/csv-stringify/test/option.cast.js b/packages/csv-stringify/test/option.cast.js index de27e369..83fcef78 100644 --- a/packages/csv-stringify/test/option.cast.js +++ b/packages/csv-stringify/test/option.cast.js @@ -1,5 +1,4 @@ import "should"; -import assert from "node:assert"; import { stringify } from "../lib/index.js"; import { stringify as stringifySync } from "../lib/sync.js"; @@ -41,32 +40,12 @@ describe("Option `cast`", function () { }); it(`reject invalid value ${JSON.stringify(value)} in the sync API`, function () { - assert.throws( - () => - stringifySync([["input"]], { cast: { string: () => ({ value }) } }), - { message }, - ); + (function () { + stringifySync([["input"]], { cast: { string: () => ({ value }) } }); + }).should.throw({ message }); }); } - it("accept string, null and undefined values in cast options", function (next) { - stringify( - [["empty", "null", "undefined", "text"]], - { - cast: { - string: (value, context) => ({ - value: ["", null, undefined, "text"][context.index], - }), - }, - }, - (err, data) => { - if (err) return next(err); - data.should.eql(",,,text\n"); - next(); - }, - ); - }); - it("validate and normalize local options", function (next) { stringify( [["invalid cast"]], diff --git a/packages/csv-stringify/test/option.cast.ts b/packages/csv-stringify/test/option.cast.ts index 56ea047e..5d27be58 100644 --- a/packages/csv-stringify/test/option.cast.ts +++ b/packages/csv-stringify/test/option.cast.ts @@ -195,6 +195,24 @@ describe("Option `cast`", function () { }); describe("info object", function () { + it("accept string, null and undefined values in cast options", function (next) { + stringify( + [["empty", "null", "undefined", "text"]], + { + cast: { + string: (value, context) => ({ + value: ["", null, undefined, "text"][context.index], + }), + }, + }, + (err, data) => { + if (err) return next(err); + data.should.eql(",,,text\n"); + next(); + }, + ); + }); + it("preserves a reused cast result", function (next) { const result = { value: "shared", quoted: true }; stringify(