XPCJSWeakReference.cpp (2736B)
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/. */ 6 7 #include "xpcprivate.h" 8 #include "XPCJSWeakReference.h" 9 10 #include "nsContentUtils.h" 11 12 using namespace JS; 13 14 xpcJSWeakReference::xpcJSWeakReference() = default; 15 16 NS_IMPL_ISUPPORTS(xpcJSWeakReference, xpcIJSWeakReference) 17 18 nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object) { 19 if (!object.isObject()) { 20 return NS_OK; 21 } 22 23 JS::RootedObject obj(cx, &object.toObject()); 24 25 XPCCallContext ccx(cx); 26 27 // See if the object is a wrapped native that supports weak references. 28 nsCOMPtr<nsISupports> supports = xpc::ReflectorToISupportsDynamic(obj, cx); 29 nsCOMPtr<nsISupportsWeakReference> supportsWeakRef = 30 do_QueryInterface(supports); 31 if (supportsWeakRef) { 32 supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent)); 33 if (mReferent) { 34 return NS_OK; 35 } 36 } 37 // If it's not a wrapped native, or it is a wrapped native that does not 38 // support weak references, fall back to getting a weak ref to the object. 39 40 // See if object is a wrapped JSObject. 41 RefPtr<nsXPCWrappedJS> wrapped; 42 nsresult rv = nsXPCWrappedJS::GetNewOrUsed(cx, obj, NS_GET_IID(nsISupports), 43 getter_AddRefs(wrapped)); 44 if (!wrapped) { 45 NS_ERROR("can't get nsISupportsWeakReference wrapper for obj"); 46 return rv; 47 } 48 49 return wrapped->GetWeakReference(getter_AddRefs(mReferent)); 50 } 51 52 NS_IMETHODIMP 53 xpcJSWeakReference::Get(JSContext* aCx, MutableHandleValue aRetval) { 54 aRetval.setNull(); 55 56 if (!mReferent) { 57 return NS_OK; 58 } 59 60 nsCOMPtr<nsISupports> supports = do_QueryReferent(mReferent); 61 if (!supports) { 62 return NS_OK; 63 } 64 65 nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(supports); 66 if (!wrappedObj) { 67 // We have a generic XPCOM object that supports weak references here. 68 // Wrap it and pass it out. 69 return nsContentUtils::WrapNative(aCx, supports, &NS_GET_IID(nsISupports), 70 aRetval); 71 } 72 73 JS::RootedObject obj(aCx, wrappedObj->GetJSObject()); 74 if (!obj) { 75 return NS_OK; 76 } 77 78 // Most users of XPCWrappedJS don't need to worry about 79 // re-wrapping because things are implicitly rewrapped by 80 // xpcconvert. However, because we're doing this directly 81 // through the native call context, we need to call 82 // JS_WrapObject(). 83 if (!JS_WrapObject(aCx, &obj)) { 84 return NS_ERROR_FAILURE; 85 } 86 87 aRetval.setObject(*obj); 88 return NS_OK; 89 }