From d7cb2a5b1b7927a6314a4a40ce6f31628db996d4 Mon Sep 17 00:00:00 2001 From: nk-batman21 Date: Tue, 20 Oct 2026 11:31:40 +0700 Subject: [PATCH] fix(csv-parse): refresh trim state after BOM detection --- packages/csv-parse/lib/api/index.js | 10 +++++++ packages/csv-parse/test/option.encoding.ts | 34 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/packages/csv-parse/lib/api/index.js b/packages/csv-parse/lib/api/index.js index ca97838cd..b49b20516 100644 --- a/packages/csv-parse/lib/api/index.js +++ b/packages/csv-parse/lib/api/index.js @@ -164,6 +164,16 @@ const transform = function (original_options = {}) { for (const key in options) { this.options[key] = options[key]; } + // Refresh buffers and lookahead sizes derived from the encoding. + const state = init_state(options); + for (const key of [ + "timchars", + "timcharFirstBytes", + "needMoreDataSize", + "recordDelimiterMaxLength", + ]) { + this.state[key] = state[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; diff --git a/packages/csv-parse/test/option.encoding.ts b/packages/csv-parse/test/option.encoding.ts index 1d3c53491..c368d3421 100644 --- a/packages/csv-parse/test/option.encoding.ts +++ b/packages/csv-parse/test/option.encoding.ts @@ -1,5 +1,6 @@ import "should"; import { parse } from "../lib/index.js"; +import { parse as parseSync } from "../lib/sync.js"; describe("Option `encoding`", function () { describe("validation & normalization", function () { @@ -64,6 +65,39 @@ describe("Option `encoding`", function () { }); describe("with BOM", function () { + for (const option of ["trim", "ltrim"] as const) { + for (const whitespace of [" ", "\u00a0"]) { + it(`utf16le auto detected with ${option} and whitespace ${JSON.stringify(whitespace)} in sync API`, function () { + const input = Buffer.from( + `\ufeff${whitespace}a,${whitespace}b`, + "utf16le", + ); + parseSync(input, { bom: true, [option]: true }).should.eql([ + ["a", "b"], + ]); + }); + + it(`utf16le auto detected with ${option} and whitespace ${JSON.stringify(whitespace)} across byte-sized writes`, function (next) { + const input = Buffer.from( + `\ufeff${whitespace}a,${whitespace}b`, + "utf16le", + ); + const parser = parse( + { bom: true, [option]: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([["a", "b"]]); + next(); + }, + ); + for (let i = 0; i < input.length; i++) { + parser.write(input.subarray(i, i + 1)); + } + parser.end(); + }); + } + } + it("utf16le auto detected", function (next) { const parser = parse( { bom: true, encoding: "utf16le" },