Bug 1131643 - Implement a Location object;r=jlong

This commit is contained in:
Eddy Bruël 2015-02-23 09:36:58 +01:00
parent e3c03410ef
commit b5d64e8bb1
4 changed files with 355 additions and 245 deletions

View File

@ -295,6 +295,133 @@ ActorPool.prototype = {
exports.ActorPool = ActorPool;
/**
* An OriginalLocation represents a location in an original source.
*
* @param SourceActor actor
* A SourceActor representing an original source.
* @param Number line
* A line within the given source.
* @param Number column
* A column within the given line.
* @param String name
* The name of the symbol corresponding to this OriginalLocation.
*/
function OriginalLocation(actor, line, column, name) {
this._connection = actor ? actor.conn : null;
this._actorID = actor ? actor.actorID : undefined;
this._line = line;
this._column = column;
this._name = name;
}
OriginalLocation.fromGeneratedLocation = function (generatedLocation) {
return new OriginalLocation(
generatedLocation.generatedSourceActor,
generatedLocation.generatedLine,
generatedLocation.generatedColumn
);
};
OriginalLocation.prototype = {
get originalSourceActor() {
return this._connection ? this._connection.getActor(this._actorID) : null;
},
get originalUrl() {
let actor = this.originalSourceActor;
let source = actor.source;
return source ? source.url : actor._originalUrl;
},
get originalLine() {
return this._line;
},
get originalColumn() {
return this._column;
},
get originalName() {
return this._name;
},
get generatedSourceActor() {
throw new Error("Shouldn't access generatedSourceActor from an OriginalLocation");
},
get generatedLine() {
throw new Error("Shouldn't access generatedLine from an OriginalLocation");
},
get generatedColumn() {
throw new Error("Shouldn't access generatedColumn from an Originallocation");
}
};
exports.OriginalLocation = OriginalLocation;
/**
* A GeneratedLocation represents a location in an original source.
*
* @param SourceActor actor
* A SourceActor representing a generated source.
* @param Number line
* A line within the given source.
* @param Number column
* A column within the given line.
*/
function GeneratedLocation(actor, line, column) {
this._connection = actor ? actor.conn : null;
this._actorID = actor ? actor.actorID : undefined;
this._line = line;
this._column = column;
}
GeneratedLocation.fromOriginalLocation = function (originalLocation) {
return new GeneratedLocation(
originalLocation.originalSourceActor,
originalLocation.originalLine,
originalLocation.originalColumn
);
};
GeneratedLocation.prototype = {
get originalSourceActor() {
throw new Error();
},
get originalUrl() {
throw new Error("Shouldn't access originalUrl from a GeneratedLocation");
},
get originalLine() {
throw new Error("Shouldn't access originalLine from a GeneratedLocation");
},
get originalColumn() {
throw new Error("Shouldn't access originalColumn from a GeneratedLocation");
},
get originalName() {
throw new Error("Shouldn't access originalName from a GeneratedLocation");
},
get generatedSourceActor() {
return this._connection ? this._connection.getActor(this._actorID) : null;
},
get generatedLine() {
return this._line;
},
get generatedColumn() {
return this._column;
}
};
exports.GeneratedLocation = GeneratedLocation;
// TODO bug 863089: use Debugger.Script.prototype.getOffsetColumn when it is
// implemented.
exports.getOffsetColumn = function getOffsetColumn(aOffset, aScript) {

View File

@ -8,7 +8,7 @@
const Services = require("Services");
const { Cc, Ci, Cu, components, ChromeWorker } = require("chrome");
const { ActorPool, getOffsetColumn } = require("devtools/server/actors/common");
const { ActorPool, OriginalLocation, GeneratedLocation, getOffsetColumn } = require("devtools/server/actors/common");
const { DebuggerServer } = require("devtools/server/main");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const { dbg_assert, dumpn, update, fetch } = DevToolsUtils;
@ -75,28 +75,23 @@ function BreakpointActorMap() {
BreakpointActorMap.prototype = {
/**
* Return the number of instances of BreakpointActor in this instance of
* BreakpointActorMap.
* Return the number of BreakpointActors in this BreakpointActorMap.
*
* @returns Number
* The number of instances of BreakpointACtor in this instance of
* BreakpointActorMap.
* The number of BreakpointActor in this BreakpointActorMap.
*/
get size() {
return this._size;
},
/**
* Generate all instances of BreakpointActor that match the given query in
* this instance of BreakpointActorMap.
* Generate all BreakpointActors that match the given location in
* this BreakpointActorMap.
*
* @param Object query
* An optional object with the following properties:
* - source (optional)
* - line (optional, requires source)
* - column (optional, requires line)
* @param GeneratedLocation location
* The location for which matching BreakpointActors should be generated.
*/
findActors: function* (query = {}) {
findActors: function* (location = new GeneratedLocation()) {
function* findKeys(object, key) {
if (key !== undefined) {
if (key in object) {
@ -110,9 +105,12 @@ BreakpointActorMap.prototype = {
}
}
query.sourceActorID = query.sourceActor ? query.sourceActor.actorID : undefined;
query.beginColumn = query.column ? query.column : undefined;
query.endColumn = query.column ? query.column + 1 : undefined;
let query = {
sourceActorID: location.generatedSourceActor ? location.generatedSourceActor.actorID : undefined,
line: location.generatedLine,
beginColumn: location.generatedColumn ? location.generatedColumn : undefined,
endColumn: location.generatedColumn ? location.generatedColumn + 1 : undefined
};
for (let sourceActorID of findKeys(this._actors, query.sourceActorID))
for (let line of findKeys(this._actors[sourceActorID], query.line))
@ -123,17 +121,14 @@ BreakpointActorMap.prototype = {
},
/**
* Return the instance of BreakpointActor at the given location in this
* instance of BreakpointActorMap.
* Return the BreakpointActor at the given location in this
* BreakpointActorMap.
*
* @param Object location
* An object with the following properties:
* - source
* - line
* - column (optional)
* @param GeneratedLocation location
* The location for which the BreakpointActor should be returned.
*
* @returns BreakpointActor actor
* The instance of BreakpointActor at the given location.
* The BreakpointActor at the given location.
*/
getActor: function (location) {
for (let actor of this.findActors(location)) {
@ -144,24 +139,22 @@ BreakpointActorMap.prototype = {
},
/**
* Set the given instance of BreakpointActor to the given location in this
* instance of BreakpointActorMap.
* Set the given BreakpointActor to the given location in this
* BreakpointActorMap.
*
* @param Object location
* An object with the following properties:
* - source
* - line
* - column (optional)
* @param GeneratedLocation location
* The location to which the given BreakpointActor should be set.
*
* @param BreakpointActor actor
* The instance of BreakpointActor to be set to the given location.
* The BreakpointActor to be set to the given location.
*/
setActor: function (location, actor) {
let { sourceActor, line, column } = location;
let { generatedSourceActor, generatedLine, generatedColumn } = location;
let sourceActorID = sourceActor.actorID;
let beginColumn = column ? column : 0;
let endColumn = column ? column + 1 : Infinity;
let sourceActorID = generatedSourceActor.actorID;
let line = generatedLine;
let beginColumn = generatedColumn ? generatedColumn : 0;
let endColumn = generatedColumn ? generatedColumn + 1 : Infinity;
if (!this._actors[sourceActorID]) {
this._actors[sourceActorID] = [];
@ -179,21 +172,19 @@ BreakpointActorMap.prototype = {
},
/**
* Delete the instance of BreakpointActor from the given location in this
* instance of BreakpointActorMap.
* Delete the BreakpointActor from the given location in this
* BreakpointActorMap.
*
* @param Object location
* An object with the following properties:
* - source
* - line
* - column (optional)
* @param GeneratedLocation location
* The location from which the BreakpointActor should be deleted.
*/
deleteActor: function (location) {
let { sourceActor, line, column } = location;
let { generatedSourceActor, generatedLine, generatedColumn } = location;
let sourceActorID = sourceActor.actorID;
let beginColumn = column ? column : 0;
let endColumn = column ? column + 1 : Infinity;
let sourceActorID = generatedSourceActor.actorID;
let line = generatedLine;
let beginColumn = generatedColumn ? generatedColumn : 0;
let endColumn = generatedColumn ? generatedColumn + 1 : Infinity;
if (this._actors[sourceActorID]) {
if (this._actors[sourceActorID][line]) {
@ -742,9 +733,10 @@ ThreadActor.prototype = {
}
packet.why = aReason;
let loc = this.sources.getFrameLocation(aFrame);
this.sources.getOriginalLocation(loc).then(aOrigPosition => {
if (!aOrigPosition.sourceActor) {
let generatedLocation = this.sources.getFrameLocation(aFrame);
this.sources.getOriginalLocation(generatedLocation)
.then((originalLocation) => {
if (!originalLocation.originalSourceActor) {
// 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
@ -759,9 +751,9 @@ ThreadActor.prototype = {
}
packet.frame.where = {
source: aOrigPosition.sourceActor.form(),
line: aOrigPosition.line,
column: aOrigPosition.column
source: originalLocation.originalSourceActor.form(),
line: originalLocation.originalLine,
column: originalLocation.originalColumn
};
resolve(onPacket(packet))
.then(null, error => {
@ -806,9 +798,9 @@ ThreadActor.prototype = {
_makeOnEnterFrame: function ({ pauseAndRespond }) {
return aFrame => {
const generatedLocation = this.sources.getFrameLocation(aFrame);
let { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
let { originalSourceActor } = this.synchronize(this.sources.getOriginalLocation(
generatedLocation));
let url = sourceActor.url;
let url = originalSourceActor.url;
return this.sources.isBlackBoxed(url)
? undefined
@ -821,9 +813,9 @@ ThreadActor.prototype = {
// onPop is called with 'this' set to the current frame.
const generatedLocation = thread.sources.getFrameLocation(this);
const { sourceActor } = thread.synchronize(thread.sources.getOriginalLocation(
const { originalSourceActor } = thread.synchronize(thread.sources.getOriginalLocation(
generatedLocation));
const url = sourceActor.url;
const url = originalSourceActor.url;
if (thread.sources.isBlackBoxed(url)) {
return undefined;
@ -882,15 +874,15 @@ ThreadActor.prototype = {
// 2.2. The source we are in is black boxed.
// Cases 2.1 and 2.2
if (newLocation.url == null
|| thread.sources.isBlackBoxed(newLocation.url)) {
if (newLocation.originalUrl == null
|| thread.sources.isBlackBoxed(newLocation.originalUrl)) {
return undefined;
}
// Cases 1.1, 1.2 and 1.3
if (this !== startFrame
|| startLocation.url !== newLocation.url
|| startLocation.line !== newLocation.line) {
|| startLocation.originalUrl !== newLocation.originalUrl
|| startLocation.originalLine !== newLocation.originalLine) {
return pauseAndRespond(this);
}
@ -1288,16 +1280,16 @@ ThreadActor.prototype = {
form.depth = i;
frames.push(form);
let promise = this.sources.getOriginalLocation({
sourceActor: this.sources.createNonSourceMappedActor(frame.script.source),
line: form.where.line,
column: form.where.column
}).then((aOrigLocation) => {
let sourceForm = aOrigLocation.sourceActor.form();
let promise = this.sources.getOriginalLocation(new GeneratedLocation(
this.sources.createNonSourceMappedActor(frame.script.source),
form.where.line,
form.where.column
)).then((originalLocation) => {
let sourceForm = originalLocation.originalSourceActor.form();
form.where = {
source: sourceForm,
line: aOrigLocation.line,
column: aOrigLocation.column
line: originalLocation.originalLine,
column: originalLocation.originalColumn
};
form.source = sourceForm;
});
@ -1903,9 +1895,9 @@ ThreadActor.prototype = {
// Don't pause if we are currently stepping (in or over) or the frame is
// black-boxed.
const generatedLocation = this.sources.getFrameLocation(aFrame);
const { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
const { originalSourceActor } = this.synchronize(this.sources.getOriginalLocation(
generatedLocation));
const url = sourceActor ? sourceActor.url : null;
const url = originalSourceActor ? originalSourceActor.url : null;
return this.sources.isBlackBoxed(url) || aFrame.onStep
? undefined
@ -2039,8 +2031,8 @@ ThreadActor.prototype = {
let source = this.sources.createNonSourceMappedActor(aScript.source);
for (let bpActor of this.breakpointActorMap.findActors({ sourceActor: source })) {
// Limit the search to the line numbers contained in the new script.
if (bpActor.generatedLocation.line >= aScript.startLine
&& bpActor.generatedLocation.line <= endLine) {
if (bpActor.generatedLocation.generatedLine >= aScript.startLine
&& bpActor.generatedLocation.generatedLine <= endLine) {
source.setBreakpointForActor(bpActor);
}
}
@ -2751,12 +2743,14 @@ SourceActor.prototype = {
* @returns Object
* The RDP response.
*/
_setBreakpointAtColumn: function (scripts, location, actor) {
_setBreakpointAtColumn: function (scripts, generatedLocation, actor) {
// Debugger.Script -> array of offset mappings
const scriptsAndOffsetMappings = new Map();
for (let script of scripts) {
this._findClosestOffsetMappings(location, script, scriptsAndOffsetMappings);
this._findClosestOffsetMappings(generatedLocation,
script,
scriptsAndOffsetMappings);
}
for (let [script, mappings] of scriptsAndOffsetMappings) {
@ -2832,18 +2826,13 @@ SourceActor.prototype = {
* A condition for the breakpoint.
*/
setBreakpoint: function (originalLine, originalColumn, condition) {
let originalLocation = {
sourceActor: this,
line: originalLine,
column: originalColumn
};
let originalLocation = new OriginalLocation(this, originalLine, originalColumn);
return this.threadActor.sources.getGeneratedLocation(originalLocation)
.then(generatedLocation => {
let actor = this._getOrCreateBreakpointActor(originalLocation,
generatedLocation,
condition);
return generatedLocation.sourceActor.setBreakpointForActor(actor);
return generatedLocation.generatedSourceActor.setBreakpointForActor(actor);
});
},
@ -2857,13 +2846,13 @@ SourceActor.prototype = {
*/
setBreakpointForActor: function (actor) {
let originalLocation = actor.originalLocation;
let generatedLocation = {
sourceActor: this,
line: actor.generatedLocation.line,
column: actor.generatedLocation.column
};
let generatedLocation = new GeneratedLocation(
this,
actor.generatedLocation.generatedLine,
actor.generatedLocation.generatedColumn
);
let { line: generatedLine, column: generatedColumn } = generatedLocation;
let { generatedLine, generatedColumn } = generatedLocation;
// Find all scripts matching the given location. We will almost always have
// a `source` object to query, but multiple inline HTML scripts are all
@ -2889,13 +2878,13 @@ SourceActor.prototype = {
// handler.
scripts = scripts.filter((script) => !actor.hasScript(script));
let actualLocation;
let actualGeneratedLocation;
// If generatedColumn is something other than 0, assume this is a column
// breakpoint and do not perform breakpoint sliding.
if (generatedColumn) {
this._setBreakpointAtColumn(scripts, generatedLocation, actor);
actualLocation = generatedLocation;
actualGeneratedLocation = generatedLocation;
} else {
let result;
if (actor.scripts.size === 0) {
@ -2925,53 +2914,49 @@ SourceActor.prototype = {
}
if (result.line !== generatedLine) {
actualLocation = {
sourceActor: generatedLocation.sourceActor,
line: result.line,
column: generatedLocation.column
};
actualGeneratedLocation = new GeneratedLocation(
generatedLocation.generatedSourceActor,
result.line,
generatedLocation.generatedColumn
);
// Check whether we already have a breakpoint actor for the actual
// location. If we do have an existing actor, then the actor we created
// above is redundant and must be destroyed. If we do not have an existing
// actor, we need to update the breakpoint store with the new location.
let existingActor = this.breakpointActorMap.getActor(actualLocation);
let existingActor = this.breakpointActorMap.getActor(actualGeneratedLocation);
if (existingActor) {
actor.onDelete();
this.breakpointActorMap.deleteActor(generatedLocation);
actor = existingActor;
} else {
actor.generatedLocation = actualLocation;
actor.generatedLocation = actualGeneratedLocation;
this.breakpointActorMap.deleteActor(generatedLocation);
this.breakpointActorMap.setActor(actualLocation, actor);
this.breakpointActorMap.setActor(actualGeneratedLocation, actor);
setBreakpointOnEntryPoints(this.threadActor, actor, result.entryPoints);
}
} else {
setBreakpointOnEntryPoints(this.threadActor, actor, result.entryPoints);
actualLocation = generatedLocation;
actualGeneratedLocation = generatedLocation;
}
}
return Promise.resolve().then(() => {
if (actualLocation.sourceActor.source) {
return this.threadActor.sources.getOriginalLocation({
sourceActor: actualLocation.sourceActor,
line: actualLocation.line,
column: actualLocation.column
});
if (actualGeneratedLocation.generatedSourceActor.source) {
return this.threadActor.sources.getOriginalLocation(actualGeneratedLocation);
} else {
return actualLocation;
return OriginalLocation.fromGeneratedLocation(actualGeneratedLocation);
}
}).then((actualLocation) => {
}).then((actualOriginalLocation) => {
let response = { actor: actor.actorID };
if (actualLocation.sourceActor.url !== originalLocation.sourceActor.url ||
actualLocation.line !== originalLocation.line)
if (actualOriginalLocation.originalSourceActor.url !== originalLocation.originalSourceActor.url ||
actualOriginalLocation.originalLine !== originalLocation.originalLine)
{
response.actualLocation = {
source: actualLocation.sourceActor.form(),
line: actualLocation.line,
column: actualLocation.column
source: actualOriginalLocation.originalSourceActor.form(),
line: actualOriginalLocation.originalLine,
column: actualOriginalLocation.originalColumn
};
}
return response;
@ -3019,7 +3004,7 @@ SourceActor.prototype = {
aScript,
aScriptsAndOffsetMappings) {
let offsetMappings = aScript.getAllColumnOffsets()
.filter(({ lineNumber }) => lineNumber === aTargetLocation.line);
.filter(({ lineNumber }) => lineNumber === aTargetLocation.generatedLine);
// Attempt to find the current closest offset distance from the target
// location by grabbing any offset mapping in the map by doing one iteration
@ -3028,13 +3013,13 @@ SourceActor.prototype = {
let closestDistance = Infinity;
if (aScriptsAndOffsetMappings.size) {
for (let mappings of aScriptsAndOffsetMappings.values()) {
closestDistance = Math.abs(aTargetLocation.column - mappings[0].columnNumber);
closestDistance = Math.abs(aTargetLocation.generatedColumn - mappings[0].columnNumber);
break;
}
}
for (let mapping of offsetMappings) {
let currentDistance = Math.abs(aTargetLocation.column - mapping.columnNumber);
let currentDistance = Math.abs(aTargetLocation.generatedColumn - mapping.columnNumber);
if (currentDistance > closestDistance) {
continue;
@ -3329,23 +3314,17 @@ ObjectActor.prototype = {
};
}
const generatedLocation = {
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 }) => {
return {
from: this.actorID,
source: sourceActor.form(),
line: line,
column: column
};
});
return this.threadActor.sources.getOriginalLocation(new GeneratedLocation(
this.threadActor.sources.createNonSourceMappedActor(this.obj.script.source),
this.obj.script.startLine,
0 // TODO bug 901138: use Debugger.Script.prototype.startColumn
)).then((originalLocation) => {
return {
source: originalLocation.originalSourceActor.form(),
line: originalLocation.originalLine,
column: originalLocation.originalColumn
};
});
},
/**
@ -4573,11 +4552,11 @@ FrameActor.prototype = {
form.this = threadActor.createValueGrip(this.frame.this);
form.arguments = this._args();
if (this.frame.script) {
var loc = this.threadActor.sources.getFrameLocation(this.frame);
var generatedLocation = this.threadActor.sources.getFrameLocation(this.frame);
form.where = {
source: loc.sourceActor.form(),
line: loc.line,
column: loc.column
source: generatedLocation.generatedSourceActor.form(),
line: generatedLocation.generatedLine,
column: generatedLocation.generatedColumn
};
}
@ -4714,10 +4693,10 @@ BreakpointActor.prototype = {
hit: function (aFrame) {
// Don't pause if we are currently stepping (in or over) or the frame is
// black-boxed.
let loc = this.threadActor.sources.getFrameLocation(aFrame);
let { sourceActor } = this.threadActor.synchronize(
this.threadActor.sources.getOriginalLocation(loc));
let url = sourceActor.url;
let generatedLocation = this.threadActor.sources.getFrameLocation(aFrame);
let { originalSourceActor } = this.threadActor.synchronize(
this.threadActor.sources.getOriginalLocation(generatedLocation));
let url = originalSourceActor.url;
if (this.threadActor.sources.isBlackBoxed(url)
|| aFrame.onStep
@ -5558,13 +5537,13 @@ ThreadSources.prototype = {
*/
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)
return new GeneratedLocation();
}
return new GeneratedLocation(
this.createNonSourceMappedActor(aFrame.script.source),
aFrame.script.getOffsetLine(aFrame.offset),
getOffsetColumn(aFrame.offset, aFrame.script)
);
},
/**
@ -5574,53 +5553,52 @@ ThreadSources.prototype = {
* sure to that it works properly, reusing source maps if already
* fetched. Use this from any actor that needs sourcemapping.
*/
getOriginalLocation: function ({ sourceActor, line, column }) {
let source = sourceActor.source;
let url = source ? source.url : sourceActor._originalUrl;
getOriginalLocation: function (generatedLocation) {
let {
generatedSourceActor,
generatedLine,
generatedColumn
} = generatedLocation;
let source = generatedSourceActor.source;
let url = source ? source.url : generatedSourceActor._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) {
return this.fetchSourceMap(source).then(map => {
if (map) {
let {
source: sourceUrl,
line: sourceLine,
column: sourceCol,
name: sourceName
} = sm.originalPositionFor({
line: line,
column: column == null ? Infinity : column
source: originalUrl,
line: originalLine,
column: originalColumn,
name: originalName
} = map.originalPositionFor({
line: generatedLine,
column: generatedColumn == null ? Infinity : generatedColumn
});
return {
// Since the `Debugger.Source` instance may come from a
// different `Debugger` instance (any actor can call this
// method), we can't rely on any of the source discovery
// setup (`_discoverSources`, etc) to have been run yet. So
// we have to assume that the actor may not already exist,
// and we might need to create it, so use `source` and give
// it the required parameters for a sourcemapped source.
sourceActor: (!sourceUrl) ? null : this.source({
originalUrl: sourceUrl,
// Since the `Debugger.Source` instance may come from a
// different `Debugger` instance (any actor can call this
// method), we can't rely on any of the source discovery
// setup (`_discoverSources`, etc) to have been run yet. So
// we have to assume that the actor may not already exist,
// and we might need to create it, so use `source` and give
// it the required parameters for a sourcemapped source.
return new OriginalLocation(
originalUrl ? this.source({
originalUrl: originalUrl,
generatedSource: source
}),
url: sourceUrl,
line: sourceLine,
column: sourceCol,
name: sourceName
};
}) : null,
originalLine,
originalColumn,
originalName
);
}
// No source map
return resolve({
sourceActor: sourceActor,
url: url,
line: line,
column: column
});
return OriginalLocation.fromGeneratedLocation(generatedLocation);
});
},
@ -5633,34 +5611,40 @@ ThreadSources.prototype = {
* the tables this function uses; thus, it won't know that S's original
* source URLs map to S until P is resolved.
*/
getGeneratedLocation: function ({ sourceActor, line, column }) {
getGeneratedLocation: function (originalLocation) {
let { originalSourceActor } = originalLocation;
// Both original sources and normal sources could have sourcemaps,
// because normal sources can be pretty-printed which generates a
// sourcemap for itself. Check both of the source properties to make it work
// for both kinds of sources.
let source = sourceActor.generatedSource || sourceActor.source;
let source = originalSourceActor.source || originalSourceActor.generatedSource;
// See comment about `fetchSourceMap` in `getOriginalLocation`.
return this.fetchSourceMap(source).then(sm => {
if (sm) {
let { line: genLine, column: genColumn } = sm.generatedPositionFor({
source: sourceActor.url,
line: line,
column: column == null ? Infinity : column
return this.fetchSourceMap(source).then((map) => {
if (map) {
let {
originalLine,
originalColumn
} = originalLocation;
let {
line: generatedLine,
column: generatedColumn
} = map.generatedPositionFor({
source: originalSourceActor.url,
line: originalLine,
column: originalColumn == null ? Infinity : originalColumn
});
return {
sourceActor: this.createNonSourceMappedActor(source),
line: genLine,
column: genColumn
};
return new GeneratedLocation(
this.createNonSourceMappedActor(source),
generatedLine,
generatedColumn
);
}
return resolve({
sourceActor: sourceActor,
line: line,
column: column
});
return GeneratedLocation.fromOriginalLocation(originalLocation);
});
},

View File

@ -8,7 +8,7 @@ const { Cu } = require("chrome");
const { DebuggerServer } = require("devtools/server/main");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const Debugger = require("Debugger");
const { getOffsetColumn } = require("devtools/server/actors/common");
const { GeneratedLocation, getOffsetColumn } = require("devtools/server/actors/common");
const promise = require("promise");
Cu.import("resource://gre/modules/Task.jsm");
@ -339,25 +339,25 @@ TracerActor.prototype = {
if (aFrame.script) {
let sources = this._parent.threadActor.sources;
sourceMappedLocation = yield sources.getOriginalLocation({
sourceActor: sources.createNonSourceMappedActor(aFrame.script.source),
url: aFrame.script.source.url,
line: aFrame.script.startLine,
sourceMappedLocation = yield sources.getOriginalLocation(new GeneratedLocation(
sources.createNonSourceMappedActor(aFrame.script.source),
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)
});
getOffsetColumn(aFrame.offset, aFrame.script)
));
}
}
if (this._requestsForTraceType.name) {
if (sourceMappedLocation && sourceMappedLocation.name) {
packet.name = sourceMappedLocation.name;
if (sourceMappedLocation && sourceMappedLocation.originalName) {
packet.name = sourceMappedLocation.originalName;
} else {
packet.name = name;
}
packet.name = name;
}
if (this._requestsForTraceType.location) {
@ -365,10 +365,9 @@ TracerActor.prototype = {
// Don't copy sourceMappedLocation directly because it
// contains a reference to the source actor
packet.location = {
url: sourceMappedLocation.url,
line: sourceMappedLocation.line,
column: sourceMappedLocation.column,
name: sourceMappedLocation.name
url: sourceMappedLocation.originalUrl,
line: sourceMappedLocation.originalLine,
column: sourceMappedLocation.originalColumn
};
}
}

View File

@ -21,13 +21,13 @@ function run_test()
function test_get_actor() {
let bpStore = new BreakpointActorMap();
let location = {
sourceActor: { actor: 'actor1' },
line: 3
generatedSourceActor: { actor: 'actor1' },
generatedLine: 3
};
let columnLocation = {
sourceActor: { actor: 'actor2' },
line: 5,
column: 15
generatedSourceActor: { actor: 'actor2' },
generatedLine: 5,
generatedColumn: 15
};
// Shouldn't have breakpoint
@ -59,9 +59,9 @@ function test_set_actor() {
// Breakpoint with column
let bpStore = new BreakpointActorMap();
let location = {
sourceActor: { actor: 'actor1' },
line: 10,
column: 9
generatedSourceActor: { actor: 'actor1' },
generatedLine: 10,
generatedColumn: 9
};
bpStore.setActor(location, {});
do_check_true(!!bpStore.getActor(location),
@ -69,8 +69,8 @@ function test_set_actor() {
// Breakpoint without column (whole line breakpoint)
location = {
sourceActor: { actor: 'actor2' },
line: 103
generatedSourceActor: { actor: 'actor2' },
generatedLine: 103
};
bpStore.setActor(location, {});
do_check_true(!!bpStore.getActor(location),
@ -81,9 +81,9 @@ function test_delete_actor() {
// Breakpoint with column
let bpStore = new BreakpointActorMap();
let location = {
sourceActor: { actor: 'actor1' },
line: 10,
column: 9
generatedSourceActor: { actor: 'actor1' },
generatedLine: 10,
generatedColumn: 9
};
bpStore.setActor(location, {});
bpStore.deleteActor(location);
@ -92,8 +92,8 @@ function test_delete_actor() {
// Breakpoint without column (whole line breakpoint)
location = {
sourceActor: { actor: 'actor2' },
line: 103
generatedSourceActor: { actor: 'actor2' },
generatedLine: 103
};
bpStore.setActor(location, {});
bpStore.deleteActor(location);
@ -103,14 +103,14 @@ function test_delete_actor() {
function test_find_actors() {
let bps = [
{ sourceActor: { actor: "actor1" }, line: 10 },
{ sourceActor: { actor: "actor1" }, line: 10, column: 3 },
{ sourceActor: { actor: "actor1" }, line: 10, column: 10 },
{ sourceActor: { actor: "actor1" }, line: 23, column: 89 },
{ sourceActor: { actor: "actor2" }, line: 10, column: 1 },
{ sourceActor: { actor: "actor2" }, line: 20, column: 5 },
{ sourceActor: { actor: "actor2" }, line: 30, column: 34 },
{ sourceActor: { actor: "actor2" }, line: 40, column: 56 }
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 10 },
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 10, generatedColumn: 3 },
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 10, generatedColumn: 10 },
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 23, generatedColumn: 89 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 10, generatedColumn: 1 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 20, generatedColumn: 5 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 30, generatedColumn: 34 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 40, generatedColumn: 56 }
];
let bpStore = new BreakpointActorMap();
@ -130,8 +130,8 @@ function test_find_actors() {
// Breakpoints by URL
bpSet = new Set(bps.filter(bp => { return bp.sourceActor.actorID === "actor1" }));
for (let bp of bpStore.findActors({ sourceActor: { actorID: "actor1" } })) {
bpSet = new Set(bps.filter(bp => { return bp.generatedSourceActor.actorID === "actor1" }));
for (let bp of bpStore.findActors({ generatedSourceActor: { actorID: "actor1" } })) {
bpSet.delete(bp);
}
do_check_eq(bpSet.size, 0,
@ -139,15 +139,15 @@ function test_find_actors() {
// Breakpoints by URL and line
bpSet = new Set(bps.filter(bp => { return bp.sourceActor.actorID === "actor1" && bp.line === 10; }));
bpSet = new Set(bps.filter(bp => { return bp.generatedSourceActor.actorID === "actor1" && bp.generatedLine === 10; }));
let first = true;
for (let bp of bpStore.findActors({ sourceActor: { actorID: "actor1" }, line: 10 })) {
for (let bp of bpStore.findActors({ generatedSourceActor: { actorID: "actor1" }, generatedLine: 10 })) {
if (first) {
do_check_eq(bp.column, undefined,
do_check_eq(bp.generatedColumn, undefined,
"Should always get the whole line breakpoint first");
first = false;
} else {
do_check_neq(bp.column, undefined,
do_check_neq(bp.generatedColumn, undefined,
"Should not get the whole line breakpoint any time other than first.");
}
bpSet.delete(bp);
@ -161,9 +161,9 @@ function test_duplicate_actors() {
// Breakpoint with column
let location = {
sourceActor: { actorID: "foo-actor" },
line: 10,
column: 9
generatedSourceActor: { actorID: "foo-actor" },
generatedLine: 10,
generatedColumn: 9
};
bpStore.setActor(location, {});
bpStore.setActor(location, {});
@ -172,8 +172,8 @@ function test_duplicate_actors() {
// Breakpoint without column (whole line breakpoint)
location = {
sourceActor: { actorID: "foo-actor" },
line: 15
generatedSourceActor: { actorID: "foo-actor" },
generatedLine: 15
};
bpStore.setActor(location, {});
bpStore.setActor(location, {});