Merge autoland to mozilla-central. a=merge

This commit is contained in:
Noemi Erli 2020-01-06 23:53:16 +02:00
commit 79c4589718
312 changed files with 5547 additions and 2113 deletions

View File

@ -1,11 +1,11 @@
An explanation of the Mozilla Source Code Directory Structure and links to
project pages with documentation can be found at:
https://firefox-source-docs.mozilla.org/tools/docs/contribute/mozilla_source_code_directory_structure.html
https://firefox-source-docs.mozilla.org/contributing/directory_structure.html
For information on how to build Mozilla from the source code and create the patch see:
https://firefox-source-docs.mozilla.org/tools/docs/contribute/how_to_contribute_firefox.html
https://firefox-source-docs.mozilla.org/contributing/how_to_contribute_firefox.html
If you have a question about developing Mozilla, and can't find the solution
on https://developer.mozilla.org, you can try asking your question on IRC at irc.mozilla.org in #introduction channel.

View File

@ -288,24 +288,25 @@ function prompt(
// nsIContentPermissionRequest, but because webrtc uses their own prompting
// system, we should manually apply the delegate policy here. Permission
// should be delegated using Feature Policy and top principal
const permDelegateHandler = aContentWindow.document.permDelegateHandler.QueryInterface(
Ci.nsIPermissionDelegateHandler
);
const shouldDelegatePermission =
Services.prefs.getBoolPref("permissions.delegation.enabled", false) &&
Services.prefs.getBoolPref("dom.security.featurePolicy.enabled", false);
permDelegateHandler.permissionDelegateFPEnabled;
const origin = shouldDelegatePermission
? aContentWindow.top.document.nodePrincipal.origin
: aContentWindow.document.nodePrincipal.origin;
let secondOrigin = undefined;
if (shouldDelegatePermission) {
const permDelegateHandler = aContentWindow.document.permDelegateHandler.QueryInterface(
Ci.nsIPermissionDelegateHandler
);
if (permDelegateHandler.maybeUnsafePermissionDelegate(requestTypes)) {
// We are going to prompt both first party and third party origin.
// SecondOrigin should be third party
secondOrigin = aContentWindow.document.nodePrincipal.origin;
}
if (
shouldDelegatePermission &&
permDelegateHandler.maybeUnsafePermissionDelegate(requestTypes)
) {
// We are going to prompt both first party and third party origin.
// SecondOrigin should be third party
secondOrigin = aContentWindow.document.nodePrincipal.origin;
}
let request = {

View File

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1576881756956">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1578084466436">
<emItems>
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
<prefs/>
@ -3440,6 +3440,14 @@
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="3d3f2971-9764-4b6d-94ef-2a0b97da7619" id="/^((\{a91c41b7-4196-4867-84b4-d417a1b10da2\})|(\{e3d3ea5c-c8c0-4c9e-89c6-f6b5677186cc\})|(\{fa3b6777-4f64-476c-9ace-a79709ccd0a6\})|(\{6251b844-0c54-44bc-8c5e-891e3ba86c2e\})|(\{8e588566-afb2-4612-a420-3e3bd18693e7\})|(\{a0bf35ec-76cc-4d86-875b-09d46e8790c2\})|(\{fd257beb-d772-4333-9901-dc5913aee499\})|(\{a9acb248-93fb-4081-9d88-92468f229842\})|(\{7e1b62bc-3ab4-4c4d-8182-b095a492eab4\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="de533f3a-d0e3-4704-916e-fd2a297cee93" id="/^((\{943773bb-c8a8-4576-bf3a-7cacca534887\})|(\{0afab6d1-c267-4ff6-9289-4a2b2ad78f33\})|(\{4278c56e-7b67-43ab-8c87-f68a6a883df6\})|(\{f146cde8-6dcf-4ebf-9d67-b7eccc9bc8a6\})|(\{d0e43d96-0e73-48d7-9a60-b235022f4330\})|(\{a94ed9b8-24a6-4719-97af-08eaac91a42b\})|(\{d62ca114-0f4e-4d25-813e-292d0c682e05\})|(\{908b1c05-3766-45e1-b56b-f0b4457c6451\})|(\{068054b5-46c0-47c2-be37-dd015fb1c050\})|(\{1c1cde54-c8e9-4c61-a2be-30411888ac8a\})|(\{b06648df-3c80-49e8-9d9e-71741ba28c72\})|(\{a085da90-cc10-4c26-954e-ae4eb773c6d7\})|(\{1d53aa0d-eca3-4bb1-947c-aebfdd0770fd\})|(\{83ebd575-b66b-4b02-a628-d2764194d0a6\})|(\{fd5f7e74-2e60-454b-b702-05e9d66b334b\})|(\{fdd2f5a3-9061-4fc8-87d2-cf7f7668d336\})|(\{f890d432-ce0b-4857-b030-dc36fc791423\})|(\{d5b4e84c-7991-4be5-9c26-c3e92ba0901a\})|(\{8d54459a-34cb-461f-b1fe-2266484cc098\})|(\{67b21df3-a1da-48ee-aee8-18ae8ad7fe21\})|(\{18feff20-5892-43cd-8606-83e8e7c33ebd\})|(\{554e901f-5476-4fad-8714-a08b8249068b\})|(\{248c9c9f-404d-4284-bd12-2fa988edb0ad\})|(\{9c347568-2528-4dea-8a0d-6e9fa7f88512\})|(\{0447e445-abb9-450b-b12c-de16fa40e176\})|(\{3015019d-1c2f-4310-adf1-1b33c4566d9e\})|(\{a3aca1ed-74b4-46d4-9c73-ca9ba8c91ac6\})|(\{7b2aabfa-673f-4afb-9cba-7a9329a24d79\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
</emItems>
<pluginItems>
<pluginItem blockID="p332">
@ -3472,15 +3480,15 @@
<infoURL>https://get.adobe.com/shockwave/</infoURL>
<versionRange maxVersion="12.2.0.162" minVersion="0" severity="0" vulnerabilitystatus="1"/>
</pluginItem>
<pluginItem blockID="832dc9ff-3314-4df2-abcf-7bd65a645371">
<match name="filename" exp="(NPSWF32.*\.dll)|(NPSWF64.*\.dll)|(Flash\ Player\.plugin)"/>
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
<versionRange maxVersion="32.0.0.270" minVersion="0" severity="0" vulnerabilitystatus="1"/>
</pluginItem>
<pluginItem blockID="49b843cc-a8fc-4ede-be0c-a0da56d0214f" os="Linux">
<match name="filename" exp="libflashplayer\.so"/>
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
<versionRange maxVersion="32.0.0.270" minVersion="0" severity="0" vulnerabilitystatus="1"/>
<versionRange maxVersion="32.0.0.293" minVersion="0" severity="0" vulnerabilitystatus="1"/>
</pluginItem>
<pluginItem blockID="832dc9ff-3314-4df2-abcf-7bd65a645371">
<match name="filename" exp="(NPSWF32.*\.dll)|(NPSWF64.*\.dll)|(Flash\ Player\.plugin)"/>
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
<versionRange maxVersion="32.0.0.293" minVersion="0" severity="0" vulnerabilitystatus="1"/>
</pluginItem>
</pluginItems>
<gfxItems>

View File

@ -406,7 +406,6 @@ pref("permissions.default.xr", 0);
pref("permissions.default.desktop-notification", 0);
pref("permissions.default.shortcuts", 0);
pref("permissions.delegation.enabled", true);
pref("permissions.desktop-notification.postPrompt.enabled", true);
pref("permissions.desktop-notification.notNow.enabled", false);
@ -1707,8 +1706,6 @@ pref("view_source.tab", true);
pref("dom.serviceWorkers.enabled", true);
pref("dom.security.featurePolicy.enabled", true);
// Enable Push API.
pref("dom.push.enabled", true);

View File

@ -539,6 +539,7 @@ class _ASRouter {
this.onPrefChange = this.onPrefChange.bind(this);
this.dispatch = this.dispatch.bind(this);
this._onLocaleChanged = this._onLocaleChanged.bind(this);
this.isUnblockedMessage = this.isUnblockedMessage.bind(this);
}
async onPrefChange(prefName) {
@ -547,7 +548,7 @@ class _ASRouter {
const invalidMessages = [];
const context = this._getMessagesContext();
for (const msg of this._getUnblockedMessages()) {
for (const msg of this.state.messages.filter(this.isUnblockedMessage)) {
if (!msg.targeting) {
continue;
}
@ -1129,6 +1130,18 @@ class _ASRouter {
return bundle.sort((a, b) => a.order - b.order);
}
isUnblockedMessage(message) {
let { state } = this;
return (
!state.messageBlockList.includes(message.id) &&
(!message.campaign ||
!state.messageBlockList.includes(message.campaign)) &&
!state.providerBlockList.includes(message.provider) &&
this.hasGroupsEnabled(message.groups) &&
!this.isExcludedByProvider(message)
);
}
// Work out if a message can be shown based on its and its provider's frequency caps.
isBelowFrequencyCaps(message) {
const { messageImpressions, groupImpressions } = this.state;
@ -1197,9 +1210,12 @@ class _ASRouter {
}
// First, find all messages of same template. These are potential matching targeting candidates
let bundledMessagesOfSameTemplate = this._getUnblockedMessages().filter(
let bundledMessagesOfSameTemplate = this.state.messages.filter(
msg =>
msg.bundled && msg.template === bundleTemplate && msg.id !== originalId
msg.bundled &&
msg.template === bundleTemplate &&
msg.id !== originalId &&
this.isUnblockedMessage(msg)
);
if (force) {
@ -1279,18 +1295,6 @@ class _ASRouter {
];
}
_getUnblockedMessages() {
let { state } = this;
return state.messages.filter(
item =>
!state.messageBlockList.includes(item.id) &&
(!item.campaign || !state.messageBlockList.includes(item.campaign)) &&
!state.providerBlockList.includes(item.provider) &&
this.hasGroupsEnabled(item.groups) &&
!this.isExcludedByProvider(item)
);
}
/**
* Route messages based on template to the correct module that can display them
*/
@ -1520,30 +1524,40 @@ class _ASRouter {
ordered = false,
returnAll = false,
}) {
let shouldCache;
const messages =
candidates ||
this._getUnblockedMessages()
.filter(m => {
if (provider && m.provider !== provider) {
return false;
}
if (template && m.template !== template) {
return false;
}
if (triggerId && !m.trigger) {
return false;
}
if (triggerId && m.trigger.id !== triggerId) {
return false;
}
this.state.messages.filter(m => {
if (provider && m.provider !== provider) {
return false;
}
if (template && m.template !== template) {
return false;
}
if (triggerId && !m.trigger) {
return false;
}
if (triggerId && m.trigger.id !== triggerId) {
return false;
}
if (!this.isUnblockedMessage(m)) {
return false;
}
if (!this.isBelowFrequencyCaps(m)) {
return false;
}
return true;
})
.filter(m => this.isBelowFrequencyCaps(m));
if (shouldCache !== false) {
shouldCache = JEXL_PROVIDER_CACHE.has(m.provider);
}
return true;
});
if (!messages.length) {
return returnAll ? messages : null;
}
const shouldCache = messages.every(m =>
JEXL_PROVIDER_CACHE.has(m.provider)
);
const context = this._getMessagesContext();
// Find a message that matches the targeting context as well as the trigger context (if one is provided)

View File

@ -1096,7 +1096,7 @@ describe("ASRouter", () => {
const result = await Router.handleMessageRequest({
provider: "snippets",
});
assert.isUndefined(result);
assert.isNull(result);
});
it("should not return a message from a blocked campaign", async () => {
// Block all messages except the first
@ -1153,7 +1153,16 @@ describe("ASRouter", () => {
const result = await Router.handleMessageRequest({
provider: "snippets",
});
assert.isNull(result);
});
it("should not return a message if the frequency cap has been hit", async () => {
sandbox.stub(Router, "isBelowFrequencyCaps").returns(false);
await Router.setState(() => ({
messages: [{ id: "foo", provider: "snippets" }],
}));
const result = await Router.handleMessageRequest({
provider: "snippets",
});
assert.isNull(result);
});
it("should get unblocked messages that match the trigger", async () => {
@ -1220,18 +1229,21 @@ describe("ASRouter", () => {
});
it("should return all unblocked messages that match the template, trigger if returnAll=true", async () => {
const message1 = {
provider: "whats_new",
id: "1",
template: "whatsnew_panel_message",
trigger: { id: "whatsNewPanelOpened" },
groups: ["whats_new"],
};
const message2 = {
provider: "whats_new",
id: "2",
template: "whatsnew_panel_message",
trigger: { id: "whatsNewPanelOpened" },
groups: ["whats_new"],
};
const message3 = {
provider: "whats_new",
id: "3",
template: "badge",
groups: ["whats_new"],
@ -1239,9 +1251,12 @@ describe("ASRouter", () => {
sandbox
.stub(ASRouterTargeting, "findMatchingMessage")
.callsFake(() => [message2, message1]);
await Router.setState({ messages: [message3, message2, message1] });
await Router.setState({
messages: [message3, message2, message1],
providers: [{ id: "whats_new" }],
});
const result = await Router.handleMessageRequest({
template: "whatsnew-panel",
template: "whatsnew_panel_message",
triggerId: "whatsNewPanelOpened",
returnAll: true,
});
@ -1794,7 +1809,7 @@ describe("ASRouter", () => {
await Router.onMessage(msg);
assert.isTrue(Router.state.messageBlockList.includes("foocampaign"));
assert.isEmpty(Router._getUnblockedMessages());
assert.isEmpty(Router.state.messages.filter(Router.isUnblockedMessage));
});
it("should not broadcast CLEAR_MESSAGE if preventDismiss is true", async () => {
const msg = fakeAsyncMessage({
@ -2094,6 +2109,20 @@ describe("ASRouter", () => {
describe("#onMessage: TRIGGER", () => {
it("should pass the trigger to ASRouterTargeting on TRIGGER message", async () => {
await Router.setState({
messages: [
{
id: "foo1",
provider: "onboarding",
template: "onboarding",
trigger: { id: "firstRun" },
content: { title: "Foo1", body: "Foo123-1" },
groups: ["onboarding"],
},
],
providers: [{ id: "onboarding" }],
});
sandbox.stub(Router, "loadMessagesFromAllProviders").resolves();
sandbox.stub(ASRouterTargeting, "findMatchingMessage").resolves();
const msg = fakeAsyncMessage({
type: "TRIGGER",

View File

@ -237,11 +237,6 @@ const kBuiltInInputs = {
},
};
// We create a new flat object to cache strings. Since gBuiltInInputs is a
// tree, caching/retrieval of localized strings would otherwise require tree
// traversal.
var localizedStrings = {};
const kHelperObservers = new Set([
"bookmark-icon-updated",
"reader-mode-available",
@ -308,6 +303,8 @@ class TouchBarHelper {
// icons) are loaded. We keep track of which inputs haven't updated and
// run an update on them after the first location change.
this._inputsNotUpdated = new Set(Object.keys(kBuiltInInputs));
// This is a temporary workaround until bug 1596723 is resolved.
this._inputsNotUpdated.delete("SearchPopover");
return layoutItems;
}
@ -354,8 +351,8 @@ class TouchBarHelper {
// Skip localization if there is already a cached localized title or if
// no title is needed.
if (
!inputData.hasOwnProperty("title") ||
localizedStrings[inputData.title]
kBuiltInInputs[inputName].hasOwnProperty("localTitle") ||
!kBuiltInInputs[inputName].hasOwnProperty("title")
) {
return item;
}
@ -363,7 +360,7 @@ class TouchBarHelper {
// Async l10n fills in the localized input labels after the initial load.
this._l10n.formatValue(item.key).then(result => {
item.title = result;
localizedStrings[inputData.title] = result; // Cache result.
kBuiltInInputs[inputName].localTitle = result; // Cache result.
// Checking TouchBarHelper.window since this callback can fire after all windows are closed.
if (TouchBarHelper.window) {
if (this._inputsNotUpdated) {
@ -478,16 +475,12 @@ class TouchBarHelper {
);
break;
case "intl:app-locales-changed":
// On locale change, refresh all inputs after loading new localTitle.
this._searchPopover = null;
localizedStrings = {};
// This event can fire before this._l10n updates to switch languages,
// so all the new translations are in the old language. To avoid this,
// we need to reinitialize this._l10n.
this._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);
helperProto._l10n = this._l10n;
this._updateTouchBarInputs(...Object.keys(kBuiltInInputs));
for (let input in kBuiltInInputs) {
delete input.localTitle;
}
this._updateTouchBarInputs(...kBuiltInInputs.keys());
break;
case "quit-application":
this.destructor();
@ -530,7 +523,7 @@ helperProto._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);
class TouchBarInput {
constructor(input) {
this._key = input.key || input.title;
this._title = localizedStrings[this._key] || "";
this._title = input.hasOwnProperty("localTitle") ? input.localTitle : "";
this._image = input.image;
this._type = input.type;
this._callback = input.callback;
@ -551,7 +544,7 @@ class TouchBarInput {
initializedChild.type = input.type + "-" + initializedChild.type;
this._children.push(initializedChild);
// Skip l10n for inputs without a title or those already localized.
if (childData.title && !localizedStrings[childData.title]) {
if (childData.title && childData.title != "") {
toLocalize.push(initializedChild);
}
}
@ -613,14 +606,9 @@ class TouchBarInput {
/**
* Apply Fluent l10n to child inputs.
* @param {Array} children
* An array of initialized TouchBarInputs.
* @param {Array} children An array of initialized TouchBarInputs.
*/
async _localizeChildren(children) {
if (!children || !children.length) {
return;
}
let titles = await helperProto._l10n.formatValues(
children.map(child => ({ id: child.key }))
);
@ -629,9 +617,7 @@ class TouchBarInput {
// results in titles match up with the inputs to be localized.
children.forEach(function(child, index) {
child.title = titles[index];
localizedStrings[child.key] = child.title;
});
gTouchBarUpdater.updateTouchBarInputs(TouchBarHelper.baseWindow, children);
}
}

View File

@ -492,12 +492,19 @@ const tests = [
info(
"With pageproxystate=valid, open the panel with openViewOnFocus, select with DOWN, Enter."
);
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.update1", true],
["browser.urlbar.openViewOnFocus", true],
],
});
await addTopSite("http://example.org/");
gURLBar.value = "";
let promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
await UrlbarTestUtils.promisePopupOpen(window, () => {
window.document.getElementById("Browser:OpenLocation").doCommand();
});
await SpecialPowers.popPrefEnv();
await UrlbarTestUtils.promiseSearchComplete(window);
while (gURLBar.untrimmedValue != "http://example.org/") {
EventUtils.synthesizeKey("KEY_ArrowDown");
@ -522,13 +529,20 @@ const tests = [
info(
"With pageproxystate=valid, open the panel with openViewOnFocus, click on entry."
);
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.update1", true],
["browser.urlbar.openViewOnFocus", true],
],
});
await addTopSite("http://example.com/");
gURLBar.value = "";
let promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
await UrlbarTestUtils.promisePopupOpen(window, () => {
window.document.getElementById("Browser:OpenLocation").doCommand();
});
Services.prefs.clearUserPref("browser.urlbar.openViewOnFocus");
await SpecialPowers.popPrefEnv();
await UrlbarTestUtils.promiseSearchComplete(window);
while (gURLBar.untrimmedValue != "http://example.com/") {
EventUtils.synthesizeKey("KEY_ArrowDown");
@ -554,6 +568,12 @@ const tests = [
info(
"With pageproxystate=invalid, open the panel with openViewOnFocus, Enter."
);
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.update1", true],
["browser.urlbar.openViewOnFocus", true],
],
});
await addTopSite("http://example.org/");
gURLBar.value = "example.org";
gURLBar.setAttribute("pageproxystate", "invalid");
@ -561,6 +581,7 @@ const tests = [
await UrlbarTestUtils.promisePopupOpen(window, () => {
window.document.getElementById("Browser:OpenLocation").doCommand();
});
await SpecialPowers.popPrefEnv();
await UrlbarTestUtils.promiseSearchComplete(window);
EventUtils.synthesizeKey("VK_RETURN");
await promise;
@ -582,6 +603,12 @@ const tests = [
info(
"With pageproxystate=invalid, open the panel with openViewOnFocus, click on entry."
);
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.update1", true],
["browser.urlbar.openViewOnFocus", true],
],
});
// This value must be different from the previous test, or else the
// Megabar's "retained results" feature will interfere with openViewOnFocus.
// This issue will be addressed in bug 1601052.
@ -591,6 +618,7 @@ const tests = [
await UrlbarTestUtils.promisePopupOpen(window, () => {
window.document.getElementById("Browser:OpenLocation").doCommand();
});
await SpecialPowers.popPrefEnv();
await UrlbarTestUtils.promiseSearchComplete(window);
let element = UrlbarTestUtils.getSelectedRow(window);
EventUtils.synthesizeMouseAtCenter(element, {});

View File

@ -15,6 +15,7 @@ const EN_US_TOPSITES =
add_task(async function init() {
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.update1", true],
["browser.urlbar.openViewOnFocus", true],
["browser.newtabpage.activity-stream.default.sites", EN_US_TOPSITES],
],

View File

@ -945,11 +945,6 @@ Function CheckExistingInstall
FunctionEnd
Function LaunchApp
!ifndef DEV_EDITION
${ManualCloseAppPrompt} "${MainWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
${ManualCloseAppPrompt} "${DialogWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
!endif
ClearErrors
${GetParameters} $0
${GetOptions} "$0" "/UAC:" $1

View File

@ -1766,22 +1766,6 @@ Function CanWrite
FunctionEnd
Function LaunchApp
!ifndef DEV_EDITION
FindWindow $0 "${MainWindowClass}"
FindWindow $1 "${DialogWindowClass}"
${If} $0 <> 0 ; integer comparison
${OrIf} $1 <> 0
StrCpy $FirefoxLaunchCode "1"
StrCpy $ProgressCompleted ${PROGRESS_BAR_TOTAL_STEPS}
Call SetProgressBars
MessageBox MB_OK|MB_ICONQUESTION "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
Call SendPing
Return
${EndIf}
!endif
StrCpy $FirefoxLaunchCode "2"
; Set the current working directory to the installation directory

View File

@ -45,7 +45,6 @@ ICONS_STARTMENU=In my &Start Menu Programs folder
ICONS_QUICKLAUNCH=In my &Quick Launch bar
WARN_MANUALLY_CLOSE_APP_INSTALL=$BrandShortName must be closed to proceed with the installation.\n\nPlease close $BrandShortName to continue.
WARN_MANUALLY_CLOSE_APP_UNINSTALL=$BrandShortName must be closed to proceed with the uninstall.\n\nPlease close $BrandShortName to continue.
WARN_MANUALLY_CLOSE_APP_LAUNCH=$BrandShortName is already running.\n\nPlease close $BrandShortName prior to launching the version you have just installed.
WARN_WRITE_ACCESS=You don't have access to write to the installation directory.\n\nClick OK to select a different directory.
WARN_DISK_SPACE=You don't have sufficient disk space to install to this location.\n\nClick OK to select a different location.
WARN_MIN_SUPPORTED_OSVER_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer. Please click the OK button for additional information.

View File

@ -43,7 +43,6 @@ WARN_MIN_SUPPORTED_CPU_MSG=Sorry, $BrandShortName cant be installed. This ver
WARN_MIN_SUPPORTED_OSVER_CPU_MSG=Sorry, $BrandShortName cant be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer and a processor with ${MinSupportedCPU} support. Please click the OK button for additional information.
WARN_WRITE_ACCESS_QUIT=You dont have access to write to the installation directory
WARN_DISK_SPACE_QUIT=You dont have sufficient disk space to install.
WARN_MANUALLY_CLOSE_APP_LAUNCH=$BrandShortName is already running.\n\nPlease close $BrandShortName prior to launching the version you have just installed.
ERROR_DOWNLOAD_CONT=Hmm. For some reason, we could not install $BrandShortName.\nChoose OK to start over.

View File

@ -733,7 +733,8 @@ toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton
border-radius: 50%;
}
.PanelUI-fxa-service-description-label {
.PanelUI-fxa-service-description-label,
.PanelUI-remotetabs-instruction-label {
/* Use 'lighter' font for this to de-emphasize it compared to the title.
* We use 300 on Linux because 100 is too light (lacks contrast with
* the background) for some fonts in combination with anti-aliasing. */
@ -784,7 +785,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton
color: var(--panel-disabled-color);
}
/* From the FxA menu -> remote tabs, we don't need to clutter the view with
/* From the FxA menu -> synced tabs, we don't need to clutter the view with
redundant buttons because these are accessible from the main menu */
panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
display: none;
@ -839,21 +840,9 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
max-width: 15em;
}
.PanelUI-fxa-service-description-label {
margin-top: 10px;
}
.PanelUI-fxa-service-description-label,
.PanelUI-remotetabs-instruction-label {
color: var(--panel-disabled-color);
}
/* The boxes with "instructions" get extra top and bottom padding for space
around the illustration and buttons */
.PanelUI-remotetabs-instruction-box {
/* If you change the padding here, the min-height of the synced tabs panel
(e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
need adjusting (see bug 1248506) */
padding-bottom: 30px;
margin-top: 10px;
}
.PanelUI-fxa-signin-button,
@ -874,7 +863,8 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
min-width: 200px;
}
.PanelUI-fxa-signin-button {
.PanelUI-fxa-signin-button,
.PanelUI-remotetabs-button {
padding: 1em;
}
@ -905,11 +895,10 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
.fxaSyncIllustration,
.fxaSyncIllustrationIssue {
/* If you change the margin here, the min-height of the synced tabs panel
(e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
need adjusting (see bug 1248506) */
(e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
need adjusting (see bug 1248506) */
width: 204px;
height: var(--panel-ui-sync-illustration-height);
margin: 38px 0 15px;
-moz-context-properties: fill;
fill: #cdcdcd;
}
@ -943,11 +932,10 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-nodevicespane,
#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-tabsdisabledpane {
min-height: calc(var(--panel-ui-sync-illustration-height) +
53px + /* margin of .fxaSyncIllustration */
15px + /* margin of .fxaSyncIllustration */
30px + /* margin of .PanelUI-remotetabs-button */
16px + /* padding of .PanelUI-remotetabs-button */
30px + /* padding of .PanelUI-remotetabs-instruction-box */
11em);
8px + /* padding of .PanelUI-remotetabs-button */
1em);
}
.PanelUI-remotetabs-clientcontainer > label[itemtype="client"] {

View File

@ -71,9 +71,9 @@ MACH_MODULES = [
'toolkit/components/telemetry/tests/marionette/mach_commands.py',
'tools/browsertime/mach_commands.py',
'tools/compare-locales/mach_commands.py',
'tools/docs/mach_commands.py',
'tools/lint/mach_commands.py',
'tools/mach_commands.py',
'tools/moztreedocs/mach_commands.py',
'tools/power/mach_commands.py',
'tools/tryselect/mach_commands.py',
'tools/vcs/mach_commands.py',

View File

@ -2,7 +2,8 @@
[include]
# Code for generating docs.
glob:tools/docs/**
glob:docs/**
glob:tools/moztreedocs/**
# Potential docs sources
glob:**/*.rst

View File

@ -88,7 +88,7 @@ mozilla.pth:testing/web-platform/tests/tools/six
mozilla.pth:testing/xpcshell
mozilla.pth:third_party/python/mock-1.0.0
mozilla.pth:xpcom/ds/tools
mozilla.pth:tools/docs
mozilla.pth:tools/moztreedocs
mozilla.pth:third_party/python/cbor2
mozilla.pth:third_party/python/pyasn1
mozilla.pth:third_party/python/pyasn1-modules

View File

@ -6579,7 +6579,7 @@ NS_CycleCollectorSuspectUsingNursery
?HasFocus@Document@dom@mozilla@@QBE_NAAVErrorResult@3@@Z
?GetFocusedWindow@nsFocusManager@@UAG?AW4nsresult@@PAPAVmozIDOMWindowProxy@@@Z
?GetCsp@SystemPrincipal@mozilla@@UAG?AW4nsresult@@PAPAVnsIContentSecurityPolicy@@@Z
?InnerSetNewDocument@nsGlobalWindowInner@@IAEXPAUJSContext@@PAVDocument@dom@mozilla@@@Z
?InitDocumentDependentState@nsGlobalWindowInner@@IAEXPAUJSContext@@@Z
?WrapObject@nsINode@@UAEPAVJSObject@@PAUJSContext@@V?$Handle@PAVJSObject@@@JS@@@Z
?WrapNode@nsHTMLDocument@@UAEPAVJSObject@@PAUJSContext@@V?$Handle@PAVJSObject@@@JS@@@Z
?Wrap@HTMLDocument_Binding@dom@mozilla@@YA_NPAUJSContext@@PAVnsHTMLDocument@@PAVnsWrapperCache@@V?$Handle@PAVJSObject@@@JS@@V?$MutableHandle@PAVJSObject@@@8@@Z

View File

@ -6535,7 +6535,7 @@ NS_CycleCollectorSuspectUsingNursery
?HasFocus@Document@dom@mozilla@@QEBA_NAEAVErrorResult@3@@Z
?GetFocusedWindow@nsFocusManager@@UEAA?AW4nsresult@@PEAPEAVmozIDOMWindowProxy@@@Z
?GetCsp@SystemPrincipal@mozilla@@UEAA?AW4nsresult@@PEAPEAVnsIContentSecurityPolicy@@@Z
?InnerSetNewDocument@nsGlobalWindowInner@@IEAAXPEAUJSContext@@PEAVDocument@dom@mozilla@@@Z
?InitDocumentDependentState@nsGlobalWindowInner@@IEAAXPEAUJSContext@@@Z
?WrapObject@nsINode@@UEAAPEAVJSObject@@PEAUJSContext@@V?$Handle@PEAVJSObject@@@JS@@@Z
?WrapNode@nsHTMLDocument@@UEAAPEAVJSObject@@PEAUJSContext@@V?$Handle@PEAVJSObject@@@JS@@@Z
?Wrap@HTMLDocument_Binding@dom@mozilla@@YA_NPEAUJSContext@@PEAVnsHTMLDocument@@PEAVnsWrapperCache@@V?$Handle@PEAVJSObject@@@JS@@V?$MutableHandle@PEAVJSObject@@@8@@Z

View File

@ -1004,21 +1004,13 @@ nsresult nsScriptSecurityManager::CheckLoadURIFlags(
}
nsresult nsScriptSecurityManager::ReportError(const char* aMessageTag,
nsIURI* aSource, nsIURI* aTarget,
const nsACString& aSourceSpec,
const nsACString& aTargetSpec,
bool aFromPrivateWindow,
uint64_t aInnerWindowID) {
nsresult rv;
NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER);
// Get the source URL spec
nsAutoCString sourceSpec;
rv = aSource->GetAsciiSpec(sourceSpec);
NS_ENSURE_SUCCESS(rv, rv);
// Get the target URL spec
nsAutoCString targetSpec;
rv = aTarget->GetAsciiSpec(targetSpec);
NS_ENSURE_SUCCESS(rv, rv);
if (aSourceSpec.IsEmpty() || aTargetSpec.IsEmpty()) {
return NS_OK;
}
nsCOMPtr<nsIStringBundle> bundle = BundleHelper::GetOrCreate();
if (NS_WARN_IF(!bundle)) {
@ -1028,9 +1020,10 @@ nsresult nsScriptSecurityManager::ReportError(const char* aMessageTag,
// Localize the error message
nsAutoString message;
AutoTArray<nsString, 2> formatStrings;
CopyASCIItoUTF16(sourceSpec, *formatStrings.AppendElement());
CopyASCIItoUTF16(targetSpec, *formatStrings.AppendElement());
rv = bundle->FormatStringFromName(aMessageTag, formatStrings, message);
CopyASCIItoUTF16(aSourceSpec, *formatStrings.AppendElement());
CopyASCIItoUTF16(aTargetSpec, *formatStrings.AppendElement());
nsresult rv =
bundle->FormatStringFromName(aMessageTag, formatStrings, message);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIConsoleService> console(
@ -1055,6 +1048,26 @@ nsresult nsScriptSecurityManager::ReportError(const char* aMessageTag,
return NS_OK;
}
nsresult nsScriptSecurityManager::ReportError(const char* aMessageTag,
nsIURI* aSource, nsIURI* aTarget,
bool aFromPrivateWindow,
uint64_t aInnerWindowID) {
NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER);
// Get the source URL spec
nsAutoCString sourceSpec;
nsresult rv = aSource->GetAsciiSpec(sourceSpec);
NS_ENSURE_SUCCESS(rv, rv);
// Get the target URL spec
nsAutoCString targetSpec;
rv = aTarget->GetAsciiSpec(targetSpec);
NS_ENSURE_SUCCESS(rv, rv);
return ReportError(aMessageTag, sourceSpec, targetSpec, aFromPrivateWindow,
aInnerWindowID);
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(
nsIPrincipal* aPrincipal, const nsACString& aTargetURIStr,

View File

@ -71,6 +71,13 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager {
static nsresult ReportError(const char* aMessageTag, nsIURI* aSource,
nsIURI* aTarget, bool aFromPrivateWindow,
uint64_t aInnerWindowID = 0);
static nsresult ReportError(const char* aMessageTag,
const nsACString& sourceSpec,
const nsACString& targetSpec,
bool aFromPrivateWindow,
uint64_t aInnerWindowID = 0);
static uint32_t HashPrincipalByOrigin(nsIPrincipal* aPrincipal);
static bool GetStrictFileOriginPolicy() { return sStrictFileOriginPolicy; }

View File

@ -1267,16 +1267,6 @@ if CONFIG['MOZ_SYSTEM_ZLIB']:
'zlib.h',
]
if CONFIG['MOZ_ENABLE_STARTUP_NOTIFICATION']:
system_headers += [
'libsn/sn-common.h',
'libsn/sn.h',
'libsn/sn-launchee.h',
'libsn/sn-launcher.h',
'libsn/sn-monitor.h',
'libsn/sn-util.h',
]
if CONFIG['MOZ_SYSTEM_LIBEVENT']:
system_headers += [
'event2/event_compat.h',

View File

@ -133,7 +133,23 @@ module.exports = {
"rules": {
"mozilla/no-define-cc-etc": "off",
}
}, ],
}, {
// All DevTools files should avoid relative paths.
"files": [
"**"
],
"excludedFiles": [
// Debugger modules have a custom bundling logic which relies on relative
// paths.
"client/debugger/**",
// `client/shared/build` contains node helpers to build the debugger and
// not devtools modules.
"client/shared/build/**",
],
"rules": {
"mozilla/reject-relative-requires": "error",
}
}],
"rules": {
// These are the rules that have been configured so far to match the
// devtools coding style.

View File

@ -8,18 +8,21 @@ const { UPDATE_DETAILS } = require("devtools/client/accessibility/constants");
/**
* Update details with the given accessible object.
*
* @param {Object} dom walker front
* @param {Object} accessible front
*/
exports.updateDetails = (domWalker, accessible) => dispatch =>
Promise.all([
domWalker.getNodeFromActor(accessible.actorID, [
"rawAccessible",
"DOMNode",
]),
accessible.getRelations(),
accessible.audit(),
accessible.hydrate(),
])
exports.updateDetails = accessible => dispatch =>
accessible.targetFront
.getFront("inspector")
.then(({ walker: domWalker }) =>
Promise.all([
domWalker.getNodeFromActor(accessible.actorID, [
"rawAccessible",
"DOMNode",
]),
accessible.getRelations(),
accessible.audit(),
accessible.hydrate(),
])
)
.then(response => dispatch({ accessible, type: UPDATE_DETAILS, response }))
.catch(error => dispatch({ accessible, type: UPDATE_DETAILS, error }));

View File

@ -154,7 +154,7 @@ class AccessibilityRow extends Component {
scrollIntoView(row);
}
async update() {
update() {
const {
dispatch,
member: { object },
@ -163,8 +163,7 @@ class AccessibilityRow extends Component {
return;
}
const domWalker = (await object.targetFront.getFront("inspector")).walker;
dispatch(updateDetails(domWalker, object));
dispatch(updateDetails(object));
window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_SELECTED, object);
}

View File

@ -185,16 +185,13 @@ class Accessible extends Component {
}
}
async update() {
update() {
const { dispatch, accessibleFront } = this.props;
if (!accessibleFront.actorID) {
return;
}
const domWalker = (await accessibleFront.targetFront.getFront("inspector"))
.walker;
dispatch(updateDetails(domWalker, accessibleFront));
dispatch(updateDetails(accessibleFront));
}
setExpanded(item, isExpanded) {

View File

@ -31,7 +31,12 @@ function ErrorRep(props) {
const mode = props.mode;
let name;
if (preview && preview.name && preview.kind) {
if (
preview &&
preview.name &&
typeof preview.name === "string" &&
preview.kind
) {
switch (preview.kind) {
case "Error":
name = preview.name;
@ -48,7 +53,7 @@ function ErrorRep(props) {
const content = [];
if (mode === MODE.TINY) {
if (mode === MODE.TINY || typeof preview.message !== "string") {
content.push(name);
} else {
content.push(`${name}: "${preview.message}"`);

View File

@ -314,4 +314,43 @@ stubs.set("Error with undefined-grip stack", {
},
});
stubs.set("Error with undefined-grip name", {
type: "object",
actor: "server0.conn0.child1/obj88",
class: "Error",
extensible: true,
frozen: false,
sealed: false,
ownPropertyLength: 4,
preview: {
kind: "Error",
name: {
type: "undefined",
},
message: "too much recursion",
stack: "@debugger eval code:16:13\n",
fileName: "debugger eval code",
lineNumber: 13,
columnNumber: 13,
},
});
stubs.set("Error with undefined-grip message", {
type: "object",
actor: "server0.conn0.child1/obj88",
class: "Error",
extensible: true,
frozen: false,
sealed: false,
ownPropertyLength: 4,
preview: {
kind: "Error",
message: { type: "undefined" },
stack: "@debugger eval code:16:13\n",
fileName: "debugger eval code",
lineNumber: 13,
columnNumber: 13,
},
});
module.exports = stubs;

View File

@ -43,6 +43,84 @@ exports[`Error - Error with invalid stack renders with expected text 1`] = `
</span>
`;
exports[`Error - Error with undefined-grip message renders with expected text 1`] = `
<span
className="objectBox-stackTrace"
data-link-actor-id="server0.conn0.child1/obj88"
>
Error
<span
className="objectBox-stackTrace-grid"
key="stack"
>
<span
className="objectBox-stackTrace-fn"
key="fn0"
>
&lt;anonymous&gt;
</span>
<span
className="objectBox-stackTrace-location"
key="location0"
>
debugger eval code:16:13
</span>
</span>
</span>
`;
exports[`Error - Error with undefined-grip message renders with expected text 2`] = `
<span
className="objectBox-stackTrace"
data-link-actor-id="server0.conn0.child1/obj88"
>
Error
</span>
`;
exports[`Error - Error with undefined-grip name renders with expected text 1`] = `
<span
className="objectBox-stackTrace"
data-link-actor-id="server0.conn0.child1/obj88"
>
Error: "too much recursion"
<span
className="objectBox-stackTrace-grid"
key="stack"
>
<span
className="objectBox-stackTrace-fn"
key="fn0"
>
&lt;anonymous&gt;
</span>
<span
className="objectBox-stackTrace-location"
key="location0"
>
debugger eval code:16:13
</span>
</span>
</span>
`;
exports[`Error - Error with undefined-grip name renders with expected text 2`] = `
<span
className="objectBox-stackTrace"
data-link-actor-id="server0.conn0.child1/obj88"
>
Error
</span>
`;
exports[`Error - Error with undefined-grip stack renders with expected text 1`] = `
<span
className="objectBox-stackTrace"

View File

@ -618,3 +618,61 @@ describe("Error - Error with undefined-grip stack", () => {
expectActorAttribute(renderedComponent, stub.actor);
});
});
describe("Error - Error with undefined-grip name", () => {
// Test object:
// x = new Error("");
// x.name = undefined;
const stub = stubs.get("Error with undefined-grip name");
it("correctly selects Error Rep for Error object", () => {
expect(getRep(stub)).toBe(ErrorRep.rep);
});
it("renders with expected text", () => {
const renderedComponent = shallow(
ErrorRep.rep({
object: stub,
})
);
expect(renderedComponent).toMatchSnapshot();
const tinyRenderedComponent = shallow(
ErrorRep.rep({
object: stub,
mode: MODE.TINY,
})
);
expect(tinyRenderedComponent).toMatchSnapshot();
});
});
describe("Error - Error with undefined-grip message", () => {
// Test object:
// x = new Error("");
// x.message = undefined;
const stub = stubs.get("Error with undefined-grip message");
it("correctly selects Error Rep for Error object", () => {
expect(getRep(stub)).toBe(ErrorRep.rep);
});
it("renders with expected text", () => {
const renderedComponent = shallow(
ErrorRep.rep({
object: stub,
})
);
expect(renderedComponent).toMatchSnapshot();
const tinyRenderedComponent = shallow(
ErrorRep.rep({
object: stub,
mode: MODE.TINY,
})
);
expect(tinyRenderedComponent).toMatchSnapshot();
});
});

View File

@ -158,6 +158,7 @@ async function expandFrames(
generatedLocation: frame.generatedLocation,
originalDisplayName: originalFrame.displayName,
originalVariables: originalFrame.variables,
asyncCause: null,
});
});
}

View File

@ -21,6 +21,11 @@ export function selectFrame(cx: ThreadContext, frame: Frame) {
return async ({ dispatch, client, getState, sourceMaps }: ThunkArgs) => {
assert(cx.thread == frame.thread, "Thread mismatch");
// Frames with an async cause are not selected
if (frame.asyncCause) {
return dispatch(selectLocation(cx, frame.location));
}
dispatch({
type: "SELECT_FRAME",
cx,
@ -33,6 +38,7 @@ export function selectFrame(cx: ThreadContext, frame: Frame) {
}
dispatch(selectLocation(cx, frame.location));
dispatch(evaluateExpressions(cx));
dispatch(fetchScopes(cx));
};

View File

@ -58,6 +58,8 @@ export function createFrame(
this: frame.this,
source: null,
index,
asyncCause: frame.asyncCause,
state: frame.state,
};
}

View File

@ -107,13 +107,13 @@ async function listWorkerTargets(args: Args) {
installingWorker,
evaluatingWorker,
} = front;
await maybeMarkServiceWorker(activeWorker, "active");
await maybeMarkServiceWorker(waitingWorker, "waiting");
await maybeMarkServiceWorker(installingWorker, "installing");
await maybeMarkServiceWorker(evaluatingWorker, "evaluating");
await maybeMarkServiceWorker(activeWorker);
await maybeMarkServiceWorker(waitingWorker);
await maybeMarkServiceWorker(installingWorker);
await maybeMarkServiceWorker(evaluatingWorker);
}
async function maybeMarkServiceWorker(info, status) {
async function maybeMarkServiceWorker(info) {
if (!info) {
return;
}
@ -123,7 +123,7 @@ async function listWorkerTargets(args: Args) {
return;
}
worker.debuggerServiceWorkerStatus = status;
worker.debuggerServiceWorkerStatus = info.stateText;
if (!workers.includes(worker)) {
workers.push(worker);
}

View File

@ -88,6 +88,8 @@ export type FrameFront = {
actorID: string,
displayName: string,
this: any,
asyncCause: null | string,
state: "on-stack" | "suspended",
};
/**
@ -156,9 +158,9 @@ export type TabPayload = {
actor: ActorId,
animationsActor: ActorId,
consoleActor: ActorId,
contentViewerActor: ActorId,
cssPropertiesActor: ActorId,
directorManagerActor: ActorId,
emulationActor: ActorId,
eventLoopLagActor: ActorId,
framerateActor: ActorId,
inspectorActor: ActorId,
@ -169,6 +171,7 @@ export type TabPayload = {
performanceEntriesActor: ActorId,
profilerActor: ActorId,
reflowActor: ActorId,
responsiveActor: ActorId,
storageActor: ActorId,
styleEditorActor: ActorId,
styleSheetsActor: ActorId,

View File

@ -68,6 +68,7 @@ type FrameComponentProps = {
copyStackTrace: Function,
toggleFrameworkGrouping: Function,
selectFrame: typeof actions.selectFrame,
selectLocation: typeof actions.selectLocation,
frameworkGroupingOn: boolean,
hideLocation: boolean,
shouldMapDisplayName: boolean,
@ -75,7 +76,7 @@ type FrameComponentProps = {
displayFullUrl: boolean,
getFrameTitle?: string => string,
disableContextMenu: boolean,
selectable: boolean,
panel: "debugger" | "webconsole",
};
export default class FrameComponent extends Component<FrameComponentProps> {
@ -85,6 +86,14 @@ export default class FrameComponent extends Component<FrameComponentProps> {
disableContextMenu: false,
};
get isSelectable() {
return this.props.panel == "webconsole";
}
get isDebugger() {
return this.props.panel == "debugger";
}
onContextMenu(event: SyntheticMouseEvent<HTMLElement>) {
const {
frame,
@ -111,6 +120,7 @@ export default class FrameComponent extends Component<FrameComponentProps> {
if (e.button !== 0) {
return;
}
this.props.selectFrame(this.props.cx, frame);
}
@ -122,6 +132,7 @@ export default class FrameComponent extends Component<FrameComponentProps> {
if (event.key != "Enter") {
return;
}
this.props.selectFrame(this.props.cx, frame);
}
@ -134,7 +145,6 @@ export default class FrameComponent extends Component<FrameComponentProps> {
displayFullUrl,
getFrameTitle,
disableContextMenu,
selectable,
} = this.props;
const { l10n } = this.context;
@ -165,12 +175,14 @@ export default class FrameComponent extends Component<FrameComponentProps> {
>
{frame.asyncCause && (
<span className="location-async-cause">
{selectable && <FrameIndent />}
{l10n.getFormatStr("stacktrace.asyncStack", frame.asyncCause)}
{selectable && <br className="clipboard-only" />}
{this.isSelectable && <FrameIndent />}
{this.isDebugger
? frame.asyncCause
: l10n.getFormatStr("stacktrace.asyncStack", frame.asyncCause)}
{this.isSelectable && <br className="clipboard-only" />}
</span>
)}
{selectable && <FrameIndent />}
{this.isSelectable && <FrameIndent />}
<FrameTitle
frame={frame}
options={{ shouldMapDisplayName }}
@ -180,7 +192,7 @@ export default class FrameComponent extends Component<FrameComponentProps> {
{!hideLocation && (
<FrameLocation frame={frame} displayFullUrl={displayFullUrl} />
)}
{selectable && <br className="clipboard-only" />}
{this.isSelectable && <br className="clipboard-only" />}
</div>
);
}

View File

@ -43,6 +43,10 @@
text-align: right;
}
.call-stack-pane .location-async-cause {
color: var(--theme-comment);
}
.theme-light .frames .location {
color: var(--theme-comment);
}

View File

@ -44,6 +44,7 @@ type Props = {
group: Frame[],
selectedFrame: Frame,
selectFrame: typeof actions.selectFrame,
selectLocation: typeof actions.selectLocation,
toggleFrameworkGrouping: Function,
copyStackTrace: Function,
toggleBlackBox: Function,
@ -51,7 +52,7 @@ type Props = {
displayFullUrl: boolean,
getFrameTitle?: string => string,
disableContextMenu: boolean,
selectable: boolean,
panel: "debugger" | "webconsole",
};
type State = {
@ -66,6 +67,10 @@ export default class Group extends Component<Props, State> {
this.state = { expanded: false };
}
get isSelectable() {
return this.props.panel == "webconsole";
}
onContextMenu(event: SyntheticMouseEvent<HTMLElement>) {
const {
group,
@ -95,6 +100,7 @@ export default class Group extends Component<Props, State> {
cx,
group,
selectFrame,
selectLocation,
selectedFrame,
toggleFrameworkGrouping,
frameworkGroupingOn,
@ -103,7 +109,7 @@ export default class Group extends Component<Props, State> {
displayFullUrl,
getFrameTitle,
disableContextMenu,
selectable,
panel,
} = this.props;
const { expanded } = this.state;
@ -114,7 +120,7 @@ export default class Group extends Component<Props, State> {
return (
<div className="frames-list">
{group.reduce((acc, frame, i) => {
if (selectable) {
if (this.isSelectable) {
acc.push(<FrameIndent key={`frame-indent-${i}`} />);
}
return acc.concat(
@ -127,13 +133,14 @@ export default class Group extends Component<Props, State> {
key={frame.id}
selectedFrame={selectedFrame}
selectFrame={selectFrame}
selectLocation={selectLocation}
shouldMapDisplayName={false}
toggleBlackBox={toggleBlackBox}
toggleFrameworkGrouping={toggleFrameworkGrouping}
displayFullUrl={displayFullUrl}
getFrameTitle={getFrameTitle}
disableContextMenu={disableContextMenu}
selectable={selectable}
panel={panel}
/>
);
}, [])}
@ -143,7 +150,7 @@ export default class Group extends Component<Props, State> {
renderDescription() {
const { l10n } = this.context;
const { selectable, group } = this.props;
const { group } = this.props;
const frame = group[0];
const expanded = this.state.expanded;
@ -161,11 +168,11 @@ export default class Group extends Component<Props, State> {
tabIndex={0}
title={title}
>
{selectable && <FrameIndent />}
{this.isSelectable && <FrameIndent />}
<FrameLocation frame={frame} expanded={expanded} />
{selectable && <span className="clipboard-only"> </span>}
{this.isSelectable && <span className="clipboard-only"> </span>}
<Badge>{this.props.group.length}</Badge>
{selectable && <br className="clipboard-only" />}
{this.isSelectable && <br className="clipboard-only" />}
</div>
);
}

View File

@ -31,21 +31,23 @@ const NUM_FRAMES_SHOWN = 7;
type OwnProps = {|
getFrameTitle?: string => string,
selectable?: boolean,
panel: "debugger" | "webconsole",
|};
type Props = {
cx: ThreadContext,
frames: Array<Frame>,
frameworkGroupingOn: boolean,
selectedFrame: Object,
selectFrame: typeof actions.selectFrame,
selectLocation: typeof actions.selectLocation,
toggleBlackBox: Function,
toggleFrameworkGrouping: Function,
disableFrameTruncate: boolean,
disableContextMenu: boolean,
displayFullUrl: boolean,
getFrameTitle?: string => string,
selectable?: boolean,
panel: "debugger" | "webconsole",
};
type State = {
@ -118,13 +120,14 @@ class Frames extends Component<Props, State> {
const {
cx,
selectFrame,
selectLocation,
selectedFrame,
toggleBlackBox,
frameworkGroupingOn,
displayFullUrl,
getFrameTitle,
disableContextMenu,
selectable = false,
panel,
} = this.props;
const framesOrGroups = this.truncateFrames(this.collapseFrames(frames));
@ -144,13 +147,14 @@ class Frames extends Component<Props, State> {
copyStackTrace={this.copyStackTrace}
frameworkGroupingOn={frameworkGroupingOn}
selectFrame={selectFrame}
selectLocation={selectLocation}
selectedFrame={selectedFrame}
toggleBlackBox={toggleBlackBox}
key={String(frameOrGroup.id)}
displayFullUrl={displayFullUrl}
getFrameTitle={getFrameTitle}
disableContextMenu={disableContextMenu}
selectable={selectable}
panel={panel}
/>
) : (
<Group
@ -160,13 +164,14 @@ class Frames extends Component<Props, State> {
copyStackTrace={this.copyStackTrace}
frameworkGroupingOn={frameworkGroupingOn}
selectFrame={selectFrame}
selectLocation={selectLocation}
selectedFrame={selectedFrame}
toggleBlackBox={toggleBlackBox}
key={frameOrGroup[0].id}
displayFullUrl={displayFullUrl}
getFrameTitle={getFrameTitle}
disableContextMenu={disableContextMenu}
selectable={selectable}
panel={panel}
/>
)
)}
@ -232,6 +237,7 @@ export default connect<Props, OwnProps, _, _, _, _>(
mapStateToProps,
{
selectFrame: actions.selectFrame,
selectLocation: actions.selectLocation,
toggleBlackBox: actions.toggleBlackBox,
toggleFrameworkGrouping: actions.toggleFrameworkGrouping,
}

View File

@ -24,10 +24,11 @@ function frameProperties(frame, selectedFrame: any, overrides = {}) {
copyStackTrace: jest.fn(),
contextTypes: {},
selectFrame: jest.fn(),
selectLocation: jest.fn(),
toggleBlackBox: jest.fn(),
displayFullUrl: false,
frameworkGroupingOn: false,
selectable: true,
panel: "webconsole",
toggleFrameworkGrouping: null,
...overrides,
};

View File

@ -25,11 +25,12 @@ function render(overrides = {}) {
frameworkGroupingOn: true,
toggleFrameworkGrouping: jest.fn(),
selectFrame: jest.fn(),
selectLocation: jest.fn(),
copyStackTrace: jest.fn(),
toggleBlackBox: jest.fn(),
disableContextMenu: false,
displayFullUrl: false,
selectable: true,
panel: "webconsole",
};
const props = { ...defaultProps, ...overrides };

View File

@ -15,6 +15,7 @@ exports[`Frame getFrameTitle 1`] = `
<FrameTitle
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 10,
@ -51,6 +52,7 @@ exports[`Frame getFrameTitle 1`] = `
"relativeUrl": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
"url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -70,6 +72,7 @@ exports[`Frame getFrameTitle 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 10,
@ -106,6 +109,7 @@ exports[`Frame getFrameTitle 1`] = `
"relativeUrl": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
"url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -131,6 +135,7 @@ exports[`Frame library frame 1`] = `
<FrameTitle
frame={
Object {
"asyncCause": null,
"displayName": "updateEvents",
"generatedLocation": Object {
"line": 12,
@ -168,6 +173,7 @@ exports[`Frame library frame 1`] = `
"relativeUrl": "backbone.js",
"url": "backbone.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -187,6 +193,7 @@ exports[`Frame library frame 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "updateEvents",
"generatedLocation": Object {
"line": 12,
@ -224,6 +231,7 @@ exports[`Frame library frame 1`] = `
"relativeUrl": "backbone.js",
"url": "backbone.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -249,6 +257,7 @@ exports[`Frame user frame (not selected) 1`] = `
<FrameTitle
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 10,
@ -285,6 +294,7 @@ exports[`Frame user frame (not selected) 1`] = `
"relativeUrl": "foo-view.js",
"url": "foo-view.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -304,6 +314,7 @@ exports[`Frame user frame (not selected) 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 10,
@ -340,6 +351,7 @@ exports[`Frame user frame (not selected) 1`] = `
"relativeUrl": "foo-view.js",
"url": "foo-view.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -365,6 +377,7 @@ exports[`Frame user frame 1`] = `
<FrameTitle
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 10,
@ -401,6 +414,7 @@ exports[`Frame user frame 1`] = `
"relativeUrl": "foo-view.js",
"url": "foo-view.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -420,6 +434,7 @@ exports[`Frame user frame 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 10,
@ -456,6 +471,7 @@ exports[`Frame user frame 1`] = `
"relativeUrl": "foo-view.js",
"url": "foo-view.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}

View File

@ -12,6 +12,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
disableContextMenu={false}
frame={
Object {
"asyncCause": null,
"displayName": "display-1",
"generatedLocation": Object {
"line": 4,
@ -48,6 +49,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -56,9 +58,9 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "display-1",
"generatedLocation": Object {
"line": 4,
@ -95,6 +97,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -108,6 +111,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
disableContextMenu={false}
frame={
Object {
"asyncCause": null,
"displayName": "display-3",
"generatedLocation": Object {
"line": 4,
@ -144,6 +148,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -152,9 +157,9 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
hideLocation={false}
key="3"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "display-1",
"generatedLocation": Object {
"line": 4,
@ -191,6 +196,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -222,7 +228,6 @@ exports[`Frames Library Frames groups all the Webpack-related frames 1`] = `
hideLocation={false}
key="1-appFrame"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": "1-appFrame",
@ -265,7 +270,6 @@ exports[`Frames Library Frames groups all the Webpack-related frames 1`] = `
}
key="2-webpackBootstrapFrame"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": "1-appFrame",
@ -297,7 +301,6 @@ exports[`Frames Library Frames selectable framework frames 1`] = `
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -320,7 +323,6 @@ exports[`Frames Library Frames selectable framework frames 1`] = `
hideLocation={false}
key="2"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -343,7 +345,6 @@ exports[`Frames Library Frames selectable framework frames 1`] = `
hideLocation={false}
key="3"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -365,7 +366,6 @@ exports[`Frames Library Frames selectable framework frames 1`] = `
hideLocation={false}
key="8"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -398,7 +398,6 @@ exports[`Frames Library Frames selectable framework frames 2`] = `
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -425,7 +424,6 @@ exports[`Frames Library Frames selectable framework frames 2`] = `
}
key="2"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -446,7 +444,6 @@ exports[`Frames Library Frames selectable framework frames 2`] = `
hideLocation={false}
key="8"
selectFrame={[MockFunction]}
selectable={true}
selectedFrame={
Object {
"id": 1,
@ -479,7 +476,6 @@ exports[`Frames Library Frames toggling framework frames 1`] = `
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -502,7 +498,6 @@ exports[`Frames Library Frames toggling framework frames 1`] = `
hideLocation={false}
key="2"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -525,7 +520,6 @@ exports[`Frames Library Frames toggling framework frames 1`] = `
hideLocation={false}
key="3"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -547,7 +541,6 @@ exports[`Frames Library Frames toggling framework frames 1`] = `
hideLocation={false}
key="8"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -580,7 +573,6 @@ exports[`Frames Library Frames toggling framework frames 2`] = `
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -607,7 +599,6 @@ exports[`Frames Library Frames toggling framework frames 2`] = `
}
key="2"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -628,7 +619,6 @@ exports[`Frames Library Frames toggling framework frames 2`] = `
hideLocation={false}
key="8"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -661,7 +651,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -679,7 +668,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="2"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -697,7 +685,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="3"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -715,7 +702,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="4"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -733,7 +719,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="5"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -751,7 +736,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="6"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -769,7 +753,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="7"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -787,7 +770,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="8"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -805,7 +787,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="9"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -823,7 +804,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="10"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -841,7 +821,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="11"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -859,7 +838,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="12"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -877,7 +855,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="13"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -895,7 +872,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="14"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -913,7 +889,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="15"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -931,7 +906,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="16"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -949,7 +923,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="17"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -967,7 +940,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="18"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -985,7 +957,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="19"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -1003,7 +974,6 @@ exports[`Frames Supports different number of frames disable frame truncation 1`]
hideLocation={false}
key="20"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -1044,7 +1014,6 @@ exports[`Frames Supports different number of frames one frame 1`] = `
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1085,7 +1054,6 @@ exports[`Frames Supports different number of frames passes the getFrameTitle pro
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={null}
shouldMapDisplayName={true}
toggleBlackBox={[MockFunction]}
@ -1114,7 +1082,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="1"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1136,7 +1103,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="2"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1158,7 +1124,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="3"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1180,7 +1145,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="4"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1202,7 +1166,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="5"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1224,7 +1187,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="6"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1246,7 +1208,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="7"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1268,7 +1229,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="8"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1290,7 +1250,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="9"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,
@ -1312,7 +1271,6 @@ exports[`Frames Supports different number of frames toggling the show more butto
hideLocation={false}
key="10"
selectFrame={[MockFunction]}
selectable={false}
selectedFrame={
Object {
"id": 1,

View File

@ -18,6 +18,7 @@ exports[`Group displays a group 1`] = `
expanded={false}
frame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -55,6 +56,7 @@ exports[`Group displays a group 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -93,6 +95,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
expanded={true}
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 55,
@ -130,6 +133,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "http://myfile.com/mahscripts.js",
"url": "http://myfile.com/mahscripts.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -167,6 +171,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "renderFoo",
"generatedLocation": Object {
"line": 55,
@ -204,6 +209,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "http://myfile.com/mahscripts.js",
"url": "http://myfile.com/mahscripts.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -212,10 +218,12 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
getFrameTitle={[Function]}
hideLocation={true}
key="1"
panel="webconsole"
selectFrame={[MockFunction]}
selectable={true}
selectLocation={[MockFunction]}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -253,6 +261,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -278,6 +287,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "a",
"generatedLocation": Object {
"line": 55,
@ -315,6 +325,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "http://myfile.com/back.js",
"url": "http://myfile.com/back.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -323,10 +334,12 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
getFrameTitle={[Function]}
hideLocation={true}
key="2"
panel="webconsole"
selectFrame={[MockFunction]}
selectable={true}
selectLocation={[MockFunction]}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -364,6 +377,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -389,6 +403,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "b",
"generatedLocation": Object {
"line": 55,
@ -426,6 +441,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "http://myfile.com/back.js",
"url": "http://myfile.com/back.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -434,10 +450,12 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
getFrameTitle={[Function]}
hideLocation={true}
key="3"
panel="webconsole"
selectFrame={[MockFunction]}
selectable={true}
selectLocation={[MockFunction]}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -475,6 +493,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -505,6 +524,7 @@ exports[`Group renders group with anonymous functions 1`] = `
expanded={false}
frame={
Object {
"asyncCause": null,
"displayName": "display-1",
"generatedLocation": Object {
"line": 55,
@ -542,6 +562,7 @@ exports[`Group renders group with anonymous functions 1`] = `
"relativeUrl": "http://myfile.com/mahscripts.js",
"url": "http://myfile.com/mahscripts.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -580,6 +601,7 @@ exports[`Group renders group with anonymous functions 2`] = `
expanded={true}
frame={
Object {
"asyncCause": null,
"displayName": "display-1",
"generatedLocation": Object {
"line": 55,
@ -617,6 +639,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "http://myfile.com/mahscripts.js",
"url": "http://myfile.com/mahscripts.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -654,6 +677,7 @@ exports[`Group renders group with anonymous functions 2`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "display-1",
"generatedLocation": Object {
"line": 55,
@ -691,6 +715,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "http://myfile.com/mahscripts.js",
"url": "http://myfile.com/mahscripts.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -698,10 +723,12 @@ exports[`Group renders group with anonymous functions 2`] = `
frameworkGroupingOn={true}
hideLocation={true}
key="1"
panel="webconsole"
selectFrame={[MockFunction]}
selectable={true}
selectLocation={[MockFunction]}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -739,6 +766,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -764,6 +792,7 @@ exports[`Group renders group with anonymous functions 2`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "display-2",
"generatedLocation": Object {
"line": 55,
@ -801,6 +830,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "http://myfile.com/back.js",
"url": "http://myfile.com/back.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -808,10 +838,12 @@ exports[`Group renders group with anonymous functions 2`] = `
frameworkGroupingOn={true}
hideLocation={true}
key="2"
panel="webconsole"
selectFrame={[MockFunction]}
selectable={true}
selectLocation={[MockFunction]}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -849,6 +881,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -874,6 +907,7 @@ exports[`Group renders group with anonymous functions 2`] = `
displayFullUrl={false}
frame={
Object {
"asyncCause": null,
"displayName": "display-3",
"generatedLocation": Object {
"line": 55,
@ -911,6 +945,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "http://myfile.com/back.js",
"url": "http://myfile.com/back.js",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}
@ -918,10 +953,12 @@ exports[`Group renders group with anonymous functions 2`] = `
frameworkGroupingOn={true}
hideLocation={true}
key="3"
panel="webconsole"
selectFrame={[MockFunction]}
selectable={true}
selectLocation={[MockFunction]}
selectedFrame={
Object {
"asyncCause": null,
"displayName": "foo",
"generatedLocation": Object {
"line": 4,
@ -959,6 +996,7 @@ exports[`Group renders group with anonymous functions 2`] = `
"relativeUrl": "url",
"url": "url",
},
"state": "on-stack",
"this": Object {},
"thread": "FakeThread",
}

View File

@ -345,7 +345,7 @@ class SecondaryPanes extends Component<Props, State> {
return {
header: L10N.getStr("callStack.header"),
className: "call-stack-pane",
component: <Frames />,
component: <Frames panel="debugger" />,
opened: prefs.callStackVisible,
onToggle: opened => {
prefs.callStackVisible = opened;

View File

@ -9,13 +9,10 @@
* @module reducers/pending-breakpoints
*/
import { getSourcesByURL } from "./sources";
import {
createPendingBreakpoint,
makePendingLocationId,
} from "../utils/breakpoint";
import { isGenerated } from "../utils/source";
import type { SourcesState } from "./sources";
import type { PendingBreakpoint, Source } from "../types";
@ -86,12 +83,6 @@ export function getPendingBreakpointsForSource(
state: OuterState,
source: Source
): PendingBreakpoint[] {
const sources = getSourcesByURL(state, source.url);
if (sources.length > 1 && isGenerated(source)) {
// Don't return pending breakpoints for duplicated generated sources
return [];
}
return getPendingBreakpointList(state).filter(pendingBreakpoint => {
return (
pendingBreakpoint.location.sourceUrl === source.url ||

View File

@ -259,7 +259,7 @@ export type Frame = {
originalVariables?: XScopeVariables,
library?: string,
index: number,
asyncCause?: string,
asyncCause: null | string,
};
export type ChromeFrame = {

View File

@ -181,6 +181,8 @@ function makeMockFrame(
scope,
this: {},
index,
asyncCause: null,
state: "on-stack",
};
}

View File

@ -16,6 +16,7 @@ support-files =
!/devtools/client/shared/test/test-actor.js
[browser_dbg-asm.js]
[browser_dbg-asyncstacks.js]
[browser_dbg-audiocontext.js]
[browser_dbg-async-stepping.js]
[browser_dbg-sourcemapped-breakpoint-console.js]

View File

@ -0,0 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// Tests that async stacks include awaitees
add_task(async function() {
pushPref("devtools.debugger.features.async-live-stacks", true);
const dbg = await initDebugger("doc-frames-async.html");
invokeInTab("main");
await waitForPaused(dbg);
is(findElement(dbg, "frame", 1).innerText, "sleep\ndoc-frames-async.html:13");
is(
findElement(dbg, "frame", 2).innerText,
"await\nmain\ndoc-frames-async.html:17"
);
});

View File

@ -83,7 +83,7 @@ add_task(async function() {
invokeInTab("registerWorker");
await checkWorkerThreads(dbg, 1);
await checkWorkerStatus(dbg, "active");
await checkWorkerStatus(dbg, "activated");
const firstTab = gBrowser.selectedTab;
@ -143,7 +143,7 @@ add_task(async function() {
await waitForBreakpointCount(dbg, 1);
await waitForPaused(dbg);
assertPausedAtSourceAndLine(dbg, workerSource.id, 2);
await checkWorkerStatus(dbg, "evaluating");
await checkWorkerStatus(dbg, "parsed");
await addBreakpoint(dbg, "service-worker.sjs", 19);
await resume(dbg);
@ -155,7 +155,7 @@ add_task(async function() {
await resume(dbg);
await waitForPaused(dbg);
assertPausedAtSourceAndLine(dbg, workerSource.id, 5);
await checkWorkerStatus(dbg, "active");
await checkWorkerStatus(dbg, "activating");
await resume(dbg);
invokeInTab("unregisterWorker");

View File

@ -0,0 +1,21 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html>
<head>
<title>Frames</title>
</head>
<body>
<script>
async function sleep() {
await new Promise(r => setTimeout(r, 10));
debugger;
}
async function main() {
await sleep();
}
</script>
</body>
</html>

View File

@ -1966,13 +1966,13 @@ Toolbox.prototype = {
if (
!ResponsiveUIManager.isActiveForTab(localTab) ||
(await !this.target.actorHasMethod("emulation", "setElementPickerState"))
(await !this.target.actorHasMethod("responsive", "setElementPickerState"))
) {
return;
}
const ui = ResponsiveUIManager.getResponsiveUIForTab(localTab);
await ui.emulationFront.setElementPickerState(state);
await ui.responsiveFront.setElementPickerState(state);
},
/**

View File

@ -168,11 +168,29 @@ class RulesView {
this.provider = provider;
}
/**
* Initializes the content-viewer front and enable the print and color scheme simulation
* if they are supported in the current target.
*/
async initSimulationFeatures() {
// In order to query if the emulation actor's print simulation methods are supported,
// we have to call the emulation front so that the actor is lazily loaded. This allows
// us to use `actorHasMethod`. Please see `getActorDescription` for more information.
this.emulationFront = await this.currentTarget.getFront("emulation");
// In order to query if the content-viewer actor's print and color simulation methods are
// supported, we have to call the content-viewer front so that the actor is lazily loaded.
// This allows us to use `actorHasMethod`. Please see `getActorDescription` for more
// information.
try {
this.contentViewerFront = await this.currentTarget.getFront(
"contentViewer"
);
} catch (e) {
console.error(e);
}
// Bug 1606852: For backwards compatibility, we need to get the emulation actor. The ContentViewer
// actor is only available in Firefox 73 or newer. We can remove this call when Firefox 73
// is on release.
if (!this.contentViewerFront) {
this.contentViewerFront = await this.currentTarget.getFront("emulation");
}
if (!this.currentTarget.chrome) {
this.store.dispatch(updatePrintSimulationHidden(false));
@ -183,14 +201,22 @@ class RulesView {
// Show the color scheme simulation toggle button if:
// - The feature pref is enabled.
// - Color scheme simulation is supported for the current target.
const isEmulateColorSchemeSupported =
(await this.currentTarget.actorHasMethod(
"contentViewer",
"getEmulatedColorScheme"
)) ||
// Bug 1606852: We can removed this check when Firefox 73 is on release.
(await this.currentTarget.actorHasMethod(
"emulation",
"getEmulatedColorScheme"
));
if (
Services.prefs.getBoolPref(
"devtools.inspector.color-scheme-simulation.enabled"
) &&
(await this.currentTarget.actorHasMethod(
"emulation",
"getEmulatedColorScheme"
))
isEmulateColorSchemeSupported
) {
this.store.dispatch(updateColorSchemeSimulationHidden(false));
} else {
@ -226,9 +252,9 @@ class RulesView {
this.elementStyle = null;
}
if (this.emulationFront) {
this.emulationFront.destroy();
this.emulationFront = null;
if (this.contentViewerFront) {
this.contentViewerFront.destroy();
this.contentViewerFront = null;
}
this._dummyElement = null;
@ -491,10 +517,10 @@ class RulesView {
* Handler for toggling color scheme simulation.
*/
async onToggleColorSchemeSimulation() {
const currentState = await this.emulationFront.getEmulatedColorScheme();
const currentState = await this.contentViewerFront.getEmulatedColorScheme();
const index = COLOR_SCHEMES.indexOf(currentState);
const nextState = COLOR_SCHEMES[(index + 1) % COLOR_SCHEMES.length];
await this.emulationFront.setEmulatedColorScheme(nextState);
await this.contentViewerFront.setEmulatedColorScheme(nextState);
await this.updateElementStyle();
}
@ -502,12 +528,12 @@ class RulesView {
* Handler for toggling print media simulation.
*/
async onTogglePrintSimulation() {
const enabled = await this.emulationFront.getIsPrintSimulationEnabled();
const enabled = await this.contentViewerFront.getIsPrintSimulationEnabled();
if (!enabled) {
await this.emulationFront.startPrintMediaSimulation();
await this.contentViewerFront.startPrintMediaSimulation();
} else {
await this.emulationFront.stopPrintMediaSimulation(false);
await this.contentViewerFront.stopPrintMediaSimulation(false);
}
await this.updateElementStyle();

View File

@ -288,10 +288,6 @@ CssRuleView.prototype = {
return this._dummyElement;
},
get emulationFront() {
return this._emulationFront;
},
// Get the highlighters overlay from the Inspector.
get highlighters() {
if (!this._highlighters) {
@ -405,15 +401,28 @@ CssRuleView.prototype = {
},
/**
* Initializes the emulation front and enable the print and color scheme simulation
* Initializes the content-viewer front and enable the print and color scheme simulation
* if they are supported in the current target.
*/
async _initSimulationFeatures() {
// In order to query if the emulation actor's print and color simulation methods are
// supported, we have to call the emulation front so that the actor is lazily loaded.
// In order to query if the content-viewer actor's print and color simulation methods are
// supported, we have to call the content-viewer front so that the actor is lazily loaded.
// This allows us to use `actorHasMethod`. Please see `getActorDescription` for more
// information.
this._emulationFront = await this.currentTarget.getFront("emulation");
try {
this.contentViewerFront = await this.currentTarget.getFront(
"contentViewer"
);
} catch (e) {
console.error(e);
}
// Bug 1606852: For backwards compatibility, we need to get the emulation actor. The ContentViewer
// actor is only available in Firefox 73 or newer. We can remove this call when Firefox 73
// is on release.
if (!this.contentViewerFront) {
this.contentViewerFront = await this.currentTarget.getFront("emulation");
}
if (!this.currentTarget.chrome) {
this.printSimulationButton.removeAttribute("hidden");
@ -426,14 +435,22 @@ CssRuleView.prototype = {
// Show the color scheme simulation toggle button if:
// - The feature pref is enabled.
// - Color scheme simulation is supported for the current target.
const isEmulateColorSchemeSupported =
(await this.currentTarget.actorHasMethod(
"contentViewer",
"getEmulatedColorScheme"
)) ||
// Bug 1606852: We can removed this check when Firefox 73 is on release.
(await this.currentTarget.actorHasMethod(
"emulation",
"getEmulatedColorScheme"
));
if (
Services.prefs.getBoolPref(
"devtools.inspector.color-scheme-simulation.enabled"
) &&
(await this.currentTarget.actorHasMethod(
"emulation",
"getEmulatedColorScheme"
))
isEmulateColorSchemeSupported
) {
this.colorSchemeSimulationButton.removeAttribute("hidden");
this.colorSchemeSimulationButton.addEventListener(
@ -847,7 +864,7 @@ CssRuleView.prototype = {
}
// Clean-up for print simulation.
if (this._emulationFront) {
if (this.contentViewerFront) {
this.colorSchemeSimulationButton.removeEventListener(
"click",
this._onToggleColorSchemeSimulation
@ -857,11 +874,11 @@ CssRuleView.prototype = {
this._onTogglePrintSimulation
);
this._emulationFront.destroy();
this.contentViewerFront.destroy();
this.colorSchemeSimulationButton = null;
this.printSimulationButton = null;
this._emulationFront = null;
this.contentViewerFront = null;
}
this.tooltips.destroy();
@ -1739,7 +1756,7 @@ CssRuleView.prototype = {
},
async _onToggleColorSchemeSimulation() {
const currentState = await this.emulationFront.getEmulatedColorScheme();
const currentState = await this.contentViewerFront.getEmulatedColorScheme();
const index = COLOR_SCHEMES.indexOf(currentState);
const nextState = COLOR_SCHEMES[(index + 1) % COLOR_SCHEMES.length];
@ -1749,19 +1766,19 @@ CssRuleView.prototype = {
this.colorSchemeSimulationButton.removeAttribute("state");
}
await this.emulationFront.setEmulatedColorScheme(nextState);
await this.contentViewerFront.setEmulatedColorScheme(nextState);
this.refreshPanel();
},
async _onTogglePrintSimulation() {
const enabled = await this.emulationFront.getIsPrintSimulationEnabled();
const enabled = await this.contentViewerFront.getIsPrintSimulationEnabled();
if (!enabled) {
this.printSimulationButton.classList.add("checked");
await this.emulationFront.startPrintMediaSimulation();
await this.contentViewerFront.startPrintMediaSimulation();
} else {
this.printSimulationButton.classList.remove("checked");
await this.emulationFront.stopPrintMediaSimulation(false);
await this.contentViewerFront.stopPrintMediaSimulation(false);
}
// Refresh the current element's rules in the panel.

View File

@ -151,17 +151,17 @@ exports.menuitems = [
// Similarly, enable them when the color picker is done picking.
if (
ResponsiveUIManager.isActiveForTab(target.localTab) &&
target.actorHasMethod("emulation", "setElementPickerState")
target.actorHasMethod("responsive", "setElementPickerState")
) {
const ui = ResponsiveUIManager.getResponsiveUIForTab(target.localTab);
await ui.emulationFront.setElementPickerState(true);
await ui.responsiveFront.setElementPickerState(true);
inspectorFront.once("color-picked", async () => {
await ui.emulationFront.setElementPickerState(false);
await ui.responsiveFront.setElementPickerState(false);
});
inspectorFront.once("color-pick-canceled", async () => {
await ui.emulationFront.setElementPickerState(false);
await ui.responsiveFront.setElementPickerState(false);
});
}

View File

@ -83,8 +83,19 @@ class FirefoxConnector {
this.tabTarget.on("will-navigate", this.willNavigate);
this.tabTarget.on("navigate", this.navigate);
// Initialize Emulation front for network throttling.
this.emulationFront = await this.tabTarget.getFront("emulation");
// Initialize Responsive Emulation front for network throttling.
try {
this.responsiveFront = await this.tabTarget.getFront("responsive");
} catch (e) {
console.error(e);
}
// Bug 1606852: For backwards compatibility, we need to get the emulation actor. The Responsive
// actor is only available in Firefox 73 or newer. We can remove this call when Firefox 73
// is on release.
if (!this.responsiveFront) {
this.responsiveFront = await this.tabTarget.getFront("emulation");
}
}
// Displaying cache events is only intended for the UI panel.
@ -100,9 +111,9 @@ class FirefoxConnector {
this.removeListeners();
if (this.emulationFront) {
this.emulationFront.destroy();
this.emulationFront = null;
if (this.responsiveFront) {
this.responsiveFront.destroy();
this.responsiveFront = null;
}
if (this.webSocketFront) {
@ -474,11 +485,11 @@ class FirefoxConnector {
async updateNetworkThrottling(enabled, profile) {
if (!enabled) {
await this.emulationFront.clearNetworkThrottling();
await this.responsiveFront.clearNetworkThrottling();
} else {
const data = throttlingProfiles.find(({ id }) => id == profile);
const { download, upload, latency } = data;
await this.emulationFront.setNetworkThrottling({
await this.responsiveFront.setNetworkThrottling({
downloadThroughput: download,
uploadThroughput: upload,
latency,

View File

@ -42,7 +42,7 @@ function testNetworkThrottlingSelectorLabel(ui, expected) {
}
var testNetworkThrottlingState = async function(ui, expected) {
const state = await ui.emulationFront.getNetworkThrottling();
const state = await ui.responsiveFront.getNetworkThrottling();
Assert.deepEqual(
state,
expected,

View File

@ -543,7 +543,7 @@ async function testTouchEventsOverride(ui, expected) {
const { document } = ui.toolWindow;
const touchButton = document.getElementById("touch-simulation-button");
const flag = await ui.emulationFront.getTouchEventsOverride();
const flag = await ui.responsiveFront.getTouchEventsOverride();
is(
flag === Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED,
expected,

View File

@ -206,7 +206,7 @@ class ResponsiveUI {
await message.request(this.toolWindow, "start-frame-script");
}
// Get the protocol ready to speak with emulation actor
// Get the protocol ready to speak with responsive emulation actor
debug("Wait until RDP server connect");
await this.connectToServer();
@ -214,7 +214,7 @@ class ResponsiveUI {
await this.restoreState();
if (this.isBrowserUIEnabled) {
await this.emulationFront.setDocumentInRDMPane(true);
await this.responsiveFront.setDocumentInRDMPane(true);
}
if (!this.isBrowserUIEnabled) {
@ -316,7 +316,7 @@ class ResponsiveUI {
}
if (this.isBrowserUIEnabled) {
await this.emulationFront.setDocumentInRDMPane(false);
await this.responsiveFront.setDocumentInRDMPane(false);
}
this.tab.removeEventListener("TabClose", this);
@ -368,14 +368,14 @@ class ResponsiveUI {
this.toolWindow = null;
this.swap = null;
// Close the debugger client used to speak with emulation actor.
// Close the debugger client used to speak with responsive emulation actor.
// The actor handles clearing any overrides itself, so it's not necessary to clear
// anything on shutdown client side.
const clientClosed = this.client.close();
if (!isTabContentDestroying) {
await clientClosed;
}
this.client = this.emulationFront = null;
this.client = this.responsiveFront = null;
if (!this.isBrowserUIEnabled && !isWindowClosing) {
// Undo the swap and return the content back to a normal tab
@ -395,11 +395,11 @@ class ResponsiveUI {
this.client = new DebuggerClient(DebuggerServer.connectPipe());
await this.client.connect();
const targetFront = await this.client.mainRoot.getTab();
this.emulationFront = await targetFront.getFront("emulation");
this.responsiveFront = await targetFront.getFront("responsive");
}
/**
* Show one-time notification about reloads for emulation.
* Show one-time notification about reloads for responsive emulation.
*/
showReloadNotification() {
if (Services.prefs.getBoolPref(RELOAD_NOTIFICATION_PREF, false)) {
@ -597,12 +597,12 @@ class ResponsiveUI {
async onScreenshot() {
const targetFront = await this.client.mainRoot.getTab();
const captureScreenshotSupported = await targetFront.actorHasMethod(
"emulation",
"responsive",
"captureScreenshot"
);
if (captureScreenshotSupported) {
const data = await this.emulationFront.captureScreenshot();
const data = await this.responsiveFront.captureScreenshot();
await saveScreenshot(this.browserWindow, {}, data);
message.post(this.rdmFrame.contentWindow, "screenshot-captured");
@ -698,10 +698,10 @@ class ResponsiveUI {
*/
async updateDPPX(dppx) {
if (!dppx) {
await this.emulationFront.clearDPPXOverride();
await this.responsiveFront.clearDPPXOverride();
return false;
}
await this.emulationFront.setDPPXOverride(dppx);
await this.responsiveFront.setDPPXOverride(dppx);
return false;
}
@ -714,12 +714,12 @@ class ResponsiveUI {
*/
async updateNetworkThrottling(enabled, profile) {
if (!enabled) {
await this.emulationFront.clearNetworkThrottling();
await this.responsiveFront.clearNetworkThrottling();
return false;
}
const data = throttlingProfiles.find(({ id }) => id == profile);
const { download, upload, latency } = data;
await this.emulationFront.setNetworkThrottling({
await this.responsiveFront.setNetworkThrottling({
downloadThroughput: download,
uploadThroughput: upload,
latency,
@ -735,9 +735,9 @@ class ResponsiveUI {
*/
updateUserAgent(userAgent) {
if (!userAgent) {
return this.emulationFront.clearUserAgentOverride();
return this.responsiveFront.clearUserAgentOverride();
}
return this.emulationFront.setUserAgentOverride(userAgent);
return this.responsiveFront.setUserAgentOverride(userAgent);
}
/**
@ -758,18 +758,18 @@ class ResponsiveUI {
false
);
reloadNeeded = await this.emulationFront.setTouchEventsOverride(
reloadNeeded = await this.responsiveFront.setTouchEventsOverride(
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED
);
if (metaViewportEnabled) {
reloadNeeded |= await this.emulationFront.setMetaViewportOverride(
reloadNeeded |= await this.responsiveFront.setMetaViewportOverride(
Ci.nsIDocShell.META_VIEWPORT_OVERRIDE_ENABLED
);
}
} else {
reloadNeeded = await this.emulationFront.clearTouchEventsOverride();
reloadNeeded |= await this.emulationFront.clearMetaViewportOverride();
reloadNeeded = await this.responsiveFront.clearTouchEventsOverride();
reloadNeeded |= await this.responsiveFront.clearMetaViewportOverride();
}
return reloadNeeded;
}
@ -791,13 +791,13 @@ class ResponsiveUI {
async updateScreenOrientation(type, angle, isViewportRotated = false) {
const targetFront = await this.client.mainRoot.getTab();
const simulateOrientationChangeSupported = await targetFront.actorHasMethod(
"emulation",
"responsive",
"simulateScreenOrientationChange"
);
// Ensure that simulateScreenOrientationChange is supported.
if (simulateOrientationChangeSupported) {
await this.emulationFront.simulateScreenOrientationChange(
await this.responsiveFront.simulateScreenOrientationChange(
type,
angle,
isViewportRotated

View File

@ -261,7 +261,7 @@ class SmartTrace extends Component {
disableContextMenu: true,
frameworkGroupingOn: true,
displayFullUrl: !this.state || !this.state.isSourceMapped,
selectable: true,
panel: "webconsole",
});
}
}

View File

@ -3179,7 +3179,7 @@ function ErrorRep(props) {
const mode = props.mode;
let name;
if (preview && preview.name && preview.kind) {
if (preview && preview.name && typeof preview.name === "string" && preview.kind) {
switch (preview.kind) {
case "Error":
name = preview.name;
@ -3198,7 +3198,7 @@ function ErrorRep(props) {
const content = [];
if (mode === MODE.TINY) {
if (mode === MODE.TINY || typeof preview.message !== "string") {
content.push(name);
} else {
content.push(`${name}: "${preview.message}"`);

View File

@ -16,6 +16,8 @@ const TEST_URI =
const STUB_FILE = "pageError.js";
add_task(async function() {
await pushPref("javascript.options.asyncstack", true);
const isStubsUpdate = env.get(STUBS_UPDATE_ENV) == "true";
info(`${isStubsUpdate ? "Update" : "Check"} ${STUB_FILE}`);

View File

@ -11,6 +11,7 @@ const TEST_URI =
"test/browser/test-error-worker.html";
add_task(async function() {
await pushPref("javascript.options.asyncstack", true);
const hud = await openNewTabAndConsole(TEST_URI);
await checkMessageStack(hud, "hello", [13, 4, 3]);

View File

@ -495,7 +495,7 @@ class WebConsoleUI {
}
getLongString(grip) {
this.getProxy().webConsoleFront.getString(grip);
return this.getProxy().webConsoleFront.getString(grip);
}
/**

View File

@ -33,6 +33,8 @@ loader.lazyRequireGetter(
* A subtle aspect of the code below is that all get* methods must return non-undefined
* values, so that the absence of a previous value can be distinguished from the value for
* "no override" for each of the properties.
*
* Bug 1606852: Delete this file when Firefox 73 is on release.
*/
const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
initialize(conn, targetActor) {

View File

@ -0,0 +1,132 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci } = require("chrome");
const protocol = require("devtools/shared/protocol");
const { contentViewerSpec } = require("devtools/shared/specs/content-viewer");
/**
* This actor emulates various browser content environments by using methods available
* on the ContentViewer exposed by the platform.
*/
const ContentViewerActor = protocol.ActorClassWithSpec(contentViewerSpec, {
initialize(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.targetActor = targetActor;
this.docShell = targetActor.docShell;
this.onWillNavigate = this.onWillNavigate.bind(this);
this.onWindowReady = this.onWindowReady.bind(this);
this.targetActor.on("will-navigate", this.onWillNavigate);
this.targetActor.on("window-ready", this.onWindowReady);
},
destroy() {
this.stopPrintMediaSimulation();
this.setEmulatedColorScheme();
this.targetActor.off("will-navigate", this.onWillNavigate);
this.targetActor.off("window-ready", this.onWindowReady);
this.targetActor = null;
this.docShell = null;
protocol.Actor.prototype.destroy.call(this);
},
onWillNavigate({ isTopLevel }) {
// Make sure that print simulation is stopped before navigating to another page. We
// need to do this since the browser will cache the last state of the page in its
// session history.
if (this._printSimulationEnabled && isTopLevel) {
this.stopPrintMediaSimulation(true);
}
},
onWindowReady({ isTopLevel }) {
// Since `emulateMedium` only works for the current page, we need to ensure persistent
// print simulation for when the user navigates to a new page while its enabled.
// To do this, we need to tell the page to begin print simulation before the DOM
// content is available to the user:
if (this._printSimulationEnabled && isTopLevel) {
this.startPrintMediaSimulation();
}
},
/* Color scheme simulation */
/**
* Returns the currently emulated color scheme.
*/
getEmulatedColorScheme() {
return this._emulatedColorScheme;
},
/**
* Sets the currently emulated color scheme or if an invalid value is given,
* the override is cleared.
*/
setEmulatedColorScheme(scheme = null) {
if (this._emulatedColorScheme === scheme) {
return;
}
let internalColorScheme;
switch (scheme) {
case "light":
internalColorScheme = Ci.nsIContentViewer.PREFERS_COLOR_SCHEME_LIGHT;
break;
case "dark":
internalColorScheme = Ci.nsIContentViewer.PREFERS_COLOR_SCHEME_DARK;
break;
case "no-preference":
internalColorScheme =
Ci.nsIContentViewer.PREFERS_COLOR_SCHEME_NO_PREFERENCE;
break;
default:
internalColorScheme = Ci.nsIContentViewer.PREFERS_COLOR_SCHEME_NONE;
}
this._emulatedColorScheme = scheme;
this.docShell.contentViewer.emulatePrefersColorScheme(internalColorScheme);
},
// The current emulated color scheme value. It's possible values are listed in the
// COLOR_SCHEMES constant in devtools/client/inspector/rules/constants.
_emulatedColorScheme: null,
/* Simulating print media for the page */
_printSimulationEnabled: false,
getIsPrintSimulationEnabled() {
return this._printSimulationEnabled;
},
async startPrintMediaSimulation() {
this._printSimulationEnabled = true;
this.targetActor.docShell.contentViewer.emulateMedium("print");
},
/**
* Stop simulating print media for the current page.
*
* @param {Boolean} state
* Whether or not to set _printSimulationEnabled to false. If true, we want to
* stop simulation print media for the current page but NOT set
* _printSimulationEnabled to false. We do this specifically for the
* "will-navigate" event where we still want to continue simulating print when
* navigating to the next page. Defaults to false, meaning we want to completely
* stop print simulation.
*/
async stopPrintMediaSimulation(state = false) {
this._printSimulationEnabled = state;
this.targetActor.docShell.contentViewer.stopEmulatingMedium();
},
});
exports.ContentViewerActor = ContentViewerActor;

View File

@ -5,5 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'content-viewer.js',
'responsive.js',
'touch-simulator.js',
)

View File

@ -0,0 +1,367 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci } = require("chrome");
const protocol = require("devtools/shared/protocol");
const { responsiveSpec } = require("devtools/shared/specs/responsive");
loader.lazyRequireGetter(
this,
"ScreenshotActor",
"devtools/server/actors/screenshot",
true
);
loader.lazyRequireGetter(
this,
"TouchSimulator",
"devtools/server/actors/emulation/touch-simulator",
true
);
/**
* This actor overrides various browser features to simulate different environments to
* test how pages perform under various conditions.
*
* The design below, which saves the previous value of each property before setting, is
* needed because it's possible to have multiple copies of this actor for a single page.
* When some instance of this actor changes a property, we want it to be able to restore
* that property to the way it was found before the change.
*
* A subtle aspect of the code below is that all get* methods must return non-undefined
* values, so that the absence of a previous value can be distinguished from the value for
* "no override" for each of the properties.
*/
const ResponsiveActor = protocol.ActorClassWithSpec(responsiveSpec, {
initialize(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.targetActor = targetActor;
this.docShell = targetActor.docShell;
},
destroy() {
this.clearDPPXOverride();
this.clearNetworkThrottling();
this.clearTouchEventsOverride();
this.clearMetaViewportOverride();
this.clearUserAgentOverride();
this.targetActor = null;
this.docShell = null;
this._screenshotActor = null;
this._touchSimulator = null;
protocol.Actor.prototype.destroy.call(this);
},
/**
* Retrieve the console actor for this tab. This allows us to expose network throttling
* as part of emulation settings, even though it's internally connected to the network
* monitor, which for historical reasons is part of the console actor.
*/
get _consoleActor() {
if (this.targetActor.exited || !this.targetActor.actorID) {
return null;
}
const form = this.targetActor.form();
return this.conn._getOrCreateActor(form.consoleActor);
},
get screenshotActor() {
if (!this._screenshotActor) {
this._screenshotActor = new ScreenshotActor(this.conn, this.targetActor);
this.manage(this._screenshotActor);
}
return this._screenshotActor;
},
get touchSimulator() {
if (!this._touchSimulator) {
this._touchSimulator = new TouchSimulator(
this.targetActor.chromeEventHandler
);
}
return this._touchSimulator;
},
get win() {
return this.docShell.chromeEventHandler.ownerGlobal;
},
/* DPPX override */
_previousDPPXOverride: undefined,
setDPPXOverride(dppx) {
if (this.getDPPXOverride() === dppx) {
return false;
}
if (this._previousDPPXOverride === undefined) {
this._previousDPPXOverride = this.getDPPXOverride();
}
this.docShell.contentViewer.overrideDPPX = dppx;
return true;
},
getDPPXOverride() {
return this.docShell.contentViewer.overrideDPPX;
},
clearDPPXOverride() {
if (this._previousDPPXOverride !== undefined) {
return this.setDPPXOverride(this._previousDPPXOverride);
}
return false;
},
/* Network Throttling */
_previousNetworkThrottling: undefined,
/**
* Transform the RDP format into the internal format and then set network throttling.
*/
setNetworkThrottling({ downloadThroughput, uploadThroughput, latency }) {
const throttleData = {
latencyMean: latency,
latencyMax: latency,
downloadBPSMean: downloadThroughput,
downloadBPSMax: downloadThroughput,
uploadBPSMean: uploadThroughput,
uploadBPSMax: uploadThroughput,
};
return this._setNetworkThrottling(throttleData);
},
_setNetworkThrottling(throttleData) {
const current = this._getNetworkThrottling();
// Check if they are both objects or both null
let match = throttleData == current;
// If both objects, check all entries
if (match && current && throttleData) {
match = Object.entries(current).every(([k, v]) => {
return throttleData[k] === v;
});
}
if (match) {
return false;
}
if (this._previousNetworkThrottling === undefined) {
this._previousNetworkThrottling = current;
}
const consoleActor = this._consoleActor;
if (!consoleActor) {
return false;
}
consoleActor.startListeners(["NetworkActivity"]);
consoleActor.setPreferences({
"NetworkMonitor.throttleData": throttleData,
});
return true;
},
/**
* Get network throttling and then transform the internal format into the RDP format.
*/
getNetworkThrottling() {
const throttleData = this._getNetworkThrottling();
if (!throttleData) {
return null;
}
const { downloadBPSMax, uploadBPSMax, latencyMax } = throttleData;
return {
downloadThroughput: downloadBPSMax,
uploadThroughput: uploadBPSMax,
latency: latencyMax,
};
},
_getNetworkThrottling() {
const consoleActor = this._consoleActor;
if (!consoleActor) {
return null;
}
const prefs = consoleActor.getPreferences(["NetworkMonitor.throttleData"]);
return prefs.preferences["NetworkMonitor.throttleData"] || null;
},
clearNetworkThrottling() {
if (this._previousNetworkThrottling !== undefined) {
return this._setNetworkThrottling(this._previousNetworkThrottling);
}
return false;
},
/* Touch events override */
_previousTouchEventsOverride: undefined,
/**
* Set the current element picker state.
*
* True means the element picker is currently active and we should not be emulating
* touch events.
* False means the element picker is not active and it is ok to emulate touch events.
*
* This actor method is meant to be called by the DevTools front-end. The reason for
* this is the following:
* RDM is the only current consumer of the touch simulator. RDM instantiates this actor
* on its own, whether or not the Toolbox is opened. That means it does so in its own
* Debugger Server instance.
* When the Toolbox is running, it uses a different DebuggerServer. Therefore, it is not
* possible for the touch simulator to know whether the picker is active or not. This
* state has to be sent by the client code of the Toolbox to this actor.
* If a future use case arises where we want to use the touch simulator from the Toolbox
* too, then we could add code in here to detect the picker mode as described in
* https://bugzilla.mozilla.org/show_bug.cgi?id=1409085#c3
* @param {Boolean} state
*/
setElementPickerState(state) {
this.touchSimulator.setElementPickerState(state);
},
setTouchEventsOverride(flag) {
if (this.getTouchEventsOverride() == flag) {
return false;
}
if (this._previousTouchEventsOverride === undefined) {
this._previousTouchEventsOverride = this.getTouchEventsOverride();
}
// Start or stop the touch simulator depending on the override flag
if (flag == Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED) {
this.touchSimulator.start();
} else {
this.touchSimulator.stop();
}
this.docShell.touchEventsOverride = flag;
return true;
},
getTouchEventsOverride() {
return this.docShell.touchEventsOverride;
},
clearTouchEventsOverride() {
if (this._previousTouchEventsOverride !== undefined) {
return this.setTouchEventsOverride(this._previousTouchEventsOverride);
}
return false;
},
/* Meta viewport override */
_previousMetaViewportOverride: undefined,
setMetaViewportOverride(flag) {
if (this.getMetaViewportOverride() == flag) {
return false;
}
if (this._previousMetaViewportOverride === undefined) {
this._previousMetaViewportOverride = this.getMetaViewportOverride();
}
this.docShell.metaViewportOverride = flag;
return true;
},
getMetaViewportOverride() {
return this.docShell.metaViewportOverride;
},
clearMetaViewportOverride() {
if (this._previousMetaViewportOverride !== undefined) {
return this.setMetaViewportOverride(this._previousMetaViewportOverride);
}
return false;
},
/* User agent override */
_previousUserAgentOverride: undefined,
setUserAgentOverride(userAgent) {
if (this.getUserAgentOverride() == userAgent) {
return false;
}
if (this._previousUserAgentOverride === undefined) {
this._previousUserAgentOverride = this.getUserAgentOverride();
}
this.docShell.customUserAgent = userAgent;
return true;
},
getUserAgentOverride() {
return this.docShell.customUserAgent;
},
clearUserAgentOverride() {
if (this._previousUserAgentOverride !== undefined) {
return this.setUserAgentOverride(this._previousUserAgentOverride);
}
return false;
},
setScreenOrientation(type, angle) {
if (
this.win.screen.orientation.angle !== angle ||
this.win.screen.orientation.type !== type
) {
this.docShell.browsingContext.setRDMPaneOrientation(type, angle);
}
},
/**
* Simulates the "orientationchange" event when device screen is rotated.
*
* @param {String} type
* The orientation type of the rotated device.
* @param {Number} angle
* The rotated angle of the device.
* @param {Boolean} isViewportRotated
* Whether or not screen orientation change is a result of rotating the viewport.
* If true, then dispatch the "orientationchange" event on the content window.
*/
async simulateScreenOrientationChange(
type,
angle,
isViewportRotated = false
) {
// Don't dispatch the "orientationchange" event if orientation change is a result
// of switching to a new device, location change, or opening RDM.
if (!isViewportRotated) {
this.setScreenOrientation(type, angle);
return;
}
const { CustomEvent } = this.win;
const orientationChangeEvent = new CustomEvent("orientationchange");
this.setScreenOrientation(type, angle);
this.win.dispatchEvent(orientationChangeEvent);
},
async captureScreenshot() {
return this.screenshotActor.capture({});
},
async setDocumentInRDMPane(inRDMPane) {
if (this.docShell && this.docShell.document) {
this.docShell.browsingContext.inRDMPane = inRDMPane;
}
},
});
exports.ResponsiveActor = ResponsiveActor;

View File

@ -214,9 +214,14 @@ const ActorRegistry = {
constructor: "AnimationsActor",
type: { target: true },
});
this.registerModule("devtools/server/actors/emulation", {
prefix: "emulation",
constructor: "EmulationActor",
this.registerModule("devtools/server/actors/emulation/responsive", {
prefix: "responsive",
constructor: "ResponsiveActor",
type: { target: true },
});
this.registerModule("devtools/server/actors/emulation/content-viewer", {
prefix: "contentViewer",
constructor: "ContentViewerActor",
type: { target: true },
});
this.registerModule(

View File

@ -0,0 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
FrontClassWithSpec,
registerFront,
} = require("devtools/shared/protocol");
const { contentViewerSpec } = require("devtools/shared/specs/content-viewer");
/**
* The corresponding Front object for the ContentViewer actor.
*/
class ContentViewerFront extends FrontClassWithSpec(contentViewerSpec) {
constructor(client, targetFront, parentFront) {
super(client, targetFront, parentFront);
// Attribute name from which to retrieve the actorID out of the target actor's form
this.formAttributeName = "contentViewerActor";
}
}
exports.ContentViewerFront = ContentViewerFront;
registerFront(ContentViewerFront);

View File

@ -12,6 +12,8 @@ const { emulationSpec } = require("devtools/shared/specs/emulation");
/**
* The corresponding Front object for the EmulationActor.
*
* Bug 1606852: Delete this file when Firefox 73 is on release.
*/
class EmulationFront extends FrontClassWithSpec(emulationSpec) {
constructor(client, targetFront, parentFront) {

View File

@ -18,6 +18,7 @@ DevToolsModules(
'animation.js',
'array-buffer.js',
'changes.js',
'content-viewer.js',
'css-properties.js',
'device.js',
'emulation.js',
@ -37,6 +38,7 @@ DevToolsModules(
'preference.js',
'property-iterator.js',
'reflow.js',
'responsive.js',
'root.js',
'screenshot.js',
'source.js',

View File

@ -0,0 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
FrontClassWithSpec,
registerFront,
} = require("devtools/shared/protocol");
const { responsiveSpec } = require("devtools/shared/specs/responsive");
/**
* The corresponding Front object for the Responsive actor.
*/
class ResponsiveFront extends FrontClassWithSpec(responsiveSpec) {
constructor(client, targetFront, parentFront) {
super(client, targetFront, parentFront);
// Attribute name from which to retrieve the actorID out of the target actor's form
this.formAttributeName = "responsiveActor";
}
}
exports.ResponsiveFront = ResponsiveFront;
registerFront(ResponsiveFront);

View File

@ -10,6 +10,7 @@ const {
FrontClassWithSpec,
registerFront,
} = require("devtools/shared/protocol");
const { Ci } = require("chrome");
class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
get fetch() {
@ -24,6 +25,25 @@ class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
return this._form.state;
}
get stateText() {
switch (this.state) {
case Ci.nsIServiceWorkerInfo.STATE_PARSED:
return "parsed";
case Ci.nsIServiceWorkerInfo.STATE_INSTALLING:
return "installing";
case Ci.nsIServiceWorkerInfo.STATE_INSTALLED:
return "installed";
case Ci.nsIServiceWorkerInfo.STATE_ACTIVATING:
return "activating";
case Ci.nsIServiceWorkerInfo.STATE_ACTIVATED:
return "activated";
case Ci.nsIServiceWorkerInfo.STATE_REDUNDANT:
return "redundant";
default:
return "unknown";
}
}
get id() {
return this._form.id;
}

View File

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol");
const contentViewerSpec = generateActorSpec({
typeName: "contentViewer",
methods: {
getEmulatedColorScheme: {
request: {},
response: {
emulated: RetVal("nullable:string"),
},
},
setEmulatedColorScheme: {
request: {
scheme: Arg(0, "nullable:string"),
},
response: {},
},
getIsPrintSimulationEnabled: {
request: {},
response: {
enabled: RetVal("boolean"),
},
},
startPrintMediaSimulation: {
request: {},
response: {},
},
stopPrintMediaSimulation: {
request: {
state: Arg(0, "boolean"),
},
response: {},
},
},
});
exports.contentViewerSpec = contentViewerSpec;

View File

@ -5,6 +5,8 @@
const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol");
// Bug 1606852: Delete this file when Firefox 73 is on release.
const emulationSpec = generateActorSpec({
typeName: "emulation",

View File

@ -47,6 +47,11 @@ const Types = (exports.__TypesForTests = [
spec: "devtools/shared/specs/changes",
front: "devtools/shared/fronts/changes",
},
{
types: ["contentViewer"],
spec: "devtools/shared/specs/content-viewer",
front: "devtools/shared/fronts/content-viewer",
},
{
types: ["cssProperties"],
spec: "devtools/shared/specs/css-properties",
@ -72,11 +77,6 @@ const Types = (exports.__TypesForTests = [
spec: "devtools/shared/specs/device",
front: "devtools/shared/fronts/device",
},
{
types: ["emulation"],
spec: "devtools/shared/specs/emulation",
front: "devtools/shared/fronts/emulation",
},
{
types: ["environment"],
spec: "devtools/shared/specs/environment",
@ -174,6 +174,11 @@ const Types = (exports.__TypesForTests = [
spec: "devtools/shared/specs/reflow",
front: "devtools/shared/fronts/reflow",
},
{
types: ["responsive"],
spec: "devtools/shared/specs/responsive",
front: "devtools/shared/fronts/responsive",
},
{
types: ["screenshot"],
spec: "devtools/shared/specs/screenshot",

View File

@ -17,6 +17,7 @@ DevToolsModules(
'animation.js',
'array-buffer.js',
'changes.js',
'content-viewer.js',
'css-properties.js',
'device.js',
'emulation.js',
@ -40,6 +41,7 @@ DevToolsModules(
'preference.js',
'property-iterator.js',
'reflow.js',
'responsive.js',
'root.js',
'screenshot.js',
'source.js',

View File

@ -0,0 +1,159 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol");
const responsiveSpec = generateActorSpec({
typeName: "responsive",
methods: {
setDPPXOverride: {
request: {
dppx: Arg(0, "number"),
},
response: {
valueChanged: RetVal("boolean"),
},
},
getDPPXOverride: {
request: {},
response: {
dppx: RetVal("number"),
},
},
clearDPPXOverride: {
request: {},
response: {
valueChanged: RetVal("boolean"),
},
},
setNetworkThrottling: {
request: {
options: Arg(0, "json"),
},
response: {
valueChanged: RetVal("boolean"),
},
},
getNetworkThrottling: {
request: {},
response: {
state: RetVal("json"),
},
},
clearNetworkThrottling: {
request: {},
response: {
valueChanged: RetVal("boolean"),
},
},
setTouchEventsOverride: {
request: {
flag: Arg(0, "number"),
},
response: {
valueChanged: RetVal("boolean"),
},
},
getTouchEventsOverride: {
request: {},
response: {
flag: RetVal("number"),
},
},
clearTouchEventsOverride: {
request: {},
response: {
valueChanged: RetVal("boolean"),
},
},
setMetaViewportOverride: {
request: {
flag: Arg(0, "number"),
},
response: {
valueChanged: RetVal("boolean"),
},
},
getMetaViewportOverride: {
request: {},
response: {
flag: RetVal("number"),
},
},
clearMetaViewportOverride: {
request: {},
response: {
valueChanged: RetVal("boolean"),
},
},
setUserAgentOverride: {
request: {
flag: Arg(0, "string"),
},
response: {
valueChanged: RetVal("boolean"),
},
},
getUserAgentOverride: {
request: {},
response: {
userAgent: RetVal("string"),
},
},
clearUserAgentOverride: {
request: {},
response: {
valueChanged: RetVal("boolean"),
},
},
setElementPickerState: {
request: {
state: Arg(0, "boolean"),
},
response: {},
},
simulateScreenOrientationChange: {
request: {
orientation: Arg(0, "string"),
angle: Arg(1, "number"),
deviceChange: Arg(2, "boolean"),
},
response: {},
},
captureScreenshot: {
request: {},
response: {
value: RetVal("json"),
},
},
setDocumentInRDMPane: {
request: {
state: Arg(0, "boolean"),
},
response: {},
},
},
});
exports.responsiveSpec = responsiveSpec;

View File

@ -14,7 +14,7 @@ from recommonmark.transform import AutoStructify
# Set up Python environment to load build system packages.
OUR_DIR = os.path.dirname(__file__)
topsrcdir = os.path.normpath(os.path.join(OUR_DIR, '..', '..'))
topsrcdir = os.path.normpath(os.path.join(OUR_DIR, '..'))
EXTRA_PATHS = (
'layout/tools/reftest',

View File

@ -3,6 +3,8 @@
# The order of the main categories are defined in index.rst
# Sub categories orders are preserved
categories:
contributing_doc:
- contributing
source_doc:
- browser
- dom
@ -21,7 +23,7 @@ categories:
- tools/try
- build/buildsystem
- taskcluster
- tools/docs
- tools/moztreedocs
testing_doc:
- testing/marionette
- testing/geckodriver
@ -52,3 +54,4 @@ redirects:
testing/marionette/marionette: testing/marionette
toolkit/components/telemetry/telemetry: toolkit/components/telemetry
tools/compare-locales/index.html: build/buildsystem/locales.html
tools/docs/index.html: tools/moztreedocs/index.html

View File

@ -0,0 +1,11 @@
Contributing to Firefox
=======================
This is the preferred location for all Firefox development process and
source code documentation.
.. toctree::
:maxdepth: 1
:glob:
*

View File

@ -2,6 +2,12 @@
Mozilla Source Tree Documentation
=================================
.. toctree::
:caption: Contributing
:maxdepth: 2
{contributing_doc}
.. toctree::
:caption: Source code doc
:maxdepth: 2

View File

@ -391,6 +391,10 @@ void Animation::UpdatePlaybackRate(double aPlaybackRate) {
//
// All we need to do is update observers so that, e.g. DevTools, report the
// right information.
//
// First we need to update the relevance however since we might have become
// current or stopped being current.
UpdateRelevance();
if (IsRelevant()) {
MutationObservers::NotifyAnimationChanged(this);
}

View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<script>
function start () {
const keyframe = new KeyframeEffect(undefined, {});
const animation = new Animation(keyframe, undefined);
// Make animation run backwards...
animation.playbackRate = -100;
// But then set the current time to the future so it becomes "current"...
animation.currentTime = 2055;
// After updating the playback rate to zero, however, it should no longer
// be "current" (and this takes effect immediately because |animation| is
// paused)...
animation.updatePlaybackRate(0);
// Now update the target and hope nothing goes wrong...
keyframe.target = div;
}
document.addEventListener('DOMContentLoaded', start)
</script>
</head>
<div id=div></div>
</html>

View File

@ -45,3 +45,4 @@ pref(dom.animations-api.implicit-keyframes.enabled,true) load 1467277-1.html
load 1524480-1.html
load 1575926.html
pref(dom.animations-api.implicit-keyframes.enabled,true) load 1585770.html
load 1604500-1.html

View File

@ -29,7 +29,7 @@ test(function(t) {
sandbox.importFunction(document, "document");
sandbox.importFunction(assert_true, "assert_true");
sandbox.importFunction(assert_unreached, "assert_unreached");
SpecialPowers.Cu.evalInSandbox(`(${contentScript.toSource()})()`, sandbox);
SpecialPowers.Cu.evalInSandbox(`(${contentScript.toString()})()`, sandbox);
}, 'Setting easing should not throw any exceptions in sandbox');
</script>

View File

@ -108,14 +108,13 @@ nsDataDocumentContentPolicy::ShouldLoad(nsIURI* aContentLocation,
// Report error, if we can.
if (node) {
nsIPrincipal* requestingPrincipal = node->NodePrincipal();
RefPtr<nsIURI> principalURI;
nsresult rv = requestingPrincipal->GetURI(getter_AddRefs(principalURI));
if (NS_SUCCEEDED(rv) && principalURI) {
nsScriptSecurityManager::ReportError(
"ExternalDataError", principalURI, aContentLocation,
requestingPrincipal->OriginAttributesRef().mPrivateBrowsingId >
0);
}
nsAutoCString sourceSpec;
requestingPrincipal->GetAsciiSpec(sourceSpec);
nsAutoCString targetSpec;
aContentLocation->GetAsciiSpec(targetSpec);
nsScriptSecurityManager::ReportError(
"ExternalDataError", sourceSpec, targetSpec,
requestingPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0);
}
} else if ((contentType == nsIContentPolicy::TYPE_IMAGE ||
contentType == nsIContentPolicy::TYPE_IMAGESET) &&

View File

@ -1535,18 +1535,16 @@ void nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc) {
TraceWrapper(aTrc, "active window global");
}
void nsGlobalWindowInner::InnerSetNewDocument(JSContext* aCx,
Document* aDocument) {
MOZ_ASSERT(aDocument);
void nsGlobalWindowInner::InitDocumentDependentState(JSContext* aCx) {
MOZ_ASSERT(mDoc);
if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)) {
nsIURI* uri = aDocument->GetDocumentURI();
nsIURI* uri = mDoc->GetDocumentURI();
MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
("DOMWINDOW %p SetNewDocument %s", this,
uri ? uri->GetSpecOrDefault().get() : ""));
}
mDoc = aDocument;
mFocusedElement = nullptr;
mLocalStorage = nullptr;
mSessionStorage = nullptr;
@ -1580,7 +1578,7 @@ void nsGlobalWindowInner::InnerSetNewDocument(JSContext* aCx,
#endif
#ifdef DEBUG
mLastOpenedURI = aDocument->GetDocumentURI();
mLastOpenedURI = mDoc->GetDocumentURI();
#endif
Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,

View File

@ -1017,9 +1017,9 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void FreeInnerObjects();
// Only to be called on an inner window.
// aDocument must not be null.
void InnerSetNewDocument(JSContext* aCx, Document* aDocument);
// Initialize state that depends on the document. By this point, mDoc should
// be set correctly and have us set as its script global object.
void InitDocumentDependentState(JSContext* aCx);
nsresult EnsureClientSource();
nsresult ExecutionReady();

View File

@ -2162,15 +2162,28 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
// Add an extra ref in case we release mContext during GC.
nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext);
// Make sure the inner's document is set correctly before we call
// SetScriptGlobalObject, because that might try to examine document-dependent
// state. Unfortunately, we can't do some of the other clearing/resetting
// work we do below until after SetScriptGlobalObject(), because it might
// depend on the document having the right scope object.
if (aState) {
MOZ_RELEASE_ASSERT(newInnerWindow->mDoc == aDocument);
} else {
if (reUseInnerWindow) {
MOZ_RELEASE_ASSERT(newInnerWindow->mDoc != aDocument);
}
newInnerWindow->mDoc = aDocument;
}
aDocument->SetScriptGlobalObject(newInnerWindow);
MOZ_ASSERT(newInnerWindow->mTabGroup,
"We must have a TabGroup cached at this point");
MOZ_RELEASE_ASSERT(newInnerWindow->mDoc == aDocument);
if (!aState) {
if (reUseInnerWindow) {
MOZ_RELEASE_ASSERT(newInnerWindow->mDoc != aDocument);
newInnerWindow->mDoc = aDocument;
// The storage objects contain the URL of the window. We have to
// recreate them when the innerWindow is reused.
newInnerWindow->mLocalStorage = nullptr;
@ -2188,7 +2201,7 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
rv = newInnerWindow->ExecutionReady();
NS_ENSURE_SUCCESS(rv, rv);
} else {
newInnerWindow->InnerSetNewDocument(cx, aDocument);
newInnerWindow->InitDocumentDependentState(cx);
// Initialize DOM classes etc on the inner window.
JS::Rooted<JSObject*> obj(cx, newInnerGlobal);

View File

@ -54,7 +54,7 @@ function compare(a, b) {
for (var p in b) bProps.push(p);
is (aProps.length, bProps.length, 'Props match');
is (aProps.sort().toSource(), bProps.sort().toSource(), 'Props match - using toSource()');
is (aProps.sort().toString(), bProps.sort().toString(), 'Props names match');
for (var p in a) {
compare(a[p], b[p]);
@ -75,7 +75,7 @@ function compare(a, b) {
}
if (type != 'null') {
is (a.toSource(), b.toSource(), 'Matching using toSource()');
is (a, b, 'Same value');
}
}

View File

@ -428,18 +428,15 @@ bool nsScriptErrorBase::ComputeIsFromPrivateWindow(
nsGlobalWindowInner* aWindow) {
// Never mark exceptions from chrome windows as having come from private
// windows, since we always want them to be reported.
// winPrincipal needs to be null-checked - Bug 1601175
nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
return aWindow->IsPrivateBrowsing() &&
(!winPrincipal || !winPrincipal->IsSystemPrincipal());
return aWindow->IsPrivateBrowsing() && !winPrincipal->IsSystemPrincipal();
}
/* static */
bool nsScriptErrorBase::ComputeIsFromChromeContext(
nsGlobalWindowInner* aWindow) {
nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
// winPrincipal needs to be null-checked - Bug 1601175
return (winPrincipal && winPrincipal->IsSystemPrincipal());
return winPrincipal->IsSystemPrincipal();
}
NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)

View File

@ -60,7 +60,7 @@ function compare(a, b) {
for (let p in b) bProps.push(p);
is(aProps.length, bProps.length, "Props match");
is(aProps.sort().toSource(), bProps.sort().toSource(), "Props match - using toSource()");
is(aProps.sort().toString(), bProps.sort().toString(), "Props names match");
for (let p in a) {
compare(a[p], b[p]);
@ -70,7 +70,7 @@ function compare(a, b) {
}
if (type != "null") {
is(a.toSource(), b.toSource(), "Matching using toSource()");
is(a, b, "Same value");
}
}

View File

@ -61,7 +61,7 @@ function workerGroupUsage() {
}
let url =
URL.createObjectURL(new Blob(["(", workerScript.toSource(), ")()"]));
URL.createObjectURL(new Blob(["(", workerScript.toString(), ")()"]));
let worker = new Worker(url);
worker.onmessage = function(e) {

View File

@ -21302,7 +21302,7 @@ function test_2d_imageSmoothing() {
pixels[1] == 255 &&
pixels[2] == 0 &&
pixels[3] == 255,
"pixel is " + pixels.toSource() + " (expected [0,255,0,255])");
"pixel is [" + pixels.toString() + "] (expected [0,255,0,255])");
}
</script>

Some files were not shown because too many files have changed in this diff Show More