зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge
This commit is contained in:
Коммит
a833a61a1b
|
@ -6,6 +6,7 @@
|
|||
#include "AccessibleWrap.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "AndroidInputType.h"
|
||||
#include "DocAccessibleWrap.h"
|
||||
#include "IDSet.h"
|
||||
#include "JavaBuiltins.h"
|
||||
|
@ -286,10 +287,11 @@ AccessibleWrap::CreateBundle(int32_t aParentID,
|
|||
GECKOBUNDLE_PUT(nodeInfo, "rangeInfo", rangeInfo);
|
||||
}
|
||||
|
||||
nsString inputType;
|
||||
nsAccUtils::GetAccAttr(aAttributes, nsGkAtoms::textInputType, inputType);
|
||||
if (!inputType.IsEmpty()) {
|
||||
GECKOBUNDLE_PUT(nodeInfo, "inputType", jni::StringParam(inputType));
|
||||
nsString inputTypeAttr;
|
||||
nsAccUtils::GetAccAttr(aAttributes, nsGkAtoms::textInputType, inputTypeAttr);
|
||||
int32_t inputType = GetInputType(inputTypeAttr);
|
||||
if (inputType) {
|
||||
GECKOBUNDLE_PUT(nodeInfo, "inputType", java::sdk::Integer::ValueOf(inputType));
|
||||
}
|
||||
|
||||
nsString posinset;
|
||||
|
@ -462,6 +464,36 @@ AccessibleWrap::GetAndroidClass(role aRole)
|
|||
#undef ROLE
|
||||
}
|
||||
|
||||
int32_t
|
||||
AccessibleWrap::GetInputType(const nsString& aInputTypeAttr)
|
||||
{
|
||||
if (aInputTypeAttr.EqualsIgnoreCase("email")) {
|
||||
return java::sdk::InputType::TYPE_CLASS_TEXT | java::sdk::InputType::TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
|
||||
}
|
||||
|
||||
if (aInputTypeAttr.EqualsIgnoreCase("number")) {
|
||||
return java::sdk::InputType::TYPE_CLASS_NUMBER;
|
||||
}
|
||||
|
||||
if (aInputTypeAttr.EqualsIgnoreCase("password")) {
|
||||
return java::sdk::InputType::TYPE_CLASS_TEXT | java::sdk::InputType::TYPE_TEXT_VARIATION_WEB_PASSWORD;
|
||||
}
|
||||
|
||||
if (aInputTypeAttr.EqualsIgnoreCase("tel")) {
|
||||
return java::sdk::InputType::TYPE_CLASS_PHONE;
|
||||
}
|
||||
|
||||
if (aInputTypeAttr.EqualsIgnoreCase("text")) {
|
||||
return java::sdk::InputType::TYPE_CLASS_TEXT | java::sdk::InputType::TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
|
||||
}
|
||||
|
||||
if (aInputTypeAttr.EqualsIgnoreCase("url")) {
|
||||
return java::sdk::InputType::TYPE_CLASS_TEXT | java::sdk::InputType::TYPE_TEXT_VARIATION_URI;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleWrap::DOMNodeID(nsString& aDOMNodeID)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,8 @@ protected:
|
|||
|
||||
static int32_t GetAndroidClass(role aRole);
|
||||
|
||||
static int32_t GetInputType(const nsString& aInputTypeAttr);
|
||||
|
||||
int32_t mID;
|
||||
|
||||
private:
|
||||
|
|
|
@ -126,7 +126,6 @@ var TrackingProtection = {
|
|||
};
|
||||
|
||||
var ThirdPartyCookies = {
|
||||
reportBreakageLabel: "cookierestrictions",
|
||||
telemetryIdentifier: "cr",
|
||||
PREF_ENABLED: "network.cookie.cookieBehavior",
|
||||
PREF_REPORT_BREAKAGE_ENABLED: "browser.contentblocking.rejecttrackers.reportBreakage.enabled",
|
||||
|
@ -144,12 +143,49 @@ var ThirdPartyCookies = {
|
|||
document.getElementById("identity-popup-content-blocking-category-3rdpartycookies");
|
||||
},
|
||||
|
||||
get reportBreakageLabel() {
|
||||
switch (this.behaviorPref) {
|
||||
case Ci.nsICookieService.BEHAVIOR_ACCEPT:
|
||||
return "nocookiesblocked";
|
||||
case Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN:
|
||||
return "allthirdpartycookiesblocked";
|
||||
case Ci.nsICookieService.BEHAVIOR_REJECT:
|
||||
return "allcookiesblocked";
|
||||
case Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN:
|
||||
return "cookiesfromunvisitedsitesblocked";
|
||||
default:
|
||||
Cu.reportError(`Error: Unknown cookieBehavior pref observed: ${this.behaviorPref}`);
|
||||
// fall through
|
||||
case Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER:
|
||||
return "cookierestrictions";
|
||||
}
|
||||
},
|
||||
|
||||
get categoryLabelDefault() {
|
||||
delete this.categoryLabelDefault;
|
||||
return this.categoryLabelDefault =
|
||||
document.getElementById("identity-popup-content-blocking-category-label-default");
|
||||
},
|
||||
|
||||
get categoryLabelTrackers() {
|
||||
delete this.categoryLabelTrackers;
|
||||
return this.categoryLabelTrackers =
|
||||
document.getElementById("identity-popup-content-blocking-category-label-trackers");
|
||||
},
|
||||
|
||||
updateCategoryLabel() {
|
||||
let rejectTrackers = this.behaviorPref == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
|
||||
this.categoryLabelDefault.hidden = rejectTrackers;
|
||||
this.categoryLabelTrackers.hidden = !rejectTrackers;
|
||||
},
|
||||
|
||||
init() {
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "behaviorPref", this.PREF_ENABLED,
|
||||
Ci.nsICookieService.BEHAVIOR_ACCEPT);
|
||||
Ci.nsICookieService.BEHAVIOR_ACCEPT, this.updateCategoryLabel.bind(this));
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "visible", this.PREF_UI_ENABLED, false);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "reportBreakageEnabled",
|
||||
this.PREF_REPORT_BREAKAGE_ENABLED, false);
|
||||
this.updateCategoryLabel();
|
||||
},
|
||||
get enabled() {
|
||||
return this.PREF_ENABLED_VALUES.includes(this.behaviorPref);
|
||||
|
|
|
@ -177,6 +177,18 @@ function testTrackingPage(window) {
|
|||
is(hidden(category + " > .identity-popup-content-blocking-category-state-label"), !blockedByTP,
|
||||
"Category item is" + (blockedByTP ? "" : " not") + " set to blocked");
|
||||
}
|
||||
|
||||
if (Services.prefs.getIntPref(TPC_PREF) == Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER) {
|
||||
ok(hidden("#identity-popup-content-blocking-category-label-default"),
|
||||
"Not showing default cookie restrictions label.");
|
||||
ok(!hidden("#identity-popup-content-blocking-category-label-trackers"),
|
||||
"Showing trackers cookie restrictions label.");
|
||||
} else {
|
||||
ok(hidden("#identity-popup-content-blocking-category-label-trackers"),
|
||||
"Not showing trackers cookie restrictions label.");
|
||||
ok(!hidden("#identity-popup-content-blocking-category-label-default"),
|
||||
"Showing default cookie restrictions label.");
|
||||
}
|
||||
}
|
||||
|
||||
function testTrackingPageUnblocked(blockedByTP, window) {
|
||||
|
|
|
@ -105,7 +105,10 @@
|
|||
<hbox id="identity-popup-content-blocking-category-3rdpartycookies"
|
||||
class="identity-popup-content-blocking-category" align="center" role="group">
|
||||
<image class="identity-popup-content-blocking-category-icon thirdpartycookies-icon"/>
|
||||
<label flex="1" class="identity-popup-content-blocking-category-label">&contentBlocking.3rdPartyCookies.label;</label>
|
||||
<label flex="1" id="identity-popup-content-blocking-category-label-default"
|
||||
class="identity-popup-content-blocking-category-label">&contentBlocking.3rdPartyCookies.label;</label>
|
||||
<label flex="1" id="identity-popup-content-blocking-category-label-trackers"
|
||||
hidden="true" class="identity-popup-content-blocking-category-label">&contentBlocking.3rdPartyCookies.trackers.label;</label>
|
||||
<label flex="1" class="identity-popup-content-blocking-category-state-label">&contentBlocking.3rdPartyCookies.blocking.label;</label>
|
||||
<label flex="1" class="identity-popup-content-blocking-category-add-blocking text-link"
|
||||
id="identity-popup-3rdpartycookies-add-blocking"
|
||||
|
|
|
@ -10,6 +10,24 @@ ChromeUtils.defineModuleGetter(this, "AddonManager",
|
|||
"resource://gre/modules/AddonManager.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "AddonRepository",
|
||||
"resource://gre/modules/addons/AddonRepository.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "RemoteSettings",
|
||||
"resource://services-settings/remote-settings.js");
|
||||
|
||||
async function installFromUrl(url, hash) {
|
||||
let install = await AddonManager.getInstallForURL(
|
||||
url, "application/x-xpinstall", hash);
|
||||
return install.install();
|
||||
}
|
||||
|
||||
async function dictionaryIdsForLocale(locale) {
|
||||
let entries = await RemoteSettings("language-dictionaries").get({
|
||||
filters: {id: locale},
|
||||
});
|
||||
if (entries.length > 0) {
|
||||
return entries[0].dictionaries;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
class OrderedListBox {
|
||||
constructor({richlistbox, upButton, downButton, removeButton, onRemove}) {
|
||||
|
@ -394,37 +412,61 @@ var gBrowserLanguagesDialog = {
|
|||
},
|
||||
|
||||
async availableLanguageSelected(item) {
|
||||
let available = new Set(Services.locale.availableLocales);
|
||||
|
||||
if (available.has(item.value)) {
|
||||
this._requestedLocales.addItem(item);
|
||||
if (available.size == this._requestedLocales.items.length) {
|
||||
// Remove the installed label, they're all installed.
|
||||
this._availableLocales.items.shift();
|
||||
this._availableLocales.setItems(this._availableLocales.items);
|
||||
}
|
||||
if (Services.locale.availableLocales.includes(item.value)) {
|
||||
this.requestLocalLanguage(item);
|
||||
} else if (this.availableLangpacks.has(item.value)) {
|
||||
this._availableLocales.disableWithMessageId("browser-languages-downloading");
|
||||
|
||||
let {url, hash} = this.availableLangpacks.get(item.value);
|
||||
let install = await AddonManager.getInstallForURL(
|
||||
url, "application/x-xpinstall", hash);
|
||||
|
||||
try {
|
||||
await install.install();
|
||||
} catch (e) {
|
||||
this.showError();
|
||||
return;
|
||||
}
|
||||
|
||||
item.installed = true;
|
||||
this._requestedLocales.addItem(item);
|
||||
this._availableLocales.enableWithMessageId("browser-languages-select-language");
|
||||
await this.requestRemoteLanguage(item);
|
||||
} else {
|
||||
this.showError();
|
||||
}
|
||||
},
|
||||
|
||||
requestLocalLanguage(item, available) {
|
||||
this._requestedLocales.addItem(item);
|
||||
let requestedCount = this._requestedLocales.items.length;
|
||||
let availableCount = Services.locale.availableLocales.length;
|
||||
if (requestedCount == availableCount) {
|
||||
// Remove the installed label, they're all installed.
|
||||
this._availableLocales.items.shift();
|
||||
this._availableLocales.setItems(this._availableLocales.items);
|
||||
}
|
||||
},
|
||||
|
||||
async requestRemoteLanguage(item) {
|
||||
this._availableLocales.disableWithMessageId(
|
||||
"browser-languages-downloading");
|
||||
|
||||
let {url, hash} = this.availableLangpacks.get(item.value);
|
||||
|
||||
try {
|
||||
await installFromUrl(url, hash);
|
||||
} catch (e) {
|
||||
this.showError();
|
||||
return;
|
||||
}
|
||||
|
||||
item.installed = true;
|
||||
this._requestedLocales.addItem(item);
|
||||
this._availableLocales.enableWithMessageId(
|
||||
"browser-languages-select-language");
|
||||
|
||||
// This is an async task that will install the recommended dictionaries for
|
||||
// this locale. This will fail silently at least until a management UI is
|
||||
// added in bug 1493705.
|
||||
this.installDictionariesForLanguage(item.value);
|
||||
},
|
||||
|
||||
async installDictionariesForLanguage(locale) {
|
||||
try {
|
||||
let ids = await dictionaryIdsForLocale(locale);
|
||||
let addonInfos = await AddonRepository.getAddonsByIDs(ids);
|
||||
await Promise.all(addonInfos.map(
|
||||
info => installFromUrl(info.sourceURI.spec)));
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
showError() {
|
||||
document.querySelectorAll(".warning-message-separator")
|
||||
.forEach(separator => separator.classList.add("thin"));
|
||||
|
|
Двоичные данные
browser/components/preferences/in-content/tests/addons/pl-dictionary.xpi
Normal file
Двоичные данные
browser/components/preferences/in-content/tests/addons/pl-dictionary.xpi
Normal file
Двоичный файл не отображается.
|
@ -5,6 +5,7 @@ prefs =
|
|||
support-files =
|
||||
head.js
|
||||
privacypane_tests_perwindow.js
|
||||
addons/pl-dictionary.xpi
|
||||
addons/set_homepage.xpi
|
||||
addons/set_newtab.xpi
|
||||
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm", this);
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
const BROWSER_LANGUAGES_URL = "chrome://browser/content/preferences/browserLanguages.xul";
|
||||
const DICTIONARY_ID_PL = "pl@dictionaries.addons.mozilla.org";
|
||||
|
||||
function getManifestData(locale) {
|
||||
return {
|
||||
|
@ -79,6 +81,45 @@ async function createLanguageToolsFile() {
|
|||
return dir;
|
||||
}
|
||||
|
||||
async function createDictionaryBrowseResults() {
|
||||
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||
let dictionaryPath = testDir + "/addons/pl-dictionary.xpi";
|
||||
let filename = "dictionaries.json";
|
||||
let response = {
|
||||
page_size: 25,
|
||||
page_count: 1,
|
||||
count: 1,
|
||||
results: [{
|
||||
current_version: {
|
||||
id: 1823648,
|
||||
compatibility: {
|
||||
firefox: {max: "9999", min: "4.0"},
|
||||
},
|
||||
files: [{
|
||||
platform: "all",
|
||||
url: dictionaryPath,
|
||||
}],
|
||||
version: "1.0.20160228",
|
||||
},
|
||||
default_locale: "pl",
|
||||
description: "Polish spell-check",
|
||||
guid: DICTIONARY_ID_PL,
|
||||
name: "Polish Dictionary",
|
||||
slug: "polish-spellchecker-dictionary",
|
||||
status: "public",
|
||||
summary: "Polish dictionary",
|
||||
type: "dictionary",
|
||||
}],
|
||||
};
|
||||
|
||||
let files = {[filename]: response};
|
||||
let dir = await AddonTestUtils.promiseWriteFilesToDir(
|
||||
AddonTestUtils.tempDir.path, files);
|
||||
dir.append(filename);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
function assertLocaleOrder(list, locales) {
|
||||
is(list.itemCount, locales.split(",").length,
|
||||
"The right number of locales are requested");
|
||||
|
@ -245,12 +286,16 @@ add_task(async function testInstallFromAMO() {
|
|||
|
||||
let langpacksFile = await createLanguageToolsFile();
|
||||
let langpacksUrl = Services.io.newFileURI(langpacksFile).spec;
|
||||
let dictionaryBrowseFile = await createDictionaryBrowseResults();
|
||||
let browseApiEndpoint = Services.io.newFileURI(dictionaryBrowseFile).spec;
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["intl.multilingual.enabled", true],
|
||||
["intl.locale.requested", "en-US"],
|
||||
["extensions.getAddons.langpacks.url", langpacksUrl],
|
||||
["extensions.langpacks.signatures.required", false],
|
||||
["extensions.getAddons.get.url", browseApiEndpoint],
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -277,6 +322,10 @@ add_task(async function testInstallFromAMO() {
|
|||
is(Services.locale.availableLocales.join(","),
|
||||
"en-US", "There is only one installed locale");
|
||||
|
||||
// Verify that there are no extra dictionaries.
|
||||
let dicts = await AddonManager.getAddonsByTypes(["dictionary"]);
|
||||
is(dicts.length, 0, "There are no installed dictionaries");
|
||||
|
||||
// Add Polish, this will install the langpack.
|
||||
requestLocale("pl", available, dialogDoc);
|
||||
|
||||
|
@ -293,10 +342,21 @@ add_task(async function testInstallFromAMO() {
|
|||
is(Services.locale.availableLocales.sort().join(","),
|
||||
"en-US,pl", "Polish is now installed");
|
||||
|
||||
// Uninstall the langpack.
|
||||
langpacks = await AddonManager.getAddonsByTypes(["locale"]);
|
||||
is(langpacks.length, 1, "There is one langpacks installed");
|
||||
await Promise.all(langpacks.map(pack => pack.uninstall()));
|
||||
await BrowserTestUtils.waitForCondition(async () => {
|
||||
let newDicts = await AddonManager.getAddonsByTypes(["dictionary"]);
|
||||
let done = newDicts.length != 0;
|
||||
|
||||
if (done) {
|
||||
is(newDicts[0].id, DICTIONARY_ID_PL, "The polish dictionary was installed");
|
||||
}
|
||||
|
||||
return done;
|
||||
});
|
||||
|
||||
// Uninstall the langpack and dictionary.
|
||||
let installs = await AddonManager.getAddonsByTypes(["locale", "dictionary"]);
|
||||
is(installs.length, 2, "There is one langpack and one dictionary installed");
|
||||
await Promise.all(installs.map(item => item.uninstall()));
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
|
|
@ -1002,6 +1002,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY contentBlocking.trackingProtection.add.label "Add Blocking…">
|
||||
|
||||
<!ENTITY contentBlocking.3rdPartyCookies.label "Third-Party Cookies">
|
||||
<!ENTITY contentBlocking.3rdPartyCookies.trackers.label "Tracking Cookies">
|
||||
<!-- LOCALIZATION NOTE (contentBlocking.3rdPartyCookies.blocked.label):
|
||||
This label signals that this type of content blocking is turned
|
||||
ON and is successfully blocking third-party cookies, so this is
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
@import "resource://devtools/client/themes/variables.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/App.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimeInfo.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/connect/ConnectSteps.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsList.css";
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
ADB_ADDON_INSTALL_START,
|
||||
ADB_ADDON_INSTALL_SUCCESS,
|
||||
ADB_ADDON_INSTALL_FAILURE,
|
||||
ADB_ADDON_UNINSTALL_START,
|
||||
ADB_ADDON_UNINSTALL_SUCCESS,
|
||||
ADB_ADDON_UNINSTALL_FAILURE,
|
||||
ADB_ADDON_STATUS_UPDATED,
|
||||
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
||||
NETWORK_LOCATIONS_UPDATED,
|
||||
|
@ -13,6 +19,7 @@ const {
|
|||
} = require("../constants");
|
||||
|
||||
const NetworkLocationsModule = require("../modules/network-locations");
|
||||
const { adbAddon } = require("devtools/shared/adb/adb-addon");
|
||||
|
||||
const Actions = require("./index");
|
||||
|
||||
|
@ -69,10 +76,38 @@ function updateNetworkLocations(locations) {
|
|||
return { type: NETWORK_LOCATIONS_UPDATED, locations };
|
||||
}
|
||||
|
||||
function installAdbAddon() {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({ type: ADB_ADDON_INSTALL_START });
|
||||
|
||||
try {
|
||||
await adbAddon.install();
|
||||
dispatch({ type: ADB_ADDON_INSTALL_SUCCESS });
|
||||
} catch (e) {
|
||||
dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e.message });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function uninstallAdbAddon() {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({ type: ADB_ADDON_UNINSTALL_START });
|
||||
|
||||
try {
|
||||
await adbAddon.uninstall();
|
||||
dispatch({ type: ADB_ADDON_UNINSTALL_SUCCESS });
|
||||
} catch (e) {
|
||||
dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e.message });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addNetworkLocation,
|
||||
installAdbAddon,
|
||||
removeNetworkLocation,
|
||||
selectPage,
|
||||
uninstallAdbAddon,
|
||||
updateAdbAddonStatus,
|
||||
updateDebugTargetCollapsibility,
|
||||
updateNetworkLocations,
|
||||
|
|
|
@ -36,7 +36,12 @@ class App extends PureComponent {
|
|||
}
|
||||
|
||||
getSelectedPageComponent() {
|
||||
const { dispatch, networkLocations, selectedPage } = this.props;
|
||||
const {
|
||||
adbAddonStatus,
|
||||
dispatch,
|
||||
networkLocations,
|
||||
selectedPage
|
||||
} = this.props;
|
||||
|
||||
if (!selectedPage) {
|
||||
// No page selected.
|
||||
|
@ -45,7 +50,11 @@ class App extends PureComponent {
|
|||
|
||||
switch (selectedPage) {
|
||||
case PAGES.CONNECT:
|
||||
return ConnectPage({ dispatch, networkLocations });
|
||||
return ConnectPage({
|
||||
adbAddonStatus,
|
||||
dispatch,
|
||||
networkLocations
|
||||
});
|
||||
default:
|
||||
// All pages except for the CONNECT page are RUNTIME pages.
|
||||
return RuntimePage({ dispatch });
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/* 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/. */
|
||||
|
||||
.connect-page__usb__toggle-button {
|
||||
margin-top: calc(var(--base-distance) * 4);
|
||||
}
|
|
@ -11,6 +11,14 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
|||
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
|
||||
const Localized = createFactory(FluentReact.Localized);
|
||||
|
||||
const {
|
||||
USB_STATES,
|
||||
} = require("../../constants");
|
||||
|
||||
const Actions = require("../../actions/index");
|
||||
|
||||
loader.lazyRequireGetter(this, "ADB_ADDON_STATES", "devtools/shared/adb/adb-addon", true);
|
||||
|
||||
const ConnectSection = createFactory(require("./ConnectSection"));
|
||||
const ConnectSteps = createFactory(require("./ConnectSteps"));
|
||||
const NetworkLocationsForm = createFactory(require("./NetworkLocationsForm"));
|
||||
|
@ -23,6 +31,7 @@ const GLOBE_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-globe-icon.
|
|||
class ConnectPage extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
adbAddonStatus: PropTypes.string,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
// Provided by wrapping the component with FluentReact.withLocalization.
|
||||
getString: PropTypes.func.isRequired,
|
||||
|
@ -54,8 +63,59 @@ class ConnectPage extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
onToggleUSBClick() {
|
||||
const { adbAddonStatus } = this.props;
|
||||
const isAddonInstalled = adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
|
||||
if (isAddonInstalled) {
|
||||
this.props.dispatch(Actions.uninstallAdbAddon());
|
||||
} else {
|
||||
this.props.dispatch(Actions.installAdbAddon());
|
||||
}
|
||||
}
|
||||
|
||||
getUsbStatus() {
|
||||
switch (this.props.adbAddonStatus) {
|
||||
case ADB_ADDON_STATES.INSTALLED:
|
||||
return USB_STATES.ENABLED_USB;
|
||||
case ADB_ADDON_STATES.UNINSTALLED:
|
||||
return USB_STATES.DISABLED_USB;
|
||||
default:
|
||||
return USB_STATES.UPDATING_USB;
|
||||
}
|
||||
}
|
||||
|
||||
renderUsbToggleButton() {
|
||||
const usbStatus = this.getUsbStatus();
|
||||
|
||||
const localizedStates = {
|
||||
[USB_STATES.ENABLED_USB]: "about-debugging-connect-usb-disable-button",
|
||||
[USB_STATES.DISABLED_USB]: "about-debugging-connect-usb-enable-button",
|
||||
[USB_STATES.UPDATING_USB]: "about-debugging-connect-usb-updating-button",
|
||||
};
|
||||
const localizedState = localizedStates[usbStatus];
|
||||
|
||||
// Disable the button while the USB status is updating.
|
||||
const disabled = usbStatus === USB_STATES.UPDATING_USB;
|
||||
|
||||
return Localized(
|
||||
{
|
||||
id: localizedState
|
||||
},
|
||||
dom.button(
|
||||
{
|
||||
className: "std-button connect-page__usb__toggle-button " +
|
||||
"js-connect-usb-toggle-button",
|
||||
disabled,
|
||||
onClick: () => this.onToggleUSBClick(),
|
||||
},
|
||||
localizedState
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderUsb() {
|
||||
const { getString } = this.props;
|
||||
const { adbAddonStatus, getString } = this.props;
|
||||
const isAddonInstalled = adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
|
||||
return Localized(
|
||||
{
|
||||
id: "about-debugging-connect-usb",
|
||||
|
@ -66,13 +126,28 @@ class ConnectPage extends PureComponent {
|
|||
icon: USB_ICON_SRC,
|
||||
title: "Via USB",
|
||||
},
|
||||
ConnectSteps({
|
||||
steps: [
|
||||
getString("about-debugging-connect-usb-step-enable-dev-menu"),
|
||||
getString("about-debugging-connect-usb-step-enable-debug"),
|
||||
getString("about-debugging-connect-usb-step-plug-device"),
|
||||
]
|
||||
})
|
||||
(isAddonInstalled ?
|
||||
ConnectSteps({
|
||||
steps: [
|
||||
getString("about-debugging-connect-usb-step-enable-dev-menu"),
|
||||
getString("about-debugging-connect-usb-step-enable-debug"),
|
||||
getString("about-debugging-connect-usb-step-plug-device"),
|
||||
]
|
||||
}) :
|
||||
Localized(
|
||||
{
|
||||
id: "about-debugging-connect-usb-disabled",
|
||||
},
|
||||
dom.aside(
|
||||
{
|
||||
className: "js-connect-usb-disabled-message"
|
||||
},
|
||||
"Enabling this will download and add the required Android USB debugging " +
|
||||
"components to Firefox."
|
||||
)
|
||||
)
|
||||
),
|
||||
this.renderUsbToggleButton()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'ConnectPage.css',
|
||||
'ConnectPage.js',
|
||||
'ConnectSection.js',
|
||||
'ConnectSteps.css',
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
"use strict";
|
||||
|
||||
const actionTypes = {
|
||||
ADB_ADDON_INSTALL_START: "ADB_ADDON_INSTALL_START",
|
||||
ADB_ADDON_INSTALL_SUCCESS: "ADB_ADDON_INSTALL_SUCCESS",
|
||||
ADB_ADDON_INSTALL_FAILURE: "ADB_ADDON_INSTALL_FAILURE",
|
||||
ADB_ADDON_UNINSTALL_START: "ADB_ADDON_UNINSTALL_START",
|
||||
ADB_ADDON_UNINSTALL_SUCCESS: "ADB_ADDON_UNINSTALL_SUCCESS",
|
||||
ADB_ADDON_UNINSTALL_FAILURE: "ADB_ADDON_UNINSTALL_FAILURE",
|
||||
ADB_ADDON_STATUS_UPDATED: "ADB_ADDON_STATUS_UPDATED",
|
||||
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
|
||||
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
|
||||
|
@ -70,6 +76,12 @@ const SERVICE_WORKER_STATUSES = {
|
|||
STOPPED: "STOPPED",
|
||||
};
|
||||
|
||||
const USB_STATES = {
|
||||
DISABLED_USB: "DISABLED_USB",
|
||||
ENABLED_USB: "ENABLED_USB",
|
||||
UPDATING_USB: "UPDATING_USB",
|
||||
};
|
||||
|
||||
// flatten constants
|
||||
module.exports = Object.assign({}, {
|
||||
DEBUG_TARGETS,
|
||||
|
@ -78,4 +90,5 @@ module.exports = Object.assign({}, {
|
|||
RUNTIMES,
|
||||
SERVICE_WORKER_FETCH_STATES,
|
||||
SERVICE_WORKER_STATUSES,
|
||||
USB_STATES,
|
||||
}, actionTypes);
|
||||
|
|
|
@ -11,6 +11,8 @@ support-files =
|
|||
!/devtools/client/shared/test/telemetry-test-helpers.js
|
||||
|
||||
[browser_aboutdebugging_connect_networklocations.js]
|
||||
[browser_aboutdebugging_connect_toggle_usb_devices.js]
|
||||
skip-if = (os == 'linux' && bits == 32) # ADB start() fails on linux 32, see Bug 1499638
|
||||
[browser_aboutdebugging_debug-target-pane_collapsibilities_interaction.js]
|
||||
[browser_aboutdebugging_debug-target-pane_collapsibilities_preference.js]
|
||||
[browser_aboutdebugging_debug-target-pane_empty.js]
|
||||
|
|
|
@ -13,17 +13,7 @@ const TEST_NETWORK_LOCATION = "localhost:1111";
|
|||
add_task(async function() {
|
||||
const { document, tab } = await openAboutDebugging();
|
||||
|
||||
const sidebarItems = document.querySelectorAll(".js-sidebar-item");
|
||||
const connectSidebarItem = [...sidebarItems].find(element => {
|
||||
return element.textContent === "Connect";
|
||||
});
|
||||
ok(connectSidebarItem, "Sidebar contains a Connect item");
|
||||
|
||||
info("Click on the Connect item in the sidebar");
|
||||
connectSidebarItem.click();
|
||||
|
||||
info("Wait until Connect page is displayed");
|
||||
await waitUntil(() => document.querySelector(".js-connect-page"));
|
||||
await selectConnectPage(document);
|
||||
|
||||
let networkLocations = document.querySelectorAll(".js-network-location");
|
||||
is(networkLocations.length, 0, "By default, no network locations are displayed");
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
|
||||
/**
|
||||
* Check that USB Devices scanning can be enabled and disabled from the connect page.
|
||||
*/
|
||||
add_task(async function() {
|
||||
await pushPref("devtools.remote.adb.extensionURL",
|
||||
CHROME_URL_ROOT + "resources/test-adb-extension/adb-extension-#OS#.xpi");
|
||||
|
||||
const { document, tab } = await openAboutDebugging();
|
||||
|
||||
await selectConnectPage(document);
|
||||
|
||||
info("Wait until Connect page is displayed");
|
||||
await waitUntil(() => document.querySelector(".js-connect-page"));
|
||||
|
||||
info("Check that by default USB devices are disabled");
|
||||
const usbDisabledMessage = document.querySelector(".js-connect-usb-disabled-message");
|
||||
ok(usbDisabledMessage, "A message about enabling USB devices is rendered");
|
||||
|
||||
const usbToggleButton = document.querySelector(".js-connect-usb-toggle-button");
|
||||
ok(usbToggleButton, "The button to toggle USB devices debugging is rendered");
|
||||
ok(usbToggleButton.textContent.includes("Enable"),
|
||||
"The text of the toggle USB button is correct");
|
||||
|
||||
info("Click on the toggle button");
|
||||
usbToggleButton.click();
|
||||
|
||||
info("Wait until the toggle button text is updated");
|
||||
await waitUntil(() => usbToggleButton.textContent.includes("Disable"));
|
||||
ok(!document.querySelector(".js-connect-usb-disabled-message"),
|
||||
"The message about enabling USB devices is no longer rendered");
|
||||
|
||||
// Right now we are resuming as soon as "USB devices enabled" is displayed, but ADB
|
||||
// might still be starting up. If we move to uninstall directly, the ADB startup will
|
||||
// fail and we will have an unhandled promise rejection.
|
||||
// See Bug 1498469.
|
||||
info("Wait until ADB has started.");
|
||||
await waitUntil(() => ADB.ready);
|
||||
|
||||
info("Click on the toggle button");
|
||||
usbToggleButton.click();
|
||||
|
||||
info("Wait until the toggle button text is updated");
|
||||
await waitUntil(() => usbToggleButton.textContent.includes("Enable"));
|
||||
ok(document.querySelector(".js-connect-usb-disabled-message"),
|
||||
"The message about enabling USB devices is rendered again");
|
||||
|
||||
await removeTab(tab);
|
||||
});
|
|
@ -11,17 +11,6 @@ const { ADB } = require("devtools/shared/adb/adb");
|
|||
* devices scanning.
|
||||
*/
|
||||
add_task(async function() {
|
||||
// Make sure the ADB addon is removed and ADB is stopped when the test ends.
|
||||
registerCleanupFunction(async function() {
|
||||
try {
|
||||
await adbAddon.uninstall();
|
||||
} catch (e) {
|
||||
// Will throw if the addon is already uninstalled, ignore exceptions here.
|
||||
}
|
||||
|
||||
await ADB.kill();
|
||||
});
|
||||
|
||||
await pushPref("devtools.remote.adb.extensionURL",
|
||||
CHROME_URL_ROOT + "resources/test-adb-extension/adb-extension-#OS#.xpi");
|
||||
|
||||
|
|
|
@ -17,6 +17,18 @@ Services.scriptloader.loadSubScript(
|
|||
Services.scriptloader.loadSubScript(
|
||||
CHROME_URL_ROOT + "debug-target-pane_collapsibilities_head.js", this);
|
||||
|
||||
// Make sure the ADB addon is removed and ADB is stopped when the test ends.
|
||||
registerCleanupFunction(async function() {
|
||||
try {
|
||||
const { adbAddon } = require("devtools/shared/adb/adb-addon");
|
||||
await adbAddon.uninstall();
|
||||
} catch (e) {
|
||||
// Will throw if the addon is already uninstalled, ignore exceptions here.
|
||||
}
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
await ADB.kill();
|
||||
});
|
||||
|
||||
/**
|
||||
* Enable the new about:debugging panel.
|
||||
*/
|
||||
|
@ -42,6 +54,23 @@ async function openAboutDebugging(page, win) {
|
|||
return { tab, document, window };
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to the Connect page. Resolves when the Connect page is rendered.
|
||||
*/
|
||||
async function selectConnectPage(doc) {
|
||||
const sidebarItems = doc.querySelectorAll(".js-sidebar-item");
|
||||
const connectSidebarItem = [...sidebarItems].find(element => {
|
||||
return element.textContent === "Connect";
|
||||
});
|
||||
ok(connectSidebarItem, "Sidebar contains a Connect item");
|
||||
|
||||
info("Click on the Connect item in the sidebar");
|
||||
connectSidebarItem.click();
|
||||
|
||||
info("Wait until Connect page is displayed");
|
||||
await waitUntil(() => doc.querySelector(".js-connect-page"));
|
||||
}
|
||||
|
||||
function findSidebarItemByText(text, document) {
|
||||
const sidebarItems = document.querySelectorAll(".js-sidebar-item");
|
||||
return [...sidebarItems].find(element => {
|
||||
|
|
|
@ -59,6 +59,11 @@ about-debugging-connect-wifi-step-enable-debug = Enable Remote Debugging via WiF
|
|||
about-debugging-connect-usb
|
||||
.title = Via USB
|
||||
|
||||
about-debugging-connect-usb-disabled = Enabling this will download and add the required Android USB debugging components to Firefox.
|
||||
about-debugging-connect-usb-enable-button = Enable USB Devices
|
||||
about-debugging-connect-usb-disable-button = Disable USB Devices
|
||||
about-debugging-connect-usb-updating-button = Updating…
|
||||
|
||||
# USB section step by step guide
|
||||
about-debugging-connect-usb-step-enable-dev-menu = Enable Developer menu on your Android device
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "test-devtools-webextension-nobg",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "test-devtools-webextension-nobg@mozilla.org"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "test-devtools-webextension-noid",
|
||||
"version": "1.0"
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "test-devtools-webextension-unknown-prop",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "test-devtools-webextension-unknown-prop@mozilla.org"
|
||||
}
|
||||
},
|
||||
"browser_actions": {
|
||||
"default_title": "WebExtension Popup Debugging",
|
||||
"default_popup": "popup.html"
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* eslint-env browser */
|
||||
/* global browser */
|
||||
|
||||
"use strict";
|
||||
|
||||
document.body.innerText = "Background Page Body Test Content";
|
||||
|
||||
// These functions are called from the following about:debugging tests:
|
||||
// - browser_addons_debug_webextension.js
|
||||
// - browser_addons_debug_webextension_popup.js
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function myWebExtensionAddonFunction() {
|
||||
console.log("Background page function called", browser.runtime.getManifest());
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function myWebExtensionShowPopup() {
|
||||
browser.test.sendMessage("readyForOpenPopup");
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "test-devtools-webextension",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "test-devtools-webextension@mozilla.org"
|
||||
}
|
||||
},
|
||||
"background": {
|
||||
"scripts": ["bg.js"]
|
||||
},
|
||||
"browser_action": {
|
||||
"default_title": "WebExtension Popup Debugging",
|
||||
"default_popup": "popup.html"
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="popup.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
Background Page Body Test Content
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* eslint-env browser */
|
||||
/* global browser */
|
||||
|
||||
"use strict";
|
||||
|
||||
// This function is called from the following about:debugging test:
|
||||
// browser_addons_debug_webextension.js
|
||||
//
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function myWebExtensionPopupAddonFunction() {
|
||||
browser.test.sendMessage("popupPageFunctionCalled", browser.runtime.getManifest());
|
||||
}
|
|
@ -39,15 +39,27 @@ add_task(async function testWebExtension() {
|
|||
const { tab, document } = await openAboutDebugging("addons");
|
||||
|
||||
await waitForInitialAddonList(document);
|
||||
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
manifest: {
|
||||
name: addonName,
|
||||
applications: {
|
||||
gecko: {id: addonId},
|
||||
},
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
await installAddon({
|
||||
document,
|
||||
path: "addons/test-devtools-webextension-nobg/manifest.json",
|
||||
file: addonFile,
|
||||
name: addonName,
|
||||
isWebExtension: true
|
||||
});
|
||||
|
||||
const container = document.querySelector(`[data-addon-id="${addonId}"]`);
|
||||
testFilePath(container, "/test/addons/test-devtools-webextension-nobg/");
|
||||
|
||||
testFilePath(container, addonFile.leafName);
|
||||
|
||||
const extensionID = container.querySelector(".extension-id span");
|
||||
ok(extensionID.textContent === "test-devtools-webextension-nobg@mozilla.org");
|
||||
|
@ -68,9 +80,17 @@ add_task(async function testTemporaryWebExtension() {
|
|||
const { tab, document } = await openAboutDebugging("addons");
|
||||
|
||||
await waitForInitialAddonList(document);
|
||||
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
manifest: {
|
||||
name: addonName,
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
await installAddon({
|
||||
document,
|
||||
path: "addons/test-devtools-webextension-noid/manifest.json",
|
||||
file: addonFile,
|
||||
name: addonName,
|
||||
isWebExtension: true
|
||||
});
|
||||
|
@ -98,9 +118,22 @@ add_task(async function testUnknownManifestProperty() {
|
|||
const { tab, document } = await openAboutDebugging("addons");
|
||||
|
||||
await waitForInitialAddonList(document);
|
||||
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
manifest: {
|
||||
name: addonName,
|
||||
applications: {
|
||||
gecko: {id: addonId},
|
||||
},
|
||||
wrong_manifest_property_name: {
|
||||
}
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
await installAddon({
|
||||
document,
|
||||
path: "addons/test-devtools-webextension-unknown-prop/manifest.json",
|
||||
file: addonFile,
|
||||
name: addonName,
|
||||
isWebExtension: true
|
||||
});
|
||||
|
@ -113,7 +146,7 @@ add_task(async function testUnknownManifestProperty() {
|
|||
|
||||
const messages = container.querySelectorAll(".addon-target-message");
|
||||
ok(messages.length === 1, "there is one message");
|
||||
ok(messages[0].textContent.match(/Error processing browser_actions/),
|
||||
ok(messages[0].textContent.match(/Error processing wrong_manifest_property_name/),
|
||||
"the message is helpful");
|
||||
ok(messages[0].classList.contains("addon-target-warning-message"),
|
||||
"the message is a warning");
|
||||
|
|
|
@ -13,7 +13,6 @@ requestLongerTimeout(2);
|
|||
|
||||
const ADDON_ID = "test-devtools-webextension@mozilla.org";
|
||||
const ADDON_NAME = "test-devtools-webextension";
|
||||
const ADDON_MANIFEST_PATH = "addons/test-devtools-webextension/manifest.json";
|
||||
|
||||
const {
|
||||
BrowserToolboxProcess
|
||||
|
@ -25,9 +24,25 @@ const {
|
|||
* has a working webconsole with the background page as default target;
|
||||
*/
|
||||
add_task(async function testWebExtensionsToolboxWebConsole() {
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
background: function() {
|
||||
window.myWebExtensionAddonFunction = function() {
|
||||
console.log("Background page function called",
|
||||
this.browser.runtime.getManifest());
|
||||
};
|
||||
},
|
||||
manifest: {
|
||||
name: ADDON_NAME,
|
||||
applications: {
|
||||
gecko: {id: ADDON_ID},
|
||||
},
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
const {
|
||||
tab, document, debugBtn,
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NAME, ADDON_MANIFEST_PATH);
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NAME, addonFile);
|
||||
|
||||
// Be careful, this JS function is going to be executed in the addon toolbox,
|
||||
// which lives in another process. So do not try to use any scope variable!
|
||||
|
|
|
@ -12,7 +12,6 @@ requestLongerTimeout(2);
|
|||
|
||||
const ADDON_ID = "test-devtools-webextension@mozilla.org";
|
||||
const ADDON_NAME = "test-devtools-webextension";
|
||||
const ADDON_PATH = "addons/test-devtools-webextension/manifest.json";
|
||||
|
||||
const {
|
||||
BrowserToolboxProcess
|
||||
|
@ -24,9 +23,22 @@ const {
|
|||
* background page as default target;
|
||||
*/
|
||||
add_task(async function testWebExtensionsToolboxInspector() {
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
background: function() {
|
||||
document.body.innerText = "Background Page Body Test Content";
|
||||
},
|
||||
manifest: {
|
||||
name: ADDON_NAME,
|
||||
applications: {
|
||||
gecko: {id: ADDON_ID},
|
||||
},
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
const {
|
||||
tab, document, debugBtn,
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NAME, ADDON_PATH);
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NAME, addonFile);
|
||||
|
||||
// Be careful, this JS function is going to be executed in the addon toolbox,
|
||||
// which lives in another process. So do not try to use any scope variable!
|
||||
|
|
|
@ -12,7 +12,6 @@ requestLongerTimeout(2);
|
|||
|
||||
const ADDON_NOBG_ID = "test-devtools-webextension-nobg@mozilla.org";
|
||||
const ADDON_NOBG_NAME = "test-devtools-webextension-nobg";
|
||||
const ADDON_NOBG_PATH = "addons/test-devtools-webextension-nobg/manifest.json";
|
||||
|
||||
const {
|
||||
BrowserToolboxProcess
|
||||
|
@ -26,9 +25,19 @@ const {
|
|||
* webextension context);
|
||||
*/
|
||||
add_task(async function testWebExtensionsToolboxNoBackgroundPage() {
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
manifest: {
|
||||
name: ADDON_NOBG_NAME,
|
||||
applications: {
|
||||
gecko: {id: ADDON_NOBG_ID},
|
||||
},
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
const {
|
||||
tab, document, debugBtn,
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NOBG_NAME, ADDON_NOBG_PATH);
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NOBG_NAME, addonFile);
|
||||
|
||||
// Be careful, this JS function is going to be executed in the addon toolbox,
|
||||
// which lives in another process. So do not try to use any scope variable!
|
||||
|
@ -36,41 +45,37 @@ add_task(async function testWebExtensionsToolboxNoBackgroundPage() {
|
|||
.getService(Ci.nsIEnvironment);
|
||||
const testScript = function() {
|
||||
/* eslint-disable no-undef */
|
||||
toolbox.selectTool("inspector")
|
||||
.then(inspector => {
|
||||
return inspector.walker.querySelector(inspector.walker.rootNode, "body");
|
||||
})
|
||||
.then((nodeActor) => {
|
||||
if (!nodeActor) {
|
||||
throw new Error("nodeActor not found");
|
||||
}
|
||||
toolbox.selectTool("inspector").then(async inspector => {
|
||||
const nodeActor = await inspector.walker.querySelector(
|
||||
inspector.walker.rootNode, "body");
|
||||
|
||||
dump("Got a nodeActor\n");
|
||||
if (!nodeActor) {
|
||||
throw new Error("nodeActor not found");
|
||||
}
|
||||
|
||||
if (!(nodeActor.inlineTextChild)) {
|
||||
throw new Error("inlineTextChild not found");
|
||||
}
|
||||
if (!(nodeActor.inlineTextChild)) {
|
||||
throw new Error("inlineTextChild not found");
|
||||
}
|
||||
|
||||
dump("Got a nodeActor with an inline text child\n");
|
||||
dump("Got a nodeActor with an inline text child\n");
|
||||
|
||||
const expectedValue = "Your addon does not have any document opened yet.";
|
||||
const actualValue = nodeActor.inlineTextChild._form.nodeValue;
|
||||
const expectedValue = "Your addon does not have any document opened yet.";
|
||||
const actualValue = nodeActor.inlineTextChild._form.nodeValue;
|
||||
|
||||
if (actualValue !== expectedValue) {
|
||||
throw new Error(
|
||||
`mismatched inlineTextchild value: "${actualValue}" !== "${expectedValue}"`
|
||||
);
|
||||
}
|
||||
if (actualValue !== expectedValue) {
|
||||
throw new Error(
|
||||
`mismatched inlineTextchild value: "${actualValue}" !== "${expectedValue}"`
|
||||
);
|
||||
}
|
||||
|
||||
dump("Got the expected inline text content in the selected node\n");
|
||||
return Promise.resolve();
|
||||
})
|
||||
.then(() => toolbox.destroy())
|
||||
.catch((error) => {
|
||||
dump("Error while running code in the browser toolbox process:\n");
|
||||
dump(error + "\n");
|
||||
dump("stack:\n" + error.stack + "\n");
|
||||
});
|
||||
dump("Got the expected inline text content in the selected node\n");
|
||||
|
||||
await toolbox.destroy();
|
||||
}).catch((error) => {
|
||||
dump("Error while running code in the browser toolbox process:\n");
|
||||
dump(error + "\n");
|
||||
dump("stack:\n" + error.stack + "\n");
|
||||
});
|
||||
/* eslint-enable no-undef */
|
||||
};
|
||||
env.set("MOZ_TOOLBOX_TEST_SCRIPT", "new " + testScript);
|
||||
|
|
|
@ -12,7 +12,6 @@ requestLongerTimeout(2);
|
|||
|
||||
const ADDON_ID = "test-devtools-webextension@mozilla.org";
|
||||
const ADDON_NAME = "test-devtools-webextension";
|
||||
const ADDON_MANIFEST_PATH = "addons/test-devtools-webextension/manifest.json";
|
||||
|
||||
const {
|
||||
BrowserToolboxProcess
|
||||
|
@ -42,6 +41,46 @@ function makeWidgetId(id) {
|
|||
}
|
||||
|
||||
add_task(async function testWebExtensionsToolboxSwitchToPopup() {
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
background: function() {
|
||||
const {browser} = this;
|
||||
window.myWebExtensionShowPopup = function() {
|
||||
browser.test.sendMessage("readyForOpenPopup");
|
||||
};
|
||||
},
|
||||
manifest: {
|
||||
name: ADDON_NAME,
|
||||
applications: {
|
||||
gecko: {id: ADDON_ID},
|
||||
},
|
||||
browser_action: {
|
||||
default_title: "WebExtension Popup Debugging",
|
||||
default_popup: "popup.html",
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"popup.html": `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="popup.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
Background Page Body Test Content
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
"popup.js": function() {
|
||||
const {browser} = this;
|
||||
window.myWebExtensionPopupAddonFunction = function() {
|
||||
browser.test.sendMessage("popupPageFunctionCalled",
|
||||
browser.runtime.getManifest());
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
let onReadyForOpenPopup;
|
||||
let onPopupCustomMessage;
|
||||
|
||||
|
@ -81,7 +120,7 @@ add_task(async function testWebExtensionsToolboxSwitchToPopup() {
|
|||
|
||||
const {
|
||||
tab, document, debugBtn,
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NAME, ADDON_MANIFEST_PATH);
|
||||
} = await setupTestAboutDebuggingWebExtension(ADDON_NAME, addonFile);
|
||||
|
||||
// Be careful, this JS function is going to be executed in the addon toolbox,
|
||||
// which lives in another process. So do not try to use any scope variable!
|
||||
|
|
|
@ -44,10 +44,20 @@ add_task(async function removeWebextension() {
|
|||
const { tab, document } = await openAboutDebugging("addons");
|
||||
await waitForInitialAddonList(document);
|
||||
|
||||
const addonFile = ExtensionTestCommon.generateXPI({
|
||||
manifest: {
|
||||
name: addonName,
|
||||
applications: {
|
||||
gecko: {id: addonID},
|
||||
},
|
||||
},
|
||||
});
|
||||
registerCleanupFunction(() => addonFile.remove(false));
|
||||
|
||||
// Install this add-on, and verify that it appears in the about:debugging UI
|
||||
await installAddon({
|
||||
document,
|
||||
path: "addons/test-devtools-webextension/manifest.json",
|
||||
file: addonFile,
|
||||
name: addonName,
|
||||
isWebExtension: true,
|
||||
});
|
||||
|
|
|
@ -14,6 +14,7 @@ Services.scriptloader.loadSubScript(
|
|||
|
||||
const { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
const { Management } = ChromeUtils.import("resource://gre/modules/Extension.jsm", {});
|
||||
const { ExtensionTestCommon } = ChromeUtils.import("resource://testing-common/ExtensionTestCommon.jsm", {});
|
||||
|
||||
async function openAboutDebugging(page, win) {
|
||||
info("opening about:debugging");
|
||||
|
@ -165,12 +166,16 @@ function getTabList(document) {
|
|||
document.querySelector("#tabs.targets");
|
||||
}
|
||||
|
||||
async function installAddon({document, path, name, isWebExtension}) {
|
||||
async function installAddon({document, path, file, name, isWebExtension}) {
|
||||
// Mock the file picker to select a test addon
|
||||
const MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(window);
|
||||
const file = getSupportsFile(path);
|
||||
MockFilePicker.setFiles([file.file]);
|
||||
if (path) {
|
||||
file = getSupportsFile(path);
|
||||
MockFilePicker.setFiles([file.file]);
|
||||
} else {
|
||||
MockFilePicker.setFiles([file]);
|
||||
}
|
||||
|
||||
let onAddonInstalled;
|
||||
|
||||
|
@ -341,7 +346,7 @@ function waitForDelayedStartupFinished(win) {
|
|||
/**
|
||||
* open the about:debugging page and install an addon
|
||||
*/
|
||||
async function setupTestAboutDebuggingWebExtension(name, path) {
|
||||
async function setupTestAboutDebuggingWebExtension(name, file) {
|
||||
await new Promise(resolve => {
|
||||
const options = {"set": [
|
||||
// Force enabling of addons debugging
|
||||
|
@ -360,7 +365,7 @@ async function setupTestAboutDebuggingWebExtension(name, path) {
|
|||
|
||||
await installAddon({
|
||||
document,
|
||||
path,
|
||||
file,
|
||||
name,
|
||||
isWebExtension: true,
|
||||
});
|
||||
|
|
|
@ -479,8 +479,8 @@ Workers.prototype = {
|
|||
|
||||
this._updateWorkerList();
|
||||
|
||||
// `_targetFront` can be BrowsingContextTargetFront (protocol.js front) or
|
||||
// WorkerClient/DebuggerClient (old fashion client)
|
||||
// `_targetFront` can be BrowsingContextTargetFront/WorkerTargetFront (protocol.js
|
||||
// front) or DebuggerClient (old fashion client)
|
||||
if (typeof(this._targetFront.on) == "function") {
|
||||
this._targetFront.on("workerListChanged", this._onWorkerListChanged);
|
||||
} else {
|
||||
|
@ -529,8 +529,8 @@ Workers.prototype = {
|
|||
},
|
||||
|
||||
_onWorkerSelect: function (workerForm) {
|
||||
DebuggerController.client.attachWorker(workerForm.actor).then(([response, workerClient]) => {
|
||||
let toolbox = gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
DebuggerController.client.attachWorker(workerForm.actor).then(([response, workerTargetFront]) => {
|
||||
let toolbox = gDevTools.showToolbox(TargetFactory.forWorker(workerTargetFront),
|
||||
"jsdebugger", Toolbox.HostType.WINDOW);
|
||||
window.emit(EVENTS.WORKER_SELECTED, toolbox);
|
||||
});
|
||||
|
|
|
@ -64,11 +64,11 @@ DebuggerPanel.prototype = {
|
|||
},
|
||||
|
||||
openWorkerToolbox: async function(worker) {
|
||||
const [response, workerClient] =
|
||||
const [response, workerTargetFront] =
|
||||
await this.toolbox.target.client.attachWorker(worker.actor);
|
||||
const workerTarget = TargetFactory.forWorker(workerClient);
|
||||
const workerTarget = TargetFactory.forWorker(workerTargetFront);
|
||||
const toolbox = await gDevTools.showToolbox(workerTarget, "jsdebugger", Toolbox.HostType.WINDOW);
|
||||
toolbox.once("destroy", () => workerClient.detach());
|
||||
toolbox.once("destroy", () => workerTargetFront.detach());
|
||||
},
|
||||
|
||||
getFrames: function() {
|
||||
|
|
|
@ -41,8 +41,8 @@ function setupEvents(dependencies) {
|
|||
});
|
||||
|
||||
if (threadClient._parent) {
|
||||
// Parent may be BrowsingContextTargetFront and be protocol.js.
|
||||
// Or DebuggerClient/WorkerClient and still be old fashion actor.
|
||||
// Parent may be BrowsingContextTargetFront/WorkerTargetFront and be protocol.js.
|
||||
// Or DebuggerClient and still be old fashion actor.
|
||||
if (threadClient._parent.on) {
|
||||
threadClient._parent.on("workerListChanged", workerListChanged);
|
||||
} else {
|
||||
|
|
|
@ -28,10 +28,10 @@ add_task(async function() {
|
|||
await createWorkerInTab(tab, WORKER_URL);
|
||||
|
||||
let { workers } = await listWorkers(targetFront);
|
||||
let [, workerClient] = await attachWorker(targetFront,
|
||||
let [, workerTargetFront] = await attachWorker(targetFront,
|
||||
findWorker(workers, WORKER_URL));
|
||||
|
||||
let toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
let toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerTargetFront),
|
||||
"jsdebugger",
|
||||
Toolbox.HostType.WINDOW);
|
||||
|
||||
|
@ -55,7 +55,7 @@ add_task(async function() {
|
|||
"Correct set of tools supported by worker");
|
||||
|
||||
terminateWorkerInTab(tab, WORKER_URL);
|
||||
await waitForWorkerClose(workerClient);
|
||||
await waitForWorkerClose(workerTargetFront);
|
||||
await close(client);
|
||||
|
||||
await toolbox.destroy();
|
||||
|
|
|
@ -1114,14 +1114,14 @@ function waitForWorkerListChanged(targetFront) {
|
|||
return targetFront.once("workerListChanged");
|
||||
}
|
||||
|
||||
function attachThread(workerClient, options) {
|
||||
function attachThread(workerTargetFront, options) {
|
||||
info("Attaching to thread.");
|
||||
return workerClient.attachThread(options);
|
||||
return workerTargetFront.attachThread(options);
|
||||
}
|
||||
|
||||
async function waitForWorkerClose(workerClient) {
|
||||
async function waitForWorkerClose(workerTargetFront) {
|
||||
info("Waiting for worker to close.");
|
||||
await workerClient.once("close");
|
||||
await workerTargetFront.once("close");
|
||||
info("Worker did close.");
|
||||
}
|
||||
|
||||
|
@ -1288,15 +1288,15 @@ async function initWorkerDebugger(TAB_URL, WORKER_URL) {
|
|||
await createWorkerInTab(tab, WORKER_URL);
|
||||
|
||||
let { workers } = await listWorkers(targetFront);
|
||||
let [, workerClient] = await attachWorker(targetFront,
|
||||
let [, workerTargetFront] = await attachWorker(targetFront,
|
||||
findWorker(workers, WORKER_URL));
|
||||
|
||||
let toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
let toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerTargetFront),
|
||||
"jsdebugger",
|
||||
Toolbox.HostType.WINDOW);
|
||||
|
||||
let debuggerPanel = toolbox.getCurrentPanel();
|
||||
let gDebugger = debuggerPanel.panelWin;
|
||||
|
||||
return {client, tab, targetFront, workerClient, toolbox, gDebugger};
|
||||
return {client, tab, targetFront, workerTargetFront, toolbox, gDebugger};
|
||||
}
|
||||
|
|
|
@ -375,10 +375,10 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
|
|||
* worker actor form to debug
|
||||
*/
|
||||
async openWorkerToolbox(client, workerTargetActor) {
|
||||
const [, workerClient] = await client.attachWorker(workerTargetActor);
|
||||
const workerTarget = TargetFactory.forWorker(workerClient);
|
||||
const [, workerTargetFront] = await client.attachWorker(workerTargetActor);
|
||||
const workerTarget = TargetFactory.forWorker(workerTargetFront);
|
||||
const toolbox = await gDevTools.showToolbox(workerTarget, null, Toolbox.HostType.WINDOW);
|
||||
toolbox.once("destroy", () => workerClient.detach());
|
||||
toolbox.once("destroy", () => workerTargetFront.detach());
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -120,11 +120,11 @@ const TargetFactory = exports.TargetFactory = {
|
|||
return targetPromise;
|
||||
},
|
||||
|
||||
forWorker: function(workerClient) {
|
||||
let target = targets.get(workerClient);
|
||||
forWorker: function(workerTargetFront) {
|
||||
let target = targets.get(workerTargetFront);
|
||||
if (target == null) {
|
||||
target = new WorkerTarget(workerClient);
|
||||
targets.set(workerClient, target);
|
||||
target = new WorkerTarget(workerTargetFront);
|
||||
targets.set(workerTargetFront, target);
|
||||
}
|
||||
return target;
|
||||
},
|
||||
|
@ -848,9 +848,9 @@ TabTarget.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
function WorkerTarget(workerClient) {
|
||||
function WorkerTarget(workerTargetFront) {
|
||||
EventEmitter.decorate(this);
|
||||
this._workerClient = workerClient;
|
||||
this._workerTargetFront = workerTargetFront;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -858,9 +858,9 @@ function WorkerTarget(workerClient) {
|
|||
* either a local or remote tab, WorkerTarget always represents a remote worker.
|
||||
* Moreover, unlike TabTarget, which is constructed with a placeholder object
|
||||
* for remote tabs (from which a TargetFront can then be lazily obtained),
|
||||
* WorkerTarget is constructed with a WorkerClient directly.
|
||||
* WorkerTarget is constructed with a WorkerTargetFront directly.
|
||||
*
|
||||
* WorkerClient is designed to mimic the interface of TargetFront as closely as
|
||||
* WorkerTargetFront is designed to mimic the interface of TargetFront as closely as
|
||||
* possible. This allows us to debug workers as if they were ordinary tabs,
|
||||
* requiring only minimal changes to the rest of the frontend.
|
||||
*/
|
||||
|
@ -878,7 +878,7 @@ WorkerTarget.prototype = {
|
|||
},
|
||||
|
||||
get url() {
|
||||
return this._workerClient.url;
|
||||
return this._workerTargetFront.url;
|
||||
},
|
||||
|
||||
get isWorkerTarget() {
|
||||
|
@ -887,12 +887,12 @@ WorkerTarget.prototype = {
|
|||
|
||||
get form() {
|
||||
return {
|
||||
consoleActor: this._workerClient.consoleActor
|
||||
consoleActor: this._workerTargetFront.consoleActor
|
||||
};
|
||||
},
|
||||
|
||||
get activeTab() {
|
||||
return this._workerClient;
|
||||
return this._workerTargetFront;
|
||||
},
|
||||
|
||||
get activeConsole() {
|
||||
|
@ -900,7 +900,7 @@ WorkerTarget.prototype = {
|
|||
},
|
||||
|
||||
get client() {
|
||||
return this._workerClient.client;
|
||||
return this._workerTargetFront.client;
|
||||
},
|
||||
|
||||
get canRewind() {
|
||||
|
@ -908,7 +908,7 @@ WorkerTarget.prototype = {
|
|||
},
|
||||
|
||||
destroy: function() {
|
||||
this._workerClient.detach();
|
||||
this._workerTargetFront.detach();
|
||||
},
|
||||
|
||||
hasActor: function(name) {
|
||||
|
|
|
@ -28,16 +28,13 @@ const flags = require("devtools/shared/flags");
|
|||
* @return {Object} the highlighterUtils public API
|
||||
*/
|
||||
exports.getHighlighterUtils = function(toolbox) {
|
||||
if (!toolbox || !toolbox.target) {
|
||||
if (!toolbox) {
|
||||
throw new Error("Missing or invalid toolbox passed to getHighlighterUtils");
|
||||
}
|
||||
|
||||
// Exported API properties will go here
|
||||
const exported = {};
|
||||
|
||||
// The current toolbox target
|
||||
let target = toolbox.target;
|
||||
|
||||
// Is the highlighter currently in pick mode
|
||||
let isPicking = false;
|
||||
|
||||
|
@ -49,17 +46,7 @@ exports.getHighlighterUtils = function(toolbox) {
|
|||
* Release this utils, nullifying the references to the toolbox
|
||||
*/
|
||||
exported.release = function() {
|
||||
toolbox = target = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Does the target have the highlighter actor.
|
||||
* The devtools must be backwards compatible with at least B2G 1.3 (28),
|
||||
* which doesn't have the highlighter actor. This can be removed as soon as
|
||||
* the minimal supported version becomes 1.4 (29)
|
||||
*/
|
||||
const isRemoteHighlightable = exported.isRemoteHighlightable = function() {
|
||||
return target.client.traits.highlightable;
|
||||
toolbox = null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -115,22 +102,13 @@ exports.getHighlighterUtils = function(toolbox) {
|
|||
await toolbox.selectTool("inspector", "inspect_dom");
|
||||
toolbox.on("select", cancelPicker);
|
||||
|
||||
if (isRemoteHighlightable()) {
|
||||
toolbox.walker.on("picker-node-hovered", onPickerNodeHovered);
|
||||
toolbox.walker.on("picker-node-picked", onPickerNodePicked);
|
||||
toolbox.walker.on("picker-node-previewed", onPickerNodePreviewed);
|
||||
toolbox.walker.on("picker-node-canceled", onPickerNodeCanceled);
|
||||
toolbox.walker.on("picker-node-hovered", onPickerNodeHovered);
|
||||
toolbox.walker.on("picker-node-picked", onPickerNodePicked);
|
||||
toolbox.walker.on("picker-node-previewed", onPickerNodePreviewed);
|
||||
toolbox.walker.on("picker-node-canceled", onPickerNodeCanceled);
|
||||
|
||||
await toolbox.highlighter.pick(doFocus);
|
||||
toolbox.emit("picker-started");
|
||||
} else {
|
||||
// If the target doesn't have the highlighter actor, we can use the
|
||||
// walker's pick method instead, knowing that it only responds when a node
|
||||
// is picked (instead of emitting events)
|
||||
toolbox.emit("picker-started");
|
||||
const node = await toolbox.walker.pick();
|
||||
onPickerNodePicked({node: node});
|
||||
}
|
||||
await toolbox.highlighter.pick(doFocus);
|
||||
toolbox.emit("picker-started");
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -147,17 +125,11 @@ exports.getHighlighterUtils = function(toolbox) {
|
|||
|
||||
toolbox.pickerButton.isChecked = false;
|
||||
|
||||
if (isRemoteHighlightable()) {
|
||||
await toolbox.highlighter.cancelPick();
|
||||
toolbox.walker.off("picker-node-hovered", onPickerNodeHovered);
|
||||
toolbox.walker.off("picker-node-picked", onPickerNodePicked);
|
||||
toolbox.walker.off("picker-node-previewed", onPickerNodePreviewed);
|
||||
toolbox.walker.off("picker-node-canceled", onPickerNodeCanceled);
|
||||
} else {
|
||||
// If the target doesn't have the highlighter actor, use the walker's
|
||||
// cancelPick method instead
|
||||
await toolbox.walker.cancelPick();
|
||||
}
|
||||
await toolbox.highlighter.cancelPick();
|
||||
toolbox.walker.off("picker-node-hovered", onPickerNodeHovered);
|
||||
toolbox.walker.off("picker-node-picked", onPickerNodePicked);
|
||||
toolbox.walker.off("picker-node-previewed", onPickerNodePreviewed);
|
||||
toolbox.walker.off("picker-node-canceled", onPickerNodeCanceled);
|
||||
|
||||
toolbox.off("select", cancelPicker);
|
||||
toolbox.emit("picker-stopped");
|
||||
|
@ -221,13 +193,7 @@ exports.getHighlighterUtils = function(toolbox) {
|
|||
}
|
||||
|
||||
isNodeFrontHighlighted = true;
|
||||
if (isRemoteHighlightable()) {
|
||||
await toolbox.highlighter.showBoxModel(nodeFront, options);
|
||||
} else {
|
||||
// If the target doesn't have the highlighter actor, revert to the
|
||||
// walker's highlight method, which draws a simple outline
|
||||
await toolbox.walker.highlight(nodeFront);
|
||||
}
|
||||
await toolbox.highlighter.showBoxModel(nodeFront, options);
|
||||
|
||||
toolbox.emit("node-highlight", nodeFront);
|
||||
});
|
||||
|
@ -271,10 +237,7 @@ exports.getHighlighterUtils = function(toolbox) {
|
|||
exported.unhighlight = async function(forceHide = false) {
|
||||
forceHide = forceHide || !flags.testing;
|
||||
|
||||
// Note that if isRemoteHighlightable is true, there's no need to hide the
|
||||
// highlighter as the walker uses setTimeout to hide it after some time
|
||||
if (isNodeFrontHighlighted && forceHide && toolbox.highlighter &&
|
||||
isRemoteHighlightable()) {
|
||||
if (isNodeFrontHighlighted && forceHide && toolbox.highlighter) {
|
||||
isNodeFrontHighlighted = false;
|
||||
await toolbox.highlighter.hideBoxModel();
|
||||
}
|
||||
|
|
|
@ -2345,7 +2345,7 @@ Toolbox.prototype = {
|
|||
await this.initInspector();
|
||||
|
||||
// Only enable frame highlighting when the top level document is targeted
|
||||
if (this._supportsFrameHighlight && this.rootFrameSelected) {
|
||||
if (this.rootFrameSelected) {
|
||||
const frameActor = await this.walker.getNodeActorFromWindowID(frameId);
|
||||
this.highlighterUtils.highlightNodeFront(frameActor);
|
||||
}
|
||||
|
@ -2680,18 +2680,11 @@ Toolbox.prototype = {
|
|||
this._selection = new Selection(this._walker);
|
||||
this._selection.on("new-node-front", this._onNewSelectedNodeFront);
|
||||
|
||||
if (this.highlighterUtils.isRemoteHighlightable()) {
|
||||
this.walker.on("highlighter-ready", this._highlighterReady);
|
||||
this.walker.on("highlighter-hide", this._highlighterHidden);
|
||||
this.walker.on("highlighter-ready", this._highlighterReady);
|
||||
this.walker.on("highlighter-hide", this._highlighterHidden);
|
||||
|
||||
const autohide = !flags.testing;
|
||||
this._highlighter = await this._inspector.getHighlighter(autohide);
|
||||
}
|
||||
if (!("_supportsFrameHighlight" in this)) {
|
||||
// Only works with FF58+ targets
|
||||
this._supportsFrameHighlight =
|
||||
await this.target.actorHasMethod("domwalker", "getNodeActorFromWindowID");
|
||||
}
|
||||
const autohide = !flags.testing;
|
||||
this._highlighter = await this._inspector.getHighlighter(autohide);
|
||||
}.bind(this))();
|
||||
}
|
||||
return this._initInspector;
|
||||
|
@ -2769,14 +2762,6 @@ Toolbox.prototype = {
|
|||
this._inspector.destroy();
|
||||
|
||||
if (this._highlighter) {
|
||||
// Note that if the toolbox is closed, this will work fine, but will fail
|
||||
// in case the browser is closed and will trigger a noSuchActor message.
|
||||
// We ignore the promise that |_hideBoxModel| returns, since we should still
|
||||
// proceed with the rest of destruction if it fails.
|
||||
// FF42+ now does the cleanup from the actor.
|
||||
if (!this.highlighter.traits.autoHideOnDestroy) {
|
||||
this.highlighterUtils.unhighlight();
|
||||
}
|
||||
await this._highlighter.destroy();
|
||||
}
|
||||
if (this._selection) {
|
||||
|
|
|
@ -4,6 +4,7 @@ subsuite = devtools
|
|||
support-files =
|
||||
doc_flexbox_simple.html
|
||||
doc_flexbox_pseudos.html
|
||||
doc_flexbox_text_nodes.html
|
||||
head.js
|
||||
!/devtools/client/inspector/test/head.js
|
||||
!/devtools/client/inspector/test/shared-head.js
|
||||
|
@ -20,4 +21,6 @@ support-files =
|
|||
[browser_flexbox_pseudo_elements_are_listed.js]
|
||||
[browser_flexbox_sizing_info_exists.js]
|
||||
[browser_flexbox_sizing_info_for_pseudos.js]
|
||||
[browser_flexbox_sizing_info_for_text_nodes.js]
|
||||
[browser_flexbox_sizing_info_has_correct_sections.js]
|
||||
[browser_flexbox_text_nodes_are_listed.js]
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the flex item sizing UI also appears for text nodes.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_flexbox_text_nodes.html";
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(TEST_URI);
|
||||
const { inspector, flexboxInspector } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
info("Select the first text node in the flex container");
|
||||
const containerNode = await getNodeFront(".container", inspector);
|
||||
const { nodes } = await inspector.walker.children(containerNode);
|
||||
const firstTextNode = nodes[0];
|
||||
|
||||
const onFlexItemSizingRendered = waitForDOM(doc, "ul.flex-item-sizing");
|
||||
const onFlexItemOutlineRendered = waitForDOM(doc, ".flex-outline-container");
|
||||
await selectNode(firstTextNode, inspector);
|
||||
const [flexSizingContainer] = await onFlexItemSizingRendered;
|
||||
const [flexOutlineContainer] = await onFlexItemOutlineRendered;
|
||||
|
||||
ok(flexSizingContainer, "The flex sizing exists in the DOM");
|
||||
ok(flexOutlineContainer, "The flex outline exists in the DOM");
|
||||
|
||||
info("Check that the various sizing sections are displayed");
|
||||
const allSections = [...flexSizingContainer.querySelectorAll(".section")];
|
||||
ok(allSections.length, "Sizing sections are displayed");
|
||||
|
||||
info("Check that the various parts of the outline are displayed");
|
||||
const [basis, final] = [...flexOutlineContainer.querySelectorAll(
|
||||
".flex-outline-basis, .flex-outline-final")];
|
||||
ok(basis && final, "The final and basis parts of the outline exist");
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that text nodes that are flex items do appear in the list of items.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_flexbox_text_nodes.html";
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(TEST_URI);
|
||||
const { inspector, flexboxInspector } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
// Select the flex container in the inspector.
|
||||
const onItemsListRendered = waitForDOM(doc,
|
||||
"#layout-flexbox-container .flex-item-list");
|
||||
await selectNode(".container", inspector);
|
||||
const [flexItemList] = await onItemsListRendered;
|
||||
|
||||
const items = [...flexItemList.querySelectorAll("li")];
|
||||
is(items.length, 3, "There are 3 items displayed in the list");
|
||||
|
||||
is(items[0].textContent, "#text", "The first item is a text node");
|
||||
is(items[2].textContent, "#text", "The third item is a text node");
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.container {
|
||||
width: 400px;
|
||||
display: flex;
|
||||
}
|
||||
.container div {
|
||||
flex-basis: 100px;
|
||||
flex-shrink: 0;
|
||||
background: #f06;
|
||||
align-self: stretch;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
A text node will be wrapped into an anonymous block container
|
||||
<div></div>
|
||||
Here is yet another text node
|
||||
</div>
|
|
@ -268,7 +268,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
|||
[browser_rules_strict-search-filter_02.js]
|
||||
[browser_rules_strict-search-filter_03.js]
|
||||
[browser_rules_style-editor-link.js]
|
||||
skip-if = true # Bug 1309759
|
||||
[browser_rules_url-click-opens-new-tab.js]
|
||||
[browser_rules_urls-clickable.js]
|
||||
[browser_rules_user-agent-styles.js]
|
||||
|
|
|
@ -10,8 +10,7 @@ const STYLESHEET_DATA_URL_CONTENTS = ["#first {",
|
|||
"color: blue",
|
||||
"}"].join("\n");
|
||||
const STYLESHEET_DATA_URL =
|
||||
`data:text/css,${encodeURIComponent(STYLESHEET_DATA_URL_CONTENTS)}`;
|
||||
const STYLESHEET_DECODED_DATA_URL = `data:text/css,${STYLESHEET_DATA_URL_CONTENTS}`;
|
||||
`data:text/css,${encodeURIComponent(STYLESHEET_DATA_URL_CONTENTS)}`;
|
||||
|
||||
const EXTERNAL_STYLESHEET_FILE_NAME = "doc_style_editor_link.css";
|
||||
const EXTERNAL_STYLESHEET_URL = URL_ROOT + EXTERNAL_STYLESHEET_FILE_NAME;
|
||||
|
@ -55,28 +54,13 @@ add_task(async function() {
|
|||
const {toolbox, inspector, view, testActor} = await openRuleView();
|
||||
await selectNode("div", inspector);
|
||||
|
||||
await testInlineStyle(view);
|
||||
testRuleViewLinkLabel(view);
|
||||
await testFirstInlineStyleSheet(view, toolbox, testActor);
|
||||
await testSecondInlineStyleSheet(view, toolbox, testActor);
|
||||
await testExternalStyleSheet(view, toolbox, testActor);
|
||||
await testDisabledStyleEditor(view, toolbox);
|
||||
});
|
||||
|
||||
async function testInlineStyle(view) {
|
||||
info("Testing inline style");
|
||||
|
||||
const onTab = waitForTab();
|
||||
info("Clicking on the first link in the rule-view");
|
||||
clickLinkByIndex(view, 0);
|
||||
|
||||
const tab = await onTab;
|
||||
|
||||
const tabURI = tab.linkedBrowser.documentURI.spec;
|
||||
ok(tabURI.startsWith("view-source:"), "View source tab is open");
|
||||
info("Closing tab");
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
|
||||
async function testFirstInlineStyleSheet(view, toolbox, testActor) {
|
||||
info("Testing inline stylesheet");
|
||||
|
||||
|
@ -103,7 +87,6 @@ async function testSecondInlineStyleSheet(view, toolbox, testActor) {
|
|||
await toolbox.selectTool("inspector");
|
||||
|
||||
info("Clicking on second inline stylesheet link");
|
||||
testRuleViewLinkLabel(view);
|
||||
clickLinkByIndex(view, 3);
|
||||
const editor = await onSelected;
|
||||
|
||||
|
@ -123,7 +106,6 @@ async function testExternalStyleSheet(view, toolbox, testActor) {
|
|||
await toolbox.selectTool("inspector");
|
||||
|
||||
info("Clicking on an external stylesheet link");
|
||||
testRuleViewLinkLabel(view);
|
||||
clickLinkByIndex(view, 1);
|
||||
const editor = await onSelected;
|
||||
|
||||
|
@ -140,8 +122,8 @@ async function validateStyleEditorSheet(editor, expectedSheetIndex, testActor) {
|
|||
const href = editor.styleSheet.href || editor.styleSheet.nodeHref;
|
||||
|
||||
const expectedHref = await testActor.eval(
|
||||
`content.document.styleSheets[${expectedSheetIndex}].href ||
|
||||
content.document.location.href`);
|
||||
`document.styleSheets[${expectedSheetIndex}].href ||
|
||||
document.location.href`);
|
||||
|
||||
is(href, expectedHref, "loaded stylesheet href matches document stylesheet");
|
||||
}
|
||||
|
@ -183,9 +165,9 @@ function testRuleViewLinkLabel(view) {
|
|||
let value = labelElem.textContent;
|
||||
let tooltipText = labelElem.getAttribute("title");
|
||||
|
||||
is(value, `${STYLESHEET_DATA_URL_CONTENTS}:1`,
|
||||
is(value, encodeURIComponent(STYLESHEET_DATA_URL_CONTENTS) + ":1",
|
||||
"Rule view data URL stylesheet display value matches contents");
|
||||
is(tooltipText, `${STYLESHEET_DECODED_DATA_URL}:1`,
|
||||
is(tooltipText, STYLESHEET_DATA_URL + ":1",
|
||||
"Rule view data URL stylesheet tooltip text matches the full URI path");
|
||||
|
||||
info("Checking the external link label");
|
||||
|
|
|
@ -283,7 +283,12 @@ RuleEditor.prototype = {
|
|||
if (Tools.styleEditor.isTargetSupported(target)) {
|
||||
gDevTools.showToolbox(target, "styleeditor").then(toolbox => {
|
||||
const {url, line, column} = this._currentLocation;
|
||||
toolbox.getCurrentPanel().selectStyleSheet(url, line, column);
|
||||
|
||||
if (!this.rule.sheet.href && this.rule.sheet.nodeHref) {
|
||||
toolbox.getCurrentPanel().selectStyleSheet(this.rule.sheet, line, column);
|
||||
} else {
|
||||
toolbox.getCurrentPanel().selectStyleSheet(url, line, column);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -44,32 +44,32 @@ function test() {
|
|||
// createWorker in the tab to be resolved.
|
||||
yield createWorkerInTab(tab, WORKER1_URL);
|
||||
let { workers } = yield listWorkers(targetFront);
|
||||
let [, workerClient1] = yield attachWorker(targetFront,
|
||||
let [, workerTargetFront1] = yield attachWorker(targetFront,
|
||||
findWorker(workers, WORKER1_URL));
|
||||
is(workerClient1.isClosed, false, "worker in tab 1 should not be closed");
|
||||
is(workerTargetFront1.isClosed, false, "worker in tab 1 should not be closed");
|
||||
|
||||
executeSoon(() => {
|
||||
BrowserTestUtils.loadURI(tab.linkedBrowser, TAB2_URL);
|
||||
});
|
||||
yield waitForWorkerClose(workerClient1);
|
||||
is(workerClient1.isClosed, true, "worker in tab 1 should be closed");
|
||||
yield waitForWorkerClose(workerTargetFront1);
|
||||
is(workerTargetFront1.isClosed, true, "worker in tab 1 should be closed");
|
||||
|
||||
yield createWorkerInTab(tab, WORKER2_URL);
|
||||
({ workers } = yield listWorkers(targetFront));
|
||||
const [, workerClient2] = yield attachWorker(targetFront,
|
||||
const [, workerTargetFront2] = yield attachWorker(targetFront,
|
||||
findWorker(workers, WORKER2_URL));
|
||||
is(workerClient2.isClosed, false, "worker in tab 2 should not be closed");
|
||||
is(workerTargetFront2.isClosed, false, "worker in tab 2 should not be closed");
|
||||
|
||||
executeSoon(() => {
|
||||
tab.linkedBrowser.goBack();
|
||||
});
|
||||
yield waitForWorkerClose(workerClient2);
|
||||
is(workerClient2.isClosed, true, "worker in tab 2 should be closed");
|
||||
yield waitForWorkerClose(workerTargetFront2);
|
||||
is(workerTargetFront2.isClosed, true, "worker in tab 2 should be closed");
|
||||
|
||||
({ workers } = yield listWorkers(targetFront));
|
||||
[, workerClient1] = yield attachWorker(targetFront,
|
||||
[, workerTargetFront1] = yield attachWorker(targetFront,
|
||||
findWorker(workers, WORKER1_URL));
|
||||
is(workerClient1.isClosed, false, "worker in tab 1 should not be closed");
|
||||
is(workerTargetFront1.isClosed, false, "worker in tab 1 should not be closed");
|
||||
|
||||
yield close(client);
|
||||
SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, oldMaxTotalViewers);
|
||||
|
|
|
@ -18,7 +18,7 @@ var TAB_URL = EXAMPLE_URL + "doc_WorkerTargetActor.attachThread-tab.html";
|
|||
var WORKER_URL = "code_WorkerTargetActor.attachThread-worker.js";
|
||||
|
||||
add_task(async function testNormalExecution() {
|
||||
const {client, tab, workerClient, toolbox} =
|
||||
const {client, tab, workerTargetFront, toolbox} =
|
||||
await initWorkerDebugger(TAB_URL, WORKER_URL);
|
||||
|
||||
const jsterm = await getSplitConsole(toolbox);
|
||||
|
@ -27,8 +27,8 @@ add_task(async function testNormalExecution() {
|
|||
"Evaluating the global's location works");
|
||||
|
||||
terminateWorkerInTab(tab, WORKER_URL);
|
||||
await waitForWorkerClose(workerClient);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
|
||||
await waitForWorkerClose(workerTargetFront);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
|
||||
await close(client);
|
||||
await removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ var WORKER_URL = "code_WorkerTargetActor.attachThread-worker.js";
|
|||
|
||||
add_task(async function testWhilePaused() {
|
||||
const dbg = await initWorkerDebugger(TAB_URL, WORKER_URL);
|
||||
const {client, tab, workerClient, toolbox} = dbg;
|
||||
const {client, tab, workerTargetFront, toolbox} = dbg;
|
||||
|
||||
// Execute some basic math to make sure evaluations are working.
|
||||
const jsterm = await getSplitConsole(toolbox);
|
||||
|
@ -55,8 +55,8 @@ add_task(async function testWhilePaused() {
|
|||
await resume(dbg);
|
||||
|
||||
terminateWorkerInTab(tab, WORKER_URL);
|
||||
await waitForWorkerClose(workerClient);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
|
||||
await waitForWorkerClose(workerTargetFront);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
|
||||
await close(client);
|
||||
await removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ var WORKER_URL = "code_WorkerTargetActor.attachThread-worker.js";
|
|||
// Test to see if creating the pause from the console works.
|
||||
add_task(async function testPausedByConsole() {
|
||||
const dbg = await initWorkerDebugger(TAB_URL, WORKER_URL);
|
||||
const {client, tab, workerClient, toolbox} = dbg;
|
||||
const {client, tab, workerTargetFront, toolbox} = dbg;
|
||||
|
||||
const jsterm = await getSplitConsole(toolbox);
|
||||
let executed = await jsterm.execute("10000+1");
|
||||
|
@ -46,8 +46,8 @@ add_task(async function testPausedByConsole() {
|
|||
"Text for message appeared correct");
|
||||
|
||||
terminateWorkerInTab(tab, WORKER_URL);
|
||||
await waitForWorkerClose(workerClient);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
|
||||
await waitForWorkerClose(workerTargetFront);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
|
||||
await close(client);
|
||||
await removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ const TAB_URL = EXAMPLE_URL + "doc_WorkerTargetActor.attachThread-tab.html";
|
|||
const WORKER_URL = "code_WorkerTargetActor.attachThread-worker.js";
|
||||
|
||||
add_task(async function testPausedByConsole() {
|
||||
const {client, tab, workerClient, toolbox} =
|
||||
const {client, tab, workerTargetFront, toolbox} =
|
||||
await initWorkerDebugger(TAB_URL, WORKER_URL);
|
||||
|
||||
info("Check Date objects can be used in the console");
|
||||
|
@ -42,8 +42,8 @@ add_task(async function testPausedByConsole() {
|
|||
"Text for message appeared correct");
|
||||
|
||||
terminateWorkerInTab(tab, WORKER_URL);
|
||||
await waitForWorkerClose(workerClient);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
|
||||
await waitForWorkerClose(workerTargetFront);
|
||||
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
|
||||
await close(client);
|
||||
await removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -118,14 +118,14 @@ function attachWorker(targetFront, worker) {
|
|||
return targetFront.attachWorker(worker.actor);
|
||||
}
|
||||
|
||||
function attachThread(workerClient, options) {
|
||||
function attachThread(workerTargetFront, options) {
|
||||
info("Attaching to thread.");
|
||||
return workerClient.attachThread(options);
|
||||
return workerTargetFront.attachThread(options);
|
||||
}
|
||||
|
||||
async function waitForWorkerClose(workerClient) {
|
||||
async function waitForWorkerClose(workerTargetFront) {
|
||||
info("Waiting for worker to close.");
|
||||
await workerClient.once("close");
|
||||
await workerTargetFront.once("close");
|
||||
info("Worker did close.");
|
||||
}
|
||||
|
||||
|
@ -164,10 +164,10 @@ async function initWorkerDebugger(TAB_URL, WORKER_URL) {
|
|||
await createWorkerInTab(tab, WORKER_URL);
|
||||
|
||||
const { workers } = await listWorkers(targetFront);
|
||||
const [, workerClient] = await attachWorker(targetFront,
|
||||
const [, workerTargetFront] = await attachWorker(targetFront,
|
||||
findWorker(workers, WORKER_URL));
|
||||
|
||||
const toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
const toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerTargetFront),
|
||||
"jsdebugger",
|
||||
Toolbox.HostType.WINDOW);
|
||||
|
||||
|
@ -177,7 +177,7 @@ async function initWorkerDebugger(TAB_URL, WORKER_URL) {
|
|||
|
||||
const context = createDebuggerContext(toolbox);
|
||||
|
||||
return { ...context, client, tab, targetFront, workerClient, toolbox, gDebugger};
|
||||
return { ...context, client, tab, targetFront, workerTargetFront, toolbox, gDebugger};
|
||||
}
|
||||
|
||||
// Override addTab/removeTab as defined by shared-head, since these have
|
||||
|
|
|
@ -113,9 +113,6 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
|||
form: function() {
|
||||
return {
|
||||
actor: this.actorID,
|
||||
traits: {
|
||||
autoHideOnDestroy: true
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -315,23 +315,29 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
|
|||
let currentNode = treeWalker.currentNode;
|
||||
let displayType = this.walker.getNode(currentNode).displayType;
|
||||
|
||||
if (!displayType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type == "flex") {
|
||||
if (displayType == "inline-flex" || displayType == "flex") {
|
||||
return new FlexboxActor(this, currentNode);
|
||||
} else if (onlyLookAtCurrentNode) {
|
||||
// If the node is an element, check first if it is itself a flex or a grid.
|
||||
if (currentNode.nodeType === currentNode.ELEMENT_NODE) {
|
||||
if (!displayType) {
|
||||
return null;
|
||||
}
|
||||
} else if (type == "grid" &&
|
||||
(displayType == "inline-grid" || displayType == "grid")) {
|
||||
return new GridActor(this, currentNode);
|
||||
|
||||
if (type == "flex") {
|
||||
if (displayType == "inline-flex" || displayType == "flex") {
|
||||
return new FlexboxActor(this, currentNode);
|
||||
} else if (onlyLookAtCurrentNode) {
|
||||
return null;
|
||||
}
|
||||
} else if (type == "grid" &&
|
||||
(displayType == "inline-grid" || displayType == "grid")) {
|
||||
return new GridActor(this, currentNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, check if this is a flex/grid item or the parent node is a flex/grid
|
||||
// container.
|
||||
// Note that text nodes that are children of flex/grid containers are wrapped in
|
||||
// anonymous containers, so even if their displayType getter returns null we still
|
||||
// want to walk up the chain to find their container.
|
||||
while ((currentNode = treeWalker.parentNode())) {
|
||||
if (!currentNode) {
|
||||
break;
|
||||
|
|
|
@ -116,9 +116,6 @@ RootActor.prototype = {
|
|||
|
||||
traits: {
|
||||
sources: true,
|
||||
// Whether the server-side highlighter actor exists and can be used to
|
||||
// remotely highlight nodes (see server/actors/highlighters.js)
|
||||
highlightable: true,
|
||||
networkMonitor: true,
|
||||
// Whether the storage inspector actor to inspect cookies, etc.
|
||||
storageInspector: true,
|
||||
|
|
|
@ -96,7 +96,6 @@ AddonTargetActor.prototype = {
|
|||
consoleActor: this._consoleActor.actorID,
|
||||
|
||||
traits: {
|
||||
highlightable: false,
|
||||
networkMonitor: false,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -119,7 +119,6 @@ ContentProcessTargetActor.prototype = {
|
|||
promisesActor: this._promisesActor.actorID,
|
||||
|
||||
traits: {
|
||||
highlightable: false,
|
||||
networkMonitor: false,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ const noop = () => {};
|
|||
* is a front to the thread actor created in the server side, hiding the
|
||||
* protocol details in a traditional JavaScript API.
|
||||
*
|
||||
* @param client DebuggerClient, WorkerClient or BrowsingContextFront
|
||||
* @param client DebuggerClient, WorkerTargetFront or BrowsingContextFront
|
||||
* The parent of the thread (tab for target-scoped debuggers,
|
||||
* DebuggerClient for chrome debuggers).
|
||||
* @param actor string
|
||||
|
|
|
@ -1604,7 +1604,13 @@ var FrontClassWithSpec = function(actorSpec, frontProto) {
|
|||
// Existing Fronts are relying on the initialize instead of constructor methods.
|
||||
const cls = function() {
|
||||
const instance = Object.create(cls.prototype);
|
||||
instance.initialize.apply(instance, arguments);
|
||||
const initializer = instance.initialize.apply(instance, arguments);
|
||||
|
||||
// Async Initialization
|
||||
// return a promise that resolves with the instance if the initializer is async
|
||||
if (initializer && typeof initializer.then === "function") {
|
||||
return initializer.then(resolve => instance);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
cls.prototype = extend(Front.prototype, generateRequestMethods(actorSpec, frontProto));
|
||||
|
|
|
@ -111,16 +111,16 @@ var _attachConsole = async function(
|
|||
"worker actor\n");
|
||||
return;
|
||||
}
|
||||
const [workerResponse, workerClient] =
|
||||
const [workerResponse, workerTargetFront] =
|
||||
await targetFront.attachWorker(workerTargetActor);
|
||||
if (!workerClient || workerResponse.error) {
|
||||
console.error("attachWorker failed. No worker client or " +
|
||||
if (!workerTargetFront || workerResponse.error) {
|
||||
console.error("attachWorker failed. No worker target front or " +
|
||||
" error: " + workerResponse.error);
|
||||
return;
|
||||
}
|
||||
await workerClient.attachThread({});
|
||||
state.actor = workerClient.consoleActor;
|
||||
state.dbgClient.attachConsole(workerClient.consoleActor, listeners)
|
||||
await workerTargetFront.attachThread({});
|
||||
state.actor = workerTargetFront.consoleActor;
|
||||
state.dbgClient.attachConsole(workerTargetFront.consoleActor, listeners)
|
||||
.then(_onAttachConsole.bind(null, state), _onAttachError.bind(null, state));
|
||||
} else {
|
||||
state.actor = tab.consoleActor;
|
||||
|
|
|
@ -9,10 +9,33 @@
|
|||
* dev tools.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A flex container's main and cross axes are either horizontal or
|
||||
* vertical, each with two possible directions.
|
||||
*/
|
||||
enum FlexPhysicalDirection {
|
||||
"horizontal-lr",
|
||||
"horizontal-rl",
|
||||
"vertical-tb",
|
||||
"vertical-bt",
|
||||
};
|
||||
|
||||
[ChromeOnly]
|
||||
interface Flex
|
||||
{
|
||||
sequence<FlexLine> getLines();
|
||||
sequence<FlexLineValues> getLines();
|
||||
|
||||
/**
|
||||
* The physical direction in which successive flex items are placed,
|
||||
* within a flex line in this flex container.
|
||||
*/
|
||||
readonly attribute FlexPhysicalDirection mainAxisDirection;
|
||||
|
||||
/**
|
||||
* The physical direction in which successive flex lines are placed
|
||||
* in this flex container (if it is or were multi-line).
|
||||
*/
|
||||
readonly attribute FlexPhysicalDirection crossAxisDirection;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -22,7 +45,7 @@ interface Flex
|
|||
enum FlexLineGrowthState { "unchanged", "shrinking", "growing" };
|
||||
|
||||
[ChromeOnly]
|
||||
interface FlexLine
|
||||
interface FlexLineValues
|
||||
{
|
||||
readonly attribute FlexLineGrowthState growthState;
|
||||
readonly attribute double crossStart;
|
||||
|
@ -35,14 +58,14 @@ interface FlexLine
|
|||
readonly attribute double lastBaselineOffset;
|
||||
|
||||
/**
|
||||
* getItems() returns FlexItems only for the Elements in this Flex
|
||||
* container -- ignoring struts and abs-pos Elements.
|
||||
* getItems() returns FlexItemValues only for the Elements in
|
||||
* this Flex container -- ignoring struts and abs-pos Elements.
|
||||
*/
|
||||
sequence<FlexItem> getItems();
|
||||
sequence<FlexItemValues> getItems();
|
||||
};
|
||||
|
||||
[ChromeOnly]
|
||||
interface FlexItem
|
||||
interface FlexItemValues
|
||||
{
|
||||
readonly attribute Node? node;
|
||||
readonly attribute double mainBaseSize;
|
|
@ -10,6 +10,9 @@ with Files("**"):
|
|||
with Files("ChannelWrapper.webidl"):
|
||||
BUG_COMPONENT = ("WebExtensions", "Request Handling")
|
||||
|
||||
with Files("Flex.webidl"):
|
||||
BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
|
||||
|
||||
with Files("HeapSnapshot.webidl"):
|
||||
BUG_COMPONENT = ("DevTools", "Memory")
|
||||
|
||||
|
@ -33,6 +36,7 @@ WEBIDL_FILES = [
|
|||
'BrowsingContext.webidl',
|
||||
'ChannelWrapper.webidl',
|
||||
'DominatorTree.webidl',
|
||||
'Flex.webidl',
|
||||
'HeapSnapshot.webidl',
|
||||
'InspectorUtils.webidl',
|
||||
'IteratorResult.webidl',
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "Flex.h"
|
||||
|
||||
#include "FlexLine.h"
|
||||
#include "FlexLineValues.h"
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
|
||||
|
@ -37,10 +37,13 @@ Flex::Flex(Element* aParent,
|
|||
mLines.SetLength(containerInfo->mLines.Length());
|
||||
uint32_t index = 0;
|
||||
for (auto&& l : containerInfo->mLines) {
|
||||
FlexLine* line = new FlexLine(this, &l);
|
||||
FlexLineValues* line = new FlexLineValues(this, &l);
|
||||
mLines.ElementAt(index) = line;
|
||||
index++;
|
||||
}
|
||||
|
||||
mMainAxisDirection = containerInfo->mMainAxisDirection;
|
||||
mCrossAxisDirection = containerInfo->mCrossAxisDirection;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -50,10 +53,22 @@ Flex::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
}
|
||||
|
||||
void
|
||||
Flex::GetLines(nsTArray<RefPtr<FlexLine>>& aResult)
|
||||
Flex::GetLines(nsTArray<RefPtr<FlexLineValues>>& aResult)
|
||||
{
|
||||
aResult.AppendElements(mLines);
|
||||
}
|
||||
|
||||
FlexPhysicalDirection
|
||||
Flex::MainAxisDirection() const
|
||||
{
|
||||
return mMainAxisDirection;
|
||||
}
|
||||
|
||||
FlexPhysicalDirection
|
||||
Flex::CrossAxisDirection() const
|
||||
{
|
||||
return mCrossAxisDirection;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_dom_Flex_h
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
|
@ -16,7 +17,7 @@ class nsFlexContainerFrame;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FlexLine;
|
||||
class FlexLineValues;
|
||||
|
||||
class Flex : public nsISupports
|
||||
, public nsWrapperCache
|
||||
|
@ -37,11 +38,15 @@ public:
|
|||
return mParent;
|
||||
}
|
||||
|
||||
void GetLines(nsTArray<RefPtr<FlexLine>>& aResult);
|
||||
void GetLines(nsTArray<RefPtr<FlexLineValues>>& aResult);
|
||||
FlexPhysicalDirection MainAxisDirection() const;
|
||||
FlexPhysicalDirection CrossAxisDirection() const;
|
||||
|
||||
protected:
|
||||
nsCOMPtr<Element> mParent;
|
||||
nsTArray<RefPtr<FlexLine>> mLines;
|
||||
nsTArray<RefPtr<FlexLineValues>> mLines;
|
||||
FlexPhysicalDirection mMainAxisDirection;
|
||||
FlexPhysicalDirection mCrossAxisDirection;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FlexItem.h"
|
||||
#include "FlexItemValues.h"
|
||||
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
|
@ -12,10 +12,10 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexItem, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexItem)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexItem)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexItem)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexItemValues, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexItemValues)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexItemValues)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexItemValues)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -38,8 +38,8 @@ ToPossiblyUnconstrainedPixels(nscoord aSize)
|
|||
return nsPresContext::AppUnitsToDoubleCSSPixels(aSize);
|
||||
}
|
||||
|
||||
FlexItem::FlexItem(FlexLine* aParent,
|
||||
const ComputedFlexItemInfo* aItem)
|
||||
FlexItemValues::FlexItemValues(FlexLineValues* aParent,
|
||||
const ComputedFlexItemInfo* aItem)
|
||||
: mParent(aParent)
|
||||
{
|
||||
MOZ_ASSERT(aItem,
|
||||
|
@ -63,49 +63,49 @@ FlexItem::FlexItem(FlexLine* aParent,
|
|||
}
|
||||
|
||||
JSObject*
|
||||
FlexItem::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
FlexItemValues::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return FlexItem_Binding::Wrap(aCx, this, aGivenProto);
|
||||
return FlexItemValues_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsINode*
|
||||
FlexItem::GetNode() const
|
||||
FlexItemValues::GetNode() const
|
||||
{
|
||||
return mNode;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainBaseSize() const
|
||||
FlexItemValues::MainBaseSize() const
|
||||
{
|
||||
return mMainBaseSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainDeltaSize() const
|
||||
FlexItemValues::MainDeltaSize() const
|
||||
{
|
||||
return mMainDeltaSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainMinSize() const
|
||||
FlexItemValues::MainMinSize() const
|
||||
{
|
||||
return mMainMinSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainMaxSize() const
|
||||
FlexItemValues::MainMaxSize() const
|
||||
{
|
||||
return mMainMaxSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::CrossMinSize() const
|
||||
FlexItemValues::CrossMinSize() const
|
||||
{
|
||||
return mCrossMinSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::CrossMaxSize() const
|
||||
FlexItemValues::CrossMaxSize() const
|
||||
{
|
||||
return mCrossMaxSize;
|
||||
}
|
|
@ -4,8 +4,8 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_FlexItem_h
|
||||
#define mozilla_dom_FlexItem_h
|
||||
#ifndef mozilla_dom_FlexItemValues_h
|
||||
#define mozilla_dom_FlexItemValues_h
|
||||
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsISupports.h"
|
||||
|
@ -16,24 +16,24 @@ struct ComputedFlexItemInfo;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FlexLine;
|
||||
class FlexLineValues;
|
||||
|
||||
class FlexItem : public nsISupports
|
||||
, public nsWrapperCache
|
||||
class FlexItemValues : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit FlexItem(FlexLine* aParent,
|
||||
const ComputedFlexItemInfo* aItem);
|
||||
explicit FlexItemValues(FlexLineValues* aParent,
|
||||
const ComputedFlexItemInfo* aItem);
|
||||
|
||||
protected:
|
||||
virtual ~FlexItem() = default;
|
||||
virtual ~FlexItemValues() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FlexItem)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FlexItemValues)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
FlexLine* GetParentObject()
|
||||
FlexLineValues* GetParentObject()
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
double CrossMaxSize() const;
|
||||
|
||||
protected:
|
||||
RefPtr<FlexLine> mParent;
|
||||
RefPtr<FlexLineValues> mParent;
|
||||
RefPtr<nsINode> mNode;
|
||||
|
||||
// These sizes are all CSS pixel units.
|
||||
|
@ -62,4 +62,4 @@ protected:
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_FlexItem_h */
|
||||
#endif /* mozilla_dom_FlexItemValues_h */
|
|
@ -4,25 +4,25 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FlexLine.h"
|
||||
#include "FlexLineValues.h"
|
||||
|
||||
#include "FlexItem.h"
|
||||
#include "FlexItemValues.h"
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexLine, mParent, mItems)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexLine)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexLine)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexLine)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexLineValues, mParent, mItems)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexLineValues)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexLineValues)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexLineValues)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
FlexLine::FlexLine(Flex* aParent,
|
||||
const ComputedFlexLineInfo* aLine)
|
||||
FlexLineValues::FlexLineValues(Flex* aParent,
|
||||
const ComputedFlexLineInfo* aLine)
|
||||
: mParent(aParent)
|
||||
{
|
||||
MOZ_ASSERT(aLine,
|
||||
|
@ -56,50 +56,50 @@ FlexLine::FlexLine(Flex* aParent,
|
|||
mItems.SetLength(aLine->mItems.Length());
|
||||
uint32_t index = 0;
|
||||
for (auto&& i : aLine->mItems) {
|
||||
FlexItem* item = new FlexItem(this, &i);
|
||||
FlexItemValues* item = new FlexItemValues(this, &i);
|
||||
mItems.ElementAt(index) = item;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
FlexLine::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
FlexLineValues::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return FlexLine_Binding::Wrap(aCx, this, aGivenProto);
|
||||
return FlexLineValues_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
FlexLineGrowthState
|
||||
FlexLine::GrowthState() const
|
||||
FlexLineValues::GrowthState() const
|
||||
{
|
||||
return mGrowthState;
|
||||
}
|
||||
|
||||
double
|
||||
FlexLine::CrossStart() const
|
||||
FlexLineValues::CrossStart() const
|
||||
{
|
||||
return mCrossStart;
|
||||
}
|
||||
|
||||
double
|
||||
FlexLine::CrossSize() const
|
||||
FlexLineValues::CrossSize() const
|
||||
{
|
||||
return mCrossSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexLine::FirstBaselineOffset() const
|
||||
FlexLineValues::FirstBaselineOffset() const
|
||||
{
|
||||
return mFirstBaselineOffset;
|
||||
}
|
||||
|
||||
double
|
||||
FlexLine::LastBaselineOffset() const
|
||||
FlexLineValues::LastBaselineOffset() const
|
||||
{
|
||||
return mLastBaselineOffset;
|
||||
}
|
||||
|
||||
void
|
||||
FlexLine::GetItems(nsTArray<RefPtr<FlexItem>>& aResult)
|
||||
FlexLineValues::GetItems(nsTArray<RefPtr<FlexItemValues>>& aResult)
|
||||
{
|
||||
aResult.AppendElements(mItems);
|
||||
}
|
|
@ -4,8 +4,8 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_FlexLine_h
|
||||
#define mozilla_dom_FlexLine_h
|
||||
#ifndef mozilla_dom_FlexLineValues_h
|
||||
#define mozilla_dom_FlexLineValues_h
|
||||
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsISupports.h"
|
||||
|
@ -17,21 +17,21 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class Flex;
|
||||
class FlexItem;
|
||||
class FlexItemValues;
|
||||
|
||||
class FlexLine : public nsISupports
|
||||
, public nsWrapperCache
|
||||
class FlexLineValues : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit FlexLine(Flex* aParent,
|
||||
const ComputedFlexLineInfo* aLine);
|
||||
explicit FlexLineValues(Flex* aParent,
|
||||
const ComputedFlexLineInfo* aLine);
|
||||
|
||||
protected:
|
||||
virtual ~FlexLine() = default;
|
||||
virtual ~FlexLineValues() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FlexLine)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FlexLineValues)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
Flex* GetParentObject()
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
double FirstBaselineOffset() const;
|
||||
double LastBaselineOffset() const;
|
||||
|
||||
void GetItems(nsTArray<RefPtr<FlexItem>>& aResult);
|
||||
void GetItems(nsTArray<RefPtr<FlexItemValues>>& aResult);
|
||||
|
||||
protected:
|
||||
RefPtr<Flex> mParent;
|
||||
|
@ -56,10 +56,10 @@ protected:
|
|||
double mFirstBaselineOffset;
|
||||
double mLastBaselineOffset;
|
||||
|
||||
nsTArray<RefPtr<FlexItem>> mItems;
|
||||
nsTArray<RefPtr<FlexItemValues>> mItems;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_FlexLine_h */
|
||||
#endif /* mozilla_dom_FlexLineValues_h */
|
|
@ -11,14 +11,14 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
|||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Flex.h',
|
||||
'FlexItem.h',
|
||||
'FlexLine.h',
|
||||
'FlexItemValues.h',
|
||||
'FlexLineValues.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Flex.cpp',
|
||||
'FlexItem.cpp',
|
||||
'FlexLine.cpp',
|
||||
'FlexItemValues.cpp',
|
||||
'FlexLineValues.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
[chrome/test_flex_axis_directions.html]
|
||||
[chrome/test_flex_items.html]
|
||||
[chrome/test_flex_lines.html]
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
f {
|
||||
display: flex;
|
||||
width: 400px;
|
||||
height: 50px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
b {
|
||||
background-color: gold;
|
||||
width: 100px;
|
||||
height: 15px;
|
||||
}
|
||||
b::after {
|
||||
content: "B";
|
||||
}
|
||||
|
||||
c {
|
||||
background-color: yellow;
|
||||
width: 100px;
|
||||
height: 15px;
|
||||
}
|
||||
c::after {
|
||||
content: "C";
|
||||
}
|
||||
|
||||
d {
|
||||
background-color: orange;
|
||||
width: 100px;
|
||||
height: 15px;
|
||||
}
|
||||
d::after {
|
||||
content: "D";
|
||||
}
|
||||
|
||||
.fdR {
|
||||
flex-direction: row;
|
||||
background-color: lightgrey;
|
||||
}
|
||||
.fdRR {
|
||||
flex-direction: row-reverse;
|
||||
background-color: lightgreen;
|
||||
}
|
||||
.fdC {
|
||||
flex-direction: column;
|
||||
background-color: lightblue;
|
||||
}
|
||||
.fdCR {
|
||||
flex-direction: column-reverse;
|
||||
background-color: lavender;
|
||||
}
|
||||
|
||||
.wmHTB {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.wmVLR {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.wmVRL {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.wmSLR {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
.wmSRL {
|
||||
writing-mode: sideways-rl;
|
||||
}
|
||||
|
||||
.dLR {
|
||||
direction: ltr;
|
||||
}
|
||||
.dRL {
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function testContainerMatchesExpectedValues(flex, values, flexIndex) {
|
||||
is(flex.mainAxisDirection, values.m, "Flex index " + flexIndex + " should have expected mainAxisDirection.");
|
||||
is(flex.crossAxisDirection, values.c, "Flex index " + flexIndex + " should have expected crossAxisDirection.");
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
const expectedValues = [
|
||||
{ m: "horizontal-lr", c: "vertical-tb" },
|
||||
{ m: "horizontal-rl", c: "vertical-tb" },
|
||||
{ m: "vertical-tb", c: "horizontal-lr" },
|
||||
{ m: "vertical-bt", c: "horizontal-lr" },
|
||||
{ m: "vertical-tb", c: "horizontal-rl" },
|
||||
{ m: "vertical-bt", c: "horizontal-rl" },
|
||||
{ m: "vertical-bt", c: "horizontal-lr" },
|
||||
{ m: "vertical-tb", c: "horizontal-lr" },
|
||||
{ m: "vertical-tb", c: "horizontal-rl" },
|
||||
{ m: "vertical-bt", c: "horizontal-rl" },
|
||||
|
||||
{ m: "horizontal-rl", c: "vertical-tb" },
|
||||
{ m: "horizontal-lr", c: "vertical-tb" },
|
||||
{ m: "vertical-bt", c: "horizontal-lr" },
|
||||
{ m: "vertical-tb", c: "horizontal-lr" },
|
||||
{ m: "vertical-bt", c: "horizontal-rl" },
|
||||
{ m: "vertical-tb", c: "horizontal-rl" },
|
||||
{ m: "vertical-tb", c: "horizontal-lr" },
|
||||
{ m: "vertical-bt", c: "horizontal-lr" },
|
||||
{ m: "vertical-bt", c: "horizontal-rl" },
|
||||
{ m: "vertical-tb", c: "horizontal-rl" },
|
||||
|
||||
{ m: "vertical-tb", c: "horizontal-lr" },
|
||||
{ m: "vertical-tb", c: "horizontal-rl" },
|
||||
{ m: "horizontal-lr", c: "vertical-tb" },
|
||||
{ m: "horizontal-lr", c: "vertical-bt" },
|
||||
{ m: "horizontal-rl", c: "vertical-tb" },
|
||||
{ m: "horizontal-rl", c: "vertical-bt" },
|
||||
{ m: "horizontal-lr", c: "vertical-bt" },
|
||||
{ m: "horizontal-lr", c: "vertical-tb" },
|
||||
{ m: "horizontal-rl", c: "vertical-tb" },
|
||||
{ m: "horizontal-rl", c: "vertical-bt" },
|
||||
|
||||
{ m: "vertical-bt", c: "horizontal-lr" },
|
||||
{ m: "vertical-bt", c: "horizontal-rl" },
|
||||
{ m: "horizontal-rl", c: "vertical-tb" },
|
||||
{ m: "horizontal-rl", c: "vertical-bt" },
|
||||
{ m: "horizontal-lr", c: "vertical-tb" },
|
||||
{ m: "horizontal-lr", c: "vertical-bt" },
|
||||
{ m: "horizontal-rl", c: "vertical-bt" },
|
||||
{ m: "horizontal-rl", c: "vertical-tb" },
|
||||
{ m: "horizontal-lr", c: "vertical-tb" },
|
||||
{ m: "horizontal-lr", c: "vertical-bt" },
|
||||
];
|
||||
|
||||
const children = document.body.children;
|
||||
is(children.length, expectedValues.length, "Document should have expected number of flex containers.");
|
||||
|
||||
for (let i = 0; i < children.length; ++i) {
|
||||
const flex = children.item(i).getAsFlexContainer();
|
||||
ok(flex, "Document child index " + i + " should be a flex container.");
|
||||
if (flex) {
|
||||
const values = expectedValues[i];
|
||||
testContainerMatchesExpectedValues(flex, values, i);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onLoad="runTests();">
|
||||
|
||||
<f class="fdR wmHTB dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmHTB dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmVLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmVLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmVRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmVRL dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmSLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmSLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmSRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdR wmSRL dRL"><b></b><c></c><d></d></f>
|
||||
|
||||
<f class="fdRR wmHTB dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmHTB dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmVLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmVLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmVRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmVRL dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmSLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmSLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmSRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdRR wmSRL dRL"><b></b><c></c><d></d></f>
|
||||
|
||||
<f class="fdC wmHTB dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmHTB dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmVLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmVLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmVRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmVRL dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmSLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmSLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmSRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdC wmSRL dRL"><b></b><c></c><d></d></f>
|
||||
|
||||
<f class="fdCR wmHTB dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmHTB dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmVLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmVLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmVRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmVRL dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmSLR dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmSLR dRL"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmSRL dLR"><b></b><c></c><d></d></f>
|
||||
<f class="fdCR wmSRL dRL"><b></b><c></c><d></d></f>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -2715,7 +2715,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
INIT_MIRROR(mMediaPrincipalHandle, PRINCIPAL_HANDLE_NONE),
|
||||
INIT_CANONICAL(mDuration, NullableTimeUnit()),
|
||||
INIT_CANONICAL(mCurrentPosition, TimeUnit::Zero()),
|
||||
INIT_CANONICAL(mIsAudioDataAudible, false)
|
||||
INIT_CANONICAL(mIsAudioDataAudible, false),
|
||||
mSetSinkRequestsCount(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
@ -3674,7 +3675,7 @@ MediaDecoderStateMachine::InvokeSetSink(RefPtr<AudioDeviceInfo> aSink)
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aSink);
|
||||
|
||||
++mSetSinkRequestsCount;
|
||||
Unused << ++mSetSinkRequestsCount;
|
||||
return InvokeAsync(
|
||||
OwnerThread(), this, __func__,
|
||||
&MediaDecoderStateMachine::SetSink, aSink);
|
||||
|
|
|
@ -103,9 +103,6 @@ with Files("FakePluginTagInit.webidl"):
|
|||
with Files("FeaturePolicy.webidl"):
|
||||
BUG_COMPONENT = ("Core", "DOM: Security")
|
||||
|
||||
with Files("Flex.webidl"):
|
||||
BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
|
||||
|
||||
with Files("FocusEvent.webidl"):
|
||||
BUG_COMPONENT = ("Core", "DOM: Events")
|
||||
|
||||
|
@ -507,7 +504,6 @@ WEBIDL_FILES = [
|
|||
'FileSystemDirectoryReader.webidl',
|
||||
'FileSystemEntry.webidl',
|
||||
'FileSystemFileEntry.webidl',
|
||||
'Flex.webidl',
|
||||
'FocusEvent.webidl',
|
||||
'FontFace.webidl',
|
||||
'FontFaceSet.webidl',
|
||||
|
|
|
@ -398,7 +398,9 @@ skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-all-on-loc
|
|||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1346081
|
||||
skip script test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js
|
||||
skip script test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js
|
||||
skip script test262/intl402/NumberFormat/prototype/format/format-significant-digits.js
|
||||
skip script test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js
|
||||
|
||||
# Hoisted block-level function named "arguments" not initialized with undefined per B.3.3.1
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1339123
|
||||
|
@ -408,6 +410,12 @@ skip script test262/annexB/language/function-code/block-decl-func-skip-arguments
|
|||
skip script test262/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js
|
||||
skip script test262/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1495072
|
||||
skip script test262/language/expressions/await/await-monkey-patched-promise.js
|
||||
skip script test262/language/expressions/await/async-await-interleaved.js
|
||||
skip script test262/language/expressions/await/for-await-of-interleaved.js
|
||||
skip script test262/language/expressions/await/async-generator-interleaved.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1321616
|
||||
skip script test262/annexB/built-ins/Function/createdynfn-html-close-comment-params.js
|
||||
|
||||
|
@ -450,6 +458,11 @@ skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-shor
|
|||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1483548
|
||||
skip script test262/intl402/RelativeTimeFormat/prototype/format/value-non-finite.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1499933
|
||||
skip script test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js
|
||||
skip script test262/intl402/PluralRules/prototype/resolvedOptions/order.js
|
||||
skip script test262/intl402/NumberFormat/prototype/resolvedOptions/order.js
|
||||
|
||||
|
||||
###########################################################
|
||||
# Tests disabled due to issues in test262 importer script #
|
||||
|
|
|
@ -21,7 +21,12 @@ from itertools import chain
|
|||
UNSUPPORTED_FEATURES = set([
|
||||
"tail-call-optimization",
|
||||
"class-fields-public",
|
||||
"class-static-fields-public",
|
||||
"class-fields-private",
|
||||
"class-static-fields-private",
|
||||
"class-methods-private",
|
||||
"class-static-methods-private",
|
||||
"dynamic-import",
|
||||
"regexp-dotall",
|
||||
"regexp-lookbehind",
|
||||
"regexp-named-groups",
|
||||
|
@ -37,6 +42,8 @@ FEATURE_CHECK_NEEDED = {
|
|||
"Atomics": "!this.hasOwnProperty('Atomics')",
|
||||
"BigInt": "!this.hasOwnProperty('BigInt')",
|
||||
"SharedArrayBuffer": "!this.hasOwnProperty('SharedArrayBuffer')",
|
||||
"Intl.ListFormat": "!Intl.hasOwnProperty('ListFormat')",
|
||||
"Intl.Segmenter": "!Intl.hasOwnProperty('Segmenter')",
|
||||
}
|
||||
RELEASE_OR_BETA = set()
|
||||
|
||||
|
|
|
@ -1,7 +1,36 @@
|
|||
commit ab436c465106be86719c4849c9cedecd7b570ff9
|
||||
Author: Leo Balter <leonardo.balter@gmail.com>
|
||||
Date: Fri Aug 17 18:06:19 2018 -0400
|
||||
commit b98c45ca5a46966bce1ac691d5f608beb36d5db7
|
||||
Author: Maya Lekova <apokalyptra@gmail.com>
|
||||
Date: Wed Oct 17 22:10:09 2018 +0200
|
||||
|
||||
Merge pull request #1677 from tc39/ofe-use-verifyproperty
|
||||
AsyncFunction: Add tests ensuring the new 1-tick await behaviour (#1843)
|
||||
|
||||
Object.fromEntries: use verifyProperty; add specification details
|
||||
* AsyncFunction: Add tests ensuring the new 1-tick await behaviour
|
||||
|
||||
This commit adds 3 tests ensuring the optimized behaviour of await
|
||||
(see https://github.com/tc39/ecma262/pull/1250) in the following cases:
|
||||
- async functions
|
||||
- yielding from async generator functions
|
||||
- for-await-of loops
|
||||
|
||||
* AsyncFunction: Add tests ensuring the monkey-patched promises behaviour
|
||||
|
||||
This commit adds 2 more tests ensuring the optimized behaviour of await
|
||||
(see tc39/ecma262#1250) in the following cases:
|
||||
- awaiting on a native promise with monkey-patched "then"
|
||||
- awaiting on a non-native promise (a "thenable" object)
|
||||
|
||||
* AsyncFunction: Add tests ensuring the non-native promises behaviour
|
||||
|
||||
This commit adds 1 more tests ensuring the optimized behaviour of await
|
||||
(see tc39/ecma262#1250) in the following cases:
|
||||
- awaiting on a non-promise, non-thenable object
|
||||
|
||||
It also renames the previous test for non-promise (a "thenable" object)
|
||||
to distinguish from the new case.
|
||||
|
||||
The commit adds checks for proper await/promises interleaving in the
|
||||
aforementioned cases and includes a small code clean-up.
|
||||
|
||||
* AsyncFunction: Refactor tests ensuring the new 1-tick await behaviour
|
||||
|
||||
Gather all the tests to their appropriate folder and update copyright header.
|
||||
|
|
|
@ -16,18 +16,18 @@ var a = getArgumentsObject([1], [2]);
|
|||
var actual = [].flat.call(a);
|
||||
assert.compareArray(actual, [1, 2], 'arguments objects');
|
||||
|
||||
var a = {
|
||||
a = {
|
||||
length: 1,
|
||||
0: [1],
|
||||
};
|
||||
var actual = [].flat.call(a);
|
||||
actual = [].flat.call(a);
|
||||
assert.compareArray(actual, [1], 'array-like objects');
|
||||
|
||||
var a = {
|
||||
a = {
|
||||
length: undefined,
|
||||
0: [1],
|
||||
};
|
||||
var actual = [].flat.call(a);
|
||||
actual = [].flat.call(a);
|
||||
assert.compareArray(actual, [], 'array-like objects; undefined length');
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -14,8 +14,10 @@ assert.sameValue(
|
|||
'The value of `Array.prototype.flat.length` is `0`'
|
||||
);
|
||||
|
||||
verifyNotEnumerable(Array.prototype.flat, 'length');
|
||||
verifyNotWritable(Array.prototype.flat, 'length');
|
||||
verifyConfigurable(Array.prototype.flat, 'length');
|
||||
verifyProperty(Array.prototype.flat, 'length', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -15,8 +15,10 @@ assert.sameValue(
|
|||
'The value of `Array.prototype.flat.name` is `"flat"`'
|
||||
);
|
||||
|
||||
verifyNotEnumerable(Array.prototype.flat, 'name');
|
||||
verifyNotWritable(Array.prototype.flat, 'name');
|
||||
verifyConfigurable(Array.prototype.flat, 'name');
|
||||
verifyProperty(Array.prototype.flat, 'name', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -17,29 +17,29 @@ var actual = a.flat(depthNum);
|
|||
assert(compareArray(actual, expected), 'non integral string depthNum');
|
||||
|
||||
// object type depthNum is converted to 0
|
||||
var depthNum = {};
|
||||
var actual = a.flat(depthNum);
|
||||
depthNum = {};
|
||||
actual = a.flat(depthNum);
|
||||
assert(compareArray(actual, expected), 'object type depthNum');
|
||||
|
||||
// negative infinity depthNum is converted to 0
|
||||
var depthNum = Number.NEGATIVE_INFINITY;
|
||||
var actual = a.flat(depthNum);
|
||||
depthNum = Number.NEGATIVE_INFINITY;
|
||||
actual = a.flat(depthNum);
|
||||
assert(compareArray(actual, expected), 'negative infinity depthNum');
|
||||
|
||||
// positive zero depthNum is converted to 0
|
||||
var depthNum = +0;
|
||||
var actual = a.flat(depthNum);
|
||||
depthNum = +0;
|
||||
actual = a.flat(depthNum);
|
||||
assert(compareArray(actual, expected), 'positive zero depthNum');
|
||||
|
||||
// negative zero depthNum is converted to 0
|
||||
var depthNum = -0;
|
||||
var actual = a.flat(depthNum);
|
||||
depthNum = -0;
|
||||
actual = a.flat(depthNum);
|
||||
assert(compareArray(actual, expected), 'negative zero depthNum');
|
||||
|
||||
// integral string depthNum is converted to an integer
|
||||
var depthNum = '1';
|
||||
var actual = a.flat(depthNum);
|
||||
var expected = [1, 2]
|
||||
depthNum = '1';
|
||||
actual = a.flat(depthNum);
|
||||
expected = [1, 2]
|
||||
assert(compareArray(actual, expected), 'integral string depthNum');
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -14,19 +14,19 @@ assert.throws(TypeError, function() {
|
|||
a.flat();
|
||||
}, 'null value');
|
||||
|
||||
var a = [];
|
||||
a = [];
|
||||
a.constructor = 1;
|
||||
assert.throws(TypeError, function() {
|
||||
a.flat();
|
||||
}, 'number value');
|
||||
|
||||
var a = [];
|
||||
a = [];
|
||||
a.constructor = 'string';
|
||||
assert.throws(TypeError, function() {
|
||||
a.flat();
|
||||
}, 'string value');
|
||||
|
||||
var a = [];
|
||||
a = [];
|
||||
a.constructor = true;
|
||||
assert.throws(TypeError, function() {
|
||||
a.flat();
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.flat
|
||||
es6id: 22.1.3
|
||||
description: Property type and descriptor.
|
||||
info: >
|
||||
17 ECMAScript Standard Built-in Objects
|
||||
|
@ -16,8 +15,10 @@ assert.sameValue(
|
|||
'`typeof Array.prototype.flat` is `function`'
|
||||
);
|
||||
|
||||
verifyNotEnumerable(Array.prototype, 'flat');
|
||||
verifyWritable(Array.prototype, 'flat');
|
||||
verifyConfigurable(Array.prototype, 'flat');
|
||||
verifyProperty(Array.prototype, 'flat', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
38
js/src/tests/test262/built-ins/Array/prototype/flat/proxy-access-count.js
поставляемый
Normal file
38
js/src/tests/test262/built-ins/Array/prototype/flat/proxy-access-count.js
поставляемый
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright (C) 2018 Richard Lawrence. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.flat
|
||||
description: >
|
||||
properties are accessed correct number of times by .flat
|
||||
info: |
|
||||
Array.prototype.flat( [ depth ] )
|
||||
|
||||
...
|
||||
6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, depthNum).
|
||||
|
||||
FlattenIntoArray (target, source, sourceLen, start, depth [ , mapperFunction, thisArg ])
|
||||
|
||||
3. Repeat, while sourceIndex < sourceLen
|
||||
a. Let P be ! ToString(sourceIndex).
|
||||
b. Let exists be ? HasProperty(source, P).
|
||||
c. If exists is true, then
|
||||
i. Let element be ? Get(source, P).
|
||||
features: [Array.prototype.flat]
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
const getCalls = [], hasCalls = [];
|
||||
const handler = {
|
||||
get : function (t, p, r) { getCalls.push(p); return Reflect.get(t, p, r); },
|
||||
has : function (t, p, r) { hasCalls.push(p); return Reflect.has(t, p, r); }
|
||||
}
|
||||
|
||||
const tier2 = new Proxy([4, 3], handler);
|
||||
const tier1 = new Proxy([2, [3, [4, 2], 2], 5, tier2, 6], handler);
|
||||
|
||||
Array.prototype.flat.call(tier1, 3);
|
||||
|
||||
assert.compareArray(getCalls, ["length", "constructor", "0", "1", "2", "3", "length", "0", "1", "4"], 'getProperty by .flat should occur exactly once per property and once for length and constructor');
|
||||
assert.compareArray(hasCalls, ["0", "1", "2", "3", "0", "1", "4"], 'hasProperty by .flat should occur exactly once per property');
|
||||
|
||||
reportCompare(0, 0);
|
|
@ -20,18 +20,18 @@ var a = getArgumentsObject(1, 2);
|
|||
var actual = [].flatMap.call(a, double);
|
||||
assert.compareArray(actual, [2, 4], 'arguments objects');
|
||||
|
||||
var a = {
|
||||
a = {
|
||||
length: 1,
|
||||
0: 1,
|
||||
};
|
||||
var actual = [].flatMap.call(a, double);
|
||||
actual = [].flatMap.call(a, double);
|
||||
assert.compareArray(actual, [2], 'array-like objects');
|
||||
|
||||
var a = {
|
||||
a = {
|
||||
length: void 0,
|
||||
0: 1,
|
||||
};
|
||||
var actual = [].flatMap.call(a, double);
|
||||
actual = [].flatMap.call(a, double);
|
||||
assert.compareArray(actual, [], 'array-like objects; undefined length');
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -14,8 +14,10 @@ assert.sameValue(
|
|||
'The value of `Array.prototype.flatmap.length` is `1`'
|
||||
);
|
||||
|
||||
verifyNotEnumerable(Array.prototype.flatMap, 'length');
|
||||
verifyNotWritable(Array.prototype.flatMap, 'length');
|
||||
verifyConfigurable(Array.prototype.flatMap, 'length');
|
||||
verifyProperty(Array.prototype.flatMap, 'length', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -14,8 +14,10 @@ assert.sameValue(
|
|||
'The value of `Array.prototype.flatMap.name` is `"flatMap"`'
|
||||
);
|
||||
|
||||
verifyNotEnumerable(Array.prototype.flatMap, 'name');
|
||||
verifyNotWritable(Array.prototype.flatMap, 'name');
|
||||
verifyConfigurable(Array.prototype.flatMap, 'name');
|
||||
verifyProperty(Array.prototype.flatMap, 'name', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -14,19 +14,19 @@ assert.throws(TypeError, function() {
|
|||
a.flatMap();
|
||||
}, 'null value');
|
||||
|
||||
var a = [];
|
||||
a = [];
|
||||
a.constructor = 1;
|
||||
assert.throws(TypeError, function() {
|
||||
a.flatMap();
|
||||
}, 'number value');
|
||||
|
||||
var a = [];
|
||||
a = [];
|
||||
a.constructor = 'string';
|
||||
assert.throws(TypeError, function() {
|
||||
a.flatMap();
|
||||
}, 'string value');
|
||||
|
||||
var a = [];
|
||||
a = [];
|
||||
a.constructor = true;
|
||||
assert.throws(TypeError, function() {
|
||||
a.flatMap();
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (C) 2018 Leo Balter. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-array.prototype.flatMap
|
||||
description: Property type and descriptor.
|
||||
info: >
|
||||
17 ECMAScript Standard Built-in Objects
|
||||
|
||||
Every other data property described in clauses 18 through 26 and in Annex B.2
|
||||
has the attributes { [[Writable]]: true, [[Enumerable]]: false,
|
||||
[[Configurable]]: true } unless otherwise specified.
|
||||
includes: [propertyHelper.js]
|
||||
features: [Array.prototype.flatMap]
|
||||
---*/
|
||||
|
||||
assert.sameValue(
|
||||
typeof Array.prototype.flatMap,
|
||||
'function',
|
||||
'`typeof Array.prototype.flatMap` is `function`'
|
||||
);
|
||||
|
||||
verifyProperty(Array.prototype, 'flatMap', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
reportCompare(0, 0);
|
38
js/src/tests/test262/built-ins/Array/prototype/flatMap/proxy-access-count.js
поставляемый
Normal file
38
js/src/tests/test262/built-ins/Array/prototype/flatMap/proxy-access-count.js
поставляемый
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright (C) 2018 Richard Lawrence. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-array.prototype.flatMap
|
||||
description: >
|
||||
properties are accessed correct number of times by .flatMap
|
||||
info: |
|
||||
Array.prototype.flatMap ( mapperFunction [ , thisArg ] )
|
||||
|
||||
...
|
||||
6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T).
|
||||
|
||||
FlattenIntoArray (target, source, sourceLen, start, depth [ , mapperFunction, thisArg ])
|
||||
|
||||
3. Repeat, while sourceIndex < sourceLen
|
||||
a. Let P be ! ToString(sourceIndex).
|
||||
b. Let exists be ? HasProperty(source, P).
|
||||
c. If exists is true, then
|
||||
i. Let element be ? Get(source, P).
|
||||
features: [Array.prototype.flat]
|
||||
includes: [compareArray.js]
|
||||
---*/
|
||||
|
||||
const getCalls = [], hasCalls = [];
|
||||
const handler = {
|
||||
get : function (t, p, r) { getCalls.push(p); return Reflect.get(t, p, r); },
|
||||
has : function (t, p, r) { hasCalls.push(p); return Reflect.has(t, p, r); }
|
||||
}
|
||||
|
||||
const tier2 = new Proxy([4, 3], handler);
|
||||
const tier1 = new Proxy([2, [3, 4, 2, 2], 5, tier2, 6], handler);
|
||||
|
||||
Array.prototype.flatMap.call(tier1, function(a){ return a; });
|
||||
|
||||
assert.compareArray(getCalls, ["length", "constructor", "0", "1", "2", "3", "length", "0", "1", "4"], 'getProperty by .flatMap should occur exactly once per property and once for length and constructor');
|
||||
assert.compareArray(hasCalls, ["0", "1", "2", "3", "0", "1", "4"], 'hasProperty by .flatMap should occur exactly once per property');
|
||||
|
||||
reportCompare(0, 0);
|
|
@ -6,13 +6,6 @@ description: >
|
|||
Collection of functions used to interact with Atomics.* operations across agent boundaries.
|
||||
---*/
|
||||
|
||||
/**
|
||||
* The amount of slack allowed for testing time-related Atomics methods (i.e. wait and notify).
|
||||
* The absolute value of the difference of the observed time and the expected time must
|
||||
* be epsilon-close.
|
||||
*/
|
||||
$262.agent.MAX_TIME_EPSILON = 100;
|
||||
|
||||
/**
|
||||
* @return {String} A report sent from an agent.
|
||||
*/
|
||||
|
|
|
@ -68,7 +68,7 @@ assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "
|
|||
|
||||
// Notify again at index 0, default => 0.
|
||||
var woken = 0;
|
||||
while ((woken = Atomics.notify(i32a, /*, default values used */)) === 0) ;
|
||||
while ((woken = Atomics.notify(i32a /*, default values used */)) === 0) ;
|
||||
assert.sameValue(woken, 1, 'Atomics.notify(i32a /*, default values used */) returns 1');
|
||||
|
||||
assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"');
|
||||
|
|
|
@ -36,16 +36,13 @@ $262.agent.start(`
|
|||
const i64a = new BigInt64Array(sab);
|
||||
Atomics.add(i64a, ${RUNNING}, 1n);
|
||||
|
||||
const before = $262.agent.monotonicNow();
|
||||
const status1 = Atomics.wait(i64a, 0, 0n, false);
|
||||
const status2 = Atomics.wait(i64a, 0, 0n, valueOf);
|
||||
const status3 = Atomics.wait(i64a, 0, 0n, toPrimitive);
|
||||
const duration = $262.agent.monotonicNow() - before;
|
||||
|
||||
$262.agent.report(status1);
|
||||
$262.agent.report(status2);
|
||||
$262.agent.report(status3);
|
||||
$262.agent.report(duration);
|
||||
$262.agent.leaving();
|
||||
});
|
||||
`);
|
||||
|
@ -76,12 +73,6 @@ assert.sameValue(
|
|||
'$262.agent.getReport() returns "timed-out"'
|
||||
);
|
||||
|
||||
const lapse = $262.agent.getReport();
|
||||
|
||||
assert(lapse >= 0, 'The result of `(lapse >= 0)` is true (timeout should be a min of 0ms)');
|
||||
|
||||
assert(lapse <= $262.agent.MAX_TIME_EPSILON, 'The result of `(lapse <= $262.agent.MAX_TIME_EPSILON)` is true');
|
||||
|
||||
assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0');
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
|
@ -36,16 +36,13 @@ $262.agent.start(`
|
|||
const i32a = new Int32Array(sab);
|
||||
Atomics.add(i32a, ${RUNNING}, 1);
|
||||
|
||||
const before = $262.agent.monotonicNow();
|
||||
const status1 = Atomics.wait(i32a, 0, 0, false);
|
||||
const status2 = Atomics.wait(i32a, 0, 0, valueOf);
|
||||
const status3 = Atomics.wait(i32a, 0, 0, toPrimitive);
|
||||
const duration = $262.agent.monotonicNow() - before;
|
||||
|
||||
$262.agent.report(status1);
|
||||
$262.agent.report(status2);
|
||||
$262.agent.report(status3);
|
||||
$262.agent.report(duration);
|
||||
$262.agent.leaving();
|
||||
});
|
||||
`);
|
||||
|
@ -76,12 +73,6 @@ assert.sameValue(
|
|||
'$262.agent.getReport() returns "timed-out"'
|
||||
);
|
||||
|
||||
const lapse = $262.agent.getReport();
|
||||
|
||||
assert(lapse >= 0, 'The result of `(lapse >= 0)` is true (timeout should be a min of 0ms)');
|
||||
|
||||
assert(lapse <= $262.agent.MAX_TIME_EPSILON, 'The result of `(lapse <= $262.agent.MAX_TIME_EPSILON)` is true');
|
||||
|
||||
assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0');
|
||||
|
||||
reportCompare(0, 0);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче