Bug 650161 - Relocate global objects (browser changes) r=bholley

This commit is contained in:
Jon Coppeard 2014-10-20 09:07:43 +01:00
parent 7cc9536de3
commit 356b68ebfb
8 changed files with 79 additions and 25 deletions

View File

@ -106,7 +106,7 @@ public:
{ {
MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!"); MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!");
MOZ_ASSERT(aWrapper, "Use ClearWrapper!"); MOZ_ASSERT(aWrapper, "Use ClearWrapper!");
MOZ_ASSERT(js::HasObjectMovedOpIfRequired(aWrapper), MOZ_ASSERT(js::HasObjectMovedOp(aWrapper),
"Object has not provided the hook to update the wrapper if it is moved"); "Object has not provided the hook to update the wrapper if it is moved");
SetWrapperJSObject(aWrapper); SetWrapperJSObject(aWrapper);

View File

@ -580,10 +580,9 @@ IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
inline bool inline bool
Unbox(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp); Unbox(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp);
/* Check whether the object's class supplies objectMovedOp for non-global objects. */
#ifdef DEBUG #ifdef DEBUG
JS_FRIEND_API(bool) JS_FRIEND_API(bool)
HasObjectMovedOpIfRequired(JSObject *obj); HasObjectMovedOp(JSObject *obj);
#endif #endif
} /* namespace js */ } /* namespace js */

View File

@ -1440,7 +1440,7 @@ js::IsInRequest(JSContext *cx)
} }
bool bool
js::HasObjectMovedOpIfRequired(JSObject *obj) { js::HasObjectMovedOp(JSObject *obj) {
return !!GetObjectClass(obj)->ext.objectMovedOp; return !!GetObjectClass(obj)->ext.objectMovedOp;
} }
#endif #endif

View File

@ -55,6 +55,11 @@ public:
MOZ_CRASH("SandboxPrivate doesn't use DOM bindings!"); MOZ_CRASH("SandboxPrivate doesn't use DOM bindings!");
} }
void ObjectMoved(JSObject *obj, const JSObject *old)
{
UpdateWrapper(obj, old);
}
private: private:
virtual ~SandboxPrivate() { } virtual ~SandboxPrivate() { }

View File

@ -15,6 +15,8 @@
#include "js/HeapAPI.h" #include "js/HeapAPI.h"
class XPCWrappedNative;
class BackstagePass : public nsIGlobalObject, class BackstagePass : public nsIGlobalObject,
public nsIScriptObjectPrincipal, public nsIScriptObjectPrincipal,
public nsIXPCScriptable, public nsIXPCScriptable,
@ -30,17 +32,13 @@ public:
return mPrincipal; return mPrincipal;
} }
virtual JSObject* GetGlobalJSObject() { virtual JSObject* GetGlobalJSObject();
return mGlobal;
}
virtual void ForgetGlobalObject() { virtual void ForgetGlobalObject() {
mGlobal = nullptr; mWrapper = nullptr;
} }
virtual void SetGlobalObject(JSObject* global) { virtual void SetGlobalObject(JSObject* global);
mGlobal = global;
}
explicit BackstagePass(nsIPrincipal *prin) : explicit BackstagePass(nsIPrincipal *prin) :
mPrincipal(prin) mPrincipal(prin)
@ -51,7 +49,7 @@ private:
virtual ~BackstagePass() { } virtual ~BackstagePass() { }
nsCOMPtr<nsIPrincipal> mPrincipal; nsCOMPtr<nsIPrincipal> mPrincipal;
JS::TenuredHeap<JSObject*> mGlobal; XPCWrappedNative *mWrapper;
}; };
nsresult nsresult

View File

