Implement URL object
Implements the JavaScript URL object (https://url.spec.whatwg.org/#api). Except that it does not currently implement the searchParams field. Task-number: QTBUG-54988 Change-Id: I19abc69e075cbf84bd15e6791be195ce16f3fe73 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
399ebb5635
commit
faa3e0b41e
|
@ -150,6 +150,7 @@ qt_add_module(Qml
|
|||
jsruntime/qv4stringobject.cpp jsruntime/qv4stringobject_p.h
|
||||
jsruntime/qv4symbol.cpp jsruntime/qv4symbol_p.h
|
||||
jsruntime/qv4typedarray.cpp jsruntime/qv4typedarray_p.h
|
||||
jsruntime/qv4urlobject.cpp jsruntime/qv4urlobject_p.h
|
||||
jsruntime/qv4value.cpp jsruntime/qv4value_p.h
|
||||
jsruntime/qv4variantobject.cpp jsruntime/qv4variantobject_p.h
|
||||
jsruntime/qv4vme_moth.cpp jsruntime/qv4vme_moth_p.h
|
||||
|
|
|
@ -150,6 +150,7 @@ qt_add_module(Qml
|
|||
jsruntime/qv4stringobject.cpp jsruntime/qv4stringobject_p.h
|
||||
jsruntime/qv4symbol.cpp jsruntime/qv4symbol_p.h
|
||||
jsruntime/qv4typedarray.cpp jsruntime/qv4typedarray_p.h
|
||||
jsruntime/qv4urlobject.cpp jsruntime/qv4urlobject_p.h
|
||||
jsruntime/qv4value.cpp jsruntime/qv4value_p.h
|
||||
jsruntime/qv4variantobject.cpp jsruntime/qv4variantobject_p.h
|
||||
jsruntime/qv4vme_moth.cpp jsruntime/qv4vme_moth_p.h
|
||||
|
|
|
@ -59,6 +59,7 @@ SOURCES += \
|
|||
$$PWD/qv4module.cpp \
|
||||
$$PWD/qv4promiseobject.cpp \
|
||||
$$PWD/qv4runtime.cpp \
|
||||
$$PWD/qv4urlobject.cpp \
|
||||
$$PWD/qv4value.cpp \
|
||||
$$PWD/qv4compilationunitmapper.cpp \
|
||||
$$PWD/qv4executablecompilationunit.cpp \
|
||||
|
@ -135,6 +136,7 @@ HEADERS += \
|
|||
$$PWD/qv4module_p.h \
|
||||
$$PWD/qv4promiseobject_p.h \
|
||||
$$PWD/qv4runtime_p.h \
|
||||
$$PWD/qv4urlobject_p.h \
|
||||
$$PWD/qv4value_p.h \
|
||||
$$PWD/qv4compilationunitmapper_p.h \
|
||||
$$PWD/qv4executablecompilationunit_p.h \
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "qv4proxy_p.h"
|
||||
#include "qv4stackframe_p.h"
|
||||
#include "qv4atomics_p.h"
|
||||
#include "qv4urlobject_p.h"
|
||||
|
||||
#if QT_CONFIG(qml_sequence_object)
|
||||
#include "qv4sequenceobject_p.h"
|
||||
|
@ -650,6 +651,13 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
|
|||
ic = newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype());
|
||||
jsObjects[StringIteratorProto] = memoryManager->allocObject<StringIteratorPrototype>(ic);
|
||||
|
||||
//
|
||||
// url
|
||||
//
|
||||
|
||||
jsObjects[Url_Ctor] = memoryManager->allocate<UrlCtor>(global);
|
||||
jsObjects[UrlProto] = memoryManager->allocate<UrlPrototype>();
|
||||
|
||||
str = newString(QStringLiteral("get [Symbol.species]"));
|
||||
jsObjects[GetSymbolSpecies] = FunctionObject::createBuiltinFunction(this, str, ArrayPrototype::method_get_species, 0);
|
||||
|
||||
|
@ -671,6 +679,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
|
|||
static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
|
||||
static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
|
||||
static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
|
||||
static_cast<UrlPrototype *>(urlPrototype())->init(this, urlCtor());
|
||||
|
||||
static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
|
||||
static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
|
||||
|
@ -760,6 +769,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
|
|||
globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
|
||||
globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
|
||||
globalObject->defineDefaultProperty(QStringLiteral("Promise"), *promiseCtor());
|
||||
globalObject->defineDefaultProperty(QStringLiteral("URL"), *urlCtor());
|
||||
|
||||
globalObject->defineDefaultProperty(QStringLiteral("SharedArrayBuffer"), *sharedArrayBufferCtor());
|
||||
globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
|
||||
|
@ -1049,6 +1059,11 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &r
|
|||
}
|
||||
#endif
|
||||
|
||||
Heap::UrlObject *ExecutionEngine::newUrlObject()
|
||||
{
|
||||
return memoryManager->allocate<UrlObject>();
|
||||
}
|
||||
|
||||
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
|
||||
{
|
||||
return ErrorObject::create<ErrorObject>(this, value, errorCtor());
|
||||
|
|
|
@ -240,6 +240,7 @@ public:
|
|||
MapIteratorProto,
|
||||
ArrayIteratorProto,
|
||||
StringIteratorProto,
|
||||
UrlProto,
|
||||
|
||||
Object_Ctor,
|
||||
String_Ctor,
|
||||
|
@ -267,6 +268,7 @@ public:
|
|||
WeakMap_Ctor,
|
||||
Map_Ctor,
|
||||
IntrinsicTypedArray_Ctor,
|
||||
Url_Ctor,
|
||||
|
||||
GetSymbolSpecies,
|
||||
|
||||
|
@ -307,6 +309,10 @@ public:
|
|||
FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
|
||||
FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
|
||||
FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
|
||||
FunctionObject *urlCtor() const
|
||||
{
|
||||
return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor);
|
||||
}
|
||||
FunctionObject *typedArrayCtors;
|
||||
|
||||
FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
|
||||
|
@ -354,6 +360,7 @@ public:
|
|||
Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
|
||||
Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
|
||||
Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
|
||||
Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); }
|
||||
|
||||
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
|
||||
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
|
||||
|
@ -583,6 +590,8 @@ public:
|
|||
Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
|
||||
#endif
|
||||
|
||||
Heap::UrlObject *newUrlObject();
|
||||
|
||||
Heap::Object *newErrorObject(const Value &value);
|
||||
Heap::Object *newErrorObject(const QString &message);
|
||||
Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
|
||||
|
|
|
@ -141,6 +141,7 @@ namespace Heap {
|
|||
struct ArgumentsObject;
|
||||
struct QObjectWrapper;
|
||||
struct RegExpObject;
|
||||
struct UrlObject;
|
||||
struct RegExp;
|
||||
struct EvalFunction;
|
||||
|
||||
|
|
|
@ -105,6 +105,9 @@ QString Managed::className() const
|
|||
case Type_MathObject:
|
||||
s = "Math";
|
||||
break;
|
||||
case Type_UrlObject:
|
||||
s = "URL";
|
||||
break;
|
||||
|
||||
case Type_ExecutionContext:
|
||||
s = "__ExecutionContext";
|
||||
|
|
|
@ -144,6 +144,7 @@ public:
|
|||
Type_JsonObject,
|
||||
Type_MathObject,
|
||||
Type_ProxyObject,
|
||||
Type_UrlObject,
|
||||
|
||||
Type_ExecutionContext,
|
||||
Type_InternalClass,
|
||||
|
|
|
@ -0,0 +1,689 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qv4urlobject_p.h"
|
||||
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
using namespace QV4;
|
||||
|
||||
DEFINE_OBJECT_VTABLE(UrlObject);
|
||||
DEFINE_OBJECT_VTABLE(UrlCtor);
|
||||
|
||||
void Heap::UrlCtor::init(QV4::ExecutionContext *scope)
|
||||
{
|
||||
Heap::FunctionObject::init(scope, QLatin1String("URL"));
|
||||
}
|
||||
|
||||
void UrlPrototype::init(ExecutionEngine *engine, Object *ctor)
|
||||
{
|
||||
Q_UNUSED(ctor)
|
||||
|
||||
Scope scope(engine);
|
||||
ScopedObject o(scope);
|
||||
|
||||
defineDefaultProperty(QLatin1String("toString"), method_getHref);
|
||||
defineDefaultProperty(QLatin1String("toJSON"), method_getHref);
|
||||
|
||||
defineAccessorProperty(QLatin1String("hash"), method_getHash, method_setHash);
|
||||
defineAccessorProperty(QLatin1String("host"), method_getHost, method_setHost);
|
||||
defineAccessorProperty(QLatin1String("hostname"), method_getHostname, method_setHostname);
|
||||
defineAccessorProperty(QLatin1String("href"), method_getHref, method_setHref);
|
||||
defineAccessorProperty(QLatin1String("origin"), method_getOrigin, nullptr);
|
||||
defineAccessorProperty(QLatin1String("password"), method_getPassword, method_setPassword);
|
||||
defineAccessorProperty(QLatin1String("pathname"), method_getPathname, method_setPathname);
|
||||
defineAccessorProperty(QLatin1String("port"), method_getPort, method_setPort);
|
||||
defineAccessorProperty(QLatin1String("protocol"), method_getProtocol, method_setProtocol);
|
||||
defineAccessorProperty(QLatin1String("search"), method_getSearch, method_setSearch);
|
||||
defineAccessorProperty(QLatin1String("username"), method_getUsername, method_setUsername);
|
||||
}
|
||||
|
||||
bool UrlObject::setHash(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;
|
||||
}
|
||||
|
||||
bool UrlObject::setHostname(QString host)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool UrlObject::setHost(QString hostname)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool UrlObject::setHref(QString href)
|
||||
{
|
||||
QUrl url(href);
|
||||
|
||||
if (!url.isValid() || url.isRelative())
|
||||
return false;
|
||||
|
||||
d()->hash.set(engine(), engine()->newString(url.fragment()));
|
||||
d()->hostname.set(engine(), engine()->newString(url.host()));
|
||||
d()->href.set(engine(), engine()->newString(url.toString()));
|
||||
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()));
|
||||
d()->search.set(engine(), engine()->newString(url.query()));
|
||||
d()->username.set(engine(), engine()->newString(url.userName()));
|
||||
|
||||
updateOrigin();
|
||||
updateHost();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UrlObject::setPassword(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;
|
||||
}
|
||||
|
||||
bool UrlObject::setPathname(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;
|
||||
}
|
||||
|
||||
bool UrlObject::setPort(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;
|
||||
}
|
||||
|
||||
bool UrlObject::setProtocol(QString protocol)
|
||||
{
|
||||
QUrl url = toQUrl();
|
||||
url.setScheme(protocol);
|
||||
|
||||
if (!url.isValid())
|
||||
return false;
|
||||
|
||||
d()->protocol.set(engine(), engine()->newString(url.scheme()));
|
||||
d()->href.set(engine(), engine()->newString(url.toString()));
|
||||
|
||||
updateOrigin();
|
||||
updateHost();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UrlObject::setSearch(QString search)
|
||||
{
|
||||
QUrl url = toQUrl();
|
||||
|
||||
if (search.startsWith(QLatin1Char('?')))
|
||||
search = search.mid(1);
|
||||
|
||||
url.setQuery(search);
|
||||
|
||||
if (!url.isValid())
|
||||
return false;
|
||||
|
||||
d()->search.set(engine(), engine()->newString(url.query()));
|
||||
d()->href.set(engine(), engine()->newString(url.toString()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UrlObject::setUsername(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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getHash(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->hash()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setHash(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
r->setHash(stringValue->toQString());
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getHost(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->host()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setHost(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
QString host = stringValue->toQString();
|
||||
if (!r->setHost(host))
|
||||
return v4->throwTypeError(QLatin1String("Invalid host: %1").arg(host));
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getHostname(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->hostname()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setHostname(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
QString hostname = stringValue->toQString();
|
||||
if (!r->setHostname(hostname))
|
||||
return v4->throwTypeError(QLatin1String("Invalid hostname: %1").arg(hostname));
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getHref(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->href()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setHref(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
QString href = stringValue->toQString();
|
||||
if (!r->setHref(href))
|
||||
return v4->throwTypeError(QLatin1String("Invalid URL: %1").arg(href));
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getOrigin(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->origin()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getPassword(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->password()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setPassword(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
r->setPassword(stringValue->toQString());
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getPathname(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->pathname()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setPathname(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
r->setPathname(stringValue->toQString());
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getPort(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->port()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setPort(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
QString port;
|
||||
|
||||
if (stringValue != nullptr)
|
||||
port = stringValue->toQString();
|
||||
else if (arg->isInt32())
|
||||
port = QString::number(arg->toInt32());
|
||||
else
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
if (!r->setPort(port))
|
||||
return v4->throwTypeError(QLatin1String("Invalid port: %1").arg(port));
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getProtocol(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->protocol()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setProtocol(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
r->setProtocol(stringValue->toQString());
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getSearch(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->search()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setSearch(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
r->setSearch(stringValue->toQString());
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_getUsername(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
return Encode(v4->newString(r->username()));
|
||||
}
|
||||
|
||||
ReturnedValue UrlPrototype::method_setUsername(const FunctionObject *b, const Value *thisObject,
|
||||
const Value *argv, int)
|
||||
{
|
||||
ExecutionEngine *v4 = b->engine();
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg(scope, argv[0]);
|
||||
String *stringValue = arg->stringValue();
|
||||
|
||||
if (stringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
|
||||
|
||||
r->setUsername(stringValue->toQString());
|
||||
|
||||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue UrlCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv,
|
||||
int argc, const Value *newTarget)
|
||||
{
|
||||
ExecutionEngine *v4 = that->engine();
|
||||
|
||||
if (argc < 1 || argc > 2)
|
||||
return v4->throwError(QLatin1String("Invalid amount of arguments"));
|
||||
|
||||
Scope scope(v4);
|
||||
|
||||
ScopedValue arg1(scope, argv[0]);
|
||||
String *arg1StringValue = arg1->stringValue();
|
||||
|
||||
if (arg1StringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
QString arg1String = arg1StringValue->toQString();
|
||||
QString urlString;
|
||||
|
||||
if (argc == 2) {
|
||||
ScopedValue arg2(scope, argv[1]);
|
||||
String *arg2StringValue = arg2->stringValue();
|
||||
|
||||
if (arg2StringValue == nullptr)
|
||||
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
|
||||
|
||||
QUrl url = QUrl(arg2StringValue->toQString());
|
||||
QUrl relativeUrl = QUrl(arg1String);
|
||||
|
||||
QString baseUrlPath = url.path();
|
||||
QString relativePath = relativeUrl.path();
|
||||
|
||||
// If the base URL contains a path the last section of it is discarded
|
||||
int lastSlash = baseUrlPath.lastIndexOf(QLatin1Char('/'));
|
||||
if (lastSlash != -1)
|
||||
baseUrlPath.truncate(lastSlash);
|
||||
|
||||
if (!relativePath.startsWith(QLatin1Char('/')))
|
||||
relativePath = relativePath.prepend(QLatin1Char('/'));
|
||||
|
||||
url.setPath(baseUrlPath + relativePath);
|
||||
url.setFragment(relativeUrl.fragment());
|
||||
url.setQuery(relativeUrl.query());
|
||||
|
||||
urlString = url.toString();
|
||||
} else {
|
||||
urlString = arg1String;
|
||||
}
|
||||
|
||||
ReturnedValue o = Encode(v4->newUrlObject());
|
||||
|
||||
if (!newTarget)
|
||||
return o;
|
||||
|
||||
ScopedObject obj(scope, o);
|
||||
obj->setProtoFromNewTarget(newTarget);
|
||||
|
||||
UrlObject *urlObject = obj->as<UrlObject>();
|
||||
|
||||
if (!urlObject->setHref(urlString))
|
||||
return v4->throwTypeError(QLatin1String("Invalid URL: %1").arg(urlString));
|
||||
|
||||
return obj->asReturnedValue();
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QV4URLOBJECT_P_H
|
||||
#define QV4URLOBJECT_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qv4object_p.h"
|
||||
#include "qv4functionobject_p.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
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
|
||||
|
||||
DECLARE_HEAP_OBJECT(UrlObject, Object)
|
||||
{
|
||||
DECLARE_MARKOBJECTS(UrlObject);
|
||||
void init() { Object::init(); }
|
||||
};
|
||||
|
||||
struct UrlCtor : FunctionObject
|
||||
{
|
||||
void init(QV4::ExecutionContext *scope);
|
||||
};
|
||||
}
|
||||
|
||||
struct UrlObject : Object
|
||||
{
|
||||
V4_OBJECT2(UrlObject, Object)
|
||||
Q_MANAGED_TYPE(UrlObject)
|
||||
V4_PROTOTYPE(urlPrototype)
|
||||
|
||||
QString hash() const { return QLatin1String("#") + d()->hash->toQString(); }
|
||||
bool setHash(QString hash);
|
||||
|
||||
QString host() const { return d()->host->toQString(); }
|
||||
bool setHost(QString host);
|
||||
|
||||
QString hostname() const { return d()->hostname->toQString(); }
|
||||
bool setHostname(QString hostname);
|
||||
|
||||
QString href() const { return d()->href->toQString(); }
|
||||
bool setHref(QString href);
|
||||
|
||||
QString origin() const { return d()->origin->toQString(); }
|
||||
|
||||
QString password() const { return d()->password->toQString(); }
|
||||
bool setPassword(QString password);
|
||||
|
||||
QString pathname() const { return d()->pathname->toQString(); }
|
||||
bool setPathname(QString pathname);
|
||||
|
||||
QString port() const { return d()->port->toQString(); }
|
||||
bool setPort(QString port);
|
||||
|
||||
QString protocol() const { return d()->protocol->toQString(); }
|
||||
bool setProtocol(QString protocol);
|
||||
|
||||
QString search() const { return QLatin1String("?") + d()->search->toQString(); }
|
||||
bool setSearch(QString search);
|
||||
|
||||
QString username() const { return d()->username->toQString(); }
|
||||
bool setUsername(QString username);
|
||||
|
||||
private:
|
||||
QUrl toQUrl() const;
|
||||
void updateOrigin();
|
||||
void updateHost();
|
||||
};
|
||||
|
||||
template<>
|
||||
inline const UrlObject *Value::as() const
|
||||
{
|
||||
return isManaged() && m()->internalClass->vtable->type == Managed::Type_UrlObject
|
||||
? static_cast<const UrlObject *>(this)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
struct UrlCtor : FunctionObject
|
||||
{
|
||||
V4_OBJECT2(UrlCtor, FunctionObject)
|
||||
|
||||
static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv,
|
||||
int argc, const Value *);
|
||||
};
|
||||
|
||||
struct UrlPrototype : Object
|
||||
{
|
||||
V4_PROTOTYPE(objectPrototype)
|
||||
|
||||
void init(ExecutionEngine *engine, Object *ctor);
|
||||
|
||||
static ReturnedValue method_getHash(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setHash(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getHost(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setHost(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getHostname(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setHostname(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getHref(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setHref(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getOrigin(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getPassword(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setPassword(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getPathname(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setPathname(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getPort(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setPort(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getProtocol(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setProtocol(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getSearch(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setSearch(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
|
||||
static ReturnedValue method_getUsername(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
static ReturnedValue method_setUsername(const FunctionObject *, const Value *thisObject,
|
||||
const Value *argv, int argc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QV4URLOBJECT_P_H
|
|
@ -1105,6 +1105,7 @@ void tst_QJSEngine::globalObjectProperties_enumerate()
|
|||
<< "Proxy"
|
||||
<< "Atomics"
|
||||
<< "Promise"
|
||||
<< "URL"
|
||||
;
|
||||
QSet<QString> actualNames;
|
||||
{
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <private/qv4alloca_p.h>
|
||||
#include <private/qv4runtime_p.h>
|
||||
#include <private/qv4object_p.h>
|
||||
#include <private/qv4urlobject_p.h>
|
||||
#include <private/qv4script_p.h>
|
||||
#include <private/qqmlcomponentattached_p.h>
|
||||
#include <private/qv4objectiterator_p.h>
|
||||
|
@ -382,6 +383,9 @@ private slots:
|
|||
void semicolonAfterProperty();
|
||||
void hugeStack();
|
||||
void bindingOnQProperty();
|
||||
void urlConstruction();
|
||||
void urlPropertyInvalid();
|
||||
void urlPropertySet();
|
||||
|
||||
void gcCrashRegressionTest();
|
||||
|
||||
|
@ -9282,6 +9286,193 @@ void tst_qqmlecmascript::bindingOnQProperty()
|
|||
QVERIFY(qprop.hasBinding());
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::urlConstruction()
|
||||
{
|
||||
QQmlEngine qmlengine;
|
||||
|
||||
QObject *o = new QObject(&qmlengine);
|
||||
|
||||
QV4::ExecutionEngine *engine = qmlengine.handle();
|
||||
QV4::Scope scope(engine);
|
||||
|
||||
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o));
|
||||
|
||||
// Invalid number of arguments
|
||||
QVERIFY(EVALUATE_ERROR("new URL()"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('a', 'b', 'c')"));
|
||||
|
||||
// Invalid arguments
|
||||
QVERIFY(EVALUATE_ERROR("new URL(null)"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('a', null)"));
|
||||
|
||||
// Invalid URL
|
||||
QVERIFY(EVALUATE_ERROR("new URL('thisisnotaurl')"));
|
||||
|
||||
// Valid URL
|
||||
QV4::ScopedValue ret(scope,
|
||||
EVALUATE("new "
|
||||
"URL('https://username:password@example.com:1234/path/to/"
|
||||
"something?search=value#hash')"));
|
||||
QV4::UrlObject *validUrl = ret->as<QV4::UrlObject>();
|
||||
QVERIFY(validUrl != nullptr);
|
||||
|
||||
QCOMPARE(validUrl->protocol(), "https");
|
||||
QCOMPARE(validUrl->hostname(), "example.com");
|
||||
QCOMPARE(validUrl->username(), "username");
|
||||
QCOMPARE(validUrl->password(), "password");
|
||||
QCOMPARE(validUrl->port(), "1234");
|
||||
QCOMPARE(validUrl->host(), "example.com:1234");
|
||||
QCOMPARE(validUrl->origin(), "https://example.com:1234");
|
||||
QCOMPARE(validUrl->href(),
|
||||
"https://username:password@example.com:1234/path/to/something?search=value#hash");
|
||||
QCOMPARE(validUrl->pathname(), "/path/to/something");
|
||||
QCOMPARE(validUrl->search(), "?search=value");
|
||||
QCOMPARE(validUrl->hash(), "#hash");
|
||||
|
||||
// Valid relative URL
|
||||
QV4::ScopedValue retRel(scope,
|
||||
EVALUATE("new URL('/path/to/something?search=value#hash', "
|
||||
"'https://username:password@example.com:1234')"));
|
||||
QV4::UrlObject *validRelativeUrl = retRel->as<QV4::UrlObject>();
|
||||
QVERIFY(validRelativeUrl != nullptr);
|
||||
|
||||
QCOMPARE(validRelativeUrl->protocol(), "https");
|
||||
QCOMPARE(validRelativeUrl->hostname(), "example.com");
|
||||
QCOMPARE(validRelativeUrl->username(), "username");
|
||||
QCOMPARE(validRelativeUrl->password(), "password");
|
||||
QCOMPARE(validRelativeUrl->port(), "1234");
|
||||
QCOMPARE(validRelativeUrl->host(), "example.com:1234");
|
||||
QCOMPARE(validRelativeUrl->origin(), "https://example.com:1234");
|
||||
QCOMPARE(validRelativeUrl->href(),
|
||||
"https://username:password@example.com:1234/path/to/something?search=value#hash");
|
||||
QCOMPARE(validRelativeUrl->pathname(), "/path/to/something");
|
||||
QCOMPARE(validRelativeUrl->search(), "?search=value");
|
||||
QCOMPARE(validRelativeUrl->hash(), "#hash");
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::urlPropertyInvalid()
|
||||
{
|
||||
QQmlEngine qmlengine;
|
||||
|
||||
QObject *o = new QObject(&qmlengine);
|
||||
|
||||
QV4::ExecutionEngine *engine = qmlengine.handle();
|
||||
QV4::Scope scope(engine);
|
||||
|
||||
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o));
|
||||
|
||||
// Try invalid values on all settable properties
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').hash = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').hostname = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').href = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').password = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').pathname = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').port = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').protocol = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').search = null;"));
|
||||
QVERIFY(EVALUATE_ERROR("new URL('https://localhost').hash = null;"));
|
||||
|
||||
// Make sure that origin does not change after trying to set it
|
||||
QVERIFY(EVALUATE_VALUE("(function() { var url = new URL('https://localhost'); url.origin = "
|
||||
"'http://example.com'; return url.origin;})()",
|
||||
QV4::ScopedValue(scope, scope.engine->newString("https://localhost"))));
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::urlPropertySet()
|
||||
{
|
||||
QQmlEngine qmlengine;
|
||||
|
||||
QObject *o = new QObject(&qmlengine);
|
||||
|
||||
QV4::ExecutionEngine *engine = qmlengine.handle();
|
||||
QV4::Scope scope(engine);
|
||||
|
||||
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o));
|
||||
|
||||
QV4::ScopedValue ret(scope, EVALUATE("this.url = new URL('http://localhost/a/b/c');"));
|
||||
QV4::UrlObject *url = ret->as<QV4::UrlObject>();
|
||||
QVERIFY(url != nullptr);
|
||||
|
||||
// protocol
|
||||
QVERIFY(EVALUATE("this.url.protocol = 'https';"));
|
||||
|
||||
QCOMPARE(url->protocol(), "https");
|
||||
QCOMPARE(url->href(), "https://localhost/a/b/c");
|
||||
QCOMPARE(url->origin(), "https://localhost");
|
||||
|
||||
// port
|
||||
QVERIFY(EVALUATE("this.url.port = 4567;"));
|
||||
|
||||
QCOMPARE(url->port(), "4567");
|
||||
QCOMPARE(url->href(), "https://localhost:4567/a/b/c");
|
||||
QCOMPARE(url->host(), "localhost:4567");
|
||||
QCOMPARE(url->origin(), "https://localhost:4567");
|
||||
|
||||
// hostname
|
||||
QVERIFY(EVALUATE("this.url.hostname = 'foobar.com';"));
|
||||
|
||||
QCOMPARE(url->hostname(), "foobar.com");
|
||||
QCOMPARE(url->href(), "https://foobar.com:4567/a/b/c");
|
||||
QCOMPARE(url->origin(), "https://foobar.com:4567");
|
||||
QCOMPARE(url->host(), "foobar.com:4567");
|
||||
|
||||
// host
|
||||
QVERIFY(EVALUATE("this.url.host = 'test.com:1111';"));
|
||||
|
||||
QCOMPARE(url->host(), "test.com:1111");
|
||||
QCOMPARE(url->hostname(), "test.com");
|
||||
QCOMPARE(url->href(), "https://test.com:1111/a/b/c");
|
||||
QCOMPARE(url->origin(), "https://test.com:1111");
|
||||
|
||||
// username
|
||||
QVERIFY(EVALUATE("this.url.username = 'uname';"));
|
||||
|
||||
QCOMPARE(url->username(), "uname");
|
||||
QCOMPARE(url->href(), "https://uname@test.com:1111/a/b/c");
|
||||
|
||||
// password
|
||||
QVERIFY(EVALUATE("this.url.password = 'pword';"));
|
||||
|
||||
QCOMPARE(url->password(), "pword");
|
||||
QCOMPARE(url->href(), "https://uname:pword@test.com:1111/a/b/c");
|
||||
|
||||
// pathname
|
||||
QVERIFY(EVALUATE("this.url.pathname = '/c/b/a';"));
|
||||
|
||||
QCOMPARE(url->pathname(), "/c/b/a");
|
||||
QCOMPARE(url->href(), "https://uname:pword@test.com:1111/c/b/a");
|
||||
|
||||
// search
|
||||
QVERIFY(EVALUATE("this.url.search = '?key=test';"));
|
||||
|
||||
QCOMPARE(url->search(), "?key=test");
|
||||
QCOMPARE(url->href(), "https://uname:pword@test.com:1111/c/b/a?key=test");
|
||||
|
||||
// hash
|
||||
QVERIFY(EVALUATE("this.url.hash = '#foo';"));
|
||||
|
||||
QCOMPARE(url->hash(), "#foo");
|
||||
QCOMPARE(url->href(), "https://uname:pword@test.com:1111/c/b/a?key=test#foo");
|
||||
|
||||
// href
|
||||
QVERIFY(EVALUATE(
|
||||
"this.url.href = "
|
||||
"'https://username:password@example.com:1234/path/to/something?search=value#hash';"));
|
||||
|
||||
QCOMPARE(url->protocol(), "https");
|
||||
QCOMPARE(url->hostname(), "example.com");
|
||||
QCOMPARE(url->username(), "username");
|
||||
QCOMPARE(url->password(), "password");
|
||||
QCOMPARE(url->port(), "1234");
|
||||
QCOMPARE(url->host(), "example.com:1234");
|
||||
QCOMPARE(url->origin(), "https://example.com:1234");
|
||||
QCOMPARE(url->href(),
|
||||
"https://username:password@example.com:1234/path/to/something?search=value#hash");
|
||||
QCOMPARE(url->pathname(), "/path/to/something");
|
||||
QCOMPARE(url->search(), "?search=value");
|
||||
QCOMPARE(url->hash(), "#hash");
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qqmlecmascript)
|
||||
|
||||
#include "tst_qqmlecmascript.moc"
|
||||
|
|
Loading…
Reference in New Issue