Bug 887364 - URL API for Workers. r=khuey

This commit is contained in:
Andrea Marchesini 2013-09-04 13:07:34 -04:00
Родитель 4c65dc3395
Коммит af0e64af33
7 изменённых файлов: 898 добавлений и 11 удалений

Просмотреть файл

@ -26,6 +26,10 @@ class MediaSource;
class GlobalObject;
struct objectURLOptions;
namespace workers {
class URLProxy;
}
class URL MOZ_FINAL
{
public:
@ -124,6 +128,8 @@ private:
nsRefPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIURI> mURI;
friend class mozilla::dom::workers::URLProxy;
};
}

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
#include "mozilla/dom/WorkerLocationBinding.h"
#include "mozilla/dom/WorkerNavigatorBinding.h"
#include "mozilla/dom/URLBinding.h"
#include "jsfriendapi.h"
BEGIN_WORKERS_NAMESPACE
@ -21,6 +22,7 @@ class XMLHttpRequest;
class XMLHttpRequestUpload;
class WorkerLocation;
class WorkerNavigator;
class URL;
namespace {
@ -54,6 +56,7 @@ SPECIALIZE_PROTO_TRAITS(XMLHttpRequest)
SPECIALIZE_PROTO_TRAITS(XMLHttpRequestUpload)
SPECIALIZE_PROTO_TRAITS(WorkerLocation)
SPECIALIZE_PROTO_TRAITS(WorkerNavigator)
SPECIALIZE_PROTO_TRAITS(URL)
#undef SPECIALIZE_PROTO_TRAITS

Просмотреть файл

@ -14,14 +14,56 @@
#include "nsPIDOMWindow.h"
#include "nsGlobalWindow.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsServiceManagerUtils.h"
#include "nsIDocument.h"
#include "nsIDOMFile.h"
USING_WORKERS_NAMESPACE
#include "DOMBindingInlines.h"
#include "mozilla/dom/URL.h"
#include "nsIIOService.h"
#include "nsNetCID.h"
BEGIN_WORKERS_NAMESPACE
using mozilla::dom::GlobalObject;
// Base class for the Revoke and Create runnable objects.
class URLProxy MOZ_FINAL
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy)
URLProxy(mozilla::dom::URL* aURL)
: mURL(aURL)
{
AssertIsOnMainThread();
}
~URLProxy()
{
MOZ_ASSERT(!mURL);
}
mozilla::dom::URL* URL()
{
return mURL;
}
nsIURI* URI()
{
return mURL->GetURI();
}
void ReleaseURI()
{
AssertIsOnMainThread();
mURL = nullptr;
}
private:
nsRefPtr<mozilla::dom::URL> mURL;
};
// Base class for the URL runnable objects.
class URLRunnable : public nsRunnable
{
protected:
@ -225,13 +267,306 @@ public:
}
};
// This class creates a URL object on the main thread.
class ConstructorRunnable : public URLRunnable
{
private:
const nsString mURL;
const nsString mBase;
nsRefPtr<URLProxy> mBaseProxy;
mozilla::ErrorResult& mRv;
nsRefPtr<URLProxy> mRetval;
public:
ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
const nsAString& aURL, const nsAString& aBase,
mozilla::ErrorResult& aRv)
: URLRunnable(aWorkerPrivate)
, mURL(aURL)
, mBase(aBase)
, mRv(aRv)
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
const nsAString& aURL, URLProxy* aBaseProxy,
mozilla::ErrorResult& aRv)
: URLRunnable(aWorkerPrivate)
, mURL(aURL)
, mBaseProxy(aBaseProxy)
, mRv(aRv)
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
void
MainThreadRun()
{
AssertIsOnMainThread();
nsresult rv;
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv)) {
mRv.Throw(rv);
return;
}
nsCOMPtr<nsIURI> baseURL;
if (!mBaseProxy) {
rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mBase), nullptr, nullptr,
getter_AddRefs(baseURL));
if (NS_FAILED(rv)) {
mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
} else {
baseURL = mBaseProxy->URI();
}
nsCOMPtr<nsIURI> url;
rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mURL), nullptr, baseURL,
getter_AddRefs(url));
if (NS_FAILED(rv)) {
mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
mRetval = new URLProxy(new mozilla::dom::URL(nullptr, url));
}
URLProxy*
GetURLProxy()
{
return mRetval;
}
};
class TeardownRunnable : public nsRunnable
{
public:
TeardownRunnable(URLProxy* aURLProxy)
: mURLProxy(aURLProxy)
{
}
NS_IMETHOD Run()
{
AssertIsOnMainThread();
mURLProxy->ReleaseURI();
mURLProxy = nullptr;
return NS_OK;
}
private:
nsRefPtr<URLProxy> mURLProxy;
};
// This class is the generic getter for any URL property.
class GetterRunnable : public URLRunnable
{
public:
enum GetterType {
GetterHref,
GetterOrigin,
GetterProtocol,
GetterUsername,
GetterPassword,
GetterHost,
GetterHostname,
GetterPort,
GetterPathname,
GetterSearch,
GetterHash,
};
GetterRunnable(WorkerPrivate* aWorkerPrivate,
GetterType aType, nsString& aValue,
URLProxy* aURLProxy)
: URLRunnable(aWorkerPrivate)
, mValue(aValue)
, mType(aType)
, mURLProxy(aURLProxy)
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
void
MainThreadRun()
{
AssertIsOnMainThread();
switch (mType) {
case GetterHref:
mURLProxy->URL()->GetHref(mValue);
break;
case GetterOrigin:
mURLProxy->URL()->GetOrigin(mValue);
break;
case GetterProtocol:
mURLProxy->URL()->GetProtocol(mValue);
break;
case GetterUsername:
mURLProxy->URL()->GetUsername(mValue);
break;
case GetterPassword:
mURLProxy->URL()->GetPassword(mValue);
break;
case GetterHost:
mURLProxy->URL()->GetHost(mValue);
break;
case GetterHostname:
mURLProxy->URL()->GetHostname(mValue);
break;
case GetterPort:
mURLProxy->URL()->GetPort(mValue);
break;
case GetterPathname:
mURLProxy->URL()->GetPathname(mValue);
break;
case GetterSearch:
mURLProxy->URL()->GetSearch(mValue);
break;
case GetterHash:
mURLProxy->URL()->GetHash(mValue);
break;
}
}
private:
nsString& mValue;
GetterType mType;
nsRefPtr<URLProxy> mURLProxy;
};
// This class is the generic setter for any URL property.
class SetterRunnable : public URLRunnable
{
public:
enum SetterType {
SetterHref,
SetterProtocol,
SetterUsername,
SetterPassword,
SetterHost,
SetterHostname,
SetterPort,
SetterPathname,
SetterSearch,
SetterHash,
};
SetterRunnable(WorkerPrivate* aWorkerPrivate,
SetterType aType, const nsAString& aValue,
URLProxy* aURLProxy, mozilla::ErrorResult& aRv)
: URLRunnable(aWorkerPrivate)
, mValue(aValue)
, mType(aType)
, mURLProxy(aURLProxy)
, mRv(aRv)
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
void
MainThreadRun()
{
AssertIsOnMainThread();
switch (mType) {
case SetterHref:
mURLProxy->URL()->SetHref(mValue, mRv);
break;
case SetterProtocol:
mURLProxy->URL()->SetProtocol(mValue);
break;
case SetterUsername:
mURLProxy->URL()->SetUsername(mValue);
break;
case SetterPassword:
mURLProxy->URL()->SetPassword(mValue);
break;
case SetterHost:
mURLProxy->URL()->SetHost(mValue);
break;
case SetterHostname:
mURLProxy->URL()->SetHostname(mValue);
break;
case SetterPort:
mURLProxy->URL()->SetPort(mValue);
break;
case SetterPathname:
mURLProxy->URL()->SetPathname(mValue);
break;
case SetterSearch:
mURLProxy->URL()->SetSearch(mValue);
break;
case SetterHash:
mURLProxy->URL()->SetHash(mValue);
break;
}
}
private:
const nsString mValue;
SetterType mType;
nsRefPtr<URLProxy> mURLProxy;
mozilla::ErrorResult& mRv;
};
// static
URL*
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
JSContext* cx = aGlobal.GetContext();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
nsRefPtr<ConstructorRunnable> runnable =
new ConstructorRunnable(workerPrivate, aUrl, aBase.GetURLProxy(), aRv);
if (!runnable->Dispatch(cx)) {
JS_ReportPendingException(cx);
}
nsRefPtr<URLProxy> proxy = runnable->GetURLProxy();
if (!proxy) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
nsRefPtr<URL> url = new URL(workerPrivate, proxy);
if (!Wrap(aGlobal.GetContext(), aGlobal.Get(), url)) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
return url;
}
// static
@ -239,113 +574,322 @@ URL*
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
const nsAString& aBase, ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
JSContext* cx = aGlobal.GetContext();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
nsRefPtr<ConstructorRunnable> runnable =
new ConstructorRunnable(workerPrivate, aUrl, aBase, aRv);
if (!runnable->Dispatch(cx)) {
JS_ReportPendingException(cx);
}
nsRefPtr<URLProxy> proxy = runnable->GetURLProxy();
if (!proxy) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
nsRefPtr<URL> url = new URL(workerPrivate, proxy);
if (!Wrap(aGlobal.GetContext(), aGlobal.Get(), url)) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
return url;
}
URL::URL(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy)
: DOMBindingBase(aWorkerPrivate->GetJSContext())
, mWorkerPrivate(aWorkerPrivate)
, mURLProxy(aURLProxy)
{
}
URL::~URL()
{
if (mURLProxy) {
nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mURLProxy);
mURLProxy = nullptr;
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_ERROR("Failed to dispatch teardown runnable!");
}
}
}
void
URL::_trace(JSTracer* aTrc)
{
DOMBindingBase::_trace(aTrc);
}
void
URL::_finalize(JSFreeOp* aFop)
{
DOMBindingBase::_finalize(aFop);
}
void
URL::GetHref(nsString& aHref) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
{
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref,
mURLProxy, aRv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetOrigin(nsString& aOrigin) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterOrigin, aOrigin,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetProtocol(nsString& aProtocol) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterProtocol, aProtocol,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetProtocol(const nsAString& aProtocol)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,
aProtocol, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetUsername(nsString& aUsername) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterUsername, aUsername,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetUsername(const nsAString& aUsername)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterUsername,
aUsername, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetPassword(nsString& aPassword) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPassword, aPassword,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetPassword(const nsAString& aPassword)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPassword,
aPassword, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetHost(nsString& aHost) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHost, aHost,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetHost(const nsAString& aHost)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHost,
aHost, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetHostname(nsString& aHostname) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHostname, aHostname,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetHostname(const nsAString& aHostname)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHostname,
aHostname, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetPort(nsString& aPort) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPort, aPort,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetPort(const nsAString& aPort)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPort,
aPort, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetPathname(nsString& aPathname) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterPathname, aPathname,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetPathname(const nsAString& aPathname)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterPathname,
aPathname, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetSearch(nsString& aSearch) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetSearch(const nsAString& aSearch)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch,
aSearch, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::GetHash(nsString& aHash) const
{
nsRefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHash, aHash,
mURLProxy);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
void
URL::SetHash(const nsAString& aHash)
{
ErrorResult rv;
nsRefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHash,
aHash, mURLProxy, rv);
if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
JS_ReportPendingException(mWorkerPrivate->GetJSContext());
}
}
// static
@ -399,3 +943,4 @@ URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl)
}
}
END_WORKERS_NAMESPACE

