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

This commit is contained in:
Daniel Varga 2019-05-23 19:03:36 +03:00
commit 2056f57259
202 changed files with 2560 additions and 1119 deletions

View File

@ -435,6 +435,9 @@ void DocAccessible::Shutdown() {
mDependentIDsHashes.Clear();
mNodeToAccessibleMap.Clear();
mAnchorJumpElm = nullptr;
mInvalidationList.Clear();
for (auto iter = mAccessibleCache.Iter(); !iter.Done(); iter.Next()) {
Accessible* accessible = iter.Data();
MOZ_ASSERT(accessible);

View File

@ -21,7 +21,7 @@
#endif
#endif
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindowMac.xhtml");
// Enables some extra Extension System Logging (can reduce performance)
pref("extensions.logging.enabled", false);

View File

@ -31,7 +31,7 @@
<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css" type="text/css"?>
# All DTD information is stored in a separate file so that it can be shared by
# hiddenWindow.xul.
# hiddenWindowMac.xhtml.
<!DOCTYPE window [
#include browser-doctype.inc
]>

View File

@ -12,7 +12,6 @@
]>
<window id="main-window"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
#include macWindow.inc.xul

View File

@ -151,7 +151,7 @@ with Files("browser-sync.js"):
with Files("contentSearch*"):
BUG_COMPONENT = ("Firefox", "Search")
with Files("hiddenWindow.xul"):
with Files("hiddenWindowMac.xhtml"):
BUG_COMPONENT = ("Firefox", "Device Permissions")
with Files("macWindow.inc.xul"):

View File

@ -44,7 +44,7 @@ function nonBrowserWindowStartup() {
// If no windows are active (i.e. we're the hidden window), disable the close, minimize
// and zoom menu commands as well
if (window.location.href == "chrome://browser/content/hiddenWindow.xul") {
if (window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml") {
var hiddenWindowDisabledItems = ["cmd_close", "minimizeWindow", "zoomWindow"];
for (let hiddenWindowDisabledItem of hiddenWindowDisabledItems) {
element = document.getElementById(hiddenWindowDisabledItem);
@ -96,7 +96,7 @@ function nonBrowserWindowDelayedStartup() {
function nonBrowserWindowShutdown() {
// If this is the hidden window being closed, release our reference to
// the dock menu element to prevent leaks on shutdown
if (window.location.href == "chrome://browser/content/hiddenWindow.xul") {
if (window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml") {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
dockSupport.dockMenu = null;

View File

@ -11,8 +11,10 @@
.tab-icon-image:not([src]):not([pinned]):not([crashed]):not([sharing]),
.tab-icon-image[busy],
.tab-throbber:not([busy]),
.tab-icon-pip:not([pictureinpicture]),
.tab-icon-sound:not([soundplaying]):not([muted]):not([activemedia-blocked]),
.tab-icon-sound[pinned],
.tab-icon-sound[pictureinpicture],
.tab-sharing-icon-overlay,
.tab-icon-overlay {
display: none;

View File

@ -1951,7 +1951,10 @@
xbl:inherits="xbl:text=label,accesskey,fadein,pinned,selected=visuallyselected,attention"
role="presentation"/>
</xul:hbox>
<xul:image xbl:inherits="soundplaying,soundplaying-scheduledremoval,pinned,muted,blocked,selected=visuallyselected,activemedia-blocked"
<xul:image xbl:inherits="pictureinpicture"
class="tab-icon-pip"
role="presentation"/>
<xul:image xbl:inherits="soundplaying,soundplaying-scheduledremoval,pinned,muted,blocked,selected=visuallyselected,activemedia-blocked,pictureinpicture"
anonid="soundplaying-icon"
class="tab-icon-sound"
role="presentation"/>
@ -2063,6 +2066,12 @@
</getter>
</property>
<property name="pictureinpicture" readonly="true">
<getter>
return this.getAttribute("pictureinpicture") == "true";
</getter>
</property>
<property name="activeMediaBlocked" readonly="true">
<getter>
return this.getAttribute("activemedia-blocked") == "true";

View File

@ -104,7 +104,7 @@ browser.jar:
content/browser/contentTheme.js (content/contentTheme.js)
#ifdef XP_MACOSX
# XXX: We should exclude this one as well (bug 71895)
* content/browser/hiddenWindow.xul (content/hiddenWindow.xul)
* content/browser/hiddenWindowMac.xhtml (content/hiddenWindowMac.xhtml)
content/browser/nonbrowser-mac.js (content/nonbrowser-mac.js)
#endif
#ifndef XP_MACOSX

View File

@ -263,6 +263,7 @@ class TabsPanel extends TabsListBase {
setAttributes(secondaryButton, {
muted: tab.muted,
soundplaying: tab.soundPlaying,
pictureinpicture: tab.pictureinpicture,
hidden: !(tab.muted || tab.soundPlaying),
});
}

View File

@ -377,6 +377,7 @@
padding: 10px calc(@horizontalTabPadding@ - 2px);
}
.tab-icon-pip,
.tab-icon-sound {
margin-inline-start: 1px;
width: 16px;
@ -384,6 +385,16 @@
padding: 0;
}
.tab-icon-pip[pictureinpicture] {
background-image: url(chrome://global/skin/media/pictureinpicture.svg);
-moz-context-properties: fill, stroke;
fill: currentColor;
stroke: currentColor;
width: 14px;
height: 14px;
margin-inline-start: 5px
}
.tab-icon-sound[soundplaying],
.tab-icon-sound[muted],
.tab-icon-sound[activemedia-blocked] {
@ -400,18 +411,21 @@
list-style-image: url(chrome://browser/skin/tabbrowser/tab-audio-blocked.svg);
}
:root[lwtheme-image] .tab-icon-pip:-moz-lwtheme-darktext[pictureinpicture],
:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-darktext[soundplaying],
:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-darktext[muted],
:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-darktext[activemedia-blocked] {
filter: drop-shadow(1px 1px 1px white);
}
:root[lwtheme-image] .tab-icon-pip:-moz-lwtheme-brighttext[pictureinpicture],
:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-brighttext[soundplaying],
:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-brighttext[muted],
:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-brighttext[activemedia-blocked] {
filter: drop-shadow(1px 1px 1px black);
}
.tab-icon-pip[pictureinpicture]:not(:hover),
.tab-icon-sound[soundplaying]:not(:hover),
.tab-icon-sound[muted]:not(:hover),
.tab-icon-sound[activemedia-blocked]:not(:hover) {

View File

@ -21,6 +21,8 @@ def rust_warning_flags(warnings_as_errors):
# we don't need a very complicated setup.
if warnings_as_errors:
flags.append('-Dwarnings')
else:
flags.extend(('--cap-lints', 'warn'))
return flags

View File

@ -58,7 +58,7 @@ if test -n "$bucket"; then
else
mk_add_options "export SCCACHE_BUCKET=$bucket"
fi
export CCACHE="$topsrcdir/sccache2/sccache"
export CCACHE="$topsrcdir/sccache/sccache"
export SCCACHE_VERBOSE_STATS=1
mk_add_options MOZBUILD_MANAGE_SCCACHE_DAEMON=${topsrcdir}/sccache2/sccache
mk_add_options MOZBUILD_MANAGE_SCCACHE_DAEMON=${topsrcdir}/sccache/sccache
fi

View File

@ -213,7 +213,11 @@ module.exports = {
// Require camel case names
"camelcase": "error",
// Warn about cyclomatic complexity in functions.
"complexity": ["error", 40],
// 20 is ESLint's default, and we want to keep it this way to prevent new highly
// complex functions from being introduced. However, because Mozilla's eslintrc has
// some other value defined, we need to override it here. See bug 1553449 for more
// information on complex DevTools functions that are currently excluded.
"complexity": ["error", 20],
// Don't warn for inconsistent naming when capturing this (not so important
// with auto-binding fat arrow functions).
"consistent-this": "off",

View File

@ -38,6 +38,7 @@ class SummaryGraph extends PureComponent {
this.props.selectAnimation(this.props.animation);
}
/* eslint-disable complexity */
getTitleText(state) {
const getTime =
time => getFormatStr("player.timeLabel", numberWithDecimals(time / 1000, 2));
@ -136,6 +137,7 @@ class SummaryGraph extends PureComponent {
return text;
}
/* eslint-enable complexity */
render() {
const {

View File

@ -199,6 +199,7 @@ const reducers = {
* - when changes cancel each other out leaving the rule unchanged, the rule is removed
* from the store. Its parent rule is removed as well if it too ends up unchanged.
*/
/* eslint-disable complexity */
[TRACK_CHANGE](state, { change }) {
const defaults = {
selector: null,
@ -351,6 +352,7 @@ const reducers = {
return state;
},
/* eslint-enable complexity */
[RESET_CHANGES](state) {
return INITIAL_STATE;

View File

@ -325,6 +325,7 @@ CssComputedView.prototype = {
* - value {Object} Depends on the type of the node
* returns null if the node isn't anything we care about
*/
/* eslint-disable complexity */
getNodeInfo: function(node) {
if (!node) {
return null;
@ -428,6 +429,7 @@ CssComputedView.prototype = {
value,
};
},
/* eslint-enable complexity */
_createPropertyViews: function() {
if (this._createViewsPromise) {

View File

@ -113,6 +113,7 @@ class FlexItemSizingProperties extends PureComponent {
);
}
/* eslint-disable complexity */
renderFlexibilitySection(flexItemSizing, mainFinalSize, properties, computedStyle) {
const {
mainDeltaSize,
@ -183,6 +184,7 @@ class FlexItemSizingProperties extends PureComponent {
)
);
}
/* eslint-enable complexity */
renderMinimumSizeSection(flexItemSizing, properties, dimension) {
const { clampState, mainMinSize, mainDeltaSize } = flexItemSizing;

View File

@ -213,6 +213,7 @@ SelectorAutocompleter.prototype = {
* '#f' requires an Id suggestion, so the state is States.ID
* 'div > .foo' requires class suggestion, so state is States.CLASS
*/
/* eslint-disable complexity */
get state() {
if (!this.searchBox || !this.searchBox.value) {
return null;
@ -306,6 +307,7 @@ SelectorAutocompleter.prototype = {
}
return this._state;
},
/* eslint-enable complexity */
/**
* Removes event listeners and cleans up references.

View File

@ -895,6 +895,7 @@ MarkupView.prototype = {
/**
* Key shortcut listener.
*/
/* eslint-disable complexity */
_onShortcut(name, event) {
if (this._isInputOrTextarea(event.target)) {
return;
@ -1024,6 +1025,7 @@ MarkupView.prototype = {
event.stopPropagation();
event.preventDefault();
},
/* eslint-enable complexity */
/**
* Check if a node is an input or textarea

View File

@ -274,6 +274,7 @@ class ElementStyle {
* Which pseudo element to flag as overridden.
* Empty string or undefined will default to no pseudo element.
*/
/* eslint-disable complexity */
updateDeclarations(pseudo = "") {
// Gather all the text properties applied by these rules, ordered
// from more- to less-specific. Text properties from keyframes rule are
@ -376,6 +377,7 @@ class ElementStyle {
}
}
}
/* eslint-enable complexity */
/**
* Adds a new declaration to the rule.

View File

@ -371,6 +371,7 @@ CssRuleView.prototype = {
* - value {Object} Depends on the type of the node
* returns null of the node isn't anything we care about
*/
/* eslint-disable complexity */
getNodeInfo: function(node) {
if (!node) {
return null;
@ -486,6 +487,7 @@ CssRuleView.prototype = {
value,
};
},
/* eslint-enable complexity */
/**
* Retrieve the RuleEditor instance.
@ -1142,6 +1144,7 @@ CssRuleView.prototype = {
/**
* Creates editor UI for each of the rules in _elementStyle.
*/
/* eslint-disable complexity */
_createEditors: function() {
// Run through the current list of rules, attaching
// their editors in order. Create editors if needed.
@ -1222,6 +1225,7 @@ CssRuleView.prototype = {
return promise.all(editorReadyPromises);
},
/* eslint-enable complexity */
/**
* Highlight rules that matches the filter search value and returns a

View File

@ -389,6 +389,7 @@ TextPropertyEditor.prototype = {
/**
* Populate the span based on changes to the TextProperty.
*/
/* eslint-disable complexity */
update: function() {
if (this.ruleView.isDestroyed) {
return;
@ -610,6 +611,7 @@ TextPropertyEditor.prototype = {
// Update the rule property highlight.
this.ruleView._updatePropertyHighlight(this);
},
/* eslint-enable complexity */
_onStartEditing: function() {
this.element.classList.remove("ruleview-overridden");

View File

@ -103,6 +103,7 @@ exports.getCustomTreeMapDisplays = function() {
* @param {snapshotState | diffingState} state
* @return {String}
*/
/* eslint-disable complexity */
exports.getStatusText = function(state) {
assert(state, "Must have a state");
@ -170,6 +171,7 @@ exports.getStatusText = function(state) {
return "";
}
};
/* eslint-enable complexity */
/**
* Returns a string representing a readable form of the snapshot's state;
@ -178,6 +180,7 @@ exports.getStatusText = function(state) {
* @param {snapshotState | diffingState} state
* @return {String}
*/
/* eslint-disable complexity */
exports.getStatusTextFull = function(state) {
assert(!!state, "Must have a state");
@ -245,6 +248,7 @@ exports.getStatusTextFull = function(state) {
return "";
}
};
/* eslint-enable complexity */
/**
* Return true if the snapshot is in a diffable state, false otherwise.

View File

@ -186,6 +186,7 @@ class RequestListItem extends Component {
}
}
/* eslint-disable complexity */
render() {
const {
blocked,
@ -284,6 +285,7 @@ class RequestListItem extends Component {
)
);
}
/* eslint-enable complexity */
}
module.exports = RequestListItem;

View File

@ -119,6 +119,7 @@ class SecurityPanel extends Component {
);
}
/* eslint-disable complexity */
render() {
const { openLink, request } = this.props;
const { securityInfo, url } = request;
@ -232,6 +233,7 @@ class SecurityPanel extends Component {
})
);
}
/* eslint-enable complexity */
}
module.exports = SecurityPanel;

View File

@ -46,6 +46,7 @@ function Requests() {
* This reducer is responsible for maintaining list of request
* within the Network panel.
*/
/* eslint-disable complexity */
function requestsReducer(state = Requests(), action) {
switch (action.type) {
// Appending new request into the list/map.
@ -182,6 +183,7 @@ function requestsReducer(state = Requests(), action) {
return state;
}
}
/* eslint-enable complexity */
// Helpers

View File

@ -120,6 +120,7 @@ function processFlagFilter(type, value) {
}
}
/* eslint-disable complexity */
function isFlagFilterMatch(item, { type, value, negative }) {
if (value == null) {
return false;
@ -233,6 +234,7 @@ function isFlagFilterMatch(item, { type, value, negative }) {
}
return match;
}
/* eslint-enable complexity */
function isSizeMatch(value, size) {
return value >= (size - size / 10) && value <= (size + size / 10);

View File

@ -25,6 +25,7 @@ class RequestListContextMenu {
this.props = props;
}
/* eslint-disable complexity */
open(event, clickedRequest, requests) {
const {
id,
@ -284,6 +285,7 @@ class RequestListContextMenu {
screenY: event.screenY,
});
}
/* eslint-enable complexity */
/**
* Opens selected item in the debugger

View File

@ -35,6 +35,7 @@ const gFrameData = new WeakMap();
* Parses the raw location of this function call to retrieve the actual
* function name, source url, host name, line and column.
*/
/* eslint-disable complexity */
function parseLocation(location, fallbackLine, fallbackColumn) {
// Parse the `location` for the function name, source url, line, column etc.
@ -182,6 +183,7 @@ function parseLocation(location, fallbackLine, fallbackColumn) {
return { functionName, fileName, host, port, url, line, column };
}
/* eslint-enable complexity */
/**
* Sets the properties of `isContent` and `category` on a frame.

View File

@ -312,6 +312,8 @@ pref("devtools.editor.detectindentation", true);
pref("devtools.editor.enableCodeFolding", true);
pref("devtools.editor.autocomplete", true);
// The angle of the viewport.
pref("devtools.responsive.viewport.angle", 0);
// The width of the viewport.
pref("devtools.responsive.viewport.width", 320);
// The height of the viewport.

View File

@ -22,7 +22,7 @@ const { post } = require("../utils/message");
const { addDevice, editDevice, getDevices, removeDevice } = require("devtools/client/shared/devices");
const { changeUserAgent, toggleTouchSimulation } = require("./ui");
const { changeDevice, changePixelRatio } = require("./viewports");
const { changeDevice, changePixelRatio, changeViewportAngle } = require("./viewports");
const DISPLAYED_DEVICES_PREF = "devtools.responsive.html.displayedDeviceList";
@ -113,6 +113,7 @@ module.exports = {
post(window, {
type: "change-device",
device: newDevice,
viewport,
});
// Update UI if the device is selected.
@ -212,13 +213,16 @@ module.exports = {
return;
}
const viewport = getState().viewports[0];
post(window, {
type: "change-device",
device,
viewport,
});
dispatch(changeDevice(id, device.name, deviceType));
dispatch(changePixelRatio(id, device.pixelRatio));
dispatch(changeViewportAngle(id, viewport.angle));
dispatch(changeUserAgent(device.userAgent));
dispatch(toggleTouchSimulation(device.touch));
};

View File

@ -48,6 +48,9 @@ createEnum([
// selected from the device pixel ratio dropdown.
"CHANGE_PIXEL_RATIO",
// Change the viewport angle.
"CHANGE_VIEWPORT_ANGLE",
// Edit a device.
"EDIT_DEVICE",

View File

@ -12,6 +12,7 @@ const {
ADD_VIEWPORT,
CHANGE_DEVICE,
CHANGE_PIXEL_RATIO,
CHANGE_VIEWPORT_ANGLE,
REMOVE_DEVICE_ASSOCIATION,
RESIZE_VIEWPORT,
ROTATE_VIEWPORT,
@ -63,6 +64,14 @@ module.exports = {
};
},
changeViewportAngle(id, angle) {
return {
type: CHANGE_VIEWPORT_ANGLE,
id,
angle,
};
},
/**
* Remove the viewport's device assocation.
*/
@ -95,18 +104,6 @@ module.exports = {
* Rotate the viewport.
*/
rotateViewport(id) {
// TODO: Add `orientation` and `angle` properties to message data. See Bug 1357774.
// There is no window object to post to when ran on XPCShell as part of the unit
// tests and will immediately throw an error as a result.
try {
post(window, {
type: "viewport-orientation-change",
});
} catch (e) {
console.log("Unable to post message to window");
}
return {
type: ROTATE_VIEWPORT,
id,

View File

@ -121,6 +121,11 @@ var global = this;
.getInterface(Ci.nsIWebProgress);
webProgress.removeProgressListener(WebProgressListener);
docShell.deviceSizeIsPageSize = gDeviceSizeWasPageSize;
// Restore the original physical screen orientation values before RDM is stopped.
// This is necessary since the window document's `setCurrentRDMPaneOrientation`
// WebIDL operation can only modify the window's screen orientation values while the
// window content is in RDM.
restoreScreenOrientation();
restoreScrollbars();
setDocumentInRDMPane(false);
stopOnResize();
@ -165,6 +170,10 @@ var global = this;
flushStyle();
}
function restoreScreenOrientation() {
docShell.contentViewer.DOMDocument.setRDMPaneOrientation("landscape-primary", 0);
}
function setDocumentInRDMPane(inRDMPane) {
// We don't propegate this property to descendent documents.
docShell.contentViewer.DOMDocument.inRDMPane = inRDMPane;
@ -199,6 +208,13 @@ var global = this;
return;
}
setDocumentInRDMPane(true);
// Notify the Responsive UI manager to set orientation state on a location change.
// This is necessary since we want to ensure that the RDM Document's orientation
// state persists throughout while RDM is opened.
sendAsyncMessage("ResponsiveMode:OnLocationChange", {
width: content.innerWidth,
height: content.innerHeight,
});
makeScrollbarsFloating();
},
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",

View File

@ -6,6 +6,7 @@
"use strict";
const Services = require("Services");
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");
@ -38,10 +39,12 @@ const {
const {
changeDevice,
changePixelRatio,
changeViewportAngle,
removeDeviceAssociation,
resizeViewport,
rotateViewport,
} = require("../actions/viewports");
const { getOrientation } = require("../utils/orientation");
const Types = require("../types");
@ -67,6 +70,7 @@ class App extends PureComponent {
this.onChangePixelRatio = this.onChangePixelRatio.bind(this);
this.onChangeTouchSimulation = this.onChangeTouchSimulation.bind(this);
this.onChangeUserAgent = this.onChangeUserAgent.bind(this);
this.onChangeViewportOrientation = this.onChangeViewportOrientation.bind(this);
this.onContentResize = this.onContentResize.bind(this);
this.onDeviceListUpdate = this.onDeviceListUpdate.bind(this);
this.onEditCustomDevice = this.onEditCustomDevice.bind(this);
@ -114,7 +118,12 @@ class App extends PureComponent {
window.postMessage({
type: "change-device",
device,
viewport: this.props.viewports[id],
}, "*");
const orientation = getOrientation(device, this.props.viewports[0]);
this.props.dispatch(changeViewportAngle(0, orientation.angle));
this.props.dispatch(changeDevice(id, device.name, deviceType));
this.props.dispatch(changePixelRatio(id, device.pixelRatio));
this.props.dispatch(changeUserAgent(device.userAgent));
@ -154,6 +163,15 @@ class App extends PureComponent {
this.props.dispatch(changeUserAgent(userAgent));
}
onChangeViewportOrientation(id, { type, angle }) {
window.postMessage({
type: "viewport-orientation-change",
orientationType: type,
angle,
}, "*");
this.props.dispatch(changeViewportAngle(id, angle));
}
onContentResize({ width, height }) {
window.postMessage({
type: "content-resize",
@ -228,7 +246,44 @@ class App extends PureComponent {
}, "*");
}
/**
* Dispatches the rotateViewport action creator. This utilized by the RDM toolbar as
* a prop.
*
* @param {Number} id
* The viewport ID.
*/
onRotateViewport(id) {
let currentDevice;
const viewport = this.props.viewports[id];
for (const type of this.props.devices.types) {
for (const device of this.props.devices[type]) {
if (viewport.device === device.name) {
currentDevice = device;
}
}
}
// If no device is selected, then assume the selected device's primary orientation is
// opposite of the viewport orientation.
if (!currentDevice) {
currentDevice = {
height: viewport.width,
width: viewport.height,
};
}
const currentAngle = Services.prefs.getIntPref("devtools.responsive.viewport.angle");
// TODO: For Firefox Android, when the device is rotated clock-wise, the angle is
// updated to 270 degrees. This is valid since the user-agent determines whether it
// will be set to 90 or 270. However, we should update the angle based on the how the
// user-agent assigns the angle value.
// See https://w3c.github.io/screen-orientation/#dfn-screen-orientation-values-table
const angleToRotateTo = currentAngle === 270 ? 0 : 270;
const orientation = getOrientation(currentDevice, viewport, angleToRotateTo);
this.onChangeViewportOrientation(id, orientation);
this.props.dispatch(rotateViewport(id));
}
@ -276,6 +331,7 @@ class App extends PureComponent {
onChangePixelRatio,
onChangeTouchSimulation,
onChangeUserAgent,
onChangeViewportOrientation,
onContentResize,
onDeviceListUpdate,
onEditCustomDevice,
@ -335,6 +391,7 @@ class App extends PureComponent {
screenshot,
viewports,
onBrowserMounted,
onChangeViewportOrientation,
onContentResize,
onRemoveDeviceAssociation,
doResizeViewport,

View File

@ -12,6 +12,7 @@ const { 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 { PORTRAIT_PRIMARY, LANDSCAPE_PRIMARY } = require("../constants");
const e10s = require("../utils/e10s");
const message = require("../utils/message");
const { getTopLevelWindow } = require("../utils/window");
@ -27,10 +28,12 @@ class Browser extends PureComponent {
static get propTypes() {
return {
onBrowserMounted: PropTypes.func.isRequired,
onChangeViewportOrientation: PropTypes.func.isRequired,
onContentResize: PropTypes.func.isRequired,
onResizeViewport: PropTypes.func.isRequired,
swapAfterMount: PropTypes.bool.isRequired,
userContextId: PropTypes.number.isRequired,
viewportId: PropTypes.number.isRequired,
};
}
@ -38,6 +41,7 @@ class Browser extends PureComponent {
super(props);
this.onContentResize = this.onContentResize.bind(this);
this.onResizeViewport = this.onResizeViewport.bind(this);
this.onSetScreenOrientation = this.onSetScreenOrientation.bind(this);
}
/**
@ -108,11 +112,20 @@ class Browser extends PureComponent {
});
}
onSetScreenOrientation(msg) {
const { width, height } = msg.data;
const angle = Services.prefs.getIntPref("devtools.responsive.viewport.angle");
const type = height >= width ? PORTRAIT_PRIMARY : LANDSCAPE_PRIMARY;
this.props.onChangeViewportOrientation(this.props.viewportId, { type, angle });
}
async startFrameScript() {
const {
browser,
onContentResize,
onResizeViewport,
onSetScreenOrientation,
} = this;
const mm = browser.frameLoader.messageManager;
@ -122,6 +135,7 @@ class Browser extends PureComponent {
// resized to match.
e10s.on(mm, "OnContentResize", onContentResize);
e10s.on(mm, "OnResizeViewport", onResizeViewport);
e10s.on(mm, "OnLocationChange", onSetScreenOrientation);
const ready = e10s.once(mm, "ChildScriptReady");
mm.loadFrameScript(FRAME_SCRIPT, true);
@ -143,11 +157,13 @@ class Browser extends PureComponent {
browser,
onContentResize,
onResizeViewport,
onSetScreenOrientation,
} = this;
const mm = browser.frameLoader.messageManager;
e10s.off(mm, "OnContentResize", onContentResize);
e10s.off(mm, "OnResizeViewport", onResizeViewport);
e10s.off(mm, "OnLocationChange", onSetScreenOrientation);
await e10s.request(mm, "Stop");
message.post(window, "stop-frame-script:done");
}

View File

@ -23,6 +23,7 @@ class ResizableViewport extends PureComponent {
return {
leftAlignmentEnabled: PropTypes.bool.isRequired,
onBrowserMounted: PropTypes.func.isRequired,
onChangeViewportOrientation: PropTypes.func.isRequired,
onContentResize: PropTypes.func.isRequired,
onRemoveDeviceAssociation: PropTypes.func.isRequired,
doResizeViewport: PropTypes.func.isRequired,
@ -150,6 +151,7 @@ class ResizableViewport extends PureComponent {
swapAfterMount,
viewport,
onBrowserMounted,
onChangeViewportOrientation,
onContentResize,
onResizeViewport,
} = this.props;
@ -178,7 +180,9 @@ class ResizableViewport extends PureComponent {
Browser({
swapAfterMount,
userContextId: viewport.userContextId,
viewportId: viewport.id,
onBrowserMounted,
onChangeViewportOrientation,
onContentResize,
onResizeViewport,
})

View File

@ -18,6 +18,7 @@ class Viewports extends PureComponent {
return {
leftAlignmentEnabled: PropTypes.bool.isRequired,
onBrowserMounted: PropTypes.func.isRequired,
onChangeViewportOrientation: PropTypes.func.isRequired,
onContentResize: PropTypes.func.isRequired,
onRemoveDeviceAssociation: PropTypes.func.isRequired,
doResizeViewport: PropTypes.func.isRequired,
@ -31,6 +32,7 @@ class Viewports extends PureComponent {
const {
leftAlignmentEnabled,
onBrowserMounted,
onChangeViewportOrientation,
onContentResize,
onRemoveDeviceAssociation,
doResizeViewport,
@ -71,6 +73,7 @@ class Viewports extends PureComponent {
key: viewport.id,
leftAlignmentEnabled,
onBrowserMounted,
onChangeViewportOrientation,
onContentResize,
onRemoveDeviceAssociation,
doResizeViewport,

View File

@ -6,3 +6,9 @@
// The minimum viewport width and height
exports.MIN_VIEWPORT_DIMENSION = 50;
// Orientation types
exports.PORTRAIT_PRIMARY = "portrait-primary";
exports.PORTRAIT_SECONDARY = "portrait-secondary";
exports.LANDSCAPE_PRIMARY = "landscape-primary";
exports.LANDSCAPE_SECONDARY = "landscape-secondary";

View File

@ -8,6 +8,7 @@ const { Ci } = require("chrome");
const promise = require("promise");
const Services = require("Services");
const EventEmitter = require("devtools/shared/event-emitter");
const { getOrientation } = require("./utils/orientation");
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
@ -582,9 +583,12 @@ ResponsiveUI.prototype = {
},
async onChangeDevice(event) {
const { userAgent, pixelRatio, touch } = event.data.device;
const { device, viewport } = event.data;
const { pixelRatio, touch, userAgent } = event.data.device;
let reloadNeeded = false;
await this.updateDPPX(pixelRatio);
await this.updateScreenOrientation(getOrientation(device, viewport), true);
reloadNeeded |= await this.updateUserAgent(userAgent) &&
this.reloadOnChange("userAgent");
reloadNeeded |= await this.updateTouchSimulation(touch) &&
@ -665,15 +669,8 @@ ResponsiveUI.prototype = {
},
async onRotateViewport(event) {
const targetFront = await this.client.mainRoot.getTab();
// Ensure that simulateScreenOrientationChange is supported.
if (await targetFront.actorHasMethod("emulation",
"simulateScreenOrientationChange")) {
// TODO: From event.data, pass orientation and angle as arguments.
// See Bug 1357774.
await this.emulationFront.simulateScreenOrientationChange();
}
const { orientationType: type, angle } = event.data;
await this.updateScreenOrientation({ type, angle }, false);
},
/**
@ -687,15 +684,21 @@ ResponsiveUI.prototype = {
return;
}
const height =
Services.prefs.getIntPref("devtools.responsive.viewport.height", 0);
const pixelRatio =
Services.prefs.getIntPref("devtools.responsive.viewport.pixelRatio", 0);
const touchSimulationEnabled =
Services.prefs.getBoolPref("devtools.responsive.touchSimulation.enabled", false);
const userAgent = Services.prefs.getCharPref("devtools.responsive.userAgent", "");
const width =
Services.prefs.getIntPref("devtools.responsive.viewport.width", 0);
let reloadNeeded = false;
const viewportOrientation = this.getInitialViewportOrientation({ width, height });
await this.updateDPPX(pixelRatio);
await this.updateScreenOrientation(viewportOrientation, true);
if (touchSimulationEnabled) {
reloadNeeded |= await this.updateTouchSimulation(touchSimulationEnabled) &&
@ -791,6 +794,29 @@ ResponsiveUI.prototype = {
return reloadNeeded;
},
/**
* Sets the screen orientation values of the simulated device.
*
* @param {Object} orientation
* The orientation to update the current device screen to.
* @param {Boolean} changeDevice
* Whether or not the reason for updating the screen orientation is a result
* of actually rotating the device via the RDM toolbar or if the user switched to
* another device.
*/
async updateScreenOrientation(orientation, changeDevice = false) {
const targetFront = await this.client.mainRoot.getTab();
const simulateOrientationChangeSupported =
await targetFront.actorHasMethod("emulation", "simulateScreenOrientationChange");
// Ensure that simulateScreenOrientationChange is supported.
if (simulateOrientationChangeSupported) {
const { type, angle } = orientation;
await this.emulationFront.simulateScreenOrientationChange(type, angle,
changeDevice);
}
},
/**
* Helper for tests. Assumes a single viewport for now.
*/
@ -820,6 +846,12 @@ ResponsiveUI.prototype = {
return this.getViewportBrowser().messageManager;
},
/**
* Helper for getting the initial viewport orientation.
*/
getInitialViewportOrientation(viewport) {
return getOrientation(viewport, viewport);
},
};
EventEmitter.decorate(ResponsiveUI.prototype);

View File

@ -10,6 +10,7 @@ const {
ADD_VIEWPORT,
CHANGE_DEVICE,
CHANGE_PIXEL_RATIO,
CHANGE_VIEWPORT_ANGLE,
EDIT_DEVICE,
REMOVE_DEVICE_ASSOCIATION,
RESIZE_VIEWPORT,
@ -19,12 +20,14 @@ const {
const VIEWPORT_WIDTH_PREF = "devtools.responsive.viewport.width";
const VIEWPORT_HEIGHT_PREF = "devtools.responsive.viewport.height";
const VIEWPORT_PIXEL_RATIO_PREF = "devtools.responsive.viewport.pixelRatio";
const VIEWPORT_ANGLE_PREF = "devtools.responsive.viewport.angle";
let nextViewportId = 0;
const INITIAL_VIEWPORTS = [];
const INITIAL_VIEWPORT = {
id: nextViewportId++,
angle: Services.prefs.getIntPref(VIEWPORT_ANGLE_PREF, 0),
device: "",
deviceType: "",
height: Services.prefs.getIntPref(VIEWPORT_HEIGHT_PREF, 480),
@ -79,6 +82,21 @@ const reducers = {
});
},
[CHANGE_VIEWPORT_ANGLE](viewports, { id, angle }) {
return viewports.map(viewport => {
if (viewport.id !== id) {
return viewport;
}
Services.prefs.setIntPref(VIEWPORT_ANGLE_PREF, angle);
return {
...viewport,
angle,
};
});
},
[EDIT_DEVICE](viewports, { viewport, newDevice, deviceType }) {
if (!viewport) {
return viewports;

View File

@ -9,13 +9,24 @@ const TEST_URL = "data:text/html;charset=utf-8,";
addRDMTask(TEST_URL, async function({ ui }) {
info("Rotate viewport to trigger 'orientationchange' event.");
await pushPref("devtools.responsive.viewport.angle", 0);
rotateViewport(ui);
await ContentTask.spawn(ui.getViewportBrowser(), {},
async function() {
info("Check the original orientation values before the orientationchange");
is(content.screen.orientation.type, "portrait-primary",
"Primary orientation type is portrait-primary.");
is(content.screen.orientation.angle, 0,
"Original angle is set at 0 degrees");
const orientationChange = new Promise(resolve => {
content.window.addEventListener("orientationchange", () => {
ok(true, "'orientationchange' event fired");
is(content.screen.orientation.type, "landscape-primary",
"Orientation state was updated to landscape-primary");
is(content.screen.orientation.angle, 270,
"Orientation angle was updated to 270 degrees.");
resolve();
});
});

View File

@ -10,5 +10,6 @@ DevToolsModules(
'l10n.js',
'message.js',
'notification.js',
'orientation.js',
'window.js',
)

View File

@ -0,0 +1,75 @@
/* 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 { PORTRAIT_PRIMARY, LANDSCAPE_PRIMARY } = require("../constants");
/**
* Helper that gets the screen orientation of the device displayed in the RDM viewport.
* This function take in both a device and viewport object and an optional rotated angle.
* If a rotated angle is passed, then we calculate what the orientation type of the device
* would be in relation to its current orientation. Otherwise, return the current
* orientation and angle.
*
* @param {Object} device
* The device whose content is displayed in the viewport. Used to determine the
* primary orientation.
* @param {Object} viewport
* The viewport displaying device content. Used to determine the current
* orientation type of the device while in RDM.
* @param {Number|null} angleToRotateTo
* Optional. The rotated angle specifies the degree to which the device WILL be
* turned to. If undefined, then only return the current orientation and angle
* of the device.
* @return {Object} the orientation of the device.
*/
function getOrientation(device, viewport, angleToRotateTo = null) {
const { width: deviceWidth, height: deviceHeight } = device;
const { width: viewportWidth, height: viewportHeight } = viewport;
// Determine the primary orientation of the device screen.
const primaryOrientation = deviceHeight >= deviceWidth ?
PORTRAIT_PRIMARY :
LANDSCAPE_PRIMARY;
// Determine the current orientation of the device screen.
const currentOrientation = viewportHeight >= viewportWidth ?
PORTRAIT_PRIMARY :
LANDSCAPE_PRIMARY;
// Calculate the orientation angle of the device.
let angle;
if (typeof angleToRotateTo === "number") {
angle = angleToRotateTo;
} else if (currentOrientation !== primaryOrientation) {
angle = 270;
} else {
angle = 0;
}
// Calculate the orientation type of the device.
let orientationType = currentOrientation;
// If the viewport orientation is different from the primary orientation and the angle
// to rotate to is 0, then we are moving the device orientation back to its primary
// orientation.
if (currentOrientation !== primaryOrientation && angleToRotateTo === 0) {
orientationType = primaryOrientation;
} else if (angleToRotateTo === 90 || angleToRotateTo === 270) {
if (currentOrientation.includes("portrait")) {
orientationType = LANDSCAPE_PRIMARY;
} else if (currentOrientation.includes("landscape")) {
orientationType = PORTRAIT_PRIMARY;
}
}
return {
type: orientationType,
angle,
};
}
exports.getOrientation = getOrientation;

View File

@ -106,6 +106,7 @@ class Frame extends Component {
};
}
/* eslint-disable complexity */
render() {
let frame, isSourceMapped;
const {
@ -250,6 +251,7 @@ class Frame extends Component {
return dom.span(attributes, ...elements);
}
/* eslint-enable complexity */
}
module.exports = Frame;

View File

@ -553,6 +553,7 @@ class Tree extends Component {
*
* @param {Event} e
*/
/* eslint-disable complexity */
_onKeyDown(e) {
if (this.props.focused == null) {
return;
@ -624,6 +625,7 @@ class Tree extends Component {
break;
}
}
/* eslint-enable complexity */
get activeElement() {
return this.refs.tree.ownerDocument.activeElement;

View File

@ -199,6 +199,7 @@ class SplitBox extends Component {
// Rendering
/* eslint-disable complexity */
render() {
const { endPanelControl, splitterSize, vert } = this.state;
const { startPanel, endPanel, minSize, maxSize } = this.props;
@ -290,6 +291,7 @@ class SplitBox extends Component {
)
);
}
/* eslint-enable complexity */
}
module.exports = SplitBox;

View File

@ -270,6 +270,7 @@ define(function(require, exports, module) {
// Event Handlers
/* eslint-disable complexity */
onKeyDown(event) {
if (!SUPPORTED_KEYS.includes(event.key)) {
return;
@ -352,6 +353,7 @@ define(function(require, exports, module) {
this.treeRef.current.focus();
event.preventDefault();
}
/* eslint-enable complexity */
onClickRow(nodePath, event) {
const onClickRow = this.props.onClickRow;

View File

@ -48,6 +48,7 @@ function naturalSortCaseInsensitive(a, b) {
* @param {Boolean} insensitive
* Should the search be case insensitive?
*/
/* eslint-disable complexity */
function naturalSort(a, b, insensitive) {
// convert all to strings strip whitespace
const i = function(s) {
@ -104,3 +105,4 @@ function naturalSort(a, b, insensitive) {
}
return null;
}
/* eslint-enable complexity */

View File

@ -654,6 +654,7 @@ OutputParser.prototype = {
* The node to which spans containing points are added.
* @returns {Node} The container to which spans have been added.
*/
/* eslint-disable complexity */
_addPolygonPointNodes: function(coords, container) {
const tokenStream = getCSSLexer(coords);
let token = tokenStream.nextToken();
@ -758,6 +759,7 @@ OutputParser.prototype = {
}
return container;
},
/* eslint-enable complexity */
/**
* Parse the given circle coordinates and populate the given container appropriately
@ -769,6 +771,7 @@ OutputParser.prototype = {
* The node to which the definition is added.
* @returns {Node} The container to which the definition has been added.
*/
/* eslint-disable complexity */
_addCirclePointNodes: function(coords, container) {
const tokenStream = getCSSLexer(coords);
let token = tokenStream.nextToken();
@ -874,6 +877,7 @@ OutputParser.prototype = {
}
return container;
},
/* eslint-enable complexity */
/**
* Parse the given ellipse coordinates and populate the given container appropriately
@ -885,6 +889,7 @@ OutputParser.prototype = {
* The node to which the definition is added.
* @returns {Node} The container to which the definition has been added.
*/
/* eslint-disable complexity */
_addEllipsePointNodes: function(coords, container) {
const tokenStream = getCSSLexer(coords);
let token = tokenStream.nextToken();
@ -1000,6 +1005,7 @@ OutputParser.prototype = {
}
return container;
},
/* eslint-enable complexity */
/**
* Parse the given inset coordinates and populate the given container appropriately.
@ -1010,6 +1016,7 @@ OutputParser.prototype = {
* The node to which the definition is added.
* @returns {Node} The container to which the definition has been added.
*/
/* eslint-disable complexity */
_addInsetPointNodes: function(coords, container) {
const insetPoints = ["top", "right", "bottom", "left"];
const tokenStream = getCSSLexer(coords);
@ -1123,6 +1130,7 @@ OutputParser.prototype = {
return container;
},
/* eslint-enable complexity */
/**
* Append a angle value to the output

View File

@ -270,6 +270,7 @@ function isContentScheme(location, i = 0) {
}
}
/* eslint-disable complexity */
function isChromeScheme(location, i = 0) {
const firstChar = location.charCodeAt(i);
@ -315,6 +316,7 @@ function isChromeScheme(location, i = 0) {
return false;
}
}
/* eslint-enable complexity */
function isWASM(location, i = 0) {
return (

View File

@ -671,6 +671,7 @@ class Telemetry {
* The ID of the tool that has been opened.
*
*/
/* eslint-disable complexity */
function getChartsFromToolId(id) {
if (!id) {
return null;
@ -750,6 +751,7 @@ function getChartsFromToolId(id) {
countScalar: countScalar,
};
}
/* eslint-enable complexity */
/**
* Displays the first caller and calling line outside of this file in the

View File

@ -799,6 +799,7 @@ VariablesView.prototype = {
/**
* Listener handling a key down event on the view.
*/
/* eslint-disable complexity */
_onViewKeyDown: function(e) {
const item = this.getFocusedItem();
@ -889,6 +890,7 @@ VariablesView.prototype = {
item._onAddProperty(e);
}
},
/* eslint-enable complexity */
/**
* Sets the text displayed in this container when there are no available items.
@ -2793,6 +2795,7 @@ Variable.prototype = extend(Scope.prototype, {
* and specifies if it's a 'this', '<exception>', '<return>' or '__proto__'
* reference.
*/
/* eslint-disable complexity */
_setAttributes: function() {
const ownerView = this.ownerView;
if (ownerView.preventDescriptorModifiers) {
@ -2850,6 +2853,7 @@ Variable.prototype = extend(Scope.prototype, {
target.setAttribute("pseudo-item", "");
}
},
/* eslint-enable complexity */
/**
* Adds the necessary event listeners for this variable.

View File

@ -506,6 +506,7 @@ class JSTerm extends Component {
* @param {Object} response
* The message received from the server.
*/
/* eslint-disable complexity */
async _executeResultCallback(response) {
if (!this.webConsoleUI) {
return null;
@ -578,6 +579,7 @@ class JSTerm extends Component {
return null;
}
/* eslint-enable complexity */
screenshotNotify(results) {
const wrappedResults = results.map(message => ({ message, type: "logMessage" }));

View File

@ -157,6 +157,7 @@ class Message extends Component {
});
}
/* eslint-disable complexity */
render() {
const {
open,
@ -346,6 +347,7 @@ class Message extends Component {
attachment ? null : dom.br(),
);
}
/* eslint-enable complexity */
}
module.exports = Message;

View File

@ -68,6 +68,7 @@ class ReverseSearchInput extends Component {
}
}
/* eslint-disable complexity */
onInputKeyDown(event) {
const {
keyCode,
@ -127,6 +128,7 @@ class ReverseSearchInput extends Component {
}
}
}
/* eslint-enable complexity */
renderSearchInformation() {
const {

View File

@ -105,6 +105,7 @@ function cloneState(state) {
* @param {UiState} uiState: The ui state.
* @returns {MessageState} a new messages state.
*/
/* eslint-disable complexity */
function addMessage(newMessage, state, filtersState, prefsState, uiState) {
const {
messagesById,
@ -274,7 +275,9 @@ function addMessage(newMessage, state, filtersState, prefsState, uiState) {
return state;
}
/* eslint-enable complexity */
/* eslint-disable complexity */
function messages(state = MessageState(), action, filtersState, prefsState, uiState) {
const {
messagesById,
@ -541,6 +544,7 @@ function messages(state = MessageState(), action, filtersState, prefsState, uiSt
return state;
}
/* eslint-enable complexity */
/**
* Returns the new current group id given the previous current group and the groupsById
@ -784,6 +788,7 @@ function getToplevelMessageCount(state) {
* - visible {Boolean}: true if the message should be visible
* - cause {String}: if visible is false, what causes the message to be hidden.
*/
/* eslint-disable complexity */
function getMessageVisibility(message, {
messagesState,
filtersState,
@ -954,6 +959,7 @@ function getMessageVisibility(message, {
visible: true,
};
}
/* eslint-enable complexity */
function isUnfilterable(message) {
return [

View File

@ -75,6 +75,7 @@ global.ChromeUtils = {
// Point to vendored-in files and mocks when needed.
const requireHacker = require("require-hacker");
/* eslint-disable complexity */
requireHacker.global_hook("default", (path, module) => {
switch (path) {
// For Enzyme
@ -138,6 +139,7 @@ requireHacker.global_hook("default", (path, module) => {
return undefined;
});
/* eslint-enable complexity */
// Configure enzyme with React 16 adapter. This needs to be done after we set the
// requireHack hook so `require()` calls in Enzyme are handled as well.

View File

@ -67,6 +67,7 @@ function transformPacket(packet) {
}
}
/* eslint-disable complexity */
function transformConsoleAPICallPacket(packet) {
const { message } = packet;
@ -198,6 +199,7 @@ function transformConsoleAPICallPacket(packet) {
chromeContext: message.chromeContext,
});
}
/* eslint-enable complexity */
function transformNavigationMessagePacket(packet) {
const { url } = packet;

View File

@ -846,7 +846,7 @@ var UI = {
return this.toolboxPromise;
}
const iframe = document.createElement("iframe");
const iframe = document.createXULElement("iframe");
iframe.id = "toolbox";
// Compute a uid on the iframe in order to identify toolbox iframe

View File

@ -505,6 +505,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* @param {Ci.nsIAccessibleEvent} subject
* accessible event object.
*/
/* eslint-disable complexity */
observe(subject) {
const event = subject.QueryInterface(Ci.nsIAccessibleEvent);
const rawAccessible = event.accessible;
@ -600,6 +601,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
break;
}
},
/* eslint-enable complexity */
/**
* Ensure that nothing interferes with the audit for an accessible object

View File

@ -463,6 +463,7 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
* it is called over the remote debugging protocol the target window is always
* `targetActor.window`.
*/
/* eslint-disable complexity */
eval(callerInfo, expression, options, customTargetWindow) {
const window = customTargetWindow || this.window;
options = options || {};
@ -639,6 +640,7 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
return {value: evalResult};
},
/* eslint-enable complexity */
}
);

View File

@ -76,6 +76,10 @@ const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
return this._touchSimulator;
},
get win() {
return this.docShell.chromeEventHandler.ownerGlobal;
},
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
@ -352,17 +356,38 @@ const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
this.targetActor.docShell.contentViewer.stopEmulatingMedium();
},
setScreenOrientation(type, angle) {
if (this.win.screen.orientation.angle !== angle ||
this.win.screen.orientation.type !== type) {
this.win.document.setRDMPaneOrientation(type, angle);
}
},
/**
* Simulates the "orientationchange" event when device screen is rotated.
*
* TODO: Update `window.screen.orientation` and `window.screen.angle` here.
* See Bug 1357774.
* @param {String} type
* The orientation type of the rotated device.
* @param {Number} angle
* The rotated angle of the device.
* @param {Boolean} deviceChange
* Whether or not screen orientation change is a result of changing the device
* or rotating the current device. If the latter, then dispatch the
* "orientationchange" event on the content window.
*/
simulateScreenOrientationChange() {
const win = this.docShell.chromeEventHandler.ownerGlobal;
const { CustomEvent } = win;
async simulateScreenOrientationChange(type, angle, deviceChange) {
// Don't dispatch the "orientationchange" event if orientation change is a result
// of switching to a new device.
if (deviceChange) {
this.setScreenOrientation(type, angle);
return;
}
const { CustomEvent } = this.win;
const orientationChangeEvent = new CustomEvent("orientationchange");
win.dispatchEvent(orientationChangeEvent);
this.setScreenOrientation(type, angle);
this.win.dispatchEvent(orientationChangeEvent);
},
});

View File

@ -88,6 +88,7 @@ TouchSimulator.prototype = {
this._isPicking = state;
},
/* eslint-disable complexity */
handleEvent(evt) {
// Bail out if devtools is in pick mode in the same tab.
if (this._isPicking) {
@ -242,6 +243,7 @@ TouchSimulator.prototype = {
evt.stopImmediatePropagation();
}
},
/* eslint-enable complexity */
fireMouseEvent(type, evt) {
const content = this.getContent(evt.target);

View File

@ -550,6 +550,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
/**
* Clear the whole alignment container along the main axis for each flex item.
*/
/* eslint-disable complexity */
renderJustifyContent() {
if (!this.flexData || !this.currentQuads.content || !this.currentQuads.content[0]) {
return;
@ -630,6 +631,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.restore();
}
/* eslint-enable complexity */
/**
* Set up the canvas with the given options prior to drawing.
@ -824,6 +826,7 @@ function getRectFromFlexItemValues(item, container) {
* The new Flex data object.
* @return {Boolean} true if the flex data has changed and false otherwise.
*/
/* eslint-disable complexity */
function compareFlexData(oldFlexData, newFlexData) {
if (!oldFlexData || !newFlexData) {
return true;
@ -884,5 +887,6 @@ function compareFlexData(oldFlexData, newFlexData) {
return false;
}
/* eslint-enable complexity */
exports.FlexboxHighlighter = FlexboxHighlighter;

View File

@ -478,6 +478,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
this.viewport = { left, right, top, bottom, padding };
}
/* eslint-disable complexity */
handleEvent(event, id) {
// No event handling if the highlighter is hidden
if (this.areShapesHidden()) {
@ -577,6 +578,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
break;
}
}
/* eslint-enable complexity */
/**
* Handle a mouse click in transform mode.
@ -1704,6 +1706,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
* @returns {String} "top", "left", "right", or "bottom" if any of those edges were
* clicked. "" if none were clicked.
*/
/* eslint-disable complexity */
getInsetPointAt(pageX, pageY) {
const { top, left, right, bottom } = this.coordinates;
const zoom = getCurrentZoom(this.win);
@ -1741,6 +1744,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
return "";
}
/* eslint-enable complexity */
/**
* Parses the CSS definition given and returns the shape type associated

View File

@ -385,6 +385,7 @@ class DOMEventCollector extends MainEventCollector {
* Get or detect jQuery events.
*/
class JQueryEventCollector extends MainEventCollector {
/* eslint-disable complexity */
getListeners(node, {checkOnly} = {}) {
const jQuery = this.getJQuery(node);
const handlers = [];
@ -471,12 +472,14 @@ class JQueryEventCollector extends MainEventCollector {
}
return handlers;
}
/* eslint-enable complexity */
}
/**
* Get or detect jQuery live events.
*/
class JQueryLiveEventCollector extends MainEventCollector {
/* eslint-disable complexity */
getListeners(node, {checkOnly} = {}) {
const jQuery = this.getJQuery(node);
const handlers = [];
@ -569,6 +572,7 @@ class JQueryLiveEventCollector extends MainEventCollector {
}
return handlers;
}
/* eslint-enable complexity */
normalizeListener(handlerDO) {
function isFunctionInProxy(funcDO) {
@ -866,6 +870,7 @@ class EventCollector {
* native: false
* }
*/
/* eslint-disable complexity */
processHandlerForEvent(listenerArray, listener, dbg) {
let globalDO;
@ -1013,6 +1018,7 @@ class EventCollector {
}
}
}
/* eslint-enable complexity */
}
exports.EventCollector = EventCollector;

View File

@ -728,6 +728,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
* hasLast: true if the last child of the node is included in the list.
* nodes: Array of DOMNodes.
*/
/* eslint-disable complexity */
_getChildren: function(node, options = {}) {
if (isNodeDead(node)) {
return { hasFirst: true, hasLast: true, nodes: [] };
@ -901,6 +902,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
return { hasFirst, hasLast, nodes };
},
/* eslint-enable complexity */
getNativeAnonymousChildren: function(rawNode) {
// Get an anonymous walker and start on the first child.
@ -1093,6 +1095,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
* @param string selectorState
* One of "pseudo", "id", "tag", "class", "null"
*/
/* eslint-disable complexity */
getSuggestionsForQuery: function(query, completing, selectorState) {
const sugs = {
classes: new Map(),
@ -1235,6 +1238,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
suggestions: result,
};
},
/* eslint-enable complexity */
/**
* Add a pseudo-class lock to a node.

View File

@ -329,6 +329,7 @@ const proto = {
* An object that maps property names to safe getter descriptors as
* defined by the remote debugging protocol.
*/
/* eslint-disable complexity */
_findSafeGetterValues: function(ownProperties, limit = 0) {
const safeGetterValues = Object.create(null);
let obj = this.obj;
@ -432,6 +433,7 @@ const proto = {
return safeGetterValues;
},
/* eslint-enable complexity */
/**
* Find the safe getters for a given Debugger.Object. Safe getters are native

View File

@ -355,6 +355,7 @@ function wrappedPrimitivePreviewer(className, classObj, objectActor, grip, rawOb
return true;
}
/* eslint-disable complexity */
function GenericObject(objectActor, grip, rawObj, specialStringBehavior = false) {
const {obj, hooks} = objectActor;
if (grip.preview || grip.displayString || hooks.getGripDepth() > 1) {
@ -442,6 +443,7 @@ function GenericObject(objectActor, grip, rawObj, specialStringBehavior = false)
return true;
}
/* eslint-enable complexity */
// Preview functions that do not rely on the object class.
previewers.Object = [
@ -672,6 +674,7 @@ previewers.Object = [
return true;
},
/* eslint-disable complexity */
function DOMEvent({obj, hooks}, grip, rawObj) {
if (isWorker || !rawObj || !Event.isInstance(rawObj)) {
return false;
@ -758,6 +761,7 @@ previewers.Object = [
return true;
},
/* eslint-enable complexity */
function DOMException({obj, hooks}, grip, rawObj) {
if (isWorker || !rawObj || obj.class !== "DOMException") {

View File

@ -835,6 +835,7 @@ var cookieHelpers = {
* }
* }
*/
/* eslint-disable complexity */
editCookie(data) {
let {field, oldValue, newValue} = data;
const origName = field === "name" ? oldValue : data.items.name;
@ -920,6 +921,7 @@ var cookieHelpers = {
cookie.sameSite
);
},
/* eslint-enable complexity */
_removeCookies(host, opts = {}) {
// We use a uniqueId to emulate compound keys for cookies. We need to
@ -2775,6 +2777,7 @@ const StorageActor = protocol.ActorClassWithSpec(specs.storageSpec, {
* Pass an empty array if the host itself was affected: either completely
* removed or cleared.
*/
/* eslint-disable complexity */
update(action, storeType, data) {
if (action == "cleared") {
this.emit("stores-cleared", { [storeType]: data });
@ -2839,6 +2842,7 @@ const StorageActor = protocol.ActorClassWithSpec(specs.storageSpec, {
return null;
},
/* eslint-enable complexity */
/**
* This method removes data from the this.boundUpdate object in the same

View File

@ -534,6 +534,7 @@ WebConsoleActor.prototype =
* @return object
* The response object which holds the startedListeners array.
*/
/* eslint-disable complexity */
startListeners: async function(request) {
const startedListeners = [];
const window = !this.parentActor.isRootActor ? this.window : null;
@ -692,6 +693,7 @@ WebConsoleActor.prototype =
traits: this.traits,
};
},
/* eslint-enable complexity */
/**
* Handler for the "stopListeners" request.
@ -985,6 +987,7 @@ WebConsoleActor.prototype =
* @return object
* The evaluation response packet.
*/
/* eslint-disable complexity */
evaluateJS: function(request) {
const input = request.text;
const timestamp = Date.now();
@ -1154,6 +1157,7 @@ WebConsoleActor.prototype =
notes: errorNotes,
};
},
/* eslint-enable complexity */
/**
* The Autocomplete request handler.

View File

@ -10,7 +10,7 @@
// this file violates some naming conventions and consequently locally
// disables some eslint rules.
/* eslint-disable camelcase, mozilla/no-aArgs, no-else-return */
/* eslint-disable camelcase, mozilla/no-aArgs, no-else-return, complexity */
"use strict";

View File

@ -539,6 +539,7 @@ function parseNamedDeclarations(isCssPropertyKnown, inputString,
* @return {Array} an array of objects with the following signature:
* [{ "value": string, "type": integer }, ...]
*/
/* eslint-disable complexity */
function parsePseudoClassesAndAttributes(value) {
if (!value) {
throw new Error("empty input string");
@ -624,6 +625,7 @@ function parsePseudoClassesAndAttributes(value) {
return result;
}
/* eslint-enable complexity */
/**
* Expects a single CSS value to be passed as the input and parses the value

View File

@ -258,6 +258,7 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
* Get any unprocessed mutation records and process them.
*/
getMutations(options = {}) {
/* eslint-disable complexity */
return super.getMutations(options).then(mutations => {
const emitMutations = [];
for (const change of mutations) {
@ -401,6 +402,7 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
this.emit("mutations", emitMutations);
});
/* eslint-enable complexity */
}
/**

View File

@ -180,6 +180,7 @@ function getLineCountInComments(text) {
* @param string text The CSS source to prettify.
* @return string Prettified CSS source
*/
/* eslint-disable complexity */
function prettifyCSS(text, ruleCount) {
if (prettifyCSS.LINE_SEPARATOR == null) {
const os = Services.appinfo.OS;
@ -405,6 +406,7 @@ function prettifyCSS(text, ruleCount) {
return result;
}
/* eslint-enable complexity */
exports.prettifyCSS = prettifyCSS;

View File

@ -151,7 +151,11 @@ const emulationSpec = generateActorSpec({
},
simulateScreenOrientationChange: {
request: {},
request: {
orientation: Arg(0, "string"),
angle: Arg(1, "number"),
deviceChange: Arg(2, "boolean"),
},
response: {},
},
},

View File

@ -60,6 +60,7 @@ function hasArrayIndex(str) {
* element access (e.g. `x["match`).
* }
*/
/* eslint-disable complexity */
function analyzeInputString(str) {
const bodyStack = [];
@ -195,6 +196,7 @@ function analyzeInputString(str) {
return buildReturnObject();
}
/* eslint-enable complexity */
/**
* Provides a list of properties, that are possible matches based on the passed

View File

@ -45,7 +45,7 @@ JSObject* CSSPseudoElement::WrapObject(JSContext* aCx,
return CSSPseudoElement_Binding::Wrap(aCx, this, aGivenProto);
}
void CSSPseudoElement::GetAnimations(const AnimationFilter& filter,
void CSSPseudoElement::GetAnimations(const GetAnimationsOptions& aOptions,
nsTArray<RefPtr<Animation>>& aRetVal) {
Document* doc = mOriginatingElement->GetComposedDoc();
if (doc) {

View File

@ -54,7 +54,7 @@ class CSSPseudoElement final : public nsWrapperCache {
return retVal.forget();
}
void GetAnimations(const AnimationFilter& filter,
void GetAnimations(const GetAnimationsOptions& aOptions,
nsTArray<RefPtr<Animation>>& aRetVal);
already_AddRefed<Animation> Animate(
JSContext* aContext, JS::Handle<JSObject*> aKeyframes,

View File

@ -1238,8 +1238,8 @@ Document::Document(const char* aContentType)
mMaybeServiceWorkerControlled(false),
mAllowZoom(false),
mValidScaleFloat(false),
mValidMinScale(false),
mValidMaxScale(false),
mScaleStrEmpty(false),
mWidthStrEmpty(false),
mParserAborted(false),
mReportedUseCounters(false),
@ -3443,9 +3443,9 @@ void Document::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations) {
if (!root) {
return;
}
AnimationFilter filter;
filter.mSubtree = true;
root->GetAnimations(filter, aAnimations);
GetAnimationsOptions options;
options.mSubtree = true;
root->GetAnimations(options, aAnimations);
}
SVGSVGElement* Document::GetSVGRootElement() const {
@ -5523,6 +5523,17 @@ already_AddRefed<Element> Document::CreateElement(
return nullptr;
}
// Temporary check until XULDocument has been removed.
if (IsXULDocument()) {
#if DEBUG
xpc_DumpJSStack(true, true, false);
#endif
MOZ_DIAGNOSTIC_ASSERT(false,
"CreateElement() not allowed in XUL document.");
rv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
bool needsLowercase = IsHTMLDocument() && !IsLowercaseASCII(aTagName);
nsAutoString lcTagName;
if (needsLowercase) {
@ -6832,9 +6843,73 @@ nsINode* Document::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv) {
bool Document::UseWidthDeviceWidthFallbackViewport() const { return false; }
void Document::ParseWidthAndHeightInMetaViewport(
const nsAString& aWidthString, const nsAString& aHeightString,
const nsAString& aScaleString) {
static Maybe<LayoutDeviceToScreenScale> ParseScaleString(
const nsString& aScaleString) {
// https://drafts.csswg.org/css-device-adapt/#min-scale-max-scale
if (aScaleString.EqualsLiteral("device-width") ||
aScaleString.EqualsLiteral("device-height")) {
return Some(LayoutDeviceToScreenScale(10.0f));
} else if (aScaleString.EqualsLiteral("yes")) {
return Some(LayoutDeviceToScreenScale(1.0f));
} else if (aScaleString.EqualsLiteral("no")) {
return Some(LayoutDeviceToScreenScale(kViewportMinScale));
} else if (aScaleString.IsEmpty()) {
return Nothing();
}
nsresult scaleErrorCode;
float scale = aScaleString.ToFloat(&scaleErrorCode);
if (NS_FAILED(scaleErrorCode)) {
return Some(LayoutDeviceToScreenScale(kViewportMinScale));
}
if (scale < 0) {
return Nothing();
}
return Some(clamped(LayoutDeviceToScreenScale(scale), kViewportMinScale,
kViewportMaxScale));
}
Maybe<LayoutDeviceToScreenScale> Document::ParseScaleInHeader(
nsAtom* aHeaderField) {
MOZ_ASSERT(aHeaderField == nsGkAtoms::viewport_initial_scale ||
aHeaderField == nsGkAtoms::viewport_maximum_scale ||
aHeaderField == nsGkAtoms::viewport_minimum_scale);
nsAutoString scaleStr;
GetHeaderData(aHeaderField, scaleStr);
return ParseScaleString(scaleStr);
}
void Document::ParseScalesInMetaViewport() {
Maybe<LayoutDeviceToScreenScale> scale;
scale = ParseScaleInHeader(nsGkAtoms::viewport_initial_scale);
mScaleFloat = scale.valueOr(LayoutDeviceToScreenScale(0.0f));
mValidScaleFloat = scale.isSome();
scale = ParseScaleInHeader(nsGkAtoms::viewport_maximum_scale);
// Chrome uses '5' for the fallback value of maximum-scale, we might
// consider matching it in future.
// https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/html_meta_element.cc?l=452&rcl=65ca4278b42d269ca738fc93ef7ae04a032afeb0
mScaleMaxFloat = scale.valueOr(kViewportMaxScale);
mValidMaxScale = scale.isSome();
scale = ParseScaleInHeader(nsGkAtoms::viewport_minimum_scale);
mScaleMinFloat = scale.valueOr(kViewportMinScale);
mValidMinScale = scale.isSome();
// Resolve min-zoom and max-zoom values.
// https://drafts.csswg.org/css-device-adapt/#constraining-min-max-zoom
if (mValidMaxScale && mValidMinScale) {
mScaleMaxFloat = std::max(mScaleMinFloat, mScaleMaxFloat);
}
}
void Document::ParseWidthAndHeightInMetaViewport(const nsAString& aWidthString,
const nsAString& aHeightString,
bool aHasValidScale) {
// The width and height properties
// https://drafts.csswg.org/css-device-adapt/#width-and-height-properties
//
@ -6865,8 +6940,7 @@ void Document::ParseWidthAndHeightInMetaViewport(
mMaxWidth = nsViewportInfo::Auto;
}
}
// FIXME: Check the scale is not 'auto' once we support auto value for it.
} else if (!aScaleString.IsEmpty()) {
} else if (aHasValidScale) {
if (aHeightString.IsEmpty()) {
mMinWidth = nsViewportInfo::ExtendToZoom;
mMaxWidth = nsViewportInfo::ExtendToZoom;
@ -6974,48 +7048,8 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
}
}
nsAutoString minScaleStr;
GetHeaderData(nsGkAtoms::viewport_minimum_scale, minScaleStr);
nsresult scaleMinErrorCode;
mScaleMinFloat =
LayoutDeviceToScreenScale(minScaleStr.ToFloat(&scaleMinErrorCode));
if (NS_FAILED(scaleMinErrorCode)) {
mScaleMinFloat = kViewportMinScale;
}
mScaleMinFloat = mozilla::clamped(mScaleMinFloat, kViewportMinScale,
kViewportMaxScale);
nsAutoString maxScaleStr;
GetHeaderData(nsGkAtoms::viewport_maximum_scale, maxScaleStr);
// We define a special error code variable for the scale and max scale,
// because they are used later (see the width calculations).
nsresult scaleMaxErrorCode;
mScaleMaxFloat =
LayoutDeviceToScreenScale(maxScaleStr.ToFloat(&scaleMaxErrorCode));
if (NS_FAILED(scaleMaxErrorCode)) {
mScaleMaxFloat = kViewportMaxScale;
}
// Resolve min-zoom and max-zoom values.
// https://drafts.csswg.org/css-device-adapt/#constraining-min-max-zoom
if (NS_SUCCEEDED(scaleMaxErrorCode) && NS_SUCCEEDED(scaleMinErrorCode)) {
mScaleMaxFloat = std::max(mScaleMinFloat, mScaleMaxFloat);
}
mScaleMaxFloat = mozilla::clamped(mScaleMaxFloat, kViewportMinScale,
kViewportMaxScale);
nsAutoString scaleStr;
GetHeaderData(nsGkAtoms::viewport_initial_scale, scaleStr);
nsresult scaleErrorCode;
mScaleFloat =
LayoutDeviceToScreenScale(scaleStr.ToFloat(&scaleErrorCode));
// Parse initial-scale, minimum-scale and maximum-scale.
ParseScalesInMetaViewport();
nsAutoString widthStr, heightStr;
@ -7024,7 +7058,7 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
// Parse width and height properties
// This function sets m{Min,Max}{Width,Height}.
ParseWidthAndHeightInMetaViewport(widthStr, heightStr, scaleStr);
ParseWidthAndHeightInMetaViewport(widthStr, heightStr, mValidScaleFloat);
mAllowZoom = true;
nsAutoString userScalable;
@ -7036,11 +7070,7 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
mAllowZoom = false;
}
mScaleStrEmpty = scaleStr.IsEmpty();
mWidthStrEmpty = widthStr.IsEmpty();
mValidScaleFloat = !scaleStr.IsEmpty() && NS_SUCCEEDED(scaleErrorCode);
mValidMaxScale =
!maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode);
mViewportType = viewportIsEmpty ? Empty : Specified;
MOZ_FALLTHROUGH;
@ -7224,7 +7254,7 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
// Also recalculate the default zoom, if it wasn't specified in the
// metadata, and the width is specified.
if (mScaleStrEmpty && !mWidthStrEmpty) {
if (!mValidScaleFloat && !mWidthStrEmpty) {
CSSToScreenScale bestFitScale(float(aDisplaySize.width) / size.width);
scaleFloat = (scaleFloat > bestFitScale) ? scaleFloat : bestFitScale;
}

View File

@ -3687,7 +3687,15 @@ class Document : public nsINode,
void ParseWidthAndHeightInMetaViewport(const nsAString& aWidthString,
const nsAString& aHeightString,
const nsAString& aScaleString);
bool aIsAutoScale);
// Parse scale values in viewport meta tag for a given |aHeaderField| which
// represents the scale property and returns the scale value if it's valid.
Maybe<LayoutDeviceToScreenScale> ParseScaleInHeader(nsAtom* aHeaderField);
// Parse scale values in viewport meta tag and set the values in
// mScaleMinFloat, mScaleMaxFloat and mScaleFloat respectively.
void ParseScalesInMetaViewport();
FlashClassification DocumentFlashClassificationInternal();
@ -4321,8 +4329,8 @@ class Document : public nsINode,
// have to recalculate it each time.
bool mAllowZoom : 1;
bool mValidScaleFloat : 1;
bool mValidMinScale : 1;
bool mValidMaxScale : 1;
bool mScaleStrEmpty : 1;
bool mWidthStrEmpty : 1;
// Parser aborted. True if the parser of this document was forcibly

View File

@ -3474,7 +3474,7 @@ already_AddRefed<Animation> Element::Animate(
return animation.forget();
}
void Element::GetAnimations(const AnimationFilter& filter,
void Element::GetAnimations(const GetAnimationsOptions& aOptions,
nsTArray<RefPtr<Animation>>& aAnimations) {
Document* doc = GetComposedDoc();
if (doc) {
@ -3505,7 +3505,7 @@ void Element::GetAnimations(const AnimationFilter& filter,
return;
}
if (!filter.mSubtree || pseudoType == PseudoStyleType::before ||
if (!aOptions.mSubtree || pseudoType == PseudoStyleType::before ||
pseudoType == PseudoStyleType::after ||
pseudoType == PseudoStyleType::marker) {
GetAnimationsUnsorted(elem, pseudoType, aAnimations);

View File

@ -84,7 +84,7 @@ namespace css {
struct URLValue;
} // namespace css
namespace dom {
struct AnimationFilter;
struct GetAnimationsOptions;
struct ScrollIntoViewOptions;
struct ScrollToOptions;
class DOMIntersectionObserver;
@ -1339,7 +1339,7 @@ class Element : public FragmentOrElement {
// Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
// Callers must keep this element alive because flushing style may destroy
// this element.
void GetAnimations(const AnimationFilter& filter,
void GetAnimations(const GetAnimationsOptions& aOptions,
nsTArray<RefPtr<Animation>>& aAnimations);
static void GetAnimationsUnsorted(Element* aElement,
PseudoStyleType aPseudoType,

View File

@ -64,12 +64,13 @@ function declTest(name, cfg) {
// Run the provided test
info("browser ready");
await Promise.resolve(test(browser, win));
// Clean up after we're done.
ChromeUtils.unregisterWindowActor("Test");
await BrowserTestUtils.closeWindow(win);
info("Exiting test: " + name);
try {
await Promise.resolve(test(browser, win));
} finally {
// Clean up after we're done.
ChromeUtils.unregisterWindowActor("Test");
await BrowserTestUtils.closeWindow(win);
info("Exiting test: " + name);
}
});
}

View File

@ -69,18 +69,21 @@ static bool IsSameOriginWithAllParentDocs(nsINode* aDoc) {
already_AddRefed<Promise> MediaDevices::GetUserMedia(
const MediaStreamConstraints& aConstraints, CallerType aCallerType,
ErrorResult& aRv) {
if (Document* doc = GetOwner()->GetExtantDoc()) {
if (!GetOwner()->IsSecureContext()) {
doc->SetDocumentAndPageUseCounter(eUseCounter_custom_GetUserMediaInsec);
}
if (!IsSameOriginWithAllParentDocs(doc)) {
doc->SetDocumentAndPageUseCounter(eUseCounter_custom_GetUserMediaXOrigin);
}
Document* topDoc = doc->GetTopLevelContentDocument();
IgnoredErrorResult ignored;
if (topDoc && !topDoc->HasFocus(ignored)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_GetUserMediaUnfocused);
if (RefPtr<nsPIDOMWindowInner> owner = GetOwner()) {
if (Document* doc = owner->GetExtantDoc()) {
if (!owner->IsSecureContext()) {
doc->SetDocumentAndPageUseCounter(eUseCounter_custom_GetUserMediaInsec);
}
if (!IsSameOriginWithAllParentDocs(doc)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_GetUserMediaXOrigin);
}
Document* topDoc = doc->GetTopLevelContentDocument();
IgnoredErrorResult ignored;
if (topDoc && !topDoc->HasFocus(ignored)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_GetUserMediaUnfocused);
}
}
}
RefPtr<Promise> p = Promise::Create(GetParentObject(), aRv);
@ -112,16 +115,18 @@ already_AddRefed<Promise> MediaDevices::EnumerateDevices(CallerType aCallerType,
ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
if (Document* doc = GetOwner()->GetExtantDoc()) {
if (!GetOwner()->IsSecureContext()) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_EnumerateDevicesInsec);
}
Document* topDoc = doc->GetTopLevelContentDocument();
IgnoredErrorResult ignored;
if (topDoc && !topDoc->HasFocus(ignored)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_EnumerateDevicesUnfocused);
if (RefPtr<nsPIDOMWindowInner> owner = GetOwner()) {
if (Document* doc = owner->GetExtantDoc()) {
if (!owner->IsSecureContext()) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_EnumerateDevicesInsec);
}
Document* topDoc = doc->GetTopLevelContentDocument();
IgnoredErrorResult ignored;
if (topDoc && !topDoc->HasFocus(ignored)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_EnumerateDevicesUnfocused);
}
}
}
RefPtr<Promise> p = Promise::Create(GetParentObject(), aRv);
@ -172,10 +177,12 @@ already_AddRefed<Promise> MediaDevices::EnumerateDevices(CallerType aCallerType,
already_AddRefed<Promise> MediaDevices::GetDisplayMedia(
const DisplayMediaStreamConstraints& aConstraints, CallerType aCallerType,
ErrorResult& aRv) {
if (Document* doc = GetOwner()->GetExtantDoc()) {
if (!IsSameOriginWithAllParentDocs(doc)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_GetDisplayMediaXOrigin);
if (RefPtr<nsPIDOMWindowInner> owner = GetOwner()) {
if (Document* doc = owner->GetExtantDoc()) {
if (!IsSameOriginWithAllParentDocs(doc)) {
doc->SetDocumentAndPageUseCounter(
eUseCounter_custom_GetDisplayMediaXOrigin);
}
}
}
RefPtr<Promise> p = Promise::Create(GetParentObject(), aRv);

View File

@ -94,9 +94,21 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder(
RefPtr<RemoteAudioDecoderChild> child = new RemoteAudioDecoderChild();
MediaResult result(NS_OK);
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderModule::CreateAudioDecoder", [&, child]() {
// We can use child as a ref here because this is a sync dispatch. In
// the error case for InitIPDL, we can't just let the RefPtr go out of
// scope at the end of the method because it will release the
// RemoteAudioDecoderChild on the wrong thread. This will assert in
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
// allows us to release the RemoteAudioDecoderChild on the manager
// thread during this single dispatch.
RefPtr<Runnable> task =
NS_NewRunnableFunction("RemoteDecoderModule::CreateAudioDecoder", [&]() {
result = child->InitIPDL(aParams.AudioConfig(), aParams.mOptions);
if (NS_FAILED(result)) {
// Release RemoteAudioDecoderChild here, while we're on
// manager thread. Don't just let the RefPtr go out of scope.
child = nullptr;
}
});
SyncRunnable::DispatchToThread(mManagerThread, task);
@ -124,10 +136,22 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
RefPtr<RemoteVideoDecoderChild> child = new RemoteVideoDecoderChild();
MediaResult result(NS_OK);
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderModule::CreateVideoDecoder", [&, child]() {
// We can use child as a ref here because this is a sync dispatch. In
// the error case for InitIPDL, we can't just let the RefPtr go out of
// scope at the end of the method because it will release the
// RemoteVideoDecoderChild on the wrong thread. This will assert in
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
// allows us to release the RemoteVideoDecoderChild on the manager
// thread during this single dispatch.
RefPtr<Runnable> task =
NS_NewRunnableFunction("RemoteDecoderModule::CreateVideoDecoder", [&]() {
result = child->InitIPDL(aParams.VideoConfig(), aParams.mRate.mValue,
aParams.mOptions);
if (NS_FAILED(result)) {
// Release RemoteVideoDecoderChild here, while we're on
// manager thread. Don't just let the RefPtr go out of scope.
child = nullptr;
}
});
SyncRunnable::DispatchToThread(mManagerThread, task);

View File

@ -607,7 +607,26 @@ void VideoSink::MaybeResolveEndPromise() {
mFrameStats.NotifyPresentedFrame();
}
}
mEndPromiseHolder.ResolveIfExists(true, __func__);
TimeStamp nowTime;
const auto clockTime = mAudioSink->GetPosition(&nowTime);
if (clockTime < mVideoFrameEndTime) {
VSINK_LOG_V(
"Not reach video end time yet, reschedule timer to resolve "
"end promise. clockTime=%" PRId64 ", endTime=%" PRId64,
clockTime.ToMicroseconds(), mVideoFrameEndTime.ToMicroseconds());
int64_t delta = (mVideoFrameEndTime - clockTime).ToMicroseconds() /
mAudioSink->GetPlaybackParams().mPlaybackRate;
TimeStamp target = nowTime + TimeDuration::FromMicroseconds(delta);
auto resolveEndPromise = [self = RefPtr<VideoSink>(this)]() {
self->mEndPromiseHolder.ResolveIfExists(true, __func__);
self->mUpdateScheduler.CompleteRequest();
};
mUpdateScheduler.Ensure(target, std::move(resolveEndPromise),
std::move(resolveEndPromise));
} else {
mEndPromiseHolder.ResolveIfExists(true, __func__);
}
}
}

View File

@ -1214,24 +1214,6 @@ void SVGElement::UpdateContentDeclarationBlock() {
continue; // xml:lang has precedence
}
if (IsSVGElement(nsGkAtoms::svg)) {
// Special case: we don't want <svg> 'width'/'height' mapped into style
// if the attribute value isn't a valid <length> according to SVG (which
// only supports a subset of the CSS <length> values). We don't enforce
// this by checking the attribute value in SVGSVGElement::
// IsAttributeMapped since we don't want that method to depend on the
// value of the attribute that is being checked. Rather we just prevent
// the actual mapping here, as necessary.
if (attrName->Atom() == nsGkAtoms::width &&
!GetAnimatedLength(nsGkAtoms::width)->HasBaseVal()) {
continue;
}
if (attrName->Atom() == nsGkAtoms::height &&
!GetAnimatedLength(nsGkAtoms::height)->HasBaseVal()) {
continue;
}
}
if (lengthAffectsStyle) {
auto const* length = GetAnimatedLength(attrName->Atom());

View File

@ -14,7 +14,7 @@ dictionary KeyframeAnimationOptions : KeyframeEffectOptions {
DOMString id = "";
};
dictionary AnimationFilter {
dictionary GetAnimationsOptions {
boolean subtree = false;
};
@ -24,5 +24,5 @@ interface Animatable {
Animation animate(object? keyframes,
optional UnrestrictedDoubleOrKeyframeAnimationOptions options);
[Func="Document::IsWebAnimationsGetAnimationsEnabled"]
sequence<Animation> getAnimations(optional AnimationFilter filter);
sequence<Animation> getAnimations(optional GetAnimationsOptions options);
};

View File

@ -231,12 +231,15 @@ XMLHttpRequestMainThread::XMLHttpRequestMainThread()
mIsMappedArrayBuffer(false),
mXPCOMifier(nullptr),
mEventDispatchingSuspended(false),
mEofDecoded(false) {
mEofDecoded(false),
mDelayedDoneNotifier(nullptr) {
mozilla::HoldJSObjects(this);
}
XMLHttpRequestMainThread::~XMLHttpRequestMainThread() {
DisconnectDoneNotifier();
MOZ_ASSERT(
!mDelayedDoneNotifier,
"How can we have mDelayedDoneNotifier, which owns us, in destructor?");
mFlagDeleted = true;
@ -2234,6 +2237,8 @@ void XMLHttpRequestMainThread::MatchCharsetAndDecoderToResponseDocument() {
}
void XMLHttpRequestMainThread::DisconnectDoneNotifier() {
if (mDelayedDoneNotifier) {
// Disconnect may release the last reference to 'this'.
RefPtr<XMLHttpRequestMainThread> kungfuDeathGrip = this;
mDelayedDoneNotifier->Disconnect();
mDelayedDoneNotifier = nullptr;
}

View File

@ -724,7 +724,7 @@ class XMLHttpRequestMainThread final : public XMLHttpRequest,
// Our parse-end listener, if we are parsing.
RefPtr<nsXHRParseEndListener> mParseEndListener;
RefPtr<XMLHttpRequestDoneNotifier> mDelayedDoneNotifier;
XMLHttpRequestDoneNotifier* mDelayedDoneNotifier;
void DisconnectDoneNotifier();
// Any stack information for the point the XHR was opened. This is deleted
@ -795,8 +795,9 @@ class XMLHttpRequestDoneNotifier : public Runnable {
NS_IMETHOD Run() override {
if (mXHR) {
RefPtr<XMLHttpRequestMainThread> xhr = mXHR;
mXHR = nullptr;
// ChangeStateToDoneInternal ends up calling Disconnect();
xhr->ChangeStateToDoneInternal();
MOZ_ASSERT(!mXHR);
}
return NS_OK;
}
@ -804,7 +805,7 @@ class XMLHttpRequestDoneNotifier : public Runnable {
void Disconnect() { mXHR = nullptr; }
private:
XMLHttpRequestMainThread* mXHR;
RefPtr<XMLHttpRequestMainThread> mXHR;
};
class nsXHRParseEndListener : public nsIDOMEventListener {

View File

@ -1541,6 +1541,7 @@ nsresult HTMLEditRules::WillInsertText(EditSubAction aEditSubAction,
return rv;
}
pos++;
MOZ_ASSERT(pointAfterInsertedSpaces.IsSet());
currentPoint = pointAfterInsertedSpaces;
pointToInsert = pointAfterInsertedSpaces;
}
@ -1581,6 +1582,7 @@ nsresult HTMLEditRules::WillInsertText(EditSubAction aEditSubAction,
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(pointAfterInsertedString.IsSet());
currentPoint = pointAfterInsertedString;
pointToInsert = pointAfterInsertedString;
}

View File

@ -368,12 +368,18 @@ nsresult WSRunObject::InsertText(Document& aDocument,
}
}
// Ready, aim, fire!
// XXX If the point is not editable, InsertTextWithTransaction() returns
// error, but we keep handling it. But I think that it wastes the
// runtime cost. So, perhaps, we should return error code which couldn't
// modify it and make each caller of this method decide whether it should
// keep or stop handling the edit action.
nsresult rv =
MOZ_KnownLive(mHTMLEditor)
->InsertTextWithTransaction(aDocument, theString, pointToInsert,
aPointAfterInsertedString);
if (NS_WARN_IF(NS_FAILED(rv))) {
// XXX Temporarily, set new insertion point to the original point.
*aPointAfterInsertedString = pointToInsert;
return NS_OK;
}
return NS_OK;

View File

@ -0,0 +1,29 @@
<html>
<head>
<script>
function start () {
const sel = document.getSelection()
const range_1 = new Range()
const noscript = document.getElementById('id_24')
const map = document.getElementById('id_26')
sel.selectAllChildren(noscript)
const range_2 = range_1.cloneRange()
range_2.selectNode(map)
const frag = range_2.extractContents()
range_2.insertNode(noscript)
document.documentElement.contentEditable = true
document.execCommand('removeFormat', false,)
noscript.contentEditable = false
document.execCommand('insertText', false, '�\n')
}
window.addEventListener('load', start)
</script>
</head>
<body>
<big class="">
<map class="" id="id_26">
<noscript class="" id="id_24">
</body>
</html>

View File

@ -108,4 +108,5 @@ load 1446451.html
asserts(0-2) load 1464251.html # assertion is that mutation event listener modifies content
pref(layout.accessiblecaret.enabled,true) load 1470926.html
load 1525481.html
load 1534394.html
load 1547898.html

View File

@ -90,39 +90,39 @@ void ScrollMetadata::SetUsesContainerScrolling(bool aValue) {
mUsesContainerScrolling = aValue;
}
void ScrollSnapInfo::InitializeScrollSnapType(WritingMode aWritingMode,
const nsStyleDisplay* aDisplay) {
void ScrollSnapInfo::InitializeScrollSnapStrictness(
WritingMode aWritingMode, const nsStyleDisplay* aDisplay) {
if (aDisplay->mScrollSnapType.strictness == StyleScrollSnapStrictness::None) {
return;
}
mScrollSnapTypeX = StyleScrollSnapStrictness::None;
mScrollSnapTypeY = StyleScrollSnapStrictness::None;
mScrollSnapStrictnessX = StyleScrollSnapStrictness::None;
mScrollSnapStrictnessY = StyleScrollSnapStrictness::None;
switch (aDisplay->mScrollSnapType.axis) {
case StyleScrollSnapAxis::X:
mScrollSnapTypeX = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessX = aDisplay->mScrollSnapType.strictness;
break;
case StyleScrollSnapAxis::Y:
mScrollSnapTypeY = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessY = aDisplay->mScrollSnapType.strictness;
break;
case StyleScrollSnapAxis::Block:
if (aWritingMode.IsVertical()) {
mScrollSnapTypeX = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessX = aDisplay->mScrollSnapType.strictness;
} else {
mScrollSnapTypeY = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessY = aDisplay->mScrollSnapType.strictness;
}
break;
case StyleScrollSnapAxis::Inline:
if (aWritingMode.IsVertical()) {
mScrollSnapTypeY = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessY = aDisplay->mScrollSnapType.strictness;
} else {
mScrollSnapTypeX = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessX = aDisplay->mScrollSnapType.strictness;
}
break;
case StyleScrollSnapAxis::Both:
mScrollSnapTypeX = aDisplay->mScrollSnapType.strictness;
mScrollSnapTypeY = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessX = aDisplay->mScrollSnapType.strictness;
mScrollSnapStrictnessY = aDisplay->mScrollSnapType.strictness;
break;
}
}

View File

@ -719,8 +719,8 @@ struct ScrollSnapInfo {
ScrollSnapInfo() = default;
bool operator==(const ScrollSnapInfo& aOther) const {
return mScrollSnapTypeX == aOther.mScrollSnapTypeX &&
mScrollSnapTypeY == aOther.mScrollSnapTypeY &&
return mScrollSnapStrictnessX == aOther.mScrollSnapStrictnessX &&
mScrollSnapStrictnessY == aOther.mScrollSnapStrictnessY &&
mScrollSnapIntervalX == aOther.mScrollSnapIntervalX &&
mScrollSnapIntervalY == aOther.mScrollSnapIntervalY &&
mScrollSnapDestination == aOther.mScrollSnapDestination &&
@ -733,24 +733,25 @@ struct ScrollSnapInfo {
}
bool HasScrollSnapping() const {
return mScrollSnapTypeY != mozilla::StyleScrollSnapStrictness::None ||
mScrollSnapTypeX != mozilla::StyleScrollSnapStrictness::None;
return mScrollSnapStrictnessY != mozilla::StyleScrollSnapStrictness::None ||
mScrollSnapStrictnessX != mozilla::StyleScrollSnapStrictness::None;
}
bool HasSnapPositions() const {
return (!mSnapPositionX.IsEmpty() &&
mScrollSnapTypeX != mozilla::StyleScrollSnapStrictness::None) ||
mScrollSnapStrictnessX !=
mozilla::StyleScrollSnapStrictness::None) ||
(!mSnapPositionY.IsEmpty() &&
mScrollSnapTypeY != mozilla::StyleScrollSnapStrictness::None);
mScrollSnapStrictnessY != mozilla::StyleScrollSnapStrictness::None);
}
void InitializeScrollSnapType(WritingMode aWritingMode,
const nsStyleDisplay* aDisplay);
void InitializeScrollSnapStrictness(WritingMode aWritingMode,
const nsStyleDisplay* aDisplay);
// The scroll frame's scroll-snap-type.
mozilla::StyleScrollSnapStrictness mScrollSnapTypeX =
mozilla::StyleScrollSnapStrictness mScrollSnapStrictnessX =
mozilla::StyleScrollSnapStrictness::None;
mozilla::StyleScrollSnapStrictness mScrollSnapTypeY =
mozilla::StyleScrollSnapStrictness mScrollSnapStrictnessY =
mozilla::StyleScrollSnapStrictness::None;
// The intervals derived from the scroll frame's scroll-snap-points.

View File

@ -660,6 +660,9 @@ void APZCTreeManager::SampleForWebRender(wr::TransactionWrapper& aTxn,
AsyncPanZoomController::eForCompositing);
transforms.AppendElement(wr::ToWrTransformProperty(
*zoomAnimationId, Matrix4x4::Scaling(zoom.scale, zoom.scale, 1.0f)));
aTxn.UpdateIsTransformPinchZooming(*zoomAnimationId,
apzc->IsPinchZooming());
}
// The positive translation means the painted content is supposed to

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