mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Preserve identity for deep wrapping (bug 610390, r=mrbkap, a=b8).
This commit is contained in:
parent
b8cc189151
commit
f7f43f70b7
@ -83,6 +83,7 @@ class XPCNativeScriptableSharedMap;
|
||||
class XPCWrappedNativeProtoMap;
|
||||
class XPCNativeWrapperMap;
|
||||
class WrappedNative2WrapperMap;
|
||||
class JSObject2JSObjectMap;
|
||||
|
||||
class nsXPCComponents;
|
||||
class nsXPCComponents_Interfaces;
|
||||
|
@ -240,6 +240,12 @@ ContextCallback(JSContext *cx, uintN operation)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
xpc::CompartmentPrivate::~CompartmentPrivate()
|
||||
{
|
||||
if (waiverWrapperMap)
|
||||
delete waiverWrapperMap;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
CompartmentCallback(JSContext *cx, JSCompartment *compartment, uintN op)
|
||||
{
|
||||
@ -545,6 +551,27 @@ DoDeferredRelease(nsTArray<T> &array)
|
||||
}
|
||||
}
|
||||
|
||||
static JSDHashOperator
|
||||
SweepWaiverWrappers(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
uint32 number, void *arg)
|
||||
{
|
||||
JSObject *key = ((JSObject2JSObjectMap::Entry *)hdr)->key;
|
||||
JSObject *value = ((JSObject2JSObjectMap::Entry *)hdr)->value;
|
||||
if(IsAboutToBeFinalized(key) || IsAboutToBeFinalized(value))
|
||||
return JS_DHASH_REMOVE;
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
SweepCompartment(nsCStringHashKey& aKey, JSCompartment *compartment, void *aClosure)
|
||||
{
|
||||
xpc::CompartmentPrivate *priv = (xpc::CompartmentPrivate *)
|
||||
JS_GetCompartmentPrivate((JSContext *)aClosure, compartment);
|
||||
if (priv->waiverWrapperMap)
|
||||
priv->waiverWrapperMap->Enumerate(SweepWaiverWrappers, nsnull);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
{
|
||||
@ -597,9 +624,14 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
Enumerate(WrappedJSDyingJSObjectFinder, &data);
|
||||
}
|
||||
|
||||
// Find dying scopes...
|
||||
// Find dying scopes.
|
||||
XPCWrappedNativeScope::FinishedMarkPhaseOfGC(cx, self);
|
||||
|
||||
// Sweep compartments.
|
||||
self->GetCompartmentMap().EnumerateRead(
|
||||
(XPCCompartmentMap::EnumReadFunction)
|
||||
SweepCompartment, cx);
|
||||
|
||||
self->mDoingFinalization = JS_TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -763,3 +763,18 @@ WrappedNative2WrapperMap::AddLink(JSObject* wrappedObject, Link* oldLink)
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// implement JSObject2JSObjectMap...
|
||||
|
||||
struct JSDHashTableOps
|
||||
JSObject2JSObjectMap::sOps = {
|
||||
JS_DHashAllocTable,
|
||||
JS_DHashFreeTable,
|
||||
JS_DHashVoidPtrKeyStub,
|
||||
JS_DHashMatchEntryStub,
|
||||
JS_DHashMoveEntryStub,
|
||||
JS_DHashClearEntryStub,
|
||||
JS_DHashFinalizeStub,
|
||||
nsnull
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -710,4 +710,80 @@ private:
|
||||
JSDHashTable *mTable;
|
||||
};
|
||||
|
||||
class JSObject2JSObjectMap
|
||||
{
|
||||
static struct JSDHashTableOps sOps;
|
||||
|
||||
public:
|
||||
struct Entry : public JSDHashEntryHdr
|
||||
{
|
||||
JSObject* key;
|
||||
JSObject* value;
|
||||
};
|
||||
|
||||
static JSObject2JSObjectMap* newMap(int size)
|
||||
{
|
||||
JSObject2JSObjectMap* map = new JSObject2JSObjectMap(size);
|
||||
if(map && map->mTable)
|
||||
return map;
|
||||
delete map;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
inline JSObject* Find(JSObject* key)
|
||||
{
|
||||
NS_PRECONDITION(key, "bad param");
|
||||
Entry* entry = (Entry*)
|
||||
JS_DHashTableOperate(mTable, key, JS_DHASH_LOOKUP);
|
||||
if(JS_DHASH_ENTRY_IS_FREE(entry))
|
||||
return nsnull;
|
||||
return entry->value;
|
||||
}
|
||||
|
||||
// Note: If the entry already exists, return the old value.
|
||||
inline JSObject* Add(JSObject *key, JSObject *value)
|
||||
{
|
||||
NS_PRECONDITION(key,"bad param");
|
||||
Entry* entry = (Entry*)
|
||||
JS_DHashTableOperate(mTable, key, JS_DHASH_ADD);
|
||||
if(!entry)
|
||||
return nsnull;
|
||||
if(entry->key)
|
||||
return entry->value;
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline void Remove(JSObject* key)
|
||||
{
|
||||
NS_PRECONDITION(key,"bad param");
|
||||
JS_DHashTableOperate(mTable, key, JS_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32 Count() {return mTable->entryCount;}
|
||||
|
||||
inline uint32 Enumerate(JSDHashEnumerator f, void *arg)
|
||||
{
|
||||
return JS_DHashTableEnumerate(mTable, f, arg);
|
||||
}
|
||||
|
||||
~JSObject2JSObjectMap()
|
||||
{
|
||||
if(mTable)
|
||||
JS_DHashTableDestroy(mTable);
|
||||
}
|
||||
|
||||
private:
|
||||
JSObject2JSObjectMap(int size)
|
||||
{
|
||||
mTable = JS_NewDHashTable(&sOps, nsnull, sizeof(Entry), size);
|
||||
}
|
||||
|
||||
JSObject2JSObjectMap(); // no implementation
|
||||
|
||||
private:
|
||||
JSDHashTable *mTable;
|
||||
};
|
||||
|
||||
#endif /* xpcmaps_h___ */
|
||||
|
@ -240,6 +240,7 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper);
|
||||
#define XPC_NATIVE_JSCLASS_MAP_SIZE 32
|
||||
#define XPC_THIS_TRANSLATOR_MAP_SIZE 8
|
||||
#define XPC_NATIVE_WRAPPER_MAP_SIZE 16
|
||||
#define XPC_WRAPPER_MAP_SIZE 16
|
||||
|
||||
/***************************************************************************/
|
||||
// data declarations...
|
||||
@ -323,7 +324,7 @@ typedef nsDataHashtableMT<nsISupportsHashKey, JSCompartment *> XPCMTCompartmentM
|
||||
typedef nsDataHashtable<xpc::PtrAndPrincipalHashKey, JSCompartment *> XPCCompartmentMap;
|
||||
|
||||
/***************************************************************************/
|
||||
// useful macros...
|
||||
// Useful macros...
|
||||
|
||||
#define XPC_STRING_GETTER_BODY(dest, src) \
|
||||
NS_ENSURE_ARG_POINTER(dest); \
|
||||
@ -4484,22 +4485,28 @@ struct CompartmentPrivate
|
||||
: key(key),
|
||||
ptr(nsnull),
|
||||
wantXrays(wantXrays),
|
||||
cycleCollectionEnabled(cycleCollectionEnabled)
|
||||
cycleCollectionEnabled(cycleCollectionEnabled),
|
||||
waiverWrapperMap(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
CompartmentPrivate(nsISupports *ptr, bool wantXrays, bool cycleCollectionEnabled)
|
||||
: key(nsnull),
|
||||
ptr(ptr),
|
||||
wantXrays(wantXrays),
|
||||
cycleCollectionEnabled(cycleCollectionEnabled)
|
||||
cycleCollectionEnabled(cycleCollectionEnabled),
|
||||
waiverWrapperMap(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
~CompartmentPrivate();
|
||||
|
||||
// NB: key and ptr are mutually exclusive.
|
||||
nsAutoPtr<PtrAndPrincipalHashKey> key;
|
||||
nsCOMPtr<nsISupports> ptr;
|
||||
bool wantXrays;
|
||||
bool cycleCollectionEnabled;
|
||||
JSObject2JSObjectMap *waiverWrapperMap;
|
||||
};
|
||||
|
||||
inline bool
|
||||
|
@ -58,6 +58,7 @@ _CHROME_FILES = \
|
||||
test_bug517163.xul \
|
||||
test_bug571849.xul \
|
||||
test_bug601803.xul \
|
||||
test_bug610390.xul \
|
||||
$(NULL)
|
||||
|
||||
# Disabled until this test gets updated to test the new proxy based
|
||||
|
34
js/src/xpconnect/tests/chrome/test_bug610390.xul
Normal file
34
js/src/xpconnect/tests/chrome/test_bug610390.xul
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=610390
|
||||
-->
|
||||
<window title="Mozilla Bug 610390"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<iframe type="content"
|
||||
src="data:text/html,<script>var x=3</script>"
|
||||
onload="go()"
|
||||
id="ifr">
|
||||
</iframe>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function go() {
|
||||
var w = $('ifr').contentWindow;
|
||||
is(w.wrappedJSObject, w.wrappedJSObject, "wrappedJSObject identity not maintained");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
]]></script>
|
||||
</window>
|
@ -48,6 +48,7 @@
|
||||
#include "XPCWrapper.h"
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "xpcmaps.h"
|
||||
|
||||
namespace xpc {
|
||||
|
||||
@ -307,10 +308,33 @@ WrapperFactory::WaiveXrayAndWrap(JSContext *cx, jsval *vp)
|
||||
obj = GetCurrentOuter(cx, obj);
|
||||
|
||||
{
|
||||
js::SwitchToCompartment sc(cx, obj->compartment());
|
||||
obj = JSWrapper::New(cx, obj, NULL, obj->getGlobal(), &WaiveXrayWrapperWrapper);
|
||||
if (!obj)
|
||||
return false;
|
||||
// See if we already have a waiver wrapper for this object.
|
||||
CompartmentPrivate *priv =
|
||||
(CompartmentPrivate *)JS_GetCompartmentPrivate(cx, obj->compartment());
|
||||
JSObject *wobj = nsnull;
|
||||
if (priv && priv->waiverWrapperMap)
|
||||
wobj = priv->waiverWrapperMap->Find(obj);
|
||||
|
||||
// No wrapper yet, make one.
|
||||
if (!wobj) {
|
||||
js::SwitchToCompartment sc(cx, obj->compartment());
|
||||
wobj = JSWrapper::New(cx, obj, NULL, obj->getGlobal(), &WaiveXrayWrapperWrapper);
|
||||
if (!wobj)
|
||||
return false;
|
||||
|
||||
// Add the new wrapper so we find it next time.
|
||||
if (priv) {
|
||||
if (!priv->waiverWrapperMap) {
|
||||
priv->waiverWrapperMap = JSObject2JSObjectMap::newMap(XPC_WRAPPER_MAP_SIZE);
|
||||
if (!priv->waiverWrapperMap)
|
||||
return false;
|
||||
}
|
||||
if (!priv->waiverWrapperMap->Add(obj, wobj))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
obj = wobj;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
|
Loading…
Reference in New Issue
Block a user