Merge mozilla-central to inbound a=merge on a CLOSED TREE

This commit is contained in:
Coroiu Cristina 2019-02-12 18:36:58 +02:00
commit e6104a10ba
44 changed files with 597 additions and 118 deletions

View File

@ -1092,8 +1092,12 @@
// overflowed.
this.arrowScrollbox._updateScrollButtonsDisabledState();
// Preload the next about:newtab if there isn't one already.
gBrowser._createPreloadBrowser();
// If this browser isn't lazy (indicating it's probably created by
// session restore), preload the next about:newtab if we don't
// already have a preloaded browser.
if (tab.linkedPanel) {
gBrowser._createPreloadBrowser();
}
]]></body>
</method>

View File

@ -97,3 +97,4 @@ skip-if = !healthreport || !telemetry || (os == 'linux' && debug) || (os == 'and
run-if = nightly_build # Containers is enabled only on Nightly
[browser_fluent.js]
[browser_hometab_restore_defaults.js]
skip-if = debug #Bug 1517966

View File

@ -260,7 +260,8 @@ class UrlbarView {
this.panel.setAttribute("width", width);
// Subtract two pixels for left and right borders on the panel.
this._mainContainer.style.maxWidth = (width - 2) + "px";
let contentWidth = width - 2;
this._mainContainer.style.maxWidth = contentWidth + "px";
// Keep the popup items' site icons aligned with the input's identity
// icon if it's not too far from the edge of the window. We define
@ -289,10 +290,12 @@ class UrlbarView {
this.panel.style.setProperty("--item-padding-start", Math.round(start) + "px");
this.panel.style.setProperty("--item-padding-end", Math.round(endOffset) + "px");
contentWidth -= start + endOffset;
} else {
this.panel.style.removeProperty("--item-padding-start");
this.panel.style.removeProperty("--item-padding-end");
}
this.panel.style.setProperty("--item-content-width", Math.round(contentWidth) + "px");
}
_createRow(resultIndex) {

View File

@ -107,6 +107,15 @@
background-image: url(chrome://browser/skin/tab.svg);
}
.urlbarView-title {
display: inline-block;
vertical-align: text-bottom;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: calc(var(--item-content-width) * .7 - 2 * (16px + @urlbarViewIconMarginEnd@));
}
.urlbarView-secondary::before {
content: "\2014";
color: var(--panel-disabled-color);

View File

@ -12,6 +12,7 @@
* Components
*/
@import "resource://devtools/client/aboutdebugging-new/src/components/App.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/ProfilerDialog.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimePage.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/connect/ConnectSteps.css";

View File

@ -13,12 +13,14 @@ const {
ADB_ADDON_UNINSTALL_FAILURE,
ADB_ADDON_STATUS_UPDATED,
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
HIDE_PROFILER_DIALOG,
NETWORK_LOCATIONS_UPDATED,
PAGE_TYPES,
SELECT_PAGE_FAILURE,
SELECT_PAGE_START,
SELECT_PAGE_SUCCESS,
SELECTED_RUNTIME_ID_UPDATED,
SHOW_PROFILER_DIALOG,
USB_RUNTIMES_SCAN_START,
USB_RUNTIMES_SCAN_SUCCESS,
} = require("../constants");
@ -51,6 +53,11 @@ function selectPage(page, runtimeId) {
return;
}
// Stop showing the profiler dialog if we are navigating to another page.
if (getState().ui.showProfilerDialog) {
await dispatch({ type: HIDE_PROFILER_DIALOG });
}
// Stop watching current runtime, if currently on a RUNTIME page.
if (currentPage === PAGE_TYPES.RUNTIME) {
const currentRuntimeId = getState().runtimes.selectedRuntimeId;
@ -93,6 +100,14 @@ function removeNetworkLocation(location) {
};
}
function showProfilerDialog() {
return { type: SHOW_PROFILER_DIALOG };
}
function hideProfilerDialog() {
return { type: HIDE_PROFILER_DIALOG };
}
function updateAdbAddonStatus(adbAddonStatus) {
return { type: ADB_ADDON_STATUS_UPDATED, adbAddonStatus };
}
@ -147,10 +162,12 @@ function scanUSBRuntimes() {
module.exports = {
addNetworkLocation,
hideProfilerDialog,
installAdbAddon,
removeNetworkLocation,
scanUSBRuntimes,
selectPage,
showProfilerDialog,
uninstallAdbAddon,
updateAdbAddonStatus,
updateDebugTargetCollapsibility,

View File

@ -34,7 +34,10 @@
--error-50: #ff0039;
--error-60: #d70022;
--highlight-50: #0a84ff;
--grey-20: #ededf0;
--grey-30: #d7d7db; /* for ui, no special semantic */
--grey-90-a60: rgba(12, 12, 13, 0.6);
--grey-90-a80: rgba(12, 12, 13, 0.8);
--white-100: #fff; /* for ui, no special semantic */
/* Global layout vars */
@ -264,6 +267,26 @@ Form controls
height: calc(var(--base-unit) * 6);
}
/* ghost button. icon button with no background from Photon guidelines */
.ghost-button {
border: none;
border-radius: calc(var(--base-unit) / 2);
fill: var(--grey-90-a80);
height: calc(var(--base-unit) * 8);
padding: calc(var(--base-unit) * 2);
width: calc(var(--base-unit) * 8);
-moz-context-properties: fill;
}
.ghost-button:hover {
background-color: var(--grey-30);
}
.ghost-button:active {
background-color: var(--grey-40);
}
/* standard inputs */
.default-input {
line-height: unset;

View File

@ -0,0 +1,55 @@
/* 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/. */
.profiler-dialog__frame {
border: none;
height: 100%;
width: 100%;
}
/*
* The current layout of the dialog header is
*
* +-----------------------------+---+
* | dialog title (auto) | X |
* +-----------------------------+---+
*/
.profiler-dialog__header {
align-items: center;
background-color: var(--grey-20);
display: grid;
grid-template-columns: 1fr max-content;
padding: var(--base-unit);
}
.profiler-dialog__header__title {
margin: 0;
margin-inline-start: calc(var(--base-unit) * 2);
/* Reset <h1> styles */
font-size: 15px;
font-weight: normal;
}
.profiler-dialog__inner {
background-color: var(--white-100);
display: grid;
height: calc(var(--base-unit) * 150); /* 600px */
grid-template-rows: max-content auto;
max-height: calc(100% - calc(var(--base-unit) * 25)); /* 100% - 100px */
position: fixed;
width: calc(var(--base-unit) * 150); /* 600px */
}
.profiler-dialog__mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--grey-90-a60);
display: flex;
align-items: center;
justify-content: center;
}

View File

@ -0,0 +1,84 @@
/* 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 { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
const Localized = createFactory(FluentReact.Localized);
const Actions = require("../actions/index");
const Types = require("../types/index");
/**
* This component a modal dialog containing the performance profiler UI.
*/
class ProfilerDialog extends PureComponent {
static get propTypes() {
return {
runtimeDetails: Types.runtimeDetails.isRequired,
dispatch: PropTypes.func.isRequired,
};
}
hide() {
this.props.dispatch(Actions.hideProfilerDialog());
}
render() {
const { clientWrapper } = this.props.runtimeDetails;
return dom.div(
{
className: "profiler-dialog__mask js-profiler-dialog-mask",
onClick: () => this.hide(),
},
dom.article(
{
className: "profiler-dialog__inner js-profiler-dialog",
onClick: e => e.stopPropagation(),
},
dom.header(
{
className: "profiler-dialog__header",
},
Localized(
{
id: "about-debugging-profiler-dialog-title",
},
dom.h1(
{
className: "profiler-dialog__header__title",
},
"Performance Profiler",
)
),
dom.button(
{
className: "ghost-button js-profiler-dialog-close",
onClick: () => this.hide(),
},
dom.img(
{
src: "chrome://devtools/skin/images/close.svg",
}
)
)
),
dom.iframe({
className: "profiler-dialog__frame",
src: clientWrapper.getPerformancePanelUrl(),
onLoad: (e) => {
clientWrapper.loadPerformanceProfiler(e.target.contentWindow);
},
})
)
);
}
}
module.exports = ProfilerDialog;

View File

@ -16,6 +16,7 @@ const ConnectionPromptSetting = createFactory(require("./ConnectionPromptSetting
const DebugTargetPane = createFactory(require("./debugtarget/DebugTargetPane"));
const ExtensionDetail = createFactory(require("./debugtarget/ExtensionDetail"));
const InspectAction = createFactory(require("./debugtarget/InspectAction"));
const ProfilerDialog = createFactory(require("./ProfilerDialog"));
const RuntimeInfo = createFactory(require("./RuntimeInfo"));
const ServiceWorkerAction = createFactory(require("./debugtarget/ServiceWorkerAction"));
const ServiceWorkersWarning = createFactory(require("./ServiceWorkersWarning"));
@ -44,6 +45,7 @@ class RuntimePage extends PureComponent {
runtimeId: PropTypes.string.isRequired,
serviceWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
sharedWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
showProfilerDialog: PropTypes.bool.isRequired,
tabs: PropTypes.arrayOf(PropTypes.object).isRequired,
temporaryExtensions: PropTypes.arrayOf(PropTypes.object).isRequired,
temporaryInstallError: PropTypes.string,
@ -57,16 +59,44 @@ class RuntimePage extends PureComponent {
dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, runtimeId));
}
renderConnectionPromptSetting() {
const { runtimeDetails, dispatch } = this.props;
onProfilerButtonClick() {
this.props.dispatch(Actions.showProfilerDialog());
}
renderRemoteRuntimeActions() {
const { runtimeDetails, runtimeId, dispatch } = this.props;
const { connectionPromptEnabled } = runtimeDetails;
return dom.div(
{
className: "connection-prompt-setting",
},
ConnectionPromptSetting({ connectionPromptEnabled, dispatch }),
);
if (runtimeId === RUNTIMES.THIS_FIREFOX) {
// Connection prompt and Profiling are only available on remote runtimes.
return null;
}
return [
dom.div(
{
className: "connection-prompt-setting",
key: "connection-prompt-setting",
},
ConnectionPromptSetting({ connectionPromptEnabled, dispatch }),
),
dom.p(
{},
Localized(
{
id: "about-debugging-runtime-profile-button",
key: "profile-runtime-button",
},
dom.button(
{
className: "default-button js-profile-runtime-button",
onClick: () => this.onProfilerButtonClick(),
},
"Profile Runtime"
),
),
),
];
}
renderDebugTargetPane(name, targets, actionComponent,
@ -100,9 +130,9 @@ class RuntimePage extends PureComponent {
installedExtensions,
otherWorkers,
runtimeDetails,
runtimeId,
serviceWorkers,
sharedWorkers,
showProfilerDialog,
tabs,
temporaryExtensions,
temporaryInstallError,
@ -114,19 +144,13 @@ class RuntimePage extends PureComponent {
return null;
}
// do not show the connection prompt setting in 'This Firefox'
const shallShowPromptSetting = runtimeId !== RUNTIMES.THIS_FIREFOX;
const { type } = runtimeDetails.info;
return dom.article(
{
className: "page js-runtime-page",
},
RuntimeInfo(runtimeDetails.info),
shallShowPromptSetting
? this.renderConnectionPromptSetting()
: null,
this.renderRemoteRuntimeActions(),
runtimeDetails.serviceWorkersAvailable ? null : ServiceWorkersWarning(),
isSupportedDebugTargetPane(type, DEBUG_TARGET_PANE.TEMPORARY_EXTENSION)
? TemporaryExtensionInstaller({
@ -169,6 +193,8 @@ class RuntimePage extends PureComponent {
WorkerDetail,
DEBUG_TARGET_PANE.OTHER_WORKER,
"about-debugging-runtime-other-workers"),
showProfilerDialog ? ProfilerDialog({ dispatch, runtimeDetails }) : null,
);
}
}
@ -181,6 +207,7 @@ const mapStateToProps = state => {
runtimeDetails: getCurrentRuntimeDetails(state.runtimes),
serviceWorkers: state.debugTargets.serviceWorkers,
sharedWorkers: state.debugTargets.sharedWorkers,
showProfilerDialog: state.ui.showProfilerDialog,
tabs: state.debugTargets.tabs,
temporaryExtensions: state.debugTargets.temporaryExtensions,
temporaryInstallError: state.ui.temporaryInstallError,

View File

@ -13,6 +13,8 @@ DevToolsModules(
'App.css',
'App.js',
'ConnectionPromptSetting.js',
'ProfilerDialog.css',
'ProfilerDialog.js',
'RuntimeInfo.js',
'RuntimePage.css',
'RuntimePage.js',

View File

@ -22,6 +22,7 @@ const actionTypes = {
DISCONNECT_RUNTIME_FAILURE: "DISCONNECT_RUNTIME_FAILURE",
DISCONNECT_RUNTIME_START: "DISCONNECT_RUNTIME_START",
DISCONNECT_RUNTIME_SUCCESS: "DISCONNECT_RUNTIME_SUCCESS",
HIDE_PROFILER_DIALOG: "HIDE_PROFILER_DIALOG",
NETWORK_LOCATIONS_UPDATED: "NETWORK_LOCATIONS_UPDATED",
REMOTE_RUNTIMES_UPDATED: "REMOTE_RUNTIMES_UPDATED",
REQUEST_EXTENSIONS_FAILURE: "REQUEST_EXTENSIONS_FAILURE",
@ -37,6 +38,7 @@ const actionTypes = {
SELECT_PAGE_START: "SELECT_PAGE_START",
SELECT_PAGE_SUCCESS: "SELECT_PAGE_SUCCESS",
SELECTED_RUNTIME_ID_UPDATED: "SELECTED_RUNTIME_ID_UPDATED",
SHOW_PROFILER_DIALOG: "SHOW_PROFILER_DIALOG",
TELEMETRY_RECORD: "TELEMETRY_RECORD",
TEMPORARY_EXTENSION_INSTALL_FAILURE: "TEMPORARY_EXTENSION_INSTALL_FAILURE",
TEMPORARY_EXTENSION_INSTALL_START: "TEMPORARY_EXTENSION_INSTALL_START",

View File

@ -154,6 +154,18 @@ class ClientWrapper {
isClosed() {
return this.client._closed;
}
// This method will be mocked to return a dummy URL during mochitests
getPerformancePanelUrl() {
return "chrome://devtools/content/performance-new/index.xhtml";
}
async loadPerformanceProfiler(win) {
const preferenceFront = await this.getFront("preference");
const perfFront = await this.getFront("perf");
const perfActorVersion = this.client.mainRoot.traits.perfActorVersion;
win.gInit(perfFront, preferenceFront, perfActorVersion);
}
}
exports.ClientWrapper = ClientWrapper;

View File

@ -7,8 +7,10 @@
const {
ADB_ADDON_STATUS_UPDATED,
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
HIDE_PROFILER_DIALOG,
NETWORK_LOCATIONS_UPDATED,
SELECT_PAGE_SUCCESS,
SHOW_PROFILER_DIALOG,
TEMPORARY_EXTENSION_INSTALL_FAILURE,
TEMPORARY_EXTENSION_INSTALL_SUCCESS,
USB_RUNTIMES_SCAN_START,
@ -25,6 +27,7 @@ function UiState(locations = [], debugTargetCollapsibilities = {},
networkEnabled,
networkLocations: locations,
selectedPage: null,
showProfilerDialog: false,
showSystemAddons,
temporaryInstallError: null,
wifiEnabled,
@ -55,6 +58,14 @@ function uiReducer(state = UiState(), action) {
return Object.assign({}, state, { selectedPage: page });
}
case SHOW_PROFILER_DIALOG: {
return Object.assign({}, state, { showProfilerDialog: true });
}
case HIDE_PROFILER_DIALOG: {
return Object.assign({}, state, { showProfilerDialog: false });
}
case USB_RUNTIMES_SCAN_START: {
return Object.assign({}, state, { isScanningUsb: true });
}

View File

@ -59,8 +59,9 @@ skip-if = (os == "win" && ccov) # Bug 1521349
[browser_aboutdebugging_devtoolstoolbox_tooltip_markupview.js]
[browser_aboutdebugging_navigate.js]
[browser_aboutdebugging_persist_connection.js]
[browser_aboutdebugging_profiler_dialog.js]
[browser_aboutdebugging_routes.js]
[browser_aboutdebugging_runtime_connection-prompt.js]
[browser_aboutdebugging_runtime_remote_runtime_buttons.js]
[browser_aboutdebugging_runtime_usbclient_closed.js]
[browser_aboutdebugging_select_network_runtime.js]
[browser_aboutdebugging_select_page_with_serviceworker.js]

View File

@ -0,0 +1,83 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/* import-globals-from helper-mocks.js */
Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-mocks.js", this);
/**
* Test opening and closing the profiler dialog.
*/
add_task(async function() {
// enable USB devices mocks
const mocks = new Mocks();
const usbClient = mocks.createUSBRuntime("1337id", {
deviceName: "Fancy Phone",
name: "Lorem ipsum",
});
const { document, tab, window } = await openAboutDebugging();
mocks.emitUSBUpdate();
await connectToRuntime("Fancy Phone", document);
await selectRuntime("Fancy Phone", "Lorem ipsum", document);
info("Open the profiler dialog");
await openProfilerDialog(usbClient, document);
assertDialogVisible(document);
info("Click on the close button and wait until the dialog disappears");
const closeDialogButton = document.querySelector(".js-profiler-dialog-close");
closeDialogButton.click();
await waitUntil(() => !document.querySelector(".js-profiler-dialog"));
assertDialogHidden(document);
info("Open the profiler dialog again");
await openProfilerDialog(usbClient, document);
assertDialogVisible(document);
info("Click on the mask element and wait until the dialog disappears");
const mask = document.querySelector(".js-profiler-dialog-mask");
EventUtils.synthesizeMouse(mask, 5, 5, {}, window);
await waitUntil(() => !document.querySelector(".js-profiler-dialog"));
assertDialogHidden(document);
info("Open the profiler dialog again");
await openProfilerDialog(usbClient, document);
assertDialogVisible(document);
info("Navigate to this-firefox and wait until the dialog disappears");
document.location.hash = "#/runtime/this-firefox";
await waitUntil(() => !document.querySelector(".js-profiler-dialog"));
assertDialogHidden(document);
info("Select the remote runtime again, check the dialog is still hidden");
await selectRuntime("Fancy Phone", "Lorem ipsum", document);
assertDialogHidden(document);
await removeTab(tab);
});
function assertDialogVisible(doc) {
ok(doc.querySelector(".js-profiler-dialog"), "Dialog is displayed");
ok(doc.querySelector(".js-profiler-dialog-mask"), "Dialog mask is displayed");
}
function assertDialogHidden(doc) {
ok(!document.querySelector(".js-profiler-dialog"), "Dialog is removed");
ok(!document.querySelector(".js-profiler-dialog-mask"), "Dialog mask is removed");
}
function openProfilerDialog(client, doc) {
const onProfilerLoaded = new Promise(r => {
client.loadPerformanceProfiler = r;
});
info("Click on the Profile Runtime button");
const profileButton = doc.querySelector(".js-profile-runtime-button");
profileButton.click();
info("Wait for the loadPerformanceProfiler callback to be executed on client-wrapper");
return onProfilerLoaded;
}

View File

@ -8,8 +8,7 @@ Services.scriptloader.loadSubScript(
CHROME_URL_ROOT + "helper-mocks.js", this);
/**
* Test that remote runtimes show the connection prompt,
* but it's hidden in 'This Firefox'
* Test that remote runtimes show action buttons that are hidden for 'This Firefox'.
*/
add_task(async function() {
// enable USB devices mocks
@ -24,6 +23,8 @@ add_task(async function() {
info("Checking This Firefox");
ok(!document.querySelector(".js-connection-prompt-toggle-button"),
"This Firefox does not contain the connection prompt button");
ok(!document.querySelector(".js-profile-runtime-button"),
"This Firefox does not contain the profile runtime button");
info("Checking a USB runtime");
mocks.emitUSBUpdate();
@ -31,6 +32,8 @@ add_task(async function() {
await selectRuntime("Fancy Phone", "Lorem ipsum", document);
ok(!!document.querySelector(".js-connection-prompt-toggle-button"),
"Runtime contains the connection prompt button");
ok(!!document.querySelector(".js-profile-runtime-button"),
"Remote runtime contains the profile runtime button");
await removeTab(tab);
});

View File

@ -87,6 +87,8 @@ function createClientMock() {
setPreference: function(prefName, value) {
this._preferences[prefName] = value;
},
getPerformancePanelUrl: () => "data:text/html;charset=UTF-8,fake_profiler_page",
loadPerformanceProfiler: () => {},
};
}

View File

@ -126,6 +126,10 @@ about-debugging-runtime-shared-workers = Shared Workers
# Title of the other workers category.
about-debugging-runtime-other-workers = Other Workers
# Label of the button opening the performance profiler panel in runtime pages for remote
# runtimes.
about-debugging-runtime-profile-button = Profile Runtime
# This string is displayed in about:debugging#workers if the current configuration of the
# browser is incompatible with service workers. Learn more points to MDN.
# https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging#Service_workers_not_compatible
@ -279,3 +283,6 @@ about-debugging-page-title-with-runtime = { -application-title } - { about-debug
# Page title without the runtime displayed in the tab
about-debugging-page-title = { -application-title } - { about-debugging-page-title-selected-page }
# Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button.
about-debugging-profiler-dialog-title = Performance Profiler

View File

@ -2,5 +2,11 @@
module.exports = {
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../../.eslintrc.mochitests.js"
"extends": "../../../../.eslintrc.mochitests.js",
"overrides": [{
"files": ["test-dynamic-import.js"],
"parserOptions": {
"sourceType": "module",
},
}]
};

View File

@ -72,6 +72,8 @@ support-files =
test-data.json
test-data.json^headers^
test-duplicate-error.html
test-dynamic-import.html
test-dynamic-import.js
test-encoding-ISO-8859-1.html
test-error.html
test-eval-in-stackframe.html
@ -217,6 +219,7 @@ skip-if = verify
[browser_jsterm_autocomplete-properties-with-non-alphanumeric-names.js]
[browser_jsterm_await_assignments.js]
[browser_jsterm_await_concurrent.js]
[browser_jsterm_await_dynamic_import.js]
[browser_jsterm_await_error.js]
[browser_jsterm_await_helper_dollar_underscore.js]
[browser_jsterm_await_paused.js]

View File

@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that top-level await with dynamic import works as expected.
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/mochitest/test-dynamic-import.html";
add_task(async function() {
// Enable dynamic import
await pushPref("javascript.options.dynamicImport", true);
// Enable await mapping.
await pushPref("devtools.debugger.features.map-await-expression", true);
// Run test with legacy JsTerm
await pushPref("devtools.webconsole.jsterm.codeMirror", false);
await performTests();
// And then run it with the CodeMirror-powered one.
await pushPref("devtools.webconsole.jsterm.codeMirror", true);
await performTests();
});
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
const executeAndWaitForResultMessage = (input, expectedOutput) =>
executeAndWaitForMessage(hud, input, expectedOutput, ".result");
info("Evaluate an expression with a dynamic import");
let importAwaitExpression = `
var {sum} = await import("./test-dynamic-import.js");
sum(1, 2, 3);
`;
await executeAndWaitForResultMessage(importAwaitExpression, `1 + 2 + 3 = 6`);
ok(true, "The `sum` module was imported and used successfully");
info("Import the same module a second time");
// This used to make the content page crash (See Bug 1523897).
importAwaitExpression = `
var {sum} = await import("./test-dynamic-import.js");
sum(2, 3, 4);
`;
await executeAndWaitForResultMessage(importAwaitExpression, `2 + 3 + 4 = 9`);
ok(true, "The `sum` module was imported and used successfully a second time");
}

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test dynamic import usage in console</title>
</head>
<body>
<h1>Test dynamic import usage in console</h1>
</body>
</html>

View File

@ -0,0 +1,12 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* @param {Number} numbers that will be summed.
* @returns {String} A string of the following form: `${arg1} + ${arg2} ${argn} = ${sum}`
*/
function sum(...args) {
return `${args.join(" + ")} = ${args.reduce((acc, i) => acc + i)}`;
}
export {sum};

View File

@ -63,6 +63,8 @@ Then run this:
./mach build
```
Please note, if this fails it might be possible you need to run the `bootstrap.py` script first. Download the [bootstrap.py script](https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py) and save it in your project directory. Then run `python bootstrap.py` and follow the prompted steps.
**Note:** if using Windows, you might need to type the commands without the `./`:
```bash

View File

@ -14,9 +14,12 @@
#include "BufferStream.h"
#include "H264.h"
#include "Index.h"
#include "MP4Decoder.h"
#include "MP4Metadata.h"
#include "MoofParser.h"
#include "ResourceStream.h"
#include "VPXDecoder.h"
#include "mozilla/Span.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/Telemetry.h"
#include "nsAutoPtr.h"
@ -71,7 +74,11 @@ class MP4TrackDemuxer : public MediaTrackDemuxer,
RefPtr<MediaRawData> mQueuedSample;
bool mNeedReIndex;
bool mNeedSPSForTelemetry;
bool mIsH264 = false;
enum CodecType {
kH264,
kVP9,
kOther
} mType = kOther;
};
// Returns true if no SPS was found and search for it should continue.
@ -350,9 +357,8 @@ MP4TrackDemuxer::MP4TrackDemuxer(MediaResource* aResource,
VideoInfo* videoInfo = mInfo->GetAsVideoInfo();
// Collect telemetry from h264 AVCC SPS.
if (videoInfo && (mInfo->mMimeType.EqualsLiteral("video/mp4") ||
mInfo->mMimeType.EqualsLiteral("video/avc"))) {
mIsH264 = true;
if (videoInfo && MP4Decoder::IsH264(mInfo->mMimeType)) {
mType = kH264;
RefPtr<MediaByteBuffer> extraData = videoInfo->mExtraData;
mNeedSPSForTelemetry = AccumulateSPSTelemetry(extraData);
SPSData spsdata;
@ -365,6 +371,9 @@ MP4TrackDemuxer::MP4TrackDemuxer(MediaResource* aResource,
videoInfo->mDisplay.height = spsdata.display_height;
}
} else {
if (videoInfo && VPXDecoder::IsVP9(mInfo->mMimeType)) {
mType = kVP9;
}
// No SPS to be found.
mNeedSPSForTelemetry = false;
}
@ -422,7 +431,7 @@ already_AddRefed<MediaRawData> MP4TrackDemuxer::GetNextSample() {
}
if (mInfo->GetAsVideoInfo()) {
sample->mExtraData = mInfo->GetAsVideoInfo()->mExtraData;
if (mIsH264 && !sample->mCrypto.IsEncrypted()) {
if (mType == kH264 && !sample->mCrypto.IsEncrypted()) {
H264::FrameType type = H264::GetFrameType(sample);
switch (type) {
case H264::FrameType::I_FRAME:
@ -455,6 +464,20 @@ already_AddRefed<MediaRawData> MP4TrackDemuxer::GetNextSample() {
// TODO: make demuxer errors non-fatal.
break;
}
} else if (mType == kVP9 && !sample->mCrypto.IsEncrypted()) {
bool keyframe = VPXDecoder::IsKeyframe(
MakeSpan<const uint8_t>(sample->Data(), sample->Size()),
VPXDecoder::Codec::VP9);
if (sample->mKeyframe != keyframe) {
NS_WARNING(nsPrintfCString(
"Frame incorrectly marked as %skeyframe "
"@ pts:%" PRId64 " dur:%" PRId64 " dts:%" PRId64,
keyframe ? "" : "non-", sample->mTime.ToMicroseconds(),
sample->mDuration.ToMicroseconds(),
sample->mTimecode.ToMicroseconds())
.get());
sample->mKeyframe = keyframe;
}
}
}
@ -491,7 +514,7 @@ RefPtr<MP4TrackDemuxer::SamplesPromise> MP4TrackDemuxer::GetSamples(
}
for (const auto& sample : samples->mSamples) {
// Collect telemetry from h264 Annex B SPS.
if (mNeedSPSForTelemetry && mIsH264 && AnnexB::IsAVCC(sample)) {
if (mNeedSPSForTelemetry && mType == kH264 && AnnexB::IsAVCC(sample)) {
RefPtr<MediaByteBuffer> extradata = H264::ExtractExtraData(sample);
if (H264::HasSPS(extradata)) {
RefPtr<MediaByteBuffer> extradata = H264::ExtractExtraData(sample);

View File

@ -174,7 +174,6 @@ impl<'a> FrameBuildingState<'a> {
#[derive(Debug)]
pub struct PictureContext {
pub pic_index: PictureIndex,
pub pipeline_id: PipelineId,
pub apply_local_clip_rect: bool,
pub allow_subpixel_aa: bool,
pub is_passthrough: bool,
@ -189,7 +188,6 @@ pub struct PictureContext {
/// Mutable state of a picture that gets modified when
/// the children are processed.
pub struct PictureState {
pub is_cacheable: bool,
pub map_local_to_pic: SpaceMapper<LayoutPixel, PicturePixel>,
pub map_pic_to_world: SpaceMapper<PicturePixel, WorldPixel>,
pub map_pic_to_raster: SpaceMapper<PicturePixel, RasterPixel>,

View File

@ -2385,7 +2385,6 @@ impl PicturePrimitive {
let state = PictureState {
//TODO: check for MAX_CACHE_SIZE here?
is_cacheable: true,
map_local_to_pic,
map_pic_to_world,
map_pic_to_raster,
@ -2432,7 +2431,6 @@ impl PicturePrimitive {
let context = PictureContext {
pic_index,
pipeline_id: self.pipeline_id,
apply_local_clip_rect: self.apply_local_clip_rect,
allow_subpixel_aa,
is_passthrough: self.raster_config.is_none(),

View File

@ -2270,10 +2270,6 @@ impl PrimitiveStore {
frame_state.clip_chain_stack.pop_surface();
}
if !pic_state_for_children.is_cacheable {
pic_state.is_cacheable = false;
}
// Restore the dependencies (borrow check dance)
self.pictures[pic_context_for_children.pic_index.0]
.restore_context(
@ -2319,11 +2315,6 @@ impl PrimitiveStore {
prim_instance.prepared_frame_id = frame_state.render_tasks.frame_id();
}
pic_state.is_cacheable &= prim_instance.is_cacheable(
&data_stores,
frame_state.resource_cache,
);
match prim_instance.kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => {
let pic = &mut self.pictures[pic_index.0];

View File

@ -70,7 +70,7 @@ class NoTypePolicy {
class BoxInputsPolicy final : public TypePolicy {
public:
constexpr BoxInputsPolicy() {}
SPECIALIZATION_DATA_;
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc,
MInstruction* def);
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,

View File

@ -6617,51 +6617,13 @@ nsresult PresShell::EventHandler::HandleEvent(nsIFrame* aFrame,
}
}
// Suppress mouse event if it's being targeted at an element inside
// a document which needs events suppressed
if (aGUIEvent->mClass == eMouseEventClass &&
frameToHandleEvent->PresContext()
->Document()
->EventHandlingSuppressed()) {
if (aGUIEvent->mMessage == eMouseDown) {
mPresShell->mNoDelayedMouseEvents = true;
} else if (!mPresShell->mNoDelayedMouseEvents &&
(aGUIEvent->mMessage == eMouseUp ||
// contextmenu is triggered after right mouseup on Windows and
// right mousedown on other platforms.
aGUIEvent->mMessage == eContextMenu)) {
auto event = MakeUnique<DelayedMouseEvent>(aGUIEvent->AsMouseEvent());
PushDelayedEventIntoQueue(std::move(event));
}
// If there is a suppressed event listener associated with the document,
// notify it about the suppressed mouse event. This allows devtools
// features to continue receiving mouse events even when the devtools
// debugger has paused execution in a page.
RefPtr<EventListener> suppressedListener =
frameToHandleEvent->PresContext()
->Document()
->GetSuppressedEventListener();
if (suppressedListener && aGUIEvent->AsMouseEvent()->mReason !=
WidgetMouseEvent::eSynthesized) {
nsCOMPtr<nsIContent> targetContent;
frameToHandleEvent->GetContentForEvent(aGUIEvent,
getter_AddRefs(targetContent));
if (targetContent) {
aGUIEvent->mTarget = targetContent;
}
nsCOMPtr<EventTarget> et = aGUIEvent->mTarget;
RefPtr<Event> event = EventDispatcher::CreateEvent(
et, frameToHandleEvent->PresContext(), aGUIEvent, EmptyString());
suppressedListener->HandleEvent(*event);
}
if (NS_WARN_IF(!frameToHandleEvent)) {
return NS_OK;
}
if (NS_WARN_IF(!frameToHandleEvent)) {
// Suppress mouse event if it's being targeted at an element inside
// a document which needs events suppressed
if (MaybeDiscardOrDelayMouseEvent(frameToHandleEvent, aGUIEvent)) {
return NS_OK;
}
@ -7260,6 +7222,61 @@ bool PresShell::EventHandler::MaybeDiscardOrDelayKeyboardEvent(
return true;
}
bool PresShell::EventHandler::MaybeDiscardOrDelayMouseEvent(
nsIFrame* aFrameToHandleEvent, WidgetGUIEvent* aGUIEvent) {
MOZ_ASSERT(aFrameToHandleEvent);
MOZ_ASSERT(aGUIEvent);
if (aGUIEvent->mClass != eMouseEventClass) {
return false;
}
if (!aFrameToHandleEvent->PresContext()
->Document()
->EventHandlingSuppressed()) {
return false;
}
if (aGUIEvent->mMessage == eMouseDown) {
mPresShell->mNoDelayedMouseEvents = true;
} else if (!mPresShell->mNoDelayedMouseEvents &&
(aGUIEvent->mMessage == eMouseUp ||
// contextmenu is triggered after right mouseup on Windows and
// right mousedown on other platforms.
aGUIEvent->mMessage == eContextMenu)) {
UniquePtr<DelayedMouseEvent> delayedMouseEvent =
MakeUnique<DelayedMouseEvent>(aGUIEvent->AsMouseEvent());
PushDelayedEventIntoQueue(std::move(delayedMouseEvent));
}
// If there is a suppressed event listener associated with the document,
// notify it about the suppressed mouse event. This allows devtools
// features to continue receiving mouse events even when the devtools
// debugger has paused execution in a page.
RefPtr<EventListener> suppressedListener = aFrameToHandleEvent->PresContext()
->Document()
->GetSuppressedEventListener();
if (!suppressedListener ||
aGUIEvent->AsMouseEvent()->mReason == WidgetMouseEvent::eSynthesized) {
return true;
}
nsCOMPtr<nsIContent> targetContent;
aFrameToHandleEvent->GetContentForEvent(aGUIEvent,
getter_AddRefs(targetContent));
if (targetContent) {
aGUIEvent->mTarget = targetContent;
}
nsCOMPtr<EventTarget> eventTarget = aGUIEvent->mTarget;
RefPtr<Event> event = EventDispatcher::CreateEvent(
eventTarget, aFrameToHandleEvent->PresContext(), aGUIEvent,
EmptyString());
suppressedListener->HandleEvent(*event);
return true;
}
nsIFrame* PresShell::EventHandler::MaybeFlushThrottledStyles(
nsIFrame* aFrameForPresShell) {

View File

@ -711,6 +711,22 @@ class PresShell final : public nsIPresShell,
*/
bool MaybeDiscardOrDelayKeyboardEvent(WidgetGUIEvent* aGUIEvent);
/**
* MaybeDiscardOrDelayMouseEvent() may discard or put aGUIEvent into the
* delayed event queue if it's a mouse event and if we should do so.
* If aGUIEvent is not a mouse event, this does nothing.
* If there is suppressed event listener like debugger of devtools, this
* notifies it of the event after discard or put it into the delayed
* event queue.
*
* @param aFrameToHandleEvent The frame to handle aGUIEvent.
* @param aGUIEvent The handling event.
* @return true if this method discard the event
* or put it into the delayed event queue.
*/
bool MaybeDiscardOrDelayMouseEvent(nsIFrame* aFrameToHandleEvent,
WidgetGUIEvent* aGUIEvent);
/**
* MaybeFlushThrottledStyles() tries to flush pending animation. If it's
* flushed and then aFrameForPresShell is destroyed, returns new frame

View File

@ -253,7 +253,7 @@ class BaseBootstrapper(object):
'%s does not yet implement suggest_mobile_android_artifact_mode_mozconfig()'
% __name__)
def ensure_clang_static_analysis_package(self, checkout_root):
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
'''
Install the clang static analysis package
'''
@ -276,23 +276,15 @@ class BaseBootstrapper(object):
'%s does not yet implement ensure_node_packages()'
% __name__)
def install_toolchain_static_analysis(self, checkout_root):
mach_binary = os.path.join(checkout_root, 'mach')
mach_binary = os.path.abspath(mach_binary)
if not os.path.exists(mach_binary):
raise ValueError("mach not found at %s" % mach_binary)
def install_toolchain_static_analysis(self, state_dir, checkout_root, toolchain_job):
clang_tools_path = os.path.join(state_dir, 'clang-tools')
import shutil
if os.path.exists(clang_tools_path):
shutil.rmtree(clang_tools_path)
if not sys.executable:
raise ValueError("cannot determine path to Python executable")
cmd = [sys.executable, mach_binary, 'static-analysis', 'install',
'--force', '--minimal-install']
from subprocess import CalledProcessError
try:
subprocess.check_call(cmd)
except CalledProcessError as e:
print(e.output)
# Re-create the directory for clang_tools
os.mkdir(clang_tools_path)
self.install_toolchain_artifact(clang_tools_path, checkout_root, toolchain_job)
def install_toolchain_artifact(self, state_dir, checkout_root, toolchain_job):
mach_binary = os.path.join(checkout_root, 'mach')

View File

@ -382,7 +382,7 @@ class Bootstrapper(object):
self.instance.ensure_node_packages(state_dir, checkout_root)
if not self.instance.artifact_mode:
self.instance.ensure_stylo_packages(state_dir, checkout_root)
self.instance.ensure_clang_static_analysis_package(checkout_root)
self.instance.ensure_clang_static_analysis_package(state_dir, checkout_root)
def check_telemetry_opt_in(self, state_dir):
# We can't prompt the user.

View File

@ -66,7 +66,7 @@ class FreeBSDBootstrapper(BaseBootstrapper):
# TODO: Figure out what not to install for artifact mode
self.pkg_install(*self.browser_packages)
def ensure_clang_static_analysis_package(self, checkout_root):
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
# TODO: we don't ship clang base static analysis for this platform
pass

View File

@ -49,10 +49,12 @@ class ClangStaticAnalysisInstall(object):
def __init__(self, **kwargs):
pass
def ensure_clang_static_analysis_package(self, checkout_root):
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
if is_non_x86_64():
print('Cannot install static analysis tools from taskcluster.\n'
'Please install these tools manually.')
return
self.install_toolchain_static_analysis(checkout_root)
from mozboot import static_analysis
self.install_toolchain_static_analysis(
state_dir, checkout_root, static_analysis.LINUX_CLANG_TIDY)

View File

@ -72,8 +72,10 @@ class MozillaBuildBootstrapper(BaseBootstrapper):
def install_mobile_android_artifact_mode_packages(self):
pass
def ensure_clang_static_analysis_package(self, checkout_root):
self.install_toolchain_static_analysis(checkout_root)
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
from mozboot import static_analysis
self.install_toolchain_static_analysis(
state_dir, checkout_root, static_analysis.WINDOWS_CLANG_TIDY)
def ensure_stylo_packages(self, state_dir, checkout_root):
# On-device artifact builds are supported; on-device desktop builds are not.

View File

@ -47,7 +47,7 @@ class OpenBSDBootstrapper(BaseBootstrapper):
# we use -z because there's no other way to say "any autoconf-2.13"
self.run_as_root(['pkg_add', '-z'] + self.browser_packages)
def ensure_clang_static_analysis_package(self, checkout_root):
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
# TODO: we don't ship clang base static analysis for this platform
pass

View File

@ -516,8 +516,10 @@ class OSXBootstrapper(BaseBootstrapper):
return active_name.lower()
def ensure_clang_static_analysis_package(self, checkout_root):
self.install_toolchain_static_analysis(checkout_root)
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
from mozboot import static_analysis
self.install_toolchain_static_analysis(
state_dir, checkout_root, static_analysis.MACOS_CLANG_TIDY)
def ensure_stylo_packages(self, state_dir, checkout_root):
from mozboot import stylo

View File

@ -0,0 +1,9 @@
# 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/.
from __future__ import absolute_import, print_function, unicode_literals
WINDOWS_CLANG_TIDY = 'win64-clang-tidy'
LINUX_CLANG_TIDY = 'linux64-clang-tidy'
MACOS_CLANG_TIDY = 'macosx64-clang-tidy'

View File

@ -99,8 +99,10 @@ class WindowsBootstrapper(BaseBootstrapper):
def install_mobile_android_artifact_mode_packages(self):
raise NotImplementedError('We do not support building Android on Windows. Sorry!')
def ensure_clang_static_analysis_package(self, checkout_root):
self.install_toolchain_static_analysis(checkout_root)
def ensure_clang_static_analysis_package(self, state_dir, checkout_root):
from mozboot import static_analysis
self.install_toolchain_static_analysis(
state_dir, checkout_root, static_analysis.WINDOWS_CLANG_TIDY)
def ensure_stylo_packages(self, state_dir, checkout_root):
# On-device artifact builds are supported; on-device desktop builds are not.

View File

@ -2817,7 +2817,8 @@ class StaticAnalysis(MachCommandBase):
# Supported extension and accepted path
path_list.append(f_in_dir)
else:
if f.endswith(extensions):
# Make sure that the file exists and it has a supported extension
if os.path.isfile(f) and f.endswith(extensions):
path_list.append(f)
return path_list

View File

@ -53,7 +53,7 @@ linux64-rust-nightly:
symbol: TL(rust-nightly)
run:
arguments: [
'--channel', 'nightly-2018-10-05',
'--channel', 'nightly-2018-12-14',
'--host', 'x86_64-unknown-linux-gnu',
'--target', 'x86_64-unknown-linux-gnu',
'--target', 'i686-unknown-linux-gnu',
@ -90,7 +90,7 @@ linux64-rust-nightly-macos:
symbol: TL(rust-nightly-macos)
run:
arguments: [
'--channel', 'nightly-2018-10-05',
'--channel', 'nightly-2018-12-14',
'--host', 'x86_64-unknown-linux-gnu',
'--target', 'x86_64-unknown-linux-gnu',
'--target', 'x86_64-apple-darwin',
@ -143,7 +143,7 @@ win64-rust-nightly:
symbol: TW64(rust-nightly)
run:
arguments: [
'--channel', 'nightly-2018-10-05',
'--channel', 'nightly-2018-12-14',
'--host', 'x86_64-pc-windows-msvc',
'--target', 'x86_64-pc-windows-msvc',
'--target', 'i686-pc-windows-msvc',

View File

@ -7,7 +7,7 @@ from __future__ import absolute_import
from setuptools import setup
PACKAGE_NAME = 'mozprofile'
PACKAGE_VERSION = '2.1.0'
PACKAGE_VERSION = '2.2.0'
deps = [
'mozfile>=1.2',