-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Unknown
-
None
-
Affects Version/s: 7.2.0
-
Component/s: Extended JSON, js-bson
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Description
The type signature of the EJSON.stringify() function allows parameter combinations that don't work as expected. Specifically, when options are passed as the second parameter and space as the third parameter, the space argument is ignored.
Problem
The current type signature of stringify is:
function stringify( value: any, replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | EJSONSerializeOptions, space?: string | number, options?: EJSONSerializeOptions ): string
This signature allows a call like:
EJSON.stringify(object, { relaxed: false }, 2)
which is used by this in tests within js-bson test/bench/etc/generate_documents.ts
Current Behavior
With this call, the following happens:
{ relaxed: false }
is passed as the replacer parameter
2
is passed as the space parameter
The code detects that replacer is an object (but not an array) and treats it as options
In doing so, space is reset to 0, causing the 2 to be ignored
Relevant code in src/extended_json.ts:484-488:
if (replacer != null && typeof replacer === 'object' && !Array.isArray(replacer)) { options = replacer; replacer = undefined; space = 0; // <-- space is ignored! }
Expected Behavior
The call
EJSON.stringify(object, { relaxed: false }, 2)
should either:
Option 1: Throw an error or be rejected by the TypeScript compiler
Option 2: Apply the options correctly AND respect the space value of 2
Reproduction
import { EJSON, Int32 } from 'bson'; const doc = { int32: new Int32(10) }; // This variant works as expected: console.log(EJSON.stringify(doc, undefined, 2)); // Output: { // "int32": 10 // } // This variant does NOT work as expected: console.log(EJSON.stringify(doc, { relaxed: false }, 2)); // Expected output: { // "int32": { // "$numberInt": "10" // } // } // Actual output: {"int32":{"$numberInt":"10"}} // (space is ignored)