Fix JSOP_SETSP to trim only the current frame's scope chain (344959, r=mrbkap).

This commit is contained in:
brendan%mozilla.org 2006-07-17 23:49:36 +00:00
parent 81d030d822
commit 606fbd540c
4 changed files with 28 additions and 7 deletions

View File

@ -2336,6 +2336,7 @@ interrupt:
withobj = JSVAL_TO_OBJECT(rval);
JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);
fp->scopeChain = OBJ_GET_PARENT(cx, withobj);
JS_SetPrivate(cx, withobj, NULL);
END_CASE(JSOP_LEAVEWITH)
BEGIN_CASE(JSOP_SETRVAL)
@ -5470,10 +5471,14 @@ interrupt:
(clasp = OBJ_GET_CLASS(cx, obj)) == &js_WithClass ||
clasp == &js_BlockClass;
obj = OBJ_GET_PARENT(cx, obj)) {
if (OBJ_BLOCK_DEPTH(cx, obj) < i)
if (JS_GetPrivate(cx, obj) != fp ||
OBJ_BLOCK_DEPTH(cx, obj) < i) {
break;
}
if (clasp == &js_BlockClass)
ok &= js_PutBlockObject(cx, obj);
else
JS_SetPrivate(cx, obj, NULL);
}
fp->scopeChain = obj;

View File

@ -1200,7 +1200,8 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSBool ok;
#if JS_HAS_EVAL_THIS_SCOPE
JSObject *callerScopeChain = NULL, *callerVarObj = NULL;
JSBool setCallerScopeChain = JS_FALSE, setCallerVarObj = JS_FALSE;
JSObject *setCallerScopeChain = NULL;
JSBool setCallerVarObj = JS_FALSE;
#endif
fp = cx->fp;
@ -1267,7 +1268,9 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* Set fp->scopeChain too, for the compiler. */
caller->scopeChain = fp->scopeChain = scopeobj;
setCallerScopeChain = JS_TRUE;
/* Remember scopeobj so we can null its private when done. */
setCallerScopeChain = scopeobj;
}
callerVarObj = caller->varobj;
@ -1350,8 +1353,11 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
out:
#if JS_HAS_EVAL_THIS_SCOPE
/* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */
if (setCallerScopeChain)
if (setCallerScopeChain) {
caller->scopeChain = callerScopeChain;
JS_ASSERT(OBJ_GET_CLASS(cx, setCallerScopeChain) == &js_WithClass);
JS_SetPrivate(cx, setCallerScopeChain, NULL);
}
if (setCallerVarObj)
caller->varobj = callerVarObj;
#endif
@ -1865,6 +1871,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
obj = js_NewObject(cx, &js_WithClass, proto, parent);
if (!obj)
return NULL;
obj->slots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(cx->fp);
OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
return obj;
}

View File

@ -249,8 +249,10 @@ extern JSClass js_BlockClass;
*
* A With object is like a Block object, in that both have one reserved slot
* telling the stack depth of the relevant slots (the slot whose value is the
* object named in the with statement; the slots containing the block's local
* variables).
* object named in the with statement, the slots containing the block's local
* variables); and both have a private slot referring to the JSStackFrame in
* whose activation they were created (or null if the with or block object
* outlives the frame).
*/
#define JSSLOT_BLOCK_DEPTH (JSSLOT_PRIVATE + 1)
@ -265,6 +267,9 @@ extern JSClass js_BlockClass;
* To make sure this slot is well-defined, always call js_NewWithObject to
* create a With object, don't call js_NewObject directly. When creating a
* With object that does not correspond to a stack slot, pass -1 for depth.
*
* When popping the stack across this object's "with" statement, client code
* must call JS_SetPrivate(cx, withobj, NULL).
*/
extern JSObject *
js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth);

View File

@ -7935,6 +7935,7 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp)
fp = cx->fp;
fp->flags |= JSFRAME_FILTERING;
scobj = js_GetScopeChain(cx, fp);
withobj = NULL;
if (!scobj)
goto bad;
xml = GetPrivate(cx, obj, "filtering predicate operator");
@ -7984,7 +7985,10 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp)
out:
fp->flags &= ~JSFRAME_FILTERING;
fp->scopeChain = scobj;
if (withobj) {
fp->scopeChain = scobj;
JS_SetPrivate(cx, withobj, NULL);
}
js_LeaveLocalRootScopeWithResult(cx, *vp);
return ok;
bad: