зеркало из https://github.com/mozilla/gecko-dev.git
bug 808369 - Use VariablesView in the Scratchpad; r=msucan
This commit is contained in:
Родитель
2307ce5a06
Коммит
744abbee16
|
@ -30,6 +30,12 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
|||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
|
||||
"resource:///modules/devtools/VariablesView.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
const SCRATCHPAD_CONTEXT_CONTENT = 1;
|
||||
const SCRATCHPAD_CONTEXT_BROWSER = 2;
|
||||
const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties";
|
||||
|
@ -38,7 +44,9 @@ const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
|
|||
const BUTTON_POSITION_SAVE = 0;
|
||||
const BUTTON_POSITION_CANCEL = 1;
|
||||
const BUTTON_POSITION_DONT_SAVE = 2;
|
||||
const BUTTON_POSITION_REVERT=0;
|
||||
const BUTTON_POSITION_REVERT = 0;
|
||||
const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
|
||||
|
||||
|
||||
/**
|
||||
* The scratchpad object handles the Scratchpad window functionality.
|
||||
|
@ -253,6 +261,18 @@ var Scratchpad = {
|
|||
return "Scratchpad/" + this._instanceId;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sidebar that contains the VariablesView for object inspection.
|
||||
*/
|
||||
get sidebar()
|
||||
{
|
||||
if (!this._sidebar) {
|
||||
this._sidebar = new ScratchpadSidebar();
|
||||
}
|
||||
return this._sidebar;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the Cu.Sandbox object for the active tab content window object. Note
|
||||
* that the returned object is cached for later reuse. The cached object is
|
||||
|
@ -423,25 +443,35 @@ var Scratchpad = {
|
|||
|
||||
/**
|
||||
* Execute the selected text (if any) or the entire editor content in the
|
||||
* current context. The resulting object is opened up in the Property Panel
|
||||
* for inspection.
|
||||
* current context. If the result is primitive then it is written as a
|
||||
* comment. Otherwise, the resulting object is inspected up in the sidebar.
|
||||
*
|
||||
* @return Promise
|
||||
* The promise for the script evaluation result.
|
||||
*/
|
||||
inspect: function SP_inspect()
|
||||
{
|
||||
let promise = this.execute();
|
||||
promise.then(([aString, aError, aResult]) => {
|
||||
let deferred = Promise.defer();
|
||||
let reject = aReason => deferred.reject(aReason);
|
||||
|
||||
this.execute().then(([aString, aError, aResult]) => {
|
||||
let resolve = () => deferred.resolve([aString, aError, aResult]);
|
||||
|
||||
if (aError) {
|
||||
this.writeAsErrorComment(aError);
|
||||
resolve();
|
||||
}
|
||||
else if (!isObject(aResult)) {
|
||||
this.writeAsComment(aResult);
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
this.deselect();
|
||||
this.openPropertyPanel(aString, aResult);
|
||||
this.sidebar.open(aString, aResult).then(resolve, reject);
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}, reject);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -552,58 +582,6 @@ var Scratchpad = {
|
|||
this.writeAsComment(newComment);
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the Property Panel to inspect the given object.
|
||||
*
|
||||
* @param string aEvalString
|
||||
* The string that was evaluated. This is re-used when the user updates
|
||||
* the properties list, by clicking the Update button.
|
||||
* @param object aOutputObject
|
||||
* The object to inspect, which is the aEvalString evaluation result.
|
||||
* @return object
|
||||
* The PropertyPanel object instance.
|
||||
*/
|
||||
openPropertyPanel: function SP_openPropertyPanel(aEvalString, aOutputObject)
|
||||
{
|
||||
let propPanel;
|
||||
// The property panel has a button:
|
||||
// `Update`: reexecutes the string executed on the command line. The
|
||||
// result will be inspected by this panel.
|
||||
let buttons = [];
|
||||
|
||||
// If there is a evalString passed to this function, then add a `Update`
|
||||
// button to the panel so that the evalString can be reexecuted to update
|
||||
// the content of the panel.
|
||||
if (aEvalString !== null) {
|
||||
buttons.push({
|
||||
label: this.strings.
|
||||
GetStringFromName("propertyPanel.updateButton.label"),
|
||||
accesskey: this.strings.
|
||||
GetStringFromName("propertyPanel.updateButton.accesskey"),
|
||||
oncommand: () => {
|
||||
this.evalForContext(aEvalString).then(([, aError, aResult]) => {
|
||||
if (!aError) {
|
||||
propPanel.treeView.data = { object: aResult };
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let doc = this.browserWindow.document;
|
||||
let parent = doc.getElementById("mainPopupSet");
|
||||
let title = String(aOutputObject);
|
||||
propPanel = new PropertyPanel(parent, title, { object: aOutputObject },
|
||||
buttons);
|
||||
|
||||
let panel = propPanel.panel;
|
||||
panel.setAttribute("class", "scratchpad_propertyPanel");
|
||||
panel.openPopup(null, "after_pointer", 0, 0, false, false);
|
||||
panel.sizeTo(200, 400);
|
||||
|
||||
return propPanel;
|
||||
},
|
||||
|
||||
// Menu Operations
|
||||
|
||||
/**
|
||||
|
@ -1495,6 +1473,132 @@ var Scratchpad = {
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulates management of the sidebar containing the VariablesView for
|
||||
* object inspection.
|
||||
*/
|
||||
function ScratchpadSidebar()
|
||||
{
|
||||
let ToolSidebar = devtools.require("devtools/framework/sidebar").ToolSidebar;
|
||||
let tabbox = document.querySelector("#scratchpad-sidebar");
|
||||
this._sidebar = new ToolSidebar(tabbox, this);
|
||||
this._splitter = document.querySelector(".devtools-side-splitter");
|
||||
}
|
||||
|
||||
ScratchpadSidebar.prototype = {
|
||||
/*
|
||||
* The ToolSidebar for this sidebar.
|
||||
*/
|
||||
_sidebar: null,
|
||||
|
||||
/*
|
||||
* The splitter element between the sidebar and the editor.
|
||||
*/
|
||||
_splitter: null,
|
||||
|
||||
/*
|
||||
* The VariablesView for this sidebar.
|
||||
*/
|
||||
variablesView: null,
|
||||
|
||||
/*
|
||||
* Whether the sidebar is currently shown.
|
||||
*/
|
||||
visible: false,
|
||||
|
||||
/**
|
||||
* Open the sidebar, if not open already, and populate it with the properties
|
||||
* of the given object.
|
||||
*
|
||||
* @param string aString
|
||||
* The string that was evaluated.
|
||||
* @param object aObject
|
||||
* The object to inspect, which is the aEvalString evaluation result.
|
||||
* @return Promise
|
||||
* A promise that will resolve once the sidebar is open.
|
||||
*/
|
||||
open: function SS_open(aEvalString, aObject)
|
||||
{
|
||||
this.show();
|
||||
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let onTabReady = () => {
|
||||
if (!this.variablesView) {
|
||||
let window = this._sidebar.getWindowForTab("variablesview");
|
||||
let container = window.document.querySelector("#variables");
|
||||
this.variablesView = new VariablesView(container);
|
||||
}
|
||||
this._update(aObject).then(() => deferred.resolve());
|
||||
};
|
||||
|
||||
if (this._sidebar.getCurrentTabID() == "variablesview") {
|
||||
onTabReady();
|
||||
}
|
||||
else {
|
||||
this._sidebar.once("variablesview-ready", onTabReady);
|
||||
this._sidebar.addTab("variablesview", VARIABLES_VIEW_URL, true);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the sidebar.
|
||||
*/
|
||||
show: function SS_show()
|
||||
{
|
||||
if (!this.visible) {
|
||||
this.visible = true;
|
||||
this._sidebar.show();
|
||||
this._splitter.setAttribute("state", "open");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the sidebar.
|
||||
*/
|
||||
hide: function SS_hide()
|
||||
{
|
||||
if (this.visible) {
|
||||
this.visible = false;
|
||||
this._sidebar.hide();
|
||||
this._splitter.setAttribute("state", "collapsed");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the object currently inspected by the sidebar.
|
||||
*
|
||||
* @param object aObject
|
||||
* The object to inspect in the sidebar.
|
||||
* @return Promise
|
||||
* A promise that resolves when the update completes.
|
||||
*/
|
||||
_update: function SS__update(aObject)
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
|
||||
this.variablesView.rawObject = aObject;
|
||||
|
||||
// In the future this will work on remote values (bug 825039).
|
||||
setTimeout(() => deferred.resolve(), 0);
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check whether a value is non-primitive.
|
||||
*/
|
||||
function isObject(aValue)
|
||||
{
|
||||
let type = typeof aValue;
|
||||
return type == "object" ? aValue != null : type == "function";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The PreferenceObserver listens for preference changes while Scratchpad is
|
||||
* running.
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
<!ENTITY % scratchpadDTD SYSTEM "chrome://browser/locale/devtools/scratchpad.dtd" >
|
||||
%scratchpadDTD;
|
||||
]>
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/scratchpad.css"?>
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?>
|
||||
|
||||
|
@ -280,7 +282,16 @@
|
|||
</popupset>
|
||||
|
||||
<notificationbox id="scratchpad-notificationbox" flex="1">
|
||||
<hbox id="scratchpad-editor" flex="1"/>
|
||||
<hbox flex="1">
|
||||
<vbox id="scratchpad-editor" flex="1"/>
|
||||
<splitter class="devtools-side-splitter"
|
||||
collapse="after"
|
||||
state="collapsed"/>
|
||||
<tabbox id="scratchpad-sidebar" class="devtools-sidebar-tabs" width="300">
|
||||
<tabs/>
|
||||
<tabpanels flex="1"/>
|
||||
</tabbox>
|
||||
</hbox>
|
||||
</notificationbox>
|
||||
|
||||
</window>
|
||||
|
|
|
@ -12,47 +12,35 @@ function test()
|
|||
openScratchpad(runTests);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<title>foobarBug636725</title>" +
|
||||
"<p>test inspect() in Scratchpad";
|
||||
content.location = "data:text/html;charset=utf8,<p>test inspect() in Scratchpad</p>";
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
let sp = gScratchpadWindow.Scratchpad;
|
||||
|
||||
sp.setText("document");
|
||||
sp.setText("({ a: 'foobarBug636725' })");
|
||||
|
||||
sp.inspect().then(function() {
|
||||
let sidebar = sp.sidebar;
|
||||
ok(sidebar.visible, "sidebar is open");
|
||||
|
||||
let propPanel = document.querySelector(".scratchpad_propertyPanel");
|
||||
ok(propPanel, "property panel is open");
|
||||
|
||||
propPanel.addEventListener("popupshown", function onPopupShown() {
|
||||
propPanel.removeEventListener("popupshown", onPopupShown, false);
|
||||
let found = false;
|
||||
|
||||
let tree = propPanel.querySelector("tree");
|
||||
ok(tree, "property panel tree found");
|
||||
|
||||
let column = tree.columns[0];
|
||||
let found = false;
|
||||
|
||||
for (let i = 0; i < tree.view.rowCount; i++) {
|
||||
let cell = tree.view.getCellText(i, column);
|
||||
if (cell == 'title: "foobarBug636725"') {
|
||||
found = true;
|
||||
break;
|
||||
outer: for (let scope in sidebar.variablesView) {
|
||||
for (let [, obj] in scope) {
|
||||
for (let [, prop] in obj) {
|
||||
if (prop.name == "a" && prop.value == "foobarBug636725") {
|
||||
found = true;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
ok(found, "found the document.title property");
|
||||
}
|
||||
|
||||
executeSoon(function() {
|
||||
propPanel.hidePopup();
|
||||
ok(found, "found the property");
|
||||
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
}, function() {
|
||||
notok(true, "document not found");
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%include ../../shared/devtools/scratchpad.inc.css
|
|
@ -171,6 +171,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%include ../../shared/devtools/scratchpad.inc.css
|
|
@ -262,6 +262,7 @@ browser.jar:
|
|||
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
%if 0
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
%endif
|
||||
|
||||
#scratchpad-sidebar > tabs {
|
||||
height: 0;
|
||||
border: none;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%include ../../shared/devtools/scratchpad.inc.css
|
|
@ -199,6 +199,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
@ -446,6 +447,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/aero/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/aero/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/aero/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
|
||||
skin/classic/aero/browser/devtools/option-icon.png (devtools/option-icon.png)
|
||||
skin/classic/aero/browser/devtools/itemToggle.png (devtools/itemToggle.png)
|
||||
|
|
Загрузка…
Ссылка в новой задаче