зеркало из https://github.com/mozilla/pjs.git
Add a way to find all of the XOWs for an object and use it to deal with hard cases where we have to clear the scope of XOWs in order to reflect changes to the underlying object. Also deal with objects moving between scopes by ensuring that we're always able to find their XOWs. bug 399587, r+sr=jst
This commit is contained in:
Родитель
59b6437c68
Коммит
dc907e2a1a
|
@ -2155,7 +2155,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||
NS_FAILED(callerPrincipal->Equals(NodePrincipal(), &samePrincipal)) ||
|
||||
!samePrincipal) {
|
||||
SetIsInitialDocument(PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
rv = window->SetNewDocument(this, nsnull, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -4718,6 +4718,21 @@ nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
// Notify any XOWs on our outer window.
|
||||
|
||||
nsGlobalWindow *outerWin = win->GetOuterWindowInternal();
|
||||
if (outerWin) {
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wn;
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
nsresult rv =
|
||||
xpc->GetWrappedNativeOfJSObject(cx, outerWin->GetGlobalJSObject(),
|
||||
getter_AddRefs(wn));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = xpc->UpdateXOWs(cx, wn, nsIXPConnect::XPC_XOW_CLEARSCOPE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -5846,10 +5861,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
// a different context.
|
||||
|
||||
if (!win->IsChromeWindow()) {
|
||||
rv = sXPConnect->GetCrossOriginWrapperForObject(cx,
|
||||
win->GetGlobalJSObject(),
|
||||
JSVAL_TO_OBJECT(v),
|
||||
&v);
|
||||
rv = sXPConnect->GetXOWForObject(cx, win->GetGlobalJSObject(),
|
||||
JSVAL_TO_OBJECT(v), &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -5960,9 +5973,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
sDoSecurityCheckInAddProperty = PR_FALSE;
|
||||
|
||||
if (!win->IsChromeWindow()) {
|
||||
rv = sXPConnect->GetCrossOriginWrapperForObject(cx, scope,
|
||||
JSVAL_TO_OBJECT(v),
|
||||
&v);
|
||||
rv = sXPConnect->GetXOWForObject(cx, scope, JSVAL_TO_OBJECT(v), &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -6070,10 +6081,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
scope = oldWin->GetGlobalJSObject();
|
||||
}
|
||||
|
||||
rv = sXPConnect->GetCrossOriginWrapperForObject(cx,
|
||||
scope,
|
||||
JSVAL_TO_OBJECT(winVal),
|
||||
&winVal);
|
||||
rv = sXPConnect->GetXOWForObject(cx, scope, JSVAL_TO_OBJECT(winVal),
|
||||
&winVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
PRBool ok =
|
||||
|
@ -6283,7 +6292,7 @@ nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
|||
}
|
||||
scope = ::JS_GetGlobalForObject(cx, scope);
|
||||
jsval v;
|
||||
rv = sXPConnect->GetCrossOriginWrapperForObject(cx, scope, winObj, &v);
|
||||
rv = sXPConnect->GetXOWForObject(cx, scope, winObj, &v);
|
||||
*_retval = NS_SUCCEEDED(rv) ? JSVAL_TO_OBJECT(v) : nsnull;
|
||||
}
|
||||
|
||||
|
@ -7629,8 +7638,8 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
|
||||
nsGlobalWindow *internalWin = static_cast<nsGlobalWindow *>(sgo);
|
||||
if (!internalWin->IsChromeWindow()) {
|
||||
rv = sXPConnect->GetCrossOriginWrapperForObject(cx, sgo->GetGlobalJSObject(),
|
||||
obj, &docVal);
|
||||
rv = sXPConnect->GetXOWForObject(cx, sgo->GetGlobalJSObject(), obj,
|
||||
&docVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -447,7 +447,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
|||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
%}
|
||||
|
||||
[uuid(2d7f1bd7-ef8b-4f62-b2bb-1a8b0801edc3)]
|
||||
[uuid(20df9082-5b83-416d-ba80-0422af516d57)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
|
@ -732,9 +732,26 @@ interface nsIXPConnect : nsISupports
|
|||
* @param aParent The parent to create the wrapper with.
|
||||
* @param aWrappedObj The object to wrap.
|
||||
*/
|
||||
[noscript] JSVal getCrossOriginWrapperForObject(in JSContextPtr aJSContext,
|
||||
in JSObjectPtr aParent,
|
||||
in JSObjectPtr aWrappedObj);
|
||||
[noscript] JSVal getXOWForObject(in JSContextPtr aJSContext,
|
||||
in JSObjectPtr aParent,
|
||||
in JSObjectPtr aWrappedObj);
|
||||
|
||||
/**
|
||||
* Tells updateXOWs to clear the scope of all of the XOWs it finds.
|
||||
*/
|
||||
const PRUint32 XPC_XOW_CLEARSCOPE = 1;
|
||||
|
||||
/**
|
||||
* Performs an operation over all of |object|'s XOWs such as clearing
|
||||
* their scopes or updating their concept of the current principal.
|
||||
*
|
||||
* @param aJSContext A context to use to perform JS operations.
|
||||
* @param aObject Which XPCWrappedNative we should find the XOWs for.
|
||||
* @param aWay What operation to perform.
|
||||
*/
|
||||
[noscript] void updateXOWs(in JSContextPtr aJSContext,
|
||||
in nsIXPConnectWrappedNative aObject,
|
||||
in PRUint32 aWay);
|
||||
|
||||
/**
|
||||
* Root JS objects held by aHolder.
|
||||
|
|
|
@ -191,6 +191,44 @@ GetSecurityManager()
|
|||
return gScriptSecurityManager;
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
XPCWrappedNativeScope *newScope)
|
||||
{
|
||||
typedef WrappedNative2WrapperMap::Link Link;
|
||||
XPCJSRuntime *rt = nsXPConnect::GetRuntime();
|
||||
WrappedNative2WrapperMap *map = innerObj->GetScope()->GetWrapperMap();
|
||||
Link *link;
|
||||
|
||||
{ // Scoped lock
|
||||
XPCAutoLock al(rt->GetMapLock());
|
||||
link = map->FindLink(innerObj->GetFlatJSObject());
|
||||
}
|
||||
|
||||
if (!link) {
|
||||
// No link here means that there were no XOWs for this object.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *xow = link->obj;
|
||||
|
||||
{ // Scoped lock.
|
||||
XPCAutoLock al(rt->GetMapLock());
|
||||
if (!newScope->GetWrapperMap()->AddLink(innerObj->GetFlatJSObject(), link))
|
||||
return JS_FALSE;
|
||||
map->Remove(innerObj->GetFlatJSObject());
|
||||
}
|
||||
|
||||
if (!xow) {
|
||||
// Nothing else to do.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return JS_SetReservedSlot(cx, xow, XPCWrapper::sNumSlots,
|
||||
PRIVATE_TO_JSVAL(newScope)) &&
|
||||
JS_SetParent(cx, xow, newScope->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
static JSBool
|
||||
IsValFrame(JSContext *cx, JSObject *obj, jsval v, XPCWrappedNative *wn)
|
||||
{
|
||||
|
@ -435,43 +473,34 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp)
|
|||
XPCCallContext ccx(NATIVE_CALLER, cx);
|
||||
NS_ENSURE_TRUE(ccx.IsValid(), JS_FALSE);
|
||||
|
||||
XPCWrappedNativeScope *parentScope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent);
|
||||
XPCWrappedNativeScope *wrapperScope = wn->GetScope();
|
||||
|
||||
#ifdef DEBUG_mrbkap
|
||||
printf("Wrapping object at %p (%s) [%p %p]\n",
|
||||
(void *)wrappedObj, JS_GET_CLASS(cx, wrappedObj)->name,
|
||||
(void *)parentScope, (void *)wrapperScope);
|
||||
#endif
|
||||
|
||||
JSObject *outerObj = nsnull;
|
||||
JSBool sameOrigin = (parentScope == wrapperScope);
|
||||
WrappedNative2WrapperMap *map =
|
||||
sameOrigin ? wrapperScope->GetWrapperMap() : parentScope->GetWrapperMap();
|
||||
|
||||
if (sameOrigin) {
|
||||
outerObj = wn->GetWrapper();
|
||||
if (outerObj && JS_GET_CLASS(cx, outerObj) == &sXPC_XOW_JSClass.base) {
|
||||
#ifdef DEBUG_mrbkap
|
||||
printf("But found a wrapper already there %p!\n", (void *)outerObj);
|
||||
#endif
|
||||
*vp = OBJECT_TO_JSVAL(outerObj);
|
||||
return JS_TRUE;
|
||||
// The parent must be the inner global object for its scope.
|
||||
parent = JS_GetGlobalForObject(cx, parent);
|
||||
JSClass *clasp = JS_GET_CLASS(cx, parent);
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp);
|
||||
if (xclasp->innerObject) {
|
||||
parent = xclasp->innerObject(cx, parent);
|
||||
if (!parent) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope *parentScope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent);
|
||||
|
||||
#ifdef DEBUG_mrbkap
|
||||
printf("Wrapping object at %p (%s) [%p]\n",
|
||||
(void *)wrappedObj, JS_GET_CLASS(cx, wrappedObj)->name,
|
||||
(void *)parentScope);
|
||||
#endif
|
||||
|
||||
JSObject *outerObj = nsnull;
|
||||
WrappedNative2WrapperMap *map = parentScope->GetWrapperMap();
|
||||
|
||||
{ // Scoped lock
|
||||
XPCAutoLock al(rt->GetMapLock());
|
||||
|
||||
if (outerObj) {
|
||||
outerObj = map->Add(wrappedObj, outerObj);
|
||||
if (sameOrigin) {
|
||||
wn->SetWrapper(nsnull);
|
||||
}
|
||||
} else {
|
||||
outerObj = map->Find(wrappedObj);
|
||||
}
|
||||
outerObj = map->Find(wrappedObj);
|
||||
}
|
||||
|
||||
if (outerObj) {
|
||||
|
@ -480,9 +509,6 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp)
|
|||
#ifdef DEBUG_mrbkap
|
||||
printf("But found a wrapper in the map %p!\n", (void *)outerObj);
|
||||
#endif
|
||||
if (sameOrigin) {
|
||||
wn->SetWrapper(outerObj);
|
||||
}
|
||||
*vp = OBJECT_TO_JSVAL(outerObj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -507,14 +533,10 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp)
|
|||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(outerObj);
|
||||
if (!sameOrigin) {
|
||||
|
||||
{ // Scoped lock
|
||||
XPCAutoLock al(rt->GetMapLock());
|
||||
map->Add(wrappedObj, outerObj);
|
||||
} else {
|
||||
#ifdef DEBUG_mrbkap
|
||||
printf("Setting wrapper to %p\n", (void *)outerObj);
|
||||
#endif
|
||||
wn->SetWrapper(outerObj);
|
||||
map->Add(wn->GetScope()->GetWrapperMap(), wrappedObj, outerObj);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
|
|
|
@ -1061,28 +1061,7 @@ XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper)
|
|||
}
|
||||
|
||||
JSObject *obj = wrapper->GetWrapper();
|
||||
if (obj && XPCNativeWrapper::IsNativeWrapper(cx, obj)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope *scope = wrapper->GetScope();
|
||||
XPCJSRuntime *rt = nsXPConnect::GetRuntime();
|
||||
|
||||
{ // Scoped lock.
|
||||
XPCAutoLock al(rt->GetMapLock());
|
||||
|
||||
if (obj) {
|
||||
obj = scope->GetWrapperMap()->Add(wrapper->GetFlatJSObject(), obj);
|
||||
wrapper->SetWrapper(nsnull);
|
||||
} else {
|
||||
obj = scope->GetWrapperMap()->Find(wrapper->GetFlatJSObject());
|
||||
}
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
NS_ASSERTION(XPCNativeWrapper::IsNativeWrapper(cx, obj),
|
||||
"Weird object in the wrapper map");
|
||||
wrapper->SetWrapper(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,10 @@ XPC_XOW_WrapFunction(JSContext *cx, JSObject *wrapperObj, JSObject *funobj,
|
|||
JSBool
|
||||
XPC_XOW_RewrapIfNeeded(JSContext *cx, JSObject *wrapperObj, jsval *vp);
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
XPCWrappedNativeScope *newScope);
|
||||
|
||||
nsresult
|
||||
IsWrapperSameOrigin(JSContext *cx, JSObject *wrappedObj);
|
||||
|
||||
|
|
|
@ -1916,16 +1916,66 @@ nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext,
|
|||
|
||||
/* [noscript] JSVal GetCrossOriginWrapperForValue(in JSContextPtr aJSContext, in JSVal aCurrentVal); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::GetCrossOriginWrapperForObject(JSContext * aJSContext,
|
||||
JSObject * aParent,
|
||||
JSObject * aWrappedObj,
|
||||
jsval * rval)
|
||||
nsXPConnect::GetXOWForObject(JSContext * aJSContext,
|
||||
JSObject * aParent,
|
||||
JSObject * aWrappedObj,
|
||||
jsval * rval)
|
||||
{
|
||||
*rval = OBJECT_TO_JSVAL(aWrappedObj);
|
||||
return XPC_XOW_WrapObject(aJSContext, aParent, rval)
|
||||
? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static inline PRBool
|
||||
PerformOp(JSContext *cx, PRUint32 aWay, JSObject *obj)
|
||||
{
|
||||
NS_ASSERTION(aWay == nsIXPConnect::XPC_XOW_CLEARSCOPE,
|
||||
"Nothing else is implemented yet");
|
||||
|
||||
JS_ClearScope(cx, obj);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/* [noscript] void updateXOWs (in JSContextPtr aJSContext,
|
||||
* in nsIXPConnectJSObjectHolder aObject,
|
||||
* in PRUint32 aWay); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::UpdateXOWs(JSContext* aJSContext,
|
||||
nsIXPConnectWrappedNative* aObject,
|
||||
PRUint32 aWay)
|
||||
{
|
||||
typedef WrappedNative2WrapperMap::Link Link;
|
||||
XPCWrappedNative* wn = static_cast<XPCWrappedNative *>(aObject);
|
||||
XPCWrappedNativeScope* scope = wn->GetScope();
|
||||
WrappedNative2WrapperMap* map = scope->GetWrapperMap();
|
||||
Link* list;
|
||||
|
||||
{
|
||||
XPCJSRuntime* rt = nsXPConnect::GetRuntime();
|
||||
XPCAutoLock al(rt->GetMapLock());
|
||||
|
||||
list = map->FindLink(wn->GetFlatJSObject());
|
||||
}
|
||||
|
||||
if(!list)
|
||||
return NS_OK; // No wrappers to update.
|
||||
|
||||
AutoJSRequestWithNoCallContext req(aJSContext);
|
||||
|
||||
Link* cur = list;
|
||||
if(cur->obj && !PerformOp(aJSContext, aWay, cur->obj))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
for(cur = (Link *)PR_NEXT_LINK(list); cur != list;
|
||||
cur = (Link *)PR_NEXT_LINK(cur))
|
||||
{
|
||||
if(!PerformOp(aJSContext, aWay, cur->obj))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute PRBool collectGarbageOnMainThreadOnly; */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::GetCollectGarbageOnMainThreadOnly(PRBool *aCollectGarbageOnMainThreadOnly)
|
||||
|
|
|
@ -652,6 +652,24 @@ XPCNativeWrapperMap::~XPCNativeWrapperMap()
|
|||
/***************************************************************************/
|
||||
// implement WrappedNative2WrapperMap...
|
||||
|
||||
struct JSDHashTableOps
|
||||
WrappedNative2WrapperMap::sOps = { nsnull };
|
||||
|
||||
// static
|
||||
void
|
||||
WrappedNative2WrapperMap::ClearLink(JSDHashTable* table,
|
||||
JSDHashEntryHdr* entry)
|
||||
{
|
||||
Entry* e = static_cast<Entry*>(entry);
|
||||
e->key = nsnull;
|
||||
if(e->value)
|
||||
{
|
||||
PR_REMOVE_LINK(e->value);
|
||||
delete e->value;
|
||||
e->value = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
WrappedNative2WrapperMap*
|
||||
WrappedNative2WrapperMap::newMap(int size)
|
||||
|
@ -665,8 +683,13 @@ WrappedNative2WrapperMap::newMap(int size)
|
|||
|
||||
WrappedNative2WrapperMap::WrappedNative2WrapperMap(int size)
|
||||
{
|
||||
mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
|
||||
sizeof(Entry), size);
|
||||
if(!sOps.allocTable)
|
||||
{
|
||||
sOps = *JS_DHashGetStubOps();
|
||||
sOps.clearEntry = WrappedNative2WrapperMap::ClearLink;
|
||||
}
|
||||
|
||||
mTable = JS_NewDHashTable(&sOps, nsnull, sizeof(Entry), size);
|
||||
}
|
||||
|
||||
WrappedNative2WrapperMap::~WrappedNative2WrapperMap()
|
||||
|
@ -675,4 +698,70 @@ WrappedNative2WrapperMap::~WrappedNative2WrapperMap()
|
|||
JS_DHashTableDestroy(mTable);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WrappedNative2WrapperMap::Add(WrappedNative2WrapperMap* head,
|
||||
JSObject* wrappedObject,
|
||||
JSObject* wrapper)
|
||||
{
|
||||
NS_PRECONDITION(wrappedObject,"bad param");
|
||||
Entry* entry = (Entry*)
|
||||
JS_DHashTableOperate(mTable, wrappedObject, JS_DHASH_ADD);
|
||||
if(!entry)
|
||||
return nsnull;
|
||||
NS_ASSERTION(!entry->key || this == head, "dangling pointer?");
|
||||
entry->key = wrappedObject;
|
||||
Link* l = new Link;
|
||||
if(!l)
|
||||
return nsnull;
|
||||
PR_INIT_CLIST(l);
|
||||
l->obj = wrapper;
|
||||
|
||||
if(this != head)
|
||||
{
|
||||
Link* headLink = head->FindLink(wrappedObject);
|
||||
if(!headLink)
|
||||
{
|
||||
Entry* dummy = (Entry*)
|
||||
JS_DHashTableOperate(head->mTable, wrappedObject, JS_DHASH_ADD);
|
||||
dummy->key = wrappedObject;
|
||||
headLink = dummy->value = new Link;
|
||||
if(!headLink)
|
||||
{
|
||||
Remove(wrappedObject);
|
||||
return nsnull;
|
||||
}
|
||||
PR_INIT_CLIST(headLink);
|
||||
headLink->obj = nsnull;
|
||||
}
|
||||
|
||||
PR_INSERT_BEFORE(l, headLink);
|
||||
}
|
||||
|
||||
entry->value = l;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
PRBool
|
||||
WrappedNative2WrapperMap::AddLink(JSObject* wrappedObject, Link* oldLink)
|
||||
{
|
||||
Entry* entry = (Entry*)
|
||||
JS_DHashTableOperate(mTable, wrappedObject, JS_DHASH_ADD);
|
||||
if(!entry)
|
||||
return PR_FALSE;
|
||||
NS_ASSERTION(!entry->key, "Eh? What's happening?");
|
||||
entry->key = wrappedObject;
|
||||
Link* newLink = entry->value = new Link;
|
||||
if(!newLink)
|
||||
{
|
||||
Remove(wrappedObject);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PR_INSERT_LINK(newLink, oldLink);
|
||||
PR_REMOVE_AND_INIT_LINK(oldLink);
|
||||
newLink->obj = oldLink->obj;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -686,12 +686,21 @@ private:
|
|||
|
||||
class WrappedNative2WrapperMap
|
||||
{
|
||||
static struct JSDHashTableOps sOps;
|
||||
|
||||
static void ClearLink(JSDHashTable* table, JSDHashEntryHdr* entry);
|
||||
|
||||
public:
|
||||
struct Link : public PRCList
|
||||
{
|
||||
JSObject *obj;
|
||||
};
|
||||
|
||||
struct Entry : public JSDHashEntryHdr
|
||||
{
|
||||
// Note: key must be the flat JSObject for a wrapped native.
|
||||
JSObject* key;
|
||||
JSObject* value;
|
||||
Link* value;
|
||||
};
|
||||
|
||||
static WrappedNative2WrapperMap* newMap(int size);
|
||||
|
@ -703,26 +712,29 @@ public:
|
|||
JS_DHashTableOperate(mTable, wrapper, JS_DHASH_LOOKUP);
|
||||
if(JS_DHASH_ENTRY_IS_FREE(entry))
|
||||
return nsnull;
|
||||
return entry->value;
|
||||
return entry->value->obj;
|
||||
}
|
||||
|
||||
// Note: If the entry already exists, then this will overwrite the
|
||||
// existing entry, returning the old value.
|
||||
inline JSObject* Add(JSObject* wrapper, JSObject *obj)
|
||||
JSObject* Add(WrappedNative2WrapperMap* head,
|
||||
JSObject* wrappedObject,
|
||||
JSObject* wrapper);
|
||||
|
||||
// Function to find a link.
|
||||
Link* FindLink(JSObject* wrappedObject)
|
||||
{
|
||||
NS_PRECONDITION(wrapper,"bad param");
|
||||
Entry* entry = (Entry*)
|
||||
JS_DHashTableOperate(mTable, wrapper, JS_DHASH_ADD);
|
||||
if(!entry)
|
||||
return nsnull;
|
||||
JSObject *old;
|
||||
if(!entry->key)
|
||||
entry->key = wrapper;
|
||||
old = entry->value;
|
||||
entry->value = obj;
|
||||
return old;
|
||||
JS_DHashTableOperate(mTable, wrappedObject, JS_DHASH_LOOKUP);
|
||||
if(JS_DHASH_ENTRY_IS_BUSY(entry))
|
||||
return entry->value;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// "Internal" function to add an empty link without doing unnecessary
|
||||
// work.
|
||||
PRBool AddLink(JSObject* wrappedObject, Link* oldLink);
|
||||
|
||||
inline void Remove(JSObject* wrapper)
|
||||
{
|
||||
NS_PRECONDITION(wrapper,"bad param");
|
||||
|
@ -734,9 +746,11 @@ public:
|
|||
{return JS_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
~WrappedNative2WrapperMap();
|
||||
|
||||
private:
|
||||
WrappedNative2WrapperMap(); // no implementation
|
||||
WrappedNative2WrapperMap(int size);
|
||||
|
||||
private:
|
||||
JSDHashTable *mTable;
|
||||
};
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "prlong.h"
|
||||
#include "prmem.h"
|
||||
#include "prenv.h"
|
||||
#include "prclist.h"
|
||||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
|
|
@ -1158,6 +1158,10 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
|
|||
{
|
||||
// Oh, so now we need to move the wrapper to a different scope.
|
||||
|
||||
// First notify any XOWs.
|
||||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
xpc->UpdateXOWs(ccx, wrapper, nsIXPConnect::XPC_XOW_CLEARSCOPE);
|
||||
|
||||
AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
|
||||
AutoMarkingWrappedNativeProtoPtr newProto(ccx);
|
||||
|
||||
|
@ -1179,6 +1183,12 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
|
|||
}
|
||||
}
|
||||
|
||||
if(!XPC_XOW_WrapperMoved(ccx, wrapper, aNewScope))
|
||||
{
|
||||
NS_RELEASE(wrapper);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
|
||||
Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = test_bug390488.html \
|
||||
test_bug393269.html \
|
||||
test_wrappers.html \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=393269
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 393269</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=393269">Mozilla Bug 393269</a>
|
||||
<iframe id="ifr"></iframe>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
(function () {
|
||||
/** Test for Bug 393269 **/
|
||||
var doc = $("ifr").contentDocument;
|
||||
is("UTF-8", doc.characterSet, "control, getting a property");
|
||||
doc.open();
|
||||
try {
|
||||
is("UTF-8", doc.characterSet,
|
||||
"can get a property after 1 document.open")
|
||||
} catch (e) {
|
||||
fail("Shouldn't have thrown: " + e);
|
||||
return;
|
||||
} finally {
|
||||
doc.close();
|
||||
}
|
||||
|
||||
doc.open();
|
||||
try {
|
||||
is("UTF-8", doc.characterSet,
|
||||
"can get a property after 2 document.opens")
|
||||
} catch (e) {
|
||||
fail("Shouldn't have thrown: " + e);
|
||||
} finally {
|
||||
doc.close();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче