From 9f4a2c578cc822ce01807ece9b8acc8185ccc216 Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Wed, 10 Dec 2003 00:24:13 +0000 Subject: [PATCH] Followup patch to cope with lightweight function calls (direct or via natives) to exec (227432, r=shaver, a=dbaron). --- js/src/jsscript.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/js/src/jsscript.c b/js/src/jsscript.c index 9ca1b4a5d8a..5d7f9dfa551 100644 --- a/js/src/jsscript.c +++ b/js/src/jsscript.c @@ -250,32 +250,35 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) /* * Emulate eval() by using caller's this, var object, sharp array, etc., - * all propagated by js_Execute via a non-null fourth |down| argument to + * all propagated by js_Execute via a non-null fourth (down) argument to * js_Execute. If there is no scripted caller, js_Execute uses its second - * |obj| argument to set the exec frame's varobj, thisp, and scopeChain. + * (chain) argument to set the exec frame's varobj, thisp, and scopeChain. * * Unlike eval, which the compiler detects, Script.prototype.exec may be * called from a lightweight function, or even from native code (in which - * case fp->varobj and fp->scopeChain are null). + * case fp->varobj and fp->scopeChain are null). If exec is called from + * a lightweight function, we will need to get a Call object representing + * its frame, to act as the var object and scope chain head. */ fp = cx->fp; caller = JS_GetScriptedCaller(cx, fp); + if (caller && !caller->varobj) { + /* Called from a lightweight function. */ + JS_ASSERT(caller->fun && !(caller->fun->flags & JSFUN_HEAVYWEIGHT)); + + /* Scope chain links from Call object to callee's parent. */ + parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(caller->argv[-2])); + if (!js_GetCallObject(cx, caller, parent)) + return JS_FALSE; + } + if (!scopeobj) { - /* No scope object passed in, use the caller's scope chain head. */ + /* No scope object passed in: try to use the caller's scope chain. */ if (caller) { - /* Called from a scripted function. */ - if (!caller->varobj) { - /* Called from a lightweight function. */ - JS_ASSERT(caller->fun && - !(caller->fun->flags & JSFUN_HEAVYWEIGHT)); - - /* Scope chain links from Call object to callee's parent. */ - parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(caller->argv[-2])); - if (!js_GetCallObject(cx, caller, parent)) - return JS_FALSE; - } - - /* Load caller->scopeChain after conditional js_GetCallObject. */ + /* + * Load caller->scopeChain after the conditional js_GetCallObject + * call above, which resets scopeChain as well as varobj. + */ scopeobj = caller->scopeChain; } else { /*