Commit df736d7d authored by podivilov@chromium.org's avatar podivilov@chromium.org
Browse files

Web Inspector: update call frame location when source mapping is changed.

https://bugs.webkit.org/show_bug.cgi?id=68997

Currently we use fake "debugger-paused" event hack to update execution line and call stack placards when source mapping is changed.
- add PresentationCallFrame.createPlacard method to create "live" placards that are updated on source mapping changes.
- remove PresentationCallFrame functionName, isInternalScript, and url getters.
- fire execution-line-changed event when selected call frame or source mapping is changed.

Reviewed by Pavel Feldman.

* inspector/compile-front-end.sh:
* inspector/front-end/CallStackSidebarPane.js:
(WebInspector.CallStackSidebarPane.prototype.update):
* inspector/front-end/CompilerSourceMapping.js:
(WebInspector.ClosureCompilerSourceMappingPayload):
(WebInspector.ClosureCompilerSourceMapping):
(WebInspector.ClosureCompilerSourceMapping.prototype._parseMappings):
* inspector/front-end/ContentProviders.js:
(WebInspector.CompilerSourceMappingContentProvider.prototype.requestContent):
(WebInspector.CompilerSourceMappingContentProvider.prototype.searchInContent):
* inspector/front-end/DebuggerPresentationModel.js:
(WebInspector.DebuggerPresentationModel):
(WebInspector.DebuggerPresentationModel.prototype.createPlacard.updatePlacard):
(WebInspector.DebuggerPresentationModel.prototype.createPlacard):
(WebInspector.DebuggerPresentationModel.prototype._debuggerPaused):
(WebInspector.DebuggerPresentationModel.prototype._debuggerResumed):
(WebInspector.DebuggerPresentationModel.prototype.set selectedCallFrame):
(WebInspector.DebuggerPresentationModel.prototype.get selectedCallFrame):
(WebInspector.DebuggerPresentationModel.prototype._dispatchExecutionLineChanged):
(WebInspector.DebuggerPresentationModel.prototype._debuggerReset):
(WebInspector.PresentationCallFrame):
(WebInspector.PresentationCallFrame.prototype.get rawSourceCode):
(WebInspector.PresentationCallFrame.prototype.uiLocation):
* inspector/front-end/ScriptsPanel.js:
(WebInspector.ScriptsPanel.prototype._debuggerPaused.else.didGetUILocation):
(WebInspector.ScriptsPanel.prototype._debuggerPaused):
(WebInspector.ScriptsPanel.prototype._executionLineChanged):
(WebInspector.ScriptsPanel.prototype._callFrameSelected):
* inspector/front-end/externs.js:
(WebInspector.displayNameForURL):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2078ccbc
2011-10-04 Pavel Podivilov <podivilov@chromium.org>
Web Inspector: update call frame location when source mapping is changed.
https://bugs.webkit.org/show_bug.cgi?id=68997
Currently we use fake "debugger-paused" event hack to update execution line and call stack placards when source mapping is changed.
- add PresentationCallFrame.createPlacard method to create "live" placards that are updated on source mapping changes.
- remove PresentationCallFrame functionName, isInternalScript, and url getters.
- fire execution-line-changed event when selected call frame or source mapping is changed.
Reviewed by Pavel Feldman.
* inspector/compile-front-end.sh:
* inspector/front-end/CallStackSidebarPane.js:
(WebInspector.CallStackSidebarPane.prototype.update):
* inspector/front-end/CompilerSourceMapping.js:
(WebInspector.ClosureCompilerSourceMappingPayload):
(WebInspector.ClosureCompilerSourceMapping):
(WebInspector.ClosureCompilerSourceMapping.prototype._parseMappings):
* inspector/front-end/ContentProviders.js:
(WebInspector.CompilerSourceMappingContentProvider.prototype.requestContent):
(WebInspector.CompilerSourceMappingContentProvider.prototype.searchInContent):
* inspector/front-end/DebuggerPresentationModel.js:
(WebInspector.DebuggerPresentationModel):
(WebInspector.DebuggerPresentationModel.prototype.createPlacard.updatePlacard):
(WebInspector.DebuggerPresentationModel.prototype.createPlacard):
(WebInspector.DebuggerPresentationModel.prototype._debuggerPaused):
(WebInspector.DebuggerPresentationModel.prototype._debuggerResumed):
(WebInspector.DebuggerPresentationModel.prototype.set selectedCallFrame):
(WebInspector.DebuggerPresentationModel.prototype.get selectedCallFrame):
(WebInspector.DebuggerPresentationModel.prototype._dispatchExecutionLineChanged):
(WebInspector.DebuggerPresentationModel.prototype._debuggerReset):
(WebInspector.PresentationCallFrame):
(WebInspector.PresentationCallFrame.prototype.get rawSourceCode):
(WebInspector.PresentationCallFrame.prototype.uiLocation):
* inspector/front-end/ScriptsPanel.js:
(WebInspector.ScriptsPanel.prototype._debuggerPaused.else.didGetUILocation):
(WebInspector.ScriptsPanel.prototype._debuggerPaused):
(WebInspector.ScriptsPanel.prototype._executionLineChanged):
(WebInspector.ScriptsPanel.prototype._callFrameSelected):
* inspector/front-end/externs.js:
(WebInspector.displayNameForURL):
2011-10-04 Pavel Feldman <pfeldman@chromium.org>
 
