This commit is contained in:
Rob Campbell 2011-10-13 13:40:01 -03:00
Родитель b478778440 bfe5f6a685
Коммит 0ffe1c280b
44 изменённых файлов: 13499 добавлений и 1876 удалений

Просмотреть файл

@ -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>&#x2192; " + 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;
}
};