diff options
| author | Ivan Tkachenko <me@ratijas.tk> | 2023-02-20 03:30:37 +0300 |
|---|---|---|
| committer | Ivan Tkachenko <me@ratijas.tk> | 2023-02-22 18:21:09 +0300 |
| commit | 4c930247e67ecad383aa7e8d9a3308b38629bef8 (patch) | |
| tree | 4aca9540a12fbd01f7a57db1232bef562134d8e2 /src/qml/jsruntime/qv4jsonobject.cpp | |
| parent | c769e1a8db9a5762bb80cbc34473ec48a670a038 (diff) | |
Set correct `this` value in JSON.stringify replacer scope
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`.
Sadly, there is no test in the whole ECMA test suite to catch this bug.
This is quite a breaking change for code which already uses Qt-specific
workarounds, so it would be better not to cherry-pick it as a hot-fix
onto existing (released) branches.
Sample use case: serialize dates as a number of seconds since epoch.
function replacer(k, v) {
if (this[k] instanceof Date) {
return Math.floor(this[k].getTime() / 1000.0);
}
return v;
}
const str = JSON.stringify(obj, replacer);
[ChangeLog][QML][Important Behavior Changes] Set correct `this` value in
JSON.stringify replacer scope, so that the value for current key in
current object is no longer pre-stringified, and can actually be used to
implement custom object serialization logic.
Fixes: QTBUG-95324
Pick-to: 6.5
Change-Id: I618a533e8eba7999d5416aca14f4971093a83f7a
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4jsonobject.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4jsonobject.cpp | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 4f46e605af..7bf7cda02f 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -695,12 +695,18 @@ QString Stringify::Str(const QString &key, const Value &v) } if (replacerFunction) { - ScopedObject holder(scope, v4->newObject()); - holder->put(scope.engine->id_empty(), value); JSCallArguments jsCallData(scope, 2); jsCallData.args[0] = v4->newString(key); jsCallData.args[1] = value; - *jsCallData.thisObject = holder; + + if (stack.isEmpty()) { + ScopedObject holder(scope, v4->newObject()); + holder->put(scope.engine->id_empty(), v); + *jsCallData.thisObject = holder; + } else { + *jsCallData.thisObject = stack.top(); + } + value = replacerFunction->call(jsCallData); if (v4->hasException) return QString(); |
