зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to m-c
This commit is contained in:
Коммит
0ffe1c280b
|
@ -1010,6 +1010,9 @@ pref("devtools.scratchpad.enabled", true);
|
|||
// Enable tools for Chrome development.
|
||||
pref("devtools.chrome.enabled", false);
|
||||
|
||||
// Disable the GCLI enhanced command line.
|
||||
pref("devtools.gcli.enable", false);
|
||||
|
||||
// The last Web Console height. This is initially 0 which means that the Web
|
||||
// Console will use the default height next time it shows.
|
||||
// Change to -1 if you do not want the Web Console to remember its last height.
|
||||
|
|
|
@ -6,4 +6,5 @@ browser.jar:
|
|||
content/browser/csshtmltree.xhtml (styleinspector/csshtmltree.xhtml)
|
||||
content/browser/orion.js (sourceeditor/orion/orion.js)
|
||||
content/browser/orion.css (sourceeditor/orion/orion.css)
|
||||
content/browser/orion-mozilla.css (sourceeditor/orion/mozilla.css)
|
||||
|
||||
|
|
|
@ -84,10 +84,10 @@ var Scratchpad = {
|
|||
executionContext: SCRATCHPAD_CONTEXT_CONTENT,
|
||||
|
||||
/**
|
||||
* Retrieve the xul:statusbarpanel DOM element. The status bar tells the
|
||||
* current code execution context.
|
||||
* Retrieve the xul:notificationbox DOM element. It notifies the user when
|
||||
* the current code execution context is SCRATCHPAD_CONTEXT_BROWSER.
|
||||
*/
|
||||
get statusbarStatus() document.getElementById("scratchpad-status"),
|
||||
get notificationBox() document.getElementById("scratchpad-notificationbox"),
|
||||
|
||||
/**
|
||||
* Get the selected text from the editor.
|
||||
|
@ -599,11 +599,15 @@ var Scratchpad = {
|
|||
*/
|
||||
setContentContext: function SP_setContentContext()
|
||||
{
|
||||
if (this.executionContext == SCRATCHPAD_CONTEXT_CONTENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
let content = document.getElementById("sp-menu-content");
|
||||
document.getElementById("sp-menu-browser").removeAttribute("checked");
|
||||
content.setAttribute("checked", true);
|
||||
this.executionContext = SCRATCHPAD_CONTEXT_CONTENT;
|
||||
this.statusbarStatus.label = content.getAttribute("label");
|
||||
this.notificationBox.removeAllNotifications(false);
|
||||
this.resetContext();
|
||||
},
|
||||
|
||||
|
@ -612,11 +616,20 @@ var Scratchpad = {
|
|||
*/
|
||||
setBrowserContext: function SP_setBrowserContext()
|
||||
{
|
||||
if (this.executionContext == SCRATCHPAD_CONTEXT_BROWSER) {
|
||||
return;
|
||||
}
|
||||
|
||||
let browser = document.getElementById("sp-menu-browser");
|
||||
document.getElementById("sp-menu-content").removeAttribute("checked");
|
||||
browser.setAttribute("checked", true);
|
||||
this.executionContext = SCRATCHPAD_CONTEXT_BROWSER;
|
||||
this.statusbarStatus.label = browser.getAttribute("label");
|
||||
this.notificationBox.appendNotification(
|
||||
this.strings.GetStringFromName("browserContext.notification"),
|
||||
SCRATCHPAD_CONTEXT_BROWSER,
|
||||
null,
|
||||
this.notificationBox.PRIORITY_WARNING_HIGH,
|
||||
null);
|
||||
this.resetContext();
|
||||
},
|
||||
|
||||
|
@ -657,17 +670,14 @@ var Scratchpad = {
|
|||
return;
|
||||
}
|
||||
|
||||
let chromeContextMenu = document.getElementById("sp-menu-browser");
|
||||
let errorConsoleMenu = document.getElementById("sp-menu-errorConsole");
|
||||
let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole");
|
||||
let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
|
||||
|
||||
let chrome = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED);
|
||||
if (chrome) {
|
||||
chromeContextMenu.removeAttribute("hidden");
|
||||
errorConsoleMenu.removeAttribute("hidden");
|
||||
errorConsoleCommand.removeAttribute("disabled");
|
||||
let environmentMenu = document.getElementById("sp-environment-menu");
|
||||
let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole");
|
||||
let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
|
||||
environmentMenu.removeAttribute("hidden");
|
||||
chromeContextCommand.removeAttribute("disabled");
|
||||
errorConsoleCommand.removeAttribute("disabled");
|
||||
}
|
||||
|
||||
this.editor = new SourceEditor();
|
||||
|
|
|
@ -261,12 +261,18 @@
|
|||
accesskey="&display.accesskey;"
|
||||
key="sp-key-display"
|
||||
command="sp-cmd-display"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="sp-text-resetContext"
|
||||
label="&resetContext.label;"
|
||||
accesskey="&resetContext.accesskey;"
|
||||
command="sp-cmd-resetContext"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="sp-environment-menu"
|
||||
label="&environmentMenu.label;"
|
||||
accesskey="&environmentMenu.accesskey;">
|
||||
accesskey="&environmentMenu.accesskey;"
|
||||
hidden="true">
|
||||
<menupopup id="sp-menu-environment">
|
||||
<menuitem id="sp-menu-content"
|
||||
label="&contentContext.label;"
|
||||
|
@ -274,33 +280,11 @@
|
|||
command="sp-cmd-contentContext"
|
||||
checked="true"
|
||||
type="radio"/>
|
||||
<menuitem id="sp-menu-browser" hidden="true"
|
||||
<menuitem id="sp-menu-browser"
|
||||
command="sp-cmd-browserContext"
|
||||
label="&browserContext.label;"
|
||||
accesskey="&browserContext.accesskey;"
|
||||
type="radio"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="sp-menu-resetContext"
|
||||
command="sp-cmd-resetContext"
|
||||
label="&resetContext.label;"
|
||||
accesskey="&resetContext.accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="sp-tools-menu"
|
||||
label="&toolsMenu.label;"
|
||||
accesskey="&toolsMenu.accesskey;">
|
||||
<menupopup id="sp-menu-tools">
|
||||
<menuitem id="sp-menu-errorConsole" hidden="true"
|
||||
label="&errorConsoleCmd.label;"
|
||||
accesskey="&errorConsoleCmd.accesskey;"
|
||||
key="sp-key-errorConsole"
|
||||
command="sp-cmd-errorConsole"/>
|
||||
<menuitem id="sp-menu-webConsole"
|
||||
label="&webConsoleCmd.label;"
|
||||
accesskey="&webConsoleCmd.accesskey;"
|
||||
key="sp-key-webConsole"
|
||||
command="sp-cmd-webConsole"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
@ -329,15 +313,16 @@
|
|||
accesskey="&display.accesskey;"
|
||||
key="sp-key-display"
|
||||
command="sp-cmd-display"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="sp-text-resetContext"
|
||||
label="&resetContext.label;"
|
||||
accesskey="&resetContext.accesskey;"
|
||||
command="sp-cmd-resetContext"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
<hbox id="scratchpad-editor" flex="1" context="scratchpad-text-popup" />
|
||||
<notificationbox id="scratchpad-notificationbox" flex="1">
|
||||
<hbox id="scratchpad-editor" flex="1" context="scratchpad-text-popup" />
|
||||
</notificationbox>
|
||||
|
||||
<statusbar id="scratchpad-statusbar" align="end">
|
||||
<statusbarpanel id="scratchpad-status"
|
||||
label="&contentContext.label;"
|
||||
class="statusbarpanel-iconic-text"/>
|
||||
<spacer flex="1"/>
|
||||
</statusbar>
|
||||
</window>
|
||||
|
|
|
@ -35,11 +35,11 @@ function runTests()
|
|||
let sp = gScratchpadWindow.Scratchpad;
|
||||
ok(sp, "Scratchpad object exists in new window");
|
||||
|
||||
let chromeContextMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-menu-browser");
|
||||
ok(chromeContextMenu, "Chrome context menuitem element exists");
|
||||
ok(!chromeContextMenu.hasAttribute("hidden"),
|
||||
"Chrome context menuitem is visible");
|
||||
let environmentMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-environment-menu");
|
||||
ok(environmentMenu, "Environment menu element exists");
|
||||
ok(!environmentMenu.hasAttribute("hidden"),
|
||||
"Environment menu is visible");
|
||||
|
||||
let errorConsoleCommand = gScratchpadWindow.document.
|
||||
getElementById("sp-cmd-errorConsole");
|
||||
|
@ -47,12 +47,6 @@ function runTests()
|
|||
ok(!errorConsoleCommand.hasAttribute("disabled"),
|
||||
"Error console command is enabled");
|
||||
|
||||
let errorConsoleMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-menu-errorConsole");
|
||||
ok(errorConsoleMenu, "Error console menu element exists");
|
||||
ok(!errorConsoleMenu.hasAttribute("hidden"),
|
||||
"Error console menuitem is visible");
|
||||
|
||||
let chromeContextCommand = gScratchpadWindow.document.
|
||||
getElementById("sp-cmd-browserContext");
|
||||
ok(chromeContextCommand, "Chrome context command element exists");
|
||||
|
|
|
@ -28,11 +28,11 @@ function runTests()
|
|||
|
||||
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
|
||||
let chromeMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
|
||||
let statusbar = sp.statusbarStatus;
|
||||
let notificationBox = sp.notificationBox;
|
||||
|
||||
ok(contentMenu, "found #sp-menu-content");
|
||||
ok(chromeMenu, "found #sp-menu-browser");
|
||||
ok(statusbar, "found Scratchpad.statusbarStatus");
|
||||
ok(notificationBox, "found Scratchpad.notificationBox");
|
||||
|
||||
sp.setContentContext();
|
||||
|
||||
|
@ -45,8 +45,8 @@ function runTests()
|
|||
ok(!chromeMenu.hasAttribute("checked"),
|
||||
"chrome menuitem is not checked");
|
||||
|
||||
is(statusbar.getAttribute("label"), contentMenu.getAttribute("label"),
|
||||
"statusbar label is correct");
|
||||
ok(!notificationBox.currentNotification,
|
||||
"there is no notification in content context");
|
||||
|
||||
sp.setText("window.foobarBug636725 = 'aloha';");
|
||||
|
||||
|
@ -69,8 +69,8 @@ function runTests()
|
|||
ok(!contentMenu.hasAttribute("checked"),
|
||||
"content menuitem is not checked");
|
||||
|
||||
is(statusbar.getAttribute("label"), chromeMenu.getAttribute("label"),
|
||||
"statusbar label is correct");
|
||||
ok(notificationBox.currentNotification,
|
||||
"there is a notification in browser context");
|
||||
|
||||
sp.setText("2'", 31, 33);
|
||||
|
||||
|
|
|
@ -32,11 +32,11 @@ function runTests()
|
|||
is(typeof sp.inspect, "function", "Scratchpad.inspect() exists");
|
||||
is(typeof sp.display, "function", "Scratchpad.display() exists");
|
||||
|
||||
let chromeContextMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-menu-browser");
|
||||
ok(chromeContextMenu, "Chrome context menuitem element exists");
|
||||
is(chromeContextMenu.getAttribute("hidden"), "true",
|
||||
"Chrome context menuitem is hidden");
|
||||
let environmentMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-environment-menu");
|
||||
ok(environmentMenu, "Environment menu element exists");
|
||||
ok(environmentMenu.hasAttribute("hidden"),
|
||||
"Environment menu is not visible");
|
||||
|
||||
let errorConsoleCommand = gScratchpadWindow.document.
|
||||
getElementById("sp-cmd-errorConsole");
|
||||
|
@ -44,12 +44,6 @@ function runTests()
|
|||
is(errorConsoleCommand.getAttribute("disabled"), "true",
|
||||
"Error console command is disabled");
|
||||
|
||||
let errorConsoleMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-menu-errorConsole");
|
||||
ok(errorConsoleMenu, "Error console menu element exists");
|
||||
is(errorConsoleMenu.getAttribute("hidden"), "true",
|
||||
"Error console menu item is hidden");
|
||||
|
||||
let chromeContextCommand = gScratchpadWindow.document.
|
||||
getElementById("sp-cmd-browserContext");
|
||||
ok(chromeContextCommand, "Chrome context command element exists");
|
||||
|
|
|
@ -38,11 +38,11 @@ function runTests()
|
|||
|
||||
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
|
||||
let browserMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
|
||||
let statusbar = sp.statusbarStatus;
|
||||
let notificationBox = sp.notificationBox;
|
||||
|
||||
ok(contentMenu, "found #sp-menu-content");
|
||||
ok(browserMenu, "found #sp-menu-browser");
|
||||
ok(statusbar, "found Scratchpad.statusbarStatus");
|
||||
ok(notificationBox, "found Scratchpad.notificationBox");
|
||||
|
||||
sp.setContentContext();
|
||||
|
||||
|
@ -55,8 +55,8 @@ function runTests()
|
|||
ok(!browserMenu.hasAttribute("checked"),
|
||||
"chrome menuitem is not checked");
|
||||
|
||||
is(statusbar.getAttribute("label"), contentMenu.getAttribute("label"),
|
||||
"statusbar label is correct");
|
||||
is(notificationBox.currentNotification, null,
|
||||
"there is no notification currently shown for content context");
|
||||
|
||||
sp.setText("window.foosbug653108 = 'aloha';");
|
||||
|
||||
|
|
|
@ -36,11 +36,9 @@ function runTests()
|
|||
"sp-text-run": "run",
|
||||
"sp-text-inspect": "inspect",
|
||||
"sp-text-display": "display",
|
||||
"sp-text-resetContext": "resetContext",
|
||||
"sp-menu-content": "setContentContext",
|
||||
"sp-menu-browser": "setBrowserContext",
|
||||
"sp-menu-resetContext": "resetContext",
|
||||
"sp-menu-errorConsole": "openErrorConsole",
|
||||
"sp-menu-webConsole": "openWebConsole",
|
||||
"sp-menu-undo": "undo",
|
||||
"sp-menu-redo": "redo",
|
||||
};
|
||||
|
|
|
@ -12,15 +12,17 @@
|
|||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is HUDService code.
|
||||
# The Original Code is the Style Inspector.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation.
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com> (Original author)
|
||||
# Mike Ratcliffe <mratcliffe@mozilla.com> (Original author)
|
||||
# Joe Walker <jwalker@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -44,12 +46,11 @@ VPATH = @srcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
# DIRS += test # no tests yet
|
||||
endif
|
||||
DIRS += test
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/Templater.jsm $(FINAL_TARGET)/modules/devtools
|
||||
$(NSINSTALL) $(srcdir)/Promise.jsm $(FINAL_TARGET)/modules/devtools
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "Promise" ];
|
||||
|
||||
/**
|
||||
* Create an unfulfilled promise
|
||||
* @constructor
|
||||
*/
|
||||
function Promise() {
|
||||
this._status = Promise.PENDING;
|
||||
this._value = undefined;
|
||||
this._onSuccessHandlers = [];
|
||||
this._onErrorHandlers = [];
|
||||
|
||||
// Debugging help
|
||||
this._id = Promise._nextId++;
|
||||
Promise._outstanding[this._id] = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* We give promises and ID so we can track which are outstanding
|
||||
*/
|
||||
Promise._nextId = 0;
|
||||
|
||||
/**
|
||||
* Outstanding promises. Handy list for debugging only
|
||||
*/
|
||||
Promise._outstanding = [];
|
||||
|
||||
/**
|
||||
* Recently resolved promises. Also for debugging only
|
||||
*/
|
||||
Promise._recent = [];
|
||||
|
||||
/**
|
||||
* A promise can be in one of 2 states.
|
||||
* The ERROR and SUCCESS states are terminal, the PENDING state is the only
|
||||
* start state.
|
||||
*/
|
||||
Promise.ERROR = -1;
|
||||
Promise.PENDING = 0;
|
||||
Promise.SUCCESS = 1;
|
||||
|
||||
/**
|
||||
* Yeay for RTTI
|
||||
*/
|
||||
Promise.prototype.isPromise = true;
|
||||
|
||||
/**
|
||||
* Have we either been resolve()ed or reject()ed?
|
||||
*/
|
||||
Promise.prototype.isComplete = function() {
|
||||
return this._status != Promise.PENDING;
|
||||
};
|
||||
|
||||
/**
|
||||
* Have we resolve()ed?
|
||||
*/
|
||||
Promise.prototype.isResolved = function() {
|
||||
return this._status == Promise.SUCCESS;
|
||||
};
|
||||
|
||||
/**
|
||||
* Have we reject()ed?
|
||||
*/
|
||||
Promise.prototype.isRejected = function() {
|
||||
return this._status == Promise.ERROR;
|
||||
};
|
||||
|
||||
/**
|
||||
* Take the specified action of fulfillment of a promise, and (optionally)
|
||||
* a different action on promise rejection
|
||||
*/
|
||||
Promise.prototype.then = function(onSuccess, onError) {
|
||||
if (typeof onSuccess === 'function') {
|
||||
if (this._status === Promise.SUCCESS) {
|
||||
onSuccess.call(null, this._value);
|
||||
}
|
||||
else if (this._status === Promise.PENDING) {
|
||||
this._onSuccessHandlers.push(onSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof onError === 'function') {
|
||||
if (this._status === Promise.ERROR) {
|
||||
onError.call(null, this._value);
|
||||
}
|
||||
else if (this._status === Promise.PENDING) {
|
||||
this._onErrorHandlers.push(onError);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Like then() except that rather than returning <tt>this</tt> we return
|
||||
* a promise which resolves when the original promise resolves
|
||||
*/
|
||||
Promise.prototype.chainPromise = function(onSuccess) {
|
||||
var chain = new Promise();
|
||||
chain._chainedFrom = this;
|
||||
this.then(function(data) {
|
||||
try {
|
||||
chain.resolve(onSuccess(data));
|
||||
}
|
||||
catch (ex) {
|
||||
chain.reject(ex);
|
||||
}
|
||||
}, function(ex) {
|
||||
chain.reject(ex);
|
||||
});
|
||||
return chain;
|
||||
};
|
||||
|
||||
/**
|
||||
* Supply the fulfillment of a promise
|
||||
*/
|
||||
Promise.prototype.resolve = function(data) {
|
||||
return this._complete(this._onSuccessHandlers,
|
||||
Promise.SUCCESS, data, 'resolve');
|
||||
};
|
||||
|
||||
/**
|
||||
* Renege on a promise
|
||||
*/
|
||||
Promise.prototype.reject = function(data) {
|
||||
return this._complete(this._onErrorHandlers, Promise.ERROR, data, 'reject');
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal method to be called on resolve() or reject()
|
||||
* @private
|
||||
*/
|
||||
Promise.prototype._complete = function(list, status, data, name) {
|
||||
// Complain if we've already been completed
|
||||
if (this._status != Promise.PENDING) {
|
||||
if (typeof 'console' === 'object') {
|
||||
console.error('Promise complete. Attempted ' + name + '() with ', data);
|
||||
console.error('Prev status = ', this._status, ', value = ', this._value);
|
||||
}
|
||||
throw new Error('Promise already complete');
|
||||
}
|
||||
|
||||
this._status = status;
|
||||
this._value = data;
|
||||
|
||||
// Call all the handlers, and then delete them
|
||||
list.forEach(function(handler) {
|
||||
handler.call(null, this._value);
|
||||
}, this);
|
||||
delete this._onSuccessHandlers;
|
||||
delete this._onErrorHandlers;
|
||||
|
||||
// Remove the given {promise} from the _outstanding list, and add it to the
|
||||
// _recent list, pruning more than 20 recent promises from that list
|
||||
delete Promise._outstanding[this._id];
|
||||
// The original code includes this very useful debugging aid, however there
|
||||
// is concern that it will create a memory leak, so we leave it out here.
|
||||
/*
|
||||
Promise._recent.push(this);
|
||||
while (Promise._recent.length > 20) {
|
||||
Promise._recent.shift();
|
||||
}
|
||||
*/
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes an array of promises and returns a promise that that is fulfilled once
|
||||
* all the promises in the array are fulfilled
|
||||
* @param promiseList The array of promises
|
||||
* @return the promise that is fulfilled when all the array is fulfilled
|
||||
*/
|
||||
Promise.group = function(promiseList) {
|
||||
if (!Array.isArray(promiseList)) {
|
||||
promiseList = Array.prototype.slice.call(arguments);
|
||||
}
|
||||
|
||||
// If the original array has nothing in it, return now to avoid waiting
|
||||
if (promiseList.length === 0) {
|
||||
return new Promise().resolve([]);
|
||||
}
|
||||
|
||||
var groupPromise = new Promise();
|
||||
var results = [];
|
||||
var fulfilled = 0;
|
||||
|
||||
var onSuccessFactory = function(index) {
|
||||
return function(data) {
|
||||
results[index] = data;
|
||||
fulfilled++;
|
||||
// If the group has already failed, silently drop extra results
|
||||
if (groupPromise._status !== Promise.ERROR) {
|
||||
if (fulfilled === promiseList.length) {
|
||||
groupPromise.resolve(results);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
promiseList.forEach(function(promise, index) {
|
||||
var onSuccess = onSuccessFactory(index);
|
||||
var onError = groupPromise.reject.bind(groupPromise);
|
||||
promise.then(onSuccess, onError);
|
||||
});
|
||||
|
||||
return groupPromise;
|
||||
};
|
|
@ -1,5 +1,3 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -13,11 +11,11 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Bespin.
|
||||
* The Original Code is GCLI
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
|
@ -39,14 +37,10 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Templater"];
|
||||
var EXPORTED_SYMBOLS = [ "Templater" ];
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const Node = Ci.nsIDOMNode;
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
const Node = Components.interfaces.nsIDOMNode;
|
||||
|
||||
// WARNING: do not 'use_strict' without reading the notes in _envEval();
|
||||
|
||||
|
@ -263,9 +257,9 @@ Templater.prototype._processForEachMember = function(member, template, siblingNo
|
|||
try {
|
||||
this._handleAsync(member, siblingNode, function(reply, node) {
|
||||
data[paramName] = reply;
|
||||
if (node.nodeName.toLowerCase() === 'loop') {
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
var clone = node.childNodes[i].cloneNode(true);
|
||||
if (template.nodeName.toLowerCase() === 'loop') {
|
||||
for (var i = 0; i < template.childNodes.length; i++) {
|
||||
var clone = template.childNodes[i].cloneNode(true);
|
||||
node.parentNode.insertBefore(clone, node);
|
||||
this.processNode(clone, data);
|
||||
}
|
||||
|
@ -331,7 +325,7 @@ Templater.prototype._toNode = function(thing, document) {
|
|||
if (thing == null) {
|
||||
thing = '' + thing;
|
||||
}
|
||||
// if (isDOMElement(reply)) { ... }
|
||||
// if thing isn't a DOM element then wrap its string value in one
|
||||
if (typeof thing.cloneNode !== 'function') {
|
||||
thing = document.createTextNode(thing.toString());
|
||||
}
|
||||
|
@ -387,7 +381,7 @@ Templater.prototype._stripBraces = function(str) {
|
|||
* </ul>
|
||||
* @param path An array of strings indicating the path through the data, or
|
||||
* a string to be cut into an array using <tt>split('.')</tt>
|
||||
* @param data An object to look in for the <tt>path</tt> argument
|
||||
* @param data the data to use for node processing
|
||||
* @param newValue (optional) If defined, this value will replace the
|
||||
* original value for the data at the path specified.
|
||||
* @return The value pointed to by <tt>path</tt> before any
|
||||
|
@ -470,4 +464,3 @@ Templater.prototype._handleError = function(message, ex) {
|
|||
Templater.prototype._logError = function(message) {
|
||||
Services.console.logStringMessage(message);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is GCLI.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation.
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Joe Walker <jwalker@mozilla.com> (Original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = browser/devtools/shared/test
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_promise_basic.js \
|
||||
browser_templater_basic.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
_BROWSER_TEST_PAGES = \
|
||||
browser_templater_basic.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
||||
libs:: $(_BROWSER_TEST_PAGES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
|
@ -0,0 +1,212 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that our Promise implementation works properly
|
||||
|
||||
Cu.import("resource:///modules/devtools/Promise.jsm");
|
||||
|
||||
function test() {
|
||||
addTab("about:blank", function() {
|
||||
info("Starting Promise Tests");
|
||||
testBasic();
|
||||
});
|
||||
}
|
||||
|
||||
var postResolution;
|
||||
|
||||
function testBasic() {
|
||||
postResolution = new Promise();
|
||||
ok(postResolution.isPromise, "We have a promise");
|
||||
ok(!postResolution.isComplete(), "Promise is initially incomplete");
|
||||
ok(!postResolution.isResolved(), "Promise is initially unresolved");
|
||||
ok(!postResolution.isRejected(), "Promise is initially unrejected");
|
||||
|
||||
// Test resolve() *after* then() in the same context
|
||||
var reply = postResolution.then(testPostResolution, fail)
|
||||
.resolve("postResolution");
|
||||
is(reply, postResolution, "return this; working ok");
|
||||
}
|
||||
|
||||
var preResolution;
|
||||
|
||||
function testPostResolution(data) {
|
||||
is(data, "postResolution", "data is postResolution");
|
||||
ok(postResolution.isComplete(), "postResolution Promise is complete");
|
||||
ok(postResolution.isResolved(), "postResolution Promise is resolved");
|
||||
ok(!postResolution.isRejected(), "postResolution Promise is unrejected");
|
||||
|
||||
try {
|
||||
info("Expected double resolve error");
|
||||
postResolution.resolve("double resolve");
|
||||
ok(false, "double resolve");
|
||||
}
|
||||
catch (ex) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
// Test resolve() *before* then() in the same context
|
||||
preResolution = new Promise();
|
||||
var reply = preResolution.resolve("preResolution")
|
||||
.then(testPreResolution, fail);
|
||||
is(reply, preResolution, "return this; working ok");
|
||||
}
|
||||
|
||||
var laterResolution;
|
||||
|
||||
function testPreResolution(data) {
|
||||
is(data, "preResolution", "data is preResolution");
|
||||
ok(preResolution.isComplete(), "preResolution Promise is complete");
|
||||
ok(preResolution.isResolved(), "preResolution Promise is resolved");
|
||||
ok(!preResolution.isRejected(), "preResolution Promise is unrejected");
|
||||
|
||||
// Test resolve() *after* then() in a later context
|
||||
laterResolution = new Promise();
|
||||
laterResolution.then(testLaterResolution, fail);
|
||||
executeSoon(function() {
|
||||
laterResolution.resolve("laterResolution");
|
||||
});
|
||||
}
|
||||
|
||||
var laterRejection;
|
||||
|
||||
function testLaterResolution(data) {
|
||||
is(data, "laterResolution", "data is laterResolution");
|
||||
ok(laterResolution.isComplete(), "laterResolution Promise is complete");
|
||||
ok(laterResolution.isResolved(), "laterResolution Promise is resolved");
|
||||
ok(!laterResolution.isRejected(), "laterResolution Promise is unrejected");
|
||||
|
||||
// Test reject() *after* then() in a later context
|
||||
laterRejection = new Promise().then(fail, testLaterRejection);
|
||||
executeSoon(function() {
|
||||
laterRejection.reject("laterRejection");
|
||||
});
|
||||
}
|
||||
|
||||
function testLaterRejection(data) {
|
||||
is(data, "laterRejection", "data is laterRejection");
|
||||
ok(laterRejection.isComplete(), "laterRejection Promise is complete");
|
||||
ok(!laterRejection.isResolved(), "laterRejection Promise is unresolved");
|
||||
ok(laterRejection.isRejected(), "laterRejection Promise is rejected");
|
||||
|
||||
// Test chaining
|
||||
var orig = new Promise();
|
||||
orig.chainPromise(function(data) {
|
||||
is(data, "origData", "data is origData");
|
||||
return data.replace(/orig/, "new");
|
||||
}).then(function(data) {
|
||||
is(data, "newData", "data is newData");
|
||||
testChain();
|
||||
});
|
||||
orig.resolve("origData");
|
||||
}
|
||||
|
||||
var member1;
|
||||
var member2;
|
||||
var member3;
|
||||
var laterGroup;
|
||||
|
||||
function testChain() {
|
||||
// Test an empty group
|
||||
var empty1 = Promise.group();
|
||||
ok(empty1.isComplete(), "empty1 Promise is complete");
|
||||
ok(empty1.isResolved(), "empty1 Promise is resolved");
|
||||
ok(!empty1.isRejected(), "empty1 Promise is unrejected");
|
||||
|
||||
// Test a group with no members
|
||||
var empty2 = Promise.group([]);
|
||||
ok(empty2.isComplete(), "empty2 Promise is complete");
|
||||
ok(empty2.isResolved(), "empty2 Promise is resolved");
|
||||
ok(!empty2.isRejected(), "empty2 Promise is unrejected");
|
||||
|
||||
// Test grouping using resolve() in a later context
|
||||
member1 = new Promise();
|
||||
member2 = new Promise();
|
||||
member3 = new Promise();
|
||||
laterGroup = Promise.group(member1, member2, member3);
|
||||
laterGroup.then(testLaterGroup, fail);
|
||||
|
||||
member1.then(function(data) {
|
||||
is(data, "member1", "member1 is member1");
|
||||
executeSoon(function() {
|
||||
member2.resolve("member2");
|
||||
});
|
||||
}, fail);
|
||||
member2.then(function(data) {
|
||||
is(data, "member2", "member2 is member2");
|
||||
executeSoon(function() {
|
||||
member3.resolve("member3");
|
||||
});
|
||||
}, fail);
|
||||
member3.then(function(data) {
|
||||
is(data, "member3", "member3 is member3");
|
||||
// The group should now fire
|
||||
}, fail);
|
||||
executeSoon(function() {
|
||||
member1.resolve("member1");
|
||||
});
|
||||
}
|
||||
|
||||
var tidyGroup;
|
||||
|
||||
function testLaterGroup(data) {
|
||||
is(data[0], "member1", "member1 is member1");
|
||||
is(data[1], "member2", "member2 is member2");
|
||||
is(data[2], "member3", "member3 is member3");
|
||||
is(data.length, 3, "data.length is right");
|
||||
ok(laterGroup.isComplete(), "laterGroup Promise is complete");
|
||||
ok(laterGroup.isResolved(), "laterGroup Promise is resolved");
|
||||
ok(!laterGroup.isRejected(), "laterGroup Promise is unrejected");
|
||||
|
||||
// Test grouping resolve() *before* then() in the same context
|
||||
tidyGroup = Promise.group([
|
||||
postResolution, preResolution, laterResolution,
|
||||
member1, member2, member3, laterGroup
|
||||
]);
|
||||
tidyGroup.then(testTidyGroup, fail);
|
||||
}
|
||||
|
||||
var failGroup;
|
||||
|
||||
function testTidyGroup(data) {
|
||||
is(data[0], "postResolution", "postResolution is postResolution");
|
||||
is(data[1], "preResolution", "preResolution is preResolution");
|
||||
is(data[2], "laterResolution", "laterResolution is laterResolution");
|
||||
is(data[3], "member1", "member1 is member1");
|
||||
is(data[6][1], "member2", "laterGroup is laterGroup");
|
||||
is(data.length, 7, "data.length is right");
|
||||
ok(tidyGroup.isComplete(), "tidyGroup Promise is complete");
|
||||
ok(tidyGroup.isResolved(), "tidyGroup Promise is resolved");
|
||||
ok(!tidyGroup.isRejected(), "tidyGroup Promise is unrejected");
|
||||
|
||||
// Test grouping resolve() *before* then() in the same context
|
||||
failGroup = Promise.group(postResolution, laterRejection);
|
||||
failGroup.then(fail, testFailGroup);
|
||||
}
|
||||
|
||||
function testFailGroup(data) {
|
||||
is(data, "laterRejection", "laterRejection is laterRejection");
|
||||
|
||||
postResolution = undefined;
|
||||
preResolution = undefined;
|
||||
laterResolution = undefined;
|
||||
member1 = undefined;
|
||||
member2 = undefined;
|
||||
member3 = undefined;
|
||||
laterGroup = undefined;
|
||||
laterRejection = undefined;
|
||||
|
||||
finished();
|
||||
}
|
||||
|
||||
function fail() {
|
||||
gBrowser.removeCurrentTab();
|
||||
info("Failed Promise Tests");
|
||||
ok(false, "fail called");
|
||||
finish();
|
||||
}
|
||||
|
||||
function finished() {
|
||||
gBrowser.removeCurrentTab();
|
||||
info("Finishing Promise Tests");
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>DOM Template Tests</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the DOM Template engine works properly
|
||||
|
||||
Cu.import("resource:///modules/devtools/Templater.jsm");
|
||||
Cu.import("resource:///modules/devtools/Promise.jsm");
|
||||
|
||||
function test() {
|
||||
addTab("http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html", function() {
|
||||
info("Starting DOM Templater Tests");
|
||||
runTest(0);
|
||||
});
|
||||
}
|
||||
|
||||
function runTest(index) {
|
||||
var options = tests[index] = tests[index]();
|
||||
var holder = content.document.createElement('div');
|
||||
holder.id = options.name;
|
||||
var body = content.document.body;
|
||||
body.appendChild(holder);
|
||||
holder.innerHTML = options.template;
|
||||
|
||||
info('Running ' + options.name);
|
||||
new Templater().processNode(holder, options.data);
|
||||
|
||||
if (typeof options.result == 'string') {
|
||||
is(holder.innerHTML, options.result, options.name);
|
||||
}
|
||||
else {
|
||||
ok(holder.innerHTML.match(options.result), options.name);
|
||||
}
|
||||
|
||||
if (options.also) {
|
||||
options.also(options);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
index++;
|
||||
if (index < tests.length) {
|
||||
runTest(index);
|
||||
}
|
||||
else {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
if (options.later) {
|
||||
var ais = is.bind(this);
|
||||
|
||||
function createTester(holder, options) {
|
||||
return function() {
|
||||
ais(holder.innerHTML, options.later, options.name + ' later');
|
||||
runNextTest();
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
executeSoon(createTester(holder, options));
|
||||
}
|
||||
else {
|
||||
runNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function finished() {
|
||||
gBrowser.removeCurrentTab();
|
||||
info("Finishing DOM Templater Tests");
|
||||
tests = null;
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Why have an array of functions that return data rather than just an array
|
||||
* of the data itself? Some of these tests contain calls to delayReply() which
|
||||
* sets up async processing using executeSoon(). Since the execution of these
|
||||
* tests is asynchronous, the delayed reply will probably arrive before the
|
||||
* test is executed, making the test be synchronous. So we wrap the data in a
|
||||
* function so we only set it up just before we use it.
|
||||
*/
|
||||
var tests = [
|
||||
function() { return {
|
||||
name: 'simpleNesting',
|
||||
template: '<div id="ex1">${nested.value}</div>',
|
||||
data: { nested:{ value:'pass 1' } },
|
||||
result: '<div id="ex1">pass 1</div>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'returnDom',
|
||||
template: '<div id="ex2">${__element.ownerDocument.createTextNode(\'pass 2\')}</div>',
|
||||
data: {},
|
||||
result: '<div id="ex2">pass 2</div>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'srcChange',
|
||||
template: '<img _src="${fred}" id="ex3">',
|
||||
data: { fred:'green.png' },
|
||||
result: /<img( id="ex3")? src="green.png"( id="ex3")?>/
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'ifTrue',
|
||||
template: '<p if="${name !== \'jim\'}">hello ${name}</p>',
|
||||
data: { name: 'fred' },
|
||||
result: '<p>hello fred</p>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'ifFalse',
|
||||
template: '<p if="${name !== \'jim\'}">hello ${name}</p>',
|
||||
data: { name: 'jim' },
|
||||
result: ''
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'simpleLoop',
|
||||
template: '<p foreach="index in ${[ 1, 2, 3 ]}">${index}</p>',
|
||||
data: {},
|
||||
result: '<p>1</p><p>2</p><p>3</p>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'loopElement',
|
||||
template: '<loop foreach="i in ${array}">${i}</loop>',
|
||||
data: { array: [ 1, 2, 3 ] },
|
||||
result: '123'
|
||||
};},
|
||||
|
||||
// Bug 692031: DOMTemplate async loops do not drop the loop element
|
||||
function() { return {
|
||||
name: 'asyncLoopElement',
|
||||
template: '<loop foreach="i in ${array}">${i}</loop>',
|
||||
data: { array: delayReply([1, 2, 3]) },
|
||||
result: '<span></span>',
|
||||
later: '123'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'saveElement',
|
||||
template: '<p save="${element}">${name}</p>',
|
||||
data: { name: 'pass 8' },
|
||||
result: '<p>pass 8</p>',
|
||||
also: function(options) {
|
||||
ok(options.data.element.innerHTML, 'pass 9', 'saveElement saved');
|
||||
delete options.data.element;
|
||||
}
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'useElement',
|
||||
template: '<p id="pass9">${adjust(__element)}</p>',
|
||||
data: {
|
||||
adjust: function(element) {
|
||||
is('pass9', element.id, 'useElement adjust');
|
||||
return 'pass 9b'
|
||||
}
|
||||
},
|
||||
result: '<p id="pass9">pass 9b</p>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'asyncInline',
|
||||
template: '${delayed}',
|
||||
data: { delayed: delayReply('inline') },
|
||||
result: '<span></span>',
|
||||
later: 'inline'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'asyncArray',
|
||||
template: '<p foreach="i in ${delayed}">${i}</p>',
|
||||
data: { delayed: delayReply([1, 2, 3]) },
|
||||
result: '<span></span>',
|
||||
later: '<p>1</p><p>2</p><p>3</p>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'asyncMember',
|
||||
template: '<p foreach="i in ${delayed}">${i}</p>',
|
||||
data: { delayed: [delayReply(4), delayReply(5), delayReply(6)] },
|
||||
result: '<span></span><span></span><span></span>',
|
||||
later: '<p>4</p><p>5</p><p>6</p>'
|
||||
};},
|
||||
|
||||
function() { return {
|
||||
name: 'asyncBoth',
|
||||
template: '<p foreach="i in ${delayed}">${i}</p>',
|
||||
data: {
|
||||
delayed: delayReply([
|
||||
delayReply(4),
|
||||
delayReply(5),
|
||||
delayReply(6)
|
||||
])
|
||||
},
|
||||
result: '<span></span>',
|
||||
later: '<p>4</p><p>5</p><p>6</p>'
|
||||
};}
|
||||
];
|
||||
|
||||
function delayReply(data) {
|
||||
var p = new Promise();
|
||||
executeSoon(function() {
|
||||
p.resolve(data);
|
||||
});
|
||||
return p;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DevTools test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (Original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let tab;
|
||||
let browser;
|
||||
|
||||
function addTab(aURL, aCallback)
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
function onTabLoad() {
|
||||
browser.removeEventListener("load", onTabLoad, true);
|
||||
aCallback();
|
||||
}
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
content.location = aURL;
|
||||
|
||||
tab = gBrowser.selectedTab;
|
||||
browser = gBrowser.getBrowserForTab(tab);
|
||||
|
||||
browser.addEventListener("load", onTabLoad, true);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function tearDown() {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
tab = undefined;
|
||||
browser = undefined;
|
||||
});
|
|
@ -8,8 +8,8 @@ The Orion editor web site: http://www.eclipse.org/orion
|
|||
|
||||
To upgrade Orion to a newer version see the UPGRADE file.
|
||||
|
||||
Orion version: git clone from 2011-07-06 (after the 0.2 release)
|
||||
commit hash b19bc0b0f4e2843823bb1b8c8b4a64395c59e617
|
||||
Orion version: git clone from 2011-10-07
|
||||
commit hash eedba6403b6dff4536bc0469d31126c3485deb56
|
||||
|
||||
# License
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
.rulerLines {
|
||||
background: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
min-width: 1.4em;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
|
@ -8,53 +8,75 @@
|
|||
}
|
||||
|
||||
.viewContent {
|
||||
}.ruler_annotation {
|
||||
background-color: #e1ebfb;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.ruler_annotation_todo {
|
||||
}
|
||||
|
||||
.ruler_annotation_todo_overview {
|
||||
background-color: lightgreen;
|
||||
border: 1px solid green;
|
||||
}
|
||||
|
||||
.ruler_annotation_breakpoint {
|
||||
}
|
||||
|
||||
.ruler_annotation_breakpoint_overview {
|
||||
background-color: lightblue;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
|
||||
.ruler_lines {
|
||||
background-color: #e1ebfb;
|
||||
border-right: 1px solid #b1badf;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ruler_overview {
|
||||
background-color: #e1ebfb;
|
||||
}
|
||||
|
||||
.ruler_lines_even {
|
||||
background-color: #e1ebfb;
|
||||
}
|
||||
|
||||
.ruler_lines_odd {
|
||||
}/* Styles for rulers */
|
||||
.ruler {
|
||||
background-color: white;
|
||||
}
|
||||
.ruler.annotations {
|
||||
border-right: 1px solid lightgray;
|
||||
width: 16px;
|
||||
}
|
||||
.ruler.folding {
|
||||
border-right: 1px solid lightgray;
|
||||
width: 14px;
|
||||
}
|
||||
.ruler.lines {
|
||||
border-right: 1px solid lightgray;
|
||||
text-align: right;
|
||||
}
|
||||
.ruler.overview {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.token_comment {
|
||||
/* Styles for the line number ruler */
|
||||
.rulerLines {
|
||||
background-color: white;
|
||||
}
|
||||
.rulerLines.even
|
||||
.rulerLines.odd {
|
||||
}
|
||||
|
||||
/* Styles for the ruler tooltips */
|
||||
.rulerTooltip {
|
||||
font-family: monospace;
|
||||
font-size: 10pt;
|
||||
background-color: InfoBackground;
|
||||
color: InfoText;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid black;
|
||||
z-index: 100;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
white-space: pre;
|
||||
}
|
||||
.rulerTooltip em {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}.token_singleline_comment {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.token_javadoc {
|
||||
.token_multiline_comment {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.token_doc_comment {
|
||||
color: #00008F;
|
||||
}
|
||||
|
||||
.token_doc_html_markup {
|
||||
color: #7F7F9F;
|
||||
}
|
||||
|
||||
.token_doc_tag {
|
||||
color: #7F9FBF;
|
||||
}
|
||||
|
||||
.token_task_tag {
|
||||
color: #7F9FBF;
|
||||
}
|
||||
|
||||
.token_string {
|
||||
color: blue;
|
||||
}
|
||||
|
@ -74,20 +96,24 @@
|
|||
}
|
||||
|
||||
.token_space {
|
||||
background-image: url('/examples/textview/images/white_space.png');
|
||||
/* images/white_space.png */
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAABnRSTlMA/wAAAACkwsAdAAAAIUlEQVR4nGP4z8CAC+GUIEXuABhgkTuABEiRw2cmae4EAH05X7xDolNRAAAAAElFTkSuQmCC");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.token_tab {
|
||||
background-image: url('/examples/textview/images/white_tab.png');
|
||||
/* images/white_tab.png */
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAJCAIAAACJ2loDAAAABnRSTlMA/wD/AP83WBt9AAAAMklEQVR4nGP4TwRgoK6i52c3bz5w6zMSA6tJn28d2Lx589nnCAYu63AaSLxJRLoJPwAAeNk0aG4opfMAAAAASUVORK5CYII=");
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
.line_caret {
|
||||
background-color: #EAF2FE;
|
||||
}/* Styling for html syntax highlighting */
|
||||
}
|
||||
|
||||
/* Styling for html syntax highlighting */
|
||||
.entity-name-tag {
|
||||
color: #3f7f7f;
|
||||
}
|
||||
|
@ -112,4 +138,4 @@
|
|||
.invalid {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -57,7 +57,8 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|||
* SourceEditor.THEMES to Orion CSS files.
|
||||
*/
|
||||
const ORION_THEMES = {
|
||||
textmate: "chrome://browser/content/orion.css",
|
||||
textmate: ["chrome://browser/content/orion.css",
|
||||
"chrome://browser/content/orion-mozilla.css"],
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -196,9 +197,9 @@ SourceEditor.prototype = {
|
|||
});
|
||||
|
||||
if (config.showLineNumbers) {
|
||||
this._lines_ruler = new textview.LineNumberRuler("left",
|
||||
{styleClass: "ruler_lines", style: {minWidth: "1.4em"}},
|
||||
{styleClass: "ruler_lines_even"}, {styleClass: "ruler_lines_even"});
|
||||
this._lines_ruler = new textview.LineNumberRuler(null, "left",
|
||||
{styleClass: "rulerLines"}, {styleClass: "rulerLine odd"},
|
||||
{styleClass: "rulerLine even"});
|
||||
|
||||
this._view.addRuler(this._lines_ruler);
|
||||
}
|
||||
|
@ -390,7 +391,7 @@ SourceEditor.prototype = {
|
|||
|
||||
let model = this._model;
|
||||
let lineIndex = model.getLineAtOffset(selection.start);
|
||||
let lineText = model.getLine(lineIndex);
|
||||
let lineText = model.getLine(lineIndex, true);
|
||||
let lineStart = model.getLineStart(lineIndex);
|
||||
let index = 0;
|
||||
let lineOffset = selection.start - lineStart;
|
||||
|
|
|
@ -145,35 +145,10 @@ function editorLoaded()
|
|||
|
||||
is(editor.getCaretOffset(), 8, "caret moved to the left");
|
||||
|
||||
EventUtils.synthesizeKey("a", {accelKey: true}, testWin);
|
||||
|
||||
is(editor.getSelectedText(), "code-ed.aitor",
|
||||
"select all worked");
|
||||
|
||||
EventUtils.synthesizeKey("x", {accelKey: true}, testWin);
|
||||
|
||||
ok(!editor.getText(), "cut works");
|
||||
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
|
||||
is(editor.getText(), "code-ed.aitorcode-ed.aitor", "paste works");
|
||||
|
||||
editor.setText("foo");
|
||||
|
||||
EventUtils.synthesizeKey("a", {accelKey: true}, testWin);
|
||||
EventUtils.synthesizeKey("c", {accelKey: true}, testWin);
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
|
||||
is(editor.getText(), "foofoo", "ctrl-a, c, v, v works");
|
||||
|
||||
is(editor.getCaretOffset(), 6, "caret location is correct");
|
||||
|
||||
EventUtils.synthesizeKey(".", {}, testWin);
|
||||
EventUtils.synthesizeKey("VK_TAB", {}, testWin);
|
||||
|
||||
is(editor.getText(), "foofoo. ", "Tab works");
|
||||
is(editor.getText(), "code-ed.. aitor", "Tab works");
|
||||
|
||||
is(editor.getCaretOffset(), 14, "caret location is correct");
|
||||
|
||||
|
@ -276,24 +251,8 @@ function editorLoaded()
|
|||
is(event.removedCharCount, 0, "event.removedCharCount is correct");
|
||||
is(event.addedCharCount, 1, "event.addedCharCount is correct");
|
||||
|
||||
let chars = editor.getText().length;
|
||||
event = null;
|
||||
|
||||
EventUtils.synthesizeKey("a", {accelKey: true}, testWin);
|
||||
EventUtils.synthesizeKey("c", {accelKey: true}, testWin);
|
||||
|
||||
editor.setCaretOffset(chars);
|
||||
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
|
||||
ok(event, "the TextChanged event fired after paste");
|
||||
is(event.start, chars, "event.start is correct");
|
||||
is(event.removedCharCount, 0, "event.removedCharCount is correct");
|
||||
is(event.addedCharCount, chars, "event.addedCharCount is correct");
|
||||
|
||||
editor.setText("line1\nline2\nline3");
|
||||
chars = editor.getText().length;
|
||||
|
||||
let chars = editor.getText().length;
|
||||
event = null;
|
||||
|
||||
editor.setText("a\nline4\nline5", chars);
|
||||
|
@ -303,6 +262,7 @@ function editorLoaded()
|
|||
is(event.removedCharCount, 0, "event.removedCharCount is correct");
|
||||
is(event.addedCharCount, 13, "event.addedCharCount is correct");
|
||||
|
||||
event = null;
|
||||
editor.setText("line3b\nline4b\nfoo", 12, 24);
|
||||
|
||||
ok(event, "the TextChanged event fired after setText() again");
|
||||
|
@ -312,8 +272,11 @@ function editorLoaded()
|
|||
|
||||
editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, eventHandler);
|
||||
|
||||
// Done.
|
||||
testClipboardEvents();
|
||||
}
|
||||
|
||||
function testEnd()
|
||||
{
|
||||
editor.destroy();
|
||||
ok(!editor.parentElement && !editor.editorElement, "destroy() works");
|
||||
|
||||
|
@ -361,3 +324,75 @@ function testReturnKey()
|
|||
"return maintains indentation (again)");
|
||||
}
|
||||
|
||||
function testClipboardEvents()
|
||||
{
|
||||
editor.setText("foobar");
|
||||
|
||||
let doCut = function() {
|
||||
EventUtils.synthesizeKey("a", {accelKey: true}, testWin);
|
||||
|
||||
is(editor.getSelectedText(), "foobar", "select all worked");
|
||||
|
||||
EventUtils.synthesizeKey("x", {accelKey: true}, testWin);
|
||||
};
|
||||
|
||||
let onCut = function() {
|
||||
ok(!editor.getText(), "cut works");
|
||||
editor.setText("test--");
|
||||
editor.setCaretOffset(5);
|
||||
|
||||
editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste1);
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
};
|
||||
|
||||
let onPaste1 = function() {
|
||||
editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste1);
|
||||
|
||||
is(editor.getText(), "test-foobar-", "paste works");
|
||||
|
||||
executeSoon(waitForClipboard.bind(this, "test", doCopy, onCopy, testEnd));
|
||||
};
|
||||
|
||||
let doCopy = function() {
|
||||
editor.setSelection(0, 4);
|
||||
EventUtils.synthesizeKey("c", {accelKey: true}, testWin);
|
||||
};
|
||||
|
||||
let onCopy = function() {
|
||||
editor.setSelection(5, 11);
|
||||
editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste2);
|
||||
EventUtils.synthesizeKey("v", {accelKey: true}, testWin);
|
||||
};
|
||||
|
||||
let pasteTextChanges = 0;
|
||||
let removedCharCount = 0;
|
||||
let addedCharCount = 0;
|
||||
let onPaste2 = function(aEvent) {
|
||||
pasteTextChanges++;
|
||||
ok(aEvent && (pasteTextChanges == 1 || pasteTextChanges == 2),
|
||||
"event TEXT_CHANGED fired " + pasteTextChanges + " time(s)");
|
||||
|
||||
is(aEvent.start, 5, "event.start is correct");
|
||||
if (aEvent.removedCharCount) {
|
||||
removedCharCount = aEvent.removedCharCount;
|
||||
}
|
||||
if (aEvent.addedCharCount) {
|
||||
addedCharCount = aEvent.addedCharCount;
|
||||
}
|
||||
|
||||
if (pasteTextChanges == 2 || addedCharCount && removedCharCount) {
|
||||
editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste2);
|
||||
executeSoon(checkPaste2Result);
|
||||
}
|
||||
};
|
||||
|
||||
let checkPaste2Result = function() {
|
||||
is(removedCharCount, 6, "event.removedCharCount is correct");
|
||||
is(addedCharCount, 4, "event.addedCharCount is correct");
|
||||
|
||||
is(editor.getText(), "test-test-", "paste works after copy");
|
||||
testEnd();
|
||||
};
|
||||
|
||||
waitForClipboard("foobar", doCut, onCut, testEnd);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is GCLI Commands.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
let EXPORTED_SYMBOLS = [ "GcliCommands" ];
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/gcli.jsm");
|
||||
Components.utils.import("resource:///modules/HUDService.jsm");
|
||||
|
||||
let bundleName = "chrome://browser/locale/devtools/gclicommands.properties";
|
||||
let stringBundle = Services.strings.createBundle(bundleName);
|
||||
|
||||
let gcli = gcli._internal.require("gcli/index");
|
||||
let canon = gcli._internal.require("gcli/canon");
|
||||
|
||||
|
||||
let document;
|
||||
|
||||
/**
|
||||
* The exported API
|
||||
*/
|
||||
let GcliCommands = {
|
||||
/**
|
||||
* Allow HUDService to inform us of the document against which we work
|
||||
*/
|
||||
setDocument: function GcliCommands_setDocument(aDocument) {
|
||||
document = aDocument;
|
||||
},
|
||||
|
||||
/**
|
||||
* Undo the effects of GcliCommands.setDocument()
|
||||
*/
|
||||
unsetDocument: function GcliCommands_unsetDocument() {
|
||||
document = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Lookup a string in the GCLI string bundle
|
||||
* @param aName The name to lookup
|
||||
* @return The looked up name
|
||||
*/
|
||||
function lookup(aName)
|
||||
{
|
||||
try {
|
||||
return stringBundle.GetStringFromName(aName);
|
||||
} catch (ex) {
|
||||
throw new Error("Failure in lookup('" + aName + "')");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup a string in the GCLI string bundle
|
||||
* @param aName The name to lookup
|
||||
* @param aSwaps An array of swaps. See stringBundle.formatStringFromName
|
||||
* @return The looked up name
|
||||
*/
|
||||
function lookupFormat(aName, aSwaps)
|
||||
{
|
||||
try {
|
||||
return stringBundle.formatStringFromName(aName, aSwaps, aSwaps.length);
|
||||
} catch (ex) {
|
||||
Services.console.logStringMessage("Failure in lookupFormat('" + aName + "')");
|
||||
throw new Error("Failure in lookupFormat('" + aName + "')");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'echo' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "echo",
|
||||
description: lookup("echoDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "message",
|
||||
type: "string",
|
||||
description: lookup("echoMessageDesc")
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
exec: function Command_echo(args, context) {
|
||||
return args.message;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'help' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "help",
|
||||
returnType: "html",
|
||||
description: lookup("helpDesc"),
|
||||
exec: function Command_help(args, context) {
|
||||
let output = [];
|
||||
|
||||
output.push("<strong>" + lookup("helpAvailable") + ":</strong><br/>");
|
||||
|
||||
let commandNames = canon.getCommandNames();
|
||||
commandNames.sort();
|
||||
|
||||
output.push("<table>");
|
||||
for (let i = 0; i < commandNames.length; i++) {
|
||||
let command = canon.getCommand(commandNames[i]);
|
||||
if (!command.hidden && command.description) {
|
||||
output.push("<tr>");
|
||||
output.push('<th class="gcliCmdHelpRight">' + command.name + "</th>");
|
||||
output.push("<td>→ " + command.description + "</td>");
|
||||
output.push("</tr>");
|
||||
}
|
||||
}
|
||||
output.push("</table>");
|
||||
|
||||
return output.join("");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'console' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "console",
|
||||
description: lookup("consoleDesc"),
|
||||
manual: lookup("consoleManual")
|
||||
});
|
||||
|
||||
/**
|
||||
* 'console clear' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "console clear",
|
||||
description: lookup("consoleclearDesc"),
|
||||
exec: function(args, context) {
|
||||
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||
hud.gcliterm.clearOutput();
|
||||
}
|
||||
});
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
* Julian Viereck <jviereck@mozilla.com>
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
* Joe Walker <jwalker@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -72,6 +73,18 @@ XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
|||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gcli", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/gcli.jsm", obj);
|
||||
return obj.gcli;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "GcliCommands", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/GcliCommands.jsm", obj);
|
||||
return obj.GcliCommands;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/devtools/StyleInspector.jsm", obj);
|
||||
|
@ -1481,6 +1494,24 @@ HUD_SERVICE.prototype =
|
|||
if (!aAnimated || hudRef.consolePanel) {
|
||||
this.disableAnimation(hudId);
|
||||
}
|
||||
|
||||
// Create a processing instruction for GCLIs CSS stylesheet, but only if
|
||||
// we don't have one for this document. Also record the context we're
|
||||
// adding this for so we know when to remove it.
|
||||
let procInstr = aContext.ownerDocument.gcliCssProcInstr;
|
||||
if (!procInstr) {
|
||||
procInstr = aContext.ownerDocument.createProcessingInstruction(
|
||||
"xml-stylesheet",
|
||||
"href='chrome://browser/skin/devtools/gcli.css' type='text/css'");
|
||||
procInstr.contexts = [];
|
||||
|
||||
let root = aContext.ownerDocument.getElementsByTagName('window')[0];
|
||||
root.parentNode.insertBefore(procInstr, root);
|
||||
aContext.ownerDocument.gcliCssProcInstr = procInstr;
|
||||
}
|
||||
if (procInstr.contexts.indexOf(hudId) == -1) {
|
||||
procInstr.contexts.push(hudId);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1512,6 +1543,20 @@ HUD_SERVICE.prototype =
|
|||
|
||||
window.focus();
|
||||
}
|
||||
|
||||
// Remove this context from the list of contexts that need the GCLI CSS
|
||||
// processing instruction and then remove the processing instruction if it
|
||||
// isn't needed any more.
|
||||
let procInstr = aContext.ownerDocument.gcliCssProcInstr;
|
||||
if (procInstr) {
|
||||
procInstr.contexts = procInstr.contexts.filter(function(id) {
|
||||
return id !== hudId;
|
||||
});
|
||||
if (procInstr.contexts.length == 0 && procInstr.parentNode) {
|
||||
procInstr.parentNode.removeChild(procInstr);
|
||||
delete aContext.ownerDocument.gcliCssProcInstr;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1750,7 +1795,12 @@ HUD_SERVICE.prototype =
|
|||
// Remove children from the output. If the output is not cleared, there can
|
||||
// be leaks as some nodes has node.onclick = function; set and GC can't
|
||||
// remove the nodes then.
|
||||
hud.jsterm.clearOutput();
|
||||
if (hud.jsterm) {
|
||||
hud.jsterm.clearOutput();
|
||||
}
|
||||
if (hud.gcliterm) {
|
||||
hud.gcliterm.clearOutput();
|
||||
}
|
||||
|
||||
hud.destroy();
|
||||
|
||||
|
@ -1769,7 +1819,9 @@ HUD_SERVICE.prototype =
|
|||
hud.splitter.parentNode.removeChild(hud.splitter);
|
||||
}
|
||||
|
||||
hud.jsterm.autocompletePopup.destroy();
|
||||
if (hud.jsterm) {
|
||||
hud.jsterm.autocompletePopup.destroy();
|
||||
}
|
||||
|
||||
delete this.hudReferences[aHUDId];
|
||||
|
||||
|
@ -3091,7 +3143,12 @@ function HeadsUpDisplay(aConfig)
|
|||
// create the JSTerm input element
|
||||
try {
|
||||
this.createConsoleInput(this.contentWindow, this.consoleWrap, this.outputNode);
|
||||
this.jsterm.inputNode.focus();
|
||||
if (this.jsterm) {
|
||||
this.jsterm.inputNode.focus();
|
||||
}
|
||||
if (this.gcliterm) {
|
||||
this.gcliterm.inputNode.focus();
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
|
@ -3212,6 +3269,9 @@ HeadsUpDisplay.prototype = {
|
|||
if (this.jsterm) {
|
||||
this.jsterm.inputNode.focus();
|
||||
}
|
||||
if (this.gcliterm) {
|
||||
this.gcliterm.inputNode.focus();
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
panel.addEventListener("popupshown", onPopupShown,false);
|
||||
|
@ -3403,6 +3463,9 @@ HeadsUpDisplay.prototype = {
|
|||
if (this.jsterm) {
|
||||
this.jsterm.inputNode.focus();
|
||||
}
|
||||
if (this.gcliterm) {
|
||||
this.gcliterm.inputNode.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -3434,6 +3497,11 @@ HeadsUpDisplay.prototype = {
|
|||
*/
|
||||
jsterm: null,
|
||||
|
||||
/**
|
||||
* The GcliTerm object that contains the console's GCLI
|
||||
*/
|
||||
gcliterm: null,
|
||||
|
||||
/**
|
||||
* creates and attaches the console input node
|
||||
*
|
||||
|
@ -3443,12 +3511,24 @@ HeadsUpDisplay.prototype = {
|
|||
createConsoleInput:
|
||||
function HUD_createConsoleInput(aWindow, aParentNode, aExistingConsole)
|
||||
{
|
||||
var context = Cu.getWeakReference(aWindow);
|
||||
let usegcli = false;
|
||||
try {
|
||||
usegcli = Services.prefs.getBoolPref("devtools.gcli.enable");
|
||||
}
|
||||
catch (ex) {}
|
||||
|
||||
if (appName() == "FIREFOX") {
|
||||
let mixin = new JSTermFirefoxMixin(context, aParentNode,
|
||||
aExistingConsole);
|
||||
this.jsterm = new JSTerm(context, aParentNode, mixin, this.console);
|
||||
if (!usegcli) {
|
||||
let context = Cu.getWeakReference(aWindow);
|
||||
let mixin = new JSTermFirefoxMixin(context, aParentNode,
|
||||
aExistingConsole);
|
||||
this.jsterm = new JSTerm(context, aParentNode, mixin, this.console);
|
||||
}
|
||||
else {
|
||||
this.gcliterm = new GcliTerm(aWindow, this.hudId, this.chromeDocument,
|
||||
this.console, this.hintNode);
|
||||
aParentNode.appendChild(this.gcliterm.element);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("Unsupported Gecko Application");
|
||||
|
@ -3471,14 +3551,17 @@ HeadsUpDisplay.prototype = {
|
|||
this.consolePanel.label = this.getPanelTitle();
|
||||
}
|
||||
|
||||
if (!this.jsterm) {
|
||||
this.createConsoleInput(this.contentWindow, this.consoleWrap, this.outputNode);
|
||||
}
|
||||
else {
|
||||
if (this.jsterm) {
|
||||
this.jsterm.context = Cu.getWeakReference(this.contentWindow);
|
||||
this.jsterm.console = this.console;
|
||||
this.jsterm.createSandbox();
|
||||
}
|
||||
else if (this.gcliterm) {
|
||||
this.gcliterm.reattachConsole(this.contentWindow, this.console);
|
||||
}
|
||||
else {
|
||||
this.createConsoleInput(this.contentWindow, this.consoleWrap, this.outputNode);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -3522,14 +3605,6 @@ HeadsUpDisplay.prototype = {
|
|||
consoleWrap.setAttribute("class", "hud-console-wrapper");
|
||||
consoleWrap.setAttribute("flex", "1");
|
||||
|
||||
this.outputNode = this.makeXULNode("richlistbox");
|
||||
this.outputNode.setAttribute("class", "hud-output-node");
|
||||
this.outputNode.setAttribute("flex", "1");
|
||||
this.outputNode.setAttribute("orient", "vertical");
|
||||
this.outputNode.setAttribute("context", this.hudId + "-output-contextmenu");
|
||||
this.outputNode.setAttribute("style", "direction: ltr;");
|
||||
this.outputNode.setAttribute("seltype", "multiple");
|
||||
|
||||
this.filterSpacer = this.makeXULNode("spacer");
|
||||
this.filterSpacer.setAttribute("flex", "1");
|
||||
|
||||
|
@ -3548,9 +3623,36 @@ HeadsUpDisplay.prototype = {
|
|||
let consoleFilterToolbar = this.makeFilterToolbar();
|
||||
consoleFilterToolbar.setAttribute("id", "viewGroup");
|
||||
this.consoleFilterToolbar = consoleFilterToolbar;
|
||||
consoleWrap.appendChild(consoleFilterToolbar);
|
||||
|
||||
consoleWrap.appendChild(this.outputNode);
|
||||
let hintSpacerNode = this.makeXULNode("box");
|
||||
hintSpacerNode.setAttribute("flex", 1);
|
||||
|
||||
this.hintNode = this.makeXULNode("div");
|
||||
this.hintNode.setAttribute("class", "gcliterm-hint-node");
|
||||
|
||||
let hintParentNode = this.makeXULNode("vbox");
|
||||
hintParentNode.setAttribute("flex", "0");
|
||||
hintParentNode.setAttribute("class", "gcliterm-hint-parent");
|
||||
hintParentNode.appendChild(hintSpacerNode);
|
||||
hintParentNode.appendChild(this.hintNode);
|
||||
hintParentNode.hidden = true;
|
||||
|
||||
let hbox = this.makeXULNode("hbox");
|
||||
hbox.setAttribute("flex", "1");
|
||||
|
||||
this.outputNode = this.makeXULNode("richlistbox");
|
||||
this.outputNode.setAttribute("class", "hud-output-node");
|
||||
this.outputNode.setAttribute("flex", "1");
|
||||
this.outputNode.setAttribute("orient", "vertical");
|
||||
this.outputNode.setAttribute("context", this.hudId + "-output-contextmenu");
|
||||
this.outputNode.setAttribute("style", "direction: ltr;");
|
||||
this.outputNode.setAttribute("seltype", "multiple");
|
||||
|
||||
hbox.appendChild(hintParentNode);
|
||||
hbox.appendChild(this.outputNode);
|
||||
|
||||
consoleWrap.appendChild(consoleFilterToolbar);
|
||||
consoleWrap.appendChild(hbox);
|
||||
|
||||
outerWrap.appendChild(consoleWrap);
|
||||
|
||||
|
@ -3865,7 +3967,13 @@ HeadsUpDisplay.prototype = {
|
|||
{
|
||||
let hudId = this.hudId;
|
||||
function HUD_clearButton_onCommand() {
|
||||
HUDService.getHudReferenceById(hudId).jsterm.clearOutput();
|
||||
let hud = HUDService.getHudReferenceById(hudId);
|
||||
if (hud.jsterm) {
|
||||
hud.jsterm.clearOutput();
|
||||
}
|
||||
if (hud.gcliterm) {
|
||||
hud.gcliterm.clearOutput();
|
||||
}
|
||||
}
|
||||
|
||||
let clearButton = this.makeXULNode("toolbarbutton");
|
||||
|
@ -3936,7 +4044,12 @@ HeadsUpDisplay.prototype = {
|
|||
*/
|
||||
destroy: function HUD_destroy()
|
||||
{
|
||||
this.jsterm.destroy();
|
||||
if (this.jsterm) {
|
||||
this.jsterm.destroy();
|
||||
}
|
||||
if (this.gcliterm) {
|
||||
this.gcliterm.destroy();
|
||||
}
|
||||
|
||||
this.positionMenuitems.above.removeEventListener("command",
|
||||
this._positionConsoleAbove, false);
|
||||
|
@ -5431,6 +5544,7 @@ JSTermFirefoxMixin.prototype = {
|
|||
this.completeNode.setAttribute("class", "jsterm-complete-node");
|
||||
this.completeNode.setAttribute("multiline", "true");
|
||||
this.completeNode.setAttribute("rows", "1");
|
||||
this.completeNode.setAttribute("tabindex", "-1");
|
||||
|
||||
this.inputNode = this.xulElementFactory("textbox");
|
||||
this.inputNode.setAttribute("class", "jsterm-input-node");
|
||||
|
@ -5444,22 +5558,15 @@ JSTermFirefoxMixin.prototype = {
|
|||
inputStack.appendChild(this.inputNode);
|
||||
|
||||
if (this.existingConsoleNode == undefined) {
|
||||
this.outputNode = this.xulElementFactory("vbox");
|
||||
this.outputNode.setAttribute("class", "jsterm-output-node");
|
||||
|
||||
this.term = this.xulElementFactory("vbox");
|
||||
this.term.setAttribute("class", "jsterm-wrapper-node");
|
||||
this.term.setAttribute("flex", "1");
|
||||
this.term.appendChild(this.outputNode);
|
||||
throw new Error("This can't happen");
|
||||
}
|
||||
else {
|
||||
this.outputNode = this.existingConsoleNode;
|
||||
|
||||
this.term = this.xulElementFactory("hbox");
|
||||
this.term.setAttribute("class", "jsterm-input-container");
|
||||
this.term.setAttribute("style", "direction: ltr;");
|
||||
this.term.appendChild(inputStack);
|
||||
}
|
||||
this.outputNode = this.existingConsoleNode;
|
||||
|
||||
this.term = this.xulElementFactory("hbox");
|
||||
this.term.setAttribute("class", "jsterm-input-container");
|
||||
this.term.setAttribute("style", "direction: ltr;");
|
||||
this.term.appendChild(inputStack);
|
||||
},
|
||||
|
||||
get inputValue()
|
||||
|
@ -5591,9 +5698,8 @@ ConsoleUtils = {
|
|||
function ConsoleUtils_createMessageNode(aDocument, aCategory, aSeverity,
|
||||
aBody, aHUDId, aSourceURL,
|
||||
aSourceLine, aClipboardText, aLevel) {
|
||||
if (aBody instanceof Ci.nsIDOMNode && aClipboardText == null) {
|
||||
throw new Error("HUDService.createMessageNode(): DOM node supplied " +
|
||||
"without any clipboard text");
|
||||
if (typeof aBody != "string" && aClipboardText == null && aBody.innerText) {
|
||||
aClipboardText = aBody.innerText;
|
||||
}
|
||||
|
||||
// Make the icon container, which is a vertical box. Its purpose is to
|
||||
|
@ -5632,6 +5738,13 @@ ConsoleUtils = {
|
|||
aBody = aBody instanceof Ci.nsIDOMNode && !(aLevel == "dir") ?
|
||||
aBody : aDocument.createTextNode(aBody);
|
||||
|
||||
if (!aBody.nodeType) {
|
||||
aBody = aDocument.createTextNode(aBody.toString());
|
||||
}
|
||||
if (typeof aBody == "string") {
|
||||
aBody = aDocument.createTextNode(aBody);
|
||||
}
|
||||
|
||||
bodyNode.appendChild(aBody);
|
||||
|
||||
let repeatContainer = aDocument.createElementNS(XUL_NS, "hbox");
|
||||
|
@ -6761,3 +6874,235 @@ catch (ex) {
|
|||
// TODO: kill anything that may have started up
|
||||
// see bug 568665
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GcliTerm
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* GcliTerm
|
||||
*
|
||||
* Initialize GCLI by creating a set of startup options from the available
|
||||
* properties.
|
||||
*
|
||||
* @param nsIDOMWindow aContentWindow
|
||||
* The content window that we're providing as the context to commands
|
||||
* @param string aHudId
|
||||
* The HUD to which we should send console messages.
|
||||
* @param nsIDOMDocument aDocument
|
||||
* The DOM document from which to create nodes.
|
||||
* @param object aConsole
|
||||
* Console object to use within the GcliTerm.
|
||||
* @param nsIDOMElement aHintNode
|
||||
* The node to which we add GCLI's hints.
|
||||
* @constructor
|
||||
*/
|
||||
function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode)
|
||||
{
|
||||
this.context = Cu.getWeakReference(aContentWindow);
|
||||
this.hudId = aHudId;
|
||||
this.document = aDocument;
|
||||
this.console = aConsole;
|
||||
this.hintNode = aHintNode;
|
||||
|
||||
this.createUI();
|
||||
this.createSandbox();
|
||||
|
||||
this.show = this.show.bind(this);
|
||||
this.hide = this.hide.bind(this);
|
||||
|
||||
this.opts = {
|
||||
environment: { hudId: this.hudId },
|
||||
chromeDocument: this.document,
|
||||
contentDocument: aContentWindow.document,
|
||||
jsEnvironment: {
|
||||
globalObject: aContentWindow,
|
||||
evalFunction: this.evalInSandbox.bind(this)
|
||||
},
|
||||
inputElement: this.inputNode,
|
||||
completeElement: this.completeNode,
|
||||
inputBackgroundElement: this.inputStack,
|
||||
hintElement: this.hintNode,
|
||||
completionPrompt: "",
|
||||
gcliTerm: this
|
||||
};
|
||||
|
||||
gcli._internal.commandOutputManager.addListener(this.onCommandOutput, this);
|
||||
gcli._internal.createView(this.opts);
|
||||
GcliCommands.setDocument(aContentWindow.document);
|
||||
}
|
||||
|
||||
GcliTerm.prototype = {
|
||||
/**
|
||||
* Remove the hint column from the display.
|
||||
*/
|
||||
hide: function GcliTerm_hide()
|
||||
{
|
||||
this.hintNode.parentNode.hidden = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Undo the effects of calling hide().
|
||||
*/
|
||||
show: function GcliTerm_show()
|
||||
{
|
||||
this.hintNode.parentNode.hidden = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the GcliTerm object. Call this method to avoid memory leaks.
|
||||
*/
|
||||
destroy: function Gcli_destroy()
|
||||
{
|
||||
GcliCommands.unsetDocument();
|
||||
gcli._internal.removeView(this.opts);
|
||||
gcli._internal.commandOutputManager.removeListener(this.onCommandOutput, this);
|
||||
|
||||
delete this.opts.chromeDocument;
|
||||
delete this.opts.inputElement;
|
||||
delete this.opts.completeElement;
|
||||
delete this.opts.inputBackgroundElement;
|
||||
delete this.opts.hintElement;
|
||||
delete this.opts.contentDocument;
|
||||
delete this.opts.jsEnvironment;
|
||||
delete this.opts.gcliTerm;
|
||||
|
||||
delete this.context;
|
||||
delete this.document;
|
||||
delete this.console;
|
||||
delete this.hintNode;
|
||||
|
||||
delete this.sandbox;
|
||||
delete this.element
|
||||
delete this.inputStack
|
||||
delete this.completeNode
|
||||
delete this.inputNode
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-attaches a console when the contentWindow is recreated.
|
||||
*
|
||||
* @param nsIDOMWindow aContentWindow
|
||||
* The content window that we're providing as the context to commands
|
||||
* @param object aConsole
|
||||
* Console object to use within the GcliTerm.
|
||||
*/
|
||||
reattachConsole: function Gcli_reattachConsole(aContentWindow, aConsole)
|
||||
{
|
||||
this.context = Cu.getWeakReference(aContentWindow);
|
||||
this.console = aConsole;
|
||||
this.createSandbox();
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates and attaches the GCLI Terminal part of the Web Console, which
|
||||
* essentially consists of the interactive JavaScript input facility.
|
||||
*/
|
||||
createUI: function Gcli_createUI()
|
||||
{
|
||||
this.element = this.document.createElement("vbox");
|
||||
this.element.setAttribute("class", "gcliterm-input-container");
|
||||
this.element.setAttribute("flex", "0");
|
||||
|
||||
this.inputStack = this.document.createElement("stack");
|
||||
this.inputStack.setAttribute("class", "gcliterm-stack-node");
|
||||
this.element.appendChild(this.inputStack);
|
||||
|
||||
this.completeNode = this.document.createElement("div");
|
||||
this.completeNode.setAttribute("class", "gcliterm-complete-node");
|
||||
this.completeNode.setAttribute("aria-live", "polite");
|
||||
this.inputStack.appendChild(this.completeNode);
|
||||
|
||||
this.inputNode = this.document.createElement("textbox");
|
||||
this.inputNode.setAttribute("class", "gcliterm-input-node");
|
||||
this.inputNode.setAttribute("rows", "1");
|
||||
this.inputStack.appendChild(this.inputNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by GCLI/canon when command line output changes.
|
||||
*/
|
||||
onCommandOutput: function Gcli_onCommandOutput(aEvent)
|
||||
{
|
||||
// When we can update the history of the console, then we should stop
|
||||
// filtering incomplete reports.
|
||||
if (!aEvent.output.completed) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.writeOutput(aEvent.output.typed, { category: CATEGORY_INPUT });
|
||||
|
||||
if (aEvent.output.output == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let output = aEvent.output.output;
|
||||
if (aEvent.output.command.returnType == "html" && typeof output == "string") {
|
||||
let frag = this.document.createRange().createContextualFragment(
|
||||
'<div xmlns="' + HTML_NS + '" xmlns:xul="' + XUL_NS + '">' +
|
||||
output + '</div>');
|
||||
|
||||
output = this.document.createElementNS(HTML_NS, "div");
|
||||
output.appendChild(frag);
|
||||
}
|
||||
this.writeOutput(output);
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the eval sandbox, should be called whenever we are attached.
|
||||
*/
|
||||
createSandbox: function Gcli_createSandbox()
|
||||
{
|
||||
let win = this.context.get().QueryInterface(Ci.nsIDOMWindow);
|
||||
|
||||
// create a JS Sandbox out of this.context
|
||||
this.sandbox = new Cu.Sandbox(win, {
|
||||
sandboxPrototype: win,
|
||||
wantXrays: false
|
||||
});
|
||||
this.sandbox.console = this.console;
|
||||
},
|
||||
|
||||
/**
|
||||
* Evaluates a string in the sandbox.
|
||||
*
|
||||
* @param string aString
|
||||
* String to evaluate in the sandbox
|
||||
* @return The result of the evaluation
|
||||
*/
|
||||
evalInSandbox: function Gcli_evalInSandbox(aString)
|
||||
{
|
||||
return Cu.evalInSandbox(aString, this.sandbox, "1.8", "Web Console", 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes a message to the HUD that originates from the interactive
|
||||
* JavaScript console.
|
||||
*
|
||||
* @param string aOutputMessage
|
||||
* The message to display.
|
||||
* @param number aCategory
|
||||
* One of the CATEGORY_ constants.
|
||||
* @param number aSeverity
|
||||
* One of the SEVERITY_ constants.
|
||||
*/
|
||||
writeOutput: function Gcli_writeOutput(aOutputMessage, aOptions)
|
||||
{
|
||||
aOptions = aOptions || {};
|
||||
|
||||
let node = ConsoleUtils.createMessageNode(
|
||||
this.document,
|
||||
aOptions.category || CATEGORY_OUTPUT,
|
||||
aOptions.severity || SEVERITY_LOG,
|
||||
aOutputMessage,
|
||||
this.hudId,
|
||||
aOptions.sourceUrl || undefined,
|
||||
aOptions.sourceLine || undefined,
|
||||
aOptions.clipboardText || undefined);
|
||||
|
||||
ConsoleUtils.outputMessageNode(node, this.hudId);
|
||||
},
|
||||
|
||||
clearOutput: JSTerm.prototype.clearOutput,
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ EXTRA_JS_MODULES = \
|
|||
NetworkHelper.jsm \
|
||||
AutocompletePopup.jsm \
|
||||
gcli.jsm \
|
||||
GcliCommands.jsm \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES = \
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -108,7 +108,6 @@ _BROWSER_TEST_FILES = \
|
|||
browser_webconsole_bug_600183_charset.js \
|
||||
browser_webconsole_bug_601177_log_levels.js \
|
||||
browser_webconsole_bug_597460_filter_scroll.js \
|
||||
browser_webconsole_gcli_require.js \
|
||||
browser_webconsole_console_extras.js \
|
||||
browser_webconsole_bug_598357_jsterm_output.js \
|
||||
browser_webconsole_bug_603750_websocket.js \
|
||||
|
@ -146,6 +145,9 @@ _BROWSER_TEST_FILES = \
|
|||
browser_webconsole_bug_659907_console_dir.js \
|
||||
browser_webconsole_bug_678816.js \
|
||||
browser_webconsole_bug_664131_console_group.js \
|
||||
browser_gcli_require.js \
|
||||
browser_gcli_integrate.js \
|
||||
browser_gcli_web.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// For more information on GCLI see:
|
||||
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
|
||||
// - https://wiki.mozilla.org/DevTools/Features/GCLI
|
||||
|
||||
// Tests that source URLs in the Web Console can be clicked to display the
|
||||
// standard View Source window.
|
||||
|
||||
Components.utils.import("resource:///modules/gcli.jsm");
|
||||
let require = gcli._internal.require;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser/test-console.html";
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
require = undefined;
|
||||
Services.prefs.clearUserPref("devtools.gcli.enable");
|
||||
});
|
||||
|
||||
function test() {
|
||||
Services.prefs.setBoolPref("devtools.gcli.enable", true);
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", onLoad, false);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
try {
|
||||
openConsole();
|
||||
|
||||
testCreateCommands();
|
||||
testCallCommands();
|
||||
testRemoveCommands();
|
||||
}
|
||||
catch (ex) {
|
||||
gcli._internal.console.error('Test Failure', ex);
|
||||
}
|
||||
finally {
|
||||
closeConsole();
|
||||
finishTest();
|
||||
}
|
||||
}
|
||||
|
||||
let tselarr = {
|
||||
name: 'tselarr',
|
||||
params: [
|
||||
{ name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } },
|
||||
{ name: 'arr', type: { name: 'array', subtype: 'string' } },
|
||||
],
|
||||
exec: function(args, env) {
|
||||
return "flu " + args.num + "-" + args.arr.join("_");
|
||||
}
|
||||
};
|
||||
|
||||
function testCreateCommands() {
|
||||
let gcli = require("gcli/index");
|
||||
gcli.addCommand(tselarr);
|
||||
|
||||
let canon = require("gcli/canon");
|
||||
let tselcmd = canon.getCommand("tselarr");
|
||||
ok(tselcmd != null, "tselarr exists in the canon");
|
||||
ok(tselcmd instanceof canon.Command, "canon storing commands");
|
||||
}
|
||||
|
||||
function testCallCommands() {
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
let gcliterm = hud.gcliterm;
|
||||
ok(gcliterm, "We have a GCLI term");
|
||||
|
||||
// Test successful auto-completion
|
||||
gcliterm.inputNode.value = "h";
|
||||
gcliterm.inputNode.focus();
|
||||
EventUtils.synthesizeKey("e", {});
|
||||
is(gcliterm.completeNode.textContent, " help", "Completion for \"he\"");
|
||||
|
||||
// Test unsuccessful auto-completion
|
||||
gcliterm.inputNode.value = "ec";
|
||||
gcliterm.inputNode.focus();
|
||||
EventUtils.synthesizeKey("d", {});
|
||||
is(gcliterm.completeNode.textContent, " ecd", "Completion for \"ecd\"");
|
||||
|
||||
// Test a normal command's life cycle
|
||||
gcliterm.opts.inputter.setInput("echo hello world");
|
||||
gcliterm.opts.requisition.exec();
|
||||
|
||||
let nodes = hud.outputNode.querySelectorAll("description");
|
||||
|
||||
is(nodes.length, 2, "Right number of output nodes");
|
||||
ok(/hello world/.test(nodes[0].textContent), "the command's output is correct.");
|
||||
|
||||
gcliterm.clearOutput();
|
||||
}
|
||||
|
||||
function testRemoveCommands() {
|
||||
let gcli = require("gcli/index");
|
||||
gcli.removeCommand(tselarr);
|
||||
|
||||
let canon = require("gcli/canon");
|
||||
let tselcmd = canon.getCommand("tselarr");
|
||||
ok(tselcmd == null, "tselcmd removed from the canon");
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// For more information on GCLI see:
|
||||
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
|
||||
// - https://wiki.mozilla.org/DevTools/Features/GCLI
|
||||
|
||||
// Tests that source URLs in the Web Console can be clicked to display the
|
||||
// standard View Source window.
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,92 @@
|
|||
# LOCALIZATION NOTE These strings are used inside the Web Console
|
||||
# command line which is available from the Web Developer sub-menu
|
||||
# -> 'Web Console'.
|
||||
# The correct localization of this file might be to keep it in
|
||||
# English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (canonDescNone): Short string used to describe any command
|
||||
# or command parameter when no description has been provided.
|
||||
canonDescNone=(No description)
|
||||
|
||||
# LOCALIZATION NOTE (cliEvalJavascript): The special '{' command allows entry
|
||||
# of JavaScript like traditional developer tool command lines. This describes
|
||||
# the '{' command.
|
||||
cliEvalJavascript=Enter JavaScript directly
|
||||
|
||||
# LOCALIZATION NOTE (fieldSelectionSelect): When a command has a parameter
|
||||
# that has a number of pre-defined options the user interface presents these
|
||||
# in a drop-down menu, where the first 'option' is an indicator that a
|
||||
# selection should be made. This string describes that first option.
|
||||
fieldSelectionSelect=Select a %S ...
|
||||
|
||||
# LOCALIZATION NOTE (fieldArrayAdd): When a command has a parameter that can
|
||||
# be repeated a number of times (e.g. like the 'cat a.txt b.txt' command) the
|
||||
# user interface presents buttons to add and remove arguments. This string is
|
||||
# used to add arguments.
|
||||
fieldArrayAdd=Add
|
||||
|
||||
# LOCALIZATION NOTE (fieldArrayDel): When a command has a parameter that can
|
||||
# be repeated a number of times (e.g. like the 'cat a.txt b.txt' command) the
|
||||
# user interface presents buttons to add and remove arguments. This string is
|
||||
# used to remove arguments.
|
||||
fieldArrayDel=Delete
|
||||
|
||||
# LOCALIZATION NOTE (jstypeParseScope): The command line provides completion
|
||||
# for JavaScript commands, however there are times when the scope of what
|
||||
# we're completing against can't be used. This error message is displayed when
|
||||
# this happens.
|
||||
jstypeParseScope=Scope lost
|
||||
|
||||
# LOCALIZATION NOTE (jstypeParseMissing): When the command line is doing
|
||||
# JavaScript completion, sometimes the property to be completed does not
|
||||
# exist. This error message is displayed when this happens.
|
||||
jstypeParseMissing=Can't find property '%S'
|
||||
|
||||
# LOCALIZATION NOTE (jstypeBeginSyntax): When the command line is doing
|
||||
# JavaScript completion using invalid JavaScript, this error message is
|
||||
# displayed.
|
||||
jstypeBeginSyntax=Syntax error
|
||||
|
||||
# LOCALIZATION NOTE (jstypeBeginUnterm): When the command line is doing
|
||||
# JavaScript completion using a string that is not properly terminated, this
|
||||
# error message is displayed.
|
||||
jstypeBeginUnterm=Unterminated string literal
|
||||
|
||||
# LOCALIZATION NOTE (typesNumberNan): When the command line is passed a
|
||||
# number, however the input string is not a valid number, this error message
|
||||
# is displayed.
|
||||
typesNumberNan=Can't convert "%S" to a number.
|
||||
|
||||
# LOCALIZATION NOTE (typesNumberMax): When the command line is passed a
|
||||
# number, but the number is bigger than the largest allowed number, this error
|
||||
# message is displayed.
|
||||
typesNumberMax=%1$S is greater that maximum allowed: %2$S.
|
||||
|
||||
# LOCALIZATION NOTE (typesNumberMin): When the command line is passed a
|
||||
# number, but the number is lower than the smallest allowed number, this error
|
||||
# message is displayed.
|
||||
typesNumberMin=%1$S is smaller that minimum allowed: %2$S.
|
||||
|
||||
# LOCALIZATION NOTE (typesSelectionNomatch): When the command line is passed
|
||||
# an option with a limited number of correct values, but the passed value is
|
||||
# not one of them, this error message is displayed.
|
||||
typesSelectionNomatch=Can't use '%S'.
|
||||
|
||||
# LOCALIZATION NOTE (nodeParseSyntax): When the command line is expecting a
|
||||
# CSS query string, however the passed string is not valid, this error message
|
||||
# is displayed.
|
||||
nodeParseSyntax=Syntax error in CSS query
|
||||
|
||||
# LOCALIZATION NOTE (nodeParseMultiple): When the command line is expecting a
|
||||
# CSS string that matches a single node, but more than one node matches, this
|
||||
# error message is displayed.
|
||||
nodeParseMultiple=Too many matches (%S)
|
||||
|
||||
# LOCALIZATION NOTE (nodeParseNone): When the command line is expecting a CSS
|
||||
# string that matches a single node, but no nodes match, this error message is
|
||||
# displayed.
|
||||
nodeParseNone=No matches
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# LOCALIZATION NOTE These strings are used inside Web Console commands.
|
||||
# The Web Console command line is available from the Web Developer sub-menu
|
||||
# -> 'Web Console'.
|
||||
#
|
||||
# The correct localization of this file might be to keep it in
|
||||
# English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (echoDesc) A very short string used to describe the
|
||||
# function of the echo command.
|
||||
echoDesc=Show a message
|
||||
|
||||
# LOCALIZATION NOTE (echoMessageDesc) A very short string used to describe the
|
||||
# message parameter to the echo command.
|
||||
echoMessageDesc=Message
|
||||
|
||||
# LOCALIZATION NOTE (helpDesc) A very short string used to describe the
|
||||
# function of the help command.
|
||||
helpDesc=Get help on the available commands
|
||||
|
||||
# LOCALIZATION NOTE (helpAvailable) Used in the output of the help command to
|
||||
# explain the contents of the command help table.
|
||||
helpAvailable=Available Commands
|
||||
|
||||
# LOCALIZATION NOTE (consoleDesc) A very short string used to describe the
|
||||
# function of the console command.
|
||||
consoleDesc=Commands to control the console
|
||||
|
||||
# LOCALIZATION NOTE (consoleManual) A longer description describing the
|
||||
# set of commands that control the console.
|
||||
consoleManual=Filter, clear and close the web console
|
||||
|
||||
# LOCALIZATION NOTE (consoleclearDesc) A very short string used to describe the
|
||||
# function of the 'console clear' command.
|
||||
consoleclearDesc=Clear the console
|
|
@ -98,19 +98,14 @@
|
|||
<!-- LOCALIZATION NOTE (resetContext.label): This command allows the developer
|
||||
- to reset/clear the global object of the environment where the code executes.
|
||||
-->
|
||||
<!ENTITY resetContext.label "Reset">
|
||||
<!ENTITY resetContext.accesskey "R">
|
||||
<!ENTITY resetContext.label "Reset Variables">
|
||||
<!ENTITY resetContext.accesskey "T">
|
||||
|
||||
<!ENTITY executeMenu.label "Execute">
|
||||
<!ENTITY executeMenu.accesskey "X">
|
||||
|
||||
<!ENTITY toolsMenu.label "Tools">
|
||||
<!ENTITY toolsMenu.accesskey "T">
|
||||
|
||||
<!ENTITY errorConsoleCmd.label "Error Console">
|
||||
<!ENTITY errorConsoleCmd.accesskey "C">
|
||||
<!ENTITY errorConsoleCmd.commandkey "j">
|
||||
|
||||
<!ENTITY webConsoleCmd.label "Web Console">
|
||||
<!ENTITY webConsoleCmd.accesskey "W">
|
||||
<!ENTITY webConsoleCmd.commandkey "k">
|
||||
|
|
|
@ -33,3 +33,7 @@ saveFile.failed=The file save operation failed.
|
|||
# how to use the Scratchpad. Note that this should be a valid JavaScript
|
||||
# comment inside /* and */.
|
||||
scratchpadIntro=/*\n * This is a JavaScript Scratchpad.\n *\n * Enter some JavaScript, then Right Click or choose from the Execute Menu:\n * 1. Run to evaluate the selected text,\n * 2. Inspect to bring up an Object Inspector on the result, or,\n * 3. Display to insert the result in a comment after the selection.\n */\n\n
|
||||
|
||||
# LOCALIZATION NOTE (notification.browserContext): This is the message displayed
|
||||
# over the top of the editor when the user has switched to browser context.
|
||||
browserContext.notification=This scratchpad executes in the Browser context.
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
* locale/browser/browser.dtd (%chrome/browser/browser.dtd)
|
||||
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
|
||||
locale/browser/browser.properties (%chrome/browser/browser.properties)
|
||||
locale/browser/devtools/gcli.properties (%chrome/browser/devtools/gcli.properties)
|
||||
locale/browser/devtools/gclicommands.properties (%chrome/browser/devtools/gclicommands.properties)
|
||||
locale/browser/styleinspector.properties (%chrome/browser/styleinspector.properties)
|
||||
locale/browser/styleinspector.dtd (%chrome/browser/styleinspector.dtd)
|
||||
locale/browser/scratchpad.properties (%chrome/browser/scratchpad.properties)
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the GCLI.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* From: $GCLI/mozilla/gcli/ui/gcliterm.css */
|
||||
.gcliterm-input-node,
|
||||
.gcliterm-complete-node {
|
||||
border: none;
|
||||
-moz-appearance: none;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
background-color: transparent;
|
||||
font: 12px Consolas, "Lucida Console", monospace;
|
||||
padding: 2px 0 0 16px;
|
||||
}
|
||||
|
||||
.gcliterm-complete-node {
|
||||
color: #FFF;
|
||||
padding: 4px 4px 2px 21px;
|
||||
}
|
||||
|
||||
.gcliVALID {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.gcliINCOMPLETE {
|
||||
color: #DDD;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
.gcliERROR {
|
||||
color: #DDD;
|
||||
border-bottom: 1px dotted #F00;
|
||||
}
|
||||
|
||||
.gcliCompl {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliterm-stack-node {
|
||||
background: url("chrome://global/skin/icons/commandline.png") 4px center no-repeat;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gcliterm-hint-node {
|
||||
color: #000;
|
||||
background: rgba(250, 250, 250, 0.8);
|
||||
border: 1px solid #AAA;
|
||||
border-bottom: 0px !important;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.gcliterm-hint-parent {
|
||||
border-bottom: 1px solid #AAA;
|
||||
}
|
||||
|
||||
.gcliCmdHelpRight {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
|
||||
.gcliCmdDesc {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.gcliParamGroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gcliParamName {
|
||||
text-align: right;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.gcliParamError {
|
||||
font-size: 80%;
|
||||
color: #900;
|
||||
}
|
||||
|
||||
.gcliParamSubmit {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.gcliGroupSymbol {
|
||||
font-size: 90%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcliRequired {
|
||||
font-size: 80%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcliParams {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/hinter.css */
|
||||
.gcliHintParent {
|
||||
color: #000;
|
||||
background: rgba(250, 250, 250, 0.8);
|
||||
border: 1px solid #AAA;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gcliHints {
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gcliHints ul {
|
||||
margin: 0;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/menu.css */
|
||||
.gcliOption {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.gcliOption:hover {
|
||||
background-color: rgb(230, 230, 230);
|
||||
}
|
||||
|
||||
.gcliOptionName {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.gcliOptionDesc {
|
||||
font-size: 80%;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliMenuError {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding: 8px 2px 2px 2px;
|
||||
font-size: 80%;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.gcliMenuField {
|
||||
background-color: white;
|
||||
color: black;
|
||||
border: 1px solid #aaa;
|
||||
padding: 2px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
max-width: 220px;
|
||||
overflow-x: hidden;
|
||||
margin: 0px 10px;
|
||||
border-top: 0px !important;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/inputter.css */
|
||||
.gcliCompletion {
|
||||
position: absolute;
|
||||
z-index: -1000;
|
||||
background-color: #DDD;
|
||||
border: 1px transparent solid;
|
||||
padding: 1px 1px 1px 2px;
|
||||
}
|
||||
|
||||
.gcliCompletion {
|
||||
color: #DDD;
|
||||
}
|
||||
|
||||
.gcliINCOMPLETE {
|
||||
border-bottom: 2px dotted #999;
|
||||
}
|
||||
|
||||
.gcliERROR {
|
||||
border-bottom: 2px dotted #F00;
|
||||
}
|
||||
|
||||
.gcliPrompt {
|
||||
color: #66F;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gcliCompl {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliCloseBrace {
|
||||
color: #999;
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the GCLI.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* From: $GCLI/mozilla/gcli/ui/gcliterm.css */
|
||||
.gcliterm-input-node,
|
||||
.gcliterm-complete-node {
|
||||
border: none;
|
||||
-moz-appearance: none;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
background-color: transparent;
|
||||
font: 12px Consolas, "Lucida Console", monospace;
|
||||
padding: 2px 0 0 16px;
|
||||
}
|
||||
|
||||
.gcliterm-complete-node {
|
||||
color: #FFF;
|
||||
padding: 4px 4px 2px 21px;
|
||||
}
|
||||
|
||||
.gcliVALID {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.gcliINCOMPLETE {
|
||||
color: #DDD;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
.gcliERROR {
|
||||
color: #DDD;
|
||||
border-bottom: 1px dotted #F00;
|
||||
}
|
||||
|
||||
.gcliCompl {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliterm-stack-node {
|
||||
background: url("chrome://global/skin/icons/commandline.png") 4px center no-repeat;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gcliterm-hint-node {
|
||||
color: #000;
|
||||
background: rgba(250, 250, 250, 0.8);
|
||||
border: 1px solid #AAA;
|
||||
border-bottom: 0px !important;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.gcliterm-hint-parent {
|
||||
border-bottom: 1px solid #AAA;
|
||||
}
|
||||
|
||||
.gcliCmdHelpRight {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
|
||||
.gcliCmdDesc {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.gcliParamGroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gcliParamName {
|
||||
text-align: right;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.gcliParamError {
|
||||
font-size: 80%;
|
||||
color: #900;
|
||||
}
|
||||
|
||||
.gcliParamSubmit {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.gcliGroupSymbol {
|
||||
font-size: 90%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcliRequired {
|
||||
font-size: 80%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcliParams {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/hinter.css */
|
||||
.gcliHintParent {
|
||||
color: #000;
|
||||
background: rgba(250, 250, 250, 0.8);
|
||||
border: 1px solid #AAA;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gcliHints {
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gcliHints ul {
|
||||
margin: 0;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/menu.css */
|
||||
.gcliOption {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.gcliOption:hover {
|
||||
background-color: rgb(230, 230, 230);
|
||||
}
|
||||
|
||||
.gcliOptionName {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.gcliOptionDesc {
|
||||
font-size: 80%;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliMenuError {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding: 8px 2px 2px 2px;
|
||||
font-size: 80%;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.gcliMenuField {
|
||||
background-color: white;
|
||||
color: black;
|
||||
border: 1px solid #aaa;
|
||||
padding: 2px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
max-width: 220px;
|
||||
overflow-x: hidden;
|
||||
margin: 0px 10px;
|
||||
border-top: 0px !important;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/inputter.css */
|
||||
.gcliCompletion {
|
||||
position: absolute;
|
||||
z-index: -1000;
|
||||
background-color: #DDD;
|
||||
border: 1px transparent solid;
|
||||
padding: 1px 1px 1px 2px;
|
||||
}
|
||||
|
||||
.gcliCompletion {
|
||||
color: #DDD;
|
||||
}
|
||||
|
||||
.gcliINCOMPLETE {
|
||||
border-bottom: 2px dotted #999;
|
||||
}
|
||||
|
||||
.gcliERROR {
|
||||
border-bottom: 2px dotted #F00;
|
||||
}
|
||||
|
||||
.gcliPrompt {
|
||||
color: #66F;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gcliCompl {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliCloseBrace {
|
||||
color: #999;
|
||||
}
|
|
@ -628,6 +628,10 @@ html[dir=rtl] #otherresults {
|
|||
-moz-margin-end: 5px;
|
||||
}
|
||||
|
||||
#otherresults .label:-moz-window-inactive {
|
||||
color: #404040;
|
||||
}
|
||||
|
||||
.inlineMatch {
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 0.4em;
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the GCLI.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Walker <jwalker@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* From: $GCLI/mozilla/gcli/ui/gcliterm.css */
|
||||
.gcliterm-input-node,
|
||||
.gcliterm-complete-node {
|
||||
border: none;
|
||||
-moz-appearance: none;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
background-color: transparent;
|
||||
font: 12px Consolas, "Lucida Console", monospace;
|
||||
padding: 2px 0 0 16px;
|
||||
}
|
||||
|
||||
.gcliterm-complete-node {
|
||||
color: #FFF;
|
||||
padding: 4px 4px 2px 21px;
|
||||
}
|
||||
|
||||
.gcliVALID {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.gcliINCOMPLETE {
|
||||
color: #DDD;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
.gcliERROR {
|
||||
color: #DDD;
|
||||
border-bottom: 1px dotted #F00;
|
||||
}
|
||||
|
||||
.gcliCompl {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliterm-stack-node {
|
||||
background: url("chrome://global/skin/icons/commandline.png") 4px center no-repeat;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gcliterm-hint-node {
|
||||
color: #000;
|
||||
background: rgba(250, 250, 250, 0.8);
|
||||
border: 1px solid #AAA;
|
||||
border-bottom: 0px !important;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.gcliterm-hint-parent {
|
||||
border-bottom: 1px solid #AAA;
|
||||
}
|
||||
|
||||
.gcliCmdHelpRight {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
|
||||
.gcliCmdDesc {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.gcliParamGroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gcliParamName {
|
||||
text-align: right;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.gcliParamError {
|
||||
font-size: 80%;
|
||||
color: #900;
|
||||
}
|
||||
|
||||
.gcliParamSubmit {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.gcliGroupSymbol {
|
||||
font-size: 90%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcliRequired {
|
||||
font-size: 80%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcliParams {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/hinter.css */
|
||||
.gcliHintParent {
|
||||
color: #000;
|
||||
background: rgba(250, 250, 250, 0.8);
|
||||
border: 1px solid #AAA;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gcliHints {
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gcliHints ul {
|
||||
margin: 0;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/menu.css */
|
||||
.gcliOption {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.gcliOption:hover {
|
||||
background-color: rgb(230, 230, 230);
|
||||
}
|
||||
|
||||
.gcliOptionName {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.gcliOptionDesc {
|
||||
font-size: 80%;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliMenuError {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding: 8px 2px 2px 2px;
|
||||
font-size: 80%;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.gcliMenuField {
|
||||
background-color: white;
|
||||
color: black;
|
||||
border: 1px solid #aaa;
|
||||
padding: 2px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
max-width: 220px;
|
||||
overflow-x: hidden;
|
||||
margin: 0px 10px;
|
||||
border-top: 0px !important;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/inputter.css */
|
||||
.gcliCompletion {
|
||||
position: absolute;
|
||||
z-index: -1000;
|
||||
background-color: #DDD;
|
||||
border: 1px transparent solid;
|
||||
padding: 1px 1px 1px 2px;
|
||||
}
|
||||
|
||||
.gcliCompletion {
|
||||
color: #DDD;
|
||||
}
|
||||
|
||||
.gcliINCOMPLETE {
|
||||
border-bottom: 2px dotted #999;
|
||||
}
|
||||
|
||||
.gcliERROR {
|
||||
border-bottom: 2px dotted #F00;
|
||||
}
|
||||
|
||||
.gcliPrompt {
|
||||
color: #66F;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.gcliCompl {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.gcliCloseBrace {
|
||||
color: #999;
|
||||
}
|
|
@ -109,6 +109,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
|
||||
skin/classic/browser/devtools/search.png (devtools/search.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
|
@ -232,6 +233,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/arrows.png (devtools/arrows.png)
|
||||
skin/classic/aero/browser/devtools/search.png (devtools/search.png)
|
||||
skin/classic/aero/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/aero/browser/devtools/gcli.css (devtools/gcli.css)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/aero/browser/sync-throbber.png
|
||||
skin/classic/aero/browser/sync-16.png
|
||||
|
|
|
@ -87,6 +87,7 @@ let initTable = [
|
|||
["wm", "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator"],
|
||||
["ww", "@mozilla.org/embedcomp/window-watcher;1", "nsIWindowWatcher"],
|
||||
["startup", "@mozilla.org/toolkit/app-startup;1", "nsIAppStartup"],
|
||||
["sysinfo", "@mozilla.org/system-info;1", "nsIPropertyBag2"],
|
||||
];
|
||||
|
||||
initTable.forEach(function ([name, contract, intf])
|
||||
|
|
|
@ -74,4 +74,5 @@ function checkServices() {
|
|||
checkService("cookies", Ci.nsICookieManager2);
|
||||
checkService("logins", Ci.nsILoginManager);
|
||||
checkService("telemetry", Ci.nsITelemetry);
|
||||
checkService("sysinfo", Ci.nsIPropertyBag2);
|
||||
}
|
||||
|
|
|
@ -1091,7 +1091,10 @@ var AddonManagerInternal = {
|
|||
},
|
||||
|
||||
get autoUpdateDefault() {
|
||||
return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
|
||||
try {
|
||||
return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
|
||||
} catch(e) { }
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче