Bug 1131609 - getOriginalLocation should take a sourceActor;r=jlong
authorEddy Bruël <ejpbruel@gmail.com>
Thu, 12 Feb 2015 05:40:52 +0100
changeset 242531 7462142c132229a8c68b296ac8db769b5bdf6391
parent 242530 8e3476364f4c0eb4ae377e61d88bf51153fbb556
child 242532 2338f0e2a5203def18f021936dffffb40239496f
push id660
push usermichael.l.comella@gmail.com
push dateThu, 12 Feb 2015 18:55:31 +0000
reviewersjlong
bugs1131609
milestone38.0a1
Bug 1131609 - getOriginalLocation should take a sourceActor;r=jlong
toolkit/devtools/server/actors/script.js
toolkit/devtools/server/actors/tracer.js
--- a/toolkit/devtools/server/actors/script.js
+++ b/toolkit/devtools/server/actors/script.js
@@ -737,17 +737,17 @@ ThreadActor.prototype = {
   _pauseAndRespond: function (aFrame, aReason, onPacket=function (k) { return k; }) {
     try {
       let packet = this._paused(aFrame);
       if (!packet) {
         return undefined;
       }
       packet.why = aReason;
 
-      let loc = getFrameLocation(aFrame);
+      let loc = this.sources.getFrameLocation(aFrame);
       this.sources.getOriginalLocation(loc).then(aOrigPosition => {
         if (!aOrigPosition.sourceActor) {
           // The only time the source actor will be null is if there
           // was a sourcemap and it tried to look up the original
           // location but there was no original URL. This is a strange
           // scenario so we simply don't pause.
           DevToolsUtils.reportException(
             'ThreadActor',
@@ -800,32 +800,32 @@ ThreadActor.prototype = {
     return {
       error: "notImplemented",
       message: "forced completion is not yet implemented."
     };
   },
 
   _makeOnEnterFrame: function ({ pauseAndRespond }) {
     return aFrame => {
-      const generatedLocation = getFrameLocation(aFrame);
+      const generatedLocation = this.sources.getFrameLocation(aFrame);
       let { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
         generatedLocation));
       let url = sourceActor.url;
 
       return this.sources.isBlackBoxed(url)
         ? undefined
         : pauseAndRespond(aFrame);
     };
   },
 
   _makeOnPop: function ({ thread, pauseAndRespond, createValueGrip }) {
     return function (aCompletion) {
       // onPop is called with 'this' set to the current frame.
 
-      const generatedLocation = getFrameLocation(this);
+      const generatedLocation = thread.sources.getFrameLocation(this);
       const { sourceActor } = thread.synchronize(thread.sources.getOriginalLocation(
         generatedLocation));
       const url = sourceActor.url;
 
       if (thread.sources.isBlackBoxed(url)) {
         return undefined;
       }
 
@@ -857,17 +857,17 @@ ThreadActor.prototype = {
         return pauseAndRespond(this);
       };
     }
 
     // Otherwise take what a "step" means into consideration.
     return function () {
       // onStep is called with 'this' set to the current frame.
 
-      const generatedLocation = getFrameLocation(this);
+      const generatedLocation = thread.sources.getFrameLocation(this);
       const newLocation = thread.synchronize(thread.sources.getOriginalLocation(
         generatedLocation));
 
       // Cases when we should pause because we have executed enough to consider
       // a "step" to have occured:
       //
       // 1.1. We change frames.
       // 1.2. We change URLs (can happen without changing frames thanks to
@@ -937,17 +937,17 @@ ThreadActor.prototype = {
    */
   _handleResumeLimit: function (aRequest) {
     let steppingType = aRequest.resumeLimit.type;
     if (["break", "step", "next", "finish"].indexOf(steppingType) == -1) {
       return reject({ error: "badParameterType",
                       message: "Unknown resumeLimit type" });
     }
 
-    const generatedLocation = getFrameLocation(this.youngestFrame);
+    const generatedLocation = this.sources.getFrameLocation(this.youngestFrame);
     return this.sources.getOriginalLocation(generatedLocation)
       .then(originalLocation => {
         const { onEnterFrame, onPop, onStep } = this._makeSteppingHooks(originalLocation,
                                                                         steppingType);
 
         // Make sure there is still a frame on the stack if we are to continue
         // stepping.
         let stepFrame = this._getNextStepFrame(this.youngestFrame);
@@ -1284,17 +1284,17 @@ ThreadActor.prototype = {
     let frames = [];
     let promises = [];
     for (; frame && (!count || i < (start + count)); i++, frame=frame.older) {
       let form = this._createFrameActor(frame).form();
       form.depth = i;
       frames.push(form);
 
       let promise = this.sources.getOriginalLocation({
-        source: frame.script.source,
+        sourceActor: this.sources.createNonSourceMappedActor(frame.script.source),
         line: form.where.line,
         column: form.where.column
       }).then((aOrigLocation) => {
         let sourceForm = aOrigLocation.sourceActor.form();
         form.where = {
           source: sourceForm,
           line: aOrigLocation.line,
           column: aOrigLocation.column
@@ -1897,17 +1897,17 @@ ThreadActor.prototype = {
    * executed in the specified frame.
    *
    * @param aFrame Debugger.Frame
    *        The stack frame that contained the debugger statement.
    */
   onDebuggerStatement: function (aFrame) {
     // Don't pause if we are currently stepping (in or over) or the frame is
     // black-boxed.
-    const generatedLocation = getFrameLocation(aFrame);
+    const generatedLocation = this.sources.getFrameLocation(aFrame);
     const { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
       generatedLocation));
     const url = sourceActor ? sourceActor.url : null;
 
     return this.sources.isBlackBoxed(url) || aFrame.onStep
       ? undefined
       : this._pauseAndRespond(aFrame, { type: "debuggerStatement" });
   },
@@ -1929,17 +1929,17 @@ ThreadActor.prototype = {
         break;
       }
     }
 
     if (willBeCaught && this._options.ignoreCaughtExceptions) {
       return undefined;
     }
 
-    const generatedLocation = getFrameLocation(aFrame);
+    const generatedLocation = this.sources.getFrameLocation(aFrame);
     const { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
       generatedLocation));
     const url = sourceActor ? sourceActor.url : null;
 
     if (this.sources.isBlackBoxed(url)) {
       return undefined;
     }
 
@@ -2951,17 +2951,17 @@ SourceActor.prototype = {
         setBreakpointOnEntryPoints(this.threadActor, actor, result.entryPoints);
         actualLocation = generatedLocation;
       }
     }
 
     return Promise.resolve().then(() => {
       if (actualLocation.sourceActor.source) {
         return this.threadActor.sources.getOriginalLocation({
-          source: actualLocation.sourceActor.source,
+          sourceActor: actualLocation.sourceActor,
           line: actualLocation.line,
           column: actualLocation.column
         });
       } else {
         return actualLocation;
       }
     }).then((actualLocation) => {
       let response = { actor: actor.actorID };
@@ -3325,17 +3325,17 @@ ObjectActor.prototype = {
       return {
         from: this.actorID,
         error: "noScript",
         message: this.actorID + " has no Debugger.Script"
       };
     }
 
     const generatedLocation = {
-      source: this.obj.script.source,
+      sourceActor: this.threadActor.sources.createNonSourceMappedActor(this.obj.script.source),
       line: this.obj.script.startLine,
       // TODO bug 901138: use Debugger.Script.prototype.startColumn.
       column: 0
     };
 
     return this.threadActor.sources.getOriginalLocation(generatedLocation)
       .then(({ sourceActor, line, column }) => {
 
@@ -4568,17 +4568,22 @@ FrameActor.prototype = {
         this.frame.environment,
         this.frameLifetimePool
       );
       form.environment = envActor.form();
     }
     form.this = threadActor.createValueGrip(this.frame.this);
     form.arguments = this._args();
     if (this.frame.script) {
-      form.where = getFrameLocation(this.frame);
+      var loc = this.threadActor.sources.getFrameLocation(this.frame);
+      form.where = {
+        source: loc.sourceActor.form(),
+        line: loc.line,
+        column: loc.column
+      };
     }
 
     if (!this.frame.older) {
       form.oldest = true;
     }
 
     return form;
   },
@@ -4704,17 +4709,17 @@ BreakpointActor.prototype = {
    * A function that the engine calls when a breakpoint has been hit.
    *
    * @param aFrame Debugger.Frame
    *        The stack frame that contained the breakpoint.
    */
   hit: function (aFrame) {
     // Don't pause if we are currently stepping (in or over) or the frame is
     // black-boxed.
-    let loc = getFrameLocation(aFrame);
+    let loc = this.threadActor.sources.getFrameLocation(aFrame);
     let { sourceActor } = this.threadActor.synchronize(
       this.threadActor.sources.getOriginalLocation(loc));
     let url = sourceActor.url;
 
     if (this.threadActor.sources.isBlackBoxed(url)
         || aFrame.onStep
         || !this.isValidCondition(aFrame)) {
       return undefined;
@@ -5532,23 +5537,46 @@ ThreadSources.prototype = {
     aSource.sourceMapURL = url;
 
     // Forcefully set the sourcemap cache. This will be used even if
     // sourcemaps are disabled.
     this._sourceMapCache[url] = resolve(aMap);
   },
 
   /**
+   * Return the non-source-mapped location of the given Debugger.Frame. If the
+   * frame does not have a script, the location's properties are all null.
+   *
+   * @param Debugger.Frame aFrame
+   *        The frame whose location we are getting.
+   * @returns Object
+   *          Returns an object of the form { source, line, column }
+   */
+  getFrameLocation: function (aFrame) {
+    if (!aFrame || !aFrame.script) {
+      return { sourceActor: null, line: null, column: null };
+    }
+    return {
+      sourceActor: this.createNonSourceMappedActor(aFrame.script.source),
+      line: aFrame.script.getOffsetLine(aFrame.offset),
+      column: getOffsetColumn(aFrame.offset, aFrame.script)
+    }
+  },
+
+  /**
    * Returns a promise of the location in the original source if the source is
    * source mapped, otherwise a promise of the same location. This can
    * be called with a source from *any* Debugger instance and we make
    * sure to that it works properly, reusing source maps if already
    * fetched. Use this from any actor that needs sourcemapping.
    */
-  getOriginalLocation: function ({ source, line, column }) {
+  getOriginalLocation: function ({ sourceActor, line, column }) {
+    let source = sourceActor.source;
+    let url = source ? source.url : sourceActor._originalUrl;
+
     // In certain scenarios the source map may have not been fetched
     // yet (or at least tied to this Debugger.Source instance), so use
     // `fetchSourceMap` instead of `getSourceMap`. This allows this
     // function to be called from anywere (across debuggers) and it
     // should just automatically work.
     return this.fetchSourceMap(source).then(sm => {
       if (sm) {
         let {
@@ -5577,18 +5605,18 @@ ThreadSources.prototype = {
           line: sourceLine,
           column: sourceCol,
           name: sourceName
         };
       }
 
       // No source map
       return resolve({
-        sourceActor: this.createNonSourceMappedActor(source),
-        url: source.url,
+        sourceActor: sourceActor,
+        url: url,
         line: line,
         column: column
       });
     });
   },
 
   /**
    * Returns a promise of the location in the generated source corresponding to
@@ -5733,36 +5761,16 @@ exports.ThreadSources = ThreadSources;
  * it's either internal or we don't support in the UI yet.
  */
 function isHiddenSource(aSource) {
   // Ignore the internal Function.prototype script
   return aSource.text === '() {\n}';
 }
 
 /**
- * Return the non-source-mapped location of the given Debugger.Frame. If the
- * frame does not have a script, the location's properties are all null.
- *
- * @param Debugger.Frame aFrame
- *        The frame whose location we are getting.
- * @returns Object
- *          Returns an object of the form { source, line, column }
- */
-function getFrameLocation(aFrame) {
-  if (!aFrame || !aFrame.script) {
-    return { source: null, line: null, column: null };
-  }
-  return {
-    source: aFrame.script.source,
-    line: aFrame.script.getOffsetLine(aFrame.offset),
-    column: getOffsetColumn(aFrame.offset, aFrame.script)
-  }
-}
-
-/**
  * Returns true if its argument is not null.
  */
 function isNotNull(aThing) {
   return aThing !== null;
 }
 
 /**
  * Report the given error in the error console and to stdout.
--- a/toolkit/devtools/server/actors/tracer.js
+++ b/toolkit/devtools/server/actors/tracer.js
@@ -335,17 +335,17 @@ TracerActor.prototype = {
           : "(" + aFrame.type + ")";
       let sourceMappedLocation;
 
       if (this._requestsForTraceType.name || this._requestsForTraceType.location) {
         if (aFrame.script) {
           let sources = this._parent.threadActor.sources;
 
           sourceMappedLocation = yield sources.getOriginalLocation({
-            source: aFrame.script.source,
+            sourceActor: sources.createNonSourceMappedActor(aFrame.script.source),
             url: aFrame.script.source.url,
             line: aFrame.script.startLine,
             // We should return the location of the start of the script, but
             // Debugger.Script does not provide complete start locations (bug
             // 901138). Instead, return the current offset (the location of the
             // first statement in the function).
             column: getOffsetColumn(aFrame.offset, aFrame.script)
           });