Bug 513065 - Part 3, compute scope in the engine before calling the thisObject hook. r=mrbkap.

This commit is contained in:
Jason Orendorff 2010-05-12 08:15:49 -05:00
Родитель e723a3bdd7
Коммит ab890a859e
8 изменённых файлов: 55 добавлений и 61 удалений

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

@ -371,11 +371,17 @@ js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp)
/* Some objects (e.g., With) delegate 'this' to another object. */
static inline JSObject *
CallThisObjectHook(JSContext *cx, JSObject *obj, jsval *argv)
CallThisObjectHook(JSContext *cx, JSObject *obj, JSObject *scope, jsval *argv)
{
JSObject *thisp = obj->thisObject(cx);
if (!thisp)
return NULL;
JSObject *thisp = obj;
if (JSThisObjectOp thisObject = obj->map->ops->thisObject) {
if (!scope)
scope = JSVAL_TO_OBJECT(argv[-2])->getGlobal();
thisp = thisObject(cx, obj, scope);
if (!thisp)
return NULL;
}
argv[-1] = OBJECT_TO_JSVAL(thisp);
return thisp;
}
@ -398,45 +404,29 @@ CallThisObjectHook(JSContext *cx, JSObject *obj, jsval *argv)
JS_STATIC_INTERPRET JSObject *
js_ComputeGlobalThis(JSContext *cx, jsval *argv)
{
JSObject *thisp;
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 *thisp = JSVAL_TO_OBJECT(argv[-2])->getGlobal();
return CallThisObjectHook(cx, thisp, thisp, argv);
}
JSObject *
js_ComputeThis(JSContext *cx, jsval *argv)
{
JS_ASSERT(argv[-1] != JSVAL_HOLE); // check for SynthesizeFrame poisoning
if (JSVAL_IS_NULL(argv[-1]))
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
@ -1058,7 +1048,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
return false;
frame.scopeChain = chain;
JSObject *thisp = JSVAL_TO_OBJECT(frame.thisv)->thisObject(cx);
JSObject *thisp = JSVAL_TO_OBJECT(frame.thisv)->thisObject(cx, chain);
if (!thisp)
return false;
frame.thisv = OBJECT_TO_JSVAL(thisp);

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

@ -2947,12 +2947,12 @@ with_TypeOf(JSContext *cx, JSObject *obj)
}
static JSObject *
with_ThisObject(JSContext *cx, JSObject *obj)
with_ThisObject(JSContext *cx, JSObject *obj, JSObject *scope)
{
JSObject *proto = obj->getProto();
if (!proto)
return obj;
return proto->thisObject(cx);
return proto->thisObject(cx, scope);
}
JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {

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

@ -161,7 +161,7 @@ struct JSObjectOps {
JSTraceOp trace;
/* Optionally non-null members start here. */
JSObjectOp thisObject;
JSThisObjectOp thisObject;
JSPropertyRefOp dropProperty;
JSNative call;
JSNative construct;
@ -634,8 +634,8 @@ struct JSObject {
}
/* These four are time-optimized to avoid stub calls. */
JSObject *thisObject(JSContext *cx) {
return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
JSObject *thisObject(JSContext *cx, JSObject *scope) {
return map->ops->thisObject ? map->ops->thisObject(cx, this, scope) : this;
}
void dropProperty(JSContext *cx, JSProperty *prop) {

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

@ -423,9 +423,19 @@ typedef JSBool
(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
/*
* 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.thisObject
* at present.
* The type of JSObjectOps::thisObject. Return a "stunt this" object for obj,
* having a parent chain that ends in scope; or NULL on error.
*
* 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 *
(* JSObjectOp)(JSContext *cx, JSObject *obj);

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

@ -9516,7 +9516,7 @@ TraceRecorder::getThis(LIns*& this_ins)
this_ins = get(&thisv);
JSObject* wrappedGlobal = globalObj->thisObject(cx);
JSObject* wrappedGlobal = globalObj->thisObject(cx, globalObj);
if (!wrappedGlobal)
RETURN_ERROR("globalObj->thisObject hook threw in getThis");

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

@ -2763,7 +2763,7 @@ split_outerObject(JSContext *cx, JSObject *obj)
}
static JSObject *
split_thisObject(JSContext *cx, JSObject *obj)
split_thisObject(JSContext *cx, JSObject *obj, JSObject */*scope*/)
{
OBJ_TO_OUTER_OBJECT(cx, obj);
if (!obj)

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

@ -133,13 +133,16 @@ xpcJSWeakReference::Get()
// nsXPConnect::GetWrapperForObject. But it takes a lot of
// arguments! It turns out that the thisObject hook on XPConnect
// objects does the right thing though, so...
if (obj->map->ops->thisObject &&
!(obj = obj->map->ops->thisObject(cx, obj)))
if (obj->map->ops->thisObject)
{
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);
}
}

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

@ -1477,7 +1477,7 @@ private:
} // namespace
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
// just hand out the given object.
@ -1488,15 +1488,6 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
if(!obj)
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);
if(!threadData)
{