diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 387dbfd91e0..956627fb00d 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -1592,6 +1592,7 @@ JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp) if (!Valueify(fp)->getValidCalleeObject(cx, &v)) return false; + *vp = v.isObject() ? Jsvalify(v) : JSVAL_VOID; *vp = Jsvalify(v); return true; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index a2a0ad6c797..295c90e8d19 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1427,7 +1427,7 @@ bool StackFrame::getValidCalleeObject(JSContext *cx, Value *vp) { if (!isFunctionFrame()) { - vp->setUndefined(); + vp->setNull(); return true; } @@ -1575,9 +1575,11 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) NULL, JSMSG_DEPRECATED_USAGE, js_arguments_str)) { return false; } - if (!js_GetArgsValue(cx, fp, vp)) - return false; - } else if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) { + + return js_GetArgsValue(cx, fp, vp); + } + + if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) { if (!fp->prev()) return true; @@ -1585,26 +1587,29 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) if (frame && !frame->getValidCalleeObject(cx, vp)) return false; - if (vp->isObject()) { - JSObject &caller = vp->toObject(); + if (!vp->isObject()) { + JS_ASSERT(vp->isNull()); + return true; + } - /* Censor the caller if it is from another compartment. */ - if (caller.compartment() != cx->compartment) { - vp->setNull(); - } else if (caller.isFunction()) { - JSFunction *callerFun = caller.getFunctionPrivate(); - if (callerFun->isInterpreted() && callerFun->inStrictMode()) { - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, - JSMSG_CALLER_IS_STRICT); - return false; - } + /* Censor the caller if it is from another compartment. */ + JSObject &caller = vp->toObject(); + if (caller.compartment() != cx->compartment) { + vp->setNull(); + } else if (caller.isFunction()) { + JSFunction *callerFun = caller.getFunctionPrivate(); + if (callerFun->isInterpreted() && callerFun->inStrictMode()) { + JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, + JSMSG_CALLER_IS_STRICT); + return false; } } - } else { - JS_NOT_REACHED("fun_getProperty"); + + return true; } - return true; + JS_NOT_REACHED("fun_getProperty"); + return false; } diff --git a/js/src/tests/ecma_5/extensions/function-properties.js b/js/src/tests/ecma_5/extensions/function-properties.js new file mode 100644 index 00000000000..9585322ef09 --- /dev/null +++ b/js/src/tests/ecma_5/extensions/function-properties.js @@ -0,0 +1,21 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +function foo() +{ + assertEq(foo.arguments.length, 0); + assertEq(foo.caller, null); +} + +assertEq(foo.arguments, null); +assertEq(foo.caller, null); +foo(); +assertEq(foo.arguments, null); +assertEq(foo.caller, null); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/ecma_5/extensions/jstests.list b/js/src/tests/ecma_5/extensions/jstests.list index b70124cfdce..e96e4789c76 100644 --- a/js/src/tests/ecma_5/extensions/jstests.list +++ b/js/src/tests/ecma_5/extensions/jstests.list @@ -14,6 +14,7 @@ skip-if(!xulRuntime.shell) script cross-global-eval-is-indirect.js # needs newGl script eval-native-callback-is-indirect.js script extension-methods-reject-null-undefined-this.js skip-if(!xulRuntime.shell) script function-definition-with.js # needs evaluate() +script function-properties.js script iterator-in-catch.js skip-if(!xulRuntime.shell) script legacy-JSON.js # needs parseLegacyJSON fails script nested-delete-name-in-evalcode.js # bug 604301, at a minimum diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index e63be4f9bd0..511a2489fcb 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -741,10 +741,9 @@ class StackFrame } /* - * getValidCalleeObject is a fallible getter to compute the correct callee - * function object, which may require deferred cloning due to the JSObject - * methodReadBarrier. For a non-function frame, return true with *vp set - * from calleev, which may not be an object (it could be undefined). + * Compute the callee function for this stack frame, cloning if needed to + * implement the method read barrier. If this is not a function frame, + * set *vp to null. */ bool getValidCalleeObject(JSContext *cx, Value *vp);