Backed out 2 changesets (bug 1013219) for failing XPCShell test_stepping-07.js on a CLOSED TREE. r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 08 Jan 2016 19:12:36 +0100
changeset 320163 d8f3e275f36eac27a835c0c13a83e1a866a39503
parent 320162 8badb4d61bc8d55863e5658ffba6fccdcf8bb935
child 320164 2ec18a7b734917ef8743a0cfcacb86ba37ab32fb
push id9143
push userahunt@mozilla.com
push dateFri, 08 Jan 2016 21:30:53 +0000
reviewersbackout
bugs1013219
milestone46.0a1
backs out6d73df273b789b5cd2bd64f531dffd9a8fac3219
7e311f480d8ffd4b81591c9252688352c668b503
Backed out 2 changesets (bug 1013219) for failing XPCShell test_stepping-07.js on a CLOSED TREE. r=backout Backed out changeset 6d73df273b78 (bug 1013219) Backed out changeset 7e311f480d8f (bug 1013219)
devtools/client/debugger/test/mochitest/browser_dbg_scripts-switching-01.js
devtools/client/debugger/test/mochitest/browser_dbg_scripts-switching-02.js
devtools/client/debugger/test/mochitest/browser_dbg_split-console-keypress.js
devtools/client/debugger/test/mochitest/browser_dbg_step-out.js
devtools/server/tests/unit/head_dbg.js
devtools/server/tests/unit/setBreakpoint-on-column-with-no-offsets-at-end-of-script.js
devtools/server/tests/unit/setBreakpoint-on-line-with-no-offsets-at-end-of-script.js
devtools/server/tests/unit/test_breakpoint-13.js
devtools/server/tests/unit/test_breakpoint-14.js
devtools/server/tests/unit/test_get-executable-lines.js
devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets-at-end-of-script.js
devtools/server/tests/unit/test_stepping-03.js
devtools/server/tests/unit/test_stepping-06.js
devtools/server/tests/unit/test_stepping-07.js
devtools/server/tests/unit/xpcshell.ini
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/Parser.cpp
js/src/jit-test/tests/debug/Frame-onPop-23.js
js/src/jit-test/tests/debug/Frame-onStep-11.js
js/src/jit-test/tests/debug/Frame-onStep-12.js
js/src/jit-test/tests/debug/Frame-onStep-13.js
js/src/jit-test/tests/debug/Frame-onStep-16.js
js/src/jit-test/tests/debug/Frame-onStep-lines-01.js
js/src/jit-test/tests/debug/Script-getAllColumnOffsets-01.js
js/src/jit-test/tests/debug/Script-getAllColumnOffsets-06.js
js/src/jit-test/tests/debug/Script-startLine.js
--- a/devtools/client/debugger/test/mochitest/browser_dbg_scripts-switching-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_scripts-switching-01.js
@@ -131,21 +131,21 @@ function test() {
       is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel1,
          "The selected value is the sources pane is incorrect.");
 
       is(gEditor.getText().search(/firstCall/), 118,
          "The first source is displayed.");
       is(gEditor.getText().search(/debugger/), -1,
          "The second source is not displayed.");
 