Not reviewed: inspector tests fix.
......@@ -44,7 +44,9 @@ java -jar ~/closure/compiler.jar --compilation_level SIMPLE_OPTIMIZATIONS --warn
--js Source/WebCore/inspector/front-end/Object.js \
--js Source/WebCore/inspector/front-end/Settings.js \
--js Source/WebCore/inspector/front-end/UserMetrics.js \
--module jsmodule_sdk:16:jsmodule_common \
--module jsmodule_sdk:18:jsmodule_common \
--js Source/WebCore/inspector/front-end/CompilerSourceMapping.js \
--js Source/WebCore/inspector/front-end/CompilerSourceMappingProvider.js \
--js Source/WebCore/inspector/front-end/ConsoleModel.js \
--js Source/WebCore/inspector/front-end/ContentProviders.js \
--js Source/WebCore/inspector/front-end/CookieParser.js \
......
......@@ -48,28 +48,9 @@ WebInspector.CallStackSidebarPane.prototype = {
for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var title = callFrame.functionName || WebInspector.UIString("(anonymous function)");
var subtitle;
if (!callFrame.isInternalScript)
subtitle = WebInspector.displayNameForURL(callFrame.url);
else
subtitle = WebInspector.UIString("(internal script)");
var placard = new WebInspector.Placard(title, subtitle);
var placard = this._model.createPlacard(callFrame);
placard.callFrame = callFrame;
placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false);
function didGetSourceLine(placard, uiSourceCode, lineNumber)
{
if (placard.subtitle)
placard.subtitle += ":" + (lineNumber + 1);
else
placard.subtitle = WebInspector.UIString("line %d", lineNumber + 1);
placard._text = WebInspector.UIString("%s() at %s", placard.title, placard.subtitle);
}
callFrame.sourceLine(didGetSourceLine.bind(this, placard));
this.placards.push(placard);
this.bodyElement.appendChild(placard.element);
}
......
......@@ -52,27 +52,37 @@ WebInspector.CompilerSourceMapping.prototype = {
}
}
/**
* @constructor
*/
WebInspector.ClosureCompilerSourceMappingPayload = function()
{
this.mappings = "";
this.sources = [];
}
/**
* Implements Source Map V3 consumer. See http://code.google.com/p/closure-compiler/wiki/SourceMaps
* for format description.
* @extends {WebInspector.CompilerSourceMapping}
* @constructor
* @param {WebInspector.ClosureCompilerSourceMappingPayload} mappingPayload
*/
WebInspector.ClosureCompilerSourceMapping = function(payload)
WebInspector.ClosureCompilerSourceMapping = function(mappingPayload)
{
if (!WebInspector.ClosureCompilerSourceMapping.prototype._base64Map) {
base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
WebInspector.ClosureCompilerSourceMapping.prototype._base64Map = {};
for (var i = 0; i < base64Digits.length; ++i)
WebInspector.ClosureCompilerSourceMapping.prototype._base64Map[base64Digits.charAt(i)] = i;
}
this._sources = payload.sources;
this._sources = mappingPayload.sources;
this._mappings = [];
this._reverseMappingsBySourceURL = {};
for (var i = 0; i < this._sources.length; ++i)
this._reverseMappingsBySourceURL[this._sources[i]] = [];
this._parseMappings(payload.mappings);
this._parseMappings(mappingPayload);
}
WebInspector.ClosureCompilerSourceMapping.prototype = {
......@@ -115,9 +125,9 @@ WebInspector.ClosureCompilerSourceMapping.prototype = {
return this._mappings[first];
},
_parseMappings: function(mappingsPayload)
_parseMappings: function(mappingPayload)
{
var stringCharIterator = new WebInspector.ClosureCompilerSourceMapping.StringCharIterator(mappingsPayload);
var stringCharIterator = new WebInspector.ClosureCompilerSourceMapping.StringCharIterator(mappingPayload.mappings);
var lineNumber = 0;
var columnNumber = 0;
......
......@@ -177,6 +177,11 @@ WebInspector.CompilerSourceMappingContentProvider.prototype = {
callback(this._mimeType, sourceCode);
}
this._compilerSourceMappingProvider.loadSourceCode(this._sourceURL, didLoadSourceCode.bind(this));
},
searchInContent: function(query, callback)
{
callback([]);
}
}
......
......@@ -38,7 +38,6 @@ WebInspector.DebuggerPresentationModel = function()
this._formatter = new WebInspector.ScriptFormatter();
this._rawSourceCode = {};
this._presentationCallFrames = [];
this._selectedCallFrameIndex = 0;
this._breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, this._breakpointAdded.bind(this), this._breakpointRemoved.bind(this), WebInspector.debuggerModel);
......@@ -63,7 +62,8 @@ WebInspector.DebuggerPresentationModel.Events = {
BreakpointRemoved: "breakpoint-removed",
DebuggerPaused: "debugger-paused",
DebuggerResumed: "debugger-resumed",
CallFrameSelected: "call-frame-selected"
CallFrameSelected: "call-frame-selected",
ExecutionLineChanged: "execution-line-changed"
}
WebInspector.DebuggerPresentationModel.prototype = {
......@@ -93,6 +93,24 @@ WebInspector.DebuggerPresentationModel.prototype = {
return anchor;
},
createPlacard: function(callFrame)
{
var title = callFrame._callFrame.functionName || WebInspector.UIString("(anonymous function)");
var placard = new WebInspector.Placard(title, "");
var rawSourceCode = callFrame._rawSourceCode;
function updatePlacard()
{
var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(callFrame._callFrame.location);
placard.subtitle = WebInspector.displayNameForURL(uiLocation.uiSourceCode.url) + ":" + (uiLocation.lineNumber + 1);
placard._text = WebInspector.UIString("%s() at %s", placard.title, placard.subtitle);
}
if (rawSourceCode.sourceMapping)
updatePlacard.call(this);
rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, updatePlacard, this);
return placard;
},
_parsedScriptSource: function(event)
{
this._addScript(event.data);
......@@ -354,35 +372,51 @@ WebInspector.DebuggerPresentationModel.prototype = {
this._presentationCallFrames = [];
for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var rawSourceCode;
var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.scriptId);
if (script)
rawSourceCode = this._rawSourceCodeForScript(script);
if (!script)
continue;
var rawSourceCode = this._rawSourceCodeForScript(script);
this._presentationCallFrames.push(new WebInspector.PresentationCallFrame(callFrame, i, this, rawSourceCode));
}
var details = WebInspector.debuggerModel.debuggerPausedDetails;
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, { callFrames: this._presentationCallFrames, details: details });
this.selectedCallFrame = this._presentationCallFrames[this._selectedCallFrameIndex];
this.selectedCallFrame = this._presentationCallFrames[0];
},
_debuggerResumed: function()
{
this._presentationCallFrames = [];
this._selectedCallFrameIndex = 0;
this.selectedCallFrame = null;
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed);
},
set selectedCallFrame(callFrame)
{
this._selectedCallFrameIndex = callFrame.index;
callFrame.select();
if (this._selectedCallFrame)
this._selectedCallFrame.rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._dispatchExecutionLineChanged, this);
this._selectedCallFrame = callFrame;
if (!this._selectedCallFrame)
return;
this._selectedCallFrame.rawSourceCode.forceUpdateSourceMapping();
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, callFrame);
if (this._selectedCallFrame.rawSourceCode.sourceMapping)
this._dispatchExecutionLineChanged(null);
this._selectedCallFrame.rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._dispatchExecutionLineChanged, this);
},
get selectedCallFrame()
{
return this._presentationCallFrames[this._selectedCallFrameIndex];
return this._selectedCallFrame;
},
_dispatchExecutionLineChanged: function(event)
{
var rawLocation = this._selectedCallFrame._callFrame.location;
var uiLocation = this._selectedCallFrame.rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation);
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ExecutionLineChanged, uiLocation);
},
/**
......@@ -417,9 +451,11 @@ WebInspector.DebuggerPresentationModel.prototype = {
_debuggerReset: function()
{
for (var id in this._rawSourceCode)
this._rawSourceCode[id].removeAllListeners();
this._rawSourceCode = {};
this._presentationCallFrames = [];
this._selectedCallFrameIndex = 0;
this._selectedCallFrame = null;
this._breakpointManager.debuggerReset();
}
}
......@@ -435,31 +471,14 @@ WebInspector.PresentationCallFrame = function(callFrame, index, model, rawSource
this._index = index;
this._model = model;
this._rawSourceCode = rawSourceCode;
this._script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.scriptId);
}
WebInspector.PresentationCallFrame.prototype = {
get functionName()
{
return this._callFrame.functionName;
},
get type()
{
return this._callFrame.type;
},
get isInternalScript()
{
return !this._script;
},
get url()
{
if (this._rawSourceCode && this._rawSourceCode.sourceMapping)
return this._rawSourceCode.sourceMapping.uiSourceCode.url;
},
get scopeChain()
{
return this._callFrame.scopeChain;
......@@ -475,10 +494,9 @@ WebInspector.PresentationCallFrame.prototype = {
return this._index;
},
select: function()
get rawSourceCode()
{
if (this._rawSourceCode)
this._rawSourceCode.forceUpdateSourceMapping();
return this._rawSourceCode;
},
evaluate: function(code, objectGroup, includeCommandLineAPI, returnByValue, callback)
......@@ -499,27 +517,17 @@ WebInspector.PresentationCallFrame.prototype = {
DebuggerAgent.evaluateOnCallFrame(this._callFrame.callFrameId, code, objectGroup, includeCommandLineAPI, returnByValue, didEvaluateOnCallFrame.bind(this));
},
sourceLine: function(callback)
uiLocation: function(callback)
{
var rawLocation = this._callFrame.location;
if (!this._rawSourceCode) {
callback(undefined, rawLocation.lineNumber);
return;
}
if (this._rawSourceCode.sourceMapping) {
var uiLocation = this._rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation);
callback(uiLocation.uiSourceCode, uiLocation.lineNumber);
return;
}
function sourceMappingUpdated()
function sourceMappingReady()
{
this._rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingUpdated, this);
var uiLocation = this._rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation);
callback(uiLocation.uiSourceCode, uiLocation.lineNumber);
this._rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingReady, this);
callback(this._rawSourceCode.sourceMapping.rawLocationToUILocation(this._callFrame.location));
}
this._rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingUpdated, this);
if (this._rawSourceCode.sourceMapping)
sourceMappingReady.call(this);
else
this._rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingReady, this);
}
}
......
......@@ -174,6 +174,7 @@ WebInspector.ScriptsPanel = function(presentationModel)
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, this._debuggerPaused, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed, this._debuggerResumed, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, this._callFrameSelected, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ExecutionLineChanged, this._executionLineChanged, this);
var enableDebugger = Preferences.debuggerAlwaysEnabled || WebInspector.settings.debuggerEnabled.get();
if (enableDebugger)
......@@ -512,14 +513,14 @@ WebInspector.ScriptsPanel.prototype = {
} else if (details.reason === WebInspector.ScriptsPanel.BreakReason.Exception) {
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
} else {
function didGetSourceLocation(uiSourceCode, lineNumber)
function didGetUILocation(uiLocation)
{
if (!uiSourceCode || !this._presentationModel.findBreakpoint(uiSourceCode, lineNumber))
if (!this._presentationModel.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber))
return;
this.sidebarPanes.jsBreakpoints.highlightBreakpoint(uiSourceCode, lineNumber);
this.sidebarPanes.jsBreakpoints.highlightBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
}
callFrames[0].sourceLine(didGetSourceLocation.bind(this));
callFrames[0].uiLocation(didGetUILocation.bind(this));
}
window.focus();
......@@ -730,11 +731,26 @@ WebInspector.ScriptsPanel.prototype = {
delete this._executionSourceFrame;
},
_callFrameSelected: function(event)
_executionLineChanged: function(event)
{
var callFrame = event.data;
var uiLocation = event.data;
this._clearCurrentExecutionLine();
if (!uiLocation)
return;
if (!uiLocation.uiSourceCode._option) {
// Anonymous scripts are not added to files select by default.
this._addOptionToFilesSelect(uiLocation.uiSourceCode);
}
var sourceFrame = this._showSourceFrameAndAddToHistory(uiLocation.uiSourceCode);
sourceFrame.setExecutionLine(uiLocation.lineNumber);
this._executionSourceFrame = sourceFrame;
},
_callFrameSelected: function(event)
{
var callFrame = event.data;
if (!callFrame)
return;
......@@ -742,21 +758,6 @@ WebInspector.ScriptsPanel.prototype = {
this.sidebarPanes.scopechain.update(callFrame);
this.sidebarPanes.watchExpressions.refreshExpressions();
this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame;
function didGetSourceLocation(uiSourceCode, lineNumber)
{
if (!uiSourceCode)
return;
if (!uiSourceCode._option) {
// Anonymous scripts are not added to files select by default.
this._addOptionToFilesSelect(uiSourceCode);
}
var sourceFrame = this._showSourceFrameAndAddToHistory(uiSourceCode);
sourceFrame.setExecutionLine(lineNumber);
this._executionSourceFrame = sourceFrame;
}
callFrame.sourceLine(didGetSourceLocation.bind(this));
},
_filesSelectChanged: function()
......
......@@ -55,6 +55,11 @@ WebInspector.linkifyStringAsFragmentWithCustomLinkifier = function(url, linkifie
*/
WebInspector.formatLinkText = function(url, lineNumber) {}
/**
* @param {string} url
*/
WebInspector.displayNameForURL = function(url) {}
/**
* @param {string} str
* @param {...*} varArgs
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment