Bug 650161 - Relocate global objects (browser changes) r=bholley
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -101,17 +101,17 @@ public:
{
return GetWrapperJSObject();
}
void SetWrapper(JSObject* aWrapper)
{
MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!");
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");
SetWrapperJSObject(aWrapper);
}
/**
* Clear the wrapper. This should be called from the finalizer for the
* wrapper.
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -575,17 +575,16 @@ ObjectClassIs(JSObject &obj, ESClassValu
/* Just a helper that checks v.isObject before calling ObjectClassIs. */
inline bool
IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
/* Fills |vp| with the unboxed value for boxed types, or undefined otherwise. */
inline bool
Unbox(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp);
-/* Check whether the object's class supplies objectMovedOp for non-global objects. */
#ifdef DEBUG
JS_FRIEND_API(bool)
-HasObjectMovedOpIfRequired(JSObject *obj);
+HasObjectMovedOp(JSObject *obj);
#endif
} /* namespace js */
#endif /* js_Class_h */
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -1435,17 +1435,17 @@ js::ReportErrorWithId(JSContext *cx, con
#ifdef DEBUG
JS_PUBLIC_API(bool)
js::IsInRequest(JSContext *cx)
{
return !!cx->runtime()->requestDepth;
}
bool
-js::HasObjectMovedOpIfRequired(JSObject *obj) {
+js::HasObjectMovedOp(JSObject *obj) {
return !!GetObjectClass(obj)->ext.objectMovedOp;
}
#endif
#ifdef JSGC_GENERATIONAL
JS_FRIEND_API(void)
JS_StoreObjectPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, JSObject *key, void *data),
--- a/js/xpconnect/public/SandboxPrivate.h
+++ b/js/xpconnect/public/SandboxPrivate.h
@@ -50,15 +50,20 @@ public:
ClearWrapper();
}
virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE
{
MOZ_CRASH("SandboxPrivate doesn't use DOM bindings!");
}
+ void ObjectMoved(JSObject *obj, const JSObject *old)
+ {
+ UpdateWrapper(obj, old);
+ }
+
private:
virtual ~SandboxPrivate() { }
nsCOMPtr<nsIPrincipal> mPrincipal;
};
#endif // __SANDBOXPRIVATE_H__
--- a/js/xpconnect/src/BackstagePass.h
+++ b/js/xpconnect/src/BackstagePass.h
@@ -10,51 +10,49 @@
#include "nsISupports.h"
#include "nsWeakReference.h"
#include "nsIGlobalObject.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIXPCScriptable.h"
#include "js/HeapAPI.h"
+class XPCWrappedNative;
+
class BackstagePass : public nsIGlobalObject,
public nsIScriptObjectPrincipal,
public nsIXPCScriptable,
public nsIClassInfo,
public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCSCRIPTABLE
NS_DECL_NSICLASSINFO
virtual nsIPrincipal* GetPrincipal() {
return mPrincipal;
}
- virtual JSObject* GetGlobalJSObject() {
- return mGlobal;
- }
+ virtual JSObject* GetGlobalJSObject();
virtual void ForgetGlobalObject() {
- mGlobal = nullptr;
+ mWrapper = nullptr;
}
- virtual void SetGlobalObject(JSObject* global) {
- mGlobal = global;
- }
+ virtual void SetGlobalObject(JSObject* global);
explicit BackstagePass(nsIPrincipal *prin) :
mPrincipal(prin)
{
}
private:
virtual ~BackstagePass() { }
nsCOMPtr<nsIPrincipal> mPrincipal;
- JS::TenuredHeap<JSObject*> mGlobal;
+ XPCWrappedNative *mWrapper;
};
nsresult
NS_NewBackstagePass(BackstagePass** ret);
#endif // BackstagePass_h__
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -306,30 +306,39 @@ sandbox_enumerate(JSContext *cx, HandleO
static bool
sandbox_resolve(JSContext *cx, HandleObject obj, HandleId id)
{
bool resolved;
return JS_ResolveStandardClass(cx, obj, id, &resolved);
}
static void
-sandbox_finalize(JSFreeOp *fop, JSObject *obj)
+sandbox_finalize(js::FreeOp *fop, JSObject *obj)
{
nsIScriptObjectPrincipal *sop =
static_cast<nsIScriptObjectPrincipal *>(xpc_GetJSPrivate(obj));
if (!sop) {
// sop can be null if CreateSandboxObject fails in the middle.
return;
}
static_cast<SandboxPrivate *>(sop)->ForgetGlobalObject();
NS_RELEASE(sop);
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
sandbox_convert(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp)
{
if (type == JSTYPE_OBJECT) {
vp.set(OBJECT_TO_JSVAL(obj));
return true;
}
@@ -439,45 +448,65 @@ sandbox_addProperty(JSContext *cx, Handl
writeToProto_getProperty, writeToProto_setProperty))
return false;
return true;
}
#define XPCONNECT_SANDBOX_CLASS_METADATA_SLOT (XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET)
-static const JSClass SandboxClass = {
+static const js::Class SandboxClass = {
"Sandbox",
XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
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
// to do the work for this class.
-static const JSClass SandboxWriteToProtoClass = {
+static const js::Class SandboxWriteToProtoClass = {
"Sandbox",
XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
sandbox_addProperty, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
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[] = {
JS_FS("dump", SandboxDump, 1,0),
JS_FS("debug", SandboxDebug, 1,0),
JS_FS("importFunction", SandboxImport, 1,0),
JS_FS_END
};
bool
xpc::IsSandbox(JSObject *obj)
{
- const JSClass *clasp = GetObjectJSClass(obj);
+ const Class *clasp = GetObjectClass(obj);
return clasp == &SandboxClass || clasp == &SandboxWriteToProtoClass;
}
/***************************************************************************/
nsXPCComponents_utils_Sandbox::nsXPCComponents_utils_Sandbox()
{
}
@@ -870,21 +899,21 @@ xpc::CreateSandboxObject(JSContext *cx,
NS_ENSURE_TRUE(addonId, NS_ERROR_FAILURE);
} else if (JSObject *obj = JS::CurrentGlobalOrNull(cx)) {
if (JSAddonId *id = JS::AddonIdOfObject(obj))
addonId = id;
}
compartmentOptions.setAddonId(addonId);
- const JSClass *clasp = options.writeToGlobalPrototype
- ? &SandboxWriteToProtoClass
- : &SandboxClass;
+ const Class *clasp = options.writeToGlobalPrototype
+ ? &SandboxWriteToProtoClass
+ : &SandboxClass;
- RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, clasp,
+ RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, js::Jsvalify(clasp),
principal, compartmentOptions));
if (!sandbox)
return NS_ERROR_FAILURE;
CompartmentPrivate::Get(sandbox)->writeToGlobalPrototype =
options.writeToGlobalPrototype;
// Set up the wantXrays flag, which indicates whether xrays are desired even
--- a/js/xpconnect/src/XPCRuntimeService.cpp
+++ b/js/xpconnect/src/XPCRuntimeService.cpp
@@ -1,14 +1,16 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
/* 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 "nsContentUtils.h"
#include "BackstagePass.h"
#include "nsIProgrammingLanguage.h"
#include "nsDOMClassInfo.h"
#include "nsIPrincipal.h"
#include "mozilla/dom/ResolveSystemBinding.h"
@@ -38,16 +40,33 @@ NS_IMPL_RELEASE(BackstagePass)
nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \
nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
nsIXPCScriptable::DONT_ENUM_STATIC_PROPS | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
nsIXPCScriptable::IS_GLOBAL_OBJECT | \
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
#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); */
NS_IMETHODIMP
BackstagePass::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * objArg,
jsid idArg, JSObject * *objpArg,
bool *_retval)
{
JS::RootedObject obj(cx, objArg);
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -506,19 +506,23 @@ XPCWrappedNativeScope::UpdateWeakPointer
while (cur) {
// Sweep waivers.
if (cur->mWaiverWrapperMap)
cur->mWaiverWrapperMap->Sweep();
XPCWrappedNativeScope* next = cur->mNext;
- // Check for finalization of the global object. Note that global
- // objects are never moved, so we don't need to handle updating the
- // object pointer here.
+ if (cur->mContentXBLScope)
+ cur->mContentXBLScope.updateWeakPointerAfterGC();
+ 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) {
cur->mGlobalJSObject.updateWeakPointerAfterGC();
if (!cur->mGlobalJSObject) {
// Move this scope from the live list to the dying list.
if (prev)
prev->mNext = next;
else
gScopes = next;