зеркало из https://github.com/mozilla/pjs.git
Bug 513065 - Part 3, compute scope in the engine before calling the thisObject hook. r=mrbkap.
This commit is contained in:
Родитель
e723a3bdd7
Коммит
ab890a859e
|
@ -371,11 +371,17 @@ js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp)
|
||||||
|
|
||||||
/* Some objects (e.g., With) delegate 'this' to another object. */
|
/* Some objects (e.g., With) delegate 'this' to another object. */
|
||||||
static inline JSObject *
|
static inline JSObject *
|
||||||
CallThisObjectHook(JSContext *cx, JSObject *obj, jsval *argv)
|
CallThisObjectHook(JSContext *cx, JSObject *obj, JSObject *scope, jsval *argv)
|
||||||
{
|
{
|
||||||
JSObject *thisp = obj->thisObject(cx);
|
JSObject *thisp = obj;
|
||||||
if (!thisp)
|
if (JSThisObjectOp thisObject = obj->map->ops->thisObject) {
|
||||||
return NULL;
|
if (!scope)
|
||||||
|
scope = JSVAL_TO_OBJECT(argv[-2])->getGlobal();
|
||||||
|
thisp = thisObject(cx, obj, scope);
|
||||||
|
if (!thisp)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
argv[-1] = OBJECT_TO_JSVAL(thisp);
|
argv[-1] = OBJECT_TO_JSVAL(thisp);
|
||||||
return thisp;
|
return thisp;
|
||||||
}
|
}
|
||||||
|
@ -398,45 +404,29 @@ CallThisObjectHook(JSContext *cx, JSObject *obj, jsval *argv)
|
||||||
JS_STATIC_INTERPRET JSObject *
|
JS_STATIC_INTERPRET JSObject *
|
||||||
js_ComputeGlobalThis(JSContext *cx, jsval *argv)
|
js_ComputeGlobalThis(JSContext *cx, jsval *argv)
|
||||||
{
|
{
|
||||||
JSObject *thisp;
|
JSObject *thisp = JSVAL_TO_OBJECT(argv[-2])->getGlobal();
|
||||||
|
return CallThisObjectHook(cx, thisp, thisp, argv);
|
||||||
if (JSVAL_IS_PRIMITIVE(argv[-2]) ||
|
|
||||||
!JSVAL_TO_OBJECT(argv[-2])->getParent()) {
|
|
||||||
thisp = cx->globalObject;
|
|
||||||
} else {
|
|
||||||
thisp = JSVAL_TO_OBJECT(argv[-2])->getGlobal();
|
|
||||||
}
|
|
||||||
|
|
||||||
return CallThisObjectHook(cx, thisp, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSObject *
|
|
||||||
ComputeThis(JSContext *cx, jsval *argv)
|
|
||||||
{
|
|
||||||
JSObject *thisp;
|
|
||||||
|
|
||||||
JS_ASSERT(!JSVAL_IS_NULL(argv[-1]));
|
|
||||||
if (!JSVAL_IS_OBJECT(argv[-1])) {
|
|
||||||
if (!js_PrimitiveToObject(cx, &argv[-1]))
|
|
||||||
return NULL;
|
|
||||||
thisp = JSVAL_TO_OBJECT(argv[-1]);
|
|
||||||
return thisp;
|
|
||||||
}
|
|
||||||
|
|
||||||
thisp = JSVAL_TO_OBJECT(argv[-1]);
|
|
||||||
if (thisp->getClass() == &js_CallClass || thisp->getClass() == &js_BlockClass)
|
|
||||||
return js_ComputeGlobalThis(cx, argv);
|
|
||||||
|
|
||||||
return CallThisObjectHook(cx, thisp, argv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
js_ComputeThis(JSContext *cx, jsval *argv)
|
js_ComputeThis(JSContext *cx, jsval *argv)
|
||||||
{
|
{
|
||||||
JS_ASSERT(argv[-1] != JSVAL_HOLE); // check for SynthesizeFrame poisoning
|
JS_ASSERT(argv[-1] != JSVAL_HOLE); // check for SynthesizeFrame poisoning
|
||||||
|
|
||||||
if (JSVAL_IS_NULL(argv[-1]))
|
if (JSVAL_IS_NULL(argv[-1]))
|
||||||
return js_ComputeGlobalThis(cx, argv);
|
return js_ComputeGlobalThis(cx, argv);
|
||||||
return ComputeThis(cx, argv);
|
|
||||||
|
if (!JSVAL_IS_OBJECT(argv[-1])) {
|
||||||
|
if (!js_PrimitiveToObject(cx, &argv[-1]))
|
||||||
|
return NULL;
|
||||||
|
return JSVAL_TO_OBJECT(argv[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *thisp = JSVAL_TO_OBJECT(argv[-1]);
|
||||||
|
if (thisp->getClass() == &js_CallClass || thisp->getClass() == &js_BlockClass)
|
||||||
|
return js_ComputeGlobalThis(cx, argv);
|
||||||
|
|
||||||
|
return CallThisObjectHook(cx, thisp, NULL, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JS_HAS_NO_SUCH_METHOD
|
#if JS_HAS_NO_SUCH_METHOD
|
||||||
|
@ -1058,7 +1048,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
||||||
return false;
|
return false;
|
||||||
frame.scopeChain = chain;
|
frame.scopeChain = chain;
|
||||||
|
|
||||||
JSObject *thisp = JSVAL_TO_OBJECT(frame.thisv)->thisObject(cx);
|
JSObject *thisp = JSVAL_TO_OBJECT(frame.thisv)->thisObject(cx, chain);
|
||||||
if (!thisp)
|
if (!thisp)
|
||||||
return false;
|
return false;
|
||||||
frame.thisv = OBJECT_TO_JSVAL(thisp);
|
frame.thisv = OBJECT_TO_JSVAL(thisp);
|
||||||
|
|
|
@ -2947,12 +2947,12 @@ with_TypeOf(JSContext *cx, JSObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSObject *
|
static JSObject *
|
||||||
with_ThisObject(JSContext *cx, JSObject *obj)
|
with_ThisObject(JSContext *cx, JSObject *obj, JSObject *scope)
|
||||||
{
|
{
|
||||||
JSObject *proto = obj->getProto();
|
JSObject *proto = obj->getProto();
|
||||||
if (!proto)
|
if (!proto)
|
||||||
return obj;
|
return obj;
|
||||||
return proto->thisObject(cx);
|
return proto->thisObject(cx, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
|
JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
|
||||||
|
|
|
@ -161,7 +161,7 @@ struct JSObjectOps {
|
||||||
JSTraceOp trace;
|
JSTraceOp trace;
|
||||||
|
|
||||||
/* Optionally non-null members start here. */
|
/* Optionally non-null members start here. */
|
||||||
JSObjectOp thisObject;
|
JSThisObjectOp thisObject;
|
||||||
JSPropertyRefOp dropProperty;
|
JSPropertyRefOp dropProperty;
|
||||||
JSNative call;
|
JSNative call;
|
||||||
JSNative construct;
|
JSNative construct;
|
||||||
|
@ -634,8 +634,8 @@ struct JSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These four are time-optimized to avoid stub calls. */
|
/* These four are time-optimized to avoid stub calls. */
|
||||||
JSObject *thisObject(JSContext *cx) {
|
JSObject *thisObject(JSContext *cx, JSObject *scope) {
|
||||||
return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
|
return map->ops->thisObject ? map->ops->thisObject(cx, this, scope) : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dropProperty(JSContext *cx, JSProperty *prop) {
|
void dropProperty(JSContext *cx, JSProperty *prop) {
|
||||||
|
|
|
@ -423,9 +423,19 @@ typedef JSBool
|
||||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A generic type for functions mapping an object to another object, or null
|
* The type of JSObjectOps::thisObject. Return a "stunt this" object for obj,
|
||||||
* if an error or exception was thrown on cx. Used by JSObjectOps.thisObject
|
* having a parent chain that ends in scope; or NULL on error.
|
||||||
* at present.
|
*
|
||||||
|
* The engine guarantees that obj->map->ops->thisObject == the callback
|
||||||
|
* and that cx, obj, and scope are non-null.
|
||||||
|
*/
|
||||||
|
typedef JSObject *
|
||||||
|
(* JSThisObjectOp)(JSContext *cx, JSObject *obj, JSObject *scope);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A generic type for functions mapping an object to another object, or null if
|
||||||
|
* an error or exception was thrown on cx. Used by JSObjectOps.innerObject and
|
||||||
|
* outerObject at present.
|
||||||
*/
|
*/
|
||||||
typedef JSObject *
|
typedef JSObject *
|
||||||
(* JSObjectOp)(JSContext *cx, JSObject *obj);
|
(* JSObjectOp)(JSContext *cx, JSObject *obj);
|
||||||
|
|
|
@ -9516,7 +9516,7 @@ TraceRecorder::getThis(LIns*& this_ins)
|
||||||
|
|
||||||
this_ins = get(&thisv);
|
this_ins = get(&thisv);
|
||||||
|
|
||||||
JSObject* wrappedGlobal = globalObj->thisObject(cx);
|
JSObject* wrappedGlobal = globalObj->thisObject(cx, globalObj);
|
||||||
if (!wrappedGlobal)
|
if (!wrappedGlobal)
|
||||||
RETURN_ERROR("globalObj->thisObject hook threw in getThis");
|
RETURN_ERROR("globalObj->thisObject hook threw in getThis");
|
||||||
|
|
||||||
|
|
|
@ -2763,7 +2763,7 @@ split_outerObject(JSContext *cx, JSObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSObject *
|
static JSObject *
|
||||||
split_thisObject(JSContext *cx, JSObject *obj)
|
split_thisObject(JSContext *cx, JSObject *obj, JSObject */*scope*/)
|
||||||
{
|
{
|
||||||
OBJ_TO_OUTER_OBJECT(cx, obj);
|
OBJ_TO_OUTER_OBJECT(cx, obj);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
|
|
|
@ -133,13 +133,16 @@ xpcJSWeakReference::Get()
|
||||||
// nsXPConnect::GetWrapperForObject. But it takes a lot of
|
// nsXPConnect::GetWrapperForObject. But it takes a lot of
|
||||||
// arguments! It turns out that the thisObject hook on XPConnect
|
// arguments! It turns out that the thisObject hook on XPConnect
|
||||||
// objects does the right thing though, so...
|
// objects does the right thing though, so...
|
||||||
|
if (obj->map->ops->thisObject)
|
||||||
if (obj->map->ops->thisObject &&
|
|
||||||
!(obj = obj->map->ops->thisObject(cx, obj)))
|
|
||||||
{
|
{
|
||||||
return NS_ERROR_FAILURE;
|
JSObject *scope = JS_GetScopeChain(cx);
|
||||||
|
if (!scope)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
scope = JS_GetGlobalForObject(cx, scope);
|
||||||
|
obj = obj->map->ops->thisObject(cx, obj, scope);
|
||||||
|
if (!obj)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*retval = OBJECT_TO_JSVAL(obj);
|
*retval = OBJECT_TO_JSVAL(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1477,7 +1477,7 @@ private:
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static JSObject*
|
static JSObject*
|
||||||
XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
|
XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj, JSObject *scope)
|
||||||
{
|
{
|
||||||
// None of the wrappers we could potentially hand out are threadsafe so
|
// None of the wrappers we could potentially hand out are threadsafe so
|
||||||
// just hand out the given object.
|
// just hand out the given object.
|
||||||
|
@ -1488,15 +1488,6 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
|
||||||
if(!obj)
|
if(!obj)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
|
|
||||||
JSObject *scope = JS_GetScopeChain(cx);
|
|
||||||
if(!scope)
|
|
||||||
{
|
|
||||||
XPCThrower::Throw(NS_ERROR_FAILURE, cx);
|
|
||||||
return nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
scope = JS_GetGlobalForObject(cx, scope);
|
|
||||||
|
|
||||||
XPCPerThreadData *threadData = XPCPerThreadData::GetData(cx);
|
XPCPerThreadData *threadData = XPCPerThreadData::GetData(cx);
|
||||||
if(!threadData)
|
if(!threadData)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче