aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4urlobject.cpp268
-rw-r--r--src/qml/jsruntime/qv4urlobject_p.h139
2 files changed, 160 insertions, 247 deletions
diff --git a/src/qml/jsruntime/qv4urlobject.cpp b/src/qml/jsruntime/qv4urlobject.cpp
index e3268e133f..ba64d84fa5 100644
--- a/src/qml/jsruntime/qv4urlobject.cpp
+++ b/src/qml/jsruntime/qv4urlobject.cpp
@@ -50,258 +50,118 @@ void UrlPrototype::init(ExecutionEngine *engine, Object *ctor)
defineAccessorProperty(QLatin1String("username"), method_getUsername, method_setUsername);
}
-bool UrlObject::setHash(QString hash)
+bool UrlObject::setHash(const QString &hash)
{
- if (hash.startsWith(QLatin1Char('#')))
- hash = hash.mid(1);
-
- QUrl url = toQUrl();
- url.setFragment(hash);
-
- if (!url.isValid())
- return false;
-
- d()->hash.set(engine(), engine()->newString(url.fragment()));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ url->setFragment(hash.startsWith(QLatin1Char('#')) ? hash.mid(1) : hash);
+ });
}
-bool UrlObject::setHostname(QString host)
+bool UrlObject::setHostname(const QString &hostName)
{
- QUrl url = toQUrl();
- url.setHost(host);
-
- if (!url.isValid())
- return false;
-
- d()->hostname.set(engine(), engine()->newString(url.host()));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- updateOrigin();
- updateHost();
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ url->setHost(hostName);
+ });
}
-bool UrlObject::setHost(QString hostname)
+bool UrlObject::setHost(const QString &host)
{
- int port = -1;
-
- if (hostname.contains(QLatin1Char(':'))) {
- const QStringList list = hostname.split(QLatin1Char(':'));
- hostname = list[0];
- port = list[1].toInt();
- }
-
- QUrl url = toQUrl();
- url.setHost(hostname);
- url.setPort(port);
-
- if (!url.isValid())
- return false;
-
- if (url.port() != -1)
- d()->port.set(engine(), engine()->newString(QString::number(url.port())));
-
- d()->hostname.set(engine(), engine()->newString(url.host()));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- updateOrigin();
- updateHost();
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ qsizetype colon = host.indexOf(QLatin1Char(':'));
+ if (colon == -1) {
+ url->setHost(host);
+ url->setPort(-1);
+ } else {
+ url->setHost(host.left(colon));
+ url->setPort(QStringView(host).mid(colon + 1).toInt());
+ }
+ });
}
-bool UrlObject::setHref(QString href)
+bool UrlObject::setHref(const QString &href)
{
- const QUrl url(href);
- if (!url.isValid() || url.isRelative())
+ QUrl replacement(href);
+ if (!replacement.isValid() || replacement.isRelative())
return false;
- setUrl(url);
+ d()->setUrl(std::move(replacement));
return true;
}
void UrlObject::setUrl(const QUrl &url)
{
- d()->hash.set(engine(), engine()->newString(url.fragment()));
- d()->hostname.set(engine(), engine()->newString(url.host()));
- d()->href.set(engine(), engine()->newString(url.toString(QUrl::ComponentFormattingOptions(QUrl::ComponentFormattingOption::FullyEncoded))));
- d()->password.set(engine(), engine()->newString(url.password()));
- d()->pathname.set(engine(), engine()->newString(url.path()));
- d()->port.set(engine(),
- engine()->newString(url.port() == -1 ? QLatin1String("")
- : QString::number(url.port())));
- d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(':')));
- d()->search.set(engine(), engine()->newString(url.query(QUrl::ComponentFormattingOptions(QUrl::ComponentFormattingOption::FullyEncoded))));
- d()->username.set(engine(), engine()->newString(url.userName()));
-
- updateOrigin();
- updateHost();
+ d()->setUrl(QUrl(url));
}
-bool UrlObject::setPassword(QString password)
+bool UrlObject::setPassword(const QString &password)
{
- QUrl url = toQUrl();
- url.setPassword(password);
-
- if (!url.isValid())
- return false;
-
- d()->password.set(engine(), engine()->newString(url.password()));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ url->setPassword(password);
+ });
}
-bool UrlObject::setPathname(QString pathname)
+bool UrlObject::setPathname(const QString &pathname)
{
- QUrl url = toQUrl();
- url.setPath(pathname);
-
- if (!url.isValid())
- return false;
-
- d()->pathname.set(engine(), engine()->newString(url.path()));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ url->setPath(pathname);
+ });
}
-bool UrlObject::setPort(QString port)
+bool UrlObject::setPort(const QString &port)
{
- QUrl url = toQUrl();
- url.setPort(port.isEmpty() ? -1 : port.toInt());
-
- if (!url.isValid())
- return false;
-
- d()->port.set(engine(),
- engine()->newString(url.port() == -1 ? QLatin1String("")
- : QString::number(url.port())));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- updateOrigin();
- updateHost();
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ url->setPort(port.isEmpty() ? -1 : port.toInt());
+ });
}
-bool UrlObject::setProtocol(QString protocolOrScheme)
+bool UrlObject::setProtocol(const QString &protocolOrScheme)
{
- QUrl url = toQUrl();
// If there is one or several ':' in the protocolOrScheme,
// everything from the first colon is removed.
- qsizetype firstColonPos = protocolOrScheme.indexOf(QLatin1Char(':'));
-
- if (firstColonPos != -1)
- protocolOrScheme.truncate(firstColonPos);
-
- url.setScheme(protocolOrScheme);
-
- if (!url.isValid())
- return false;
-
- d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(':')));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- updateOrigin();
- updateHost();
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ const qsizetype colon = protocolOrScheme.indexOf(QLatin1Char(':'));
+ url->setScheme(colon == -1 ? protocolOrScheme : protocolOrScheme.left(colon));
+ });
}
-bool UrlObject::setSearch(QString search)
+bool UrlObject::setSearch(const QString &search)
{
- QUrl url = toQUrl();
-
- if (search.startsWith(QLatin1Char('?'))) {
- search = search.mid(1);
- } else if (search.isEmpty()) {
- // In JS, setting an empty query removes the '?' as well. QUrl only does that for a null QString.
- // The way to get a lone '?' in JS is to set the search property to "?". That is why this is in
- // the else branch.
- search = QString(); // it's null now
- }
-
- url.setQuery(search);
-
- if (!url.isValid())
- return false;
+ return updateUrl([&](QUrl *url) {
+ if (search.startsWith(QLatin1Char('?'))) {
+ url->setQuery(search.mid(1));
+ return;
+ }
- d()->search.set(engine(), engine()->newString(url.query()));
- d()->href.set(engine(), engine()->newString(url.toString()));
+ if (search.isEmpty()) {
+ // In JS, setting an empty query removes the '?' as well. QUrl only does that for a
+ // null QString. The way to get a lone '?' in JS is to set the search property to "?".
+ // That is why this is in the else branch.
+ url->setQuery(QString()); // it's null now
+ return;
+ }
- return true;
+ url->setQuery(search);
+ });
}
-bool UrlObject::setUsername(QString username)
+bool UrlObject::setUsername(const QString &username)
{
- QUrl url = toQUrl();
- url.setUserName(username);
-
- if (!url.isValid())
- return false;
-
- d()->username.set(engine(), engine()->newString(url.userName()));
- d()->href.set(engine(), engine()->newString(url.toString()));
-
- return true;
+ return updateUrl([&](QUrl *url) {
+ url->setUserName(username);
+ });
}
QString UrlObject::search() const
{
- auto url = QUrl(href());
- if (auto url = QUrl(href()); !url.hasQuery() || url.query().isEmpty())
- return QLatin1String("");
+ const QUrl url = d()->url();
+ if (!url.hasQuery() || url.query().isEmpty())
+ return QString();
constexpr auto options = QUrl::ComponentFormattingOption::EncodeSpaces
| QUrl::ComponentFormattingOption::EncodeUnicode
| QUrl::ComponentFormattingOption::EncodeReserved;
- return u'?' + url.query(options);
-}
-
-QUrl UrlObject::toQUrl() const
-{
- return QUrl(href());
-}
-
-void UrlObject::updateOrigin()
-{
- QUrl url = toQUrl();
-
- QString proto = url.scheme();
-
- // A blob's origin is the origin of the URL that it points to
- if (proto == QLatin1String("blob")) {
- url = QUrl(url.path());
- proto = url.scheme();
- }
-
- QString origin;
- if (proto == QLatin1String("http") || proto == QLatin1String("https")
- || proto == QLatin1String("ftp")) {
- origin = QLatin1String("%1://%2").arg(url.scheme(), url.host());
-
- if (url.port() != -1)
- origin.append(QLatin1String(":") + QString::number(url.port()));
- }
-
- d()->origin.set(engine(), engine()->newString(origin));
-}
-
-void UrlObject::updateHost()
-{
- QUrl url = toQUrl();
-
- QString host = url.host();
-
- if (url.port() != -1)
- host.append(QLatin1String(":") + QString::number(url.port()));
-
- d()->host.set(engine(), engine()->newString(host));
+ return QLatin1Char('?') + url.query(options);
}
static bool checkUrlObjectType(ExecutionEngine *v4, const Scoped<UrlObject> &r)
diff --git a/src/qml/jsruntime/qv4urlobject_p.h b/src/qml/jsruntime/qv4urlobject_p.h
index ae3e9d8351..525120e96e 100644
--- a/src/qml/jsruntime/qv4urlobject_p.h
+++ b/src/qml/jsruntime/qv4urlobject_p.h
@@ -25,25 +25,31 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Heap {
-// clang-format off
-#define UrlObjectMembers(class, Member) \
- Member(class, Pointer, String *, hash) \
- Member(class, Pointer, String *, host) \
- Member(class, Pointer, String *, hostname) \
- Member(class, Pointer, String *, href) \
- Member(class, Pointer, String *, origin) \
- Member(class, Pointer, String *, password) \
- Member(class, Pointer, String *, pathname) \
- Member(class, Pointer, String *, port) \
- Member(class, Pointer, String *, protocol) \
- Member(class, Pointer, String *, search) \
- Member(class, Pointer, String *, username)
-// clang-format on
-
+#define UrlObjectMembers(class, Member)
DECLARE_HEAP_OBJECT(UrlObject, Object)
{
DECLARE_MARKOBJECTS(UrlObject)
- void init() { Object::init(); }
+ void init()
+ {
+ new (&m_url) QUrl;
+ Object::init();
+ }
+ void init(const QUrl &url)
+ {
+ new (&m_url) QUrl(url);
+ Object::init();
+ }
+
+ void destroy()
+ {
+ std::destroy_at<QUrl>(reinterpret_cast<QUrl *>(&m_url));
+ }
+
+ QUrl url() const { return *reinterpret_cast<const QUrl *>(&m_url); }
+ void setUrl(QUrl &&url) { *reinterpret_cast<QUrl *>(&m_url) = std::move(url); }
+
+ static constexpr auto alignment = alignof(QUrl);
+ alignas(alignment) std::byte m_url[sizeof(QUrl)];
};
struct UrlCtor : FunctionObject
@@ -74,52 +80,99 @@ struct UrlSearchParamsCtor : FunctionObject
struct UrlObject : Object
{
V4_OBJECT2(UrlObject, Object)
+ V4_NEEDS_DESTROY
Q_MANAGED_TYPE(UrlObject)
V4_PROTOTYPE(urlPrototype)
- QString hash() const { return QLatin1String("#") + toQString(d()->hash); }
- bool setHash(QString hash);
+ QString hash() const
+ {
+ const QUrl url = constD()->url();
+ return QLatin1Char('#') + url.fragment();
+ }
+ bool setHash(const QString &hash);
- QString host() const { return toQString(d()->host); }
- bool setHost(QString host);
+ QString host() const
+ {
+ const QUrl url = constD()->url();
+ const int port = url.port();
+ return port == -1 ? url.host() : (url.host() + QLatin1Char(':') + QString::number(port));
+ }
+ bool setHost(const QString &host);
- QString hostname() const { return toQString(d()->hostname); }
- bool setHostname(QString hostname);
+ QString hostname() const
+ {
+ const QUrl url = constD()->url();
+ return url.isValid() ? url.host() : QString();
+ }
+ bool setHostname(const QString &hostname);
- QString href() const { return toQString(d()->href); }
- bool setHref(QString href);
+ QString href() const
+ {
+ return constD()->url().toString(QUrl::ComponentFormattingOption::FullyEncoded);
+ }
+ bool setHref(const QString &href);
- QString origin() const { return toQString(d()->origin); }
+ QString origin() const
+ {
+ const auto resolve = [](const QUrl &url) {
+ const QString proto = url.scheme();
+ if (proto != QLatin1String("http") && proto != QLatin1String("https")
+ && proto != QLatin1String("ftp")) {
+ return QString();
+ }
+
+ const QString origin = QLatin1String("%1://%2").arg(proto, url.host());
+ const int port = url.port();
+ return port == -1 ? origin : (origin + QLatin1Char(':') + QString::number(port));
+ };
+
+ const QUrl url = constD()->url();
+
+ // A blob's origin is the origin of the URL that it points to
+ return url.scheme() == QLatin1String("blob") ? resolve(QUrl(url.path())) : resolve(url);
+ }
- QString password() const { return toQString(d()->password); }
- bool setPassword(QString password);
+ QString password() const { return constD()->url().password(); }
+ bool setPassword(const QString &password);
- QString pathname() const { return toQString(d()->pathname); }
- bool setPathname(QString pathname);
+ QString pathname() const { return constD()->url().path(); }
+ bool setPathname(const QString &pathname);
- QString port() const { return toQString(d()->port); }
- bool setPort(QString port);
+ QString port() const
+ {
+ const int port = constD()->url().port();
+ return port == -1 ? QString() : QString::number(port);
+ }
+ bool setPort(const QString &port);
- QString protocol() const { return toQString(d()->protocol); }
- bool setProtocol(QString protocol);
+ QString protocol() const { return constD()->url().scheme() + QLatin1Char(':'); }
+ bool setProtocol(const QString &protocol);
Q_QML_AUTOTEST_EXPORT QString search() const;
- bool setSearch(QString search);
+ bool setSearch(const QString &search);
- QString username() const { return toQString(d()->username); }
- bool setUsername(QString username);
+ QString username() const { return constD()->url().userName(); }
+ bool setUsername(const QString &username);
- QUrl toQUrl() const;
+ QUrl toQUrl() const
+ {
+ return d()->url();
+ }
void setUrl(const QUrl &url);
private:
- static QString toQString(const Heap::String *string)
- {
- return string ? string->toQString() : QString();
- }
+ const Heap::UrlObject *constD() const { return d(); }
+
+ template<typename F>
+ bool updateUrl(F &&f) {
+ QUrl url = d()->url();
+ f(&url);
+ if (!url.isValid())
+ return false;
- void updateOrigin();
- void updateHost();
+ d()->setUrl(std::move(url));
+ return true;
+ }
};
template<>