Skip to content

stringifyAsync: a promise resolving to undefined, NaN, -0 or Infinity inside an object parses back as -1, -3, -6 or -4 #211

Open

Description

@DRMacIver

undefined, NaN, -0 and Infinity round-trip through stringify/parse, but when they are the resolved values of promises inside an object passed to stringifyAsync, they come back as the numbers -1, -3, -6 and -4; a promise at the root round-trips:

import { stringify, stringifyAsync, parse } from "devalue";

const plain = { a: undefined, b: [NaN, -0, Infinity] };
const promised = {
  a: Promise.resolve(undefined),
  b: [Promise.resolve(NaN), Promise.resolve(-0), Promise.resolve(Infinity)],
};

const s = stringify(plain);
const t = await stringifyAsync(promised);
console.log(s, "->", parse(s));
console.log(t, "->", parse(t));

const r = await stringifyAsync(Promise.resolve(undefined));
console.log(r, "->", parse(r));

Output:

[{"a":-1,"b":1},[-3,-6,-4]] -> { a: undefined, b: [ NaN, -0, Infinity ] }
[{"a":1,"b":2},-1,[3,4,5],-3,-6,-4] -> { a: -1, b: [ -3, -6, -4 ] }
-1 -> undefined

The promised values come back as the numbers -1, -3, -6 and -4, and neither stringifyAsync nor parse reports an error. A promise of undefined at the root (third line) round-trips correctly; it is only when the promise sits inside an object or array that its resolved value is replaced by a number. The README says of stringifyAsync that "the output format is identical to stringify, so parse and unflatten work unchanged", so I expected the second line to parse to the same value as the first.

Tested on devalue 6.0.0 from npm and on current main (80e75e7, the 6.0.0 release commit), with Node 26.8.1.

BTW, this was found by an automated program that writes property-based tests for various open source projects using hegel (but it has been reviewed by hand before reporting). We've also potentially found (but not yet hand validated) 6 other bugs in devalue. You can see the tests at https://github.com/hegeldev/hegel-zoo/tree/main/targets/typescript/devalue. Let us know if you would like us to file the other bugs found and/or contribute the tests. NB the tests are currently LLM generated and probably not yet suitable for inclusion as is, but we're happy to help get them into a better state if you want them.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions