TestFunctions.cpp (11452B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/TestFunctions.h" 8 9 #include "mozITestInterfaceJS.h" 10 #include "mozilla/StringBuffer.h" 11 #include "mozilla/dom/BindingUtils.h" 12 #include "mozilla/dom/Document.h" 13 #include "mozilla/dom/TestFunctionsBinding.h" 14 #include "mozilla/dom/WindowBinding.h" 15 #include "mozilla/dom/WrapperCachedNonISupportsTestInterface.h" 16 #include "nsComponentManagerUtils.h" 17 #include "nsGlobalWindowInner.h" 18 19 namespace mozilla::dom { 20 21 /* static */ 22 UniquePtr<TestFunctions> TestFunctions::Constructor(GlobalObject& aGlobal) { 23 return MakeUnique<TestFunctions>(); 24 } 25 26 /* static */ 27 void TestFunctions::ThrowUncatchableException(GlobalObject& aGlobal, 28 ErrorResult& aRv) { 29 aRv.ThrowUncatchableException(); 30 } 31 32 /* static */ 33 Promise* TestFunctions::PassThroughPromise(GlobalObject& aGlobal, 34 Promise& aPromise) { 35 return &aPromise; 36 } 37 38 /* static */ 39 already_AddRefed<Promise> TestFunctions::PassThroughCallbackPromise( 40 GlobalObject& aGlobal, PromiseReturner& aCallback, ErrorResult& aRv) { 41 return aCallback.Call(aRv); 42 } 43 44 void TestFunctions::SetStringData(const nsAString& aString) { 45 mStringData = aString; 46 } 47 48 void TestFunctions::GetStringDataAsAString(nsAString& aString) { 49 aString = mStringData; 50 } 51 52 void TestFunctions::GetStringDataAsAString(uint32_t aLength, 53 nsAString& aString) { 54 MOZ_RELEASE_ASSERT(aLength <= mStringData.Length(), 55 "Bogus test passing in a too-big length"); 56 aString.Assign(mStringData.BeginReading(), aLength); 57 } 58 59 void TestFunctions::GetStringDataAsDOMString(const Optional<uint32_t>& aLength, 60 DOMString& aString) { 61 uint32_t length; 62 if (aLength.WasPassed()) { 63 length = aLength.Value(); 64 MOZ_RELEASE_ASSERT(length <= mStringData.Length(), 65 "Bogus test passing in a too-big length"); 66 } else { 67 length = mStringData.Length(); 68 } 69 70 if (StringBuffer* buf = mStringData.GetStringBuffer()) { 71 aString.SetKnownLiveStringBuffer(buf, length); 72 return; 73 } 74 75 // We better have an empty mStringData; otherwise why did we not have a string 76 // buffer? 77 MOZ_RELEASE_ASSERT(length == 0, "Why no stringbuffer?"); 78 // No need to do anything here; aString is already empty. 79 } 80 81 void TestFunctions::GetShortLiteralString(nsAString& aString) { 82 // JS inline strings can hold 2 * sizeof(void*) chars, which on 32-bit means 8 83 // chars. Return fewer than that. 84 aString.AssignLiteral(u"012345"); 85 } 86 87 void TestFunctions::GetMediumLiteralString(nsAString& aString) { 88 // JS inline strings are at most 2 * sizeof(void*) chars, so at most 16 on 89 // 64-bit. FakeString can hold 63 chars in its inline buffer (plus the null 90 // terminator). Let's return 40 chars; that way if we ever move to 128-bit 91 // void* or something this test will still be valid. 92 aString.AssignLiteral(u"0123456789012345678901234567890123456789"); 93 } 94 95 void TestFunctions::GetLongLiteralString(nsAString& aString) { 96 // Need more than 64 chars. 97 aString.AssignLiteral( 98 u"0123456789012345678901234567890123456789" // 40 99 "0123456789012345678901234567890123456789" // 80 100 ); 101 } 102 103 void TestFunctions::GetStringbufferString(const nsAString& aInput, 104 nsAString& aRetval) { 105 // We have to be a bit careful: if aRetval is an autostring, if we just assign 106 // it won't cause stringbuffer allocation. So we have to round-trip through 107 // something that definitely causes a stringbuffer allocation. 108 nsString str; 109 // Can't use operator= here, because if aInput is a literal string then str 110 // would end up the same way. 111 str.Assign(aInput.BeginReading(), aInput.Length()); 112 113 // Now we might end up hitting our external string cache and getting the wrong 114 // sort of external string, so replace the last char by a different value 115 // (replacing, not just appending, to preserve the length). If we have an 116 // empty string, our caller screwed up and there's not much we can do for 117 // them. 118 if (str.Length() > 1) { 119 char16_t last = str[str.Length() - 1]; 120 str.Truncate(str.Length() - 1); 121 if (last == 'x') { 122 str.Append('y'); 123 } else { 124 str.Append('x'); 125 } 126 } 127 128 // Here we use operator= to preserve stringbufferness. 129 aRetval = str; 130 } 131 132 StringType TestFunctions::GetStringType(const nsAString& aString) { 133 if (aString.IsLiteral()) { 134 return StringType::Literal; 135 } 136 137 if (aString.GetStringBuffer()) { 138 return StringType::Stringbuffer; 139 } 140 141 if (aString.GetDataFlags() & nsAString::DataFlags::INLINE) { 142 return StringType::Inline; 143 } 144 145 return StringType::Other; 146 } 147 148 bool TestFunctions::StringbufferMatchesStored(const nsAString& aString) { 149 return aString.GetStringBuffer() && 150 aString.GetStringBuffer() == mStringData.GetStringBuffer(); 151 } 152 153 void TestFunctions::TestThrowNsresult(ErrorResult& aError) { 154 nsCOMPtr<mozITestInterfaceJS> impl = 155 do_CreateInstance("@mozilla.org/dom/test-interface-js;1"); 156 aError = impl->TestThrowNsresult(); 157 } 158 159 void TestFunctions::TestThrowNsresultFromNative(ErrorResult& aError) { 160 nsCOMPtr<mozITestInterfaceJS> impl = 161 do_CreateInstance("@mozilla.org/dom/test-interface-js;1"); 162 aError = impl->TestThrowNsresultFromNative(); 163 } 164 165 already_AddRefed<Promise> TestFunctions::ThrowToRejectPromise( 166 GlobalObject& aGlobal, ErrorResult& aError) { 167 aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); 168 return nullptr; 169 } 170 171 int32_t TestFunctions::One() const { return 1; } 172 173 int32_t TestFunctions::Two() const { return 2; } 174 175 void TestFunctions::SetClampedNullableOctet(const Nullable<uint8_t>& aOctet) { 176 mClampedNullableOctet = aOctet; 177 } 178 179 Nullable<uint8_t> TestFunctions::GetClampedNullableOctet() const { 180 return mClampedNullableOctet; 181 } 182 183 void TestFunctions::SetEnforcedNullableOctet(const Nullable<uint8_t>& aOctet) { 184 mEnforcedNullableOctet = aOctet; 185 } 186 187 Nullable<uint8_t> TestFunctions::GetEnforcedNullableOctet() const { 188 return mEnforcedNullableOctet; 189 } 190 191 void TestFunctions::SetArrayBufferView(const ArrayBufferView& aBuffer) {} 192 193 void TestFunctions::GetArrayBufferView(JSContext* aCx, 194 JS::Handle<JSObject*> aObj, 195 JS::MutableHandle<JSObject*> aRetval, 196 ErrorResult& aError) { 197 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 198 } 199 200 void TestFunctions::SetAllowSharedArrayBufferView( 201 const ArrayBufferView& aBuffer) {} 202 203 void TestFunctions::GetAllowSharedArrayBufferView( 204 JSContext* aCx, JS::Handle<JSObject*> aObj, 205 JS::MutableHandle<JSObject*> aRetval, ErrorResult& aError) { 206 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 207 } 208 209 void TestFunctions::SetSequenceOfArrayBufferView( 210 const Sequence<ArrayBufferView>& aBuffers) {} 211 212 void TestFunctions::GetSequenceOfArrayBufferView(JSContext* aCx, 213 JS::Handle<JSObject*> aObj, 214 nsTArray<JSObject*>& aRetval, 215 ErrorResult& aError) { 216 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 217 } 218 219 void TestFunctions::SetSequenceOfAllowSharedArrayBufferView( 220 const Sequence<ArrayBufferView>& aBuffers) {} 221 222 void TestFunctions::GetSequenceOfAllowSharedArrayBufferView( 223 JSContext* aCx, JS::Handle<JSObject*> aObj, nsTArray<JSObject*>& aRetval, 224 ErrorResult& aError) { 225 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 226 } 227 228 void TestFunctions::SetArrayBuffer(const ArrayBuffer& aBuffer) {} 229 230 void TestFunctions::GetArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObj, 231 JS::MutableHandle<JSObject*> aRetval, 232 ErrorResult& aError) { 233 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 234 } 235 236 void TestFunctions::SetAllowSharedArrayBuffer(const ArrayBuffer& aBuffer) {} 237 238 void TestFunctions::GetAllowSharedArrayBuffer( 239 JSContext* aCx, JS::Handle<JSObject*> aObj, 240 JS::MutableHandle<JSObject*> aRetval, ErrorResult& aError) { 241 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 242 } 243 244 void TestFunctions::SetSequenceOfArrayBuffer( 245 const Sequence<ArrayBuffer>& aBuffers) {} 246 247 void TestFunctions::GetSequenceOfArrayBuffer(JSContext* aCx, 248 JS::Handle<JSObject*> aObj, 249 nsTArray<JSObject*>& aRetval, 250 ErrorResult& aError) { 251 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 252 } 253 254 void TestFunctions::SetSequenceOfAllowSharedArrayBuffer( 255 const Sequence<ArrayBuffer>& aBuffers) {} 256 257 void TestFunctions::GetSequenceOfAllowSharedArrayBuffer( 258 JSContext* aCx, JS::Handle<JSObject*> aObj, nsTArray<JSObject*>& aRetval, 259 ErrorResult& aError) { 260 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 261 } 262 263 void TestFunctions::TestNotAllowShared(const ArrayBufferView& aBuffer) {} 264 265 void TestFunctions::TestNotAllowShared(const ArrayBuffer& aBuffer) {} 266 267 void TestFunctions::TestNotAllowShared(const nsAString& aBuffer) {} 268 269 void TestFunctions::TestAllowShared(const ArrayBufferView& aBuffer) {} 270 271 void TestFunctions::TestAllowShared(const ArrayBuffer& aBuffer) {} 272 273 void TestFunctions::TestDictWithAllowShared( 274 const DictWithAllowSharedBufferSource& aDict) {} 275 276 void TestFunctions::TestUnionOfBufferSource( 277 const ArrayBufferOrArrayBufferViewOrString& aUnion) {} 278 279 void TestFunctions::TestUnionOfAllowSharedBufferSource( 280 const AllowSharedBufferSource& aUnion) {} 281 282 void TestFunctions::TestUnionWithAllowShared( 283 const MaybeSharedInt8ArrayOrMaybeSharedInt16Array& aUnion) {} 284 285 bool TestFunctions::ObjectFromAboutBlank(JSContext* aCx, JSObject* aObj) { 286 // We purposefully don't use WindowOrNull here, because we want to 287 // demonstrate the incorrect behavior we get, not just fail some asserts. 288 RefPtr<nsGlobalWindowInner> win; 289 UNWRAP_MAYBE_CROSS_ORIGIN_OBJECT(Window, aObj, win, aCx); 290 if (!win) { 291 return false; 292 } 293 294 Document* doc = win->GetDoc(); 295 if (!doc) { 296 return false; 297 } 298 299 return doc->GetDocumentURI()->GetSpecOrDefault().EqualsLiteral("about:blank"); 300 } 301 302 WrapperCachedNonISupportsTestInterface* 303 TestFunctions::WrapperCachedNonISupportsObject() { 304 if (!mWrapperCachedNonISupportsTestInterface) { 305 mWrapperCachedNonISupportsTestInterface = 306 new WrapperCachedNonISupportsTestInterface(); 307 } 308 return mWrapperCachedNonISupportsTestInterface; 309 } 310 311 /* static */ 312 already_AddRefed<TestChromeOnlyInterface> 313 TestFunctions::CreateTestChromeOnlyInterface(GlobalObject& aGlobal) { 314 return MakeRefPtr<TestChromeOnlyInterface>(aGlobal.GetAsSupports()).forget(); 315 } 316 317 bool TestFunctions::WrapObject(JSContext* aCx, 318 JS::Handle<JSObject*> aGivenProto, 319 JS::MutableHandle<JSObject*> aWrapper) { 320 return TestFunctions_Binding::Wrap(aCx, this, aGivenProto, aWrapper); 321 } 322 323 JSObject* TestChromeOnlyInterface::WrapObject( 324 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 325 return TestChromeOnlyInterface_Binding::Wrap(aCx, this, aGivenProto); 326 } 327 328 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestChromeOnlyInterface, mParent) 329 330 } // namespace mozilla::dom