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 <fabian.kosmale@qt.io>
This commit is contained in:
Olivier De Cannière 2023-02-06 10:12:11 +01:00
parent 2af8743aab
commit d2c8fe712a
5 changed files with 116 additions and 3 deletions

View File

@ -670,6 +670,7 @@ ReturnedValue UrlPrototype::method_getSearchParams(const FunctionObject *b, cons
Scoped<UrlSearchParamsObject> usp(scope, v4->newUrlSearchParamsObject());
usp->setUrlObject(thisObject->as<UrlObject>());
usp->initializeParams(r->search());
return usp->asReturnedValue();
@ -960,6 +961,11 @@ void UrlSearchParamsObject::setParams(QList<QStringList> 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<QStringList> 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 &param = 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<UrlObject> scopedUrlObject(scope, o->d()->url.get());
if (scopedUrlObject)
scopedUrlObject->setSearch(o->searchString());
return Encode::undefined();
}

View File

@ -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<QStringList> params() const;
void setParams(QList<QStringList> params);
Heap::UrlObject *urlObject() const;
void setUrlObject(const UrlObject *url);
QString searchString() const;
QString nameAt(int index) const;
Heap::String * nameAtRaw(int index) const;

View File

@ -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()

View File

@ -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:
#####################################################################

View File

@ -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 <qtest.h>
#include <QtQml/qjsengine.h>
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"