author | Julian Descottes <jdescottes@mozilla.com> |
Fri, 02 Oct 2020 15:40:19 +0000 | |
changeset 551364 | 6fcccce2d45e1aaa2a8a015f724ffa401be2676e |
parent 551363 | b1da49c81d0ca950d5fbdd5452e7779b614cc8e8 |
child 551365 | ebec4e2881c9a996ef1426e04ae97ec1c8df7274 |
push id | 127820 |
push user | jdescottes@mozilla.com |
push date | Fri, 02 Oct 2020 22:08:32 +0000 |
treeherder | autoland@ba4685a82eea [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | nchevobbe |
bugs | 1668117 |
milestone | 83.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/devtools/client/debugger/.eslintignore +++ b/devtools/client/debugger/.eslintignore @@ -2,13 +2,11 @@ assets/* src/test/examples/** src/test/integration/** src/test/unit-sources/** src/**/fixtures/** src/test/mochitest/** bin/ packages/**/fixtures/** packages/devtools-config/** -packages/devtools-contextmenu/** packages/devtools-environment/** -packages/devtools-modules/** node_modules out
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-contextmenu/README.md +++ /dev/null @@ -1,6 +0,0 @@ -### DevTools ContextMenu - - -The devtools contextmenu is an HTML shim, which lets us create -fake contextmenus in HTML namespaces and real context menus in the -firefox toolbox.
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-contextmenu/menu.css +++ /dev/null @@ -1,89 +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/. */ - -menu { - display: inline; - padding: 0; -} - -menu > menuitem::after { - content: "►"; - float: right; - padding-left: 5px; -} - -menu > menupopup { - display: none; -} - -menu > menuitem:hover + menupopup, -menu > menupopup:hover { - display: block; -} - -menupopup { - position: fixed; - z-index: 10000; - background: white; - border: 1px solid #cccccc; - padding: 5px 0; - background: #f2f2f2; - border-radius: 5px; - color: #585858; - box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8); - min-width: 130px; -} - -menuitem { - display: block; - padding: 0 20px; - line-height: 20px; - font-weight: 500; - font-size: 13px; - user-select: none; -} - -menuitem:hover { - background: #3780fb; - color: white; - cursor: pointer; -} - -menuitem[disabled=true] { - color: #cccccc; -} - -menuitem[disabled=true]:hover { - background-color: transparent; - cursor: default; -} - -menuitem[type=checkbox]::before { - content: ""; - width: 10px; - display: inline-block; -} - -menuitem[type=checkbox][checked=true]::before { - content: "✓"; - left: -8px; - position: relative; -} - -menuseparator { - border-bottom: 1px solid #cacdd3; - width: 100%; - height: 5px; - display: block; - margin-bottom: 5px; -} - -#contextmenu-mask.show { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 999; -}
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-contextmenu/menu.js +++ /dev/null @@ -1,148 +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/. */ - -const Menu = require("devtools-modules/src/menu"); -const MenuItem = require("devtools-modules/src/menu/menu-item"); - -function inToolbox() { - try { - return window.parent.document.documentURI.startsWith("about:devtools-toolbox"); - } catch (e) { - // If `window` is not available, it's very likely that we are in the toolbox. - return true; - } -} - -if (!inToolbox()) { - require("./menu.css"); -} - -function createPopup(doc) { - let popup = doc.createElement("menupopup"); - popup.className = "landing-popup"; - if (popup.openPopupAtScreen) { - return popup; - } - - function preventDefault(e) { - e.preventDefault(); - e.returnValue = false; - } - - let mask = document.querySelector("#contextmenu-mask"); - if (!mask) { - mask = doc.createElement("div"); - mask.id = "contextmenu-mask"; - document.body.appendChild(mask); - } - - mask.onclick = () => popup.hidePopup(); - - popup.openPopupAtScreen = function (clientX, clientY) { - this.style.setProperty("left", `${clientX}px`); - this.style.setProperty("top", `${clientY}px`); - mask = document.querySelector("#contextmenu-mask"); - window.onwheel = preventDefault; - mask.classList.add("show"); - this.dispatchEvent(new Event("popupshown")); - this.popupshown; - }; - - popup.hidePopup = function () { - this.remove(); - mask = document.querySelector("#contextmenu-mask"); - mask.classList.remove("show"); - window.onwheel = null; - }; - - return popup; -} - -if (!inToolbox()) { - Menu.prototype.createPopup = createPopup; -} - -function onShown(menu, popup) { - popup.childNodes.forEach((menuItemNode, i) => { - let item = menu.items[i]; - - if (!item.disabled && item.visible) { - menuItemNode.onclick = () => { - item.click(); - popup.hidePopup(); - }; - - showSubMenu(item.submenu, menuItemNode, popup); - } - }); -} - -function showMenu(evt, items) { - if (items.length === 0) { - return; - } - - let menu = new Menu(); - items - .filter((item) => item.visible === undefined || item.visible === true) - .forEach((item) => { - let menuItem = new MenuItem(item); - menuItem.submenu = createSubMenu(item.submenu); - menu.append(menuItem); - }); - - if (inToolbox()) { - menu.popup(evt.screenX, evt.screenY, window.parent.document); - return; - } - - menu.on("open", (_, popup) => onShown(menu, popup)); - menu.popup(evt.clientX, evt.clientY, document); -} - -function createSubMenu(subItems) { - if (subItems) { - let subMenu = new Menu(); - subItems.forEach((subItem) => { - subMenu.append(new MenuItem(subItem)); - }); - return subMenu; - } - return null; -} - -function showSubMenu(subMenu, menuItemNode, popup) { - if (subMenu) { - let subMenuNode = menuItemNode.querySelector("menupopup"); - let { top } = menuItemNode.getBoundingClientRect(); - let { left, width } = popup.getBoundingClientRect(); - subMenuNode.style.setProperty("left", `${left + width - 1}px`); - subMenuNode.style.setProperty("top", `${top}px`); - - let subMenuItemNodes = menuItemNode - .querySelector("menupopup:not(.landing-popup)").childNodes; - subMenuItemNodes.forEach((subMenuItemNode, j) => { - let subMenuItem = subMenu.items.filter((item) => - item.visible === undefined || item.visible === true)[j]; - if (!subMenuItem.disabled && subMenuItem.visible) { - subMenuItemNode.onclick = () => { - subMenuItem.click(); - popup.hidePopup(); - }; - } - }); - } -} - -function buildMenu(items) { - return items.map(itm => { - const hide = typeof itm.hidden === "function" ? itm.hidden() : itm.hidden; - return hide ? null : itm.item; - }).filter(itm => itm !== null); -} - -module.exports = { - showMenu, - buildMenu -};
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-contextmenu/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "devtools-contextmenu", - "version": "1.0.14", - "description": "DevTools Contextmenu", - "main": "menu.js", - "scripts": { - "test": "# No tests available" - }, - "author": "Jason Laster", - "license": "MPL-2.0", - "dependencies": { - "devtools-modules": "~1.1.9" - } -}
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-contextmenu/yarn.lock +++ /dev/null @@ -1,18 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -devtools-modules@~1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/devtools-modules/-/devtools-modules-1.1.5.tgz#55e71233692b4095f0277a00e6bfe3ff374d37f1" - dependencies: - devtools-services "0.0.1" - punycode "^2.1.0" - -devtools-services@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/devtools-services/-/devtools-services-0.0.1.tgz#9042600c11d1f4d45cc6ca299588a86fac1fbdd5" - -punycode@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/LICENSE +++ /dev/null @@ -1,362 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - 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/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0.
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## Devtools Modules - -[](https://npmjs.org/package/devtools-modules) - -* *KeyShortcuts* - keyboard shortcuts library -* *Menu* - Context Menu library -* *Services* - A de-privilidged shim for prefs and appInfo -* *PrefsHelper* - A Prefs convenience Wrapper
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/index.js +++ /dev/null @@ -1,24 +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/. */ - -const { PrefsHelper } = require("./src/prefs"); -const KeyShortcuts = require("./src/key-shortcuts"); -const EventEmitter = require("./src/utils/event-emitter"); -const Telemetry = require("./src/utils/telemetry"); -const { getUnicodeHostname, getUnicodeUrlPath, getUnicodeUrl } = - require("./src/unicode-url"); -const PluralForm = require("./src/plural-form"); -const saveAs = require("./src/saveAs") - -module.exports = { - KeyShortcuts, - PrefsHelper, - EventEmitter, - Telemetry, - getUnicodeHostname, - getUnicodeUrlPath, - getUnicodeUrl, - PluralForm, - saveAs -};
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "devtools-modules", - "version": "1.1.9", - "description": "DevTools Modules from M-C", - "main": "index.js", - "scripts": { - "license-check": "devtools-license-check", - "test": "jest" - }, - "author": "", - "license": "MPL-2.0", - "dependencies": { - "punycode": "^2.1.0", - "devtools-services": "0.0.1" - }, - "devDependencies": { - "jest": "^23.0.0" - }, - "files": [ - "src" - ], - "jest": { - "rootDir": "src", - "testMatch": [ - "**/tests/**/*.js" - ], - "testPathIgnorePatterns": [ - "<rootDir>/tests/helpers/local-storage-mock.js" - ], - "transformIgnorePatterns": [], - "setupFiles": [ - "<rootDir>/tests/helpers/local-storage-mock.js" - ], - "moduleNameMapper": {}, - "testURL": "http://localhost/" - } -}
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/key-shortcuts.js +++ /dev/null @@ -1,243 +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/. */ - -const { appinfo } = require("devtools-services"); -const EventEmitter = require("./utils/event-emitter"); -const isOSX = appinfo.OS === "Darwin"; - -// List of electron keys mapped to DOM API (DOM_VK_*) key code -const ElectronKeysMapping = { - "F1": "DOM_VK_F1", - "F2": "DOM_VK_F2", - "F3": "DOM_VK_F3", - "F4": "DOM_VK_F4", - "F5": "DOM_VK_F5", - "F6": "DOM_VK_F6", - "F7": "DOM_VK_F7", - "F8": "DOM_VK_F8", - "F9": "DOM_VK_F9", - "F10": "DOM_VK_F10", - "F11": "DOM_VK_F11", - "F12": "DOM_VK_F12", - "F13": "DOM_VK_F13", - "F14": "DOM_VK_F14", - "F15": "DOM_VK_F15", - "F16": "DOM_VK_F16", - "F17": "DOM_VK_F17", - "F18": "DOM_VK_F18", - "F19": "DOM_VK_F19", - "F20": "DOM_VK_F20", - "F21": "DOM_VK_F21", - "F22": "DOM_VK_F22", - "F23": "DOM_VK_F23", - "F24": "DOM_VK_F24", - "Space": "DOM_VK_SPACE", - "Backspace": "DOM_VK_BACK_SPACE", - "Delete": "DOM_VK_DELETE", - "Insert": "DOM_VK_INSERT", - "Return": "DOM_VK_RETURN", - "Enter": "DOM_VK_RETURN", - "Up": "DOM_VK_UP", - "Down": "DOM_VK_DOWN", - "Left": "DOM_VK_LEFT", - "Right": "DOM_VK_RIGHT", - "Home": "DOM_VK_HOME", - "End": "DOM_VK_END", - "PageUp": "DOM_VK_PAGE_UP", - "PageDown": "DOM_VK_PAGE_DOWN", - "Escape": "DOM_VK_ESCAPE", - "Esc": "DOM_VK_ESCAPE", - "Tab": "DOM_VK_TAB", - "VolumeUp": "DOM_VK_VOLUME_UP", - "VolumeDown": "DOM_VK_VOLUME_DOWN", - "VolumeMute": "DOM_VK_VOLUME_MUTE", - "PrintScreen": "DOM_VK_PRINTSCREEN", -}; - -/** - * Helper to listen for keyboard events decribed in .properties file. - * - * let shortcuts = new KeyShortcuts({ - * window - * }); - * shortcuts.on("Ctrl+F", event => { - * // `event` is the KeyboardEvent which relates to the key shortcuts - * }); - * - * @param DOMWindow window - * The window object of the document to listen events from. - * @param DOMElement target - * Optional DOM Element on which we should listen events from. - * If omitted, we listen for all events fired on `window`. - */ -function KeyShortcuts({ window, target }) { - this.window = window; - this.target = target || window; - this.keys = new Map(); - this.eventEmitter = new EventEmitter(); - this.target.addEventListener("keydown", this); -} - -/* - * Parse an electron-like key string and return a normalized object which - * allow efficient match on DOM key event. The normalized object matches DOM - * API. - * - * @param DOMWindow window - * Any DOM Window object, just to fetch its `KeyboardEvent` object - * @param String str - * The shortcut string to parse, following this document: - * https://github.com/electron/electron/blob/master/docs/api/accelerator.md - */ -KeyShortcuts.parseElectronKey = function(window, str) { - let modifiers = str.split("+"); - let key = modifiers.pop(); - - let shortcut = { - ctrl: false, - meta: false, - alt: false, - shift: false, - // Set for character keys - key: undefined, - // Set for non-character keys - keyCode: undefined, - }; - for (let mod of modifiers) { - if (mod === "Alt") { - shortcut.alt = true; - } else if (["Command", "Cmd"].includes(mod)) { - shortcut.meta = true; - } else if (["CommandOrControl", "CmdOrCtrl"].includes(mod)) { - if (isOSX) { - shortcut.meta = true; - } else { - shortcut.ctrl = true; - } - } else if (["Control", "Ctrl"].includes(mod)) { - shortcut.ctrl = true; - } else if (mod === "Shift") { - shortcut.shift = true; - } else { - console.error("Unsupported modifier:", mod, "from key:", str); - return null; - } - } - - // Plus is a special case. It's a character key and shouldn't be matched - // against a keycode as it is only accessible via Shift/Capslock - if (key === "Plus") { - key = "+"; - } - - if (typeof key === "string" && key.length === 1) { - // Match any single character - shortcut.key = key.toLowerCase(); - } else if (key in ElectronKeysMapping) { - // Maps the others manually to DOM API DOM_VK_* - key = ElectronKeysMapping[key]; - shortcut.keyCode = window.KeyboardEvent[key]; - // Used only to stringify the shortcut - shortcut.keyCodeString = key; - shortcut.key = key; - } else { - console.error("Unsupported key:", key); - return null; - } - - return shortcut; -}; - -KeyShortcuts.stringify = function(shortcut) { - let list = []; - if (shortcut.alt) { - list.push("Alt"); - } - if (shortcut.ctrl) { - list.push("Ctrl"); - } - if (shortcut.meta) { - list.push("Cmd"); - } - if (shortcut.shift) { - list.push("Shift"); - } - let key; - if (shortcut.key) { - key = shortcut.key.toUpperCase(); - } else { - key = shortcut.keyCodeString; - } - list.push(key); - return list.join("+"); -}; - -KeyShortcuts.prototype = { - destroy() { - this.target.removeEventListener("keydown", this); - this.keys.clear(); - }, - - doesEventMatchShortcut(event, shortcut) { - if (shortcut.meta != event.metaKey) { - return false; - } - if (shortcut.ctrl != event.ctrlKey) { - return false; - } - if (shortcut.alt != event.altKey) { - return false; - } - // Shift is a special modifier, it may implicitely be required if the - // expected key is a special character accessible via shift. - if (shortcut.shift != event.shiftKey && event.key && - event.key.match(/[a-zA-Z]/)) { - return false; - } - if (shortcut.keyCode) { - return event.keyCode == shortcut.keyCode; - } else if (event.key in ElectronKeysMapping) { - return ElectronKeysMapping[event.key] === shortcut.key; - } - - // get the key from the keyCode if key is not provided. - let key = event.key || String.fromCharCode(event.keyCode); - - // For character keys, we match if the final character is the expected one. - // But for digits we also accept indirect match to please azerty keyboard, - // which requires Shift to be pressed to get digits. - return key.toLowerCase() == shortcut.key || - (shortcut.key.match(/^[0-9]$/) && - event.keyCode == shortcut.key.charCodeAt(0)); - }, - - handleEvent(event) { - for (let [key, shortcut] of this.keys) { - if (this.doesEventMatchShortcut(event, shortcut)) { - this.eventEmitter.emit(key, event); - } - } - }, - - on(key, listener) { - if (typeof listener !== "function") { - throw new Error("KeyShortcuts.on() expects a function as " + - "second argument"); - } - if (!this.keys.has(key)) { - let shortcut = KeyShortcuts.parseElectronKey(this.window, key); - // The key string is wrong and we were unable to compute the key shortcut - if (!shortcut) { - return; - } - this.keys.set(key, shortcut); - } - this.eventEmitter.on(key, listener); - }, - - off(key, listener) { - this.eventEmitter.off(key, listener); - }, -}; -module.exports = KeyShortcuts;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/menu/index.js +++ /dev/null @@ -1,247 +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/. */ - -import Services from "devtools-services"; - -const { appinfo } = Services; - -const isMacOS = appinfo.OS === "Darwin"; - -const EventEmitter = require("../utils/event-emitter"); - -/** - * Formats key for use in tooltips - * For macOS we use the following unicode - * - * cmd ⌘ = \u2318 - * shift ⇧ – \u21E7 - * option (alt) ⌥ \u2325 - * - * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl - * - * @static - */ -function formatKeyShortcut(shortcut) { - if (isMacOS) { - return shortcut - .replace(/Shift\+/g, "\u21E7") - .replace(/Command\+|Cmd\+/g, "\u2318") - .replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318") - .replace(/Alt\+/g, "\u2325"); - } - return shortcut - .replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")}+`) - .replace(/Shift\+/g, "Shift+"); -} - -function inToolbox() { - try { - return window.parent.document.documentURI.startsWith("about:devtools-toolbox"); - } catch (e) { - // If `window` is not available, it's very likely that we are in the toolbox. - return true; - } -} - -// Copied from m-c DevToolsUtils. -function getTopWindow(win) { - return win.windowRoot ? win.windowRoot.ownerGlobal : win.top; -} - -/** - * A partial implementation of the Menu API provided by electron: - * https://github.com/electron/electron/blob/master/docs/api/menu.md. - * - * Extra features: - * - Emits an 'open' and 'close' event when the menu is opened/closed - - * @param String id (non standard) - * Needed so tests can confirm the XUL implementation is working - */ -function Menu({ id = null } = {}) { - this.menuitems = []; - this.id = id; - - Object.defineProperty(this, "items", { - get() { - return this.menuitems; - } - }); - - EventEmitter.decorate(this); -} - -/** - * Add an item to the end of the Menu - * - * @param {MenuItem} menuItem - */ -Menu.prototype.append = function (menuItem) { - this.menuitems.push(menuItem); -}; - -/** - * Add an item to a specified position in the menu - * - * @param {int} pos - * @param {MenuItem} menuItem - */ -Menu.prototype.insert = function (pos, menuItem) { - throw Error("Not implemented"); -}; - -/** - * Show the Menu at a specified location on the screen - * - * Missing features: - * - browserWindow - BrowserWindow (optional) - Default is null. - * - positioningItem Number - (optional) OS X - * - * @param {int} screenX - * @param {int} screenY - * @param {Document} doc - * The document that should own the context menu. - */ -Menu.prototype.popup = function (screenX, screenY, doc) { - // The context-menu will be created in the topmost window to preserve keyboard - // navigation. See Bug 1543940. Keep a reference on the window owning the menu to hide - // the popup on unload. - const win = doc.defaultView; - doc = getTopWindow(doc.defaultView).document; - - let popupset = doc.querySelector("popupset"); - if (!popupset) { - popupset = doc.createXULElement("popupset"); - doc.documentElement.appendChild(popupset); - } - // See bug 1285229, on Windows, opening the same popup multiple times in a - // row ends up duplicating the popup. The newly inserted popup doesn't - // dismiss the old one. So remove any previously displayed popup before - // opening a new one. - let popup = popupset.querySelector("menupopup[menu-api=\"true\"]"); - if (popup) { - popup.hidePopup(); - } - - popup = this.createPopup(doc); - popup.setAttribute("menu-api", "true"); - - if (this.id) { - popup.id = this.id; - } - this._createMenuItems(popup); - - // The context menu will be created in the topmost chrome window. Hide it manually when - // the owner document is unloaded. - const onWindowUnload = () => popup.hidePopup(); - win.addEventListener("unload", onWindowUnload); - - // Remove the menu from the DOM once it's hidden. - popup.addEventListener("popuphidden", (e) => { - if (e.target === popup) { - win.removeEventListener("unload", onWindowUnload); - popup.remove(); - this.emit("close", popup); - } - }); - - popup.addEventListener("popupshown", (e) => { - if (e.target === popup) { - this.emit("open", popup); - } - }); - - popupset.appendChild(popup); - popup.openPopupAtScreen(screenX, screenY, true); -}; - -Menu.prototype.createPopup = function(doc) { - return doc.createElement("menupopup"); -} - -Menu.prototype._createMenuItems = function(parent) { - let doc = parent.ownerDocument; - this.menuitems.forEach(item => { - if (!item.visible) { - return; - } - - if (item.submenu) { - let menupopup = doc.createElement("menupopup"); - item.submenu._createMenuItems(menupopup); - - let menuitem = doc.createElement("menuitem"); - menuitem.setAttribute("label", item.label); - if (!inToolbox()) { - menuitem.textContent = item.label; - } - - let menu = doc.createElement("menu"); - menu.appendChild(menuitem); - menu.appendChild(menupopup); - if (item.disabled) { - menu.setAttribute("disabled", "true"); - } - if (item.accesskey) { - menu.setAttribute("accesskey", item.accesskey); - } - if (item.id) { - menu.id = item.id; - } - if (item.accelerator) { - menuitem.setAttribute("acceltext", formatKeyShortcut(item.accelerator)); - } - parent.appendChild(menu); - } else if (item.type === "separator") { - let menusep = doc.createElement("menuseparator"); - parent.appendChild(menusep); - } else { - let menuitem = doc.createElement("menuitem"); - menuitem.setAttribute("label", item.label); - - if (!inToolbox()) { - menuitem.textContent = item.label; - } - - menuitem.addEventListener("command", () => item.click()); - - if (item.type === "checkbox") { - menuitem.setAttribute("type", "checkbox"); - } - if (item.type === "radio") { - menuitem.setAttribute("type", "radio"); - } - if (item.disabled) { - menuitem.setAttribute("disabled", "true"); - } - if (item.checked) { - menuitem.setAttribute("checked", "true"); - } - if (item.accesskey) { - menuitem.setAttribute("accesskey", item.accesskey); - } - if (item.id) { - menuitem.id = item.id; - } - if (item.accelerator) { - menuitem.setAttribute("acceltext", formatKeyShortcut(item.accelerator)); - } - parent.appendChild(menuitem); - } - }); -}; - -Menu.setApplicationMenu = () => { - throw Error("Not implemented"); -}; - -Menu.sendActionToFirstResponder = () => { - throw Error("Not implemented"); -}; - -Menu.buildFromTemplate = () => { - throw Error("Not implemented"); -}; - -module.exports = Menu;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/menu/menu-item.js +++ /dev/null @@ -1,64 +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/. */ - -/** - * A partial implementation of the MenuItem API provided by electron: - * https://github.com/electron/electron/blob/master/docs/api/menu-item.md. - * - * Missing features: - * - id String - Unique within a single menu. If defined then it can be used - * as a reference to this item by the position attribute. - * - role String - Define the action of the menu item; when specified the - * click property will be ignored - * - sublabel String - * - icon NativeImage - * - position String - This field allows fine-grained definition of the - * specific location within a given menu. - * - * Implemented features: - * @param Object options - * Function click - * Will be called with click(menuItem, browserWindow) when the menu item - * is clicked - * String type - * Can be normal, separator, submenu, checkbox or radio - * String label - * Boolean enabled - * If false, the menu item will be greyed out and unclickable. - * Boolean checked - * Should only be specified for checkbox or radio type menu items. - * Menu submenu - * Should be specified for submenu type menu items. If submenu is specified, - * the type: 'submenu' can be omitted. If the value is not a Menu then it - * will be automatically converted to one using Menu.buildFromTemplate. - * Boolean visible - * If false, the menu item will be entirely hidden. - * String accelerator - * If specified, will be used as accelerator text for MenuItem - */ -function MenuItem({ - accesskey = null, - checked = false, - click = () => {}, - disabled = false, - label = "", - id = null, - submenu = null, - type = "normal", - visible = true, - accelerator = "", -} = { }) { - this.accesskey = accesskey; - this.checked = checked; - this.click = click; - this.disabled = disabled; - this.id = id; - this.label = label; - this.submenu = submenu; - this.type = type; - this.visible = visible; - this.accelerator = accelerator; -} - -module.exports = MenuItem;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/plural-form.js +++ /dev/null @@ -1,160 +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/. */ - -// These are the available plural functions that give the appropriate index -// based on the plural rule number specified. The first element is the number -// of plural forms and the second is the function to figure out the index. -const gFunctions = [ - // 0: Chinese - [1, (n) => 0], - // 1: English - [2, (n) => n!=1?1:0], - // 2: French - [2, (n) => n>1?1:0], - // 3: Latvian - [3, (n) => n%10==1&&n%100!=11?1:n%10==0?0:2], - // 4: Scottish Gaelic - [4, (n) => n==1||n==11?0:n==2||n==12?1:n>0&&n<20?2:3], - // 5: Romanian - [3, (n) => n==1?0:n==0||n%100>0&&n%100<20?1:2], - // 6: Lithuanian - [3, (n) => n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?2:1], - // 7: Russian - [3, (n) => n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2], - // 8: Slovak - [3, (n) => n==1?0:n>=2&&n<=4?1:2], - // 9: Polish - [3, (n) => n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2], - // 10: Slovenian - [4, (n) => n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3], - // 11: Irish Gaeilge - [5, (n) => n==1?0:n==2?1:n>=3&&n<=6?2:n>=7&&n<=10?3:4], - // 12: Arabic - [6, (n) => n==0?5:n==1?0:n==2?1:n%100>=3&&n%100<=10?2:n%100>=11&&n%100<=99?3:4], - // 13: Maltese - [4, (n) => n==1?0:n==0||n%100>0&&n%100<=10?1:n%100>10&&n%100<20?2:3], - // 14: Unused - [3, (n) => n%10==1?0:n%10==2?1:2], - // 15: Icelandic, Macedonian - [2, (n) => n%10==1&&n%100!=11?0:1], - // 16: Breton - [5, (n) => n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?0:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?1:(n%10==3||n%10==4||n%10==9)&&n%100!=13&&n%100!=14&&n%100!=19&&n%100!=73&&n%100!=74&&n%100!=79&&n%100!=93&&n%100!=94&&n%100!=99?2:n%1000000==0&&n!=0?3:4], - // 17: Shuar - [2, (n) => n!=0?1:0], - // 18: Welsh - [6, (n) => n==0?0:n==1?1:n==2?2:n==3?3:n==6?4:5], - // 19: Bosnian, Croatian, Serbian - [3, (n) => n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2], -]; - -const PluralForm = { - /** - * Get the correct plural form of a word based on the number - * - * @param aNum - * The number to decide which plural form to use - * @param aWords - * A semi-colon (;) separated string of words to pick the plural form - * @return The appropriate plural form of the word - */ - get get() - { - // This method will lazily load to avoid perf when it is first needed and - // creates getPluralForm function. The function it creates is based on the - // value of pluralRule specified in the intl stringbundle. - // See: http://developer.mozilla.org/en/docs/Localization_and_Plurals - - // Delete the getters to be overwritten - delete this.numForms; - delete this.get; - - // Make the plural form get function and set it as the default get - [this.get, this.numForms] = this.makeGetter(this.ruleNum); - return this.get; - }, - - /** - * Create a pair of plural form functions for the given plural rule number. - * - * @param aRuleNum - * The plural rule number to create functions - * @return A pair: [function that gets the right plural form, - * function that returns the number of plural forms] - */ - makeGetter: function(aRuleNum) - { - // Default to "all plural" if the value is out of bounds or invalid - if (aRuleNum < 0 || aRuleNum >= gFunctions.length || isNaN(aRuleNum)) { - log(["Invalid rule number: ", aRuleNum, " -- defaulting to 0"]); - aRuleNum = 0; - } - - // Get the desired pluralRule function - let [numForms, pluralFunc] = gFunctions[aRuleNum]; - - // Return functions that give 1) the number of forms and 2) gets the right - // plural form - return [function(aNum, aWords) { - // Figure out which index to use for the semi-colon separated words - let index = pluralFunc(aNum ? Number(aNum) : 0); - let words = aWords ? aWords.split(/;/) : [""]; - - // Explicitly check bounds to avoid strict warnings - let ret = index < words.length ? words[index] : undefined; - - // Check for array out of bounds or empty strings - if ((ret == undefined) || (ret == "")) { - // Display a message in the error console - log(["Index #", index, " of '", aWords, "' for value ", aNum, - " is invalid -- plural rule #", aRuleNum, ";"]); - - // Default to the first entry (which might be empty, but not undefined) - ret = words[0]; - } - - return ret; - }, () => numForms]; - }, - - /** - * Get the number of forms for the current plural rule - * - * @return The number of forms - */ - get numForms() - { - // We lazily load numForms, so trigger the init logic with get() - this.get(); - return this.numForms; - }, - - /** - * Get the plural rule number from the intl stringbundle - * - * @return The plural rule number - */ - get ruleNum() - { - try { - return parseInt(L10N.getStr("pluralRule"), 10); - } catch (e) { - // Fallback to English if the pluralRule property is not available. - return 1; - } - } -}; - -/** - * Private helper function to log errors to the error console and command line - * - * @param aMsg - * Error message to log or an array of strings to concat - */ -function log(aMsg) -{ - let msg = "plural-form.js: " + (aMsg.join ? aMsg.join("") : aMsg); - console.log(msg + "\n"); -} - -module.exports = PluralForm;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/prefs.js +++ /dev/null @@ -1,187 +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/. */ - -const Services = require("devtools-services"); -const EventEmitter = require("./utils/event-emitter"); - -/** - * Shortcuts for lazily accessing and setting various preferences. - * Usage: - * let prefs = new Prefs("root.path.to.branch", { - * myIntPref: ["Int", "leaf.path.to.my-int-pref"], - * myCharPref: ["Char", "leaf.path.to.my-char-pref"], - * myJsonPref: ["Json", "leaf.path.to.my-json-pref"], - * myFloatPref: ["Float", "leaf.path.to.my-float-pref"] - * ... - * }); - * - * Get/set: - * prefs.myCharPref = "foo"; - * let aux = prefs.myCharPref; - * - * Observe: - * prefs.registerObserver(); - * prefs.on("pref-changed", (prefName, prefValue) => { - * ... - * }); - * - * @param string prefsRoot - * The root path to the required preferences branch. - * @param object prefsBlueprint - * An object containing { accessorName: [prefType, prefName, prefDefault] } keys. - */ -function PrefsHelper(prefsRoot = "", prefsBlueprint = {}) { - EventEmitter.decorate(this); - - let cache = new Map(); - - for (let accessorName in prefsBlueprint) { - let [prefType, prefName, prefDefault] = prefsBlueprint[accessorName]; - map(this, cache, accessorName, prefType, prefsRoot, prefName, prefDefault); - } - - let observer = makeObserver(this, cache, prefsRoot, prefsBlueprint); - this.registerObserver = () => observer.register(); - this.unregisterObserver = () => observer.unregister(); -} - -/** - * Helper method for getting a pref value. - * - * @param Map cache - * @param string prefType - * @param string prefsRoot - * @param string prefName - * @return any - */ -function get(cache, prefType, prefsRoot, prefName) { - let cachedPref = cache.get(prefName); - if (cachedPref !== undefined) { - return cachedPref; - } - let value = Services.prefs["get" + prefType + "Pref"]( - [prefsRoot, prefName].join(".") - ); - cache.set(prefName, value); - return value; -} - -/** - * Helper method for setting a pref value. - * - * @param Map cache - * @param string prefType - * @param string prefsRoot - * @param string prefName - * @param any value - */ -function set(cache, prefType, prefsRoot, prefName, value) { - Services.prefs["set" + prefType + "Pref"]( - [prefsRoot, prefName].join("."), - value - ); - cache.set(prefName, value); -} - -/** - * Maps a property name to a pref, defining lazy getters and setters. - * Supported types are "Bool", "Char", "Int", "Float" (sugar around "Char" - * type and casting), and "Json" (which is basically just sugar for "Char" - * using the standard JSON serializer). - * - * @param PrefsHelper self - * @param Map cache - * @param string accessorName - * @param string prefType - * @param string prefsRoot - * @param string prefName - * @param string prefDefault - * @param array serializer [optional] - */ -function map(self, cache, accessorName, prefType, prefsRoot, prefName, prefDefault, - serializer = { in: e => e, out: e => e }) { - if (prefName in self) { - throw new Error(`Can't use ${prefName} because it overrides a property` + - "on the instance."); - } - if (prefType == "Json") { - map(self, cache, accessorName, "String", prefsRoot, prefName, prefDefault, { - in: JSON.parse, - out: JSON.stringify - }); - return; - } - if (prefType == "Float") { - map(self, cache, accessorName, "Char", prefsRoot, prefName, prefDefault, { - in: Number.parseFloat, - out: (n) => n + "" - }); - return; - } - - Object.defineProperty(self, accessorName, { - get: () => { - try { - return serializer.in(get(cache, prefType, prefsRoot, prefName)); - } catch (e) { - if (typeof prefDefault !== 'undefined') { - return prefDefault; - } - throw e; - } - }, - set: (e) => set(cache, prefType, prefsRoot, prefName, serializer.out(e)) - }); -} - -/** - * Finds the accessor for the provided pref, based on the blueprint object - * used in the constructor. - * - * @param PrefsHelper self - * @param object prefsBlueprint - * @return string - */ -function accessorNameForPref(somePrefName, prefsBlueprint) { - for (let accessorName in prefsBlueprint) { - let [, prefName] = prefsBlueprint[accessorName]; - if (somePrefName == prefName) { - return accessorName; - } - } - return ""; -} - -/** - * Creates a pref observer for `self`. - * - * @param PrefsHelper self - * @param Map cache - * @param string prefsRoot - * @param object prefsBlueprint - * @return object - */ -function makeObserver(self, cache, prefsRoot, prefsBlueprint) { - return { - register: function() { - this._branch = Services.prefs.getBranch(prefsRoot + "."); - this._branch.addObserver("", this); - }, - unregister: function() { - this._branch.removeObserver("", this); - }, - observe: function(subject, topic, prefName) { - // If this particular pref isn't handled by the blueprint object, - // even though it's in the specified branch, ignore it. - let accessorName = accessorNameForPref(prefName, prefsBlueprint); - if (!(accessorName in self)) { - return; - } - cache.delete(prefName); - self.emit("pref-changed", accessorName, self[accessorName]); - } - }; -} - -exports.PrefsHelper = PrefsHelper;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/saveAs.js +++ /dev/null @@ -1,5 +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/. */ - -module.exports = () => {}
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/tests/helpers/local-storage-mock.js +++ /dev/null @@ -1,30 +0,0 @@ -var localStorageMock = (() => { - let store = {}; - return { - getItem: (key) => { - if (!store.hasOwnProperty(key)) { - return ""; - } - return store[key]; - }, - setItem: (key, value) => { - store[key] = value.toString(); - }, - clear: () => { - store = {}; - }, - removeItem: (key) => { - delete store[key]; - }, - key: (index) => { - return Object.keys(store)[index]; - }, - get length() { - return Object.keys(store).length; - } - }; -})(); - -Object.defineProperty(window, "localStorage", { - value: localStorageMock -});
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/tests/prefs-helper.js +++ /dev/null @@ -1,37 +0,0 @@ -const { PrefsHelper } = require("../prefs"); -const Services = require("devtools-services"); -const pref = Services.pref; - -describe("prefs helper", () => { - beforeEach(() => {}); - - afterEach(() => { - localStorage.clear(); - }); - - it("supports fallback values", () => { - pref("devtools.valid", "{\"valid\": true}"); - pref("devtools.invalid", "{not valid at all]"); - pref("devtools.nodefault", "{not valid at all]"); - pref("devtools.validnodefault", "{\"nodefault\": true}"); - - const prefs = new PrefsHelper("devtools", { - valid: ["Json", "valid", {valid: true}], - invalid: ["Json", "invalid", {}], - nodefault: ["Json", "nodefault"], - validnodefault: ["Json", "validnodefault"], - }); - - // Valid Json pref should return the actual value - expect(prefs.valid).toEqual({valid: true}); - - // Invalid Json pref with a fallback shoud return the fallback value - expect(prefs.invalid).toEqual({}); - - // Invalid Json pref with no fallback should throw - expect(() => prefs.nodefault).toThrow(); - - // Valid Json pref with no fallback should return the value - expect(prefs.validnodefault).toEqual({nodefault: true}); - }); -});
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/tests/services-prefs.js +++ /dev/null @@ -1,200 +0,0 @@ -const Services = require("devtools-services"); -const pref = Services.pref; - -describe("services prefs shim", () => { - beforeEach(() => { - // Add some starter prefs. - localStorage.setItem("Services.prefs:devtools.branch1.somebool", JSON.stringify({ - // bool - type: 128, - defaultValue: false, - hasUserValue: false, - userValue: false - })); - - localStorage.setItem("Services.prefs:devtools.branch1.somestring", JSON.stringify({ - // string - type: 32, - defaultValue: "dinosaurs", - hasUserValue: true, - userValue: "elephants" - })); - - localStorage.setItem("Services.prefs:devtools.branch2.someint", JSON.stringify({ - // int - type: 64, - defaultValue: -16, - hasUserValue: false, - userValue: null - })); - }); - - afterEach(() => { - localStorage.clear(); - }); - - it("can get and set preferences", () => { - expect(Services.prefs.getBoolPref("devtools.branch1.somebool")).toBe(false); - Services.prefs.setBoolPref("devtools.branch1.somebool", true); - expect(Services.prefs.getBoolPref("devtools.branch1.somebool")).toBe(true); - - Services.prefs.clearUserPref("devtools.branch1.somestring"); - expect(Services.prefs.getCharPref("devtools.branch1.somestring")).toBe("dinosaurs"); - - expect(Services.prefs.prefHasUserValue("devtools.branch1.somebool")).toBe(true, - "bool pref has user value"); - expect(Services.prefs.prefHasUserValue("devtools.branch1.somestring")).toBe(false, - "string pref does not have user value"); - - // String prefs actually differ from Char prefs in the real implementation of - // Services.prefs, but for this shim, both are using the same implementation. - Services.prefs.setStringPref("devtools.branch1.somerealstring", "abcdef"); - expect(Services.prefs.getStringPref("devtools.branch1.somerealstring")).toBe("abcdef"); - }); - - it("can call savePrefFile without crashing", () => { - Services.prefs.savePrefFile(null); - }); - - it("can use branches", () => { - let branch0 = Services.prefs.getBranch(null); - let branch1 = Services.prefs.getBranch("devtools.branch1."); - - branch1.setCharPref("somestring", "octopus"); - Services.prefs.setCharPref("devtools.branch1.somestring", "octopus"); - expect(Services.prefs.getCharPref("devtools.branch1.somestring")).toEqual("octopus"); - expect(branch0.getCharPref("devtools.branch1.somestring")).toEqual("octopus"); - expect(branch1.getCharPref("somestring")).toEqual("octopus"); - }); - - it("throws exceptions when expected", () => { - expect(() => { - Services.prefs.setIntPref("devtools.branch1.somebool", 27); - }).toThrow(); - - expect(() => { - Services.prefs.setBoolPref("devtools.branch1.somebool", 27); - }).toThrow(); - - expect(() => { - Services.prefs.getCharPref("devtools.branch2.someint"); - }).toThrow(); - - expect(() => { - Services.prefs.setCharPref("devtools.branch2.someint", "whatever"); - }).toThrow(); - - expect(() => { - Services.prefs.setIntPref("devtools.branch2.someint", "whatever"); - }).toThrow(); - - expect(() => { - Services.prefs.getBoolPref("devtools.branch1.somestring"); - }).toThrow(); - - expect(() => { - Services.prefs.setBoolPref("devtools.branch1.somestring", true); - }).toThrow(); - - expect(() => { - Services.prefs.setCharPref("devtools.branch1.somestring", true); - }).toThrow(); - }); - - it("returns correct pref types", () => { - expect(Services.prefs.getPrefType("devtools.branch1.somebool")) - .toEqual(Services.prefs.PREF_BOOL); - expect(Services.prefs.getPrefType("devtools.branch2.someint")) - .toEqual(Services.prefs.PREF_INT); - expect(Services.prefs.getPrefType("devtools.branch1.somestring")) - .toEqual(Services.prefs.PREF_STRING); - }); - - it("supports observers", () => { - let notifications = {}; - let clearNotificationList = () => { - notifications = {}; - }; - - let observer = { - observe: function (subject, topic, data) { - notifications[data] = true; - } - }; - - let branch0 = Services.prefs.getBranch(null); - let branch1 = Services.prefs.getBranch("devtools.branch1."); - - branch0.addObserver("devtools.branch1", null, null); - branch0.addObserver("devtools.branch1.", observer); - branch1.addObserver("", observer); - - Services.prefs.setCharPref("devtools.branch1.somestring", "elf owl"); - expect(notifications).toEqual({ - "devtools.branch1.somestring": true, - "somestring": true - }, "notifications sent to two listeners"); - - clearNotificationList(); - Services.prefs.setIntPref("devtools.branch2.someint", 1729); - expect(notifications).toEqual({}, "no notifications sent"); - - clearNotificationList(); - branch0.removeObserver("devtools.branch1.", observer); - Services.prefs.setCharPref("devtools.branch1.somestring", "tapir"); - expect(notifications).toEqual({ - "somestring": true - }, "removeObserver worked"); - - clearNotificationList(); - branch0.addObserver("devtools.branch1.somestring", observer); - Services.prefs.setCharPref("devtools.branch1.somestring", "northern shoveler"); - expect(notifications).toEqual({ - "devtools.branch1.somestring": true, - "somestring": true - }, "notifications sent to two listeners"); - branch0.removeObserver("devtools.branch1.somestring", observer); - - // Make sure we update if the pref change comes from somewhere else. - clearNotificationList(); - pref("devtools.branch1.someotherstring", "lazuli bunting"); - expect(notifications).toEqual({ - "someotherstring": true - }, "pref worked"); - }); - - it("does not crash when setting prefs (bug 1296427)", () => { - // Regression test for bug 1296427. - pref("devtools.hud.loglimit", 1000); - pref("devtools.hud.loglimit.network", 1000); - }); - - it("fixes observer bug (bug 1319150)", () => { - // Regression test for bug 1319150. - let seen = false; - let fnObserver = () => { - seen = true; - }; - - let branch0 = Services.prefs.getBranch(null); - branch0.addObserver("devtools.branch1.somestring", fnObserver); - Services.prefs.setCharPref("devtools.branch1.somestring", "common merganser"); - expect(seen).toBe(true); - branch0.removeObserver("devtools.branch1.somestring", fnObserver); - }); - - it("supports default value argument", () => { - // Check support for default values - let intPrefWithDefault = - Services.prefs.getIntPref("devtools.branch1.missing", 1); - expect(intPrefWithDefault).toEqual(1); - - let charPrefWithDefault = - Services.prefs.getCharPref("devtools.branch1.missing", "test"); - expect(charPrefWithDefault).toEqual("test"); - - let boolPrefWithDefault = - Services.prefs.getBoolPref("devtools.branch1.missing", true); - expect(boolPrefWithDefault).toBe(true); - }); -});
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/tests/services-telemetry.js +++ /dev/null @@ -1,41 +0,0 @@ -const Services = require("devtools-services"); - -// const pref = Services; - -describe("services telemetry shim", () => { - beforeEach(() => { - telemetry.scalars = {}; - telemetry.histograms = {}; - }); - - it("getHistogramById", () => { - const hist = Services.telemetry.getHistogramById("foo"); - hist.add(3); - expect(telemetry.histograms.foo).toEqual([3]); - - hist.add(3); - expect(telemetry.histograms.foo).toEqual([3, 3]); - }); - - it("getKeyedHistogramById", () => { - const hist = Services.telemetry.getKeyedHistogramById("foo"); - hist.add("a", 3); - expect(telemetry.histograms.foo.a).toEqual([3]); - - hist.add("a", 3); - expect(telemetry.histograms.foo.a).toEqual([3, 3]); - }); - - it("scalarSet", () => { - Services.telemetry.scalarSet("foo", 3); - expect(telemetry.scalars.foo).toEqual(3); - }); - - it("scalarAdd", () => { - Services.telemetry.scalarAdd("foo", 3); - expect(telemetry.scalars.foo).toEqual(3); - - Services.telemetry.scalarAdd("foo", 3); - expect(telemetry.scalars.foo).toEqual(6); - }); -});
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/tests/telemetry.js +++ /dev/null @@ -1,120 +0,0 @@ -const Telemetry = require("../utils/telemetry"); -const telemetry = new Telemetry(); - -describe("telemetry shim", () => { - it("msSystemNow", () => { - expect(() => { - telemetry.msSystemNow; - }).not.toThrow(); - }); - - it("start", () => { - expect(() => { - telemetry.start("foo", this); - }).not.toThrow(); - }); - - it("startKeyed", () => { - expect(() => { - telemetry.startKeyed("foo", "bar", this); - }).not.toThrow(); - }); - - it("finish", () => { - expect(() => { - telemetry.finish("foo", this); - }).not.toThrow(); - }); - - it("finishKeyed", () => { - expect(() => { - telemetry.finishKeyed("foo", "bar", this); - }).not.toThrow(); - }); - - it("getHistogramById", () => { - expect(() => { - telemetry.getHistogramById("foo").add(3); - }).not.toThrow(); - }); - - it("getKeyedHistogramById", () => { - expect(() => { - telemetry.getKeyedHistogramById("foo").add("foo", 3); - }).not.toThrow(); - }); - - it("scalarSet", () => { - expect(() => { - telemetry.scalarSet("foo", 3); - }).not.toThrow(); - }); - - it("scalarAdd", () => { - expect(() => { - telemetry.scalarAdd("foo", 3); - }).not.toThrow(); - }); - - it("keyedScalarAdd", () => { - expect(() => { - telemetry.keyedScalarAdd("foo", "bar", 3); - }).not.toThrow(); - }); - - it("setEventRecordingEnabled", () => { - expect(() => { - telemetry.setEventRecordingEnabled("foo", true); - }).not.toThrow(); - }); - - it("preparePendingEvent", () => { - expect(() => { - telemetry.preparePendingEvent( - "devtools.main", "open", "inspector", null, ["foo", "bar"]); - }).not.toThrow(); - }); - - it("addEventProperty", () => { - expect(() => { - telemetry.addEventProperty( - "devtools.main", "open", "inspector", "foo", "1"); - }).not.toThrow(); - }); - - it("addEventProperties", () => { - expect(() => { - telemetry.addEventProperties("devtools.main", "open", "inspector", { - "foo": "1", - "bar": "2" - }); - }).not.toThrow(); - }); - - it("_sendPendingEvent", () => { - expect(() => { - telemetry._sendPendingEvent("devtools.main", "open", "inspector", null); - }).not.toThrow(); - }); - - it("recordEvent", () => { - expect(() => { - telemetry.recordEvent("devtools.main", "open", "inspector", null, { - "foo": "1", - "bar": "2" - }); - }).not.toThrow(); - }); - - it("toolOpened", () => { - expect(() => { - telemetry.toolOpened("foo"); - }).not.toThrow(); - }); - - it("toolClosed", () => { - expect(() => { - telemetry.toolClosed("foo"); - }).not.toThrow(); - }); -});
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/tests/unicode-url.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/. */ - -const { getUnicodeUrl, getUnicodeUrlPath, getUnicodeHostname } = - require("../unicode-url"); - -describe("unicode-url", () => { - // List of URLs used to test Unicode URL conversion - const TEST_URLS = [ - // Type: Readable ASCII URLs - // Expected: All of Unicode versions should equal to the raw. - { - raw: "https://example.org", - expectedUnicode: "https://example.org", - }, - { - raw: "http://example.org", - expectedUnicode: "http://example.org", - }, - { - raw: "ftp://example.org", - expectedUnicode: "ftp://example.org", - }, - { - raw: "https://example.org.", - expectedUnicode: "https://example.org.", - }, - { - raw: "https://example.org/", - expectedUnicode: "https://example.org/", - }, - { - raw: "https://example.org/test", - expectedUnicode: "https://example.org/test", - }, - { - raw: "https://example.org/test.html", - expectedUnicode: "https://example.org/test.html", - }, - { - raw: "https://example.org/test.html?one=1&two=2", - expectedUnicode: "https://example.org/test.html?one=1&two=2", - }, - { - raw: "https://example.org/test.html#here", - expectedUnicode: "https://example.org/test.html#here", - }, - { - raw: "https://example.org/test.html?one=1&two=2#here", - expectedUnicode: "https://example.org/test.html?one=1&two=2#here", - }, - // Type: Unreadable URLs with either Punycode domain names or URI-encoded - // paths - // Expected: Unreadable domain names and URI-encoded paths should be converted - // to readable Unicode. - { - raw: "https://xn--g6w.xn--8pv/test.html", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "https://\u6e2c.\u672c/test.html", - }, - { - raw: "https://example.org/%E6%B8%AC%E8%A9%A6.html", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "https://example.org/\u6e2c\u8a66.html", - }, - { - raw: "https://example.org/test.html?One=%E4%B8%80", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "https://example.org/test.html?One=\u4e00", - }, - { - raw: "https://example.org/test.html?%E4%B8%80=1", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "https://example.org/test.html?\u4e00=1", - }, - { - raw: "https://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9%A6.html" + - "?%E4%B8%80=%E4%B8%80" + - "#%E6%AD%A4", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "https://\u6e2c.\u672c/\u6e2c\u8a66.html" + - "?\u4e00=\u4e00" + - "#\u6b64", - }, - // Type: data: URIs - // Expected: All should not be converted. - { - raw: "data:text/plain;charset=UTF-8;Hello%20world", - expectedUnicode: "data:text/plain;charset=UTF-8;Hello%20world", - }, - { - raw: "data:text/plain;charset=UTF-8;%E6%B8%AC%20%E8%A9%A6", - expectedUnicode: "data:text/plain;charset=UTF-8;%E6%B8%AC%20%E8%A9%A6", - }, - { - raw: "data:image/png;base64,iVBORw0KGgoAAA" + - "ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4" + - "//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU" + - "5ErkJggg==", - expectedUnicode: "data:image/png;base64,iVBORw0KGgoAAA" + - "ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4" + - "//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU" + - "5ErkJggg==", - }, - // Type: Malformed URLs - // Expected: All should not be converted. - { - raw: "://example.org/test", - expectedUnicode: "://example.org/test", - }, - { - raw: "://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9%A6.html" + - "?%E4%B8%80=%E4%B8%80", - expectedUnicode: "://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9%A6.html" + - "?%E4%B8%80=%E4%B8%80", - }, - { - // %E8%A9 isn't a valid UTF-8 code, so this URL is malformed. - raw: "https://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9", - expectedUnicode: "https://xn--g6w.xn--8pv/%E6%B8%AC%E8%A9", - }, - ]; - - // List of hostanmes used to test Unicode hostname conversion - const TEST_HOSTNAMES = [ - // Type: Readable ASCII hostnames - // Expected: All of Unicode versions should equal to the raw. - { - raw: "example", - expectedUnicode: "example", - }, - { - raw: "example.org", - expectedUnicode: "example.org", - }, - // Type: Unreadable Punycode hostnames - // Expected: Punycode should be converted to readable Unicode. - { - raw: "xn--g6w", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "\u6e2c", - }, - { - raw: "xn--g6w.xn--8pv", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "\u6e2c.\u672c", - }, - ]; - - // List of URL paths used to test Unicode URL path conversion - const TEST_URL_PATHS = [ - // Type: Readable ASCII URL paths - // Expected: All of Unicode versions should equal to the raw. - { - raw: "test", - expectedUnicode: "test", - }, - { - raw: "/", - expectedUnicode: "/", - }, - { - raw: "/test", - expectedUnicode: "/test", - }, - { - raw: "/test.html?one=1&two=2#here", - expectedUnicode: "/test.html?one=1&two=2#here", - }, - // Type: Unreadable URI-encoded URL paths - // Expected: URL paths should be converted to readable Unicode. - { - raw: "/%E6%B8%AC%E8%A9%A6", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "/\u6e2c\u8a66", - }, - { - raw: "/%E6%B8%AC%E8%A9%A6.html", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "/\u6e2c\u8a66.html", - }, - { - raw: "/%E6%B8%AC%E8%A9%A6.html" + - "?%E4%B8%80=%E4%B8%80&%E4%BA%8C=%E4%BA%8C" + - "#%E6%AD%A4", - // Do not type Unicode characters directly, because this test file isn't - // specified with a known encoding. - expectedUnicode: "/\u6e2c\u8a66.html" + - "?\u4e00=\u4e00&\u4e8c=\u4e8c" + - "#\u6b64", - }, - // Type: Malformed URL paths - // Expected: All should not be converted. - { - // %E8%A9 isn't a valid UTF-8 code, so this URL is malformed. - raw: "/%E6%B8%AC%E8%A9", - expectedUnicode: "/%E6%B8%AC%E8%A9", - }, - ]; - - it("Get Unicode URLs", () => { - for (let url of TEST_URLS) { - expect(getUnicodeUrl(url.raw)).toBe(url.expectedUnicode); - } - }); - - it("Get Unicode hostnames", () => { - for (let hostname of TEST_HOSTNAMES) { - expect(getUnicodeHostname(hostname.raw)).toBe(hostname.expectedUnicode); - } - }); - - it("Get Unicode URL paths", () => { - for (let urlPath of TEST_URL_PATHS) { - expect(getUnicodeUrlPath(urlPath.raw)).toBe(urlPath.expectedUnicode); - } - }); -});
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/unicode-url.js +++ /dev/null @@ -1,115 +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/. */ - -// This file is a chrome-API-free version of the module -// devtools/client/shared/unicode-url.js in the mozilla-central repository, so -// that it can be used in Chrome-API-free applications, such as the Launchpad. -// But because of this, it cannot take advantage of utilizing chrome APIs and -// should implement the similar functionalities on its own. -// -// Please keep in mind that if the feature in this file has changed, don't -// forget to also change that accordingly in -// devtools/client/shared/unicode-url.js in the mozilla-central repository. - -"use strict"; - -const punycode = require("punycode"); - -/** - * Gets a readble Unicode hostname from a hostname. - * - * If the `hostname` is a readable ASCII hostname, such as example.org, then - * this function will simply return the original `hostname`. - * - * If the `hostname` is a Punycode hostname representing a Unicode domain name, - * such as xn--g6w.xn--8pv, then this function will return the readable Unicode - * domain name by decoding the Punycode hostname. - * - * @param {string} hostname - * the hostname from which the Unicode hostname will be - * parsed, such as example.org, xn--g6w.xn--8pv. - * @return {string} The Unicode hostname. It may be the same as the `hostname` - * passed to this function if the `hostname` itself is - * a readable ASCII hostname or a Unicode hostname. - */ -function getUnicodeHostname(hostname) { - try { - return punycode.toUnicode(hostname); - } catch (err) { - } - return hostname; -} - -/** - * Gets a readble Unicode URL pathname from a URL pathname. - * - * If the `urlPath` is a readable ASCII URL pathname, such as /a/b/c.js, then - * this function will simply return the original `urlPath`. - * - * If the `urlPath` is a URI-encoded pathname, such as %E8%A9%A6/%E6%B8%AC.js, - * then this function will return the readable Unicode pathname. - * - * If the `urlPath` is a malformed URL pathname, then this function will simply - * return the original `urlPath`. - * - * @param {string} urlPath - * the URL path from which the Unicode URL path will be parsed, - * such as /a/b/c.js, %E8%A9%A6/%E6%B8%AC.js. - * @return {string} The Unicode URL Path. It may be the same as the `urlPath` - * passed to this function if the `urlPath` itself is a readable - * ASCII url or a Unicode url. - */ -function getUnicodeUrlPath(urlPath) { - try { - return decodeURIComponent(urlPath); - } catch (err) { - } - return urlPath; -} - -/** - * Gets a readable Unicode URL from a URL. - * - * If the `url` is a readable ASCII URL, such as http://example.org/a/b/c.js, - * then this function will simply return the original `url`. - * - * If the `url` includes either an unreadable Punycode domain name or an - * unreadable URI-encoded pathname, such as - * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js, then this function will return - * the readable URL by decoding all its unreadable URL components to Unicode - * characters. - * - * If the `url` is a malformed URL, then this function will return the original - * `url`. - * - * If the `url` is a data: URI, then this function will return the original - * `url`. - * - * @param {string} url - * the full URL, or a data: URI. from which the readable URL - * will be parsed, such as, http://example.org/a/b/c.js, - * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js - * @return {string} The readable URL. It may be the same as the `url` passed to - * this function if the `url` itself is readable. - */ -function getUnicodeUrl(url) { - try { - const { protocol, hostname } = new URL(url); - if (protocol === "data:") { - // Never convert a data: URI. - return url; - } - const readableHostname = getUnicodeHostname(hostname); - url = decodeURIComponent(url); - return url.replace(hostname, readableHostname); - } catch (err) { - } - return url; -} - -module.exports = { - getUnicodeHostname, - getUnicodeUrlPath, - getUnicodeUrl, -};
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/utils/defer.js +++ /dev/null @@ -1,25 +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"; - -// See bug 1273941 to understand this choice of promise. -const Promise = require("../sham/promise"); - -/** - * Returns a deferred object, with a resolve and reject property. - * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred - */ -module.exports = function defer() { - let resolve, reject; - let promise = new Promise(function () { - resolve = arguments[0]; - reject = arguments[1]; - }); - return { - resolve: resolve, - reject: reject, - promise: promise - }; -};
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/utils/event-emitter.js +++ /dev/null @@ -1,127 +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/. */ - -var EventEmitter = function EventEmitter() {}; -module.exports = EventEmitter; - -const promise = require("./promise"); - -/** - * Decorate an object with event emitter functionality. - * - * @param Object aObjectToDecorate - * Bind all public methods of EventEmitter to - * the aObjectToDecorate object. - */ -EventEmitter.decorate = function EventEmitter_decorate (aObjectToDecorate) { - let emitter = new EventEmitter(); - aObjectToDecorate.on = emitter.on.bind(emitter); - aObjectToDecorate.off = emitter.off.bind(emitter); - aObjectToDecorate.once = emitter.once.bind(emitter); - aObjectToDecorate.emit = emitter.emit.bind(emitter); -}; - -EventEmitter.prototype = { - /** - * Connect a listener. - * - * @param string aEvent - * The event name to which we're connecting. - * @param function aListener - * Called when the event is fired. - */ - on: function EventEmitter_on(aEvent, aListener) { - if (!this._eventEmitterListeners) - this._eventEmitterListeners = new Map(); - if (!this._eventEmitterListeners.has(aEvent)) { - this._eventEmitterListeners.set(aEvent, []); - } - this._eventEmitterListeners.get(aEvent).push(aListener); - }, - - /** - * Listen for the next time an event is fired. - * - * @param string aEvent - * The event name to which we're connecting. - * @param function aListener - * (Optional) Called when the event is fired. Will be called at most - * one time. - * @return promise - * A promise which is resolved when the event next happens. The - * resolution value of the promise is the first event argument. If - * you need access to second or subsequent event arguments (it's rare - * that this is needed) then use aListener - */ - once: function EventEmitter_once(aEvent, aListener) { - let deferred = promise.defer(); - - let handler = (aEvent, aFirstArg, ...aRest) => { - this.off(aEvent, handler); - if (aListener) { - aListener.apply(null, [aEvent, aFirstArg, ...aRest]); - } - deferred.resolve(aFirstArg); - }; - - handler._originalListener = aListener; - this.on(aEvent, handler); - - return deferred.promise; - }, - - /** - * Remove a previously-registered event listener. Works for events - * registered with either on or once. - * - * @param string aEvent - * The event name whose listener we're disconnecting. - * @param function aListener - * The listener to remove. - */ - off: function EventEmitter_off(aEvent, aListener) { - if (!this._eventEmitterListeners) - return; - let listeners = this._eventEmitterListeners.get(aEvent); - if (listeners) { - this._eventEmitterListeners.set(aEvent, listeners.filter(l => { - return l !== aListener && l._originalListener !== aListener; - })); - } - }, - - /** - * Emit an event. All arguments to this method will - * be sent to listener functions. - */ - emit: function EventEmitter_emit(aEvent) { - if (!this._eventEmitterListeners || !this._eventEmitterListeners.has(aEvent)) { - return; - } - - let originalListeners = this._eventEmitterListeners.get(aEvent); - for (let listener of this._eventEmitterListeners.get(aEvent)) { - // If the object was destroyed during event emission, stop - // emitting. - if (!this._eventEmitterListeners) { - break; - } - - // If listeners were removed during emission, make sure the - // event handler we're going to fire wasn't removed. - if (originalListeners === this._eventEmitterListeners.get(aEvent) || - this._eventEmitterListeners.get(aEvent).some(l => l === listener)) { - try { - listener.apply(null, arguments); - } - catch (ex) { - // Prevent a bad listener from interfering with the others. - let msg = ex + ": " + ex.stack; - //console.error(msg); - console.log(msg); - } - } - } - }, -};
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/utils/promise.js +++ /dev/null @@ -1,29 +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/. */ - -/* - * A sham for https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/Promise.jsm - */ - -/** - * Promise.jsm is mostly the Promise web API with a `defer` method. Just drop this in here, - * and use the native web API (although building with webpack/babel, it may replace this - * with it's own version if we want to target environments that do not have `Promise`. - */ - -let p = typeof window != "undefined" ? window.Promise : Promise; -p.defer = function defer() { - var resolve, reject; - var promise = new Promise(function() { - resolve = arguments[0]; - reject = arguments[1]; - }); - return { - resolve: resolve, - reject: reject, - promise: promise, - }; -}; - -module.exports = p;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/utils/task.js +++ /dev/null @@ -1,515 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ -/* 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"; - -/* eslint-disable spaced-comment */ -/* globals StopIteration */ - -/** - * This module implements a subset of "Task.js" <http://taskjs.org/>. - * It is a copy of toolkit/modules/Task.jsm. Please try not to - * diverge the API here. - * - * Paraphrasing from the Task.js site, tasks make sequential, asynchronous - * operations simple, using the power of JavaScript's "yield" operator. - * - * Tasks are built upon generator functions and promises, documented here: - * - * <https://developer.mozilla.org/en/JavaScript/Guide/Iterators_and_Generators> - * <http://wiki.commonjs.org/wiki/Promises/A> - * - * The "Task.spawn" function takes a generator function and starts running it as - * a task. Every time the task yields a promise, it waits until the promise is - * fulfilled. "Task.spawn" returns a promise that is resolved when the task - * completes successfully, or is rejected if an exception occurs. - * - * ----------------------------------------------------------------------------- - * - * const {Task} = require("devtools/shared/task"); - * - * Task.spawn(function* () { - * - * // This is our task. Let's create a promise object, wait on it and capture - * // its resolution value. - * let myPromise = getPromiseResolvedOnTimeoutWithValue(1000, "Value"); - * let result = yield myPromise; - * - * // This part is executed only after the promise above is fulfilled (after - * // one second, in this imaginary example). We can easily loop while - * // calling asynchronous functions, and wait multiple times. - * for (let i = 0; i < 3; i++) { - * result += yield getPromiseResolvedOnTimeoutWithValue(50, "!"); - * } - * - * return "Resolution result for the task: " + result; - * }).then(function (result) { - * - * // result == "Resolution result for the task: Value!!!" - * - * // The result is undefined if no value was returned. - * - * }, function (exception) { - * - * // Failure! We can inspect or report the exception. - * - * }); - * - * ----------------------------------------------------------------------------- - * - * This module implements only the "Task.js" interfaces described above, with no - * additional features to control the task externally, or do custom scheduling. - * It also provides the following extensions that simplify task usage in the - * most common cases: - * - * - The "Task.spawn" function also accepts an iterator returned by a generator - * function, in addition to a generator function. This way, you can call into - * the generator function with the parameters you want, and with "this" bound - * to the correct value. Also, "this" is never bound to the task object when - * "Task.spawn" calls the generator function. - * - * - In addition to a promise object, a task can yield the iterator returned by - * a generator function. The iterator is turned into a task automatically. - * This reduces the syntax overhead of calling "Task.spawn" explicitly when - * you want to recurse into other task functions. - * - * - The "Task.spawn" function also accepts a primitive value, or a function - * returning a primitive value, and treats the value as the result of the - * task. This makes it possible to call an externally provided function and - * spawn a task from it, regardless of whether it is an asynchronous generator - * or a synchronous function. This comes in handy when iterating over - * function lists where some items have been converted to tasks and some not. - */ - -//////////////////////////////////////////////////////////////////////////////// -//// Globals - -const Promise = require("../sham/promise"); -const defer = require("./defer"); - -// The following error types are considered programmer errors, which should be -// reported (possibly redundantly) so as to let programmers fix their code. -const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", - "TypeError"]; - -/** - * The Task currently being executed - */ -var gCurrentTask = null; - -/** - * If `true`, capture stacks whenever entering a Task and rewrite the - * stack any exception thrown through a Task. - */ -var gMaintainStack = false; - -/** - * Iterate through the lines of a string. - * - * @return Iterator<string> - */ -function* linesOf(string) { - let reLine = /([^\r\n])+/g; - let match; - while ((match = reLine.exec(string))) { - yield [match[0], match.index]; - } -} - -/** - * Detect whether a value is a generator. - * - * @param aValue - * The value to identify. - * @return A boolean indicating whether the value is a generator. - */ -function isGenerator(value) { - return Object.prototype.toString.call(value) == "[object Generator]"; -} - -//////////////////////////////////////////////////////////////////////////////// -//// Task - -/** - * This object provides the public module functions. - */ -var Task = { - /** - * Creates and starts a new task. - * - * @param task - * - If you specify a generator function, it is called with no - * arguments to retrieve the associated iterator. The generator - * function is a task, that is can yield promise objects to wait - * upon. - * - If you specify the iterator returned by a generator function you - * called, the generator function is also executed as a task. This - * allows you to call the function with arguments. - * - If you specify a function that is not a generator, it is called - * with no arguments, and its return value is used to resolve the - * returned promise. - * - If you specify anything else, you get a promise that is already - * resolved with the specified value. - * - * @return A promise object where you can register completion callbacks to be - * called when the task terminates. - */ - spawn: function (task) { - return createAsyncFunction(task)(); - }, - - /** - * Create and return an 'async function' that starts a new task. - * - * This is similar to 'spawn' except that it doesn't immediately start - * the task, it binds the task to the async function's 'this' object and - * arguments, and it requires the task to be a function. - * - * It simplifies the common pattern of implementing a method via a task, - * like this simple object with a 'greet' method that has a 'name' parameter - * and spawns a task to send a greeting and return its reply: - * - * let greeter = { - * message: "Hello, NAME!", - * greet: function(name) { - * return Task.spawn((function* () { - * return yield sendGreeting(this.message.replace(/NAME/, name)); - * }).bind(this); - * }) - * }; - * - * With Task.async, the method can be declared succinctly: - * - * let greeter = { - * message: "Hello, NAME!", - * greet: Task.async(function* (name) { - * return yield sendGreeting(this.message.replace(/NAME/, name)); - * }) - * }; - * - * While maintaining identical semantics: - * - * greeter.greet("Mitchell").then((reply) => { ... }); // behaves the same - * - * @param task - * The task function to start. - * - * @return A function that starts the task function and returns its promise. - */ - async: function (task) { - if (typeof (task) != "function") { - throw new TypeError("task argument must be a function"); - } - - return createAsyncFunction(task); - }, - - /** - * Constructs a special exception that, when thrown inside a legacy generator - * function (non-star generator), allows the associated task to be resolved - * with a specific value. - * - * Example: throw new Task.Result("Value"); - */ - Result: function (value) { - this.value = value; - } -}; - -function createAsyncFunction(task) { - let asyncFunction = function () { - let result = task; - if (task && typeof (task) == "function") { - if (task.isAsyncFunction) { - throw new TypeError( - "Cannot use an async function in place of a promise. " + - "You should either invoke the async function first " + - "or use 'Task.spawn' instead of 'Task.async' to start " + - "the Task and return its promise."); - } - - try { - // Let's call into the function ourselves. - result = task.apply(this, arguments); - } catch (ex) { - if (ex instanceof Task.Result) { - return Promise.resolve(ex.value); - } - return Promise.reject(ex); - } - } - - if (isGenerator(result)) { - // This is an iterator resulting from calling a generator function. - return new TaskImpl(result).deferred.promise; - } - - // Just propagate the given value to the caller as a resolved promise. - return Promise.resolve(result); - }; - - asyncFunction.isAsyncFunction = true; - - return asyncFunction; -} - -//////////////////////////////////////////////////////////////////////////////// -//// TaskImpl - -/** - * Executes the specified iterator as a task, and gives access to the promise - * that is fulfilled when the task terminates. - */ -function TaskImpl(iterator) { - if (gMaintainStack) { - this._stack = (new Error()).stack; - } - this.deferred = defer(); - this._iterator = iterator; - this._isStarGenerator = !("send" in iterator); - this._run(true); -} - -TaskImpl.prototype = { - /** - * Includes the promise object where task completion callbacks are registered, - * and methods to resolve or reject the promise at task completion. - */ - deferred: null, - - /** - * The iterator returned by the generator function associated with this task. - */ - _iterator: null, - - /** - * Whether this Task is using a star generator. - */ - _isStarGenerator: false, - - /** - * Main execution routine, that calls into the generator function. - * - * @param sendResolved - * If true, indicates that we should continue into the generator - * function regularly (if we were waiting on a promise, it was - * resolved). If true, indicates that we should cause an exception to - * be thrown into the generator function (if we were waiting on a - * promise, it was rejected). - * @param sendValue - * Resolution result or rejection exception, if any. - */ - _run: function (sendResolved, sendValue) { - try { - gCurrentTask = this; - - if (this._isStarGenerator) { - try { - let result = sendResolved ? this._iterator.next(sendValue) - : this._iterator.throw(sendValue); - - if (result.done) { - // The generator function returned. - this.deferred.resolve(result.value); - } else { - // The generator function yielded. - this._handleResultValue(result.value); - } - } catch (ex) { - // The generator function failed with an uncaught exception. - this._handleException(ex); - } - } else { - try { - let yielded = sendResolved ? this._iterator.send(sendValue) - : this._iterator.throw(sendValue); - this._handleResultValue(yielded); - } catch (ex) { - if (ex instanceof Task.Result) { - // The generator function threw the special exception that - // allows it to return a specific value on resolution. - this.deferred.resolve(ex.value); - } else if (ex instanceof StopIteration) { - // The generator function terminated with no specific result. - this.deferred.resolve(undefined); - } else { - // The generator function failed with an uncaught exception. - this._handleException(ex); - } - } - } - } finally { - // - // At this stage, the Task may have finished executing, or have - // walked through a `yield` or passed control to a sub-Task. - // Regardless, if we still own `gCurrentTask`, reset it. If we - // have not finished execution of this Task, re-entering `_run` - // will set `gCurrentTask` to `this` as needed. - // - // We just need to be careful here in case we hit the following - // pattern: - // - // Task.spawn(foo); - // Task.spawn(bar); - // - // Here, `foo` and `bar` may be interleaved, so when we finish - // executing `foo`, `gCurrentTask` may actually either `foo` or - // `bar`. If `gCurrentTask` has already been set to `bar`, leave - // it be and it will be reset to `null` once `bar` is complete. - // - if (gCurrentTask == this) { - gCurrentTask = null; - } - } - }, - - /** - * Handle a value yielded by a generator. - * - * @param value - * The yielded value to handle. - */ - _handleResultValue: function (value) { - // If our task yielded an iterator resulting from calling another - // generator function, automatically spawn a task from it, effectively - // turning it into a promise that is fulfilled on task completion. - if (isGenerator(value)) { - value = Task.spawn(value); - } - - if (value && typeof (value.then) == "function") { - // We have a promise object now. When fulfilled, call again into this - // function to continue the task, with either a resolution or rejection - // condition. - value.then(this._run.bind(this, true), - this._run.bind(this, false)); - } else { - // If our task yielded a value that is not a promise, just continue and - // pass it directly as the result of the yield statement. - this._run(true, value); - } - }, - - /** - * Handle an uncaught exception thrown from a generator. - * - * @param exception - * The uncaught exception to handle. - */ - _handleException: function (exception) { - gCurrentTask = this; - - if (exception && typeof exception == "object" && "stack" in exception) { - let stack = exception.stack; - - if (gMaintainStack && - exception._capturedTaskStack != this._stack && - typeof stack == "string") { - // Rewrite the stack for more readability. - - let bottomStack = this._stack; - - stack = Task.Debugging.generateReadableStack(stack); - - exception.stack = stack; - - // If exception is reinjected in the same task and rethrown, - // we don't want to perform the rewrite again. - exception._capturedTaskStack = bottomStack; - } else if (!stack) { - stack = "Not available"; - } - - if ("name" in exception && - ERRORS_TO_REPORT.indexOf(exception.name) != -1) { - // We suspect that the exception is a programmer error, so we now - // display it using dump(). Note that we do not use Cu.reportError as - // we assume that this is a programming error, so we do not want end - // users to see it. Also, if the programmer handles errors correctly, - // they will either treat the error or log them somewhere. - - dump("*************************\n"); - dump("A coding exception was thrown and uncaught in a Task.\n\n"); - dump("Full message: " + exception + "\n"); - dump("Full stack: " + exception.stack + "\n"); - dump("*************************\n"); - } - } - - this.deferred.reject(exception); - }, - - get callerStack() { - // Cut `this._stack` at the last line of the first block that - // contains task.js, keep the tail. - for (let [line, index] of linesOf(this._stack || "")) { - if (line.indexOf("/task.js:") == -1) { - return this._stack.substring(index); - } - } - return ""; - } -}; - -Task.Debugging = { - - /** - * Control stack rewriting. - * - * If `true`, any exception thrown from a Task will be rewritten to - * provide a human-readable stack trace. Otherwise, stack traces will - * be left unchanged. - * - * There is a (small but existing) runtime cost associated to stack - * rewriting, so you should probably not activate this in production - * code. - * - * @type {bool} - */ - get maintainStack() { - return gMaintainStack; - }, - set maintainStack(x) { - if (!x) { - gCurrentTask = null; - } - gMaintainStack = x; - return x; - }, - - /** - * Generate a human-readable stack for an error raised in - * a Task. - * - * @param {string} topStack The stack provided by the error. - * @param {string=} prefix Optionally, a prefix for each line. - */ - generateReadableStack: function (topStack, prefix = "") { - if (!gCurrentTask) { - return topStack; - } - - // Cut `topStack` at the first line that contains task.js, keep the head. - let lines = []; - for (let [line] of linesOf(topStack)) { - if (line.indexOf("/task.js:") != -1) { - break; - } - lines.push(prefix + line); - } - if (!prefix) { - lines.push(gCurrentTask.callerStack); - } else { - for (let [line] of linesOf(gCurrentTask.callerStack)) { - lines.push(prefix + line); - } - } - - return lines.join("\n"); - } -}; - -exports.Task = Task;
deleted file mode 100644 --- a/devtools/client/debugger/packages/devtools-modules/src/utils/telemetry.js +++ /dev/null @@ -1,331 +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/>. */ - -/** - * This is a stub of the DevTools telemetry module and will be replaced by the - * full version of the file by Webpack for running inside Firefox. - */ - -class Telemetry { - /** - * Time since the system wide epoch. This is not a monotonic timer but - * can be used across process boundaries. - */ - get msSystemNow() { - return 0; - } - - /** - * Starts a timer associated with a telemetry histogram. The timer can be - * directly associated with a histogram, or with a pair of a histogram and - * an object. - * - * @param {String} histogramId - * A string which must be a valid histogram name. - * @param {Object} obj - * Optional parameter. If specified, the timer is associated with this - * object, meaning that multiple timers for the same histogram may be - * run concurrently, as long as they are associated with different - * objects. - * - * @returns {Boolean} - * True if the timer was successfully started, false otherwise. If a - * timer already exists, it can't be started again, and the existing - * one will be cleared in order to avoid measurements errors. - */ - start(histogramId, obj) { - return true; - } - - /** - * Starts a timer associated with a keyed telemetry histogram. The timer can - * be directly associated with a histogram and its key. Similarly to - * TelemetryStopwatch.start the histogram and its key can be associated - * with an object. Each key may have multiple associated objects and each - * object can be associated with multiple keys. - * - * @param {String} histogramId - * A string which must be a valid histogram name. - * @param {String} key - * A string which must be a valid histgram key. - * @param {Object} obj - * Optional parameter. If specified, the timer is associated with this - * object, meaning that multiple timers for the same histogram may be - * run concurrently,as long as they are associated with different - * objects. - * - * @returns {Boolean} - * True if the timer was successfully started, false otherwise. If a - * timer already exists, it can't be started again, and the existing - * one will be cleared in order to avoid measurements errors. - */ - startKeyed(histogramId, key, obj) { - return true; - } - - /** - * Stops the timer associated with the given histogram (and object), - * calculates the time delta between start and finish, and adds the value - * to the histogram. - * - * @param {String} histogramId - * A string which must be a valid histogram name. - * @param {Object} obj - * Optional parameter which associates the histogram timer with the - * given object. - * @param {Boolean} canceledOkay - * Optional parameter which will suppress any warnings that normally - * fire when a stopwatch is finished after being cancelled. - * Defaults to false. - * - * @returns {Boolean} - * True if the timer was succesfully stopped and the data was added - * to the histogram, False otherwise. - */ - finish(histogramId, obj, canceledOkay) { - return true; - } - - /** - * Stops the timer associated with the given keyed histogram (and object), - * calculates the time delta between start and finish, and adds the value - * to the keyed histogram. - * - * @param {String} histogramId - * A string which must be a valid histogram name. - * @param {String} key - * A string which must be a valid histogram key. - * @param {Object} obj - * Optional parameter which associates the histogram timer with the - * given object. - * @param {Boolean} canceledOkay - * Optional parameter which will suppress any warnings that normally - * fire when a stopwatch is finished after being cancelled. - * Defaults to false. - * - * @returns {Boolean} - * True if the timer was succesfully stopped and the data was added - * to the histogram, False otherwise. - */ - finishKeyed(histogramId, key, obj, cancelledOkay) { - return true; - } - - /** - * Log a value to a histogram. - * - * @param {String} histogramId - * Histogram in which the data is to be stored. - */ - getHistogramById(histogramId) { - return { - add: () => {} - }; - } - - /** - * Get a keyed histogram. - * - * @param {String} histogramId - * Histogram in which the data is to be stored. - */ - getKeyedHistogramById(histogramId) { - return { - add: () => {} - }; - } - - /** - * Log a value to a scalar. - * - * @param {String} scalarId - * Scalar in which the data is to be stored. - * @param value - * Value to store. - */ - scalarSet(scalarId, value) {} - - /** - * Log a value to a count scalar. - * - * @param {String} scalarId - * Scalar in which the data is to be stored. - * @param value - * Value to store. - */ - scalarAdd(scalarId, value) {} - - /** - * Log a value to a keyed count scalar. - * - * @param {String} scalarId - * Scalar in which the data is to be stored. - * @param {String} key - * The key within the scalar. - * @param value - * Value to store. - */ - keyedScalarAdd(scalarId, key, value) {} - - /** - * Event telemetry is disabled by default. Use this method to enable it for - * a particular category. - * - * @param {Boolean} enabled - * Enabled: true or false. - */ - setEventRecordingEnabled(enabled) { - return enabled; - } - - /** - * Telemetry events often need to make use of a number of properties from - * completely different codepaths. To make this possible we create a - * "pending event" along with an array of property names that we need to wait - * for before sending the event. - * - * As each property is received via addEventProperty() we check if all - * properties have been received. Once they have all been received we send the - * telemetry event. - * - * @param {Object} obj - * The telemetry event or ping is associated with this object, meaning - * that multiple events or pings for the same histogram may be run - * concurrently, as long as they are associated with different objects. - * @param {String} method - * The telemetry event method (describes the type of event that - * occurred e.g. "open") - * @param {String} object - * The telemetry event object name (the name of the object the event - * occurred on) e.g. "tools" or "setting" - * @param {String|null} value - * The telemetry event value (a user defined value, providing context - * for the event) e.g. "console" - * @param {Array} expected - * An array of the properties needed before sending the telemetry - * event e.g. - * [ - * "host", - * "width" - * ] - */ - preparePendingEvent(obj, method, object, value, expected = []) {} - - /** - * Adds an expected property for either a current or future pending event. - * This means that if preparePendingEvent() is called before or after sending - * the event properties they will automatically added to the event. - * - * @param {Object} obj - * The telemetry event or ping is associated with this object, meaning - * that multiple events or pings for the same histogram may be run - * concurrently, as long as they are associated with different objects. - * @param {String} method - * The telemetry event method (describes the type of event that - * occurred e.g. "open") - * @param {String} object - * The telemetry event object name (the name of the object the event - * occurred on) e.g. "tools" or "setting" - * @param {String|null} value - * The telemetry event value (a user defined value, providing context - * for the event) e.g. "console" - * @param {String} pendingPropName - * The pending property name - * @param {String} pendingPropValue - * The pending property value - */ - addEventProperty(obj, method, object, value, pendingPropName, pendingPropValue) {} - - /** - * Adds expected properties for either a current or future pending event. - * This means that if preparePendingEvent() is called before or after sending - * the event properties they will automatically added to the event. - * - * @param {Object} obj - * The telemetry event or ping is associated with this object, meaning - * that multiple events or pings for the same histogram may be run - * concurrently, as long as they are associated with different objects. - * @param {String} method - * The telemetry event method (describes the type of event that - * occurred e.g. "open") - * @param {String} object - * The telemetry event object name (the name of the object the event - * occurred on) e.g. "tools" or "setting" - * @param {String|null} value - * The telemetry event value (a user defined value, providing context - * for the event) e.g. "console" - * @param {String} pendingObject - * An object containing key, value pairs that should be added to the - * event as properties. - */ - addEventProperties(obj, method, object, value, pendingObject) {} - - /** - * A private method that is not to be used externally. This method is used to - * prepare a pending telemetry event for sending and then send it via - * recordEvent(). - * - * @param {Object} obj - * The telemetry event or ping is associated with this object, meaning - * that multiple events or pings for the same histogram may be run - * concurrently, as long as they are associated with different objects. - * @param {String} method - * The telemetry event method (describes the type of event that - * occurred e.g. "open") - * @param {String} object - * The telemetry event object name (the name of the object the event - * occurred on) e.g. "tools" or "setting" - * @param {String|null} value - * The telemetry event value (a user defined value, providing context - * for the event) e.g. "console" - */ - _sendPendingEvent(obj, method, object, value) {} - - /** - * Send a telemetry event. - * - * @param {String} method - * The telemetry event method (describes the type of event that - * occurred e.g. "open") - * @param {String} object - * The telemetry event object name (the name of the object the event - * occurred on) e.g. "tools" or "setting" - * @param {String|null} value - * The telemetry event value (a user defined value, providing context - * for the event) e.g. "console" - * @param {Object} extra - * The telemetry event extra object containing the properties that will - * be sent with the event e.g. - * { - * host: "bottom", - * width: "1024" - * } - */ - recordEvent(method, object, value, extra) {} - - /** - * Sends telemetry pings to indicate that a tool has been opened. - * - * @param {String} id - * The ID of the tool opened. - * @param {String} sessionId - * Toolbox session id used when we need to ensure a tool really has a - * timer before calculating a delta. - * @param {Object} obj - * The telemetry event or ping is associated with this object, meaning - * that multiple events or pings for the same histogram may be run - * concurrently, as long as they are associated with different objects. - */ - toolOpened(id, sessionId, obj) {} - - /** - * Sends telemetry pings to indicate that a tool has been closed. - * - * @param {String} id - * The ID of the tool opened. - */ - toolClosed(id, sessionId, obj) {} -} - -module.exports = Telemetry;