Bug 965990 - Allow URLSearchParams objects to be associated with multiple URLs, r=ehsan

This commit is contained in:
Andrea Marchesini 2014-02-03 16:48:38 +00:00
parent 600a53b971
commit 893a19e4bb
11 changed files with 175 additions and 179 deletions

View File

@ -217,9 +217,7 @@ void
Link::SetSearch(const nsAString& aSearch) Link::SetSearch(const nsAString& aSearch)
{ {
SetSearchInternal(aSearch); SetSearchInternal(aSearch);
if (mSearchParams) { UpdateURLSearchParams();
mSearchParams->Invalidate();
}
} }
void void
@ -487,9 +485,7 @@ Link::ResetLinkState(bool aNotify, bool aHasHref)
// If we've cached the URI, reset always invalidates it. // If we've cached the URI, reset always invalidates it.
mCachedURI = nullptr; mCachedURI = nullptr;
if (mSearchParams) { UpdateURLSearchParams();
mSearchParams->Invalidate();
}
// Update our state back to the default. // Update our state back to the default.
mLinkState = defaultState; mLinkState = defaultState;
@ -589,16 +585,13 @@ Link::SetSearchParams(URLSearchParams* aSearchParams)
return; return;
} }
if (!aSearchParams->HasURLAssociated()) { if (mSearchParams) {
MOZ_ASSERT(aSearchParams->IsValid()); mSearchParams->RemoveObserver(this);
mSearchParams = aSearchParams;
mSearchParams->SetObserver(this);
} else {
CreateSearchParamsIfNeeded();
mSearchParams->CopyFromURLSearchParams(*aSearchParams);
} }
mSearchParams = aSearchParams;
mSearchParams->AddObserver(this);
nsAutoString search; nsAutoString search;
mSearchParams->Serialize(search); mSearchParams->Serialize(search);
SetSearchInternal(search); SetSearchInternal(search);
@ -607,7 +600,7 @@ Link::SetSearchParams(URLSearchParams* aSearchParams)
void void
Link::URLSearchParamsUpdated() Link::URLSearchParamsUpdated()
{ {
MOZ_ASSERT(mSearchParams && mSearchParams->IsValid()); MOZ_ASSERT(mSearchParams);
nsString search; nsString search;
mSearchParams->Serialize(search); mSearchParams->Serialize(search);
@ -615,9 +608,11 @@ Link::URLSearchParamsUpdated()
} }
void void
Link::URLSearchParamsNeedsUpdates() Link::UpdateURLSearchParams()
{ {
MOZ_ASSERT(mSearchParams); if (!mSearchParams) {
return;
}
nsAutoCString search; nsAutoCString search;
nsCOMPtr<nsIURI> uri(GetURI()); nsCOMPtr<nsIURI> uri(GetURI());
@ -629,7 +624,7 @@ Link::URLSearchParamsNeedsUpdates()
} }
} }
mSearchParams->ParseInput(search); mSearchParams->ParseInput(search, this);
} }
void void
@ -637,15 +632,18 @@ Link::CreateSearchParamsIfNeeded()
{ {
if (!mSearchParams) { if (!mSearchParams) {
mSearchParams = new URLSearchParams(); mSearchParams = new URLSearchParams();
mSearchParams->SetObserver(this); mSearchParams->AddObserver(this);
mSearchParams->Invalidate(); UpdateURLSearchParams();
} }
} }
void void
Link::Unlink() Link::Unlink()
{ {
mSearchParams = nullptr; if (mSearchParams) {
mSearchParams->RemoveObserver(this);
mSearchParams = nullptr;
}
} }
void void

View File

