aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4stringobject.cpp
diff options
context:
space:
mode:
authorLuca Di Sera <luca.disera@qt.io>2024-06-21 15:39:07 +0200
committerLuca Di Sera <luca.disera@qt.io>2024-06-28 11:05:05 +0200
commitdf684931c96b174033730971ec5cb63a03f01483 (patch)
tree48a920345f7d50af732953615071d8a25d2c7a03 /src/qml/jsruntime/qv4stringobject.cpp
parent4506b936b4dcaeb42d91e3b25789ec91d13b584e (diff)
QJSEngine: Treat empty string literals as non-null, empty QStrings
When evaluating a script with `QJSEngine` an empty string literal will be treated as a null string. For example evaluating `""` will produce a string-holding `QJSValue` that produces a null `QString` when the string value is extracted. This is in contrast with the general behavior of `QJSValue`, where directly constructing a `QJSValue` from a null or empty `QString` will produce a `QString` value that is empty but not null. When the engine reads the literal from the string table, it specifically returns a null `QString` for zero-sized strings. This null `QString` will then propagate its null-ness when used to allocate a string, which will in turn propagate all the way up to the returned `QJSValue` that holds the produced string. To align the behavior of a string-holding `QJSValue` produced from the engine to the behavior of a `QJSValue` directly built from a `QString`, the specialized code that produced the original null `QString` was removed, so that an empty string is constructed instead. This partially amends ff0857541d5d391c7c03cce5893b41dd9b35e7fa, which introduced the specialized construction of the null string in relation to another issue. The change was already partially amended in 86379e265e19a078545306d93c59b0d92c04920a, where some of the additional behavior introduced by the original patch was rendered unnecessary by changes in Qt itself. The null string behavior for empty literals that was added as part of the original patch was partly tied to the code removed in the first amendment and is not expected to break the original case anymore due to the changes in the context around it. A test case was added to `tst_QJSEngine` to test the behavior. The test case that was originally added in ff0857541d5d391c7c03cce5893b41dd9b35e7fa, which tested that empty string literals were treated as nulls was modified to align to the new behavior of non-null, empty strings. A slight change was made to the implementation for the String prototype `startsWith` method to adapt it to the changes which exposed a previously existing bug. When `startsWith` was given a position as part of its second argument, this would have been retrieved as a double and then directly passed to `QStringView::mid`, producing an implicit conversion to `qsizetype`. For values that `qsizetype` cannot hold, the result can be different between platforms. In particular, this showed on a ecmascript compliancy test that would now fail on ARM mac platforms. The test would pass infinity as the second argument and an empty literal string as the first in a call to `startsWith`, which, by the spec description should return true. In general, on an ARM mac platform, the conversion would saturate to the nearest integer, a positive value. On such a parameter the call to `mid` would return a null string. Due to the way the `startsWith` implementation for `QStringView` works, this would require the searched for string to be null for the search to return true. Previously, due to literal empty strings being read as null, this would silently pass. On the contrary, on a platform such as x86_64, the implicit cast would generally produce the indefinite integer value, which appears as a negative integer, producing the whole original string on a call to mid, which then would have the correct behavior on a call to `QStringView::startsWith` with regards to the test in question, so that it would generally pass. To avoid the platform specific behavior, the position in double form is now clamped between zero and the length of the string that should be searched, which should generally avoid the unexpected behavior and be relatively consistent between platforms. [ChangeLog][QtQml] Assigning an empty JavaScript string to a property of type QString now produces only an empty QString, not a null QString. Fixes: QTBUG-125611 Pick-to: 6.8 Change-Id: Id6850fd98082f33db93d2a7d0bc4f7b5fdcad45b Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4stringobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 5f3d833f33..40d176723b 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -1012,6 +1012,11 @@ ReturnedValue StringPrototype::method_startsWith(const FunctionObject *b, const
if (argc > 1)
pos = argv[1].toInteger();
+ pos = std::clamp(
+ pos,
+ 0.0,
+ double(value.size()));
+
if (pos == 0)
return Encode(value.startsWith(searchString));