-      ok(isCaretPos(gPanel, 6),
+      ok(isCaretPos(gPanel, 5),
          "Editor caret location is correct.");
-      is(gEditor.getDebugLocation(), 5,
+      is(gEditor.getDebugLocation(), 4,
          "Editor debugger location is correct.");
-      ok(gEditor.hasLineClass(5, "debug-line"),
+      ok(gEditor.hasLineClass(4, "debug-line"),
          "The debugged line is highlighted appropriately (3).");
     }
 
     Task.spawn(function*() {
       yield waitForSourceShown(gPanel, "-01.js", 1);
       ok(gDebugger.document.title.endsWith(EXAMPLE_URL + gLabel1),
          "Title with first source is correct.");
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_scripts-switching-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_scripts-switching-02.js
@@ -126,21 +126,21 @@ function test() {
          "The selected value is the sources pane is incorrect.");
 
       is(gEditor.getText().search(/firstCall/), 118,
          "The first source is displayed.");
       is(gEditor.getText().search(/debugger/), -1,
          "The second source is not displayed.");
 
       // The editor's debug location takes a tick to update.
-      ok(isCaretPos(gPanel, 6),
+      ok(isCaretPos(gPanel, 5),
          "Editor caret location is correct.");
-      is(gEditor.getDebugLocation(), 5,
+      is(gEditor.getDebugLocation(), 4,
          "Editor debugger location is correct.");
-      ok(gEditor.hasLineClass(5, "debug-line"),
+      ok(gEditor.hasLineClass(4, "debug-line"),
          "The debugged line is highlighted appropriately.");
 
       deferred.resolve();
 
       return deferred.promise;
     }
 
     Task.spawn(function*() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_split-console-keypress.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_split-console-keypress.js
@@ -31,23 +31,23 @@ function test() {
     // The console is now open (if not make the test fail already)
     ok(gToolbox.splitConsole, "Split console is shown.");
 
     // Information for sub-tests. When 'key' is synthesized 'keyRepeat' times,
     // cursor should be at 'caretLine' of this test..
     let stepTests = [
       {key: 'VK_F11', keyRepeat: 1, caretLine: 16},
       {key: 'VK_F11', keyRepeat: 2, caretLine: 18},
-      {key: 'VK_F11', keyRepeat: 2, caretLine: 27},
-      {key: 'VK_F10', keyRepeat: 1, caretLine: 27},
-      {key: 'VK_F11', keyRepeat: 1, caretLine: 18},
-      {key: 'VK_F11', keyRepeat: 5, caretLine: 32},
-      {key: 'VK_F11', modifier:'Shift', keyRepeat: 1, caretLine: 29},
-      {key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 34},
-      {key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 34}
+      {key: 'VK_F11', keyRepeat: 2, caretLine: 26},
+      {key: 'VK_F10', keyRepeat: 1, caretLine: 18},
+      {key: 'VK_F11', keyRepeat: 1, caretLine: 19},
+      {key: 'VK_F11', keyRepeat: 5, caretLine: 29},
+      {key: 'VK_F11', modifier:'Shift', keyRepeat: 1, caretLine: 32},
+      {key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 32},
+      {key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 20}
     ];
     // Trigger script that stops at debugger statement
     executeSoon(() => generateMouseClickInTab(gTab,
       "content.document.getElementById('start')"));
     yield waitForPause(gThreadClient);
 
     // Focus the console and add event listener to track whether it loses focus
     // (Must happen after generateMouseClickInTab() call)
--- a/devtools/client/debugger/test/mochitest/browser_dbg_step-out.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_step-out.js
@@ -18,17 +18,17 @@ function test() {
     gVars = gDebugger.DebuggerView.Variables;
 
     testNormalReturn();
   });
 }
 
 function testNormalReturn() {
   waitForSourceAndCaretAndScopes(gPanel, ".html", 17).then(() => {
-    waitForCaretAndScopes(gPanel, 20).then(() => {
+    waitForCaretAndScopes(gPanel, 19).then(() => {
       let innerScope = gVars.getScopeAtIndex(0);
       let returnVar = innerScope.get("<return>");
 
       is(returnVar.name, "<return>",
         "Should have the right property name for the returned value.");
       is(returnVar.value, 10,
         "Should have the right property value for the returned value.");
       ok(returnVar._internalItem, "Should be an internal item");
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -368,23 +368,20 @@ function attachTestThread(aClient, aTitl
     }, onAttach);
   });
 }
 
 // Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's
 // thread, and then resume it. Pass |aCallback| the thread's response to
 // the 'resume' packet, a TabClient for the tab, and a ThreadClient for the
 // thread.
-function attachTestTabAndResume(aClient, aTitle, aCallback = () => {}) {
-  return new Promise((resolve, reject) => {
-    attachTestThread(aClient, aTitle, function(aResponse, aTabClient, aThreadClient) {
-      aThreadClient.resume(function (aResponse) {
-        aCallback(aResponse, aTabClient, aThreadClient);
-        resolve([aResponse, aTabClient, aThreadClient]);
-      });
+function attachTestTabAndResume(aClient, aTitle, aCallback) {
+  attachTestThread(aClient, aTitle, function(aResponse, aTabClient, aThreadClient) {
+    aThreadClient.resume(function (aResponse) {
+      aCallback(aResponse, aTabClient, aThreadClient);
     });
   });
 }
 
 /**
  * Initialize the testing debugger server.
  */
 function initTestDebuggerServer(aServer = DebuggerServer)
@@ -748,31 +745,16 @@ function resumeAndWaitForPause(client, t
 function stepIn(client, threadClient) {
   dumpn("Stepping in.");
   const paused = waitForPause(client);
   return rdpRequest(threadClient, threadClient.stepIn)
     .then(() => paused);
 }
 
 /**
- * Resume JS execution for a step over and wait for the pause after the step
- * has been taken.
- *
- * @param DebuggerClient client
- * @param ThreadClient threadClient
- * @returns Promise
- */
-function stepOver(client, threadClient) {
-  dumpn("Stepping over.");
-  const paused = waitForPause(client);
-  return rdpRequest(threadClient, threadClient.stepOver)
-    .then(() => paused);
-}
-
-/**
  * Get the list of `count` frames currently on stack, starting at the index
  * `first` for the specified thread.
  *
  * @param ThreadClient threadClient
  * @param Number first
  * @param Number count
  * @returns Promise
  */
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/setBreakpoint-on-column-with-no-offsets-at-end-of-script.js
@@ -0,0 +1,5 @@
+"use strict";
+
+function f() {
+  function g() { var a = 1; var b = 2; } g();
+}
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/setBreakpoint-on-line-with-no-offsets-at-end-of-script.js
@@ -0,0 +1,11 @@
+"use strict";
+
+function f() {
+  function g() {
+    var a = 1;
+    var b = 2;
+
+  }
+
+  g();
+}
--- a/devtools/server/tests/unit/test_breakpoint-13.js
+++ b/devtools/server/tests/unit/test_breakpoint-13.js
@@ -34,78 +34,79 @@ function run_test_with_server(aServer, a
 }
 
 function test_simple_breakpoint()
 {
   gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
     let source = gThreadClient.source(aPacket.frame.where.source);
     let location = { line: gDebuggee.line0 + 2 };
 
-    source.setBreakpoint(location, Task.async(function*(aResponse, bpClient) {
-      const testCallbacks = [
-        function(aPacket) {
-          // Check that the stepping worked.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
+    source.setBreakpoint(location, function (aResponse, bpClient) {
+      gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+        // Check that the stepping worked.
+        do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
+        do_check_eq(aPacket.why.type, "resumeLimit");
+
+        gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
           // Entered the foo function call frame.
           do_check_eq(aPacket.frame.where.line, location.line);
           do_check_neq(aPacket.why.type, "breakpoint");
           do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
-          // At the end of the foo function call frame.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
-          do_check_neq(aPacket.why.type, "breakpoint");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
-          // Check that the breakpoint wasn't the reason for this pause, but
-          // that the frame is about to be popped while stepping.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
-          do_check_neq(aPacket.why.type, "breakpoint");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-          do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
-        },
-        function(aPacket) {
-          // The foo function call frame was just popped from the stack.
-          do_check_eq(gDebuggee.a, 1);
-          do_check_eq(gDebuggee.b, undefined);
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
-          do_check_eq(aPacket.why.type, "resumeLimit");
-          do_check_eq(aPacket.poppedFrames.length, 1);
-        },
-        function(aPacket) {
-          // Check that the debugger statement wasn't the reason for this pause.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
-          do_check_neq(aPacket.why.type, "debuggerStatement");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
-          // Check that the debugger statement wasn't the reason for this pause.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
-          do_check_neq(aPacket.why.type, "debuggerStatement");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-      ];
+
+          gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+            // Check that the breakpoint wasn't the reason for this pause, but
+            // that the frame is about to be popped while stepping.
+            do_check_eq(aPacket.frame.where.line, location.line);
+            do_check_neq(aPacket.why.type, "breakpoint");
+            do_check_eq(aPacket.why.type, "resumeLimit");
+            do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
+
+            gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+              // The foo function call frame was just popped from the stack.
+              do_check_eq(gDebuggee.a, 1);
+              do_check_eq(gDebuggee.b, undefined);
+              do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
+              do_check_eq(aPacket.why.type, "resumeLimit");
+              do_check_eq(aPacket.poppedFrames.length, 1);
+
+              gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+                // Check that the debugger statement wasn't the reason for this pause.
+                do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
+                do_check_neq(aPacket.why.type, "debuggerStatement");
+                do_check_eq(aPacket.why.type, "resumeLimit");
 
-      for (let callback of testCallbacks) {
-        let waiter = waitForPause(gThreadClient);
-        gThreadClient.stepIn();
-        let packet = yield waiter;
-        callback(packet);
-      }
+                gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+                  // Check that the debugger statement wasn't the reason for this pause.
+                  do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
+                  do_check_neq(aPacket.why.type, "debuggerStatement");
+                  do_check_eq(aPacket.why.type, "resumeLimit");
+
+                  // Remove the breakpoint and finish.
+                  bpClient.remove(() => gThreadClient.resume(() => gClient.close(gCallback)));
 
-      // Remove the breakpoint and finish.
-      let waiter = waitForPause(gThreadClient);
+                });
+                // Step past the debugger statement.
+                gThreadClient.stepIn();
+              });
+              // Step into the debugger statement.
+              gThreadClient.stepIn();
+            });
+            // Get back to the frame above.
+            gThreadClient.stepIn();
+          });
+          // Step to the end of the function call frame.
+          gThreadClient.stepIn();
+        });
+
+        // Step into the function call.
+        gThreadClient.stepIn();
+      });
+      // Step into the next line with the function call.
       gThreadClient.stepIn();
-      yield waiter;
-      bpClient.remove(() => gThreadClient.resume(() => gClient.close(gCallback)));
-    }));
+    });
   });
 
   Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
                    "function foo() {\n" + // line0 + 1
                    "  this.a = 1;\n" +    // line0 + 2 <-- Breakpoint is set here.
                    "}\n" +                // line0 + 3
                    "debugger;\n" +        // line0 + 4
                    "foo();\n" +           // line0 + 5
--- a/devtools/server/tests/unit/test_breakpoint-14.js
+++ b/devtools/server/tests/unit/test_breakpoint-14.js
@@ -34,76 +34,77 @@ function run_test_with_server(aServer, a
 }
 
 function test_simple_breakpoint()
 {
   gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
     let source = gThreadClient.source(aPacket.frame.where.source);
     let location = { line: gDebuggee.line0 + 2 };
 
-    source.setBreakpoint(location, Task.async(function*(aResponse, bpClient) {
-      const testCallbacks = [
-        function(aPacket) {
-          // Check that the stepping worked.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
+    source.setBreakpoint(location, function (aResponse, bpClient) {
+      gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+        // Check that the stepping worked.
+        do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
+        do_check_eq(aPacket.why.type, "resumeLimit");
+
+        gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
           // Reached the breakpoint.
           do_check_eq(aPacket.frame.where.line, location.line);
           do_check_eq(aPacket.why.type, "breakpoint");
           do_check_neq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
-          // Stepped to the closing brace of the function.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
-          // The frame is about to be popped while stepping.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
-          do_check_neq(aPacket.why.type, "breakpoint");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-          do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
-        },
-        function(aPacket) {
-          // The foo function call frame was just popped from the stack.
-          do_check_eq(gDebuggee.a, 1);
-          do_check_eq(gDebuggee.b, undefined);
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
-          do_check_eq(aPacket.why.type, "resumeLimit");
-          do_check_eq(aPacket.poppedFrames.length, 1);
-        },
-        function(aPacket) {
-          // Check that the debugger statement wasn't the reason for this pause.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
-          do_check_neq(aPacket.why.type, "debuggerStatement");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-        function(aPacket) {
-          // Check that the debugger statement wasn't the reason for this pause.
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
-          do_check_neq(aPacket.why.type, "debuggerStatement");
-          do_check_eq(aPacket.why.type, "resumeLimit");
-        },
-      ];
+
+          gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+            // The frame is about to be popped while stepping.
+            do_check_eq(aPacket.frame.where.line, location.line);
+            do_check_neq(aPacket.why.type, "breakpoint");
+            do_check_eq(aPacket.why.type, "resumeLimit");
+            do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
+
+            gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+              // The foo function call frame was just popped from the stack.
+              do_check_eq(gDebuggee.a, 1);
+              do_check_eq(gDebuggee.b, undefined);
+              do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
+              do_check_eq(aPacket.why.type, "resumeLimit");
+              do_check_eq(aPacket.poppedFrames.length, 1);
+
+              gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+                // Check that the debugger statement wasn't the reason for this pause.
+                do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
+                do_check_neq(aPacket.why.type, "debuggerStatement");
+                do_check_eq(aPacket.why.type, "resumeLimit");
 
-      for (let callback of testCallbacks) {
-        let waiter = waitForPause(gThreadClient);
-        gThreadClient.stepOver();
-        let packet = yield waiter;
-        callback(packet);
-      }
+                gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
+                  // Check that the debugger statement wasn't the reason for this pause.
+                  do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
+                  do_check_neq(aPacket.why.type, "debuggerStatement");
+                  do_check_eq(aPacket.why.type, "resumeLimit");
+
+                  // Remove the breakpoint and finish.
+                  bpClient.remove(() => gThreadClient.resume(() => gClient.close(gCallback)));
 
-      // Remove the breakpoint and finish.
-      let waiter = waitForPause(gThreadClient);
+                });
+                // Step past the debugger statement.
+                gThreadClient.stepOver();
+              });
+              // Step over the debugger statement.
+              gThreadClient.stepOver();
+            });
+            // Get back to the frame above.
+            gThreadClient.stepOver();
+          });
+          // Step to the end of the function call frame.
+          gThreadClient.stepOver();
+        });
+        // Step over the function call.
+        gThreadClient.stepOver();
+      });
+      // Step over to the next line with the function call.
       gThreadClient.stepOver();
-      yield waiter;
-      bpClient.remove(() => gThreadClient.resume(() => gClient.close(gCallback)));
-    }));
+    });
   });
 
   Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
                    "function foo() {\n" + // line0 + 1
                    "  this.a = 1;\n" +    // line0 + 2 <-- Breakpoint is set here.
                    "}\n" +                // line0 + 3
                    "debugger;\n" +        // line0 + 4
                    "foo();\n" +           // line0 + 5
--- a/devtools/server/tests/unit/test_get-executable-lines.js
+++ b/devtools/server/tests/unit/test_get-executable-lines.js
@@ -33,17 +33,17 @@ function run_test() {
 function test_executable_lines() {
   gThreadClient.addOneTimeListener("newSource", function _onNewSource(evt, packet) {
     do_check_eq(evt, "newSource");
 
     gThreadClient.getSources(function ({error, sources}) {
       do_check_true(!error);
       let source = gThreadClient.source(sources[0]);
       source.getExecutableLines(function(lines){
-        do_check_true(arrays_equal([2, 5, 7, 8, 10, 12, 14, 16], lines));
+        do_check_true(arrays_equal([2, 5, 7, 8, 12, 14, 16], lines));
         finishClient(gClient);
       });
     });
   });
 
   let code = readFile("sourcemapped.js");
 
   Components.utils.evalInSandbox(code, gDebuggee, "1.8",
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets-at-end-of-script.js
@@ -0,0 +1,53 @@
+"use strict";
+
+var SOURCE_URL = getFileUrl("setBreakpoint-on-line-with-no-offsets-at-end-of-script.js");
+
+function run_test() {
+  return Task.spawn(function* () {
+    do_test_pending();
+
+    DebuggerServer.registerModule("xpcshell-test/testactors");
+    DebuggerServer.init(() => true);
+
+    let global = createTestGlobal("test");
+    DebuggerServer.addTestGlobal(global);
+
+    let client = new DebuggerClient(DebuggerServer.connectPipe());
+    yield connect(client);
+
+    let { tabs } = yield listTabs(client);
+    let tab = findTab(tabs, "test");
+    let [, tabClient] = yield attachTab(client, tab);
+    let [, threadClient] = yield attachThread(tabClient);
+    yield resume(threadClient);
+
+    let promise = waitForNewSource(threadClient, SOURCE_URL);
+    loadSubScript(SOURCE_URL, global);
+    let { source } = yield promise;
+    let sourceClient = threadClient.source(source);
+
+    let location = { line: 7 };
+    let [packet, breakpointClient] = yield setBreakpoint(sourceClient, location);
+    do_check_false(packet.isPending); // NOTE: Change this when bug 1148356 lands
+    do_check_true("actualLocation" in packet);
+    let actualLocation = packet.actualLocation;
+    do_check_eq(actualLocation.line, 10);
+
+    packet = yield executeOnNextTickAndWaitForPause(function () {
+      Cu.evalInSandbox("f()", global);
+    }, client);
+    do_check_eq(packet.type, "paused");
+    let why = packet.why;
+    do_check_eq(why.type, "breakpoint");
+    do_check_eq(why.actors.length, 1);
+    do_check_eq(why.actors[0], breakpointClient.actor);
+    let where = packet.frame.where;
+    do_check_eq(where.source.actor, source.actor);
+    do_check_eq(where.line, actualLocation.line);
+
+    yield resume(threadClient);
+    yield close(client);
+
+    do_test_finished();
+  });
+}
--- a/devtools/server/tests/unit/test_stepping-03.js
+++ b/devtools/server/tests/unit/test_stepping-03.js
@@ -33,17 +33,17 @@ function run_test_with_server(aServer, a
 }
 
 function test_simple_stepping()
 {
   gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
     gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
       // Check the return value.
       do_check_eq(aPacket.type, "paused");
-      do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
+      do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 4);
       do_check_eq(aPacket.why.type, "resumeLimit");
       // Check that stepping worked.
       do_check_eq(gDebuggee.a, 1);
       do_check_eq(gDebuggee.b, 2);
 
       gThreadClient.resume(function () {
         gClient.close(gCallback);
       });
--- a/devtools/server/tests/unit/test_stepping-06.js
+++ b/devtools/server/tests/unit/test_stepping-06.js
@@ -38,25 +38,25 @@ function run_test_with_server(aServer, a
 }
 
 function test_simple_stepping()
 {
   gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
     gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
       // Check that the return value is 10.
       do_check_eq(aPacket.type, "paused");
-      do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
+      do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 4);
       do_check_eq(aPacket.why.type, "resumeLimit");
       do_check_eq(aPacket.why.frameFinished.return, 10);
 
       gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
         gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
           // Check that the return value is undefined.
           do_check_eq(aPacket.type, "paused");
-          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 8);
+          do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
           do_check_eq(aPacket.why.type, "resumeLimit");
           do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
 
           gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
             gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
               // Check that the exception was thrown.
               do_check_eq(aPacket.type, "paused");
               do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 11);
deleted file mode 100644
--- a/devtools/server/tests/unit/test_stepping-07.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Check that stepping over an implicit return makes sense. Bug 1155966.
- */
-
-var gDebuggee;
-var gClient;
-var gCallback;
-
-function run_test() {
-  do_test_pending();
-  run_test_with_server(DebuggerServer, function () {
-    run_test_with_server(WorkerDebuggerServer, do_test_finished);
-  });
-};
-
-function run_test_with_server(aServer, aCallback) {
-  gCallback = aCallback;
-  initTestDebuggerServer(aServer);
-  gDebuggee = addTestGlobal("test-stepping", aServer);
-  gClient = new DebuggerClient(aServer.connectPipe());
-  gClient.connect(testSteppingAndReturns);
-}
-
-const testSteppingAndReturns = Task.async(function*() {
-  const [attachResponse, tabClient, threadClient] = yield attachTestTabAndResume(gClient, "test-stepping");
-  ok(!attachResponse.error, "Should not get an error attaching");
-
-  dumpn("Evaluating test code and waiting for first debugger statement");
-  const dbgStmt1 = yield executeOnNextTickAndWaitForPause(evaluateTestCode, gClient)
-  equal(dbgStmt1.frame.where.line, 3,
-        "Should be at debugger statement on line 3")
-
-  dumpn("Testing stepping with implicit return");
-  const step1 = yield stepOver(gClient, threadClient);
-  equal(step1.frame.where.line, 4, "Should step to line 4");
-  const step2 = yield stepOver(gClient, threadClient);
-  equal(step2.frame.where.line, 7,
-        "Should step to line 7, the implicit return at the last line of the function");
-  // This assertion doesn't pass yet. You would need to do *another*
-  // step at the end of this function to get the frameFinished.
-  // See bug 923975.
-  //
-  // ok(step2.why.frameFinished, "This should be the implicit function return");
-
-  dumpn("Continuing and waiting for second debugger statement");
-  const dbgStmt2 = yield resumeAndWaitForPause(gClient, threadClient);
-  equal(dbgStmt2.frame.where.line, 12,
-        "Should be at debugger statement on line 3")
-
-  dumpn("Testing stepping with explicit return");
-  const step3 = yield stepOver(gClient, threadClient);
-  equal(step3.frame.where.line, 13, "Should step to line 13");
-  const step4 = yield stepOver(gClient, threadClient);
-  equal(step4.frame.where.line, 15, "Should step out of the function from line 15");
-  // This step is a bit funny, see bug 1013219 for details.
-  const step5 = yield stepOver(gClient, threadClient);
-  equal(step5.frame.where.line, 15, "Should step out of the function from line 15");
-  ok(step5.why.frameFinished, "This should be the explicit function return");
-
-  finishClient(gClient, gCallback);
-});
-
-function evaluateTestCode() {
-  Cu.evalInSandbox(
-    `                                   //  1
-    function implicitReturn() {         //  2
-      debugger;                         //  3
-      if (this.someUndefinedProperty) { //  4
-        yikes();                        //  5
-      }                                 //  6
-    }                                   //  7
-                                        //  8
-    var yes = true;                     //  9
-    function explicitReturn() {         // 10
-      if (yes) {                        // 11
-        debugger;                       // 12
-        return 1;                       // 13
-      }                                 // 14
-    }                                   // 15
-                                        // 16
-    implicitReturn();                   // 17
-    explicitReturn();                   // 18
-    `,                                  // 19
-    gDebuggee,
-    "1.8",
-    "test_stepping-07-test-code.js",
-    1
-  );
-}
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -18,22 +18,24 @@ support-files =
   registertestactors-03.js
   sourcemapped.js
   testactors.js
   hello-actor.js
   setBreakpoint-on-column.js
   setBreakpoint-on-column-in-gcd-script.js
   setBreakpoint-on-column-with-no-offsets.js
   setBreakpoint-on-column-with-no-offsets-at-end-of-line.js
+  setBreakpoint-on-column-with-no-offsets-at-end-of-script.js
   setBreakpoint-on-column-with-no-offsets-in-gcd-script.js
   setBreakpoint-on-line.js
   setBreakpoint-on-line-in-gcd-script.js
   setBreakpoint-on-line-with-multiple-offsets.js
   setBreakpoint-on-line-with-multiple-statements.js
   setBreakpoint-on-line-with-no-offsets.js
+  setBreakpoint-on-line-with-no-offsets-at-end-of-script.js
   setBreakpoint-on-line-with-no-offsets-in-gcd-script.js
 
 [test_ScriptStore.js]
 [test_actor-registry-actor.js]
 [test_nesting-01.js]
 [test_nesting-02.js]
 [test_nesting-03.js]
 [test_forwardingprefix.js]
@@ -198,17 +200,16 @@ reason = bug 820380
 [test_promise_state-03.js]
 [test_interrupt.js]
 [test_stepping-01.js]
 [test_stepping-02.js]
 [test_stepping-03.js]
 [test_stepping-04.js]
 [test_stepping-05.js]
 [test_stepping-06.js]
-[test_stepping-07.js]
 [test_framebindings-01.js]
 [test_framebindings-02.js]
 [test_framebindings-03.js]
 [test_framebindings-04.js]
 [test_framebindings-05.js]
 [test_framebindings-06.js]
 [test_framebindings-07.js]
 [test_pause_exceptions-01.js]
@@ -256,11 +257,12 @@ reason = bug 1014071
 [test_setBreakpoint-on-column.js]
 [test_setBreakpoint-on-column-in-gcd-script.js]
 [test_setBreakpoint-on-column-with-no-offsets-at-end-of-line.js]
 [test_setBreakpoint-on-line.js]
 [test_setBreakpoint-on-line-in-gcd-script.js]
 [test_setBreakpoint-on-line-with-multiple-offsets.js]
 [test_setBreakpoint-on-line-with-multiple-statements.js]
 [test_setBreakpoint-on-line-with-no-offsets.js]
+[test_setBreakpoint-on-line-with-no-offsets-at-end-of-script.js]
 [test_setBreakpoint-on-line-with-no-offsets-in-gcd-script.js]
 [test_safe-getter.js]
 [test_client_close.js]
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -341,26 +341,22 @@ BytecodeCompiler::handleParseFailure(con
     return true;
 }
 
 bool
 BytecodeCompiler::prepareAndEmitTree(ParseNode** ppn)
 {
     if (!FoldConstants(cx, ppn, parser.ptr()) ||
         !NameFunctions(cx, *ppn) ||
-        !emitter->updateLocalsToFrameSlots())
+        !emitter->updateLocalsToFrameSlots() ||
+        !emitter->emitTree(*ppn))
     {
         return false;
     }
 
-    emitter->setFunctionBodyEndPos((*ppn)->pn_pos);
-
-    if (!emitter->emitTree(*ppn))
-        return false;
-
     return true;
 }
 
 bool
 BytecodeCompiler::maybeSetDisplayURL(TokenStream& tokenStream)
 {
     if (tokenStream.hasDisplayURL()) {
         if (!scriptSource->setDisplayURL(cx, tokenStream.displayURL()))
@@ -827,17 +823,17 @@ frontend::CompileLazyFunction(JSContext*
      * We just pass false for insideNonGlobalEval and insideEval, because we
      * don't actually know whether we are or not.  The only consumer of those
      * booleans is TryConvertFreeName, and it has special machinery to avoid
      * doing bad things when a lazy function is inside eval.
      */
     MOZ_ASSERT(!options.forEval);
     BytecodeEmitter bce(/* parent = */ nullptr, &parser, pn->pn_funbox, script, lazy,
                         /* insideEval = */ false, /* evalCaller = */ nullptr,
-                        /* insideNonGlobalEval = */ false, pn->pn_pos,
+                        /* insideNonGlobalEval = */ false, options.lineno,
                         BytecodeEmitter::LazyFunction);
     if (!bce.init())
         return false;
 
     return bce.emitFunctionScript(pn->pn_body);
 }
 
 // Compile a JS function body, which might appear as the value of an event
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -140,37 +140,22 @@ BytecodeEmitter::BytecodeEmitter(Bytecod
     typesetCount(0),
     hasSingletons(false),
     hasTryFinally(false),
     emittingForInit(false),
     emittingRunOnceLambda(false),
     insideEval(insideEval),
     insideNonGlobalEval(insideNonGlobalEval),
     insideModule(false),
-    emitterMode(emitterMode),
-    functionBodyEndPosSet(false)
+    emitterMode(emitterMode)
 {
     MOZ_ASSERT_IF(evalCaller, insideEval);
     MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
 }
 
-BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
-                                 Parser<FullParseHandler>* parser, SharedContext* sc,
-                                 HandleScript script, Handle<LazyScript*> lazyScript,
-                                 bool insideEval, HandleScript evalCaller,
-                                 bool insideNonGlobalEval, TokenPos bodyPosition,
-                                 EmitterMode emitterMode)
-    : BytecodeEmitter(parent, parser, sc, script, lazyScript, insideEval,
-                      evalCaller, insideNonGlobalEval,
-                      parser->tokenStream.srcCoords.lineNum(bodyPosition.begin),
-                      emitterMode)
-{
-    setFunctionBodyEndPos(bodyPosition);
-}
-
 bool
 BytecodeEmitter::init()
 {
     return atomIndices.ensureMap(cx);
 }
 
 bool
 BytecodeEmitter::updateLocalsToFrameSlots()
@@ -3588,23 +3573,19 @@ BytecodeEmitter::emitFunctionScript(Pars
     bool runOnce = isRunOnceLambda();
     if (runOnce) {
         switchToPrologue();
         if (!emit1(JSOP_RUNONCE))
             return false;
         switchToMain();
     }
 
-    setFunctionBodyEndPos(body->pn_pos);
     if (!emitTree(body))
         return false;
 
-    if (!updateSourceCoordNotes(body->pn_pos.end))
-        return false;
-
     if (sc->isFunctionBox()) {
         if (sc->asFunctionBox()->isGenerator()) {
             // If we fall off the end of a generator, do a final yield.
             if (sc->asFunctionBox()->isStarGenerator() && !emitPrepareIteratorResult())
                 return false;
 
             if (!emit1(JSOP_UNDEFINED))
                 return false;
@@ -3694,17 +3675,16 @@ BytecodeEmitter::emitModuleScript(ParseN
 
     ModuleBox* modulebox = sc->asModuleBox();
     MOZ_ASSERT(modulebox);
 
     // Link the module and the script to each other, so that StaticScopeIter
     // may walk the scope chain of currently compiling scripts.
     JSScript::linkToModuleFromEmitter(cx, script, modulebox);
 
-    setFunctionBodyEndPos(body->pn_pos);
     if (!emitTree(body))
         return false;
 
     // Always end the script with a JSOP_RETRVAL. Some other parts of the codebase
     // depend on this opcode, e.g. InterpreterRegs::setToEndOfScript.
     if (!emit1(JSOP_RETRVAL))
         return false;
 
@@ -6361,19 +6341,20 @@ BytecodeEmitter::emitFunction(ParseNode*
             Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
                                                           sourceObject,
                                                           funbox->bufStart, funbox->bufEnd));
             if (!script)
                 return false;
 
             script->bindings = funbox->bindings;
 
+            uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin);
             BytecodeEmitter bce2(this, parser, funbox, script, /* lazyScript = */ nullptr,
                                  insideEval, evalCaller,
-                                 insideNonGlobalEval, pn->pn_pos, emitterMode);
+                                 insideNonGlobalEval, lineNum, emitterMode);
             if (!bce2.init())
                 return false;
 
             /* We measured the max scope depth when we parsed the function. */
             if (!bce2.emitFunctionScript(pn->pn_body))
                 return false;
 
             if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
@@ -6734,23 +6715,16 @@ BytecodeEmitter::emitReturn(ParseNode* p
             return false;
     }
 
     if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
         if (!emitFinishIteratorResult(true))
             return false;
     }
 
-    // We know functionBodyEndPos is set because "return" is only
-    // valid in a function, and so we've passed through
-    // emitFunctionScript.
-    MOZ_ASSERT(functionBodyEndPosSet);
-    if (!updateSourceCoordNotes(functionBodyEndPos))
-        return false;
-
     /*
      * EmitNonLocalJumpFixup may add fixup bytecode to close open try
      * blocks having finally clauses and to exit intermingled let blocks.
      * We can't simply transfer control flow to our caller in that case,
      * because we must gosub to those finally clauses from inner to outer,
      * with the correct stack pointer (i.e., after popping any with,
      * for/in, etc., slots nested inside the finally's try).
      *
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -229,39 +229,26 @@ struct BytecodeEmitter
          * Check the static scope chain of the root function for resolving free
          * variable accesses in the script.
          */
         LazyFunction
     };
 
     const EmitterMode emitterMode;
 
-    // The end location of a function body that is being emitted.
-    uint32_t functionBodyEndPos;
-    // Whether functionBodyEndPos was set.
-    bool functionBodyEndPosSet;
-
     /*
      * Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
      * space above their tempMark points. This means that you cannot alloc from
      * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter
      * destruction.
      */
     BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler>* parser, SharedContext* sc,
                     HandleScript script, Handle<LazyScript*> lazyScript,
                     bool insideEval, HandleScript evalCaller,
                     bool insideNonGlobalEval, uint32_t lineNum, EmitterMode emitterMode = Normal);