@ -311,7 +311,7 @@ sandbox_resolve(JSContext *cx, HandleObject obj, HandleId id)
} }
static void static void
sandbox_finalize(JSFreeOp *fop, JSObject *obj) sandbox_finalize(js::FreeOp *fop, JSObject *obj)
{ {
nsIScriptObjectPrincipal *sop = nsIScriptObjectPrincipal *sop =
static_cast<nsIScriptObjectPrincipal *>(xpc_GetJSPrivate(obj)); static_cast<nsIScriptObjectPrincipal *>(xpc_GetJSPrivate(obj));
@ -325,6 +325,15 @@ sandbox_finalize(JSFreeOp *fop, JSObject *obj)
DestroyProtoAndIfaceCache(obj); DestroyProtoAndIfaceCache(obj);
} }
static void
sandbox_moved(JSObject *obj, const JSObject *old)
{
nsIScriptObjectPrincipal *sop =
static_cast<nsIScriptObjectPrincipal *>(xpc_GetJSPrivate(obj));
MOZ_ASSERT(sop);
static_cast<SandboxPrivate *>(sop)->ObjectMoved(obj, old);
}
static bool static bool
sandbox_convert(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp) sandbox_convert(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp)
{ {
@ -444,22 +453,42 @@ sandbox_addProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleV
#define XPCONNECT_SANDBOX_CLASS_METADATA_SLOT (XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET) #define XPCONNECT_SANDBOX_CLASS_METADATA_SLOT (XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET)
static const JSClass SandboxClass = { static const js::Class SandboxClass = {
"Sandbox", "Sandbox",
XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1), XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
sandbox_enumerate, sandbox_resolve, sandbox_convert, sandbox_finalize, sandbox_enumerate, sandbox_resolve, sandbox_convert, sandbox_finalize,
nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook,
JS_NULL_CLASS_SPEC,
{
nullptr, /* outerObject */
nullptr, /* innerObject */
nullptr, /* iteratorObject */
false, /* isWrappedNative */
nullptr, /* weakmapKeyDelegateOp */
sandbox_moved /* objectMovedOp */
},
JS_NULL_OBJECT_OPS
}; };
// Note to whomever comes here to remove addProperty hooks: billm has promised // Note to whomever comes here to remove addProperty hooks: billm has promised
// to do the work for this class. // to do the work for this class.
static const JSClass SandboxWriteToProtoClass = { static const js::Class SandboxWriteToProtoClass = {
"Sandbox", "Sandbox",
XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1), XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
sandbox_addProperty, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, sandbox_addProperty, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
sandbox_enumerate, sandbox_resolve, sandbox_convert, sandbox_finalize, sandbox_enumerate, sandbox_resolve, sandbox_convert, sandbox_finalize,
nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook,
JS_NULL_CLASS_SPEC,
{
nullptr, /* outerObject */
nullptr, /* innerObject */
nullptr, /* iteratorObject */
false, /* isWrappedNative */
nullptr, /* weakmapKeyDelegateOp */
sandbox_moved /* objectMovedOp */
},
JS_NULL_OBJECT_OPS
}; };
static const JSFunctionSpec SandboxFunctions[] = { static const JSFunctionSpec SandboxFunctions[] = {
@ -472,7 +501,7 @@ static const JSFunctionSpec SandboxFunctions[] = {
bool bool
xpc::IsSandbox(JSObject *obj) xpc::IsSandbox(JSObject *obj)
{ {
const JSClass *clasp = GetObjectJSClass(obj); const Class *clasp = GetObjectClass(obj);
return clasp == &SandboxClass || clasp == &SandboxWriteToProtoClass; return clasp == &SandboxClass || clasp == &SandboxWriteToProtoClass;
} }
@ -875,11 +904,11 @@ xpc::CreateSandboxObject(JSContext *cx, MutableHandleValue vp, nsISupports *prin
compartmentOptions.setAddonId(addonId); compartmentOptions.setAddonId(addonId);
const JSClass *clasp = options.writeToGlobalPrototype const Class *clasp = options.writeToGlobalPrototype
? &SandboxWriteToProtoClass ? &SandboxWriteToProtoClass
: &SandboxClass; : &SandboxClass;
RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, clasp, RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, js::Jsvalify(clasp),
principal, compartmentOptions)); principal, compartmentOptions));
if (!sandbox) if (!sandbox)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

View File

@ -4,6 +4,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xpcprivate.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "BackstagePass.h" #include "BackstagePass.h"
#include "nsIProgrammingLanguage.h" #include "nsIProgrammingLanguage.h"
@ -43,6 +45,23 @@ NS_IMPL_RELEASE(BackstagePass)
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
#include "xpc_map_end.h" /* This will #undef the above */ #include "xpc_map_end.h" /* This will #undef the above */
JSObject *
BackstagePass::GetGlobalJSObject()
{
if (mWrapper)
return mWrapper->GetFlatJSObject();
return nullptr;
}
void
BackstagePass::SetGlobalObject(JSObject* global)
{
nsISupports* p = XPCWrappedNative::Get(global);
MOZ_ASSERT(p);
mWrapper = static_cast<XPCWrappedNative*>(p);
}
/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */
NS_IMETHODIMP NS_IMETHODIMP
BackstagePass::NewResolve(nsIXPConnectWrappedNative *wrapper, BackstagePass::NewResolve(nsIXPConnectWrappedNative *wrapper,

View File

@ -511,9 +511,13 @@ XPCWrappedNativeScope::UpdateWeakPointersAfterGC(XPCJSRuntime* rt)
XPCWrappedNativeScope* next = cur->mNext; XPCWrappedNativeScope* next = cur->mNext;
// Check for finalization of the global object. Note that global if (cur->mContentXBLScope)
// objects are never moved, so we don't need to handle updating the cur->mContentXBLScope.updateWeakPointerAfterGC();
// object pointer here. for (size_t i = 0; i < cur->mAddonScopes.Length(); i++)
cur->mAddonScopes[i].updateWeakPointerAfterGC();
// Check for finalization of the global object or update our pointer if
// it was moved.
if (cur->mGlobalJSObject) { if (cur->mGlobalJSObject) {
cur->mGlobalJSObject.updateWeakPointerAfterGC(); cur->mGlobalJSObject.updateWeakPointerAfterGC();
if (!cur->mGlobalJSObject) { if (!cur->mGlobalJSObject) {