@ -114,7 +114,6 @@ public:
// URLSearchParamsObserver // URLSearchParamsObserver
void URLSearchParamsUpdated() MOZ_OVERRIDE; void URLSearchParamsUpdated() MOZ_OVERRIDE;
void URLSearchParamsNeedsUpdates() MOZ_OVERRIDE;
protected: protected:
virtual ~Link(); virtual ~Link();
@ -134,6 +133,8 @@ protected:
nsIURI* GetCachedURI() const { return mCachedURI; } nsIURI* GetCachedURI() const { return mCachedURI; }
bool HasCachedURI() const { return !!mCachedURI; } bool HasCachedURI() const { return !!mCachedURI; }
void UpdateURLSearchParams();
// CC methods // CC methods
void Unlink(); void Unlink();
void Traverse(nsCycleCollectionTraversalCallback &cb); void Traverse(nsCycleCollectionTraversalCallback &cb);

View File

@ -20,7 +20,18 @@
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
NS_IMPL_CYCLE_COLLECTION_1(URL, mSearchParams) NS_IMPL_CYCLE_COLLECTION_CLASS(URL)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(URL)
if (tmp->mSearchParams) {
tmp->mSearchParams->RemoveObserver(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(URL)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSearchParams)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(URL) NS_IMPL_CYCLE_COLLECTING_ADDREF(URL)
NS_IMPL_CYCLE_COLLECTING_RELEASE(URL) NS_IMPL_CYCLE_COLLECTING_RELEASE(URL)
@ -221,10 +232,7 @@ URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
} }
aRv = mURI->SetSpec(href); aRv = mURI->SetSpec(href);
UpdateURLSearchParams();
if (mSearchParams) {
mSearchParams->Invalidate();
}
} }
void void
@ -304,7 +312,7 @@ URL::SetHost(const nsAString& aHost)
void void
URL::URLSearchParamsUpdated() URL::URLSearchParamsUpdated()
{ {
MOZ_ASSERT(mSearchParams && mSearchParams->IsValid()); MOZ_ASSERT(mSearchParams);
nsAutoString search; nsAutoString search;
mSearchParams->Serialize(search); mSearchParams->Serialize(search);
@ -312,9 +320,11 @@ URL::URLSearchParamsUpdated()
} }
void void
URL::URLSearchParamsNeedsUpdates() URL::UpdateURLSearchParams()
{ {
MOZ_ASSERT(mSearchParams); if (!mSearchParams) {
return;
}
nsAutoCString search; nsAutoCString search;
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI)); nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
@ -325,7 +335,7 @@ URL::URLSearchParamsNeedsUpdates()
} }
} }
mSearchParams->ParseInput(search); mSearchParams->ParseInput(search, this);
} }
void void
@ -426,10 +436,7 @@ void
URL::SetSearch(const nsAString& aSearch) URL::SetSearch(const nsAString& aSearch)
{ {
SetSearchInternal(aSearch); SetSearchInternal(aSearch);
UpdateURLSearchParams();
if (mSearchParams) {
mSearchParams->Invalidate();
}
} }
void void
@ -458,16 +465,14 @@ URL::SetSearchParams(URLSearchParams* aSearchParams)
return; return;
} }
if (!aSearchParams->HasURLAssociated()) { if (mSearchParams) {
MOZ_ASSERT(aSearchParams->IsValid()); mSearchParams->RemoveObserver(this);
mSearchParams = aSearchParams;
mSearchParams->SetObserver(this);
} else {
CreateSearchParamsIfNeeded();
mSearchParams->CopyFromURLSearchParams(*aSearchParams);
} }
// the observer will be cleared using the cycle collector.
mSearchParams = aSearchParams;
mSearchParams->AddObserver(this);
nsAutoString search; nsAutoString search;
mSearchParams->Serialize(search); mSearchParams->Serialize(search);
SetSearchInternal(search); SetSearchInternal(search);
@ -506,8 +511,8 @@ URL::CreateSearchParamsIfNeeded()
{ {
if (!mSearchParams) { if (!mSearchParams) {
mSearchParams = new URLSearchParams(); mSearchParams = new URLSearchParams();
mSearchParams->SetObserver(this); mSearchParams->AddObserver(this);
mSearchParams->Invalidate(); UpdateURLSearchParams();
} }
} }

View File