-
-    // An alternate constructor that uses a TokenPos for the starting
-    // line and that sets functionBodyEndPos as well.
-    BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler>* parser, SharedContext* sc,
-                    HandleScript script, Handle<LazyScript*> lazyScript,
-                    bool insideEval, HandleScript evalCaller,
-                    bool insideNonGlobalEval, TokenPos bodyPosition, EmitterMode emitterMode = Normal);
-
     bool init();
     bool updateLocalsToFrameSlots();
 
     StmtInfoBCE* innermostStmt() const { return stmtStack.innermost(); }
     StmtInfoBCE* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); }
     JSObject* innermostStaticScope() const;
     JSObject* blockScopeOfDef(Definition* dn) const {
         return parser->blockScopes[dn->pn_blockid];
@@ -312,21 +299,16 @@ struct BytecodeEmitter
     void switchToPrologue() { current = &prologue; }
     bool inPrologue() const { return current == &prologue; }
 
     SrcNotesVector& notes() const { return current->notes; }
     ptrdiff_t lastNoteOffset() const { return current->lastNoteOffset; }
     unsigned currentLine() const { return current->currentLine; }
     unsigned lastColumn() const { return current->lastColumn; }
 
-    void setFunctionBodyEndPos(TokenPos pos) {
-        functionBodyEndPos = pos.end;
-        functionBodyEndPosSet = true;
-    }
-
     bool reportError(ParseNode* pn, unsigned errorNumber, ...);
     bool reportStrictWarning(ParseNode* pn, unsigned errorNumber, ...);
     bool reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...);
 
     // If pn contains a useful expression, return true with *answer set to true.
     // If pn contains a useless expression, return true with *answer set to
     // false. Return false on error.
     //
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -3143,18 +3143,16 @@ Parser<ParseHandler>::functionArgsAndBod
 #endif
         if (tokenStream.hadError())
             return false;
         funbox->bufEnd = pos().end;
         if (kind == Statement && !MatchOrInsertSemicolonAfterExpression(tokenStream))
             return false;
     }
 
