diff --git a/src/turbo-stream.spec.ts b/src/turbo-stream.spec.ts index 8a6244f..882b767 100644 --- a/src/turbo-stream.spec.ts +++ b/src/turbo-stream.spec.ts @@ -419,6 +419,38 @@ test("should encode and decode objects with multiple promises resolving to the s expect(Array.from(encoded.matchAll(/"baz"/g))).toHaveLength(1); }); +test("should encode and decode objects with reused values", async () => { + const input = { + foo: Promise.resolve({ use: 'baz' }), + bar: Promise.resolve('baz'), + data: Promise.resolve({ quux: 'quux' }), + }; + + const decoded = await decode(encode(input)); + const value = decoded.value as typeof input; + expect(value).toEqual({ + foo: expect.any(Promise), + bar: expect.any(Promise), + data: expect.any(Promise), + }); + expect(await value.foo).toEqual(await input.foo); + expect(await value.bar).toEqual(await input.bar); + expect(await value.data).toEqual(await input.data); + + // Ensure we aren't duplicating values in the stream + let encoded = ""; + const stream = encode(input); + await stream.pipeThrough(new TextDecoderStream()).pipeTo( + new WritableStream({ + write(chunk) { + encoded += chunk; + }, + }) + ); + expect(Array.from(encoded.matchAll(/"baz"/g))).toHaveLength(1); + await decoded.done; +}); + test("should encode and decode objects with multiple promises rejecting to the same values", async () => { const err = new Error("baz"); const input = { diff --git a/src/turbo-stream.ts b/src/turbo-stream.ts index 3661a4f..626a59f 100644 --- a/src/turbo-stream.ts +++ b/src/turbo-stream.ts @@ -181,6 +181,8 @@ export function encode( `${TYPE_PROMISE}${deferredId}:[["${TYPE_PREVIOUS_RESOLVED}",${id[0]}]]\n` ) ); + encoder.index++; + lastSentIndex++; } else if (id < 0) { controller.enqueue( textEncoder.encode(`${TYPE_PROMISE}${deferredId}:${id}\n`) @@ -213,6 +215,8 @@ export function encode( `${TYPE_ERROR}${deferredId}:[["${TYPE_PREVIOUS_RESOLVED}",${id[0]}]]\n` ) ); + encoder.index++; + lastSentIndex++; } else if (id < 0) { controller.enqueue( textEncoder.encode(`${TYPE_ERROR}${deferredId}:${id}\n`)