Bug 580128 - Give objects a way to inform XPConnect that they implement their own JS object in a way that does not involve wrapped natives. r=peterv

This commit is contained in:
Blake Kaplan 2010-09-17 14:54:40 -07:00
Родитель c5cde776e4
Коммит 234cbcb3a1
3 изменённых файлов: 110 добавлений и 47 удалений

Просмотреть файл

@ -78,7 +78,8 @@ public:
void SetWrapper(JSObject* aWrapper)
{
NS_ASSERTION(!PreservingWrapper(), "Clearing a preserved wrapper!");
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper);
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper) |
(mWrapperPtrBits & WRAPPER_IS_PROXY);
}
void ClearWrapper()
@ -99,12 +100,23 @@ public:
PRBool PreservingWrapper()
{
return mWrapperPtrBits & WRAPPER_BIT_PRESERVED;
return (mWrapperPtrBits & WRAPPER_BIT_PRESERVED) != 0;
}
void SetIsProxy()
{
mWrapperPtrBits |= WRAPPER_IS_PROXY;
}
PRBool IsProxy()
{
return (mWrapperPtrBits & WRAPPER_IS_PROXY) != 0;
}
private:
enum { WRAPPER_BIT_PRESERVED = 1 << 0 };
enum { kWrapperBitMask = 0x1 };
enum { WRAPPER_IS_PROXY = 1 << 1 };
enum { kWrapperBitMask = (WRAPPER_BIT_PRESERVED | WRAPPER_IS_PROXY) };
PtrBits mWrapperPtrBits;
};

Просмотреть файл

@ -1070,7 +1070,7 @@ CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, jsval* d,
XPCJSObjectHolder* objHolder = XPCJSObjectHolder::newHolder(ccx, obj);
if(!objHolder)
return JS_FALSE;
NS_ADDREF(*dest = objHolder);
}
@ -1079,6 +1079,48 @@ CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, jsval* d,
return JS_TRUE;
}
static void
ComputeWrapperInfo(const XPCCallContext &ccx,
JSObject **callee,
JSScript **script)
{
*callee = nsnull;
*script = nsnull;
if(ccx.GetXPCContext()->CallerTypeIsJavaScript())
{
// Called from JS. We're going to hand the resulting
// JSObject to said JS, so look for the script we want on
// the stack.
JSStackFrame* fp = JS_GetScriptedCaller(ccx, NULL);
if(fp)
{
*script = fp->maybeScript();
*callee = fp->isFunctionFrame()
? &fp->callee()
: &fp->scopeChain();
}
}
else if(ccx.GetXPCContext()->CallerTypeIsNative())
{
*callee = ccx.GetCallee();
if(*callee && JS_ObjectIsFunction(ccx, *callee))
{
// Called from c++, and calling out to |callee|, which is a JS
// function object. Look for the script for this function.
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(*callee);
NS_ASSERTION(fun, "Must have JSFunction for a Function object");
*script = JS_GetFunctionScript(ccx, fun);
}
else
{
// Else we don't know whom we're calling, so don't
// create XPCNativeWrappers.
*callee = nsnull;
}
}
}
/***************************************************************************/
// static
JSBool
@ -1151,11 +1193,38 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject *callee = nsnull;
JSScript *script = nsnull;
PRBool tryConstructSlimWrapper = PR_FALSE;
JSObject *flat;
if(cache)
{
flat = cache->GetWrapper();
if(cache->IsProxy())
{
if(flat)
{
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(!ccx.IsValid())
return JS_FALSE;
ComputeWrapperInfo(ccx, &callee, &script);
if(!callee)
callee = xpcscope->GetGlobalJSObject();
JSAutoCrossCompartmentCall accc;
if(!accc.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
return JS_FALSE;
return CreateHolderIfNeeded(ccx, flat, d, dest);
}
else
{
tryConstructSlimWrapper = PR_TRUE;
}
}
if(!dest)
{
if(!flat)
@ -1196,6 +1265,22 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
// fall through because we either have a slim wrapper that needs to be
// morphed or we have an XPCWrappedNative.
flat = cache->GetWrapper();
if(cache->IsProxy())
{
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(!ccx.IsValid())
return JS_FALSE;
ComputeWrapperInfo(ccx, &callee, &script);
if(!callee)
callee = xpcscope->GetGlobalJSObject();
JSAutoCrossCompartmentCall accc;
if(!accc.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
return JS_FALSE;
return CreateHolderIfNeeded(ccx, flat, d, dest);
}
}
AutoMarkingNativeInterfacePtr iface;
@ -1221,7 +1306,8 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
}
}
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(flat->getClass()),
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(flat->getClass()) ||
cache->IsProxy(),
"What kind of wrapper is this?");
nsresult rv;
@ -1257,7 +1343,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
else
rv = NS_OK;
}
else
else if(!cache->IsProxy())
{
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
"What kind of wrapper is this?");
@ -1299,45 +1385,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
// printf("Wrapped native accessed across scope boundary\n");
JSScript* script = nsnull;
JSObject* callee = nsnull;
if(ccx.GetXPCContext()->CallerTypeIsJavaScript())
{
// Called from JS. We're going to hand the resulting
// JSObject to said JS, so look for the script we want on
// the stack.
JSContext* cx = ccx;
JSStackFrame* fp = JS_GetScriptedCaller(cx, NULL);
if(fp)
{
script = JS_GetFrameScript(cx, fp);
callee = JS_GetFrameCalleeObject(cx, fp);
}
}
else if(ccx.GetXPCContext()->CallerTypeIsNative())
{
callee = ccx.GetCallee();
if(callee && JS_ObjectIsFunction(ccx, callee))
{
// Called from c++, and calling out to |callee|, which
// is a JS function object. Look for the script for
// this function.
JSFunction* fun =
(JSFunction*) xpc_GetJSPrivate(callee);
NS_ASSERTION(fun,
"Must have JSFunction for a Function "
"object");
script = JS_GetFunctionScript(ccx, fun);
}
else
{
// Else we don't know whom we're calling, so don't
// create XPCNativeWrappers.
callee = nsnull;
}
}
// else don't create XPCNativeWrappers, since we have
// no idea what's calling what here.
ComputeWrapperInfo(ccx, &callee, &script);
flags = script ? JS_GetScriptFilenameFlags(script) : 0;
NS_ASSERTION(flags != JSFILENAME_NULL, "null script filename");

Просмотреть файл

@ -3879,11 +3879,15 @@ ConstructSlimWrapper(XPCCallContext &ccx,
return JS_FALSE;
}
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject* plannedParent = parent;
rv = classInfoHelper->PreCreate(identityObj, ccx, parent, &parent);
if(rv != NS_SUCCESS_ALLOW_SLIM_WRAPPERS)
{
SLIM_LOG_NOT_CREATED(ccx, identityObj, "PreCreate hook refused");
if(cache->IsProxy())
NS_ASSERTION(cache->GetWrapper(), "out of memory?");
else
SLIM_LOG_NOT_CREATED(ccx, identityObj, "PreCreate hook refused");
return JS_FALSE;
}
@ -3902,7 +3906,6 @@ ConstructSlimWrapper(XPCCallContext &ccx,
// The PreCreate hook could have forced the creation of a wrapper, need
// to check for that here and return early.
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject* wrapper = cache->GetWrapper();
if(wrapper)
{