-    handler.setEndPosition(body, pos().begin);
-
     return finishFunctionDefinition(pn, funbox, body);
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::checkYieldNameValidity()
 {
     // In star generators and in JS >= 1.7, yield is a keyword.  Otherwise in
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Frame-onPop-23.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Check that the line number reported at an onPop stop makes sense,
-// even when it happens on an "artificial" instruction.
-
-var g = newGlobal();
-
-// This bit of code arranges for the line number of the "artificial"
-// instruction to be something nonsensical -- the middle of a loop
-// which cannot be entered.
-g.eval(`function f() {
-  debugger;                   // +0
-  if(false) {                 // +1
-    for(var b=0; b<0; b++) {  // +2
-      c = 2;                  // +3
-    }                         // +4
-  }                           // +5
-}                             // +6
-`);
-
-var dbg = Debugger(g);
-
-let debugLine;
-let foundLine;
-
-dbg.onDebuggerStatement = function(frame) {
-  debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber;
-  frame.onPop = function(c) {
-    foundLine = this.script.getOffsetLocation(this.offset).lineNumber;
-  };
-};
-
-g.eval("f();\n");
-
-// The stop should happen on the closing brace of the function.
-assertEq(foundLine == debugLine + 6, true);
--- a/js/src/jit-test/tests/debug/Frame-onStep-11.js
+++ b/js/src/jit-test/tests/debug/Frame-onStep-11.js
@@ -28,9 +28,9 @@ dbg.onDebuggerStatement = function(frame
     if (foundLine != debugLine && this.script.getLineOffsets(foundLine).indexOf(this.offset) >= 0) {
       foundLines += "," + (foundLine - debugLine);
     }
   };
 };
 
 g.f();
 