Просмотреть файл

@ -7,15 +7,30 @@
#ifndef mozilla_dom_workers_url_h__
#define mozilla_dom_workers_url_h__
#include "mozilla/dom/workers/bindings/DOMBindingBase.h"
#include "mozilla/dom/URLBinding.h"
#include "EventTarget.h"
BEGIN_WORKERS_NAMESPACE
class URL : public EventTarget
class URLProxy;
class URL MOZ_FINAL : public DOMBindingBase
{
public: // Methods for WebIDL
public:
URL(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy);
~URL();
virtual void
_trace(JSTracer* aTrc) MOZ_OVERRIDE;
virtual void
_finalize(JSFreeOp* aFop) MOZ_OVERRIDE;
// Methods for WebIDL
static URL*
Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv);
@ -79,12 +94,13 @@ public: // Methods for WebIDL
void SetHash(const nsAString& aHash);
private:
mozilla::dom::URL* GetURL() const
URLProxy* GetURLProxy() const
{
return mURL;
return mURLProxy;
}
nsRefPtr<mozilla::dom::URL> mURL;
WorkerPrivate* mWorkerPrivate;
nsRefPtr<URLProxy> mURLProxy;
};
END_WORKERS_NAMESPACE

Просмотреть файл

@ -108,6 +108,8 @@ MOCHITEST_FILES = \
url_worker.js \
test_bug911085.html \
bug911085_worker.js \
test_urlApi.html \
urlApi_worker.js \
$(NULL)
# Bug 842386 - Disabled on OSX due to intermittent failures.