@ -125,7 +125,6 @@ public:
// URLSearchParamsObserver // URLSearchParamsObserver
void URLSearchParamsUpdated() MOZ_OVERRIDE; void URLSearchParamsUpdated() MOZ_OVERRIDE;
void URLSearchParamsNeedsUpdates() MOZ_OVERRIDE;
private: private:
nsIURI* GetURI() const nsIURI* GetURI() const
@ -137,6 +136,8 @@ private:
void SetSearchInternal(const nsAString& aSearch); void SetSearchInternal(const nsAString& aSearch);
void UpdateURLSearchParams();
static void CreateObjectURLInternal(const GlobalObject& aGlobal, static void CreateObjectURLInternal(const GlobalObject& aGlobal,
nsISupports* aObject, nsISupports* aObject,
const nsACString& aScheme, const nsACString& aScheme,

View File

@ -9,7 +9,7 @@
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(URLSearchParams, mObserver) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(URLSearchParams, mObservers)
NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearchParams) NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearchParams)
NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams) NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams)
@ -19,7 +19,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URLSearchParams)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
URLSearchParams::URLSearchParams() URLSearchParams::URLSearchParams()
: mValid(false)
{ {
SetIsDOMBinding(); SetIsDOMBinding();
} }
@ -41,7 +40,7 @@ URLSearchParams::Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv) ErrorResult& aRv)
{ {
nsRefPtr<URLSearchParams> sp = new URLSearchParams(); nsRefPtr<URLSearchParams> sp = new URLSearchParams();
sp->ParseInput(NS_ConvertUTF16toUTF8(aInit)); sp->ParseInput(NS_ConvertUTF16toUTF8(aInit), nullptr);
return sp.forget(); return sp.forget();
} }
@ -52,12 +51,12 @@ URLSearchParams::Constructor(const GlobalObject& aGlobal,
{ {
nsRefPtr<URLSearchParams> sp = new URLSearchParams(); nsRefPtr<URLSearchParams> sp = new URLSearchParams();
aInit.mSearchParams.EnumerateRead(CopyEnumerator, sp); aInit.mSearchParams.EnumerateRead(CopyEnumerator, sp);
sp->mValid = true;
return sp.forget(); return sp.forget();
} }
void void
URLSearchParams::ParseInput(const nsACString& aInput) URLSearchParams::ParseInput(const nsACString& aInput,
URLSearchParamsObserver* aObserver)
{ {
// Remove all the existing data before parsing a new input. // Remove all the existing data before parsing a new input.
DeleteAll(); DeleteAll();
@ -109,7 +108,7 @@ URLSearchParams::ParseInput(const nsACString& aInput)
NS_ConvertUTF8toUTF16(decodedValue)); NS_ConvertUTF8toUTF16(decodedValue));
} }
mValid = true; NotifyObservers(aObserver);
} }
void void
@ -165,18 +164,6 @@ URLSearchParams::DecodeString(const nsACString& aInput, nsACString& aOutput)
} }
} }
void
URLSearchParams::CopyFromURLSearchParams(URLSearchParams& aSearchParams)
{
// The other SearchParams must be valid before copying its data.
aSearchParams.Validate();
// Remove all the existing data before parsing a new input.
DeleteAll();
aSearchParams.mSearchParams.EnumerateRead(CopyEnumerator, this);
mValid = true;
}
/* static */ PLDHashOperator /* static */ PLDHashOperator
URLSearchParams::CopyEnumerator(const nsAString& aName, URLSearchParams::CopyEnumerator(const nsAString& aName,
nsTArray<nsString>* aArray, nsTArray<nsString>* aArray,
@ -192,27 +179,23 @@ URLSearchParams::CopyEnumerator(const nsAString& aName,
} }
void void
URLSearchParams::SetObserver(URLSearchParamsObserver* aObserver) URLSearchParams::AddObserver(URLSearchParamsObserver* aObserver)
{ {
MOZ_ASSERT(!mObserver); MOZ_ASSERT(aObserver);
mObserver = aObserver; MOZ_ASSERT(!mObservers.Contains(aObserver));
mObservers.AppendElement(aObserver);
} }
void void
URLSearchParams::Validate() URLSearchParams::RemoveObserver(URLSearchParamsObserver* aObserver)
{ {
MOZ_ASSERT(mValid || mObserver); MOZ_ASSERT(aObserver);
if (!mValid) { mObservers.RemoveElement(aObserver);
mObserver->URLSearchParamsNeedsUpdates();
MOZ_ASSERT(mValid);
}
} }
void void
URLSearchParams::Get(const nsAString& aName, nsString& aRetval) URLSearchParams::Get(const nsAString& aName, nsString& aRetval)
{ {
Validate();
nsTArray<nsString>* array; nsTArray<nsString>* array;
if (!mSearchParams.Get(aName, &array)) { if (!mSearchParams.Get(aName, &array)) {
aRetval.Truncate(); aRetval.Truncate();
@ -225,8 +208,6 @@ URLSearchParams::Get(const nsAString& aName, nsString& aRetval)
void void
URLSearchParams::GetAll(const nsAString& aName, nsTArray<nsString>& aRetval) URLSearchParams::GetAll(const nsAString& aName, nsTArray<nsString>& aRetval)
{ {
Validate();
nsTArray<nsString>* array; nsTArray<nsString>* array;
if (!mSearchParams.Get(aName, &array)) { if (!mSearchParams.Get(aName, &array)) {
return; return;
@ -238,10 +219,6 @@ URLSearchParams::GetAll(const nsAString& aName, nsTArray<nsString>& aRetval)
void void
URLSearchParams::Set(const nsAString& aName, const nsAString& aValue) URLSearchParams::Set(const nsAString& aName, const nsAString& aValue)
{ {
// Before setting any new value we have to be sure to have all the previous
// values in place.
Validate();
nsTArray<nsString>* array; nsTArray<nsString>* array;
if (!mSearchParams.Get(aName, &array)) { if (!mSearchParams.Get(aName, &array)) {
array = new nsTArray<nsString>(); array = new nsTArray<nsString>();
@ -251,18 +228,14 @@ URLSearchParams::Set(const nsAString& aName, const nsAString& aValue)
array->ElementAt(0) = aValue; array->ElementAt(0) = aValue;
} }
NotifyObserver(); NotifyObservers(nullptr);
} }
void void
URLSearchParams::Append(const nsAString& aName, const nsAString& aValue) URLSearchParams::Append(const nsAString& aName, const nsAString& aValue)
{ {
// Before setting any new value we have to be sure to have all the previous
// values in place.
Validate();
AppendInternal(aName, aValue); AppendInternal(aName, aValue);
NotifyObserver(); NotifyObservers(nullptr);
} }
void void
@ -280,17 +253,12 @@ URLSearchParams::AppendInternal(const nsAString& aName, const nsAString& aValue)
bool bool
URLSearchParams::Has(const nsAString& aName) URLSearchParams::Has(const nsAString& aName)
{ {
Validate();
return mSearchParams.Get(aName, nullptr); return mSearchParams.Get(aName, nullptr);
} }
void void
URLSearchParams::Delete(const nsAString& aName) URLSearchParams::Delete(const nsAString& aName)
{ {
// Before deleting any value we have to be sure to have all the previous
// values in place.
Validate();
nsTArray<nsString>* array; nsTArray<nsString>* array;
if (!mSearchParams.Get(aName, &array)) { if (!mSearchParams.Get(aName, &array)) {
return; return;
@ -298,7 +266,7 @@ URLSearchParams::Delete(const nsAString& aName)
mSearchParams.Remove(aName); mSearchParams.Remove(aName);
NotifyObserver(); NotifyObservers(nullptr);
} }
void void
@ -343,8 +311,6 @@ public:
void void
URLSearchParams::Serialize(nsAString& aValue) const URLSearchParams::Serialize(nsAString& aValue) const
{ {
MOZ_ASSERT(mValid);
SerializeData data; SerializeData data;
mSearchParams.EnumerateRead(SerializeEnumerator, &data); mSearchParams.EnumerateRead(SerializeEnumerator, &data);
aValue.Assign(data.mValue); aValue.Assign(data.mValue);
@ -373,18 +339,14 @@ URLSearchParams::SerializeEnumerator(const nsAString& aName,
} }
void void
URLSearchParams::NotifyObserver() URLSearchParams::NotifyObservers(URLSearchParamsObserver* aExceptObserver)
{ {
if (mObserver) { for (uint32_t i = 0; i < mObservers.Length(); ++i) {
mObserver->URLSearchParamsUpdated(); if (mObservers[i] != aExceptObserver) {
mObservers[i]->URLSearchParamsUpdated();
}
} }
} }
void
URLSearchParams::Invalidate()
{
mValid = false;
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -23,7 +23,6 @@ public:
virtual ~URLSearchParamsObserver() {} virtual ~URLSearchParamsObserver() {}
virtual void URLSearchParamsUpdated() = 0; virtual void URLSearchParamsUpdated() = 0;
virtual void URLSearchParamsNeedsUpdates() = 0;
}; };
class URLSearchParams MOZ_FINAL : public nsISupports, class URLSearchParams MOZ_FINAL : public nsISupports,
@ -36,11 +35,6 @@ public:
URLSearchParams(); URLSearchParams();
~URLSearchParams(); ~URLSearchParams();
bool HasURLAssociated() const
{
return !!mObserver;
}
// WebIDL methods // WebIDL methods
nsISupports* GetParentObject() const nsISupports* GetParentObject() const
{ {
@ -58,18 +52,11 @@ public:
Constructor(const GlobalObject& aGlobal, URLSearchParams& aInit, Constructor(const GlobalObject& aGlobal, URLSearchParams& aInit,
ErrorResult& aRv); ErrorResult& aRv);
void ParseInput(const nsACString& aInput); void ParseInput(const nsACString& aInput,
URLSearchParamsObserver* aObserver);
void CopyFromURLSearchParams(URLSearchParams& aSearchParams); void AddObserver(URLSearchParamsObserver* aObserver);
void RemoveObserver(URLSearchParamsObserver* aObserver);
void SetObserver(URLSearchParamsObserver* aObserver);
void Invalidate();
bool IsValid() const
{
return mValid;
}
void Serialize(nsAString& aValue) const; void Serialize(nsAString& aValue) const;
@ -87,7 +74,6 @@ public:
void Stringify(nsString& aRetval) void Stringify(nsString& aRetval)
{ {
Validate();
Serialize(aRetval); Serialize(aRetval);
} }
@ -98,7 +84,7 @@ private:
void DecodeString(const nsACString& aInput, nsACString& aOutput); void DecodeString(const nsACString& aInput, nsACString& aOutput);
void NotifyObserver(); void NotifyObservers(URLSearchParamsObserver* aExceptObserver);
static PLDHashOperator static PLDHashOperator
CopyEnumerator(const nsAString& aName, nsTArray<nsString>* aArray, CopyEnumerator(const nsAString& aName, nsTArray<nsString>* aArray,
@ -108,14 +94,9 @@ private:
SerializeEnumerator(const nsAString& aName, nsTArray<nsString>* aArray, SerializeEnumerator(const nsAString& aName, nsTArray<nsString>* aArray,
void *userData); void *userData);
void
Validate();
nsClassHashtable<nsStringHashKey, nsTArray<nsString>> mSearchParams; nsClassHashtable<nsStringHashKey, nsTArray<nsString>> mSearchParams;
nsRefPtr<URLSearchParamsObserver> mObserver; nsTArray<nsRefPtr<URLSearchParamsObserver>> mObservers;
bool mValid;
}; };
} // namespace dom } // namespace dom

View File

@ -137,7 +137,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887836
var url2 = new URL('http://www.example.net?e=f'); var url2 = new URL('http://www.example.net?e=f');
url.searchParams = url2.searchParams; url.searchParams = url2.searchParams;
isnot(url.searchParams, url2.searchParams, "URL.searchParams is not the same object"); is(url.searchParams, url2.searchParams, "URL.searchParams is not the same object");
is(url.searchParams.get('e'), 'f', "URL.searchParams.get('e')"); is(url.searchParams.get('e'), 'f', "URL.searchParams.get('e')");
url.href = "http://www.example.net?bar=foo"; url.href = "http://www.example.net?bar=foo";
@ -170,7 +170,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887836
var url2 = new URL('http://www.example.net?e=f'); var url2 = new URL('http://www.example.net?e=f');
e.searchParams = url2.searchParams; e.searchParams = url2.searchParams;
isnot(e.searchParams, url2.searchParams, "e.searchParams is not the same object"); is(e.searchParams, url2.searchParams, "e.searchParams is not the same object");
is(e.searchParams.get('e'), 'f', "e.searchParams.get('e')"); is(e.searchParams.get('e'), 'f', "e.searchParams.get('e')");
e.href = "http://www.example.net?bar=foo"; e.href = "http://www.example.net?bar=foo";
@ -203,6 +203,45 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887836
runTest(); runTest();
} }
function testMultiURL() {
var a = new URL('http://www.example.net?a=b&c=d');
var b = new URL('http://www.example.net?e=f');
var c = document.createElement('a');
var d = document.createElement('area');
ok(a.searchParams.has('a'), "a.searchParams.has('a')");
ok(a.searchParams.has('c'), "a.searchParams.has('c')");
ok(b.searchParams.has('e'), "b.searchParams.has('e')");
ok(c.searchParams, "c.searchParams");
ok(d.searchParams, "d.searchParams");
var u = new URLSearchParams();
a.searchParams = b.searchParams = c.searchParams = d.searchParams = u;
is(a.searchParams, u, "a.searchParams === u");
is(b.searchParams, u, "b.searchParams === u");
is(c.searchParams, u, "c.searchParams === u");
is(d.searchParams, u, "d.searchParams === u");
ok(!a.searchParams.has('a'), "!a.searchParams.has('a')");
ok(!a.searchParams.has('c'), "!a.searchParams.has('c')");
ok(!b.searchParams.has('e'), "!b.searchParams.has('e')");
u.append('foo', 'bar');
is(a.searchParams.get('foo'), 'bar', "a has foo=bar");
is(b.searchParams.get('foo'), 'bar', "b has foo=bar");
is(c.searchParams.get('foo'), 'bar', "c has foo=bar");
is(d.searchParams.get('foo'), 'bar', "d has foo=bar");
is(a + "", b + "", "stringify a == b");
is(c.searchParams + "", b.searchParams + "", "stringify c.searchParams == b.searchParams");
is(d.searchParams + "", b.searchParams + "", "stringify d.searchParams == b.searchParams");
a.search = "?bar=foo";
is(a.searchParams.get('bar'), 'foo', "a has bar=foo");
is(b.searchParams.get('bar'), 'foo', "b has bar=foo");
is(c.searchParams.get('bar'), 'foo', "c has bar=foo");
is(d.searchParams.get('bar'), 'foo', "d has bar=foo");
runTest();
}
var tests = [ var tests = [
testSimpleURLSearchParams, testSimpleURLSearchParams,
testCopyURLSearchParams, testCopyURLSearchParams,
@ -210,7 +249,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=887836
testURL, testURL,
function() { testElement(document.getElementById('anchor')) }, function() { testElement(document.getElementById('anchor')) },
function() { testElement(document.getElementById('area')) }, function() { testElement(document.getElementById('area')) },
testEncoding testEncoding,
testMultiURL
]; ];
function runTest() { function runTest() {

View File

@ -615,9 +615,7 @@ URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
JS_ReportPendingException(mWorkerPrivate->GetJSContext()); JS_ReportPendingException(mWorkerPrivate->GetJSContext());
} }
if (mSearchParams) { UpdateURLSearchParams();
mSearchParams->Invalidate();
}
} }
void void
@ -823,10 +821,7 @@ void
URL::SetSearch(const nsAString& aSearch) URL::SetSearch(const nsAString& aSearch)
{ {
SetSearchInternal(aSearch); SetSearchInternal(aSearch);
UpdateURLSearchParams();
if (mSearchParams) {
mSearchParams->Invalidate();
}
} }
void void
@ -856,16 +851,12 @@ URL::SetSearchParams(URLSearchParams* aSearchParams)
return; return;
} }
if (!aSearchParams->HasURLAssociated()) { if (mSearchParams) {
MOZ_ASSERT(aSearchParams->IsValid()); mSearchParams->RemoveObserver(this);
mSearchParams = aSearchParams;
mSearchParams->SetObserver(this);
} else {
CreateSearchParamsIfNeeded();
mSearchParams->CopyFromURLSearchParams(*aSearchParams);
} }
mSearchParams = aSearchParams;
mSearchParams->AddObserver(this);
nsString search; nsString search;
mSearchParams->Serialize(search); mSearchParams->Serialize(search);
@ -951,7 +942,7 @@ URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aUrl)
void void
URL::URLSearchParamsUpdated() URL::URLSearchParamsUpdated()
{ {
MOZ_ASSERT(mSearchParams && mSearchParams->IsValid()); MOZ_ASSERT(mSearchParams);
nsString search; nsString search;
mSearchParams->Serialize(search); mSearchParams->Serialize(search);
@ -959,13 +950,13 @@ URL::URLSearchParamsUpdated()
} }
void void
URL::URLSearchParamsNeedsUpdates() URL::UpdateURLSearchParams()
{ {
MOZ_ASSERT(mSearchParams); if (mSearchParams) {
nsString search;
nsString search; GetSearch(search);
GetSearch(search); mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)), this);
mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1))); }
} }
void void
@ -973,8 +964,8 @@ URL::CreateSearchParamsIfNeeded()
{ {
if (!mSearchParams) { if (!mSearchParams) {
mSearchParams = new URLSearchParams(); mSearchParams = new URLSearchParams();
mSearchParams->SetObserver(this); mSearchParams->AddObserver(this);
mSearchParams->Invalidate(); UpdateURLSearchParams();
} }
} }

View File

@ -119,7 +119,6 @@ public:
// IURLSearchParamsObserver // IURLSearchParamsObserver
void URLSearchParamsUpdated() MOZ_OVERRIDE; void URLSearchParamsUpdated() MOZ_OVERRIDE;
void URLSearchParamsNeedsUpdates() MOZ_OVERRIDE;
private: private:
URLProxy* GetURLProxy() const URLProxy* GetURLProxy() const
@ -131,6 +130,8 @@ private:
void SetSearchInternal(const nsAString& aSearch); void SetSearchInternal(const nsAString& aSearch);
void UpdateURLSearchParams();
WorkerPrivate* mWorkerPrivate; WorkerPrivate* mWorkerPrivate;
nsRefPtr<URLProxy> mURLProxy; nsRefPtr<URLProxy> mURLProxy;
nsRefPtr<URLSearchParams> mSearchParams; nsRefPtr<URLSearchParams> mSearchParams;

View File

@ -8,11 +8,6 @@ function is(a, b, msg) {
postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg }); postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
} }
function isnot(a, b, msg) {
dump("ISNOT: " + (a!==b) + " => " + a + " | " + b + " " + msg + "\n");
postMessage({type: 'status', status: a !== b, msg: a + " !== " + b + ": " + msg });
}
onmessage = function() { onmessage = function() {
status = false; status = false;
try { try {
@ -134,7 +129,7 @@ onmessage = function() {
var url2 = new URL('http://www.example.net?e=f'); var url2 = new URL('http://www.example.net?e=f');
url.searchParams = url2.searchParams; url.searchParams = url2.searchParams;
isnot(url.searchParams, url2.searchParams, "URL.searchParams is not the same object"); is(url.searchParams, url2.searchParams, "URL.searchParams is not the same object");
is(url.searchParams.get('e'), 'f', "URL.searchParams.get('e')"); is(url.searchParams.get('e'), 'f', "URL.searchParams.get('e')");
url.href = "http://www.example.net?bar=foo"; url.href = "http://www.example.net?bar=foo";
@ -164,12 +159,39 @@ onmessage = function() {
runTest(); runTest();
} }
function testMultiURL() {
var a = new URL('http://www.example.net?a=b&c=d');
var b = new URL('http://www.example.net?e=f');
ok(a.searchParams.has('a'), "a.searchParams.has('a')");
ok(a.searchParams.has('c'), "a.searchParams.has('c')");
ok(b.searchParams.has('e'), "b.searchParams.has('e')");
var u = new URLSearchParams();
a.searchParams = b.searchParams = u;
is(a.searchParams, u, "a.searchParams === u");
is(b.searchParams, u, "b.searchParams === u");
ok(!a.searchParams.has('a'), "!a.searchParams.has('a')");
ok(!a.searchParams.has('c'), "!a.searchParams.has('c')");
ok(!b.searchParams.has('e'), "!b.searchParams.has('e')");
u.append('foo', 'bar');
is(a.searchParams.get('foo'), 'bar', "a has foo=bar");
is(b.searchParams.get('foo'), 'bar', "b has foo=bar");
is(a + "", b + "", "stringify a == b");
a.search = "?bar=foo";
is(a.searchParams.get('bar'), 'foo', "a has bar=foo");
is(b.searchParams.get('bar'), 'foo', "b has bar=foo");
runTest();
}
var tests = [ var tests = [
testSimpleURLSearchParams, testSimpleURLSearchParams,
testCopyURLSearchParams, testCopyURLSearchParams,
testParserURLSearchParams, testParserURLSearchParams,
testURL, testURL,
testEncoding testEncoding,
testMultiURL
]; ];
function runTest() { function runTest() {

View File

@ -123,9 +123,9 @@ Link::URLSearchParamsUpdated()
} }
void void
Link::URLSearchParamsNeedsUpdates() Link::UpdateURLSearchParams()
{ {
NS_NOTREACHED("Unexpected call to Link::URLSearchParamsNeedsUpdates"); NS_NOTREACHED("Unexpected call to Link::UpdateURLSearchParams");
} }
NS_IMPL_CYCLE_COLLECTION_CLASS(URLSearchParams) NS_IMPL_CYCLE_COLLECTION_CLASS(URLSearchParams)
@ -159,19 +159,20 @@ URLSearchParams::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
} }
void void
URLSearchParams::ParseInput(const nsACString& aInput) URLSearchParams::ParseInput(const nsACString& aInput,
URLSearchParamsObserver* aObserver)
{ {
NS_NOTREACHED("Unexpected call to URLSearchParams::ParseInput"); NS_NOTREACHED("Unexpected call to URLSearchParams::ParseInput");
} }
void void
URLSearchParams::CopyFromURLSearchParams(URLSearchParams& aSearchParams) URLSearchParams::AddObserver(URLSearchParamsObserver* aObserver)
{ {
NS_NOTREACHED("Unexpected call to URLSearchParams::CopyFromURLSearchParams"); NS_NOTREACHED("Unexpected call to URLSearchParams::SetObserver");
} }
void void
URLSearchParams::SetObserver(URLSearchParamsObserver* aObserver) URLSearchParams::RemoveObserver(URLSearchParamsObserver* aObserver)
{ {
NS_NOTREACHED("Unexpected call to URLSearchParams::SetObserver"); NS_NOTREACHED("Unexpected call to URLSearchParams::SetObserver");
} }
@ -232,18 +233,11 @@ URLSearchParams::DeleteAll()
} }
void void
URLSearchParams::NotifyObserver() URLSearchParams::NotifyObservers(URLSearchParamsObserver* aExceptObserver)
{ {
NS_NOTREACHED("Unexpected call to URLSearchParams::NotifyObserver"); NS_NOTREACHED("Unexpected call to URLSearchParams::NotifyObservers");
} }
void
URLSearchParams::Invalidate()
{
NS_NOTREACHED("Unexpected call to URLSearchParams::Invalidate");
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla