Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / dom / url / URLSearchParams.cpp
blob3bd08a9020b712f8dc5cedd5e1da768fad04014c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/URLSearchParams.h"
9 // XXX encoding_rs.h is not self-contained, this order is required
10 #include "mozilla/Encoding.h"
11 #include "encoding_rs.h"
13 #include <new>
14 #include <type_traits>
15 #include <utility>
16 #include "js/StructuredClone.h"
17 #include "mozilla/ArrayIterator.h"
18 #include "mozilla/Attributes.h"
19 #include "mozilla/ErrorResult.h"
20 #include "mozilla/MacroForEach.h"
21 #include "mozilla/NotNull.h"
22 #include "mozilla/dom/BindingDeclarations.h"
23 #include "mozilla/dom/Record.h"
24 #include "mozilla/dom/StructuredCloneHolder.h"
25 #include "mozilla/dom/URLSearchParamsBinding.h"
26 #include "mozilla/fallible.h"
27 #include "nsDOMString.h"
28 #include "nsError.h"
29 #include "nsIGlobalObject.h"
30 #include "nsLiteralString.h"
31 #include "nsPrintfCString.h"
32 #include "nsString.h"
33 #include "nsStringFlags.h"
34 #include "nsStringIterator.h"
35 #include "nsStringStream.h"
36 #include "nsURLHelper.h"
38 namespace mozilla::dom {
40 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(URLSearchParams, mParent, mObserver)
41 NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearchParams)
42 NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams)
44 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URLSearchParams)
45 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
46 NS_INTERFACE_MAP_ENTRY(nsISupports)
47 NS_INTERFACE_MAP_END
49 URLSearchParams::URLSearchParams(nsISupports* aParent,
50 URLSearchParamsObserver* aObserver)
51 : mParams(new URLParams()), mParent(aParent), mObserver(aObserver) {}
53 URLSearchParams::~URLSearchParams() { DeleteAll(); }
55 JSObject* URLSearchParams::WrapObject(JSContext* aCx,
56 JS::Handle<JSObject*> aGivenProto) {
57 return URLSearchParams_Binding::Wrap(aCx, this, aGivenProto);
60 /* static */
61 already_AddRefed<URLSearchParams> URLSearchParams::Constructor(
62 const GlobalObject& aGlobal,
63 const USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString& aInit,
64 ErrorResult& aRv) {
65 RefPtr<URLSearchParams> sp =
66 new URLSearchParams(aGlobal.GetAsSupports(), nullptr);
68 if (aInit.IsUSVString()) {
69 NS_ConvertUTF16toUTF8 input(aInit.GetAsUSVString());
70 if (StringBeginsWith(input, "?"_ns)) {
71 sp->ParseInput(Substring(input, 1, input.Length() - 1));
72 } else {
73 sp->ParseInput(input);
75 } else if (aInit.IsUSVStringSequenceSequence()) {
76 const Sequence<Sequence<nsString>>& list =
77 aInit.GetAsUSVStringSequenceSequence();
78 for (uint32_t i = 0; i < list.Length(); ++i) {
79 const Sequence<nsString>& item = list[i];
80 if (item.Length() != 2) {
81 nsPrintfCString err("Expected 2 items in pair but got %zu",
82 item.Length());
83 aRv.ThrowTypeError(err);
84 return nullptr;
86 sp->Append(item[0], item[1]);
88 } else if (aInit.IsUSVStringUSVStringRecord()) {
89 const Record<nsString, nsString>& record =
90 aInit.GetAsUSVStringUSVStringRecord();
91 for (auto& entry : record.Entries()) {
92 sp->Append(entry.mKey, entry.mValue);
94 } else {
95 MOZ_CRASH("This should not happen.");
98 return sp.forget();
101 void URLSearchParams::ParseInput(const nsACString& aInput) {
102 mParams->ParseInput(aInput);
105 uint32_t URLSearchParams::Size() const { return mParams->Length(); }
107 void URLSearchParams::Get(const nsAString& aName, nsString& aRetval) {
108 return mParams->Get(aName, aRetval);
111 void URLSearchParams::GetAll(const nsAString& aName,
112 nsTArray<nsString>& aRetval) {
113 return mParams->GetAll(aName, aRetval);
116 void URLSearchParams::Set(const nsAString& aName, const nsAString& aValue) {
117 mParams->Set(aName, aValue);
118 NotifyObserver();
121 void URLSearchParams::Append(const nsAString& aName, const nsAString& aValue) {
122 mParams->Append(aName, aValue);
123 NotifyObserver();
126 bool URLSearchParams::Has(const nsAString& aName,
127 const Optional<nsAString>& aValue) {
128 if (!aValue.WasPassed()) {
129 return mParams->Has(aName);
131 return mParams->Has(aName, aValue.Value());
134 void URLSearchParams::Delete(const nsAString& aName,
135 const Optional<nsAString>& aValue) {
136 if (!aValue.WasPassed()) {
137 mParams->Delete(aName);
138 NotifyObserver();
139 return;
141 mParams->Delete(aName, aValue.Value());
142 NotifyObserver();
145 void URLSearchParams::DeleteAll() { mParams->DeleteAll(); }
147 void URLSearchParams::Serialize(nsAString& aValue) const {
148 mParams->Serialize(aValue, true);
151 void URLSearchParams::NotifyObserver() {
152 if (mObserver) {
153 mObserver->URLSearchParamsUpdated(this);
157 uint32_t URLSearchParams::GetIterableLength() const {
158 return mParams->Length();
161 const nsAString& URLSearchParams::GetKeyAtIndex(uint32_t aIndex) const {
162 return mParams->GetKeyAtIndex(aIndex);
165 const nsAString& URLSearchParams::GetValueAtIndex(uint32_t aIndex) const {
166 return mParams->GetValueAtIndex(aIndex);
169 void URLSearchParams::Sort(ErrorResult& aRv) {
170 mParams->Sort();
171 NotifyObserver();
174 bool URLSearchParams::WriteStructuredClone(
175 JSStructuredCloneWriter* aWriter) const {
176 const uint32_t& nParams = mParams->Length();
177 if (!JS_WriteUint32Pair(aWriter, nParams, 0)) {
178 return false;
180 for (uint32_t i = 0; i < nParams; ++i) {
181 if (!StructuredCloneHolder::WriteString(aWriter,
182 mParams->GetKeyAtIndex(i)) ||
183 !StructuredCloneHolder::WriteString(aWriter,
184 mParams->GetValueAtIndex(i))) {
185 return false;
188 return true;
191 bool URLSearchParams::ReadStructuredClone(JSStructuredCloneReader* aReader) {
192 MOZ_ASSERT(aReader);
194 DeleteAll();
196 uint32_t nParams, zero;
197 nsAutoString key, value;
198 if (!JS_ReadUint32Pair(aReader, &nParams, &zero) || zero != 0) {
199 return false;
202 for (uint32_t i = 0; i < nParams; ++i) {
203 if (!StructuredCloneHolder::ReadString(aReader, key) ||
204 !StructuredCloneHolder::ReadString(aReader, value)) {
205 return false;
207 Append(key, value);
209 return true;
212 bool URLSearchParams::WriteStructuredClone(
213 JSContext* aCx, JSStructuredCloneWriter* aWriter) const {
214 return WriteStructuredClone(aWriter);
217 // static
218 already_AddRefed<URLSearchParams> URLSearchParams::ReadStructuredClone(
219 JSContext* aCx, nsIGlobalObject* aGlobal,
220 JSStructuredCloneReader* aReader) {
221 RefPtr<URLSearchParams> params = new URLSearchParams(aGlobal);
222 if (!params->ReadStructuredClone(aReader)) {
223 return nullptr;
225 return params.forget();
228 // contentTypeWithCharset can be set to the contentType or
229 // contentType+charset based on what the spec says.
230 // See: https://fetch.spec.whatwg.org/#concept-bodyinit-extract
231 nsresult URLSearchParams::GetSendInfo(nsIInputStream** aBody,
232 uint64_t* aContentLength,
233 nsACString& aContentTypeWithCharset,
234 nsACString& aCharset) const {
235 aContentTypeWithCharset.AssignLiteral(
236 "application/x-www-form-urlencoded;charset=UTF-8");
237 aCharset.AssignLiteral("UTF-8");
239 nsAutoString serialized;
240 Serialize(serialized);
241 NS_ConvertUTF16toUTF8 converted(serialized);
242 *aContentLength = converted.Length();
243 return NS_NewCStringInputStream(aBody, std::move(converted));
246 } // namespace mozilla::dom