diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/qml/jsruntime/qv4urlobject.cpp | 268 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4urlobject_p.h | 139 |
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<> |
