Web Inspector: save and restore source positions in back/forward history

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

Patch by Brian J. Burg <burg@cs.washington.edu> on 2013-10-02
Reviewed by Timothy Hatcher.

Previously, the back/forward entries comprised of only the content
views, but not their positions if navigated via hyperlink (i.e.,
handling script.js:42).  When multiple instances of the same
content view appeared in the back/forward list, the most recent
navigation was displayed rather than the linked position.

We now store context necessary to re-navigate such hyperlinks by
storing view- specific data inside a cookie object, and invoke a
supplied callback to take any position initialization actions,
such as calling TextEditor.revealPosition.  This state is
encapsulated into BackForwardEntry instances.

Functions that save and restore scroll positions inside content
views have been changed to store state in BackForwardEntry
instances, so multiple scroll positions can be saved for a content
view appearing in the navigation history more than once.

* UserInterface/BackForwardEntry.js: Added.
(WebInspector.BackForwardEntry):
(WebInspector.BackForwardEntry.prototype.get contentView):
(WebInspector.BackForwardEntry.prototype.get cookie):
(WebInspector.BackForwardEntry.prototype.prepareToShow):
(WebInspector.BackForwardEntry.prototype.prepareToHide):
(WebInspector.BackForwardEntry.prototype._restoreFromCookie):
(WebInspector.BackForwardEntry.prototype._restoreScrollPositions):
(WebInspector.BackForwardEntry.prototype._saveScrollPositions):
* UserInterface/ContentBrowser.js:
(WebInspector.ContentBrowser.prototype.showContentView):
(WebInspector.ContentBrowser.prototype._updateContentViewNavigationItems):
(WebInspector.ContentBrowser.prototype._updateFindBanner):
* UserInterface/ContentViewContainer.js:
(WebInspector.ContentViewContainer.prototype.get currentContentView):
(WebInspector.ContentViewContainer.prototype.get currentBackForwardEntry):
(WebInspector.ContentViewContainer.prototype.showContentView):
(WebInspector.ContentViewContainer.prototype.showBackForwardEntryForIndex):
(WebInspector.ContentViewContainer.prototype.replaceContentView):
(WebInspector.ContentViewContainer.prototype.closeAllContentViewsOfPrototype):
(WebInspector.ContentViewContainer.prototype.closeAllContentViews):
(WebInspector.ContentViewContainer.prototype.goBack):
(WebInspector.ContentViewContainer.prototype.goForward):
(WebInspector.ContentViewContainer.prototype.shown):
(WebInspector.ContentViewContainer.prototype.hidden):
(WebInspector.ContentViewContainer.prototype._showEntry):
(WebInspector.ContentViewContainer.prototype._hideEntry):
* UserInterface/Main.html:
* UserInterface/Main.js:
(WebInspector.openURL):
* UserInterface/ResourceSidebarPanel.js:
(WebInspector.ResourceSidebarPanel.prototype.restoreCallback):
(WebInspector.ResourceSidebarPanel.prototype.showSourceCode):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156809 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 90884345
2013-10-02 Brian J. Burg <burg@cs.washington.edu>
Web Inspector: save and restore source positions in back/forward history
https://bugs.webkit.org/show_bug.cgi?id=122062
Reviewed by Timothy Hatcher.
Previously, the back/forward entries comprised of only the content
views, but not their positions if navigated via hyperlink (i.e.,
handling script.js:42). When multiple instances of the same
content view appeared in the back/forward list, the most recent
navigation was displayed rather than the linked position.
We now store context necessary to re-navigate such hyperlinks by
storing view- specific data inside a cookie object, and invoke a
supplied callback to take any position initialization actions,
such as calling TextEditor.revealPosition. This state is
encapsulated into BackForwardEntry instances.
Functions that save and restore scroll positions inside content
views have been changed to store state in BackForwardEntry
instances, so multiple scroll positions can be saved for a content
view appearing in the navigation history more than once.
* UserInterface/BackForwardEntry.js: Added.
(WebInspector.BackForwardEntry):
(WebInspector.BackForwardEntry.prototype.get contentView):
(WebInspector.BackForwardEntry.prototype.get cookie):
(WebInspector.BackForwardEntry.prototype.prepareToShow):
(WebInspector.BackForwardEntry.prototype.prepareToHide):
(WebInspector.BackForwardEntry.prototype._restoreFromCookie):
(WebInspector.BackForwardEntry.prototype._restoreScrollPositions):
(WebInspector.BackForwardEntry.prototype._saveScrollPositions):
* UserInterface/ContentBrowser.js:
(WebInspector.ContentBrowser.prototype.showContentView):
(WebInspector.ContentBrowser.prototype._updateContentViewNavigationItems):
(WebInspector.ContentBrowser.prototype._updateFindBanner):
* UserInterface/ContentViewContainer.js:
(WebInspector.ContentViewContainer.prototype.get currentContentView):
(WebInspector.ContentViewContainer.prototype.get currentBackForwardEntry):
(WebInspector.ContentViewContainer.prototype.showContentView):
(WebInspector.ContentViewContainer.prototype.showBackForwardEntryForIndex):
(WebInspector.ContentViewContainer.prototype.replaceContentView):
(WebInspector.ContentViewContainer.prototype.closeAllContentViewsOfPrototype):
(WebInspector.ContentViewContainer.prototype.closeAllContentViews):
(WebInspector.ContentViewContainer.prototype.goBack):
(WebInspector.ContentViewContainer.prototype.goForward):
(WebInspector.ContentViewContainer.prototype.shown):
(WebInspector.ContentViewContainer.prototype.hidden):
(WebInspector.ContentViewContainer.prototype._showEntry):
(WebInspector.ContentViewContainer.prototype._hideEntry):
* UserInterface/Main.html:
* UserInterface/Main.js:
(WebInspector.openURL):
* UserInterface/ResourceSidebarPanel.js:
(WebInspector.ResourceSidebarPanel.prototype.restoreCallback):
(WebInspector.ResourceSidebarPanel.prototype.showSourceCode):
2013-10-02 Antoine Quint <graouts@apple.com>
Web Inspector: highlight newly added console messages in the Activity Viewer
......
/*
* Copyright (C) 2013 University of Washington. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.BackForwardEntry = function(contentView, cookie, restoreCallback)
{
WebInspector.Object.call(this);
this._contentView = contentView;
// Cookies are compared with Object.shallowEqual, so should not store objects or arrays.
this._cookie = cookie || {};
this._scrollPositions = [];
this._restoreCallback = restoreCallback;
};
WebInspector.BackForwardEntry.prototype = {
constructor: WebInspector.BackForwardEntry,
__proto__: WebInspector.Object.prototype,
// Public
get contentView()
{
return this._contentView;
},
get cookie()
{
// Cookies are immutable; they represent a specific navigation action.
return Object.shallowCopy(this._cookie);
},
prepareToShow: function()
{
this._restoreFromCookie();
this.contentView.visible = true;
this.contentView.shown();
this.contentView.updateLayout();
},
prepareToHide: function()
{
this.contentView.visible = false;
this.contentView.hidden();
this._saveScrollPositions();
},
// Private
_restoreFromCookie: function()
{
this._restoreScrollPositions();
if (this._restoreCallback && typeof this._restoreCallback === "function")
this._restoreCallback.call(null, this.contentView, this.cookie);
},
_restoreScrollPositions: function()
{
// If no scroll positions are saved, do nothing.
if (!this._scrollPositions.length)
return;
var scrollableElements = this.contentView.scrollableElements || [];
console.assert(this._scrollPositions.length === scrollableElements.length);
for (var i = 0; i < scrollableElements.length; ++i) {
var position = this._scrollPositions[i];
var element = scrollableElements[i];
if (!element)
continue;
// Restore the top scroll position by either scrolling to the bottom or to the saved position.
element.scrollTop = position.isScrolledToBottom ? element.scrollHeight : position.scrollTop;
// Don't restore the left scroll position when scrolled to the bottom. This way the when content changes
// the user won't be left in a weird horizontal position.
element.scrollLeft = position.isScrolledToBottom ? 0 : position.scrollLeft;
}
},
_saveScrollPositions: function()
{
var scrollableElements = this.contentView.scrollableElements || [];
var scrollPositions = [];
for (var i = 0; i < scrollableElements.length; ++i) {
var element = scrollableElements[i];
if (!element)
continue;
var position = { scrollTop: element.scrollTop, scrollLeft: element.scrollLeft };
if (this.contentView.shouldKeepElementsScrolledToBottom)
position.isScrolledToBottom = element.isScrolledToBottom();
scrollPositions.push(position);
}
this._scrollPositions = scrollPositions;
}
};
......@@ -157,9 +157,9 @@ WebInspector.ContentBrowser.prototype = {
return this._contentViewContainer.showContentViewForRepresentedObject(representedObject);
},
showContentView: function(contentView)
showContentView: function(contentView, cookie, restoreCallback)
{
return this._contentViewContainer.showContentView(contentView);
return this._contentViewContainer.showContentView(contentView, cookie, restoreCallback);
},
contentViewForRepresentedObject: function(representedObject, onlyExisting)
......@@ -411,7 +411,7 @@ WebInspector.ContentBrowser.prototype = {
// Go through each of the items of the new content view and add a divider before them.
currentContentView.navigationItems.forEach(function(navigationItem, index) {
// Add dividers before items unless it's the first item and not a button.
// Add dividers before items unless it's the first item and not a button.
if (index !== 0 || navigationItem instanceof WebInspector.ButtonNavigationItem) {
var divider = new WebInspector.DividerNavigationItem;
navigationBar.insertNavigationItem(divider, insertionIndex++);
......@@ -433,7 +433,7 @@ WebInspector.ContentBrowser.prototype = {
this._findBanner.numberOfResults = null;
return;
}
this._findBanner.targetElement = currentContentView.element;
this._findBanner.numberOfResults = currentContentView.hasPerformedSearch ? currentContentView.numberOfSearchResults : null;
......
......@@ -61,6 +61,13 @@ WebInspector.ContentViewContainer.prototype = {
},
get currentContentView()
{
if (this._currentIndex < 0 || this._currentIndex > this._backForwardList.length - 1)
return null;
return this._backForwardList[this._currentIndex].contentView;
},
get currentBackForwardEntry()
{
if (this._currentIndex < 0 || this._currentIndex > this._backForwardList.length - 1)
return null;
......@@ -126,7 +133,7 @@ WebInspector.ContentViewContainer.prototype = {
return contentView;
},
showContentView: function(contentView)
showContentView: function(contentView, cookie, restoreCallback)
{
console.assert(contentView instanceof WebInspector.ContentView);
if (!(contentView instanceof WebInspector.ContentView))
......@@ -138,10 +145,11 @@ WebInspector.ContentViewContainer.prototype = {
if (contentView.parentContainer && contentView.parentContainer !== this)
return null;
// Don't do anything if the content view is already the current content view.
var currentContentView = this.currentContentView;
if (currentContentView === contentView)
return contentView;
var currentEntry = this.currentBackForwardEntry;
var provisionalEntry = new WebInspector.BackForwardEntry(contentView, cookie, restoreCallback);
// Don't do anything if we would have added an identical back/forward list entry.
if (currentEntry && currentEntry.contentView === contentView && Object.shallowEqual(provisionalEntry.cookie, currentEntry.cookie))
return currentEntry.contentView;
// Showing a content view will truncate the back/forward list after the current index and insert the content view
// at the end of the list. Finally, the current index will be updated to point to the end of the back/forward list.
......@@ -150,29 +158,30 @@ WebInspector.ContentViewContainer.prototype = {
var newIndex = this._currentIndex + 1;
// Insert the content view at the new index. This will remove any content views greater than or equal to the index.
var removedItems = this._backForwardList.splice(newIndex, this._backForwardList.length - newIndex, contentView);
var removedEntries = this._backForwardList.splice(newIndex, this._backForwardList.length - newIndex, provisionalEntry);
console.assert(newIndex === this._backForwardList.length - 1);
console.assert(this._backForwardList[newIndex] === contentView);
console.assert(this._backForwardList[newIndex] === provisionalEntry);
// Disassociate with the removed content views.
for (var i = 0; i < removedItems.length; ++i) {
for (var i = 0; i < removedEntries.length; ++i) {
// Skip disassociation if this content view is still in the back/forward list.
if (this._backForwardList.contains(removedItems[i]))
continue;
this._disassociateFromContentView(removedItems[i]);
var shouldDissociateContentView = this._backForwardList.some(function(existingEntry) {
return existingEntry.contentView === removedEntries[i].contentView;
});
if (shouldDissociateContentView)
this._disassociateFromContentView(removedEntries[i]);
}
// Associate with the new content view.
contentView._parentContainer = this;
this.showBackForwardEntry(newIndex);
this.showBackForwardEntryForIndex(newIndex);
return contentView;
},
showBackForwardEntry: function(index)
showBackForwardEntryForIndex: function(index)
{
console.assert(index >= 0 && index <= this._backForwardList.length - 1);
if (index < 0 || index > this._backForwardList.length - 1)
......@@ -182,13 +191,15 @@ WebInspector.ContentViewContainer.prototype = {
return;
// Hide the currently visible content view.
var currentContentView = this.currentContentView;
if (currentContentView)
this._hideContentView(currentContentView);
var previousEntry = this.currentBackForwardEntry;
if (previousEntry)
this._hideEntry(previousEntry);
this._currentIndex = index;
var currentEntry = this.currentBackForwardEntry;
console.assert(currentEntry);
this._showContentView(this.currentContentView);
this._showEntry(currentEntry);
this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange);
},
......@@ -213,7 +224,7 @@ WebInspector.ContentViewContainer.prototype = {
var currentlyShowing = (this.currentContentView === oldContentView);
if (currentlyShowing)
this._hideContentView(oldContentView);
this._hideEntry(this.currentBackForwardEntry);
// Disassociate with the old content view.
this._disassociateFromContentView(oldContentView);
......@@ -223,12 +234,13 @@ WebInspector.ContentViewContainer.prototype = {
// Replace all occurrences of oldContentView with newContentView in the back/forward list.
for (var i = 0; i < this._backForwardList.length; ++i) {
if (this._backForwardList[i] === oldContentView)
this._backForwardList[i] = newContentView;
if (this._backForwardList[i].contentView === oldContentView)
this._backForwardList[i].contentView = newContentView;
}
// Re-show the current entry, because its content view instance was replaced.
if (currentlyShowing) {
this._showContentView(newContentView);
this._showEntry(this.currentBackForwardEntry);
this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange);
}
},
......@@ -244,7 +256,7 @@ WebInspector.ContentViewContainer.prototype = {
// If they all are we can use the quicker closeAllContentViews method.
var allSamePrototype = true;
for (var i = this._backForwardList.length - 1; i >= 0; --i) {
if (!(this._backForwardList[i] instanceof constructor)) {
if (!(this._backForwardList[i].contentView instanceof constructor)) {
allSamePrototype = false;
break;
}
......@@ -260,12 +272,12 @@ WebInspector.ContentViewContainer.prototype = {
var backForwardListDidChange = false;
// Hide and disassociate with all the content views that are instances of the constructor.
for (var i = this._backForwardList.length - 1; i >= 0; --i) {
var contentView = this._backForwardList[i];
if (!(contentView instanceof constructor))
var entry = this._backForwardList[i];
if (!(entry.contentView instanceof constructor))
continue;
if (contentView === oldCurrentContentView)
this._hideContentView(contentView);
if (entry.contentView === oldCurrentContentView)
this._hideEntry(entry);
if (this._currentIndex >= i) {
// Decrement the currentIndex since we will remove an item in the back/forward array
......@@ -273,18 +285,18 @@ WebInspector.ContentViewContainer.prototype = {
--this._currentIndex;
}
this._disassociateFromContentView(contentView);
this._disassociateFromContentView(entry.contentView);
// Remove the item from the back/forward list.
this._backForwardList.splice(i, 1);
backForwardListDidChange = true;
}
var currentContentView = this.currentContentView;
console.assert(currentContentView || (!currentContentView && this._currentIndex === -1));
var currentEntry = this.currentBackForwardEntry;
console.assert(currentEntry || (!currentEntry && this._currentIndex === -1));
if (currentContentView && (currentContentView !== oldCurrentContentView || backForwardListDidChange)) {
this._showContentView(currentContentView);
if (currentEntry && currentEntry.contentView !== oldCurrentContentView || backForwardListDidChange) {
this._showEntry(currentEntry);
this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange);
}
},
......@@ -298,10 +310,10 @@ WebInspector.ContentViewContainer.prototype = {
// Hide and disassociate with all the content views.
for (var i = 0; i < this._backForwardList.length; ++i) {
var contentView = this._backForwardList[i];
var entry = this._backForwardList[i];
if (i === this._currentIndex)
this._hideContentView(contentView);
this._disassociateFromContentView(contentView);
this._hideEntry(entry);
this._disassociateFromContentView(entry.contentView);
}
this._backForwardList = [];
......@@ -324,32 +336,32 @@ WebInspector.ContentViewContainer.prototype = {
{
if (!this.canGoBack())
return;
this.showBackForwardEntry(this._currentIndex - 1);
this.showBackForwardEntryForIndex(this._currentIndex - 1);
},
goForward: function()
{
if (!this.canGoForward())
return;
this.showBackForwardEntry(this._currentIndex + 1);
this.showBackForwardEntryForIndex(this._currentIndex + 1);
},
shown: function()
{
var currentContentView = this.currentContentView;
if (!currentContentView)
var currentEntry = this.currentBackForwardEntry;
if (!currentEntry)
return;
this._showContentView(currentContentView);
this._showEntry(currentEntry);
},
hidden: function()
{
var currentContentView = this.currentContentView;
if (!currentContentView)
var currentEntry = this.currentBackForwardEntry;
if (!currentEntry)
return;
this._hideContentView(currentContentView);
this._hideEntry(currentEntry);
},
// Private
......@@ -381,72 +393,20 @@ WebInspector.ContentViewContainer.prototype = {
contentView.closed();
},
_saveScrollPositionsForContentView: function(contentView)
{
var scrollableElements = contentView.scrollableElements || [];
for (var i = 0; i < scrollableElements.length; ++i) {
var element = scrollableElements[i];
if (!element)
continue;
if (contentView.shouldKeepElementsScrolledToBottom)
element._savedIsScrolledToBottom = element.isScrolledToBottom();
element._savedScrollTop = element.scrollTop;
element._savedScrollLeft = element.scrollLeft;
}
},
_restoreScrollPositionsForContentView: function(contentView)
_showEntry: function(entry)
{
var scrollableElements = contentView.scrollableElements || [];
for (var i = 0; i < scrollableElements.length; ++i) {
var element = scrollableElements[i];
if (!element)
continue;
// Restore the top scroll position by either scrolling to the bottom or to the saved position.
element.scrollTop = element._savedIsScrolledToBottom ? element.scrollHeight : element._savedScrollTop;
// Don't restore the left scroll position when scrolled to the bottom. This way the when content changes
// the user won't be left in a weird horizontal position.
element.scrollLeft = element._savedIsScrolledToBottom ? 0 : element._savedScrollLeft;
}
},
_showContentView: function(contentView)
{
if (contentView.visible)
return;
this._addContentViewElement(contentView);
this._prepareContentViewToShow(contentView);
},
_prepareContentViewToShow: function(contentView)
{
this._restoreScrollPositionsForContentView(contentView);
contentView.visible = true;
contentView.shown();
contentView.updateLayout();
},
_hideContentView: function(contentView)
{
if (!contentView.visible)
return;
this._prepareContentViewToHide(contentView);
console.assert(entry instanceof WebInspector.BackForwardEntry);
this._removeContentViewElement(contentView);
this._addContentViewElement(entry.contentView);
entry.prepareToShow();
},
_prepareContentViewToHide: function(contentView)
_hideEntry: function(entry)
{
contentView.visible = false;
contentView.hidden();
console.assert(entry instanceof WebInspector.BackForwardEntry);
this._saveScrollPositionsForContentView(contentView);
entry.prepareToHide();
this._removeContentViewElement(entry.contentView);
}
};
......
......@@ -239,6 +239,7 @@
<script src="TextEditor.js"></script>
<script src="EventHandler.js"></script>
<script src="SourceCodeTextEditor.js"></script>
<script src="BackForwardEntry.js"></script>
<script src="ContentViewContainer.js"></script>
<script src="ContentView.js"></script>
<script src="ClusterContentView.js"></script>
......
......@@ -511,7 +511,8 @@ WebInspector.openURL = function(url, frame, alwaysOpenExternally, lineNumber)
// WebInspector.Frame.resourceForURL does not check the main resource, only sub-resources. So check both.
var resource = frame.url === url ? frame.mainResource : frame.resourceForURL(url, searchChildFrames);
if (resource) {
this.resourceSidebarPanel.showSourceCode(resource, lineNumber);
var position = new WebInspector.SourceCodePosition(lineNumber, 0);
this.resourceSidebarPanel.showSourceCode(resource, position);
return;
}
......
......@@ -248,6 +248,7 @@ WebInspector.ResourceSidebarPanel.prototype = {
showSourceCode: function(sourceCode, positionToReveal, textRangeToSelect, forceUnformatted)
{
console.assert(!positionToReveal || positionToReveal instanceof WebInspector.SourceCodePosition, positionToReveal);
var representedObject = sourceCode;
if (representedObject instanceof WebInspector.Script) {
......@@ -259,16 +260,23 @@ WebInspector.ResourceSidebarPanel.prototype = {
if (representedObject instanceof WebInspector.Resource && representedObject.isMainResource())
representedObject = representedObject.parentFrame;
var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(representedObject);
var newContentView = WebInspector.contentBrowser.contentViewForRepresentedObject(representedObject);
var cookie = {lineNumber: positionToReveal.lineNumber, columnNumber: positionToReveal.columnNumber};
if (contentView instanceof WebInspector.FrameContentView)
contentView.showSourceCode(positionToReveal, textRangeToSelect, forceUnformatted);
else if (contentView instanceof WebInspector.ResourceClusterContentView)
contentView.showResponse(positionToReveal, textRangeToSelect, forceUnformatted);
else if (contentView instanceof WebInspector.ScriptContentView)
contentView.revealPosition(positionToReveal, textRangeToSelect, forceUnformatted);
var restoreCallback = function(contentView, savedCookie) {
var lineNumber = savedCookie.lineNumber;
var columnNumber = savedCookie.columnNumber;
var position = new WebInspector.SourceCodePosition(lineNumber, columnNumber);
WebInspector.contentBrowser.showContentView(contentView);
if (contentView instanceof WebInspector.FrameContentView)
contentView.showSourceCode(position)
else if (contentView instanceof WebInspector.ResourceClusterContentView)
contentView.showResponse(position)
else if (contentView instanceof WebInspector.ScriptContentView)
contentView.revealPosition(position)
};
WebInspector.contentBrowser.showContentView(newContentView, cookie, restoreCallback);
},
showSourceCodeLocation: function(sourceCodeLocation)
......
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