diff options
| author | Luca Di Sera <luca.disera@qt.io> | 2024-06-21 15:39:07 +0200 |
|---|---|---|
| committer | Luca Di Sera <luca.disera@qt.io> | 2024-06-28 11:05:05 +0200 |
| commit | df684931c96b174033730971ec5cb63a03f01483 (patch) | |
| tree | 48a920345f7d50af732953615071d8a25d2c7a03 /src/qml/jsruntime/qv4stringobject.cpp | |
| parent | 4506b936b4dcaeb42d91e3b25789ec91d13b584e (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.cpp | 5 |
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)); |
