зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
c5cde776e4
Коммит
234cbcb3a1
|
@ -78,7 +78,8 @@ public:
|
||||||
void SetWrapper(JSObject* aWrapper)
|
void SetWrapper(JSObject* aWrapper)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(!PreservingWrapper(), "Clearing a preserved wrapper!");
|
NS_ASSERTION(!PreservingWrapper(), "Clearing a preserved wrapper!");
|
||||||
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper);
|
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper) |
|
||||||
|
(mWrapperPtrBits & WRAPPER_IS_PROXY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearWrapper()
|
void ClearWrapper()
|
||||||
|
@ -99,12 +100,23 @@ public:
|
||||||
|
|
||||||
PRBool PreservingWrapper()
|
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:
|
private:
|
||||||
enum { WRAPPER_BIT_PRESERVED = 1 << 0 };
|
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;
|
PtrBits mWrapperPtrBits;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1070,7 +1070,7 @@ CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, jsval* d,
|
||||||
XPCJSObjectHolder* objHolder = XPCJSObjectHolder::newHolder(ccx, obj);
|
XPCJSObjectHolder* objHolder = XPCJSObjectHolder::newHolder(ccx, obj);
|
||||||
if(!objHolder)
|
if(!objHolder)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
NS_ADDREF(*dest = objHolder);
|
NS_ADDREF(*dest = objHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1079,6 +1079,48 @@ CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, jsval* d,
|
||||||
return JS_TRUE;
|
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
|
// static
|
||||||
JSBool
|
JSBool
|
||||||
|
@ -1151,11 +1193,38 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||||
|
|
||||||
nsWrapperCache *cache = aHelper.GetWrapperCache();
|
nsWrapperCache *cache = aHelper.GetWrapperCache();
|
||||||
|
|
||||||
|
JSObject *callee = nsnull;
|
||||||
|
JSScript *script = nsnull;
|
||||||
|
|
||||||
PRBool tryConstructSlimWrapper = PR_FALSE;
|
PRBool tryConstructSlimWrapper = PR_FALSE;
|
||||||
JSObject *flat;
|
JSObject *flat;
|
||||||
if(cache)
|
if(cache)
|
||||||
{
|
{
|
||||||
flat = cache->GetWrapper();
|
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(!dest)
|
||||||
{
|
{
|
||||||
if(!flat)
|
if(!flat)
|
||||||
|
@ -1196,6 +1265,22 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||||
// fall through because we either have a slim wrapper that needs to be
|
// fall through because we either have a slim wrapper that needs to be
|
||||||
// morphed or we have an XPCWrappedNative.
|
// morphed or we have an XPCWrappedNative.
|
||||||
flat = cache->GetWrapper();
|
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;
|
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?");
|
"What kind of wrapper is this?");
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
@ -1257,7 +1343,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||||
else
|
else
|
||||||
rv = NS_OK;
|
rv = NS_OK;
|
||||||
}
|
}
|
||||||
else
|
else if(!cache->IsProxy())
|
||||||
{
|
{
|
||||||
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
|
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
|
||||||
"What kind of wrapper is this?");
|
"What kind of wrapper is this?");
|
||||||
|
@ -1299,45 +1385,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||||
|
|
||||||
// printf("Wrapped native accessed across scope boundary\n");
|
// printf("Wrapped native accessed across scope boundary\n");
|
||||||
|
|
||||||
JSScript* script = nsnull;
|
ComputeWrapperInfo(ccx, &callee, &script);
|
||||||
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.
|
|
||||||
|
|
||||||
flags = script ? JS_GetScriptFilenameFlags(script) : 0;
|
flags = script ? JS_GetScriptFilenameFlags(script) : 0;
|
||||||
NS_ASSERTION(flags != JSFILENAME_NULL, "null script filename");
|
NS_ASSERTION(flags != JSFILENAME_NULL, "null script filename");
|
||||||
|
|
|
@ -3879,11 +3879,15 @@ ConstructSlimWrapper(XPCCallContext &ccx,
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsWrapperCache *cache = aHelper.GetWrapperCache();
|
||||||
JSObject* plannedParent = parent;
|
JSObject* plannedParent = parent;
|
||||||
rv = classInfoHelper->PreCreate(identityObj, ccx, parent, &parent);
|
rv = classInfoHelper->PreCreate(identityObj, ccx, parent, &parent);
|
||||||
if(rv != NS_SUCCESS_ALLOW_SLIM_WRAPPERS)
|
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;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -3902,7 +3906,6 @@ ConstructSlimWrapper(XPCCallContext &ccx,
|
||||||
|
|
||||||
// The PreCreate hook could have forced the creation of a wrapper, need
|
// The PreCreate hook could have forced the creation of a wrapper, need
|
||||||
// to check for that here and return early.
|
// to check for that here and return early.
|
||||||
nsWrapperCache *cache = aHelper.GetWrapperCache();
|
|
||||||
JSObject* wrapper = cache->GetWrapper();
|
JSObject* wrapper = cache->GetWrapper();
|
||||||
if(wrapper)
|
if(wrapper)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче