Bug 1508314 Part 3 - Clear out stepping hooks via ReplayDebugger, r=lsmyth.
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 20 Nov 2018 14:27:18 -1000
changeset 504173 f668df79d93b379add8c1019792e6fdef687506b
parent 504172 795cc577254c0b9b8665c78c6b2a4bdad9cfa5be
child 504174 8a54a4fa7f4c2b275208c760d7e93b00b7c78161
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsmyth
bugs1508314
milestone65.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
Bug 1508314 Part 3 - Clear out stepping hooks via ReplayDebugger, r=lsmyth.
devtools/server/actors/replay/debugger.js
devtools/server/actors/thread.js
--- a/devtools/server/actors/replay/debugger.js
+++ b/devtools/server/actors/replay/debugger.js
@@ -397,16 +397,23 @@ ReplayDebugger.prototype = {
   _breakpointKindSetter(kind, handler, callback) {
     if (handler) {
       this._setBreakpoint(callback, { kind }, handler);
     } else {
       this._clearMatchingBreakpoints(({position}) => position.kind == kind);
     }
   },
 
+  // Clear OnStep and OnPop hooks for all frames.
+  replayClearSteppingHooks() {
+    this._clearMatchingBreakpoints(
+      ({position}) => position.kind == "OnStep" || position.kind == "OnPop"
+    );
+  },
+
   /////////////////////////////////////////////////////////
   // Script methods
   /////////////////////////////////////////////////////////
 
   _getScript(id) {
     if (!id) {
       return null;
     }
@@ -760,31 +767,21 @@ ReplayDebuggerFrame.prototype = {
 
   get onStep() {
     return this._dbg._searchBreakpoints(({position, data}) => {
       return this._positionMatches(position, "OnStep") ? data : null;
     });
   },
 
   set onStep(handler) {
-    if (handler) {
-      // Use setReplayingOnStep instead.
-      NotAllowed();
-    }
-    this._clearOnStepBreakpoints();
-  },
-
-  _clearOnStepBreakpoints() {
-    this._dbg._clearMatchingBreakpoints(
-      ({position}) => this._positionMatches(position, "OnStep")
-    );
+    // Use setReplayingOnStep or replayClearSteppingHooks instead.
+    NotAllowed();
   },
 
   setReplayingOnStep(handler, offsets) {
-    this._clearOnStepBreakpoints();
     offsets.forEach(offset => {
       this._dbg._setBreakpoint(
         () => { handler.call(this._dbg.getNewestFrame()); },
         { kind: "OnStep",
           script: this._data.script,
           offset,
           frameIndex: this._data.index },
         handler);
@@ -802,19 +799,18 @@ ReplayDebuggerFrame.prototype = {
       this._dbg._setBreakpoint(() => {
           const result = this._dbg._sendRequest({ type: "popFrameResult" });
           handler.call(this._dbg.getNewestFrame(),
                        this._dbg._convertCompletionValue(result));
         },
         { kind: "OnPop", script: this._data.script, frameIndex: this._data.index },
         handler);
     } else {
-      this._dbg._clearMatchingBreakpoints(
-        ({position}) => this._positionMatches(position, "OnPop")
-      );
+      // Use replayClearSteppingHooks instead.
+      NotAllowed();
     }
   },
 
   get older() {
     if (this._data.index == 0) {
       // This is the oldest frame.
       return null;
     }
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -854,28 +854,29 @@ const ThreadActor = ActorClassWithSpec(t
           break;
       }
     }
 
     return true;
   },
 
   /**
-   * Clear the onStep and onPop hooks from the given frame and all of the frames
-   * below it.
-   *
-   * @param Debugger.Frame aFrame
-   *        The frame we want to clear the stepping hooks from.
+   * Clear the onStep and onPop hooks for all frames on the stack.
    */
-  _clearSteppingHooks: function(frame) {
-    if (frame && frame.live) {
-      while (frame) {
-        frame.onStep = undefined;
-        frame.onPop = undefined;
-        frame = frame.older;
+  _clearSteppingHooks: function() {
+    if (this.dbg.replaying) {
+      this.dbg.replayClearSteppingHooks();
+    } else {
+      let frame = this.youngestFrame;
+      if (frame && frame.live) {
+        while (frame) {
+          frame.onStep = undefined;
+          frame.onPop = undefined;
+          frame = frame.older;
+        }
       }
     }
   },
 
   /**
    * Listen to the debuggee's DOM events if we received a request to do so.
    *
    * @param Object request
@@ -935,17 +936,17 @@ const ThreadActor = ActorClassWithSpec(t
         message: "Can't rewind a debuggee that is not replaying.",
       };
     }
 
     let resumeLimitHandled;
     if (request && request.resumeLimit) {
       resumeLimitHandled = this._handleResumeLimit(request);
     } else {
-      this._clearSteppingHooks(this.youngestFrame);
+      this._clearSteppingHooks();
       resumeLimitHandled = Promise.resolve(true);
     }
 
     return resumeLimitHandled.then(() => {
       if (request) {
         this._options.pauseOnExceptions = request.pauseOnExceptions;
         this._options.ignoreCaughtExceptions = request.ignoreCaughtExceptions;
         this.maybePauseOnExceptions();
@@ -1457,20 +1458,17 @@ const ThreadActor = ActorClassWithSpec(t
     if (this.state === "paused") {
       return undefined;
     }
 
     // Clear stepping hooks.
     this.dbg.onEnterFrame = undefined;
     this.dbg.replayingOnPopFrame = undefined;
     this.dbg.onExceptionUnwind = undefined;
-    if (frame) {
-      frame.onStep = undefined;
-      frame.onPop = undefined;
-    }
+    this._clearSteppingHooks();
 
     // Clear DOM event breakpoints.
     // XPCShell tests don't use actual DOM windows for globals and cause
     // removeListenerForAllEvents to throw.
     if (!isWorker &&
         this.global &&
         !this.dbg.replaying &&
         !this.global.toString().includes("Sandbox")) {