-assertEq(foundLines, ",1,2,3,4,5,6,7,8,10,11");
+assertEq(foundLines, ",1,2,3,4,5,6,7,8,10");
--- a/js/src/jit-test/tests/debug/Frame-onStep-12.js
+++ b/js/src/jit-test/tests/debug/Frame-onStep-12.js
@@ -60,70 +60,70 @@ function testOne(name, body, expected) {
 
 // Test the instructions at the end of a "try".
 testOne("testTryFinally",
         `try {
            ${bitOfCode}
          } finally {            // +6
          }                      // +7
          nothing();             // +8
-        `, "1689");
+        `, "168");
 
 // The same but without a finally clause.
 testOne("testTryCatch",
         `try {
            ${bitOfCode}
          } catch (e) {          // +6
          }                      // +7
          nothing();             // +8
-        `, "189");
+        `, "18");
 
 // Test the instructions at the end of a "catch".
 testOne("testCatchFinally",
         `try {
            throw new TypeError();
          } catch (e) {
            ${bitOfCode}
          } finally {            // +6
          }                      // +7
          nothing();             // +8
-        `, "1689");
+        `, "168");
 
 // The same but without a finally clause.  This relies on a
 // SpiderMonkey extension, because otherwise there's no way to see
 // extra instructions at the end of a catch.
 testOne("testCatch",
         `try {
            throw new TypeError();
          } catch (e if e instanceof TypeError) {
            ${bitOfCode}
          } catch (e) {          // +6
          }                      // +7
          nothing();             // +8
