diff --git a/packages/csv-parse/lib/api/index.js b/packages/csv-parse/lib/api/index.js index ca97838cd..38e8fa759 100644 --- a/packages/csv-parse/lib/api/index.js +++ b/packages/csv-parse/lib/api/index.js @@ -415,9 +415,10 @@ const transform = function (original_options = {}) { if (this.state.commenting === false) { if ( max_record_size !== 0 && + this.state.recordHasError === false && this.state.record_length + this.state.field.length > max_record_size ) { - return this.__error( + const err = this.__error( new CsvError( "CSV_MAX_RECORD_SIZE", [ @@ -430,6 +431,7 @@ const transform = function (original_options = {}) { this.__infoField(), ), ); + if (err !== undefined) return err; } } const lappend = @@ -442,18 +444,21 @@ const transform = function (original_options = {}) { if (lappend === true && rappend === true) { this.state.field.append(chr); } else if (rtrim === true && !this.__isCharTrimable(buf, pos)) { - return this.__error( - new CsvError( - "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE", - [ - "Invalid Closing Quote:", - "found non trimable byte after quote", - `at line ${this.info.lines}`, - ], - this.options, - this.__infoField(), - ), - ); + if (this.state.recordHasError === false) { + const err = this.__error( + new CsvError( + "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE", + [ + "Invalid Closing Quote:", + "found non trimable byte after quote", + `at line ${this.info.lines}`, + ], + this.options, + this.__infoField(), + ), + ); + if (err !== undefined) return err; + } } else { if (lappend === false) { pos += this.__isCharTrimable(buf, pos) - 1; diff --git a/packages/csv-parse/test/option.skip_records_with_error.ts b/packages/csv-parse/test/option.skip_records_with_error.ts index 1389ff7e7..aecf99eab 100644 --- a/packages/csv-parse/test/option.skip_records_with_error.ts +++ b/packages/csv-parse/test/option.skip_records_with_error.ts @@ -159,6 +159,72 @@ describe("Option `skip_records_with_error`", function () { parser.end(); }); + it('handle "CSV_MAX_RECORD_SIZE"', function (next) { + const errors: CsvError[] = []; + const parser = parse( + { max_record_size: 5, skip_records_with_error: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["a", "b"], + ["c", "d"], + ["e", "f"], + ]); + assert_error(errors, [ + { + message: + "Max Record Size: record exceed the maximum number of tolerated bytes of 5 at line 2", + code: "CSV_MAX_RECORD_SIZE", + }, + ]); + errors.length.should.eql(1); + next(); + }, + ); + parser.on("skip", (err) => { + errors.push(err); + }); + // Split the oversized field across writes + parser.write("a,b\n12"); + parser.write("3456789,0\nc,d\n"); + parser.write("e,f\n"); + parser.end(); + }); + + it('handle "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE"', function (next) { + const errors: CsvError[] = []; + const parser = parse( + { rtrim: true, skip_records_with_error: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["a", "b"], + ["c", "d"], + ["e", "f"], + ]); + assert_error(errors, [ + { + message: + "Invalid Closing Quote: found non trimable byte after quote at line 2", + code: "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE", + }, + ]); + errors.length.should.eql(1); + next(); + }, + ); + parser.on("skip", (err) => { + errors.push(err); + }); + parser.write(dedent` + a,b + "1" xx,2 + c,d + e,f + `); + parser.end(); + }); + describe("with `bom` option", function () { it('handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" with bom (fix #411)', function (next) { let errors = 0;