Remove JS_GetScriptedCaller (bug 732652, r=luke,mrbkap,bholley,smaug,bent).
authorDavid Anderson <danderson@mozilla.com>
Tue, 06 Mar 2012 15:33:12 -0800
changeset 88828 0215639e611a03c4efde0f0e5440890761dd7cfa
parent 88827 b55bf024c09a3fe2a8c4782079fa10787340d43d
child 88829 804103f3020c2599174f032d60aba05c15e76d45
push id7037
push userdanderson@mozilla.com
push dateMon, 12 Mar 2012 20:56:58 +0000
treeherdermozilla-inbound@0215639e611a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, mrbkap, bholley, smaug, bent
bugs732652
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Remove JS_GetScriptedCaller (bug 732652, r=luke,mrbkap,bholley,smaug,bent).
content/base/src/nsWebSocket.cpp
dom/base/nsJSEnvironment.cpp
dom/workers/WorkerPrivate.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsfun.cpp
js/src/jsopcode.cpp
js/src/shell/js.cpp
js/src/shell/jsworkers.cpp
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/xpconnect/shell/xpcshell.cpp
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -1545,27 +1545,22 @@ nsWebSocket::Init(nsIPrincipal* aPrincip
   NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(this, DOM_WINDOW_FROZEN_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIJSContextStack> stack =
     do_GetService("@mozilla.org/js/xpc/ContextStack;1");
   JSContext* cx = nsnull;
   if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) {
-    JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
-    if (fp) {
-      JSScript *script = JS_GetFrameScript(cx, fp);
-      if (script) {
+    unsigned lineno;
+    JSScript *script;
+
+    if (JS_DescribeScriptedCaller(cx, &script, &lineno)) {
         mScriptFile = JS_GetScriptFilename(cx, script);
-      }
-
-      jsbytecode *pc = JS_GetFramePC(cx, fp);
-      if (script && pc) {
-        mScriptLine = JS_PCToLineNumber(cx, script, pc);
-      }
+        mScriptLine = lineno;
     }
 
     mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
   }
 
   // parses the url
   rv = ParseURL(PromiseFlatString(aURL));
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -734,18 +734,21 @@ nsJSContext::DOMOperationCallback(JSCont
 
   // If we get here we're most likely executing an infinite loop in JS,
   // we'll tell the user about this and we'll give the user the option
   // of stopping the execution of the script.
   nsCOMPtr<nsIPrompt> prompt = GetPromptFromContext(ctx);
   NS_ENSURE_TRUE(prompt, JS_FALSE);
 
   // Check if we should offer the option to debug
-  JSStackFrame* fp = ::JS_GetScriptedCaller(cx, NULL);
-  bool debugPossible = fp && js::CanCallContextDebugHandler(cx);
+  JSScript *script;
+  unsigned lineno;
+  JSBool hasFrame = ::JS_DescribeScriptedCaller(cx, &script, &lineno);
+
+  bool debugPossible = hasFrame && js::CanCallContextDebugHandler(cx);
 #ifdef MOZ_JSDEBUGGER
   // Get the debugger service if necessary.
   if (debugPossible) {
     bool jsds_IsOn = false;
     const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
     nsCOMPtr<jsdIExecutionHook> jsdHook;
     nsCOMPtr<jsdIDebuggerService> jsds = do_GetService(jsdServiceCtrID, &rv);
 
@@ -800,42 +803,32 @@ nsJSContext::DOMOperationCallback(JSCont
   //GetStringFromName can return NS_OK and still give NULL string
   if (NS_FAILED(rv) || !title || !msg || !stopButton || !waitButton ||
       (!debugButton && debugPossible) || !neverShowDlg) {
     NS_ERROR("Failed to get localized strings.");
     return JS_TRUE;
   }
 
   // Append file and line number information, if available
-  JSScript *script = fp ? ::JS_GetFrameScript(cx, fp) : nsnull;
   if (script) {
     const char *filename = ::JS_GetScriptFilename(cx, script);
     if (filename) {
       nsXPIDLString scriptLocation;
       NS_ConvertUTF8toUTF16 filenameUTF16(filename);
       const PRUnichar *formatParams[] = { filenameUTF16.get() };
       rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                                  "KillScriptLocation",
                                                  formatParams,
                                                  scriptLocation);
 
       if (NS_SUCCEEDED(rv) && scriptLocation) {
         msg.AppendLiteral("\n\n");
         msg.Append(scriptLocation);
-
-        JSStackFrame *fp, *iterator = nsnull;
-        fp = ::JS_FrameIterator(cx, &iterator);
-        if (fp) {
-          jsbytecode *pc = ::JS_GetFramePC(cx, fp);
-          if (pc) {
-            PRUint32 lineno = ::JS_PCToLineNumber(cx, script, pc);
-            msg.Append(':');
-            msg.AppendInt(lineno);
-          }
-        }
+        msg.Append(':');
+        msg.AppendInt(lineno);
       }
     }
   }
 
   PRInt32 buttonPressed = 0; //In case user exits dialog by clicking X
   bool neverShowDlgChk = false;
   PRUint32 buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
                          (nsIPrompt::BUTTON_TITLE_IS_STRING *
@@ -862,32 +855,17 @@ nsJSContext::DOMOperationCallback(JSCont
       Preferences::SetInt(isTrackingChromeCodeTime ?
         "dom.max_chrome_script_run_time" : "dom.max_script_run_time", 0);
     }
 
     ctx->mOperationCallbackTime = PR_Now();
     return JS_TRUE;
   }
   else if ((buttonPressed == 2) && debugPossible) {
-    // Debug the script
-    jsval rval;
-    switch (js::CallContextDebugHandler(cx, script, JS_GetFramePC(cx, fp), &rval)) {
-      case JSTRAP_RETURN:
-        JS_SetFrameReturnValue(cx, fp, rval);
-        return JS_TRUE;
-      case JSTRAP_ERROR:
-        JS_ClearPendingException(cx);
-        return JS_FALSE;
-      case JSTRAP_THROW:
-        JS_SetPendingException(cx, rval);
-        return JS_FALSE;
-      case JSTRAP_CONTINUE:
-      default:
-        return JS_TRUE;
-    }
+    return js_CallContextDebugHandler(cx);
   }
 
   JS_ClearPendingException(cx);
   return JS_FALSE;
 }
 
 void
 nsJSContext::EnterModalState()
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2523,23 +2523,18 @@ WorkerPrivate::Create(JSContext* aCx, JS
     else {
       // Not a window
       NS_ASSERTION(isChrome, "Should be chrome only!");
 
       parentContext = nsnull;
 
       // We're being created outside of a window. Need to figure out the script
       // that is creating us in order for us to use relative URIs later on.
-      JSStackFrame* frame = JS_GetScriptedCaller(aCx, nsnull);
-      if (frame) {
-        JSScript* script = JS_GetFrameScript(aCx, frame);
-        if (!script) {
-          JS_ReportError(aCx, "Could not get frame script!");
-          return nsnull;
-        }
+      JSScript *script;
+      if (JS_DescribeScriptedCaller(aCx, &script, nsnull)) {
         if (NS_FAILED(NS_NewURI(getter_AddRefs(baseURI),
                                 JS_GetScriptFilename(aCx, script)))) {
           JS_ReportError(aCx, "Failed to construct base URI!");
           return nsnull;
         }
       }
     }
 
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -268,20 +268,20 @@ BEGIN_TEST(testDebugger_singleStepThrow)
              "try { f(); }\n"
              "catch (x) { e = x; }\n");
         return true;
     }
 
     static JSBool
     setStepMode(JSContext *cx, unsigned argc, jsval *vp)
     {
-        JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
-        JS_ASSERT(fp);
-        JSScript *script = JS_GetFrameScript(cx, fp);
+        JSScript *script;
+        JS_DescribeScriptedCaller(cx, &script, NULL);
         JS_ASSERT(script);
+
         if (!JS_SetSingleStepMode(cx, script, true))
             return false;
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return true;
     }
 
     static JSTrapStatus
     onStep(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6633,16 +6633,35 @@ JS_IsIdentifier(JSContext *cx, JSString 
     JSLinearString* linearStr = str->ensureLinear(cx);
     if (!linearStr)
         return false;
 
     *isIdentifier = js::IsIdentifier(linearStr);
     return true;
 }
 
+JS_PUBLIC_API(JSBool)
+JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno)
+{
+    if (script)
+        *script = NULL;
+    if (lineno)
+        *lineno = 0;
+
+    FrameRegsIter i(cx);
+    if (i.done())
+        return JS_FALSE;
+
+    if (script)
+        *script = i.script();
+    if (lineno)
+        *lineno = js::PCToLineNumber(i.script(), i.pc());
+    return JS_TRUE;
+}
+
 #ifdef JS_THREADSAFE
 static PRStatus
 CallOnce(void *func)
 {
     JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
     return init() ? PR_SUCCESS : PR_FAILURE;
 }
 #endif
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5421,11 +5421,19 @@ extern JS_PUBLIC_API(JSBool)
 JS_IndexToId(JSContext *cx, uint32_t index, jsid *id);
 
 /*
  *  Test if the given string is a valid ECMAScript identifier
  */
 extern JS_PUBLIC_API(JSBool)
 JS_IsIdentifier(JSContext *cx, JSString *str, JSBool *isIdentifier);
 
+/*
+ * Return the current script and line number of the most currently running
+ * frame. Returns true if a scripted frame was found, false otherwise.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno);
+
+
 JS_END_EXTERN_C
 
 #endif /* jsapi_h___ */
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -914,27 +914,16 @@ JSBool
 js_HandleExecutionInterrupt(JSContext *cx)
 {
     JSBool result = JS_TRUE;
     if (cx->runtime->interrupt)
         result = js_InvokeOperationCallback(cx) && result;
     return result;
 }
 
-StackFrame *
-js_GetScriptedCaller(JSContext *cx, StackFrame *fp)
-{
-    if (!fp)
-        fp = js_GetTopStackFrame(cx, FRAME_EXPAND_ALL);
-    while (fp && fp->isDummyFrame())
-        fp = fp->prev();
-    JS_ASSERT_IF(fp, fp->isScriptFrame());
-    return fp;
-}
-
 jsbytecode*
 js_GetCurrentBytecodePC(JSContext* cx)
 {
     return cx->hasfp() ? cx->regs().pc : NULL;
 }
 
 void
 DSTOffsetCache::purge()
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1525,24 +1525,16 @@ extern JSErrorFormatString js_ErrorForma
  * is to be terminated.
  */
 extern JSBool
 js_InvokeOperationCallback(JSContext *cx);
 
 extern JSBool
 js_HandleExecutionInterrupt(JSContext *cx);
 
-/*
- * Get the topmost scripted frame in a context. Note: if the topmost frame is
- * in the middle of an inline call, that call will be expanded. To avoid this,
- * use cx->stack.currentScript or cx->stack.currentScriptedScopeChain.
- */
-extern js::StackFrame *
-js_GetScriptedCaller(JSContext *cx, js::StackFrame *fp);
-
 extern jsbytecode*
 js_GetCurrentBytecodePC(JSContext* cx);
 
 extern JSScript *
 js_GetCurrentScript(JSContext* cx);
 
 namespace js {
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -513,22 +513,16 @@ JS_GetFrameScript(JSContext *cx, JSStack
 }
 
 JS_PUBLIC_API(jsbytecode *)
 JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
 {
     return Valueify(fp)->pcQuadratic(cx->stack);
 }
 
-JS_PUBLIC_API(JSStackFrame *)
-JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
-{
-    return Jsvalify(js_GetScriptedCaller(cx, Valueify(fp)));
-}
-
 JS_PUBLIC_API(void *)
 JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fpArg)
 {
     StackFrame *fp = Valueify(fpArg);
     if (fp->annotation() && fp->isScriptFrame()) {
         JSPrincipals *principals = fp->scopeChain().principals(cx);
 
         if (principals) {
@@ -1663,8 +1657,30 @@ JS_DumpCompartmentPCCounts(JSContext *cx
     }
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_UnwrapObject(JSObject *obj)
 {
     return UnwrapObject(obj);
 }
+
+JS_FRIEND_API(JSBool)
+js_CallContextDebugHandler(JSContext *cx)
+{
+    FrameRegsIter iter(cx);
+    JS_ASSERT(!iter.done());
+
+    jsval rval;
+    switch (js::CallContextDebugHandler(cx, iter.script(), iter.pc(), &rval)) {
+      case JSTRAP_ERROR:
+        JS_ClearPendingException(cx);
+        return JS_FALSE;
+      case JSTRAP_THROW:
+        JS_SetPendingException(cx, rval);
+        return JS_FALSE;
+      case JSTRAP_RETURN:
+      case JSTRAP_CONTINUE:
+      default:
+        return JS_TRUE;
+    }
+}
+
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -236,22 +236,16 @@ extern JS_PUBLIC_API(JSStackFrame *)
 JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
 
 extern JS_PUBLIC_API(jsbytecode *)
 JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
 
-/*
- * Get the closest scripted frame below fp.  If fp is null, start from cx->fp.
- */
-extern JS_PUBLIC_API(JSStackFrame *)
-JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
-
 extern JS_PUBLIC_API(void *)
 JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
 
 extern JS_PUBLIC_API(void)
 JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
 
 extern JS_PUBLIC_API(JSBool)
 JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);
@@ -576,11 +570,15 @@ extern JS_PUBLIC_API(void)
 JS_DumpPCCounts(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(void)
 JS_DumpCompartmentPCCounts(JSContext *cx);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_UnwrapObject(JSObject *obj);
 
+/* Call the context debug handler on the topmost scripted frame. */
+extern JS_FRIEND_API(JSBool)
+js_CallContextDebugHandler(JSContext *cx);
+
 JS_END_EXTERN_C
 
 #endif /* jsdbgapi_h___ */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -777,17 +777,20 @@ fun_getProperty(JSContext *cx, JSObject 
         *vp = ObjectValue(*argsobj);
         return true;
     }
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
         if (!fp->prev())
             return true;
 
-        StackFrame *frame = js_GetScriptedCaller(cx, fp->prev());
+        StackFrame *frame = fp->prev();
+        while (frame && frame->isDummyFrame())
+            frame = frame->prev();
+
         if (frame && !frame->getValidCalleeObject(cx, vp))
             return false;
 
         if (!vp->isObject()) {
             JS_ASSERT(vp->isNull());
             return true;
         }
 
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2710,18 +2710,19 @@ Decompile(SprintStack *ss, jsbytecode *p
             /*
              * Rewrite non-get ops to their "get" format if the error is in
              * the bytecode at pc, or if at an inner opcode of a 'fat' outer
              * opcode at pc, so we don't decompile more than the error
              * expression.
              */
             uint32_t format = cs->format;
             bool matchPC = false;
-            if (StackFrame *fp = js_GetScriptedCaller(cx, NULL)) {
-                jsbytecode *npc = fp->pcQuadratic(cx);
+            FrameRegsIter iter(cx);
+            if (!iter.done()) {
+                jsbytecode *npc = iter.pc();
                 if (pc == npc) {
                     matchPC = true;
                 } else if (format & JOF_DECOMPOSE) {
                     if (unsigned(npc - pc) < GetDecomposeLength(pc, js_CodeSpec[*pc].length))
                         matchPC = true;
                 }
             }
             if ((matchPC || (pc == startpc && nuses != 0)) &&
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1298,21 +1298,29 @@ SetDebug(JSContext *cx, unsigned argc, j
      */
 
     JSBool ok = JS_SetDebugMode(cx, JSVAL_TO_BOOLEAN(argv[0]));
     if (ok)
         JS_SET_RVAL(cx, vp, JSVAL_TRUE);
     return ok;
 }
 
+static JSScript *
+GetTopScript(JSContext *cx)
+{
+    JSScript *script;
+    JS_DescribeScriptedCaller(cx, &script, NULL);
+    return script;
+}
+
 static JSBool
 GetScriptAndPCArgs(JSContext *cx, unsigned argc, jsval *argv, JSScript **scriptp,
                    int32_t *ip)
 {
-    JSScript *script = JS_GetFrameScript(cx, JS_GetScriptedCaller(cx, NULL));
+    JSScript *script = GetTopScript(cx);
     *ip = 0;
     if (argc != 0) {
         jsval v = argv[0];
         unsigned intarg = 0;
         if (!JSVAL_IS_PRIMITIVE(v) &&
             JS_GetClass(JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass)) {
             script = ValueToScript(cx, v);
             if (!script)
@@ -1334,18 +1342,22 @@ GetScriptAndPCArgs(JSContext *cx, unsign
     return JS_TRUE;
 }
 
 static JSTrapStatus
 TrapHandler(JSContext *cx, JSScript *, jsbytecode *pc, jsval *rval,
             jsval closure)
 {
     JSString *str = JSVAL_TO_STRING(closure);
-    JSStackFrame *caller = JS_GetScriptedCaller(cx, NULL);
-    JSScript *script = JS_GetFrameScript(cx, caller);
+
+    FrameRegsIter iter(cx);
+    JS_ASSERT(!iter.done());
+
+    JSStackFrame *caller = Jsvalify(iter.fp());
+    JSScript *script = iter.script();
 
     size_t length;
     const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
     if (!chars)
         return JSTRAP_ERROR;
 
     if (!JS_EvaluateUCInStackFrame(cx, caller, chars, length,
                                    script->filename,
@@ -1450,17 +1462,17 @@ LineToPC(JSContext *cx, unsigned argc, j
     int32_t lineArg = 0;
     uint32_t lineno;
     jsbytecode *pc;
 
     if (argc == 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE);
         return JS_FALSE;
     }
-    script = JS_GetFrameScript(cx, JS_GetScriptedCaller(cx, NULL));
+    script = GetTopScript(cx);
     jsval v = JS_ARGV(cx, vp)[0];
     if (!JSVAL_IS_PRIMITIVE(v) &&
         JS_GetClass(JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass))
     {
         script = ValueToScript(cx, v);
         if (!script)
             return JS_FALSE;
         lineArg++;
@@ -1796,18 +1808,17 @@ DisassembleToString(JSContext *cx, unsig
 
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return false;
 
     bool ok = true;
     if (p.argc == 0) {
         /* Without arguments, disassemble the current script. */
-        if (JSStackFrame *frame = JS_GetScriptedCaller(cx, NULL)) {
-            JSScript *script = JS_GetFrameScript(cx, frame);
+        if (JSScript *script = GetTopScript(cx)) {
             if (js_Disassemble(cx, script, p.lines, &sprinter)) {
                 SrcNotes(cx, script, &sprinter);
                 TryNotes(cx, script, &sprinter);
             } else {
                 ok = false;
             }
         }
     } else {
@@ -1834,18 +1845,17 @@ Disassemble(JSContext *cx, unsigned argc
 
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return false;
 
     bool ok = true;
     if (p.argc == 0) {
         /* Without arguments, disassemble the current script. */
-        if (JSStackFrame *frame = JS_GetScriptedCaller(cx, NULL)) {
-            JSScript *script = JS_GetFrameScript(cx, frame);
+        if (JSScript *script = GetTopScript(cx)) {
             if (js_Disassemble(cx, script, p.lines, &sprinter)) {
                 SrcNotes(cx, script, &sprinter);
                 TryNotes(cx, script, &sprinter);
             } else {
                 ok = false;
             }
         }
     } else {
@@ -2665,19 +2675,20 @@ EvalInContext(JSContext *cx, unsigned ar
             return false;
     }
 
     if (srclen == 0) {
         JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sobj));
         return true;
     }
 
-    JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
-    JSScript *script = JS_GetFrameScript(cx, fp);
-    jsbytecode *pc = JS_GetFramePC(cx, fp);
+    JSScript *script;
+    unsigned lineno;
+
+    JS_DescribeScriptedCaller(cx, &script, &lineno);
     jsval rval;
     {
         JSAutoEnterCompartment ac;
         unsigned flags;
         JSObject *unwrapped = UnwrapObject(sobj, true, &flags);
         if (flags & Wrapper::CROSS_COMPARTMENT) {
             sobj = unwrapped;
             if (!ac.enter(cx, sobj))
@@ -2688,17 +2699,17 @@ EvalInContext(JSContext *cx, unsigned ar
         if (!sobj)
             return false;
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportError(cx, "Invalid scope argument to evalcx");
             return false;
         }
         if (!JS_EvaluateUCScript(cx, sobj, src, srclen,
                                  script->filename,
-                                 JS_PCToLineNumber(cx, script, pc),
+                                 lineno,
                                  &rval)) {
             return false;
         }
     }
 
     if (!cx->compartment->wrap(cx, &rval))
         return false;
 
@@ -3374,19 +3385,18 @@ Snarf(JSContext *cx, unsigned argc, jsva
     str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
     JSAutoByteString filename(cx, str);
     if (!filename)
         return JS_FALSE;
 
     /* Get the currently executing script's name. */
-    JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
-    JSScript *script = JS_GetFrameScript(cx, fp);
-    JS_ASSERT(fp && script->filename);
+    JSScript *script = GetTopScript(cx);
+    JS_ASSERT(script->filename);
     const char *pathname = filename.ptr();
 #ifdef XP_UNIX
     FreeOnReturn pnGuard(cx);
     if (pathname[0] != '/') {
         pathname = MakeAbsolutePathname(cx, script->filename, pathname);
         if (!pathname)
             return JS_FALSE;
         pnGuard.init(pathname);
--- a/js/src/shell/jsworkers.cpp
+++ b/js/src/shell/jsworkers.cpp
@@ -1115,18 +1115,19 @@ Worker *
 Worker::create(JSContext *parentcx, WorkerParent *parent, JSString *scriptName, JSObject *obj)
 {
     Worker *w = new Worker();
     if (!w || !w->init(parentcx, parent, obj)) {
         delete w;
         return NULL;
     }
 
-    JSStackFrame *frame = JS_GetScriptedCaller(parentcx, NULL);
-    const char *base = JS_GetScriptFilename(parentcx, JS_GetFrameScript(parentcx, frame));
+    JSScript *script;
+    JS_DescribeScriptedCaller(parentcx, &script, NULL);
+    const char *base = JS_GetScriptFilename(parentcx, script);
     JSString *scriptPath = ResolveRelativePath(parentcx, base, scriptName);
     if (!scriptPath)
         return NULL;
 
     // Post an InitEvent to run the initialization script.
     Event *event = InitEvent::create(parentcx, w, scriptPath);
     if (!event)
         return NULL;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -973,16 +973,17 @@ ContextStack::restoreFrameChain()
 
 /*****************************************************************************/
 
 void
 StackIter::poisonRegs()
 {
     sp_ = (Value *)0xbad;
     pc_ = (jsbytecode *)0xbad;
+    script_ = (JSScript *)0xbad;
 }
 
 void
 StackIter::popFrame()
 {
     StackFrame *oldfp = fp_;
     JS_ASSERT(seg_->contains(oldfp));
     fp_ = fp_->prev();
@@ -1014,16 +1015,18 @@ StackIter::popFrame()
         } else if (oldfp->isFramePushedByExecute()) {
             /* pushExecuteFrame pushes exactly (callee, this) before frame. */
             sp_ = (Value *)oldfp - 2;
         } else {
             /* pushDummyFrame pushes exactly 0 slots before frame. */
             JS_ASSERT(oldfp->isDummyFrame());
             sp_ = (Value *)oldfp;
         }
+
+        script_ = fp_->maybeScript();
     } else {
         poisonRegs();
     }
 }
 
 void
 StackIter::popCall()
 {
@@ -1039,16 +1042,18 @@ StackIter::popCall()
 }
 
 void
 StackIter::settleOnNewSegment()
 {
     if (FrameRegs *regs = seg_->maybeRegs()) {
         sp_ = regs->sp;
         pc_ = regs->pc;
+        if (fp_)
+            script_ = fp_->maybeScript();
     } else {
         poisonRegs();
     }
 }
 
 void
 StackIter::startOnSegment(StackSegment *seg)
 {
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1813,16 +1813,17 @@ class StackIter
     State        state_;
 
     StackFrame   *fp_;
     CallArgsList *calls_;
 
     StackSegment *seg_;
     Value        *sp_;
     jsbytecode   *pc_;
+    JSScript     *script_;
     CallArgs     args_;
 
     void poisonRegs();
     void popFrame();
     void popCall();
     void settleOnNewSegment();
     void settleOnNewState();
     void startOnSegment(StackSegment *seg);
@@ -1835,16 +1836,17 @@ class StackIter
 
     bool operator==(const StackIter &rhs) const;
     bool operator!=(const StackIter &rhs) const { return !(*this == rhs); }
 
     bool isScript() const { JS_ASSERT(!done()); return state_ == SCRIPTED; }
     StackFrame *fp() const { JS_ASSERT(!done() && isScript()); return fp_; }
     Value      *sp() const { JS_ASSERT(!done() && isScript()); return sp_; }
     jsbytecode *pc() const { JS_ASSERT(!done() && isScript()); return pc_; }
+    JSScript   *script() const { JS_ASSERT(!done() && isScript()); return script_; }
 
     bool isNativeCall() const { JS_ASSERT(!done()); return state_ != SCRIPTED; }
     CallArgs nativeArgs() const { JS_ASSERT(!done() && isNativeCall()); return args_; }
 };
 
 /* A filtering of the StackIter to only stop at scripts. */
 class FrameRegsIter
 {
@@ -1863,16 +1865,17 @@ class FrameRegsIter
     FrameRegsIter &operator++() { ++iter_; settle(); return *this; }
 
     bool operator==(const FrameRegsIter &rhs) const { return iter_ == rhs.iter_; }
     bool operator!=(const FrameRegsIter &rhs) const { return iter_ != rhs.iter_; }
 
     StackFrame *fp() const { return iter_.fp(); }
     Value      *sp() const { return iter_.sp(); }
     jsbytecode *pc() const { return iter_.pc(); }
+    JSScript   *script() const { return iter_.script(); }
 };
 
 /*****************************************************************************/
 
 /*
  * Blindly iterate over all frames in the current thread's stack. These frames
  * can be from different contexts and compartments, so beware.
  */
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -163,18 +163,18 @@ nsAutoString *gWorkingDirectory = nsnull
 
 static JSBool
 GetLocationProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
 #if !defined(XP_WIN) && !defined(XP_UNIX)
     //XXX: your platform should really implement this
     return false;
 #else
-    JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
-    JSScript *script = JS_GetFrameScript(cx, fp);
+    JSScript *script;
+    JS_DescribeScriptedCaller(cx, &script, NULL);
     const char *filename = JS_GetScriptFilename(cx, script);
 
     if (filename) {
         nsresult rv;
         nsCOMPtr<nsIXPConnect> xpc =
             do_GetService(kXPConnectServiceContractID, &rv);
 
 #if defined(XP_WIN)