diff --git a/src/turbo-stream.spec.ts b/src/turbo-stream.spec.ts index 78e0241..a60a827 100644 --- a/src/turbo-stream.spec.ts +++ b/src/turbo-stream.spec.ts @@ -120,6 +120,15 @@ test("should encode and decode Map", async () => { expect(output).toEqual(input); }); +test("should preserve Map entry order", async () => { + const input = new Map([ + ["foo", "bar"], + ["baz", "qux"], + ]); + const output = await quickDecode(encode(input)); + expect([...output as Map]).toEqual([...input]) +}) + test("should encode and decode empty Map", async () => { const input = new Map(); const output = await quickDecode(encode(input)); @@ -132,6 +141,12 @@ test("should encode and decode Set", async () => { expect(output).toEqual(input); }); +test("should preserve Set entry order", async () => { + const input = new Set(["foo", "bar"]); + const output = await quickDecode(encode(input)); + expect([...output as Set]).toEqual([...input]); +}) + test("should encode and decode empty Set", async () => { const input = new Set(); const output = await quickDecode(encode(input)); diff --git a/src/unflatten.ts b/src/unflatten.ts index 5dbb7b2..ca41de9 100644 --- a/src/unflatten.ts +++ b/src/unflatten.ts @@ -117,7 +117,11 @@ function hydrate(this: ThisDecode, index: number): any { case TYPE_SET: const newSet = new Set(); hydrated[index] = newSet; - for (let i = 1; i < value.length; i++) + // Going through the entries from back to front, because the postRun + // callbacks run in reverse (from last item to first) + // This results in a Set with its item order mirrored if we visit the + // first item first. + for (let i = value.length - 1; i >= 1; i --) stack.push([ value[i], (v) => { @@ -129,7 +133,11 @@ function hydrate(this: ThisDecode, index: number): any { case TYPE_MAP: const map = new Map(); hydrated[index] = map; - for (let i = 1; i < value.length; i += 2) { + // Going through the entries from back to front, because the postRun + // callbacks run in reverse (from last item to first) + // This results in a Map with its item order mirrored if we visit the + // first item first. + for (let i = value.length - 2; i >= 1; i -= 2) { const r: any[] = []; stack.push([ value[i + 1],