diff --git a/.eslintignore b/.eslintignore
index 44fe00ba15e9..4d1468b70833 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -135,7 +135,6 @@ devtools/shared/css/generated/properties-db.js
# Ignore devtools third-party libs
devtools/shared/jsbeautify/*
devtools/shared/acorn/*
-devtools/shared/gcli/source/*
devtools/shared/node-properties/*
devtools/shared/pretty-fast/*
devtools/shared/sourcemap/*
diff --git a/browser/base/content/test/static/browser_all_files_referenced.js b/browser/base/content/test/static/browser_all_files_referenced.js
index 842c3bbb54f1..68f4353a1f55 100644
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -409,14 +409,13 @@ function parseCodeFile(fileUri) {
if (isDevtools) {
let rules = [
- ["gcli", "resource://devtools/shared/gcli/source/lib/gcli"],
["devtools/client/locales", "chrome://devtools/locale"],
["devtools/shared/locales", "chrome://devtools-shared/locale"],
["devtools/shared/platform", "resource://devtools/shared/platform/chrome"],
["devtools", "resource://devtools"],
];
- match = line.match(/["']((?:devtools|gcli)\/[^\\#"']+)["']/);
+ match = line.match(/["']((?:devtools)\/[^\\#"']+)["']/);
if (match && match[1]) {
let path = match[1];
for (let rule of rules) {
diff --git a/devtools/client/debugger/test/mochitest/head.js b/devtools/client/debugger/test/mochitest/head.js
index 7763369cd971..c1f1701d1c30 100644
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -62,7 +62,6 @@ registerCleanupFunction(async function() {
});
});
-// Import the GCLI test helper
var testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
testDir = testDir.replace(/\/\//g, "/");
testDir = testDir.replace("chrome:/mochitest", "chrome://mochitest");
diff --git a/devtools/client/definitions.js b/devtools/client/definitions.js
index 7bcd377fbac2..8c61a200ed0d 100644
--- a/devtools/client/definitions.js
+++ b/devtools/client/definitions.js
@@ -547,8 +547,7 @@ exports.ToolboxButtons = [
onClick(event, toolbox) {
const tab = toolbox.target.tab;
const browserWindow = tab.ownerDocument.defaultView;
- ResponsiveUIManager.handleGcliCommand(browserWindow, tab,
- "resize toggle", null);
+ ResponsiveUIManager.toggle(browserWindow, tab, { trigger: "toolbox" });
},
isChecked(toolbox) {
if (!toolbox.target.tab) {
diff --git a/devtools/client/framework/devtools-browser.js b/devtools/client/framework/devtools-browser.js
index 54a1377f84fa..915f7fff98b7 100644
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -127,8 +127,8 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
/**
* This function makes sure that the "devtoolstheme" attribute is set on the browser
- * window to make it possible to change colors on elements in the browser (like gcli,
- * or the splitter between the toolbox and web content).
+ * window to make it possible to change colors on elements in the browser (like the
+ * splitter between the toolbox and web content).
*/
updateDevtoolsThemeAttribute(win) {
// Set an attribute on root element of each window to make it possible
@@ -138,7 +138,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
devtoolsTheme = "light";
}
- // Style gcli and the splitter between the toolbox and page content. This used to
+ // Style the splitter between the toolbox and page content. This used to
// set the attribute on the browser's root node but that regressed tpaint:
// bug 1331449.
win.document.getElementById("browser-bottombox")
diff --git a/devtools/client/inspector/inspector.js b/devtools/client/inspector/inspector.js
index 13b58a61ccbc..34f081e9a1c8 100644
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -2322,7 +2322,7 @@ Inspector.prototype = {
},
/**
- * Initiate gcli screenshot command on selected node.
+ * Initiate screenshot command on selected node.
*/
async screenshotNode() {
// Bug 1332936 - it's possible to call `screenshotNode` while the BoxModel highlighter
diff --git a/devtools/client/netmonitor/README.md b/devtools/client/netmonitor/README.md
index 7b5e0f494507..c9a0f81c5963 100644
--- a/devtools/client/netmonitor/README.md
+++ b/devtools/client/netmonitor/README.md
@@ -6,81 +6,6 @@ The Network Monitor (netmonitor) shows you all the network requests Firefox make
If you want to build the Network Monitor inside of the DevTools toolbox (Firefox Devtools Panels), follow the [simple Firefox build](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_build) document in MDN. Start your compiled firefox and open the Firefox developer tool, you can see the Network Monitor inside.
-If you would like to run the Network Monitor in the browser tab (experimental), you need following packages:
-
-* [node](https://nodejs.org/) >= 6.9.x JavaScript runtime.
-* [yarn](https://yarnpkg.com/docs/install) >= 0.21.x the package dependency management tool.
-* [Firefox](https://www.mozilla.org/firefox/new/) any version or build from the source code.
-
-## Quick Setup
-
-Navigate to the `mozilla-central/devtools/client/netmonitor` folder with your terminal.
-Note that this folder is available after `mozilla-central` was cloned in order to get a local copy of the repository. Then run the following commands:
-
-```bash
-# Install packages
-yarn install
-
-# Create a dev server instance for hosting netmonitor on browser
-yarn start
-
-# Run firefox
-firefox http://localhost:8000 --start-debugger-server 6080
-```
-
-Then open `localhost:8000` in any browser to see all tabs in Firefox.
-
-### More detailed setup
-
-Instead of running command to open a new Firefox window like
-
-```
-firefox http://localhost:8000 --start-debugger-server 6080
-```
-
-If you have an opened Firefox browser, you can manually configure Firefox via type `about:config` in Firefox URL field, grant the warning to access preferences. And set these two preferences:
-
-* disable `devtools.debugger.prompt-connection` to remove the connection prompt.
-* enable `devtools.debugger.remote-enabled` to allow remote debugging a browser tab via the Mozilla remote debugging protocol (RDP)
-
-Go to the Web Developer menu in Firefox and select [Developer Toolbar](https://developer.mozilla.org/docs/Tools/GCLI). Run the command
-
-`listen 6080 mozilla-rdp`
-
-The command will make Firefox act as a remote debugging server.
-
-Run the command
-
-`yarn start`
-
-Then open `localhost:8000` in any browser to see all tabs in Firefox.
-
-### How it works
-
-The Network Monitor uses [webpack](https://webpack.js.org/) and several packages from [devtools-core](https://github.com/devtools-html/devtools-core) to run the Network Monitor as a normal web page. The Network Monitor uses [Mozilla remote debugging protocol](http://searchfox.org/mozilla-central/source/devtools/docs/backend/protocol.md) to fetch result and execute commands from Firefox browser.
-
-
-
-Open `localhost:8000` in any browser to see the [launchpad](https://github.com/devtools-html/devtools-core/tree/master/packages/devtools-launchpad) interface. Devtools Launchpad will communicate with Firefox (the remote debugging server) and list all opened tabs from Firefox. Click one of the browser tab entry, now you can see the Network Monitor runs in a browser tab.
-
-### Develop with related modules
-
-When working on make the Network Monitor running in the browser tab, you may need to work on external modules. Besides the third party modules, here are modules required for the Network Monitor and is hosted under `devtools-html` (modules shared across Devtools):
-
-* [devtools-config](https://github.com/devtools-html/devtools-core/blob/master/packages/devtools-config/#readme) config used in dev server
-* [devtools-launchpad](https://github.com/devtools-html/devtools-core/blob/master/packages/devtools-launchpad/#readme) provide the dev server, landing page and the bootstrap functions to run devtools in the browser tab.
-* [devtools-modules](https://github.com/devtools-html/devtools-core/blob/master/packages/devtools-modules/#readme) Devtools shared and shim modules.
-* [devtools-source-editor](https://github.com/devtools-html/devtools-core/blob/master/packages/devtools-source-editor/#readme) Source Editor component.
-* [devtools-reps](https://github.com/devtools-html/debugger.html/blob/master/packages/devtools-reps/#readme) remote object formatter for variables representation.
-
-Do `yarn link` modules in related module directory, then do `yarn link [module-name]` after `yarn install` modules.
-
-## Code Structure
-
-Top level files are used to launch the Network Monitor inside of the DevTools toolbox or run in the browser tab (experimental). The Network Monitor source is mainly located in the `src/` folder, the same code base is used to run in both environments.
-
-We prefer use web standard API instead of FIrefox specific API, to make the Network Monitor can be opened in any browser tab.
-
### Run inside of the DevTools toolbox
Files used to run the Network Monitor inside of the DevTools toolbox.
diff --git a/devtools/client/responsive.html/index.js b/devtools/client/responsive.html/index.js
index 7248f8b7638b..701250f027e8 100644
--- a/devtools/client/responsive.html/index.js
+++ b/devtools/client/responsive.html/index.js
@@ -137,7 +137,7 @@ window.getViewportSize = () => {
};
/**
- * Called by manager.js to set viewport size from tests, GCLI, etc.
+ * Called by manager.js to set viewport size from tests, etc.
*/
window.setViewportSize = ({ width, height }) => {
try {
diff --git a/devtools/client/responsive.html/manager.js b/devtools/client/responsive.html/manager.js
index df5d6f5909e9..6e422abef077 100644
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -53,7 +53,7 @@ const ResponsiveUIManager = exports.ResponsiveUIManager = {
* @param options
* Other options associated with toggling. Currently includes:
* - `trigger`: String denoting the UI entry point, such as:
- * - `command`: GCLI command bar or toolbox button
+ * - `toolbox`: Toolbox Button
* - `menu`: Web Developer menu item
* - `shortcut`: Keyboard shortcut
* @return Promise
@@ -78,7 +78,7 @@ const ResponsiveUIManager = exports.ResponsiveUIManager = {
* @param options
* Other options associated with opening. Currently includes:
* - `trigger`: String denoting the UI entry point, such as:
- * - `command`: GCLI command bar or toolbox button
+ * - `toolbox`: Toolbox Button
* - `menu`: Web Developer menu item
* - `shortcut`: Keyboard shortcut
* @return Promise
@@ -135,7 +135,7 @@ const ResponsiveUIManager = exports.ResponsiveUIManager = {
* @param options
* Other options associated with closing. Currently includes:
* - `trigger`: String denoting the UI entry point, such as:
- * - `command`: GCLI command bar or toolbox button
+ * - `toolbox`: Toolbox Button
* - `menu`: Web Developer menu item
* - `shortcut`: Keyboard shortcut
* - `reason`: String detailing the specific cause for closing
@@ -212,39 +212,6 @@ const ResponsiveUIManager = exports.ResponsiveUIManager = {
return this.activeTabs.get(tab);
},
- /**
- * Handle GCLI commands.
- *
- * @param window
- * The main browser chrome window.
- * @param tab
- * The browser tab.
- * @param command
- * The GCLI command name.
- * @param args
- * The GCLI command arguments.
- */
- handleGcliCommand(window, tab, command, args) {
- let completed;
- switch (command) {
- case "resize to":
- completed = this.openIfNeeded(window, tab, { trigger: "command" });
- this.activeTabs.get(tab).setViewportSize(args);
- break;
- case "resize on":
- completed = this.openIfNeeded(window, tab, { trigger: "command" });
- break;
- case "resize off":
- completed = this.closeIfNeeded(window, tab, { trigger: "command" });
- break;
- case "resize toggle":
- completed = this.toggle(window, tab, { trigger: "command" });
- break;
- default:
- }
- completed.catch(console.error);
- },
-
handleMenuCheck({target}) {
ResponsiveUIManager.setMenuCheckFor(target);
},
@@ -272,15 +239,13 @@ const ResponsiveUIManager = exports.ResponsiveUIManager = {
showRemoteOnlyNotification(window, tab, { trigger } = {}) {
showNotification(window, tab, {
- command: trigger == "command",
+ toolboxButton: trigger == "toolbox",
msg: l10n.getStr("responsive.remoteOnly"),
priority: PriorityLevels.PRIORITY_CRITICAL_MEDIUM,
});
},
};
-// GCLI commands in ./commands.js listen for events from this object to know
-// when the UI for a tab has opened or closed.
EventEmitter.decorate(ResponsiveUIManager);
/**
@@ -689,7 +654,7 @@ ResponsiveUI.prototype = {
},
/**
- * Helper for tests, GCLI, etc. Assumes a single viewport for now.
+ * Helper for tests, etc. Assumes a single viewport for now.
*/
async setViewportSize(size) {
await this.inited;
diff --git a/devtools/client/responsive.html/utils/notification.js b/devtools/client/responsive.html/utils/notification.js
index e965fe43fd78..aaddcf9e07e5 100644
--- a/devtools/client/responsive.html/utils/notification.js
+++ b/devtools/client/responsive.html/utils/notification.js
@@ -17,19 +17,19 @@ loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools"
* The browser tab.
* @param options
* Other options associated with opening. Currently includes:
- * - `command`: Whether initiated via GCLI command bar or toolbox button
+ * - `toolbox`: Whether initiated via toolbox button
* - `msg`: String to show in the notification
* - `priority`: Priority level for the notification, which affects the icon and
* overall appearance.
*/
-function showNotification(window, tab, { command, msg, priority } = {}) {
+function showNotification(window, tab, { toolboxButton, msg, priority } = {}) {
// Default to using the browser's per-tab notification box
let nbox = window.gBrowser.getNotificationBox(tab.linkedBrowser);
- // If opening was initiated by GCLI command bar or toolbox button, check for an open
+ // If opening was initiated by a toolbox button, check for an open
// toolbox for the tab. If one exists, use the toolbox's notification box so that the
// message is placed closer to the action taken by the user.
- if (command) {
+ if (toolboxButton) {
const target = TargetFactory.forTab(tab);
const toolbox = gDevTools.getToolbox(target);
if (toolbox) {
diff --git a/devtools/client/shared/developer-toolbar.js b/devtools/client/shared/developer-toolbar.js
deleted file mode 100644
index b559d770a4de..000000000000
--- a/devtools/client/shared/developer-toolbar.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const promise = require("promise");
-
-loader.lazyRequireGetter(this, "gcliInit", "devtools/shared/gcli/commands/index");
-
-/**
- * A collection of utilities to help working with commands
- */
-var CommandUtils = {
- /**
- * Caches requisitions created when calling executeOnTarget:
- * Target => Requisition Promise
- */
- _requisitions: new WeakMap(),
-
- /**
- * Utility to execute a command string on a given target
- */
- async executeOnTarget(target, command) {
- let requisitionPromise = this._requisitions.get(target);
- if (!requisitionPromise) {
- requisitionPromise = this.createRequisition(target, {
- environment: CommandUtils.createEnvironment({ target }, "target")
- });
- // Store the promise to avoid races by storing the promise immediately
- this._requisitions.set(target, requisitionPromise);
- }
- const requisition = await requisitionPromise;
- requisition.updateExec(command);
- },
-
- /**
- * Utility to ensure that things are loaded in the correct order
- */
- createRequisition: function(target, options) {
- if (!gcliInit) {
- return promise.reject("Unable to load gcli");
- }
- return gcliInit.getSystem(target).then(system => {
- const Requisition = require("gcli/cli").Requisition;
- return new Requisition(system, options);
- });
- },
-
- /**
- * Destroy the remote side of the requisition as well as the local side
- */
- destroyRequisition: function(requisition, target) {
- requisition.destroy();
- gcliInit.releaseSystem(target);
- },
-
- /**
- * A helper function to create the environment object that is passed to
- * GCLI commands.
- * @param targetContainer An object containing a 'target' property which
- * reflects the current debug target
- */
- createEnvironment: function(container, targetProperty = "target") {
- if (!container[targetProperty].toString ||
- !/TabTarget/.test(container[targetProperty].toString())) {
- throw new Error("Missing target");
- }
-
- return {
- get target() {
- if (!container[targetProperty].toString ||
- !/TabTarget/.test(container[targetProperty].toString())) {
- throw new Error("Removed target");
- }
-
- return container[targetProperty];
- },
-
- get chromeWindow() {
- return this.target.tab.ownerDocument.defaultView;
- },
-
- get chromeDocument() {
- return this.target.tab.ownerDocument.defaultView.document;
- },
-
- get window() {
- // throw new
- // Error("environment.window is not available in runAt:client commands");
- return this.chromeWindow.gBrowser.contentWindowAsCPOW;
- },
-
- get document() {
- // throw new
- // Error("environment.document is not available in runAt:client commands");
- return this.chromeWindow.gBrowser.contentDocumentAsCPOW;
- }
- };
- },
-};
-
-exports.CommandUtils = CommandUtils;
diff --git a/devtools/client/shared/keycodes.js b/devtools/client/shared/keycodes.js
index fe4764dbe26a..0a70a8fbcfae 100644
--- a/devtools/client/shared/keycodes.js
+++ b/devtools/client/shared/keycodes.js
@@ -4,10 +4,6 @@
"use strict";
-// This was copied (and slightly modified) from
-// devtools/shared/gcli/source/lib/gcli/util/util.js, which in turn
-// says:
-
/**
* Keyboard handling is a mess. http://unixpapa.com/js/key.html
* It would be good to use DOM L3 Keyboard events,
@@ -17,7 +13,7 @@
* and when the code that uses this KeyEvent was written, nothing was clear,
* so instead, we're using this unmodern shim:
* http://stackoverflow.com/questions/5681146/chrome-10-keyevent-or-something-similar-to-firefoxs-keyevent
- * See BUG 664991: GCLI's keyboard handling should be updated to use DOM-L3
+ * See BUG 664991: keyboard handling should be updated to use DOM-L3
* https://bugzilla.mozilla.org/show_bug.cgi?id=664991
*/
@@ -136,9 +132,6 @@ exports.KeyCodes = {
DOM_VK_CLOSE_BRACKET: 221,
DOM_VK_QUOTE: 222,
DOM_VK_META: 224,
-
- // A few that did not appear in gcli, but that are apparently used
- // in devtools.
DOM_VK_COLON: 58,
DOM_VK_VOLUME_MUTE: 181,
DOM_VK_VOLUME_DOWN: 182,
diff --git a/devtools/client/shared/moz.build b/devtools/client/shared/moz.build
index 2190701a1a5c..7f02c9dac57e 100644
--- a/devtools/client/shared/moz.build
+++ b/devtools/client/shared/moz.build
@@ -25,7 +25,6 @@ DevToolsModules(
'css-angle.js',
'curl.js',
'demangle.js',
- 'developer-toolbar.js',
'devices.js',
'DOMHelpers.jsm',
'enum.js',
diff --git a/devtools/client/shared/telemetry.js b/devtools/client/shared/telemetry.js
index f26e7f8964a6..1821255487a3 100644
--- a/devtools/client/shared/telemetry.js
+++ b/devtools/client/shared/telemetry.js
@@ -672,7 +672,6 @@ function getChartsFromToolId(id) {
case "ABOUTDEBUGGING":
case "BROWSERCONSOLE":
case "CANVASDEBUGGER":
- case "DEVELOPERTOOLBAR":
case "DOM":
case "INSPECTOR":
case "JSBROWSERDEBUGGER":
diff --git a/devtools/client/shared/test/browser.ini b/devtools/client/shared/test/browser.ini
index c961b488a51d..f638e2f203b3 100644
--- a/devtools/client/shared/test/browser.ini
+++ b/devtools/client/shared/test/browser.ini
@@ -198,7 +198,6 @@ skip-if = !e10s || os == "win" # RDM only works for remote tabs, Win: bug 140419
[browser_telemetry_toolboxtabs_styleeditor.js]
[browser_telemetry_toolboxtabs_webaudioeditor.js]
[browser_telemetry_toolboxtabs_webconsole.js]
-[browser_templater_basic.js]
[browser_treeWidget_basic.js]
[browser_treeWidget_keyboard_interaction.js]
[browser_treeWidget_mouse_interaction.js]
diff --git a/devtools/client/shared/test/browser_templater_basic.js b/devtools/client/shared/test/browser_templater_basic.js
deleted file mode 100644
index 3cd61d28b853..000000000000
--- a/devtools/client/shared/test/browser_templater_basic.js
+++ /dev/null
@@ -1,287 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Tests that the DOM Template engine works properly
-
-/*
- * These tests run both in Mozilla/Mochitest and plain browsers (as does
- * domtemplate)
- * We should endevour to keep the source in sync.
- */
-
-const {template} = require("devtools/shared/gcli/templater");
-
-const TEST_URI = TEST_URI_ROOT + "doc_templater_basic.html";
-
-var test = async function() {
- await addTab("about:blank");
- const [host,, doc] = await createHost("bottom", TEST_URI);
-
- info("Starting DOM Templater Tests");
- runTest(0, host, doc);
-};
-
-function runTest(index, host, doc) {
- const options = tests[index] = tests[index]();
- const holder = doc.createElement("div");
- holder.id = options.name;
- const body = doc.body;
- body.appendChild(holder);
- // eslint-disable-next-line no-unsanitized/property
- holder.innerHTML = options.template;
-
- info("Running " + options.name);
- template(holder, options.data, options.options);
-
- if (typeof options.result == "string") {
- is(holder.innerHTML, options.result, options.name);
- } else {
- ok(holder.innerHTML.match(options.result) != null,
- options.name + " result='" + holder.innerHTML + "'");
- }
-
- if (options.also) {
- options.also(options);
- }
-
- function runNextTest() {
- index++;
- if (index < tests.length) {
- runTest(index, host, doc);
- } else {
- finished(host);
- }
- }
-
- if (options.later) {
- const ais = is.bind(this);
-
- function createTester(testHolder, testOptions) {
- return () => {
- ais(testHolder.innerHTML, testOptions.later, testOptions.name + " later");
- runNextTest();
- };
- }
-
- executeSoon(createTester(holder, options));
- } else {
- runNextTest();
- }
-}
-
-function finished(host) {
- host.destroy();
- 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 = [
- () => ({
- name: "simpleNesting",
- template: '
'
- })
- /* eslint-enable max-len */
-];
-
-function delayReply(data) {
- return new Promise(resolve => resolve(data));
-}
diff --git a/devtools/client/themes/images/gcli_sec_bad.svg b/devtools/client/themes/images/gcli_sec_bad.svg
deleted file mode 100644
index 4f440eb6ba71..000000000000
--- a/devtools/client/themes/images/gcli_sec_bad.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
\ No newline at end of file
diff --git a/devtools/client/themes/images/gcli_sec_good.svg b/devtools/client/themes/images/gcli_sec_good.svg
deleted file mode 100644
index f1b33d0737a1..000000000000
--- a/devtools/client/themes/images/gcli_sec_good.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
\ No newline at end of file
diff --git a/devtools/client/themes/images/gcli_sec_moderate.svg b/devtools/client/themes/images/gcli_sec_moderate.svg
deleted file mode 100644
index 3a88aa4688bf..000000000000
--- a/devtools/client/themes/images/gcli_sec_moderate.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
\ No newline at end of file
diff --git a/devtools/docs/files/adding-files.md b/devtools/docs/files/adding-files.md
index 7e0c493493b5..d3f2e1f23557 100644
--- a/devtools/docs/files/adding-files.md
+++ b/devtools/docs/files/adding-files.md
@@ -151,8 +151,8 @@ Example:
Example:
-* File: `/devtools/shared/locales/en-US/gcli.properties`
-* Usage: `chrome://devtools-shared/locale/gcli.properties`
+* File: `/devtools/shared/locales/en-US/screenshot.properties`
+* Usage: `chrome://devtools-shared/locale/screenshot.properties`
### Guidelines
diff --git a/devtools/docs/frontend/telemetry.md b/devtools/docs/frontend/telemetry.md
index 347ce6fc6e25..e78b2bf4aa4e 100644
--- a/devtools/docs/frontend/telemetry.md
+++ b/devtools/docs/frontend/telemetry.md
@@ -121,7 +121,7 @@ devtools.main:
release_channel_collection: opt-out
expiry_version: never
extra_keys:
- entrypoint: How was the toolbox opened? CommandLine, ContextMenu, DeveloperToolbar, HamburgerMenu, KeyShortcut, SessionRestore or SystemMenu
+ entrypoint: How was the toolbox opened? CommandLine, ContextMenu, HamburgerMenu, KeyShortcut, SessionRestore or SystemMenu
first_panel: The name of the first panel opened.
host: "Toolbox host (positioning): bottom, side, window or other."
splitconsole: Indicates whether the split console was open.
diff --git a/devtools/server/actors/gcli.js b/devtools/server/actors/gcli.js
deleted file mode 100644
index f68a00bc6f40..000000000000
--- a/devtools/server/actors/gcli.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
-const { gcliSpec } = require("devtools/shared/specs/gcli");
-const { createSystem } = require("gcli/system");
-
-/**
- * Manage remote connections that want to talk to GCLI
- */
-const GcliActor = ActorClassWithSpec(gcliSpec, {
- initialize: function(conn, targetActor) {
- Actor.prototype.initialize.call(this, conn);
-
- this._commandsChanged = this._commandsChanged.bind(this);
-
- this._targetActor = targetActor;
- // see _getRequisition()
- this._requisitionPromise = undefined;
- },
-
- destroy: function() {
- Actor.prototype.destroy.call(this);
-
- // If _getRequisition has not been called, just bail quickly
- if (this._requisitionPromise == null) {
- this._commandsChanged = undefined;
- this._targetActor = undefined;
- return Promise.resolve();
- }
-
- return this._getRequisition().then(requisition => {
- requisition.destroy();
-
- this._system.commands.onCommandsChange.remove(this._commandsChanged);
- this._system.destroy();
- this._system = undefined;
-
- this._requisitionPromise = undefined;
- this._targetActor = undefined;
-
- this._commandsChanged = undefined;
- });
- },
-
- /**
- * Load a module into the requisition
- */
- _testOnlyAddItemsByModule: function(names) {
- return this._getRequisition().then(requisition => {
- return requisition.system.addItemsByModule(names);
- });
- },
-
- /**
- * Unload a module from the requisition
- */
- _testOnlyRemoveItemsByModule: function(names) {
- return this._getRequisition().then(requisition => {
- return requisition.system.removeItemsByModule(names);
- });
- },
-
- /**
- * Retrieve a list of the remotely executable commands
- * @param customProps Array of strings containing additional properties which,
- * if specified in the command spec, will be included in the JSON. Normally we
- * transfer only the properties required for GCLI to function.
- */
- specs: function(customProps) {
- return this._getRequisition().then(requisition => {
- return requisition.system.commands.getCommandSpecs(customProps);
- });
- },
-
- /**
- * Execute a GCLI command
- * @return a promise of an object with the following properties:
- * - data: The output of the command
- * - type: The type of the data to allow selection of a converter
- * - error: True if the output was considered an error
- */
- execute: function(typed) {
- return this._getRequisition().then(requisition => {
- return requisition.updateExec(typed).then(output => output.toJson());
- });
- },
-
- /**
- * Get the state of an input string. i.e. requisition.getStateData()
- */
- state: function(typed, start, rank) {
- return this._getRequisition().then(requisition => {
- return requisition.update(typed).then(() => {
- return requisition.getStateData(start, rank);
- });
- });
- },
-
- /**
- * Call type.parse to check validity. Used by the remote type
- * @return a promise of an object with the following properties:
- * - status: Of of the following strings: VALID|INCOMPLETE|ERROR
- * - message: The message to display to the user
- * - predictions: An array of suggested values for the given parameter
- */
- parseType: function(typed, paramName) {
- return this._getRequisition().then(requisition => {
- return requisition.update(typed).then(() => {
- const assignment = requisition.getAssignment(paramName);
- return Promise.resolve(assignment.predictions).then(predictions => {
- return {
- status: assignment.getStatus().toString(),
- message: assignment.message,
- predictions: predictions
- };
- });
- });
- });
- },
-
- /**
- * Get the incremented/decremented value of some type
- * @return a promise of a string containing the new argument text
- */
- nudgeType: function(typed, by, paramName) {
- return this.requisition.update(typed).then(() => {
- const assignment = this.requisition.getAssignment(paramName);
- return this.requisition.nudge(assignment, by).then(() => {
- return assignment.arg == null ? undefined : assignment.arg.text;
- });
- });
- },
-
- /**
- * Perform a lookup on a selection type to get the allowed values
- */
- getSelectionLookup: function(commandName, paramName) {
- return this._getRequisition().then(requisition => {
- const command = requisition.system.commands.get(commandName);
- if (command == null) {
- throw new Error("No command called '" + commandName + "'");
- }
-
- let type;
- command.params.forEach(param => {
- if (param.name === paramName) {
- type = param.type;
- }
- });
-
- if (type == null) {
- throw new Error("No parameter called '" + paramName + "' in '" +
- commandName + "'");
- }
-
- const reply = type.getLookup(requisition.executionContext);
- return Promise.resolve(reply).then(lookup => {
- // lookup returns an array of objects with name/value properties and
- // the values might not be JSONable, so remove them
- return lookup.map(info => ({ name: info.name }));
- });
- });
- },
-
- /**
- * Lazy init for a Requisition
- */
- _getRequisition: function() {
- if (this._targetActor == null) {
- throw new Error("GcliActor used post-destroy");
- }
-
- if (this._requisitionPromise != null) {
- return this._requisitionPromise;
- }
-
- const Requisition = require("gcli/cli").Requisition;
- const targetActor = this._targetActor;
-
- this._system = createSystem({ location: "server" });
- this._system.commands.onCommandsChange.add(this._commandsChanged);
-
- const gcliInit = require("devtools/shared/gcli/commands/index");
- gcliInit.addAllItemsByModule(this._system);
-
- // this._requisitionPromise should be created synchronously with the call
- // to _getRequisition so that destroy can tell whether there is an async
- // init in progress
- this._requisitionPromise = this._system.load().then(() => {
- const environment = {
- get chromeWindow() {
- throw new Error("environment.chromeWindow is not available in runAt:server" +
- " commands");
- },
-
- get chromeDocument() {
- throw new Error("environment.chromeDocument is not available in runAt:server" +
- " commands");
- },
-
- get window() {
- return targetActor.window;
- },
-
- get document() {
- return targetActor.window && targetActor.window.document;
- }
- };
-
- return new Requisition(this._system, { environment: environment });
- });
-
- return this._requisitionPromise;
- },
-
- /**
- * Pass events from requisition.system.commands.onCommandsChange upwards
- */
- _commandsChanged: function() {
- this.emit("commands-changed");
- },
-});
-
-exports.GcliActor = GcliActor;
diff --git a/devtools/server/actors/highlighters.js b/devtools/server/actors/highlighters.js
index ff17e60900c9..78b11a9819a7 100644
--- a/devtools/server/actors/highlighters.js
+++ b/devtools/server/actors/highlighters.js
@@ -553,8 +553,7 @@ exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSp
* most frequent way of using it, since highlighters are usually initialized by
* the HighlighterActor or CustomHighlighterActor, which have a targetActor
* reference). It can also be initialized just with a window object (which is
- * useful for when a highlighter is used outside of the debugger server context,
- * for instance from a gcli command).
+ * useful for when a highlighter is used outside of the debugger server context.
*/
function HighlighterEnvironment() {
this.relayTargetActorWindowReady = this.relayTargetActorWindowReady.bind(this);
diff --git a/devtools/server/actors/moz.build b/devtools/server/actors/moz.build
index bd79292d7e5b..dbf8b8f71596 100644
--- a/devtools/server/actors/moz.build
+++ b/devtools/server/actors/moz.build
@@ -38,7 +38,6 @@ DevToolsModules(
'errordocs.js',
'frame.js',
'framerate.js',
- 'gcli.js',
'heap-snapshot-file.js',
'highlighters.css',
'highlighters.js',
diff --git a/devtools/server/actors/webconsole/commands.js b/devtools/server/actors/webconsole/commands.js
index 01648614f1c5..e88790e586f5 100644
--- a/devtools/server/actors/webconsole/commands.js
+++ b/devtools/server/actors/webconsole/commands.js
@@ -116,7 +116,7 @@ function parseCommand(tokens) {
const { value, offset } = collectString(nextToken, tokens, nextTokenIndex);
// in order for JSON.stringify to correctly output values, they must be correctly
// typed
- // As per the GCLI documentation, we can only have one value associated with a
+ // As per the old GCLI documentation, we can only have one value associated with a
// flag but multiple flags with the same name can exist and should be combined
// into and array. Here we are associating only the value on the right hand
// side if it is of type `arg` as a single value; the second case initializes
diff --git a/devtools/server/main.js b/devtools/server/main.js
index eaf2c7721029..f21323c029bf 100644
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -358,11 +358,6 @@ var DebuggerServer = {
constructor: "StorageActor",
type: { target: true }
});
- this.registerModule("devtools/server/actors/gcli", {
- prefix: "gcli",
- constructor: "GcliActor",
- type: { target: true }
- });
this.registerModule("devtools/server/actors/memory", {
prefix: "memory",
constructor: "MemoryActor",
diff --git a/devtools/shared/Loader.jsm b/devtools/shared/Loader.jsm
index 1db7f6ba19dc..66a1ba62c5d9 100644
--- a/devtools/shared/Loader.jsm
+++ b/devtools/shared/Loader.jsm
@@ -33,8 +33,6 @@ BuiltinProvider.prototype = {
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
"devtools": "resource://devtools",
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
- "gcli": "resource://devtools/shared/gcli/source/lib/gcli",
- // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
"acorn": "resource://devtools/shared/acorn",
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
"acorn/util/walk": "resource://devtools/shared/acorn/walk.js",
diff --git a/devtools/shared/fronts/gcli.js b/devtools/shared/fronts/gcli.js
deleted file mode 100644
index dad72dedb2df..000000000000
--- a/devtools/shared/fronts/gcli.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
-const { gcliSpec } = require("devtools/shared/specs/gcli");
-
-/**
- *
- */
-const GcliFront = exports.GcliFront = FrontClassWithSpec(gcliSpec, {
- initialize: function(client, tabForm) {
- Front.prototype.initialize.call(this, client);
- this.actorID = tabForm.gcliActor;
-
- // XXX: This is the first actor type in its hierarchy to use the protocol
- // library, so we're going to self-own on the client side for now.
- this.manage(this);
- },
-});
-
-// A cache of created fronts: WeakMap
-const knownFronts = new WeakMap();
-
-/**
- * Create a GcliFront only when needed (returns a promise)
- * For notes on target.makeRemote(), see
- * https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c7
- */
-exports.GcliFront.create = function(target) {
- return target.makeRemote().then(() => {
- let front = knownFronts.get(target.client);
- if (front == null && target.form.gcliActor != null) {
- front = new GcliFront(target.client, target.form);
- knownFronts.set(target.client, front);
- }
- return front;
- });
-};
diff --git a/devtools/shared/fronts/moz.build b/devtools/shared/fronts/moz.build
index eebfa5f6bf4a..7723a7525a8e 100644
--- a/devtools/shared/fronts/moz.build
+++ b/devtools/shared/fronts/moz.build
@@ -19,7 +19,6 @@ DevToolsModules(
'device.js',
'emulation.js',
'framerate.js',
- 'gcli.js',
'highlighters.js',
'inspector.js',
'layout.js',
diff --git a/devtools/shared/gcli/command-state.js b/devtools/shared/gcli/command-state.js
deleted file mode 100644
index b9a875d8e4d1..000000000000
--- a/devtools/shared/gcli/command-state.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EventEmitter = require("devtools/shared/event-emitter");
-
-const getTargetId = ({tab}) => tab.linkedBrowser.outerWindowID;
-const enabledCommands = new Map();
-
-/**
- * The `CommandState` is a singleton that provides utility methods to keep the commands'
- * state in sync between the toolbox, the toolbar and the content.
- */
-const CommandState = EventEmitter.decorate({
- /**
- * Returns if a command is enabled on a given target.
- *
- * @param {Object} target
- * The target object must have a tab's reference.
- * @param {String} command
- * The command's name used in gcli.
- * @ returns {Boolean} returns `false` if the command is not enabled for the target
- * given, or if the target given hasn't a tab; `true` otherwise.
- */
- isEnabledForTarget(target, command) {
- if (!target.tab || !enabledCommands.has(command)) {
- return false;
- }
-
- return enabledCommands.get(command).has(getTargetId(target));
- },
-
- /**
- * Enables a command on a given target.
- * Emits a "changed" event to notify potential observers about the new commands state.
- *
- * @param {Object} target
- * The target object must have a tab's reference.
- * @param {String} command
- * The command's name used in gcli.
- */
- enableForTarget(target, command) {
- if (!target.tab) {
- return;
- }
-
- if (!enabledCommands.has(command)) {
- enabledCommands.set(command, new Set());
- }
-
- enabledCommands.get(command).add(getTargetId(target));
-
- CommandState.emit("changed", {target, command});
- },
-
- /**
- * Disabled a command on a given target.
- * Emits a "changed" event to notify potential observers about the new commands state.
- *
- * @param {Object} target
- * The target object must have a tab's reference.
- * @param {String} command
- * The command's name used in gcli.
- */
- disableForTarget(target, command) {
- if (!target.tab || !enabledCommands.has(command)) {
- return;
- }
-
- enabledCommands.get(command).delete(getTargetId(target));
-
- CommandState.emit("changed", {target, command});
- },
-});
-exports.CommandState = CommandState;
-
diff --git a/devtools/shared/gcli/commands/index.js b/devtools/shared/gcli/commands/index.js
deleted file mode 100644
index bfdf94cd3c6b..000000000000
--- a/devtools/shared/gcli/commands/index.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { createSystem, connectFront, disconnectFront } = require("gcli/system");
-const { GcliFront } = require("devtools/shared/fronts/gcli");
-
-/**
- * This is the basic list of modules that should be loaded into each
- * requisition instance whether server side or client side
- */
-exports.baseModules = [
- "gcli/types/delegate",
- "gcli/types/selection",
- "gcli/types/array",
-
- "gcli/types/boolean",
- "gcli/types/command",
- "gcli/types/date",
- "gcli/types/file",
- "gcli/types/javascript",
- "gcli/types/node",
- "gcli/types/number",
- "gcli/types/resource",
- "gcli/types/setting",
- "gcli/types/string",
- "gcli/types/union",
- "gcli/types/url",
-
- "gcli/fields/fields",
- "gcli/fields/delegate",
- "gcli/fields/selection",
-
- "gcli/ui/focus",
- "gcli/ui/intro",
-
- "gcli/converters/converters",
- "gcli/converters/basic",
- "gcli/converters/terminal",
-
- "gcli/languages/command",
- "gcli/languages/javascript",
-
- "gcli/commands/clear",
- "gcli/commands/context",
- "gcli/commands/help",
- "gcli/commands/pref",
-];
-
-/**
- * Some commands belong to a tool (see getToolModules). This is a list of the
- * modules that are *not* owned by a tool.
- */
-exports.devtoolsModules = [
- "devtools/shared/gcli/commands/measure",
- "devtools/shared/gcli/commands/paintflashing",
- "devtools/shared/gcli/commands/rulers",
- "devtools/shared/gcli/commands/screenshot",
-];
-
-/**
- * Register commands from tools with 'command: [ "some/module" ]' definitions.
- * The map/reduce incantation squashes the array of arrays to a single array.
- */
-try {
- const { defaultTools } = require("devtools/client/definitions");
- exports.devtoolsToolModules = defaultTools.map(def => def.commands || [])
- .reduce((prev, curr) => prev.concat(curr), []);
-} catch (e) {
- // "devtools/client/definitions" is only accessible from Firefox
- exports.devtoolsToolModules = [];
-}
-
-/**
- * Register commands from toolbox buttons with 'command: [ "some/module" ]'
- * definitions. The map/reduce incantation squashes the array of arrays to a
- * single array.
- */
-try {
- const { ToolboxButtons } = require("devtools/client/definitions");
- exports.devtoolsButtonModules = ToolboxButtons.map(def => def.commands || [])
- .reduce((prev, curr) => prev.concat(curr), []);
-} catch (e) {
- // "devtools/client/definitions" is only accessible from Firefox
- exports.devtoolsButtonModules = [];
-}
-
-/**
- * Add modules to a system for use in a content process (but don't call load)
- */
-exports.addAllItemsByModule = function(system) {
- system.addItemsByModule(exports.baseModules, { delayedLoad: true });
- system.addItemsByModule(exports.devtoolsModules, { delayedLoad: true });
- system.addItemsByModule(exports.devtoolsToolModules, { delayedLoad: true });
- system.addItemsByModule(exports.devtoolsButtonModules, { delayedLoad: true });
-};
-
-/**
- * This is WeakMap where Links is an object that looks like
- * { refs: number, promise: Promise, front: GcliFront }
- */
-var linksForTarget = new WeakMap();
-
-/**
- * The toolbox uses the following properties on a command to allow it to be
- * added to the toolbox toolbar
- */
-var customProperties = [ "buttonId", "buttonClass", "tooltipText" ];
-
-/**
- * Create a system which connects to a GCLI in a remote target
- * @return Promise for the given target
- */
-exports.getSystem = function(target) {
- const existingLinks = linksForTarget.get(target);
- if (existingLinks != null) {
- existingLinks.refs++;
- return existingLinks.promise;
- }
-
- const system = createSystem({ location: "client" });
-
- exports.addAllItemsByModule(system);
-
- // Load the client system
- const links = {
- refs: 1,
- system,
- promise: system.load().then(() => {
- return GcliFront.create(target).then(front => {
- links.front = front;
- return connectFront(system, front, customProperties).then(() => system);
- });
- })
- };
-
- linksForTarget.set(target, links);
- return links.promise;
-};
-
-/**
- * Someone that called getSystem doesn't need it any more, so decrement the
- * count of users of the system for that target, and destroy if needed
- */
-exports.releaseSystem = function(target) {
- const links = linksForTarget.get(target);
- if (links == null) {
- throw new Error("releaseSystem called for unknown target");
- }
-
- links.refs--;
- if (links.refs === 0) {
- disconnectFront(links.system, links.front);
- links.system.destroy();
- linksForTarget.delete(target);
- }
-};
diff --git a/devtools/shared/gcli/commands/measure.js b/devtools/shared/gcli/commands/measure.js
deleted file mode 100644
index 8deeaf6cc0ab..000000000000
--- a/devtools/shared/gcli/commands/measure.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EventEmitter = require("devtools/shared/event-emitter");
-
-loader.lazyRequireGetter(this, "CommandState",
- "devtools/shared/gcli/command-state", true);
-
-const l10n = require("gcli/l10n");
-require("devtools/server/actors/inspector/inspector");
-const { HighlighterEnvironment } =
- require("devtools/server/actors/highlighters");
-const { MeasuringToolHighlighter } =
- require("devtools/server/actors/highlighters/measuring-tool");
-
-const highlighters = new WeakMap();
-
-exports.items = [
- // The client measure command is used to maintain the toolbar button state
- // only and redirects to the server command to actually toggle the measuring
- // tool (see `measure_server` below).
- {
- name: "measure",
- runAt: "client",
- description: l10n.lookup("measureDesc"),
- manual: l10n.lookup("measureManual"),
- buttonId: "command-button-measure",
- buttonClass: "command-button",
- tooltipText: l10n.lookup("measureTooltip"),
- state: {
- isChecked: (target) => CommandState.isEnabledForTarget(target, "measure"),
- onChange: (target, handler) => CommandState.on("changed", handler),
- offChange: (target, handler) => CommandState.off("changed", handler)
- },
- exec: function* (args, context) {
- const { target } = context.environment;
-
- // Pipe the call to the server command.
- const response = yield context.updateExec("measure_server");
- const isEnabled = response.data;
-
- if (isEnabled) {
- CommandState.enableForTarget(target, "measure");
- } else {
- CommandState.disableForTarget(target, "measure");
- }
-
- // Toggle off the button when the page navigates because the measuring
- // tool is removed automatically by the MeasuringToolHighlighter on the
- // server then.
- target.once("will-navigate", () =>
- CommandState.disableForTarget(target, "measure"));
- }
- },
- // The server measure command is hidden by default, it's just used by the
- // client command.
- {
- name: "measure_server",
- runAt: "server",
- hidden: true,
- returnType: "highlighterVisibility",
- exec: function(args, context) {
- const env = context.environment;
- const { document } = env;
-
- // Calling the command again after the measuring tool has been shown once,
- // hides it.
- if (highlighters.has(document)) {
- const { highlighter } = highlighters.get(document);
- highlighter.destroy();
- return false;
- }
-
- // Otherwise, display the measuring tool.
- const environment = new HighlighterEnvironment();
- environment.initFromWindow(env.window);
- const highlighter = new MeasuringToolHighlighter(environment);
-
- // Store the instance of the measuring tool highlighter for this document
- // so we can hide it later.
- highlighters.set(document, { highlighter, environment });
-
- // Listen to the highlighter's destroy event which may happen if the
- // window is refreshed or closed with the measuring tool shown.
- EventEmitter.once(highlighter, "destroy", () => {
- if (highlighters.has(document)) {
- const { environment: toDestroy } = highlighters.get(document);
- toDestroy.destroy();
- highlighters.delete(document);
- }
- });
-
- highlighter.show();
- return true;
- }
- }
-];
diff --git a/devtools/shared/gcli/commands/moz.build b/devtools/shared/gcli/commands/moz.build
deleted file mode 100644
index 98e2e415e912..000000000000
--- a/devtools/shared/gcli/commands/moz.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'index.js',
- 'measure.js',
- 'paintflashing.js',
- 'rulers.js',
- 'screenshot.js',
-)
diff --git a/devtools/shared/gcli/commands/paintflashing.js b/devtools/shared/gcli/commands/paintflashing.js
deleted file mode 100644
index 162c051ba7c9..000000000000
--- a/devtools/shared/gcli/commands/paintflashing.js
+++ /dev/null
@@ -1,182 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-loader.lazyRequireGetter(this, "CommandState",
- "devtools/shared/gcli/command-state", true);
-
-var telemetry;
-try {
- const Telemetry = require("devtools/client/shared/telemetry");
- telemetry = new Telemetry();
-} catch (e) {
- // DevTools Telemetry module only available in Firefox
-}
-
-const gcli = require("gcli/index");
-const l10n = require("gcli/l10n");
-
-/**
- * Fire events and telemetry when paintFlashing happens
- */
-function onPaintFlashingChanged(target, flashing) {
- if (flashing) {
- CommandState.enableForTarget(target, "paintflashing");
- } else {
- CommandState.disableForTarget(target, "paintflashing");
- }
-
- target.once("will-navigate", () =>
- CommandState.disableForTarget(target, "paintflashing"));
-
- if (!telemetry) {
- return;
- }
- if (flashing) {
- telemetry.toolOpened("paintflashing");
- } else {
- telemetry.toolClosed("paintflashing");
- }
-}
-
-/**
- * Alter the paintFlashing state of a window and report on the new value.
- * This works with chrome or content windows.
- *
- * This is a bizarre method that you could argue should be broken up into
- * separate getter and setter functions, however keeping it as one helps
- * to simplify the commands below.
- *
- * @param state {string} One of:
- * - "on" which does window.paintFlashing = true
- * - "off" which does window.paintFlashing = false
- * - "toggle" which does window.paintFlashing = !window.paintFlashing
- * - "query" which does nothing
- * @return The new value of the window.paintFlashing flag
- */
-function setPaintFlashing(window, state) {
- const winUtils = window.windowUtils;
-
- if (!["on", "off", "toggle", "query"].includes(state)) {
- throw new Error(`Unsupported state: ${state}`);
- }
-
- if (state === "on") {
- winUtils.paintFlashing = true;
- } else if (state === "off") {
- winUtils.paintFlashing = false;
- } else if (state === "toggle") {
- winUtils.paintFlashing = !winUtils.paintFlashing;
- }
-
- return winUtils.paintFlashing;
-}
-
-exports.items = [
- {
- name: "paintflashing",
- description: l10n.lookup("paintflashingDesc")
- },
- {
- item: "command",
- runAt: "client",
- name: "paintflashing on",
- description: l10n.lookup("paintflashingOnDesc"),
- manual: l10n.lookup("paintflashingManual"),
- params: [{
- group: "options",
- params: [
- {
- type: "boolean",
- name: "chrome",
- get hidden() {
- return gcli.hiddenByChromePref();
- },
- description: l10n.lookup("paintflashingChromeDesc"),
- }
- ]
- }],
- exec: function* (args, context) {
- if (!args.chrome) {
- const output = yield context.updateExec("paintflashing_server --state on");
-
- onPaintFlashingChanged(context.environment.target, output.data);
- } else {
- setPaintFlashing(context.environment.chromeWindow, "on");
- }
- }
- },
- {
- item: "command",
- runAt: "client",
- name: "paintflashing off",
- description: l10n.lookup("paintflashingOffDesc"),
- manual: l10n.lookup("paintflashingManual"),
- params: [{
- group: "options",
- params: [
- {
- type: "boolean",
- name: "chrome",
- get hidden() {
- return gcli.hiddenByChromePref();
- },
- description: l10n.lookup("paintflashingChromeDesc"),
- }
- ]
- }],
- exec: function* (args, context) {
- if (!args.chrome) {
- const output = yield context.updateExec("paintflashing_server --state off");
-
- onPaintFlashingChanged(context.environment.target, output.data);
- } else {
- setPaintFlashing(context.environment.chromeWindow, "off");
- }
- }
- },
- {
- item: "command",
- runAt: "client",
- name: "paintflashing toggle",
- hidden: true,
- buttonId: "command-button-paintflashing",
- buttonClass: "command-button",
- state: {
- isChecked: (target) => CommandState.isEnabledForTarget(target, "paintflashing"),
- onChange: (_, handler) => CommandState.on("changed", handler),
- offChange: (_, handler) => CommandState.off("changed", handler),
- },
- tooltipText: l10n.lookup("paintflashingTooltip"),
- description: l10n.lookup("paintflashingToggleDesc"),
- manual: l10n.lookup("paintflashingManual"),
- exec: function* (args, context) {
- const output = yield context.updateExec("paintflashing_server --state toggle");
-
- onPaintFlashingChanged(context.environment.target, output.data);
- }
- },
- {
- item: "command",
- runAt: "server",
- name: "paintflashing_server",
- hidden: true,
- params: [
- {
- name: "state",
- type: {
- name: "selection",
- data: [ "on", "off", "toggle", "query" ]
- }
- },
- ],
- returnType: "paintFlashingState",
- exec: function(args, context) {
- const { window } = context.environment;
-
- return setPaintFlashing(window, args.state);
- }
- }
-];
diff --git a/devtools/shared/gcli/commands/rulers.js b/devtools/shared/gcli/commands/rulers.js
deleted file mode 100644
index 110504ea414f..000000000000
--- a/devtools/shared/gcli/commands/rulers.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EventEmitter = require("devtools/shared/event-emitter");
-
-loader.lazyRequireGetter(this, "CommandState",
- "devtools/shared/gcli/command-state", true);
-
-const l10n = require("gcli/l10n");
-require("devtools/server/actors/inspector/inspector");
-const { HighlighterEnvironment } =
- require("devtools/server/actors/highlighters");
-const { RulersHighlighter } =
- require("devtools/server/actors/highlighters/rulers");
-
-const highlighters = new WeakMap();
-
-exports.items = [
- // The client rulers command is used to maintain the toolbar button state only
- // and redirects to the server command to actually toggle the rulers (see
- // rulers_server below).
- {
- name: "rulers",
- runAt: "client",
- description: l10n.lookup("rulersDesc"),
- manual: l10n.lookup("rulersManual"),
- buttonId: "command-button-rulers",
- buttonClass: "command-button",
- tooltipText: l10n.lookup("rulersTooltip"),
- state: {
- isChecked: (target) => CommandState.isEnabledForTarget(target, "rulers"),
- onChange: (target, handler) => CommandState.on("changed", handler),
- offChange: (target, handler) => CommandState.off("changed", handler)
- },
- exec: function* (args, context) {
- const { target } = context.environment;
-
- // Pipe the call to the server command.
- const response = yield context.updateExec("rulers_server");
- const isEnabled = response.data;
-
- if (isEnabled) {
- CommandState.enableForTarget(target, "rulers");
- } else {
- CommandState.disableForTarget(target, "rulers");
- }
-
- // Toggle off the button when the page navigates because the rulers are
- // removed automatically by the RulersHighlighter on the server then.
- target.once("will-navigate", () => CommandState.disableForTarget(target, "rulers"));
- }
- },
- // The server rulers command is hidden by default, it's just used by the
- // client command.
- {
- name: "rulers_server",
- runAt: "server",
- hidden: true,
- returnType: "highlighterVisibility",
- exec: function(args, context) {
- const env = context.environment;
- const { document } = env;
-
- // Calling the command again after the rulers have been shown once hides
- // them.
- if (highlighters.has(document)) {
- const { highlighter } = highlighters.get(document);
- highlighter.destroy();
- return false;
- }
-
- // Otherwise, display the rulers.
- const environment = new HighlighterEnvironment();
- environment.initFromWindow(env.window);
- const highlighter = new RulersHighlighter(environment);
-
- // Store the instance of the rulers highlighter for this document so we
- // can hide it later.
- highlighters.set(document, { highlighter, environment });
-
- // Listen to the highlighter's destroy event which may happen if the
- // window is refreshed or closed with the rulers shown.
- EventEmitter.once(highlighter, "destroy", () => {
- if (highlighters.has(document)) {
- const { environment: toDestroy } = highlighters.get(document);
- toDestroy.destroy();
- highlighters.delete(document);
- }
- });
-
- highlighter.show();
- return true;
- }
- }
-];
diff --git a/devtools/shared/gcli/commands/screenshot.js b/devtools/shared/gcli/commands/screenshot.js
deleted file mode 100644
index 355e1c9cd4c3..000000000000
--- a/devtools/shared/gcli/commands/screenshot.js
+++ /dev/null
@@ -1,593 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { Cc, Ci, Cr, Cu } = require("chrome");
-const ChromeUtils = require("ChromeUtils");
-const l10n = require("gcli/l10n");
-const Services = require("Services");
-const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
-const { getRect } = require("devtools/shared/layout/utils");
-const defer = require("devtools/shared/defer");
-const { Task } = require("devtools/shared/task");
-
-loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
-
-loader.lazyImporter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
-loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
-loader.lazyImporter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
-loader.lazyImporter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-// String used as an indication to generate default file name in the following
-// format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
-const FILENAME_DEFAULT_VALUE = " ";
-const CONTAINER_FLASHING_DURATION = 500;
-
-/*
- * There are 2 commands and 1 converter here. The 2 commands are nearly
- * identical except that one runs on the client and one in the server.
- *
- * The server command is hidden, and is designed to be called from the client
- * command.
- */
-
-/**
- * Both commands have the same initial filename parameter
- */
-const filenameParam = {
- name: "filename",
- type: "string",
- defaultValue: FILENAME_DEFAULT_VALUE,
- description: l10n.lookup("screenshotFilenameDesc"),
- manual: l10n.lookup("screenshotFilenameManual")
-};
-
-/**
- * Both commands have almost the same set of standard optional parameters, except for the
- * type of the --selector option, which can be a node only on the server.
- */
-const getScreenshotCommandParams = function(isClient) {
- return {
- group: l10n.lookup("screenshotGroupOptions"),
- params: [
- {
- name: "clipboard",
- type: "boolean",
- description: l10n.lookup("screenshotClipboardDesc"),
- manual: l10n.lookup("screenshotClipboardManual")
- },
- {
- name: "imgur",
- type: "boolean",
- description: l10n.lookup("screenshotImgurDesc"),
- manual: l10n.lookup("screenshotImgurManual")
- },
- {
- name: "delay",
- type: { name: "number", min: 0 },
- defaultValue: 0,
- description: l10n.lookup("screenshotDelayDesc"),
- manual: l10n.lookup("screenshotDelayManual")
- },
- {
- name: "dpr",
- type: { name: "number", min: 0, allowFloat: true },
- defaultValue: 0,
- description: l10n.lookup("screenshotDPRDesc"),
- manual: l10n.lookup("screenshotDPRManual")
- },
- {
- name: "fullpage",
- type: "boolean",
- description: l10n.lookup("screenshotFullPageDesc"),
- manual: l10n.lookup("screenshotFullPageManual")
- },
- {
- name: "selector",
- // On the client side, don't try to parse the selector as a node as it will
- // trigger an unsafe CPOW.
- type: isClient ? "string" : "node",
- defaultValue: null,
- description: l10n.lookup("inspectNodeDesc"),
- manual: l10n.lookup("inspectNodeManual")
- },
- {
- name: "file",
- type: "boolean",
- description: l10n.lookup("screenshotFileDesc"),
- manual: l10n.lookup("screenshotFileManual"),
- },
- ]
- };
-};
-
-const clientScreenshotParams = getScreenshotCommandParams(true);
-const serverScreenshotParams = getScreenshotCommandParams(false);
-
-exports.items = [
- {
- /**
- * Format an 'imageSummary' (as output by the screenshot command).
- * An 'imageSummary' is a simple JSON object that looks like this:
- *
- * {
- * destinations: [ "..." ], // Required array of descriptions of the
- * // locations of the result image (the command
- * // can have multiple outputs)
- * data: "...", // Optional Base64 encoded image data
- * width:1024, height:768, // Dimensions of the image data, required
- * // if data != null
- * filename: "...", // If set, clicking the image will open the
- * // folder containing the given file
- * href: "...", // If set, clicking the image will open the
- * // link in a new tab
- * }
- */
- item: "converter",
- from: "imageSummary",
- to: "dom",
- exec: function(imageSummary, context) {
- const document = context.document;
- const root = document.createElement("div");
-
- // Add a line to the result for each destination
- imageSummary.destinations.forEach(destination => {
- const title = document.createElement("div");
- title.textContent = destination;
- root.appendChild(title);
- });
-
- // Add the thumbnail image
- if (imageSummary.data != null) {
- const image = context.document.createElement("div");
- const previewHeight = parseInt(256 * imageSummary.height / imageSummary.width,
- 10);
- const style = "" +
- "width: 256px;" +
- "height: " + previewHeight + "px;" +
- "max-height: 256px;" +
- "background-image: url('" + imageSummary.data + "');" +
- "background-size: 256px " + previewHeight + "px;" +
- "margin: 4px;" +
- "display: block;";
- image.setAttribute("style", style);
- root.appendChild(image);
- }
-
- // Click handler
- if (imageSummary.href || imageSummary.filename) {
- root.style.cursor = "pointer";
- root.addEventListener("click", () => {
- if (imageSummary.href) {
- openContentLink(imageSummary.href);
- } else if (imageSummary.filename) {
- const file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
- file.initWithPath(imageSummary.filename);
- file.reveal();
- }
- });
- }
-
- return root;
- }
- },
- {
- item: "command",
- runAt: "client",
- name: "screenshot",
- description: l10n.lookup("screenshotDesc"),
- manual: l10n.lookup("screenshotManual"),
- returnType: "imageSummary",
- buttonId: "command-button-screenshot",
- buttonClass: "command-button",
- tooltipText: l10n.lookup("screenshotTooltipPage"),
- params: [
- filenameParam,
- clientScreenshotParams,
- ],
- exec: function(args, context) {
- // Re-execute the command on the server
- const command = context.typed.replace(/^screenshot/, "screenshot_server");
- const capture = context.updateExec(command).then(output => {
- return output.error ? Promise.reject(output.data) : output.data;
- });
-
- simulateCameraEffect(context.environment.chromeDocument, "shutter");
- return capture.then(saveScreenshot.bind(null, args, context));
- },
- },
- {
- item: "command",
- runAt: "server",
- name: "screenshot_server",
- hidden: true,
- returnType: "imageSummary",
- params: [
- filenameParam,
- serverScreenshotParams,
- ],
- exec: function(args, context) {
- return captureScreenshot(args, context.environment.document);
- },
- }
-];
-
-/**
- * This function is called to simulate camera effects
- */
-function simulateCameraEffect(document, effect) {
- const window = document.defaultView;
- if (effect === "shutter") {
- if (Services.prefs.getBoolPref("devtools.screenshot.audio.enabled")) {
- const audioCamera = new window.Audio("resource://devtools/client/themes/audio/shutter.wav");
- audioCamera.play();
- }
- }
- if (effect == "flash") {
- const frames = Cu.cloneInto({ opacity: [ 0, 1 ] }, window);
- document.documentElement.animate(frames, CONTAINER_FLASHING_DURATION);
- }
-}
-
-/**
- * This function simply handles the --delay argument before calling
- * createScreenshotData
- */
-function captureScreenshot(args, document) {
- if (args.delay > 0) {
- return new Promise((resolve, reject) => {
- document.defaultView.setTimeout(() => {
- createScreenshotData(document, args).then(resolve, reject);
- }, args.delay * 1000);
- });
- }
- return createScreenshotData(document, args);
-}
-
-/**
- * There are several possible destinations for the screenshot, SKIP is used
- * in saveScreenshot() whenever one of them is not used
- */
-const SKIP = Promise.resolve();
-
-/**
- * Save the captured screenshot to one of several destinations.
- */
-function saveScreenshot(args, context, reply) {
- const fileNeeded = args.filename != FILENAME_DEFAULT_VALUE ||
- (!args.imgur && !args.clipboard) || args.file;
-
- return Promise.all([
- args.clipboard ? saveToClipboard(context, reply) : SKIP,
- args.imgur ? uploadToImgur(reply) : SKIP,
- fileNeeded ? saveToFile(context, reply) : SKIP,
- ]).then(() => reply);
-}
-
-/**
- * This does the dirty work of creating a base64 string out of an
- * area of the browser window
- */
-function createScreenshotData(document, args) {
- const window = document.defaultView;
- let left = 0;
- let top = 0;
- let width;
- let height;
- const currentX = window.scrollX;
- const currentY = window.scrollY;
-
- let filename = getFilename(args.filename);
-
- if (args.fullpage) {
- // Bug 961832: GCLI screenshot shows fixed position element in wrong
- // position if we don't scroll to top
- window.scrollTo(0, 0);
- width = window.innerWidth + window.scrollMaxX - window.scrollMinX;
- height = window.innerHeight + window.scrollMaxY - window.scrollMinY;
- filename = filename.replace(".png", "-fullpage.png");
- } else if (args.selector) {
- ({ top, left, width, height } = getRect(window, args.selector, window));
- } else {
- left = window.scrollX;
- top = window.scrollY;
- width = window.innerWidth;
- height = window.innerHeight;
- }
-
- // Only adjust for scrollbars when considering the full window
- if (!args.selector) {
- const winUtils = window.windowUtils;
- const scrollbarHeight = {};
- const scrollbarWidth = {};
- winUtils.getScrollbarSize(false, scrollbarWidth, scrollbarHeight);
- width -= scrollbarWidth.value;
- height -= scrollbarHeight.value;
- }
-
- const canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
- const ctx = canvas.getContext("2d");
- const ratio = args.dpr ? args.dpr : window.devicePixelRatio;
- canvas.width = width * ratio;
- canvas.height = height * ratio;
- ctx.scale(ratio, ratio);
- ctx.drawWindow(window, left, top, width, height, "#fff");
- const data = canvas.toDataURL("image/png", "");
-
- // See comment above on bug 961832
- if (args.fullpage) {
- window.scrollTo(currentX, currentY);
- }
-
- simulateCameraEffect(document, "flash");
-
- return Promise.resolve({
- destinations: [],
- data: data,
- height: height,
- width: width,
- filename: filename,
- });
-}
-
-/**
- * We may have a filename specified in args, or we might have to generate
- * one.
- */
-function getFilename(defaultName) {
- // Create a name for the file if not present
- if (defaultName != FILENAME_DEFAULT_VALUE) {
- return defaultName;
- }
-
- const date = new Date();
- let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
- "-" + date.getDate();
- dateString = dateString.split("-").map(function(part) {
- if (part.length == 1) {
- part = "0" + part;
- }
- return part;
- }).join("-");
-
- const timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
- return l10n.lookupFormat("screenshotGeneratedFilename",
- [ dateString, timeString ]) + ".png";
-}
-
-/**
- * Save the image data to the clipboard. This returns a promise, so it can
- * be treated exactly like imgur / file processing, but it's really sync
- * for now.
- */
-function saveToClipboard(context, reply) {
- return new Promise(resolve => {
- try {
- const channel = NetUtil.newChannel({
- uri: reply.data,
- loadUsingSystemPrincipal: true,
- contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
- });
- const input = channel.open2();
-
- const loadContext = context.environment.chromeWindow.docShell
- .QueryInterface(Ci.nsILoadContext);
-
- const callback = {
- onImageReady(container, status) {
- if (!container) {
- console.error("imgTools.decodeImageAsync failed");
- reply.destinations.push(l10n.lookup("screenshotErrorCopying"));
- resolve();
- return;
- }
-
- try {
- const wrapped = Cc["@mozilla.org/supports-interface-pointer;1"]
- .createInstance(Ci.nsISupportsInterfacePointer);
- wrapped.data = container;
-
- const trans = Cc["@mozilla.org/widget/transferable;1"]
- .createInstance(Ci.nsITransferable);
- trans.init(loadContext);
- trans.addDataFlavor(channel.contentType);
- trans.setTransferData(channel.contentType, wrapped, -1);
-
- Services.clipboard.setData(trans, null, Ci.nsIClipboard.kGlobalClipboard);
-
- reply.destinations.push(l10n.lookup("screenshotCopied"));
- } catch (ex) {
- console.error(ex);
- reply.destinations.push(l10n.lookup("screenshotErrorCopying"));
- }
- resolve();
- }
- };
-
- const threadManager = Cc["@mozilla.org/thread-manager;1"].getService();
- const imgTools = Cc["@mozilla.org/image/tools;1"]
- .getService(Ci.imgITools);
- imgTools.decodeImageAsync(input, channel.contentType, callback,
- threadManager.currentThread);
- } catch (ex) {
- console.error(ex);
- reply.destinations.push(l10n.lookup("screenshotErrorCopying"));
- resolve();
- }
- });
-}
-
-/**
- * Upload screenshot data to Imgur, returning a promise of a URL (as a string)
- */
-function uploadToImgur(reply) {
- return new Promise((resolve, reject) => {
- const xhr = new XMLHttpRequest();
- const fd = new FormData();
- fd.append("image", reply.data.split(",")[1]);
- fd.append("type", "base64");
- fd.append("title", reply.filename);
-
- const postURL = Services.prefs.getCharPref("devtools.gcli.imgurUploadURL");
- const clientID = "Client-ID " +
- Services.prefs.getCharPref("devtools.gcli.imgurClientID");
-
- xhr.open("POST", postURL);
- xhr.setRequestHeader("Authorization", clientID);
- xhr.send(fd);
- xhr.responseType = "json";
-
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- if (xhr.status == 200) {
- reply.href = xhr.response.data.link;
- reply.destinations.push(l10n.lookupFormat("screenshotImgurUploaded",
- [ reply.href ]));
- } else {
- reply.destinations.push(l10n.lookup("screenshotImgurError"));
- }
-
- resolve();
- }
- };
- });
-}
-
-/**
- * Progress listener that forwards calls to a transfer object.
- *
- * This is used below in saveToFile to forward progress updates from the
- * nsIWebBrowserPersist object that does the actual saving to the nsITransfer
- * which just represents the operation for the Download Manager. This keeps the
- * Download Manager updated on saving progress and completion, so that it gives
- * visual feedback from the downloads toolbar button when the save is done.
- *
- * It also allows the browser window to show auth prompts if needed (should not
- * be needed for saving screenshots).
- *
- * This code is borrowed directly from contentAreaUtils.js.
- */
-function DownloadListener(win, transfer) {
- this.window = win;
- this.transfer = transfer;
-
- // For most method calls, forward to the transfer object.
- for (const name in transfer) {
- if (name != "QueryInterface" &&
- name != "onStateChange") {
- this[name] = (...args) => transfer[name].apply(transfer, args);
- }
- }
-
- // Allow saveToFile to await completion for error handling
- this._completedDeferred = defer();
- this.completed = this._completedDeferred.promise;
-}
-
-DownloadListener.prototype = {
- QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor",
- "nsIWebProgressListener",
- "nsIWebProgressListener2"]),
-
- getInterface: function(iid) {
- if (iid.equals(Ci.nsIAuthPrompt) ||
- iid.equals(Ci.nsIAuthPrompt2)) {
- const ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(Ci.nsIPromptFactory);
- return ww.getPrompt(this.window, iid);
- }
-
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
-
- onStateChange: function(webProgress, request, state, status) {
- // Check if the download has completed
- if ((state & Ci.nsIWebProgressListener.STATE_STOP) &&
- (state & Ci.nsIWebProgressListener.STATE_IS_NETWORK)) {
- if (status == Cr.NS_OK) {
- this._completedDeferred.resolve();
- } else {
- this._completedDeferred.reject();
- }
- }
-
- this.transfer.onStateChange.apply(this.transfer, arguments);
- }
-};
-
-/**
- * Save the screenshot data to disk, returning a promise which is resolved on
- * completion.
- */
-var saveToFile = Task.async(function* (context, reply) {
- const document = context.environment.chromeDocument;
- const window = context.environment.chromeWindow;
-
- // Check there is a .png extension to filename
- if (!reply.filename.match(/.png$/i)) {
- reply.filename += ".png";
- }
-
- const downloadsDir = yield Downloads.getPreferredDownloadsDirectory();
- const downloadsDirExists = yield OS.File.exists(downloadsDir);
- if (downloadsDirExists) {
- // If filename is absolute, it will override the downloads directory and
- // still be applied as expected.
- reply.filename = OS.Path.join(downloadsDir, reply.filename);
- }
-
- const sourceURI = Services.io.newURI(reply.data);
- const targetFile = new FileUtils.File(reply.filename);
- const targetFileURI = Services.io.newFileURI(targetFile);
-
- // Create download and track its progress.
- // This is adapted from saveURL in contentAreaUtils.js, but simplified greatly
- // and modified to allow saving to arbitrary paths on disk. Using these
- // objects as opposed to just writing with OS.File allows us to tie into the
- // download manager to record a download entry and to get visual feedback from
- // the downloads toolbar button when the save is done.
- const nsIWBP = Ci.nsIWebBrowserPersist;
- const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
- nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
- nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
- const isPrivate =
- PrivateBrowsingUtils.isContentWindowPrivate(document.defaultView);
- const persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
- .createInstance(Ci.nsIWebBrowserPersist);
- persist.persistFlags = flags;
- const tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
- tr.init(sourceURI,
- targetFileURI,
- "",
- null,
- null,
- null,
- persist,
- isPrivate);
- const listener = new DownloadListener(window, tr);
- persist.progressListener = listener;
- const principal = Services.scriptSecurityManager.getSystemPrincipal();
- persist.savePrivacyAwareURI(sourceURI,
- principal,
- 0,
- document.documentURIObject,
- Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
- null,
- null,
- targetFileURI,
- isPrivate);
-
- try {
- // Await successful completion of the save via the listener
- yield listener.completed;
- reply.destinations.push(l10n.lookup("screenshotSavedToFile") +
- ` "${reply.filename}"`);
- } catch (ex) {
- console.error(ex);
- reply.destinations.push(l10n.lookup("screenshotErrorSavingToFile") + " " +
- reply.filename);
- }
-});
diff --git a/devtools/shared/gcli/moz.build b/devtools/shared/gcli/moz.build
deleted file mode 100644
index be9317aa87b5..000000000000
--- a/devtools/shared/gcli/moz.build
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += [
- 'commands',
- 'source/lib/gcli',
- 'source/lib/gcli/connectors',
- 'source/lib/gcli/converters',
- 'source/lib/gcli/commands',
- 'source/lib/gcli/fields',
- 'source/lib/gcli/languages',
- 'source/lib/gcli/mozui',
- 'source/lib/gcli/types',
- 'source/lib/gcli/ui',
- 'source/lib/gcli/util',
-]
-
-DevToolsModules(
- 'command-state.js',
- 'templater.js'
-)
diff --git a/devtools/shared/gcli/source/LICENSE b/devtools/shared/gcli/source/LICENSE
deleted file mode 100644
index d64569567334..000000000000
--- a/devtools/shared/gcli/source/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/devtools/shared/gcli/source/docs/design.md b/devtools/shared/gcli/source/docs/design.md
deleted file mode 100644
index 5e3c0a2f3097..000000000000
--- a/devtools/shared/gcli/source/docs/design.md
+++ /dev/null
@@ -1,102 +0,0 @@
-
-# The Design of GCLI
-
-## Design Goals
-
-GCLI should be:
-
-- primarily for technical users.
-- as fast as a traditional CLI. It should be possible to put your head down,
- and look at the keyboard and use GCLI 'blind' at full speed without making
- mistakes.
-- principled about the way it encourages people to build commands. There is
- benefit from unifying the underlying concepts.
-- automatically helpful.
-
-GCLI should not attempt to:
-
-- convert existing GUI users to a CLI.
-- use natural language input. The closest we should get to natural language is
- thinking of commands as ```verb noun --adjective```.
-- gain a touch based interface. Whilst it's possible (even probable) that touch
- can provide further benefits to command line users, that can wait while we
- catch up with 1985.
-- slavishly follow the syntax of existing commands, predictability is more
- important.
-- be a programming language. Shell scripts are mini programming languages but
- we have JavaScript sat just next door. It's better to integrate than compete.
-
-
-## Design Challenges
-
-What has changed since 1970 that might cause us to make changes to the design
-of the command line?
-
-
-### Connection limitations
-
-Unix pre-dates the Internet and treats almost everything as a file. Since the
-Internet it could be more useful to use URIs as ways to identify sources of data.
-
-
-### Memory limitations
-
-Modern computers have something like 6 orders of magnitude more memory than the
-PDP-7 on which Unix was developed. Innovations like stdin/stdout and pipes are
-ways to connect systems without long-term storage of the results. The ability
-to store results for some time (potentially in more than one format)
-significantly reduces the need for these concepts. We should make the results
-of past commands addressable for re-use at a later time.
-
-There are a number of possible policies for eviction of items from the history.
-We should investigate options other than a simple stack.
-
-
-### Multi-tasking limitations
-
-Multi-tasking was a problem in 1970; the problem was getting a computer to do
-many jobs on 1 core. Today the problem is getting a computer to do one job on
-many cores. However we're stuck with this legacy in 2 ways. Firstly that the
-default is to force everything to wait until the previous job is finished, but
-more importantly that output from parallel jobs frequently collides
-
- $ find / -ctime 5d -print &
- $ find / -uid 0 -print &
- // good luck working out what came from where
-
- $ tail -f logfile.txt &
- $ vi main.c
- // have a nice time editing that file
-
-GCLI should allow commands to be asynchronous and will provide UI elements to
-inform the user of job completion. It will also keep asynchronous command
-output contained within it's own display area.
-
-
-### Output limitations
-
-The PDP-7 had a teletype. There is something like 4 orders of magnitude more
-information that can be displayed on a modern display than a 80x24 character
-based console. We can use this flexibility to provide better help to the user
-in entering their command.
-
-The additional display richness can also allow interaction with result output.
-Command output can include links to follow-up commands, and even ask for
-additional input. (e.g. "your search returned zero results do you want to try
-again with a different search string")
-
-There is no reason why output must be static. For example, it could be
-informative to see the results of an "ls" command alter given changes made by
-subsequent commands. (It should be noted that there are times when historical
-information is important too)
-
-
-### Integration limitations
-
-In 1970, command execution meant retrieving a program from storage, and running
-it. This required minimal interaction between the command line processor and
-the program being run, and was good for resource constrained systems.
-This lack of interaction resulted in the processing of command line arguments
-being done everywhere, when the task was better suited to command line.
-We should provide metadata about the commands being run, to allow the command
-line to process, interpret and provide help on the input.
diff --git a/devtools/shared/gcli/source/docs/developing-gcli.md b/devtools/shared/gcli/source/docs/developing-gcli.md
deleted file mode 100644
index 1137126552e1..000000000000
--- a/devtools/shared/gcli/source/docs/developing-gcli.md
+++ /dev/null
@@ -1,213 +0,0 @@
-
-# Developing GCLI
-
-## About the code
-
-The majority of the GCLI source is stored in the ``lib`` directory.
-
-The ``docs`` directory contains documentation.
-The ``scripts`` directory contains RequireJS that GCLI uses.
-The ``build`` directory contains files used when creating builds.
-The ``mozilla`` directory contains the mercurial patch queue of patches to apply
-to mozilla-central.
-The ``selenium-tests`` directory contains selenium web-page integration tests.
-
-The source in the ``lib`` directory is split into 4 sections:
-
-- ``lib/demo`` contains commands used in the demo page. It is not needed except
- for demo purposes.
-- ``lib/test`` contains a small test harness for testing GCLI.
-- ``lib/gclitest`` contains tests that run in the test harness
-- ``lib/gcli`` contains the actual meat
-
-GCLI is split into a UI portion and a Model/Controller portion.
-
-
-## The GCLI Model
-
-The heart of GCLI is a ``Requisition``, which is an AST for the input. A
-``Requisition`` is a command that we'd like to execute, and we're filling out
-all the inputs required to execute the command.
-
-A ``Requisition`` has a ``Command`` that is to be executed. Each Command has a
-number of ``Parameter``s, each of which has a name and a type as detailed
-above.
-
-As you type, your input is split into ``Argument``s, which are then assigned to
-``Parameter``s using ``Assignment``s. Each ``Assignment`` has a ``Conversion``
-which stores the input argument along with the value that is was converted into
-according to the type of the parameter.
-
-There are special assignments called ``CommandAssignment`` which the
-``Requisition`` uses to link to the command to execute, and
-``UnassignedAssignment``used to store arguments that do not have a parameter
-to be assigned to.
-
-
-## The GCLI UI
-
-There are several components of the GCLI UI. Each can have a script portion,
-some template HTML and a CSS file. The template HTML is processed by
-``domtemplate`` before use.
-
-DomTemplate is fully documented in [it's own repository]
-(https://github.com/joewalker/domtemplate).
-
-The components are:
-
-- ``Inputter`` controls the input field, processing special keyboard events and
- making sure that it stays in sync with the Requisition.
-- ``Completer`` updates a div that is located behind the input field and used
- to display completion advice and hint highlights. It is stored in
- completer.js.
-- ``Display`` is responsible for containing the popup hints that are displayed
- above the command line. Typically Display contains a Hinter and a RequestsView
- although these are not both required. Display itself is optional, and isn't
- planned for use in the first release of GCLI in Firefox.
-- ``Hinter`` Is used to display input hints. It shows either a Menu or an
- ArgFetch component depending on the state of the Requisition
-- ``Menu`` is used initially to select the command to be executed. It can act
- somewhat like the Start menu on windows.
-- ``ArgFetch`` Once the command to be executed has been selected, ArgFetch
- shows a 'dialog' allowing the user to enter the parameters to the selected
- command.
-- ``RequestsView`` Contains a set of ``RequestView`` components, each of which
- displays a command that has been invoked. RequestsView is a poor name, and
- should better be called ReportView
-
-ArgFetch displays a number of Fields. There are fields for most of the Types
-discussed earlier. See 'Writing Fields' above for more information.
-
-
-## Testing
-
-GCLI contains 2 test suites:
-
-- JS level testing is run with the ``test`` command. The tests are located in
- ``lib/gclitest`` and they use the test runner in ``lib/test``. This is fairly
- comprehensive, however it does not do UI level testing.
- If writing a new test it needs to be registered in ``lib/gclitest/index``.
- For an example of how to write tests, see ``lib/gclitest/testSplit.js``.
- The test functions are implemented in ``lib/test/assert``.
-- Browser integration tests are included in ``browser_webconsole_gcli_*.js``,
- in ``toolkit/components/console/hudservice/tests/browser``. These are
- run with the rest of the Mozilla test suite.
-
-
-## Coding Conventions
-
-The coding conventions for the GCLI project come from the Bespin/Skywriter and
-Ace projects. They are roughly [Crockford]
-(http://javascript.crockford.com/code.html) with a few exceptions and
-additions:
-
-* ``var`` does not need to be at the top of each function, we'd like to move
- to ``let`` when it's generally available, and ``let`` doesn't have the same
- semantic twists as ``var``.
-
-* Strings are generally enclosed in single quotes.
-
-* ``eval`` is to be avoided, but we don't declare it evil.
-
-The [Google JavaScript conventions]
-(https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) are
-more detailed, we tend to deviate in:
-
-* Custom exceptions: We generally just use ``throw new Error('message');``
-
-* Multi-level prototype hierarchies: Allowed; we don't have ``goog.inherits()``
-
-* ``else`` begins on a line by itself:
-
- if (thing) {
- doThis();
- }
- else {
- doThat();
- }
-
-
-## Startup
-
-Internally GCLI modules have ``startup()``/``shutdown()`` functions which are
-called on module init from the top level ``index.js`` of that 'package'.
-
-In order to initialize a package all that is needed is to require the package
-index (e.g. ``require('package/index')``).
-
-The ``shutdown()`` function was useful when GCLI was used in Bespin as part of
-dynamic registration/de-registration. It is not known if this feature will be
-useful in the future. So it has not been entirely removed, it may be at some
-future date.
-
-
-## Running the Unit Tests
-
-Start the GCLI static server:
-
- cd path/to/gcli
- node gcli.js
-
-Now point your browser to http://localhost:9999/localtest.html. When the page
-loads the tests will be automatically run outputting to the console, or you can
-enter the ``test`` command to run the unit tests.
-
-
-## Contributing Code
-
-Please could you do the following to help minimize the amount of rework that we
-do:
-
-1. Check the unit tests run correctly (see **Running the Unit Tests** above)
-2. Check the code follows the style guide. At a minimum it should look like the
- code around it. For more detailed notes, see **Coding Conventions** above
-3. Help me review your work by using good commit comments. Which means 2 things
- * Well formatted messages, i.e. 50 char summary including bug tag, followed
- by a blank line followed by a more in-depth message wrapped to 72 chars
- per line. This is basically the format used by the Linux Kernel. See the
- [commit log](https://github.com/joewalker/gcli/commits/master) for
- examples. The be extra helpful, please use the "shortdesc-BUGNUM: " if
- possible which also helps in reviews.
- * Commit your changes as a story. Make it easy for me to understand the
- changes that you've made.
-4. Sign your work. To improve tracking of who did what, we follow the sign-off
- procedure used in the Linux Kernel.
- The sign-off is a simple line at the end of the explanation for the
- patch, which certifies that you wrote it or otherwise have the right to
- pass it on as an open-source patch. The rules are pretty simple: if you
- can certify the below:
-
- Developer's Certificate of Origin 1.1
-
- By making a contribution to this project, I certify that:
-
- (a) The contribution was created in whole or in part by me and I
- have the right to submit it under the open source license
- indicated in the file; or
-
- (b) The contribution is based upon previous work that, to the best
- of my knowledge, is covered under an appropriate open source
- license and I have the right under that license to submit that
- work with modifications, whether created in whole or in part
- by me, under the same open source license (unless I am
- permitted to submit under a different license), as indicated
- in the file; or
-
- (c) The contribution was provided directly to me by some other
- person who certified (a), (b) or (c) and I have not modified
- it.
-
- (d) I understand and agree that this project and the contribution
- are public and that a record of the contribution (including all
- personal information I submit with it, including my sign-off) is
- maintained indefinitely and may be redistributed consistent with
- this project or the open source license(s) involved.
-
- then you just add a line saying
-
- Signed-off-by: Random J Developer
-
- using your real name (sorry, no pseudonyms or anonymous contributions.)
-
-Thanks for wanting to contribute code.
-
diff --git a/devtools/shared/gcli/source/docs/index.md b/devtools/shared/gcli/source/docs/index.md
deleted file mode 100644
index dce112e6d974..000000000000
--- a/devtools/shared/gcli/source/docs/index.md
+++ /dev/null
@@ -1,150 +0,0 @@
-
-# About GCLI
-
-## GCLI is a Graphical Command Line Interpreter.
-
-GCLI is a command line for modern computers. When command lines were invented,
-computers were resource-limited, disconnected systems with slow multi-tasking
-and poor displays. The design of the Unix CLI made sense in 1970, but over 40
-years on, considering the pace of change, there are many improvements we can
-make.
-
-CLIs generally suffer from poor discoverability; It's hard when faced with a
-blank command line to work out what to do. As a result the majority of programs
-today use purely graphical user interfaces, however in doing so, they lose some
-of the benefits of CLIs. CLIs are still used because generally, in the hands of
-a skilled user they are faster, and have a wider range of available options.
-
-GCLI attempts to get the best of the GUI world and the CLI world to produce
-something that is both easy to use and learn as well as fast and powerful.
-
-GCLI has a type system to help ensure that users are inputting valid commands
-and to enable us to provide sensible context sensitive help. GCLI provides
-integration with JavaScript rather than being an alternative (like CoffeeScript).
-
-
-## History
-
-GCLI was born as part of the
-[Bespin](http://ajaxian.com/archives/canvas-for-a-text-editor) project and was
-[discussed at the time](http://j.mp/bespin-cli). The command line component
-survived the rename of Bepsin to Skywriter and the merger with Ace, got a name
-of it's own (Cockpit) which didn't last long before the project was named GCLI.
-It is now being used in the Firefox's web console where it doesn't have a
-separate identity but it's still called GCLI outside of Firefox. It is also
-used in [Eclipse Orion](http://www.eclipse.org/orion/).
-
-
-## Environments
-
-GCLI is designed to work in a number of environments:
-
-1. As a component of Firefox developer tools.
-2. As an adjunct to Orion/Ace and other online editors.
-3. As a plugin to any web-page wishing to provide its own set of commands.
-4. As part of a standalone web browser extension with it's own set of commands.
-
-
-## Related Pages
-
-Other sources of GCLI documentation:
-
-- [Writing Commands](writing-commands.md)
-- [Writing Types](writing-types.md)
-- [Developing GCLI](developing-gcli.md)
-- [Writing Tests](writing-tests.md) / [Running Tests](running-tests.md)
-- [The Design of GCLI](design.md)
-- Source
- - The most up-to-date source is in [this Github repository](https://github.com/joewalker/gcli/).
- - When a feature is 'done' it's merged into the [Mozilla clone](https://github.com/mozilla/gcli/).
- - From which it flows into [Mozilla Central](https://hg.mozilla.org/mozilla-central/file/tip/devtools/client/commandline).
-- [Demo of GCLI](http://mozilla.github.com/gcli/) with an arbitrary set of demo
- commands
-- Other Documentation
- - [Embedding docs](https://github.com/mozilla/gcli/blob/master/docs/index.md)
- - [Status page](http://mozilla.github.com/devtools/2011/status.html#gcli)
-
-
-## Accessibility
-
-GCLI uses ARIA roles to guide a screen-reader as to the important sections to
-voice. We welcome [feedback on how these roles are implemented](https://bugzilla.mozilla.org/enter_bug.cgi?product=Firefox&component=Developer+Tools:+Graphic+Commandline+and+Toolbar&rep_platform=All&op_sys=All&short_desc=GCLI).
-
-The command line uses TAB as a method of completing current input, this
-prevents use of TAB for keyboard navigation. Instead of using TAB to move to
-the next field you can use F6. In addition to F6, ALT+TAB, CTRL+TAB, META+TAB
-make an attempt to move the focus on. How well this works depends on your
-OS/browser combination.
-
-
-## Embedding GCLI
-
-There are 3 basic steps in using GCLI in your system.
-
-1. Import a GCLI JavaScript file.
- For serious use of GCLI you are likely to be creating a custom build (see
- below) however if you just want to have a quick play, you can use
- ``gcli-uncompressed.js`` from [the gh-pages branch of GCLI]
- (https://github.com/mozilla/gcli/tree/gh-pages)
- Just place the following wherever you place your script files.
-
-
-
-2. Having imported GCLI, we need to tell it where to display. The simplest
- method is to include an elements with the id of ``gcli-input`` and
- ``gcli-display``.
-
-
-
-
-3. Tell GCLI what commands to make available. See the sections on Writing
- Commands, Writing Types and Writing Fields for more information.
-
- GCLI uses the CommonJS AMD format for it's files, so a 'require' statement
- is needed to get started.
-
- require([ 'gcli/index' ], function(gcli) {
- gcli.add(...); // Register custom commands/types/etc
- gcli.createTerminal(); // Create a user interface
- });
-
- The createTerminal() function takes an ``options`` objects which allows
- customization. At the current time the documentation of these object is left
- to the source.
-
-
-## Backwards Compatibility
-
-The goals of the GCLI project are:
-
-- Aim for very good backwards compatibility with code required from an
- 'index' module. This means we will not break code without a cycle of
- deprecation warnings.
-
- There are currently 3 'index' modules:
- - gcli/index (all you need to get started with GCLI)
- - demo/index (a number of demo commands)
- - gclitest/index (GCLI test suite)
-
- Code from these modules uses the module pattern to prevent access to internal
- functions, so in essence, if you can get to it from an index module, you
- should be ok.
-
-- We try to avoid needless change to other modules, however we don't make any
- promises, and don't provide a deprecation cycle.
-
- Code from other modules uses classes rather than modules, so member variables
- are exposed. Many classes mark private members using the `_underscorePrefix`
- pattern. Particular care should be taken if access is needed to a private
- member.
-
-
-## Creating Custom Builds
-
-GCLI uses [DryIce](https://github.com/mozilla/dryice) to create custom builds.
-If dryice is installed (``npm install .``) then you can create a built
-version of GCLI simply using ``node gcli.js standard``. DryIce supplies a custom
-module loader to replace RequireJS for built applications.
-
-The build will be output to the ``built`` directory. The directory will be
-created if it doesn't exist.
diff --git a/devtools/shared/gcli/source/docs/running-tests.md b/devtools/shared/gcli/source/docs/running-tests.md
deleted file mode 100644
index 378c40837111..000000000000
--- a/devtools/shared/gcli/source/docs/running-tests.md
+++ /dev/null
@@ -1,60 +0,0 @@
-
-# Running Tests
-
-GCLI has a test suite that can be run in a number of different environments.
-Some of the tests don't work in all environments. These should be automatically
-skipped when not applicable.
-
-
-## Web
-
-Running a limited set of test from the web is the easiest. Simply load
-'localtest.html' and the unit tests should be run automatically, with results
-displayed on the console. Tests can be re-run using the 'test' command.
-
-It also creates a function 'testCommands()' to be run at a JS prompt, which
-enables the test commands for debugging purposes.
-
-
-## Firefox
-
-GCLI's test suite integrates with Mochitest and runs automatically on each test
-run. Dryice packages the tests to format them for the Firefox build system.
-
-For more information about running Mochitest on Firefox (including GCLI) see
-[the MDN, Mochitest docs](https://developer.mozilla.org/en/Mochitest)
-
-
-# Node
-
-Running the test suite under node can be done as follows:
-
- $ node gcli.js test
-
-Or, using the `test` command:
-
- $ node gcli.js
- Serving GCLI to http://localhost:9999/
- This is also a limited GCLI prompt.
- Type 'help' for a list of commands, CTRL+C twice to exit:
- : test
-
- testCli: Pass (funcs=9, checks=208)
- testCompletion: Pass (funcs=1, checks=139)
- testExec: Pass (funcs=1, checks=133)
- testHistory: Pass (funcs=3, checks=13)
- ....
-
- Summary: Pass (951 checks)
-
-
-# Travis CI
-
-GCLI check-ins are automatically tested by [Travis CI](https://travis-ci.org/joewalker/gcli).
-
-
-# Test Case Generation
-
-GCLI can generate test cases automagically. Load ```localtest.html```, type a
-command to be tested into GCLI, and the press F2. GCLI will output to the
-console a template test case for the entered command.
diff --git a/devtools/shared/gcli/source/docs/writing-commands.md b/devtools/shared/gcli/source/docs/writing-commands.md
deleted file mode 100644
index e73050279184..000000000000
--- a/devtools/shared/gcli/source/docs/writing-commands.md
+++ /dev/null
@@ -1,757 +0,0 @@
-
-# Writing Commands
-
-## Basics
-
-GCLI has opinions about how commands should be written, and it encourages you
-to do The Right Thing. The opinions are based on helping users convert their
-intentions to commands and commands to what's actually going to happen.
-
-- Related commands should be sub-commands of a parent command. One of the goals
- of GCLI is to support a large number of commands without things becoming
- confusing, this will require some sort of namespacing or there will be
- many people wanting to implement the ``add`` command. This style of
- writing commands has become common place in Unix as the number of commands
- has gone up.
- The ```context``` command allows users to focus on a parent command, promoting
- its sub-commands above others.
-
-- Each command should do exactly and only one thing. An example of a Unix
- command that breaks this principle is the ``tar`` command
-
- $ tar -zcf foo.tar.gz .
- $ tar -zxf foo.tar.gz .
-
- These 2 commands do exactly opposite things. Many a file has died as a result
- of a x/c typo. In GCLI this would be better expressed:
-
- $ tar create foo.tar.gz -z .
- $ tar extract foo.tar.gz -z .
-
- There may be commands (like tar) which have enough history behind them
- that we shouldn't force everyone to re-learn a new syntax. The can be achieved
- by having a single string parameter and parsing the input in the command)
-
-- Avoid errors. We try to avoid the user having to start again with a command
- due to some problem. The majority of problems are simple typos which we can
- catch using command metadata, but there are 2 things command authors can do
- to prevent breakage.
-
- - Where possible avoid the need to validate command line parameters in the
- exec function. This can be done by good parameter design (see 'do exactly
- and only one thing' above)
-
- - If there is an obvious fix for an unpredictable problem, offer the
- solution in the command output. So rather than use request.error (see
- Request Object below) output some HTML which contains a link to a fixed
- command line.
-
-Currently these concepts are not enforced at a code level, but they could be in
-the future.
-
-
-## How commands work
-
-This is how to create a basic ``greet`` command:
-
- gcli.addItems([{
- name: 'greet',
- description: 'Show a greeting',
- params: [
- {
- name: 'name',
- type: 'string',
- description: 'The name to greet'
- }
- ],
- returnType: 'string',
- exec: function(args, context) {
- return 'Hello, ' + args.name;
- }
- }]);
-
-This command is used as follows:
-
- : greet Joe
- Hello, Joe
-
-Some terminology that isn't always obvious: a function has 'parameters', and
-when you call a function, you pass 'arguments' to it.
-
-
-## Internationalization (i18n)
-
-There are several ways that GCLI commands can be localized. The best method
-depends on what context you are writing your command for.
-
-### Firefox Embedding
-
-GCLI supports Mozilla style localization. To add a command that will only ever
-be used embedded in Firefox, this is the way to go. Your strings should be
-stored in ``toolkit/locales/en-US/chrome/global/devtools/gclicommands.properties``,
-And you should access them using ``let l10n = require("gcli/l10n")`` and then
-``l10n.lookup(...)`` or ``l10n.lookupFormat()``
-
-For examples of existing commands, take a look in
-``devtools/client/webconsole/GcliCommands.jsm``, which contains most of the
-current GCLI commands. If you will be adding a number of new commands, then
-consider starting a new JSM.
-
-Your command will then look something like this:
-
- gcli.addItems([{
- name: 'greet',
- description: gcli.lookup("greetDesc")
- ...
- }]);
-
-### Web Commands
-
-There are 2 ways to provide translated strings for web use. The first is to
-supply the translated strings in the description:
-
- gcli.addItems([{
- name: 'greet',
- description: {
- 'root': 'Show a greeting',
- 'fr-fr': 'Afficher un message d'accueil',
- 'de-de': 'Zeige einen Gruß',
- 'gk-gk': 'Εμφάνιση ένα χαιρετισμό',
- ...
- }
- ...
- }]);
-
-Each description should contain at least a 'root' entry which is the
-default if no better match is found. This method has the benefit of being
-compact and simple, however it has the significant drawback of being wasteful
-of memory and bandwidth to transmit and store a significant number of strings,
-the majority of which will never be used.
-
-More efficient is to supply a lookup key and ask GCLI to lookup the key from an
-appropriate localized strings file:
-
- gcli.addItems([{
- name: 'greet',
- description: { 'key': 'demoGreetingDesc' }
- ...
- }]);
-
-For web usage, the central store of localized strings is
-``lib/gcli/nls/strings.js``. Other string files can be added using the
-``l10n.registerStringsSource(...)`` function.
-
-This method can be used both in Firefox and on the Web (see the help command
-for an example). However this method has the drawback that it will not work
-with DryIce built files until we fix bug 683844.
-
-
-## Default argument values
-
-The ``greet`` command requires the entry of the ``name`` parameter. This
-parameter can be made optional with the addition of a ``defaultValue`` to the
-parameter:
-
- gcli.addItems([{
- name: 'greet',
- description: 'Show a message to someone',
- params: [
- {
- name: 'name',
- type: 'string',
- description: 'The name to greet',
- defaultValue: 'World!'
- }
- ],
- returnType: 'string',
- exec: function(args, context) {
- return "Hello, " + args.name;
- }
- }]);
-
-Now we can also use the ``greet`` command as follows:
-
- : greet
- Hello, World!
-
-
-## Positional vs. named arguments
-
-Arguments can be entered either positionally or as named arguments. Generally
-users will prefer to type the positional version, however the named alternative
-can be more self documenting.
-
-For example, we can also invoke the greet command as follows:
-
- : greet --name Joe
- Hello, Joe
-
-
-## Short argument names
-
-GCLI allows you to specify a 'short' character for any parameter:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- {
- name: 'name',
- short: 'n',
- type: 'string',
- ...
- }
- ],
- ...
- }]);
-
-This is used as follows:
-
- : greet -n Fred
- Hello, Fred
-
-Currently GCLI does not allow short parameter merging (i.e. ```ls -la```)
-however this is planned.
-
-
-## Parameter types
-
-Initially the available types are:
-
-- string
-- boolean
-- number
-- selection
-- delegate
-- date
-- array
-- file
-- node
-- nodelist
-- resource
-- command
-- setting
-
-This list can be extended. See [Writing Types](writing-types.md) on types for
-more information.
-
-The following examples assume the following definition of the ```greet```
-command:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- { name: 'name', type: 'string' },
- { name: 'repeat', type: 'number' }
- ],
- ...
- }]);
-
-Parameters can be specified either with named arguments:
-
- : greet --name Joe --repeat 2
-
-And sometimes positionally:
-
- : greet Joe 2
-
-Parameters can be specified positionally if they are considered 'important'.
-Unimportant parameters must be specified with a named argument.
-
-Named arguments can be specified anywhere on the command line (after the
-command itself) however positional arguments must be in order. So
-these examples are the same:
-
- : greet --name Joe --repeat 2
- : greet --repeat 2 --name Joe
-
-However (obviously) these are not the same:
-
- : greet Joe 2
- : greet 2 Joe
-
-(The second would be an error because 'Joe' is not a number).
-
-Named arguments are assigned first, then the remaining arguments are assigned
-to the remaining parameters. So the following is valid and unambiguous:
-
- : greet 2 --name Joe
-
-Positional parameters quickly become unwieldy with long parameter lists so we
-recommend only having 2 or 3 important parameters. GCLI provides hints for
-important parameters more obviously than unimportant ones.
-
-Parameters are 'important' if they are not in a parameter group. The easiest way
-to achieve this is to use the ```option: true``` property.
-
-For example, using:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- { name: 'name', type: 'string' },
- { name: 'repeat', type: 'number', option: true, defaultValue: 1 }
- ],
- ...
- }]);
-
-Would mean that this is an error
-
- : greet Joe 2
-
-You would instead need to do the following:
-
- : greet Joe --repeat 2
-
-For more on parameter groups, see below.
-
-In addition to being 'important' and 'unimportant' parameters can also be
-optional. If is possible to be important and optional, but it is not possible
-to be unimportant and non-optional.
-
-Parameters are optional if they either:
-- Have a ```defaultValue``` property
-- Are of ```type=boolean``` (boolean arguments automatically default to being false)
-
-There is currently no way to make parameters mutually exclusive.
-
-
-## Selection types
-
-Parameters can have a type of ``selection``. For example:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- { name: 'name', ... },
- {
- name: 'lang',
- description: 'In which language should we greet',
- type: { name: 'selection', data: [ 'en', 'fr', 'de', 'es', 'gk' ] },
- defaultValue: 'en'
- }
- ],
- ...
- }]);
-
-GCLI will enforce that the value of ``arg.lang`` was one of the values
-specified. Alternatively ``data`` can be a function which returns an array of
-strings.
-
-The ``data`` property is useful when the underlying type is a string but it
-doesn't work when the underlying type is something else. For this use the
-``lookup`` property as follows:
-
- type: {
- name: 'selection',
- lookup: {
- 'en': Locale.EN,
- 'fr': Locale.FR,
- ...
- }
- },
-
-Similarly, ``lookup`` can be a function returning the data of this type.
-
-
-## Number types
-
-Number types are mostly self explanatory, they have one special property which
-is the ability to specify upper and lower bounds for the number:
-
- gcli.addItems([{
- name: 'volume',
- params: [
- {
- name: 'vol',
- description: 'How loud should we go',
- type: { name: 'number', min: 0, max: 11 }
- }
- ],
- ...
- }]);
-
-You can also specify a ``step`` property which specifies by what amount we
-should increment and decrement the values. The ``min``, ``max``, and ``step``
-properties are used by the command line when up and down are pressed and in
-the input type of a dialog generated from this command.
-
-
-## Delegate types
-
-Delegate types are needed when the type of some parameter depends on the type
-of another parameter. For example:
-
- : set height 100
- : set name "Joe Walker"
-
-We can achieve this as follows:
-
- gcli.addItems([{
- name: 'set',
- params: [
- {
- name: 'setting',
- type: { name: 'selection', values: [ 'height', 'name' ] }
- },
- {
- name: 'value',
- type: {
- name: 'delegate',
- delegateType: function() { ... }
- }
- }
- ],
- ...
- }]);
-
-Several details are left out of this example, like how the delegateType()
-function knows what the current setting is. See the ``pref`` command for an
-example.
-
-
-## Array types
-
-Parameters can have a type of ``array``. For example:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- {
- name: 'names',
- type: { name: 'array', subtype: 'string' },
- description: 'The names to greet',
- defaultValue: [ 'World!' ]
- }
- ],
- ...
- exec: function(args, context) {
- return "Hello, " + args.names.join(', ') + '.';
- }
- }]);
-
-This would be used as follows:
-
- : greet Fred Jim Shiela
- Hello, Fred, Jim, Shiela.
-
-Or using named arguments:
-
- : greet --names Fred --names Jim --names Shiela
- Hello, Fred, Jim, Shiela.
-
-There can only be one ungrouped parameter with an array type, and it must be
-at the end of the list of parameters (i.e. just before any parameter groups).
-This avoids confusion as to which parameter an argument should be assigned.
-
-
-## Sub-commands
-
-It is common for commands to be groups into those with similar functionality.
-Examples include virtually all VCS commands, ``apt-get``, etc. There are many
-examples of commands that should be structured as in a sub-command style -
-``tar`` being the obvious example, but others include ``crontab``.
-
-Groups of commands are specified with the top level command not having an
-exec function:
-
- gcli.addItems([
- {
- name: 'tar',
- description: 'Commands to manipulate archives',
- },
- {
- name: 'tar create',
- description: 'Create a new archive',
- exec: function(args, context) { ... },
- ...
- },
- {
- name: 'tar extract',
- description: 'Extract from an archive',
- exec: function(args, context) { ... },
- ...
- }
- ]);
-
-
-## Parameter groups
-
-Parameters can be grouped into sections.
-
-There are 3 ways to assign a parameter to a group.
-
-The simplest uses ```option: true``` to put a parameter into the default
-'Options' group:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- { name: 'repeat', type: 'number', option: true }
- ],
- ...
- }]);
-
-The ```option``` property can also take a string to use an alternative parameter
-group:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- { name: 'repeat', type: 'number', option: 'Advanced' }
- ],
- ...
- }]);
-
-An example of how this can be useful is 'git' which categorizes parameters into
-'porcelain' and 'plumbing'.
-
-Finally, parameters can be grouped together as follows:
-
- gcli.addItems([{
- name: 'greet',
- params: [
- { name: 'name', type: 'string', description: 'The name to greet' },
- {
- group: 'Advanced Options',
- params: [
- { name: 'repeat', type: 'number', defaultValue: 1 },
- { name: 'debug', type: 'boolean' }
- ]
- }
- ],
- ...
- }]);
-
-This could be used as follows:
-
- : greet Joe --repeat 2 --debug
- About to send greeting
- Hello, Joe
- Hello, Joe
- Done!
-
-Parameter groups must come after non-grouped parameters because non-grouped
-parameters can be assigned positionally, so their index is important. We don't
-want 'holes' in the order caused by parameter groups.
-
-
-## Command metadata
-
-Each command should have the following properties:
-
-- A string ``name``.
-- A short ``description`` string. Generally no more than 20 characters without
- a terminating period/fullstop.
-- A function to ``exec``ute. (Optional for the parent containing sub-commands)
- See below for more details.
-
-And optionally the following extra properties:
-
-- A declaration of the accepted ``params``.
-- A ``hidden`` property to stop the command showing up in requests for help.
-- A ``context`` property which defines the scope of the function that we're
- calling. Rather than simply call ``exec()``, we do ``exec.call(context)``.
-- A ``manual`` property which allows a fuller description of the purpose of the
- command.
-- A ``returnType`` specifying how we should handle the value returned from the
- exec function.
-
-The ``params`` property is an array of objects, one for each parameter. Each
-parameter object should have the following 3 properties:
-
-- A string ``name``.
-- A short string ``description`` as for the command.
-- A ``type`` which refers to an existing Type (see Writing Types).
-
-Optionally each parameter can have these properties:
-
-- A ``defaultValue`` (which should be in the type specified in ``type``).
- The defaultValue will be used when there is no argument supplied for this
- parameter on the command line.
- If the parameter has a ``defaultValue``, other than ``undefined`` then the
- parameter is optional, and if unspecified on the command line, the matching
- argument will have this value when the function is called.
- If ``defaultValue`` is missing, or if it is set to ``undefined``, then the
- system will ensure that a value is provided before anything is executed.
- There are 2 special cases:
- - If the type is ``selection``, then defaultValue must not be undefined.
- The defaultValue must either be ``null`` (meaning that a value must be
- supplied by the user) or one of the selection values.
- - If the type is ``boolean``, then ``defaultValue:false`` is implied and
- can't be changed. Boolean toggles are assumed to be off by default, and
- should be named to match.
-- A ``manual`` property for parameters is exactly analogous to the ``manual``
- property for commands - descriptive text that is longer than than 20
- characters.
-
-
-## The Command Function (exec)
-
-The parameters to the exec function are designed to be useful when you have a
-large number of parameters, and to give direct access to the environment (if
-used).
-
- gcli.addItems([{
- name: 'echo',
- description: 'The message to display.',
- params: [
- {
- name: 'message',
- type: 'string',
- description: 'The message to display.'
- }
- ],
- returnType: 'string',
- exec: function(args, context) {
- return args.message;
- }
- }]);
-
-The ``args`` object contains the values specified on the params section and
-provided on the command line. In this example it would contain the message for
-display as ``args.message``.
-
-The ``context`` object has the following signature:
-
- {
- environment: ..., // environment object passed to createTerminal()
- exec: ..., // function to execute a command
- update: ..., // function to alter the text of the input area
- createView: ..., // function to help creating rich output
- defer: ..., // function to create a deferred promise
- }
-
-The ``environment`` object is opaque to GCLI. It can be used for providing
-arbitrary data to your commands about their environment. It is most useful
-when more than one command line exists on a page with similar commands in both
-which should act in their own ways.
-An example use for ``environment`` would be a page with several tabs, each
-containing an editor with a command line. Commands executed in those editors
-should apply to the relevant editor.
-The ``environment`` object is passed to GCLI at startup (probably in the
-``createTerminal()`` function).
-
-The ``document`` object is also passed to GCLI at startup. In some environments
-(e.g. embedded in Firefox) there is no global ``document``. This object
-provides a way to create DOM nodes.
-
-``defer()`` allows commands to execute asynchronously.
-
-
-## Returning data
-
-The command meta-data specifies the type of data returned by the command using
-the ``returnValue`` setting.
-
-``returnValue`` processing is currently functioning, but incomplete, and being
-tracked in [Bug 657595](http://bugzil.la/657595). Currently you should specify
-a ``returnType`` of ``string`` or ``html``. If using HTML, you can return
-either an HTML string or a DOM node.
-
-In the future, JSON will be strongly encouraged as the return type, with some
-formatting functions to convert the JSON to HTML.
-
-Asynchronous output is achieved using a promise created from the ``context``
-parameter: ``context.defer()``.
-
-Some examples of this is practice:
-
- { returnType: "string" }
- ...
- return "example";
-
-GCLI interprets the output as a plain string. It will be escaped before display
-and available as input to other commands as a plain string.
-
- { returnType: "html" }
- ...
- return "
Hello
";
-
-GCLI will interpret this as HTML, and parse it for display.
-
- { returnType: "dom" }
- ...
- return util.createElement(context.document, 'div');
-
-``util.createElement`` is a utility to ensure use of the XHTML namespace in XUL
-and other XML documents. In an HTML document it's functionally equivalent to
-``context.document.createElement('div')``. If your command is likely to be used
-in Firefox or another XML environment, you should use it. You can import it
-with ``var util = require('util/util');``.
-
-GCLI will use the returned HTML element as returned. See notes on ``context``
-above.
-
- { returnType: "number" }
- ...
- return 42;
-
-GCLI will display the element in a similar way to a string, but it the value
-will be available to future commands as a number.
-
- { returnType: "date" }
- ...
- return new Date();
-
- { returnType: "file" }
- ...
- return new File();
-
-Both these examples return data as a given type, for which a converter will
-be required before the value can be displayed. The type system is likely to
-change before this is finalized. Please contact the author for more
-information.
-
- { returnType: "string" }
- ...
- var deferred = context.defer();
- setTimeout(function() {
- deferred.resolve("hello");
- }, 500);
- return deferred.promise;
-
-Errors can be signaled by throwing an exception. GCLI will display the message
-property (or the toString() value if there is no message property). (However
-see *3 principles for writing commands* above for ways to avoid doing this).
-
-
-## Specifying Types
-
-Types are generally specified by a simple string, e.g. ``'string'``. For most
-types this is enough detail. There are a number of exceptions:
-
-* Array types. We declare a parameter to be an array of things using ``[]``,
- for example: ``number[]``.
-* Selection types. There are 3 ways to specify the options in a selection:
- * Using a lookup map
-
- type: {
- name: 'selection',
- lookup: { one:1, two:2, three:3 }
- }
-
- (The boolean type is effectively just a selection that uses
- ``lookup:{ 'true': true, 'false': false }``)
-
- * Using given strings
-
- type: {
- name: 'selection',
- data: [ 'left', 'center', 'right' ]
- }
-
- * Using named objects, (objects with a ``name`` property)
-
- type: {
- name: 'selection',
- data: [
- { name: 'Google', url: 'http://www.google.com/' },
- { name: 'Microsoft', url: 'http://www.microsoft.com/' },
- { name: 'Yahoo', url: 'http://www.yahoo.com/' }
- ]
- }
-
-* Delegate type. It is generally best to inherit from Delegate in order to
- provide a customization of this type. See settingValue for an example.
-
-See below for more information.
diff --git a/devtools/shared/gcli/source/docs/writing-tests.md b/devtools/shared/gcli/source/docs/writing-tests.md
deleted file mode 100644
index 4d42142cd0d2..000000000000
--- a/devtools/shared/gcli/source/docs/writing-tests.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-# Writing Tests
-
-There are several sources of GCLI tests and several environments in which they
-are run.
-
-The majority of GCLI tests are stored in
-[this repository](https://github.com/joewalker/gcli/) in files named like
-```./lib/gclitest/test*.js```. These tests run in Firefox, Chrome, Opera,
-and NodeJS/JsDom
-
-See [Running Tests](running-tests.md) for further details.
-
-GCLI comes with a generic unit test harness (in ```./lib/test/```) and a
-set of helpers for creating GCLI tests (in ```./lib/gclitest/helpers.js```).
-
-# GCLI tests in Firefox
-
-The build process converts the GCLI tests to run under Mochitest inside the
-Firefox unit tests. It also adds some
diff --git a/devtools/shared/gcli/source/docs/writing-types.md b/devtools/shared/gcli/source/docs/writing-types.md
deleted file mode 100644
index ed2f7543853b..000000000000
--- a/devtools/shared/gcli/source/docs/writing-types.md
+++ /dev/null
@@ -1,106 +0,0 @@
-
-# Writing Types
-
-Commands are a fundamental building block because they are what the users
-directly interacts with, however they are built on ``Type``s. There are a
-number of built in types:
-
-* string. This is a JavaScript string
-* number. A JavaScript number
-* boolean. A JavaScript boolean
-* selection. This is an selection from a number of alternatives
-* delegate. This type could change depending on other factors, but is well
- defined when one of the conversion routines is called.
-
-There are a number of additional types defined by Pilot and GCLI as
-extensions to the ``selection`` and ``delegate`` types
-
-* setting. One of the defined settings
-* settingValue. A value that can be applied to an associated setting.
-* command. One of the defined commands
-
-Most of our types are 'static' e.g. there is only one type of 'string', however
-some types like 'selection' and 'delegate' are customizable.
-
-All types must inherit from Type and have the following methods:
-
- /**
- * Convert the given value to a string representation.
- * Where possible, there should be round-tripping between values and their
- * string representations.
- */
- stringify: function(value) { return 'string version of value'; },
-
- /**
- * Convert the given str to an instance of this type.
- * Where possible, there should be round-tripping between values and their
- * string representations.
- * @return Conversion
- */
- parse: function(str) { return new Conversion(...); },
-
- /**
- * The plug-in system, and other things need to know what this type is
- * called. The name alone is not enough to fully specify a type. Types like
- * 'selection' and 'delegate' need extra data, however this function returns
- * only the name, not the extra data.
- *
In old bespin, equality was based on the name. This may turn out to be
- * important in Ace too.
- */
- name: 'example',
-
-In addition, defining the following function can be helpful, although Type
-contains default implementations:
-
-* nudge(value, by)
-
-Type, Conversion and Status are all declared by commands.js.
-
-The values produced by the parse function can be of any type, but if you are
-producing your own, you are strongly encouraged to include properties called
-``name`` and ``description`` where it makes sense. There are a number of
-places in GCLI where the UI will be able to provide better help to users if
-your values include these properties.
-
-
-# Writing Fields
-
-Fields are visual representations of types. For simple types like string it is
-enough to use ````, however more complex types we may wish to
-provide a custom widget to allow the user to enter values of the given type.
-
-This is an example of a very simple new password field type:
-
- function PasswordField(doc) {
- this.doc = doc;
- }
-
- PasswordField.prototype = Object.create(Field.prototype);
-
- PasswordField.prototype.createElement = function(assignment) {
- this.assignment = assignment;
- this.input = dom.createElement(this.doc, 'input');
- this.input.type = 'password';
- this.input.value = assignment.arg ? assignment.arg.text : '';
-
- this.onKeyup = function() {
- this.assignment.setValue(this.input.value);
- }.bind(this);
- this.input.addEventListener('keyup', this.onKeyup, false);
-
- this.onChange = function() {
- this.input.value = this.assignment.arg.text;
- };
- this.assignment.onAssignmentChange.add(this.onChange, this);
-
- return this.input;
- };
-
- PasswordField.prototype.destroy = function() {
- this.input.removeEventListener('keyup', this.onKeyup, false);
- this.assignment.onAssignmentChange.remove(this.onChange, this);
- };
-
- PasswordField.claim = function(type) {
- return type.name === 'password' ? Field.claim.MATCH : Field.claim.NO_MATCH;
- };
diff --git a/devtools/shared/gcli/source/lib/gcli/cli.js b/devtools/shared/gcli/source/lib/gcli/cli.js
deleted file mode 100644
index 77130d4d6bcc..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/cli.js
+++ /dev/null
@@ -1,2209 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('./util/util');
-var host = require('./util/host');
-var l10n = require('./util/l10n');
-
-var view = require('./ui/view');
-var Parameter = require('./commands/commands').Parameter;
-var CommandOutputManager = require('./commands/commands').CommandOutputManager;
-
-var Status = require('./types/types').Status;
-var Conversion = require('./types/types').Conversion;
-var commandModule = require('./types/command');
-var selectionModule = require('./types/selection');
-
-var Argument = require('./types/types').Argument;
-var ArrayArgument = require('./types/types').ArrayArgument;
-var NamedArgument = require('./types/types').NamedArgument;
-var TrueNamedArgument = require('./types/types').TrueNamedArgument;
-var MergedArgument = require('./types/types').MergedArgument;
-var ScriptArgument = require('./types/types').ScriptArgument;
-
-var RESOLVED = Promise.resolve(undefined);
-
-// Helper to produce a `deferred` object
-// using DOM Promise
-function defer() {
- let resolve, reject;
- let p = new Promise((a, b) => {
- resolve = a;
- reject = b;
- });
- return {
- promise: p,
- resolve: resolve,
- reject: reject
- };
-}
-
-/**
- * This is a list of the known command line components to enable certain
- * privileged commands to alter parts of a running command line. It is an array
- * of objects shaped like:
- * { conversionContext:..., executionContext:..., mapping:... }
- * So lookup is O(n) where 'n' is the number of command lines.
- */
-var instances = [];
-
-/**
- * An indexOf that looks-up both types of context
- */
-function instanceIndex(context) {
- for (var i = 0; i < instances.length; i++) {
- var instance = instances[i];
- if (instance.conversionContext === context ||
- instance.executionContext === context) {
- return i;
- }
- }
- return -1;
-}
-
-/**
- * findInstance gets access to a Terminal object given a conversionContext or
- * an executionContext (it doesn't have to be a terminal object, just whatever
- * was passed into addMapping()
- */
-exports.getMapping = function(context) {
- var index = instanceIndex(context);
- if (index === -1) {
- console.log('Missing mapping for context: ', context);
- console.log('Known contexts: ', instances);
- throw new Error('Missing mapping for context');
- }
- return instances[index].mapping;
-};
-
-/**
- * Add a requisition context->terminal mapping
- */
-var addMapping = function(requisition) {
- if (instanceIndex(requisition.conversionContext) !== -1) {
- throw new Error('Remote existing mapping before adding a new one');
- }
-
- instances.push({
- conversionContext: requisition.conversionContext,
- executionContext: requisition.executionContext,
- mapping: { requisition: requisition }
- });
-};
-
-/**
- * Remove a requisition context->terminal mapping
- */
-var removeMapping = function(requisition) {
- var index = instanceIndex(requisition.conversionContext);
- instances.splice(index, 1);
-};
-
-/**
- * Assignment is a link between a parameter and the data for that parameter.
- * The data for the parameter is available as in the preferred type and as
- * an Argument for the CLI.
- *
We also record validity information where applicable.
- *
For values, null and undefined have distinct definitions. null means
- * that a value has been provided, undefined means that it has not.
- * Thus, null is a valid default value, and common because it identifies an
- * parameter that is optional. undefined means there is no value from
- * the command line.
- * @constructor
- */
-function Assignment(param) {
- // The parameter that we are assigning to
- this.param = param;
- this.conversion = undefined;
-}
-
-/**
- * Easy accessor for conversion.arg.
- * This is a read-only property because writes to arg should be done through
- * the 'conversion' property.
- */
-Object.defineProperty(Assignment.prototype, 'arg', {
- get: function() {
- return this.conversion == null ? undefined : this.conversion.arg;
- },
- enumerable: true
-});
-
-/**
- * Easy accessor for conversion.value.
- * This is a read-only property because writes to value should be done through
- * the 'conversion' property.
- */
-Object.defineProperty(Assignment.prototype, 'value', {
- get: function() {
- return this.conversion == null ? undefined : this.conversion.value;
- },
- enumerable: true
-});
-
-/**
- * Easy (and safe) accessor for conversion.message
- */
-Object.defineProperty(Assignment.prototype, 'message', {
- get: function() {
- if (this.conversion != null && this.conversion.message) {
- return this.conversion.message;
- }
- // ERROR conversions have messages, VALID conversions don't need one, so
- // we just need to consider INCOMPLETE conversions.
- if (this.getStatus() === Status.INCOMPLETE) {
- return l10n.lookupFormat('cliIncompleteParam', [ this.param.name ]);
- }
- return '';
- },
- enumerable: true
-});
-
-/**
- * Easy (and safe) accessor for conversion.getPredictions()
- * @return An array of objects with name and value elements. For example:
- * [ { name:'bestmatch', value:foo1 }, { name:'next', value:foo2 }, ... ]
- */
-Assignment.prototype.getPredictions = function(context) {
- return this.conversion == null ? [] : this.conversion.getPredictions(context);
-};
-
-/**
- * Accessor for a prediction by index.
- * This is useful above getPredictions()[index] because it normalizes
- * index to be within the bounds of the predictions, which means that the UI
- * can maintain an index of which prediction to choose without caring how many
- * predictions there are.
- * @param rank The index of the prediction to choose
- */
-Assignment.prototype.getPredictionRanked = function(context, rank) {
- if (rank == null) {
- rank = 0;
- }
-
- if (this.isInName()) {
- return Promise.resolve(undefined);
- }
-
- return this.getPredictions(context).then(predictions => {
- if (predictions.length === 0) {
- return undefined;
- }
-
- rank = rank % predictions.length;
- if (rank < 0) {
- rank = predictions.length + rank;
- }
- return predictions[rank];
- });
-};
-
-/**
- * Some places want to take special action if we are in the name part of a
- * named argument (i.e. the '--foo' bit).
- * Currently this does not take actual cursor position into account, it just
- * assumes that the cursor is at the end. In the future we will probably want
- * to take this into account.
- */
-Assignment.prototype.isInName = function() {
- return this.conversion.arg.type === 'NamedArgument' &&
- this.conversion.arg.prefix.slice(-1) !== ' ';
-};
-
-/**
- * Work out what the status of the current conversion is which involves looking
- * not only at the conversion, but also checking if data has been provided
- * where it should.
- * @param arg For assignments with multiple args (e.g. array assignments) we
- * can narrow the search for status to a single argument.
- */
-Assignment.prototype.getStatus = function(arg) {
- if (this.param.isDataRequired && !this.conversion.isDataProvided()) {
- return Status.INCOMPLETE;
- }
-
- // Selection/Boolean types with a defined range of values will say that
- // '' is INCOMPLETE, but the parameter may be optional, so we don't ask
- // if the user doesn't need to enter something and hasn't done so.
- if (!this.param.isDataRequired && this.arg.type === 'BlankArgument') {
- return Status.VALID;
- }
-
- return this.conversion.getStatus(arg);
-};
-
-/**
- * Helper when we're rebuilding command lines.
- */
-Assignment.prototype.toString = function() {
- return this.conversion.toString();
-};
-
-/**
- * For test/debug use only. The output from this function is subject to wanton
- * random change without notice, and should not be relied upon to even exist
- * at some later date.
- */
-Object.defineProperty(Assignment.prototype, '_summaryJson', {
- get: function() {
- return {
- param: this.param.name + '/' + this.param.type.name,
- defaultValue: this.param.defaultValue,
- arg: this.conversion.arg._summaryJson,
- value: this.value,
- message: this.message,
- status: this.getStatus().toString()
- };
- },
- enumerable: true
-});
-
-exports.Assignment = Assignment;
-
-
-/**
- * How to dynamically execute JavaScript code
- */
-var customEval = eval;
-
-/**
- * Setup a function to be called in place of 'eval', generally for security
- * reasons
- */
-exports.setEvalFunction = function(newCustomEval) {
- customEval = newCustomEval;
-};
-
-/**
- * Remove the binding done by setEvalFunction().
- * We purposely set customEval to undefined rather than to 'eval' because there
- * is an implication of setEvalFunction that we're in a security sensitive
- * situation. What if we can trick GCLI into calling unsetEvalFunction() at the
- * wrong time?
- * So to properly undo the effects of setEvalFunction(), you need to call
- * setEvalFunction(eval) rather than unsetEvalFunction(), however the latter is
- * preferred in most cases.
- */
-exports.unsetEvalFunction = function() {
- customEval = undefined;
-};
-
-/**
- * 'eval' command
- */
-var evalCmd = {
- item: 'command',
- name: '{',
- params: [
- {
- name: 'javascript',
- type: 'javascript',
- description: ''
- }
- ],
- hidden: true,
- description: { key: 'cliEvalJavascript' },
- exec: function(args, context) {
- var reply = customEval(args.javascript);
- return context.typedData(typeof reply, reply);
- },
- isCommandRegexp: /^\s*\{\s*/
-};
-
-exports.items = [ evalCmd ];
-
-/**
- * This is a special assignment to reflect the command itself.
- */
-function CommandAssignment(requisition) {
- var commandParamMetadata = {
- name: '__command',
- type: { name: 'command', allowNonExec: false }
- };
- // This is a hack so that rather than reply with a generic description of the
- // command assignment, we reply with the description of the assigned command,
- // (using a generic term if there is no assigned command)
- var self = this;
- Object.defineProperty(commandParamMetadata, 'description', {
- get: function() {
- var value = self.value;
- return value && value.description ?
- value.description :
- 'The command to execute';
- },
- enumerable: true
- });
- this.param = new Parameter(requisition.system.types, commandParamMetadata);
-}
-
-CommandAssignment.prototype = Object.create(Assignment.prototype);
-
-CommandAssignment.prototype.getStatus = function(arg) {
- return Status.combine(
- Assignment.prototype.getStatus.call(this, arg),
- this.conversion.value && this.conversion.value.exec ?
- Status.VALID : Status.INCOMPLETE
- );
-};
-
-exports.CommandAssignment = CommandAssignment;
-
-
-/**
- * Special assignment used when ignoring parameters that don't have a home
- */
-function UnassignedAssignment(requisition, arg) {
- var isIncompleteName = (arg.text.charAt(0) === '-');
- this.param = new Parameter(requisition.system.types, {
- name: '__unassigned',
- description: l10n.lookup('cliOptions'),
- type: {
- name: 'param',
- requisition: requisition,
- isIncompleteName: isIncompleteName
- }
- });
-
- // It would be nice to do 'conversion = parm.type.parse(arg, ...)' except
- // that type.parse returns a promise (even though it's synchronous in this
- // case)
- if (isIncompleteName) {
- var lookup = commandModule.getDisplayedParamLookup(requisition);
- var predictions = selectionModule.findPredictions(arg, lookup);
- this.conversion = selectionModule.convertPredictions(arg, predictions);
- }
- else {
- var message = l10n.lookup('cliUnusedArg');
- this.conversion = new Conversion(undefined, arg, Status.ERROR, message);
- }
-
- this.conversion.assignment = this;
-}
-
-UnassignedAssignment.prototype = Object.create(Assignment.prototype);
-
-UnassignedAssignment.prototype.getStatus = function(arg) {
- return this.conversion.getStatus();
-};
-
-var logErrors = true;
-
-/**
- * Allow tests that expect failures to avoid clogging up the console
- */
-Object.defineProperty(exports, 'logErrors', {
- get: function() {
- return logErrors;
- },
- set: function(val) {
- logErrors = val;
- },
- enumerable: true
-});
-
-/**
- * A Requisition collects the information needed to execute a command.
- *
- * (For a definition of the term, see http://en.wikipedia.org/wiki/Requisition)
- * This term is used because carries the notion of a work-flow, or process to
- * getting the information to execute a command correct.
- * There is little point in a requisition for parameter-less commands because
- * there is no information to collect. A Requisition is a collection of
- * assignments of values to parameters, each handled by an instance of
- * Assignment.
- *
- * @param system Allows access to the various plug-in points in GCLI. At a
- * minimum it must contain commands and types objects.
- * @param options A set of options to customize how GCLI is used. Includes:
- * - environment An optional opaque object passed to commands in the
- * Execution Context.
- * - document A DOM Document passed to commands using the Execution Context in
- * order to allow creation of DOM nodes. If missing Requisition will use the
- * global 'document', or leave undefined.
- * - commandOutputManager A custom commandOutputManager to which output should
- * be sent
- * @constructor
- */
-function Requisition(system, options) {
- options = options || {};
-
- this.environment = options.environment || {};
- this.document = options.document;
- if (this.document == null) {
- try {
- this.document = document;
- }
- catch (ex) {
- // Ignore
- }
- }
-
- this.commandOutputManager = options.commandOutputManager || new CommandOutputManager();
- this.system = system;
-
- this.shell = {
- cwd: '/', // Where we store the current working directory
- env: {} // Where we store the current environment
- };
-
- // The command that we are about to execute.
- // @see setCommandConversion()
- this.commandAssignment = new CommandAssignment(this);
-
- // The object that stores of Assignment objects that we are filling out.
- // The Assignment objects are stored under their param.name for named
- // lookup. Note: We make use of the property of Javascript objects that
- // they are not just hashmaps, but linked-list hashmaps which iterate in
- // insertion order.
- // _assignments excludes the commandAssignment.
- this._assignments = {};
-
- // The count of assignments. Excludes the commandAssignment
- this.assignmentCount = 0;
-
- // Used to store cli arguments in the order entered on the cli
- this._args = [];
-
- // Used to store cli arguments that were not assigned to parameters
- this._unassigned = [];
-
- // Changes can be asynchronous, when one update starts before another
- // finishes we abandon the former change
- this._nextUpdateId = 0;
-
- // We can set a prefix to typed commands to make it easier to focus on
- // Allowing us to type "add -a; commit" in place of "git add -a; git commit"
- this.prefix = '';
-
- addMapping(this);
- this._setBlankAssignment(this.commandAssignment);
-
- // If a command calls context.update then the UI needs some way to be
- // informed of the change
- this.onExternalUpdate = util.createEvent('Requisition.onExternalUpdate');
-}
-
-/**
- * Avoid memory leaks
- */
-Requisition.prototype.destroy = function() {
- this.document = undefined;
- this.environment = undefined;
- removeMapping(this);
-};
-
-/**
- * If we're about to make an asynchronous change when other async changes could
- * overtake this one, then we want to be able to bail out if overtaken. The
- * value passed back from beginChange should be passed to endChangeCheckOrder
- * on completion of calculation, before the results are applied in order to
- * check that the calculation has not been overtaken
- */
-Requisition.prototype._beginChange = function() {
- var updateId = this._nextUpdateId;
- this._nextUpdateId++;
- return updateId;
-};
-
-/**
- * Check to see if another change has started since updateId started.
- * This allows us to bail out of an update.
- * It's hard to make updates atomic because until you've responded to a parse
- * of the command argument, you don't know how to parse the arguments to that
- * command.
- */
-Requisition.prototype._isChangeCurrent = function(updateId) {
- return updateId + 1 === this._nextUpdateId;
-};
-
-/**
- * See notes on beginChange
- */
-Requisition.prototype._endChangeCheckOrder = function(updateId) {
- if (updateId + 1 !== this._nextUpdateId) {
- // An update that started after we did has already finished, so our
- // changes are out of date. Abandon further work.
- return false;
- }
-
- return true;
-};
-
-var legacy = false;
-
-/**
- * Functions and data related to the execution of a command
- */
-Object.defineProperty(Requisition.prototype, 'executionContext', {
- get: function() {
- if (this._executionContext == null) {
- this._executionContext = {
- defer: defer,
- typedData: function(type, data) {
- return {
- isTypedData: true,
- data: data,
- type: type
- };
- },
- getArgsObject: this.getArgsObject.bind(this)
- };
-
- // Alias requisition so we're clear about what's what
- var requisition = this;
- Object.defineProperty(this._executionContext, 'prefix', {
- get: function() { return requisition.prefix; },
- enumerable: true
- });
- Object.defineProperty(this._executionContext, 'typed', {
- get: function() { return requisition.toString(); },
- enumerable: true
- });
- Object.defineProperty(this._executionContext, 'environment', {
- get: function() { return requisition.environment; },
- enumerable: true
- });
- Object.defineProperty(this._executionContext, 'shell', {
- get: function() { return requisition.shell; },
- enumerable: true
- });
- Object.defineProperty(this._executionContext, 'system', {
- get: function() { return requisition.system; },
- enumerable: true
- });
-
- this._executionContext.updateExec = this._contextUpdateExec.bind(this);
-
- if (legacy) {
- this._executionContext.createView = view.createView;
- this._executionContext.exec = this.exec.bind(this);
- this._executionContext.update = this._contextUpdate.bind(this);
-
- Object.defineProperty(this._executionContext, 'document', {
- get: function() { return requisition.document; },
- enumerable: true
- });
- }
- }
-
- return this._executionContext;
- },
- enumerable: true
-});
-
-/**
- * Functions and data related to the conversion of the output of a command
- */
-Object.defineProperty(Requisition.prototype, 'conversionContext', {
- get: function() {
- if (this._conversionContext == null) {
- this._conversionContext = {
- defer: defer,
-
- createView: view.createView,
- exec: this.exec.bind(this),
- update: this._contextUpdate.bind(this),
- updateExec: this._contextUpdateExec.bind(this)
- };
-
- // Alias requisition so we're clear about what's what
- var requisition = this;
-
- Object.defineProperty(this._conversionContext, 'document', {
- get: function() { return requisition.document; },
- enumerable: true
- });
- Object.defineProperty(this._conversionContext, 'environment', {
- get: function() { return requisition.environment; },
- enumerable: true
- });
- Object.defineProperty(this._conversionContext, 'system', {
- get: function() { return requisition.system; },
- enumerable: true
- });
- }
-
- return this._conversionContext;
- },
- enumerable: true
-});
-
-/**
- * Assignments have an order, so we need to store them in an array.
- * But we also need named access ...
- * @return The found assignment, or undefined, if no match was found
- */
-Requisition.prototype.getAssignment = function(nameOrNumber) {
- var name = (typeof nameOrNumber === 'string') ?
- nameOrNumber :
- Object.keys(this._assignments)[nameOrNumber];
- return this._assignments[name] || undefined;
-};
-
-/**
- * Where parameter name == assignment names - they are the same
- */
-Requisition.prototype.getParameterNames = function() {
- return Object.keys(this._assignments);
-};
-
-/**
- * The overall status is the most severe status.
- * There is no such thing as an INCOMPLETE overall status because the
- * definition of INCOMPLETE takes into account the cursor position to say 'this
- * isn't quite ERROR because the user can fix it by typing', however overall,
- * this is still an error status.
- */
-Object.defineProperty(Requisition.prototype, 'status', {
- get: function() {
- var status = Status.VALID;
- if (this._unassigned.length !== 0) {
- var isAllIncomplete = true;
- this._unassigned.forEach(function(assignment) {
- if (!assignment.param.type.isIncompleteName) {
- isAllIncomplete = false;
- }
- });
- status = isAllIncomplete ? Status.INCOMPLETE : Status.ERROR;
- }
-
- this.getAssignments(true).forEach(function(assignment) {
- var assignStatus = assignment.getStatus();
- if (assignStatus > status) {
- status = assignStatus;
- }
- }, this);
- if (status === Status.INCOMPLETE) {
- status = Status.ERROR;
- }
- return status;
- },
- enumerable : true
-});
-
-/**
- * If ``requisition.status != VALID`` message then return a string which
- * best describes what is wrong. Generally error messages are delivered by
- * looking at the error associated with the argument at the cursor, but there
- * are times when you just want to say 'tell me the worst'.
- * If ``requisition.status != VALID`` then return ``null``.
- */
-Requisition.prototype.getStatusMessage = function() {
- if (this.commandAssignment.getStatus() !== Status.VALID) {
- return l10n.lookupFormat('cliUnknownCommand2',
- [ this.commandAssignment.arg.text ]);
- }
-
- var assignments = this.getAssignments();
- for (var i = 0; i < assignments.length; i++) {
- if (assignments[i].getStatus() !== Status.VALID) {
- return assignments[i].message;
- }
- }
-
- if (this._unassigned.length !== 0) {
- return l10n.lookup('cliUnusedArg');
- }
-
- return null;
-};
-
-/**
- * Extract the names and values of all the assignments, and return as
- * an object.
- */
-Requisition.prototype.getArgsObject = function() {
- var args = {};
- this.getAssignments().forEach(function(assignment) {
- args[assignment.param.name] = assignment.conversion.isDataProvided() ?
- assignment.value :
- assignment.param.defaultValue;
- }, this);
- return args;
-};
-
-/**
- * Access the arguments as an array.
- * @param includeCommand By default only the parameter arguments are
- * returned unless (includeCommand === true), in which case the list is
- * prepended with commandAssignment.arg
- */
-Requisition.prototype.getAssignments = function(includeCommand) {
- var assignments = [];
- if (includeCommand === true) {
- assignments.push(this.commandAssignment);
- }
- Object.keys(this._assignments).forEach(function(name) {
- assignments.push(this.getAssignment(name));
- }, this);
- return assignments;
-};
-
-/**
- * There are a few places where we need to know what the 'next thing' is. What
- * is the user going to be filling out next (assuming they don't enter a named
- * argument). The next argument is the first in line that is both blank, and
- * that can be filled in positionally.
- * @return The next assignment to be used, or null if all the positional
- * parameters have values.
- */
-Requisition.prototype._getFirstBlankPositionalAssignment = function() {
- var reply = null;
- Object.keys(this._assignments).some(function(name) {
- var assignment = this.getAssignment(name);
- if (assignment.arg.type === 'BlankArgument' &&
- assignment.param.isPositionalAllowed) {
- reply = assignment;
- return true; // i.e. break
- }
- return false;
- }, this);
- return reply;
-};
-
-/**
- * The update process is asynchronous, so there is (unavoidably) a window
- * where we've worked out the command but don't yet understand all the params.
- * If we try to do things to a requisition in this window we may get
- * inconsistent results. Asynchronous promises have made the window bigger.
- * The only time we've seen this in practice is during focus events due to
- * clicking on a shortcut. The focus want to check the cursor position while
- * the shortcut is updating the command line.
- * This function allows us to detect and back out of this problem.
- * We should be able to remove this function when all the state in a
- * requisition can be encapsulated and updated atomically.
- */
-Requisition.prototype.isUpToDate = function() {
- if (!this._args) {
- return false;
- }
- for (var i = 0; i < this._args.length; i++) {
- if (this._args[i].assignment == null) {
- return false;
- }
- }
- return true;
-};
-
-/**
- * Look through the arguments attached to our assignments for the assignment
- * at the given position.
- * @param {number} cursor The cursor position to query
- */
-Requisition.prototype.getAssignmentAt = function(cursor) {
- // We short circuit this one because we may have no args, or no args with
- // any size and the alg below only finds arguments with size.
- if (cursor === 0) {
- return this.commandAssignment;
- }
-
- var assignForPos = [];
- var i, j;
- for (i = 0; i < this._args.length; i++) {
- var arg = this._args[i];
- var assignment = arg.assignment;
-
- // prefix and text are clearly part of the argument
- for (j = 0; j < arg.prefix.length; j++) {
- assignForPos.push(assignment);
- }
- for (j = 0; j < arg.text.length; j++) {
- assignForPos.push(assignment);
- }
-
- // suffix is part of the argument only if this is a named parameter,
- // otherwise it looks forwards
- if (arg.assignment.arg.type === 'NamedArgument') {
- // leave the argument as it is
- }
- else if (this._args.length > i + 1) {
- // first to the next argument
- assignment = this._args[i + 1].assignment;
- }
- else {
- // then to the first blank positional parameter, leaving 'as is' if none
- var nextAssignment = this._getFirstBlankPositionalAssignment();
- if (nextAssignment != null) {
- assignment = nextAssignment;
- }
- }
-
- for (j = 0; j < arg.suffix.length; j++) {
- assignForPos.push(assignment);
- }
- }
-
- // Possible shortcut, we don't really need to go through all the args
- // to work out the solution to this
-
- return assignForPos[cursor - 1];
-};
-
-/**
- * Extract a canonical version of the input
- * @return a promise of a string which is the canonical version of what was
- * typed
- */
-Requisition.prototype.toCanonicalString = function() {
- var cmd = this.commandAssignment.value ?
- this.commandAssignment.value.name :
- this.commandAssignment.arg.text;
-
- // Canonically, if we've opened with a { then we should have a } to close
- var lineSuffix = '';
- if (cmd === '{') {
- var scriptSuffix = this.getAssignment(0).arg.suffix;
- lineSuffix = (!scriptSuffix.includes('}')) ? ' }' : '';
- }
-
- var ctx = this.executionContext;
-
- // First stringify all the arguments
- var argPromise = util.promiseEach(this.getAssignments(), assignment => {
- // Bug 664377: This will cause problems if there is a non-default value
- // after a default value. Also we need to decide when to use
- // named parameters in place of positional params. Both can wait.
- if (assignment.value === assignment.param.defaultValue) {
- return '';
- }
-
- var val = assignment.param.type.stringify(assignment.value, ctx);
- return Promise.resolve(val).then(str => {
- return ' ' + str;
- });
- });
-
- return argPromise.then(strings => {
- return cmd + strings.join('') + lineSuffix;
- });
-};
-
-/**
- * Reconstitute the input from the args
- */
-Requisition.prototype.toString = function() {
- if (!this._args) {
- throw new Error('toString requires a command line. See source.');
- }
-
- return this._args.map(function(arg) {
- return arg.toString();
- }).join('');
-};
-
-/**
- * For test/debug use only. The output from this function is subject to wanton
- * random change without notice, and should not be relied upon to even exist
- * at some later date.
- */
-Object.defineProperty(Requisition.prototype, '_summaryJson', {
- get: function() {
- var summary = {
- $args: this._args.map(function(arg) {
- return arg._summaryJson;
- }),
- _command: this.commandAssignment._summaryJson,
- _unassigned: this._unassigned.forEach(function(assignment) {
- return assignment._summaryJson;
- })
- };
-
- Object.keys(this._assignments).forEach(name => {
- summary[name] = this.getAssignment(name)._summaryJson;
- });
-
- return summary;
- },
- enumerable: true
-});
-
-/**
- * When any assignment changes, we might need to update the _args array to
- * match and inform people of changes to the typed input text.
- */
-Requisition.prototype._setAssignmentInternal = function(assignment, conversion) {
- var oldConversion = assignment.conversion;
-
- assignment.conversion = conversion;
- assignment.conversion.assignment = assignment;
-
- // Do nothing if the conversion is unchanged
- if (assignment.conversion.equals(oldConversion)) {
- if (assignment === this.commandAssignment) {
- this._setBlankArguments();
- }
- return;
- }
-
- // When the command changes, we need to keep a bunch of stuff in sync
- if (assignment === this.commandAssignment) {
- this._assignments = {};
-
- var command = this.commandAssignment.value;
- if (command) {
- for (var i = 0; i < command.params.length; i++) {
- var param = command.params[i];
- var newAssignment = new Assignment(param);
- this._setBlankAssignment(newAssignment);
- this._assignments[param.name] = newAssignment;
- }
- }
- this.assignmentCount = Object.keys(this._assignments).length;
- }
-};
-
-/**
- * Internal function to alter the given assignment using the given arg.
- * @param assignment The assignment to alter
- * @param arg The new value for the assignment. An instance of Argument, or an
- * instance of Conversion, or null to set the blank value.
- * @param options There are a number of ways to customize how the assignment
- * is made, including:
- * - internal: (default:false) External updates are required to do more work,
- * including adjusting the args in this requisition to stay in sync.
- * On the other hand non internal changes use beginChange to back out of
- * changes when overtaken asynchronously.
- * Setting internal:true effectively means this is being called as part of
- * the update process.
- * - matchPadding: (default:false) Alter the whitespace on the prefix and
- * suffix of the new argument to match that of the old argument. This only
- * makes sense with internal=false
- * @return A promise that resolves to undefined when the assignment is complete
- */
-Requisition.prototype.setAssignment = function(assignment, arg, options) {
- options = options || {};
- if (!options.internal) {
- var originalArgs = assignment.arg.getArgs();
-
- // Update the args array
- var replacementArgs = arg.getArgs();
- var maxLen = Math.max(originalArgs.length, replacementArgs.length);
- for (var i = 0; i < maxLen; i++) {
- // If there are no more original args, or if the original arg was blank
- // (i.e. not typed by the user), we'll just need to add at the end
- if (i >= originalArgs.length || originalArgs[i].type === 'BlankArgument') {
- this._args.push(replacementArgs[i]);
- continue;
- }
-
- var index = this._args.indexOf(originalArgs[i]);
- if (index === -1) {
- console.error('Couldn\'t find ', originalArgs[i], ' in ', this._args);
- throw new Error('Couldn\'t find ' + originalArgs[i]);
- }
-
- // If there are no more replacement args, we just remove the original args
- // Otherwise swap original args and replacements
- if (i >= replacementArgs.length) {
- this._args.splice(index, 1);
- }
- else {
- if (options.matchPadding) {
- if (replacementArgs[i].prefix.length === 0 &&
- this._args[index].prefix.length !== 0) {
- replacementArgs[i].prefix = this._args[index].prefix;
- }
- if (replacementArgs[i].suffix.length === 0 &&
- this._args[index].suffix.length !== 0) {
- replacementArgs[i].suffix = this._args[index].suffix;
- }
- }
- this._args[index] = replacementArgs[i];
- }
- }
- }
-
- var updateId = options.internal ? null : this._beginChange();
-
- var setAssignmentInternal = conversion => {
- if (options.internal || this._isChangeCurrent(updateId)) {
- this._setAssignmentInternal(assignment, conversion);
- }
-
- if (!options.internal) {
- this._endChangeCheckOrder(updateId);
- }
-
- return Promise.resolve(undefined);
- };
-
- if (arg == null) {
- var blank = assignment.param.type.getBlank(this.executionContext);
- return setAssignmentInternal(blank);
- }
-
- if (typeof arg.getStatus === 'function') {
- // It's not really an arg, it's a conversion already
- return setAssignmentInternal(arg);
- }
-
- var parsed = assignment.param.type.parse(arg, this.executionContext);
- return parsed.then(setAssignmentInternal);
-};
-
-/**
- * Reset an assignment to its default value.
- * For internal use only.
- * Happens synchronously.
- */
-Requisition.prototype._setBlankAssignment = function(assignment) {
- var blank = assignment.param.type.getBlank(this.executionContext);
- this._setAssignmentInternal(assignment, blank);
-};
-
-/**
- * Reset all the assignments to their default values.
- * For internal use only.
- * Happens synchronously.
- */
-Requisition.prototype._setBlankArguments = function() {
- this.getAssignments().forEach(this._setBlankAssignment.bind(this));
-};
-
-/**
- * Input trace gives us an array of Argument tracing objects, one for each
- * character in the typed input, from which we can derive information about how
- * to display this typed input. It's a bit like toString on steroids.
- *
- * The returned object has the following members:
- *
character: The character to which this arg trace refers.
- *
arg: The Argument to which this character is assigned.
- *
part: One of ['prefix'|'text'|suffix'] - how was this char understood
- *
- *
- * The Argument objects are as output from tokenize() rather than as applied
- * to Assignments by _assign() (i.e. they are not instances of NamedArgument,
- * ArrayArgument, etc).
- *
- * To get at the arguments applied to the assignments simply call
- * arg.assignment.arg. If arg.assignment.arg !== arg then
- * the arg applied to the assignment will contain the original arg.
- * See _assign() for details.
- */
-Requisition.prototype.createInputArgTrace = function() {
- if (!this._args) {
- throw new Error('createInputMap requires a command line. See source.');
- }
-
- var args = [];
- var i;
- this._args.forEach(function(arg) {
- for (i = 0; i < arg.prefix.length; i++) {
- args.push({ arg: arg, character: arg.prefix[i], part: 'prefix' });
- }
- for (i = 0; i < arg.text.length; i++) {
- args.push({ arg: arg, character: arg.text[i], part: 'text' });
- }
- for (i = 0; i < arg.suffix.length; i++) {
- args.push({ arg: arg, character: arg.suffix[i], part: 'suffix' });
- }
- });
-
- return args;
-};
-
-/**
- * If the last character is whitespace then things that we suggest to add to
- * the end don't need a space prefix.
- * While this is quite a niche function, it has 2 benefits:
- * - it's more correct because we can distinguish between final whitespace that
- * is part of an unclosed string, and parameter separating whitespace.
- * - also it's faster than toString() the whole thing and checking the end char
- * @return true iff the last character is interpreted as parameter separating
- * whitespace
- */
-Requisition.prototype.typedEndsWithSeparator = function() {
- if (!this._args) {
- throw new Error('typedEndsWithSeparator requires a command line. See source.');
- }
-
- if (this._args.length === 0) {
- return false;
- }
-
- // This is not as easy as doing (this.toString().slice(-1) === ' ')
- // See the doc comments above; We're checking for separators, not spaces
- var lastArg = this._args.slice(-1)[0];
- if (lastArg.suffix.slice(-1) === ' ') {
- return true;
- }
-
- return lastArg.text === '' && lastArg.suffix === ''
- && lastArg.prefix.slice(-1) === ' ';
-};
-
-/**
- * Return an array of Status scores so we can create a marked up
- * version of the command line input.
- * @param cursor We only take a status of INCOMPLETE to be INCOMPLETE when the
- * cursor is actually in the argument. Otherwise it's an error.
- * @return Array of objects each containing status property and a
- * string property containing the characters to which the status
- * applies. Concatenating the strings in order gives the original input.
- */
-Requisition.prototype.getInputStatusMarkup = function(cursor) {
- var argTraces = this.createInputArgTrace();
- // Generally the 'argument at the cursor' is the argument before the cursor
- // unless it is before the first char, in which case we take the first.
- cursor = cursor === 0 ? 0 : cursor - 1;
- var cTrace = argTraces[cursor];
-
- var markup = [];
- for (var i = 0; i < argTraces.length; i++) {
- var argTrace = argTraces[i];
- var arg = argTrace.arg;
- var status = Status.VALID;
- // When things get very async we can get here while something else is
- // doing an update, in which case arg.assignment == null, so we check first
- if (argTrace.part === 'text' && arg.assignment != null) {
- status = arg.assignment.getStatus(arg);
- // Promote INCOMPLETE to ERROR ...
- if (status === Status.INCOMPLETE) {
- // If the cursor is in the prefix or suffix of an argument then we
- // don't consider it in the argument for the purposes of preventing
- // the escalation to ERROR. However if this is a NamedArgument, then we
- // allow the suffix (as space between 2 parts of the argument) to be in.
- // We use arg.assignment.arg not arg because we're looking at the arg
- // that got put into the assignment not as returned by tokenize()
- var isNamed = (cTrace.arg.assignment.arg.type === 'NamedArgument');
- var isInside = cTrace.part === 'text' ||
- (isNamed && cTrace.part === 'suffix');
- if (arg.assignment !== cTrace.arg.assignment || !isInside) {
- // And if we're not in the command
- if (!(arg.assignment instanceof CommandAssignment)) {
- status = Status.ERROR;
- }
- }
- }
- }
-
- markup.push({ status: status, string: argTrace.character });
- }
-
- // De-dupe: merge entries where 2 adjacent have same status
- i = 0;
- while (i < markup.length - 1) {
- if (markup[i].status === markup[i + 1].status) {
- markup[i].string += markup[i + 1].string;
- markup.splice(i + 1, 1);
- }
- else {
- i++;
- }
- }
-
- return markup;
-};
-
-/**
- * Describe the state of the current input in a way that allows display of
- * predictions and completion hints
- * @param start The location of the cursor
- * @param rank The index of the chosen prediction
- * @return A promise of an object containing the following properties:
- * - statusMarkup: An array of Status scores so we can create a marked up
- * version of the command line input. See getInputStatusMarkup() for details
- * - unclosedJs: Is the entered command a JS command with no closing '}'?
- * - directTabText: A promise of the text that we *add* to the command line
- * when TAB is pressed, to be displayed directly after the cursor. See also
- * arrowTabText.
- * - emptyParameters: A promise of the text that describes the arguments that
- * the user is yet to type.
- * - arrowTabText: A promise of the text that *replaces* the current argument
- * when TAB is pressed, generally displayed after a "|->" symbol. See also
- * directTabText.
- */
-Requisition.prototype.getStateData = function(start, rank) {
- var typed = this.toString();
- var current = this.getAssignmentAt(start);
- var context = this.executionContext;
- var predictionPromise = (typed.trim().length !== 0) ?
- current.getPredictionRanked(context, rank) :
- Promise.resolve(null);
-
- return predictionPromise.then(prediction => {
- // directTabText is for when the current input is a prefix of the completion
- // arrowTabText is for when we need to use an -> to show what will be used
- var directTabText = '';
- var arrowTabText = '';
- var emptyParameters = [];
-
- if (typed.trim().length !== 0) {
- var cArg = current.arg;
-
- if (prediction) {
- var tabText = prediction.name;
- var existing = cArg.text;
-
- // Normally the cursor being just before whitespace means that you are
- // 'in' the previous argument, which means that the prediction is based
- // on that argument, however NamedArguments break this by having 2 parts
- // so we need to prepend the tabText with a space for NamedArguments,
- // but only when there isn't already a space at the end of the prefix
- // (i.e. ' --name' not ' --name ')
- if (current.isInName()) {
- tabText = ' ' + tabText;
- }
-
- if (existing !== tabText) {
- // Decide to use directTabText or arrowTabText
- // Strip any leading whitespace from the user inputted value because
- // the tabText will never have leading whitespace.
- var inputValue = existing.replace(/^\s*/, '');
- var isStrictCompletion = tabText.indexOf(inputValue) === 0;
- if (isStrictCompletion && start === typed.length) {
- // Display the suffix of the prediction as the completion
- var numLeadingSpaces = existing.match(/^(\s*)/)[0].length;
-
- directTabText = tabText.slice(existing.length - numLeadingSpaces);
- }
- else {
- // Display the '-> prediction' at the end of the completer element
- // \u21E5 is the JS escape right arrow
- arrowTabText = '\u21E5 ' + tabText;
- }
- }
- }
- else {
- // There's no prediction, but if this is a named argument that needs a
- // value (that is without any) then we need to show that one is needed
- // For example 'git commit --message ', clearly needs some more text
- if (cArg.type === 'NamedArgument' && cArg.valueArg == null) {
- emptyParameters.push('<' + current.param.type.name + '>\u00a0');
- }
- }
- }
-
- // Add a space between the typed text (+ directTabText) and the hints,
- // making sure we don't add 2 sets of padding
- if (directTabText !== '') {
- directTabText += '\u00a0'; // a.k.a
- }
- else if (!this.typedEndsWithSeparator()) {
- emptyParameters.unshift('\u00a0');
- }
-
- // Calculate the list of parameters to be filled in
- // We generate an array of emptyParameter markers for each positional
- // parameter to the current command.
- // Generally each emptyParameter marker begins with a space to separate it
- // from whatever came before, unless what comes before ends in a space.
-
- this.getAssignments().forEach(assignment => {
- // Named arguments are handled with a group [options] marker
- if (!assignment.param.isPositionalAllowed) {
- return;
- }
-
- // No hints if we've got content for this parameter
- if (assignment.arg.toString().trim() !== '') {
- return;
- }
-
- // No hints if we have a prediction
- if (directTabText !== '' && current === assignment) {
- return;
- }
-
- var text = (assignment.param.isDataRequired) ?
- '<' + assignment.param.name + '>\u00a0' :
- '[' + assignment.param.name + ']\u00a0';
-
- emptyParameters.push(text);
- });
-
- var command = this.commandAssignment.value;
- var addOptionsMarker = false;
-
- // We add an '[options]' marker when there are named parameters that are
- // not filled in and not hidden, and we don't have any directTabText
- if (command && command.hasNamedParameters) {
- command.params.forEach(function(param) {
- var arg = this.getAssignment(param.name).arg;
- if (!param.isPositionalAllowed && !param.hidden
- && arg.type === 'BlankArgument') {
- addOptionsMarker = true;
- }
- }, this);
- }
-
- if (addOptionsMarker) {
- // Add an nbsp if we don't have one at the end of the input or if
- // this isn't the first param we've mentioned
- emptyParameters.push('[options]\u00a0');
- }
-
- // Is the entered command a JS command with no closing '}'?
- var unclosedJs = command && command.name === '{' &&
- !this.getAssignment(0).arg.suffix.includes('}');
-
- return {
- statusMarkup: this.getInputStatusMarkup(start),
- unclosedJs: unclosedJs,
- directTabText: directTabText,
- arrowTabText: arrowTabText,
- emptyParameters: emptyParameters
- };
- });
-};
-
-/**
- * Pressing TAB sometimes requires that we add a space to denote that we're on
- * to the 'next thing'.
- * @param assignment The assignment to which to append the space
- */
-Requisition.prototype._addSpace = function(assignment) {
- var arg = assignment.arg.beget({ suffixSpace: true });
- if (arg !== assignment.arg) {
- return this.setAssignment(assignment, arg);
- }
- else {
- return Promise.resolve(undefined);
- }
-};
-
-/**
- * Complete the argument at cursor.
- * Basically the same as:
- * assignment = getAssignmentAt(cursor);
- * assignment.value = assignment.conversion.predictions[0];
- * Except it's done safely, and with particular care to where we place the
- * space, which is complex, and annoying if we get it wrong.
- *
- * WARNING: complete() can happen asynchronously.
- *
- * @param cursor The cursor configuration. Should have start and end properties
- * which should be set to start and end of the selection.
- * @param rank The index of the prediction that we should choose.
- * This number is not bounded by the size of the prediction array, we take the
- * modulus to get it within bounds
- * @return A promise which completes (with undefined) when any outstanding
- * completion tasks are done.
- */
-Requisition.prototype.complete = function(cursor, rank) {
- var assignment = this.getAssignmentAt(cursor.start);
-
- var context = this.executionContext;
- var predictionPromise = assignment.getPredictionRanked(context, rank);
- return predictionPromise.then(prediction => {
- var outstanding = [];
-
- // Note: Since complete is asynchronous we should perhaps have a system to
- // bail out of making changes if the command line has changed since TAB
- // was pressed. It's not yet clear if this will be a problem.
-
- if (prediction == null) {
- // No predictions generally means we shouldn't change anything on TAB,
- // but TAB has the connotation of 'next thing' and when we're at the end
- // of a thing that implies that we should add a space. i.e.
- // 'help' -> 'help '
- // But we should only do this if the thing that we're 'completing' is
- // valid and doesn't already end in a space.
- if (assignment.arg.suffix.slice(-1) !== ' ' &&
- assignment.getStatus() === Status.VALID) {
- outstanding.push(this._addSpace(assignment));
- }
-
- // Also add a space if we are in the name part of an assignment, however
- // this time we don't want the 'push the space to the next assignment'
- // logic, so we don't use addSpace
- if (assignment.isInName()) {
- var newArg = assignment.arg.beget({ prefixPostSpace: true });
- outstanding.push(this.setAssignment(assignment, newArg));
- }
- }
- else {
- // Mutate this argument to hold the completion
- var arg = assignment.arg.beget({
- text: prediction.name,
- dontQuote: (assignment === this.commandAssignment)
- });
- var assignPromise = this.setAssignment(assignment, arg);
-
- if (!prediction.incomplete) {
- assignPromise = assignPromise.then(() => {
- // The prediction is complete, add a space to let the user move-on
- return this._addSpace(assignment).then(() => {
- // Bug 779443 - Remove or explain the re-parse
- if (assignment instanceof UnassignedAssignment) {
- return this.update(this.toString());
- }
- });
- });
- }
-
- outstanding.push(assignPromise);
- }
-
- return Promise.all(outstanding).then(() => {
- return true;
- });
- });
-};
-
-/**
- * Replace the current value with the lower value if such a concept exists.
- */
-Requisition.prototype.nudge = function(assignment, by) {
- var ctx = this.executionContext;
- var val = assignment.param.type.nudge(assignment.value, by, ctx);
- return Promise.resolve(val).then(replacement => {
- if (replacement != null) {
- var val = assignment.param.type.stringify(replacement, ctx);
- return Promise.resolve(val).then(str => {
- var arg = assignment.arg.beget({ text: str });
- return this.setAssignment(assignment, arg);
- });
- }
- });
-};
-
-/**
- * Helper to find the 'data-command' attribute, used by |update()|
- */
-function getDataCommandAttribute(element) {
- var command = element.getAttribute('data-command');
- if (!command) {
- command = element.querySelector('*[data-command]')
- .getAttribute('data-command');
- }
- return command;
-}
-
-/**
- * Designed to be called from context.update(). Acts just like update() except
- * that it also calls onExternalUpdate() to inform the UI of an unexpected
- * change to the current command.
- */
-Requisition.prototype._contextUpdate = function(typed) {
- return this.update(typed).then(reply => {
- this.onExternalUpdate({ typed: typed });
- return reply;
- });
-};
-
-/**
- * Called by the UI when ever the user interacts with a command line input
- * @param typed The contents of the input field OR an HTML element (or an event
- * that targets an HTML element) which has a data-command attribute or a child
- * with the same that contains the command to update with
- */
-Requisition.prototype.update = function(typed) {
- // Should be "if (typed instanceof HTMLElement)" except Gecko
- if (typeof typed.querySelector === 'function') {
- typed = getDataCommandAttribute(typed);
- }
- // Should be "if (typed instanceof Event)" except Gecko
- if (typeof typed.currentTarget === 'object') {
- typed = getDataCommandAttribute(typed.currentTarget);
- }
-
- var updateId = this._beginChange();
-
- this._args = exports.tokenize(typed);
- var args = this._args.slice(0); // i.e. clone
-
- this._split(args);
-
- return this._assign(args).then(() => {
- return this._endChangeCheckOrder(updateId);
- });
-};
-
-/**
- * Similar to update('') except that it's guaranteed to execute synchronously
- */
-Requisition.prototype.clear = function() {
- var arg = new Argument('', '', '');
- this._args = [ arg ];
-
- var conversion = commandModule.parse(this.executionContext, arg, false);
- this.setAssignment(this.commandAssignment, conversion, { internal: true });
-};
-
-/**
- * tokenize() is a state machine. These are the states.
- */
-var In = {
- /**
- * The last character was ' '.
- * Typing a ' ' character will not change the mode
- * Typing one of '"{ will change mode to SINGLE_Q, DOUBLE_Q or SCRIPT.
- * Anything else goes into SIMPLE mode.
- */
- WHITESPACE: 1,
-
- /**
- * The last character was part of a parameter.
- * Typing ' ' returns to WHITESPACE mode. Any other character
- * (including '"{} which are otherwise special) does not change the mode.
- */
- SIMPLE: 2,
-
- /**
- * We're inside single quotes: '
- * Typing ' returns to WHITESPACE mode. Other characters do not change mode.
- */
- SINGLE_Q: 3,
-
- /**
- * We're inside double quotes: "
- * Typing " returns to WHITESPACE mode. Other characters do not change mode.
- */
- DOUBLE_Q: 4,
-
- /**
- * We're inside { and }
- * Typing } returns to WHITESPACE mode. Other characters do not change mode.
- * SCRIPT mode is slightly different from other modes in that spaces between
- * the {/} delimiters and the actual input are not considered significant.
- * e.g: " x " is a 3 character string, delimited by double quotes, however
- * { x } is a 1 character JavaScript surrounded by whitespace and {}
- * delimiters.
- * In the short term we assume that the JS routines can make sense of the
- * extra whitespace, however at some stage we may need to move the space into
- * the Argument prefix/suffix.
- * Also we don't attempt to handle nested {}. See bug 678961
- */
- SCRIPT: 5
-};
-
-/**
- * Split up the input taking into account ', " and {.
- * We don't consider \t or other classical whitespace characters to split
- * arguments apart. For one thing these characters are hard to type, but also
- * if the user has gone to the trouble of pasting a TAB character into the
- * input field (or whatever it takes), they probably mean it.
- */
-exports.tokenize = function(typed) {
- // For blank input, place a dummy empty argument into the list
- if (typed == null || typed.length === 0) {
- return [ new Argument('', '', '') ];
- }
-
- if (isSimple(typed)) {
- return [ new Argument(typed, '', '') ];
- }
-
- var mode = In.WHITESPACE;
-
- // First we swap out escaped characters that are special to the tokenizer.
- // So a backslash followed by any of ['"{} ] is turned into a unicode private
- // char so we can swap back later
- typed = typed
- .replace(/\\\\/g, '\uF000')
- .replace(/\\ /g, '\uF001')
- .replace(/\\'/g, '\uF002')
- .replace(/\\"/g, '\uF003')
- .replace(/\\{/g, '\uF004')
- .replace(/\\}/g, '\uF005');
-
- function unescape2(escaped) {
- return escaped
- .replace(/\uF000/g, '\\\\')
- .replace(/\uF001/g, '\\ ')
- .replace(/\uF002/g, '\\\'')
- .replace(/\uF003/g, '\\\"')
- .replace(/\uF004/g, '\\{')
- .replace(/\uF005/g, '\\}');
- }
-
- var i = 0; // The index of the current character
- var start = 0; // Where did this section start?
- var prefix = ''; // Stuff that comes before the current argument
- var args = []; // The array that we're creating
- var blockDepth = 0; // For JS with nested {}
-
- // This is just a state machine. We're going through the string char by char
- // The 'mode' is one of the 'In' states. As we go, we're adding Arguments
- // to the 'args' array.
-
- while (true) {
- var c = typed[i];
- var str;
- switch (mode) {
- case In.WHITESPACE:
- if (c === '\'') {
- prefix = typed.substring(start, i + 1);
- mode = In.SINGLE_Q;
- start = i + 1;
- }
- else if (c === '"') {
- prefix = typed.substring(start, i + 1);
- mode = In.DOUBLE_Q;
- start = i + 1;
- }
- else if (c === '{') {
- prefix = typed.substring(start, i + 1);
- mode = In.SCRIPT;
- blockDepth++;
- start = i + 1;
- }
- else if (/ /.test(c)) {
- // Still whitespace, do nothing
- }
- else {
- prefix = typed.substring(start, i);
- mode = In.SIMPLE;
- start = i;
- }
- break;
-
- case In.SIMPLE:
- // There is an edge case of xx'xx which we are assuming to
- // be a single parameter (and same with ")
- if (c === ' ') {
- str = unescape2(typed.substring(start, i));
- args.push(new Argument(str, prefix, ''));
- mode = In.WHITESPACE;
- start = i;
- prefix = '';
- }
- break;
-
- case In.SINGLE_Q:
- if (c === '\'') {
- str = unescape2(typed.substring(start, i));
- args.push(new Argument(str, prefix, c));
- mode = In.WHITESPACE;
- start = i + 1;
- prefix = '';
- }
- break;
-
- case In.DOUBLE_Q:
- if (c === '"') {
- str = unescape2(typed.substring(start, i));
- args.push(new Argument(str, prefix, c));
- mode = In.WHITESPACE;
- start = i + 1;
- prefix = '';
- }
- break;
-
- case In.SCRIPT:
- if (c === '{') {
- blockDepth++;
- }
- else if (c === '}') {
- blockDepth--;
- if (blockDepth === 0) {
- str = unescape2(typed.substring(start, i));
- args.push(new ScriptArgument(str, prefix, c));
- mode = In.WHITESPACE;
- start = i + 1;
- prefix = '';
- }
- }
- break;
- }
-
- i++;
-
- if (i >= typed.length) {
- // There is nothing else to read - tidy up
- if (mode === In.WHITESPACE) {
- if (i !== start) {
- // There's whitespace at the end of the typed string. Add it to the
- // last argument's suffix, creating an empty argument if needed.
- var extra = typed.substring(start, i);
- var lastArg = args[args.length - 1];
- if (!lastArg) {
- args.push(new Argument('', extra, ''));
- }
- else {
- lastArg.suffix += extra;
- }
- }
- }
- else if (mode === In.SCRIPT) {
- str = unescape2(typed.substring(start, i + 1));
- args.push(new ScriptArgument(str, prefix, ''));
- }
- else {
- str = unescape2(typed.substring(start, i + 1));
- args.push(new Argument(str, prefix, ''));
- }
- break;
- }
- }
-
- return args;
-};
-
-/**
- * If the input has no spaces, quotes, braces or escapes,
- * we can take the fast track.
- */
-function isSimple(typed) {
- for (var i = 0; i < typed.length; i++) {
- var c = typed.charAt(i);
- if (c === ' ' || c === '"' || c === '\'' ||
- c === '{' || c === '}' || c === '\\') {
- return false;
- }
- }
- return true;
-}
-
-/**
- * Looks in the commands for a command extension that matches what has been
- * typed at the command line.
- */
-Requisition.prototype._split = function(args) {
- // Handle the special case of the user typing { javascript(); }
- // We use the hidden 'eval' command directly rather than shift()ing one of
- // the parameters, and parse()ing it.
- var conversion;
- if (args[0].type === 'ScriptArgument') {
- // Special case: if the user enters { console.log('foo'); } then we need to
- // use the hidden 'eval' command
- var command = this.system.commands.get(evalCmd.name);
- conversion = new Conversion(command, new ScriptArgument());
- this._setAssignmentInternal(this.commandAssignment, conversion);
- return;
- }
-
- var argsUsed = 1;
-
- while (argsUsed <= args.length) {
- var arg = (argsUsed === 1) ?
- args[0] :
- new MergedArgument(args, 0, argsUsed);
-
- if (this.prefix != null && this.prefix !== '') {
- var prefixArg = new Argument(this.prefix, '', ' ');
- var prefixedArg = new MergedArgument([ prefixArg, arg ]);
-
- conversion = commandModule.parse(this.executionContext, prefixedArg, false);
- if (conversion.value == null) {
- conversion = commandModule.parse(this.executionContext, arg, false);
- }
- }
- else {
- conversion = commandModule.parse(this.executionContext, arg, false);
- }
-
- // We only want to carry on if this command is a parent command,
- // which means that there is a commandAssignment, but not one with
- // an exec function.
- if (!conversion.value || conversion.value.exec) {
- break;
- }
-
- // Previously we needed a way to hide commands depending context.
- // We have not resurrected that feature yet, but if we do we should
- // insert code here to ignore certain commands depending on the
- // context/environment
-
- argsUsed++;
- }
-
- // This could probably be re-written to consume args as we go
- for (var i = 0; i < argsUsed; i++) {
- args.shift();
- }
-
- this._setAssignmentInternal(this.commandAssignment, conversion);
-};
-
-/**
- * Add all the passed args to the list of unassigned assignments.
- */
-Requisition.prototype._addUnassignedArgs = function(args) {
- args.forEach(arg => {
- this._unassigned.push(new UnassignedAssignment(this, arg));
- });
-
- return RESOLVED;
-};
-
-/**
- * Work out which arguments are applicable to which parameters.
- */
-Requisition.prototype._assign = function(args) {
- // See comment in _split. Avoid multiple updates
- var noArgUp = { internal: true };
-
- this._unassigned = [];
-
- if (!this.commandAssignment.value) {
- return this._addUnassignedArgs(args);
- }
-
- if (args.length === 0) {
- this._setBlankArguments();
- return RESOLVED;
- }
-
- // Create an error if the command does not take parameters, but we have
- // been given them ...
- if (this.assignmentCount === 0) {
- return this._addUnassignedArgs(args);
- }
-
- // Special case: if there is only 1 parameter, and that's of type
- // text, then we put all the params into the first param
- if (this.assignmentCount === 1) {
- var assignment = this.getAssignment(0);
- if (assignment.param.type.name === 'string') {
- var arg = (args.length === 1) ? args[0] : new MergedArgument(args);
- return this.setAssignment(assignment, arg, noArgUp);
- }
- }
-
- // Positional arguments can still be specified by name, but if they are
- // then we need to ignore them when working them out positionally
- var unassignedParams = this.getParameterNames();
-
- // We collect the arguments used in arrays here before assigning
- var arrayArgs = {};
-
- // Extract all the named parameters
- var assignments = this.getAssignments(false);
- var namedDone = util.promiseEach(assignments, function(assignment) {
- // Loop over the arguments
- // Using while rather than loop because we remove args as we go
- var i = 0;
- while (i < args.length) {
- if (!assignment.param.isKnownAs(args[i].text)) {
- // Skip this parameter and handle as a positional parameter
- i++;
- continue;
- }
-
- var arg = args.splice(i, 1)[0];
- /* jshint loopfunc:true */
- unassignedParams = unassignedParams.filter(function(test) {
- return test !== assignment.param.name;
- });
-
- // boolean parameters don't have values, default to false
- if (assignment.param.type.name === 'boolean') {
- arg = new TrueNamedArgument(arg);
- }
- else {
- var valueArg = null;
- if (i + 1 <= args.length) {
- valueArg = args.splice(i, 1)[0];
- }
- arg = new NamedArgument(arg, valueArg);
- }
-
- if (assignment.param.type.name === 'array') {
- var arrayArg = arrayArgs[assignment.param.name];
- if (!arrayArg) {
- arrayArg = new ArrayArgument();
- arrayArgs[assignment.param.name] = arrayArg;
- }
- arrayArg.addArgument(arg);
- return RESOLVED;
- }
- else {
- if (assignment.arg.type === 'BlankArgument') {
- return this.setAssignment(assignment, arg, noArgUp);
- }
- else {
- return this._addUnassignedArgs(arg.getArgs());
- }
- }
- }
- }, this);
-
- // What's left are positional parameters: assign in order
- var positionalDone = namedDone.then(() => {
- return util.promiseEach(unassignedParams, function(name) {
- var assignment = this.getAssignment(name);
-
- // If not set positionally, and we can't set it non-positionally,
- // we have to default it to prevent previous values surviving
- if (!assignment.param.isPositionalAllowed) {
- this._setBlankAssignment(assignment);
- return RESOLVED;
- }
-
- // If this is a positional array argument, then it swallows the
- // rest of the arguments.
- if (assignment.param.type.name === 'array') {
- var arrayArg = arrayArgs[assignment.param.name];
- if (!arrayArg) {
- arrayArg = new ArrayArgument();
- arrayArgs[assignment.param.name] = arrayArg;
- }
- arrayArg.addArguments(args);
- args = [];
- // The actual assignment to the array parameter is done below
- return RESOLVED;
- }
-
- // Set assignment to defaults if there are no more arguments
- if (args.length === 0) {
- this._setBlankAssignment(assignment);
- return RESOLVED;
- }
-
- var arg = args.splice(0, 1)[0];
- // --foo and -f are named parameters, -4 is a number. So '-' is either
- // the start of a named parameter or a number depending on the context
- var isIncompleteName = assignment.param.type.name === 'number' ?
- /-[-a-zA-Z_]/.test(arg.text) :
- arg.text.charAt(0) === '-';
-
- if (isIncompleteName) {
- this._unassigned.push(new UnassignedAssignment(this, arg));
- return RESOLVED;
- }
- else {
- return this.setAssignment(assignment, arg, noArgUp);
- }
- }, this);
- });
-
- // Now we need to assign the array argument (if any)
- var arrayDone = positionalDone.then(() => {
- return util.promiseEach(Object.keys(arrayArgs), function(name) {
- var assignment = this.getAssignment(name);
- return this.setAssignment(assignment, arrayArgs[name], noArgUp);
- }, this);
- });
-
- // What's left is can't be assigned, but we need to officially unassign them
- return arrayDone.then(() => {
- return this._addUnassignedArgs(args);
- });
-};
-
-/**
- * Entry point for keyboard accelerators or anything else that wants to execute
- * a command.
- * @param options Object describing how the execution should be handled.
- * (optional). Contains some of the following properties:
- * - hidden (boolean, default=false) Should the output be hidden from the
- * commandOutputManager for this requisition
- * - command/args A fast shortcut to executing a known command with a known
- * set of parsed arguments.
- */
-Requisition.prototype.exec = function(options) {
- var command = null;
- var args = null;
- var hidden = false;
-
- if (options) {
- if (options.hidden) {
- hidden = true;
- }
-
- if (options.command != null) {
- // Fast track by looking up the command directly since passed args
- // means there is no command line to parse.
- command = this.system.commands.get(options.command);
- if (!command) {
- console.error('Command not found: ' + options.command);
- }
- args = options.args;
- }
- }
-
- if (!command) {
- command = this.commandAssignment.value;
- args = this.getArgsObject();
- }
-
- // Display JavaScript input without the initial { or closing }
- var typed = this.toString();
- if (evalCmd.isCommandRegexp.test(typed)) {
- typed = typed.replace(evalCmd.isCommandRegexp, '');
- // Bug 717763: What if the JavaScript naturally ends with a }?
- typed = typed.replace(/\s*}\s*$/, '');
- }
-
- var output = new Output({
- command: command,
- args: args,
- typed: typed,
- canonical: this.toCanonicalString(),
- hidden: hidden
- });
-
- this.commandOutputManager.onOutput({ output: output });
-
- var onDone = function(data) {
- output.complete(data, false);
- return output;
- };
-
- var onError = function(data, ex) {
- if (logErrors) {
- if (ex != null) {
- util.errorHandler(ex);
- }
- else {
- console.error(data);
- }
- }
-
- if (data != null && typeof data === 'string') {
- data = data.replace(/^Protocol error: /, ''); // Temp fix for bug 1035296
- }
-
- data = (data != null && data.isTypedData) ? data : {
- isTypedData: true,
- data: data,
- type: 'error'
- };
- output.complete(data, true);
- return output;
- };
-
- if (this.status !== Status.VALID) {
- var ex = new Error(this.getStatusMessage());
- // We only reject a call to exec if GCLI breaks. Errors with commands are
- // exposed in the 'error' status of the Output object
- return Promise.resolve(onError(ex)).then(output => {
- this.clear();
- return output;
- });
- }
- else {
- try {
- return host.exec(() => {
- return command.exec(args, this.executionContext);
- }).then(onDone, onError);
- }
- catch (ex) {
- var data = (typeof ex.message === 'string' && ex.stack != null) ?
- ex.message : ex;
- return Promise.resolve(onError(data, ex));
- }
- finally {
- this.clear();
- }
- }
-};
-
-/**
- * Designed to be called from context.updateExec(). Acts just like updateExec()
- * except that it also calls onExternalUpdate() to inform the UI of an
- * unexpected change to the current command.
- */
-Requisition.prototype._contextUpdateExec = function(typed, options) {
- var reqOpts = {
- document: this.document,
- environment: this.environment
- };
- var child = new Requisition(this.system, reqOpts);
- return child.updateExec(typed, options).then(function(reply) {
- child.destroy();
- return reply;
- }.bind(child));
-};
-
-/**
- * A shortcut for calling update, resolving the promise and then exec.
- * @param input The string to execute
- * @param options Passed to exec
- * @return A promise of an output object
- */
-Requisition.prototype.updateExec = function(input, options) {
- return this.update(input).then(() => {
- return this.exec(options);
- });
-};
-
-exports.Requisition = Requisition;
-
-/**
- * A simple object to hold information about the output of a command
- */
-function Output(options) {
- options = options || {};
- this.command = options.command || '';
- this.args = options.args || {};
- this.typed = options.typed || '';
- this.canonical = options.canonical || '';
- this.hidden = options.hidden === true ? true : false;
-
- this.type = undefined;
- this.data = undefined;
- this.completed = false;
- this.error = false;
- this.start = new Date();
-
- this.promise = new Promise((resolve, reject) => {
- this._resolve = resolve;
- });
-}
-
-/**
- * Called when there is data to display, and the command has finished executing
- * See changed() for details on parameters.
- */
-Output.prototype.complete = function(data, error) {
- this.end = new Date();
- this.completed = true;
- this.error = error;
-
- if (data != null && data.isTypedData) {
- this.data = data.data;
- this.type = data.type;
- }
- else {
- this.data = data;
- this.type = this.command.returnType;
- if (this.type == null) {
- this.type = (this.data == null) ? 'undefined' : typeof this.data;
- }
- }
-
- if (this.type === 'object') {
- throw new Error('No type from output of ' + this.typed);
- }
-
- this._resolve();
-};
-
-/**
- * Call converters.convert using the data in this Output object
- */
-Output.prototype.convert = function(type, conversionContext) {
- var converters = conversionContext.system.converters;
- return converters.convert(this.data, this.type, type, conversionContext);
-};
-
-Output.prototype.toJson = function() {
- // Exceptions don't stringify, so we try a bit harder
- var data = this.data;
- if (this.error && JSON.stringify(this.data) === '{}') {
- data = {
- columnNumber: data.columnNumber,
- fileName: data.fileName,
- lineNumber: data.lineNumber,
- message: data.message,
- stack: data.stack
- };
- }
-
- return {
- typed: this.typed,
- type: this.type,
- data: data,
- isError: this.error
- };
-};
-
-exports.Output = Output;
diff --git a/devtools/shared/gcli/source/lib/gcli/commands/clear.js b/devtools/shared/gcli/source/lib/gcli/commands/clear.js
deleted file mode 100644
index 8f932702116e..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/commands/clear.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-
-exports.items = [
- {
- // A command to clear the output area
- item: 'command',
- runAt: 'client',
- name: 'clear',
- description: l10n.lookup('clearDesc'),
- returnType: 'clearoutput',
- exec: function(args, context) { }
- },
- {
- item: 'converter',
- from: 'clearoutput',
- to: 'view',
- exec: function(ignore, conversionContext) {
- return {
- html: '',
- data: {
- onload: function(ev) {
- // element starts off being the span above, and we walk up the
- // tree looking for the terminal
- var element = ev.target;
- while (element != null && element.terminal == null) {
- element = element.parentElement;
- }
-
- if (element == null) {
- // This is only an event handler on a completed command
- // So we're relying on this showing up in the console
- throw new Error('Failed to find clear');
- }
-
- element.terminal.clear();
- }
- }
- };
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/commands/commands.js b/devtools/shared/gcli/source/lib/gcli/commands/commands.js
deleted file mode 100644
index ad7b22fc72c2..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/commands/commands.js
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var l10n = require('../util/l10n');
-
-/**
- * Implement the localization algorithm for any documentation objects (i.e.
- * description and manual) in a command.
- * @param data The data assigned to a description or manual property
- * @param onUndefined If data == null, should we return the data untouched or
- * lookup a 'we don't know' key in it's place.
- */
-function lookup(data, onUndefined) {
- if (data == null) {
- if (onUndefined) {
- return l10n.lookup(onUndefined);
- }
-
- return data;
- }
-
- if (typeof data === 'string') {
- return data;
- }
-
- if (typeof data === 'object') {
- if (data.key) {
- return l10n.lookup(data.key);
- }
-
- var locales = l10n.getPreferredLocales();
- var translated;
- locales.some(function(locale) {
- translated = data[locale];
- return translated != null;
- });
- if (translated != null) {
- return translated;
- }
-
- console.error('Can\'t find locale in descriptions: ' +
- 'locales=' + JSON.stringify(locales) + ', ' +
- 'description=' + JSON.stringify(data));
- return '(No description)';
- }
-
- return l10n.lookup(onUndefined);
-}
-
-
-/**
- * The command object is mostly just setup around a commandSpec (as passed to
- * Commands.add()).
- */
-function Command(types, commandSpec) {
- Object.keys(commandSpec).forEach(function(key) {
- this[key] = commandSpec[key];
- }, this);
-
- if (!this.name) {
- throw new Error('All registered commands must have a name');
- }
-
- if (this.params == null) {
- this.params = [];
- }
- if (!Array.isArray(this.params)) {
- throw new Error('command.params must be an array in ' + this.name);
- }
-
- this.hasNamedParameters = false;
- this.description = 'description' in this ? this.description : undefined;
- this.description = lookup(this.description, 'canonDescNone');
- this.manual = 'manual' in this ? this.manual : undefined;
- this.manual = lookup(this.manual);
-
- // At this point this.params has nested param groups. We want to flatten it
- // out and replace the param object literals with Parameter objects
- var paramSpecs = this.params;
- this.params = [];
- this.paramGroups = {};
- this._shortParams = {};
-
- var addParam = param => {
- var groupName = param.groupName || l10n.lookup('canonDefaultGroupName');
- this.params.push(param);
- if (!this.paramGroups.hasOwnProperty(groupName)) {
- this.paramGroups[groupName] = [];
- }
- this.paramGroups[groupName].push(param);
- };
-
- // Track if the user is trying to mix default params and param groups.
- // All the non-grouped parameters must come before all the param groups
- // because non-grouped parameters can be assigned positionally, so their
- // index is important. We don't want 'holes' in the order caused by
- // parameter groups.
- var usingGroups = false;
-
- // In theory this could easily be made recursive, so param groups could
- // contain nested param groups. Current thinking is that the added
- // complexity for the UI probably isn't worth it, so this implementation
- // prevents nesting.
- paramSpecs.forEach(function(spec) {
- if (!spec.group) {
- var param = new Parameter(types, spec, this, null);
- addParam(param);
-
- if (!param.isPositionalAllowed) {
- this.hasNamedParameters = true;
- }
-
- if (usingGroups && param.groupName == null) {
- throw new Error('Parameters can\'t come after param groups.' +
- ' Ignoring ' + this.name + '/' + spec.name);
- }
-
- if (param.groupName != null) {
- usingGroups = true;
- }
- }
- else {
- spec.params.forEach(function(ispec) {
- var param = new Parameter(types, ispec, this, spec.group);
- addParam(param);
-
- if (!param.isPositionalAllowed) {
- this.hasNamedParameters = true;
- }
- }, this);
-
- usingGroups = true;
- }
- }, this);
-
- this.params.forEach(function(param) {
- if (param.short != null) {
- if (this._shortParams[param.short] != null) {
- throw new Error('Multiple params using short name ' + param.short);
- }
- this._shortParams[param.short] = param;
- }
- }, this);
-}
-
-/**
- * JSON serializer that avoids non-serializable data
- * @param customProps Array of strings containing additional properties which,
- * if specified in the command spec, will be included in the JSON. Normally we
- * transfer only the properties required for GCLI to function.
- */
-Command.prototype.toJson = function(customProps) {
- var json = {
- item: 'command',
- name: this.name,
- params: this.params.map(function(param) { return param.toJson(); }),
- returnType: this.returnType,
- isParent: (this.exec == null)
- };
-
- if (this.description !== l10n.lookup('canonDescNone')) {
- json.description = this.description;
- }
- if (this.manual != null) {
- json.manual = this.manual;
- }
- if (this.hidden != null) {
- json.hidden = this.hidden;
- }
-
- if (Array.isArray(customProps)) {
- customProps.forEach(prop => {
- if (this[prop] != null) {
- json[prop] = this[prop];
- }
- });
- }
-
- return json;
-};
-
-/**
- * Easy way to lookup parameters by full name
- */
-Command.prototype.getParameterByName = function(name) {
- var reply;
- this.params.forEach(function(param) {
- if (param.name === name) {
- reply = param;
- }
- });
- return reply;
-};
-
-/**
- * Easy way to lookup parameters by short name
- */
-Command.prototype.getParameterByShortName = function(short) {
- return this._shortParams[short];
-};
-
-exports.Command = Command;
-
-
-/**
- * A wrapper for a paramSpec so we can sort out shortened versions names for
- * option switches
- */
-function Parameter(types, paramSpec, command, groupName) {
- this.command = command || { name: 'unnamed' };
- this.paramSpec = paramSpec;
- this.name = this.paramSpec.name;
- this.type = this.paramSpec.type;
- this.short = this.paramSpec.short;
-
- if (this.short != null && !/[0-9A-Za-z]/.test(this.short)) {
- throw new Error('\'short\' value must be a single alphanumeric digit.');
- }
-
- this.groupName = groupName;
- if (this.groupName != null) {
- if (this.paramSpec.option != null) {
- throw new Error('Can\'t have a "option" property in a nested parameter');
- }
- }
- else {
- if (this.paramSpec.option != null) {
- this.groupName = (this.paramSpec.option === true) ?
- l10n.lookup('canonDefaultGroupName') :
- '' + this.paramSpec.option;
- }
- }
-
- if (!this.name) {
- throw new Error('In ' + this.command.name +
- ': all params must have a name');
- }
-
- var typeSpec = this.type;
- this.type = types.createType(typeSpec);
- if (this.type == null) {
- console.error('Known types: ' + types.getTypeNames().join(', '));
- throw new Error('In ' + this.command.name + '/' + this.name +
- ': can\'t find type for: ' + JSON.stringify(typeSpec));
- }
-
- // boolean parameters have an implicit defaultValue:false, which should
- // not be changed. See the docs.
- if (this.type.name === 'boolean' &&
- this.paramSpec.defaultValue !== undefined) {
- throw new Error('In ' + this.command.name + '/' + this.name +
- ': boolean parameters can not have a defaultValue.' +
- ' Ignoring');
- }
-
- // All parameters that can only be set via a named parameter must have a
- // non-undefined default value
- if (!this.isPositionalAllowed && this.paramSpec.defaultValue === undefined &&
- this.type.getBlank == null && this.type.name !== 'boolean') {
- throw new Error('In ' + this.command.name + '/' + this.name +
- ': Missing defaultValue for optional parameter.');
- }
-
- if (this.paramSpec.defaultValue !== undefined) {
- this.defaultValue = this.paramSpec.defaultValue;
- }
- else {
- Object.defineProperty(this, 'defaultValue', {
- get: function() {
- return this.type.getBlank().value;
- },
- enumerable: true
- });
- }
-
- // Resolve the documentation
- this.manual = lookup(this.paramSpec.manual);
- this.description = lookup(this.paramSpec.description, 'canonDescNone');
-
- // Is the user required to enter data for this parameter? (i.e. has
- // defaultValue been set to something other than undefined)
- // TODO: When the defaultValue comes from type.getBlank().value (see above)
- // then perhaps we should set using something like
- // isDataRequired = (type.getBlank().status !== VALID)
- this.isDataRequired = (this.defaultValue === undefined);
-
- // Are we allowed to assign data to this parameter using positional
- // parameters?
- this.isPositionalAllowed = this.groupName == null;
-}
-
-/**
- * Does the given name uniquely identify this param (among the other params
- * in this command)
- * @param name The name to check
- */
-Parameter.prototype.isKnownAs = function(name) {
- return (name === '--' + this.name) || (name === '-' + this.short);
-};
-
-/**
- * Reflect the paramSpec 'hidden' property (dynamically so it can change)
- */
-Object.defineProperty(Parameter.prototype, 'hidden', {
- get: function() {
- return this.paramSpec.hidden;
- },
- enumerable: true
-});
-
-/**
- * JSON serializer that avoids non-serializable data
- */
-Parameter.prototype.toJson = function() {
- var json = {
- name: this.name,
- type: this.type.getSpec(this.command.name, this.name),
- short: this.short
- };
-
- // Values do not need to be serializable, so we don't try. For the client
- // side (which doesn't do any executing) we only care whether default value is
- // undefined, null, or something else.
- if (this.paramSpec.defaultValue !== undefined) {
- json.defaultValue = (this.paramSpec.defaultValue === null) ? null : {};
- }
- if (this.paramSpec.description != null) {
- json.description = this.paramSpec.description;
- }
- if (this.paramSpec.manual != null) {
- json.manual = this.paramSpec.manual;
- }
- if (this.paramSpec.hidden != null) {
- json.hidden = this.paramSpec.hidden;
- }
-
- // groupName can be set outside a paramSpec, (e.g. in grouped parameters)
- // but it works like 'option' does so we use 'option' for groupNames
- if (this.groupName != null || this.paramSpec.option != null) {
- json.option = this.groupName || this.paramSpec.option;
- }
-
- return json;
-};
-
-exports.Parameter = Parameter;
-
-
-/**
- * A store for a list of commands
- * @param types Each command uses a set of Types to parse its parameters so the
- * Commands container needs access to the list of available types.
- * @param location String that, if set will force all commands to have a
- * matching runAt property to be accepted
- */
-function Commands(types, location) {
- this.types = types;
- this.location = location;
-
- // A lookup hash of our registered commands
- this._commands = {};
- // A sorted list of command names, we regularly want them in order, so pre-sort
- this._commandNames = [];
- // A lookup of the original commandSpecs by command name
- this._commandSpecs = {};
-
- // Enable people to be notified of changes to the list of commands
- this.onCommandsChange = util.createEvent('commands.onCommandsChange');
-}
-
-/**
- * Add a command to the list of known commands.
- * @param commandSpec The command and its metadata.
- * @return The new command, or null if a location property has been set and the
- * commandSpec doesn't have a matching runAt property.
- */
-Commands.prototype.add = function(commandSpec) {
- if (this.location != null && commandSpec.runAt != null &&
- commandSpec.runAt !== this.location) {
- return;
- }
-
- if (this._commands[commandSpec.name] != null) {
- // Roughly commands.remove() without the event call, which we do later
- delete this._commands[commandSpec.name];
- this._commandNames = this._commandNames.filter(function(test) {
- return test !== commandSpec.name;
- });
- }
-
- var command = new Command(this.types, commandSpec);
- this._commands[commandSpec.name] = command;
- this._commandNames.push(commandSpec.name);
- this._commandNames.sort();
-
- this._commandSpecs[commandSpec.name] = commandSpec;
-
- this.onCommandsChange();
- return command;
-};
-
-/**
- * Remove an individual command. The opposite of Commands.add().
- * Removing a non-existent command is a no-op.
- * @param commandOrName Either a command name or the command itself.
- * @return true if a command was removed, false otherwise.
- */
-Commands.prototype.remove = function(commandOrName) {
- var name = typeof commandOrName === 'string' ?
- commandOrName :
- commandOrName.name;
-
- if (!this._commands[name]) {
- return false;
- }
-
- // See start of commands.add if changing this code
- delete this._commands[name];
- delete this._commandSpecs[name];
- this._commandNames = this._commandNames.filter(function(test) {
- return test !== name;
- });
-
- this.onCommandsChange();
- return true;
-};
-
-/**
- * Retrieve a command by name
- * @param name The name of the command to retrieve
- */
-Commands.prototype.get = function(name) {
- // '|| undefined' is to silence 'reference to undefined property' warnings
- return this._commands[name] || undefined;
-};
-
-/**
- * Get an array of all the registered commands.
- */
-Commands.prototype.getAll = function() {
- return Object.keys(this._commands).map(function(name) {
- return this._commands[name];
- }, this);
-};
-
-/**
- * Get access to the stored commandMetaDatas (i.e. before they were made into
- * instances of Command/Parameters) so we can remote them.
- * @param customProps Array of strings containing additional properties which,
- * if specified in the command spec, will be included in the JSON. Normally we
- * transfer only the properties required for GCLI to function.
- */
-Commands.prototype.getCommandSpecs = function(customProps) {
- var commandSpecs = [];
-
- Object.keys(this._commands).forEach(name => {
- var command = this._commands[name];
- if (!command.noRemote) {
- commandSpecs.push(command.toJson(customProps));
- }
- });
-
- return commandSpecs;
-};
-
-/**
- * Add a set of commands that are executed somewhere else, optionally with a
- * command prefix to distinguish these commands from a local set of commands.
- * @param commandSpecs Presumably as obtained from getCommandSpecs
- * @param remoter Function to call on exec of a new remote command. This is
- * defined just like an exec function (i.e. that takes args/context as params
- * and returns a promise) with one extra feature, that the context includes a
- * 'commandName' property that contains the original command name.
- * @param prefix The name prefix that we assign to all command names
- * @param to URL-like string that describes where the commands are executed.
- * This is to complete the parent command description.
- */
-Commands.prototype.addProxyCommands = function(commandSpecs, remoter, prefix, to) {
- if (prefix != null) {
- if (this._commands[prefix] != null) {
- throw new Error(l10n.lookupFormat('canonProxyExists', [ prefix ]));
- }
-
- // We need to add the parent command so all the commands from the other
- // system have a parent
- this.add({
- name: prefix,
- isProxy: true,
- description: l10n.lookupFormat('canonProxyDesc', [ to ]),
- manual: l10n.lookupFormat('canonProxyManual', [ to ])
- });
- }
-
- commandSpecs.forEach(commandSpec => {
- var originalName = commandSpec.name;
- if (!commandSpec.isParent) {
- commandSpec.exec = (args, context) => {
- context.commandName = originalName;
- return remoter(args, context);
- };
- }
-
- if (prefix != null) {
- commandSpec.name = prefix + ' ' + commandSpec.name;
- }
- commandSpec.isProxy = true;
- this.add(commandSpec);
- });
-};
-
-/**
- * Remove a set of commands added with addProxyCommands.
- * @param prefix The name prefix that we assign to all command names
- */
-Commands.prototype.removeProxyCommands = function(prefix) {
- var toRemove = [];
- Object.keys(this._commandSpecs).forEach(name => {
- if (name.indexOf(prefix) === 0) {
- toRemove.push(name);
- }
- });
-
- var removed = [];
- toRemove.forEach(name => {
- var command = this.get(name);
- if (command.isProxy) {
- this.remove(name);
- removed.push(name);
- }
- else {
- console.error('Skipping removal of \'' + name +
- '\' because it is not a proxy command.');
- }
- });
-
- return removed;
-};
-
-exports.Commands = Commands;
-
-/**
- * CommandOutputManager stores the output objects generated by executed
- * commands.
- *
- * CommandOutputManager is exposed to the the outside world and could (but
- * shouldn't) be used before gcli.startup() has been called.
- * This could should be defensive to that where possible, and we should
- * certainly document if the use of it or similar will fail if used too soon.
- */
-function CommandOutputManager() {
- this.onOutput = util.createEvent('CommandOutputManager.onOutput');
-}
-
-exports.CommandOutputManager = CommandOutputManager;
diff --git a/devtools/shared/gcli/source/lib/gcli/commands/context.js b/devtools/shared/gcli/source/lib/gcli/commands/context.js
deleted file mode 100644
index ad1f87ee818c..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/commands/context.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var cli = require('../cli');
-
-/**
- * 'context' command
- */
-var context = {
- item: 'command',
- name: 'context',
- description: l10n.lookup('contextDesc'),
- manual: l10n.lookup('contextManual'),
- params: [
- {
- name: 'prefix',
- type: 'command',
- description: l10n.lookup('contextPrefixDesc'),
- defaultValue: null
- }
- ],
- returnType: 'string',
- // The context command is client only because it's essentially sugar for
- // typing commands. When there is a command prefix in action, it is the job
- // of the remoter to add the prefix to the typed strings that are sent for
- // remote execution
- noRemote: true,
- exec: function echo(args, context) {
- var requisition = cli.getMapping(context).requisition;
-
- if (args.prefix == null) {
- requisition.prefix = null;
- return l10n.lookup('contextEmptyReply');
- }
-
- if (args.prefix.exec != null) {
- throw new Error(l10n.lookupFormat('contextNotParentError',
- [ args.prefix.name ]));
- }
-
- requisition.prefix = args.prefix.name;
- return l10n.lookupFormat('contextReply', [ args.prefix.name ]);
- }
-};
-
-exports.items = [ context ];
diff --git a/devtools/shared/gcli/source/lib/gcli/commands/help.js b/devtools/shared/gcli/source/lib/gcli/commands/help.js
deleted file mode 100644
index cc83c7cbca41..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/commands/help.js
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var cli = require('../cli');
-
-/**
- * Add an 'paramGroups' accessor to a command metadata object to sort the
- * params into groups according to the option of the param.
- */
-function addParamGroups(command) {
- Object.defineProperty(command, 'paramGroups', {
- get: function() {
- var paramGroups = {};
- this.params.forEach(function(param) {
- var groupName = param.option || l10n.lookup('canonDefaultGroupName');
- if (paramGroups[groupName] == null) {
- paramGroups[groupName] = [];
- }
- paramGroups[groupName].push(param);
- });
- return paramGroups;
- },
- enumerable: true
- });
-}
-
-/**
- * Get a data block for the help_man.html/help_man.txt templates
- */
-function getHelpManData(commandData, context) {
- // Filter out hidden parameters
- commandData.command.params = commandData.command.params.filter(
- param => !param.hidden
- );
-
- addParamGroups(commandData.command);
- commandData.subcommands.forEach(addParamGroups);
-
- return {
- l10n: l10n.propertyLookup,
- onclick: context.update,
- ondblclick: context.updateExec,
- describe: function(item) {
- return item.manual || item.description;
- },
- getTypeDescription: function(param) {
- var input = '';
- if (param.defaultValue === undefined) {
- input = l10n.lookup('helpManRequired');
- }
- else if (param.defaultValue === null) {
- input = l10n.lookup('helpManOptional');
- }
- else {
- // We need defaultText to work the text version of defaultValue
- input = l10n.lookup('helpManOptional');
- /*
- var val = param.type.stringify(param.defaultValue);
- input = Promise.resolve(val).then(function(defaultValue) {
- return l10n.lookupFormat('helpManDefault', [ defaultValue ]);
- }.bind(this));
- */
- }
-
- return Promise.resolve(input).then(defaultDescr => {
- return '(' + (param.type.name || param.type) + ', ' + defaultDescr + ')';
- });
- },
- getSynopsis: function(param) {
- var name = param.name + (param.short ? '|-' + param.short : '');
- if (param.option == null) {
- return param.defaultValue !== undefined ?
- '[' + name + ']' :
- '<' + name + '>';
- }
- else {
- return param.type === 'boolean' || param.type.name === 'boolean' ?
- '[--' + name + ']' :
- '[--' + name + ' ...]';
- }
- },
- command: commandData.command,
- subcommands: commandData.subcommands
- };
-}
-
-/**
- * Get a data block for the help_list.html/help_list.txt templates
- */
-function getHelpListData(commandsData, context) {
- commandsData.commands.forEach(addParamGroups);
-
- var heading;
- if (commandsData.commands.length === 0) {
- heading = l10n.lookupFormat('helpListNone', [ commandsData.prefix ]);
- }
- else if (commandsData.prefix == null) {
- heading = l10n.lookup('helpListAll');
- }
- else {
- heading = l10n.lookupFormat('helpListPrefix', [ commandsData.prefix ]);
- }
-
- return {
- l10n: l10n.propertyLookup,
- includeIntro: commandsData.prefix == null,
- heading: heading,
- onclick: context.update,
- ondblclick: context.updateExec,
- matchingCommands: commandsData.commands
- };
-}
-
-/**
- * Create a block of data suitable to be passed to the help_list.html template
- */
-function getMatchingCommands(context, prefix) {
- var commands = cli.getMapping(context).requisition.system.commands;
- var reply = commands.getAll().filter(function(command) {
- if (command.hidden) {
- return false;
- }
-
- if (prefix && command.name.indexOf(prefix) !== 0) {
- // Filtered out because they don't match the search
- return false;
- }
- if (!prefix && command.name.includes(' ')) {
- // We don't show sub commands with plain 'help'
- return false;
- }
- return true;
- });
-
- reply.sort(function(c1, c2) {
- return c1.name.localeCompare(c2.name);
- });
-
- reply = reply.map(function(command) {
- return command.toJson();
- });
-
- return reply;
-}
-
-/**
- * Find all the sub commands of the given command
- */
-function getSubCommands(context, command) {
- var commands = cli.getMapping(context).requisition.system.commands;
- var subcommands = commands.getAll().filter(function(subcommand) {
- return subcommand.name.indexOf(command.name) === 0 &&
- subcommand.name !== command.name &&
- !subcommand.hidden;
- });
-
- subcommands.sort(function(c1, c2) {
- return c1.name.localeCompare(c2.name);
- });
-
- subcommands = subcommands.map(function(subcommand) {
- return subcommand.toJson();
- });
-
- return subcommands;
-}
-
-var helpCss = '' +
- '.gcli-help-name {\n' +
- ' text-align: end;\n' +
- '}\n' +
- '\n' +
- '.gcli-help-arrow {\n' +
- ' color: #AAA;\n' +
- '}\n' +
- '\n' +
- '.gcli-help-description {\n' +
- ' margin: 0 20px;\n' +
- ' padding: 0;\n' +
- '}\n' +
- '\n' +
- '.gcli-help-parameter {\n' +
- ' margin: 0 30px;\n' +
- ' padding: 0;\n' +
- '}\n' +
- '\n' +
- '.gcli-help-header {\n' +
- ' margin: 10px 0 6px;\n' +
- '}\n';
-
-exports.items = [
- {
- // 'help' command
- item: 'command',
- name: 'help',
- runAt: 'client',
- description: l10n.lookup('helpDesc'),
- manual: l10n.lookup('helpManual'),
- params: [
- {
- name: 'search',
- type: 'string',
- description: l10n.lookup('helpSearchDesc'),
- manual: l10n.lookup('helpSearchManual3'),
- defaultValue: null
- }
- ],
-
- exec: function(args, context) {
- var commands = cli.getMapping(context).requisition.system.commands;
- var command = commands.get(args.search);
- if (command) {
- return context.typedData('commandData', {
- command: command.toJson(),
- subcommands: getSubCommands(context, command)
- });
- }
-
- return context.typedData('commandsData', {
- prefix: args.search,
- commands: getMatchingCommands(context, args.search)
- });
- }
- },
- {
- // Convert a command into an HTML man page
- item: 'converter',
- from: 'commandData',
- to: 'view',
- exec: function(commandData, context) {
- return {
- html:
- '
\n',
- options: { blankNullUndefined: true, stack: 'prefsData#inner' },
- data: this
- });
-
- view.appendTo(table, true);
-};
-
-PrefList.prototype.onFilterChange = function(ev) {
- if (ev.target.value !== this.search) {
- this.search = ev.target.value;
-
- var root = ev.target.parentNode.parentNode;
- var table = root.querySelector('.gcli-pref-list-table');
- this.updateTable(table);
- }
-};
-
-PrefList.prototype.onSetClick = function(ev) {
- var typed = ev.currentTarget.getAttribute('data-command');
- this.conversionContext.update(typed);
-};
-
-exports.items = [ prefsViewConverter, prefsStringConverter, prefList ];
diff --git a/devtools/shared/gcli/source/lib/gcli/commands/test.js b/devtools/shared/gcli/source/lib/gcli/commands/test.js
deleted file mode 100644
index 3ddaf0bba440..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/commands/test.js
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var examiner = require('../testharness/examiner');
-var stati = require('../testharness/status').stati;
-var helpers = require('../test/helpers');
-var suite = require('../test/suite');
-var cli = require('../cli');
-var Requisition = require('../cli').Requisition;
-var createRequisitionAutomator = require('../test/automators/requisition').createRequisitionAutomator;
-
-var isNode = (typeof(process) !== 'undefined' &&
- process.title.includes('node'));
-
-suite.init(isNode);
-
-exports.optionsContainer = [];
-
-exports.items = [
- {
- item: 'type',
- name: 'suite',
- parent: 'selection',
- cacheable: true,
- lookup: function() {
- return Object.keys(examiner.suites).map(function(name) {
- return { name: name, value: examiner.suites[name] };
- });
- }
- },
- {
- item: 'command',
- name: 'test',
- description: 'Run GCLI unit tests',
- params: [
- {
- name: 'suite',
- type: 'suite',
- description: 'Test suite to run.',
- defaultValue: examiner
- },
- {
- name: 'usehost',
- type: 'boolean',
- description: 'Run the unit tests in the host window',
- option: true
- }
- ],
- returnType: 'examiner-output',
- noRemote: true,
- exec: function(args, context) {
- if (args.usehost && exports.optionsContainer.length === 0) {
- throw new Error('Can\'t use --usehost without injected options');
- }
-
- var options;
- if (args.usehost) {
- options = exports.optionsContainer[0];
- }
- else {
- var env = {
- document: document,
- window: window
- };
- options = {
- isNode: isNode,
- isFirefox: false,
- isPhantomjs: false,
- requisition: new Requisition(context.system, { environment: env })
- };
- options.automator = createRequisitionAutomator(options.requisition);
- }
-
- var requisition = options.requisition;
- requisition.system.commands.get('mocks').on(requisition);
- helpers.resetResponseTimes();
- examiner.reset();
-
- return args.suite.run(options).then(function() {
- requisition.system.commands.get('mocks').off(requisition);
- var output = context.typedData('examiner-output', examiner.toRemote());
-
- if (output.data.summary.status === stati.pass) {
- return output;
- }
- else {
- cli.logErrors = false;
- throw output;
- }
- });
- }
- },
- {
- item: 'converter',
- from: 'examiner-output',
- to: 'string',
- exec: function(output, conversionContext) {
- return '\n' + examiner.detailedResultLog('NodeJS/NoDom') +
- '\n' + helpers.timingSummary;
- }
- },
- {
- item: 'converter',
- from: 'examiner-output',
- to: 'view',
- exec: function(output, conversionContext) {
- return {
- html:
- '
\n' +
- '
\n' +
- ' \n' +
- '
\n' +
- '
Suite
\n' +
- '
Test
\n' +
- '
Results
\n' +
- '
Checks
\n' +
- '
Notes
\n' +
- '
\n' +
- ' \n' +
- ' \n' +
- '
\n' +
- '
${suite.name}
\n' +
- '
${test.title}
\n' +
- '
${test.status.name}
\n' +
- '
${test.checks}
\n' +
- '
\n' +
- '
\n' +
- ' ${failure.message}\n' +
- '
\n' +
- '
P1: ${failure.p1}
\n' +
- '
P2: ${failure.p2}
\n' +
- '
\n' +
- '
\n' +
- '
\n' +
- '
\n' +
- ' \n' +
- ' \n' +
- '
\n' +
- '
\n' +
- '
Total
\n' +
- '
${summary.status.name}
\n' +
- '
${summary.checks}
\n' +
- '
\n' +
- '
\n' +
- ' \n' +
- '
\n' +
- '
',
- css:
- '.gcliTestSkipped {\n' +
- ' background-color: #EEE;\n' +
- ' color: #000;\n' +
- '}\n' +
- '\n' +
- '.gcliTestExecuting {\n' +
- ' background-color: #888;\n' +
- ' color: #FFF;\n' +
- '}\n' +
- '\n' +
- '.gcliTestWaiting {\n' +
- ' background-color: #FFA;\n' +
- ' color: #000;\n' +
- '}\n' +
- '\n' +
- '.gcliTestPass {\n' +
- ' background-color: #8F8;\n' +
- ' color: #000;\n' +
- '}\n' +
- '\n' +
- '.gcliTestFail {\n' +
- ' background-color: #F00;\n' +
- ' color: #FFF;\n' +
- '}\n' +
- '\n' +
- 'td.gcliTestSuite {\n' +
- ' font-family: monospace;\n' +
- ' font-size: 90%;\n' +
- ' text-align: right;\n' +
- '}\n' +
- '\n' +
- '.gcliTestResults th.gcliTestSuite,\n' +
- '.gcliTestResults .gcliTestChecks {\n' +
- ' text-align: right;\n' +
- '}\n' +
- '\n' +
- '.gcliTestResults th {\n' +
- ' text-align: left;\n' +
- '}\n' +
- '\n' +
- '.gcliTestMessages ul {\n' +
- ' margin: 0 0 10px;\n' +
- ' padding-left: 20px;\n' +
- ' list-style-type: square;\n' +
- '}\n',
- cssId: 'gcli-test',
- data: output,
- options: { allowEval: true, stack: 'test.html' }
- };
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/connectors/connectors.js b/devtools/shared/gcli/source/lib/gcli/connectors/connectors.js
deleted file mode 100644
index 30d7e4bb8fa8..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/connectors/connectors.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-/**
- * This is how to implement a connector
- * var baseConnector = {
- * item: 'connector',
- * name: 'foo',
- *
- * connect: function(url) {
- * return Promise.resolve(new FooConnection(url));
- * }
- * };
- */
-
-/**
- * A prototype base for Connectors
- */
-function Connection() {
-}
-
-/**
- * Add an event listener
- */
-Connection.prototype.on = function(event, action) {
- if (!this._listeners) {
- this._listeners = {};
- }
- if (!this._listeners[event]) {
- this._listeners[event] = [];
- }
- this._listeners[event].push(action);
-};
-
-/**
- * Remove an event listener
- */
-Connection.prototype.off = function(event, action) {
- if (!this._listeners) {
- return;
- }
- var actions = this._listeners[event];
- if (actions) {
- this._listeners[event] = actions.filter(li => {
- return li !== action;
- });
- }
-};
-
-/**
- * Emit an event. For internal use only
- */
-Connection.prototype._emit = function(event, data) {
- if (this._listeners == null || this._listeners[event] == null) {
- return;
- }
-
- var listeners = this._listeners[event];
- listeners.forEach(listener => {
- // Fail fast if we mutate the list of listeners while emitting
- if (listeners !== this._listeners[event]) {
- throw new Error('Listener list changed while emitting');
- }
-
- try {
- listener.call(null, data);
- }
- catch (ex) {
- console.log('Error calling listeners to ' + event);
- console.error(ex);
- }
- });
-};
-
-/**
- * Send a message to the other side of the connection
- */
-Connection.prototype.call = function(feature, data) {
- throw new Error('Not implemented');
-};
-
-/**
- * Disconnecting a Connection destroys the resources it holds. There is no
- * common route back to being connected once this has been called
- */
-Connection.prototype.disconnect = function() {
- return Promise.resolve();
-};
-
-exports.Connection = Connection;
-
-/**
- * A manager for the registered Connectors
- */
-function Connectors() {
- // This is where we cache the connectors that we know about
- this._registered = {};
-}
-
-/**
- * Add a new connector to the cache
- */
-Connectors.prototype.add = function(connector) {
- this._registered[connector.name] = connector;
-};
-
-/**
- * Remove an existing connector from the cache
- */
-Connectors.prototype.remove = function(connector) {
- var name = typeof connector === 'string' ? connector : connector.name;
- delete this._registered[name];
-};
-
-/**
- * Get access to the list of known connectors
- */
-Connectors.prototype.getAll = function() {
- return Object.keys(this._registered).map(name => {
- return this._registered[name];
- });
-};
-
-var defaultConnectorName;
-
-/**
- * Get access to a connector by name. If name is undefined then first try to
- * use the same connector that we used last time, and if there was no last
- * time, then just use the first registered connector as a default.
- */
-Connectors.prototype.get = function(name) {
- if (name == null) {
- name = (defaultConnectorName == null) ?
- Object.keys(this._registered)[0] :
- defaultConnectorName;
- }
-
- defaultConnectorName = name;
- return this._registered[name];
-};
-
-exports.Connectors = Connectors;
diff --git a/devtools/shared/gcli/source/lib/gcli/connectors/moz.build b/devtools/shared/gcli/source/lib/gcli/connectors/moz.build
deleted file mode 100644
index 33fda8fbc40c..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/connectors/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'connectors.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/converters/basic.js b/devtools/shared/gcli/source/lib/gcli/converters/basic.js
deleted file mode 100644
index 3cb448e9145b..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/converters/basic.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-
-/**
- * Several converters are just data.toString inside a 'p' element
- */
-function nodeFromDataToString(data, conversionContext) {
- var node = util.createElement(conversionContext.document, 'p');
- node.textContent = data.toString();
- return node;
-}
-
-exports.items = [
- {
- item: 'converter',
- from: 'string',
- to: 'dom',
- exec: nodeFromDataToString
- },
- {
- item: 'converter',
- from: 'number',
- to: 'dom',
- exec: nodeFromDataToString
- },
- {
- item: 'converter',
- from: 'boolean',
- to: 'dom',
- exec: nodeFromDataToString
- },
- {
- item: 'converter',
- from: 'undefined',
- to: 'dom',
- exec: function(data, conversionContext) {
- return util.createElement(conversionContext.document, 'span');
- }
- },
- {
- item: 'converter',
- from: 'json',
- to: 'view',
- exec: function(json, context) {
- var html = JSON.stringify(json, null, ' ').replace(/\n/g, ' ');
- return {
- html: '
' + html + '
'
- };
- }
- },
- {
- item: 'converter',
- from: 'number',
- to: 'string',
- exec: function(data) { return '' + data; }
- },
- {
- item: 'converter',
- from: 'boolean',
- to: 'string',
- exec: function(data) { return '' + data; }
- },
- {
- item: 'converter',
- from: 'undefined',
- to: 'string',
- exec: function(data) { return ''; }
- },
- {
- item: 'converter',
- from: 'json',
- to: 'string',
- exec: function(json, conversionContext) {
- return JSON.stringify(json, null, ' ');
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/converters/converters.js b/devtools/shared/gcli/source/lib/gcli/converters/converters.js
deleted file mode 100644
index ea8c74611be3..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/converters/converters.js
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var host = require('../util/host');
-
-// It's probably easiest to read this bottom to top
-
-/**
- * Best guess at creating a DOM element from random data
- */
-var fallbackDomConverter = {
- from: '*',
- to: 'dom',
- exec: function(data, conversionContext) {
- return conversionContext.document.createTextNode(data || '');
- }
-};
-
-/**
- * Best guess at creating a string from random data
- */
-var fallbackStringConverter = {
- from: '*',
- to: 'string',
- exec: function(data, conversionContext) {
- return data == null ? '' : data.toString();
- }
-};
-
-/**
- * Convert a view object to a DOM element
- */
-var viewDomConverter = {
- item: 'converter',
- from: 'view',
- to: 'dom',
- exec: function(view, conversionContext) {
- if (!view.isView) {
- view = conversionContext.createView(view);
- }
- return view.toDom(conversionContext.document);
- }
-};
-
-/**
- * Convert a view object to a string
- */
-var viewStringConverter = {
- item: 'converter',
- from: 'view',
- to: 'string',
- exec: function(view, conversionContext) {
- if (!view.isView) {
- view = conversionContext.createView(view);
- }
- return view.toDom(conversionContext.document).textContent;
- }
-};
-
-/**
- * Convert a view object to a string
- */
-var stringViewStringConverter = {
- item: 'converter',
- from: 'stringView',
- to: 'string',
- exec: function(view, conversionContext) {
- if (!view.isView) {
- view = conversionContext.createView(view);
- }
- return view.toDom(conversionContext.document).textContent;
- }
-};
-
-/**
- * Convert an exception to a DOM element
- */
-var errorDomConverter = {
- item: 'converter',
- from: 'error',
- to: 'dom',
- exec: function(ex, conversionContext) {
- var node = util.createElement(conversionContext.document, 'p');
- node.className = 'gcli-error';
- node.textContent = errorStringConverter.exec(ex, conversionContext);
- return node;
- }
-};
-
-/**
- * Convert an exception to a string
- */
-var errorStringConverter = {
- item: 'converter',
- from: 'error',
- to: 'string',
- exec: function(ex, conversionContext) {
- if (typeof ex === 'string') {
- return ex;
- }
- if (ex instanceof Error) {
- return '' + ex;
- }
- if (typeof ex.message === 'string') {
- return ex.message;
- }
- return '' + ex;
- }
-};
-
-/**
- * Create a new converter by using 2 converters, one after the other
- */
-function getChainConverter(first, second) {
- if (first.to !== second.from) {
- throw new Error('Chain convert impossible: ' + first.to + '!=' + second.from);
- }
- return {
- from: first.from,
- to: second.to,
- exec: function(data, conversionContext) {
- var intermediate = first.exec(data, conversionContext);
- return second.exec(intermediate, conversionContext);
- }
- };
-}
-
-/**
- * A manager for the registered Converters
- */
-function Converters() {
- // This is where we cache the converters that we know about
- this._registered = {
- from: {}
- };
-}
-
-/**
- * Add a new converter to the cache
- */
-Converters.prototype.add = function(converter) {
- var fromMatch = this._registered.from[converter.from];
- if (fromMatch == null) {
- fromMatch = {};
- this._registered.from[converter.from] = fromMatch;
- }
-
- fromMatch[converter.to] = converter;
-};
-
-/**
- * Remove an existing converter from the cache
- */
-Converters.prototype.remove = function(converter) {
- var fromMatch = this._registered.from[converter.from];
- if (fromMatch == null) {
- return;
- }
-
- if (fromMatch[converter.to] === converter) {
- fromMatch[converter.to] = null;
- }
-};
-
-/**
- * Work out the best converter that we've got, for a given conversion.
- */
-Converters.prototype.get = function(from, to) {
- var fromMatch = this._registered.from[from];
- if (fromMatch == null) {
- return this._getFallbackConverter(from, to);
- }
-
- var converter = fromMatch[to];
- if (converter == null) {
- // Someone is going to love writing a graph search algorithm to work out
- // the smallest number of conversions, or perhaps the least 'lossy'
- // conversion but for now the only 2 step conversions which we are going to
- // special case are foo->view->dom and foo->stringView->string.
- if (to === 'dom') {
- converter = fromMatch.view;
- if (converter != null) {
- return getChainConverter(converter, viewDomConverter);
- }
- }
-
- if (to === 'string') {
- converter = fromMatch.stringView;
- if (converter != null) {
- return getChainConverter(converter, stringViewStringConverter);
- }
- converter = fromMatch.view;
- if (converter != null) {
- return getChainConverter(converter, viewStringConverter);
- }
- }
-
- return this._getFallbackConverter(from, to);
- }
- return converter;
-};
-
-/**
- * Get all the registered converters. Most for debugging
- */
-Converters.prototype.getAll = function() {
- return Object.keys(this._registered.from).map(name => {
- return this._registered.from[name];
- });
-};
-
-/**
- * Helper for get to pick the best fallback converter
- */
-Converters.prototype._getFallbackConverter = function(from, to) {
- console.error('No converter from ' + from + ' to ' + to + '. Using fallback');
-
- if (to === 'dom') {
- return fallbackDomConverter;
- }
-
- if (to === 'string') {
- return fallbackStringConverter;
- }
-
- throw new Error('No conversion possible from ' + from + ' to ' + to + '.');
-};
-
-/**
- * Convert some data from one type to another
- * @param data The object to convert
- * @param from The type of the data right now
- * @param to The type that we would like the data in
- * @param conversionContext An execution context (i.e. simplified requisition)
- * which is often required for access to a document, or createView function
- */
-Converters.prototype.convert = function(data, from, to, conversionContext) {
- try {
- if (from === to) {
- return Promise.resolve(data);
- }
-
- var converter = this.get(from, to);
- return host.exec(() => {
- return converter.exec(data, conversionContext);
- });
- }
- catch (ex) {
- var converter = this.get('error', to);
- return host.exec(() => {
- return converter.exec(ex, conversionContext);
- });
- }
-};
-
-exports.Converters = Converters;
-
-/**
- * Items for export
- */
-exports.items = [
- viewDomConverter, viewStringConverter, stringViewStringConverter,
- errorDomConverter, errorStringConverter
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/converters/html.js b/devtools/shared/gcli/source/lib/gcli/converters/html.js
deleted file mode 100644
index 2dea0eb82546..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/converters/html.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-
-/**
- * 'html' means a string containing HTML markup. We use innerHTML to inject
- * this into a DOM which has security implications, so this module will not
- * be used in all implementations.
- */
-exports.items = [
- {
- item: 'converter',
- from: 'html',
- to: 'dom',
- exec: function(html, conversionContext) {
- var div = util.createElement(conversionContext.document, 'div');
- div.innerHTML = html;
- return div;
- }
- },
- {
- item: 'converter',
- from: 'html',
- to: 'string',
- exec: function(html, conversionContext) {
- var div = util.createElement(conversionContext.document, 'div');
- div.innerHTML = html;
- return div.textContent;
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/converters/moz.build b/devtools/shared/gcli/source/lib/gcli/converters/moz.build
deleted file mode 100644
index d3a649197174..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/converters/moz.build
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'basic.js',
- 'converters.js',
- 'html.js',
- 'terminal.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/converters/terminal.js b/devtools/shared/gcli/source/lib/gcli/converters/terminal.js
deleted file mode 100644
index a2406c68947b..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/converters/terminal.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-
-/**
- * A 'terminal' object is a string or an array of strings, which are typically
- * the output from a shell command
- */
-exports.items = [
- {
- item: 'converter',
- from: 'terminal',
- to: 'dom',
- createTextArea: function(text, conversionContext) {
- var node = util.createElement(conversionContext.document, 'textarea');
- node.classList.add('gcli-row-subterminal');
- node.readOnly = true;
- node.textContent = text;
- return node;
- },
- exec: function(data, conversionContext) {
- if (Array.isArray(data)) {
- var node = util.createElement(conversionContext.document, 'div');
- data.forEach(function(member) {
- node.appendChild(this.createTextArea(member, conversionContext));
- });
- return node;
- }
- return this.createTextArea(data);
- }
- },
- {
- item: 'converter',
- from: 'terminal',
- to: 'string',
- exec: function(data, conversionContext) {
- return Array.isArray(data) ? data.join('') : '' + data;
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/fields/delegate.js b/devtools/shared/gcli/source/lib/gcli/fields/delegate.js
deleted file mode 100644
index a2fa508f0d17..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/fields/delegate.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var Field = require('./fields').Field;
-
-/**
- * A field that works with delegate types by delaying resolution until that
- * last possible time
- */
-function DelegateField(type, options) {
- Field.call(this, type, options);
- this.options = options;
-
- this.element = util.createElement(this.document, 'div');
- this.update();
-
- this.onFieldChange = util.createEvent('DelegateField.onFieldChange');
-}
-
-DelegateField.prototype = Object.create(Field.prototype);
-
-DelegateField.prototype.update = function() {
- var subtype = this.type.getType(this.options.requisition.executionContext);
- if (typeof subtype.parse !== 'function') {
- subtype = this.options.requisition.system.types.createType(subtype);
- }
-
- // It's not clear that we can compare subtypes in this way.
- // Perhaps we need a type.equals(...) function
- if (subtype === this.subtype) {
- return;
- }
-
- if (this.field) {
- this.field.destroy();
- }
-
- this.subtype = subtype;
- var fields = this.options.requisition.system.fields;
- this.field = fields.get(subtype, this.options);
-
- util.clearElement(this.element);
- this.element.appendChild(this.field.element);
-};
-
-DelegateField.claim = function(type, context) {
- return type.isDelegate ? Field.MATCH : Field.NO_MATCH;
-};
-
-DelegateField.prototype.destroy = function() {
- this.element = undefined;
- this.options = undefined;
- if (this.field) {
- this.field.destroy();
- }
- this.subtype = undefined;
- Field.prototype.destroy.call(this);
-};
-
-DelegateField.prototype.setConversion = function(conversion) {
- this.field.setConversion(conversion);
-};
-
-DelegateField.prototype.getConversion = function() {
- return this.field.getConversion();
-};
-
-Object.defineProperty(DelegateField.prototype, 'isImportant', {
- get: function() {
- return this.field.isImportant;
- },
- enumerable: true
-});
-
-/**
- * Exported items
- */
-exports.items = [
- DelegateField
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/fields/fields.js b/devtools/shared/gcli/source/lib/gcli/fields/fields.js
deleted file mode 100644
index c97184731fa7..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/fields/fields.js
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-
-/**
- * A Field is a way to get input for a single parameter.
- * This class is designed to be inherited from. It's important that all
- * subclasses have a similar constructor signature because they are created
- * via Fields.get(...)
- * @param type The type to use in conversions
- * @param options A set of properties to help fields configure themselves:
- * - document: The document we use in calling createElement
- * - requisition: The requisition that we're attached to
- */
-function Field(type, options) {
- this.type = type;
- this.document = options.document;
- this.requisition = options.requisition;
-}
-
-/**
- * Enable registration of fields using addItems
- */
-Field.prototype.item = 'field';
-
-/**
- * Subclasses should assign their element with the DOM node that gets added
- * to the 'form'. It doesn't have to be an input node, just something that
- * contains it.
- */
-Field.prototype.element = undefined;
-
-/**
- * Called from the outside to indicate that the command line has changed and
- * the field should update itself
- */
-Field.prototype.update = function() {
-};
-
-/**
- * Indicates that this field should drop any resources that it has created
- */
-Field.prototype.destroy = function() {
- this.messageElement = undefined;
- this.document = undefined;
- this.requisition = undefined;
-};
-
-// Note: We could/should probably change Fields from working with Conversions
-// to working with Arguments (Tokens), which makes for less calls to parse()
-
-/**
- * Update this field display with the value from this conversion.
- * Subclasses should provide an implementation of this function.
- */
-Field.prototype.setConversion = function(conversion) {
- throw new Error('Field should not be used directly');
-};
-
-/**
- * Extract a conversion from the values in this field.
- * Subclasses should provide an implementation of this function.
- */
-Field.prototype.getConversion = function() {
- throw new Error('Field should not be used directly');
-};
-
-/**
- * Set the element where messages and validation errors will be displayed
- * @see setMessage()
- */
-Field.prototype.setMessageElement = function(element) {
- this.messageElement = element;
-};
-
-/**
- * Display a validation message in the UI
- */
-Field.prototype.setMessage = function(message) {
- if (this.messageElement) {
- util.setTextContent(this.messageElement, message || '');
- }
-};
-
-/**
- * Some fields contain information that is more important to the user, for
- * example error messages and completion menus.
- */
-Field.prototype.isImportant = false;
-
-/**
- * 'static/abstract' method to allow implementations of Field to lay a claim
- * to a type. This allows claims of various strength to be weighted up.
- * See the Field.*MATCH values.
- */
-Field.claim = function(type, context) {
- throw new Error('Field should not be used directly');
-};
-
-/**
- * How good a match is a field for a given type
- */
-Field.MATCH = 3; // Good match
-Field.DEFAULT = 2; // A default match
-Field.BASIC = 1; // OK in an emergency. i.e. assume Strings
-Field.NO_MATCH = 0; // This field can't help with the given type
-
-exports.Field = Field;
-
-
-/**
- * A manager for the registered Fields
- */
-function Fields() {
- // Internal array of known fields
- this._fieldCtors = [];
-}
-
-/**
- * Add a field definition by field constructor
- * @param fieldCtor Constructor function of new Field
- */
-Fields.prototype.add = function(fieldCtor) {
- if (typeof fieldCtor !== 'function') {
- console.error('fields.add erroring on ', fieldCtor);
- throw new Error('fields.add requires a Field constructor');
- }
- this._fieldCtors.push(fieldCtor);
-};
-
-/**
- * Remove a Field definition
- * @param field A previously registered field, specified either with a field
- * name or from the field name
- */
-Fields.prototype.remove = function(field) {
- if (typeof field !== 'string') {
- this._fieldCtors = this._fieldCtors.filter(function(test) {
- return test !== field;
- });
- }
- else if (field instanceof Field) {
- this.remove(field.name);
- }
- else {
- console.error('fields.remove erroring on ', field);
- throw new Error('fields.remove requires an instance of Field');
- }
-};
-
-/**
- * Find the best possible matching field from the specification of the type
- * of field required.
- * @param type An instance of Type that we will represent
- * @param options A set of properties that we should attempt to match, and use
- * in the construction of the new field object:
- * - document: The document to use in creating new elements
- * - requisition: The requisition we're monitoring,
- * @return A newly constructed field that best matches the input options
- */
-Fields.prototype.get = function(type, options) {
- var FieldConstructor;
- var highestClaim = -1;
- this._fieldCtors.forEach(function(fieldCtor) {
- var context = (options.requisition == null) ?
- null : options.requisition.executionContext;
- var claim = fieldCtor.claim(type, context);
- if (claim > highestClaim) {
- highestClaim = claim;
- FieldConstructor = fieldCtor;
- }
- });
-
- if (!FieldConstructor) {
- console.error('Unknown field type ', type, ' in ', this._fieldCtors);
- throw new Error('Can\'t find field for ' + type);
- }
-
- if (highestClaim < Field.DEFAULT) {
- return new BlankField(type, options);
- }
-
- return new FieldConstructor(type, options);
-};
-
-/**
- * Get all the registered fields. Most for debugging
- */
-Fields.prototype.getAll = function() {
- return this._fieldCtors.slice();
-};
-
-exports.Fields = Fields;
-
-/**
- * For use with delegate types that do not yet have anything to resolve to.
- * BlankFields are not for general use.
- */
-function BlankField(type, options) {
- Field.call(this, type, options);
-
- this.element = util.createElement(this.document, 'div');
-
- this.onFieldChange = util.createEvent('BlankField.onFieldChange');
-}
-
-BlankField.prototype = Object.create(Field.prototype);
-
-BlankField.claim = function(type, context) {
- return type.name === 'blank' ? Field.MATCH : Field.NO_MATCH;
-};
-
-BlankField.prototype.destroy = function() {
- this.element = undefined;
- Field.prototype.destroy.call(this);
-};
-
-BlankField.prototype.setConversion = function(conversion) {
- this.setMessage(conversion.message);
-};
-
-BlankField.prototype.getConversion = function() {
- return this.type.parseString('', this.requisition.executionContext);
-};
-
-/**
- * Items for export
- */
-exports.items = [ BlankField ];
diff --git a/devtools/shared/gcli/source/lib/gcli/fields/moz.build b/devtools/shared/gcli/source/lib/gcli/fields/moz.build
deleted file mode 100644
index 74fa1cc95c95..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/fields/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'delegate.js',
- 'fields.js',
- 'selection.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/fields/selection.js b/devtools/shared/gcli/source/lib/gcli/fields/selection.js
deleted file mode 100644
index 9d3b54b55159..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/fields/selection.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var Menu = require('../ui/menu').Menu;
-
-var Argument = require('../types/types').Argument;
-var Conversion = require('../types/types').Conversion;
-var Field = require('./fields').Field;
-
-/**
- * A field that allows selection of one of a number of options
- */
-function SelectionField(type, options) {
- Field.call(this, type, options);
-
- this.arg = new Argument();
-
- this.menu = new Menu({
- document: this.document,
- maxPredictions: Conversion.maxPredictions
- });
- this.element = this.menu.element;
-
- this.onFieldChange = util.createEvent('SelectionField.onFieldChange');
-
- // i.e. Register this.onItemClick as the default action for a menu click
- this.menu.onItemClick.add(this.itemClicked, this);
-}
-
-SelectionField.prototype = Object.create(Field.prototype);
-
-SelectionField.claim = function(type, context) {
- if (context == null) {
- return Field.NO_MATCH;
- }
- return type.getType(context).hasPredictions ? Field.DEFAULT : Field.NO_MATCH;
-};
-
-SelectionField.prototype.destroy = function() {
- this.menu.onItemClick.remove(this.itemClicked, this);
- this.menu.destroy();
- this.menu = undefined;
- this.element = undefined;
- Field.prototype.destroy.call(this);
-};
-
-SelectionField.prototype.setConversion = function(conversion) {
- this.arg = conversion.arg;
- this.setMessage(conversion.message);
-
- var context = this.requisition.executionContext;
- conversion.getPredictions(context).then(predictions => {
- var items = predictions.map(function(prediction) {
- // If the prediction value is an 'item' (that is an object with a name and
- // description) then use that, otherwise use the prediction itself, because
- // at least that has a name.
- return prediction.value && prediction.value.description ?
- prediction.value :
- prediction;
- }, this);
- if (this.menu != null) {
- this.menu.show(items, conversion.arg.text);
- }
- }).catch(util.errorHandler);
-};
-
-SelectionField.prototype.itemClicked = function(ev) {
- var arg = new Argument(ev.name, '', ' ');
- var context = this.requisition.executionContext;
-
- this.type.parse(arg, context).then(conversion => {
- this.onFieldChange({ conversion: conversion });
- this.setMessage(conversion.message);
- }).catch(util.errorHandler);
-};
-
-SelectionField.prototype.getConversion = function() {
- // This tweaks the prefix/suffix of the argument to fit
- this.arg = this.arg.beget({ text: this.input.value });
- return this.type.parse(this.arg, this.requisition.executionContext);
-};
-
-/**
- * Allow the terminal to use RETURN to chose the current menu item when
- * it can't execute the command line
- * @return true if an item was 'clicked', false otherwise
- */
-SelectionField.prototype.selectChoice = function() {
- var selected = this.menu.selected;
- if (selected == null) {
- return false;
- }
-
- this.itemClicked({ name: selected });
- return true;
-};
-
-Object.defineProperty(SelectionField.prototype, 'isImportant', {
- get: function() {
- return this.type.name !== 'command';
- },
- enumerable: true
-});
-
-/**
- * Allow registration and de-registration.
- */
-exports.items = [ SelectionField ];
diff --git a/devtools/shared/gcli/source/lib/gcli/index.js b/devtools/shared/gcli/source/lib/gcli/index.js
deleted file mode 100644
index e65d1156bdbd..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/index.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var Cc = require('chrome').Cc;
-var Ci = require('chrome').Ci;
-
-
-var prefSvc = Cc['@mozilla.org/preferences-service;1']
- .getService(Ci.nsIPrefService);
-var prefBranch = prefSvc.getBranch(null).QueryInterface(Ci.nsIPrefBranch);
-
-exports.hiddenByChromePref = function() {
- return !prefBranch.prefHasUserValue('devtools.chrome.enabled');
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/l10n.js b/devtools/shared/gcli/source/lib/gcli/l10n.js
deleted file mode 100644
index 4d3f365955fe..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/l10n.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-"use strict";
-
-var Cc = require("chrome").Cc;
-var Ci = require("chrome").Ci;
-
-var prefSvc = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
-var prefBranch = prefSvc.getBranch(null).QueryInterface(Ci.nsIPrefBranch);
-
-const {LocalizationHelper} = require("devtools/shared/l10n");
-const L10N = new LocalizationHelper("devtools/shared/locales/gclicommands.properties");
-
-/**
- * Lookup a string in the GCLI string bundle
- */
-exports.lookup = function (name) {
- try {
- return L10N.getStr(name);
- } catch (ex) {
- throw new Error("Failure in lookup('" + name + "')");
- }
-};
-
-/**
- * An alternative to lookup().
- * l10n.lookup("BLAH") === l10n.propertyLookup.BLAH
- * This is particularly nice for templates because you can pass
- * l10n:l10n.propertyLookup in the template data and use it
- * like ${l10n.BLAH}
- */
-exports.propertyLookup = new Proxy({}, {
- get: function (rcvr, name) {
- return exports.lookup(name);
- }
-});
-
-/**
- * Lookup a string in the GCLI string bundle
- */
-exports.lookupFormat = function (name, swaps) {
- try {
- return L10N.getFormatStr(name, ...swaps);
- } catch (ex) {
- throw new Error("Failure in lookupFormat('" + name + "')");
- }
-};
-
-/**
- * Allow GCLI users to be hidden by the "devtools.chrome.enabled" pref.
- * Use it in commands like this:
- *
diff --git a/devtools/shared/gcli/source/lib/gcli/languages/command.js b/devtools/shared/gcli/source/lib/gcli/languages/command.js
deleted file mode 100644
index cc460663a0ff..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/languages/command.js
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var domtemplate = require('../util/domtemplate');
-var host = require('../util/host');
-
-var Status = require('../types/types').Status;
-var cli = require('../cli');
-var Requisition = require('../cli').Requisition;
-var CommandAssignment = require('../cli').CommandAssignment;
-var intro = require('../ui/intro');
-
-var RESOLVED = Promise.resolve(true);
-
-/**
- * Various ways in which we need to manipulate the caret/selection position.
- * A value of null means we're not expecting a change
- */
-var Caret = exports.Caret = {
- /**
- * We are expecting changes, but we don't need to move the cursor
- */
- NO_CHANGE: 0,
-
- /**
- * We want the entire input area to be selected
- */
- SELECT_ALL: 1,
-
- /**
- * The whole input has changed - push the cursor to the end
- */
- TO_END: 2,
-
- /**
- * A part of the input has changed - push the cursor to the end of the
- * changed section
- */
- TO_ARG_END: 3
-};
-
-/**
- * Shared promise for loading command.html
- */
-var commandHtmlPromise;
-
-var commandLanguage = exports.commandLanguage = {
- // Language implementation for GCLI commands
- item: 'language',
- name: 'commands',
- prompt: ':',
- proportionalFonts: true,
-
- constructor: function(terminal) {
- this.terminal = terminal;
- this.document = terminal.document;
- this.focusManager = terminal.focusManager;
-
- var options = this.terminal.options;
- this.requisition = options.requisition;
- if (this.requisition == null) {
- if (options.environment == null) {
- options.environment = {};
- options.environment.document = options.document || this.document;
- options.environment.window = options.environment.document.defaultView;
- }
-
- this.requisition = new Requisition(terminal.system, options);
- }
-
- // We also keep track of the last known arg text for the current assignment
- this.lastText = undefined;
-
- // Used to effect caret changes. See _processCaretChange()
- this._caretChange = null;
-
- // We keep track of which assignment the cursor is in
- this.assignment = this.requisition.getAssignmentAt(0);
-
- if (commandHtmlPromise == null) {
- commandHtmlPromise = host.staticRequire(module, './command.html');
- }
-
- return commandHtmlPromise.then(commandHtml => {
- this.commandDom = host.toDom(this.document, commandHtml);
-
- this.requisition.commandOutputManager.onOutput.add(this.outputted, this);
- var mapping = cli.getMapping(this.requisition.executionContext);
- mapping.terminal = this.terminal;
-
- this.requisition.onExternalUpdate.add(this.textChanged, this);
-
- return this;
- });
- },
-
- destroy: function() {
- var mapping = cli.getMapping(this.requisition.executionContext);
- delete mapping.terminal;
-
- this.requisition.commandOutputManager.onOutput.remove(this.outputted, this);
- this.requisition.onExternalUpdate.remove(this.textChanged, this);
-
- this.terminal = undefined;
- this.requisition = undefined;
- this.commandDom = undefined;
- },
-
- textChanged: function() {
- if (this.terminal == null) {
- return; // This can happen post-destroy()
- }
-
- if (this.terminal._caretChange == null) {
- // We weren't expecting a change so this was requested by the hint system
- // we should move the cursor to the end of the 'changed section', and the
- // best we can do for that right now is the end of the current argument.
- this.terminal._caretChange = Caret.TO_ARG_END;
- }
-
- var newStr = this.requisition.toString();
- var input = this.terminal.getInputState();
-
- input.typed = newStr;
- this._processCaretChange(input);
-
- // We don't update terminal._previousValue. Should we?
- // Shouldn't this really be a function of terminal?
- if (this.terminal.inputElement.value !== newStr) {
- this.terminal.inputElement.value = newStr;
- }
- this.terminal.onInputChange({ inputState: input });
-
- // We get here for minor things like whitespace change in arg prefix,
- // so we ignore anything but an actual value change.
- if (this.assignment.arg.text === this.lastText) {
- return;
- }
-
- this.lastText = this.assignment.arg.text;
-
- this.terminal.field.update();
- this.terminal.field.setConversion(this.assignment.conversion);
- util.setTextContent(this.terminal.descriptionEle, this.description);
- },
-
- // Called internally whenever we think that the current assignment might
- // have changed, typically on mouse-clicks or key presses.
- caretMoved: function(start) {
- if (!this.requisition.isUpToDate()) {
- return;
- }
- var newAssignment = this.requisition.getAssignmentAt(start);
- if (newAssignment == null) {
- return;
- }
-
- if (this.assignment !== newAssignment) {
- if (this.assignment.param.type.onLeave) {
- this.assignment.param.type.onLeave(this.assignment);
- }
-
- // This can be kicked off either by requisition doing an assign or by
- // terminal noticing a cursor movement out of a command, so we should
- // check that this really is a new assignment
- var isNew = (this.assignment !== newAssignment);
-
- this.assignment = newAssignment;
- this.terminal.updateCompletion().catch(util.errorHandler);
-
- if (isNew) {
- this.updateHints();
- }
-
- if (this.assignment.param.type.onEnter) {
- this.assignment.param.type.onEnter(this.assignment);
- }
- }
- else {
- if (this.assignment && this.assignment.param.type.onChange) {
- this.assignment.param.type.onChange(this.assignment);
- }
- }
-
- // Warning: compare the logic here with the logic in fieldChanged, which
- // is slightly different. They should probably be the same
- var error = (this.assignment.status === Status.ERROR);
- this.focusManager.setError(error);
- },
-
- // Called whenever the assignment that we're providing help with changes
- updateHints: function() {
- this.lastText = this.assignment.arg.text;
-
- var field = this.terminal.field;
- if (field) {
- field.onFieldChange.remove(this.terminal.fieldChanged, this.terminal);
- field.destroy();
- }
-
- var fields = this.terminal.system.fields;
- field = this.terminal.field = fields.get(this.assignment.param.type, {
- document: this.terminal.document,
- requisition: this.requisition
- });
-
- this.focusManager.setImportantFieldFlag(field.isImportant);
-
- field.onFieldChange.add(this.terminal.fieldChanged, this.terminal);
- field.setConversion(this.assignment.conversion);
-
- // Filled in by the template process
- this.terminal.errorEle = undefined;
- this.terminal.descriptionEle = undefined;
-
- var contents = this.terminal.tooltipTemplate.cloneNode(true);
- domtemplate.template(contents, this.terminal, {
- blankNullUndefined: true,
- stack: 'terminal.html#tooltip'
- });
-
- util.clearElement(this.terminal.tooltipElement);
- this.terminal.tooltipElement.appendChild(contents);
- this.terminal.tooltipElement.style.display = 'block';
-
- field.setMessageElement(this.terminal.errorEle);
- },
-
- /**
- * See also handleDownArrow for some symmetry
- */
- handleUpArrow: function() {
- // If the user is on a valid value, then we increment the value, but if
- // they've typed something that's not right we page through predictions
- if (this.assignment.getStatus() === Status.VALID) {
- return this.requisition.nudge(this.assignment, 1).then(() => {
- this.textChanged();
- this.focusManager.onInputChange();
- return true;
- });
- }
-
- return Promise.resolve(false);
- },
-
- /**
- * See also handleUpArrow for some symmetry
- */
- handleDownArrow: function() {
- if (this.assignment.getStatus() === Status.VALID) {
- return this.requisition.nudge(this.assignment, -1).then(() => {
- this.textChanged();
- this.focusManager.onInputChange();
- return true;
- });
- }
-
- return Promise.resolve(false);
- },
-
- /**
- * RETURN checks status and might exec
- */
- handleReturn: function(input) {
- // Deny RETURN unless the command might work
- if (this.requisition.status !== Status.VALID) {
- return Promise.resolve(false);
- }
-
- this.terminal.history.add(input);
- this.terminal.unsetChoice().catch(util.errorHandler);
-
- this.terminal._previousValue = this.terminal.inputElement.value;
- this.terminal.inputElement.value = '';
-
- return this.requisition.exec().then(() => {
- this.textChanged();
- return true;
- });
- },
-
- /**
- * Warning: We get TAB events for more than just the user pressing TAB in our
- * input element.
- */
- handleTab: function() {
- // It's possible for TAB to not change the input, in which case the
- // textChanged event will not fire, and the caret move will not be
- // processed. So we check that this is done first
- this.terminal._caretChange = Caret.TO_ARG_END;
- var inputState = this.terminal.getInputState();
- this._processCaretChange(inputState);
-
- this.terminal._previousValue = this.terminal.inputElement.value;
-
- // The changes made by complete may happen asynchronously, so after the
- // the call to complete() we should avoid making changes before the end
- // of the event loop
- var index = this.terminal.getChoiceIndex();
- return this.requisition.complete(inputState.cursor, index).then(updated => {
- // Abort UI changes if this UI update has been overtaken
- if (!updated) {
- return RESOLVED;
- }
- this.textChanged();
- return this.terminal.unsetChoice();
- });
- },
-
- /**
- * The input text has changed in some way.
- */
- handleInput: function(value) {
- this.terminal._caretChange = Caret.NO_CHANGE;
-
- return this.requisition.update(value).then(updated => {
- // Abort UI changes if this UI update has been overtaken
- if (!updated) {
- return RESOLVED;
- }
- this.textChanged();
- return this.terminal.unsetChoice();
- });
- },
-
- /**
- * Counterpart to |setInput| for moving the cursor.
- * @param cursor A JS object shaped like { start: x, end: y }
- */
- setCursor: function(cursor) {
- this._caretChange = Caret.NO_CHANGE;
- this._processCaretChange({
- typed: this.terminal.inputElement.value,
- cursor: cursor
- });
- },
-
- /**
- * If this._caretChange === Caret.TO_ARG_END, we alter the input object to move
- * the selection start to the end of the current argument.
- * @param input An object shaped like { typed:'', cursor: { start:0, end:0 }}
- */
- _processCaretChange: function(input) {
- var start, end;
- switch (this._caretChange) {
- case Caret.SELECT_ALL:
- start = 0;
- end = input.typed.length;
- break;
-
- case Caret.TO_END:
- start = input.typed.length;
- end = input.typed.length;
- break;
-
- case Caret.TO_ARG_END:
- // There could be a fancy way to do this involving assignment/arg math
- // but it doesn't seem easy, so we cheat a move the cursor to just before
- // the next space, or the end of the input
- start = input.cursor.start;
- do {
- start++;
- }
- while (start < input.typed.length && input.typed[start - 1] !== ' ');
-
- end = start;
- break;
-
- default:
- start = input.cursor.start;
- end = input.cursor.end;
- break;
- }
-
- start = (start > input.typed.length) ? input.typed.length : start;
- end = (end > input.typed.length) ? input.typed.length : end;
-
- var newInput = {
- typed: input.typed,
- cursor: { start: start, end: end }
- };
-
- if (this.terminal.inputElement.selectionStart !== start) {
- this.terminal.inputElement.selectionStart = start;
- }
- if (this.terminal.inputElement.selectionEnd !== end) {
- this.terminal.inputElement.selectionEnd = end;
- }
-
- this.caretMoved(start);
-
- this._caretChange = null;
- return newInput;
- },
-
- /**
- * Calculate the properties required by the template process for completer.html
- */
- getCompleterTemplateData: function() {
- var input = this.terminal.getInputState();
- var start = input.cursor.start;
- var index = this.terminal.getChoiceIndex();
-
- return this.requisition.getStateData(start, index).then(function(data) {
- // Calculate the statusMarkup required to show wavy lines underneath the
- // input text (like that of an inline spell-checker) which used by the
- // template process for completer.html
- // i.e. s/space/ /g in the string (for HTML display) and status to an
- // appropriate class name (i.e. lower cased, prefixed with gcli-in-)
- data.statusMarkup.forEach(function(member) {
- member.string = member.string.replace(/ /g, '\u00a0'); // i.e.
- member.className = 'gcli-in-' + member.status.toString().toLowerCase();
- }, this);
-
- return data;
- });
- },
-
- /**
- * Called by the onFieldChange event (via the terminal) on the current Field
- */
- fieldChanged: function(ev) {
- this.requisition.setAssignment(this.assignment, ev.conversion.arg,
- { matchPadding: true }).then(() => {
- this.textChanged();
- });
-
- var isError = ev.conversion.message != null && ev.conversion.message !== '';
- this.focusManager.setError(isError);
- },
-
- /**
- * Monitor for new command executions
- */
- outputted: function(ev) {
- if (ev.output.hidden) {
- return;
- }
-
- var template = this.commandDom.cloneNode(true);
- var templateOptions = { stack: 'terminal.html#outputView' };
-
- var context = this.requisition.conversionContext;
- var data = {
- onclick: context.update,
- ondblclick: context.updateExec,
- language: this,
- output: ev.output,
- promptClass: (ev.output.error ? 'gcli-row-error' : '') +
- (ev.output.completed ? ' gcli-row-complete' : ''),
- // Elements attached to this by template().
- rowinEle: null,
- rowoutEle: null,
- throbEle: null,
- promptEle: null
- };
-
- domtemplate.template(template, data, templateOptions);
-
- ev.output.promise.then(() => {
- var document = data.rowoutEle.ownerDocument;
-
- if (ev.output.completed) {
- data.promptEle.classList.add('gcli-row-complete');
- }
- if (ev.output.error) {
- data.promptEle.classList.add('gcli-row-error');
- }
-
- util.clearElement(data.rowoutEle);
-
- return ev.output.convert('dom', context).then(node => {
- this.terminal.scrollToBottom();
- data.throbEle.style.display = ev.output.completed ? 'none' : 'block';
-
- if (node == null) {
- data.promptEle.classList.add('gcli-row-error');
- // TODO: show some error to the user
- }
-
- this._linksToNewTab(node);
- data.rowoutEle.appendChild(node);
-
- var event = document.createEvent('Event');
- event.initEvent('load', true, true);
- event.addedElement = node;
- node.dispatchEvent(event);
- });
- }).catch(console.error);
-
- this.terminal.addElement(data.rowinEle);
- this.terminal.addElement(data.rowoutEle);
- this.terminal.scrollToBottom();
-
- this.focusManager.outputted();
- },
-
- /**
- * Find elements with href attributes and add a target=_blank so opened links
- * will open in a new window
- */
- _linksToNewTab: function(element) {
- var links = element.querySelectorAll('*[href]');
- for (var i = 0; i < links.length; i++) {
- links[i].setAttribute('target', '_blank');
- }
- return element;
- },
-
- /**
- * Show a short introduction to this language
- */
- showIntro: function() {
- intro.maybeShowIntro(this.requisition.commandOutputManager,
- this.requisition.conversionContext);
- },
-};
-
-/**
- * The description (displayed at the top of the hint area) should be blank if
- * we're entering the CommandAssignment (because it's obvious) otherwise it's
- * the parameter description.
- */
-Object.defineProperty(commandLanguage, 'description', {
- get: function() {
- if (this.assignment == null || (
- this.assignment instanceof CommandAssignment &&
- this.assignment.value == null)) {
- return '';
- }
-
- return this.assignment.param.manual || this.assignment.param.description;
- },
- enumerable: true
-});
-
-/**
- * Present an error message to the hint popup
- */
-Object.defineProperty(commandLanguage, 'message', {
- get: function() {
- return this.assignment.conversion.message;
- },
- enumerable: true
-});
-
-exports.items = [ commandLanguage ];
diff --git a/devtools/shared/gcli/source/lib/gcli/languages/javascript.js b/devtools/shared/gcli/source/lib/gcli/languages/javascript.js
deleted file mode 100644
index 2d8a6a97c09c..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/languages/javascript.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var host = require('../util/host');
-var prism = require('../util/prism').Prism;
-
-function isMultiline(text) {
- return typeof text === 'string' && text.indexOf('\n') > -1;
-}
-
-exports.items = [
- {
- // Language implementation for Javascript
- item: 'language',
- name: 'javascript',
- prompt: '>',
-
- constructor: function(terminal) {
- this.document = terminal.document;
- this.focusManager = terminal.focusManager;
-
- this.updateHints();
- },
-
- destroy: function() {
- this.document = undefined;
- },
-
- exec: function(input) {
- return this.evaluate(input).then(response => {
- var output = (response.exception != null) ?
- response.exception.class :
- response.output;
-
- var isSameString = typeof output === 'string' &&
- input.substr(1, input.length - 2) === output;
- var isSameOther = typeof output !== 'string' &&
- input === '' + output;
-
- // Place strings in quotes
- if (typeof output === 'string' && response.exception == null) {
- if (!output.includes('\'')) {
- output = '\'' + output + '\'';
- }
- else {
- output = output.replace(/\\/, '\\').replace(/"/, '"').replace(/'/, '\'');
- output = '"' + output + '"';
- }
- }
-
- var line;
- if (isSameString || isSameOther || output === undefined) {
- line = input;
- }
- else if (isMultiline(output)) {
- line = input + '\n/*\n' + output + '\n*/';
- }
- else {
- line = input + ' // ' + output;
- }
-
- var grammar = prism.languages[this.name];
- return prism.highlight(line, grammar, this.name);
- });
- },
-
- evaluate: function(input) {
- return host.script.evaluate(input);
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/languages/languages.js b/devtools/shared/gcli/source/lib/gcli/languages/languages.js
deleted file mode 100644
index ddea414a1401..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/languages/languages.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-
-var RESOLVED = Promise.resolve(true);
-
-/**
- * This is the base implementation for all languages
- */
-var baseLanguage = {
- item: 'language',
- name: undefined,
-
- constructor: function(terminal) {
- },
-
- destroy: function() {
- },
-
- updateHints: function() {
- util.clearElement(this.terminal.tooltipElement);
- },
-
- description: '',
- message: '',
- caretMoved: function() {},
-
- handleUpArrow: function() {
- return Promise.resolve(false);
- },
-
- handleDownArrow: function() {
- return Promise.resolve(false);
- },
-
- handleTab: function() {
- return this.terminal.unsetChoice().then(function() {
- return RESOLVED;
- }, util.errorHandler);
- },
-
- handleInput: function(input) {
- if (input === ':') {
- return this.terminal.setInput('').then(() => {
- return this.terminal.pushLanguage('commands');
- });
- }
-
- return this.terminal.unsetChoice().then(function() {
- return RESOLVED;
- }, util.errorHandler);
- },
-
- handleReturn: function(input) {
- var rowoutEle = this.document.createElement('pre');
- rowoutEle.classList.add('gcli-row-out');
- rowoutEle.classList.add('gcli-row-script');
- rowoutEle.setAttribute('aria-live', 'assertive');
-
- return this.exec(input).then(line => {
- rowoutEle.innerHTML = line;
-
- this.terminal.addElement(rowoutEle);
- this.terminal.scrollToBottom();
-
- this.focusManager.outputted();
-
- this.terminal.unsetChoice().catch(util.errorHandler);
- this.terminal.inputElement.value = '';
- });
- },
-
- setCursor: function(cursor) {
- this.terminal.inputElement.selectionStart = cursor.start;
- this.terminal.inputElement.selectionEnd = cursor.end;
- },
-
- getCompleterTemplateData: function() {
- return Promise.resolve({
- statusMarkup: [
- {
- string: this.terminal.inputElement.value.replace(/ /g, '\u00a0'), // i.e.
- className: 'gcli-in-valid'
- }
- ],
- unclosedJs: false,
- directTabText: '',
- arrowTabText: '',
- emptyParameters: ''
- });
- },
-
- showIntro: function() {
- },
-
- exec: function(input) {
- throw new Error('Missing implementation of handleReturn() or exec() ' + this.name);
- }
-};
-
-/**
- * A manager for the registered Languages
- */
-function Languages() {
- // This is where we cache the languages that we know about
- this._registered = {};
-}
-
-/**
- * Add a new language to the cache
- */
-Languages.prototype.add = function(language) {
- this._registered[language.name] = language;
-};
-
-/**
- * Remove an existing language from the cache
- */
-Languages.prototype.remove = function(language) {
- var name = typeof language === 'string' ? language : language.name;
- delete this._registered[name];
-};
-
-/**
- * Get access to the list of known languages
- */
-Languages.prototype.getAll = function() {
- return Object.keys(this._registered).map(name => {
- return this._registered[name];
- });
-};
-
-/**
- * Find a previously registered language
- */
-Languages.prototype.createLanguage = function(name, terminal) {
- if (name == null) {
- name = Object.keys(this._registered)[0];
- }
-
- var language = (typeof name === 'string') ? this._registered[name] : name;
- if (!language) {
- console.error('Known languages: ' + Object.keys(this._registered).join(', '));
- throw new Error('Unknown language: \'' + name + '\'');
- }
-
- // clone 'type'
- var newInstance = {};
- util.copyProperties(baseLanguage, newInstance);
- util.copyProperties(language, newInstance);
-
- if (typeof newInstance.constructor === 'function') {
- var reply = newInstance.constructor(terminal);
- return Promise.resolve(reply).then(function() {
- return newInstance;
- });
- }
- else {
- return Promise.resolve(newInstance);
- }
-};
-
-exports.Languages = Languages;
diff --git a/devtools/shared/gcli/source/lib/gcli/languages/moz.build b/devtools/shared/gcli/source/lib/gcli/languages/moz.build
deleted file mode 100644
index e1828a51fff3..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/languages/moz.build
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'command.html',
- 'command.js',
- 'javascript.js',
- 'languages.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/moz.build b/devtools/shared/gcli/source/lib/gcli/moz.build
deleted file mode 100644
index 7b1e6dd2a0c0..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/moz.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'cli.js',
- 'index.js',
- 'l10n.js',
- 'settings.js',
- 'system.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/mozui/completer.js b/devtools/shared/gcli/source/lib/gcli/mozui/completer.js
deleted file mode 100644
index a742c41d2892..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/mozui/completer.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var host = require('../util/host');
-var domtemplate = require('../util/domtemplate');
-
-var completerHtml =
- '\n' +
- ' \n' +
- ' \n' +
- ' \n' +
- ' \n' +
- ' \n' +
- ' \n' +
- ' \n' +
- '\n';
-
-/**
- * Completer is an 'input-like' element that sits an input element annotating
- * it with visual goodness.
- * @param components Object that links to other UI components. GCLI provided:
- * - requisition: A GCLI Requisition object whose state is monitored
- * - element: Element to use as root
- * - autoResize: (default=false): Should we attempt to sync the dimensions of
- * the complete element with the input element.
- */
-function Completer(components) {
- this.requisition = components.requisition;
- this.input = { typed: '', cursor: { start: 0, end: 0 } };
- this.choice = 0;
-
- this.element = components.element;
- this.element.classList.add('gcli-in-complete');
- this.element.setAttribute('tabindex', '-1');
- this.element.setAttribute('aria-live', 'polite');
-
- this.document = this.element.ownerDocument;
-
- this.inputter = components.inputter;
-
- this.inputter.onInputChange.add(this.update, this);
- this.inputter.onAssignmentChange.add(this.update, this);
- this.inputter.onChoiceChange.add(this.update, this);
-
- this.autoResize = components.autoResize;
- if (this.autoResize) {
- this.inputter.onResize.add(this.resized, this);
-
- var dimensions = this.inputter.getDimensions();
- if (dimensions) {
- this.resized(dimensions);
- }
- }
-
- this.template = host.toDom(this.document, completerHtml);
- // We want the spans to line up without the spaces in the template
- util.removeWhitespace(this.template, true);
-
- this.update();
-}
-
-/**
- * Avoid memory leaks
- */
-Completer.prototype.destroy = function() {
- this.inputter.onInputChange.remove(this.update, this);
- this.inputter.onAssignmentChange.remove(this.update, this);
- this.inputter.onChoiceChange.remove(this.update, this);
-
- if (this.autoResize) {
- this.inputter.onResize.remove(this.resized, this);
- }
-
- this.document = undefined;
- this.element = undefined;
- this.template = undefined;
- this.inputter = undefined;
-};
-
-/**
- * Ensure that the completion element is the same size and the inputter element
- */
-Completer.prototype.resized = function(ev) {
- this.element.style.top = ev.top + 'px';
- this.element.style.height = ev.height + 'px';
- this.element.style.lineHeight = ev.height + 'px';
- this.element.style.left = ev.left + 'px';
- this.element.style.width = ev.width + 'px';
-};
-
-/**
- * Bring the completion element up to date with what the requisition says
- */
-Completer.prototype.update = function(ev) {
- this.choice = (ev && ev.choice != null) ? ev.choice : 0;
-
- this._getCompleterTemplateData().then(data => {
- if (this.template == null) {
- return; // destroy() has been called
- }
-
- var template = this.template.cloneNode(true);
- domtemplate.template(template, data, { stack: 'completer.html' });
-
- util.clearElement(this.element);
- while (template.hasChildNodes()) {
- this.element.appendChild(template.firstChild);
- }
- });
-};
-
-/**
- * Calculate the properties required by the template process for completer.html
- */
-Completer.prototype._getCompleterTemplateData = function() {
- var input = this.inputter.getInputState();
- var start = input.cursor.start;
-
- return this.requisition.getStateData(start, this.choice).then(function(data) {
- // Calculate the statusMarkup required to show wavy lines underneath the
- // input text (like that of an inline spell-checker) which used by the
- // template process for completer.html
- // i.e. s/space/ /g in the string (for HTML display) and status to an
- // appropriate class name (i.e. lower cased, prefixed with gcli-in-)
- data.statusMarkup.forEach(function(member) {
- member.string = member.string.replace(/ /g, '\u00a0'); // i.e.
- member.className = 'gcli-in-' + member.status.toString().toLowerCase();
- }, this);
-
- return data;
- });
-};
-
-exports.Completer = Completer;
diff --git a/devtools/shared/gcli/source/lib/gcli/mozui/inputter.js b/devtools/shared/gcli/source/lib/gcli/mozui/inputter.js
deleted file mode 100644
index 640d250d1710..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/mozui/inputter.js
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var KeyEvent = require('../util/util').KeyEvent;
-
-var Status = require('../types/types').Status;
-var History = require('../ui/history').History;
-
-var Telemetry = require("devtools/client/shared/telemetry");
-
-var RESOLVED = Promise.resolve(true);
-
-/**
- * A wrapper to take care of the functions concerning an input element
- * @param components Object that links to other UI components. GCLI provided:
- * - requisition
- * - focusManager
- * - element
- */
-function Inputter(components) {
- this.requisition = components.requisition;
- this.focusManager = components.focusManager;
-
- this.element = components.element;
- this.element.classList.add('gcli-in-input');
- this.element.spellcheck = false;
-
- this.document = this.element.ownerDocument;
-
- // Used to distinguish focus from TAB in CLI. See onKeyUp()
- this.lastTabDownAt = 0;
-
- // Used to effect caret changes. See _processCaretChange()
- this._caretChange = null;
-
- // Use telemetry
- this._telemetry = new Telemetry();
-
- // Ensure that TAB/UP/DOWN isn't handled by the browser
- this.onKeyDown = this.onKeyDown.bind(this);
- this.onKeyUp = this.onKeyUp.bind(this);
- this.element.addEventListener('keydown', this.onKeyDown);
- this.element.addEventListener('keyup', this.onKeyUp);
-
- // Setup History
- this.history = new History();
- this._scrollingThroughHistory = false;
-
- // Used when we're selecting which prediction to complete with
- this._choice = null;
- this.onChoiceChange = util.createEvent('Inputter.onChoiceChange');
-
- // Cursor position affects hint severity
- this.onMouseUp = this.onMouseUp.bind(this);
- this.element.addEventListener('mouseup', this.onMouseUp);
-
- if (this.focusManager) {
- this.focusManager.addMonitoredElement(this.element, 'input');
- }
-
- // Initially an asynchronous completion isn't in-progress
- this._completed = RESOLVED;
-
- this.textChanged = this.textChanged.bind(this);
-
- this.outputted = this.outputted.bind(this);
- this.requisition.commandOutputManager.onOutput.add(this.outputted, this);
-
- this.assignment = this.requisition.getAssignmentAt(0);
- this.onAssignmentChange = util.createEvent('Inputter.onAssignmentChange');
- this.onInputChange = util.createEvent('Inputter.onInputChange');
-
- this.onResize = util.createEvent('Inputter.onResize');
- this.onWindowResize = this.onWindowResize.bind(this);
- this.document.defaultView.addEventListener('resize', this.onWindowResize);
- this.requisition.onExternalUpdate.add(this.textChanged, this);
-
- this._previousValue = undefined;
- this.requisition.update(this.element.value || '');
-}
-
-/**
- * Avoid memory leaks
- */
-Inputter.prototype.destroy = function() {
- this.document.defaultView.removeEventListener('resize', this.onWindowResize);
-
- this.requisition.commandOutputManager.onOutput.remove(this.outputted, this);
- this.requisition.onExternalUpdate.remove(this.textChanged, this);
- if (this.focusManager) {
- this.focusManager.removeMonitoredElement(this.element, 'input');
- }
-
- this.element.removeEventListener('mouseup', this.onMouseUp);
- this.element.removeEventListener('keydown', this.onKeyDown);
- this.element.removeEventListener('keyup', this.onKeyUp);
-
- this.history.destroy();
-
- if (this.style) {
- this.style.remove();
- this.style = undefined;
- }
-
- this.textChanged = undefined;
- this.outputted = undefined;
- this.onMouseUp = undefined;
- this.onKeyDown = undefined;
- this.onKeyUp = undefined;
- this.onWindowResize = undefined;
- this.tooltip = undefined;
- this.document = undefined;
- this.element = undefined;
- this._telemetry = undefined;
-};
-
-/**
- * Make ourselves visually similar to the input element, and make the input
- * element transparent so our background shines through
- */
-Inputter.prototype.onWindowResize = function() {
- // Mochitest sometimes causes resize after shutdown. See Bug 743190
- if (!this.element) {
- return;
- }
-
- this.onResize(this.getDimensions());
-};
-
-/**
- * Make ourselves visually similar to the input element, and make the input
- * element transparent so our background shines through
- */
-Inputter.prototype.getDimensions = function() {
- var fixedLoc = {};
- var currentElement = this.element.parentNode;
- while (currentElement && currentElement.nodeName !== '#document') {
- var style = this.document.defaultView.getComputedStyle(currentElement);
- if (style) {
- var position = style.getPropertyValue('position');
- if (position === 'absolute' || position === 'fixed') {
- var bounds = currentElement.getBoundingClientRect();
- fixedLoc.top = bounds.top;
- fixedLoc.left = bounds.left;
- break;
- }
- }
- currentElement = currentElement.parentNode;
- }
-
- var rect = this.element.getBoundingClientRect();
- return {
- top: rect.top - (fixedLoc.top || 0) + 1,
- height: rect.bottom - rect.top - 1,
- left: rect.left - (fixedLoc.left || 0) + 2,
- width: rect.right - rect.left
- };
-};
-
-/**
- * Pass 'outputted' events on to the focus manager
- */
-Inputter.prototype.outputted = function() {
- if (this.focusManager) {
- this.focusManager.outputted();
- }
-};
-
-/**
- * Handler for the input-element.onMouseUp event
- */
-Inputter.prototype.onMouseUp = function(ev) {
- this._checkAssignment();
-};
-
-/**
- * Function called when we think the text might have changed
- */
-Inputter.prototype.textChanged = function() {
- if (!this.document) {
- return; // This can happen post-destroy()
- }
-
- if (this._caretChange == null) {
- // We weren't expecting a change so this was requested by the hint system
- // we should move the cursor to the end of the 'changed section', and the
- // best we can do for that right now is the end of the current argument.
- this._caretChange = Caret.TO_ARG_END;
- }
-
- var newStr = this.requisition.toString();
- var input = this.getInputState();
-
- input.typed = newStr;
- this._processCaretChange(input);
-
- if (this.element.value !== newStr) {
- this.element.value = newStr;
- }
- this.onInputChange({ inputState: input });
-
- this.tooltip.textChanged();
-};
-
-/**
- * Various ways in which we need to manipulate the caret/selection position.
- * A value of null means we're not expecting a change
- */
-var Caret = {
- /**
- * We are expecting changes, but we don't need to move the cursor
- */
- NO_CHANGE: 0,
-
- /**
- * We want the entire input area to be selected
- */
- SELECT_ALL: 1,
-
- /**
- * The whole input has changed - push the cursor to the end
- */
- TO_END: 2,
-
- /**
- * A part of the input has changed - push the cursor to the end of the
- * changed section
- */
- TO_ARG_END: 3
-};
-
-/**
- * If this._caretChange === Caret.TO_ARG_END, we alter the input object to move
- * the selection start to the end of the current argument.
- * @param input An object shaped like { typed:'', cursor: { start:0, end:0 }}
- */
-Inputter.prototype._processCaretChange = function(input) {
- var start, end;
- switch (this._caretChange) {
- case Caret.SELECT_ALL:
- start = 0;
- end = input.typed.length;
- break;
-
- case Caret.TO_END:
- start = input.typed.length;
- end = input.typed.length;
- break;
-
- case Caret.TO_ARG_END:
- // There could be a fancy way to do this involving assignment/arg math
- // but it doesn't seem easy, so we cheat a move the cursor to just before
- // the next space, or the end of the input
- start = input.cursor.start;
- do {
- start++;
- }
- while (start < input.typed.length && input.typed[start - 1] !== ' ');
-
- end = start;
- break;
-
- default:
- start = input.cursor.start;
- end = input.cursor.end;
- break;
- }
-
- start = (start > input.typed.length) ? input.typed.length : start;
- end = (end > input.typed.length) ? input.typed.length : end;
-
- var newInput = {
- typed: input.typed,
- cursor: { start: start, end: end }
- };
-
- if (this.element.selectionStart !== start) {
- this.element.selectionStart = start;
- }
- if (this.element.selectionEnd !== end) {
- this.element.selectionEnd = end;
- }
-
- this._checkAssignment(start);
-
- this._caretChange = null;
- return newInput;
-};
-
-/**
- * To be called internally whenever we think that the current assignment might
- * have changed, typically on mouse-clicks or key presses.
- * @param start Optional - if specified, the cursor position to use in working
- * out the current assignment. This is needed because setting the element
- * selection start is only recognised when the event loop has finished
- */
-Inputter.prototype._checkAssignment = function(start) {
- if (start == null) {
- start = this.element.selectionStart;
- }
- if (!this.requisition.isUpToDate()) {
- return;
- }
- var newAssignment = this.requisition.getAssignmentAt(start);
- if (newAssignment == null) {
- return;
- }
- if (this.assignment !== newAssignment) {
- if (this.assignment.param.type.onLeave) {
- this.assignment.param.type.onLeave(this.assignment);
- }
-
- this.assignment = newAssignment;
- this.onAssignmentChange({ assignment: this.assignment });
-
- if (this.assignment.param.type.onEnter) {
- this.assignment.param.type.onEnter(this.assignment);
- }
- }
- else {
- if (this.assignment && this.assignment.param.type.onChange) {
- this.assignment.param.type.onChange(this.assignment);
- }
- }
-
- // This is slightly nasty - the focusManager generally relies on people
- // telling it what it needs to know (which makes sense because the event
- // system to do it with events would be unnecessarily complex). However
- // requisition doesn't know about the focusManager either. So either one
- // needs to know about the other, or a third-party needs to break the
- // deadlock. These 2 lines are all we're quibbling about, so for now we hack
- if (this.focusManager) {
- var error = (this.assignment.status === Status.ERROR);
- this.focusManager.setError(error);
- }
-};
-
-/**
- * Set the input field to a value, for external use.
- * This function updates the data model. It sets the caret to the end of the
- * input. It does not make any similarity checks so calling this function with
- * it's current value resets the cursor position.
- * It does not execute the input or affect the history.
- * This function should not be called internally, by Inputter and never as a
- * result of a keyboard event on this.element or bug 676520 could be triggered.
- */
-Inputter.prototype.setInput = function(str) {
- this._caretChange = Caret.TO_END;
- return this.requisition.update(str).then(updated => {
- this.textChanged();
- return updated;
- });
-};
-
-/**
- * Counterpart to |setInput| for moving the cursor.
- * @param cursor An object shaped like { start: x, end: y }
- */
-Inputter.prototype.setCursor = function(cursor) {
- this._caretChange = Caret.NO_CHANGE;
- this._processCaretChange({ typed: this.element.value, cursor: cursor });
- return RESOLVED;
-};
-
-/**
- * Focus the input element
- */
-Inputter.prototype.focus = function() {
- this.element.focus();
- this._checkAssignment();
-};
-
-/**
- * Ensure certain keys (arrows, tab, etc) that we would like to handle
- * are not handled by the browser
- */
-Inputter.prototype.onKeyDown = function(ev) {
- if (ev.keyCode === KeyEvent.DOM_VK_UP || ev.keyCode === KeyEvent.DOM_VK_DOWN) {
- ev.preventDefault();
- return;
- }
-
- // The following keys do not affect the state of the command line so we avoid
- // informing the focusManager about keyboard events that involve these keys
- if (ev.keyCode === KeyEvent.DOM_VK_F1 ||
- ev.keyCode === KeyEvent.DOM_VK_ESCAPE ||
- ev.keyCode === KeyEvent.DOM_VK_UP ||
- ev.keyCode === KeyEvent.DOM_VK_DOWN) {
- return;
- }
-
- if (this.focusManager) {
- this.focusManager.onInputChange();
- }
-
- if (ev.keyCode === KeyEvent.DOM_VK_TAB) {
- this.lastTabDownAt = 0;
- if (!ev.shiftKey) {
- ev.preventDefault();
- // Record the timestamp of this TAB down so onKeyUp can distinguish
- // focus from TAB in the CLI.
- this.lastTabDownAt = ev.timeStamp;
- }
- if (ev.metaKey || ev.altKey || ev.crtlKey) {
- if (this.document.commandDispatcher) {
- this.document.commandDispatcher.advanceFocus();
- }
- else {
- this.element.blur();
- }
- }
- }
-};
-
-/**
- * Handler for use with DOM events, which just calls the promise enabled
- * handleKeyUp function but checks the exit state of the promise so we know
- * if something went wrong.
- */
-Inputter.prototype.onKeyUp = function(ev) {
- this.handleKeyUp(ev).catch(util.errorHandler);
-};
-
-/**
- * The main keyboard processing loop
- * @return A promise that resolves (to undefined) when the actions kicked off
- * by this handler are completed.
- */
-Inputter.prototype.handleKeyUp = function(ev) {
- if (this.focusManager && ev.keyCode === KeyEvent.DOM_VK_F1) {
- this.focusManager.helpRequest();
- return RESOLVED;
- }
-
- if (this.focusManager && ev.keyCode === KeyEvent.DOM_VK_ESCAPE) {
- this.focusManager.removeHelp();
- return RESOLVED;
- }
-
- if (ev.keyCode === KeyEvent.DOM_VK_UP) {
- return this._handleUpArrow();
- }
-
- if (ev.keyCode === KeyEvent.DOM_VK_DOWN) {
- return this._handleDownArrow();
- }
-
- if (ev.keyCode === KeyEvent.DOM_VK_RETURN) {
- return this._handleReturn();
- }
-
- if (ev.keyCode === KeyEvent.DOM_VK_TAB && !ev.shiftKey) {
- return this._handleTab(ev);
- }
-
- if (this._previousValue === this.element.value) {
- return RESOLVED;
- }
-
- this._scrollingThroughHistory = false;
- this._caretChange = Caret.NO_CHANGE;
-
- this._completed = this.requisition.update(this.element.value);
- this._previousValue = this.element.value;
-
- return this._completed.then(() => {
- // Abort UI changes if this UI update has been overtaken
- if (this._previousValue === this.element.value) {
- this._choice = null;
- this.textChanged();
- this.onChoiceChange({ choice: this._choice });
- }
- });
-};
-
-/**
- * See also _handleDownArrow for some symmetry
- */
-Inputter.prototype._handleUpArrow = function() {
- if (this.tooltip && this.tooltip.isMenuShowing) {
- this.changeChoice(-1);
- return RESOLVED;
- }
-
- if (this.element.value === '' || this._scrollingThroughHistory) {
- this._scrollingThroughHistory = true;
- return this.requisition.update(this.history.backward()).then(updated => {
- this.textChanged();
- return updated;
- });
- }
-
- // If the user is on a valid value, then we increment the value, but if
- // they've typed something that's not right we page through predictions
- if (this.assignment.getStatus() === Status.VALID) {
- return this.requisition.nudge(this.assignment, 1).then(() => {
- // See notes on focusManager.onInputChange in onKeyDown
- this.textChanged();
- if (this.focusManager) {
- this.focusManager.onInputChange();
- }
- });
- }
-
- this.changeChoice(-1);
- return RESOLVED;
-};
-
-/**
- * See also _handleUpArrow for some symmetry
- */
-Inputter.prototype._handleDownArrow = function() {
- if (this.tooltip && this.tooltip.isMenuShowing) {
- this.changeChoice(+1);
- return RESOLVED;
- }
-
- if (this.element.value === '' || this._scrollingThroughHistory) {
- this._scrollingThroughHistory = true;
- return this.requisition.update(this.history.forward()).then(updated => {
- this.textChanged();
- return updated;
- });
- }
-
- // See notes above for the UP key
- if (this.assignment.getStatus() === Status.VALID) {
- return this.requisition.nudge(this.assignment, -1).then(() => {
- // See notes on focusManager.onInputChange in onKeyDown
- this.textChanged();
- if (this.focusManager) {
- this.focusManager.onInputChange();
- }
- });
- }
-
- this.changeChoice(+1);
- return RESOLVED;
-};
-
-/**
- * RETURN checks status and might exec
- */
-Inputter.prototype._handleReturn = function() {
- // Deny RETURN unless the command might work
- if (this.requisition.status === Status.VALID) {
- this._scrollingThroughHistory = false;
- this.history.add(this.element.value);
-
- let name = this.requisition.commandAssignment.value.name;
- this._telemetry.getKeyedHistogramById("DEVTOOLS_GCLI_COMMANDS_KEYED")
- .add(name);
-
- return this.requisition.exec().then(() => {
- this.textChanged();
- });
- }
-
- // If we can't execute the command, but there is a menu choice to use
- // then use it.
- if (!this.tooltip.selectChoice()) {
- this.focusManager.setError(true);
- }
-
- this._choice = null;
- return RESOLVED;
-};
-
-/**
- * Warning: We get TAB events for more than just the user pressing TAB in our
- * input element.
- */
-Inputter.prototype._handleTab = function(ev) {
- // Being able to complete 'nothing' is OK if there is some context, but
- // when there is nothing on the command line it just looks bizarre.
- var hasContents = (this.element.value.length > 0);
-
- // If the TAB keypress took the cursor from another field to this one,
- // then they get the keydown/keypress, and we get the keyup. In this
- // case we don't want to do any completion.
- // If the time of the keydown/keypress of TAB was close (i.e. within
- // 1 second) to the time of the keyup then we assume that we got them
- // both, and do the completion.
- if (hasContents && this.lastTabDownAt + 1000 > ev.timeStamp) {
- // It's possible for TAB to not change the input, in which case the caret
- // move will not be processed. So we check that this is done first
- this._caretChange = Caret.TO_ARG_END;
- var inputState = this.getInputState();
- this._processCaretChange(inputState);
-
- if (this._choice == null) {
- this._choice = 0;
- }
-
- // The changes made by complete may happen asynchronously, so after the
- // the call to complete() we should avoid making changes before the end
- // of the event loop
- this._completed = this.requisition.complete(inputState.cursor,
- this._choice);
- this._previousValue = this.element.value;
- }
- this.lastTabDownAt = 0;
- this._scrollingThroughHistory = false;
-
- return this._completed.then(updated => {
- // Abort UI changes if this UI update has been overtaken
- if (updated) {
- this.textChanged();
- this._choice = null;
- this.onChoiceChange({ choice: this._choice });
- }
- });
-};
-
-/**
- * Used by onKeyUp for UP/DOWN to change the current choice from an options
- * menu.
- */
-Inputter.prototype.changeChoice = function(amount) {
- if (this._choice == null) {
- this._choice = 0;
- }
- // There's an annoying up is down thing here, the menu is presented
- // with the zeroth index at the top working down, so the UP arrow needs
- // pick the choice below because we're working down
- this._choice += amount;
- this.onChoiceChange({ choice: this._choice });
-};
-
-/**
- * Pull together an input object, which may include XUL hacks
- */
-Inputter.prototype.getInputState = function() {
- var input = {
- typed: this.element.value,
- cursor: {
- start: this.element.selectionStart,
- end: this.element.selectionEnd
- }
- };
-
- // Workaround for potential XUL bug 676520 where textbox gives incorrect
- // values for its content
- if (input.typed == null) {
- input = { typed: '', cursor: { start: 0, end: 0 } };
- }
-
- return input;
-};
-
-exports.Inputter = Inputter;
diff --git a/devtools/shared/gcli/source/lib/gcli/mozui/moz.build b/devtools/shared/gcli/source/lib/gcli/mozui/moz.build
deleted file mode 100644
index af76e0d99ee6..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/mozui/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'completer.js',
- 'inputter.js',
- 'tooltip.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/mozui/tooltip.js b/devtools/shared/gcli/source/lib/gcli/mozui/tooltip.js
deleted file mode 100644
index 62a47ea08a93..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/mozui/tooltip.js
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var host = require('../util/host');
-var domtemplate = require('../util/domtemplate');
-
-var CommandAssignment = require('../cli').CommandAssignment;
-
-var tooltipHtml =
- '
\n' +
- '
${description}
\n' +
- ' ${field.element}\n' +
- '
${assignment.conversion.message}
\n' +
- ' \n' +
- '
';
-
-/**
- * A widget to display an inline dialog which allows the user to fill out
- * the arguments to a command.
- * @param components Object that links to other UI components. GCLI provided:
- * - requisition: The Requisition to fill out
- * - inputter: An instance of Inputter
- * - focusManager: Component to manage hiding/showing this element
- * - panelElement (optional): The element to show/hide on visibility events
- * - element: The root element to populate
- */
-function Tooltip(components) {
- this.inputter = components.inputter;
- this.requisition = components.requisition;
- this.focusManager = components.focusManager;
-
- this.element = components.element;
- this.element.classList.add('gcliterm-tooltip');
- this.document = this.element.ownerDocument;
-
- this.panelElement = components.panelElement;
- if (this.panelElement) {
- this.panelElement.classList.add('gcli-panel-hide');
- this.focusManager.onVisibilityChange.add(this.visibilityChanged, this);
- }
- this.focusManager.addMonitoredElement(this.element, 'tooltip');
-
- // We cache the fields we create so we can destroy them later
- this.fields = [];
-
- this.template = host.toDom(this.document, tooltipHtml);
- this.templateOptions = { blankNullUndefined: true, stack: 'tooltip.html' };
-
- this.inputter.onChoiceChange.add(this.choiceChanged, this);
- this.inputter.onAssignmentChange.add(this.assignmentChanged, this);
-
- // We keep a track of which assignment the cursor is in
- this.assignment = undefined;
- this.assignmentChanged({ assignment: this.inputter.assignment });
-
- // We also keep track of the last known arg text for the current assignment
- this.lastText = undefined;
-}
-
-/**
- * Avoid memory leaks
- */
-Tooltip.prototype.destroy = function() {
- this.inputter.onAssignmentChange.remove(this.assignmentChanged, this);
- this.inputter.onChoiceChange.remove(this.choiceChanged, this);
-
- if (this.panelElement) {
- this.focusManager.onVisibilityChange.remove(this.visibilityChanged, this);
- }
- this.focusManager.removeMonitoredElement(this.element, 'tooltip');
-
- if (this.style) {
- this.style.remove();
- this.style = undefined;
- }
-
- this.field.onFieldChange.remove(this.fieldChanged, this);
- this.field.destroy();
-
- this.lastText = undefined;
- this.assignment = undefined;
-
- this.errorEle = undefined;
- this.descriptionEle = undefined;
- this.highlightEle = undefined;
-
- this.document = undefined;
- this.element = undefined;
- this.panelElement = undefined;
- this.template = undefined;
-};
-
-/**
- * The inputter acts on UP/DOWN if there is a menu showing
- */
-Object.defineProperty(Tooltip.prototype, 'isMenuShowing', {
- get: function() {
- return this.focusManager.isTooltipVisible &&
- this.field != null &&
- this.field.menu != null;
- },
- enumerable: true
-});
-
-/**
- * Called whenever the assignment that we're providing help with changes
- */
-Tooltip.prototype.assignmentChanged = function(ev) {
- // This can be kicked off either by requisition doing an assign or by
- // inputter noticing a cursor movement out of a command, so we should check
- // that this really is a new assignment
- if (this.assignment === ev.assignment) {
- return;
- }
-
- this.assignment = ev.assignment;
- this.lastText = this.assignment.arg.text;
-
- if (this.field) {
- this.field.onFieldChange.remove(this.fieldChanged, this);
- this.field.destroy();
- }
-
- this.field = this.requisition.system.fields.get(this.assignment.param.type, {
- document: this.document,
- requisition: this.requisition
- });
-
- this.focusManager.setImportantFieldFlag(this.field.isImportant);
-
- this.field.onFieldChange.add(this.fieldChanged, this);
- this.field.setConversion(this.assignment.conversion);
-
- // Filled in by the template process
- this.errorEle = undefined;
- this.descriptionEle = undefined;
- this.highlightEle = undefined;
-
- var contents = this.template.cloneNode(true);
- domtemplate.template(contents, this, this.templateOptions);
- util.clearElement(this.element);
- this.element.appendChild(contents);
- this.element.style.display = 'block';
-
- this.field.setMessageElement(this.errorEle);
-
- this._updatePosition();
-};
-
-/**
- * Forward the event to the current field
- */
-Tooltip.prototype.choiceChanged = function(ev) {
- if (this.field && this.field.menu) {
- var conversion = this.assignment.conversion;
- var context = this.requisition.executionContext;
- conversion.constrainPredictionIndex(context, ev.choice).then(choice => {
- this.field.menu._choice = choice;
- this.field.menu._updateHighlight();
- }).catch(util.errorHandler);
- }
-};
-
-/**
- * Allow the inputter to use RETURN to chose the current menu item when
- * it can't execute the command line
- * @return true if there was a selection to use, false otherwise
- */
-Tooltip.prototype.selectChoice = function(ev) {
- if (this.field && this.field.selectChoice) {
- return this.field.selectChoice();
- }
- return false;
-};
-
-/**
- * Called by the onFieldChange event on the current Field
- */
-Tooltip.prototype.fieldChanged = function(ev) {
- this.requisition.setAssignment(this.assignment, ev.conversion.arg,
- { matchPadding: true });
-
- var isError = ev.conversion.message != null && ev.conversion.message !== '';
- this.focusManager.setError(isError);
-
- // Nasty hack, the inputter won't know about the text change yet, so it will
- // get it's calculations wrong. We need to wait until the current set of
- // changes has had a chance to propagate
- this.document.defaultView.setTimeout(() => {
- this.inputter.focus();
- }, 10);
-};
-
-/**
- * Called by the Inputter when the text changes
- */
-Tooltip.prototype.textChanged = function() {
- // We get here for minor things like whitespace change in arg prefix,
- // so we ignore anything but an actual value change.
- if (this.assignment.arg.text === this.lastText) {
- return;
- }
-
- this.lastText = this.assignment.arg.text;
-
- this.field.setConversion(this.assignment.conversion);
- util.setTextContent(this.descriptionEle, this.description);
-
- this._updatePosition();
-};
-
-/**
- * Called to move the tooltip to the correct horizontal position
- */
-Tooltip.prototype._updatePosition = function() {
- var dimensions = this.getDimensionsOfAssignment();
-
- // 10 is roughly the width of a char
- if (this.panelElement) {
- this.panelElement.style.left = (dimensions.start * 10) + 'px';
- }
-
- this.focusManager.updatePosition(dimensions);
-};
-
-/**
- * Returns a object containing 'start' and 'end' properties which identify the
- * number of pixels from the left hand edge of the input element that represent
- * the text portion of the current assignment.
- */
-Tooltip.prototype.getDimensionsOfAssignment = function() {
- var before = '';
- var assignments = this.requisition.getAssignments(true);
- for (var i = 0; i < assignments.length; i++) {
- if (assignments[i] === this.assignment) {
- break;
- }
- before += assignments[i].toString();
- }
- before += this.assignment.arg.prefix;
-
- var startChar = before.length;
- before += this.assignment.arg.text;
- var endChar = before.length;
-
- return { start: startChar, end: endChar };
-};
-
-/**
- * The description (displayed at the top of the hint area) should be blank if
- * we're entering the CommandAssignment (because it's obvious) otherwise it's
- * the parameter description.
- */
-Object.defineProperty(Tooltip.prototype, 'description', {
- get: function() {
- if (this.assignment instanceof CommandAssignment &&
- this.assignment.value == null) {
- return '';
- }
-
- return this.assignment.param.manual || this.assignment.param.description;
- },
- enumerable: true
-});
-
-/**
- * Tweak CSS to show/hide the output
- */
-Tooltip.prototype.visibilityChanged = function(ev) {
- if (!this.panelElement) {
- return;
- }
-
- if (ev.tooltipVisible) {
- this.panelElement.classList.remove('gcli-panel-hide');
- }
- else {
- this.panelElement.classList.add('gcli-panel-hide');
- }
-};
-
-exports.Tooltip = Tooltip;
diff --git a/devtools/shared/gcli/source/lib/gcli/settings.js b/devtools/shared/gcli/source/lib/gcli/settings.js
deleted file mode 100644
index 361fedfe37fb..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/settings.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var imports = {};
-
-var Cc = require('chrome').Cc;
-var Ci = require('chrome').Ci;
-var Cu = require('chrome').Cu;
-
-var XPCOMUtils = require('resource://gre/modules/XPCOMUtils.jsm').XPCOMUtils;
-var Services = require("Services");
-
-XPCOMUtils.defineLazyGetter(imports, 'prefBranch', function() {
- var prefService = Cc['@mozilla.org/preferences-service;1']
- .getService(Ci.nsIPrefService);
- return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch);
-});
-
-var util = require('./util/util');
-
-/**
- * All local settings have this prefix when used in Firefox
- */
-var DEVTOOLS_PREFIX = 'devtools.gcli.';
-
-/**
- * A manager for the registered Settings
- */
-function Settings(types, settingValues) {
- this._types = types;
-
- if (settingValues != null) {
- throw new Error('settingValues is not supported when writing to prefs');
- }
-
- // Collection of preferences for sorted access
- this._settingsAll = [];
-
- // Collection of preferences for fast indexed access
- this._settingsMap = new Map();
-
- // Flag so we know if we've read the system preferences
- this._hasReadSystem = false;
-
- // Event for use to detect when the list of settings changes
- this.onChange = util.createEvent('Settings.onChange');
-}
-
-/**
- * Load system prefs if they've not been loaded already
- * @return true
- */
-Settings.prototype._readSystem = function() {
- if (this._hasReadSystem) {
- return;
- }
-
- imports.prefBranch.getChildList('').forEach(name => {
- var setting = new Setting(this, name);
- this._settingsAll.push(setting);
- this._settingsMap.set(name, setting);
- });
-
- this._settingsAll.sort((s1, s2) => {
- return s1.name.localeCompare(s2.name);
- });
-
- this._hasReadSystem = true;
-};
-
-/**
- * Get an array containing all known Settings filtered to match the given
- * filter (string) at any point in the name of the setting
- */
-Settings.prototype.getAll = function(filter) {
- this._readSystem();
-
- if (filter == null) {
- return this._settingsAll;
- }
-
- return this._settingsAll.filter(setting => {
- return setting.name.includes(filter);
- });
-};
-
-/**
- * Add a new setting
- */
-Settings.prototype.add = function(prefSpec) {
- var setting = new Setting(this, prefSpec);
-
- if (this._settingsMap.has(setting.name)) {
- // Once exists already, we're going to need to replace it in the array
- for (var i = 0; i < this._settingsAll.length; i++) {
- if (this._settingsAll[i].name === setting.name) {
- this._settingsAll[i] = setting;
- }
- }
- }
-
- this._settingsMap.set(setting.name, setting);
- this.onChange({ added: setting.name });
-
- return setting;
-};
-
-/**
- * Getter for an existing setting. Generally use of this function should be
- * avoided. Systems that define a setting should export it if they wish it to
- * be available to the outside, or not otherwise. Use of this function breaks
- * that boundary and also hides dependencies. Acceptable uses include testing
- * and embedded uses of GCLI that pre-define all settings (e.g. Firefox)
- * @param name The name of the setting to fetch
- * @return The found Setting object, or undefined if the setting was not found
- */
-Settings.prototype.get = function(name) {
- // We might be able to give the answer without needing to read all system
- // settings if this is an internal setting
- var found = this._settingsMap.get(name);
- if (!found) {
- found = this._settingsMap.get(DEVTOOLS_PREFIX + name);
- }
-
- if (found) {
- return found;
- }
-
- if (this._hasReadSystem) {
- return undefined;
- }
- else {
- this._readSystem();
- found = this._settingsMap.get(name);
- if (!found) {
- found = this._settingsMap.get(DEVTOOLS_PREFIX + name);
- }
- return found;
- }
-};
-
-/**
- * Remove a setting. A no-op in this case
- */
-Settings.prototype.remove = function() {
-};
-
-exports.Settings = Settings;
-
-/**
- * A class to wrap up the properties of a Setting.
- * @see toolkit/components/viewconfig/content/config.js
- */
-function Setting(settings, prefSpec) {
- this._settings = settings;
- if (typeof prefSpec === 'string') {
- // We're coming from getAll() i.e. a full listing of prefs
- this.name = prefSpec;
- this.description = '';
- }
- else {
- // A specific addition by GCLI
- this.name = DEVTOOLS_PREFIX + prefSpec.name;
-
- if (prefSpec.ignoreTypeDifference !== true && prefSpec.type) {
- if (this.type.name !== prefSpec.type) {
- throw new Error('Locally declared type (' + prefSpec.type + ') != ' +
- 'Mozilla declared type (' + this.type.name + ') for ' + this.name);
- }
- }
-
- this.description = prefSpec.description;
- }
-
- this.onChange = util.createEvent('Setting.onChange');
-}
-
-/**
- * Reset this setting to it's initial default value
- */
-Setting.prototype.setDefault = function() {
- imports.prefBranch.clearUserPref(this.name);
- Services.prefs.savePrefFile(null);
-};
-
-/**
- * What type is this property: boolean/integer/string?
- */
-Object.defineProperty(Setting.prototype, 'type', {
- get: function() {
- switch (imports.prefBranch.getPrefType(this.name)) {
- case imports.prefBranch.PREF_BOOL:
- return this._settings._types.createType('boolean');
-
- case imports.prefBranch.PREF_INT:
- return this._settings._types.createType('number');
-
- case imports.prefBranch.PREF_STRING:
- return this._settings._types.createType('string');
-
- default:
- throw new Error('Unknown type for ' + this.name);
- }
- },
- enumerable: true
-});
-
-/**
- * What type is this property: boolean/integer/string?
- */
-Object.defineProperty(Setting.prototype, 'value', {
- get: function() {
- switch (imports.prefBranch.getPrefType(this.name)) {
- case imports.prefBranch.PREF_BOOL:
- return imports.prefBranch.getBoolPref(this.name);
-
- case imports.prefBranch.PREF_INT:
- return imports.prefBranch.getIntPref(this.name);
-
- case imports.prefBranch.PREF_STRING:
- var value = imports.prefBranch.getStringPref(this.name);
- // In case of a localized string
- if (/^chrome:\/\/.+\/locale\/.+\.properties/.test(value)) {
- value = imports.prefBranch.getComplexValue(this.name,
- Ci.nsIPrefLocalizedString).data;
- }
- return value;
-
- default:
- throw new Error('Invalid value for ' + this.name);
- }
- },
-
- set: function(value) {
- if (imports.prefBranch.prefIsLocked(this.name)) {
- throw new Error('Locked preference ' + this.name);
- }
-
- switch (imports.prefBranch.getPrefType(this.name)) {
- case imports.prefBranch.PREF_BOOL:
- imports.prefBranch.setBoolPref(this.name, value);
- break;
-
- case imports.prefBranch.PREF_INT:
- imports.prefBranch.setIntPref(this.name, value);
- break;
-
- case imports.prefBranch.PREF_STRING:
- imports.prefBranch.setStringPref(this.name, value);
- break;
-
- default:
- throw new Error('Invalid value for ' + this.name);
- }
-
- Services.prefs.savePrefFile(null);
- },
-
- enumerable: true
-});
diff --git a/devtools/shared/gcli/source/lib/gcli/system.js b/devtools/shared/gcli/source/lib/gcli/system.js
deleted file mode 100644
index 1b6360497994..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/system.js
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('./util/util');
-var Commands = require('./commands/commands').Commands;
-var Connectors = require('./connectors/connectors').Connectors;
-var Converters = require('./converters/converters').Converters;
-var Fields = require('./fields/fields').Fields;
-var Languages = require('./languages/languages').Languages;
-var Settings = require('./settings').Settings;
-var Types = require('./types/types').Types;
-
-/**
- * This is the heart of the API that we expose to the outside.
- * @param options Object that customizes how the system acts. Valid properties:
- * - commands, connectors, converters, fields, languages, settings, types:
- * Custom configured manager objects for these item types
- * - location: a system with a location will ignore commands that don't have a
- * matching runAt property. This is principly for client/server setups where
- * we import commands from the server to the client, so a system with
- * `{ location: 'client' }` will silently ignore commands with
- * `{ runAt: 'server' }`. Any system without a location will accept commands
- * with any runAt property (including none).
- */
-exports.createSystem = function(options) {
- options = options || {};
- var location = options.location;
-
- // The plural/singular thing may make you want to scream, but it allows us
- // to say components[getItemType(item)], so a lookup here (and below) saves
- // multiple lookups in the middle of the code
- var components = {
- connector: options.connectors || new Connectors(),
- converter: options.converters || new Converters(),
- field: options.fields || new Fields(),
- language: options.languages || new Languages(),
- type: options.types || new Types()
- };
- components.setting = new Settings(components.type);
- components.command = new Commands(components.type, location);
-
- var getItemType = function(item) {
- if (item.item) {
- return item.item;
- }
- // Some items are registered using the constructor so we need to check
- // the prototype for the the type of the item
- return (item.prototype && item.prototype.item) ?
- item.prototype.item : 'command';
- };
-
- var addItem = function(item) {
- try {
- components[getItemType(item)].add(item);
- }
- catch (ex) {
- if (item != null) {
- console.error('While adding: ' + item.name);
- }
- throw ex;
- }
- };
-
- var removeItem = function(item) {
- components[getItemType(item)].remove(item);
- };
-
- /**
- * loadableModules is a lookup of names to module loader functions (like
- * the venerable 'require') to which we can pass a name and get back a
- * JS object (or a promise of a JS object). This allows us to have custom
- * loaders to get stuff from the filesystem etc.
- */
- var loadableModules = {};
-
- /**
- * loadedModules is a lookup by name of the things returned by the functions
- * in loadableModules so we can track what we need to unload / reload.
- */
- var loadedModules = {};
-
- var unloadModule = function(name) {
- var existingModule = loadedModules[name];
- if (existingModule != null) {
- existingModule.items.forEach(removeItem);
- }
- delete loadedModules[name];
- };
-
- var loadModule = function(name) {
- var existingModule = loadedModules[name];
- unloadModule(name);
-
- // And load the new items
- try {
- var loader = loadableModules[name];
- return Promise.resolve(loader(name)).then(function(newModule) {
- if (existingModule === newModule) {
- return;
- }
-
- if (newModule == null) {
- throw 'Module \'' + name + '\' not found';
- }
-
- if (newModule.items == null || typeof newModule.items.forEach !== 'function') {
- console.log('Exported properties: ' + Object.keys(newModule).join(', '));
- throw 'Module \'' + name + '\' has no \'items\' array export';
- }
-
- newModule.items.forEach(addItem);
-
- loadedModules[name] = newModule;
- });
- }
- catch (ex) {
- console.error('Failed to load module ' + name + ': ' + ex);
- console.error(ex.stack);
-
- return Promise.resolve();
- }
- };
-
- var pendingChanges = false;
-
- var system = {
- addItems: function(items) {
- items.forEach(addItem);
- },
-
- removeItems: function(items) {
- items.forEach(removeItem);
- },
-
- addItemsByModule: function(names, options) {
- var promises = [];
-
- options = options || {};
- if (!options.delayedLoad) {
- // We could be about to add many commands, just report the change once
- this.commands.onCommandsChange.holdFire();
- }
-
- if (typeof names === 'string') {
- names = [ names ];
- }
- names.forEach(function(name) {
- if (options.loader == null) {
- options.loader = function(name) {
- return require(name);
- };
- }
- loadableModules[name] = options.loader;
-
- if (options.delayedLoad) {
- pendingChanges = true;
- }
- else {
- promises.push(loadModule(name).catch(console.error));
- }
- });
-
- if (options.delayedLoad) {
- return Promise.resolve();
- }
- else {
- return Promise.all(promises).then(() => {
- this.commands.onCommandsChange.resumeFire();
- });
- }
- },
-
- removeItemsByModule: function(name) {
- this.commands.onCommandsChange.holdFire();
-
- delete loadableModules[name];
- unloadModule(name);
-
- this.commands.onCommandsChange.resumeFire();
- },
-
- load: function() {
- if (!pendingChanges) {
- return Promise.resolve();
- }
- this.commands.onCommandsChange.holdFire();
-
- // clone loadedModules, so we can remove what is left at the end
- var modules = Object.keys(loadedModules).map(function(name) {
- return loadedModules[name];
- });
-
- var promises = Object.keys(loadableModules).map(function(name) {
- delete modules[name];
- return loadModule(name).catch(console.error);
- });
-
- Object.keys(modules).forEach(unloadModule);
- pendingChanges = false;
-
- return Promise.all(promises).then(() => {
- this.commands.onCommandsChange.resumeFire();
- });
- },
-
- destroy: function() {
- this.commands.onCommandsChange.holdFire();
-
- Object.keys(loadedModules).forEach(function(name) {
- unloadModule(name);
- });
-
- this.commands.onCommandsChange.resumeFire();
- },
-
- toString: function() {
- return 'System [' +
- 'commands:' + components.command.getAll().length + ', ' +
- 'connectors:' + components.connector.getAll().length + ', ' +
- 'converters:' + components.converter.getAll().length + ', ' +
- 'fields:' + components.field.getAll().length + ', ' +
- 'settings:' + components.setting.getAll().length + ', ' +
- 'types:' + components.type.getTypeNames().length + ']';
- }
- };
-
- Object.defineProperty(system, 'commands', {
- get: function() { return components.command; },
- enumerable: true
- });
-
- Object.defineProperty(system, 'connectors', {
- get: function() { return components.connector; },
- enumerable: true
- });
-
- Object.defineProperty(system, 'converters', {
- get: function() { return components.converter; },
- enumerable: true
- });
-
- Object.defineProperty(system, 'fields', {
- get: function() { return components.field; },
- enumerable: true
- });
-
- Object.defineProperty(system, 'languages', {
- get: function() { return components.language; },
- enumerable: true
- });
-
- Object.defineProperty(system, 'settings', {
- get: function() { return components.setting; },
- enumerable: true
- });
-
- Object.defineProperty(system, 'types', {
- get: function() { return components.type; },
- enumerable: true
- });
-
- return system;
-};
-
-/**
- * Connect a local system with another at the other end of a connector
- * @param system System to which we're adding commands
- * @param front Front which allows access to the remote system from which we
- * import commands
- * @param customProps Array of strings specifying additional properties defined
- * on remote commands that should be considered part of the metadata for the
- * commands imported into the local system
- */
-exports.connectFront = function(system, front, customProps) {
- system._handleCommandsChanged = function() {
- syncItems(system, front, customProps).catch(util.errorHandler);
- };
- front.on('commands-changed', system._handleCommandsChanged);
-
- return syncItems(system, front, customProps);
-};
-
-/**
- * Undo the effect of #connectFront
- */
-exports.disconnectFront = function(system, front) {
- front.off('commands-changed', system._handleCommandsChanged);
- system._handleCommandsChanged = undefined;
- removeItemsFromFront(system, front);
-};
-
-/**
- * Remove the items in this system that came from a previous sync action, and
- * re-add them. See connectFront() for explanation of properties
- */
-function syncItems(system, front, customProps) {
- return front.specs(customProps).then(function(specs) {
- removeItemsFromFront(system, front);
-
- var remoteItems = addLocalFunctions(specs, front);
- system.addItems(remoteItems);
-
- return system;
- });
-};
-
-/**
- * Take the data from the 'specs' command (or the 'commands-changed' event) and
- * add function to proxy the execution back over the front
- */
-function addLocalFunctions(specs, front) {
- // Inject an 'exec' function into the commands, and the front into
- // all the remote types
- specs.forEach(function(commandSpec) {
- // HACK: Tack the front to the command so we know how to remove it
- // in removeItemsFromFront() below
- commandSpec.front = front;
-
- // Tell the type instances for a command how to contact their counterparts
- // Don't confuse this with setting the front on the commandSpec which is
- // about associating a proxied command with it's source for later removal.
- // This is actually going to be used by the type
- commandSpec.params.forEach(function(param) {
- if (typeof param.type !== 'string') {
- param.type.front = front;
- }
- });
-
- if (!commandSpec.isParent) {
- commandSpec.exec = function(args, context) {
- var typed = (context.prefix ? context.prefix + ' ' : '') + context.typed;
- return front.execute(typed).then(function(reply) {
- var typedData = context.typedData(reply.type, reply.data);
- return reply.isError ? Promise.reject(typedData) : typedData;
- });
- };
- }
-
- commandSpec.isProxy = true;
- });
-
- return specs;
-}
-
-/**
- * Go through all the commands removing any that are associated with the
- * given front. The method of association is the hack in addLocalFunctions.
- */
-function removeItemsFromFront(system, front) {
- system.commands.getAll().forEach(function(command) {
- if (command.front === front) {
- system.commands.remove(command);
- }
- });
-}
diff --git a/devtools/shared/gcli/source/lib/gcli/types/array.js b/devtools/shared/gcli/source/lib/gcli/types/array.js
deleted file mode 100644
index 072b8bd5c9ec..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/array.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var ArrayConversion = require('./types').ArrayConversion;
-var ArrayArgument = require('./types').ArrayArgument;
-
-exports.items = [
- {
- // A set of objects of the same type
- item: 'type',
- name: 'array',
- subtype: undefined,
-
- constructor: function() {
- if (!this.subtype) {
- console.error('Array.typeSpec is missing subtype. Assuming string.' +
- this.name);
- this.subtype = 'string';
- }
- this.subtype = this.types.createType(this.subtype);
- },
-
- getSpec: function(commandName, paramName) {
- return {
- name: 'array',
- subtype: this.subtype.getSpec(commandName, paramName),
- };
- },
-
- stringify: function(values, context) {
- if (values == null) {
- return '';
- }
- // BUG 664204: Check for strings with spaces and add quotes
- return values.join(' ');
- },
-
- parse: function(arg, context) {
- if (arg.type !== 'ArrayArgument') {
- console.error('non ArrayArgument to ArrayType.parse', arg);
- throw new Error('non ArrayArgument to ArrayType.parse');
- }
-
- // Parse an argument to a conversion
- // Hack alert. ArrayConversion needs to be able to answer questions about
- // the status of individual conversions in addition to the overall state.
- // |subArg.conversion| allows us to do that easily.
- var subArgParse = subArg => {
- return this.subtype.parse(subArg, context).then(conversion => {
- subArg.conversion = conversion;
- return conversion;
- });
- };
-
- var conversionPromises = arg.getArguments().map(subArgParse);
- return Promise.all(conversionPromises).then(function(conversions) {
- return new ArrayConversion(conversions, arg);
- });
- },
-
- getBlank: function(context) {
- return new ArrayConversion([], new ArrayArgument());
- }
- },
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/boolean.js b/devtools/shared/gcli/source/lib/gcli/types/boolean.js
deleted file mode 100644
index 01f5f5022ab7..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/boolean.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-var BlankArgument = require('./types').BlankArgument;
-var SelectionType = require('./selection').SelectionType;
-
-exports.items = [
- {
- // 'boolean' type
- item: 'type',
- name: 'boolean',
- parent: 'selection',
-
- getSpec: function() {
- return 'boolean';
- },
-
- lookup: [
- { name: 'false', value: false },
- { name: 'true', value: true }
- ],
-
- parse: function(arg, context) {
- if (arg.type === 'TrueNamedArgument') {
- return Promise.resolve(new Conversion(true, arg));
- }
- if (arg.type === 'FalseNamedArgument') {
- return Promise.resolve(new Conversion(false, arg));
- }
- return SelectionType.prototype.parse.call(this, arg, context);
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
- return '' + value;
- },
-
- getBlank: function(context) {
- return new Conversion(false, new BlankArgument(), Status.VALID, '',
- Promise.resolve(this.lookup));
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/command.js b/devtools/shared/gcli/source/lib/gcli/types/command.js
deleted file mode 100644
index 74cb80cb7359..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/command.js
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var spell = require('../util/spell');
-var SelectionType = require('./selection').SelectionType;
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-var cli = require('../cli');
-
-exports.items = [
- {
- // Select from the available parameters to a command
- item: 'type',
- name: 'param',
- parent: 'selection',
- stringifyProperty: 'name',
- requisition: undefined,
- isIncompleteName: undefined,
-
- getSpec: function() {
- throw new Error('param type is not remotable');
- },
-
- lookup: function() {
- return exports.getDisplayedParamLookup(this.requisition);
- },
-
- parse: function(arg, context) {
- if (this.isIncompleteName) {
- return SelectionType.prototype.parse.call(this, arg, context);
- }
- else {
- var message = l10n.lookup('cliUnusedArg');
- return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, message));
- }
- }
- },
- {
- // Select from the available commands
- // This is very similar to a SelectionType, however the level of hackery in
- // SelectionType to make it handle Commands correctly was to high, so we
- // simplified.
- // If you are making changes to this code, you should check there too.
- item: 'type',
- name: 'command',
- parent: 'selection',
- stringifyProperty: 'name',
- allowNonExec: true,
-
- getSpec: function() {
- return {
- name: 'command',
- allowNonExec: this.allowNonExec
- };
- },
-
- lookup: function(context) {
- var commands = cli.getMapping(context).requisition.system.commands;
- return exports.getCommandLookup(commands);
- },
-
- parse: function(arg, context) {
- var conversion = exports.parse(context, arg, this.allowNonExec);
- return Promise.resolve(conversion);
- }
- }
-];
-
-exports.getDisplayedParamLookup = function(requisition) {
- var displayedParams = [];
- var command = requisition.commandAssignment.value;
- if (command != null) {
- command.params.forEach(function(param) {
- var arg = requisition.getAssignment(param.name).arg;
- if (!param.isPositionalAllowed && arg.type === 'BlankArgument') {
- displayedParams.push({ name: '--' + param.name, value: param });
- }
- });
- }
- return displayedParams;
-};
-
-exports.parse = function(context, arg, allowNonExec) {
- var commands = cli.getMapping(context).requisition.system.commands;
- var lookup = exports.getCommandLookup(commands);
- var predictions = exports.findPredictions(arg, lookup);
- return exports.convertPredictions(commands, arg, allowNonExec, predictions);
-};
-
-exports.getCommandLookup = function(commands) {
- var sorted = commands.getAll().sort(function(c1, c2) {
- return c1.name.localeCompare(c2.name);
- });
- return sorted.map(function(command) {
- return { name: command.name, value: command };
- });
-};
-
-exports.findPredictions = function(arg, lookup) {
- var predictions = [];
- var i, option;
- var maxPredictions = Conversion.maxPredictions;
- var match = arg.text.toLowerCase();
-
- // Add an option to our list of predicted options
- var addToPredictions = function(option) {
- if (arg.text.length === 0) {
- // If someone hasn't typed anything, we only show top level commands in
- // the menu. i.e. sub-commands (those with a space in their name) are
- // excluded. We do this to keep the list at an overview level.
- if (!option.name.includes(' ')) {
- predictions.push(option);
- }
- }
- else {
- // If someone has typed something, then we exclude parent commands
- // (those without an exec). We do this because the user is drilling
- // down and doesn't need the summary level.
- if (option.value.exec != null) {
- predictions.push(option);
- }
- }
- };
-
- // If the arg has a suffix then we're kind of 'done'. Only an exact
- // match will do.
- if (arg.suffix.match(/ +/)) {
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option.name === arg.text ||
- option.name.indexOf(arg.text + ' ') === 0) {
- addToPredictions(option);
- }
- }
-
- return predictions;
- }
-
- // Cache lower case versions of all the option names
- for (i = 0; i < lookup.length; i++) {
- option = lookup[i];
- if (option._gcliLowerName == null) {
- option._gcliLowerName = option.name.toLowerCase();
- }
- }
-
- // Exact hidden matches. If 'hidden: true' then we only allow exact matches
- // All the tests after here check that !option.value.hidden
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option.name === arg.text) {
- addToPredictions(option);
- }
- }
-
- // Start with prefix matching
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option._gcliLowerName.indexOf(match) === 0 && !option.value.hidden) {
- if (!predictions.includes(option)) {
- addToPredictions(option);
- }
- }
- }
-
- // Try infix matching if we get less half max matched
- if (predictions.length < (maxPredictions / 2)) {
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option._gcliLowerName.includes(match) && !option.value.hidden) {
- if (!predictions.includes(option)) {
- addToPredictions(option);
- }
- }
- }
- }
-
- // Try fuzzy matching if we don't get a prefix match
- if (predictions.length === 0) {
- var names = [];
- lookup.forEach(function(opt) {
- if (!opt.value.hidden) {
- names.push(opt.name);
- }
- });
- var corrected = spell.correct(match, names);
- if (corrected) {
- lookup.forEach(function(opt) {
- if (opt.name === corrected) {
- predictions.push(opt);
- }
- });
- }
- }
-
- return predictions;
-};
-
-exports.convertPredictions = function(commands, arg, allowNonExec, predictions) {
- var command = commands.get(arg.text);
- // Helper function - Commands like 'context' work best with parent
- // commands which are not executable. However obviously to execute a
- // command, it needs an exec function.
- var execWhereNeeded = (allowNonExec ||
- (command != null && typeof command.exec === 'function'));
-
- var isExact = command && command.name === arg.text &&
- execWhereNeeded && predictions.length === 1;
- var alternatives = isExact ? [] : predictions;
-
- if (command) {
- var status = execWhereNeeded ? Status.VALID : Status.INCOMPLETE;
- return new Conversion(command, arg, status, '', alternatives);
- }
-
- if (predictions.length === 0) {
- var msg = l10n.lookupFormat('typesSelectionNomatch', [ arg.text ]);
- return new Conversion(undefined, arg, Status.ERROR, msg, alternatives);
- }
-
- command = predictions[0].value;
-
- if (predictions.length === 1) {
- // Is it an exact match of an executable command,
- // or just the only possibility?
- if (command.name === arg.text && execWhereNeeded) {
- return new Conversion(command, arg, Status.VALID, '');
- }
-
- return new Conversion(undefined, arg, Status.INCOMPLETE, '', alternatives);
- }
-
- // It's valid if the text matches, even if there are several options
- if (predictions[0].name === arg.text) {
- return new Conversion(command, arg, Status.VALID, '', alternatives);
- }
-
- return new Conversion(undefined, arg, Status.INCOMPLETE, '', alternatives);
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/types/date.js b/devtools/shared/gcli/source/lib/gcli/types/date.js
deleted file mode 100644
index 9e6e59444b23..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/date.js
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-
-/**
- * Helper for stringify() to left pad a single digit number with a single '0'
- * so 1 -> '01', 42 -> '42', etc.
- */
-function pad(number) {
- var r = String(number);
- return r.length === 1 ? '0' + r : r;
-}
-
-/**
- * Utility to convert a string to a date, throwing if the date can't be
- * parsed rather than having an invalid date
- */
-function toDate(str) {
- var millis = Date.parse(str);
- if (isNaN(millis)) {
- throw new Error(l10n.lookupFormat('typesDateNan', [ str ]));
- }
- return new Date(millis);
-}
-
-/**
- * Is |thing| a valid date?
- * @see http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript
- */
-function isDate(thing) {
- return Object.prototype.toString.call(thing) === '[object Date]'
- && !isNaN(thing.getTime());
-}
-
-exports.items = [
- {
- // ECMA 5.1 §15.9.1.1
- // @see http://stackoverflow.com/questions/11526504/minimum-and-maximum-date
- item: 'type',
- name: 'date',
- step: 1,
- min: new Date(-8640000000000000),
- max: new Date(8640000000000000),
-
- constructor: function() {
- this._origMin = this.min;
- if (this.min != null) {
- if (typeof this.min === 'string') {
- this.min = toDate(this.min);
- }
- else if (isDate(this.min) || typeof this.min === 'function') {
- this.min = this.min;
- }
- else {
- throw new Error('date min value must be one of string/date/function');
- }
- }
-
- this._origMax = this.max;
- if (this.max != null) {
- if (typeof this.max === 'string') {
- this.max = toDate(this.max);
- }
- else if (isDate(this.max) || typeof this.max === 'function') {
- this.max = this.max;
- }
- else {
- throw new Error('date max value must be one of string/date/function');
- }
- }
- },
-
- getSpec: function() {
- var spec = {
- name: 'date'
- };
- if (this.step !== 1) {
- spec.step = this.step;
- }
- if (this._origMax != null) {
- spec.max = this._origMax;
- }
- if (this._origMin != null) {
- spec.min = this._origMin;
- }
- return spec;
- },
-
- stringify: function(value, context) {
- if (!isDate(value)) {
- return '';
- }
-
- var str = pad(value.getFullYear()) + '-' +
- pad(value.getMonth() + 1) + '-' +
- pad(value.getDate());
-
- // Only add in the time if it's not midnight
- if (value.getHours() !== 0 || value.getMinutes() !== 0 ||
- value.getSeconds() !== 0 || value.getMilliseconds() !== 0) {
-
- // What string should we use to separate the date from the time?
- // There are 3 options:
- // 'T': This is the standard from ISO8601. i.e. 2013-05-20T11:05
- // The good news - it's a standard. The bad news - it's weird and
- // alien to many if not most users
- // ' ': This looks nicest, but needs escaping (which GCLI will do
- // automatically) so it would look like: '2013-05-20 11:05'
- // Good news: looks best, bad news: on completion we place the
- // cursor after the final ', breaking repeated increment/decrement
- // '\ ': It's possible that we could find a way to use a \ to escape
- // the space, so the output would look like: 2013-05-20\ 11:05
- // This would involve changes to a number of parts, and is
- // probably too complex a solution for this problem for now
- // In the short term I'm going for ' ', and raising the priority of
- // cursor positioning on actions like increment/decrement/tab.
-
- str += ' ' + pad(value.getHours());
- str += ':' + pad(value.getMinutes());
-
- // Only add in seconds/milliseconds if there is anything to report
- if (value.getSeconds() !== 0 || value.getMilliseconds() !== 0) {
- str += ':' + pad(value.getSeconds());
- if (value.getMilliseconds() !== 0) {
- var milliVal = (value.getUTCMilliseconds() / 1000).toFixed(3);
- str += '.' + String(milliVal).slice(2, 5);
- }
- }
- }
-
- return str;
- },
-
- getMax: function(context) {
- if (typeof this.max === 'function') {
- return this._max(context);
- }
- if (isDate(this.max)) {
- return this.max;
- }
- return undefined;
- },
-
- getMin: function(context) {
- if (typeof this.min === 'function') {
- return this._min(context);
- }
- if (isDate(this.min)) {
- return this.min;
- }
- return undefined;
- },
-
- parse: function(arg, context) {
- var value;
-
- if (arg.text.replace(/\s/g, '').length === 0) {
- return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
- }
-
- // Lots of room for improvement here: 1h ago, in two days, etc.
- // Should "1h ago" dynamically update the step?
- if (arg.text.toLowerCase() === 'now' ||
- arg.text.toLowerCase() === 'today') {
- value = new Date();
- }
- else if (arg.text.toLowerCase() === 'yesterday') {
- value = new Date();
- value.setDate(value.getDate() - 1);
- }
- else if (arg.text.toLowerCase() === 'tomorrow') {
- value = new Date();
- value.setDate(value.getDate() + 1);
- }
- else {
- // So now actual date parsing.
- // Javascript dates are a mess. Like the default date libraries in most
- // common languages, but with added browser weirdness.
- // There is an argument for saying that the user will expect dates to
- // be formatted as JavaScript dates, except that JS dates are of
- // themselves very unexpected.
- // See http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html
-
- // The timezone used by Date.parse depends on whether or not the string
- // can be interpreted as ISO-8601, so "2000-01-01" is not the same as
- // "2000/01/01" (unless your TZ aligns with UTC) because the first is
- // ISO-8601 and therefore assumed to be UTC, where the latter is
- // assumed to be in the local timezone.
-
- // First, if the user explicitly includes a 'Z' timezone marker, then
- // we assume they know what they are doing with timezones. ISO-8601
- // uses 'Z' as a marker for 'Zulu time', zero hours offset i.e. UTC
- if (arg.text.includes('Z')) {
- value = new Date(arg.text);
- }
- else {
- // Now we don't want the browser to assume ISO-8601 and therefore use
- // UTC so we replace the '-' with '/'
- value = new Date(arg.text.replace(/-/g, '/'));
- }
-
- if (isNaN(value.getTime())) {
- var msg = l10n.lookupFormat('typesDateNan', [ arg.text ]);
- return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
- }
- }
-
- return Promise.resolve(new Conversion(value, arg));
- },
-
- nudge: function(value, by, context) {
- if (!isDate(value)) {
- return new Date();
- }
-
- var newValue = new Date(value);
- newValue.setDate(value.getDate() + (by * this.step));
-
- if (newValue < this.getMin(context)) {
- return this.getMin(context);
- }
- else if (newValue > this.getMax(context)) {
- return this.getMax();
- }
- else {
- return newValue;
- }
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/delegate.js b/devtools/shared/gcli/source/lib/gcli/types/delegate.js
deleted file mode 100644
index 07571e27a54d..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/delegate.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var Conversion = require('./types').Conversion;
-var Status = require('./types').Status;
-var BlankArgument = require('./types').BlankArgument;
-
-/**
- * The types we expose for registration
- */
-exports.items = [
- // A type for "we don't know right now, but hope to soon"
- {
- item: 'type',
- name: 'delegate',
-
- getSpec: function(commandName, paramName) {
- return {
- name: 'delegate',
- param: paramName
- };
- },
-
- // Child types should implement this method to return an instance of the type
- // that should be used. If no type is available, or some sort of temporary
- // placeholder is required, BlankType can be used.
- delegateType: undefined,
-
- stringify: function(value, context) {
- return this.getType(context).then(delegated => {
- return delegated.stringify(value, context);
- });
- },
-
- parse: function(arg, context) {
- return this.getType(context).then(delegated => {
- return delegated.parse(arg, context);
- });
- },
-
- nudge: function(value, by, context) {
- return this.getType(context).then(delegated => {
- return delegated.nudge ?
- delegated.nudge(value, by, context) :
- undefined;
- });
- },
-
- getType: function(context) {
- if (this.delegateType === undefined) {
- return Promise.resolve(this.types.createType('blank'));
- }
-
- var type = this.delegateType(context);
- if (typeof type.parse !== 'function') {
- type = this.types.createType(type);
- }
- return Promise.resolve(type);
- },
-
- // DelegateType is designed to be inherited from, so DelegateField needs a
- // way to check if something works like a delegate without using 'name'
- isDelegate: true,
-
- // Technically we perhaps should proxy this, except that properties are
- // inherently synchronous, so we can't. It doesn't seem important enough to
- // change the function definition to accommodate this right now
- isImportant: false
- },
- {
- item: 'type',
- name: 'remote',
- paramName: undefined,
- blankIsValid: false,
- hasPredictions: true,
-
- getSpec: function(commandName, paramName) {
- return {
- name: 'remote',
- commandName: commandName,
- paramName: paramName,
- blankIsValid: this.blankIsValid
- };
- },
-
- getBlank: function(context) {
- if (this.blankIsValid) {
- return new Conversion({ stringified: '' },
- new BlankArgument(), Status.VALID);
- }
- else {
- return new Conversion(undefined, new BlankArgument(),
- Status.INCOMPLETE, '');
- }
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
- // remote types are client only, and we don't attempt to transfer value
- // objects to the client (we can't be sure the are jsonable) so it is a
- // bit strange to be asked to stringify a value object, however since
- // parse creates a Conversion with a (fake) value object we might be
- // asked to stringify that. We can stringify fake value objects.
- if (typeof value.stringified === 'string') {
- return value.stringified;
- }
- throw new Error('Can\'t stringify that value');
- },
-
- parse: function(arg, context) {
- return this.front.parseType(context.typed, this.paramName).then(json => {
- var status = Status.fromString(json.status);
- return new Conversion(undefined, arg, status, json.message, json.predictions);
- });
- },
-
- nudge: function(value, by, context) {
- return this.front.nudgeType(context.typed, by, this.paramName).then(json => {
- return { stringified: json.arg };
- });
- }
- },
- // 'blank' is a type for use with DelegateType when we don't know yet.
- // It should not be used anywhere else.
- {
- item: 'type',
- name: 'blank',
-
- getSpec: function(commandName, paramName) {
- return 'blank';
- },
-
- stringify: function(value, context) {
- return '';
- },
-
- parse: function(arg, context) {
- return Promise.resolve(new Conversion(undefined, arg));
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/file.js b/devtools/shared/gcli/source/lib/gcli/types/file.js
deleted file mode 100644
index 004f0108c832..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/file.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-/*
- * The file type is a bit of a spiders-web, but there isn't a nice solution
- * yet. The core of the problem is that the modules used by Firefox and NodeJS
- * intersect with the modules used by the web, but not each other. Except here.
- * So we have to do something fancy to get the sharing but not mess up the web.
- *
- * This file requires 'gcli/types/fileparser', and there are 4 implementations
- * of this:
- * - '/lib/gcli/types/fileparser.js', the default web version that uses XHR to
- * talk to the node server
- * - '/lib/server/gcli/types/fileparser.js', an NodeJS stub, and ...
- * - '/mozilla/gcli/types/fileparser.js', the Firefox implementation both of
- * these are shims which import
- * - 'gcli/util/fileparser', does the real work, except the actual file access
- *
- * The file access comes from the 'gcli/util/filesystem' module, and there are
- * 2 implementations of this:
- * - '/lib/server/gcli/util/filesystem.js', which uses NodeJS APIs
- * - '/mozilla/gcli/util/filesystem.js', which uses OS.File APIs
- */
-
-var fileparser = require('./fileparser');
-var Conversion = require('./types').Conversion;
-
-exports.items = [
- {
- item: 'type',
- name: 'file',
-
- filetype: 'any', // One of 'file', 'directory', 'any'
- existing: 'maybe', // Should be one of 'yes', 'no', 'maybe'
- matches: undefined, // RegExp to match the file part of the path
-
- hasPredictions: true,
-
- constructor: function() {
- if (this.filetype !== 'any' && this.filetype !== 'file' &&
- this.filetype !== 'directory') {
- throw new Error('filetype must be one of [any|file|directory]');
- }
-
- if (this.existing !== 'yes' && this.existing !== 'no' &&
- this.existing !== 'maybe') {
- throw new Error('existing must be one of [yes|no|maybe]');
- }
- },
-
- getSpec: function(commandName, paramName) {
- return {
- name: 'remote',
- commandName: commandName,
- paramName: paramName
- };
- },
-
- stringify: function(file) {
- if (file == null) {
- return '';
- }
-
- return file.toString();
- },
-
- parse: function(arg, context) {
- var options = {
- filetype: this.filetype,
- existing: this.existing,
- matches: this.matches
- };
- var promise = fileparser.parse(context, arg.text, options);
-
- return promise.then(function(reply) {
- return new Conversion(reply.value, arg, reply.status,
- reply.message, reply.predictor);
- });
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/fileparser.js b/devtools/shared/gcli/source/lib/gcli/types/fileparser.js
deleted file mode 100644
index 5db86dc66e05..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/fileparser.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-exports.parse = require('../util/fileparser').parse;
diff --git a/devtools/shared/gcli/source/lib/gcli/types/javascript.js b/devtools/shared/gcli/source/lib/gcli/types/javascript.js
deleted file mode 100644
index 03b24209d866..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/javascript.js
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-
-var Conversion = require('./types').Conversion;
-var Type = require('./types').Type;
-var Status = require('./types').Status;
-
-/**
- * 'javascript' handles scripted input
- */
-function JavascriptType(typeSpec) {
-}
-
-JavascriptType.prototype = Object.create(Type.prototype);
-
-JavascriptType.prototype.getSpec = function(commandName, paramName) {
- return {
- name: 'remote',
- paramName: paramName
- };
-};
-
-JavascriptType.prototype.stringify = function(value, context) {
- if (value == null) {
- return '';
- }
- return value;
-};
-
-/**
- * When sorting out completions, there is no point in displaying millions of
- * matches - this the number of matches that we aim for
- */
-JavascriptType.MAX_COMPLETION_MATCHES = 10;
-
-JavascriptType.prototype.parse = function(arg, context) {
- var typed = arg.text;
- var scope = (context.environment.window == null) ?
- null : context.environment.window;
-
- // No input is undefined
- if (typed === '') {
- return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE));
- }
- // Just accept numbers
- if (!isNaN(parseFloat(typed)) && isFinite(typed)) {
- return Promise.resolve(new Conversion(typed, arg));
- }
- // Just accept constants like true/false/null/etc
- if (typed.trim().match(/(null|undefined|NaN|Infinity|true|false)/)) {
- return Promise.resolve(new Conversion(typed, arg));
- }
-
- // Analyze the input text and find the beginning of the last part that
- // should be completed.
- var beginning = this._findCompletionBeginning(typed);
-
- // There was an error analyzing the string.
- if (beginning.err) {
- return Promise.resolve(new Conversion(typed, arg, Status.ERROR, beginning.err));
- }
-
- // If the current state is ParseState.COMPLEX, then we can't do completion.
- // so bail out now
- if (beginning.state === ParseState.COMPLEX) {
- return Promise.resolve(new Conversion(typed, arg));
- }
-
- // If the current state is not ParseState.NORMAL, then we are inside of a
- // string which means that no completion is possible.
- if (beginning.state !== ParseState.NORMAL) {
- return Promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
- }
-
- var completionPart = typed.substring(beginning.startPos);
- var properties = completionPart.split('.');
- var matchProp;
- var prop;
-
- if (properties.length > 1) {
- matchProp = properties.pop().trimLeft();
- for (var i = 0; i < properties.length; i++) {
- prop = properties[i].trim();
-
- // We can't complete on null.foo, so bail out
- if (scope == null) {
- return Promise.resolve(new Conversion(typed, arg, Status.ERROR,
- l10n.lookup('jstypeParseScope')));
- }
-
- if (prop === '') {
- return Promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
- }
-
- // Check if prop is a getter function on 'scope'. Functions can change
- // other stuff so we can't execute them to get the next object. Stop here.
- if (this._isSafeProperty(scope, prop)) {
- return Promise.resolve(new Conversion(typed, arg));
- }
-
- try {
- scope = scope[prop];
- }
- catch (ex) {
- // It would be nice to be able to report this error in some way but
- // as it can happen just when someone types '{sessionStorage.', it
- // almost doesn't really count as an error, so we ignore it
- return Promise.resolve(new Conversion(typed, arg, Status.VALID, ''));
- }
- }
- }
- else {
- matchProp = properties[0].trimLeft();
- }
-
- // If the reason we just stopped adjusting the scope was a non-simple string,
- // then we're not sure if the input is valid or invalid, so accept it
- if (prop && !prop.match(/^[0-9A-Za-z]*$/)) {
- return Promise.resolve(new Conversion(typed, arg));
- }
-
- // However if the prop was a simple string, it is an error
- if (scope == null) {
- var msg = l10n.lookupFormat('jstypeParseMissing', [ prop ]);
- return Promise.resolve(new Conversion(typed, arg, Status.ERROR, msg));
- }
-
- // If the thing we're looking for isn't a simple string, then we're not going
- // to find it, but we're not sure if it's valid or invalid, so accept it
- if (!matchProp.match(/^[0-9A-Za-z]*$/)) {
- return Promise.resolve(new Conversion(typed, arg));
- }
-
- // Skip Iterators and Generators.
- if (this._isIteratorOrGenerator(scope)) {
- return Promise.resolve(new Conversion(typed, arg));
- }
-
- var matchLen = matchProp.length;
- var prefix = matchLen === 0 ? typed : typed.slice(0, -matchLen);
- var status = Status.INCOMPLETE;
- var message = '';
-
- // We really want an array of matches (for sorting) but it's easier to
- // detect existing members if we're using a map initially
- var matches = {};
-
- // We only display a maximum of MAX_COMPLETION_MATCHES, so there is no point
- // in digging up the prototype chain for matches that we're never going to
- // use. Initially look for matches directly on the object itself and then
- // look up the chain to find more
- var distUpPrototypeChain = 0;
- var root = scope;
- try {
- while (root != null &&
- Object.keys(matches).length < JavascriptType.MAX_COMPLETION_MATCHES) {
-
- /* jshint loopfunc:true */
- Object.keys(root).forEach(function(property) {
- // Only add matching properties. Also, as we're walking up the
- // prototype chain, properties on 'higher' prototypes don't override
- // similarly named properties lower down
- if (property.indexOf(matchProp) === 0 && !(property in matches)) {
- matches[property] = {
- prop: property,
- distUpPrototypeChain: distUpPrototypeChain
- };
- }
- });
-
- distUpPrototypeChain++;
- root = Object.getPrototypeOf(root);
- }
- }
- catch (ex) {
- return Promise.resolve(new Conversion(typed, arg, Status.INCOMPLETE, ''));
- }
-
- // Convert to an array for sorting, and while we're at it, note if we got
- // an exact match so we know that this input is valid
- matches = Object.keys(matches).map(function(property) {
- if (property === matchProp) {
- status = Status.VALID;
- }
- return matches[property];
- });
-
- // The sort keys are:
- // - Being on the object itself, not in the prototype chain
- // - The lack of existence of a vendor prefix
- // - The name
- matches.sort(function(m1, m2) {
- if (m1.distUpPrototypeChain !== m2.distUpPrototypeChain) {
- return m1.distUpPrototypeChain - m2.distUpPrototypeChain;
- }
- // Push all vendor prefixes to the bottom of the list
- return isVendorPrefixed(m1.prop) ?
- (isVendorPrefixed(m2.prop) ? m1.prop.localeCompare(m2.prop) : 1) :
- (isVendorPrefixed(m2.prop) ? -1 : m1.prop.localeCompare(m2.prop));
- });
-
- // Trim to size. There is a bug for doing a better job of finding matches
- // (bug 682694), but in the mean time there is a performance problem
- // associated with creating a large number of DOM nodes that few people will
- // ever read, so trim ...
- if (matches.length > JavascriptType.MAX_COMPLETION_MATCHES) {
- matches = matches.slice(0, JavascriptType.MAX_COMPLETION_MATCHES - 1);
- }
-
- // Decorate the matches with:
- // - a description
- // - a value (for the menu) and,
- // - an incomplete flag which reports if we should assume that the user isn't
- // going to carry on the JS expression with this input so far
- var predictions = matches.map(function(match) {
- var description;
- var incomplete = true;
-
- if (this._isSafeProperty(scope, match.prop)) {
- description = '(property getter)';
- }
- else {
- try {
- var value = scope[match.prop];
-
- if (typeof value === 'function') {
- description = '(function)';
- }
- else if (typeof value === 'boolean' || typeof value === 'number') {
- description = '= ' + value;
- incomplete = false;
- }
- else if (typeof value === 'string') {
- if (value.length > 40) {
- value = value.substring(0, 37) + '…';
- }
- description = '= \'' + value + '\'';
- incomplete = false;
- }
- else {
- description = '(' + typeof value + ')';
- }
- }
- catch (ex) {
- description = '(' + l10n.lookup('jstypeParseError') + ')';
- }
- }
-
- return {
- name: prefix + match.prop,
- value: {
- name: prefix + match.prop,
- description: description
- },
- description: description,
- incomplete: incomplete
- };
- }, this);
-
- if (predictions.length === 0) {
- status = Status.ERROR;
- message = l10n.lookupFormat('jstypeParseMissing', [ matchProp ]);
- }
-
- // If the match is the only one possible, and its VALID, predict nothing
- if (predictions.length === 1 && status === Status.VALID) {
- predictions = [];
- }
-
- return Promise.resolve(new Conversion(typed, arg, status, message,
- Promise.resolve(predictions)));
-};
-
-/**
- * Does the given property have a prefix that indicates that it is vendor
- * specific?
- */
-function isVendorPrefixed(name) {
- return name.indexOf('moz') === 0 ||
- name.indexOf('webkit') === 0 ||
- name.indexOf('ms') === 0;
-}
-
-/**
- * Constants used in return value of _findCompletionBeginning()
- */
-var ParseState = {
- /**
- * We have simple input like window.foo, without any punctuation that makes
- * completion prediction be confusing or wrong
- */
- NORMAL: 0,
-
- /**
- * The cursor is in some Javascript that makes completion hard to predict,
- * like console.log(
- */
- COMPLEX: 1,
-
- /**
- * The cursor is inside single quotes (')
- */
- QUOTE: 2,
-
- /**
- * The cursor is inside single quotes (")
- */
- DQUOTE: 3
-};
-
-var OPEN_BODY = '{[('.split('');
-var CLOSE_BODY = '}])'.split('');
-var OPEN_CLOSE_BODY = {
- '{': '}',
- '[': ']',
- '(': ')'
-};
-
-/**
- * How we distinguish between simple and complex JS input. We attempt
- * completion against simple JS.
- */
-var simpleChars = /[a-zA-Z0-9.]/;
-
-/**
- * Analyzes a given string to find the last statement that is interesting for
- * later completion.
- * @param text A string to analyze
- * @return If there was an error in the string detected, then a object like
- * { err: 'ErrorMesssage' }
- * is returned, otherwise a object like
- * {
- * state: ParseState.NORMAL|ParseState.QUOTE|ParseState.DQUOTE,
- * startPos: index of where the last statement begins
- * }
- */
-JavascriptType.prototype._findCompletionBeginning = function(text) {
- var bodyStack = [];
-
- var state = ParseState.NORMAL;
- var start = 0;
- var c;
- var complex = false;
-
- for (var i = 0; i < text.length; i++) {
- c = text[i];
- if (!simpleChars.test(c)) {
- complex = true;
- }
-
- switch (state) {
- // Normal JS state.
- case ParseState.NORMAL:
- if (c === '"') {
- state = ParseState.DQUOTE;
- }
- else if (c === '\'') {
- state = ParseState.QUOTE;
- }
- else if (c === ';') {
- start = i + 1;
- }
- else if (c === ' ') {
- start = i + 1;
- }
- else if (OPEN_BODY.includes(c)) {
- bodyStack.push({
- token: c,
- start: start
- });
- start = i + 1;
- }
- else if (CLOSE_BODY.includes(c)) {
- var last = bodyStack.pop();
- if (!last || OPEN_CLOSE_BODY[last.token] != c) {
- return { err: l10n.lookup('jstypeBeginSyntax') };
- }
- if (c === '}') {
- start = i + 1;
- }
- else {
- start = last.start;
- }
- }
- break;
-
- // Double quote state > " <
- case ParseState.DQUOTE:
- if (c === '\\') {
- i ++;
- }
- else if (c === '\n') {
- return { err: l10n.lookup('jstypeBeginUnterm') };
- }
- else if (c === '"') {
- state = ParseState.NORMAL;
- }
- break;
-
- // Single quote state > ' <
- case ParseState.QUOTE:
- if (c === '\\') {
- i ++;
- }
- else if (c === '\n') {
- return { err: l10n.lookup('jstypeBeginUnterm') };
- }
- else if (c === '\'') {
- state = ParseState.NORMAL;
- }
- break;
- }
- }
-
- if (state === ParseState.NORMAL && complex) {
- state = ParseState.COMPLEX;
- }
-
- return {
- state: state,
- startPos: start
- };
-};
-
-/**
- * Return true if the passed object is either an iterator or a generator, and
- * false otherwise
- * @param obj The object to check
- */
-JavascriptType.prototype._isIteratorOrGenerator = function(obj) {
- if (obj === null) {
- return false;
- }
-
- if (typeof aObject === 'object') {
- if (typeof obj.__iterator__ === 'function' ||
- obj.constructor && obj.constructor.name === 'Iterator') {
- return true;
- }
-
- try {
- var str = obj.toString();
- if (typeof obj.next === 'function' &&
- str.indexOf('[object Generator') === 0) {
- return true;
- }
- }
- catch (ex) {
- // window.history.next throws in the typeof check above.
- return false;
- }
- }
-
- return false;
-};
-
-/**
- * Would calling 'scope[prop]' cause the invocation of a non-native (i.e. user
- * defined) function property?
- * Since calling functions can have side effects, it's only safe to do that if
- * explicitly requested, rather than because we're trying things out for the
- * purposes of completion.
- */
-JavascriptType.prototype._isSafeProperty = function(scope, prop) {
- if (typeof scope !== 'object') {
- return false;
- }
-
- // Walk up the prototype chain of 'scope' looking for a property descriptor
- // for 'prop'
- var propDesc;
- while (scope) {
- try {
- propDesc = Object.getOwnPropertyDescriptor(scope, prop);
- if (propDesc) {
- break;
- }
- }
- catch (ex) {
- // Native getters throw here. See bug 520882.
- if (ex.name === 'NS_ERROR_XPC_BAD_CONVERT_JS' ||
- ex.name === 'NS_ERROR_XPC_BAD_OP_ON_WN_PROTO') {
- return false;
- }
- return true;
- }
- scope = Object.getPrototypeOf(scope);
- }
-
- if (!propDesc) {
- return false;
- }
-
- if (!propDesc.get) {
- return false;
- }
-
- // The property is safe if 'get' isn't a function or if the function has a
- // prototype (in which case it's native)
- return typeof propDesc.get !== 'function' || 'prototype' in propDesc.get;
-};
-
-JavascriptType.prototype.name = 'javascript';
-
-exports.items = [ JavascriptType ];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/moz.build b/devtools/shared/gcli/source/lib/gcli/types/moz.build
deleted file mode 100644
index dc3063594a98..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/moz.build
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'array.js',
- 'boolean.js',
- 'command.js',
- 'date.js',
- 'delegate.js',
- 'file.js',
- 'fileparser.js',
- 'javascript.js',
- 'node.js',
- 'number.js',
- 'resource.js',
- 'selection.js',
- 'setting.js',
- 'string.js',
- 'types.js',
- 'union.js',
- 'url.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/types/node.js b/devtools/shared/gcli/source/lib/gcli/types/node.js
deleted file mode 100644
index 2f71704e302b..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/node.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var Highlighter = require('../util/host').Highlighter;
-var l10n = require('../util/l10n');
-var util = require('../util/util');
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-var BlankArgument = require('./types').BlankArgument;
-
-/**
- * Helper functions to be attached to the prototypes of NodeType and
- * NodeListType to allow terminal to tell us which nodes should be highlighted
- */
-function onEnter(assignment) {
- // TODO: GCLI doesn't support passing a context to notifications of cursor
- // position, so onEnter/onLeave/onChange are disabled below until we fix this
- assignment.highlighter = new Highlighter(context.environment.window.document);
- assignment.highlighter.nodelist = assignment.conversion.matches;
-}
-
-/** @see #onEnter() */
-function onLeave(assignment) {
- if (!assignment.highlighter) {
- return;
- }
-
- assignment.highlighter.destroy();
- delete assignment.highlighter;
-}
-/** @see #onEnter() */
-function onChange(assignment) {
- if (assignment.conversion.matches == null) {
- return;
- }
- if (!assignment.highlighter) {
- return;
- }
-
- assignment.highlighter.nodelist = assignment.conversion.matches;
-}
-
-/**
- * The exported 'node' and 'nodelist' types
- */
-exports.items = [
- {
- // The 'node' type is a CSS expression that refers to a single node
- item: 'type',
- name: 'node',
-
- getSpec: function(commandName, paramName) {
- return {
- name: 'remote',
- commandName: commandName,
- paramName: paramName
- };
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
- return value.__gcliQuery || 'Error';
- },
-
- parse: function(arg, context) {
- var reply;
-
- if (arg.text === '') {
- reply = new Conversion(undefined, arg, Status.INCOMPLETE);
- }
- else {
- var nodes;
- try {
- nodes = context.environment.window.document.querySelectorAll(arg.text);
- if (nodes.length === 0) {
- reply = new Conversion(undefined, arg, Status.INCOMPLETE,
- l10n.lookup('nodeParseNone'));
- }
- else if (nodes.length === 1) {
- var node = nodes.item(0);
- node.__gcliQuery = arg.text;
-
- reply = new Conversion(node, arg, Status.VALID, '');
- }
- else {
- var msg = l10n.lookupFormat('nodeParseMultiple', [ nodes.length ]);
- reply = new Conversion(undefined, arg, Status.ERROR, msg);
- }
-
- reply.matches = nodes;
- }
- catch (ex) {
- reply = new Conversion(undefined, arg, Status.ERROR,
- l10n.lookup('nodeParseSyntax'));
- }
- }
-
- return Promise.resolve(reply);
- },
-
- // onEnter: onEnter,
- // onLeave: onLeave,
- // onChange: onChange
- },
- {
- // The 'nodelist' type is a CSS expression that refers to a node list
- item: 'type',
- name: 'nodelist',
-
- // The 'allowEmpty' option ensures that we do not complain if the entered
- // CSS selector is valid, but does not match any nodes. There is some
- // overlap between this option and 'defaultValue'. What the user wants, in
- // most cases, would be to use 'defaultText' (i.e. what is typed rather than
- // the value that it represents). However this isn't a concept that exists
- // yet and should probably be a part of GCLI if/when it does.
- // All NodeListTypes have an automatic defaultValue of an empty NodeList so
- // they can easily be used in named parameters.
- allowEmpty: false,
-
- constructor: function() {
- if (typeof this.allowEmpty !== 'boolean') {
- throw new Error('Legal values for allowEmpty are [true|false]');
- }
- },
-
- getSpec: function(commandName, paramName) {
- return {
- name: 'remote',
- commandName: commandName,
- paramName: paramName,
- blankIsValid: true
- };
- },
-
- getBlank: function(context) {
- var emptyNodeList = [];
- if (context != null && context.environment.window != null) {
- var doc = context.environment.window.document;
- emptyNodeList = util.createEmptyNodeList(doc);
- }
- return new Conversion(emptyNodeList, new BlankArgument(), Status.VALID);
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
- return value.__gcliQuery || 'Error';
- },
-
- parse: function(arg, context) {
- var reply;
- try {
- if (arg.text === '') {
- reply = new Conversion(undefined, arg, Status.INCOMPLETE);
- }
- else {
- var nodes = context.environment.window.document.querySelectorAll(arg.text);
-
- if (nodes.length === 0 && !this.allowEmpty) {
- reply = new Conversion(undefined, arg, Status.INCOMPLETE,
- l10n.lookup('nodeParseNone'));
- }
- else {
- nodes.__gcliQuery = arg.text;
- reply = new Conversion(nodes, arg, Status.VALID, '');
- }
-
- reply.matches = nodes;
- }
- }
- catch (ex) {
- reply = new Conversion(undefined, arg, Status.ERROR,
- l10n.lookup('nodeParseSyntax'));
- }
-
- return Promise.resolve(reply);
- },
-
- // onEnter: onEnter,
- // onLeave: onLeave,
- // onChange: onChange
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/number.js b/devtools/shared/gcli/source/lib/gcli/types/number.js
deleted file mode 100644
index 1057c4c73e7c..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/number.js
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-
-exports.items = [
- {
- // 'number' type
- // Has custom max / min / step values to control increment and decrement
- // and a boolean allowFloat property to clamp values to integers
- item: 'type',
- name: 'number',
-
- allowFloat: false,
- max: undefined,
- min: undefined,
- step: 1,
-
- constructor: function() {
- if (!this.allowFloat &&
- (this._isFloat(this.min) ||
- this._isFloat(this.max) ||
- this._isFloat(this.step))) {
- throw new Error('allowFloat is false, but non-integer values given in type spec');
- }
- },
-
- getSpec: function() {
- var spec = {
- name: 'number'
- };
- if (this.step !== 1) {
- spec.step = this.step;
- }
- if (this.max != null) {
- spec.max = this.max;
- }
- if (this.min != null) {
- spec.min = this.min;
- }
- if (this.allowFloat) {
- spec.allowFloat = true;
- }
- return (Object.keys(spec).length === 1) ? 'number' : spec;
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
- return '' + value;
- },
-
- getMin: function(context) {
- if (this.min != null) {
- if (typeof this.min === 'function') {
- return this.min(context);
- }
- if (typeof this.min === 'number') {
- return this.min;
- }
- }
- return undefined;
- },
-
- getMax: function(context) {
- if (this.max != null) {
- if (typeof this.max === 'function') {
- return this.max(context);
- }
- if (typeof this.max === 'number') {
- return this.max;
- }
- }
- return undefined;
- },
-
- parse: function(arg, context) {
- var msg;
- if (arg.text.replace(/^\s*-?/, '').length === 0) {
- return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
- }
-
- if (!this.allowFloat && (arg.text.includes('.'))) {
- msg = l10n.lookupFormat('typesNumberNotInt2', [ arg.text ]);
- return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
- }
-
- var value;
- if (this.allowFloat) {
- value = parseFloat(arg.text);
- }
- else {
- value = parseInt(arg.text, 10);
- }
-
- if (isNaN(value)) {
- msg = l10n.lookupFormat('typesNumberNan', [ arg.text ]);
- return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
- }
-
- var max = this.getMax(context);
- if (max != null && value > max) {
- msg = l10n.lookupFormat('typesNumberMax', [ value, max ]);
- return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
- }
-
- var min = this.getMin(context);
- if (min != null && value < min) {
- msg = l10n.lookupFormat('typesNumberMin', [ value, min ]);
- return Promise.resolve(new Conversion(undefined, arg, Status.ERROR, msg));
- }
-
- return Promise.resolve(new Conversion(value, arg));
- },
-
- nudge: function(value, by, context) {
- if (typeof value !== 'number' || isNaN(value)) {
- if (by < 0) {
- return this.getMax(context) || 1;
- }
- else {
- var min = this.getMin(context);
- return min != null ? min : 0;
- }
- }
-
- var newValue = value + (by * this.step);
-
- // Snap to the nearest incremental of the step
- if (by < 0) {
- newValue = Math.ceil(newValue / this.step) * this.step;
- }
- else {
- newValue = Math.floor(newValue / this.step) * this.step;
- if (this.getMax(context) == null) {
- return newValue;
- }
- }
- return this._boundsCheck(newValue, context);
- },
-
- // Return the input value so long as it is within the max/min bounds.
- // If it is lower than the minimum, return the minimum. If it is bigger
- // than the maximum then return the maximum.
- _boundsCheck: function(value, context) {
- var min = this.getMin(context);
- if (min != null && value < min) {
- return min;
- }
- var max = this.getMax(context);
- if (max != null && value > max) {
- return max;
- }
- return value;
- },
-
- // Return true if the given value is a finite number and not an integer,
- // else return false.
- _isFloat: function(value) {
- return ((typeof value === 'number') && isFinite(value) && (value % 1 !== 0));
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/resource.js b/devtools/shared/gcli/source/lib/gcli/types/resource.js
deleted file mode 100644
index 30b9f042f9c8..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/resource.js
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-exports.clearResourceCache = function() {
- ResourceCache.clear();
-};
-
-/**
- * Resources are bits of CSS and JavaScript that the page either includes
- * directly or as a result of reading some remote resource.
- * Resource should not be used directly, but instead through a sub-class like
- * CssResource or ScriptResource.
- */
-function Resource(name, type, inline, element) {
- this.name = name;
- this.type = type;
- this.inline = inline;
- this.element = element;
-}
-
-/**
- * Get the contents of the given resource as a string.
- * The base Resource leaves this unimplemented.
- */
-Resource.prototype.loadContents = function() {
- throw new Error('not implemented');
-};
-
-Resource.TYPE_SCRIPT = 'text/javascript';
-Resource.TYPE_CSS = 'text/css';
-
-/**
- * A CssResource provides an implementation of Resource that works for both
- * [style] elements and [link type='text/css'] elements in the [head].
- */
-function CssResource(domSheet) {
- this.name = domSheet.href;
- if (!this.name) {
- this.name = domSheet.ownerNode && domSheet.ownerNode.id ?
- 'css#' + domSheet.ownerNode.id :
- 'inline-css';
- }
-
- this.inline = (domSheet.href == null);
- this.type = Resource.TYPE_CSS;
- this.element = domSheet;
-}
-
-CssResource.prototype = Object.create(Resource.prototype);
-
-CssResource.prototype.loadContents = function() {
- return new Promise((resolve, reject) => {
- resolve(this.element.ownerNode.innerHTML);
- });
-};
-
-CssResource._getAllStyles = function(context) {
- var resources = [];
- if (context.environment.window == null) {
- return resources;
- }
-
- var doc = context.environment.window.document;
- Array.prototype.forEach.call(doc.styleSheets, function(domSheet) {
- CssResource._getStyle(domSheet, resources);
- });
-
- dedupe(resources, function(clones) {
- for (var i = 0; i < clones.length; i++) {
- clones[i].name = clones[i].name + '-' + i;
- }
- });
-
- return resources;
-};
-
-CssResource._getStyle = function(domSheet, resources) {
- var resource = ResourceCache.get(domSheet);
- if (!resource) {
- resource = new CssResource(domSheet);
- ResourceCache.add(domSheet, resource);
- }
- resources.push(resource);
-
- // Look for imported stylesheets
- try {
- Array.prototype.forEach.call(domSheet.cssRules, function(domRule) {
- if (domRule.type == CSSRule.IMPORT_RULE && domRule.styleSheet) {
- CssResource._getStyle(domRule.styleSheet, resources);
- }
- }, this);
- }
- catch (ex) {
- // For system stylesheets
- }
-};
-
-/**
- * A ScriptResource provides an implementation of Resource that works for
- * [script] elements (both with a src attribute, and used directly).
- */
-function ScriptResource(scriptNode) {
- this.name = scriptNode.src;
- if (!this.name) {
- this.name = scriptNode.id ?
- 'script#' + scriptNode.id :
- 'inline-script';
- }
-
- this.inline = (scriptNode.src === '' || scriptNode.src == null);
- this.type = Resource.TYPE_SCRIPT;
- this.element = scriptNode;
-}
-
-ScriptResource.prototype = Object.create(Resource.prototype);
-
-ScriptResource.prototype.loadContents = function() {
- return new Promise((resolve, reject) => {
- if (this.inline) {
- resolve(this.element.innerHTML);
- }
- else {
- // It would be good if there was a better way to get the script source
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function() {
- if (xhr.readyState !== xhr.DONE) {
- return;
- }
- resolve(xhr.responseText);
- };
- xhr.open('GET', this.element.src, true);
- xhr.send();
- }
- });
-};
-
-ScriptResource._getAllScripts = function(context) {
- if (context.environment.window == null) {
- return [];
- }
-
- var doc = context.environment.window.document;
- var scriptNodes = doc.querySelectorAll('script');
- var resources = Array.prototype.map.call(scriptNodes, function(scriptNode) {
- var resource = ResourceCache.get(scriptNode);
- if (!resource) {
- resource = new ScriptResource(scriptNode);
- ResourceCache.add(scriptNode, resource);
- }
- return resource;
- });
-
- dedupe(resources, function(clones) {
- for (var i = 0; i < clones.length; i++) {
- clones[i].name = clones[i].name + '-' + i;
- }
- });
-
- return resources;
-};
-
-/**
- * Find resources with the same name, and call onDupe to change the names
- */
-function dedupe(resources, onDupe) {
- // first create a map of name->[array of resources with same name]
- var names = {};
- resources.forEach(function(scriptResource) {
- if (names[scriptResource.name] == null) {
- names[scriptResource.name] = [];
- }
- names[scriptResource.name].push(scriptResource);
- });
-
- // Call the de-dupe function for each set of dupes
- Object.keys(names).forEach(function(name) {
- var clones = names[name];
- if (clones.length > 1) {
- onDupe(clones);
- }
- });
-}
-
-/**
- * A quick cache of resources against nodes
- * TODO: Potential memory leak when the target document has css or script
- * resources repeatedly added and removed. Solution might be to use a weak
- * hash map or some such.
- */
-var ResourceCache = {
- _cached: [],
-
- /**
- * Do we already have a resource that was created for the given node
- */
- get: function(node) {
- for (var i = 0; i < ResourceCache._cached.length; i++) {
- if (ResourceCache._cached[i].node === node) {
- return ResourceCache._cached[i].resource;
- }
- }
- return null;
- },
-
- /**
- * Add a resource for a given node
- */
- add: function(node, resource) {
- ResourceCache._cached.push({ node: node, resource: resource });
- },
-
- /**
- * Drop all cache entries. Helpful to prevent memory leaks
- */
- clear: function() {
- ResourceCache._cached = [];
- }
-};
-
-/**
- * The resource type itself
- */
-exports.items = [
- {
- item: 'type',
- name: 'resource',
- parent: 'selection',
- cacheable: false,
- include: null,
-
- constructor: function() {
- if (this.include !== Resource.TYPE_SCRIPT &&
- this.include !== Resource.TYPE_CSS &&
- this.include != null) {
- throw new Error('invalid include property: ' + this.include);
- }
- },
-
- lookup: function(context) {
- var resources = [];
- if (this.include !== Resource.TYPE_SCRIPT) {
- Array.prototype.push.apply(resources,
- CssResource._getAllStyles(context));
- }
- if (this.include !== Resource.TYPE_CSS) {
- Array.prototype.push.apply(resources,
- ScriptResource._getAllScripts(context));
- }
-
- return Promise.resolve(resources.map(function(resource) {
- return { name: resource.name, value: resource };
- }));
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/selection.js b/devtools/shared/gcli/source/lib/gcli/types/selection.js
deleted file mode 100644
index d0b252625860..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/selection.js
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var spell = require('../util/spell');
-var Type = require('./types').Type;
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-var BlankArgument = require('./types').BlankArgument;
-
-/**
- * A selection allows the user to pick a value from known set of options.
- * An option is made up of a name (which is what the user types) and a value
- * (which is passed to exec)
- * @param typeSpec Object containing properties that describe how this
- * selection functions. Properties include:
- * - lookup: An array of objects, one for each option, which contain name and
- * value properties. lookup can be a function which returns this array
- * - data: An array of strings - alternative to 'lookup' where the valid values
- * are strings. i.e. there is no mapping between what is typed and the value
- * that is used by the program
- * - stringifyProperty: Conversion from value to string is generally a process
- * of looking through all the valid options for a matching value, and using
- * the associated name. However the name maybe available directly from the
- * value using a property lookup. Setting 'stringifyProperty' allows
- * SelectionType to take this shortcut.
- * - cacheable: If lookup is a function, then we normally assume that
- * the values fetched can change. Setting 'cacheable:true' enables internal
- * caching.
- */
-function SelectionType(typeSpec) {
- if (typeSpec) {
- Object.keys(typeSpec).forEach(function(key) {
- this[key] = typeSpec[key];
- }, this);
- }
-
- if (this.name !== 'selection' &&
- this.lookup == null && this.data == null) {
- throw new Error(this.name + ' has no lookup or data');
- }
-
- this._dataToLookup = this._dataToLookup.bind(this);
-}
-
-SelectionType.prototype = Object.create(Type.prototype);
-
-SelectionType.prototype.getSpec = function(commandName, paramName) {
- var spec = { name: 'selection' };
- if (this.lookup != null && typeof this.lookup !== 'function') {
- spec.lookup = this.lookup;
- }
- if (this.data != null && typeof this.data !== 'function') {
- spec.data = this.data;
- }
- if (this.stringifyProperty != null) {
- spec.stringifyProperty = this.stringifyProperty;
- }
- if (this.cacheable) {
- spec.cacheable = true;
- }
- if (typeof this.lookup === 'function' || typeof this.data === 'function') {
- spec.commandName = commandName;
- spec.paramName = paramName;
- spec.remoteLookup = true;
- }
- return spec;
-};
-
-SelectionType.prototype.stringify = function(value, context) {
- if (value == null) {
- return '';
- }
- if (this.stringifyProperty != null) {
- return value[this.stringifyProperty];
- }
-
- return this.getLookup(context).then(lookup => {
- var name = null;
- lookup.some(function(item) {
- if (item.value === value) {
- name = item.name;
- return true;
- }
- return false;
- }, this);
- return name;
- });
-};
-
-/**
- * If typeSpec contained cacheable:true then calls to parse() work on cached
- * data. clearCache() enables the cache to be cleared.
- */
-SelectionType.prototype.clearCache = function() {
- this._cachedLookup = undefined;
-};
-
-/**
- * There are several ways to get selection data. This unifies them into one
- * single function.
- * @return An array of objects with name and value properties.
- */
-SelectionType.prototype.getLookup = function(context) {
- if (this._cachedLookup != null) {
- return this._cachedLookup;
- }
-
- var reply;
-
- if (this.remoteLookup) {
- reply = this.front.getSelectionLookup(this.commandName, this.paramName);
- reply = resolve(reply, context);
- }
- else if (typeof this.lookup === 'function') {
- reply = resolve(this.lookup.bind(this), context);
- }
- else if (this.lookup != null) {
- reply = resolve(this.lookup, context);
- }
- else if (this.data != null) {
- reply = resolve(this.data, context).then(this._dataToLookup);
- }
- else {
- throw new Error(this.name + ' has no lookup or data');
- }
-
- if (this.cacheable) {
- this._cachedLookup = reply;
- }
-
- if (reply == null) {
- console.error(arguments);
- }
- return reply;
-};
-
-/**
- * Both 'lookup' and 'data' properties (see docs on SelectionType constructor)
- * in addition to being real data can be a function or a promise, or even a
- * function which returns a promise of real data, etc. This takes a thing and
- * returns a promise of actual values.
- */
-function resolve(thing, context) {
- return Promise.resolve(thing).then(function(resolved) {
- if (typeof resolved === 'function') {
- return resolve(resolved(context), context);
- }
- return resolved;
- });
-}
-
-/**
- * Selection can be provided with either a lookup object (in the 'lookup'
- * property) or an array of strings (in the 'data' property). Internally we
- * always use lookup, so we need a way to convert a 'data' array to a lookup.
- */
-SelectionType.prototype._dataToLookup = function(data) {
- if (!Array.isArray(data)) {
- throw new Error('data for ' + this.name + ' resolved to non-array');
- }
-
- return data.map(function(option) {
- return { name: option, value: option };
- });
-};
-
-/**
- * Return a list of possible completions for the given arg.
- * @param arg The initial input to match
- * @return A trimmed array of string:value pairs
- */
-exports.findPredictions = function(arg, lookup) {
- var predictions = [];
- var i, option;
- var maxPredictions = Conversion.maxPredictions;
- var match = arg.text.toLowerCase();
-
- // If the arg has a suffix then we're kind of 'done'. Only an exact match
- // will do.
- if (arg.suffix.length > 0) {
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option.name === arg.text) {
- predictions.push(option);
- }
- }
-
- return predictions;
- }
-
- // Cache lower case versions of all the option names
- for (i = 0; i < lookup.length; i++) {
- option = lookup[i];
- if (option._gcliLowerName == null) {
- option._gcliLowerName = option.name.toLowerCase();
- }
- }
-
- // Exact hidden matches. If 'hidden: true' then we only allow exact matches
- // All the tests after here check that !isHidden(option)
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option.name === arg.text) {
- predictions.push(option);
- }
- }
-
- // Start with prefix matching
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option._gcliLowerName.indexOf(match) === 0 && !isHidden(option)) {
- if (!predictions.includes(option)) {
- predictions.push(option);
- }
- }
- }
-
- // Try infix matching if we get less half max matched
- if (predictions.length < (maxPredictions / 2)) {
- for (i = 0; i < lookup.length && predictions.length < maxPredictions; i++) {
- option = lookup[i];
- if (option._gcliLowerName.includes(match) && !isHidden(option)) {
- if (!predictions.includes(option)) {
- predictions.push(option);
- }
- }
- }
- }
-
- // Try fuzzy matching if we don't get a prefix match
- if (predictions.length === 0) {
- var names = [];
- lookup.forEach(function(opt) {
- if (!isHidden(opt)) {
- names.push(opt.name);
- }
- });
- var corrected = spell.correct(match, names);
- if (corrected) {
- lookup.forEach(function(opt) {
- if (opt.name === corrected) {
- predictions.push(opt);
- }
- }, this);
- }
- }
-
- return predictions;
-};
-
-SelectionType.prototype.parse = function(arg, context) {
- return Promise.resolve(this.getLookup(context)).then(lookup => {
- var predictions = exports.findPredictions(arg, lookup);
- return exports.convertPredictions(arg, predictions);
- });
-};
-
-/**
- * Decide what sort of conversion to return based on the available predictions
- * and how they match the passed arg
- */
-exports.convertPredictions = function(arg, predictions) {
- if (predictions.length === 0) {
- var msg = l10n.lookupFormat('typesSelectionNomatch', [ arg.text ]);
- return new Conversion(undefined, arg, Status.ERROR, msg,
- Promise.resolve(predictions));
- }
-
- if (predictions[0].name === arg.text) {
- var value = predictions[0].value;
- return new Conversion(value, arg, Status.VALID, '',
- Promise.resolve(predictions));
- }
-
- return new Conversion(undefined, arg, Status.INCOMPLETE, '',
- Promise.resolve(predictions));
-};
-
-/**
- * Checking that an option is hidden involves messing in properties on the
- * value right now (which isn't a good idea really) we really should be marking
- * that on the option, so this encapsulates the problem
- */
-function isHidden(option) {
- return option.hidden === true ||
- (option.value != null && option.value.hidden);
-}
-
-SelectionType.prototype.getBlank = function(context) {
- var predictFunc = context2 => {
- return Promise.resolve(this.getLookup(context2)).then(function(lookup) {
- return lookup.filter(function(option) {
- return !isHidden(option);
- }).slice(0, Conversion.maxPredictions - 1);
- });
- };
-
- return new Conversion(undefined, new BlankArgument(), Status.INCOMPLETE, '',
- predictFunc);
-};
-
-/**
- * Increment and decrement are confusing for selections. +1 is -1 and -1 is +1.
- * Given an array e.g. [ 'a', 'b', 'c' ] with the current selection on 'b',
- * displayed to the user in the natural way, i.e.:
- *
- * 'a'
- * 'b' <- highlighted as current value
- * 'c'
- *
- * Pressing the UP arrow should take us to 'a', which decrements this index
- * (compare pressing UP on a number which would increment the number)
- *
- * So for selections, we treat +1 as -1 and -1 as +1.
- */
-SelectionType.prototype.nudge = function(value, by, context) {
- return this.getLookup(context).then(lookup => {
- var index = this._findValue(lookup, value);
- if (index === -1) {
- if (by < 0) {
- // We're supposed to be doing a decrement (which means +1), but the
- // value isn't found, so we reset the index to the top of the list
- // which is index 0
- index = 0;
- }
- else {
- // For an increment operation when there is nothing to start from, we
- // want to start from the top, i.e. index 0, so the value before we
- // 'increment' (see note above) must be 1.
- index = 1;
- }
- }
-
- // This is where we invert the sense of up/down (see doc comment)
- index -= by;
-
- if (index >= lookup.length) {
- index = 0;
- }
- return lookup[index].value;
- });
-};
-
-/**
- * Walk through an array of { name:.., value:... } objects looking for a
- * matching value (using strict equality), returning the matched index (or -1
- * if not found).
- * @param lookup Array of objects with name/value properties to search through
- * @param value The value to search for
- * @return The index at which the match was found, or -1 if no match was found
- */
-SelectionType.prototype._findValue = function(lookup, value) {
- var index = -1;
- for (var i = 0; i < lookup.length; i++) {
- var pair = lookup[i];
- if (pair.value === value) {
- index = i;
- break;
- }
- }
- return index;
-};
-
-/**
- * This is how we indicate to SelectionField that we have predictions that
- * might work in a menu.
- */
-SelectionType.prototype.hasPredictions = true;
-
-SelectionType.prototype.name = 'selection';
-
-exports.SelectionType = SelectionType;
-exports.items = [ SelectionType ];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/setting.js b/devtools/shared/gcli/source/lib/gcli/types/setting.js
deleted file mode 100644
index 26c6f40638a3..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/setting.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-exports.items = [
- {
- // A type for selecting a known setting
- item: 'type',
- name: 'setting',
- parent: 'selection',
- cacheable: true,
- lookup: function(context) {
- var settings = context.system.settings;
-
- // Lazily add a settings.onChange listener to clear the cache
- if (!this._registeredListener) {
- settings.onChange.add(function(ev) {
- this.clearCache();
- }, this);
- this._registeredListener = true;
- }
-
- return settings.getAll().map(function(setting) {
- return { name: setting.name, value: setting };
- });
- }
- },
- {
- // A type for entering the value of a known setting
- // Customizations:
- // - settingParamName The name of the setting parameter so we can customize
- // the type that we are expecting to read
- item: 'type',
- name: 'settingValue',
- parent: 'delegate',
- settingParamName: 'setting',
- delegateType: function(context) {
- if (context != null) {
- var setting = context.getArgsObject()[this.settingParamName];
- if (setting != null) {
- return setting.type;
- }
- }
-
- return 'blank';
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/string.js b/devtools/shared/gcli/source/lib/gcli/types/string.js
deleted file mode 100644
index a3aebacadf42..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/string.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-
-exports.items = [
- {
- // 'string' the most basic string type where all we need to do is to take
- // care of converting escaped characters like \t, \n, etc.
- // For the full list see
- // https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Values,_variables,_and_literals
- // The exception is that we ignore \b because replacing '\b' characters in
- // stringify() with their escaped version injects '\\b' all over the place
- // and the need to support \b seems low)
- // Customizations:
- // allowBlank: Allow a blank string to be counted as valid
- item: 'type',
- name: 'string',
- allowBlank: false,
-
- getSpec: function() {
- return this.allowBlank ?
- { name: 'string', allowBlank: true } :
- 'string';
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
-
- return value
- .replace(/\\/g, '\\\\')
- .replace(/\f/g, '\\f')
- .replace(/\n/g, '\\n')
- .replace(/\r/g, '\\r')
- .replace(/\t/g, '\\t')
- .replace(/\v/g, '\\v')
- .replace(/\n/g, '\\n')
- .replace(/\r/g, '\\r')
- .replace(/ /g, '\\ ')
- .replace(/'/g, '\\\'')
- .replace(/"/g, '\\"')
- .replace(/{/g, '\\{')
- .replace(/}/g, '\\}');
- },
-
- parse: function(arg, context) {
- if (!this.allowBlank && (arg.text == null || arg.text === '')) {
- return Promise.resolve(new Conversion(undefined, arg, Status.INCOMPLETE, ''));
- }
-
- // The string '\\' (i.e. an escaped \ (represented here as '\\\\' because it
- // is double escaped)) is first converted to a private unicode character and
- // then at the end from \uF000 to a single '\' to avoid the string \\n being
- // converted first to \n and then to a
- var value = arg.text
- .replace(/\\\\/g, '\uF000')
- .replace(/\\f/g, '\f')
- .replace(/\\n/g, '\n')
- .replace(/\\r/g, '\r')
- .replace(/\\t/g, '\t')
- .replace(/\\v/g, '\v')
- .replace(/\\n/g, '\n')
- .replace(/\\r/g, '\r')
- .replace(/\\ /g, ' ')
- .replace(/\\'/g, '\'')
- .replace(/\\"/g, '"')
- .replace(/\\{/g, '{')
- .replace(/\\}/g, '}')
- .replace(/\uF000/g, '\\');
-
- return Promise.resolve(new Conversion(value, arg));
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/types.js b/devtools/shared/gcli/source/lib/gcli/types/types.js
deleted file mode 100644
index 60ad940e67a8..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/types.js
+++ /dev/null
@@ -1,1146 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-
-/**
- * We record where in the input string an argument comes so we can report
- * errors against those string positions.
- * @param text The string (trimmed) that contains the argument
- * @param prefix Knowledge of quotation marks and whitespace used prior to the
- * text in the input string allows us to re-generate the original input from
- * the arguments.
- * @param suffix Any quotation marks and whitespace used after the text.
- * Whitespace is normally placed in the prefix to the succeeding argument, but
- * can be used here when this is the last argument.
- * @constructor
- */
-function Argument(text, prefix, suffix) {
- if (text === undefined) {
- this.text = '';
- this.prefix = '';
- this.suffix = '';
- }
- else {
- this.text = text;
- this.prefix = prefix !== undefined ? prefix : '';
- this.suffix = suffix !== undefined ? suffix : '';
- }
-}
-
-Argument.prototype.type = 'Argument';
-
-/**
- * Return the result of merging these arguments.
- * case and some of the arguments are in quotation marks?
- */
-Argument.prototype.merge = function(following) {
- // Is it possible that this gets called when we're merging arguments
- // for the single string?
- return new Argument(
- this.text + this.suffix + following.prefix + following.text,
- this.prefix, following.suffix);
-};
-
-/**
- * Returns a new Argument like this one but with various items changed.
- * @param options Values to use in creating a new Argument.
- * Warning: some implementations of beget make additions to the options
- * argument. You should be aware of this in the unlikely event that you want to
- * reuse 'options' arguments.
- * Properties:
- * - text: The new text value
- * - prefixSpace: Should the prefix be altered to begin with a space?
- * - prefixPostSpace: Should the prefix be altered to end with a space?
- * - suffixSpace: Should the suffix be altered to end with a space?
- * - type: Constructor to use in creating new instances. Default: Argument
- * - dontQuote: Should we avoid adding prefix/suffix quotes when the text value
- * has a space? Needed when we're completing a sub-command.
- */
-Argument.prototype.beget = function(options) {
- var text = this.text;
- var prefix = this.prefix;
- var suffix = this.suffix;
-
- if (options.text != null) {
- text = options.text;
-
- // We need to add quotes when the replacement string has spaces or is empty
- if (!options.dontQuote) {
- var needsQuote = text.includes(' ') || text.length === 0;
- var hasQuote = /['"]$/.test(prefix);
- if (needsQuote && !hasQuote) {
- prefix = prefix + '\'';
- suffix = '\'' + suffix;
- }
- }
- }
-
- if (options.prefixSpace && prefix.charAt(0) !== ' ') {
- prefix = ' ' + prefix;
- }
-
- if (options.prefixPostSpace && prefix.charAt(prefix.length - 1) !== ' ') {
- prefix = prefix + ' ';
- }
-
- if (options.suffixSpace && suffix.charAt(suffix.length - 1) !== ' ') {
- suffix = suffix + ' ';
- }
-
- if (text === this.text && suffix === this.suffix && prefix === this.prefix) {
- return this;
- }
-
- var ArgumentType = options.type || Argument;
- return new ArgumentType(text, prefix, suffix);
-};
-
-/**
- * We need to keep track of which assignment we've been assigned to
- */
-Object.defineProperty(Argument.prototype, 'assignment', {
- get: function() { return this._assignment; },
- set: function(assignment) { this._assignment = assignment; },
- enumerable: true
-});
-
-/**
- * Sub-classes of Argument are collections of arguments, getArgs() gets access
- * to the members of the collection in order to do things like re-create input
- * command lines. For the simple Argument case it's just an array containing
- * only this.
- */
-Argument.prototype.getArgs = function() {
- return [ this ];
-};
-
-/**
- * We define equals to mean all arg properties are strict equals.
- * Used by Conversion.argEquals and Conversion.equals and ultimately
- * Assignment.equals to avoid reporting a change event when a new conversion
- * is assigned.
- */
-Argument.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null || !(that instanceof Argument)) {
- return false;
- }
-
- return this.text === that.text &&
- this.prefix === that.prefix && this.suffix === that.suffix;
-};
-
-/**
- * Helper when we're putting arguments back together
- */
-Argument.prototype.toString = function() {
- // BUG 664207: We should re-escape escaped characters
- // But can we do that reliably?
- return this.prefix + this.text + this.suffix;
-};
-
-/**
- * Merge an array of arguments into a single argument.
- * All Arguments in the array are expected to have the same emitter
- */
-Argument.merge = function(argArray, start, end) {
- start = (start === undefined) ? 0 : start;
- end = (end === undefined) ? argArray.length : end;
-
- var joined;
- for (var i = start; i < end; i++) {
- var arg = argArray[i];
- if (!joined) {
- joined = arg;
- }
- else {
- joined = joined.merge(arg);
- }
- }
- return joined;
-};
-
-/**
- * For test/debug use only. The output from this function is subject to wanton
- * random change without notice, and should not be relied upon to even exist
- * at some later date.
- */
-Object.defineProperty(Argument.prototype, '_summaryJson', {
- get: function() {
- var assignStatus = this.assignment == null ?
- 'null' :
- this.assignment.param.name;
- return '<' + this.prefix + ':' + this.text + ':' + this.suffix + '>' +
- ' (a=' + assignStatus + ',' + ' t=' + this.type + ')';
- },
- enumerable: true
-});
-
-exports.Argument = Argument;
-
-
-/**
- * BlankArgument is a marker that the argument wasn't typed but is there to
- * fill a slot. Assignments begin with their arg set to a BlankArgument.
- */
-function BlankArgument() {
- this.text = '';
- this.prefix = '';
- this.suffix = '';
-}
-
-BlankArgument.prototype = Object.create(Argument.prototype);
-
-BlankArgument.prototype.type = 'BlankArgument';
-
-exports.BlankArgument = BlankArgument;
-
-
-/**
- * ScriptArgument is a marker that the argument is designed to be JavaScript.
- * It also implements the special rules that spaces after the { or before the
- * } are part of the pre/suffix rather than the content, and that they are
- * never 'blank' so they can be used by Requisition._split() and not raise an
- * ERROR status due to being blank.
- */
-function ScriptArgument(text, prefix, suffix) {
- this.text = text !== undefined ? text : '';
- this.prefix = prefix !== undefined ? prefix : '';
- this.suffix = suffix !== undefined ? suffix : '';
-
- ScriptArgument._moveSpaces(this);
-}
-
-ScriptArgument.prototype = Object.create(Argument.prototype);
-
-ScriptArgument.prototype.type = 'ScriptArgument';
-
-/**
- * Private/Dangerous: Alters a ScriptArgument to move the spaces at the start
- * or end of the 'text' into the prefix/suffix. With a string, " a " is 3 chars
- * long, but with a ScriptArgument, { a } is only one char long.
- * Arguments are generally supposed to be immutable, so this method should only
- * be called on a ScriptArgument that isn't exposed to the outside world yet.
- */
-ScriptArgument._moveSpaces = function(arg) {
- while (arg.text.charAt(0) === ' ') {
- arg.prefix = arg.prefix + ' ';
- arg.text = arg.text.substring(1);
- }
-
- while (arg.text.charAt(arg.text.length - 1) === ' ') {
- arg.suffix = ' ' + arg.suffix;
- arg.text = arg.text.slice(0, -1);
- }
-};
-
-/**
- * As Argument.beget that implements the space rule documented in the ctor.
- */
-ScriptArgument.prototype.beget = function(options) {
- options.type = ScriptArgument;
- var begotten = Argument.prototype.beget.call(this, options);
- ScriptArgument._moveSpaces(begotten);
- return begotten;
-};
-
-exports.ScriptArgument = ScriptArgument;
-
-
-/**
- * Commands like 'echo' with a single string argument, and used with the
- * special format like: 'echo a b c' effectively have a number of arguments
- * merged together.
- */
-function MergedArgument(args, start, end) {
- if (!Array.isArray(args)) {
- throw new Error('args is not an array of Arguments');
- }
-
- if (start === undefined) {
- this.args = args;
- }
- else {
- this.args = args.slice(start, end);
- }
-
- var arg = Argument.merge(this.args);
- this.text = arg.text;
- this.prefix = arg.prefix;
- this.suffix = arg.suffix;
-}
-
-MergedArgument.prototype = Object.create(Argument.prototype);
-
-MergedArgument.prototype.type = 'MergedArgument';
-
-/**
- * Keep track of which assignment we've been assigned to, and allow the
- * original args to do the same.
- */
-Object.defineProperty(MergedArgument.prototype, 'assignment', {
- get: function() { return this._assignment; },
- set: function(assignment) {
- this._assignment = assignment;
-
- this.args.forEach(function(arg) {
- arg.assignment = assignment;
- }, this);
- },
- enumerable: true
-});
-
-MergedArgument.prototype.getArgs = function() {
- return this.args;
-};
-
-MergedArgument.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null || !(that instanceof MergedArgument)) {
- return false;
- }
-
- // We might need to add a check that args is the same here
-
- return this.text === that.text &&
- this.prefix === that.prefix && this.suffix === that.suffix;
-};
-
-exports.MergedArgument = MergedArgument;
-
-
-/**
- * TrueNamedArguments are for when we have an argument like --verbose which
- * has a boolean value, and thus the opposite of '--verbose' is ''.
- */
-function TrueNamedArgument(arg) {
- this.arg = arg;
- this.text = arg.text;
- this.prefix = arg.prefix;
- this.suffix = arg.suffix;
-}
-
-TrueNamedArgument.prototype = Object.create(Argument.prototype);
-
-TrueNamedArgument.prototype.type = 'TrueNamedArgument';
-
-Object.defineProperty(TrueNamedArgument.prototype, 'assignment', {
- get: function() { return this._assignment; },
- set: function(assignment) {
- this._assignment = assignment;
-
- if (this.arg) {
- this.arg.assignment = assignment;
- }
- },
- enumerable: true
-});
-
-TrueNamedArgument.prototype.getArgs = function() {
- return [ this.arg ];
-};
-
-TrueNamedArgument.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null || !(that instanceof TrueNamedArgument)) {
- return false;
- }
-
- return this.text === that.text &&
- this.prefix === that.prefix && this.suffix === that.suffix;
-};
-
-/**
- * As Argument.beget that rebuilds nameArg and valueArg
- */
-TrueNamedArgument.prototype.beget = function(options) {
- if (options.text) {
- console.error('Can\'t change text of a TrueNamedArgument', this, options);
- }
-
- options.type = TrueNamedArgument;
- var begotten = Argument.prototype.beget.call(this, options);
- begotten.arg = new Argument(begotten.text, begotten.prefix, begotten.suffix);
- return begotten;
-};
-
-exports.TrueNamedArgument = TrueNamedArgument;
-
-
-/**
- * FalseNamedArguments are for when we don't have an argument like --verbose
- * which has a boolean value, and thus the opposite of '' is '--verbose'.
- */
-function FalseNamedArgument() {
- this.text = '';
- this.prefix = '';
- this.suffix = '';
-}
-
-FalseNamedArgument.prototype = Object.create(Argument.prototype);
-
-FalseNamedArgument.prototype.type = 'FalseNamedArgument';
-
-FalseNamedArgument.prototype.getArgs = function() {
- return [ ];
-};
-
-FalseNamedArgument.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null || !(that instanceof FalseNamedArgument)) {
- return false;
- }
-
- return this.text === that.text &&
- this.prefix === that.prefix && this.suffix === that.suffix;
-};
-
-exports.FalseNamedArgument = FalseNamedArgument;
-
-
-/**
- * A named argument is for cases where we have input in one of the following
- * formats:
- *
- *
--param value
- *
-p value
- *
- * We model this as a normal argument but with a long prefix.
- *
- * There are 2 ways to construct a NamedArgument. One using 2 Arguments which
- * are taken to be the argument for the name (e.g. '--param') and one for the
- * value to assign to that parameter.
- * Alternatively, you can pass in the text/prefix/suffix values in the same
- * way as an Argument is constructed. If you do this then you are expected to
- * assign to nameArg and valueArg before exposing the new NamedArgument.
- */
-function NamedArgument() {
- if (typeof arguments[0] === 'string') {
- this.nameArg = null;
- this.valueArg = null;
- this.text = arguments[0];
- this.prefix = arguments[1];
- this.suffix = arguments[2];
- }
- else if (arguments[1] == null) {
- this.nameArg = arguments[0];
- this.valueArg = null;
- this.text = '';
- this.prefix = this.nameArg.toString();
- this.suffix = '';
- }
- else {
- this.nameArg = arguments[0];
- this.valueArg = arguments[1];
- this.text = this.valueArg.text;
- this.prefix = this.nameArg.toString() + this.valueArg.prefix;
- this.suffix = this.valueArg.suffix;
- }
-}
-
-NamedArgument.prototype = Object.create(Argument.prototype);
-
-NamedArgument.prototype.type = 'NamedArgument';
-
-Object.defineProperty(NamedArgument.prototype, 'assignment', {
- get: function() { return this._assignment; },
- set: function(assignment) {
- this._assignment = assignment;
-
- this.nameArg.assignment = assignment;
- if (this.valueArg != null) {
- this.valueArg.assignment = assignment;
- }
- },
- enumerable: true
-});
-
-NamedArgument.prototype.getArgs = function() {
- return this.valueArg ? [ this.nameArg, this.valueArg ] : [ this.nameArg ];
-};
-
-NamedArgument.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null) {
- return false;
- }
-
- if (!(that instanceof NamedArgument)) {
- return false;
- }
-
- // We might need to add a check that nameArg and valueArg are the same
-
- return this.text === that.text &&
- this.prefix === that.prefix && this.suffix === that.suffix;
-};
-
-/**
- * As Argument.beget that rebuilds nameArg and valueArg
- */
-NamedArgument.prototype.beget = function(options) {
- options.type = NamedArgument;
- var begotten = Argument.prototype.beget.call(this, options);
-
- // Cut the prefix into |whitespace|non-whitespace|whitespace+quote so we can
- // rebuild nameArg and valueArg from the parts
- var matches = /^([\s]*)([^\s]*)([\s]*['"]?)$/.exec(begotten.prefix);
-
- if (this.valueArg == null && begotten.text === '') {
- begotten.nameArg = new Argument(matches[2], matches[1], matches[3]);
- begotten.valueArg = null;
- }
- else {
- begotten.nameArg = new Argument(matches[2], matches[1], '');
- begotten.valueArg = new Argument(begotten.text, matches[3], begotten.suffix);
- }
-
- return begotten;
-};
-
-exports.NamedArgument = NamedArgument;
-
-
-/**
- * An argument the groups together a number of plain arguments together so they
- * can be jointly assigned to a single array parameter
- */
-function ArrayArgument() {
- this.args = [];
-}
-
-ArrayArgument.prototype = Object.create(Argument.prototype);
-
-ArrayArgument.prototype.type = 'ArrayArgument';
-
-ArrayArgument.prototype.addArgument = function(arg) {
- this.args.push(arg);
-};
-
-ArrayArgument.prototype.addArguments = function(args) {
- Array.prototype.push.apply(this.args, args);
-};
-
-ArrayArgument.prototype.getArguments = function() {
- return this.args;
-};
-
-Object.defineProperty(ArrayArgument.prototype, 'assignment', {
- get: function() { return this._assignment; },
- set: function(assignment) {
- this._assignment = assignment;
-
- this.args.forEach(function(arg) {
- arg.assignment = assignment;
- }, this);
- },
- enumerable: true
-});
-
-ArrayArgument.prototype.getArgs = function() {
- return this.args;
-};
-
-ArrayArgument.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null) {
- return false;
- }
-
- if (that.type !== 'ArrayArgument') {
- return false;
- }
-
- if (this.args.length !== that.args.length) {
- return false;
- }
-
- for (var i = 0; i < this.args.length; i++) {
- if (!this.args[i].equals(that.args[i])) {
- return false;
- }
- }
-
- return true;
-};
-
-/**
- * Helper when we're putting arguments back together
- */
-ArrayArgument.prototype.toString = function() {
- return '{' + this.args.map(function(arg) {
- return arg.toString();
- }, this).join(',') + '}';
-};
-
-exports.ArrayArgument = ArrayArgument;
-
-/**
- * Some types can detect validity, that is to say they can distinguish between
- * valid and invalid values.
- * We might want to change these constants to be numbers for better performance
- */
-var Status = {
- /**
- * The conversion process worked without any problem, and the value is
- * valid. There are a number of failure states, so the best way to check
- * for failure is (x !== Status.VALID)
- */
- VALID: {
- toString: function() { return 'VALID'; },
- valueOf: function() { return 0; }
- },
-
- /**
- * A conversion process failed, however it was noted that the string
- * provided to 'parse()' could be VALID by the addition of more characters,
- * so the typing may not be actually incorrect yet, just unfinished.
- * @see Status.ERROR
- */
- INCOMPLETE: {
- toString: function() { return 'INCOMPLETE'; },
- valueOf: function() { return 1; }
- },
-
- /**
- * The conversion process did not work, the value should be null and a
- * reason for failure should have been provided. In addition some
- * completion values may be available.
- * @see Status.INCOMPLETE
- */
- ERROR: {
- toString: function() { return 'ERROR'; },
- valueOf: function() { return 2; }
- },
-
- /**
- * A combined status is the worser of the provided statuses. The statuses
- * can be provided either as a set of arguments or a single array
- */
- combine: function() {
- var combined = Status.VALID;
- for (var i = 0; i < arguments.length; i++) {
- var status = arguments[i];
- if (Array.isArray(status)) {
- status = Status.combine.apply(null, status);
- }
- if (status > combined) {
- combined = status;
- }
- }
- return combined;
- },
-
- fromString: function(str) {
- switch (str) {
- case Status.VALID.toString():
- return Status.VALID;
- case Status.INCOMPLETE.toString():
- return Status.INCOMPLETE;
- case Status.ERROR.toString():
- return Status.ERROR;
- default:
- throw new Error('\'' + str + '\' is not a status');
- }
- }
-};
-
-exports.Status = Status;
-
-
-/**
- * The type.parse() method converts an Argument into a value, Conversion is
- * a wrapper to that value.
- * Conversion is needed to collect a number of properties related to that
- * conversion in one place, i.e. to handle errors and provide traceability.
- * @param value The result of the conversion. null if status == VALID
- * @param arg The data from which the conversion was made
- * @param status See the Status values [VALID|INCOMPLETE|ERROR] defined above.
- * The default status is Status.VALID.
- * @param message If status=ERROR, there should be a message to describe the
- * error. A message is not needed unless for other statuses, but could be
- * present for any status including VALID (in the case where we want to note a
- * warning, for example).
- * See BUG 664676: GCLI conversion error messages should be localized
- * @param predictions If status=INCOMPLETE, there could be predictions as to
- * the options available to complete the input.
- * We generally expect there to be about 7 predictions (to match human list
- * comprehension ability) however it is valid to provide up to about 20,
- * or less. It is the job of the predictor to decide a smart cut-off.
- * For example if there are 4 very good matches and 4 very poor ones,
- * probably only the 4 very good matches should be presented.
- * The predictions are presented either as an array of prediction objects or as
- * a function which returns this array when called with no parameters.
- * Each prediction object has the following shape:
- * {
- * name: '...', // textual completion. i.e. what the cli uses
- * value: { ... }, // value behind the textual completion
- * incomplete: true // this completion is only partial (optional)
- * }
- * The 'incomplete' property could be used to denote a valid completion which
- * could have sub-values (e.g. for tree navigation).
- */
-function Conversion(value, arg, status, message, predictions) {
- if (arg == null) {
- throw new Error('Missing arg');
- }
-
- if (predictions != null && typeof predictions !== 'function' &&
- !Array.isArray(predictions) && typeof predictions.then !== 'function') {
- throw new Error('predictions exists but is not a promise, function or array');
- }
-
- if (status === Status.ERROR && !message) {
- throw new Error('Conversion has status=ERROR but no message');
- }
-
- this.value = value;
- this.arg = arg;
- this._status = status || Status.VALID;
- this.message = message;
- this.predictions = predictions;
-}
-
-/**
- * Ensure that all arguments that are part of this conversion know what they
- * are assigned to.
- * @param assignment The Assignment (param/conversion link) to inform the
- * argument about.
- */
-Object.defineProperty(Conversion.prototype, 'assignment', {
- get: function() { return this.arg.assignment; },
- set: function(assignment) { this.arg.assignment = assignment; },
- enumerable: true
-});
-
-/**
- * Work out if there is information provided in the contained argument.
- */
-Conversion.prototype.isDataProvided = function() {
- return this.arg.type !== 'BlankArgument';
-};
-
-/**
- * 2 conversions are equal if and only if their args are equal (argEquals) and
- * their values are equal (valueEquals).
- * @param that The conversion object to compare against.
- */
-Conversion.prototype.equals = function(that) {
- if (this === that) {
- return true;
- }
- if (that == null) {
- return false;
- }
- return this.valueEquals(that) && this.argEquals(that);
-};
-
-/**
- * Check that the value in this conversion is strict equal to the value in the
- * provided conversion.
- * @param that The conversion to compare values with
- */
-Conversion.prototype.valueEquals = function(that) {
- return that != null && this.value === that.value;
-};
-
-/**
- * Check that the argument in this conversion is equal to the value in the
- * provided conversion as defined by the argument (i.e. arg.equals).
- * @param that The conversion to compare arguments with
- */
-Conversion.prototype.argEquals = function(that) {
- return that == null ? false : this.arg.equals(that.arg);
-};
-
-/**
- * Accessor for the status of this conversion
- */
-Conversion.prototype.getStatus = function(arg) {
- return this._status;
-};
-
-/**
- * Defined by the toString() value provided by the argument
- */
-Conversion.prototype.toString = function() {
- return this.arg.toString();
-};
-
-/**
- * If status === INCOMPLETE, then we may be able to provide predictions as to
- * how the argument can be completed.
- * @return An array of items, or a promise of an array of items, where each
- * item is an object with the following properties:
- * - name (mandatory): Displayed to the user, and typed in. No whitespace
- * - description (optional): Short string for display in a tool-tip
- * - manual (optional): Longer description which details usage
- * - incomplete (optional): Indicates that the prediction if used should not
- * be considered necessarily sufficient, which typically will mean that the
- * UI should not append a space to the completion
- * - value (optional): If a value property is present, this will be used as the
- * value of the conversion, otherwise the item itself will be used.
- */
-Conversion.prototype.getPredictions = function(context) {
- if (typeof this.predictions === 'function') {
- return this.predictions(context);
- }
- return Promise.resolve(this.predictions || []);
-};
-
-/**
- * Return a promise of an index constrained by the available predictions.
- * i.e. (index % predicitons.length)
- * This code can probably be removed when the Firefox developer toolbar isn't
- * needed any more.
- */
-Conversion.prototype.constrainPredictionIndex = function(context, index) {
- if (index == null) {
- return Promise.resolve();
- }
-
- return this.getPredictions(context).then(value => {
- if (value.length === 0) {
- return undefined;
- }
-
- index = index % value.length;
- if (index < 0) {
- index = value.length + index;
- }
- return index;
- });
-};
-
-/**
- * Constant to allow everyone to agree on the maximum number of predictions
- * that should be provided. We actually display 1 less than this number.
- */
-Conversion.maxPredictions = 9;
-
-exports.Conversion = Conversion;
-
-
-/**
- * ArrayConversion is a special Conversion, needed because arrays are converted
- * member by member rather then as a whole, which means we can track the
- * conversion if individual array elements. So an ArrayConversion acts like a
- * normal Conversion (which is needed as Assignment requires a Conversion) but
- * it can also be devolved into a set of Conversions for each array member.
- */
-function ArrayConversion(conversions, arg) {
- this.arg = arg;
- this.conversions = conversions;
- this.value = conversions.map(function(conversion) {
- return conversion.value;
- }, this);
-
- this._status = Status.combine(conversions.map(function(conversion) {
- return conversion.getStatus();
- }));
-
- // This message is just for reporting errors like "not enough values"
- // rather that for problems with individual values.
- this.message = '';
-
- // Predictions are generally provided by individual values
- this.predictions = [];
-}
-
-ArrayConversion.prototype = Object.create(Conversion.prototype);
-
-Object.defineProperty(ArrayConversion.prototype, 'assignment', {
- get: function() { return this._assignment; },
- set: function(assignment) {
- this._assignment = assignment;
-
- this.conversions.forEach(function(conversion) {
- conversion.assignment = assignment;
- }, this);
- },
- enumerable: true
-});
-
-ArrayConversion.prototype.getStatus = function(arg) {
- if (arg && arg.conversion) {
- return arg.conversion.getStatus();
- }
- return this._status;
-};
-
-ArrayConversion.prototype.isDataProvided = function() {
- return this.conversions.length > 0;
-};
-
-ArrayConversion.prototype.valueEquals = function(that) {
- if (that == null) {
- return false;
- }
-
- if (!(that instanceof ArrayConversion)) {
- throw new Error('Can\'t compare values with non ArrayConversion');
- }
-
- if (this.value === that.value) {
- return true;
- }
-
- if (this.value.length !== that.value.length) {
- return false;
- }
-
- for (var i = 0; i < this.conversions.length; i++) {
- if (!this.conversions[i].valueEquals(that.conversions[i])) {
- return false;
- }
- }
-
- return true;
-};
-
-ArrayConversion.prototype.toString = function() {
- return '[ ' + this.conversions.map(function(conversion) {
- return conversion.toString();
- }, this).join(', ') + ' ]';
-};
-
-exports.ArrayConversion = ArrayConversion;
-
-
-/**
- * Most of our types are 'static' e.g. there is only one type of 'string',
- * however some types like 'selection' and 'delegate' are customizable.
- * The basic Type type isn't useful, but does provide documentation about what
- * types do.
- */
-function Type() {
-}
-
-/**
- * Get a JSONable data structure that entirely describes this type.
- * commandName and paramName are the names of the command and parameter which
- * we are remoting to help the server get back to the remoted action.
- */
-Type.prototype.getSpec = function(commandName, paramName) {
- throw new Error('Not implemented');
-};
-
-/**
- * Convert the given value to a string representation.
- * Where possible, there should be round-tripping between values and their
- * string representations.
- * @param value The object to convert into a string
- * @param context An ExecutionContext to allow basic Requisition access
- */
-Type.prototype.stringify = function(value, context) {
- throw new Error('Not implemented');
-};
-
-/**
- * Convert the given arg to an instance of this type.
- * Where possible, there should be round-tripping between values and their
- * string representations.
- * @param arg An instance of Argument to convert.
- * @param context An ExecutionContext to allow basic Requisition access
- * @return Conversion
- */
-Type.prototype.parse = function(arg, context) {
- throw new Error('Not implemented');
-};
-
-/**
- * A convenience method for times when you don't have an argument to parse
- * but instead have a string.
- * @see #parse(arg)
- */
-Type.prototype.parseString = function(str, context) {
- return this.parse(new Argument(str), context);
-};
-
-/**
- * The plug-in system, and other things need to know what this type is
- * called. The name alone is not enough to fully specify a type. Types like
- * 'selection' and 'delegate' need extra data, however this function returns
- * only the name, not the extra data.
- */
-Type.prototype.name = undefined;
-
-/**
- * If there is some concept of a lower or higher value, return it,
- * otherwise return undefined.
- * @param by number indicating how much to nudge by, usually +1 or -1 which is
- * caused by the user pressing the UP/DOWN keys with the cursor in this type
- */
-Type.prototype.nudge = function(value, by, context) {
- return undefined;
-};
-
-/**
- * The 'blank value' of most types is 'undefined', but there are exceptions;
- * This allows types to specify a better conversion from empty string than
- * 'undefined'.
- * 2 known examples of this are boolean -> false and array -> []
- */
-Type.prototype.getBlank = function(context) {
- return new Conversion(undefined, new BlankArgument(), Status.INCOMPLETE, '');
-};
-
-/**
- * This is something of a hack for the benefit of DelegateType which needs to
- * be able to lie about it's type for fields to accept it as one of their own.
- * Sub-types can ignore this unless they're DelegateType.
- * @param context An ExecutionContext to allow basic Requisition access
- */
-Type.prototype.getType = function(context) {
- return this;
-};
-
-/**
- * addItems allows registrations of a number of things. This allows it to know
- * what type of item, and how it should be registered.
- */
-Type.prototype.item = 'type';
-
-exports.Type = Type;
-
-/**
- * 'Types' represents a registry of types
- */
-function Types() {
- // Invariant: types[name] = type.name
- this._registered = {};
-}
-
-exports.Types = Types;
-
-/**
- * Get an array of the names of registered types
- */
-Types.prototype.getTypeNames = function() {
- return Object.keys(this._registered);
-};
-
-/**
- * Add a new type to the list available to the system.
- * You can pass 2 things to this function - either an instance of Type, in
- * which case we return this instance when #getType() is called with a 'name'
- * that matches type.name.
- * Also you can pass in a constructor (i.e. function) in which case when
- * #getType() is called with a 'name' that matches Type.prototype.name we will
- * pass the typeSpec into this constructor.
- */
-Types.prototype.add = function(type) {
- if (typeof type === 'object') {
- if (!type.name) {
- throw new Error('All registered types must have a name');
- }
-
- if (type instanceof Type) {
- this._registered[type.name] = type;
- }
- else {
- var name = type.name;
- var parent = type.parent;
- type.name = parent;
- delete type.parent;
-
- this._registered[name] = this.createType(type);
-
- type.name = name;
- type.parent = parent;
- }
- }
- else if (typeof type === 'function') {
- if (!type.prototype.name) {
- throw new Error('All registered types must have a name');
- }
- this._registered[type.prototype.name] = type;
- }
- else {
- throw new Error('Unknown type: ' + type);
- }
-};
-
-/**
- * Remove a type from the list available to the system
- */
-Types.prototype.remove = function(type) {
- delete this._registered[type.name];
-};
-
-/**
- * Find a previously registered type
- */
-Types.prototype.createType = function(typeSpec) {
- if (typeof typeSpec === 'string') {
- typeSpec = { name: typeSpec };
- }
-
- if (typeof typeSpec !== 'object') {
- throw new Error('Can\'t extract type from ' + typeSpec);
- }
-
- var NewTypeCtor, newType;
- if (typeSpec.name == null || typeSpec.name == 'type') {
- NewTypeCtor = Type;
- }
- else {
- NewTypeCtor = this._registered[typeSpec.name];
- }
-
- if (!NewTypeCtor) {
- console.error('Known types: ' + Object.keys(this._registered).join(', '));
- throw new Error('Unknown type: \'' + typeSpec.name + '\'');
- }
-
- if (typeof NewTypeCtor === 'function') {
- newType = new NewTypeCtor(typeSpec);
- }
- else {
- // clone 'type'
- newType = {};
- util.copyProperties(NewTypeCtor, newType);
- }
-
- // Copy the properties of typeSpec onto the new type
- util.copyProperties(typeSpec, newType);
-
- // Several types need special powers to create child types
- newType.types = this;
-
- if (typeof NewTypeCtor !== 'function') {
- if (typeof newType.constructor === 'function') {
- newType.constructor();
- }
- }
-
- return newType;
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/types/union.js b/devtools/shared/gcli/source/lib/gcli/types/union.js
deleted file mode 100644
index 55c3023687c3..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/union.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2014, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var Conversion = require('./types').Conversion;
-var Status = require('./types').Status;
-
-exports.items = [
- {
- // The union type allows for a combination of different parameter types.
- item: 'type',
- name: 'union',
- hasPredictions: true,
-
- constructor: function() {
- // Get the properties of the type. Later types in the list should always
- // be more general, so 'catch all' types like string must be last
- this.alternatives = this.alternatives.map(typeData => {
- return this.types.createType(typeData);
- });
- },
-
- getSpec: function(command, param) {
- var spec = { name: 'union', alternatives: [] };
- this.alternatives.forEach(type => {
- spec.alternatives.push(type.getSpec(command, param));
- });
- return spec;
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
-
- var type = this.alternatives.find(function(typeData) {
- return typeData.name === value.type;
- });
-
- return type.stringify(value[value.type], context);
- },
-
- parse: function(arg, context) {
- var conversionPromises = this.alternatives.map(type => {
- return type.parse(arg, context);
- });
-
- return Promise.all(conversionPromises).then(conversions => {
- // Find a list of the predictions made by any conversion
- var predictionPromises = conversions.map(conversion => {
- return conversion.getPredictions(context);
- });
-
- return Promise.all(predictionPromises).then(allPredictions => {
- // Take one prediction from each set of predictions, ignoring
- // duplicates, until we've got up to Conversion.maxPredictions
- var maxIndex = allPredictions.reduce((prev, prediction) => {
- return Math.max(prev, prediction.length);
- }, 0);
- var predictions = [];
-
- indexLoop:
- for (var index = 0; index < maxIndex; index++) {
- for (var p = 0; p <= allPredictions.length; p++) {
- if (predictions.length >= Conversion.maxPredictions) {
- break indexLoop;
- }
-
- if (allPredictions[p] != null) {
- var prediction = allPredictions[p][index];
- if (prediction != null && !predictions.includes(prediction)) {
- predictions.push(prediction);
- }
- }
- }
- }
-
- var bestStatus = Status.ERROR;
- var value;
- for (var i = 0; i < conversions.length; i++) {
- var conversion = conversions[i];
- var thisStatus = conversion.getStatus(arg);
- if (thisStatus < bestStatus) {
- bestStatus = thisStatus;
- }
- if (bestStatus === Status.VALID) {
- var type = this.alternatives[i].name;
- value = { type: type };
- value[type] = conversion.value;
- break;
- }
- }
-
- var msg = (bestStatus === Status.VALID) ?
- '' :
- l10n.lookupFormat('typesSelectionNomatch', [ arg.text ]);
- return new Conversion(value, arg, bestStatus, msg, predictions);
- });
- });
- },
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/types/url.js b/devtools/shared/gcli/source/lib/gcli/types/url.js
deleted file mode 100644
index 2dad210f99c5..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/types/url.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var host = require('../util/host');
-var Status = require('./types').Status;
-var Conversion = require('./types').Conversion;
-
-exports.items = [
- {
- item: 'type',
- name: 'url',
-
- getSpec: function() {
- return 'url';
- },
-
- stringify: function(value, context) {
- if (value == null) {
- return '';
- }
- return value.href;
- },
-
- parse: function(arg, context) {
- var conversion;
-
- try {
- var url = host.createUrl(arg.text);
- conversion = new Conversion(url, arg);
- }
- catch (ex) {
- var predictions = [];
- var status = Status.ERROR;
-
- // Maybe the URL was missing a scheme?
- if (!arg.text.includes('://')) {
- [ 'http', 'https' ].forEach(scheme => {
- try {
- var http = host.createUrl(scheme + '://' + arg.text);
- predictions.push({ name: http.href, value: http });
- }
- catch (ex) {
- // Ignore
- }
- });
-
- // Try to create a URL with the current page as a base ref
- if ('window' in context.environment) {
- try {
- var base = context.environment.window.location.href;
- var localized = host.createUrl(arg.text, base);
- predictions.push({ name: localized.href, value: localized });
- }
- catch (ex) {
- // Ignore
- }
- }
- }
-
- if (predictions.length > 0) {
- status = Status.INCOMPLETE;
- }
-
- conversion = new Conversion(undefined, arg, status,
- ex.message, predictions);
- }
-
- return Promise.resolve(conversion);
- }
- }
-];
diff --git a/devtools/shared/gcli/source/lib/gcli/ui/focus.js b/devtools/shared/gcli/source/lib/gcli/ui/focus.js
deleted file mode 100644
index da3d5efdf1ea..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/ui/focus.js
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var l10n = require('../util/l10n');
-
-/**
- * Record how much help the user wants from the tooltip
- */
-var Eagerness = {
- NEVER: 1,
- SOMETIMES: 2,
- ALWAYS: 3
-};
-
-/**
- * Export the eagerHelper setting
- */
-exports.items = [
- {
- item: 'setting',
- name: 'eagerHelper',
- type: {
- name: 'selection',
- lookup: [
- { name: 'never', value: Eagerness.NEVER },
- { name: 'sometimes', value: Eagerness.SOMETIMES },
- { name: 'always', value: Eagerness.ALWAYS }
- ]
- },
- defaultValue: Eagerness.SOMETIMES,
- description: l10n.lookup('eagerHelperDesc'),
- ignoreTypeDifference: true
- }
-];
-
-/**
- * FocusManager solves the problem of tracking focus among a set of nodes.
- * The specific problem we are solving is when the hint element must be visible
- * if either the command line or any of the inputs in the hint element has the
- * focus, and invisible at other times, without hiding and showing the hint
- * element even briefly as the focus changes between them.
- * It does this simply by postponing the hide events by 250ms to see if
- * something else takes focus.
- */
-function FocusManager(document, settings) {
- if (document == null) {
- throw new Error('document == null');
- }
-
- this.document = document;
- this.settings = settings;
- this.debug = false;
- this.blurDelay = 150;
- this.window = this.document.defaultView;
-
- this._blurDelayTimeout = null; // Result of setTimeout in delaying a blur
- this._monitoredElements = []; // See addMonitoredElement()
-
- this._isError = false;
- this._hasFocus = false;
- this._helpRequested = false;
- this._recentOutput = false;
-
- this.onVisibilityChange = util.createEvent('FocusManager.onVisibilityChange');
-
- this._focused = this._focused.bind(this);
- if (this.document.addEventListener) {
- this.document.addEventListener('focus', this._focused, true);
- }
-
- var eagerHelper = this.settings.get('eagerHelper');
- eagerHelper.onChange.add(this._eagerHelperChanged, this);
-
- this.isTooltipVisible = undefined;
- this.isOutputVisible = undefined;
- this._checkShow();
-}
-
-/**
- * Avoid memory leaks
- */
-FocusManager.prototype.destroy = function() {
- var eagerHelper = this.settings.get('eagerHelper');
- eagerHelper.onChange.remove(this._eagerHelperChanged, this);
-
- this.document.removeEventListener('focus', this._focused, true);
-
- for (var i = 0; i < this._monitoredElements.length; i++) {
- var monitor = this._monitoredElements[i];
- console.error('Hanging monitored element: ', monitor.element);
-
- monitor.element.removeEventListener('focus', monitor.onFocus, true);
- monitor.element.removeEventListener('blur', monitor.onBlur, true);
- }
-
- if (this._blurDelayTimeout) {
- this.window.clearTimeout(this._blurDelayTimeout);
- this._blurDelayTimeout = null;
- }
-
- this._focused = undefined;
- this.document = undefined;
- this.settings = undefined;
- this.window = undefined;
-};
-
-/**
- * The easy way to include an element in the set of things that are part of the
- * aggregate focus. Using [add|remove]MonitoredElement() is a simpler way of
- * option than calling report[Focus|Blur]()
- * @param element The element on which to track focus|blur events
- * @param where Optional source string for debugging only
- */
-FocusManager.prototype.addMonitoredElement = function(element, where) {
- if (this.debug) {
- console.log('FocusManager.addMonitoredElement(' + (where || 'unknown') + ')');
- }
-
- var monitor = {
- element: element,
- where: where,
- onFocus: () => { this._reportFocus(where); },
- onBlur: () => { this._reportBlur(where); }
- };
-
- element.addEventListener('focus', monitor.onFocus, true);
- element.addEventListener('blur', monitor.onBlur, true);
-
- if (this.document.activeElement === element) {
- this._reportFocus(where);
- }
-
- this._monitoredElements.push(monitor);
-};
-
-/**
- * Undo the effects of addMonitoredElement()
- * @param element The element to stop tracking
- * @param where Optional source string for debugging only
- */
-FocusManager.prototype.removeMonitoredElement = function(element, where) {
- if (this.debug) {
- console.log('FocusManager.removeMonitoredElement(' + (where || 'unknown') + ')');
- }
-
- this._monitoredElements = this._monitoredElements.filter(function(monitor) {
- if (monitor.element === element) {
- element.removeEventListener('focus', monitor.onFocus, true);
- element.removeEventListener('blur', monitor.onBlur, true);
- return false;
- }
- return true;
- });
-};
-
-/**
- * Monitor for new command executions
- */
-FocusManager.prototype.updatePosition = function(dimensions) {
- var ev = {
- tooltipVisible: this.isTooltipVisible,
- outputVisible: this.isOutputVisible,
- dimensions: dimensions
- };
- this.onVisibilityChange(ev);
-};
-
-/**
- * Monitor for new command executions
- */
-FocusManager.prototype.outputted = function() {
- this._recentOutput = true;
- this._helpRequested = false;
- this._checkShow();
-};
-
-/**
- * We take a focus event anywhere to be an indication that we might be about
- * to lose focus
- */
-FocusManager.prototype._focused = function() {
- this._reportBlur('document');
-};
-
-/**
- * Some component has received a 'focus' event. This sets the internal status
- * straight away and informs the listeners
- * @param where Optional source string for debugging only
- */
-FocusManager.prototype._reportFocus = function(where) {
- if (this.debug) {
- console.log('FocusManager._reportFocus(' + (where || 'unknown') + ')');
- }
-
- if (this._blurDelayTimeout) {
- if (this.debug) {
- console.log('FocusManager.cancelBlur');
- }
- this.window.clearTimeout(this._blurDelayTimeout);
- this._blurDelayTimeout = null;
- }
-
- if (!this._hasFocus) {
- this._hasFocus = true;
- }
- this._checkShow();
-};
-
-/**
- * Some component has received a 'blur' event. This waits for a while to see if
- * we are going to get any subsequent 'focus' events and then sets the internal
- * status and informs the listeners
- * @param where Optional source string for debugging only
- */
-FocusManager.prototype._reportBlur = function(where) {
- if (this.debug) {
- console.log('FocusManager._reportBlur(' + where + ')');
- }
-
- if (this._hasFocus) {
- if (this._blurDelayTimeout) {
- if (this.debug) {
- console.log('FocusManager.blurPending');
- }
- return;
- }
-
- this._blurDelayTimeout = this.window.setTimeout(() => {
- if (this.debug) {
- console.log('FocusManager.blur');
- }
- this._hasFocus = false;
- this._checkShow();
- this._blurDelayTimeout = null;
- }, this.blurDelay);
- }
-};
-
-/**
- * The setting has changed
- */
-FocusManager.prototype._eagerHelperChanged = function() {
- this._checkShow();
-};
-
-/**
- * The terminal tells us about keyboard events so we can decide to delay
- * showing the tooltip element
- */
-FocusManager.prototype.onInputChange = function() {
- this._recentOutput = false;
- this._checkShow();
-};
-
-/**
- * Generally called for something like a F1 key press, when the user explicitly
- * wants help
- */
-FocusManager.prototype.helpRequest = function() {
- if (this.debug) {
- console.log('FocusManager.helpRequest');
- }
-
- this._helpRequested = true;
- this._recentOutput = false;
- this._checkShow();
-};
-
-/**
- * Generally called for something like a ESC key press, when the user explicitly
- * wants to get rid of the help
- */
-FocusManager.prototype.removeHelp = function() {
- if (this.debug) {
- console.log('FocusManager.removeHelp');
- }
-
- this._importantFieldFlag = false;
- this._isError = false;
- this._helpRequested = false;
- this._recentOutput = false;
- this._checkShow();
-};
-
-/**
- * Set to true whenever a field thinks it's output is important
- */
-FocusManager.prototype.setImportantFieldFlag = function(flag) {
- if (this.debug) {
- console.log('FocusManager.setImportantFieldFlag', flag);
- }
- this._importantFieldFlag = flag;
- this._checkShow();
-};
-
-/**
- * Set to true whenever a field thinks it's output is important
- */
-FocusManager.prototype.setError = function(isError) {
- if (this.debug) {
- console.log('FocusManager._isError', isError);
- }
- this._isError = isError;
- this._checkShow();
-};
-
-/**
- * Helper to compare the current showing state with the value calculated by
- * _shouldShow() and take appropriate action
- */
-FocusManager.prototype._checkShow = function() {
- var fire = false;
- var ev = {
- tooltipVisible: this.isTooltipVisible,
- outputVisible: this.isOutputVisible
- };
-
- var showTooltip = this._shouldShowTooltip();
- if (this.isTooltipVisible !== showTooltip.visible) {
- ev.tooltipVisible = this.isTooltipVisible = showTooltip.visible;
- fire = true;
- }
-
- var showOutput = this._shouldShowOutput();
- if (this.isOutputVisible !== showOutput.visible) {
- ev.outputVisible = this.isOutputVisible = showOutput.visible;
- fire = true;
- }
-
- if (fire) {
- if (this.debug) {
- console.log('FocusManager.onVisibilityChange', ev);
- }
- this.onVisibilityChange(ev);
- }
-};
-
-/**
- * Calculate if we should be showing or hidden taking into account all the
- * available inputs
- */
-FocusManager.prototype._shouldShowTooltip = function() {
- var eagerHelper = this.settings.get('eagerHelper');
- if (eagerHelper.value === Eagerness.NEVER) {
- return { visible: false, reason: 'eagerHelperNever' };
- }
-
- if (eagerHelper.value === Eagerness.ALWAYS) {
- return { visible: true, reason: 'eagerHelperAlways' };
- }
-
- if (!this._hasFocus) {
- return { visible: false, reason: 'notHasFocus' };
- }
-
- if (this._isError) {
- return { visible: true, reason: 'isError' };
- }
-
- if (this._helpRequested) {
- return { visible: true, reason: 'helpRequested' };
- }
-
- if (this._importantFieldFlag) {
- return { visible: true, reason: 'importantFieldFlag' };
- }
-
- return { visible: false, reason: 'default' };
-};
-
-/**
- * Calculate if we should be showing or hidden taking into account all the
- * available inputs
- */
-FocusManager.prototype._shouldShowOutput = function() {
- if (!this._hasFocus) {
- return { visible: false, reason: 'notHasFocus' };
- }
-
- if (this._recentOutput) {
- return { visible: true, reason: 'recentOutput' };
- }
-
- return { visible: false, reason: 'default' };
-};
-
-exports.FocusManager = FocusManager;
diff --git a/devtools/shared/gcli/source/lib/gcli/ui/history.js b/devtools/shared/gcli/source/lib/gcli/ui/history.js
deleted file mode 100644
index a9d4b868c29d..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/ui/history.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-/**
- * A History object remembers commands that have been entered in the past and
- * provides an API for accessing them again.
- * See Bug 681340: Search through history (like C-r in bash)?
- */
-function History() {
- // This is the actual buffer where previous commands are kept.
- // 'this._buffer[0]' should always be equal the empty string. This is so
- // that when you try to go in to the "future", you will just get an empty
- // command.
- this._buffer = [''];
-
- // This is an index in to the history buffer which points to where we
- // currently are in the history.
- this._current = 0;
-}
-
-/**
- * Avoid memory leaks
- */
-History.prototype.destroy = function() {
- this._buffer = undefined;
-};
-
-/**
- * Record and save a new command in the history.
- */
-History.prototype.add = function(command) {
- this._buffer.splice(1, 0, command);
- this._current = 0;
-};
-
-/**
- * Get the next (newer) command from history.
- */
-History.prototype.forward = function() {
- if (this._current > 0 ) {
- this._current--;
- }
- return this._buffer[this._current];
-};
-
-/**
- * Get the previous (older) item from history.
- */
-History.prototype.backward = function() {
- if (this._current < this._buffer.length - 1) {
- this._current++;
- }
- return this._buffer[this._current];
-};
-
-exports.History = History;
diff --git a/devtools/shared/gcli/source/lib/gcli/ui/intro.js b/devtools/shared/gcli/source/lib/gcli/ui/intro.js
deleted file mode 100644
index 9abf51db649f..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/ui/intro.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var l10n = require('../util/l10n');
-var Output = require('../cli').Output;
-var view = require('./view');
-
-/**
- * Record if the user has clicked on 'Got It!'
- */
-exports.items = [
- {
- item: 'setting',
- name: 'hideIntro',
- type: 'boolean',
- description: l10n.lookup('hideIntroDesc'),
- defaultValue: false
- }
-];
-
-/**
- * Called when the UI is ready to add a welcome message to the output
- */
-exports.maybeShowIntro = function (commandOutputManager, conversionContext,
- outputPanel) {
- var hideIntro = conversionContext.system.settings.get('hideIntro');
- if (hideIntro.value) {
- return;
- }
-
- var output = new Output(conversionContext);
- output.type = 'view';
- commandOutputManager.onOutput({ output: output });
-
- var viewData = this.createView(null, conversionContext, true, outputPanel);
-
- output.complete({ isTypedData: true, type: 'view', data: viewData });
-};
-
-/**
- * Called when the UI is ready to add a welcome message to the output
- */
-exports.createView = function (ignoreArgs, conversionContext, showHideButton,
- outputPanel) {
- return view.createView({
- html:
- '
diff --git a/devtools/shared/gcli/source/lib/gcli/ui/menu.js b/devtools/shared/gcli/source/lib/gcli/ui/menu.js
deleted file mode 100644
index 8fddfec01da7..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/ui/menu.js
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var l10n = require('../util/l10n');
-var domtemplate = require('../util/domtemplate');
-var host = require('../util/host');
-
-/**
- * Shared promises for loading resource files
- */
-var menuCssPromise;
-var menuHtmlPromise;
-
-/**
- * Menu is a display of the commands that are possible given the state of a
- * requisition.
- * @param options A way to customize the menu display.
- * - document: The document to use in creating widgets
- * - maxPredictions (default=8): The maximum predictions to show at one time
- * If more are requested, a message will be displayed asking the user to
- * continue typing to narrow the list of options
- */
-function Menu(options) {
- options = options || {};
- this.document = options.document || document;
- this.maxPredictions = options.maxPredictions || 8;
-
- // Keep track of any highlighted items
- this._choice = null;
-
- // FF can be really hard to debug if doc is null, so we check early on
- if (!this.document) {
- throw new Error('No document');
- }
-
- this.element = util.createElement(this.document, 'div');
- this.element.classList.add('gcli-menu');
-
- if (menuCssPromise == null) {
- menuCssPromise = host.staticRequire(module, './menu.css');
- }
- menuCssPromise.then(menuCss => {
- // Pull the HTML into the DOM, but don't add it to the document
- if (menuCss != null) {
- util.importCss(menuCss, this.document, 'gcli-menu');
- }
- }, console.error);
-
- this.templateOptions = { blankNullUndefined: true, stack: 'menu.html' };
- if (menuHtmlPromise == null) {
- menuHtmlPromise = host.staticRequire(module, './menu.html');
- }
- menuHtmlPromise.then(menuHtml => {
- if (this.document == null) {
- return; // destroy() has been called
- }
-
- this.template = host.toDom(this.document, menuHtml);
- }, console.error);
-
- // Contains the items that should be displayed
- this.items = [];
-
- this.onItemClick = util.createEvent('Menu.onItemClick');
-}
-
-/**
- * Allow the template engine to get at localization strings
- */
-Menu.prototype.l10n = l10n.propertyLookup;
-
-/**
- * Avoid memory leaks
- */
-Menu.prototype.destroy = function() {
- this.element = undefined;
- this.template = undefined;
- this.document = undefined;
- this.items = undefined;
-};
-
-/**
- * The default is to do nothing when someone clicks on the menu.
- * This is called from template.html
- * @param ev The click event from the browser
- */
-Menu.prototype.onItemClickInternal = function(ev) {
- var name = ev.currentTarget.getAttribute('data-name');
- if (!name) {
- var named = ev.currentTarget.querySelector('[data-name]');
- name = named.getAttribute('data-name');
- }
- this.onItemClick({ name: name });
-};
-
-/**
- * Act as though someone clicked on the selected item
- */
-Menu.prototype.clickSelected = function() {
- this.onItemClick({ name: this.selected });
-};
-
-/**
- * What is the currently selected item?
- */
-Object.defineProperty(Menu.prototype, 'isSelected', {
- get: function() {
- return this.selected != null;
- },
- enumerable: true
-});
-
-/**
- * What is the currently selected item?
- */
-Object.defineProperty(Menu.prototype, 'selected', {
- get: function() {
- var item = this.element.querySelector('.gcli-menu-name.gcli-menu-highlight');
- if (!item) {
- return null;
- }
- return item.textContent;
- },
- enumerable: true
-});
-
-/**
- * Display a number of items in the menu (or hide the menu if there is nothing
- * to display)
- * @param items The items to show in the menu
- * @param match Matching text to highlight in the output
- */
-Menu.prototype.show = function(items, match) {
- // If the HTML hasn't loaded yet then just don't show a menu
- if (this.template == null) {
- return;
- }
-
- this.items = items.filter(item => {
- return item.hidden === undefined || item.hidden !== true;
- });
-
- this.items = this.items.map(item => {
- return getHighlightingProxy(item, match, this.template.ownerDocument);
- });
-
- if (this.items.length === 0) {
- this.element.style.display = 'none';
- return;
- }
-
- if (this.items.length >= this.maxPredictions) {
- this.items.splice(-1);
- this.hasMore = true;
- }
- else {
- this.hasMore = false;
- }
-
- var options = this.template.cloneNode(true);
- domtemplate.template(options, this, this.templateOptions);
-
- util.clearElement(this.element);
- this.element.appendChild(options);
-
- this.element.style.display = 'block';
-};
-
-var MAX_ITEMS = 3;
-
-/**
- * Takes an array of items and cuts it into an array of arrays to help us
- * to place the items into columns.
- * The inner arrays will have at most MAX_ITEMS in them, with the number of
- * outer arrays expanding to accommodate.
- */
-Object.defineProperty(Menu.prototype, 'itemsSubdivided', {
- get: function() {
- var reply = [];
-
- var taken = 0;
- while (taken < this.items.length) {
- reply.push(this.items.slice(taken, taken + MAX_ITEMS));
- taken += MAX_ITEMS;
- }
-
- return reply;
- },
- enumerable: true
-});
-
-/**
- * Create a proxy around an item that highlights matching text
- */
-function getHighlightingProxy(item, match, document) {
- var proxy = {};
- Object.defineProperties(proxy, {
- highlight: {
- get: function() {
- if (!match) {
- return item.name;
- }
-
- var value = item.name;
- var startMatch = value.indexOf(match);
- if (startMatch === -1) {
- return value;
- }
-
- var before = value.substr(0, startMatch);
- var after = value.substr(startMatch + match.length);
- var parent = util.createElement(document, 'span');
- parent.appendChild(document.createTextNode(before));
- var highlight = util.createElement(document, 'span');
- highlight.classList.add('gcli-menu-typed');
- highlight.appendChild(document.createTextNode(match));
- parent.appendChild(highlight);
- parent.appendChild(document.createTextNode(after));
- return parent;
- },
- enumerable: true
- },
-
- name: {
- value: item.name,
- enumerable: true
- },
-
- manual: {
- value: item.manual,
- enumerable: true
- },
-
- description: {
- value: item.description,
- enumerable: true
- }
- });
- return proxy;
-}
-
-/**
- * @return {int} current choice index
- */
-Menu.prototype.getChoiceIndex = function() {
- return this._choice == null ? 0 : this._choice;
-};
-
-/**
- * Highlight the next (for by=1) or previous (for by=-1) option
- */
-Menu.prototype.nudgeChoice = function(by) {
- if (this._choice == null) {
- this._choice = 0;
- }
-
- // There's an annoying up is down thing here, the menu is presented
- // with the zeroth index at the top working down, so the UP arrow needs
- // pick the choice below because we're working down
- this._choice -= by;
- this._updateHighlight();
-};
-
-/**
- * Highlight nothing
- */
-Menu.prototype.unsetChoice = function() {
- this._choice = null;
- this._updateHighlight();
-};
-
-/**
- * Internal option to update the currently highlighted option
- */
-Menu.prototype._updateHighlight = function() {
- var names = this.element.querySelectorAll('.gcli-menu-name');
- var descs = this.element.querySelectorAll('.gcli-menu-desc');
- for (var i = 0; i < names.length; i++) {
- names[i].classList.remove('gcli-menu-highlight');
- }
- for (i = 0; i < descs.length; i++) {
- descs[i].classList.remove('gcli-menu-highlight');
- }
-
- if (this._choice == null || names.length === 0) {
- return;
- }
-
- var index = this._choice % names.length;
- if (index < 0) {
- index = names.length + index;
- }
-
- names.item(index).classList.add('gcli-menu-highlight');
- descs.item(index).classList.add('gcli-menu-highlight');
-};
-
-/**
- * Hide the menu
- */
-Menu.prototype.hide = function() {
- this.element.style.display = 'none';
-};
-
-/**
- * Change how much vertical space this menu can take up
- */
-Menu.prototype.setMaxHeight = function(height) {
- this.element.style.maxHeight = height + 'px';
-};
-
-exports.Menu = Menu;
diff --git a/devtools/shared/gcli/source/lib/gcli/ui/moz.build b/devtools/shared/gcli/source/lib/gcli/ui/moz.build
deleted file mode 100644
index 70ac666f0fb2..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/ui/moz.build
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'focus.js',
- 'history.js',
- 'intro.js',
- 'menu.css',
- 'menu.html',
- 'menu.js',
- 'view.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/ui/view.js b/devtools/shared/gcli/source/lib/gcli/ui/view.js
deleted file mode 100644
index 193fb2d96645..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/ui/view.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('../util/util');
-var host = require('../util/host');
-var domtemplate = require('../util/domtemplate');
-
-
-/**
- * We want to avoid commands having to create DOM structures because that's
- * messy and because we're going to need to have command output displayed in
- * different documents. A View is a way to wrap an HTML template (for
- * domtemplate) in with the data and options to render the template, so anyone
- * can later run the template in the context of any document.
- * View also cuts out a chunk of boiler place code.
- * @param options The information needed to create the DOM from HTML. Includes:
- * - html (required): The HTML source, probably from a call to require
- * - options (default={}): The domtemplate options. See domtemplate for details
- * - data (default={}): The data to domtemplate. See domtemplate for details.
- * - css (default=none): Some CSS to be added to the final document. If 'css'
- * is used, use of cssId is strongly recommended.
- * - cssId (default=none): An ID to prevent multiple CSS additions. See
- * util.importCss for more details.
- * @return An object containing a single function 'appendTo()' which runs the
- * template adding the result to the specified element. Takes 2 parameters:
- * - element (required): the element to add to
- * - clear (default=false): if clear===true then remove all pre-existing
- * children of 'element' before appending the results of this template.
- */
-exports.createView = function(options) {
- if (options.html == null) {
- throw new Error('options.html is missing');
- }
-
- return {
- /**
- * RTTI. Yeah.
- */
- isView: true,
-
- /**
- * Run the template against the document to which element belongs.
- * @param element The element to append the result to
- * @param clear Set clear===true to remove all children of element
- */
- appendTo: function(element, clear) {
- // Strict check on the off-chance that we later think of other options
- // and want to replace 'clear' with an 'options' parameter, but want to
- // support backwards compat.
- if (clear === true) {
- util.clearElement(element);
- }
-
- element.appendChild(this.toDom(element.ownerDocument));
- },
-
- /**
- * Actually convert the view data into a DOM suitable to be appended to
- * an element
- * @param document to use in realizing the template
- */
- toDom: function(document) {
- if (options.css) {
- util.importCss(options.css, document, options.cssId);
- }
-
- var child = host.toDom(document, options.html);
- domtemplate.template(child, options.data || {}, options.options || {});
- return child;
- }
- };
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/util/domtemplate.js b/devtools/shared/gcli/source/lib/gcli/util/domtemplate.js
deleted file mode 100644
index d8979db3b574..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/domtemplate.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var {template} = require("devtools/shared/gcli/templater");
-exports.template = template;
diff --git a/devtools/shared/gcli/source/lib/gcli/util/fileparser.js b/devtools/shared/gcli/source/lib/gcli/util/fileparser.js
deleted file mode 100644
index 4c470e638830..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/fileparser.js
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var util = require('./util');
-var l10n = require('./l10n');
-var spell = require('./spell');
-var filesystem = require('./filesystem');
-var Status = require('../types/types').Status;
-
-/*
- * An implementation of the functions that call the filesystem, designed to
- * support the file type.
- */
-
-/**
- * Helper for the parse() function from the file type.
- * See gcli/util/filesystem.js for details
- */
-exports.parse = function(context, typed, options) {
- return filesystem.stat(typed).then(function(stats) {
- // The 'save-as' case - the path should not exist but does
- if (options.existing === 'no' && stats.exists) {
- return {
- value: undefined,
- status: Status.INCOMPLETE,
- message: l10n.lookupFormat('fileErrExists', [ typed ]),
- predictor: undefined // No predictions that we can give here
- };
- }
-
- if (stats.exists) {
- // The path exists - check it's the correct file type ...
- if (options.filetype === 'file' && !stats.isFile) {
- return {
- value: undefined,
- status: Status.INCOMPLETE,
- message: l10n.lookupFormat('fileErrIsNotFile', [ typed ]),
- predictor: getPredictor(typed, options)
- };
- }
-
- if (options.filetype === 'directory' && !stats.isDir) {
- return {
- value: undefined,
- status: Status.INCOMPLETE,
- message: l10n.lookupFormat('fileErrIsNotDirectory', [ typed ]),
- predictor: getPredictor(typed, options)
- };
- }
-
- // ... and that it matches any 'match' RegExp
- if (options.matches != null && !options.matches.test(typed)) {
- return {
- value: undefined,
- status: Status.INCOMPLETE,
- message: l10n.lookupFormat('fileErrDoesntMatch',
- [ typed, options.source ]),
- predictor: getPredictor(typed, options)
- };
- }
- }
- else {
- if (options.existing === 'yes') {
- // We wanted something that exists, but it doesn't. But we don't know
- // if the path so far is an ERROR or just INCOMPLETE
- var parentName = filesystem.dirname(typed);
- return filesystem.stat(parentName).then(function(stats) {
- return {
- value: undefined,
- status: stats.isDir ? Status.INCOMPLETE : Status.ERROR,
- message: l10n.lookupFormat('fileErrNotExists', [ typed ]),
- predictor: getPredictor(typed, options)
- };
- });
- }
- }
-
- // We found no problems
- return {
- value: typed,
- status: Status.VALID,
- message: undefined,
- predictor: getPredictor(typed, options)
- };
- });
-};
-
-var RANK_OPTIONS = { noSort: true, prefixZero: true };
-
-/**
- * We want to be able to turn predictions off in Firefox
- */
-exports.supportsPredictions = false;
-
-/**
- * Get a function which creates predictions of files that match the given
- * path
- */
-function getPredictor(typed, options) {
- if (!exports.supportsPredictions) {
- return undefined;
- }
-
- return function() {
- var allowFile = (options.filetype !== 'directory');
- var parts = filesystem.split(typed);
-
- var absolute = (typed.indexOf('/') === 0);
- var roots;
- if (absolute) {
- roots = [ { name: '/', dist: 0, original: '/' } ];
- }
- else {
- roots = dirHistory.getCommonDirectories().map(function(root) {
- return { name: root, dist: 0, original: root };
- });
- }
-
- // Add each part of the typed pathname onto each of the roots in turn,
- // Finding options from each of those paths, and using these options as
- // our roots for the next part
- var partsAdded = util.promiseEach(parts, function(part, index) {
-
- var partsSoFar = filesystem.join.apply(filesystem, parts.slice(0, index + 1));
-
- // We allow this file matches in this pass if we're allowed files at all
- // (i.e this isn't 'cd') and if this is the last part of the path
- var allowFileForPart = (allowFile && index >= parts.length - 1);
-
- var rootsPromise = util.promiseEach(roots, function(root) {
-
- // Extend each roots to a list of all the files in each of the roots
- var matchFile = allowFileForPart ? options.matches : null;
- var promise = filesystem.ls(root.name, matchFile);
-
- var onSuccess = function(entries) {
- // Unless this is the final part filter out the non-directories
- if (!allowFileForPart) {
- entries = entries.filter(function(entry) {
- return entry.isDir;
- });
- }
- var entryMap = {};
- entries.forEach(function(entry) {
- entryMap[entry.pathname] = entry;
- });
- return entryMap;
- };
-
- var onError = function(err) {
- // We expect errors due to the path not being a directory, not being
- // accessible, or removed since the call to 'readdir'
- return {};
- };
-
- promise = promise.then(onSuccess, onError);
-
- // We want to compare all the directory entries with the original root
- // plus the partsSoFar
- var compare = filesystem.join(root.original, partsSoFar);
-
- return promise.then(function(entryMap) {
-
- var ranks = spell.rank(compare, Object.keys(entryMap), RANK_OPTIONS);
- // penalize each path by the distance of it's parent
- ranks.forEach(function(rank) {
- rank.original = root.original;
- rank.stats = entryMap[rank.name];
- });
- return ranks;
- });
- });
-
- return rootsPromise.then(function(data) {
- // data is an array of arrays of ranking objects. Squash down.
- data = data.reduce(function(prev, curr) {
- return prev.concat(curr);
- }, []);
-
- data.sort(function(r1, r2) {
- return r1.dist - r2.dist;
- });
-
- // Trim, but by how many?
- // If this is the last run through, we want to present the user with
- // a sensible set of predictions. Otherwise we want to trim the tree
- // to a reasonable set of matches, so we're happy with 1
- // We look through x +/- 3 roots, and find the one with the biggest
- // distance delta, and cut below that
- // x=5 for the last time through, and x=8 otherwise
- var isLast = index >= parts.length - 1;
- var start = isLast ? 1 : 5;
- var end = isLast ? 7 : 10;
-
- var maxDeltaAt = start;
- var maxDelta = data[start].dist - data[start - 1].dist;
-
- for (var i = start + 1; i < end; i++) {
- var delta = data[i].dist - data[i - 1].dist;
- if (delta >= maxDelta) {
- maxDelta = delta;
- maxDeltaAt = i;
- }
- }
-
- // Update the list of roots for the next time round
- roots = data.slice(0, maxDeltaAt);
- });
- });
-
- return partsAdded.then(function() {
- var predictions = roots.map(function(root) {
- var isFile = root.stats && root.stats.isFile;
- var isDir = root.stats && root.stats.isDir;
-
- var name = root.name;
- if (isDir && name.charAt(name.length) !== filesystem.sep) {
- name += filesystem.sep;
- }
-
- return {
- name: name,
- incomplete: !(allowFile && isFile),
- isFile: isFile, // Added for describe, below
- dist: root.dist, // TODO: Remove - added for debug in describe
- };
- });
-
- return util.promiseEach(predictions, function(prediction) {
- if (!prediction.isFile) {
- prediction.description = '(' + prediction.dist + ')';
- prediction.dist = undefined;
- prediction.isFile = undefined;
- return prediction;
- }
-
- return filesystem.describe(prediction.name).then(function(description) {
- prediction.description = description;
- prediction.dist = undefined;
- prediction.isFile = undefined;
- return prediction;
- });
- });
- });
- };
-}
-
-// =============================================================================
-
-/*
- * The idea is that we maintain a list of 'directories that the user is
- * interested in'. We store directories in a most-frequently-used cache
- * of some description.
- * But for now we're just using / and ~/
- */
-var dirHistory = {
- getCommonDirectories: function() {
- return [
- filesystem.sep, // i.e. the root directory
- filesystem.home // i.e. the users home directory
- ];
- },
- addCommonDirectory: function(ignore) {
- // Not implemented yet
- }
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/util/filesystem.js b/devtools/shared/gcli/source/lib/gcli/util/filesystem.js
deleted file mode 100644
index 19ffb4d4f71c..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/filesystem.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var Cu = require('chrome').Cu;
-var Cc = require('chrome').Cc;
-var Ci = require('chrome').Ci;
-
-var OS = require('resource://gre/modules/osfile.jsm').OS;
-
-/**
- * A set of functions that don't really belong in 'fs' (because they're not
- * really universal in scope) but also kind of do (because they're not specific
- * to GCLI
- */
-
-exports.join = OS.Path.join;
-exports.sep = OS.Path.sep;
-exports.dirname = OS.Path.dirname;
-
-// On B2G, there is no home folder
-var home = null;
-try {
- var dirService = Cc['@mozilla.org/file/directory_service;1']
- .getService(Ci.nsIProperties);
- home = dirService.get('Home', Ci.nsIFile).path;
-} catch(e) {}
-exports.home = home;
-
-if ('winGetDrive' in OS.Path) {
- exports.sep = '\\';
-}
-else {
- exports.sep = '/';
-}
-
-/**
- * Split a path into its components.
- * @param pathname (string) The part to cut up
- * @return An array of path components
- */
-exports.split = function(pathname) {
- return OS.Path.split(pathname).components;
-};
-
-/**
- * @param pathname string, path of an existing directory
- * @param matches optional regular expression - filter output to include only
- * the files that match the regular expression. The regexp is applied to the
- * filename only not to the full path
- * @return A promise of an array of stat objects for each member of the
- * directory pointed to by ``pathname``, each containing 2 extra properties:
- * - pathname: The full pathname of the file
- * - filename: The final filename part of the pathname
- */
-exports.ls = function(pathname, matches) {
- var iterator = new OS.File.DirectoryIterator(pathname);
- var entries = [];
-
- var iteratePromise = iterator.forEach(function(entry) {
- entries.push({
- exists: true,
- isDir: entry.isDir,
- isFile: !entry.isFile,
- filename: entry.name,
- pathname: entry.path
- });
- });
-
- return iteratePromise.then(function onSuccess() {
- iterator.close();
- return entries;
- },
- function onFailure(reason) {
- iterator.close();
- throw reason;
- }
- );
-};
-
-/**
- * stat() is annoying because it considers stat('/doesnt/exist') to be an
- * error, when the point of stat() is to *find* *out*. So this wrapper just
- * converts 'ENOENT' i.e. doesn't exist to { exists:false } and adds
- * exists:true to stat blocks from existing paths
- */
-exports.stat = function(pathname) {
- var onResolve = function(stats) {
- return {
- exists: true,
- isDir: stats.isDir,
- isFile: !stats.isFile
- };
- };
-
- var onReject = function(err) {
- if (err instanceof OS.File.Error && err.becauseNoSuchFile) {
- return {
- exists: false,
- isDir: false,
- isFile: false
- };
- }
- throw err;
- };
-
- return OS.File.stat(pathname).then(onResolve, onReject);
-};
-
-/**
- * We may read the first line of a file to describe it?
- * Right now, however, we do nothing.
- */
-exports.describe = function(pathname) {
- return Promise.resolve('');
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/util/host.js b/devtools/shared/gcli/source/lib/gcli/util/host.js
deleted file mode 100644
index 8850d9afbdc3..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/host.js
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-const { Cc, Ci, Cu } = require("chrome");
-
-Cu.importGlobalProperties(["XMLHttpRequest"]);
-
-var { Task } = require("devtools/shared/task");
-
-var util = require('./util');
-
-function Highlighter(document) {
- this._document = document;
- this._nodes = util.createEmptyNodeList(this._document);
-}
-
-Object.defineProperty(Highlighter.prototype, 'nodelist', {
- set: function(nodes) {
- Array.prototype.forEach.call(this._nodes, this._unhighlightNode, this);
- this._nodes = (nodes == null) ?
- util.createEmptyNodeList(this._document) :
- nodes;
- Array.prototype.forEach.call(this._nodes, this._highlightNode, this);
- },
- get: function() {
- return this._nodes;
- },
- enumerable: true
-});
-
-Highlighter.prototype.destroy = function() {
- this.nodelist = null;
-};
-
-Highlighter.prototype._highlightNode = function(node) {
- // Enable when the highlighter rewrite is done
-};
-
-Highlighter.prototype._unhighlightNode = function(node) {
- // Enable when the highlighter rewrite is done
-};
-
-exports.Highlighter = Highlighter;
-
-/**
- * See docs in lib/gcli/util/host.js
- */
-exports.exec = function(task) {
- return Task.spawn(task);
-};
-
-/**
- * The URL API is new enough that we need specific platform help
- */
-exports.createUrl = function(uristr, base) {
- return new URL(uristr, base);
-};
-
-/**
- * Load some HTML into the given document and return a DOM element.
- * This utility assumes that the html has a single root (other than whitespace)
- */
-exports.toDom = function(document, html) {
- var div = util.createElement(document, 'div');
- util.setContents(div, html);
- return div.children[0];
-};
-
-/**
- * When dealing with module paths on windows we want to use the unix
- * directory separator rather than the windows one, so we avoid using
- * OS.Path.dirname, and use unix version on all platforms.
- */
-var resourceDirName = function(path) {
- var index = path.lastIndexOf('/');
- if (index == -1) {
- return '.';
- }
- while (index >= 0 && path[index] == '/') {
- --index;
- }
- return path.slice(0, index + 1);
-};
-
-/**
- * Asynchronously load a text resource
- * @see lib/gcli/util/host.js
- */
-exports.staticRequire = function(requistingModule, name) {
- if (name.match(/\.css$/)) {
- return Promise.resolve('');
- }
- else {
- return new Promise((resolve, reject) => {
- var filename = resourceDirName(requistingModule.id) + '/' + name;
- filename = filename.replace(/\/\.\//g, '/');
- filename = 'resource://devtools/shared/gcli/source/lib/' + filename;
-
- var xhr = new XMLHttpRequest();
-
- xhr.onload = () => {
- resolve(xhr.responseText);
- };
-
- xhr.onabort = xhr.onerror = xhr.ontimeout = err => {
- reject(err);
- };
-
- xhr.open('GET', filename);
- xhr.send();
- });
- }
-};
-
-/**
- * A group of functions to help scripting. Small enough that it doesn't need
- * a separate module (it's basically a wrapper around 'eval' in some contexts)
- */
-var client;
-var target;
-var consoleActor;
-var webConsoleClient;
-
-exports.script = { };
-
-exports.script.onOutput = util.createEvent('Script.onOutput');
-
-/**
- * Setup the environment to eval JavaScript
- */
-exports.script.useTarget = function(tgt) {
- target = tgt;
-
- // Local debugging needs to make the target remote.
- var targetPromise = target.isRemote ?
- Promise.resolve(target) :
- target.makeRemote();
-
- return targetPromise.then(function() {
- return new Promise((resolve, reject) => {
- client = target._client;
-
- client.addListener('pageError', function(packet) {
- if (packet.from === consoleActor) {
- // console.log('pageError', packet.pageError);
- exports.script.onOutput({
- level: 'exception',
- message: packet.exception.class
- });
- }
- });
-
- client.addListener('consoleAPICall', function(type, packet) {
- if (packet.from === consoleActor) {
- var data = packet.message;
-
- var ev = {
- level: data.level,
- arguments: data.arguments,
- };
-
- if (data.filename !== 'debugger eval code') {
- ev.source = {
- filename: data.filename,
- lineNumber: data.lineNumber,
- functionName: data.functionName
- };
- }
-
- exports.script.onOutput(ev);
- }
- });
-
- consoleActor = target._form.consoleActor;
-
- var listeners = [ 'PageError', 'ConsoleAPI' ];
- client.attachConsole(consoleActor, listeners)
- .then(([response, wcc]) => {
- webConsoleClient = wcc;
- resolve(response);
- }, response => {
- reject(response);
- });
- });
- });
-};
-
-/**
- * Execute some JavaScript
- */
-exports.script.evaluate = function(javascript) {
- return new Promise((resolve, reject) => {
- var onResult = function(response) {
- var output = response.result;
- if (typeof output === 'object' && output.type === 'undefined') {
- output = undefined;
- }
-
- resolve({
- input: response.input,
- output: output,
- exception: response.exception
- });
- };
-
- webConsoleClient.evaluateJS(javascript, onResult, {});
- });
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/util/l10n.js b/devtools/shared/gcli/source/lib/gcli/util/l10n.js
deleted file mode 100644
index 6d0c7c8f4aa3..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/l10n.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-"use strict";
-
-const {LocalizationHelper} = require("devtools/shared/l10n");
-const L10N = new LocalizationHelper("devtools/shared/locales/gcli.properties");
-
-/*
- * Not supported when embedded - we"re doing things the Mozilla way not the
- * require.js way.
- */
-exports.registerStringsSource = function (modulePath) {
- throw new Error("registerStringsSource is not available in mozilla");
-};
-
-exports.unregisterStringsSource = function (modulePath) {
- throw new Error("unregisterStringsSource is not available in mozilla");
-};
-
-exports.lookupSwap = function (key, swaps) {
- throw new Error("lookupSwap is not available in mozilla");
-};
-
-exports.lookupPlural = function (key, ord, swaps) {
- throw new Error("lookupPlural is not available in mozilla");
-};
-
-exports.getPreferredLocales = function () {
- return [ "root" ];
-};
-
-/** @see lookup() in lib/gcli/util/l10n.js */
-exports.lookup = function (key) {
- try {
- // Our memory leak hunter walks reachable objects trying to work out what
- // type of thing they are using object.constructor.name. If that causes
- // problems then we can avoid the unknown-key-exception with the following:
- /*
- if (key === "constructor") {
- return { name: "l10n-mem-leak-defeat" };
- }
- */
-
- return L10N.getStr(key);
- } catch (ex) {
- console.error("Failed to lookup ", key, ex);
- return key;
- }
-};
-
-/** @see propertyLookup in lib/gcli/util/l10n.js */
-exports.propertyLookup = new Proxy({}, {
- get: function (rcvr, name) {
- return exports.lookup(name);
- }
-});
-
-/** @see lookupFormat in lib/gcli/util/l10n.js */
-exports.lookupFormat = function (key, swaps) {
- try {
- return L10N.getFormatStr(key, ...swaps);
- } catch (ex) {
- console.error("Failed to format ", key, ex);
- return key;
- }
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/util/legacy.js b/devtools/shared/gcli/source/lib/gcli/util/legacy.js
deleted file mode 100644
index 07b0fd71aa28..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/legacy.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-/**
- * Fake a console for IE9
- */
-if (typeof window !== 'undefined' && window.console == null) {
- window.console = {};
-}
-'debug,log,warn,error,trace,group,groupEnd'.split(',').forEach(function(f) {
- if (typeof window !== 'undefined' && !window.console[f]) {
- window.console[f] = function() {};
- }
-});
-
-/**
- * Fake Element.classList for IE9
- * Based on https://gist.github.com/1381839 by Devon Govett
- */
-if (typeof document !== 'undefined' && typeof HTMLElement !== 'undefined' &&
- !('classList' in document.documentElement) && Object.defineProperty) {
- Object.defineProperty(HTMLElement.prototype, 'classList', {
- get: function() {
- var self = this;
- function update(fn) {
- return function(value) {
- var classes = self.className.split(/\s+/);
- var index = classes.indexOf(value);
- fn(classes, index, value);
- self.className = classes.join(' ');
- };
- }
-
- var ret = {
- add: update(function(classes, index, value) {
- ~index || classes.push(value);
- }),
- remove: update(function(classes, index) {
- ~index && classes.splice(index, 1);
- }),
- toggle: update(function(classes, index, value) {
- ~index ? classes.splice(index, 1) : classes.push(value);
- }),
- contains: function(value) {
- return !!~self.className.split(/\s+/).indexOf(value);
- },
- item: function(i) {
- return self.className.split(/\s+/)[i] || null;
- }
- };
-
- Object.defineProperty(ret, 'length', {
- get: function() {
- return self.className.split(/\s+/).length;
- }
- });
-
- return ret;
- }
- });
-}
-
-/**
- * Array.find
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
- */
-if (!Array.prototype.find) {
- Object.defineProperty(Array.prototype, 'find', {
- enumerable: false,
- configurable: true,
- writable: true,
- value: function(predicate) {
- if (this == null) {
- throw new TypeError('Array.prototype.find called on null or undefined');
- }
- if (typeof predicate !== 'function') {
- throw new TypeError('predicate must be a function');
- }
- var list = Object(this);
- var length = list.length >>> 0;
- var thisArg = arguments[1];
- var value;
-
- for (var i = 0; i < length; i++) {
- if (i in list) {
- value = list[i];
- if (predicate.call(thisArg, value, i, list)) {
- return value;
- }
- }
- }
- return undefined;
- }
- });
-}
-
-/**
- * String.prototype.trimLeft is non-standard, but it works in Firefox,
- * Chrome and Opera. It's easiest to create a shim here.
- */
-if (!String.prototype.trimLeft) {
- String.prototype.trimLeft = function() {
- return String(this).replace(/\s*$/, '');
- };
-}
-
-/**
- * Polyfil taken from
- * https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
- */
-if (!Function.prototype.bind) {
- Function.prototype.bind = function(oThis) {
- if (typeof this !== 'function') {
- // closest thing possible to the ECMAScript 5 internal IsCallable function
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
-
- var aArgs = Array.prototype.slice.call(arguments, 1),
- fToBind = this,
- fNOP = function () {},
- fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis,
- aArgs.concat(Array.prototype.slice.call(arguments)));
- };
-
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
diff --git a/devtools/shared/gcli/source/lib/gcli/util/moz.build b/devtools/shared/gcli/source/lib/gcli/util/moz.build
deleted file mode 100644
index 0fdeb96ecfcd..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/moz.build
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DevToolsModules(
- 'domtemplate.js',
- 'fileparser.js',
- 'filesystem.js',
- 'host.js',
- 'l10n.js',
- 'legacy.js',
- 'prism.js',
- 'spell.js',
- 'util.js',
-)
diff --git a/devtools/shared/gcli/source/lib/gcli/util/prism.js b/devtools/shared/gcli/source/lib/gcli/util/prism.js
deleted file mode 100644
index 6f457cf23a78..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/prism.js
+++ /dev/null
@@ -1,361 +0,0 @@
-/**
- * Prism: Lightweight, robust, elegant syntax highlighting
- * MIT license http://www.opensource.org/licenses/mit-license.php/
- * @author Lea Verou http://lea.verou.me
- */
-
-'use strict';
-
-// Private helper vars
-var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
-
-var Prism = exports.Prism = {
- util: {
- type: function (o) {
- return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
- },
-
- // Deep clone a language definition (e.g. to extend it)
- clone: function (o) {
- var type = Prism.util.type(o);
-
- switch (type) {
- case 'Object':
- var clone = {};
-
- for (var key in o) {
- if (o.hasOwnProperty(key)) {
- clone[key] = Prism.util.clone(o[key]);
- }
- }
-
- return clone;
-
- case 'Array':
- return o.slice();
- }
-
- return o;
- }
- },
-
- languages: {
- extend: function (id, redef) {
- var lang = Prism.util.clone(Prism.languages[id]);
-
- for (var key in redef) {
- lang[key] = redef[key];
- }
-
- return lang;
- },
-
- // Insert a token before another token in a language literal
- insertBefore: function (inside, before, insert, root) {
- root = root || Prism.languages;
- var grammar = root[inside];
- var ret = {};
-
- for (var token in grammar) {
-
- if (grammar.hasOwnProperty(token)) {
-
- if (token == before) {
-
- for (var newToken in insert) {
-
- if (insert.hasOwnProperty(newToken)) {
- ret[newToken] = insert[newToken];
- }
- }
- }
-
- ret[token] = grammar[token];
- }
- }
-
- root[inside] = ret;
- return ret;
- },
-
- // Traverse a language definition with Depth First Search
- DFS: function(o, callback) {
- for (var i in o) {
- callback.call(o, i, o[i]);
-
- if (Prism.util.type(o) === 'Object') {
- Prism.languages.DFS(o[i], callback);
- }
- }
- }
- },
-
- highlightAll: function(async, callback) {
- var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
-
- elements.forEach(function(element) {
- Prism.highlightElement(element, async === true, callback);
- });
- },
-
- highlightElement: function(element, async, callback) {
- // Find language
- var language;
- var grammar;
-
- var parent = element;
- while (parent && !lang.test(parent.className)) {
- parent = parent.parentNode;
- }
-
- if (parent) {
- language = (parent.className.match(lang) || [,''])[1];
- grammar = Prism.languages[language];
- }
-
- if (!grammar) {
- return;
- }
-
- // Set language on the element, if not present
- element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
-
- // Set language on the parent, for styling
- parent = element.parentNode;
-
- if (/pre/i.test(parent.nodeName)) {
- parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
- }
-
- var code = element.textContent;
-
- if (!code) {
- return;
- }
-
- code = code.replace(/&/g, '&').replace(/ text.length) {
- // Something went terribly wrong, ABORT, ABORT!
- break tokenloop;
- }
-
- if (str instanceof Token) {
- continue;
- }
-
- pattern.lastIndex = 0;
-
- var match = pattern.exec(str);
-
- if (match) {
- if (lookbehind) {
- lookbehindLength = match[1].length;
- }
-
- var from = match.index - 1 + lookbehindLength;
- match = match[0].slice(lookbehindLength);
- var len = match.length;
- var to = from + len;
- var before = str.slice(0, from + 1);
- var after = str.slice(to + 1);
-
- var args = [i, 1];
-
- if (before) {
- args.push(before);
- }
-
- var wrapped = new Token(token, inside? Prism.tokenize(match, inside) : match);
-
- args.push(wrapped);
-
- if (after) {
- args.push(after);
- }
-
- Array.prototype.splice.apply(strarr, args);
- }
- }
- }
-
- return strarr;
- },
-
- hooks: {
- all: {},
-
- add: function (name, callback) {
- var hooks = Prism.hooks.all;
-
- hooks[name] = hooks[name] || [];
-
- hooks[name].push(callback);
- },
-
- run: function (name, env) {
- var callbacks = Prism.hooks.all[name];
-
- if (!callbacks || !callbacks.length) {
- return;
- }
-
- callbacks.forEach(function(callback) {
- callback(env);
- });
- }
- }
-};
-
-var Token = Prism.Token = function(type, content) {
- this.type = type;
- this.content = content;
-};
-
-Token.stringify = function(o, language, parent) {
- if (typeof o == 'string') {
- return o;
- }
-
- if (Object.prototype.toString.call(o) == '[object Array]') {
- return o.map(function(element) {
- return Token.stringify(element, language, o);
- }).join('');
- }
-
- var env = {
- type: o.type,
- content: Token.stringify(o.content, language, parent),
- tag: 'span',
- classes: ['token', o.type],
- attributes: {},
- language: language,
- parent: parent
- };
-
- if (env.type == 'comment') {
- env.attributes.spellcheck = 'true';
- }
-
- Prism.hooks.run('wrap', env);
-
- var attributes = '';
-
- for (var name in env.attributes) {
- attributes += name + '="' + (env.attributes[name] || '') + '"';
- }
-
- return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + '' + env.tag + '>';
-};
-
-Prism.languages.clike = {
- 'comment': {
- pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,
- lookbehind: true
- },
- 'string': /("|')(\\?.)*?\1/g,
- 'class-name': {
- pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,
- lookbehind: true,
- inside: {
- punctuation: /(\.|\\)/
- }
- },
- 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,
- 'boolean': /\b(true|false)\b/g,
- 'function': {
- pattern: /[a-z0-9_]+\(/ig,
- inside: {
- punctuation: /\(/
- }
- },
- 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
- 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
- 'ignore': /&(lt|gt|amp);/gi,
- 'punctuation': /[{}[\];(),.:]/g
-};
-
-Prism.languages.javascript = Prism.languages.extend('clike', {
- 'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|throw|catch|finally|null|break|continue)\b/g,
- 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g
-});
-
-Prism.languages.insertBefore('javascript', 'keyword', {
- 'regex': {
- pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,
- lookbehind: true
- }
-});
-
-if (Prism.languages.markup) {
- Prism.languages.insertBefore('markup', 'tag', {
- 'script': {
- pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,
- inside: {
- 'tag': {
- pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,
- inside: Prism.languages.markup.tag.inside
- },
- rest: Prism.languages.javascript
- }
- }
- });
-}
diff --git a/devtools/shared/gcli/source/lib/gcli/util/spell.js b/devtools/shared/gcli/source/lib/gcli/util/spell.js
deleted file mode 100644
index f16724f2a7a2..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/spell.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-/*
- * A spell-checker based on Damerau-Levenshtein distance.
- */
-
-var CASE_CHANGE_COST = 1;
-var INSERTION_COST = 10;
-var DELETION_COST = 10;
-var SWAP_COST = 10;
-var SUBSTITUTION_COST = 20;
-var MAX_EDIT_DISTANCE = 40;
-
-/**
- * Compute Damerau-Levenshtein Distance, with a modification to allow a low
- * case-change cost (1/10th of a swap-cost)
- * @see http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
- */
-var distance = exports.distance = function(wordi, wordj) {
- var wordiLen = wordi.length;
- var wordjLen = wordj.length;
-
- // We only need to store three rows of our dynamic programming matrix.
- // (Without swap, it would have been two.)
- var row0 = new Array(wordiLen+1);
- var row1 = new Array(wordiLen+1);
- var row2 = new Array(wordiLen+1);
- var tmp;
-
- var i, j;
-
- // The distance between the empty string and a string of size i is the cost
- // of i insertions.
- for (i = 0; i <= wordiLen; i++) {
- row1[i] = i * INSERTION_COST;
- }
-
- // Row-by-row, we're computing the edit distance between substrings wordi[0..i]
- // and wordj[0..j].
- for (j = 1; j <= wordjLen; j++) {
- // Edit distance between wordi[0..0] and wordj[0..j] is the cost of j
- // insertions.
- row0[0] = j * INSERTION_COST;
-
- for (i = 1; i <= wordiLen; i++) {
- // Handle deletion, insertion and substitution: we can reach each cell
- // from three other cells corresponding to those three operations. We
- // want the minimum cost.
- var dc = row0[i - 1] + DELETION_COST;
- var ic = row1[i] + INSERTION_COST;
- var sc0;
- if (wordi[i-1] === wordj[j-1]) {
- sc0 = 0;
- }
- else {
- if (wordi[i-1].toLowerCase() === wordj[j-1].toLowerCase()) {
- sc0 = CASE_CHANGE_COST;
- }
- else {
- sc0 = SUBSTITUTION_COST;
- }
- }
- var sc = row1[i-1] + sc0;
-
- row0[i] = Math.min(dc, ic, sc);
-
- // We handle swap too, eg. distance between help and hlep should be 1. If
- // we find such a swap, there's a chance to update row0[1] to be lower.
- if (i > 1 && j > 1 && wordi[i-1] === wordj[j-2] && wordj[j-1] === wordi[i-2]) {
- row0[i] = Math.min(row0[i], row2[i-2] + SWAP_COST);
- }
- }
-
- tmp = row2;
- row2 = row1;
- row1 = row0;
- row0 = tmp;
- }
-
- return row1[wordiLen];
-};
-
-/**
- * As distance() except that we say that if word is a prefix of name then we
- * only count the case changes. This allows us to use words that can be
- * completed by typing as more likely than short words
- */
-var distancePrefix = exports.distancePrefix = function(word, name) {
- var dist = 0;
-
- for (var i = 0; i < word.length; i++) {
- if (name[i] !== word[i]) {
- if (name[i].toLowerCase() === word[i].toLowerCase()) {
- dist++;
- }
- else {
- // name does not start with word, even ignoring case, use
- // Damerau-Levenshtein
- return exports.distance(word, name);
- }
- }
- }
-
- return dist;
-};
-
-/**
- * A function that returns the correction for the specified word.
- */
-exports.correct = function(word, names) {
- if (names.length === 0) {
- return undefined;
- }
-
- var distances = {};
- var sortedCandidates;
-
- names.forEach(function(candidate) {
- distances[candidate] = exports.distance(word, candidate);
- });
-
- sortedCandidates = names.sort(function(worda, wordb) {
- if (distances[worda] !== distances[wordb]) {
- return distances[worda] - distances[wordb];
- }
- else {
- // if the score is the same, always return the first string
- // in the lexicographical order
- return worda < wordb;
- }
- });
-
- if (distances[sortedCandidates[0]] <= MAX_EDIT_DISTANCE) {
- return sortedCandidates[0];
- }
- else {
- return undefined;
- }
-};
-
-/**
- * Return a ranked list of matches:
- *
- * spell.rank('fred', [ 'banana', 'fred', 'ed', 'red' ]);
- * ↓
- * [
- * { name: 'fred', dist: 0 },
- * { name: 'red', dist: 1 },
- * { name: 'ed', dist: 2 },
- * { name: 'banana', dist: 10 },
- * ]
- *
- * @param word The string that we're comparing names against
- * @param names An array of strings to compare word against
- * @param options Comparison options:
- * - noSort: Do not sort the output by distance
- * - prefixZero: Count prefix matches as edit distance 0 (i.e. word='bana' and
- * names=['banana'], would return { name:'banana': dist: 0 }) This is useful
- * if someone is typing the matches and may not have finished yet
- */
-exports.rank = function(word, names, options) {
- options = options || {};
-
- var reply = names.map(function(name) {
- // If any name starts with the word then the distance is based on the
- // number of case changes rather than Damerau-Levenshtein
- var algo = options.prefixZero ? distancePrefix : distance;
- return {
- name: name,
- dist: algo(word, name)
- };
- });
-
- if (!options.noSort) {
- reply = reply.sort(function(d1, d2) {
- return d1.dist - d2.dist;
- });
- }
-
- return reply;
-};
diff --git a/devtools/shared/gcli/source/lib/gcli/util/util.js b/devtools/shared/gcli/source/lib/gcli/util/util.js
deleted file mode 100644
index b1ead1ffc5da..000000000000
--- a/devtools/shared/gcli/source/lib/gcli/util/util.js
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-/*
- * A number of DOM manipulation and event handling utilities.
- */
-
-//------------------------------------------------------------------------------
-
-var eventDebug = false;
-
-/**
- * Patch up broken console API from node
- */
-if (eventDebug) {
- if (console.group == null) {
- console.group = function() { console.log(arguments); };
- }
- if (console.groupEnd == null) {
- console.groupEnd = function() { console.log(arguments); };
- }
-}
-
-/**
- * Useful way to create a name for a handler, used in createEvent()
- */
-function nameFunction(handler) {
- var scope = handler.scope ? handler.scope.constructor.name + '.' : '';
- var name = handler.func.name;
- if (name) {
- return scope + name;
- }
- for (var prop in handler.scope) {
- if (handler.scope[prop] === handler.func) {
- return scope + prop;
- }
- }
- return scope + handler.func;
-}
-
-/**
- * Create an event.
- * For use as follows:
- *
- * function Hat() {
- * this.putOn = createEvent('Hat.putOn');
- * ...
- * }
- * Hat.prototype.adorn = function(person) {
- * this.putOn({ hat: hat, person: person });
- * ...
- * }
- *
- * var hat = new Hat();
- * hat.putOn.add(function(ev) {
- * console.log('The hat ', ev.hat, ' has is worn by ', ev.person);
- * }, scope);
- *
- * @param name Optional name to help with debugging
- */
-exports.createEvent = function(name) {
- var handlers = [];
- var fireHoldCount = 0;
- var heldEvents = [];
- var eventCombiner;
-
- /**
- * This is how the event is triggered.
- * @param ev The event object to be passed to the event listeners
- */
- var event = function(ev) {
- if (fireHoldCount > 0) {
- heldEvents.push(ev);
- if (eventDebug) {
- console.log('Held fire: ' + name, ev);
- }
- return;
- }
-
- if (eventDebug) {
- console.group('Fire: ' + name + ' to ' + handlers.length + ' listeners', ev);
- }
-
- // Use for rather than forEach because it step debugs better, which is
- // important for debugging events
- for (var i = 0; i < handlers.length; i++) {
- var handler = handlers[i];
- if (eventDebug) {
- console.log(nameFunction(handler));
- }
- handler.func.call(handler.scope, ev);
- }
-
- if (eventDebug) {
- console.groupEnd();
- }
- };
-
- /**
- * Add a new handler function
- * @param func The function to call when this event is triggered
- * @param scope Optional 'this' object for the function call
- */
- event.add = function(func, scope) {
- if (typeof func !== 'function') {
- throw new Error(name + ' add(func,...), 1st param is ' + typeof func);
- }
-
- if (eventDebug) {
- console.log('Adding listener to ' + name);
- }
-
- handlers.push({ func: func, scope: scope });
- };
-
- /**
- * Remove a handler function added through add(). Both func and scope must
- * be strict equals (===) the values used in the call to add()
- * @param func The function to call when this event is triggered
- * @param scope Optional 'this' object for the function call
- */
- event.remove = function(func, scope) {
- if (eventDebug) {
- console.log('Removing listener from ' + name);
- }
-
- var found = false;
- handlers = handlers.filter(function(test) {
- var match = (test.func === func && test.scope === scope);
- if (match) {
- found = true;
- }
- return !match;
- });
- if (!found) {
- console.warn('Handler not found. Attached to ' + name);
- }
- };
-
- /**
- * Remove all handlers.
- * Reset the state of this event back to it's post create state
- */
- event.removeAll = function() {
- handlers = [];
- };
-
- /**
- * Fire an event just once using a promise.
- */
- event.once = function() {
- if (arguments.length !== 0) {
- throw new Error('event.once uses promise return values');
- }
-
- return new Promise(function(resolve, reject) {
- var handler = function(arg) {
- event.remove(handler);
- resolve(arg);
- };
-
- event.add(handler);
- });
- };
-
- /**
- * Temporarily prevent this event from firing.
- * @see resumeFire(ev)
- */
- event.holdFire = function() {
- if (eventDebug) {
- console.group('Holding fire: ' + name);
- }
-
- fireHoldCount++;
- };
-
- /**
- * Resume firing events.
- * If there are heldEvents, then we fire one event to cover them all. If an
- * event combining function has been provided then we use that to combine the
- * events. Otherwise the last held event is used.
- * @see holdFire()
- */
- event.resumeFire = function() {
- if (eventDebug) {
- console.groupEnd('Resume fire: ' + name);
- }
-
- if (fireHoldCount === 0) {
- throw new Error('fireHoldCount === 0 during resumeFire on ' + name);
- }
-
- fireHoldCount--;
- if (heldEvents.length === 0) {
- return;
- }
-
- if (heldEvents.length === 1) {
- event(heldEvents[0]);
- }
- else {
- var first = heldEvents[0];
- var last = heldEvents[heldEvents.length - 1];
- if (eventCombiner) {
- event(eventCombiner(first, last, heldEvents));
- }
- else {
- event(last);
- }
- }
-
- heldEvents = [];
- };
-
- /**
- * When resumeFire has a number of events to combine, by default it just
- * picks the last, however you can provide an eventCombiner which returns a
- * combined event.
- * eventCombiners will be passed 3 parameters:
- * - first The first event to be held
- * - last The last event to be held
- * - all An array containing all the held events
- * The return value from an eventCombiner is expected to be an event object
- */
- Object.defineProperty(event, 'eventCombiner', {
- set: function(newEventCombiner) {
- if (typeof newEventCombiner !== 'function') {
- throw new Error('eventCombiner is not a function');
- }
- eventCombiner = newEventCombiner;
- },
-
- enumerable: true
- });
-
- return event;
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * promiseEach is roughly like Array.forEach except that the action is taken to
- * be something that completes asynchronously, returning a promise, so we wait
- * for the action to complete for each array element before moving onto the
- * next.
- * @param array An array of objects to enumerate
- * @param action A function to call for each member of the array
- * @param scope Optional object to use as 'this' for the function calls
- * @return A promise which is resolved (with an array of resolution values)
- * when all the array members have been passed to the action function, and
- * rejected as soon as any of the action function calls fails
- */
-exports.promiseEach = function(array, action, scope) {
- if (array.length === 0) {
- return Promise.resolve([]);
- }
-
- var allReply = [];
- var promise = Promise.resolve();
-
- array.forEach(function(member, i) {
- promise = promise.then(function() {
- var reply = action.call(scope, member, i, array);
- return Promise.resolve(reply).then(function(data) {
- allReply[i] = data;
- });
- });
- });
-
- return promise.then(function() {
- return allReply;
- });
-};
-
-/**
- * Catching errors from promises isn't as simple as:
- * promise.then(handler, console.error);
- * for a number of reasons:
- * - chrome's console doesn't have bound functions (why?)
- * - we don't get stack traces out from console.error(ex);
- */
-exports.errorHandler = function(ex) {
- if (ex instanceof Error) {
- // V8 weirdly includes the exception message in the stack
- if (ex.stack.includes(ex.message)) {
- console.error(ex.stack);
- }
- else {
- console.error('' + ex);
- console.error(ex.stack);
- }
- }
- else {
- console.error(ex);
- }
-};
-
-
-//------------------------------------------------------------------------------
-
-/**
- * Copy the properties from one object to another in a way that preserves
- * function properties as functions rather than copying the calculated value
- * as copy time
- */
-exports.copyProperties = function(src, dest) {
- for (var key in src) {
- var descriptor;
- var obj = src;
- while (true) {
- descriptor = Object.getOwnPropertyDescriptor(obj, key);
- if (descriptor != null) {
- break;
- }
- obj = Object.getPrototypeOf(obj);
- if (obj == null) {
- throw new Error('Can\'t find descriptor of ' + key);
- }
- }
-
- if ('value' in descriptor) {
- dest[key] = src[key];
- }
- else if ('get' in descriptor) {
- Object.defineProperty(dest, key, {
- get: descriptor.get,
- set: descriptor.set,
- enumerable: descriptor.enumerable
- });
- }
- else {
- throw new Error('Don\'t know how to copy ' + key + ' property.');
- }
- }
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * XHTML namespace
- */
-exports.NS_XHTML = 'http://www.w3.org/1999/xhtml';
-
-/**
- * XUL namespace
- */
-exports.NS_XUL = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
-
-/**
- * Create an HTML or XHTML element depending on whether the document is HTML
- * or XML based. Where HTML/XHTML elements are distinguished by whether they
- * are created using doc.createElementNS('http://www.w3.org/1999/xhtml', tag)
- * or doc.createElement(tag)
- * If you want to create a XUL element then you don't have a problem knowing
- * what namespace you want.
- * @param doc The document in which to create the element
- * @param tag The name of the tag to create
- * @returns The created element
- */
-exports.createElement = function(doc, tag) {
- if (exports.isXmlDocument(doc)) {
- return doc.createElementNS(exports.NS_XHTML, tag);
- }
- else {
- return doc.createElement(tag);
- }
-};
-
-/**
- * Remove all the child nodes from this node
- * @param elem The element that should have it's children removed
- */
-exports.clearElement = function(elem) {
- while (elem.hasChildNodes()) {
- elem.firstChild.remove();
- }
-};
-
-var isAllWhitespace = /^\s*$/;
-
-/**
- * Iterate over the children of a node looking for TextNodes that have only
- * whitespace content and remove them.
- * This utility is helpful when you have a template which contains whitespace
- * so it looks nice, but where the whitespace interferes with the rendering of
- * the page
- * @param elem The element which should have blank whitespace trimmed
- * @param deep Should this node removal include child elements
- */
-exports.removeWhitespace = function(elem, deep) {
- var i = 0;
- while (i < elem.childNodes.length) {
- var child = elem.childNodes.item(i);
- if (child.nodeType === 3 /*Node.TEXT_NODE*/ &&
- isAllWhitespace.test(child.textContent)) {
- elem.removeChild(child);
- }
- else {
- if (deep && child.nodeType === 1 /*Node.ELEMENT_NODE*/) {
- exports.removeWhitespace(child, deep);
- }
- i++;
- }
- }
-};
-
-/**
- * Create a style element in the document head, and add the given CSS text to
- * it.
- * @param cssText The CSS declarations to append
- * @param doc The document element to work from
- * @param id Optional id to assign to the created style tag. If the id already
- * exists on the document, we do not add the CSS again.
- */
-exports.importCss = function(cssText, doc, id) {
- if (!cssText) {
- return undefined;
- }
-
- doc = doc || document;
-
- if (!id) {
- id = 'hash-' + hash(cssText);
- }
-
- var found = doc.getElementById(id);
- if (found) {
- if (found.tagName.toLowerCase() !== 'style') {
- console.error('Warning: importCss passed id=' + id +
- ', but that pre-exists (and isn\'t a style tag)');
- }
- return found;
- }
-
- var style = exports.createElement(doc, 'style');
- style.id = id;
- style.appendChild(doc.createTextNode(cssText));
-
- var head = doc.getElementsByTagName('head')[0] || doc.documentElement;
- head.appendChild(style);
-
- return style;
-};
-
-/**
- * Simple hash function which happens to match Java's |String.hashCode()|
- * Done like this because I we don't need crypto-security, but do need speed,
- * and I don't want to spend a long time working on it.
- * @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
- */
-function hash(str) {
- var h = 0;
- if (str.length === 0) {
- return h;
- }
- for (var i = 0; i < str.length; i++) {
- var character = str.charCodeAt(i);
- h = ((h << 5) - h) + character;
- h = h & h; // Convert to 32bit integer
- }
- return h;
-}
-
-/**
- * Shortcut for clearElement/createTextNode/appendChild to make up for the lack
- * of standards around textContent/innerText
- */
-exports.setTextContent = function(elem, text) {
- exports.clearElement(elem);
- var child = elem.ownerDocument.createTextNode(text);
- elem.appendChild(child);
-};
-
-/**
- * There are problems with innerHTML on XML documents, so we need to do a dance
- * using document.createRange().createContextualFragment() when in XML mode
- */
-exports.setContents = function(elem, contents) {
- if (typeof HTMLElement !== 'undefined' && contents instanceof HTMLElement) {
- exports.clearElement(elem);
- elem.appendChild(contents);
- return;
- }
-
- if ("innerHTML" in elem) {
- elem.innerHTML = contents;
- } else {
- try {
- var ns = elem.ownerDocument.documentElement.namespaceURI;
- if (!ns) {
- ns = exports.NS_XHTML;
- }
- exports.clearElement(elem);
- contents = '
' + contents + '
';
- var range = elem.ownerDocument.createRange();
- var child = range.createContextualFragment(contents).firstChild;
- while (child.hasChildNodes()) {
- elem.appendChild(child.firstChild);
- }
- }
- catch (ex) {
- console.error('Bad XHTML', ex);
- console.trace();
- throw ex;
- }
- }
-};
-
-/**
- * How to detect if we're in an XML document.
- * In a Mozilla we check that document.xmlVersion = null, however in Chrome
- * we use document.contentType = undefined.
- * @param doc The document element to work from (defaulted to the global
- * 'document' if missing
- */
-exports.isXmlDocument = function(doc) {
- doc = doc || document;
- // Best test for Firefox
- if (doc.contentType && doc.contentType != 'text/html') {
- return true;
- }
- // Best test for Chrome
- if (doc.xmlVersion != null) {
- return true;
- }
- return false;
-};
-
-/**
- * We'd really like to be able to do 'new NodeList()'
- */
-exports.createEmptyNodeList = function(doc) {
- if (doc.createDocumentFragment) {
- return doc.createDocumentFragment().childNodes;
- }
- return doc.querySelectorAll('x>:root');
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * Keyboard handling is a mess. http://unixpapa.com/js/key.html
- * It would be good to use DOM L3 Keyboard events,
- * http://www.w3.org/TR/2010/WD-DOM-Level-3-Events-20100907/#events-keyboardevents
- * however only Webkit supports them, and there isn't a shim on Modernizr:
- * https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills
- * and when the code that uses this KeyEvent was written, nothing was clear,
- * so instead, we're using this unmodern shim:
- * http://stackoverflow.com/questions/5681146/chrome-10-keyevent-or-something-similar-to-firefoxs-keyevent
- * See BUG 664991: GCLI's keyboard handling should be updated to use DOM-L3
- * https://bugzilla.mozilla.org/show_bug.cgi?id=664991
- */
-exports.KeyEvent = {
- DOM_VK_CANCEL: 3,
- DOM_VK_HELP: 6,
- DOM_VK_BACK_SPACE: 8,
- DOM_VK_TAB: 9,
- DOM_VK_CLEAR: 12,
- DOM_VK_RETURN: 13,
- DOM_VK_SHIFT: 16,
- DOM_VK_CONTROL: 17,
- DOM_VK_ALT: 18,
- DOM_VK_PAUSE: 19,
- DOM_VK_CAPS_LOCK: 20,
- DOM_VK_ESCAPE: 27,
- DOM_VK_SPACE: 32,
- DOM_VK_PAGE_UP: 33,
- DOM_VK_PAGE_DOWN: 34,
- DOM_VK_END: 35,
- DOM_VK_HOME: 36,
- DOM_VK_LEFT: 37,
- DOM_VK_UP: 38,
- DOM_VK_RIGHT: 39,
- DOM_VK_DOWN: 40,
- DOM_VK_PRINTSCREEN: 44,
- DOM_VK_INSERT: 45,
- DOM_VK_DELETE: 46,
- DOM_VK_0: 48,
- DOM_VK_1: 49,
- DOM_VK_2: 50,
- DOM_VK_3: 51,
- DOM_VK_4: 52,
- DOM_VK_5: 53,
- DOM_VK_6: 54,
- DOM_VK_7: 55,
- DOM_VK_8: 56,
- DOM_VK_9: 57,
- DOM_VK_SEMICOLON: 59,
- DOM_VK_EQUALS: 61,
- DOM_VK_A: 65,
- DOM_VK_B: 66,
- DOM_VK_C: 67,
- DOM_VK_D: 68,
- DOM_VK_E: 69,
- DOM_VK_F: 70,
- DOM_VK_G: 71,
- DOM_VK_H: 72,
- DOM_VK_I: 73,
- DOM_VK_J: 74,
- DOM_VK_K: 75,
- DOM_VK_L: 76,
- DOM_VK_M: 77,
- DOM_VK_N: 78,
- DOM_VK_O: 79,
- DOM_VK_P: 80,
- DOM_VK_Q: 81,
- DOM_VK_R: 82,
- DOM_VK_S: 83,
- DOM_VK_T: 84,
- DOM_VK_U: 85,
- DOM_VK_V: 86,
- DOM_VK_W: 87,
- DOM_VK_X: 88,
- DOM_VK_Y: 89,
- DOM_VK_Z: 90,
- DOM_VK_CONTEXT_MENU: 93,
- DOM_VK_NUMPAD0: 96,
- DOM_VK_NUMPAD1: 97,
- DOM_VK_NUMPAD2: 98,
- DOM_VK_NUMPAD3: 99,
- DOM_VK_NUMPAD4: 100,
- DOM_VK_NUMPAD5: 101,
- DOM_VK_NUMPAD6: 102,
- DOM_VK_NUMPAD7: 103,
- DOM_VK_NUMPAD8: 104,
- DOM_VK_NUMPAD9: 105,
- DOM_VK_MULTIPLY: 106,
- DOM_VK_ADD: 107,
- DOM_VK_SEPARATOR: 108,
- DOM_VK_SUBTRACT: 109,
- DOM_VK_DECIMAL: 110,
- DOM_VK_DIVIDE: 111,
- DOM_VK_F1: 112,
- DOM_VK_F2: 113,
- DOM_VK_F3: 114,
- DOM_VK_F4: 115,
- DOM_VK_F5: 116,
- DOM_VK_F6: 117,
- DOM_VK_F7: 118,
- DOM_VK_F8: 119,
- DOM_VK_F9: 120,
- DOM_VK_F10: 121,
- DOM_VK_F11: 122,
- DOM_VK_F12: 123,
- DOM_VK_F13: 124,
- DOM_VK_F14: 125,
- DOM_VK_F15: 126,
- DOM_VK_F16: 127,
- DOM_VK_F17: 128,
- DOM_VK_F18: 129,
- DOM_VK_F19: 130,
- DOM_VK_F20: 131,
- DOM_VK_F21: 132,
- DOM_VK_F22: 133,
- DOM_VK_F23: 134,
- DOM_VK_F24: 135,
- DOM_VK_NUM_LOCK: 144,
- DOM_VK_SCROLL_LOCK: 145,
- DOM_VK_COMMA: 188,
- DOM_VK_PERIOD: 190,
- DOM_VK_SLASH: 191,
- DOM_VK_BACK_QUOTE: 192,
- DOM_VK_OPEN_BRACKET: 219,
- DOM_VK_BACK_SLASH: 220,
- DOM_VK_CLOSE_BRACKET: 221,
- DOM_VK_QUOTE: 222,
- DOM_VK_META: 224
-};
diff --git a/devtools/shared/gcli/templater.js b/devtools/shared/gcli/templater.js
deleted file mode 100644
index 185d39539021..000000000000
--- a/devtools/shared/gcli/templater.js
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * Copyright 2012, Mozilla Foundation and contributors
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-"use strict";
-
-/* globals document */
-
-/**
- * For full documentation, see:
- * https://github.com/mozilla/domtemplate/blob/master/README.md
- */
-
-/**
- * Begin a new templating process.
- * @param node A DOM element or string referring to an element's id
- * @param data Data to use in filling out the template
- * @param options Options to customize the template processing. One of:
- * - allowEval: boolean (default false) Basic template interpolations are
- * either property paths (e.g. ${a.b.c.d}), or if allowEval=true then we
- * allow arbitrary JavaScript
- * - stack: string or array of strings (default empty array) The template
- * engine maintains a stack of tasks to help debug where it is. This allows
- * this stack to be prefixed with a template name
- * - blankNullUndefined: By default DOMTemplate exports null and undefined
- * values using the strings 'null' and 'undefined', which can be helpful for
- * debugging, but can introduce unnecessary extra logic in a template to
- * convert null/undefined to ''. By setting blankNullUndefined:true, this
- * conversion is handled by DOMTemplate
- */
-var template = function(node, data, options) {
- const state = {
- options: options || {},
- // We keep a track of the nodes that we've passed through so we can keep
- // data.__element pointing to the correct node
- nodes: []
- };
-
- state.stack = state.options.stack;
-
- if (!Array.isArray(state.stack)) {
- if (typeof state.stack === "string") {
- state.stack = [ options.stack ];
- } else {
- state.stack = [];
- }
- }
-
- processNode(state, node, data);
-};
-
-if (typeof exports !== "undefined") {
- exports.template = template;
-}
-this.template = template;
-
-/**
- * Helper for the places where we need to act asynchronously and keep track of
- * where we are right now
- */
-function cloneState(state) {
- return {
- options: state.options,
- stack: state.stack.slice(),
- nodes: state.nodes.slice()
- };
-}
-
-/**
- * Regex used to find ${...} sections in some text.
- * Performance note: This regex uses ( and ) to capture the 'script' for
- * further processing. Not all of the uses of this regex use this feature so
- * if use of the capturing group is a performance drain then we should split
- * this regex in two.
- */
-var TEMPLATE_REGION = /\$\{([^}]*)\}/g;
-
-/**
- * Recursive function to walk the tree processing the attributes as it goes.
- * @param node the node to process. If you pass a string in instead of a DOM
- * element, it is assumed to be an id for use with document.getElementById()
- * @param data the data to use for node processing.
- */
-function processNode(state, node, data) {
- if (typeof node === "string") {
- node = document.getElementById(node);
- }
- if (data == null) {
- data = {};
- }
- state.stack.push(node.nodeName + (node.id ? "#" + node.id : ""));
- let pushedNode = false;
- try {
- // Process attributes
- if (node.attributes && node.attributes.length) {
- // We need to handle 'foreach' and 'if' first because they might stop
- // some types of processing from happening, and foreach must come first
- // because it defines new data on which 'if' might depend.
- if (node.hasAttribute("foreach")) {
- processForEach(state, node, data);
- return;
- }
- if (node.hasAttribute("if")) {
- if (!processIf(state, node, data)) {
- return;
- }
- }
- // Only make the node available once we know it's not going away
- state.nodes.push(data.__element);
- data.__element = node;
- pushedNode = true;
- // It's good to clean up the attributes when we've processed them,
- // but if we do it straight away, we mess up the array index
- const attrs = Array.prototype.slice.call(node.attributes);
- for (let i = 0; i < attrs.length; i++) {
- let value = attrs[i].value;
- let name = attrs[i].name;
-
- state.stack.push(name);
- try {
- if (name === "save") {
- // Save attributes are a setter using the node
- value = stripBraces(state, value);
- property(state, value, data, node);
- node.removeAttribute("save");
- } else if (name.substring(0, 2) === "on") {
- // If this attribute value contains only an expression
- if (value.substring(0, 2) === "${" && value.slice(-1) === "}" &&
- !value.includes("${", 2)) {
- value = stripBraces(state, value);
- const func = property(state, value, data);
- if (typeof func === "function") {
- node.removeAttribute(name);
- const capture = node.hasAttribute("capture" + name.substring(2));
- node.addEventListener(name.substring(2), func, capture);
- if (capture) {
- node.removeAttribute("capture" + name.substring(2));
- }
- } else {
- // Attribute value is not a function - use as a DOM-L0 string
- node.setAttribute(name, func);
- }
- } else {
- // Attribute value is not a single expression use as DOM-L0
- node.setAttribute(name, processString(state, value, data));
- }
- } else {
- node.removeAttribute(name);
- // Remove '_' prefix of attribute names so the DOM won't try
- // to use them before we've processed the template
- if (name.charAt(0) === "_") {
- name = name.substring(1);
- }
-
- // Async attributes can only work if the whole attribute is async
- let replacement;
- if (value.indexOf("${") === 0 &&
- value.charAt(value.length - 1) === "}") {
- replacement = envEval(state, value.slice(2, -1), data, value);
- if (replacement && typeof replacement.then === "function") {
- node.setAttribute(name, "");
- /* jshint loopfunc:true */
- replacement.then(function(newValue) {
- node.setAttribute(name, newValue);
- }).catch(console.error);
- } else {
- if (state.options.blankNullUndefined && replacement == null) {
- replacement = "";
- }
- node.setAttribute(name, replacement);
- }
- } else {
- node.setAttribute(name, processString(state, value, data));
- }
- }
- } finally {
- state.stack.pop();
- }
- }
- }
-
- // Loop through our children calling processNode. First clone them, so the
- // set of nodes that we visit will be unaffected by additions or removals.
- const childNodes = Array.prototype.slice.call(node.childNodes);
- for (let j = 0; j < childNodes.length; j++) {
- processNode(state, childNodes[j], data);
- }
-
- /* 3 === Node.TEXT_NODE */
- if (node.nodeType === 3) {
- processTextNode(state, node, data);
- }
- } finally {
- if (pushedNode) {
- data.__element = state.nodes.pop();
- }
- state.stack.pop();
- }
-}
-
-/**
- * Handle attribute values where the output can only be a string
- */
-function processString(state, value, data) {
- return value.replace(TEMPLATE_REGION, function(path) {
- const insert = envEval(state, path.slice(2, -1), data, value);
- return state.options.blankNullUndefined && insert == null ? "" : insert;
- });
-}
-
-/**
- * Handle
- * @param node An element with an 'if' attribute
- * @param data The data to use with envEval()
- * @returns true if processing should continue, false otherwise
- */
-function processIf(state, node, data) {
- state.stack.push("if");
- try {
- const originalValue = node.getAttribute("if");
- const value = stripBraces(state, originalValue);
- let recurse = true;
- try {
- const reply = envEval(state, value, data, originalValue);
- recurse = !!reply;
- } catch (ex) {
- handleError(state, "Error with '" + value + "'", ex);
- recurse = false;
- }
- if (!recurse) {
- node.remove();
- }
- node.removeAttribute("if");
- return recurse;
- } finally {
- state.stack.pop();
- }
-}
-
-/**
- * Handle and the special case of
- * .
- * This function is responsible for extracting what it has to do from the
- * attributes, and getting the data to work on (including resolving promises
- * in getting the array). It delegates to processForEachLoop to actually
- * unroll the data.
- * @param node An element with a 'foreach' attribute
- * @param data The data to use with envEval()
- */
-function processForEach(state, node, data) {
- state.stack.push("foreach");
- try {
- const originalValue = node.getAttribute("foreach");
- let value = originalValue;
-
- let paramName = "param";
- if (value.charAt(0) === "$") {
- // No custom loop variable name. Use the default: 'param'
- value = stripBraces(state, value);
- } else {
- // Extract the loop variable name from 'NAME in ${ARRAY}'
- const nameArr = value.split(" in ");
- paramName = nameArr[0].trim();
- value = stripBraces(state, nameArr[1].trim());
- }
- node.removeAttribute("foreach");
- try {
- const evaled = envEval(state, value, data, originalValue);
- const cState = cloneState(state);
- handleAsync(evaled, node, function(reply, siblingNode) {
- processForEachLoop(cState, reply, node, siblingNode, data, paramName);
- });
- node.remove();
- } catch (ex) {
- handleError(state, "Error with " + value + "'", ex);
- }
- } finally {
- state.stack.pop();
- }
-}
-
-/**
- * Called by processForEach to handle looping over the data in a foreach loop.
- * This works with both arrays and objects.
- * Calls processForEachMember() for each member of 'set'
- * @param set The object containing the data to loop over
- * @param templNode The node to copy for each set member
- * @param sibling The sibling node to which we add things
- * @param data the data to use for node processing
- * @param paramName foreach loops have a name for the parameter currently being
- * processed. The default is 'param'. e.g. ...
- */
-function processForEachLoop(state, set, templNode, sibling, data, paramName) {
- if (Array.isArray(set)) {
- set.forEach(function(member, i) {
- processForEachMember(state, member, templNode, sibling,
- data, paramName, "" + i);
- });
- } else {
- for (const member in set) {
- if (set.hasOwnProperty(member)) {
- processForEachMember(state, member, templNode, sibling,
- data, paramName, member);
- }
- }
- }
-}
-
-/**
- * Called by processForEachLoop() to resolve any promises in the array (the
- * array itself can also be a promise, but that is resolved by
- * processForEach()). Handle elements (which are taken out of the DOM),
- * clone the template node, and pass the processing on to processNode().
- * @param member The data item to use in templating
- * @param templNode The node to copy for each set member
- * @param siblingNode The parent node to which we add things
- * @param data the data to use for node processing
- * @param paramName The name given to 'member' by the foreach attribute
- * @param frame A name to push on the stack for debugging
- */
-function processForEachMember(state, member, templNode, siblingNode, data,
- paramName, frame) {
- state.stack.push(frame);
- try {
- const cState = cloneState(state);
- handleAsync(member, siblingNode, function(reply, node) {
- // Clone data because we can't be sure that we can safely mutate it
- const newData = Object.create(null);
- Object.keys(data).forEach(function(key) {
- newData[key] = data[key];
- });
- newData[paramName] = reply;
- if (node.parentNode != null) {
- let clone;
- if (templNode.nodeName.toLowerCase() === "loop") {
- for (let i = 0; i < templNode.childNodes.length; i++) {
- clone = templNode.childNodes[i].cloneNode(true);
- node.parentNode.insertBefore(clone, node);
- processNode(cState, clone, newData);
- }
- } else {
- clone = templNode.cloneNode(true);
- clone.removeAttribute("foreach");
- node.parentNode.insertBefore(clone, node);
- processNode(cState, clone, newData);
- }
- }
- });
- } finally {
- state.stack.pop();
- }
-}
-
-/**
- * Take a text node and replace it with another text node with the ${...}
- * sections parsed out. We replace the node by altering node.parentNode but
- * we could probably use a DOM Text API to achieve the same thing.
- * @param node The Text node to work on
- * @param data The data to use in calls to envEval()
- */
-function processTextNode(state, node, data) {
- // Replace references in other attributes
- let value = node.data;
- // We can't use the string.replace() with function trick (see generic
- // attribute processing in processNode()) because we need to support
- // functions that return DOM nodes, so we can't have the conversion to a
- // string.
- // Instead we process the string as an array of parts. In order to split
- // the string up, we first replace '${' with '\uF001$' and '}' with '\uF002'
- // We can then split using \uF001 or \uF002 to get an array of strings
- // where scripts are prefixed with $.
- // \uF001 and \uF002 are just unicode chars reserved for private use.
- value = value.replace(TEMPLATE_REGION, "\uF001$$$1\uF002");
- // Split a string using the unicode chars F001 and F002.
- const parts = value.split(/\uF001|\uF002/);
- if (parts.length > 1) {
- parts.forEach(function(part) {
- if (part === null || part === undefined || part === "") {
- return;
- }
- if (part.charAt(0) === "$") {
- part = envEval(state, part.slice(1), data, node.data);
- }
- const cState = cloneState(state);
- handleAsync(part, node, function(reply, siblingNode) {
- const doc = siblingNode.ownerDocument;
- if (reply == null) {
- reply = cState.options.blankNullUndefined ? "" : "" + reply;
- }
- if (typeof reply.cloneNode === "function") {
- // i.e. if (reply instanceof Element) { ...
- reply = maybeImportNode(cState, reply, doc);
- siblingNode.parentNode.insertBefore(reply, siblingNode);
- } else if (typeof reply.item === "function" && reply.length) {
- // NodeLists can be live, in which case maybeImportNode can
- // remove them from the document, and thus the NodeList, which in
- // turn breaks iteration. So first we clone the list
- const list = Array.prototype.slice.call(reply, 0);
- list.forEach(function(child) {
- const imported = maybeImportNode(cState, child, doc);
- siblingNode.parentNode.insertBefore(imported, siblingNode);
- });
- } else {
- // if thing isn't a DOM element then wrap its string value in one
- reply = doc.createTextNode(reply.toString());
- siblingNode.parentNode.insertBefore(reply, siblingNode);
- }
- });
- });
- node.remove();
- }
-}
-
-/**
- * Return node or a import of node, if it's not in the given document
- * @param node The node that we want to be properly owned
- * @param doc The document that the given node should belong to
- * @return A node that belongs to the given document
- */
-function maybeImportNode(state, node, doc) {
- return node.ownerDocument === doc ? node : doc.importNode(node, true);
-}
-
-/**
- * A function to handle the fact that some nodes can be promises, so we check
- * and resolve if needed using a marker node to keep our place before calling
- * an inserter function.
- * @param thing The object which could be real data or a promise of real data
- * we use it directly if it's not a promise, or resolve it if it is.
- * @param siblingNode The element before which we insert new elements.
- * @param inserter The function to to the insertion. If thing is not a promise
- * then handleAsync() is just 'inserter(thing, siblingNode)'
- */
-function handleAsync(thing, siblingNode, inserter) {
- if (thing != null && typeof thing.then === "function") {
- // Placeholder element to be replaced once we have the real data
- const tempNode = siblingNode.ownerDocument.createElement("span");
- siblingNode.parentNode.insertBefore(tempNode, siblingNode);
- thing.then(function(delayed) {
- inserter(delayed, tempNode);
- if (tempNode.parentNode != null) {
- tempNode.remove();
- }
- }).catch(function(error) {
- console.error(error.stack);
- });
- } else {
- inserter(thing, siblingNode);
- }
-}
-
-/**
- * Warn of string does not begin '${' and end '}'
- * @param str the string to check.
- * @return The string stripped of ${ and }, or untouched if it does not match
- */
-function stripBraces(state, str) {
- if (!str.match(TEMPLATE_REGION)) {
- handleError(state, "Expected " + str + " to match ${...}");
- return str;
- }
- return str.slice(2, -1);
-}
-
-/**
- * Combined getter and setter that works with a path through some data set.
- * For example:
- *
property(state, 'a', { a: { b: 99 }}, 42); // returns 99 and alters the
- * input data to be { a: { b: 42 }}
- *
- * @param path An array of strings indicating the path through the data, or
- * a string to be cut into an array using split('.')
- * @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 path before any
- * newValue is applied.
- */
-function property(state, path, data, newValue) {
- try {
- if (typeof path === "string") {
- path = path.split(".");
- }
- const value = data[path[0]];
- if (path.length === 1) {
- if (newValue !== undefined) {
- data[path[0]] = newValue;
- }
- if (typeof value === "function") {
- return value.bind(data);
- }
- return value;
- }
- if (!value) {
- handleError(state, "\"" + path[0] + "\" is undefined");
- return null;
- }
- return property(state, path.slice(1), value, newValue);
- } catch (ex) {
- handleError(state, "Path error with '" + path + "'", ex);
- return "${" + path + "}";
- }
-}
-
-/**
- * Like eval, but that creates a context of the variables in env in
- * which the script is evaluated.
- * @param script The string to be evaluated.
- * @param data The environment in which to eval the script.
- * @param frame Optional debugging string in case of failure.
- * @return The return value of the script, or the error message if the script
- * execution failed.
- */
-function envEval(state, script, data, frame) {
- try {
- state.stack.push(frame.replace(/\s+/g, " "));
- // Detect if a script is capable of being interpreted using property()
- if (/^[_a-zA-Z0-9.]*$/.test(script)) {
- return property(state, script, data);
- }
- if (!state.options.allowEval) {
- handleError(state, "allowEval is not set, however '" + script + "'" +
- " can not be resolved using a simple property path.");
- return "${" + script + "}";
- }
-
- // What we're looking to do is basically:
- // with(data) { return eval(script); }
- // except in strict mode where 'with' is banned.
- // So we create a function which has a parameter list the same as the
- // keys in 'data' and with 'script' as its function body.
- // We then call this function with the values in 'data'
- const keys = allKeys(data);
- const func = Function.apply(null, keys.concat("return " + script));
-
- const values = keys.map((key) => data[key]);
- return func.apply(null, values);
-
- // TODO: The 'with' method is different from the code above in the value
- // of 'this' when calling functions. For example:
- // envEval(state, 'foo()', { foo: function () { return this; } }, ...);
- // The global for 'foo' when using 'with' is the data object. However the
- // code above, the global is null. (Using 'func.apply(data, values)'
- // changes 'this' in the 'foo()' frame, but not in the inside the body
- // of 'foo', so that wouldn't help)
- } catch (ex) {
- handleError(state, "Template error evaluating '" + script + "'", ex);
- return "${" + script + "}";
- } finally {
- state.stack.pop();
- }
-}
-
-/**
- * Object.keys() that respects the prototype chain
- */
-function allKeys(data) {
- const keys = [];
- for (const key in data) {
- keys.push(key);
- }
- return keys;
-}
-
-/**
- * A generic way of reporting errors, for easy overloading in different
- * environments.
- * @param message the error message to report.
- * @param ex optional associated exception.
- */
-function handleError(state, message, ex) {
- logError(message + " (In: " + state.stack.join(" > ") + ")");
- if (ex) {
- logError(ex);
- }
-}
-
-/**
- * A generic way of reporting errors, for easy overloading in different
- * environments.
- * @param message the error message to report.
- */
-function logError(message) {
- console.error(message);
-}
-
-exports.template = template;
diff --git a/devtools/shared/locales/en-US/gcli.properties b/devtools/shared/locales/en-US/gcli.properties
deleted file mode 100644
index 2f2b9609ea74..000000000000
--- a/devtools/shared/locales/en-US/gcli.properties
+++ /dev/null
@@ -1,301 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# 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.
-
-# For each command there are in general two strings. As an example consider
-# the 'pref' command.
-# commandDesc (e.g. prefDesc for the command 'pref'): this string contains a
-# very short description of the command. It's designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-# commandManual (e.g. prefManual for the command 'pref'): this string will
-# contain a fuller description of the command. It's displayed when the user
-# asks for help about a specific command (e.g. 'help pref').
-
-# LOCALIZATION NOTE: This message is used to describe any command or command
-# parameter when no description has been provided.
-canonDescNone=(No description)
-
-# LOCALIZATION NOTE: The default name for a group of parameters.
-canonDefaultGroupName=Options
-
-# LOCALIZATION NOTE (canonProxyDesc, canonProxyManual): These commands are
-# used to execute commands on a remote system (using a proxy). Parameters: %S
-# is the name of the remote system.
-canonProxyDesc=Execute a command on %S
-canonProxyManual=A set of commands that are executed on a remote system. The remote system is reached via %S
-
-# LOCALIZATION NOTE: This error message is displayed when we try to add a new
-# command (using a proxy) where one already exists with the same name.
-canonProxyExists=There is already a command called ‘%S’
-
-# LOCALIZATION NOTE: This message describes the '{' command, which allows
-# entry of JavaScript like traditional developer tool command lines.
-cliEvalJavascript=Enter JavaScript directly
-
-# LOCALIZATION NOTE: This message is displayed when the command line has more
-# arguments than the current command can understand.
-cliUnusedArg=Too many arguments
-
-# LOCALIZATION NOTE: The title of the dialog which displays the options that
-# are available to the current command.
-cliOptions=Available Options
-
-# LOCALIZATION NOTE: The error message when the user types a command that
-# isn't registered
-cliUnknownCommand2=Invalid Command: ‘%1$S’.
-
-# LOCALIZATION NOTE: A parameter should have a value, but doesn't
-cliIncompleteParam=Value required for ‘%1$S’.
-
-# LOCALIZATION NOTE: Error message given when a file argument points to a file
-# that does not exist, but should (e.g. for use with File->Open) %1$S is a
-# filename
-fileErrNotExists=‘%1$S’ doesn’t exist
-
-# LOCALIZATION NOTE: Error message given when a file argument points to a file
-# that exists, but should not (e.g. for use with File->Save As) %1$S is a
-# filename
-fileErrExists=‘%1$S’ already exists
-
-# LOCALIZATION NOTE: Error message given when a file argument points to a
-# non-file, when a file is needed. %1$S is a filename
-fileErrIsNotFile=‘%1$S’ is not a file
-
-# LOCALIZATION NOTE: Error message given when a file argument points to a
-# non-directory, when a directory is needed (e.g. for use with 'cd') %1$S is a
-# filename
-fileErrIsNotDirectory=‘%1$S’ is not a directory
-
-# LOCALIZATION NOTE: Error message given when a file argument does not match
-# the specified regular expression %1$S is a filename %2$S is a regular
-# expression
-fileErrDoesntMatch=‘%1$S’ does not match ‘%2$S’
-
-# LOCALIZATION NOTE: When the menu has displayed all the matches that it
-# should (i.e. about 10 items) then we display this to alert the user that
-# more matches are available.
-fieldMenuMore=More matches, keep typing
-
-# LOCALIZATION NOTE: 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, jstypeBeginSyntax,
-# jstypeBeginUnterm): These error messages are displayed when the command line
-# is doing JavaScript completion and encounters errors.
-jstypeParseMissing=Can’t find property ‘%S’
-jstypeBeginSyntax=Syntax error
-jstypeBeginUnterm=Unterminated string literal
-
-# LOCALIZATION NOTE: This message is displayed if the system for providing
-# JavaScript completions encounters and error it displays this.
-jstypeParseError=Error
-
-# LOCALIZATION NOTE (typesNumberNan, typesNumberNotInt2, typesDateNan): These
-# error messages are displayed when the command line is passed a variable
-# which has the wrong format and can't be converted. Parameters: %S is the
-# passed variable.
-typesNumberNan=Can’t convert “%S” to a number.
-typesNumberNotInt2=Can’t convert “%S” to an integer.
-typesDateNan=Can’t convert “%S” to a date.
-
-# LOCALIZATION NOTE (typesNumberMax, typesNumberMin, typesDateMax,
-# typesDateMin): These error messages are displayed when the command line is
-# passed a variable which has a value out of range (number or date).
-# Parameters: %1$S is the passed variable, %2$S is the limit value.
-typesNumberMax=%1$S is greater than maximum allowed: %2$S.
-typesNumberMin=%1$S is smaller than minimum allowed: %2$S.
-typesDateMax=%1$S is later than maximum allowed: %2$S.
-typesDateMin=%1$S is earlier than minimum allowed: %2$S.
-
-# LOCALIZATION NOTE: This error message is displayed when the command line is
-# passed an option with a limited number of correct values, but the passed
-# value is not one of them.
-typesSelectionNomatch=Can’t use ‘%S’.
-
-# LOCALIZATION NOTE: This error message is displayed when the command line is
-# expecting a CSS query string, however the passed string is not valid.
-nodeParseSyntax=Syntax error in CSS query
-
-# LOCALIZATION NOTE (nodeParseMultiple, nodeParseNone): These error messages
-# are displayed when the command line is expecting a CSS string that matches a
-# single node, but more nodes (or none) match.
-nodeParseMultiple=Too many matches (%S)
-nodeParseNone=No matches
-
-# LOCALIZATION NOTE (helpDesc, helpManual, helpSearchDesc, helpSearchManual3):
-# These strings describe the "help" command, used to display a description of
-# a command (e.g. "help pref"), and its parameter 'search'.
-helpDesc=Get help on the available commands
-helpManual=Provide help either on a specific command (if a search string is provided and an exact match is found) or on the available commands (if a search string is not provided, or if no exact match is found).
-helpSearchDesc=Search string
-helpSearchManual3=search string to use in narrowing down the displayed commands. Regular expressions not supported.
-
-# LOCALIZATION NOTE: These strings are displayed in the help page for a
-# command in the console.
-helpManSynopsis=Synopsis
-
-# LOCALIZATION NOTE: This message is displayed in the help page if the command
-# has no parameters.
-helpManNone=None
-
-# LOCALIZATION NOTE: This message is displayed in response to the 'help'
-# command when used without a filter, just above the list of known commands.
-helpListAll=Available Commands:
-
-# LOCALIZATION NOTE (helpListPrefix, helpListNone): These messages are
-# displayed in response to the 'help ' command (i.e. with a search
-# string), just above the list of matching commands. Parameters: %S is the
-# search string.
-helpListPrefix=Commands starting with ‘%S’:
-helpListNone=No commands starting with ‘%S’
-
-# LOCALIZATION NOTE (helpManRequired, helpManOptional, helpManDefault): When
-# the 'help x' command wants to show the manual for the 'x' command, it needs
-# to be able to describe the parameters as either required or optional, or if
-# they have a default value.
-helpManRequired=required
-helpManOptional=optional
-helpManDefault=optional, default=%S
-
-# LOCALIZATION NOTE: This forms part of the output from the 'help' command.
-# 'GCLI' is a project name and should be left untranslated.
-helpIntro=GCLI is an experiment to create a highly usable command line for web developers.
-
-# LOCALIZATION NOTE: Text shown as part of the output of the 'help' command
-# when the command in question has sub-commands, before a list of the matching
-# sub-commands.
-subCommands=Sub-Commands
-
-# LOCALIZATION NOTE: This error message is displayed when the command line is
-# cannot find a match for the parse types.
-commandParseError=Command line parsing error
-
-# LOCALIZATION NOTE (contextDesc, contextManual, contextPrefixDesc): These
-# strings are used to describe the 'context' command and its 'prefix'
-# parameter. See localization comment for 'connect' for an explanation about
-# 'prefix'.
-contextDesc=Concentrate on a group of commands
-contextManual=Setup a default prefix to future commands. For example ‘context git’ would allow you to type ‘commit’ rather than ‘git commit’.
-contextPrefixDesc=The command prefix
-
-# LOCALIZATION NOTE: This message message displayed during the processing of
-# the 'context' command, when the found command is not a parent command.
-contextNotParentError=Can’t use ‘%S’ as a prefix because it is not a parent command.
-
-# LOCALIZATION NOTE (contextReply, contextEmptyReply): These messages are
-# displayed during the processing of the 'context' command, to indicate
-# success or that there is no command prefix.
-contextReply=Using %S as a command prefix
-contextEmptyReply=Command prefix is unset
-
-# LOCALIZATION NOTE (connectDesc, connectManual, connectPrefixDesc,
-# connectMethodDesc, connectUrlDesc, connectDupReply): These strings describe
-# the 'connect' command and all its available parameters. A 'prefix' is an
-# alias for the remote server (think of it as a "connection name"), and it
-# allows to identify a specific server when connected to multiple remote
-# servers.
-connectDesc=Proxy commands to server
-connectManual=Connect to the server, creating local versions of the commands on the server. Remote commands initially have a prefix to distinguish them from local commands (but see the context command to get past this)
-connectPrefixDesc=Parent prefix for imported commands
-connectMethodDesc=The method of connecting
-connectUrlDesc=The URL to connect to
-connectDupReply=Connection called %S already exists.
-
-# LOCALIZATION NOTE: The output of the 'connect' command, telling the user
-# what it has done. Parameters: %S is the prefix command. See localization
-# comment for 'connect' for an explanation about 'prefix'.
-connectReply=Added %S commands.
-
-# LOCALIZATION NOTE (disconnectDesc2, disconnectManual2,
-# disconnectPrefixDesc): These strings describe the 'disconnect' command and
-# all its available parameters. See localization comment for 'connect' for an
-# explanation about 'prefix'.
-disconnectDesc2=Disconnect from server
-disconnectManual2=Disconnect from a server currently connected for remote commands execution
-disconnectPrefixDesc=Parent prefix for imported commands
-
-# LOCALIZATION NOTE: This is the output of the 'disconnect' command,
-# explaining the user what has been done. Parameters: %S is the number of
-# commands removed.
-disconnectReply=Removed %S commands.
-
-# LOCALIZATION NOTE: These strings describe the 'clear' command
-clearDesc=Clear the output area
-
-# LOCALIZATION NOTE (prefDesc, prefManual, prefListDesc, prefListManual,
-# prefListSearchDesc, prefListSearchManual, prefShowDesc, prefShowManual,
-# prefShowSettingDesc, prefShowSettingManual): These strings describe the
-# 'pref' command and all its available sub-commands and parameters.
-prefDesc=Commands to control settings
-prefManual=Commands to display and alter preferences both for GCLI and the surrounding environment
-prefListDesc=Display available settings
-prefListManual=Display a list of preferences, optionally filtered when using the ‘search’ parameter
-prefListSearchDesc=Filter the list of settings displayed
-prefListSearchManual=Search for the given string in the list of available preferences
-prefShowDesc=Display setting value
-prefShowManual=Display the value of a given preference
-prefShowSettingDesc=Setting to display
-prefShowSettingManual=The name of the setting to display
-
-# LOCALIZATION NOTE: This message is used to show the preference name and the
-# associated preference value. Parameters: %1$S is the preference name, %2$S
-# is the preference value.
-prefShowSettingValue=%1$S: %2$S
-
-# LOCALIZATION NOTE (prefSetDesc, prefSetManual, prefSetSettingDesc,
-# prefSetSettingManual, prefSetValueDesc, prefSetValueManual): These strings
-# describe the 'pref set' command and all its parameters.
-prefSetDesc=Alter a setting
-prefSetManual=Alter preferences defined by the environment
-prefSetSettingDesc=Setting to alter
-prefSetSettingManual=The name of the setting to alter.
-prefSetValueDesc=New value for setting
-prefSetValueManual=The new value for the specified setting
-
-# LOCALIZATION NOTE (prefResetDesc, prefResetManual, prefResetSettingDesc,
-# prefResetSettingManual): These strings describe the 'pref reset' command and
-# all its parameters.
-prefResetDesc=Reset a setting
-prefResetManual=Reset the value of a setting to the system defaults
-prefResetSettingDesc=Setting to reset
-prefResetSettingManual=The name of the setting to reset to the system default value
-
-# LOCALIZATION NOTE: This string is displayed in the output from the 'pref
-# list' command as a label to an input element that allows the user to filter
-# the results.
-prefOutputFilter=Filter
-
-# LOCALIZATION NOTE (prefOutputName, prefOutputValue): These strings are
-# displayed in the output from the 'pref list' command as table headings.
-prefOutputName=Name
-prefOutputValue=Value
-
-# LOCALIZATION NOTE (introTextOpening3, introTextCommands, introTextKeys2,
-# introTextF1Escape, introTextGo): These strings are displayed when the user
-# first opens the developer toolbar to explain the command line, and is shown
-# each time it is opened until the user clicks the 'Got it!' button.
-introTextOpening3=GCLI is an experiment to create a highly usable command line for web developers.
-introTextCommands=For a list of commands type
-introTextKeys2=, or to show/hide command hints press
-introTextF1Escape=F1/Escape
-introTextGo=Got it!
-
-# LOCALIZATION NOTE: This is a short description of the 'hideIntro' setting.
-hideIntroDesc=Show the initial welcome message
-
-# LOCALIZATION NOTE: This is a description of the 'eagerHelper' setting. It's
-# displayed when the user asks for help on the settings. eagerHelper allows
-# users to select between showing no tooltips, permanent tooltips, and only
-# important tooltips.
-eagerHelperDesc=How eager are the tooltips
diff --git a/devtools/shared/locales/en-US/gclicommands.properties b/devtools/shared/locales/en-US/gclicommands.properties
deleted file mode 100644
index 4ab3d928fb5f..000000000000
--- a/devtools/shared/locales/en-US/gclicommands.properties
+++ /dev/null
@@ -1,497 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# 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 (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.
-
-# LOCALIZATION NOTE (notAvailableInE10S) Used in the output of any command that
-# is not compatible with multiprocess mode (E10S).
-
-# 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
-
-# LOCALIZATION NOTE (screenshotDesc) A very short description of the
-# 'screenshot' command. See screenshotManual for a fuller description of what
-# it does. This string is designed to be shown in a menu alongside the
-# command name, which is why it should be as short as possible.
-screenshotDesc=Save an image of the page
-
-# LOCALIZATION NOTE (screenshotManual) A fuller description of the 'screenshot'
-# command, displayed when the user asks for help on what it does.
-screenshotManual=Save a PNG image of the entire visible window (optionally after a delay)
-
-# LOCALIZATION NOTE (screenshotFilenameDesc) A very short string to describe
-# the 'filename' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotFilenameDesc=Destination filename
-
-# LOCALIZATION NOTE (screenshotFilenameManual) A fuller description of the
-# 'filename' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotFilenameManual=The name of the file (should have a ‘.png’ extension) to which we write the screenshot.
-
-# LOCALIZATION NOTE (screenshotClipboardDesc) A very short string to describe
-# the 'clipboard' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotClipboardDesc=Copy screenshot to clipboard? (true/false)
-
-# LOCALIZATION NOTE (screenshotClipboardManual) A fuller description of the
-# 'clipboard' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotClipboardManual=True if you want to copy the screenshot instead of saving it to a file.
-
-# LOCALIZATION NOTE (screenshotGroupOptions) A label for the optional options of
-# the screenshot command.
-screenshotGroupOptions=Options
-
-# LOCALIZATION NOTE (screenshotDelayDesc) A very short string to describe
-# the 'delay' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotDelayDesc=Delay (seconds)
-
-# LOCALIZATION NOTE (screenshotDelayManual) A fuller description of the
-# 'delay' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotDelayManual=The time to wait (in seconds) before the screenshot is taken
-
-# LOCALIZATION NOTE (screenshotDPRDesc) A very short string to describe
-# the 'dpr' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotDPRDesc=Device pixel ratio
-
-# LOCALIZATION NOTE (screenshotDPRManual) A fuller description of the
-# 'dpr' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotDPRManual=The device pixel ratio to use when taking the screenshot
-
-# LOCALIZATION NOTE (screenshotFullPageDesc) A very short string to describe
-# the 'fullpage' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotFullPageDesc=Entire webpage? (true/false)
-
-# LOCALIZATION NOTE (screenshotFullPageManual) A fuller description of the
-# 'fullpage' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotFullPageManual=True if the screenshot should also include parts of the webpage which are outside the current scrolled bounds.
-
-# LOCALIZATION NOTE (screenshotFileDesc) A very short string to describe
-# the 'file' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotFileDesc=Save to file? (true/false)
-
-# LOCALIZATION NOTE (screenshotFileManual) A fuller description of the
-# 'file' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotFileManual=True if the screenshot should save the file even when other options are enabled (eg. clipboard).
-
-# LOCALIZATION NOTE (screenshotGeneratedFilename) The auto generated filename
-# when no file name is provided. The first argument (%1$S) is the date string
-# in yyyy-mm-dd format and the second argument (%2$S) is the time string
-# in HH.MM.SS format. Please don't add the extension here.
-screenshotGeneratedFilename=Screen Shot %1$S at %2$S
-
-# LOCALIZATION NOTE (screenshotErrorSavingToFile) Text displayed to user upon
-# encountering error while saving the screenshot to the file specified.
-screenshotErrorSavingToFile=Error saving to
-
-# LOCALIZATION NOTE (screenshotSavedToFile) Text displayed to user when the
-# screenshot is successfully saved to the file specified.
-screenshotSavedToFile=Saved to
-
-# LOCALIZATION NOTE (screenshotErrorCopying) Text displayed to user upon
-# encountering error while copying the screenshot to clipboard.
-screenshotErrorCopying=Error occurred while copying to clipboard.
-
-# LOCALIZATION NOTE (screenshotCopied) Text displayed to user when the
-# screenshot is successfully copied to the clipboard.
-screenshotCopied=Copied to clipboard.
-
-# LOCALIZATION NOTE (screenshotTooltipPage) Text displayed as tooltip for screenshot button in devtools ToolBox.
-screenshotTooltipPage=Take a screenshot of the entire page
-
-# LOCALIZATION NOTE (screenshotImgurDesc) A very short string to describe
-# the 'imgur' parameter to the 'screenshot' command, which is displayed in
-# a dialog when the user is using this command.
-screenshotImgurDesc=Upload to imgur.com
-
-# LOCALIZATION NOTE (screenshotImgurManual) A fuller description of the
-# 'imgur' parameter to the 'screenshot' command, displayed when the user
-# asks for help on what it does.
-screenshotImgurManual=Use if you want to upload to imgur.com instead of saving to disk
-
-# LOCALIZATION NOTE (screenshotImgurError) Text displayed to user upon
-# encountering error while uploading the screenshot to imgur.com.
-screenshotImgurError=Could not reach imgur API
-
-# LOCALIZATION NOTE (screenshotImgurUploaded) Text displayed to user when the
-# screenshot is successfully sent to Imgur but the program is waiting on a response.
-# The argument (%1$S) is a new image URL at Imgur.
-screenshotImgurUploaded=Uploaded to %1$S
-
-# LOCALIZATION NOTE (inspectDesc) A very short description of the 'inspect'
-# command. See inspectManual for a fuller description of what it does. This
-# string is designed to be shown in a menu alongside the command name, which
-# is why it should be as short as possible.
-inspectDesc=Inspect a node
-
-# LOCALIZATION NOTE (inspectManual) A fuller description of the 'inspect'
-# command, displayed when the user asks for help on what it does.
-inspectManual=Investigate the dimensions and properties of an element using a CSS selector to open the DOM highlighter
-
-# LOCALIZATION NOTE (inspectNodeDesc) A very short string to describe the
-# 'node' parameter to the 'inspect' command, which is displayed in a dialog
-# when the user is using this command.
-inspectNodeDesc=CSS selector
-
-# LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
-# parameter to the 'inspect' command, displayed when the user asks for help
-# on what it does.
-inspectNodeManual=A CSS selector for use with document.querySelector which identifies a single element
-
-# LOCALIZATION NOTE (eyedropperDesc) A very short description of the 'eyedropper'
-# command. See eyedropperManual for a fuller description of what it does. This
-# string is designed to be shown in a menu alongside the command name, which
-# is why it should be as short as possible.
-eyedropperDesc=Grab a color from the page
-
-# LOCALIZATION NOTE (eyedropperManual) A fuller description of the 'eyedropper'
-# command, displayed when the user asks for help on what it does.
-eyedropperManual=Open a panel that magnifies an area of page to inspect pixels and copy color values
-
-# LOCALIZATION NOTE (debuggerClosed) Used in the output of several commands
-# to explain that the debugger must be opened first.
-debuggerClosed=The debugger must be opened before using this command
-
-# LOCALIZATION NOTE (debuggerStopped) Used in the output of several commands
-# to explain that the debugger must be opened first before setting breakpoints.
-debuggerStopped=The debugger must be opened before setting breakpoints
-
-# LOCALIZATION NOTE (breakDesc) A very short string used to describe the
-# function of the break command.
-breakDesc=Manage breakpoints
-
-# LOCALIZATION NOTE (breakManual) A longer description describing the
-# set of commands that control breakpoints.
-breakManual=Commands to list, add and remove breakpoints
-
-# LOCALIZATION NOTE (breaklistDesc) A very short string used to describe the
-# function of the 'break list' command.
-breaklistDesc=Display known breakpoints
-
-# LOCALIZATION NOTE (breaklistNone) Used in the output of the 'break list'
-# command to explain that the list is empty.
-breaklistNone=No breakpoints set
-
-# LOCALIZATION NOTE (breaklistOutRemove) A title used in the output from the
-# 'break list' command on a button which can be used to remove breakpoints
-breaklistOutRemove=Remove
-
-# LOCALIZATION NOTE (breakaddAdded) Used in the output of the 'break add'
-# command to explain that a breakpoint was added.
-breakaddAdded=Added breakpoint
-
-# LOCALIZATION NOTE (breakaddFailed) Used in the output of the 'break add'
-# command to explain that a breakpoint could not be added.
-breakaddFailed=Could not set breakpoint: %S
-
-# LOCALIZATION NOTE (breakaddDesc) A very short string used to describe the
-# function of the 'break add' command.
-breakaddDesc=Add a breakpoint
-
-# LOCALIZATION NOTE (breakaddManual) A longer description describing the
-# set of commands that are responsible for adding breakpoints.
-breakaddManual=Breakpoint types supported: line
-
-# LOCALIZATION NOTE (breakaddlineDesc) A very short string used to describe the
-# function of the 'break add line' command.
-breakaddlineDesc=Add a line breakpoint
-
-# LOCALIZATION NOTE (breakaddlineFileDesc) A very short string used to describe
-# the function of the file parameter in the 'break add line' command.
-breakaddlineFileDesc=JS file URI
-
-# LOCALIZATION NOTE (breakaddlineLineDesc) A very short string used to describe
-# the function of the line parameter in the 'break add line' command.
-breakaddlineLineDesc=Line number
-
-# LOCALIZATION NOTE (breakdelDesc) A very short string used to describe the
-# function of the 'break del' command.
-breakdelDesc=Remove a breakpoint
-
-# LOCALIZATION NOTE (breakdelBreakidDesc) A very short string used to describe
-# the function of the index parameter in the 'break del' command.
-breakdelBreakidDesc=Index of breakpoint
-
-# LOCALIZATION NOTE (breakdelRemoved) Used in the output of the 'break del'
-# command to explain that a breakpoint was removed.
-breakdelRemoved=Breakpoint removed
-
-# LOCALIZATION NOTE (dbgDesc) A very short string used to describe the
-# function of the dbg command.
-dbgDesc=Manage debugger
-
-# LOCALIZATION NOTE (dbgManual) A longer description describing the
-# set of commands that control the debugger.
-dbgManual=Commands to interrupt or resume the main thread, step in, out and over lines of code
-
-# LOCALIZATION NOTE (dbgOpen) A very short string used to describe the function
-# of the dbg open command.
-dbgOpen=Open the debugger
-
-# LOCALIZATION NOTE (dbgClose) A very short string used to describe the function
-# of the dbg close command.
-dbgClose=Close the debugger
-
-# LOCALIZATION NOTE (dbgInterrupt) A very short string used to describe the
-# function of the dbg interrupt command.
-dbgInterrupt=Pauses the main thread
-
-# LOCALIZATION NOTE (dbgContinue) A very short string used to describe the
-# function of the dbg continue command.
-dbgContinue=Resumes the main thread, and continues execution following a breakpoint, until the next breakpoint or the termination of the script.
-
-# LOCALIZATION NOTE (dbgStepDesc) A very short string used to describe the
-# function of the dbg step command.
-dbgStepDesc=Manage stepping
-
-# LOCALIZATION NOTE (dbgStepManual) A longer description describing the
-# set of commands that control stepping.
-dbgStepManual=Commands to step in, out and over lines of code
-
-# LOCALIZATION NOTE (dbgStepOverDesc) A very short string used to describe the
-# function of the dbg step over command.
-dbgStepOverDesc=Executes the current statement and then stops at the next statement. If the current statement is a function call then the debugger executes the whole function, and it stops at the next statement after the function call
-
-# LOCALIZATION NOTE (dbgStepInDesc) A very short string used to describe the
-# function of the dbg step in command.
-dbgStepInDesc=Executes the current statement and then stops at the next statement. If the current statement is a function call, then the debugger steps into that function, otherwise it stops at the next statement
-
-# LOCALIZATION NOTE (dbgStepOutDesc) A very short string used to describe the
-# function of the dbg step out command.
-dbgStepOutDesc=Steps out of the current function and up one level if the function is nested. If in the main body, the script is executed to the end, or to the next breakpoint. The skipped statements are executed, but not stepped through
-
-# LOCALIZATION NOTE (dbgListSourcesDesc) A very short string used to describe the
-# function of the dbg list command.
-dbgListSourcesDesc=List the source URLs loaded in the debugger
-
-# LOCALIZATION NOTE (dbgBlackBoxDesc) A very short string used to describe the
-# function of the 'dbg blackbox' command.
-dbgBlackBoxDesc=Black box sources in the debugger
-
-# LOCALIZATION NOTE (dbgBlackBoxSourceDesc) A very short string used to describe the
-# 'source' parameter to the 'dbg blackbox' command.
-dbgBlackBoxSourceDesc=A specific source to black box
-
-# LOCALIZATION NOTE (dbgBlackBoxGlobDesc) A very short string used to describe the
-# 'glob' parameter to the 'dbg blackbox' command.
-dbgBlackBoxGlobDesc=Black box all sources that match this glob (for example: “*.min.js”)
-
-# LOCALIZATION NOTE (dbgBlackBoxInvertDesc) A very short string used to describe the
-# 'invert' parameter to the 'dbg blackbox' command.
-dbgBlackBoxInvertDesc=Invert matching, so that we black box every source that is not the source provided or does not match the provided glob pattern.
-
-# LOCALIZATION NOTE (dbgBlackBoxEmptyDesc) A very short string used to let the
-# user know that no sources were black boxed.
-dbgBlackBoxEmptyDesc=(No sources black boxed)
-
-# LOCALIZATION NOTE (dbgBlackBoxNonEmptyDesc) A very short string used to let the
-# user know which sources were black boxed.
-dbgBlackBoxNonEmptyDesc=The following sources were black boxed:
-
-# LOCALIZATION NOTE (dbgBlackBoxErrorDesc) A very short string used to let the
-# user know there was an error black boxing a source (whose url follows this
-# text).
-dbgBlackBoxErrorDesc=Error black boxing:
-
-# LOCALIZATION NOTE (dbgUnBlackBoxDesc) A very short string used to describe the
-# function of the 'dbg unblackbox' command.
-dbgUnBlackBoxDesc=Stop black boxing sources in the debugger
-
-# LOCALIZATION NOTE (dbgUnBlackBoxSourceDesc) A very short string used to describe the
-# 'source' parameter to the 'dbg unblackbox' command.
-dbgUnBlackBoxSourceDesc=A specific source to stop black boxing
-
-# LOCALIZATION NOTE (dbgUnBlackBoxGlobDesc) A very short string used to describe the
-# 'glob' parameter to the 'dbg blackbox' command.
-dbgUnBlackBoxGlobDesc=Stop black boxing all sources that match this glob (for example: “*.min.js”)
-
-# LOCALIZATION NOTE (dbgUnBlackBoxEmptyDesc) A very short string used to let the
-# user know that we did not stop black boxing any sources.
-dbgUnBlackBoxEmptyDesc=(Did not stop black boxing any sources)
-
-# LOCALIZATION NOTE (dbgUnBlackBoxNonEmptyDesc) A very short string used to let the
-# user know which sources we stopped black boxing.
-dbgUnBlackBoxNonEmptyDesc=Stopped black boxing the following sources:
-
-# LOCALIZATION NOTE (dbgUnBlackBoxErrorDesc) A very short string used to let the
-# user know there was an error black boxing a source (whose url follows this
-# text).
-dbgUnBlackBoxErrorDesc=Error stopping black boxing:
-
-# LOCALIZATION NOTE (dbgUnBlackBoxInvertDesc) A very short string used to describe the
-# 'invert' parameter to the 'dbg unblackbox' command.
-dbgUnBlackBoxInvertDesc=Invert matching, so that we stop black boxing every source that is not the source provided or does not match the provided glob pattern.
-
-# LOCALIZATION NOTE (consolecloseDesc) A very short description of the
-# 'console close' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-consolecloseDesc=Close the console
-
-# LOCALIZATION NOTE (consoleopenDesc) A very short description of the
-# 'console open' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-consoleopenDesc=Open the console
-
-# LOCALIZATION NOTE (editDesc) A very short description of the 'edit'
-# command. See editManual2 for a fuller description of what it does. This
-# string is designed to be shown in a menu alongside the command name, which
-# is why it should be as short as possible.
-editDesc=Tweak a page resource
-
-# LOCALIZATION NOTE (editManual2) A fuller description of the 'edit' command,
-# displayed when the user asks for help on what it does.
-editManual2=Edit one of the resources that is part of this page
-
-# LOCALIZATION NOTE (editResourceDesc) A very short string to describe the
-# 'resource' parameter to the 'edit' command, which is displayed in a dialog
-# when the user is using this command.
-editResourceDesc=URL to edit
-
-# LOCALIZATION NOTE (editLineToJumpToDesc) A very short string to describe the
-# 'line' parameter to the 'edit' command, which is displayed in a dialog
-# when the user is using this command.
-editLineToJumpToDesc=Line to jump to
-
-# LOCALIZATION NOTE (resizePageArgWidthDesc) A very short string to describe the
-# 'width' parameter to the 'resizepage' command, which is displayed in a dialog
-# when the user is using this command.
-resizePageArgWidthDesc=Width in pixels
-
-# LOCALIZATION NOTE (resizePageArgHeightDesc) A very short string to describe the
-# 'height' parameter to the 'resizepage' command, which is displayed in a dialog
-# when the user is using this command.
-resizePageArgHeightDesc=Height in pixels
-
-# LOCALIZATION NOTE (resizeModeOnDesc) A very short string to describe the
-# 'resizeon ' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-resizeModeOnDesc=Enter Responsive Design Mode
-
-# LOCALIZATION NOTE (resizeModeOffDesc) A very short string to describe the
-# 'resize off' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-resizeModeOffDesc=Exit Responsive Design Mode
-
-# LOCALIZATION NOTE (resizeModeToggleDesc) A very short string to describe the
-# 'resize toggle' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-resizeModeToggleDesc=Toggle Responsive Design Mode
-
-# LOCALIZATION NOTE (resizeModeToggleTooltip2) A string displayed as the
-# tooltip of button in devtools toolbox which toggles Responsive Design Mode.
-# Keyboard shortcut will be shown inside brackets.
-resizeModeToggleTooltip2=Responsive Design Mode (%S)
-
-# LOCALIZATION NOTE (resizeModeToDesc) A very short string to describe the
-# 'resize to' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-resizeModeToDesc=Alter page size
-
-# LOCALIZATION NOTE (resizeModeDesc) A very short string to describe the
-# 'resize' command. This string is designed to be shown in a menu
-# alongside the command name, which is why it should be as short as possible.
-resizeModeDesc=Control Responsive Design Mode
-
-# LOCALIZATION NOTE (resizeModeManual2) A fuller description of the 'resize'
-# command, displayed when the user asks for help on what it does.
-# The argument (%1$S) is the browser name.
-resizeModeManual2=Responsive websites respond to their environment, so they look good on a mobile display, a cinema display and everything in-between. Responsive Design Mode allows you to easily test a variety of page sizes in %1$S without needing to resize your whole browser.
-
-# LOCALIZATION NOTE (scratchpadOpenTooltip) A string displayed as the
-# tooltip of button in devtools toolbox which opens Scratchpad.
-scratchpadOpenTooltip=Scratchpad
-
-# LOCALIZATION NOTE (paintflashingDesc) A very short string used to describe the
-# function of the "paintflashing" command
-paintflashingDesc=Highlight painted area
-
-# LOCALIZATION NOTE (paintflashingOnDesc) A very short string used to describe the
-# function of the "paintflashing on" command.
-paintflashingOnDesc=Turn on paint flashing
-
-# LOCALIZATION NOTE (paintflashingOffDesc) A very short string used to describe the
-# function of the "paintflashing off" command.
-paintflashingOffDesc=Turn off paint flashing
-
-# LOCALIZATION NOTE (paintflashingChromeDesc) A very short string used to describe the
-# function of the "paintflashing on/off chrome" command.
-paintflashingChromeDesc=chrome frames
-
-# LOCALIZATION NOTE (paintflashingManual) A longer description describing the
-# set of commands that control paint flashing.
-paintflashingManual=Draw repainted areas in different colors
-
-# LOCALIZATION NOTE (paintflashingTooltip) A string displayed as the
-# tooltip of button in devtools toolbox which toggles paint flashing.
-paintflashingTooltip=Highlight painted area
-
-# LOCALIZATION NOTE (paintflashingToggleDesc) A very short string used to describe the
-# function of the "paintflashing toggle" command.
-paintflashingToggleDesc=Toggle paint flashing
-
-# LOCALIZATION NOTE (splitconsoleTooltip2) A string displayed as the
-# tooltip of button in devtools toolbox which toggles the split webconsole.
-# Keyboard shortcut will be shown inside brackets.
-splitconsoleTooltip2=Toggle split console (%S)
-
-# LOCALIZATION NOTE (rulersDesc) A very short description of the
-# 'rulers' command. See rulersManual for a fuller description of what
-# it does. This string is designed to be shown in a menu alongside the
-# command name, which is why it should be as short as possible.
-rulersDesc=Toggle rulers for the page
-
-# LOCALIZATION NOTE (rulersManual) A fuller description of the 'rulers'
-# command, displayed when the user asks for help on what it does.
-rulersManual=Toggle the horizontal and vertical rulers for the current page
-
-# LOCALIZATION NOTE (rulersTooltip) A string displayed as the
-# tooltip of button in devtools toolbox which toggles the rulers.
-rulersTooltip=Toggle rulers for the page
-
-# LOCALIZATION NOTE (measureDesc) A very short description of the
-# 'measure' command. See measureManual for a fuller description of what
-# it does. This string is designed to be shown in a menu alongside the
-# command name, which is why it should be as short as possible.
-measureDesc=Measure a portion of the page
-
-# LOCALIZATION NOTE (measureManual) A fuller description of the 'measure'
-# command, displayed when the user asks for help on what it does.
-measureManual=Activate the measuring tool to measure an arbitrary area of the page
-
-# LOCALIZATION NOTE (measureTooltip) A string displayed as the
-# tooltip of button in devtools toolbox which toggles the measuring tool.
-measureTooltip=Measure a portion of the page
diff --git a/devtools/shared/moz.build b/devtools/shared/moz.build
index 66d5a8eb4d6e..336c68490f27 100644
--- a/devtools/shared/moz.build
+++ b/devtools/shared/moz.build
@@ -14,7 +14,6 @@ DIRS += [
'css',
'discovery',
'fronts',
- 'gcli',
'heapsnapshot',
'inspector',
'jsbeautify',
diff --git a/devtools/shared/preferences/devtools-shared.js b/devtools/shared/preferences/devtools-shared.js
index ad5c2ea74a76..317671860270 100644
--- a/devtools/shared/preferences/devtools-shared.js
+++ b/devtools/shared/preferences/devtools-shared.js
@@ -64,22 +64,3 @@ pref("devtools.remote.adb.extensionID", "adb@mozilla.org");
// URL of the remote JSON catalog used for device simulation
pref("devtools.devices.url", "https://code.cdn.mozilla.net/devices/devices.json");
-
-// Display the introductory text
-pref("devtools.gcli.hideIntro", false);
-
-// How eager are we to show help: never=1, sometimes=2, always=3
-pref("devtools.gcli.eagerHelper", 2);
-
-// Alias to the script URLs for inject command.
-pref("devtools.gcli.jquerySrc", "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js");
-pref("devtools.gcli.lodashSrc", "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.6.1/lodash.min.js");
-pref("devtools.gcli.underscoreSrc", "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js");
-
-// Set imgur upload client ID
-pref("devtools.gcli.imgurClientID", '0df414e888d7240');
-// Imgur's upload URL
-pref("devtools.gcli.imgurUploadURL", "https://api.imgur.com/3/image");
-
-// GCLI commands directory
-pref("devtools.commands.dir", "");
diff --git a/devtools/shared/screenshot/capture.js b/devtools/shared/screenshot/capture.js
index e3da3dff3740..69a330988d77 100644
--- a/devtools/shared/screenshot/capture.js
+++ b/devtools/shared/screenshot/capture.js
@@ -59,7 +59,7 @@ function createScreenshotDataURL(document, args) {
let filename = getFilename(args.filename);
if (args.fullpage) {
- // Bug 961832: GCLI screenshot shows fixed position element in wrong
+ // Bug 961832: Screenshot shows fixed position element in wrong
// position if we don't scroll to top
window.scrollTo(0, 0);
width = window.innerWidth + window.scrollMaxX - window.scrollMinX;
diff --git a/devtools/shared/specs/gcli.js b/devtools/shared/specs/gcli.js
deleted file mode 100644
index 2e0768bc8f95..000000000000
--- a/devtools/shared/specs/gcli.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol");
-
-const gcliSpec = generateActorSpec({
- typeName: "gcli",
-
- events: {
- "commands-changed": {
- type: "commandsChanged"
- }
- },
-
- methods: {
- _testOnlyAddItemsByModule: {
- request: {
- customProps: Arg(0, "array:string")
- }
- },
- _testOnlyRemoveItemsByModule: {
- request: {
- customProps: Arg(0, "array:string")
- }
- },
- specs: {
- request: {
- customProps: Arg(0, "nullable:array:string")
- },
- response: {
- value: RetVal("array:json")
- }
- },
- execute: {
- request: {
- // The command string
- typed: Arg(0, "string")
- },
- response: RetVal("json")
- },
- state: {
- request: {
- // The command string
- typed: Arg(0, "string"),
- // Cursor start position
- start: Arg(1, "number"),
- // The prediction offset (# times UP/DOWN pressed)
- rank: Arg(2, "number")
- },
- response: RetVal("json")
- },
- parseType: {
- request: {
- // The command string
- typed: Arg(0, "string"),
- // The name of the parameter to parse
- paramName: Arg(1, "string")
- },
- response: RetVal("json")
- },
- nudgeType: {
- request: {
- // The command string
- typed: Arg(0, "string"),
- // +1/-1 for increment / decrement
- by: Arg(1, "number"),
- // The name of the parameter to parse
- paramName: Arg(2, "string")
- },
- response: RetVal("string")
- },
- getSelectionLookup: {
- request: {
- // The command containing the parameter in question
- commandName: Arg(0, "string"),
- // The name of the parameter
- paramName: Arg(1, "string"),
- },
- response: RetVal("json")
- }
- }
-});
-
-exports.gcliSpec = gcliSpec;
diff --git a/devtools/shared/specs/index.js b/devtools/shared/specs/index.js
index 3cba20c9e758..37013991a00b 100644
--- a/devtools/shared/specs/index.js
+++ b/devtools/shared/specs/index.js
@@ -100,11 +100,6 @@ const Types = exports.__TypesForTests = [
spec: "devtools/shared/specs/framerate",
front: "devtools/shared/fronts/framerate",
},
- {
- types: ["gcli"],
- spec: "devtools/shared/specs/gcli",
- front: "devtools/shared/fronts/gcli",
- },
/* heap snapshot has old fashion client and no front */
{
types: ["heapSnapshotFile"],
diff --git a/devtools/shared/specs/moz.build b/devtools/shared/specs/moz.build
index 2dcd598f8255..5a1b569ec125 100644
--- a/devtools/shared/specs/moz.build
+++ b/devtools/shared/specs/moz.build
@@ -24,7 +24,6 @@ DevToolsModules(
'environment.js',
'frame.js',
'framerate.js',
- 'gcli.js',
'heap-snapshot-file.js',
'highlighters.js',
'index.js',
diff --git a/toolkit/components/telemetry/Events.yaml b/toolkit/components/telemetry/Events.yaml
index 1aaf6146e3b8..3e5af9b918a9 100644
--- a/toolkit/components/telemetry/Events.yaml
+++ b/toolkit/components/telemetry/Events.yaml
@@ -231,7 +231,7 @@ devtools.main:
release_channel_collection: opt-out
expiry_version: never
extra_keys:
- entrypoint: How was the toolbox opened? CommandLine, ContextMenu, DeveloperToolbar, HamburgerMenu, KeyShortcut, SessionRestore or SystemMenu
+ entrypoint: How was the toolbox opened? CommandLine, ContextMenu, HamburgerMenu, KeyShortcut, SessionRestore or SystemMenu
first_panel: The name of the first panel opened.
host: "Toolbox host (positioning): bottom, side, window or other."
splitconsole: Indicates whether the split console was open.
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index 799e28023484..ad581d190170 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9356,7 +9356,7 @@
"alert_emails": ["dev-developer-tools@lists.mozilla.org", "apoirot@mozilla.com"],
"expires_in_version": "never",
"kind": "categorical",
- "labels": ["KeyShortcut", "SystemMenu", "HamburgerMenu", "ContextMenu", "CommandLine", "DeveloperToolbar", "SessionRestore"],
+ "labels": ["KeyShortcut", "SystemMenu", "HamburgerMenu", "ContextMenu", "CommandLine", "SessionRestore"],
"releaseChannelCollection": "opt-out",
"description": "Records how the user is triggering Developer Tools startup."
},
@@ -9612,15 +9612,6 @@
"description": "Number of times the DevTools Eyedropper has been opened via the color picker.",
"releaseChannelCollection": "opt-out"
},
- "DEVTOOLS_DEVELOPERTOOLBAR_OPENED_COUNT": {
- "record_in_processes": ["main", "content"],
- "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
- "expires_in_version": "never",
- "kind": "count",
- "bug_numbers": [1247985],
- "description": "Number of times the DevTools Developer Toolbar / GCLI has been opened.",
- "releaseChannelCollection": "opt-out"
- },
"DEVTOOLS_ABOUTDEBUGGING_OPENED_COUNT": {
"record_in_processes": ["main", "content"],
"alert_emails": ["dev-developer-tools@lists.mozilla.org", "jan@mozilla.com"],
@@ -9974,17 +9965,6 @@
"releaseChannelCollection": "opt-out",
"description": "How long has the responsive view been active (seconds)"
},
- "DEVTOOLS_DEVELOPERTOOLBAR_TIME_ACTIVE_SECONDS": {
- "record_in_processes": ["main", "content"],
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 10000000,
- "n_buckets": 100,
- "bug_numbers": [1446496],
- "alert_emails": ["dev-developer-tools@lists.mozilla.org", "jryans@mozilla.com"],
- "releaseChannelCollection": "opt-out",
- "description": "How long has the developer toolbar been active (seconds)"
- },
"DEVTOOLS_ABOUTDEBUGGING_TIME_ACTIVE_SECONDS": {
"record_in_processes": ["main", "content"],
"expires_in_version": "never",
@@ -10270,15 +10250,6 @@
"releaseChannelCollection": "opt-out",
"description": "Records DevTools toolbox host each time the toolbox is opened and when the host is changed (0:Bottom, 1:Side, 2:Window, 3:Custom, 9:Unknown)."
},
- "DEVTOOLS_GCLI_COMMANDS_KEYED": {
- "record_in_processes": ["main", "content"],
- "bug_numbers": [1347517],
- "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
- "expires_in_version": "never",
- "keyed": true,
- "kind": "count",
- "description": "Reports the command name used in GCLI e.g. 'screenshot'"
- },
"DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE": {
"record_in_processes": ["main", "content"],
"alert_emails": ["dev-developer-tools@lists.mozilla.org"],
diff --git a/toolkit/components/telemetry/histogram-whitelists.json b/toolkit/components/telemetry/histogram-whitelists.json
index b0d4a108f882..a20175f0c438 100644
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -1486,11 +1486,9 @@
"DEVTOOLS_CANVASDEBUGGER_OPENED_COUNT",
"DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT",
"DEVTOOLS_CUSTOM_OPENED_COUNT",
- "DEVTOOLS_DEVELOPERTOOLBAR_OPENED_COUNT",
"DEVTOOLS_DOM_OPENED_COUNT",
"DEVTOOLS_EYEDROPPER_OPENED_COUNT",
"DEVTOOLS_FONTINSPECTOR_OPENED_COUNT",
- "DEVTOOLS_GCLI_COMMANDS_KEYED",
"DEVTOOLS_INSPECTOR_OPENED_COUNT",
"DEVTOOLS_JSBROWSERDEBUGGER_OPENED_COUNT",
"DEVTOOLS_JSDEBUGGER_OPENED_COUNT",