Repository: mholt/PapaParse (js)

Issue:
Data corruption in 5.5.1 when streaming data with step function
We recently tried upgrading from 5.4.1 to 5.5.1 and encountered this error

We started seeing `Duplicate headers found and renamed` in the logs and noticed that our data was corrupted.

It seems that instead of deduplicating just the header row, it deduplicates all the data in each row too.

You can reproduce with this file:
```
const Papa = require("papaparse");

const csv = `a,b,c,c
d,d,e,e
d,f,f,g`;

Papa.parse(csv, {
    header: true,
    step: function(results) {
        console.log(results.data);
    },
    complete: function() {
        console.log("Parsing complete");
    }
});
```


In 5.4.1 it outputs the following, correctly deduplicating the extra `c` column
```
{ a: 'd', b: 'd', c: 'e', c_1: 'e' }
{ a: 'd', b: 'f', c: 'f', c_1: 'g' }
Parsing complete
```

In 5.5.1 it outputs the following, incorrectly deduplicating the `d`, `e`, and `f` in the data

```
Duplicate headers found and renamed.
Duplicate headers found and renamed.
{ a: 'd', b: 'd_1', c: 'e', c_1: 'e_1' }
Duplicate headers found and renamed.
{ a: 'd', b: 'f', c: 'f_1', c_1: 'g' }
Parsing complete
```

Pull request description:
Only attempt to parse headers once
Hopefully this is the right way to fix this, I'm not very familiar with this codebase so please advise :) .


fixes #1085 

Patch:
diff --git a/papaparse.js b/papaparse.js
index c1d6334..23513ff 100755
--- a/papaparse.js
+++ b/papaparse.js
@@ -1426,6 +1426,7 @@ License: MIT
 		var fastMode = config.fastMode;
 		var quoteChar;
 		var renamedHeaders = null;
+		var headerParsed = false;
 
 		if (config.quoteChar === undefined || config.quoteChar === null) {
 			quoteChar = '"';
@@ -1741,7 +1742,7 @@ License: MIT
 			/** Returns an object with the results, errors, and meta. */
 			function returnable(stopped)
 			{
-				if (config.header && !baseIndex && data.length)
+				if (config.header && !baseIndex && data.length && !headerParsed)
 				{
 					const result = data[0];
 					const headerCount = {}; // To track the count of each base header
@@ -1781,6 +1782,7 @@ License: MIT
 					if (duplicateHeaders) {
 						console.warn('Duplicate headers found and renamed.');
 					}
+					headerParsed = true;
 				}
 				return {
 					data: data,


Test patch:
diff --git a/tests/test-cases.js b/tests/test-cases.js
index 5eaa943..589a707 100644
--- a/tests/test-cases.js
+++ b/tests/test-cases.js
@@ -2338,6 +2338,22 @@ var CUSTOM_TESTS = [
 			});
 		}
 	},
+	{
+		description: "Data is correctly parsed with steps when there are empty values",
+		expected: [{A: 'a', B: 'b', C: 'c', D: 'd'}, {A: 'a', B: '', C: '', D: ''}],
+		run: function(callback) {
+			var data = [];
+			Papa.parse('A,B,C,D\na,b,c,d\na,,,', {
+				header: true,
+				step: function(results) {
+					data.push(results.data);
+				},
+				complete: function() {
+					callback(data);
+				}
+			});
+		}
+	},
 	{
 		description: "Step is called with the contents of the row",
 		expected: ['A', 'b', 'c'],