-        `, "189");
+        `, "18");
 
 // Test the instruction at the end of a "finally" clause.
 testOne("testFinally",
         `try {
          } finally {
            ${bitOfCode}
          }                      // +6
          nothing();             // +7
-        `, "178");
+        `, "17");
 
 // Test the instruction at the end of a "then" clause.
 testOne("testThen",
         `if (1 === 1) {
            ${bitOfCode}
          } else {               // +6
          }                      // +7
          nothing();             // +8
-        `, "189");
+        `, "18");
 
 // Test the instructions leaving a switch block.
 testOne("testSwitch",
         `var x = 5;
          switch (x) {
            case 5:
              ${bitOfCode}
          }                      // +6
          nothing();             // +7
-        `, "178");
+        `, "17");
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Frame-onStep-13.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Stepping over a not-taken "if" that is at the end of the function
-// should move to the end of the function, not somewhere in the body
-// of the "if".
-
-var g = newGlobal();
-g.eval(`function f() {        // 1
-  var a,c;                    // 2
-  debugger;                   // 3
-  if(false) {                 // 4
-    for(var b=0; b<0; b++) {  // 5
-      c = 2;                  // 6
-    }                         // 7
-  }                           // 8
-}                             // 9
-`);
-
-var dbg = Debugger(g);
-var badStep = false;
-
-dbg.onDebuggerStatement = function(frame) {
-  let debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber;
-  assertEq(debugLine, 3);
-  frame.onStep = function() {
-    let foundLine = this.script.getOffsetLocation(this.offset).lineNumber;
-    assertEq(foundLine <= 4 || foundLine >= 8, true);
-  };
-};
-
-g.eval("f();\n");
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Frame-onStep-16.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Stepping through a function with a return statement should pause on
-// the closing brace of the function.
-
-var g = newGlobal();
-var dbg = Debugger(g);
-var log;
-
-function test(fnStr) {
-  log = '';
-  g.eval(fnStr);
-
-  dbg.onDebuggerStatement = function(frame) {
-        frame.onStep = function() {
-      let {lineNumber, isEntryPoint} = frame.script.getOffsetLocation(frame.offset);
-      if (isEntryPoint) {
-        log += lineNumber + ' ';
-      }
-    };
-  };
-
-  g.eval("f(23);");
-}
-
-test("function f(x) {\n" +    // 1
-     "    debugger;\n" +      // 2
-     "    return 23 + x;\n" + // 3
-     "}\n");                  // 4
-assertEq(log, '3 4 ');
-
-test("function f(x) {\n" +    // 1
-     "    debugger;\n" +      // 2
-     "    return;\n" +        // 3
-     "}\n");                  // 4
-assertEq(log, '3 4 ');
--- a/js/src/jit-test/tests/debug/Frame-onStep-lines-01.js
+++ b/js/src/jit-test/tests/debug/Frame-onStep-lines-01.js
@@ -43,17 +43,17 @@ assertEq(Object.keys(offsets).length, 1)
 g.eval('t(10,20,30)');
 assertEq(Object.keys(offsets).length, 2);
 
 // This shouldn't stop at all. It's the frame that's in single-step mode,
 // not the script, so the prior execution of t in single-step mode should
 // have no effect on this one.
 doSingleStep = false;
 g.eval('t(0, 0, 0)');
-assertEq(Object.keys(offsets).length, 7);
+assertEq(Object.keys(offsets).length, 6);
 doSingleStep = true;
 
 // Single-step in an eval frame. This should reach every line but the
 // first.
 g.eval(
        'debugger;                        \n' +
        'var a=1, b=2, c=3;               \n' +
        'var x = a;                       \n' +
--- a/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-01.js
+++ b/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-01.js
@@ -11,9 +11,9 @@ Debugger(global).onDebuggerStatement = f
             }
         });
     });
 };
 
 global.log = '';
 global.eval("function f(n) { for (var i = 0; i < n; ++i) log += '. '; log += '! '; } debugger;");
 global.f(3);
-assertEq(global.log, "25 32 44 . 39 32 44 . 39 32 44 . 39 32 57 ! 70 ");
+assertEq(global.log, "25 32 44 . 39 32 44 . 39 32 44 . 39 32 57 ! 69 ");
--- a/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-06.js
+++ b/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-06.js
@@ -11,18 +11,18 @@ Debugger(global).onDebuggerStatement = f
             }
         });
     });
 };
 
 global.log = "";
 global.eval("function ppppp() { return 1; }");
 //                     1         2         3         4
-//           01234567890123456789012345678901234567890123456789
+//           0123456789012345678901234567890123456789012345678
 global.eval("function f(){ 1 && ppppp(ppppp()) && new Error() } debugger;");
 global.f();
 
 // 14 - Enter the function body
 // 25 - Inner print()
 // 19 - Outer print()
 // 37 - new Error()
-// 49 - Exit the function body
-assertEq(global.log, "14 25 19 37 49 ");
+// 48 - Exit the function body
+assertEq(global.log, "14 25 19 37 48 ");
--- a/js/src/jit-test/tests/debug/Script-startLine.js
+++ b/js/src/jit-test/tests/debug/Script-startLine.js
@@ -50,14 +50,12 @@ g.eval("/* Any copyright is dedicated to
        " http://creativecommons.org/publicdomain/zero/1.0/ */\n" +
        "\n" +
        "function secondCall() { first = Error().lineNumber;\n" +
        "    debugger;\n" +
        "    // Comment\n" +
        "    eval(\"42;\");\n" +
        "    function foo() {}\n" +
        "    if (true) {\n" +
-       "        foo();\n" +
-       // The "missing" newline here is a trick to make a newline
-       // source note come at the end.  A real newline between the two
-       // closing braces causes a setline note instead.
-       "    } }");
-test(g.secondCall, 8);
+       "        foo();\n" +  // <- this is +6 and must be within the extent
+       "    }\n" +
+       "}");
+test(g.secondCall, 7);