ToJSValue.cpp (4167B)
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/ToJSValue.h" 8 9 #include "mozilla/dom/DOMException.h" 10 #include "mozilla/dom/Exceptions.h" 11 #include "mozilla/dom/Promise.h" 12 #include "mozilla/dom/WindowProxyHolder.h" 13 #include "nsAString.h" 14 #include "nsContentUtils.h" 15 #include "xpcpublic.h" 16 17 namespace mozilla::dom { 18 19 bool ToJSValue(JSContext* aCx, const nsAString& aArgument, 20 JS::MutableHandle<JS::Value> aValue) { 21 // Make sure we're called in a compartment 22 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 23 return xpc::NonVoidStringToJsval(aCx, aArgument, aValue); 24 } 25 26 bool ToJSValue(JSContext* aCx, const nsACString& aArgument, 27 JS::MutableHandle<JS::Value> aValue) { 28 return UTF8StringToJsval(aCx, aArgument, aValue); 29 } 30 31 bool ToJSValue(JSContext* aCx, nsresult aArgument, 32 JS::MutableHandle<JS::Value> aValue) { 33 RefPtr<Exception> exception = CreateException(aArgument); 34 return ToJSValue(aCx, exception, aValue); 35 } 36 37 bool ToJSValue(JSContext* aCx, ErrorResult&& aArgument, 38 JS::MutableHandle<JS::Value> aValue) { 39 MOZ_ASSERT(aArgument.Failed()); 40 MOZ_ASSERT( 41 !aArgument.IsUncatchableException(), 42 "Doesn't make sense to convert uncatchable exception to a JS value!"); 43 MOZ_ALWAYS_TRUE(aArgument.MaybeSetPendingException(aCx)); 44 MOZ_ALWAYS_TRUE(JS_GetPendingException(aCx, aValue)); 45 JS_ClearPendingException(aCx); 46 return true; 47 } 48 49 bool ToJSValue(JSContext* aCx, Promise& aArgument, 50 JS::MutableHandle<JS::Value> aValue) { 51 aValue.setObject(*aArgument.PromiseObj()); 52 return MaybeWrapObjectValue(aCx, aValue); 53 } 54 55 bool ToJSValue(JSContext* aCx, const WindowProxyHolder& aArgument, 56 JS::MutableHandle<JS::Value> aValue) { 57 BrowsingContext* bc = aArgument.get(); 58 if (!bc) { 59 aValue.setNull(); 60 return true; 61 } 62 JS::Rooted<JSObject*> windowProxy(aCx); 63 if (bc->IsInProcess()) { 64 windowProxy = bc->GetWindowProxy(); 65 if (!windowProxy) { 66 nsPIDOMWindowOuter* window = bc->GetDOMWindow(); 67 if (!window) { 68 // Torn down enough that we should just return null. 69 aValue.setNull(); 70 return true; 71 } 72 if (!window->EnsureInnerWindow()) { 73 return Throw(aCx, NS_ERROR_UNEXPECTED); 74 } 75 windowProxy = bc->GetWindowProxy(); 76 } 77 return ToJSValue(aCx, windowProxy, aValue); 78 } 79 80 if (!GetRemoteOuterWindowProxy(aCx, bc, /* aTransplantTo = */ nullptr, 81 &windowProxy)) { 82 return false; 83 } 84 aValue.setObjectOrNull(windowProxy); 85 return true; 86 } 87 88 // Static assertion tests for the `binding_detail::ScriptableInterfaceType` 89 // helper template, used by `ToJSValue`. 90 namespace binding_detail { 91 static_assert(std::is_same_v<ScriptableInterfaceType<nsISupports>, nsISupports>, 92 "nsISupports works with ScriptableInterfaceType"); 93 static_assert( 94 std::is_same_v<ScriptableInterfaceType<nsIGlobalObject>, nsISupports>, 95 "non-scriptable interfaces get a fallback"); 96 static_assert(std::is_same_v<ScriptableInterfaceType<nsIObserver>, nsIObserver>, 97 "scriptable interfaces should get the correct type"); 98 static_assert(std::is_same_v<ScriptableInterfaceType<nsIRunnable>, nsIRunnable>, 99 "scriptable interfaces should get the correct type"); 100 class SingleScriptableInterface : public nsIObserver {}; 101 static_assert( 102 std::is_same_v<ScriptableInterfaceType<SingleScriptableInterface>, 103 nsIObserver>, 104 "Concrete type with one scriptable interface picks the correct interface"); 105 class MultiScriptableInterface : public nsIObserver, public nsIRunnable {}; 106 static_assert(std::is_same_v<ScriptableInterfaceType<MultiScriptableInterface>, 107 nsISupports>, 108 "Concrete type with multiple scriptable interfaces falls back"); 109 } // namespace binding_detail 110 } // namespace mozilla::dom