Просмотреть файл

@ -0,0 +1,45 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for URL API object in workers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var worker = new Worker("urlApi_worker.js");
worker.onmessage = function(event) {
is(event.target, worker);
if (event.data.type == 'finish') {
SimpleTest.finish();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
};
worker.onerror = function(event) {
is(event.target, worker);
ok(false, "Worker had an error: " + event.data);
SimpleTest.finish();
};
worker.postMessage(true);
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,270 @@
function ok(a, msg) {
dump("OK: " + !!a + " => " + a + " " + msg + "\n");
postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
}
function is(a, b, msg) {
dump("IS: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
}
onmessage = function() {
status = false;
try {
if ((URL instanceof Object)) {
status = true;
}
} catch(e) {
}
var tests = [
{ url: 'http://www.abc.com',
base: undefined,
error: false,
href: 'http://www.abc.com/',
origin: 'http://www.abc.com',
protocol: 'http:',
username: '',
password: '',
host: 'www.abc.com',
hostname: 'www.abc.com',
port: '',
pathname: '/',
search: '',
hash: ''
},
{ url: 'ftp://auser:apw@www.abc.com',
base: undefined,
error: false,
href: 'ftp://auser:apw@www.abc.com/',
origin: 'ftp://www.abc.com',
protocol: 'ftp:',
username: 'auser',
password: 'apw',
host: 'www.abc.com',
hostname: 'www.abc.com',
port: '',
pathname: '/',
search: '',
hash: ''
},
{ url: 'http://www.abc.com:90/apath/',
base: undefined,
error: false,
href: 'http://www.abc.com:90/apath/',
origin: 'http://www.abc.com:90',
protocol: 'http:',
username: '',
password: '',
host: 'www.abc.com:90',
hostname: 'www.abc.com',
port: '90',
pathname: '/apath/',
search: '',
hash: ''
},
{ url: 'http://www.abc.com/apath/afile.txt#ahash',
base: undefined,
error: false,
href: 'http://www.abc.com/apath/afile.txt#ahash',
origin: 'http://www.abc.com',
protocol: 'http:',
username: '',
password: '',
host: 'www.abc.com',
hostname: 'www.abc.com',
port: '',
pathname: '/apath/afile.txt',
search: '',
hash: '#ahash'
},
{ url: 'http://example.com/?test#hash',
base: undefined,
error: false,
href: 'http://example.com/?test#hash',
origin: 'http://example.com',
protocol: 'http:',
username: '',
password: '',
host: 'example.com',
hostname: 'example.com',
port: '',
pathname: '/',
search: '?test',
hash: '#hash'
},
{ url: 'http://example.com/?test',
base: undefined,
error: false,
href: 'http://example.com/?test',
origin: 'http://example.com',
protocol: 'http:',
username: '',
password: '',
host: 'example.com',
hostname: 'example.com',
port: '',
pathname: '/',
search: '?test',
hash: ''
},
{ url: 'http://example.com/carrot#question%3f',
base: undefined,
error: false,
hash: '#question?'
},
{ url: 'https://example.com:4443?',
base: undefined,
error: false,
protocol: 'https:',
port: '4443',
pathname: '/',
hash: '',
search: ''
},
{ url: 'http://www.abc.com/apath/afile.txt#ahash?asearch',
base: undefined,
error: false,
href: 'http://www.abc.com/apath/afile.txt#ahash?asearch',
protocol: 'http:',
pathname: '/apath/afile.txt',
hash: '#ahash?asearch',
search: ''
},
{ url: 'http://www.abc.com/apath/afile.txt?asearch#ahash',
base: undefined,
error: false,
href: 'http://www.abc.com/apath/afile.txt?asearch#ahash',
protocol: 'http:',
pathname: '/apath/afile.txt',
hash: '#ahash',
search: '?asearch'
},
{ url: 'http://abc.com/apath/afile.txt?#ahash',
base: undefined,
error: false,
pathname: '/apath/afile.txt',
hash: '#ahash',
search: ''
},
{ url: 'http://auser:apassword@www.abc.com:90/apath/afile.txt?asearch#ahash',
base: undefined,
error: false,
protocol: 'http:',
username: 'auser',
password: 'apassword',
host: 'www.abc.com:90',
hostname: 'www.abc.com',
port: '90',
pathname: '/apath/afile.txt',
hash: '#ahash',
search: '?asearch',
origin: 'http://www.abc.com:90'
},
{ url: '/foo#bar',
base: 'www.test.org',
error: true,
},
{ url: '/foo#bar',
base: null,
error: true,
},
{ url: '/foo#bar',
base: 42,
error: true,
},
{ url: 'ftp://ftp.something.net',
base: undefined,
error: false,
protocol: 'ftp:',
},
{ url: 'file:///tmp/file',
base: undefined,
error: false,
protocol: 'file:',
},
{ url: 'gopher://gopher.something.net',
base: undefined,
error: false,
protocol: 'gopher:',
},
{ url: 'ws://ws.something.net',
base: undefined,
error: false,
protocol: 'ws:',
},
{ url: 'wss://ws.something.net',
base: undefined,
error: false,
protocol: 'wss:',
},
{ url: 'foo://foo.something.net',
base: undefined,
error: false,
protocol: 'foo:',
},
];
while(tests.length) {
var test = tests.shift();
var error = false;
var url;
try {
if (test.base) {
url = new URL(test.url, test.base);
} else {
url = new URL(test.url);
}
} catch(e) {
error = true;
}
is(test.error, error, "Error creating URL");
if (test.error) {
continue;
}
if ('href' in test) is(url.href, test.href, "href");
if ('origin' in test) is(url.origin, test.origin, "origin");
if ('protocol' in test) is(url.protocol, test.protocol, "protocol");
if ('username' in test) is(url.username, test.username, "username");
if ('password' in test) is(url.password, test.password, "password");
if ('host' in test) is(url.host, test.host, "host");
if ('hostname' in test) is(url.hostname, test.hostname, "hostname");
if ('port' in test) is(url.port, test.port, "port");
if ('pathname' in test) is(url.pathname, test.pathname, "pathname");
if ('search' in test) is(url.search, test.search, "search");
if ('hash' in test) is(url.hash, test.hash, "hash");
url = new URL('https://www.example.net/what#foo?bar');
ok(url, "Url exists!");
if ('href' in test) url.href = test.href;
if ('protocol' in test) url.protocol = test.protocol;
if ('username' in test && test.username) url.username = test.username;
if ('password' in test && test.password) url.password = test.password;
if ('host' in test) url.host = test.host;
if ('hostname' in test) url.hostname = test.hostname;
if ('port' in test) url.port = test.port;
if ('pathname' in test) url.pathname = test.pathname;
if ('search' in test) url.search = test.search;
if ('hash' in test) url.hash = test.hash;
if ('href' in test) is(url.href, test.href, "href");
if ('origin' in test) is(url.origin, test.origin, "origin");
if ('protocol' in test) is(url.protocol, test.protocol, "protocol");
if ('username' in test) is(url.username, test.username, "username");
if ('password' in test) is(url.password, test.password, "password");
if ('host' in test) is(url.host, test.host, "host");
if ('hostname' in test) is(test.hostname, url.hostname, "hostname");
if ('port' in test) is(test.port, url.port, "port");
if ('pathname' in test) is(test.pathname, url.pathname, "pathname");
if ('search' in test) is(test.search, url.search, "search");
if ('hash' in test) is(test.hash, url.hash, "hash");
}
postMessage({type: 'finish' });
}