/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "xpcprivate.h" #include "XPCJSWeakReference.h" #include "nsContentUtils.h" using namespace JS; xpcJSWeakReference::xpcJSWeakReference() = default; NS_IMPL_ISUPPORTS(xpcJSWeakReference, xpcIJSWeakReference) nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object) { if (!object.isObject()) { return NS_OK; } JS::RootedObject obj(cx, &object.toObject()); XPCCallContext ccx(cx); // See if the object is a wrapped native that supports weak references. nsCOMPtr<nsISupports> supports = xpc::ReflectorToISupportsDynamic(obj, cx); nsCOMPtr<nsISupportsWeakReference> supportsWeakRef = do_QueryInterface(supports); if (supportsWeakRef) { supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent)); if (mReferent) { return NS_OK; } } // If it's not a wrapped native, or it is a wrapped native that does not // support weak references, fall back to getting a weak ref to the object. // See if object is a wrapped JSObject. RefPtr<nsXPCWrappedJS> wrapped; nsresult rv = nsXPCWrappedJS::GetNewOrUsed(cx, obj, NS_GET_IID(nsISupports), getter_AddRefs(wrapped)); if (!wrapped) { NS_ERROR("can't get nsISupportsWeakReference wrapper for obj"); return rv; } return wrapped->GetWeakReference(getter_AddRefs(mReferent)); } NS_IMETHODIMP xpcJSWeakReference::Get(JSContext* aCx, MutableHandleValue aRetval) { aRetval.setNull(); if (!mReferent) { return NS_OK; } nsCOMPtr<nsISupports> supports = do_QueryReferent(mReferent); if (!supports) { return NS_OK; } nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(supports); if (!wrappedObj) { // We have a generic XPCOM object that supports weak references here. // Wrap it and pass it out. return nsContentUtils::WrapNative(aCx, supports, &NS_GET_IID(nsISupports), aRetval); } JS::RootedObject obj(aCx, wrappedObj->GetJSObject()); if (!obj) { return NS_OK; } // Most users of XPCWrappedJS don't need to worry about // re-wrapping because things are implicitly rewrapped by // xpcconvert. However, because we're doing this directly // through the native call context, we need to call // JS_WrapObject(). if (!JS_WrapObject(aCx, &obj)) { return NS_ERROR_FAILURE; } aRetval.setObject(*obj); return NS_OK; }