From d2c8fe712a87a247864decd9d13167f847035aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20De=20Canni=C3=A8re?= Date: Mon, 6 Feb 2023 10:12:11 +0100 Subject: [PATCH] UrlObject: Fix setting searchParams not modifying the url's search field Previously, setting the search params via the searchParams.set() method did not change the url's search field. The searchParams object now has a back pointer to the urlObject it belongs to. Whenever a search param is set, the url search field is also updated. The tst_qv4urlobject test was also added to check proper behavior. Pick-to: 6.5 Task-number: QTBUG-110454 Change-Id: I3b0e843395da8a0e5aedcf71895981f68560d9c6 Reviewed-by: Fabian Kosmale --- src/qml/jsruntime/qv4urlobject.cpp | 29 ++++++++++ src/qml/jsruntime/qv4urlobject_p.h | 11 +++- tests/auto/qml/CMakeLists.txt | 1 + tests/auto/qml/qv4urlobject/CMakeLists.txt | 20 +++++++ .../qml/qv4urlobject/tst_qv4urlobject.cpp | 58 +++++++++++++++++++ 5 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 tests/auto/qml/qv4urlobject/CMakeLists.txt create mode 100644 tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp diff --git a/src/qml/jsruntime/qv4urlobject.cpp b/src/qml/jsruntime/qv4urlobject.cpp index 8b6db439e2..e5d8ddb9e8 100644 --- a/src/qml/jsruntime/qv4urlobject.cpp +++ b/src/qml/jsruntime/qv4urlobject.cpp @@ -670,6 +670,7 @@ ReturnedValue UrlPrototype::method_getSearchParams(const FunctionObject *b, cons Scoped usp(scope, v4->newUrlSearchParamsObject()); + usp->setUrlObject(thisObject->as()); usp->initializeParams(r->search()); return usp->asReturnedValue(); @@ -960,6 +961,11 @@ void UrlSearchParamsObject::setParams(QList params) d()->values.set(engine(), values); } +void UrlSearchParamsObject::setUrlObject(const UrlObject *url) +{ + d()->url.set(engine(), url->d()); +} + void UrlSearchParamsObject::append(Heap::String *name, Heap::String *value) { Scope scope(engine()); @@ -1008,6 +1014,25 @@ QList UrlSearchParamsObject::params() const return result; } +Heap::UrlObject *UrlSearchParamsObject::urlObject() const +{ + return d()->url.get(); +} + +QString UrlSearchParamsObject::searchString() const +{ + QString search = QLatin1String(""); + auto params = this->params(); + auto len = params.size(); + for (int i = 0; i < len; ++i) { + const QStringList ¶m = params[i]; + search += param[0] + QLatin1Char('=') + param[1]; + if (i != len - 1) + search += QLatin1Char('&'); + } + return search; +} + int UrlSearchParamsObject::length() const { auto *arrayObject = d()->params.get(); @@ -1335,6 +1360,10 @@ ReturnedValue UrlSearchParamsPrototype::method_set(const FunctionObject *b, cons o->setParams(params); + Scoped scopedUrlObject(scope, o->d()->url.get()); + if (scopedUrlObject) + scopedUrlObject->setSearch(o->searchString()); + return Encode::undefined(); } diff --git a/src/qml/jsruntime/qv4urlobject_p.h b/src/qml/jsruntime/qv4urlobject_p.h index e4a3ba073b..4e4a03a923 100644 --- a/src/qml/jsruntime/qv4urlobject_p.h +++ b/src/qml/jsruntime/qv4urlobject_p.h @@ -50,12 +50,13 @@ struct UrlCtor : FunctionObject void init(QV4::ExecutionContext *scope); }; -// clang-format on +// clang-format off #define UrlSearchParamsObjectMembers(class, Member) \ Member(class, Pointer, ArrayObject *, params) \ Member(class, Pointer, ArrayObject *, keys) \ - Member(class, Pointer, ArrayObject *, values) -// clang-format off + Member(class, Pointer, ArrayObject *, values) \ + Member(class, Pointer, UrlObject *, url) +// clang-format on DECLARE_HEAP_OBJECT(UrlSearchParamsObject, Object) { @@ -212,6 +213,10 @@ struct UrlSearchParamsObject : Object QList params() const; void setParams(QList params); + Heap::UrlObject *urlObject() const; + void setUrlObject(const UrlObject *url); + + QString searchString() const; QString nameAt(int index) const; Heap::String * nameAtRaw(int index) const; diff --git a/tests/auto/qml/CMakeLists.txt b/tests/auto/qml/CMakeLists.txt index 77663f350d..e5b6de7b8c 100644 --- a/tests/auto/qml/CMakeLists.txt +++ b/tests/auto/qml/CMakeLists.txt @@ -142,6 +142,7 @@ if(QT_FEATURE_private_tests) add_subdirectory(qv4mm) add_subdirectory(qv4identifiertable) add_subdirectory(qv4regexp) + add_subdirectory(qv4urlobject) if(QT_FEATURE_process AND NOT QNX) add_subdirectory(ecmascripttests) endif() diff --git a/tests/auto/qml/qv4urlobject/CMakeLists.txt b/tests/auto/qml/qv4urlobject/CMakeLists.txt new file mode 100644 index 0000000000..4686efe4a3 --- /dev/null +++ b/tests/auto/qml/qv4urlobject/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from qv4urlobject.pro. + +##################################################################### +## tst_qv4urlobject Test: +##################################################################### + +qt_internal_add_test(tst_qv4urlobject + SOURCES + tst_qv4urlobject.cpp + LIBRARIES + Qt::Gui + Qt::Qml + Qt::QmlPrivate +) + +## Scopes: +##################################################################### diff --git a/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp b/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp new file mode 100644 index 0000000000..99a5803586 --- /dev/null +++ b/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include +#include + +class tst_urlobject : public QObject +{ + Q_OBJECT + +private slots: + void searchParams_set(); + void searchParams_nullUrlPointer(); +}; + +void tst_urlobject::searchParams_set() +{ + QJSEngine engine; + QJSValue result = + engine.evaluate(QLatin1String("var url = new URL(\"http://www.google.com/search\");" + "url.href")); + QVERIFY(!result.isError()); + QCOMPARE(result.toString(), "http://www.google.com/search"); + + result = engine.evaluate(QLatin1String("url.toString()")); + QVERIFY(!result.isError()); + QCOMPARE(result.toString(), "http://www.google.com/search"); + + result = engine.evaluate(QLatin1String("url.searchParams.set(\"q\", \"value\");" + "url.href;")); + QVERIFY(!result.isError()); + QCOMPARE(result.toString(), "http://www.google.com/search?q=value"); + + result = engine.evaluate(QLatin1String("url.toString()")); + QVERIFY(!result.isError()); + QCOMPARE(result.toString(), "http://www.google.com/search?q=value"); + + result = engine.evaluate(QLatin1String("url.searchParams.set(\"t\", \"otherValue\");" + "url.href;")); + QVERIFY(!result.isError()); + QCOMPARE(result.toString(), "http://www.google.com/search?q=value&t=otherValue"); + + result = engine.evaluate(QLatin1String("url.toString()")); + QVERIFY(!result.isError()); + QCOMPARE(result.toString(), "http://www.google.com/search?q=value&t=otherValue"); +} + +void tst_urlobject::searchParams_nullUrlPointer() +{ + QJSEngine engine; + QJSValue result = engine.evaluate(QLatin1String("let params = new URLSearchParams();" + "params.set(\"foo\", \"bar\");")); + QVERIFY(!result.isError()); +} + +QTEST_MAIN(tst_urlobject) + +#include "tst_qv4urlobject.moc"