Add Debugger.Script.prototype.{url,startLine,lineCount}.
authorJason Orendorff <jorendorff@mozilla.com>
Fri, 08 Jul 2011 12:41:12 -0500
changeset 74506 94d505fb0a67cad3d3023fb9f1881e86631270b0
parent 74505 2e006cccde9f5b6b2b42049bb4d2a01cfc832d84
child 74507 3ff3eab2e220a588c7bee8aa8ec1b1afb733a85c
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone7.0a1
Add Debugger.Script.prototype.{url,startLine,lineCount}.
js/src/jit-test/tests/debug/Script-startLine.js
js/src/jsdbg.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Script-startLine.js
@@ -0,0 +1,45 @@
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+var start, count;
+dbg.hooks = {
+    debuggerHandler: function (frame) {
+	assertEq(start, undefined);
+	start = frame.script.startLine;
+	count = frame.script.lineCount;
+	assertEq(typeof frame.script.url, 'string');
+    }
+};
+
+function test(f) {
+    start = count = g.first = g.last = undefined;
+    f();
+    assertEq(start, g.first);
+    assertEq(count, g.last + 1 - g.first);
+    print(start, count);
+}
+
+test(function () {
+    g.eval("first = Error().lineNumber;\n" +
+	   "debugger;\n" +
+	   "last = Error().lineNumber;\n");
+});
+
+test(function () {
+    g.evaluate("first = Error().lineNumber;\n" +
+	       "debugger;\n" +
+	       Array(17000).join("\n") +
+	       "last = Error().lineNumber;\n");
+});
+
+test(function () {
+    g.eval("function f1() { first = Error().lineNumber\n" +
+	   "    debugger;\n" +
+	   "    last = Error().lineNumber; }\n" +
+	   "f1();");
+});
+
+g.eval("function f2() {\n" +
+       "    eval('first = Error().lineNumber\\n\\ndebugger;\\n\\nlast = Error().lineNumber;');\n" +
+       "}\n");
+test(g.f2);
+test(g.f2);
--- a/js/src/jsdbg.cpp
+++ b/js/src/jsdbg.cpp
@@ -1687,16 +1687,60 @@ DebuggerScript_checkThis(JSContext *cx, 
         return false;                                                               \
     JSScript *script = GetScriptReferent(obj)
 
 #define THIS_DEBUGSCRIPT_SCRIPT(cx, vp, fnname, obj, script)                  \
     THIS_DEBUGSCRIPT_SCRIPT_NEEDLIVE(cx, vp, fnname, obj, script, false)
 #define THIS_DEBUGSCRIPT_LIVE_SCRIPT(cx, vp, fnname, obj, script)             \
     THIS_DEBUGSCRIPT_SCRIPT_NEEDLIVE(cx, vp, fnname, obj, script, true)
 
+static JSBool
+DebuggerScript_getUrl(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGSCRIPT_LIVE_SCRIPT(cx, vp, "get url", obj, script);
+
+    JSString *str = js_NewStringCopyZ(cx, script->filename);
+    if (!str)
+        return false;
+    vp->setString(str);
+    return true;
+}
+
+static JSBool
+DebuggerScript_getStartLine(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGSCRIPT_LIVE_SCRIPT(cx, vp, "get startLine", obj, script);
+    vp->setNumber(script->lineno);
+    return true;
+}
+
+static JSBool
+DebuggerScript_getLineCount(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGSCRIPT_LIVE_SCRIPT(cx, vp, "get lineCount", obj, script);
+
+    // A script's line count is not stored, so we calculate it by reading all
+    // the source notes for the whole script.
+    size_t line = script->lineno, maxLine = line;
+    for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+        JSSrcNoteType type = (JSSrcNoteType) SN_TYPE(sn);
+        if (type == SRC_SETLINE)
+            line = size_t(js_GetSrcNoteOffset(sn, 0));
+        else if (type == SRC_NEWLINE)
+            line++;
+        else
+            continue;
+
+        if (line > maxLine)
+            maxLine = line;
+    }
+
+    vp->setNumber(jsdouble(maxLine + 1 - script->lineno));
+    return true;
+}
 
 static JSBool
 DebuggerScript_getLive(JSContext *cx, uintN argc, Value *vp)
 {
     THIS_DEBUGSCRIPT_SCRIPT(cx, vp, "get live", obj, script);
     vp->setBoolean(!!script);
     return true;
 }
@@ -2109,16 +2153,19 @@ DebuggerScript_clearAllBreakpoints(JSCon
 static JSBool
 DebuggerScript_construct(JSContext *cx, uintN argc, Value *vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debugger.Script");
     return false;
 }
 
 static JSPropertySpec DebuggerScript_properties[] = {
+    JS_PSG("url", DebuggerScript_getUrl, 0),
+    JS_PSG("startLine", DebuggerScript_getStartLine, 0),
+    JS_PSG("lineCount", DebuggerScript_getLineCount, 0),
     JS_PSG("live", DebuggerScript_getLive, 0),
     JS_PS_END
 };
 
 static JSFunctionSpec DebuggerScript_methods[] = {
     JS_FN("getChildScripts", DebuggerScript_getChildScripts, 0, 0),
     JS_FN("getAllOffsets", DebuggerScript_getAllOffsets, 0, 0),
     JS_FN("getLineOffsets", DebuggerScript_getLineOffsets, 1, 0),