mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Merge mozilla-central to inbound a=merge on a CLOSED TREE
This commit is contained in:
commit
59f79d44b0
@ -36,6 +36,7 @@ uriloader/exthandler/**
|
||||
uriloader/exthandler/tests/mochitest/**
|
||||
widget/headless/tests/**
|
||||
widget/tests/**
|
||||
xpfe/**
|
||||
|
||||
# We currently have no js files in these directories, so we ignore them by
|
||||
# default to aid ESLint's performance.
|
||||
@ -50,7 +51,6 @@ mozglue/**
|
||||
nsprpub/**
|
||||
other-licenses/**
|
||||
startupcache/**
|
||||
xpfe/**
|
||||
|
||||
# These directories only contain crashtests, but we still skip the whole
|
||||
# directory to aid performance.
|
||||
@ -239,6 +239,7 @@ dom/xul/**
|
||||
# Third-party
|
||||
dom/canvas/test/webgl-conf/**
|
||||
dom/imptests/**
|
||||
dom/media/webaudio/test/blink/**
|
||||
dom/media/webvtt/**
|
||||
|
||||
# Third-party
|
||||
@ -255,6 +256,9 @@ intl/locale/**
|
||||
intl/strres/**
|
||||
intl/uconv/**
|
||||
|
||||
# Third-party
|
||||
layout/mathml/imptests/**
|
||||
|
||||
# Exclude everything but self-hosted JS
|
||||
js/ductwork/**
|
||||
js/examples/**
|
||||
|
@ -1354,9 +1354,12 @@ pref("dom.debug.propagate_gesture_events_through_content", false);
|
||||
|
||||
// All the Geolocation preferences are here.
|
||||
//
|
||||
#ifndef EARLY_BETA_OR_EARLIER
|
||||
pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
|
||||
// MLS URL:
|
||||
// pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
#else
|
||||
// Use MLS on Nightly and early Beta.
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
pref("geo.provider.use_corelocation", true);
|
||||
|
@ -231,22 +231,6 @@ function initPage() {
|
||||
var errContainer = document.getElementById("errorContainer");
|
||||
errContainer.remove();
|
||||
|
||||
if (className && className != "expertBadCert") {
|
||||
// Associate a CSS class with the root of the page, if one was passed in,
|
||||
// to allow custom styling.
|
||||
// Not "expertBadCert" though, don't want to deal with the favicon
|
||||
document.documentElement.className = className;
|
||||
|
||||
// Also, if they specified a CSS class, they must supply their own
|
||||
// favicon. In order to trigger the browser to repaint though, we
|
||||
// need to remove/add the link element.
|
||||
var favicon = document.getElementById("favicon");
|
||||
var faviconParent = favicon.parentNode;
|
||||
faviconParent.removeChild(favicon);
|
||||
favicon.setAttribute("href", "chrome://global/skin/icons/" + className + "_favicon.png");
|
||||
faviconParent.appendChild(favicon);
|
||||
}
|
||||
|
||||
if (err == "remoteXUL") {
|
||||
// Remove the "Try again" button for remote XUL errors given that
|
||||
// it is useless.
|
||||
|
@ -2122,13 +2122,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
}
|
||||
|
||||
// Set the direction of the popup based on the textbox (bug 649840).
|
||||
// getComputedStyle causes a layout flush, so avoid calling it if a
|
||||
// direction has already been set.
|
||||
if (!this.style.direction) {
|
||||
this.style.direction =
|
||||
aElement.ownerGlobal.getComputedStyle(aElement).direction;
|
||||
}
|
||||
let popupDirection = this.style.direction;
|
||||
let popupDirection = this.style.direction = (RTL_UI ? "rtl" : "ltr");
|
||||
|
||||
// Make the popup span the width of the window. First, set its width.
|
||||
let documentRect =
|
||||
|
@ -258,9 +258,7 @@ class PageAction {
|
||||
|
||||
headerLabel.value = await this.getStrings(content.heading_text);
|
||||
headerLink.setAttribute("href", SUMO_BASE_URL + content.info_icon.sumo_path);
|
||||
const isRTL = this.window.getComputedStyle(notification).direction === "rtl";
|
||||
const attribute = isRTL ? "left" : "right";
|
||||
headerLink.setAttribute(attribute, 0);
|
||||
headerLink.setAttribute(this.window.RTL_UI ? "left" : "right", 0);
|
||||
headerImage.setAttribute("tooltiptext", await this.getStrings(content.info_icon.label, "tooltiptext"));
|
||||
headerLink.onclick = () => this._sendTelemetry({message_id: id, bucket_id: content.bucket_id, event: "RATIONALE"});
|
||||
|
||||
|
@ -627,6 +627,20 @@ var paymentDialogWrapper = {
|
||||
this.sendMessageToContent("responseSent");
|
||||
},
|
||||
|
||||
async onChangePayerAddress({payerAddressGUID}) {
|
||||
if (payerAddressGUID) {
|
||||
// If a payer address was de-selected e.g. the selected address was deleted, we'll
|
||||
// just wait to send the address change when the payer address is eventually selected
|
||||
// before clicking Pay since it's a required field.
|
||||
let {
|
||||
payerName,
|
||||
payerEmail,
|
||||
payerPhone,
|
||||
} = await this._convertProfileAddressToPayerData(payerAddressGUID);
|
||||
paymentSrv.changePayerDetail(this.request.requestId, payerName, payerEmail, payerPhone);
|
||||
}
|
||||
},
|
||||
|
||||
async onChangeShippingAddress({shippingAddressGUID}) {
|
||||
if (shippingAddressGUID) {
|
||||
// If a shipping address was de-selected e.g. the selected address was deleted, we'll
|
||||
@ -733,6 +747,10 @@ var paymentDialogWrapper = {
|
||||
this.initializeFrame();
|
||||
break;
|
||||
}
|
||||
case "changePayerAddress": {
|
||||
this.onChangePayerAddress(data);
|
||||
break;
|
||||
}
|
||||
case "changeShippingAddress": {
|
||||
this.onChangeShippingAddress(data);
|
||||
break;
|
||||
|
@ -132,7 +132,17 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
paymentRequest.pay(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the selectedShippingAddress or its properties are changed.
|
||||
* @param {string} shippingAddressGUID
|
||||
*/
|
||||
changeShippingAddress(shippingAddressGUID) {
|
||||
// Clear shipping address merchant errors when the shipping address changes.
|
||||
let request = Object.assign({}, this.requestStore.getState().request);
|
||||
request.paymentDetails = Object.assign({}, request.paymentDetails);
|
||||
request.paymentDetails.shippingAddressErrors = {};
|
||||
this.requestStore.setState({request});
|
||||
|
||||
paymentRequest.changeShippingAddress({
|
||||
shippingAddressGUID,
|
||||
});
|
||||
@ -144,6 +154,36 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the selectedPaymentCard or its relevant properties or billingAddress are changed.
|
||||
* @param {string} selectedPaymentCardGUID
|
||||
*/
|
||||
changePaymentMethod(selectedPaymentCardGUID) {
|
||||
// Clear paymentMethod merchant errors when the paymentMethod or billingAddress changes.
|
||||
let request = Object.assign({}, this.requestStore.getState().request);
|
||||
request.paymentDetails = Object.assign({}, request.paymentDetails);
|
||||
request.paymentDetails.paymentMethodErrors = null;
|
||||
this.requestStore.setState({request});
|
||||
|
||||
// TODO: Bug 1477113 - Dispatch paymentmethodchange
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the selectedPayerAddress or its relevant properties are changed.
|
||||
* @param {string} payerAddressGUID
|
||||
*/
|
||||
changePayerAddress(payerAddressGUID) {
|
||||
// Clear payer address merchant errors when the payer address changes.
|
||||
let request = Object.assign({}, this.requestStore.getState().request);
|
||||
request.paymentDetails = Object.assign({}, request.paymentDetails);
|
||||
request.paymentDetails.payerErrors = {};
|
||||
this.requestStore.setState({request});
|
||||
|
||||
paymentRequest.changePayerAddress({
|
||||
payerAddressGUID,
|
||||
});
|
||||
}
|
||||
|
||||
_isPayerRequested(paymentOptions) {
|
||||
return paymentOptions.requestPayerName ||
|
||||
paymentOptions.requestPayerEmail ||
|
||||
@ -188,8 +228,9 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
*
|
||||
* @param {object} state - See `PaymentsStore.setState`
|
||||
*/
|
||||
async setStateFromParent(state) {
|
||||
async setStateFromParent(state) { // eslint-disable-line complexity
|
||||
let oldAddresses = paymentRequest.getAddresses(this.requestStore.getState());
|
||||
let oldBasicCards = paymentRequest.getBasicCards(this.requestStore.getState());
|
||||
if (state.request) {
|
||||
state = this._updateCompleteStatus(state);
|
||||
}
|
||||
@ -204,33 +245,67 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
selectedShippingOption,
|
||||
} = state;
|
||||
let addresses = paymentRequest.getAddresses(state);
|
||||
let shippingOptions = state.request.paymentDetails.shippingOptions;
|
||||
let shippingAddress = selectedShippingAddress && addresses[selectedShippingAddress];
|
||||
let oldShippingAddress = selectedShippingAddress &&
|
||||
oldAddresses[selectedShippingAddress];
|
||||
let {paymentOptions} = state.request;
|
||||
|
||||
// Ensure `selectedShippingAddress` never refers to a deleted address.
|
||||
// We also compare address timestamps to notify about changes
|
||||
// made outside the payments UI.
|
||||
if (shippingAddress) {
|
||||
// invalidate the cached value if the address was modified
|
||||
if (oldShippingAddress &&
|
||||
shippingAddress.guid == oldShippingAddress.guid &&
|
||||
shippingAddress.timeLastModified != oldShippingAddress.timeLastModified) {
|
||||
delete this._cachedState.selectedShippingAddress;
|
||||
if (paymentOptions.requestShipping) {
|
||||
let shippingOptions = state.request.paymentDetails.shippingOptions;
|
||||
let shippingAddress = selectedShippingAddress && addresses[selectedShippingAddress];
|
||||
let oldShippingAddress = selectedShippingAddress &&
|
||||
oldAddresses[selectedShippingAddress];
|
||||
|
||||
// Ensure `selectedShippingAddress` never refers to a deleted address.
|
||||
// We also compare address timestamps to notify about changes
|
||||
// made outside the payments UI.
|
||||
if (shippingAddress) {
|
||||
// invalidate the cached value if the address was modified
|
||||
if (oldShippingAddress &&
|
||||
shippingAddress.guid == oldShippingAddress.guid &&
|
||||
shippingAddress.timeLastModified != oldShippingAddress.timeLastModified) {
|
||||
delete this._cachedState.selectedShippingAddress;
|
||||
}
|
||||
} else if (selectedShippingAddress !== null) {
|
||||
// null out the `selectedShippingAddress` property if it is undefined,
|
||||
// or if the address it pointed to was removed from storage.
|
||||
log.debug("resetting invalid/deleted shipping address");
|
||||
this.requestStore.setState({
|
||||
selectedShippingAddress: null,
|
||||
});
|
||||
}
|
||||
|
||||
// Ensure `selectedShippingOption` never refers to a deleted shipping option and
|
||||
// matches the merchant's selected option if the user hasn't made a choice.
|
||||
if (shippingOptions && (!selectedShippingOption ||
|
||||
!shippingOptions.find(opt => opt.id == selectedShippingOption))) {
|
||||
this._cachedState.selectedShippingOption = selectedShippingOption;
|
||||
this.requestStore.setState({
|
||||
// Use the DOM's computed selected shipping option:
|
||||
selectedShippingOption: state.request.shippingOption,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let basicCards = paymentRequest.getBasicCards(state);
|
||||
let oldPaymentMethod = selectedPaymentCard && oldBasicCards[selectedPaymentCard];
|
||||
let paymentMethod = selectedPaymentCard && basicCards[selectedPaymentCard];
|
||||
if (oldPaymentMethod && paymentMethod.guid == oldPaymentMethod.guid &&
|
||||
paymentMethod.timeLastModified != oldPaymentMethod.timeLastModified) {
|
||||
delete this._cachedState.selectedPaymentCard;
|
||||
} else {
|
||||
// Changes to the billing address record don't change the `timeLastModified`
|
||||
// on the card record so we have to check for changes to the address separately.
|
||||
|
||||
let billingAddressGUID = paymentMethod && paymentMethod.billingAddressGUID;
|
||||
let billingAddress = billingAddressGUID && addresses[billingAddressGUID];
|
||||
let oldBillingAddress = billingAddressGUID && oldAddresses[billingAddressGUID];
|
||||
|
||||
if (oldBillingAddress && billingAddress &&
|
||||
billingAddress.timeLastModified != oldBillingAddress.timeLastModified) {
|
||||
delete this._cachedState.selectedPaymentCard;
|
||||
}
|
||||
} else if (selectedShippingAddress !== null) {
|
||||
// null out the `selectedShippingAddress` property if it is undefined,
|
||||
// or if the address it pointed to was removed from storage.
|
||||
log.debug("resetting invalid/deleted shipping address");
|
||||
this.requestStore.setState({
|
||||
selectedShippingAddress: null,
|
||||
});
|
||||
}
|
||||
|
||||
// Ensure `selectedPaymentCard` never refers to a deleted payment card and refers
|
||||
// to a payment card if one exists.
|
||||
let basicCards = paymentRequest.getBasicCards(state);
|
||||
if (!basicCards[selectedPaymentCard]) {
|
||||
// Determining the initial selection is tracked in bug 1455789
|
||||
this.requestStore.setState({
|
||||
@ -239,23 +314,26 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
});
|
||||
}
|
||||
|
||||
// Ensure `selectedShippingOption` never refers to a deleted shipping option and
|
||||
// matches the merchant's selected option if the user hasn't made a choice.
|
||||
if (shippingOptions && (!selectedShippingOption ||
|
||||
!shippingOptions.find(option => option.id == selectedShippingOption))) {
|
||||
this._cachedState.selectedShippingOption = selectedShippingOption;
|
||||
this.requestStore.setState({
|
||||
// Use the DOM's computed selected shipping option:
|
||||
selectedShippingOption: state.request.shippingOption,
|
||||
});
|
||||
}
|
||||
if (this._isPayerRequested(state.request.paymentOptions)) {
|
||||
let payerAddress = selectedPayerAddress && addresses[selectedPayerAddress];
|
||||
let oldPayerAddress = selectedPayerAddress && oldAddresses[selectedPayerAddress];
|
||||
|
||||
// Ensure `selectedPayerAddress` never refers to a deleted address and refers
|
||||
// to an address if one exists.
|
||||
if (!addresses[selectedPayerAddress]) {
|
||||
this.requestStore.setState({
|
||||
selectedPayerAddress: Object.keys(addresses)[0] || null,
|
||||
});
|
||||
if (oldPayerAddress && payerAddress && (
|
||||
(paymentOptions.requestPayerName && payerAddress.name != oldPayerAddress.name) ||
|
||||
(paymentOptions.requestPayerEmail && payerAddress.email != oldPayerAddress.email) ||
|
||||
(paymentOptions.requestPayerPhone && payerAddress.tel != oldPayerAddress.tel)
|
||||
)) {
|
||||
// invalidate the cached value if the payer address fields were modified
|
||||
delete this._cachedState.selectedPayerAddress;
|
||||
}
|
||||
|
||||
// Ensure `selectedPayerAddress` never refers to a deleted address and refers
|
||||
// to an address if one exists.
|
||||
if (!addresses[selectedPayerAddress]) {
|
||||
this.requestStore.setState({
|
||||
selectedPayerAddress: Object.keys(addresses)[0] || null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,8 +432,20 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
}
|
||||
}
|
||||
|
||||
if (state.selectedPaymentCard != this._cachedState.selectedPaymentCard) {
|
||||
this.changePaymentMethod(state.selectedPaymentCard);
|
||||
}
|
||||
|
||||
if (this._isPayerRequested(state.request.paymentOptions)) {
|
||||
if (state.selectedPayerAddress != this._cachedState.selectedPayerAddress) {
|
||||
this.changePayerAddress(state.selectedPayerAddress);
|
||||
}
|
||||
}
|
||||
|
||||
this._cachedState.selectedShippingAddress = state.selectedShippingAddress;
|
||||
this._cachedState.selectedShippingOption = state.selectedShippingOption;
|
||||
this._cachedState.selectedPaymentCard = state.selectedPaymentCard;
|
||||
this._cachedState.selectedPayerAddress = state.selectedPayerAddress;
|
||||
}
|
||||
|
||||
render(state) {
|
||||
|
@ -200,6 +200,10 @@ var paymentRequest = {
|
||||
this.sendMessageToChrome("changeShippingOption", data);
|
||||
},
|
||||
|
||||
changePayerAddress(data) {
|
||||
this.sendMessageToChrome("changePayerAddress", data);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add/update an autofill storage record.
|
||||
*
|
||||
|
@ -76,16 +76,31 @@ var PaymentTestUtils = {
|
||||
content[eventName + "Promise"] =
|
||||
new Promise(resolve => {
|
||||
content.rq.addEventListener(eventName, () => {
|
||||
info(`Received event: ${eventName}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
awaitPaymentRequestEventPromise: async ({eventName}) => {
|
||||
/**
|
||||
* Used for PaymentRequest and PaymentResponse event promises.
|
||||
*/
|
||||
awaitPaymentEventPromise: async ({eventName}) => {
|
||||
await content[eventName + "Promise"];
|
||||
return true;
|
||||
},
|
||||
|
||||
promisePaymentResponseEvent: async ({eventName}) => {
|
||||
let response = await content.showPromise;
|
||||
content[eventName + "Promise"] =
|
||||
new Promise(resolve => {
|
||||
response.addEventListener(eventName, () => {
|
||||
info(`Received event: ${eventName}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
updateWith: async ({eventName, details}) => {
|
||||
/* globals ok */
|
||||
if (details.error &&
|
||||
@ -176,15 +191,15 @@ var PaymentTestUtils = {
|
||||
doc.querySelector("address-picker[selected-state-key='selectedShippingAddress']");
|
||||
let select = Cu.waiveXrays(addressPicker).dropdown.popupBox;
|
||||
let option = select.querySelector(`[country="${country}"]`);
|
||||
if (Cu.waiveXrays(doc.activeElement) == select) {
|
||||
// If the <select> is already focused, blur and re-focus to reset the
|
||||
// filter-as-you-type timer so that the synthesizeKey below will work
|
||||
// correctly if this method was called recently.
|
||||
select.blur();
|
||||
}
|
||||
select.focus();
|
||||
// eslint-disable-next-line no-undef
|
||||
EventUtils.synthesizeKey(option.label, {}, content.window);
|
||||
content.fillField(select, option.value);
|
||||
},
|
||||
|
||||
selectPayerAddressByGuid: guid => {
|
||||
let doc = content.document;
|
||||
let addressPicker =
|
||||
doc.querySelector("address-picker[selected-state-key='selectedPayerAddress']");
|
||||
let select = Cu.waiveXrays(addressPicker).dropdown.popupBox;
|
||||
content.fillField(select, guid);
|
||||
},
|
||||
|
||||
selectShippingAddressByGuid: guid => {
|
||||
@ -192,16 +207,7 @@ var PaymentTestUtils = {
|
||||
let addressPicker =
|
||||
doc.querySelector("address-picker[selected-state-key='selectedShippingAddress']");
|
||||
let select = Cu.waiveXrays(addressPicker).dropdown.popupBox;
|
||||
let option = select.querySelector(`[guid="${guid}"]`);
|
||||
if (Cu.waiveXrays(doc.activeElement) == select) {
|
||||
// If the <select> is already focused, blur and re-focus to reset the
|
||||
// filter-as-you-type timer so that the synthesizeKey below will work
|
||||
// correctly if this method was called recently.
|
||||
select.blur();
|
||||
}
|
||||
select.focus();
|
||||
// eslint-disable-next-line no-undef
|
||||
EventUtils.synthesizeKey(option.label, {}, content.window);
|
||||
content.fillField(select, guid);
|
||||
},
|
||||
|
||||
selectShippingOptionById: value => {
|
||||
@ -209,33 +215,14 @@ var PaymentTestUtils = {
|
||||
let optionPicker =
|
||||
doc.querySelector("shipping-option-picker");
|
||||
let select = Cu.waiveXrays(optionPicker).dropdown.popupBox;
|
||||
let option = select.querySelector(`[value="${value}"]`);
|
||||
if (Cu.waiveXrays(doc.activeElement) == select) {
|
||||
// If the <select> is already focused, blur and re-focus to reset the
|
||||
// filter-as-you-type timer so that the synthesizeKey below will work
|
||||
// correctly if this method was called recently.
|
||||
select.blur();
|
||||
}
|
||||
select.focus();
|
||||
// eslint-disable-next-line no-undef
|
||||
EventUtils.synthesizeKey(option.textContent, {}, content.window);
|
||||
content.fillField(select, value);
|
||||
},
|
||||
|
||||
selectPaymentOptionByGuid: guid => {
|
||||
let doc = content.document;
|
||||
let methodPicker = doc.querySelector("payment-method-picker");
|
||||
let select = Cu.waiveXrays(methodPicker).dropdown.popupBox;
|
||||
let option = select.querySelector(`[value="${guid}"]`);
|
||||
if (Cu.waiveXrays(doc.activeElement) == select) {
|
||||
// If the <select> is already focused, blur and re-focus to reset the
|
||||
// filter-as-you-type timer so that the synthesizeKey below will work
|
||||
// correctly if this method was called recently.
|
||||
select.blur();
|
||||
}
|
||||
select.focus();
|
||||
// just type the first few characters to select the right option
|
||||
// eslint-disable-next-line no-undef
|
||||
EventUtils.synthesizeKey(option.textContent.substring(0, 4), {}, content.window);
|
||||
content.fillField(select, guid);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -249,7 +236,7 @@ var PaymentTestUtils = {
|
||||
let {requestStore} = Cu.waiveXrays(content.document.querySelector("payment-dialog"));
|
||||
let {page} = requestStore.getState();
|
||||
let button = content.document.querySelector(`#${page.id} button.primary`);
|
||||
ok(!button.disabled, "Primary button should not be disabled when clicking it");
|
||||
ok(!button.disabled, `#${page.id} primary button should not be disabled when clicking it`);
|
||||
button.click();
|
||||
},
|
||||
|
||||
@ -273,7 +260,15 @@ var PaymentTestUtils = {
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
completePayment: () => {
|
||||
completePayment: async () => {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "payment-summary";
|
||||
}, "Wait for change to payment-summary before clicking Pay");
|
||||
|
||||
let button = content.document.getElementById("pay");
|
||||
ok(!button.disabled, "Pay button should not be disabled when clicking it");
|
||||
button.click();
|
||||
@ -532,7 +527,7 @@ var PaymentTestUtils = {
|
||||
"postal-code": "02138",
|
||||
country: "DE",
|
||||
tel: "+16172535702",
|
||||
email: "timbl@example.org",
|
||||
email: "timbl@example.com",
|
||||
},
|
||||
/* Used as a temporary (not persisted in autofill storage) address in tests */
|
||||
Temp: {
|
||||
|
@ -25,6 +25,7 @@ skip-if = debug && (os == 'mac' || os == 'linux') # bug 1465673
|
||||
[browser_request_serialization.js]
|
||||
[browser_request_shipping.js]
|
||||
[browser_retry.js]
|
||||
[browser_retry_fieldErrors.js]
|
||||
[browser_shippingaddresschange_error.js]
|
||||
[browser_show_dialog.js]
|
||||
skip-if = os == 'win' && debug # bug 1418385
|
||||
|
@ -58,7 +58,7 @@ add_task(async function test_add_link() {
|
||||
for (let options of testOptions) {
|
||||
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await manuallyAddShippingAddress(frame, newAddress, options);
|
||||
await shippingAddressChangePromise;
|
||||
@ -108,7 +108,7 @@ add_task(async function test_edit_link() {
|
||||
|
||||
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
const EXPECTED_ADDRESS = {
|
||||
"given-name": "Jaws",
|
||||
@ -556,7 +556,7 @@ add_task(async function test_private_persist_addresses() {
|
||||
info("awaiting the shippingaddresschange event");
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async (args) => {
|
||||
let {address, tempAddressGuid} = args;
|
||||
|
@ -41,7 +41,7 @@ add_task(async function test_hiddenFieldNotSaved() {
|
||||
|
||||
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
let options = {
|
||||
addLinkSelector: "address-picker.shipping-related .add-link",
|
||||
@ -108,7 +108,7 @@ add_task(async function test_hiddenFieldRemovedWhenCountryChanged() {
|
||||
|
||||
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async (args) => {
|
||||
let {
|
||||
|
@ -58,7 +58,7 @@ add_task(async function test_change_shipping() {
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
info("got shippingaddresschange event");
|
||||
|
||||
// verify update of shippingOptions
|
||||
@ -177,7 +177,7 @@ add_task(async function test_default_shippingOptions_noneSelected() {
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
info("got shippingaddresschange event");
|
||||
|
||||
shippingOptions =
|
||||
@ -236,7 +236,7 @@ add_task(async function test_default_shippingOptions_allSelected() {
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
info("got shippingaddresschange event");
|
||||
|
||||
shippingOptions =
|
||||
@ -330,7 +330,7 @@ add_task(async function test_address_edit() {
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
addressOptions =
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.getShippingAddresses);
|
||||
|
@ -0,0 +1,543 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test the merchant calling .retry() with field-specific errors.
|
||||
*/
|
||||
|
||||
async function setup() {
|
||||
await setupFormAutofillStorage();
|
||||
await cleanupFormAutofillStorage();
|
||||
// add 2 addresses and 2 cards to avoid the FTU sequence and test address errors
|
||||
let prefilledGuids = await addSampleAddressesAndBasicCard(
|
||||
[PTU.Addresses.TimBL, PTU.Addresses.TimBL2],
|
||||
[PTU.BasicCards.JaneMasterCard, PTU.BasicCards.JohnDoe]);
|
||||
|
||||
info("associating card1 with a billing address");
|
||||
await formAutofillStorage.creditCards.update(prefilledGuids.card1GUID, {
|
||||
billingAddressGUID: prefilledGuids.address1GUID,
|
||||
}, true);
|
||||
info("associating card2 with a billing address");
|
||||
await formAutofillStorage.creditCards.update(prefilledGuids.card2GUID, {
|
||||
billingAddressGUID: prefilledGuids.address1GUID,
|
||||
}, true);
|
||||
|
||||
return prefilledGuids;
|
||||
}
|
||||
|
||||
add_task(async function test_retry_with_shipppingAddressErrors() {
|
||||
if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
|
||||
todo(false, "Cannot test OS key store login on official builds.");
|
||||
return;
|
||||
}
|
||||
await setup();
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: BLANK_PAGE_URL,
|
||||
}, async browser => {
|
||||
let {win, frame} = await setupPaymentDialog(browser, {
|
||||
methodData: [PTU.MethodData.basicCard],
|
||||
details: Object.assign({}, PTU.Details.twoShippingOptions, PTU.Details.total60USD),
|
||||
options: PTU.Options.requestShippingOption,
|
||||
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
|
||||
});
|
||||
|
||||
await selectPaymentDialogShippingAddressByCountry(frame, "DE");
|
||||
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.setSecurityCode, {
|
||||
securityCode: "123",
|
||||
});
|
||||
|
||||
info("clicking the button to try pay the 1st time");
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
let retryUpdatePromise = spawnPaymentDialogTask(frame, async function checkDialog() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
let state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "processing";
|
||||
}, "Wait for completeStatus from pay button click");
|
||||
|
||||
is(state.request.completeStatus, "processing", "Check completeStatus is processing");
|
||||
is(state.request.paymentDetails.shippingAddressErrors.country, undefined,
|
||||
"Check country error string is empty");
|
||||
ok(state.changesPrevented, "Changes prevented");
|
||||
|
||||
state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "";
|
||||
}, "Wait for completeStatus from DOM update");
|
||||
|
||||
is(state.request.completeStatus, "", "Check completeStatus");
|
||||
is(state.request.paymentDetails.shippingAddressErrors.country, "Can only ship to USA",
|
||||
"Check country error string in state");
|
||||
ok(!state.changesPrevented, "Changes no longer prevented");
|
||||
is(state.page.id, "payment-summary", "Check still on payment-summary");
|
||||
|
||||
ok(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("Can only ship to USA"),
|
||||
"Check error visibility on summary page");
|
||||
ok(content.document.getElementById("pay").disabled,
|
||||
"Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
// Add a handler to retry the payment above.
|
||||
info("Tell merchant page to retry with a country error string");
|
||||
let retryPromise = ContentTask.spawn(browser,
|
||||
{
|
||||
delayMs: 1000,
|
||||
validationErrors: {
|
||||
shippingAddress: {
|
||||
country: "Can only ship to USA",
|
||||
},
|
||||
},
|
||||
},
|
||||
PTU.ContentTasks.addRetryHandler);
|
||||
|
||||
await retryUpdatePromise;
|
||||
|
||||
info("Changing to a US address to clear the error");
|
||||
await selectPaymentDialogShippingAddressByCountry(frame, "US");
|
||||
|
||||
info("Tell merchant page to retry with a regionCode error string");
|
||||
let retryPromise2 = ContentTask.spawn(browser,
|
||||
{
|
||||
delayMs: 1000,
|
||||
validationErrors: {
|
||||
shippingAddress: {
|
||||
regionCode: "Can only ship to California",
|
||||
},
|
||||
},
|
||||
},
|
||||
PTU.ContentTasks.addRetryHandler);
|
||||
|
||||
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkRegionError() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
let state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "";
|
||||
}, "Wait for completeStatus from DOM update");
|
||||
|
||||
is(state.request.completeStatus, "", "Check completeStatus");
|
||||
is(state.request.paymentDetails.shippingAddressErrors.regionCode,
|
||||
"Can only ship to California",
|
||||
"Check regionCode error string in state");
|
||||
ok(!state.changesPrevented, "Changes no longer prevented");
|
||||
is(state.page.id, "payment-summary", "Check still on payment-summary");
|
||||
|
||||
ok(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("Can only ship to California"),
|
||||
"Check error visibility on summary page");
|
||||
ok(content.document.getElementById("pay").disabled,
|
||||
"Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
info("Changing the shipping state to CA without changing selectedShippingAddress");
|
||||
await navigateToAddShippingAddressPage(frame, {
|
||||
addLinkSelector: "address-picker[selected-state-key=\"selectedShippingAddress\"] .edit-link",
|
||||
});
|
||||
await fillInShippingAddressForm(frame, { "address-level1": "CA" });
|
||||
await submitAddressForm(frame, null, {isEditing: true});
|
||||
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
// We can only check the retry response after the closing as it only resolves upon complete.
|
||||
let {retryException} = await retryPromise;
|
||||
ok(!retryException, "Expect no exception to be thrown when calling retry()");
|
||||
|
||||
let {retryException2} = await retryPromise2;
|
||||
ok(!retryException2, "Expect no exception to be thrown when calling retry()");
|
||||
|
||||
// Add a handler to complete the payment above.
|
||||
info("acknowledging the completion from the merchant page");
|
||||
let result = await ContentTask.spawn(browser, {}, PTU.ContentTasks.addCompletionHandler);
|
||||
|
||||
// Verify response has the expected properties
|
||||
let expectedDetails = Object.assign({
|
||||
"cc-security-code": "123",
|
||||
}, PTU.BasicCards.JohnDoe);
|
||||
|
||||
checkPaymentMethodDetailsMatchesCard(result.response.details, expectedDetails,
|
||||
"Check response payment details");
|
||||
checkPaymentAddressMatchesStorageAddress(result.response.shippingAddress,
|
||||
{...PTU.Addresses.TimBL, ...{"address-level1": "CA"}},
|
||||
"Check response shipping address");
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_retry_with_payerErrors() {
|
||||
if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
|
||||
todo(false, "Cannot test OS key store login on official builds.");
|
||||
return;
|
||||
}
|
||||
let prefilledGuids = await setup();
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: BLANK_PAGE_URL,
|
||||
}, async browser => {
|
||||
let {win, frame} = await setupPaymentDialog(browser, {
|
||||
methodData: [PTU.MethodData.basicCard],
|
||||
details: PTU.Details.total60USD,
|
||||
options: PTU.Options.requestPayerNameEmailAndPhone,
|
||||
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.setSecurityCode, {
|
||||
securityCode: "123",
|
||||
});
|
||||
|
||||
info("clicking the button to try pay the 1st time");
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
let retryUpdatePromise = spawnPaymentDialogTask(frame, async function checkDialog() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
let state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "processing";
|
||||
}, "Wait for completeStatus from pay button click");
|
||||
|
||||
is(state.request.completeStatus, "processing", "Check completeStatus is processing");
|
||||
|
||||
is(state.request.paymentDetails.payerErrors.email, undefined,
|
||||
"Check email error isn't present");
|
||||
ok(state.changesPrevented, "Changes prevented");
|
||||
|
||||
state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "";
|
||||
}, "Wait for completeStatus from DOM update");
|
||||
|
||||
is(state.request.completeStatus, "", "Check completeStatus");
|
||||
is(state.request.paymentDetails.payerErrors.email, "You must use your employee email address",
|
||||
"Check email error string in state");
|
||||
ok(!state.changesPrevented, "Changes no longer prevented");
|
||||
is(state.page.id, "payment-summary", "Check still on payment-summary");
|
||||
|
||||
ok(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("You must use your employee email address"),
|
||||
"Check error visibility on summary page");
|
||||
ok(content.document.getElementById("pay").disabled,
|
||||
"Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
|
||||
// Add a handler to retry the payment above.
|
||||
info("Tell merchant page to retry with a country error string");
|
||||
let retryPromise = ContentTask.spawn(browser,
|
||||
{
|
||||
delayMs: 1000,
|
||||
validationErrors: {
|
||||
payer: {
|
||||
email: "You must use your employee email address",
|
||||
},
|
||||
},
|
||||
},
|
||||
PTU.ContentTasks.addRetryHandler);
|
||||
|
||||
await retryUpdatePromise;
|
||||
|
||||
info("Changing to a different email address to clear the error");
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.selectPayerAddressByGuid,
|
||||
prefilledGuids.address1GUID);
|
||||
|
||||
info("Tell merchant page to retry with a phone error string");
|
||||
let retryPromise2 = ContentTask.spawn(browser,
|
||||
{
|
||||
delayMs: 1000,
|
||||
validationErrors: {
|
||||
payer: {
|
||||
phone: "Your phone number isn't valid",
|
||||
},
|
||||
},
|
||||
},
|
||||
PTU.ContentTasks.addRetryHandler);
|
||||
|
||||
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkRegionError() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
let state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "";
|
||||
}, "Wait for completeStatus from DOM update");
|
||||
|
||||
is(state.request.completeStatus, "", "Check completeStatus");
|
||||
is(state.request.paymentDetails.payerErrors.phone,
|
||||
"Your phone number isn't valid",
|
||||
"Check regionCode error string in state");
|
||||
ok(!state.changesPrevented, "Changes no longer prevented");
|
||||
is(state.page.id, "payment-summary", "Check still on payment-summary");
|
||||
|
||||
ok(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("Your phone number isn't valid"),
|
||||
"Check error visibility on summary page");
|
||||
ok(content.document.getElementById("pay").disabled,
|
||||
"Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
info("Changing the payer phone to be valid without changing selectedPayerAddress");
|
||||
await navigateToAddAddressPage(frame, {
|
||||
addLinkSelector: "address-picker[selected-state-key=\"selectedPayerAddress\"] .edit-link",
|
||||
initialPageId: "payment-summary",
|
||||
addressPageId: "payer-address-page",
|
||||
});
|
||||
|
||||
let newPhoneNumber = "+16175555555";
|
||||
await fillInPayerAddressForm(frame, { tel: newPhoneNumber });
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "payerdetailchange",
|
||||
}, PTU.ContentTasks.promisePaymentResponseEvent);
|
||||
|
||||
await submitAddressForm(frame, null, {isEditing: true});
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "payerdetailchange",
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
// We can only check the retry response after the closing as it only resolves upon complete.
|
||||
let {retryException} = await retryPromise;
|
||||
ok(!retryException, "Expect no exception to be thrown when calling retry()");
|
||||
|
||||
let {retryException2} = await retryPromise2;
|
||||
ok(!retryException2, "Expect no exception to be thrown when calling retry()");
|
||||
|
||||
// Add a handler to complete the payment above.
|
||||
info("acknowledging the completion from the merchant page");
|
||||
let result = await ContentTask.spawn(browser, {}, PTU.ContentTasks.addCompletionHandler);
|
||||
|
||||
// Verify response has the expected properties
|
||||
let expectedDetails = Object.assign({
|
||||
"cc-security-code": "123",
|
||||
}, PTU.BasicCards.JohnDoe);
|
||||
|
||||
checkPaymentMethodDetailsMatchesCard(result.response.details, expectedDetails,
|
||||
"Check response payment details");
|
||||
let {
|
||||
"given-name": givenName,
|
||||
"additional-name": additionalName,
|
||||
"family-name": familyName,
|
||||
email,
|
||||
} = PTU.Addresses.TimBL;
|
||||
is(result.response.payerName, `${givenName} ${additionalName} ${familyName}`,
|
||||
"Check payer name");
|
||||
is(result.response.payerEmail, email, "Check payer email");
|
||||
is(result.response.payerPhone, newPhoneNumber, "Check payer phone");
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_retry_with_paymentMethodErrors() {
|
||||
if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
|
||||
todo(false, "Cannot test OS key store login on official builds.");
|
||||
return;
|
||||
}
|
||||
let prefilledGuids = await setup();
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: BLANK_PAGE_URL,
|
||||
}, async browser => {
|
||||
let {win, frame} = await setupPaymentDialog(browser, {
|
||||
methodData: [PTU.MethodData.basicCard],
|
||||
details: PTU.Details.total60USD,
|
||||
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.setSecurityCode, {
|
||||
securityCode: "123",
|
||||
});
|
||||
|
||||
info("clicking the button to try pay the 1st time");
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
let retryUpdatePromise = spawnPaymentDialogTask(frame, async function checkDialog() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
let state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "processing";
|
||||
}, "Wait for completeStatus from pay button click");
|
||||
|
||||
is(state.request.completeStatus, "processing", "Check completeStatus is processing");
|
||||
|
||||
is(state.request.paymentDetails.paymentMethodErrors, null,
|
||||
"Check no paymentMethod errors are present");
|
||||
ok(state.changesPrevented, "Changes prevented");
|
||||
|
||||
state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "";
|
||||
}, "Wait for completeStatus from DOM update");
|
||||
|
||||
is(state.request.completeStatus, "", "Check completeStatus");
|
||||
is(state.request.paymentDetails.paymentMethodErrors.cardSecurityCode,
|
||||
"Your CVV is incorrect",
|
||||
"Check cardSecurityCode error string in state");
|
||||
|
||||
ok(!state.changesPrevented, "Changes no longer prevented");
|
||||
is(state.page.id, "payment-summary", "Check still on payment-summary");
|
||||
|
||||
todo(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("Your CVV is incorrect"),
|
||||
"Bug 1491815: Check error visibility on summary page");
|
||||
todo(content.document.getElementById("pay").disabled,
|
||||
"Bug 1491815: Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
// Add a handler to retry the payment above.
|
||||
info("Tell merchant page to retry with a cardSecurityCode error string");
|
||||
let retryPromise = ContentTask.spawn(browser,
|
||||
{
|
||||
delayMs: 1000,
|
||||
validationErrors: {
|
||||
paymentMethod: {
|
||||
cardSecurityCode: "Your CVV is incorrect",
|
||||
},
|
||||
},
|
||||
},
|
||||
PTU.ContentTasks.addRetryHandler);
|
||||
|
||||
await retryUpdatePromise;
|
||||
|
||||
info("Changing to a different card to clear the error");
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.selectPaymentOptionByGuid,
|
||||
prefilledGuids.card1GUID);
|
||||
|
||||
info("Tell merchant page to retry with a billing postalCode error string");
|
||||
let retryPromise2 = ContentTask.spawn(browser,
|
||||
{
|
||||
delayMs: 1000,
|
||||
validationErrors: {
|
||||
paymentMethod: {
|
||||
billingAddress: {
|
||||
postalCode: "Your postal code isn't valid",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
PTU.ContentTasks.addRetryHandler);
|
||||
|
||||
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkPostalCodeError() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
let state = await PTU.DialogContentUtils.waitForState(content, ({request}) => {
|
||||
return request.completeStatus === "";
|
||||
}, "Wait for completeStatus from DOM update");
|
||||
|
||||
is(state.request.completeStatus, "", "Check completeStatus");
|
||||
is(state.request.paymentDetails.paymentMethodErrors.billingAddress.postalCode,
|
||||
"Your postal code isn't valid",
|
||||
"Check postalCode error string in state");
|
||||
ok(!state.changesPrevented, "Changes no longer prevented");
|
||||
is(state.page.id, "payment-summary", "Check still on payment-summary");
|
||||
|
||||
todo(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("Your postal code isn't valid"),
|
||||
"Bug 1491815: Check error visibility on summary page");
|
||||
todo(content.document.getElementById("pay").disabled,
|
||||
"Bug 1491815: Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
info("Changing the billingAddress postalCode to be valid without changing selectedPaymentCard");
|
||||
|
||||
await navigateToAddCardPage(frame, {
|
||||
addLinkSelector: "payment-method-picker .edit-link",
|
||||
});
|
||||
|
||||
await navigateToAddAddressPage(frame, {
|
||||
addLinkSelector: ".billingAddressRow .edit-link",
|
||||
initialPageId: "basic-card-page",
|
||||
addressPageId: "billing-address-page",
|
||||
});
|
||||
|
||||
let newPostalCode = "90210";
|
||||
await fillInBillingAddressForm(frame, { "postal-code": newPostalCode });
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "paymentmethodchange",
|
||||
}, PTU.ContentTasks.promisePaymentResponseEvent);
|
||||
|
||||
await submitAddressForm(frame, null, {
|
||||
isEditing: true,
|
||||
nextPageId: "basic-card-page",
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkErrorsCleared() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.request.paymentDetails.paymentMethodErrors == null;
|
||||
},
|
||||
"Check no paymentMethod errors are present");
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkErrorsCleared() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.request.paymentDetails.paymentMethodErrors == null;
|
||||
},
|
||||
"Check no card errors are present after save");
|
||||
});
|
||||
|
||||
// TODO: Add an `await` here after bug 1477113.
|
||||
ContentTask.spawn(browser, {
|
||||
eventName: "paymentmethodchange",
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await loginAndCompletePayment(frame);
|
||||
|
||||
// We can only check the retry response after the closing as it only resolves upon complete.
|
||||
let {retryException} = await retryPromise;
|
||||
ok(!retryException, "Expect no exception to be thrown when calling retry()");
|
||||
|
||||
let {retryException2} = await retryPromise2;
|
||||
ok(!retryException2, "Expect no exception to be thrown when calling retry()");
|
||||
|
||||
// Add a handler to complete the payment above.
|
||||
info("acknowledging the completion from the merchant page");
|
||||
let result = await ContentTask.spawn(browser, {}, PTU.ContentTasks.addCompletionHandler);
|
||||
|
||||
// Verify response has the expected properties
|
||||
let expectedDetails = Object.assign({
|
||||
"cc-security-code": "123",
|
||||
}, PTU.BasicCards.JaneMasterCard);
|
||||
|
||||
let expectedBillingAddress = Object.assign({}, PTU.Addresses.TimBL, {
|
||||
"postal-code": newPostalCode,
|
||||
});
|
||||
|
||||
checkPaymentMethodDetailsMatchesCard(result.response.details, expectedDetails,
|
||||
"Check response payment details");
|
||||
checkPaymentAddressMatchesStorageAddress(result.response.details.billingAddress,
|
||||
expectedBillingAddress,
|
||||
"Check response billing address");
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||
});
|
||||
});
|
@ -34,7 +34,7 @@ add_task(async function test_show_error_on_addresschange() {
|
||||
info("awaiting the shippingoptionchange event");
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingoptionchange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await spawnPaymentDialogTask(frame, expectedText => {
|
||||
let errorText = content.document.querySelector("header .page-error");
|
||||
@ -56,7 +56,7 @@ add_task(async function test_show_error_on_addresschange() {
|
||||
info("awaiting the shippingaddresschange event");
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await spawnPaymentDialogTask(frame, () => {
|
||||
let errorText = content.document.querySelector("header .page-error");
|
||||
@ -101,7 +101,7 @@ add_task(async function test_show_field_specific_error_on_addresschange() {
|
||||
info("awaiting the shippingaddresschange event");
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async () => {
|
||||
let {
|
||||
@ -160,6 +160,52 @@ add_task(async function test_show_field_specific_error_on_addresschange() {
|
||||
}
|
||||
});
|
||||
|
||||
info("setting up the event handler for a 2nd shippingaddresschange with a different error");
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
details: Object.assign({},
|
||||
{
|
||||
shippingAddressErrors: {
|
||||
phone: "Invalid phone number",
|
||||
},
|
||||
},
|
||||
PTU.Details.noShippingOptions,
|
||||
PTU.Details.total2USD),
|
||||
}, PTU.ContentTasks.updateWith);
|
||||
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkForNewErrors() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "payment-summary" &&
|
||||
state.request.paymentDetails.shippingAddressErrors.phone == "Invalid phone number";
|
||||
}, "Check the new error is in state");
|
||||
|
||||
ok(content.document.querySelector("#payment-summary").innerText
|
||||
.includes("Invalid phone number"),
|
||||
"Check error visibility on summary page");
|
||||
ok(content.document.getElementById("pay").disabled,
|
||||
"Pay button should be disabled until the field error is addressed");
|
||||
});
|
||||
|
||||
await navigateToAddShippingAddressPage(frame, {
|
||||
addLinkSelector: "address-picker[selected-state-key=\"selectedShippingAddress\"] .edit-link",
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function checkForNewErrorOnEdit() {
|
||||
let addressForm = content.document.querySelector("#shipping-address-page");
|
||||
is(addressForm.querySelectorAll(".error-text:not(:empty)").length, 1,
|
||||
"Check one error shown");
|
||||
});
|
||||
|
||||
await fillInShippingAddressForm(frame, {
|
||||
tel: PTU.Addresses.TimBL2.tel,
|
||||
});
|
||||
|
||||
info("setup updateWith to clear errors");
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
@ -168,14 +214,13 @@ add_task(async function test_show_field_specific_error_on_addresschange() {
|
||||
PTU.Details.total2USD),
|
||||
}, PTU.ContentTasks.updateWith);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async () => {
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function fixLastError() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
info("saving corrections");
|
||||
content.document.querySelector("#shipping-address-page .save-button").click();
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "payment-summary";
|
||||
}, "Check we're back on summary view");
|
||||
|
@ -128,7 +128,7 @@ add_task(async function test_show_completePayment2() {
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingoptionchange",
|
||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||
}, PTU.ContentTasks.awaitPaymentEventPromise);
|
||||
info("got shippingoptionchange event");
|
||||
|
||||
info("select the shipping address");
|
||||
|
@ -431,7 +431,7 @@ async function navigateToAddAddressPage(frame, aOptions = {}) {
|
||||
|
||||
async function navigateToAddShippingAddressPage(frame, aOptions = {}) {
|
||||
let options = Object.assign({
|
||||
addLinkSelector: "address-picker[selected-state-key=\"selectedShippingAddress\"] a.add-link",
|
||||
addLinkSelector: "address-picker[selected-state-key=\"selectedShippingAddress\"] .add-link",
|
||||
initialPageId: "payment-summary",
|
||||
addressPageId: "shipping-address-page",
|
||||
}, aOptions);
|
||||
|
@ -548,7 +548,7 @@
|
||||
arrowbox.style.transform = "translate(0, " + -offset + "px)";
|
||||
|
||||
// The assigned side stays the same regardless of direction.
|
||||
var isRTL = (window.getComputedStyle(this).direction == "rtl");
|
||||
let isRTL = this.matches(":-moz-locale-dir(rtl)");
|
||||
|
||||
if (position.indexOf("start_") == 0) {
|
||||
container.dir = "reverse";
|
||||
|
@ -91,7 +91,7 @@
|
||||
onsyncfrompreference="return gMainPane.readLinkTarget();"
|
||||
onsynctopreference="return gMainPane.writeLinkTarget();"/>
|
||||
|
||||
<checkbox id="warnCloseMultiple" data-l10n-id="warn-on-quit-close-multiple-tabs"
|
||||
<checkbox id="warnCloseMultiple" data-l10n-id="warn-on-close-multiple-tabs"
|
||||
preference="browser.tabs.warnOnClose"/>
|
||||
|
||||
<checkbox id="warnOpenMany" data-l10n-id="warn-on-open-many-tabs"
|
||||
|
@ -198,7 +198,7 @@
|
||||
data-l10n-id="do-not-track-learn-more"></label></label>
|
||||
<radiogroup id="doNotTrackRadioGroup" aria-labelledby="doNotTrackDesc" preference="privacy.donottrackheader.enabled">
|
||||
<radio value="true" data-l10n-id="do-not-track-option-always"/>
|
||||
<radio value="false" data-l10n-id="do-not-track-option-default-content-blocking"/>
|
||||
<radio value="false" data-l10n-id="do-not-track-option-default-content-blocking-known"/>
|
||||
</radiogroup>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/browser-test"
|
||||
"plugin:mozilla/chrome-test",
|
||||
]
|
||||
};
|
@ -4,8 +4,8 @@
|
||||
|
||||
do-not-track-description = Send websites a “Do Not Track” signal that you don’t want to be tracked
|
||||
do-not-track-learn-more = Learn more
|
||||
do-not-track-option-default-content-blocking =
|
||||
.label = Only when { -brand-short-name } is set to block Detected Trackers
|
||||
do-not-track-option-default-content-blocking-known =
|
||||
.label = Only when { -brand-short-name } is set to block known trackers
|
||||
do-not-track-option-always =
|
||||
.label = Always
|
||||
|
||||
@ -178,8 +178,8 @@ open-new-link-as-tabs =
|
||||
.label = Open links in tabs instead of new windows
|
||||
.accesskey = w
|
||||
|
||||
warn-on-quit-close-multiple-tabs =
|
||||
.label = Warn you when quitting and closing multiple tabs
|
||||
warn-on-close-multiple-tabs =
|
||||
.label = Warn you when closing multiple tabs
|
||||
.accesskey = m
|
||||
|
||||
warn-on-open-many-tabs =
|
||||
|
@ -18,3 +18,8 @@
|
||||
.tracking-protection-button > .button-box > .button-icon {
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
/* This overrides color: -moz-buttonhovertext from toolbarbutton.css */
|
||||
.identity-popup-content-blocking-category:hover {
|
||||
color: inherit;
|
||||
}
|
||||
|
@ -11,11 +11,10 @@ const protocol = require("devtools/shared/protocol");
|
||||
/**
|
||||
* The corresponding Front object for the CallWatcherActor.
|
||||
*/
|
||||
var CallWatcherFront =
|
||||
exports.CallWatcherFront =
|
||||
protocol.FrontClassWithSpec(callWatcherSpec, {
|
||||
initialize: function(client, { callWatcherActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: callWatcherActor });
|
||||
class CallWatcherFront extends protocol.FrontClassWithSpec(callWatcherSpec) {
|
||||
constructor(client, { callWatcherActor }) {
|
||||
super(client, { actor: callWatcherActor });
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.CallWatcherFront = CallWatcherFront;
|
||||
|
@ -9,7 +9,6 @@ DIRS += [
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'new/test/mochitest/browser.ini',
|
||||
'test/mochitest/browser.ini'
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
|
@ -1,6 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
// Extend from the shared list of defined globals for mochitests.
|
||||
"extends": "../../../.eslintrc.mochitests.js"
|
||||
};
|
@ -1,27 +0,0 @@
|
||||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
skip-if = (os == 'linux' && debug && bits == 32)
|
||||
support-files =
|
||||
doc_promise-get-allocation-stack.html
|
||||
doc_promise-get-fulfillment-stack.html
|
||||
doc_promise-get-rejection-stack.html
|
||||
doc_terminate-on-tab-close.html
|
||||
head.js
|
||||
!/devtools/client/shared/test/shared-head.js
|
||||
!/devtools/client/shared/test/telemetry-test-helpers.js
|
||||
[browser_dbg_promises-allocation-stack.js]
|
||||
uses-unsafe-cpows = true
|
||||
skip-if = true
|
||||
[browser_dbg_promises-chrome-allocation-stack.js]
|
||||
uses-unsafe-cpows = true
|
||||
skip-if = true # Bug 1177730
|
||||
[browser_dbg_promises-fulfillment-stack.js]
|
||||
uses-unsafe-cpows = true
|
||||
skip-if = true
|
||||
[browser_dbg_promises-rejection-stack.js]
|
||||
uses-unsafe-cpows = true
|
||||
skip-if = true
|
||||
[browser_dbg_terminate-on-tab-close.js]
|
||||
uses-unsafe-cpows = true
|
||||
skip-if = true
|
@ -1,87 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's allocation point.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_promise-get-allocation-stack.html";
|
||||
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
||||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
|
||||
let options = {
|
||||
source: TAB_URL,
|
||||
line: 1
|
||||
};
|
||||
const [ tab, panel ] = yield initDebugger(TAB_URL, options);
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client);
|
||||
|
||||
let { tabs } = yield listTabs(client);
|
||||
let targetTab = findTab(tabs, TAB_URL);
|
||||
yield attachTarget(client, targetTab);
|
||||
|
||||
yield testGetAllocationStack(client, targetTab, tab);
|
||||
|
||||
yield close(client);
|
||||
yield closeDebuggerAndFinish(panel);
|
||||
}).catch(error => {
|
||||
ok(false, "Got an error: " + error.message + "\n" + error.stack);
|
||||
});
|
||||
}
|
||||
|
||||
function* testGetAllocationStack(client, form, tab) {
|
||||
let front = PromisesFront(client, form);
|
||||
|
||||
yield front.attach();
|
||||
yield front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
let onNewPromise = new Promise(resolve => {
|
||||
EventEmitter.on(front, "new-promises", promises => {
|
||||
for (let p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
callInTab(tab, "makePromises");
|
||||
|
||||
let grip = yield onNewPromise;
|
||||
ok(grip, "Found our promise p");
|
||||
|
||||
let objectClient = new ObjectClient(client, grip);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
yield new Promise(resolve => {
|
||||
objectClient.getPromiseAllocationStack(response => {
|
||||
ok(response.allocationStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let stack of response.allocationStack) {
|
||||
is(stack.source.url, TAB_URL, "Got correct source URL.");
|
||||
is(stack.functionDisplayName, "makePromises",
|
||||
"Got correct function display name.");
|
||||
is(typeof stack.line, "number", "Expect stack line to be a number.");
|
||||
is(typeof stack.column, "number",
|
||||
"Expect stack column to be a number.");
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield front.detach();
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's allocation point in the chrome
|
||||
* process.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const SOURCE_URL = "browser_dbg_promises-chrome-allocation-stack.js";
|
||||
const PromisesFront = require("devtools/shared/fronts/promises");
|
||||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
const STACK_DATA = [
|
||||
{ functionDisplayName: "test/</<" },
|
||||
{ functionDisplayName: "testGetAllocationStack" },
|
||||
];
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
requestLongerTimeout(10);
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
DebuggerServer.allowChromeProcess = true;
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client);
|
||||
let targetFront = yield client.mainRoot.getMainProcess();
|
||||
yield targetFront.attach();
|
||||
yield targetFront.attachThread();
|
||||
|
||||
yield testGetAllocationStack(client, chrome.form, () => {
|
||||
let p = new Promise(() => {});
|
||||
p.name = "p";
|
||||
let q = p.then();
|
||||
q.name = "q";
|
||||
let r = p.catch(() => {});
|
||||
r.name = "r";
|
||||
});
|
||||
|
||||
yield close(client);
|
||||
finish();
|
||||
}).catch(error => {
|
||||
ok(false, "Got an error: " + error.message + "\n" + error.stack);
|
||||
});
|
||||
}
|
||||
|
||||
function* testGetAllocationStack(client, form, makePromises) {
|
||||
let front = PromisesFront(client, form);
|
||||
|
||||
yield front.attach();
|
||||
yield front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
let onNewPromise = new Promise(resolve => {
|
||||
EventEmitter.on(front, "new-promises", promises => {
|
||||
for (let p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
makePromises();
|
||||
|
||||
let grip = yield onNewPromise;
|
||||
ok(grip, "Found our promise p");
|
||||
|
||||
let objectClient = new ObjectClient(client, grip);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
yield new Promise(resolve => {
|
||||
objectClient.getPromiseAllocationStack(response => {
|
||||
ok(response.allocationStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let i = 0; i < STACK_DATA.length; i++) {
|
||||
let data = STACK_DATA[i];
|
||||
let stack = response.allocationStack[i];
|
||||
|
||||
ok(stack.source.url.startsWith("chrome:"), "Got a chrome source URL");
|
||||
ok(stack.source.url.endsWith(SOURCE_URL), "Got correct source URL.");
|
||||
is(stack.functionDisplayName, data.functionDisplayName,
|
||||
"Got correct function display name.");
|
||||
is(typeof stack.line, "number", "Expect stack line to be a number.");
|
||||
is(typeof stack.column, "number",
|
||||
"Expect stack column to be a number.");
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield front.detach();
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's fulfillment point.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_promise-get-fulfillment-stack.html";
|
||||
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
||||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
const TEST_DATA = [
|
||||
{
|
||||
functionDisplayName: "returnPromise/<",
|
||||
line: 19,
|
||||
column: 37
|
||||
},
|
||||
{
|
||||
functionDisplayName: "returnPromise",
|
||||
line: 19,
|
||||
column: 14
|
||||
},
|
||||
{
|
||||
functionDisplayName: "makePromise",
|
||||
line: 14,
|
||||
column: 15
|
||||
},
|
||||
];
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
|
||||
let options = {
|
||||
source: TAB_URL,
|
||||
line: 1
|
||||
};
|
||||
const [ tab, panel ] = yield initDebugger(TAB_URL, options);
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client);
|
||||
|
||||
let { tabs } = yield listTabs(client);
|
||||
let targetTab = findTab(tabs, TAB_URL);
|
||||
yield attachTarget(client, targetTab);
|
||||
|
||||
yield testGetFulfillmentStack(client, targetTab, tab);
|
||||
|
||||
yield close(client);
|
||||
yield closeDebuggerAndFinish(panel);
|
||||
}).catch(error => {
|
||||
ok(false, "Got an error: " + error.message + "\n" + error.stack);
|
||||
});
|
||||
}
|
||||
|
||||
function* testGetFulfillmentStack(client, form, tab) {
|
||||
let front = PromisesFront(client, form);
|
||||
|
||||
yield front.attach();
|
||||
yield front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
let onNewPromise = new Promise(resolve => {
|
||||
EventEmitter.on(front, "new-promises", promises => {
|
||||
for (let p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
callInTab(tab, "makePromise");
|
||||
|
||||
let grip = yield onNewPromise;
|
||||
ok(grip, "Found our promise p");
|
||||
|
||||
let objectClient = new ObjectClient(client, grip);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
yield new Promise(resolve => {
|
||||
objectClient.getPromiseFulfillmentStack(response => {
|
||||
ok(response.fulfillmentStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
let stack = response.fulfillmentStack[i];
|
||||
let data = TEST_DATA[i];
|
||||
is(stack.source.url, TAB_URL, "Got correct source URL.");
|
||||
is(stack.functionDisplayName, data.functionDisplayName,
|
||||
"Got correct function display name.");
|
||||
is(stack.line, data.line, "Got correct stack line number.");
|
||||
is(stack.column, data.column, "Got correct stack column number.");
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield front.detach();
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's rejection point.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_promise-get-rejection-stack.html";
|
||||
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
||||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
// The code in the document above leaves an uncaught rejection. This is only
|
||||
// reported to the testing framework if the code is loaded in the main process.
|
||||
if (!gMultiProcessBrowser) {
|
||||
ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
|
||||
PromiseTestUtils.expectUncaughtRejection(/hello/);
|
||||
}
|
||||
|
||||
const TEST_DATA = [
|
||||
{
|
||||
functionDisplayName: "returnPromise/<",
|
||||
line: 19,
|
||||
column: 47
|
||||
},
|
||||
{
|
||||
functionDisplayName: "returnPromise",
|
||||
line: 19,
|
||||
column: 14
|
||||
},
|
||||
{
|
||||
functionDisplayName: "makePromise",
|
||||
line: 14,
|
||||
column: 15
|
||||
},
|
||||
];
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
|
||||
let options = {
|
||||
source: TAB_URL,
|
||||
line: 1
|
||||
};
|
||||
const [ tab, panel ] = yield initDebugger(TAB_URL, options);
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client);
|
||||
|
||||
let { tabs } = yield listTabs(client);
|
||||
let targetTab = findTab(tabs, TAB_URL);
|
||||
yield attachTarget(client, targetTab);
|
||||
|
||||
yield testGetRejectionStack(client, targetTab, tab);
|
||||
|
||||
yield close(client);
|
||||
yield closeDebuggerAndFinish(panel);
|
||||
}).catch(error => {
|
||||
ok(false, "Got an error: " + error.message + "\n" + error.stack);
|
||||
});
|
||||
}
|
||||
|
||||
function* testGetRejectionStack(client, form, tab) {
|
||||
let front = PromisesFront(client, form);
|
||||
|
||||
yield front.attach();
|
||||
yield front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
let onNewPromise = new Promise(resolve => {
|
||||
EventEmitter.on(front, "new-promises", promises => {
|
||||
for (let p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
callInTab(tab, "makePromise");
|
||||
|
||||
let grip = yield onNewPromise;
|
||||
ok(grip, "Found our promise p");
|
||||
|
||||
let objectClient = new ObjectClient(client, grip);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
yield new Promise(resolve => {
|
||||
objectClient.getPromiseRejectionStack(response => {
|
||||
ok(response.rejectionStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
let stack = response.rejectionStack[i];
|
||||
let data = TEST_DATA[i];
|
||||
is(stack.source.url, TAB_URL, "Got correct source URL.");
|
||||
is(stack.functionDisplayName, data.functionDisplayName,
|
||||
"Got correct function display name.");
|
||||
is(stack.line, data.line, "Got correct stack line number.");
|
||||
is(stack.column, data.column, "Got correct stack column number.");
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield front.detach();
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that debuggee scripts are terminated on tab closure.
|
||||
*/
|
||||
|
||||
// The following rejection should not be left uncaught. This test has been
|
||||
// whitelisted until the issue is fixed.
|
||||
if (!gMultiProcessBrowser) {
|
||||
ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
|
||||
PromiseTestUtils.expectUncaughtRejection(/error\.message is undefined/);
|
||||
}
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_terminate-on-tab-close.html";
|
||||
|
||||
function test() {
|
||||
let options = {
|
||||
source: TAB_URL,
|
||||
line: 1
|
||||
};
|
||||
initDebugger(TAB_URL, options).then(([aTab, aPanel]) => {
|
||||
const gTab = aTab;
|
||||
const gPanel = aPanel;
|
||||
const gDebugger = gPanel.panelWin;
|
||||
|
||||
gDebugger.gThreadClient.addOneTimeListener("paused", () => {
|
||||
resumeDebuggerThenCloseAndFinish(gPanel).then(function () {
|
||||
ok(true, "should not throw after this point");
|
||||
});
|
||||
});
|
||||
|
||||
callInTab(gTab, "debuggerThenThrow");
|
||||
});
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Debugger test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
function debuggerThenThrow() {
|
||||
debugger;
|
||||
throw "unreachable";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
@ -473,7 +473,7 @@ ResponsiveUI.prototype = {
|
||||
this.client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
await this.client.connect();
|
||||
const { tab } = await this.client.getTab();
|
||||
this.emulationFront = EmulationFront(this.client, tab);
|
||||
this.emulationFront = new EmulationFront(this.client, tab);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -791,12 +791,13 @@ var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSpec, {
|
||||
initialize: function(client, { testActor }, toolbox) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: testActor });
|
||||
class TestActorFront extends protocol.FrontClassWithSpec(testSpec) {
|
||||
constructor(client, { testActor }, toolbox) {
|
||||
super(client, { actor: testActor });
|
||||
|
||||
this.manage(this);
|
||||
this.toolbox = toolbox;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom the current page to a given level.
|
||||
@ -805,19 +806,17 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
* @return {Promise} The returned promise will only resolve when the
|
||||
* highlighter has updated to the new zoom level.
|
||||
*/
|
||||
zoomPageTo: function(level, actorID = this.toolbox.highlighter.actorID) {
|
||||
zoomPageTo(level, actorID = this.toolbox.highlighter.actorID) {
|
||||
return this.changeZoomLevel(level, actorID);
|
||||
},
|
||||
}
|
||||
|
||||
/* eslint-disable max-len */
|
||||
changeHighlightedNodeWaitForUpdate: protocol.custom(function(name, value, highlighter) {
|
||||
changeHighlightedNodeWaitForUpdate(name, value, highlighter) {
|
||||
/* eslint-enable max-len */
|
||||
return this._changeHighlightedNodeWaitForUpdate(
|
||||
return super.changeHighlightedNodeWaitForUpdate(
|
||||
name, value, (highlighter || this.toolbox.highlighter).actorID
|
||||
);
|
||||
}, {
|
||||
impl: "_changeHighlightedNodeWaitForUpdate",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of an attribute on one of the highlighter's node.
|
||||
@ -826,27 +825,25 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
* @param {Object} highlighter Optional custom highlither to target
|
||||
* @return {String} value
|
||||
*/
|
||||
getHighlighterNodeAttribute: function(nodeID, name, highlighter) {
|
||||
getHighlighterNodeAttribute(nodeID, name, highlighter) {
|
||||
return this.getHighlighterAttribute(
|
||||
nodeID, name, (highlighter || this.toolbox.highlighter).actorID
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
getHighlighterNodeTextContent: protocol.custom(function(nodeID, highlighter) {
|
||||
return this._getHighlighterNodeTextContent(
|
||||
getHighlighterNodeTextContent(nodeID, highlighter) {
|
||||
return super.getHighlighterNodeTextContent(
|
||||
nodeID, (highlighter || this.toolbox.highlighter).actorID
|
||||
);
|
||||
}, {
|
||||
impl: "_getHighlighterNodeTextContent",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the highlighter currently visible on the page?
|
||||
*/
|
||||
isHighlighting: function() {
|
||||
isHighlighting() {
|
||||
return this.getHighlighterNodeAttribute("box-model-elements", "hidden")
|
||||
.then(value => value === null);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the box-model highlighter's current position corresponds to the
|
||||
@ -871,7 +868,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
prefix + boxType + " point " + point + " y coordinate is correct");
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current rect of the border region of the box-model highlighter
|
||||
@ -886,7 +883,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
width: p2.x - p1.x,
|
||||
height: p4.y - p1.y,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current positions and visibility of the various box-model highlighter
|
||||
@ -911,7 +908,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the box-model highlighter is currently highlighting the node matching the
|
||||
@ -922,7 +919,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
async assertHighlightedNode(selector) {
|
||||
const rect = await this.getNodeRect(selector);
|
||||
return this.isNodeRectHighlighted(rect);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the box-model highlighter is currently highlighting the text node that can
|
||||
@ -935,7 +932,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
async assertHighlightedTextNode(parentSelector, childNodeIndex) {
|
||||
const rect = await this.getTextNodeRect(parentSelector, childNodeIndex);
|
||||
return this.isNodeRectHighlighted(rect);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the box-model highlighter is currently highlighting the given rect.
|
||||
@ -966,7 +963,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
isInside([right, top], points) &&
|
||||
isInside([right, bottom], points) &&
|
||||
isInside([left, bottom], points);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the coordinate (points attribute) from one of the polygon elements in the
|
||||
@ -1002,7 +999,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
y: parseFloat(points[3][1]),
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a given region polygon element of the box-model highlighter currently
|
||||
@ -1011,7 +1008,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
async _isRegionHidden(region) {
|
||||
const value = await this.getHighlighterNodeAttribute("box-model-" + region, "hidden");
|
||||
return value !== null;
|
||||
},
|
||||
}
|
||||
|
||||
async _getGuideStatus(location) {
|
||||
const id = "box-model-guide-" + location;
|
||||
@ -1029,7 +1026,7 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
x2: x2,
|
||||
y2: y2,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the coordinates of the rectangle that is defined by the 4 guides displayed
|
||||
@ -1053,13 +1050,11 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
p3: {x: +rGuide.x1 + 1, y: +bGuide.y1 + 1},
|
||||
p4: {x: lGuide.x1, y: +bGuide.y1 + 1},
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
waitForHighlighterEvent: protocol.custom(function(event) {
|
||||
return this._waitForHighlighterEvent(event, this.toolbox.highlighter.actorID);
|
||||
}, {
|
||||
impl: "_waitForHighlighterEvent",
|
||||
}),
|
||||
waitForHighlighterEvent(event) {
|
||||
return super.waitForHighlighterEvent(event, this.toolbox.highlighter.actorID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "d" attribute value for one of the box-model highlighter's region
|
||||
@ -1092,8 +1087,9 @@ var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSp
|
||||
}
|
||||
|
||||
return {d, points};
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.TestActorFront = TestActorFront;
|
||||
|
||||
/**
|
||||
* Check whether a point is included in a polygon.
|
||||
|
@ -97,7 +97,7 @@ How do you get an initial reference to the front? That's a bit tricky, but basi
|
||||
|
||||
Manually - If you're using a DebuggerClient instance, you can discover the actorID manually and create a Front for it:
|
||||
|
||||
let hello = HelloFront(this.client, { actor: <hello actorID> });
|
||||
let hello = new HelloFront(this.client, { actor: <hello actorID> });
|
||||
|
||||
Magically - Once you have an initial reference to a protocol.js object, it can return other protocol.js objects and fronts will automatically be created.
|
||||
|
||||
|
@ -11,6 +11,9 @@ support-files =
|
||||
doc_force_gc.html
|
||||
doc_innerHTML.html
|
||||
doc_perf.html
|
||||
doc_promise-get-allocation-stack.html
|
||||
doc_promise-get-fulfillment-stack.html
|
||||
doc_promise-get-rejection-stack.html
|
||||
error-actor.js
|
||||
grid.html
|
||||
inspectedwindow-reload-target.sjs
|
||||
@ -102,3 +105,7 @@ skip-if = (verify && debug && (os == 'mac' || os == 'linux'))
|
||||
[browser_stylesheets_nested-iframes.js]
|
||||
[browser_register_actor.js]
|
||||
[browser_webextension_inspected_window.js]
|
||||
[browser_dbg_promises-allocation-stack.js]
|
||||
[browser_dbg_promises-chrome-allocation-stack.js]
|
||||
[browser_dbg_promises-fulfillment-stack.js]
|
||||
[browser_dbg_promises-rejection-stack.js]
|
||||
|
@ -0,0 +1,68 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's allocation point.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TAB_URL = URL_ROOT + "doc_promise-get-allocation-stack.html";
|
||||
|
||||
const ObjectClient = require("devtools/shared/client/object-client");
|
||||
|
||||
add_task(async function test() {
|
||||
const browser = await addTab(TAB_URL);
|
||||
const tab = gBrowser.getTabForBrowser(browser);
|
||||
const target = await TargetFactory.forTab(tab);
|
||||
await target.attach();
|
||||
|
||||
await testGetAllocationStack(tab, target);
|
||||
|
||||
await target.destroy();
|
||||
});
|
||||
|
||||
async function testGetAllocationStack(tab, target) {
|
||||
const front = await target.getFront("promises");
|
||||
|
||||
await front.attach();
|
||||
await front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
const onNewPromise = new Promise(resolve => {
|
||||
front.on("new-promises", promises => {
|
||||
for (const p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await ContentTask.spawn(tab.linkedBrowser, {}, () => {
|
||||
content.wrappedJSObject.makePromises();
|
||||
});
|
||||
|
||||
const form = await onNewPromise;
|
||||
ok(form, "Found our promise p");
|
||||
|
||||
const objectClient = new ObjectClient(target.client, form);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
const response = await objectClient.getPromiseAllocationStack();
|
||||
ok(response.allocationStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (const stack of response.allocationStack) {
|
||||
is(stack.source.url, TAB_URL, "Got correct source URL.");
|
||||
is(stack.functionDisplayName, "makePromises",
|
||||
"Got correct function display name.");
|
||||
is(typeof stack.line, "number", "Expect stack line to be a number.");
|
||||
is(typeof stack.column, "number",
|
||||
"Expect stack column to be a number.");
|
||||
}
|
||||
|
||||
await front.detach();
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's allocation point in the chrome
|
||||
* process.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const SOURCE_URL = "browser_dbg_promises-chrome-allocation-stack.js";
|
||||
|
||||
const ObjectClient = require("devtools/shared/client/object-client");
|
||||
|
||||
const STACK_DATA = [
|
||||
{ functionDisplayName: "test/<" },
|
||||
{ functionDisplayName: "testGetAllocationStack" },
|
||||
];
|
||||
|
||||
add_task(async function test() {
|
||||
requestLongerTimeout(10);
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
DebuggerServer.allowChromeProcess = true;
|
||||
|
||||
const client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
await client.connect();
|
||||
const targetFront = await client.mainRoot.getMainProcess();
|
||||
const target = await TargetFactory.forRemoteTab({
|
||||
client,
|
||||
activeTab: targetFront,
|
||||
chrome: true,
|
||||
});
|
||||
await target.attach();
|
||||
|
||||
await testGetAllocationStack(client, target, () => {
|
||||
const p = new Promise(() => {});
|
||||
p.name = "p";
|
||||
const q = p.then();
|
||||
q.name = "q";
|
||||
const r = p.catch(() => {});
|
||||
r.name = "r";
|
||||
});
|
||||
|
||||
await target.destroy();
|
||||
});
|
||||
|
||||
async function testGetAllocationStack(client, target, makePromises) {
|
||||
const front = await target.getFront("promises");
|
||||
|
||||
await front.attach();
|
||||
await front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
const onNewPromise = new Promise(resolve => {
|
||||
front.on("new-promises", promises => {
|
||||
for (const p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
makePromises();
|
||||
|
||||
const form = await onNewPromise;
|
||||
ok(form, "Found our promise p");
|
||||
|
||||
const objectClient = new ObjectClient(client, form);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
const response = await objectClient.getPromiseAllocationStack();
|
||||
ok(response.allocationStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let i = 0; i < STACK_DATA.length; i++) {
|
||||
const data = STACK_DATA[i];
|
||||
const stack = response.allocationStack[i];
|
||||
|
||||
ok(stack.source.url.startsWith("chrome:"), "Got a chrome source URL");
|
||||
ok(stack.source.url.endsWith(SOURCE_URL), "Got correct source URL.");
|
||||
is(stack.functionDisplayName, data.functionDisplayName,
|
||||
"Got correct function display name.");
|
||||
is(typeof stack.line, "number", "Expect stack line to be a number.");
|
||||
is(typeof stack.column, "number",
|
||||
"Expect stack column to be a number.");
|
||||
}
|
||||
|
||||
await front.detach();
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's fulfillment point.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TAB_URL = URL_ROOT + "doc_promise-get-fulfillment-stack.html";
|
||||
|
||||
const ObjectClient = require("devtools/shared/client/object-client");
|
||||
|
||||
const TEST_DATA = [
|
||||
{
|
||||
functionDisplayName: "returnPromise/<",
|
||||
line: 21,
|
||||
column: 37,
|
||||
},
|
||||
{
|
||||
functionDisplayName: "returnPromise",
|
||||
line: 21,
|
||||
column: 14,
|
||||
},
|
||||
{
|
||||
functionDisplayName: "makePromise",
|
||||
line: 16,
|
||||
column: 17,
|
||||
},
|
||||
];
|
||||
|
||||
add_task(async () => {
|
||||
const browser = await addTab(TAB_URL);
|
||||
const tab = gBrowser.getTabForBrowser(browser);
|
||||
const target = await TargetFactory.forTab(tab);
|
||||
await target.attach();
|
||||
|
||||
await testGetFulfillmentStack(tab, target);
|
||||
await target.destroy();
|
||||
});
|
||||
|
||||
async function testGetFulfillmentStack(tab, target) {
|
||||
const front = await target.getFront("promises");
|
||||
|
||||
await front.attach();
|
||||
await front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
const onNewPromise = new Promise(resolve => {
|
||||
front.on("new-promises", promises => {
|
||||
for (const p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await ContentTask.spawn(tab.linkedBrowser, {}, async function() {
|
||||
content.wrappedJSObject.makePromise();
|
||||
});
|
||||
|
||||
const form = await onNewPromise;
|
||||
ok(form, "Found our promise p");
|
||||
|
||||
const objectClient = new ObjectClient(target.client, form);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
const response = await objectClient.getPromiseFulfillmentStack();
|
||||
ok(response.fulfillmentStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
const stack = response.fulfillmentStack[i];
|
||||
const data = TEST_DATA[i];
|
||||
is(stack.source.url, TAB_URL, "Got correct source URL.");
|
||||
is(stack.functionDisplayName, data.functionDisplayName,
|
||||
"Got correct function display name.");
|
||||
is(stack.line, data.line, "Got correct stack line number.");
|
||||
is(stack.column, data.column, "Got correct stack column number.");
|
||||
}
|
||||
|
||||
await front.detach();
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can get a stack to a promise's rejection point.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TAB_URL = URL_ROOT + "doc_promise-get-rejection-stack.html";
|
||||
|
||||
const ObjectClient = require("devtools/shared/client/object-client");
|
||||
|
||||
// The code in the document above leaves an uncaught rejection. This is only
|
||||
// reported to the testing framework if the code is loaded in the main process.
|
||||
if (!gMultiProcessBrowser) {
|
||||
ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
|
||||
PromiseTestUtils.expectUncaughtRejection(/hello/);
|
||||
}
|
||||
|
||||
const TEST_DATA = [
|
||||
{
|
||||
functionDisplayName: "returnPromise/<",
|
||||
line: 21,
|
||||
column: 47,
|
||||
},
|
||||
{
|
||||
functionDisplayName: "returnPromise",
|
||||
line: 21,
|
||||
column: 14,
|
||||
},
|
||||
{
|
||||
functionDisplayName: "makePromise",
|
||||
line: 16,
|
||||
column: 17,
|
||||
},
|
||||
];
|
||||
|
||||
add_task(async () => {
|
||||
const browser = await addTab(TAB_URL);
|
||||
const tab = gBrowser.getTabForBrowser(browser);
|
||||
const target = await TargetFactory.forTab(tab);
|
||||
await target.attach();
|
||||
|
||||
await testGetRejectionStack(tab, target);
|
||||
await target.destroy();
|
||||
});
|
||||
|
||||
async function testGetRejectionStack(tab, target) {
|
||||
const front = await target.getFront("promises");
|
||||
|
||||
await front.attach();
|
||||
await front.listPromises();
|
||||
|
||||
// Get the grip for promise p
|
||||
const onNewPromise = new Promise(resolve => {
|
||||
front.on("new-promises", promises => {
|
||||
for (const p of promises) {
|
||||
if (p.preview.ownProperties.name &&
|
||||
p.preview.ownProperties.name.value === "p") {
|
||||
resolve(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await ContentTask.spawn(tab.linkedBrowser, {}, async function() {
|
||||
content.wrappedJSObject.makePromise();
|
||||
});
|
||||
|
||||
const form = await onNewPromise;
|
||||
ok(form, "Found our promise p");
|
||||
|
||||
const objectClient = new ObjectClient(target.client, form);
|
||||
ok(objectClient, "Got Object Client");
|
||||
|
||||
const response = await objectClient.getPromiseRejectionStack();
|
||||
ok(response.rejectionStack.length, "Got promise allocation stack.");
|
||||
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
const stack = response.rejectionStack[i];
|
||||
const data = TEST_DATA[i];
|
||||
is(stack.source.url, TAB_URL, "Got correct source URL.");
|
||||
is(stack.functionDisplayName, data.functionDisplayName,
|
||||
"Got correct function display name.");
|
||||
is(stack.line, data.line, "Got correct stack line number.");
|
||||
is(stack.column, data.column, "Got correct stack column number.");
|
||||
}
|
||||
|
||||
await front.detach();
|
||||
}
|
@ -29,11 +29,11 @@ add_task(async function() {
|
||||
const { client } = target;
|
||||
const form = targetFront.targetForm;
|
||||
|
||||
const inContentFront = InContentFront(client, form);
|
||||
const inContentFront = new InContentFront(client, form);
|
||||
const isInContent = await inContentFront.isInContent();
|
||||
ok(isInContent, "ContentActor really runs in the content process");
|
||||
const formSpawn = await inContentFront.spawnInParent(ACTOR_URL);
|
||||
const inParentFront = InParentFront(client, formSpawn);
|
||||
const inParentFront = new InParentFront(client, formSpawn);
|
||||
const {
|
||||
args,
|
||||
isInParent,
|
||||
|
@ -10,12 +10,15 @@
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function makePromises() {
|
||||
var p = new Promise(() => {});
|
||||
const p = new Promise(() => {});
|
||||
p.name = "p";
|
||||
var q = p.then();
|
||||
const q = p.then();
|
||||
q.name = "q";
|
||||
var r = p.catch(() => {});
|
||||
const r = p.catch(() => {});
|
||||
r.name = "r";
|
||||
}
|
||||
</script>
|
@ -10,8 +10,10 @@
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function makePromise() {
|
||||
var p = returnPromise();
|
||||
const p = returnPromise();
|
||||
p.name = "p";
|
||||
}
|
||||
|
@ -10,8 +10,10 @@
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function makePromise() {
|
||||
var p = returnPromise();
|
||||
const p = returnPromise();
|
||||
p.name = "p";
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
"use strict";
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec } = protocol;
|
||||
const { DebuggerServerConnection } = require("devtools/server/main");
|
||||
const Services = require("Services");
|
||||
|
||||
@ -51,13 +52,14 @@ exports.InContentActor = protocol.ActorClassWithSpec(inContentSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
exports.InContentFront = protocol.FrontClassWithSpec(inContentSpec, {
|
||||
initialize: function(client, tabForm) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class InContentFront extends FrontClassWithSpec(inContentSpec) {
|
||||
constructor(client, tabForm) {
|
||||
super(client, tabForm);
|
||||
this.actorID = tabForm.inContentActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.InContentFront = InContentFront;
|
||||
|
||||
const inParentSpec = protocol.generateActorSpec({
|
||||
typeName: "inParent",
|
||||
@ -91,10 +93,11 @@ exports.InParentActor = protocol.ActorClassWithSpec(inParentSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
exports.InParentFront = protocol.FrontClassWithSpec(inParentSpec, {
|
||||
initialize: function(client, tabForm) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class InParentFront extends FrontClassWithSpec(inParentSpec) {
|
||||
constructor(client, tabForm) {
|
||||
super(client, tabForm);
|
||||
this.actorID = tabForm.inParentActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.InParentFront = InParentFront;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var {RetVal, Actor, ActorClassWithSpec, Front, FrontClassWithSpec,
|
||||
var {RetVal, Actor, ActorClassWithSpec, FrontClassWithSpec,
|
||||
generateActorSpec} = require("devtools/shared/protocol");
|
||||
var Services = require("Services");
|
||||
|
||||
@ -31,12 +31,13 @@ exports.LazyActor = ActorClassWithSpec(lazySpec, {
|
||||
|
||||
Services.obs.notifyObservers(null, "actor", "loaded");
|
||||
|
||||
exports.LazyFront = FrontClassWithSpec(lazySpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client);
|
||||
class LazyFront extends FrontClassWithSpec(lazySpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.actorID = form.lazyActor;
|
||||
|
||||
client.addActorPool(this);
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.LazyFront = LazyFront;
|
||||
|
@ -27,7 +27,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
async function testAttach(client, parent) {
|
||||
const promises = PromisesFront(client, parent);
|
||||
const promises = new PromisesFront(client, parent);
|
||||
|
||||
try {
|
||||
await promises.detach();
|
||||
|
@ -34,7 +34,7 @@ add_task(async function() {
|
||||
async function testListPromises(client, form, makePromise) {
|
||||
const resolution = SECRET + Math.random();
|
||||
const promise = makePromise(resolution);
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
|
||||
await front.attach();
|
||||
|
||||
|
@ -35,7 +35,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
async function testNewPromisesEvent(client, form, makePromise) {
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
const resolution = "MyLittleSecret" + Math.random();
|
||||
let found = false;
|
||||
|
||||
|
@ -42,7 +42,7 @@ add_task(async function() {
|
||||
|
||||
async function testPromisesSettled(client, form, makeResolvePromise,
|
||||
makeRejectPromise) {
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
const resolution = "MyLittleSecret" + Math.random();
|
||||
|
||||
await front.attach();
|
||||
|
@ -50,7 +50,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
async function testGetDependentPromises(client, form, makePromises) {
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
|
||||
await front.attach();
|
||||
await front.listPromises();
|
||||
|
@ -45,7 +45,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
async function testPromiseCreationTimestamp(client, form, makePromise) {
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
const resolution = "MyLittleSecret" + Math.random();
|
||||
|
||||
await front.attach();
|
||||
|
@ -48,7 +48,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
async function testGetTimeToSettle(client, form, makePromises) {
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
|
||||
await front.attach();
|
||||
await front.listPromises();
|
||||
|
@ -37,7 +37,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
async function testGetTimeToSettle(client, form, makePromise) {
|
||||
const front = PromisesFront(client, form);
|
||||
const front = new PromisesFront(client, form);
|
||||
const resolution = "MyLittleSecret" + Math.random();
|
||||
let found = false;
|
||||
|
||||
|
@ -46,14 +46,14 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize: function(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
DebuggerServer.createRootActor = RootActor;
|
||||
@ -64,7 +64,7 @@ function run_test() {
|
||||
let rootFront;
|
||||
|
||||
client.connect().then(([applicationType, traits]) => {
|
||||
rootFront = RootFront(client);
|
||||
rootFront = new RootFront(client);
|
||||
|
||||
rootFront.simpleReturn().then(() => {
|
||||
ok(false, "Connection was aborted, request shouldn't resolve");
|
||||
|
@ -90,14 +90,14 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize: function(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
DebuggerServer.createRootActor = RootActor;
|
||||
@ -108,7 +108,7 @@ function run_test() {
|
||||
let rootFront;
|
||||
|
||||
client.connect().then(([applicationType, traits]) => {
|
||||
rootFront = RootFront(client);
|
||||
rootFront = new RootFront(client);
|
||||
|
||||
const calls = [];
|
||||
let sequence = 0;
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Test simple requests using the protocol helpers.
|
||||
*/
|
||||
var protocol = require("devtools/shared/protocol");
|
||||
var {preEvent, types, Arg, RetVal} = protocol;
|
||||
var {types, Arg, RetVal} = protocol;
|
||||
|
||||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
@ -162,46 +162,51 @@ var ChildActor = protocol.ActorClassWithSpec(childSpec, {
|
||||
release: function() { },
|
||||
});
|
||||
|
||||
var ChildFront = protocol.FrontClassWithSpec(childSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
},
|
||||
class ChildFront extends protocol.FrontClassWithSpec(childSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
destroy: function() {
|
||||
this.before("event1", this.onEvent1.bind(this));
|
||||
this.before("event2", this.onEvent2a.bind(this));
|
||||
this.on("event2", this.onEvent2b.bind(this));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
marshallPool: function() {
|
||||
marshallPool() {
|
||||
return this.parent();
|
||||
},
|
||||
}
|
||||
|
||||
toString: function() {
|
||||
toString() {
|
||||
return "[child front " + this.childID + "]";
|
||||
},
|
||||
}
|
||||
|
||||
form: function(form, detail) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
return;
|
||||
}
|
||||
this.childID = form.childID;
|
||||
this.detail = form.detail;
|
||||
},
|
||||
}
|
||||
|
||||
onEvent1: preEvent("event1", function(a, b, c) {
|
||||
onEvent1(a, b, c) {
|
||||
this.event1arg3 = c;
|
||||
}),
|
||||
}
|
||||
|
||||
onEvent2a: preEvent("event2", function(a, b, c) {
|
||||
onEvent2a(a, b, c) {
|
||||
return Promise.resolve().then(() => {
|
||||
this.event2arg3 = c;
|
||||
});
|
||||
}),
|
||||
}
|
||||
|
||||
onEvent2b: preEvent("event2", function(a, b, c) {
|
||||
onEvent2b(a, b, c) {
|
||||
this.event2arg2 = b;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
protocol.registerFront(ChildFront);
|
||||
|
||||
types.addDictType("manyChildrenDict", {
|
||||
child5: "childActor",
|
||||
@ -301,39 +306,36 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
toString: function() {
|
||||
return "[root front]";
|
||||
},
|
||||
initialize: function(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root actor owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
getTemporaryChild: protocol.custom(function(id) {
|
||||
toString() {
|
||||
return "[root front]";
|
||||
}
|
||||
|
||||
getTemporaryChild(id) {
|
||||
if (!this._temporaryHolder) {
|
||||
this._temporaryHolder = new protocol.Front(this.conn);
|
||||
this._temporaryHolder.actorID = this.actorID + "_temp";
|
||||
this.manage(this._temporaryHolder);
|
||||
}
|
||||
return this._getTemporaryChild(id);
|
||||
}, {
|
||||
impl: "_getTemporaryChild",
|
||||
}),
|
||||
return super.getTemporaryChild(id);
|
||||
}
|
||||
|
||||
clearTemporaryChildren: protocol.custom(function() {
|
||||
clearTemporaryChildren() {
|
||||
if (!this._temporaryHolder) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
this._temporaryHolder.destroy();
|
||||
delete this._temporaryHolder;
|
||||
return this._clearTemporaryChildren();
|
||||
}, {
|
||||
impl: "_clearTemporaryChildren",
|
||||
}),
|
||||
});
|
||||
return super.clearTemporaryChildren();
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
@ -349,7 +351,7 @@ function run_test() {
|
||||
"traits": []});
|
||||
Assert.equal(applicationType, "xpcshell-tests");
|
||||
|
||||
const rootFront = RootFront(client);
|
||||
const rootFront = new RootFront(client);
|
||||
let childFront = null;
|
||||
|
||||
const expectRootChildren = size => {
|
||||
|
@ -34,15 +34,16 @@ var ChildActor = protocol.ActorClassWithSpec(childSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var ChildFront = protocol.FrontClassWithSpec(childSpec, {
|
||||
initialize(client) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
},
|
||||
class ChildFront extends protocol.FrontClassWithSpec(childSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
}
|
||||
|
||||
form(v, ctx, detail) {
|
||||
this.extra = v.extra;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
protocol.registerFront(ChildFront);
|
||||
|
||||
const rootSpec = protocol.generateActorSpec({
|
||||
typeName: "root",
|
||||
@ -127,19 +128,19 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
form(v, ctx, detail) {
|
||||
this.lastForm = v;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const run_test = Test(async function() {
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
@ -158,7 +159,7 @@ const run_test = Test(async function() {
|
||||
// So override it again with test one before asserting.
|
||||
protocol.types.registeredTypes.get("root").actorSpec = rootSpec;
|
||||
|
||||
const rootFront = RootFront(conn);
|
||||
const rootFront = new RootFront(conn);
|
||||
|
||||
// Trigger some methods that return forms.
|
||||
let retval = await rootFront.getDefault();
|
||||
|
@ -85,14 +85,15 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize: function(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
@ -112,7 +113,7 @@ function run_test() {
|
||||
};
|
||||
|
||||
client.connect().then(([applicationType, traits]) => {
|
||||
rootFront = RootFront(client);
|
||||
rootFront = new RootFront(client);
|
||||
|
||||
// Root actor has no children yet.
|
||||
expectRootChildren(0);
|
||||
|
@ -69,23 +69,24 @@ const RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
const ChildFront = protocol.FrontClassWithSpec(childSpec, {
|
||||
class ChildFront extends protocol.FrontClassWithSpec(childSpec) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
return;
|
||||
}
|
||||
this.childID = form.childID;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
protocol.registerFront(ChildFront);
|
||||
|
||||
const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function run_test() {
|
||||
DebuggerServer.createRootActor = RootActor;
|
||||
|
@ -150,14 +150,14 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize: function(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
@ -166,10 +166,7 @@ function run_test() {
|
||||
DebuggerServer.init();
|
||||
|
||||
Assert.throws(() => {
|
||||
const badActor = protocol.ActorClassWithSpec({}, {
|
||||
missing: protocol.preEvent("missing-event", function() {
|
||||
}),
|
||||
});
|
||||
const badActor = protocol.ActorClassWithSpec({}, {});
|
||||
void badActor;
|
||||
}, /Actor specification must have a typeName member/);
|
||||
|
||||
@ -192,7 +189,7 @@ function run_test() {
|
||||
"traits": []});
|
||||
Assert.equal(applicationType, "xpcshell-tests");
|
||||
|
||||
rootFront = RootFront(client);
|
||||
rootFront = new RootFront(client);
|
||||
|
||||
rootFront.simpleReturn().then(ret => {
|
||||
trace.expectSend({"type": "simpleReturn", "to": "<actorid>"});
|
||||
|
@ -47,14 +47,14 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, {
|
||||
},
|
||||
});
|
||||
|
||||
var RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize: function(client) {
|
||||
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
if (!Services.prefs.getBoolPref("javascript.options.asyncstack")) {
|
||||
@ -70,7 +70,7 @@ function run_test() {
|
||||
let rootFront;
|
||||
|
||||
client.connect().then(function onConnect() {
|
||||
rootFront = RootFront(client);
|
||||
rootFront = new RootFront(client);
|
||||
|
||||
rootFront.simpleReturn().then(() => {
|
||||
let stack = Components.stack;
|
||||
|
@ -49,7 +49,7 @@ function test_lazy_api() {
|
||||
Assert.ok("lazyActor" in response);
|
||||
|
||||
const {LazyFront} = require("xpcshell-test/registertestactors-lazy");
|
||||
const front = LazyFront(client, response);
|
||||
const front = new LazyFront(client, response);
|
||||
front.hello().then(onRequest);
|
||||
}
|
||||
function onRequest(response) {
|
||||
|
@ -4,10 +4,8 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
custom,
|
||||
Front,
|
||||
FrontClassWithSpec,
|
||||
preEvent,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol.js");
|
||||
const {
|
||||
accessibleSpec,
|
||||
@ -16,58 +14,69 @@ const {
|
||||
} = require("devtools/shared/specs/accessibility");
|
||||
const events = require("devtools/shared/event-emitter");
|
||||
|
||||
const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
|
||||
initialize(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
},
|
||||
class AccessibleFront extends FrontClassWithSpec(accessibleSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
this.before("name-change", this.nameChange.bind(this));
|
||||
this.before("value-change", this.valueChange.bind(this));
|
||||
this.before("description-change", this.descriptionChange.bind(this));
|
||||
this.before("shortcut-change", this.shortcutChange.bind(this));
|
||||
this.before("reorder", this.reorder.bind(this));
|
||||
this.before("text-change", this.textChange.bind(this));
|
||||
this.before("index-in-parent-change", this.indexInParentChange.bind(this));
|
||||
this.before("states-change", this.statesChange.bind(this));
|
||||
this.before("actions-change", this.actionsChange.bind(this));
|
||||
this.before("attributes-change", this.attributesChange.bind(this));
|
||||
}
|
||||
|
||||
marshallPool() {
|
||||
return this.parent();
|
||||
},
|
||||
}
|
||||
|
||||
get role() {
|
||||
return this._form.role;
|
||||
},
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._form.name;
|
||||
},
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._form.value;
|
||||
},
|
||||
}
|
||||
|
||||
get description() {
|
||||
return this._form.description;
|
||||
},
|
||||
}
|
||||
|
||||
get keyboardShortcut() {
|
||||
return this._form.keyboardShortcut;
|
||||
},
|
||||
}
|
||||
|
||||
get childCount() {
|
||||
return this._form.childCount;
|
||||
},
|
||||
}
|
||||
|
||||
get domNodeType() {
|
||||
return this._form.domNodeType;
|
||||
},
|
||||
}
|
||||
|
||||
get indexInParent() {
|
||||
return this._form.indexInParent;
|
||||
},
|
||||
}
|
||||
|
||||
get states() {
|
||||
return this._form.states;
|
||||
},
|
||||
}
|
||||
|
||||
get actions() {
|
||||
return this._form.actions;
|
||||
},
|
||||
}
|
||||
|
||||
get attributes() {
|
||||
return this._form.attributes;
|
||||
},
|
||||
}
|
||||
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
@ -77,117 +86,126 @@ const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
|
||||
|
||||
this.actorID = form.actor;
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
nameChange: preEvent("name-change", function(name, parent, walker) {
|
||||
nameChange(name, parent, walker) {
|
||||
this._form.name = name;
|
||||
// Name change event affects the tree rendering, we fire this event on
|
||||
// accessibility walker as the point of interaction for UI.
|
||||
if (walker) {
|
||||
events.emit(walker, "name-change", this, parent);
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
valueChange: preEvent("value-change", function(value) {
|
||||
valueChange(value) {
|
||||
this._form.value = value;
|
||||
}),
|
||||
}
|
||||
|
||||
descriptionChange: preEvent("description-change", function(description) {
|
||||
descriptionChange(description) {
|
||||
this._form.description = description;
|
||||
}),
|
||||
}
|
||||
|
||||
shortcutChange: preEvent("shortcut-change", function(keyboardShortcut) {
|
||||
shortcutChange(keyboardShortcut) {
|
||||
this._form.keyboardShortcut = keyboardShortcut;
|
||||
}),
|
||||
}
|
||||
|
||||
reorder: preEvent("reorder", function(childCount, walker) {
|
||||
reorder(childCount, walker) {
|
||||
this._form.childCount = childCount;
|
||||
// Reorder event affects the tree rendering, we fire this event on
|
||||
// accessibility walker as the point of interaction for UI.
|
||||
if (walker) {
|
||||
events.emit(walker, "reorder", this);
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
textChange: preEvent("text-change", function(walker) {
|
||||
textChange(walker) {
|
||||
// Text event affects the tree rendering, we fire this event on
|
||||
// accessibility walker as the point of interaction for UI.
|
||||
if (walker) {
|
||||
events.emit(walker, "text-change", this);
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
indexInParentChange: preEvent("index-in-parent-change", function(indexInParent) {
|
||||
indexInParentChange(indexInParent) {
|
||||
this._form.indexInParent = indexInParent;
|
||||
}),
|
||||
}
|
||||
|
||||
statesChange: preEvent("states-change", function(states) {
|
||||
statesChange(states) {
|
||||
this._form.states = states;
|
||||
}),
|
||||
}
|
||||
|
||||
actionsChange: preEvent("actions-change", function(actions) {
|
||||
actionsChange(actions) {
|
||||
this._form.actions = actions;
|
||||
}),
|
||||
}
|
||||
|
||||
attributesChange: preEvent("attributes-change", function(attributes) {
|
||||
attributesChange(attributes) {
|
||||
this._form.attributes = attributes;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const AccessibleWalkerFront = FrontClassWithSpec(accessibleWalkerSpec, {
|
||||
accessibleDestroy: preEvent("accessible-destroy", function(accessible) {
|
||||
class AccessibleWalkerFront extends FrontClassWithSpec(accessibleWalkerSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.before("accessible-destroy", this.accessibleDestroy.bind(this));
|
||||
}
|
||||
|
||||
accessibleDestroy(accessible) {
|
||||
accessible.destroy();
|
||||
}),
|
||||
}
|
||||
|
||||
form(json) {
|
||||
this.actorID = json.actor;
|
||||
},
|
||||
}
|
||||
|
||||
pick: custom(function(doFocus) {
|
||||
pick(doFocus) {
|
||||
if (doFocus) {
|
||||
return this.pickAndFocus();
|
||||
}
|
||||
|
||||
return this._pick();
|
||||
}, {
|
||||
impl: "_pick",
|
||||
}),
|
||||
});
|
||||
return super.pick();
|
||||
}
|
||||
}
|
||||
|
||||
const AccessibilityFront = FrontClassWithSpec(accessibilitySpec, {
|
||||
initialize(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
class AccessibilityFront extends FrontClassWithSpec(accessibilitySpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.actorID = form.accessibilityActor;
|
||||
this.manage(this);
|
||||
},
|
||||
|
||||
bootstrap: custom(function() {
|
||||
return this._bootstrap().then(state => {
|
||||
this.before("init", this.init.bind(this));
|
||||
this.before("shutdown", this.shutdown.bind(this));
|
||||
this.before("can-be-enabled-change", this.canBeEnabled.bind(this));
|
||||
this.before("can-be-disabled-change", this.canBeDisabled.bind(this));
|
||||
}
|
||||
|
||||
bootstrap() {
|
||||
return super.bootstrap().then(state => {
|
||||
this.enabled = state.enabled;
|
||||
this.canBeEnabled = state.canBeEnabled;
|
||||
this.canBeDisabled = state.canBeDisabled;
|
||||
});
|
||||
}, {
|
||||
impl: "_bootstrap",
|
||||
}),
|
||||
}
|
||||
|
||||
init: preEvent("init", function() {
|
||||
init() {
|
||||
this.enabled = true;
|
||||
}),
|
||||
}
|
||||
|
||||
shutdown: preEvent("shutdown", function() {
|
||||
shutdown() {
|
||||
this.enabled = false;
|
||||
}),
|
||||
}
|
||||
|
||||
canBeEnabled: preEvent("can-be-enabled-change", function(canBeEnabled) {
|
||||
canBeEnabled(canBeEnabled) {
|
||||
this.canBeEnabled = canBeEnabled;
|
||||
}),
|
||||
}
|
||||
|
||||
canBeDisabled: preEvent("can-be-disabled-change", function(canBeDisabled) {
|
||||
canBeDisabled(canBeDisabled) {
|
||||
this.canBeDisabled = canBeDisabled;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.AccessibleFront = AccessibleFront;
|
||||
registerFront(AccessibleFront);
|
||||
exports.AccessibleWalkerFront = AccessibleWalkerFront;
|
||||
registerFront(AccessibleWalkerFront);
|
||||
exports.AccessibilityFront = AccessibilityFront;
|
||||
registerFront(AccessibilityFront);
|
||||
|
@ -6,18 +6,18 @@
|
||||
const { components } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { actorActorSpec, actorRegistrySpec } = require("devtools/shared/specs/actor-registry");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { custom } = protocol;
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
const ActorActorFront = protocol.FrontClassWithSpec(actorActorSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
},
|
||||
});
|
||||
class ActorActorFront extends FrontClassWithSpec(actorActorSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
}
|
||||
}
|
||||
|
||||
exports.ActorActorFront = ActorActorFront;
|
||||
registerFront(ActorActorFront);
|
||||
|
||||
function request(uri) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -46,22 +46,21 @@ function request(uri) {
|
||||
});
|
||||
}
|
||||
|
||||
const ActorRegistryFront = protocol.FrontClassWithSpec(actorRegistrySpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client,
|
||||
class ActorRegistryFront extends FrontClassWithSpec(actorRegistrySpec) {
|
||||
constructor(client, form) {
|
||||
super(client,
|
||||
{ actor: form.actorRegistryActor });
|
||||
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
registerActor: custom(function(uri, options) {
|
||||
registerActor(uri, options) {
|
||||
return request(uri, options)
|
||||
.then(sourceText => {
|
||||
return this._registerActor(sourceText, uri, options);
|
||||
return super.registerActor(sourceText, uri, options);
|
||||
});
|
||||
}, {
|
||||
impl: "_registerActor",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.ActorRegistryFront = ActorRegistryFront;
|
||||
registerFront(ActorRegistryFront);
|
||||
|
@ -4,14 +4,15 @@
|
||||
"use strict";
|
||||
|
||||
const {addonsSpec} = require("devtools/shared/specs/addon/addons");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
const AddonsFront = protocol.FrontClassWithSpec(addonsSpec, {
|
||||
initialize: function(client, {addonsActor}) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class AddonsFront extends FrontClassWithSpec(addonsSpec) {
|
||||
constructor(client, {addonsActor}) {
|
||||
super(client);
|
||||
this.actorID = addonsActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.AddonsFront = AddonsFront;
|
||||
registerFront(AddonsFront);
|
||||
|
@ -7,21 +7,20 @@ const {
|
||||
webExtensionInspectedWindowSpec,
|
||||
} = require("devtools/shared/specs/addon/webextension-inspected-window");
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the WebExtensionInspectedWindowActor.
|
||||
*/
|
||||
const WebExtensionInspectedWindowFront = protocol.FrontClassWithSpec(
|
||||
webExtensionInspectedWindowSpec,
|
||||
{
|
||||
initialize: function(client, { webExtensionInspectedWindowActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, {
|
||||
actor: webExtensionInspectedWindowActor,
|
||||
});
|
||||
this.manage(this);
|
||||
},
|
||||
class WebExtensionInspectedWindowFront extends
|
||||
FrontClassWithSpec(webExtensionInspectedWindowSpec) {
|
||||
constructor(client, { webExtensionInspectedWindowActor }) {
|
||||
super(client, {
|
||||
actor: webExtensionInspectedWindowActor,
|
||||
});
|
||||
this.manage(this);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
exports.WebExtensionInspectedWindowFront = WebExtensionInspectedWindowFront;
|
||||
registerFront(WebExtensionInspectedWindowFront);
|
||||
|
@ -4,35 +4,34 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
Front,
|
||||
FrontClassWithSpec,
|
||||
custom,
|
||||
preEvent,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const {
|
||||
animationPlayerSpec,
|
||||
animationsSpec,
|
||||
} = require("devtools/shared/specs/animation");
|
||||
|
||||
const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
|
||||
initialize: function(conn, form, detail, ctx) {
|
||||
Front.prototype.initialize.call(this, conn, form, detail, ctx);
|
||||
class AnimationPlayerFront extends FrontClassWithSpec(animationPlayerSpec) {
|
||||
constructor(conn, form, detail, ctx) {
|
||||
super(conn, form, detail, ctx);
|
||||
|
||||
this.state = {};
|
||||
},
|
||||
this.before("changed", this.onChanged.bind(this));
|
||||
}
|
||||
|
||||
form: function(form, detail) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this._form = form;
|
||||
this.state = this.initialState;
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the AnimationsActor was given a reference to the WalkerActor previously
|
||||
@ -44,7 +43,7 @@ const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
|
||||
}
|
||||
|
||||
return this.conn.getActor(this._form.animationTargetNodeActorID);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the initial state of the player. Up to date states can be
|
||||
@ -74,16 +73,16 @@ const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
|
||||
currentTimeAtCreated: this._form.currentTimeAtCreated,
|
||||
absoluteValues: this.calculateAbsoluteValues(this._form),
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed when the AnimationPlayerActor emits a "changed" event. Used to
|
||||
* update the local knowledge of the state.
|
||||
*/
|
||||
onChanged: preEvent("changed", function(partialState) {
|
||||
onChanged(partialState) {
|
||||
const {state} = this.reconstructState(partialState);
|
||||
this.state = state;
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the current state of this animation on the client from information
|
||||
@ -94,24 +93,22 @@ const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
|
||||
if (this.currentStateHasChanged) {
|
||||
this.state = data;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* getCurrentState interceptor re-constructs incomplete states since the actor
|
||||
* only sends the values that have changed.
|
||||
*/
|
||||
getCurrentState: custom(function() {
|
||||
getCurrentState() {
|
||||
this.currentStateHasChanged = false;
|
||||
return this._getCurrentState().then(partialData => {
|
||||
return super.getCurrentState().then(partialData => {
|
||||
const {state, hasChanged} = this.reconstructState(partialData);
|
||||
this.currentStateHasChanged = hasChanged;
|
||||
return state;
|
||||
});
|
||||
}, {
|
||||
impl: "_getCurrentState",
|
||||
}),
|
||||
}
|
||||
|
||||
reconstructState: function(data) {
|
||||
reconstructState(data) {
|
||||
let hasChanged = false;
|
||||
|
||||
for (const key in this.state) {
|
||||
@ -124,7 +121,7 @@ const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
|
||||
|
||||
data.absoluteValues = this.calculateAbsoluteValues(data);
|
||||
return {state: data, hasChanged};
|
||||
},
|
||||
}
|
||||
|
||||
calculateAbsoluteValues(data) {
|
||||
const {
|
||||
@ -198,20 +195,22 @@ const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
|
||||
startTime: absoluteStartTime,
|
||||
startTimeAtCreated: absoluteStartTimeAtCreated,
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.AnimationPlayerFront = AnimationPlayerFront;
|
||||
registerFront(AnimationPlayerFront);
|
||||
|
||||
const AnimationsFront = FrontClassWithSpec(animationsSpec, {
|
||||
initialize: function(client, {animationsActor}) {
|
||||
Front.prototype.initialize.call(this, client, {actor: animationsActor});
|
||||
class AnimationsFront extends FrontClassWithSpec(animationsSpec) {
|
||||
constructor(client, {animationsActor}) {
|
||||
super(client, {actor: animationsActor});
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
});
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.AnimationsFront = AnimationsFront;
|
||||
registerFront(AnimationsFront);
|
||||
|
@ -12,37 +12,35 @@ const {
|
||||
DRAW_CALLS,
|
||||
INTERESTING_CALLS,
|
||||
} = require("devtools/shared/specs/canvas");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const promise = require("promise");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FrameSnapshotActor.
|
||||
*/
|
||||
const FrameSnapshotFront = protocol.FrontClassWithSpec(frameSnapshotSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
class FrameSnapshotFront extends FrontClassWithSpec(frameSnapshotSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this._animationFrameEndScreenshot = null;
|
||||
this._cachedScreenshots = new WeakMap();
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation caches the animation frame end screenshot to optimize
|
||||
* frontend requests to `generateScreenshotFor`.
|
||||
*/
|
||||
getOverview: protocol.custom(function() {
|
||||
return this._getOverview().then(data => {
|
||||
getOverview() {
|
||||
return super.getOverview().then(data => {
|
||||
this._animationFrameEndScreenshot = data.screenshot;
|
||||
return data;
|
||||
});
|
||||
}, {
|
||||
impl: "_getOverview",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation saves a roundtrip to the backend if the screenshot
|
||||
* was already generated and retrieved once.
|
||||
*/
|
||||
generateScreenshotFor: protocol.custom(function(functionCall) {
|
||||
generateScreenshotFor(functionCall) {
|
||||
if (CanvasFront.ANIMATION_GENERATORS.has(functionCall.name) ||
|
||||
CanvasFront.LOOP_GENERATORS.has(functionCall.name)) {
|
||||
return promise.resolve(this._animationFrameEndScreenshot);
|
||||
@ -51,25 +49,24 @@ const FrameSnapshotFront = protocol.FrontClassWithSpec(frameSnapshotSpec, {
|
||||
if (cachedScreenshot) {
|
||||
return cachedScreenshot;
|
||||
}
|
||||
const screenshot = this._generateScreenshotFor(functionCall);
|
||||
const screenshot = super.generateScreenshotFor(functionCall);
|
||||
this._cachedScreenshots.set(functionCall, screenshot);
|
||||
return screenshot;
|
||||
}, {
|
||||
impl: "_generateScreenshotFor",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.FrameSnapshotFront = FrameSnapshotFront;
|
||||
registerFront(FrameSnapshotFront);
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the CanvasActor.
|
||||
*/
|
||||
const CanvasFront = protocol.FrontClassWithSpec(canvasSpec, {
|
||||
initialize: function(client, { canvasActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: canvasActor });
|
||||
class CanvasFront extends FrontClassWithSpec(canvasSpec) {
|
||||
constructor(client, { canvasActor }) {
|
||||
super(client, { actor: canvasActor });
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
@ -89,3 +86,4 @@ CanvasFront.INVALID_SNAPSHOT_IMAGE = {
|
||||
};
|
||||
|
||||
exports.CanvasFront = CanvasFront;
|
||||
registerFront(CanvasFront);
|
||||
|
@ -4,21 +4,22 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {changesSpec} = require("devtools/shared/specs/changes");
|
||||
|
||||
/**
|
||||
* ChangesFront, the front object for the ChangesActor
|
||||
*/
|
||||
const ChangesFront = protocol.FrontClassWithSpec(changesSpec, {
|
||||
initialize: function(client, {changesActor}) {
|
||||
protocol.Front.prototype.initialize.call(this, client, {actor: changesActor});
|
||||
class ChangesFront extends FrontClassWithSpec(changesSpec) {
|
||||
constructor(client, {changesActor}) {
|
||||
super(client, {actor: changesActor});
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
});
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.ChangesFront = ChangesFront;
|
||||
registerFront(ChangesFront);
|
||||
|
@ -9,7 +9,7 @@ loader.lazyRequireGetter(this, "CSS_PROPERTIES_DB",
|
||||
loader.lazyRequireGetter(this, "cssColors",
|
||||
"devtools/shared/css/color-db", true);
|
||||
|
||||
const { FrontClassWithSpec, Front } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { cssPropertiesSpec } = require("devtools/shared/specs/css-properties");
|
||||
|
||||
/**
|
||||
@ -42,12 +42,12 @@ var cachedCssProperties = new WeakMap();
|
||||
* interface that provides synchronous methods for finding out what CSS
|
||||
* properties the current server supports.
|
||||
*/
|
||||
const CssPropertiesFront = FrontClassWithSpec(cssPropertiesSpec, {
|
||||
initialize: function(client, { cssPropertiesActor }) {
|
||||
Front.prototype.initialize.call(this, client, {actor: cssPropertiesActor});
|
||||
class CssPropertiesFront extends FrontClassWithSpec(cssPropertiesSpec) {
|
||||
constructor(client, { cssPropertiesActor }) {
|
||||
super(client, {actor: cssPropertiesActor});
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the feature supporting status in the featureSet.
|
||||
@ -359,3 +359,4 @@ module.exports = {
|
||||
initCssProperties,
|
||||
isCssVariable,
|
||||
};
|
||||
registerFront(CssPropertiesFront);
|
||||
|
@ -4,8 +4,7 @@
|
||||
"use strict";
|
||||
|
||||
const {cssUsageSpec} = require("devtools/shared/specs/csscoverage");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {custom} = protocol;
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
const L10N = new LocalizationHelper("devtools/shared/locales/csscoverage.properties");
|
||||
@ -32,14 +31,15 @@ var chromeWindow;
|
||||
/**
|
||||
* Front for CSSUsageActor
|
||||
*/
|
||||
const CSSUsageFront = protocol.FrontClassWithSpec(cssUsageSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
class CSSUsageFront extends FrontClassWithSpec(cssUsageSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.actorID = form.cssUsageActor;
|
||||
this.manage(this);
|
||||
},
|
||||
this.before("state-change", this._onStateChange.bind(this));
|
||||
}
|
||||
|
||||
_onStateChange: protocol.preEvent("state-change", function(ev) {
|
||||
_onStateChange(ev) {
|
||||
isRunning = ev.isRunning;
|
||||
ev.target = target;
|
||||
|
||||
@ -70,38 +70,35 @@ const CSSUsageFront = protocol.FrontClassWithSpec(cssUsageSpec, {
|
||||
gDevTools.showToolbox(target, "styleeditor");
|
||||
target = undefined;
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side start is above. Client-side start adds a notification box
|
||||
*/
|
||||
start: custom(function(newChromeWindow, newTarget, noreload = false) {
|
||||
start(newChromeWindow, newTarget, noreload = false) {
|
||||
target = newTarget;
|
||||
chromeWindow = newChromeWindow;
|
||||
|
||||
return this._start(noreload);
|
||||
}, {
|
||||
impl: "_start",
|
||||
}),
|
||||
return super.start(noreload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side start is above. Client-side start adds a notification box
|
||||
*/
|
||||
toggle: custom(function(newChromeWindow, newTarget) {
|
||||
toggle(newChromeWindow, newTarget) {
|
||||
target = newTarget;
|
||||
chromeWindow = newChromeWindow;
|
||||
|
||||
return this._toggle();
|
||||
}, {
|
||||
impl: "_toggle",
|
||||
}),
|
||||
return super.toggle();
|
||||
}
|
||||
|
||||
/**
|
||||
* We count STARTING and STOPPING as 'running'
|
||||
*/
|
||||
isRunning: function() {
|
||||
isRunning() {
|
||||
return isRunning;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.CSSUsageFront = CSSUsageFront;
|
||||
registerFront(CSSUsageFront);
|
||||
|
@ -5,17 +5,17 @@
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
const {deviceSpec} = require("devtools/shared/specs/device");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const defer = require("devtools/shared/defer");
|
||||
|
||||
const DeviceFront = protocol.FrontClassWithSpec(deviceSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class DeviceFront extends FrontClassWithSpec(deviceSpec) {
|
||||
constructor(client, form) {
|
||||
super(client);
|
||||
this.actorID = form.deviceActor;
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
screenshotToBlob: function() {
|
||||
screenshotToBlob() {
|
||||
return this.screenshotToDataURL().then(longstr => {
|
||||
return longstr.string().then(dataURL => {
|
||||
const deferred = defer();
|
||||
@ -33,7 +33,8 @@ const DeviceFront = protocol.FrontClassWithSpec(deviceSpec, {
|
||||
return deferred.promise;
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.DeviceFront = DeviceFront;
|
||||
registerFront(DeviceFront);
|
||||
|
@ -3,22 +3,23 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { emulationSpec } = require("devtools/shared/specs/emulation");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the EmulationActor.
|
||||
*/
|
||||
const EmulationFront = FrontClassWithSpec(emulationSpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client);
|
||||
class EmulationFront extends FrontClassWithSpec(emulationSpec) {
|
||||
constructor(client, form) {
|
||||
super(client);
|
||||
this.actorID = form.emulationActor;
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
});
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.EmulationFront = EmulationFront;
|
||||
registerFront(EmulationFront);
|
||||
|
@ -3,17 +3,18 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { framerateSpec } = require("devtools/shared/specs/framerate");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FramerateActor.
|
||||
*/
|
||||
var FramerateFront = exports.FramerateFront = FrontClassWithSpec(framerateSpec, {
|
||||
initialize: function(client, { framerateActor }) {
|
||||
Front.prototype.initialize.call(this, client, { actor: framerateActor });
|
||||
class FramerateFront extends FrontClassWithSpec(framerateSpec) {
|
||||
constructor(client, { framerateActor }) {
|
||||
super(client, { actor: framerateActor });
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.FramerateFront = FramerateFront;
|
||||
registerFront(FramerateFront);
|
||||
|
@ -4,21 +4,21 @@
|
||||
"use strict";
|
||||
|
||||
const { functionCallSpec } = require("devtools/shared/specs/function-call");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FunctionCallActor.
|
||||
*/
|
||||
const FunctionCallFront = protocol.FrontClassWithSpec(functionCallSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
},
|
||||
class FunctionCallFront extends FrontClassWithSpec(functionCallSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some generic information directly to this instance,
|
||||
* to avoid extra roundtrips.
|
||||
*/
|
||||
form: function(form) {
|
||||
form(form) {
|
||||
this.actorID = form.actor;
|
||||
this.type = form.type;
|
||||
this.name = form.name;
|
||||
@ -28,10 +28,11 @@ const FunctionCallFront = protocol.FrontClassWithSpec(functionCallSpec, {
|
||||
this.callerPreview = form.callerPreview;
|
||||
this.argsPreview = form.argsPreview;
|
||||
this.resultPreview = form.resultPreview;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.FunctionCallFront = FunctionCallFront;
|
||||
registerFront(FunctionCallFront);
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
|
@ -3,30 +3,33 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, custom } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const flags = require("devtools/shared/flags");
|
||||
const {
|
||||
customHighlighterSpec,
|
||||
highlighterSpec,
|
||||
} = require("devtools/shared/specs/highlighters");
|
||||
|
||||
const HighlighterFront = FrontClassWithSpec(highlighterSpec, {
|
||||
isNodeFrontHighlighted: false,
|
||||
class HighlighterFront extends FrontClassWithSpec(highlighterSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
this.isNodeFrontHighlighted = false;
|
||||
}
|
||||
|
||||
// Update the object given a form representation off the wire.
|
||||
form: function(json) {
|
||||
form(json) {
|
||||
this.actorID = json.actor;
|
||||
// FF42+ HighlighterActors starts exposing custom form, with traits object
|
||||
this.traits = json.traits || {};
|
||||
},
|
||||
}
|
||||
|
||||
pick: custom(function(doFocus) {
|
||||
if (doFocus && this.pickAndFocus) {
|
||||
return this.pickAndFocus();
|
||||
pick(doFocus) {
|
||||
if (doFocus && super.pickAndFocus) {
|
||||
return super.pickAndFocus();
|
||||
}
|
||||
return this._pick();
|
||||
}, {
|
||||
impl: "_pick",
|
||||
}),
|
||||
return super.pick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the box model highlighter on a node in the content page.
|
||||
@ -36,7 +39,7 @@ const HighlighterFront = FrontClassWithSpec(highlighterSpec, {
|
||||
* @param {Object} options
|
||||
* @return A promise that resolves when the node has been highlighted
|
||||
*/
|
||||
highlight: async function(nodeFront, options = {}) {
|
||||
async highlight(nodeFront, options = {}) {
|
||||
if (!nodeFront) {
|
||||
return;
|
||||
}
|
||||
@ -44,7 +47,7 @@ const HighlighterFront = FrontClassWithSpec(highlighterSpec, {
|
||||
this.isNodeFrontHighlighted = true;
|
||||
await this.showBoxModel(nodeFront, options);
|
||||
this.emit("node-highlight", nodeFront);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the highlighter.
|
||||
@ -55,7 +58,7 @@ const HighlighterFront = FrontClassWithSpec(highlighterSpec, {
|
||||
* markup view, which is when this param is passed to true
|
||||
* @return a promise that resolves when the highlighter is hidden
|
||||
*/
|
||||
unhighlight: async function(forceHide = false) {
|
||||
async unhighlight(forceHide = false) {
|
||||
forceHide = forceHide || !flags.testing;
|
||||
|
||||
if (this.isNodeFrontHighlighted && forceHide) {
|
||||
@ -64,31 +67,33 @@ const HighlighterFront = FrontClassWithSpec(highlighterSpec, {
|
||||
}
|
||||
|
||||
this.emit("node-unhighlight");
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.HighlighterFront = HighlighterFront;
|
||||
registerFront(HighlighterFront);
|
||||
|
||||
const CustomHighlighterFront = FrontClassWithSpec(customHighlighterSpec, {
|
||||
_isShown: false,
|
||||
class CustomHighlighterFront extends FrontClassWithSpec(customHighlighterSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
show: custom(function(...args) {
|
||||
this._isShown = true;
|
||||
return this._show(...args);
|
||||
}, {
|
||||
impl: "_show",
|
||||
}),
|
||||
|
||||
hide: custom(function() {
|
||||
this._isShown = false;
|
||||
return this._hide();
|
||||
}, {
|
||||
impl: "_hide",
|
||||
}),
|
||||
}
|
||||
|
||||
isShown: function() {
|
||||
show(...args) {
|
||||
this._isShown = true;
|
||||
return super.show(...args);
|
||||
}
|
||||
|
||||
hide() {
|
||||
this._isShown = false;
|
||||
return super.hide();
|
||||
}
|
||||
|
||||
isShown() {
|
||||
return this._isShown;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.CustomHighlighterFront = CustomHighlighterFront;
|
||||
registerFront(CustomHighlighterFront);
|
||||
|
@ -11,11 +11,9 @@ const SHOW_ALL_ANONYMOUS_CONTENT_PREF = "devtools.inspector.showAllAnonymousCont
|
||||
const SHOW_UA_SHADOW_ROOTS_PREF = "devtools.inspector.showUserAgentShadowRoots";
|
||||
|
||||
const {
|
||||
Front,
|
||||
FrontClassWithSpec,
|
||||
custom,
|
||||
preEvent,
|
||||
types,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol.js");
|
||||
const {
|
||||
inspectorSpec,
|
||||
@ -34,39 +32,41 @@ loader.lazyRequireGetter(this, "flags",
|
||||
/**
|
||||
* Client side of the DOM walker.
|
||||
*/
|
||||
const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
// Set to true if cleanup should be requested after every mutation list.
|
||||
autoCleanup: true,
|
||||
|
||||
class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
||||
/**
|
||||
* This is kept for backward-compatibility reasons with older remote target.
|
||||
* Targets previous to bug 916443
|
||||
*/
|
||||
pick: custom(function() {
|
||||
return this._pick().then(response => {
|
||||
pick() {
|
||||
return super.pick().then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {impl: "_pick"}),
|
||||
}
|
||||
|
||||
initialize: function(client, form) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this._createRootNodePromise();
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
this._orphaned = new Set();
|
||||
this._retainedOrphans = new Set();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
// Set to true if cleanup should be requested after every mutation list.
|
||||
this.autoCleanup = true;
|
||||
|
||||
this.before("new-mutations", this.onMutations.bind(this));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
// Update the object given a form representation off the wire.
|
||||
form: function(json) {
|
||||
form(json) {
|
||||
this.actorID = json.actor;
|
||||
this.rootNode = types.getType("domnode").read(json.root, this);
|
||||
this._rootNodeDeferred.resolve(this.rootNode);
|
||||
// FF42+ the actor starts exposing traits
|
||||
this.traits = json.traits || {};
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Clients can use walker.rootNode to get the current root node of the
|
||||
@ -74,20 +74,20 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
* method returns a promise that will resolve to the root node when it is
|
||||
* set.
|
||||
*/
|
||||
getRootNode: function() {
|
||||
getRootNode() {
|
||||
return this._rootNodeDeferred.promise;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the root node promise, triggering the "new-root" notification
|
||||
* on resolution.
|
||||
*/
|
||||
_createRootNodePromise: function() {
|
||||
_createRootNodePromise() {
|
||||
this._rootNodeDeferred = defer();
|
||||
this._rootNodeDeferred.promise.then(() => {
|
||||
this.emit("new-root");
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* When reading an actor form off the wire, we want to hook it up to its
|
||||
@ -97,14 +97,14 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
* a bare-bones stand-in node. The stand-in node will be updated
|
||||
* with a real form by the end of the deserialization.
|
||||
*/
|
||||
ensureDOMNodeFront: function(id) {
|
||||
ensureDOMNodeFront(id) {
|
||||
const front = this.get(id);
|
||||
if (front) {
|
||||
return front;
|
||||
}
|
||||
|
||||
return types.getType("domnode").read({ actor: id }, this, "standin");
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* See the documentation for WalkerActor.prototype.retainNode for
|
||||
@ -126,84 +126,68 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
* semantics by setting our local retained flag on the node only AFTER
|
||||
* a SUCCESSFUL retainNode call.
|
||||
*/
|
||||
retainNode: custom(function(node) {
|
||||
return this._retainNode(node).then(() => {
|
||||
retainNode(node) {
|
||||
return super.retainNode(node).then(() => {
|
||||
node.retained = true;
|
||||
});
|
||||
}, {
|
||||
impl: "_retainNode",
|
||||
}),
|
||||
}
|
||||
|
||||
unretainNode: custom(function(node) {
|
||||
return this._unretainNode(node).then(() => {
|
||||
unretainNode(node) {
|
||||
return super.unretainNode(node).then(() => {
|
||||
node.retained = false;
|
||||
if (this._retainedOrphans.has(node)) {
|
||||
this._retainedOrphans.delete(node);
|
||||
this._releaseFront(node);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
impl: "_unretainNode",
|
||||
}),
|
||||
}
|
||||
|
||||
releaseNode: custom(function(node, options = {}) {
|
||||
releaseNode(node, options = {}) {
|
||||
// NodeFront.destroy will destroy children in the ownership tree too,
|
||||
// mimicking what the server will do here.
|
||||
const actorID = node.actorID;
|
||||
this._releaseFront(node, !!options.force);
|
||||
return this._releaseNode({ actorID: actorID });
|
||||
}, {
|
||||
impl: "_releaseNode",
|
||||
}),
|
||||
return super.releaseNode({ actorID: actorID });
|
||||
}
|
||||
|
||||
findInspectingNode: custom(function() {
|
||||
return this._findInspectingNode().then(response => {
|
||||
findInspectingNode() {
|
||||
return super.findInspectingNode().then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {
|
||||
impl: "_findInspectingNode",
|
||||
}),
|
||||
}
|
||||
|
||||
querySelector: custom(function(queryNode, selector) {
|
||||
return this._querySelector(queryNode, selector).then(response => {
|
||||
querySelector(queryNode, selector) {
|
||||
return super.querySelector(queryNode, selector).then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {
|
||||
impl: "_querySelector",
|
||||
}),
|
||||
}
|
||||
|
||||
gripToNodeFront: async function(grip) {
|
||||
async gripToNodeFront(grip) {
|
||||
const response = await this.getNodeActorFromObjectActor(grip.actor);
|
||||
const nodeFront = response ? response.node : null;
|
||||
if (!nodeFront) {
|
||||
throw new Error("The ValueGrip passed could not be translated to a NodeFront");
|
||||
}
|
||||
return nodeFront;
|
||||
},
|
||||
}
|
||||
|
||||
getNodeActorFromWindowID: custom(function(windowID) {
|
||||
return this._getNodeActorFromWindowID(windowID).then(response => {
|
||||
getNodeActorFromWindowID(windowID) {
|
||||
return super.getNodeActorFromWindowID(windowID).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getNodeActorFromWindowID",
|
||||
}),
|
||||
}
|
||||
|
||||
getStyleSheetOwnerNode: custom(function(styleSheetActorID) {
|
||||
return this._getStyleSheetOwnerNode(styleSheetActorID).then(response => {
|
||||
getStyleSheetOwnerNode(styleSheetActorID) {
|
||||
return super.getStyleSheetOwnerNode(styleSheetActorID).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getStyleSheetOwnerNode",
|
||||
}),
|
||||
}
|
||||
|
||||
getNodeFromActor: custom(function(actorID, path) {
|
||||
return this._getNodeFromActor(actorID, path).then(response => {
|
||||
getNodeFromActor(actorID, path) {
|
||||
return super.getNodeFromActor(actorID, path).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getNodeFromActor",
|
||||
}),
|
||||
}
|
||||
|
||||
/*
|
||||
* Incrementally search the document for a given string.
|
||||
@ -216,9 +200,9 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
* @param {Object} options
|
||||
* - "reverse": search backwards
|
||||
*/
|
||||
search: custom(async function(query, options = { }) {
|
||||
async search(query, options = { }) {
|
||||
const searchData = this.searchData = this.searchData || { };
|
||||
const result = await this._search(query, options);
|
||||
const result = await super.search(query, options);
|
||||
const nodeList = result.list;
|
||||
|
||||
// If this is a new search, start at the beginning.
|
||||
@ -249,11 +233,9 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
resultsLength: nodeList.length,
|
||||
resultsIndex: searchData.index,
|
||||
};
|
||||
}, {
|
||||
impl: "_search",
|
||||
}),
|
||||
}
|
||||
|
||||
_releaseFront: function(node, force) {
|
||||
_releaseFront(node, force) {
|
||||
if (node.retained && !force) {
|
||||
node.reparent(null);
|
||||
this._retainedOrphans.add(node);
|
||||
@ -273,13 +255,13 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
// All children will have been removed from the node by this point.
|
||||
node.reparent(null);
|
||||
node.destroy();
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any unprocessed mutation records and process them.
|
||||
*/
|
||||
getMutations: custom(function(options = {}) {
|
||||
return this._getMutations(options).then(mutations => {
|
||||
getMutations(options = {}) {
|
||||
return super.getMutations(options).then(mutations => {
|
||||
const emitMutations = [];
|
||||
for (const change of mutations) {
|
||||
// The target is only an actorID, get the associated front.
|
||||
@ -422,44 +404,42 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
|
||||
this.emit("mutations", emitMutations);
|
||||
});
|
||||
}, {
|
||||
impl: "_getMutations",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the `new-mutations` notification by fetching the
|
||||
* available mutation records.
|
||||
*/
|
||||
onMutations: preEvent("new-mutations", function() {
|
||||
onMutations() {
|
||||
// Fetch and process the mutations.
|
||||
this.getMutations({cleanup: this.autoCleanup}).catch(() => {});
|
||||
}),
|
||||
}
|
||||
|
||||
isLocal: function() {
|
||||
isLocal() {
|
||||
return !!this.conn._transport._serverConnection;
|
||||
},
|
||||
}
|
||||
|
||||
removeNode: custom(async function(node) {
|
||||
async removeNode(node) {
|
||||
const previousSibling = await this.previousSibling(node);
|
||||
const nextSibling = await this._removeNode(node);
|
||||
const nextSibling = await super.removeNode(node);
|
||||
return {
|
||||
previousSibling: previousSibling,
|
||||
nextSibling: nextSibling,
|
||||
};
|
||||
}, {
|
||||
impl: "_removeNode",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.WalkerFront = WalkerFront;
|
||||
registerFront(WalkerFront);
|
||||
|
||||
/**
|
||||
* Client side of the inspector actor, which is used to create
|
||||
* inspector-related actors, including the walker.
|
||||
*/
|
||||
var InspectorFront = FrontClassWithSpec(inspectorSpec, {
|
||||
initialize: async function(client, tabForm) {
|
||||
Front.prototype.initialize.call(this, client);
|
||||
class InspectorFront extends FrontClassWithSpec(inspectorSpec) {
|
||||
constructor(client, tabForm) {
|
||||
super(client, tabForm);
|
||||
|
||||
this.actorID = tabForm.inspectorActor;
|
||||
this._client = client;
|
||||
this._highlighters = new Map();
|
||||
@ -467,17 +447,19 @@ var InspectorFront = FrontClassWithSpec(inspectorSpec, {
|
||||
// XXX: This is the first actor type in its hierarchy to use the protocol
|
||||
// library, so we're going to self-own on the client side for now.
|
||||
this.manage(this);
|
||||
}
|
||||
|
||||
// async initialization
|
||||
// async initialization
|
||||
async initialize() {
|
||||
await Promise.all([
|
||||
this._getWalker(),
|
||||
this._getHighlighter(),
|
||||
]);
|
||||
|
||||
this.selection = new Selection(this.walker);
|
||||
},
|
||||
}
|
||||
|
||||
_getWalker: async function() {
|
||||
async _getWalker() {
|
||||
const showAllAnonymousContent = Services.prefs.getBoolPref(
|
||||
SHOW_ALL_ANONYMOUS_CONTENT_PREF);
|
||||
const showUserAgentShadowRoots = Services.prefs.getBoolPref(
|
||||
@ -486,18 +468,18 @@ var InspectorFront = FrontClassWithSpec(inspectorSpec, {
|
||||
showAllAnonymousContent,
|
||||
showUserAgentShadowRoots,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_getHighlighter: async function() {
|
||||
async _getHighlighter() {
|
||||
const autohide = !flags.testing;
|
||||
this.highlighter = await this.getHighlighter(autohide);
|
||||
},
|
||||
}
|
||||
|
||||
hasHighlighter(type) {
|
||||
return this._highlighters.has(type);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
destroy() {
|
||||
// Selection isn't a Front and so isn't managed by InspectorFront
|
||||
// and has to be destroyed manually
|
||||
this.selection.destroy();
|
||||
@ -505,41 +487,40 @@ var InspectorFront = FrontClassWithSpec(inspectorSpec, {
|
||||
// automatically destroyed. But we have to clear the `_highlighters`
|
||||
// Map as well as explicitly call `finalize` request on all of them.
|
||||
this.destroyHighlighters();
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
destroyHighlighters: function() {
|
||||
destroyHighlighters() {
|
||||
for (const type of this._highlighters.keys()) {
|
||||
if (this._highlighters.has(type)) {
|
||||
this._highlighters.get(type).finalize();
|
||||
this._highlighters.delete(type);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getKnownHighlighter: function(type) {
|
||||
getKnownHighlighter(type) {
|
||||
return this._highlighters.get(type);
|
||||
},
|
||||
}
|
||||
|
||||
getOrCreateHighlighterByType: async function(type) {
|
||||
async getOrCreateHighlighterByType(type) {
|
||||
let front = this._highlighters.get(type);
|
||||
if (!front) {
|
||||
front = await this.getHighlighterByType(type);
|
||||
this._highlighters.set(type, front);
|
||||
}
|
||||
return front;
|
||||
},
|
||||
}
|
||||
|
||||
pickColorFromPage: custom(async function(options) {
|
||||
await this._pickColorFromPage(options);
|
||||
async pickColorFromPage(options) {
|
||||
await super.pickColorFromPage(options);
|
||||
if (options && options.fromMenu) {
|
||||
telemetry.getHistogramById(TELEMETRY_EYEDROPPER_OPENED_MENU).add(true);
|
||||
} else {
|
||||
telemetry.getHistogramById(TELEMETRY_EYEDROPPER_OPENED).add(true);
|
||||
}
|
||||
}, {
|
||||
impl: "_pickColorFromPage",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.InspectorFront = InspectorFront;
|
||||
registerFront(InspectorFront);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
flexboxSpec,
|
||||
flexItemSpec,
|
||||
@ -12,14 +12,14 @@ const {
|
||||
layoutSpec,
|
||||
} = require("devtools/shared/specs/layout");
|
||||
|
||||
const FlexboxFront = FrontClassWithSpec(flexboxSpec, {
|
||||
form: function(form, detail) {
|
||||
class FlexboxFront extends FrontClassWithSpec(flexboxSpec) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* In some cases, the FlexboxActor already knows the NodeActor ID of the node where the
|
||||
@ -31,31 +31,31 @@ const FlexboxFront = FrontClassWithSpec(flexboxSpec, {
|
||||
}
|
||||
|
||||
return this.conn.getActor(this._form.containerNodeActorID);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the computed style properties for the flex container.
|
||||
*/
|
||||
get properties() {
|
||||
return this._form.properties;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const FlexItemFront = FrontClassWithSpec(flexItemSpec, {
|
||||
form: function(form, detail) {
|
||||
class FlexItemFront extends FrontClassWithSpec(flexItemSpec) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the flex item sizing data.
|
||||
*/
|
||||
get flexItemSizing() {
|
||||
return this._form.flexItemSizing;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* In some cases, the FlexItemActor already knows the NodeActor ID of the node where the
|
||||
@ -67,31 +67,31 @@ const FlexItemFront = FrontClassWithSpec(flexItemSpec, {
|
||||
}
|
||||
|
||||
return this.conn.getActor(this._form.nodeActorID);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the computed style properties for the flex item.
|
||||
*/
|
||||
get computedStyle() {
|
||||
return this._form.computedStyle;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style properties for the flex item.
|
||||
*/
|
||||
get properties() {
|
||||
return this._form.properties;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const GridFront = FrontClassWithSpec(gridSpec, {
|
||||
form: function(form, detail) {
|
||||
class GridFront extends FrontClassWithSpec(gridSpec) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* In some cases, the GridActor already knows the NodeActor ID of the node where the
|
||||
@ -103,7 +103,7 @@ const GridFront = FrontClassWithSpec(gridSpec, {
|
||||
}
|
||||
|
||||
return this.conn.getActor(this._form.containerNodeActorID);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text direction of the grid container.
|
||||
@ -115,14 +115,14 @@ const GridFront = FrontClassWithSpec(gridSpec, {
|
||||
}
|
||||
|
||||
return this._form.direction;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the grid fragments data.
|
||||
*/
|
||||
get gridFragments() {
|
||||
return this._form.gridFragments;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the writing mode of the grid container.
|
||||
@ -134,12 +134,17 @@ const GridFront = FrontClassWithSpec(gridSpec, {
|
||||
}
|
||||
|
||||
return this._form.writingMode;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const LayoutFront = FrontClassWithSpec(layoutSpec, {});
|
||||
class LayoutFront extends FrontClassWithSpec(layoutSpec) {
|
||||
}
|
||||
|
||||
exports.FlexboxFront = FlexboxFront;
|
||||
registerFront(FlexboxFront);
|
||||
exports.FlexItemFront = FlexItemFront;
|
||||
registerFront(FlexItemFront);
|
||||
exports.GridFront = GridFront;
|
||||
registerFront(GridFront);
|
||||
exports.LayoutFront = LayoutFront;
|
||||
registerFront(LayoutFront);
|
||||
|
@ -4,21 +4,21 @@
|
||||
"use strict";
|
||||
|
||||
const { memorySpec } = require("devtools/shared/specs/memory");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyRequireGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
|
||||
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
|
||||
const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
class MemoryFront extends FrontClassWithSpec(memorySpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this._client = client;
|
||||
this.actorID = form.memoryActor;
|
||||
this.heapSnapshotFileActorID = null;
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a heap snapshot, transfer it from the server to the client if the
|
||||
@ -38,8 +38,8 @@ const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
||||
*
|
||||
* @returns Promise<String>
|
||||
*/
|
||||
saveHeapSnapshot: protocol.custom(async function(options = {}) {
|
||||
const snapshotId = await this._saveHeapSnapshotImpl(options.boundaries);
|
||||
async saveHeapSnapshot(options = {}) {
|
||||
const snapshotId = await super.saveHeapSnapshot(options.boundaries);
|
||||
|
||||
if (!options.forceCopy &&
|
||||
(await HeapSnapshotFileUtils.haveHeapSnapshotTempFile(snapshotId))) {
|
||||
@ -47,9 +47,7 @@ const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
||||
}
|
||||
|
||||
return this.transferHeapSnapshot(snapshotId);
|
||||
}, {
|
||||
impl: "_saveHeapSnapshotImpl",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Given that we have taken a heap snapshot with the given id, transfer the
|
||||
@ -60,7 +58,7 @@ const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
||||
*
|
||||
* @returns Promise<String>
|
||||
*/
|
||||
transferHeapSnapshot: protocol.custom(async function(snapshotId) {
|
||||
async transferHeapSnapshot(snapshotId) {
|
||||
if (!this.heapSnapshotFileActorID) {
|
||||
const form = await this._client.mainRoot.rootForm;
|
||||
this.heapSnapshotFileActorID = form.heapSnapshotFileActor;
|
||||
@ -99,7 +97,8 @@ const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
||||
// Otherwise, rethrow the error
|
||||
throw e;
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.MemoryFront = MemoryFront;
|
||||
registerFront(MemoryFront);
|
||||
|
@ -4,10 +4,9 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
Front,
|
||||
FrontClassWithSpec,
|
||||
custom,
|
||||
types,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol.js");
|
||||
|
||||
const {
|
||||
@ -26,42 +25,39 @@ const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||
/**
|
||||
* Client side of a node list as returned by querySelectorAll()
|
||||
*/
|
||||
const NodeListFront = FrontClassWithSpec(nodeListSpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
},
|
||||
class NodeListFront extends FrontClassWithSpec(nodeListSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
marshallPool: function() {
|
||||
marshallPool() {
|
||||
return this.parent();
|
||||
},
|
||||
}
|
||||
|
||||
// Update the object given a form representation off the wire.
|
||||
form: function(json) {
|
||||
form(json) {
|
||||
this.length = json.length;
|
||||
},
|
||||
}
|
||||
|
||||
item: custom(function(index) {
|
||||
return this._item(index).then(response => {
|
||||
item(index) {
|
||||
return super.item(index).then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {
|
||||
impl: "_item",
|
||||
}),
|
||||
}
|
||||
|
||||
items: custom(function(start, end) {
|
||||
return this._items(start, end).then(response => {
|
||||
items(start, end) {
|
||||
return super.items(start, end).then(response => {
|
||||
return response.nodes;
|
||||
});
|
||||
}, {
|
||||
impl: "_items",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.NodeListFront = NodeListFront;
|
||||
registerFront(NodeListFront);
|
||||
|
||||
/**
|
||||
* Convenience API for building a list of attribute modifications
|
||||
@ -118,8 +114,9 @@ class AttributeModificationList {
|
||||
* the parent node from clients, but the `children` request should be used
|
||||
* to traverse children.
|
||||
*/
|
||||
const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
initialize: function(conn, form, detail, ctx) {
|
||||
class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
||||
constructor(conn, form, detail, ctx) {
|
||||
super(conn, form, detail, ctx);
|
||||
// The parent node
|
||||
this._parent = null;
|
||||
// The first child of this node.
|
||||
@ -128,20 +125,19 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
this._next = null;
|
||||
// The previous sibling of this node.
|
||||
this._prev = null;
|
||||
Front.prototype.initialize.call(this, conn, form, detail, ctx);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a node front. The node must have been removed from the
|
||||
* ownership tree before this is called, unless the whole walker front
|
||||
* is being destroyed.
|
||||
*/
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
// Update the object given a form representation off the wire.
|
||||
form: function(form, detail, ctx) {
|
||||
form(form, detail, ctx) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
@ -177,22 +173,22 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
} else {
|
||||
this.inlineTextChild = undefined;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent NodeFront for this NodeFront.
|
||||
*/
|
||||
parentNode: function() {
|
||||
parentNode() {
|
||||
return this._parent;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the NodeFront corresponding to the parentNode of this NodeFront, or the
|
||||
* NodeFront corresponding to the host element for shadowRoot elements.
|
||||
*/
|
||||
parentOrHost: function() {
|
||||
parentOrHost() {
|
||||
return this.isShadowRoot ? this.host : this._parent;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a mutation entry as returned from the walker's `getMutations`
|
||||
@ -200,7 +196,7 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
* themselves (character data and attribute changes), the walker itself
|
||||
* will keep the ownership tree up to date.
|
||||
*/
|
||||
updateMutation: function(change) {
|
||||
updateMutation(change) {
|
||||
if (change.type === "attributes") {
|
||||
// We'll need to lazily reparse the attributes after this change.
|
||||
this._attrMap = undefined;
|
||||
@ -236,140 +232,140 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
} else if (change.type === "events") {
|
||||
this._form.hasEventListeners = change.hasEventListeners;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Some accessors to make NodeFront feel more like a Node
|
||||
|
||||
get id() {
|
||||
return this.getAttribute("id");
|
||||
},
|
||||
}
|
||||
|
||||
get nodeType() {
|
||||
return this._form.nodeType;
|
||||
},
|
||||
}
|
||||
get namespaceURI() {
|
||||
return this._form.namespaceURI;
|
||||
},
|
||||
}
|
||||
get nodeName() {
|
||||
return this._form.nodeName;
|
||||
},
|
||||
}
|
||||
get displayName() {
|
||||
const {displayName, nodeName} = this._form;
|
||||
|
||||
// Keep `nodeName.toLowerCase()` for backward compatibility
|
||||
return displayName || nodeName.toLowerCase();
|
||||
},
|
||||
}
|
||||
get doctypeString() {
|
||||
return "<!DOCTYPE " + this._form.name +
|
||||
(this._form.publicId ? " PUBLIC \"" + this._form.publicId + "\"" : "") +
|
||||
(this._form.systemId ? " \"" + this._form.systemId + "\"" : "") +
|
||||
">";
|
||||
},
|
||||
}
|
||||
|
||||
get baseURI() {
|
||||
return this._form.baseURI;
|
||||
},
|
||||
}
|
||||
|
||||
get className() {
|
||||
return this.getAttribute("class") || "";
|
||||
},
|
||||
}
|
||||
|
||||
get hasChildren() {
|
||||
return this._form.numChildren > 0;
|
||||
},
|
||||
}
|
||||
get numChildren() {
|
||||
return this._form.numChildren;
|
||||
},
|
||||
}
|
||||
get hasEventListeners() {
|
||||
return this._form.hasEventListeners;
|
||||
},
|
||||
}
|
||||
|
||||
get isBeforePseudoElement() {
|
||||
return this._form.isBeforePseudoElement;
|
||||
},
|
||||
}
|
||||
get isAfterPseudoElement() {
|
||||
return this._form.isAfterPseudoElement;
|
||||
},
|
||||
}
|
||||
get isPseudoElement() {
|
||||
return this.isBeforePseudoElement || this.isAfterPseudoElement;
|
||||
},
|
||||
}
|
||||
get isAnonymous() {
|
||||
return this._form.isAnonymous;
|
||||
},
|
||||
}
|
||||
get isInHTMLDocument() {
|
||||
return this._form.isInHTMLDocument;
|
||||
},
|
||||
}
|
||||
get tagName() {
|
||||
return this.nodeType === nodeConstants.ELEMENT_NODE ? this.nodeName : null;
|
||||
},
|
||||
}
|
||||
|
||||
get isDocumentElement() {
|
||||
return !!this._form.isDocumentElement;
|
||||
},
|
||||
}
|
||||
|
||||
get isShadowRoot() {
|
||||
return this._form.isShadowRoot;
|
||||
},
|
||||
}
|
||||
|
||||
get shadowRootMode() {
|
||||
return this._form.shadowRootMode;
|
||||
},
|
||||
}
|
||||
|
||||
get isShadowHost() {
|
||||
return this._form.isShadowHost;
|
||||
},
|
||||
}
|
||||
|
||||
get customElementLocation() {
|
||||
return this._form.customElementLocation;
|
||||
},
|
||||
}
|
||||
|
||||
get isDirectShadowHostChild() {
|
||||
return this._form.isDirectShadowHostChild;
|
||||
},
|
||||
}
|
||||
|
||||
// doctype properties
|
||||
get name() {
|
||||
return this._form.name;
|
||||
},
|
||||
}
|
||||
get publicId() {
|
||||
return this._form.publicId;
|
||||
},
|
||||
}
|
||||
get systemId() {
|
||||
return this._form.systemId;
|
||||
},
|
||||
}
|
||||
|
||||
getAttribute: function(name) {
|
||||
getAttribute(name) {
|
||||
const attr = this._getAttribute(name);
|
||||
return attr ? attr.value : null;
|
||||
},
|
||||
hasAttribute: function(name) {
|
||||
}
|
||||
hasAttribute(name) {
|
||||
this._cacheAttributes();
|
||||
return (name in this._attrMap);
|
||||
},
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
const cls = this.getAttribute("class");
|
||||
return cls && cls.indexOf(HIDDEN_CLASS) > -1;
|
||||
},
|
||||
}
|
||||
|
||||
get attributes() {
|
||||
return this._form.attrs;
|
||||
},
|
||||
}
|
||||
|
||||
get pseudoClassLocks() {
|
||||
return this._form.pseudoClassLocks || [];
|
||||
},
|
||||
hasPseudoClassLock: function(pseudo) {
|
||||
}
|
||||
hasPseudoClassLock(pseudo) {
|
||||
return this.pseudoClassLocks.some(locked => locked === pseudo);
|
||||
},
|
||||
}
|
||||
|
||||
get displayType() {
|
||||
return this._form.displayType;
|
||||
},
|
||||
}
|
||||
|
||||
get isDisplayed() {
|
||||
return this._form.isDisplayed;
|
||||
},
|
||||
}
|
||||
|
||||
get isTreeDisplayed() {
|
||||
let parent = this;
|
||||
@ -380,29 +376,27 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
parent = parent.parentNode();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
getNodeValue: custom(function() {
|
||||
getNodeValue() {
|
||||
// backward-compatibility: if nodevalue is null and shortValue is defined, the actual
|
||||
// value of the node needs to be fetched on the server.
|
||||
if (this._form.nodeValue === null && this._form.shortValue) {
|
||||
return this._getNodeValue();
|
||||
return super.getNodeValue();
|
||||
}
|
||||
|
||||
const str = this._form.nodeValue || "";
|
||||
return promise.resolve(new SimpleStringFront(str));
|
||||
}, {
|
||||
impl: "_getNodeValue",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new AttributeModificationList for this node.
|
||||
*/
|
||||
startModifyingAttributes: function() {
|
||||
startModifyingAttributes() {
|
||||
return new AttributeModificationList(this);
|
||||
},
|
||||
}
|
||||
|
||||
_cacheAttributes: function() {
|
||||
_cacheAttributes() {
|
||||
if (typeof this._attrMap != "undefined") {
|
||||
return;
|
||||
}
|
||||
@ -410,19 +404,19 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
for (const attr of this.attributes) {
|
||||
this._attrMap[attr.name] = attr;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getAttribute: function(name) {
|
||||
_getAttribute(name) {
|
||||
this._cacheAttributes();
|
||||
return this._attrMap[name] || undefined;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this node's parent. Note that the children saved in
|
||||
* this tree are unordered and incomplete, so shouldn't be used
|
||||
* instead of a `children` request.
|
||||
*/
|
||||
reparent: function(parent) {
|
||||
reparent(parent) {
|
||||
if (this._parent === parent) {
|
||||
return;
|
||||
}
|
||||
@ -448,18 +442,18 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
this._next._prev = this;
|
||||
}
|
||||
parent._child = this;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the known children of this node.
|
||||
*/
|
||||
treeChildren: function() {
|
||||
treeChildren() {
|
||||
const ret = [];
|
||||
for (let child = this._child; child != null; child = child._next) {
|
||||
ret.push(child);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we use a local target?
|
||||
@ -468,16 +462,16 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
* This will, one day, be removed. External code should
|
||||
* not need to know if the target is remote or not.
|
||||
*/
|
||||
isLocalToBeDeprecated: function() {
|
||||
isLocalToBeDeprecated() {
|
||||
return !!this.conn._transport._serverConnection;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Node for the given node front. This only works locally,
|
||||
* and is only intended as a stopgap during the transition to the remote
|
||||
* protocol. If you depend on this you're likely to break soon.
|
||||
*/
|
||||
rawNode: function(rawNode) {
|
||||
rawNode(rawNode) {
|
||||
if (!this.isLocalToBeDeprecated()) {
|
||||
console.warn("Tried to use rawNode on a remote connection.");
|
||||
return null;
|
||||
@ -490,7 +484,8 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
|
||||
return null;
|
||||
}
|
||||
return actor.rawNode;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.NodeFront = NodeFront;
|
||||
registerFront(NodeFront);
|
||||
|
@ -3,13 +3,15 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, Front } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { perfSpec } = require("devtools/shared/specs/perf");
|
||||
|
||||
exports.PerfFront = FrontClassWithSpec(perfSpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
class PerfFront extends FrontClassWithSpec(perfSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.actorID = form.perfActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registerFront(PerfFront);
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { performanceRecordingSpec } = require("devtools/shared/specs/performance-recording");
|
||||
|
||||
loader.lazyRequireGetter(this, "PerformanceIO",
|
||||
@ -17,9 +17,8 @@ loader.lazyRequireGetter(this, "RecordingUtils",
|
||||
* This can be used on older Profiler implementations, but the methods cannot
|
||||
* be changed -- you must introduce a new method, and detect the server.
|
||||
*/
|
||||
const PerformanceRecordingFront = FrontClassWithSpec(performanceRecordingSpec,
|
||||
Object.assign({
|
||||
form: function(form, detail) {
|
||||
class PerformanceRecordingFront extends FrontClassWithSpec(performanceRecordingSpec) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
@ -49,20 +48,20 @@ Object.assign({
|
||||
this._markers = this._markers.sort((a, b) => (a.start > b.start));
|
||||
this._markersSorted = true;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
initialize: function(client, form, config) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
constructor(client, form, config) {
|
||||
super(client, form);
|
||||
this._markers = [];
|
||||
this._frames = [];
|
||||
this._memory = [];
|
||||
this._ticks = [];
|
||||
this._allocations = { sites: [], timestamps: [], frames: [], sizes: [] };
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current recording to a file.
|
||||
@ -70,15 +69,15 @@ Object.assign({
|
||||
* @param nsIFile file
|
||||
* The file to stream the data into.
|
||||
*/
|
||||
exportRecording: function(file) {
|
||||
exportRecording(file) {
|
||||
const recordingData = this.getAllData();
|
||||
return PerformanceIO.saveRecordingToFile(recordingData, file);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired whenever the PerformanceFront emits markers, memory or ticks.
|
||||
*/
|
||||
_addTimelineData: function(eventName, data) {
|
||||
_addTimelineData(eventName, data) {
|
||||
const config = this.getConfiguration();
|
||||
|
||||
switch (eventName) {
|
||||
@ -144,9 +143,18 @@ Object.assign({
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toString: () => "[object PerformanceRecordingFront]",
|
||||
}, PerformanceRecordingCommon));
|
||||
toString() {
|
||||
return "[object PerformanceRecordingFront]";
|
||||
}
|
||||
}
|
||||
|
||||
// PerformanceRecordingFront also needs to inherit from PerformanceRecordingCommon
|
||||
// but as ES classes don't support multiple inheritance, we are overriding the
|
||||
// prototype with PerformanceRecordingCommon methods.
|
||||
Object.defineProperties(PerformanceRecordingFront.prototype,
|
||||
Object.getOwnPropertyDescriptors(PerformanceRecordingCommon));
|
||||
|
||||
exports.PerformanceRecordingFront = PerformanceRecordingFront;
|
||||
registerFront(PerformanceRecordingFront);
|
||||
|
@ -4,7 +4,7 @@
|
||||
"use strict";
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const { Front, FrontClassWithSpec, custom, preEvent } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { PerformanceRecordingFront } = require("devtools/shared/fronts/performance-recording");
|
||||
const { performanceSpec } = require("devtools/shared/specs/performance");
|
||||
|
||||
@ -13,30 +13,31 @@ loader.lazyRequireGetter(this, "PerformanceIO",
|
||||
loader.lazyRequireGetter(this, "getSystemInfo",
|
||||
"devtools/shared/system", true);
|
||||
|
||||
const PerformanceFront = FrontClassWithSpec(performanceSpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
class PerformanceFront extends FrontClassWithSpec(performanceSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.actorID = form.performanceActor;
|
||||
this.manage(this);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
this.before("profiler-status", this._onProfilerStatus.bind(this));
|
||||
this.before("timeline-data", this._onTimelineEvent.bind(this));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Conenct to the server, and handle once-off tasks like storing traits
|
||||
* or system info.
|
||||
*/
|
||||
connect: custom(async function() {
|
||||
async connect() {
|
||||
const systemClient = await getSystemInfo();
|
||||
const { traits } = await this._connect({ systemClient });
|
||||
const { traits } = await super.connect({ systemClient });
|
||||
this._traits = traits;
|
||||
|
||||
return this._traits;
|
||||
}, {
|
||||
impl: "_connect",
|
||||
}),
|
||||
}
|
||||
|
||||
get traits() {
|
||||
if (!this._traits) {
|
||||
@ -44,7 +45,7 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, {
|
||||
"calling `connect()`.");
|
||||
}
|
||||
return this._traits;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass in a PerformanceRecording and get a normalized value from 0 to 1 of how much
|
||||
@ -53,7 +54,7 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, {
|
||||
* @param {PerformanceRecording} recording
|
||||
* @return {number?}
|
||||
*/
|
||||
getBufferUsageForRecording: function(recording) {
|
||||
getBufferUsageForRecording(recording) {
|
||||
if (!recording.isRecording()) {
|
||||
return void 0;
|
||||
}
|
||||
@ -82,7 +83,7 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, {
|
||||
}
|
||||
|
||||
return percent;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a recording from a file.
|
||||
@ -91,7 +92,7 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, {
|
||||
* The file to import the data from.
|
||||
* @return {Promise<PerformanceRecordingFront>}
|
||||
*/
|
||||
importRecording: function(file) {
|
||||
importRecording(file) {
|
||||
return PerformanceIO.loadRecordingFromFile(file).then(recordingData => {
|
||||
const model = new PerformanceRecordingFront();
|
||||
model._imported = true;
|
||||
@ -108,26 +109,27 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, {
|
||||
model._systemClient = recordingData.systemClient;
|
||||
return model;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Store profiler status when the position has been update so we can
|
||||
* calculate recording's buffer percentage usage after emitting the event.
|
||||
*/
|
||||
_onProfilerStatus: preEvent("profiler-status", function(data) {
|
||||
_onProfilerStatus(data) {
|
||||
this._currentBufferStatus = data;
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* For all PerformanceRecordings that are recording, and needing realtime markers,
|
||||
* apply the timeline data to the front PerformanceRecording (so we only have one event
|
||||
* for each timeline data chunk as they could be shared amongst several recordings).
|
||||
*/
|
||||
_onTimelineEvent: preEvent("timeline-data", function(type, data, recordings) {
|
||||
_onTimelineEvent(type, data, recordings) {
|
||||
for (const recording of recordings) {
|
||||
recording._addTimelineData(type, data);
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.PerformanceFront = PerformanceFront;
|
||||
registerFront(PerformanceFront);
|
||||
|
@ -4,14 +4,15 @@
|
||||
"use strict";
|
||||
|
||||
const {preferenceSpec} = require("devtools/shared/specs/preference");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
const PreferenceFront = protocol.FrontClassWithSpec(preferenceSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class PreferenceFront extends FrontClassWithSpec(preferenceSpec) {
|
||||
constructor(client, form) {
|
||||
super(client);
|
||||
this.actorID = form.preferenceActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.PreferenceFront = PreferenceFront;
|
||||
registerFront(PreferenceFront);
|
||||
|
@ -4,24 +4,25 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
Front,
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { promisesSpec } = require("devtools/shared/specs/promises");
|
||||
|
||||
/**
|
||||
* PromisesFront, the front for the PromisesActor.
|
||||
*/
|
||||
const PromisesFront = FrontClassWithSpec(promisesSpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
class PromisesFront extends FrontClassWithSpec(promisesSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
this.actorID = form.promisesActor;
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
});
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.PromisesFront = PromisesFront;
|
||||
registerFront(PromisesFront);
|
||||
|
@ -5,25 +5,26 @@
|
||||
"use strict";
|
||||
|
||||
const {reflowSpec} = require("devtools/shared/specs/reflow");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
/**
|
||||
* Usage example of the reflow front:
|
||||
*
|
||||
* let front = ReflowFront(toolbox.target.client, toolbox.target.form);
|
||||
* let front = new ReflowFront(toolbox.target.client, toolbox.target.form);
|
||||
* front.on("reflows", this._onReflows);
|
||||
* front.start();
|
||||
* // now wait for events to come
|
||||
*/
|
||||
const ReflowFront = protocol.FrontClassWithSpec(reflowSpec, {
|
||||
initialize: function(client, {reflowActor}) {
|
||||
protocol.Front.prototype.initialize.call(this, client, {actor: reflowActor});
|
||||
class ReflowFront extends FrontClassWithSpec(reflowSpec) {
|
||||
constructor(client, {reflowActor}) {
|
||||
super(client, {actor: reflowActor});
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
});
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.ReflowFront = ReflowFront;
|
||||
registerFront(ReflowFront);
|
||||
|
@ -5,16 +5,15 @@
|
||||
|
||||
const {Ci} = require("chrome");
|
||||
const {rootSpec} = require("devtools/shared/specs/root");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {custom} = protocol;
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true);
|
||||
loader.lazyRequireGetter(this, "BrowsingContextTargetFront", "devtools/shared/fronts/targets/browsing-context", true);
|
||||
loader.lazyRequireGetter(this, "ContentProcessTargetFront", "devtools/shared/fronts/targets/content-process", true);
|
||||
|
||||
const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: form.from });
|
||||
class RootFront extends FrontClassWithSpec(rootSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, { actor: form.from });
|
||||
|
||||
this.applicationType = form.applicationType;
|
||||
this.traits = form.traits;
|
||||
@ -34,7 +33,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
this.fronts = new Map();
|
||||
|
||||
this._client = client;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all service worker registrations as well as workers from the parent and
|
||||
@ -51,7 +50,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
* - {Array} other
|
||||
* Array of WorkerTargetActor forms, containing other workers.
|
||||
*/
|
||||
listAllWorkers: async function() {
|
||||
async listAllWorkers() {
|
||||
let registrations = [];
|
||||
let workers = [];
|
||||
|
||||
@ -132,7 +131,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the ParentProcessTargetActor for the main process.
|
||||
@ -142,13 +141,13 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
*/
|
||||
getMainProcess() {
|
||||
return this.getProcess(0);
|
||||
},
|
||||
}
|
||||
|
||||
getProcess: custom(async function(id) {
|
||||
async getProcess(id) {
|
||||
// Do not use specification automatic marshalling as getProcess may return
|
||||
// two different type: ParentProcessTargetActor or ContentProcessTargetActor.
|
||||
// Also, we do want to memoize the fronts and return already existing ones.
|
||||
const { form } = await this._getProcess(id);
|
||||
const { form } = await super.getProcess(id);
|
||||
let front = this.actor(form.actor);
|
||||
if (front) {
|
||||
return front;
|
||||
@ -167,9 +166,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
this.manage(front);
|
||||
|
||||
return front;
|
||||
}, {
|
||||
impl: "_getProcess",
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the target actor for the currently selected tab, or for a specific
|
||||
@ -183,7 +180,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
* If nothing is specified, returns the actor for the currently
|
||||
* selected tab.
|
||||
*/
|
||||
getTab: custom(async function(filter) {
|
||||
async getTab(filter) {
|
||||
const packet = {};
|
||||
if (filter) {
|
||||
if (typeof (filter.outerWindowID) == "number") {
|
||||
@ -210,10 +207,8 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
}
|
||||
}
|
||||
|
||||
return this._getTab(packet);
|
||||
}, {
|
||||
impl: "_getTab",
|
||||
}),
|
||||
return super.getTab(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the target front for a given add-on.
|
||||
@ -227,7 +222,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
const addons = await this.listAddons();
|
||||
const addonTargetFront = addons.find(addon => addon.id === id);
|
||||
return addonTargetFront;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Test request that returns the object passed as first argument.
|
||||
@ -239,7 +234,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
echo(packet) {
|
||||
packet.type = "echo";
|
||||
return this.request(packet);
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a protocol.js Front for any root actor.
|
||||
@ -257,6 +252,7 @@ const RootFront = protocol.FrontClassWithSpec(rootSpec, {
|
||||
front = getFront(this._client, typeName, rootForm);
|
||||
this.fronts.set(typeName, front);
|
||||
return front;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.RootFront = RootFront;
|
||||
registerFront(RootFront);
|
||||
|
@ -5,19 +5,20 @@
|
||||
|
||||
const {screenshotSpec} = require("devtools/shared/specs/screenshot");
|
||||
const saveScreenshot = require("devtools/shared/screenshot/save");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
const ScreenshotFront = protocol.FrontClassWithSpec(screenshotSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class ScreenshotFront extends FrontClassWithSpec(screenshotSpec) {
|
||||
constructor(client, form) {
|
||||
super(client);
|
||||
this.actorID = form.screenshotActor;
|
||||
this.manage(this);
|
||||
},
|
||||
}
|
||||
|
||||
async captureAndSave(window, args) {
|
||||
const screenshot = await this.capture(args);
|
||||
return saveScreenshot(window, args, screenshot);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.ScreenshotFront = ScreenshotFront;
|
||||
registerFront(ScreenshotFront);
|
||||
|
@ -3,11 +3,11 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const specs = require("devtools/shared/specs/storage");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { childSpecs, storageSpec } = require("devtools/shared/specs/storage");
|
||||
|
||||
for (const childSpec of Object.values(specs.childSpecs)) {
|
||||
protocol.FrontClassWithSpec(childSpec, {
|
||||
for (const childSpec of Object.values(childSpecs)) {
|
||||
class ChildStorageFront extends FrontClassWithSpec(childSpec) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
@ -17,16 +17,18 @@ for (const childSpec of Object.values(specs.childSpecs)) {
|
||||
this.actorID = form.actor;
|
||||
this.hosts = form.hosts;
|
||||
return null;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
registerFront(ChildStorageFront);
|
||||
}
|
||||
|
||||
const StorageFront = protocol.FrontClassWithSpec(specs.storageSpec, {
|
||||
initialize(client, tabForm) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class StorageFront extends FrontClassWithSpec(storageSpec) {
|
||||
constructor(client, tabForm) {
|
||||
super(client);
|
||||
this.actorID = tabForm.storageActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.StorageFront = StorageFront;
|
||||
registerFront(StorageFront);
|
||||
|
@ -6,27 +6,27 @@
|
||||
const {DebuggerServer} = require("devtools/server/main");
|
||||
const promise = require("promise");
|
||||
const {longStringSpec, SimpleStringFront} = require("devtools/shared/specs/string");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
const LongStringFront = protocol.FrontClassWithSpec(longStringSpec, {
|
||||
initialize: function(client) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
},
|
||||
class LongStringFront extends FrontClassWithSpec(longStringSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
destroy() {
|
||||
this.initial = null;
|
||||
this.length = null;
|
||||
this.strPromise = null;
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
form: function(form) {
|
||||
form(form) {
|
||||
this.actorID = form.actor;
|
||||
this.initial = form.initial;
|
||||
this.length = form.length;
|
||||
},
|
||||
}
|
||||
|
||||
string: function() {
|
||||
string() {
|
||||
if (!this.strPromise) {
|
||||
const promiseRest = (thusFar) => {
|
||||
if (thusFar.length === this.length) {
|
||||
@ -40,8 +40,10 @@ const LongStringFront = protocol.FrontClassWithSpec(longStringSpec, {
|
||||
this.strPromise = promiseRest(this.initial);
|
||||
}
|
||||
return this.strPromise;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.LongStringFront = LongStringFront;
|
||||
registerFront(LongStringFront);
|
||||
exports.SimpleStringFront = SimpleStringFront;
|
||||
registerFront(SimpleStringFront);
|
||||
|
@ -4,10 +4,8 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
Front,
|
||||
FrontClassWithSpec,
|
||||
custom,
|
||||
preEvent,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const {
|
||||
pageStyleSpec,
|
||||
@ -21,57 +19,55 @@ loader.lazyRequireGetter(this, "RuleRewriter",
|
||||
/**
|
||||
* PageStyleFront, the front object for the PageStyleActor
|
||||
*/
|
||||
const PageStyleFront = FrontClassWithSpec(pageStyleSpec, {
|
||||
initialize: function(conn, form, ctx, detail) {
|
||||
Front.prototype.initialize.call(this, conn, form, ctx, detail);
|
||||
class PageStyleFront extends FrontClassWithSpec(pageStyleSpec) {
|
||||
constructor(conn, form, ctx, detail) {
|
||||
super(conn, form, ctx, detail);
|
||||
this.inspector = this.parent();
|
||||
},
|
||||
}
|
||||
|
||||
form: function(form, detail) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
get walker() {
|
||||
return this.inspector.walker;
|
||||
},
|
||||
}
|
||||
|
||||
get supportsAuthoredStyles() {
|
||||
return this._form.traits && this._form.traits.authoredStyles;
|
||||
},
|
||||
}
|
||||
|
||||
get supportsFontStretchLevel4() {
|
||||
return this._form.traits && this._form.traits.fontStretchLevel4;
|
||||
},
|
||||
}
|
||||
|
||||
get supportsFontStyleLevel4() {
|
||||
return this._form.traits && this._form.traits.fontStyleLevel4;
|
||||
},
|
||||
}
|
||||
|
||||
get supportsFontVariations() {
|
||||
return this._form.traits && this._form.traits.fontVariations;
|
||||
},
|
||||
}
|
||||
|
||||
get supportsFontWeightLevel4() {
|
||||
return this._form.traits && this._form.traits.fontWeightLevel4;
|
||||
},
|
||||
}
|
||||
|
||||
getMatchedSelectors: custom(function(node, property, options) {
|
||||
return this._getMatchedSelectors(node, property, options).then(ret => {
|
||||
getMatchedSelectors(node, property, options) {
|
||||
return super.getMatchedSelectors(node, property, options).then(ret => {
|
||||
return ret.matched;
|
||||
});
|
||||
}, {
|
||||
impl: "_getMatchedSelectors",
|
||||
}),
|
||||
}
|
||||
|
||||
getApplied: custom(async function(node, options = {}) {
|
||||
async getApplied(node, options = {}) {
|
||||
// If the getApplied method doesn't recreate the style cache itself, this
|
||||
// means a call to cssLogic.highlight is required before trying to access
|
||||
// the applied rules. Issue a request to getLayout if this is the case.
|
||||
@ -79,42 +75,41 @@ const PageStyleFront = FrontClassWithSpec(pageStyleSpec, {
|
||||
if (!this._form.traits || !this._form.traits.getAppliedCreatesStyleCache) {
|
||||
await this.getLayout(node);
|
||||
}
|
||||
const ret = await this._getApplied(node, options);
|
||||
const ret = await super.getApplied(node, options);
|
||||
return ret.entries;
|
||||
}, {
|
||||
impl: "_getApplied",
|
||||
}),
|
||||
}
|
||||
|
||||
addNewRule: custom(function(node, pseudoClasses) {
|
||||
addNewRule(node, pseudoClasses) {
|
||||
let addPromise;
|
||||
if (this.supportsAuthoredStyles) {
|
||||
addPromise = this._addNewRule(node, pseudoClasses, true);
|
||||
addPromise = super.addNewRule(node, pseudoClasses, true);
|
||||
} else {
|
||||
addPromise = this._addNewRule(node, pseudoClasses);
|
||||
addPromise = super.addNewRule(node, pseudoClasses);
|
||||
}
|
||||
return addPromise.then(ret => {
|
||||
return ret.entries[0];
|
||||
});
|
||||
}, {
|
||||
impl: "_addNewRule",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.PageStyleFront = PageStyleFront;
|
||||
registerFront(PageStyleFront);
|
||||
|
||||
/**
|
||||
* StyleRuleFront, the front for the StyleRule actor.
|
||||
*/
|
||||
const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
initialize: function(client, form, ctx, detail) {
|
||||
Front.prototype.initialize.call(this, client, form, ctx, detail);
|
||||
},
|
||||
class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
|
||||
constructor(client, form, ctx, detail) {
|
||||
super(client, form, ctx, detail);
|
||||
|
||||
destroy: function() {
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
this.before("location-changed", this._locationChangedPre.bind(this));
|
||||
}
|
||||
|
||||
form: function(form, detail) {
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
@ -124,16 +119,16 @@ const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
if (this._mediaText) {
|
||||
this._mediaText = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure _form is updated when location-changed is emitted.
|
||||
*/
|
||||
_locationChangedPre: preEvent("location-changed", function(line, column) {
|
||||
_locationChangedPre(line, column) {
|
||||
this._clearOriginalLocation();
|
||||
this._form.line = line;
|
||||
this._form.column = column;
|
||||
}),
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new RuleModificationList or RuleRewriter for this node.
|
||||
@ -145,43 +140,43 @@ const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
* This is needed by the RuleRewriter.
|
||||
* @return {RuleModificationList}
|
||||
*/
|
||||
startModifyingProperties: function(cssProperties) {
|
||||
startModifyingProperties(cssProperties) {
|
||||
if (this.canSetRuleText) {
|
||||
return new RuleRewriter(cssProperties.isKnown, this, this.authoredText);
|
||||
}
|
||||
return new RuleModificationList(this);
|
||||
},
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._form.type;
|
||||
},
|
||||
}
|
||||
get line() {
|
||||
return this._form.line || -1;
|
||||
},
|
||||
}
|
||||
get column() {
|
||||
return this._form.column || -1;
|
||||
},
|
||||
}
|
||||
get cssText() {
|
||||
return this._form.cssText;
|
||||
},
|
||||
}
|
||||
get authoredText() {
|
||||
return this._form.authoredText || this._form.cssText;
|
||||
},
|
||||
}
|
||||
get declarations() {
|
||||
return this._form.declarations || [];
|
||||
},
|
||||
}
|
||||
get keyText() {
|
||||
return this._form.keyText;
|
||||
},
|
||||
}
|
||||
get name() {
|
||||
return this._form.name;
|
||||
},
|
||||
}
|
||||
get selectors() {
|
||||
return this._form.selectors;
|
||||
},
|
||||
}
|
||||
get media() {
|
||||
return this._form.media;
|
||||
},
|
||||
}
|
||||
get mediaText() {
|
||||
if (!this._form.media) {
|
||||
return null;
|
||||
@ -191,19 +186,19 @@ const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
}
|
||||
this._mediaText = this.media.join(", ");
|
||||
return this._mediaText;
|
||||
},
|
||||
}
|
||||
|
||||
get parentRule() {
|
||||
return this.conn.getActor(this._form.parentRule);
|
||||
},
|
||||
}
|
||||
|
||||
get parentStyleSheet() {
|
||||
return this.conn.getActor(this._form.parentStyleSheet);
|
||||
},
|
||||
}
|
||||
|
||||
get element() {
|
||||
return this.conn.getActor(this._form.element);
|
||||
},
|
||||
}
|
||||
|
||||
get href() {
|
||||
if (this._form.href) {
|
||||
@ -211,16 +206,16 @@ const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
}
|
||||
const sheet = this.parentStyleSheet;
|
||||
return sheet ? sheet.href : "";
|
||||
},
|
||||
}
|
||||
|
||||
get nodeHref() {
|
||||
const sheet = this.parentStyleSheet;
|
||||
return sheet ? sheet.nodeHref : "";
|
||||
},
|
||||
}
|
||||
|
||||
get canSetRuleText() {
|
||||
return this._form.traits && this._form.traits.canSetRuleText;
|
||||
},
|
||||
}
|
||||
|
||||
get location() {
|
||||
return {
|
||||
@ -229,13 +224,13 @@ const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
line: this.line,
|
||||
column: this.column,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
_clearOriginalLocation: function() {
|
||||
_clearOriginalLocation() {
|
||||
this._originalLocation = null;
|
||||
},
|
||||
}
|
||||
|
||||
getOriginalLocation: function() {
|
||||
getOriginalLocation() {
|
||||
if (this._originalLocation) {
|
||||
return promise.resolve(this._originalLocation);
|
||||
}
|
||||
@ -262,33 +257,30 @@ const StyleRuleFront = FrontClassWithSpec(styleRuleSpec, {
|
||||
this._originalLocation = location;
|
||||
return location;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
modifySelector: custom(async function(node, value) {
|
||||
async modifySelector(node, value) {
|
||||
let response;
|
||||
if (this.canSetRuleText) {
|
||||
response = await this._modifySelector(node, value, true);
|
||||
response = await super.modifySelector(node, value, true);
|
||||
} else {
|
||||
response = await this._modifySelector(node, value);
|
||||
response = await super.modifySelector(node, value);
|
||||
}
|
||||
|
||||
if (response.ruleProps) {
|
||||
response.ruleProps = response.ruleProps.entries[0];
|
||||
}
|
||||
return response;
|
||||
}, {
|
||||
impl: "_modifySelector",
|
||||
}),
|
||||
}
|
||||
|
||||
setRuleText: custom(function(newText, modifications) {
|
||||
setRuleText(newText, modifications) {
|
||||
this._form.authoredText = newText;
|
||||
return this._setRuleText(newText, modifications);
|
||||
}, {
|
||||
impl: "_setRuleText",
|
||||
}),
|
||||
});
|
||||
return super.setRuleText(newText, modifications);
|
||||
}
|
||||
}
|
||||
|
||||
exports.StyleRuleFront = StyleRuleFront;
|
||||
registerFront(StyleRuleFront);
|
||||
|
||||
/**
|
||||
* Convenience API for building a list of attribute modifications
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
mediaRuleSpec,
|
||||
styleSheetSpec,
|
||||
@ -19,102 +19,103 @@ loader.lazyRequireGetter(this, "getIndentationFromString",
|
||||
/**
|
||||
* Corresponding client-side front for a MediaRuleActor.
|
||||
*/
|
||||
const MediaRuleFront = FrontClassWithSpec(mediaRuleSpec, {
|
||||
initialize: function(client, form) {
|
||||
Front.prototype.initialize.call(this, client, form);
|
||||
class MediaRuleFront extends FrontClassWithSpec(mediaRuleSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
this._onMatchesChange = this._onMatchesChange.bind(this);
|
||||
this.on("matches-change", this._onMatchesChange);
|
||||
},
|
||||
}
|
||||
|
||||
_onMatchesChange: function(matches) {
|
||||
_onMatchesChange(matches) {
|
||||
this._form.matches = matches;
|
||||
},
|
||||
}
|
||||
|
||||
form: function(form, detail) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this.actorID = form.actor;
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
get mediaText() {
|
||||
return this._form.mediaText;
|
||||
},
|
||||
}
|
||||
get conditionText() {
|
||||
return this._form.conditionText;
|
||||
},
|
||||
}
|
||||
get matches() {
|
||||
return this._form.matches;
|
||||
},
|
||||
}
|
||||
get line() {
|
||||
return this._form.line || -1;
|
||||
},
|
||||
}
|
||||
get column() {
|
||||
return this._form.column || -1;
|
||||
},
|
||||
}
|
||||
get parentStyleSheet() {
|
||||
return this.conn.getActor(this._form.parentStyleSheet);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.MediaRuleFront = MediaRuleFront;
|
||||
registerFront(MediaRuleFront);
|
||||
|
||||
/**
|
||||
* StyleSheetFront is the client-side counterpart to a StyleSheetActor.
|
||||
*/
|
||||
const StyleSheetFront = FrontClassWithSpec(styleSheetSpec, {
|
||||
initialize: function(conn, form) {
|
||||
Front.prototype.initialize.call(this, conn, form);
|
||||
class StyleSheetFront extends FrontClassWithSpec(styleSheetSpec) {
|
||||
constructor(conn, form) {
|
||||
super(conn, form);
|
||||
|
||||
this._onPropertyChange = this._onPropertyChange.bind(this);
|
||||
this.on("property-change", this._onPropertyChange);
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
destroy() {
|
||||
this.off("property-change", this._onPropertyChange);
|
||||
Front.prototype.destroy.call(this);
|
||||
},
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
_onPropertyChange: function(property, value) {
|
||||
_onPropertyChange(property, value) {
|
||||
this._form[property] = value;
|
||||
},
|
||||
}
|
||||
|
||||
form: function(form, detail) {
|
||||
form(form, detail) {
|
||||
if (detail === "actorid") {
|
||||
this.actorID = form;
|
||||
return;
|
||||
}
|
||||
this.actorID = form.actor;
|
||||
this._form = form;
|
||||
},
|
||||
}
|
||||
|
||||
get href() {
|
||||
return this._form.href;
|
||||
},
|
||||
}
|
||||
get nodeHref() {
|
||||
return this._form.nodeHref;
|
||||
},
|
||||
}
|
||||
get disabled() {
|
||||
return !!this._form.disabled;
|
||||
},
|
||||
}
|
||||
get title() {
|
||||
return this._form.title;
|
||||
},
|
||||
}
|
||||
get isSystem() {
|
||||
return this._form.system;
|
||||
},
|
||||
}
|
||||
get styleSheetIndex() {
|
||||
return this._form.styleSheetIndex;
|
||||
},
|
||||
}
|
||||
get ruleCount() {
|
||||
return this._form.ruleCount;
|
||||
},
|
||||
}
|
||||
get sourceMapURL() {
|
||||
return this._form.sourceMapURL;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indentation to use for edits to this style sheet.
|
||||
@ -122,7 +123,7 @@ const StyleSheetFront = FrontClassWithSpec(styleSheetSpec, {
|
||||
* @return {Promise} A promise that will resolve to a string that
|
||||
* should be used to indent a block in this style sheet.
|
||||
*/
|
||||
guessIndentation: function() {
|
||||
guessIndentation() {
|
||||
const prefIndent = getIndentationFromPrefs();
|
||||
if (prefIndent) {
|
||||
const {indentUnit, indentWithTabs} = prefIndent;
|
||||
@ -137,20 +138,22 @@ const StyleSheetFront = FrontClassWithSpec(styleSheetSpec, {
|
||||
|
||||
return indentWithTabs ? "\t" : " ".repeat(indentUnit);
|
||||
}.bind(this))();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.StyleSheetFront = StyleSheetFront;
|
||||
registerFront(StyleSheetFront);
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the StyleSheetsActor.
|
||||
*/
|
||||
const StyleSheetsFront = FrontClassWithSpec(styleSheetsSpec, {
|
||||
initialize: function(client, tabForm) {
|
||||
Front.prototype.initialize.call(this, client);
|
||||
class StyleSheetsFront extends FrontClassWithSpec(styleSheetsSpec) {
|
||||
constructor(client, tabForm) {
|
||||
super(client);
|
||||
this.actorID = tabForm.styleSheetsActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.StyleSheetsFront = StyleSheetsFront;
|
||||
registerFront(StyleSheetsFront);
|
||||
|
@ -4,18 +4,17 @@
|
||||
"use strict";
|
||||
|
||||
const {addonTargetSpec} = require("devtools/shared/specs/targets/addon");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {custom} = protocol;
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
loader.lazyRequireGetter(this, "BrowsingContextTargetFront", "devtools/shared/fronts/targets/browsing-context", true);
|
||||
|
||||
const AddonTargetFront = protocol.FrontClassWithSpec(addonTargetSpec, {
|
||||
initialize: function(client) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class AddonTargetFront extends FrontClassWithSpec(addonTargetSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this.client = client;
|
||||
|
||||
this.traits = {};
|
||||
},
|
||||
}
|
||||
|
||||
form(json) {
|
||||
this.actorID = json.actor;
|
||||
@ -32,7 +31,7 @@ const AddonTargetFront = protocol.FrontClassWithSpec(addonTargetSpec, {
|
||||
}
|
||||
this[name] = json[name];
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
isLegacyTemporaryExtension() {
|
||||
if (!this.type) {
|
||||
@ -45,7 +44,7 @@ const AddonTargetFront = protocol.FrontClassWithSpec(addonTargetSpec, {
|
||||
this.temporarilyInstalled &&
|
||||
!this.isWebExtension &&
|
||||
!this.isAPIExtension;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual target front for web extensions.
|
||||
@ -56,34 +55,31 @@ const AddonTargetFront = protocol.FrontClassWithSpec(addonTargetSpec, {
|
||||
* inherits from BrowsingContextTargetActor. This connect method is used to retrive
|
||||
* the final target actor to use.
|
||||
*/
|
||||
connect: custom(async function() {
|
||||
const { form } = await this._connect();
|
||||
async connect() {
|
||||
const { form } = await super.connect();
|
||||
const front = new BrowsingContextTargetFront(this.client, form);
|
||||
this.manage(front);
|
||||
return front;
|
||||
}, {
|
||||
impl: "_connect",
|
||||
}),
|
||||
}
|
||||
|
||||
attach: custom(async function() {
|
||||
const response = await this._attach();
|
||||
async attach() {
|
||||
const response = await super.attach();
|
||||
|
||||
this.threadActor = response.threadActor;
|
||||
|
||||
return response;
|
||||
}, {
|
||||
impl: "_attach",
|
||||
}),
|
||||
}
|
||||
|
||||
reconfigure: function() {
|
||||
reconfigure() {
|
||||
// Toolbox and options panel are calling this method but Addon Target can't be
|
||||
// reconfigured. So we ignore this call here.
|
||||
return Promise.resolve();
|
||||
},
|
||||
}
|
||||
|
||||
attachThread: function() {
|
||||
attachThread() {
|
||||
return this.client.attachThread(this.threadActor);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.AddonTargetFront = AddonTargetFront;
|
||||
registerFront(AddonTargetFront);
|
||||
|
@ -4,15 +4,13 @@
|
||||
"use strict";
|
||||
|
||||
const {browsingContextTargetSpec} = require("devtools/shared/specs/targets/browsing-context");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {custom} = protocol;
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyRequireGetter(this, "ThreadClient", "devtools/shared/client/thread-client");
|
||||
|
||||
const BrowsingContextTargetFront =
|
||||
protocol.FrontClassWithSpec(browsingContextTargetSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
class BrowsingContextTargetFront extends FrontClassWithSpec(browsingContextTargetSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
this.thread = null;
|
||||
|
||||
@ -28,7 +26,7 @@ protocol.FrontClassWithSpec(browsingContextTargetSpec, {
|
||||
// Save the full form for Target class usage
|
||||
// Do not use `form` name to avoid colliding with protocol.js's `form` method
|
||||
this.targetForm = form;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach to a thread actor.
|
||||
@ -37,7 +35,7 @@ protocol.FrontClassWithSpec(browsingContextTargetSpec, {
|
||||
* Configuration options.
|
||||
* - useSourceMaps: whether to use source maps or not.
|
||||
*/
|
||||
attachThread: function(options = {}) {
|
||||
attachThread(options = {}) {
|
||||
if (this.thread) {
|
||||
return Promise.resolve([{}, this.thread]);
|
||||
}
|
||||
@ -52,36 +50,32 @@ protocol.FrontClassWithSpec(browsingContextTargetSpec, {
|
||||
this.client.registerClient(this.thread);
|
||||
return [response, this.thread];
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
attach: custom(async function() {
|
||||
const response = await this._attach();
|
||||
async attach() {
|
||||
const response = await super.attach();
|
||||
|
||||
this._threadActor = response.threadActor;
|
||||
this.configureOptions.javascriptEnabled = response.javascriptEnabled;
|
||||
this.traits = response.traits || {};
|
||||
|
||||
return response;
|
||||
}, {
|
||||
impl: "_attach",
|
||||
}),
|
||||
}
|
||||
|
||||
reconfigure: custom(async function({ options }) {
|
||||
const response = await this._reconfigure({ options });
|
||||
async reconfigure({ options }) {
|
||||
const response = await super.reconfigure({ options });
|
||||
|
||||
if (typeof options.javascriptEnabled != "undefined") {
|
||||
this.configureOptions.javascriptEnabled = options.javascriptEnabled;
|
||||
}
|
||||
|
||||
return response;
|
||||
}, {
|
||||
impl: "_reconfigure",
|
||||
}),
|
||||
}
|
||||
|
||||
detach: custom(async function() {
|
||||
async detach() {
|
||||
let response;
|
||||
try {
|
||||
response = await this._detach();
|
||||
response = await super.detach();
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`Error while detaching the browsing context target front: ${e.message}`);
|
||||
@ -98,9 +92,8 @@ protocol.FrontClassWithSpec(browsingContextTargetSpec, {
|
||||
this.destroy();
|
||||
|
||||
return response;
|
||||
}, {
|
||||
impl: "_detach",
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.BrowsingContextTargetFront = BrowsingContextTargetFront;
|
||||
registerFront(BrowsingContextTargetFront);
|
||||
|
@ -4,11 +4,11 @@
|
||||
"use strict";
|
||||
|
||||
const {contentProcessTargetSpec} = require("devtools/shared/specs/targets/content-process");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
const ContentProcessTargetFront = protocol.FrontClassWithSpec(contentProcessTargetSpec, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
class ContentProcessTargetFront extends FrontClassWithSpec(contentProcessTargetSpec) {
|
||||
constructor(client, form) {
|
||||
super(client, form);
|
||||
|
||||
this.client = client;
|
||||
this.chromeDebugger = form.chromeDebugger;
|
||||
@ -18,17 +18,18 @@ const ContentProcessTargetFront = protocol.FrontClassWithSpec(contentProcessTarg
|
||||
this.targetForm = form;
|
||||
|
||||
this.traits = {};
|
||||
},
|
||||
}
|
||||
|
||||
attachThread() {
|
||||
return this.client.attachThread(this.chromeDebugger);
|
||||
},
|
||||
}
|
||||
|
||||
reconfigure: function() {
|
||||
reconfigure() {
|
||||
// Toolbox and options panel are calling this method but Worker Target can't be
|
||||
// reconfigured. So we ignore this call here.
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.ContentProcessTargetFront = ContentProcessTargetFront;
|
||||
registerFront(ContentProcessTargetFront);
|
||||
|
@ -4,14 +4,13 @@
|
||||
"use strict";
|
||||
|
||||
const {workerTargetSpec} = require("devtools/shared/specs/targets/worker");
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {custom} = protocol;
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyRequireGetter(this, "ThreadClient", "devtools/shared/client/thread-client");
|
||||
|
||||
const WorkerTargetFront = protocol.FrontClassWithSpec(workerTargetSpec, {
|
||||
initialize: function(client) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
class WorkerTargetFront extends FrontClassWithSpec(workerTargetSpec) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this.thread = null;
|
||||
this.traits = {};
|
||||
@ -23,7 +22,7 @@ const WorkerTargetFront = protocol.FrontClassWithSpec(workerTargetSpec, {
|
||||
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.on("close", this.destroy);
|
||||
},
|
||||
}
|
||||
|
||||
form(json) {
|
||||
this.actorID = json.actor;
|
||||
@ -35,13 +34,13 @@ const WorkerTargetFront = protocol.FrontClassWithSpec(workerTargetSpec, {
|
||||
this.type = json.type;
|
||||
this.scope = json.scope;
|
||||
this.fetch = json.fetch;
|
||||
},
|
||||
}
|
||||
|
||||
get isClosed() {
|
||||
return this._isClosed;
|
||||
},
|
||||
}
|
||||
|
||||
destroy: function() {
|
||||
destroy() {
|
||||
this.off("close", this.destroy);
|
||||
this._isClosed = true;
|
||||
|
||||
@ -51,11 +50,11 @@ const WorkerTargetFront = protocol.FrontClassWithSpec(workerTargetSpec, {
|
||||
|
||||
this.unmanage(this);
|
||||
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
attach: custom(async function() {
|
||||
const response = await this._attach();
|
||||
async attach() {
|
||||
const response = await super.attach();
|
||||
|
||||
this.url = response.url;
|
||||
|
||||
@ -67,33 +66,29 @@ const WorkerTargetFront = protocol.FrontClassWithSpec(workerTargetSpec, {
|
||||
this.threadActor = connectResponse.threadActor;
|
||||
|
||||
return response;
|
||||
}, {
|
||||
impl: "_attach",
|
||||
}),
|
||||
}
|
||||
|
||||
detach: custom(async function() {
|
||||
async detach() {
|
||||
if (this.isClosed) {
|
||||
return {};
|
||||
}
|
||||
let response;
|
||||
try {
|
||||
response = await this._detach();
|
||||
response = await super.detach();
|
||||
} catch (e) {
|
||||
console.warn(`Error while detaching the worker target front: ${e.message}`);
|
||||
}
|
||||
this.destroy();
|
||||
return response;
|
||||
}, {
|
||||
impl: "_detach",
|
||||
}),
|
||||
}
|
||||
|
||||
reconfigure: function() {
|
||||
reconfigure() {
|
||||
// Toolbox and options panel are calling this method but Worker Target can't be
|
||||
// reconfigured. So we ignore this call here.
|
||||
return Promise.resolve();
|
||||
},
|
||||
}
|
||||
|
||||
attachThread: async function(options = {}) {
|
||||
async attachThread(options = {}) {
|
||||
if (this.thread) {
|
||||
const response = [{
|
||||
type: "connected",
|
||||
@ -112,8 +107,8 @@ const WorkerTargetFront = protocol.FrontClassWithSpec(workerTargetSpec, {
|
||||
this.client.registerClient(this.thread);
|
||||
|
||||
return [attachResponse, this.thread];
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.WorkerTargetFront = WorkerTargetFront;
|
||||
registerFront(WorkerTargetFront);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user