From dfe9ae28b13de662859fbf25121cffac1f604fc5 Mon Sep 17 00:00:00 2001 From: Henrik Blum Date: Tue, 3 Mar 2026 15:53:30 +0100 Subject: [PATCH] fix: correct prePush ordering for ReadableString in object properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a ReadableString (created from a Readable stream) appeared as a non-first property in an object, _push() would prepend prePush (the opening quote) before the objectItem prefix (e.g. ',"key":'), producing invalid JSON like {"key":"value"","data":hello"}. Fix: separate the objectItem prefix from the data, so that prePush is inserted between the prefix and data rather than before the prefix. Before: '",key:value' — quote lands before comma After: ',key:"value' — quote lands after colon, before value Added two test cases covering ReadableStream values as non-first object properties. --- src/JsonStreamStringify.ts | 10 ++++++---- test-src/JsonStreamStringify.spec.ts | 11 +++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/JsonStreamStringify.ts b/src/JsonStreamStringify.ts index 971e63e..3f66975 100644 --- a/src/JsonStreamStringify.ts +++ b/src/JsonStreamStringify.ts @@ -454,12 +454,14 @@ export class JsonStreamStringify extends Readable { /** if set, this string will be prepended to the next _push call, if the call output is not empty, and set to undefined */ prePush?: string; private _push(data) { - const out = (this.objectItem ? this.objectItem.write() : '') + data; - if (this.prePush && out.length) { - this.buffer += this.prePush; + const prefix = this.objectItem ? this.objectItem.write() : ''; + if (this.prePush && (prefix.length || data.length)) { + this.buffer += prefix + this.prePush; this.prePush = undefined; + } else { + this.buffer += prefix; } - this.buffer += out; + this.buffer += data; if (this.buffer.length >= this.bufferSize) { this.pushCalled = !this.push(this.buffer); this.buffer = ''; diff --git a/test-src/JsonStreamStringify.spec.ts b/test-src/JsonStreamStringify.spec.ts index ef92614..5f31480 100644 --- a/test-src/JsonStreamStringify.spec.ts +++ b/test-src/JsonStreamStringify.spec.ts @@ -274,6 +274,17 @@ describe('JsonStreamStringify', function () { a: readableStream(1, 2, 3), }, '{"a":[1,2,3]}')); + it('{key:"value",data:readableStream("hello")} should be {"key":"value","data":"hello"}', createTest({ + key: 'value', + data: readableStream('hello'), + }, '{"key":"value","data":"hello"}')); + + it('{a:"b",c:readableStream("d"),e:"f"} should be {"a":"b","c":"d","e":"f"}', createTest({ + a: 'b', + c: readableStream('d'), + e: 'f', + }, '{"a":"b","c":"d","e":"f"}')); + it('readableStream(\'a\', \'b\', \'c\') should be "abc"', createTest(readableStream('a', 'b', 'c'), '"abc"')); it('readableStream(\'a\', \'b\', \'c\') should be "abc"', () => {