Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.15.2, 6.1.2
-
-
4c930247e (dev), d7602cb31 (6.5)
Description
Summary
In JSON.stringify implementation, replacer function's this value is not set to a containing object as required by specs (and implemented in all other engines).
Description
Long story short, JSON.stringify takes optional second argument which can be a replacer function. It is supposed to be called for each encountered key-value during serialization. While replacer's second argument is already serialized (so you could just return it), just in case you are not satisfied with default serialization — the original value is still passed in together with the whole object as a value of javascript this.
Expected behavior (Alternatives)
WebKit defines it as follow:
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
MDN defines it as follow:
As a function, it takes two parameters: the key and the value being stringified. The object in which the key was found is provided as the replacer's this parameter.
Actual behavior
Qt/QML V4 engine, however, violates this twice at once:
1. this is set to a new object with a value for an empty ("") key;
2. value on this is the same already toJSON() serialized value as the second argument.
…which is kinda defeats the purpose, and buggy as hell. I wonder, how it happened that no tests exist to check such behavior.
Why I care?
I wanted to serialize Date objects as number of seconds since epoch (because that's how they expect it on server API). Normally, I would set a global replacer function in my HTTP request sending flow:
function objectToApiJsonReplacer(k /*string*/, v /*any*/) { if (this[k] instanceof Date) { return dateToApiFormat(this[k]); } return v; } function dateToApiFormat(date /*Date*/) { return Math.floor(date.getTime() / 1000.0); } JSON.stringify(body, objectToApiJsonReplacer)
It works in browsers and nodejs CLI, but fails miserably in Qt.