From 1ab38f76fb99920207db07ed523070494921c50e Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Mon, 20 Oct 2025 15:38:44 -0600 Subject: [PATCH] fix: allow custom revivers to revive things serialized by buitin reducers --- .changeset/fresh-lights-battle.md | 5 +++++ src/parse.js | 8 +++++++- test/test.js | 22 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 .changeset/fresh-lights-battle.md diff --git a/.changeset/fresh-lights-battle.md b/.changeset/fresh-lights-battle.md new file mode 100644 index 0000000..209eed2 --- /dev/null +++ b/.changeset/fresh-lights-battle.md @@ -0,0 +1,5 @@ +--- +"devalue": patch +--- + +fix: allow custom revivers to revive things serialized by builtin reducers diff --git a/src/parse.js b/src/parse.js index bc089a2..62bb3b6 100644 --- a/src/parse.js +++ b/src/parse.js @@ -60,7 +60,13 @@ export function unflatten(parsed, revivers) { const reviver = revivers?.[type]; if (reviver) { - return (hydrated[index] = reviver(hydrate(value[1]))); + let i = value[1]; + if (typeof i !== 'number') { + // if it's not a number, it was serialized by a builtin reviver + // so we need to munge it into the format expected by a custom reviver + i = values.push(value[1]) - 1; + } + return (hydrated[index] = reviver(hydrate(i))); } switch (type) { diff --git a/test/test.js b/test/test.js index 9997ed0..7058709 100644 --- a/test/test.js +++ b/test/test.js @@ -582,7 +582,27 @@ const fixtures = { assert.equal(obj1.value.bar.value.answer, 42); } } - ])(new Foo({ bar: new Bar({ answer: 42 }) })) + ])(new Foo({ bar: new Bar({ answer: 42 }) })), + + custom_fallback: ((date) => [ + { + name: 'Custom fallback', + value: date, + js: "new Date('')", + json: '[["Date",""]]', + replacer: (value) => value instanceof Date && `new Date('')`, + reducers: { + Date: (value) => value instanceof Date && '', + }, + revivers: { + Date: (value) => new Date(value) + }, + validate: (obj) => { + assert.ok(obj instanceof Date); + assert.ok(isNaN(obj.getDate())); + } + } + ])(new Date('invalid')) }; for (const [name, tests] of Object.entries(fixtures)) {