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

This commit is contained in:
Bogdan Tara 2018-07-07 01:11:36 +03:00
Родитель 5c9335136e f06fbe92ac
Коммит d01e0f82de
84 изменённых файлов: 25226 добавлений и 23107 удалений

Просмотреть файл

@ -4,9 +4,13 @@ ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E741
max-line-length = 99
exclude =
browser/extensions/mortar/ppapi/,
browser/moz.configure,
build/moz.configure/*.configure,
build/pymake/,
js/*.configure,
memory/moz.configure,
mobile/android/*.configure,
node_modules,
security/nss/,
testing/mochitest/pywebsocket,
tools/lint/test/files,

Просмотреть файл

@ -45,12 +45,6 @@ var gIdentityHandler = {
*/
_state: 0,
/**
* This flag gets set if the identity popup was opened by a keypress,
* to be able to focus it on the popupshown event.
*/
_popupTriggeredByKeyboard: false,
/**
* RegExp used to decide if an about url should be shown as being part of
* the browser UI.
@ -831,7 +825,14 @@ var gIdentityHandler = {
return;
}
this._popupTriggeredByKeyboard = event.type == "keypress";
// Move focus to the next available element in the identity popup.
// This is required by role=alertdialog and fixes an issue where
// an already open panel would steal focus from the identity popup.
if (event.type == "keypress") {
let panelView = PanelView.forNode(this._identityPopupMainView);
this._identityPopupMainView.addEventListener("ViewShown", () => panelView.focusFirstNavigableElement(),
{once: true});
}
// Make sure that the display:none style we set in xul is removed now that
// the popup is actually needed
@ -853,13 +854,6 @@ var gIdentityHandler = {
onPopupShown(event) {
if (event.target == this._identityPopup) {
if (this._popupTriggeredByKeyboard) {
// Move focus to the next available element in the identity popup.
// This is required by role=alertdialog and fixes an issue where
// an already open panel would steal focus from the identity popup.
document.commandDispatcher.advanceFocusIntoSubtree(this._identityPopup);
}
window.addEventListener("focus", this, true);
}
},

Просмотреть файл

@ -87,6 +87,19 @@ const whitelist = {
]),
};
// Items on this list are allowed to be loaded but not
// required, as opposed to items in the main whitelist,
// which are all required.
const intermittently_loaded_whitelist = {
components: new Set([
"nsAsyncShutdown.js",
]),
modules: new Set([
"resource://gre/modules/sessionstore/Utils.jsm",
"resource://gre/modules/TelemetryStopwatch.jsm",
]),
};
const blacklist = {
services: new Set([
"@mozilla.org/base/telemetry-startup;1",
@ -145,6 +158,10 @@ add_task(async function() {
return false;
});
loadedList[scriptType] = loadedList[scriptType].filter(c => {
return !intermittently_loaded_whitelist[scriptType].has(c);
});
is(loadedList[scriptType].length, 0,
`should have no unexpected ${scriptType} loaded on content process startup`);

Просмотреть файл

@ -15,6 +15,7 @@ add_task(async function() {
// Ensure all the frame data is in the test compartment to avoid traversing
// a cross compartment wrapper for each pixel.
let frames = Cu.cloneInto(startupRecorder.data.frames, {});
ok(frames.length > 0, "Should have captured some frames.");
let unexpectedRects = 0;
let alreadyFocused = false;

Просмотреть файл

@ -47,7 +47,7 @@
</vbox>
</vbox>
<button id="identity-popup-security-expander"
class="identity-popup-expander"
class="identity-popup-expander subviewkeynav"
when-connection="not-secure secure secure-ev secure-cert-user-overridden"
oncommand="gIdentityHandler.showSecuritySubView();"/>
</hbox>
@ -84,22 +84,22 @@
crop="end">&trackingProtection.reloadRequired2;</description>
<button id="tracking-action-reload"
class="tracking-protection-button"
class="tracking-protection-button subviewkeynav"
label="&trackingProtection.reload2.label;"
accesskey="&trackingProtection.reload2.accesskey;"
oncommand="TrackingProtection.hideIdentityPopupAndReload();" />
<button id="tracking-action-unblock"
class="tracking-protection-button"
class="tracking-protection-button subviewkeynav"
label="&trackingProtection.unblock3.label;"
accesskey="&trackingProtection.unblock3.accesskey;"
oncommand="TrackingProtection.disableForCurrentPage();" />
<button id="tracking-action-unblock-private"
class="tracking-protection-button"
class="tracking-protection-button subviewkeynav"
label="&trackingProtection.unblockPrivate3.label;"
accesskey="&trackingProtection.unblockPrivate3.accesskey;"
oncommand="TrackingProtection.disableForCurrentPage();" />
<button id="tracking-action-block"
class="tracking-protection-button"
class="tracking-protection-button subviewkeynav"
label="&trackingProtection.block4.label;"
accesskey="&trackingProtection.block4.accesskey;"
oncommand="TrackingProtection.enableForCurrentPage();" />

Просмотреть файл

@ -1363,7 +1363,7 @@ var PanelView = class extends AssociatedToNode {
*
* @return {Array}
*/
getNavigableElements() {
_getNavigableElements() {
let buttons = Array.from(this.node.querySelectorAll(
".subviewbutton:not([disabled]), .subviewkeynav:not([disabled])"));
let dwu = this._dwu;
@ -1379,7 +1379,7 @@ var PanelView = class extends AssociatedToNode {
* undefined at any time.
*
* The element is usually, but not necessarily, in the "buttons" property
* which in turn is initialized from the getNavigableElements list.
* which in turn is initialized from the _getNavigableElements list.
*/
get selectedElement() {
return this._selectedElement && this._selectedElement.get();
@ -1392,6 +1392,15 @@ var PanelView = class extends AssociatedToNode {
}
}
/**
* Focuses and moves keyboard selection to the first navigable element.
* This is a no-op if there are no navigable elements.
*/
focusFirstNavigableElement() {
this.selectedElement = this._getNavigableElements()[0];
this.focusSelectedElement();
}
/**
* Based on going up or down, select the previous or next focusable button.
*
@ -1472,7 +1481,7 @@ var PanelView = class extends AssociatedToNode {
let buttons = this.buttons;
if (!buttons || !buttons.length) {
buttons = this.buttons = this.getNavigableElements();
buttons = this.buttons = this._getNavigableElements();
// Set the 'tabindex' attribute on the buttons to make sure they're focussable.
for (let button of buttons) {
if (!button.classList.contains("subviewbutton-back") &&

Просмотреть файл

@ -10,7 +10,7 @@ const kHelpButtonId = "appMenu-help-button";
add_task(async function testUpDownKeys() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
for (let button of buttons) {
if (button.disabled)
@ -39,7 +39,7 @@ add_task(async function testUpDownKeys() {
add_task(async function testEnterKeyBehaviors() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
// Navigate to the 'Help' button, which points to a subview.
EventUtils.synthesizeKey("KEY_ArrowUp");
@ -56,7 +56,7 @@ add_task(async function testEnterKeyBehaviors() {
EventUtils.synthesizeKey("KEY_Enter");
await promise;
let helpButtons = PanelView.forNode(PanelUI.helpView).getNavigableElements();
let helpButtons = PanelView.forNode(PanelUI.helpView)._getNavigableElements();
Assert.ok(helpButtons[0].classList.contains("subviewbutton-back"),
"First button in help view should be a back button");
@ -132,7 +132,7 @@ add_task(async function testLeftRightKeys() {
add_task(async function testTabKey() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
for (let button of buttons) {
if (button.disabled)
@ -165,7 +165,7 @@ add_task(async function testTabKey() {
add_task(async function testInterleavedTabAndArrowKeys() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let tab = false;
for (let button of buttons) {
@ -188,7 +188,7 @@ add_task(async function testInterleavedTabAndArrowKeys() {
add_task(async function testSpaceDownAfterTabNavigation() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let button;
for (button of buttons) {

Просмотреть файл

@ -281,8 +281,10 @@
where += "-background";
} else {
var newTabPref = Services.prefs.getBoolPref("browser.search.openintab");
if (((aEvent instanceof KeyboardEvent) && aEvent.altKey) ^ newTabPref)
if (((aEvent instanceof KeyboardEvent && aEvent.altKey) ^ newTabPref) &&
!isTabEmpty(gBrowser.selectedTab)) {
where = "tab";
}
if ((aEvent instanceof MouseEvent) &&
(aEvent.button == 1 || aEvent.getModifierState("Accel"))) {
where = "tab";
@ -1783,8 +1785,10 @@
}
} else {
var newTabPref = Services.prefs.getBoolPref("browser.search.openintab");
if (((aEvent instanceof KeyboardEvent) && aEvent.altKey) ^ newTabPref)
if (((aEvent instanceof KeyboardEvent && aEvent.altKey) ^ newTabPref) &&
!isTabEmpty(gBrowser.selectedTab)) {
where = "tab";
}
if ((aEvent instanceof MouseEvent) &&
(aEvent.button == 1 || aEvent.getModifierState("Accel"))) {
where = "tab";

Просмотреть файл

@ -95,6 +95,21 @@ startupRecorder.prototype = {
return;
}
// We only care about the first paint notification for browser windows, and
// not other types (for example, the gfx sanity test window)
if (topic == firstPaintNotification) {
// In the case we're handling xul-window-visible, we'll have been handed
// an nsIXULWindow instead of an nsIDOMWindow.
if (subject instanceof Ci.nsIXULWindow) {
subject = subject.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
}
if (subject.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
}
if (topic == "image-drawing" || topic == "image-loading") {
this.data.images[topic].add(data);
return;
@ -104,7 +119,9 @@ startupRecorder.prototype = {
if (topic == firstPaintNotification &&
Services.prefs.getBoolPref("browser.startup.record", false)) {
win = Services.wm.getMostRecentWindow("navigator:browser");
// Because of the check for navigator:browser we made earlier, we know
// that if we got here, then the subject must be the first browser window.
win = subject;
canvas = win.document.createElementNS("http://www.w3.org/1999/xhtml",
"canvas");
canvas.mozOpaque = true;

Просмотреть файл

@ -293,7 +293,7 @@ class PlacesFeed {
break;
}
case at.BOOKMARK_URL:
NewTabUtils.activityStreamLinks.addBookmark(action.data, action._target.browser);
NewTabUtils.activityStreamLinks.addBookmark(action.data, action._target.browser.ownerGlobal);
break;
case at.DELETE_BOOKMARK_BY_ID:
NewTabUtils.activityStreamLinks.deleteBookmark(action.data);

Просмотреть файл

@ -14,6 +14,16 @@ import six
here = os.path.abspath(os.path.dirname(__file__))
try:
# buildconfig doesn't yet support Python 3, so we can use pathlib to
# resolve the topsrcdir relative to our current location.
from pathlib import Path
topsrcdir = Path(here).parents[2]
except ImportError:
from mozbuild.base import MozbuildObject
build = MozbuildObject.from_environment(cwd=here)
topsrcdir = build.topsrcdir
StringIO = six.StringIO
'''Helper to make python unit tests report the way that the Mozilla
@ -234,6 +244,7 @@ def main(*args, **kwargs):
module = __import__('__main__')
args.extend([
'--rootdir', topsrcdir,
'-c', os.path.join(here, 'pytest.ini'),
'-vv',
'-p', 'mozlog.pytest_mozlog.plugin',

Просмотреть файл

@ -101,4 +101,4 @@ const clientEvents = {
newSource
};
exports.setupEvents = setupEvents;
exports.clientEvents = clientEvents;
exports.clientEvents = clientEvents;

Просмотреть файл

@ -205,6 +205,11 @@ networkMenu.sizeGB=%S GB
# unavailable.
networkMenu.sizeUnavailable=
# LOCALIZATION NOTE (networkMenu.sizeUnavailable.title): This is the tooltip
# displayed in the network menu specifying that the transferred size of a
# request is unavailable.
networkMenu.sizeUnavailable.title=Transferred size is not available
# LOCALIZATION NOTE (networkMenu.sizeCached): This is the label displayed
# in the network menu specifying the transferred of a request is
# cached.

Просмотреть файл

@ -15,6 +15,7 @@ const { div } = dom;
const SIZE_CACHED = L10N.getStr("networkMenu.sizeCached");
const SIZE_SERVICE_WORKER = L10N.getStr("networkMenu.sizeServiceWorker");
const SIZE_UNAVAILABLE = L10N.getStr("networkMenu.sizeUnavailable");
const SIZE_UNAVAILABLE_TITLE = L10N.getStr("networkMenu.sizeUnavailable.title");
const UPDATED_TRANSFERRED_PROPS = [
"transferredSize",
"fromCache",
@ -46,8 +47,10 @@ class RequestListColumnTransferredSize extends Component {
text = SIZE_UNAVAILABLE;
}
const title = text == SIZE_UNAVAILABLE ? SIZE_UNAVAILABLE_TITLE : text;
return (
div({ className: "requests-list-column requests-list-transferred", title: text },
div({ className: "requests-list-column requests-list-transferred", title: title },
text
)
);

Просмотреть файл

@ -76,7 +76,7 @@ function AutocompletePopup(toolboxDoc, options = {}) {
}
this._list.className = "devtools-autocomplete-listbox " + theme + "-theme";
this._tooltip.setContent(this._list);
this._tooltip.setContent(this._list, { height: Infinity });
this.onClick = this.onClick.bind(this);
this._list.addEventListener("click", this.onClick);

Просмотреть файл

@ -17,7 +17,7 @@ You should start by upgrading our prop-types library to match the latest version
```bash
git clone https://github.com/facebook/react.git
cd react
git checkout v16.2.0 # or the version you are targetting
git checkout v16.4.1 # or the version you are targetting
```
## Preparing to Build
@ -27,6 +27,7 @@ We need to disable minification and tree shaking as they overcomplicate the upgr
- Open scripts/rollup/build.js
- Find a method called `function getRollupOutputOptions()`
- After `sourcemap: false` add `treeshake: false` and `freeze: false`
- Remove `freeze: !isProduction,` from the same section.
- Change this:
```js
@ -66,40 +67,6 @@ yarn
yarn build
```
### Package Testing Utilities
Go through `build/packages/react-test-renderer` and in each file remove all code meant for a production build e.g.
Change this:
```js
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-test-renderer-shallow.production.min.js');
} else {
module.exports = require('./cjs/react-test-renderer-shallow.development.js');
}
```
To this:
```js
module.exports = require('./cjs/react-test-renderer-shallow.development.js');
```
**NOTE: Be sure to remove all `process.env` conditions from inside the files in the cjs folder.**
Also in the cjs folder replace the React require paths to point at the current React version:
```js
var React = require('../../../dist/react.development');
```
From within `build/packages/react-test-renderer`:
```bash
browserify shallow.js -o react-test-renderer-shallow.js --standalone ShallowRenderer
```
### Copy the Files Into your Firefox Repo
```bash
@ -112,7 +79,7 @@ cp build/dist/react.development.js <gecko-dev>/devtools/client/shared/vendor/rea
cp build/dist/react-dom.development.js <gecko-dev>/devtools/client/shared/vendor/react-dom-dev.js
cp build/dist/react-dom-server.browser.development.js <gecko-dev>/devtools/client/shared/vendor/react-dom-server-dev.js
cp build/dist/react-dom-test-utils.development.js <gecko-dev>/devtools/client/shared/vendor/react-dom-test-utils-dev.js
cp build/packages/react-test-renderer/react-test-renderer-shallow.js <gecko-dev>/devtools/client/shared/vendor/react-test-renderer-shallow.js
cp build/dist/react-test-renderer-shallow.production.min.js <gecko-dev>/devtools/client/shared/vendor/react-test-renderer-shallow.js
```
From this point we will no longer need your react repository so feel free to delete it.

385
devtools/client/shared/vendor/react-dev.js поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
/** @license React v16.2.0
/** @license React v16.4.1
* react.development.js
*
* Copyright (c) 2013-present, Facebook, Inc.
@ -108,17 +108,22 @@ var objectAssign = shouldUseNative() ? Object.assign : function (target, source)
// TODO: this is special because it gets imported during build.
var ReactVersion = '16.2.0';
var ReactVersion = '16.4.1';
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
var hasSymbol = typeof Symbol === 'function' && Symbol['for'];
var hasSymbol = typeof Symbol === 'function' && Symbol.for;
var REACT_ELEMENT_TYPE = hasSymbol ? Symbol['for']('react.element') : 0xeac7;
var REACT_CALL_TYPE = hasSymbol ? Symbol['for']('react.call') : 0xeac8;
var REACT_RETURN_TYPE = hasSymbol ? Symbol['for']('react.return') : 0xeac9;
var REACT_PORTAL_TYPE = hasSymbol ? Symbol['for']('react.portal') : 0xeaca;
var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol['for']('react.fragment') : 0xeacb;
var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace;
var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
var REACT_TIMEOUT_TYPE = hasSymbol ? Symbol.for('react.timeout') : 0xead1;
var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = '@@iterator';
@ -134,31 +139,6 @@ function getIteratorFn(maybeIterable) {
return null;
}
/**
* WARNING: DO NOT manually require this module.
* This is a replacement for `invariant(...)` used by the error code system
* and will _only_ be required by the corresponding babel pass.
* It always throws.
*/
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
var emptyObject = {};
{
Object.freeze(emptyObject);
}
var emptyObject_1 = emptyObject;
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -213,6 +193,59 @@ function invariant(condition, format, a, b, c, d, e, f) {
var invariant_1 = invariant;
// Relying on the `invariant()` implementation lets us
// have preserve the format and params in the www builds.
// Exports ReactDOM.createRoot
// Experimental error-boundary API that can recover from errors within a single
// render phase
// Suspense
var enableSuspense = false;
// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
// In some cases, StrictMode should also double-render lifecycles.
// This can be confusing for tests though,
// And it can be bad for performance in production.
// This feature flag can be used to control the behavior:
// To preserve the "Pause on caught exceptions" behavior of the debugger, we
// replay the begin phase of a failed component inside invokeGuardedCallback.
// Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
// Warn about legacy context API
// Gather advanced timing metrics for Profiler subtrees.
// Only used in www builds.
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
var emptyObject = {};
{
Object.freeze(emptyObject);
}
var emptyObject_1 = emptyObject;
/**
* Forked from fbjs/warning:
* https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js
@ -368,13 +401,13 @@ var didWarnStateUpdateForUnmountedComponent = {};
function warnNoop(publicInstance, callerName) {
{
var constructor = publicInstance.constructor;
var componentName = constructor && (constructor.displayName || constructor.name) || 'ReactClass';
var _constructor = publicInstance.constructor;
var componentName = _constructor && (_constructor.displayName || _constructor.name) || 'ReactClass';
var warningKey = componentName + '.' + callerName;
if (didWarnStateUpdateForUnmountedComponent[warningKey]) {
return;
}
warning_1(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op.\n\nPlease check the code for the %s component.', callerName, callerName, componentName);
warning_1(false, "Can't call %s on a component that is not yet mounted. " + 'This is a no-op, but it might indicate a bug in your application. ' + 'Instead, assign to `this.state` directly or define a `state = {};` ' + 'class property with the desired state in the %s component.', callerName, componentName);
didWarnStateUpdateForUnmountedComponent[warningKey] = true;
}
}
@ -534,46 +567,36 @@ Component.prototype.forceUpdate = function (callback) {
}
}
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
/**
* Base class helpers for the updating state of a component.
* Convenience component with default shallow equality check for sCU.
*/
function PureComponent(props, context, updater) {
// Duplicated from Component.
this.props = props;
this.context = context;
this.refs = emptyObject_1;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
}
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
objectAssign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;
function AsyncComponent(props, context, updater) {
// Duplicated from Component.
this.props = props;
this.context = context;
this.refs = emptyObject_1;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
// an immutable object with a single mutable value
function createRef() {
var refObject = {
current: null
};
{
Object.seal(refObject);
}
return refObject;
}
var asyncComponentPrototype = AsyncComponent.prototype = new ComponentDummy();
asyncComponentPrototype.constructor = AsyncComponent;
// Avoid an extra prototype jump for these methods.
objectAssign(asyncComponentPrototype, Component.prototype);
asyncComponentPrototype.unstable_isAsyncReactComponent = true;
asyncComponentPrototype.render = function () {
return this.props.children;
};
/**
* Keeps track of the current owner.
*
@ -597,8 +620,8 @@ var RESERVED_PROPS = {
__source: true
};
var specialPropKeyWarningShown;
var specialPropRefWarningShown;
var specialPropKeyWarningShown = void 0;
var specialPropRefWarningShown = void 0;
function hasValidRef(config) {
{
@ -674,7 +697,7 @@ function defineRefPropWarningGetter(props, displayName) {
*/
var ReactElement = function (type, key, ref, self, source, owner, props) {
var element = {
// This tag allow us to uniquely identify this as a React Element
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
@ -733,7 +756,7 @@ var ReactElement = function (type, key, ref, self, source, owner, props) {
* See https://reactjs.org/docs/react-api.html#createelement
*/
function createElement(type, config, children) {
var propName;
var propName = void 0;
// Reserved names are extracted
var props = {};
@ -821,7 +844,9 @@ function cloneAndReplaceKey(oldElement, newKey) {
* See https://reactjs.org/docs/react-api.html#cloneelement
*/
function cloneElement(element, config, children) {
var propName;
!!(element === null || element === undefined) ? invariant_1(false, 'React.cloneElement(...): The argument must be a React element, but you passed %s.', element) : void 0;
var propName = void 0;
// Original props are copied
var props = objectAssign({}, element.props);
@ -850,7 +875,7 @@ function cloneElement(element, config, children) {
}
// Remaining properties override existing props
var defaultProps;
var defaultProps = void 0;
if (element.type && element.type.defaultProps) {
defaultProps = element.type.defaultProps;
}
@ -1004,8 +1029,6 @@ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
case 'object':
switch (children.$$typeof) {
case REACT_ELEMENT_TYPE:
case REACT_CALL_TYPE:
case REACT_RETURN_TYPE:
case REACT_PORTAL_TYPE:
invokeCallback = true;
}
@ -1020,8 +1043,8 @@ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
return 1;
}
var child;
var nextName;
var child = void 0;
var nextName = void 0;
var subtreeCount = 0; // Count of children found in the current subtree.
var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
@ -1037,13 +1060,13 @@ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
{
// Warn about using Maps as children
if (iteratorFn === children.entries) {
warning_1(didWarnAboutMaps, 'Using Maps as children is unsupported and will likely yield ' + 'unexpected results. Convert it to a sequence/iterable of keyed ' + 'ReactElements instead.%s', ReactDebugCurrentFrame.getStackAddendum());
!didWarnAboutMaps ? warning_1(false, 'Using Maps as children is unsupported and will likely yield ' + 'unexpected results. Convert it to a sequence/iterable of keyed ' + 'ReactElements instead.%s', ReactDebugCurrentFrame.getStackAddendum()) : void 0;
didWarnAboutMaps = true;
}
}
var iterator = iteratorFn.call(children);
var step;
var step = void 0;
var ii = 0;
while (!(step = iterator.next()).done) {
child = step.value;
@ -1115,7 +1138,7 @@ function forEachSingleChild(bookKeeping, child, name) {
/**
* Iterates through children that are typically specified as `props.children`.
*
* See https://reactjs.org/docs/react-api.html#react.children.foreach
* See https://reactjs.org/docs/react-api.html#reactchildrenforeach
*
* The provided forEachFunc(child, index) will be called for each
* leaf child.
@ -1167,7 +1190,7 @@ function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
/**
* Maps children that are typically specified as `props.children`.
*
* See https://reactjs.org/docs/react-api.html#react.children.map
* See https://reactjs.org/docs/react-api.html#reactchildrenmap
*
* The provided mapFunction(child, key, index) will be called for each
* leaf child.
@ -1190,12 +1213,12 @@ function mapChildren(children, func, context) {
* Count the number of children that are typically specified as
* `props.children`.
*
* See https://reactjs.org/docs/react-api.html#react.children.count
* See https://reactjs.org/docs/react-api.html#reactchildrencount
*
* @param {?*} children Children tree container.
* @return {number} The number of children.
*/
function countChildren(children, context) {
function countChildren(children) {
return traverseAllChildren(children, emptyFunction_1.thatReturnsNull, null);
}
@ -1203,7 +1226,7 @@ function countChildren(children, context) {
* Flatten a children object (typically specified as `props.children`) and
* return an array with appropriately re-keyed children.
*
* See https://reactjs.org/docs/react-api.html#react.children.toarray
* See https://reactjs.org/docs/react-api.html#reactchildrentoarray
*/
function toArray(children) {
var result = [];
@ -1215,7 +1238,7 @@ function toArray(children) {
* Returns the first child in a collection of children and verifies that there
* is only one child in the collection.
*
* See https://reactjs.org/docs/react-api.html#react.children.only
* See https://reactjs.org/docs/react-api.html#reactchildrenonly
*
* The current implementation of this function assumes that a single child gets
* passed without a wrapper, but the purpose of this helper function is to
@ -1230,18 +1253,105 @@ function onlyChild(children) {
return children;
}
function createContext(defaultValue, calculateChangedBits) {
if (calculateChangedBits === undefined) {
calculateChangedBits = null;
} else {
{
!(calculateChangedBits === null || typeof calculateChangedBits === 'function') ? warning_1(false, 'createContext: Expected the optional second argument to be a ' + 'function. Instead received: %s', calculateChangedBits) : void 0;
}
}
var context = {
$$typeof: REACT_CONTEXT_TYPE,
_calculateChangedBits: calculateChangedBits,
_defaultValue: defaultValue,
_currentValue: defaultValue,
// As a workaround to support multiple concurrent renderers, we categorize
// some renderers as primary and others as secondary. We only expect
// there to be two concurrent renderers at most: React Native (primary) and
// Fabric (secondary); React DOM (primary) and React ART (secondary).
// Secondary renderers store their context values on separate fields.
_currentValue2: defaultValue,
_changedBits: 0,
_changedBits2: 0,
// These are circular
Provider: null,
Consumer: null
};
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context
};
context.Consumer = context;
{
context._currentRenderer = null;
context._currentRenderer2 = null;
}
return context;
}
function forwardRef(render) {
{
!(typeof render === 'function') ? warning_1(false, 'forwardRef requires a render function but was given %s.', render === null ? 'null' : typeof render) : void 0;
if (render != null) {
!(render.defaultProps == null && render.propTypes == null) ? warning_1(false, 'forwardRef render functions do not support propTypes or defaultProps. ' + 'Did you accidentally pass a React component?') : void 0;
}
}
return {
$$typeof: REACT_FORWARD_REF_TYPE,
render: render
};
}
var describeComponentFrame = function (name, source, ownerName) {
return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
};
function isValidElementType(type) {
return typeof type === 'string' || typeof type === 'function' ||
// Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
type === REACT_FRAGMENT_TYPE || type === REACT_ASYNC_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_TIMEOUT_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE);
}
function getComponentName(fiber) {
var type = fiber.type;
if (typeof type === 'function') {
return type.displayName || type.name;
}
if (typeof type === 'string') {
return type;
}
if (typeof type === 'function') {
return type.displayName || type.name;
switch (type) {
case REACT_ASYNC_MODE_TYPE:
return 'AsyncMode';
case REACT_CONTEXT_TYPE:
return 'Context.Consumer';
case REACT_FRAGMENT_TYPE:
return 'ReactFragment';
case REACT_PORTAL_TYPE:
return 'ReactPortal';
case REACT_PROFILER_TYPE:
return 'Profiler(' + fiber.pendingProps.id + ')';
case REACT_PROVIDER_TYPE:
return 'Context.Provider';
case REACT_STRICT_MODE_TYPE:
return 'StrictMode';
case REACT_TIMEOUT_TYPE:
return 'Timeout';
}
if (typeof type === 'object' && type !== null) {
switch (type.$$typeof) {
case REACT_FORWARD_REF_TYPE:
var functionName = type.render.displayName || type.render.name || '';
return functionName !== '' ? 'ForwardRef(' + functionName + ')' : 'ForwardRef';
}
}
return null;
}
@ -1326,26 +1436,38 @@ var checkPropTypes_1 = checkPropTypes;
* that support it.
*/
var currentlyValidatingElement = void 0;
var propTypesMisspellWarningShown = void 0;
var getDisplayName = function () {};
var getStackAddendum = function () {};
{
var currentlyValidatingElement = null;
currentlyValidatingElement = null;
var propTypesMisspellWarningShown = false;
propTypesMisspellWarningShown = false;
var getDisplayName = function (element) {
getDisplayName = function (element) {
if (element == null) {
return '#empty';
} else if (typeof element === 'string' || typeof element === 'number') {
return '#text';
} else if (typeof element.type === 'string') {
return element.type;
} else if (element.type === REACT_FRAGMENT_TYPE) {
}
var type = element.type;
if (type === REACT_FRAGMENT_TYPE) {
return 'React.Fragment';
} else if (typeof type === 'object' && type !== null && type.$$typeof === REACT_FORWARD_REF_TYPE) {
var functionName = type.render.displayName || type.render.name || '';
return functionName !== '' ? 'ForwardRef(' + functionName + ')' : 'ForwardRef';
} else {
return element.type.displayName || element.type.name || 'Unknown';
return type.displayName || type.name || 'Unknown';
}
};
var getStackAddendum = function () {
getStackAddendum = function () {
var stack = '';
if (currentlyValidatingElement) {
var name = getDisplayName(currentlyValidatingElement);
@ -1355,8 +1477,6 @@ var checkPropTypes_1 = checkPropTypes;
stack += ReactDebugCurrentFrame.getStackAddendum() || '';
return stack;
};
var VALID_FRAGMENT_PROPS = new Map([['children', true], ['key', true]]);
}
function getDeclarationErrorAddendum() {
@ -1469,7 +1589,7 @@ function validateChildKeys(node, parentType) {
// but now we print a separate warning for them later.
if (iteratorFn !== node.entries) {
var iterator = iteratorFn.call(node);
var step;
var step = void 0;
while (!(step = iterator.next()).done) {
if (isValidElement(step.value)) {
validateExplicitKey(step.value, parentType);
@ -1487,22 +1607,31 @@ function validateChildKeys(node, parentType) {
* @param {ReactElement} element
*/
function validatePropTypes(element) {
var componentClass = element.type;
if (typeof componentClass !== 'function') {
var type = element.type;
var name = void 0,
propTypes = void 0;
if (typeof type === 'function') {
// Class or functional component
name = type.displayName || type.name;
propTypes = type.propTypes;
} else if (typeof type === 'object' && type !== null && type.$$typeof === REACT_FORWARD_REF_TYPE) {
// ForwardRef
var functionName = type.render.displayName || type.render.name || '';
name = functionName !== '' ? 'ForwardRef(' + functionName + ')' : 'ForwardRef';
propTypes = type.propTypes;
} else {
return;
}
var name = componentClass.displayName || componentClass.name;
var propTypes = componentClass.propTypes;
if (propTypes) {
currentlyValidatingElement = element;
checkPropTypes_1(propTypes, element.props, 'prop', name, getStackAddendum);
currentlyValidatingElement = null;
} else if (componentClass.PropTypes !== undefined && !propTypesMisspellWarningShown) {
} else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
propTypesMisspellWarningShown = true;
warning_1(false, 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', name || 'Unknown');
}
if (typeof componentClass.getDefaultProps === 'function') {
warning_1(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');
if (typeof type.getDefaultProps === 'function') {
!type.getDefaultProps.isReactClassApproved ? warning_1(false, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;
}
}
@ -1513,31 +1642,12 @@ function validatePropTypes(element) {
function validateFragmentProps(fragment) {
currentlyValidatingElement = fragment;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = Object.keys(fragment.props)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var key = _step.value;
if (!VALID_FRAGMENT_PROPS.has(key)) {
warning_1(false, 'Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.%s', key, getStackAddendum());
break;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
var keys = Object.keys(fragment.props);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (key !== 'children' && key !== 'key') {
warning_1(false, 'Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.%s', key, getStackAddendum());
break;
}
}
@ -1549,7 +1659,8 @@ function validateFragmentProps(fragment) {
}
function createElementWithValidation(type, props, children) {
var validType = typeof type === 'string' || typeof type === 'function' || typeof type === 'symbol' || typeof type === 'number';
var validType = isValidElementType(type);
// We warn in this case but don't throw. We expect the element creation to
// succeed and there will likely be errors in render.
if (!validType) {
@ -1567,7 +1678,16 @@ function createElementWithValidation(type, props, children) {
info += getStackAddendum() || '';
warning_1(false, 'React.createElement: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', type == null ? type : typeof type, info);
var typeString = void 0;
if (type === null) {
typeString = 'null';
} else if (Array.isArray(type)) {
typeString = 'array';
} else {
typeString = typeof type;
}
warning_1(false, 'React.createElement: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);
}
var element = createElement.apply(this, arguments);
@ -1589,7 +1709,7 @@ function createElementWithValidation(type, props, children) {
}
}
if (typeof type === 'symbol' && type === REACT_FRAGMENT_TYPE) {
if (type === REACT_FRAGMENT_TYPE) {
validateFragmentProps(element);
} else {
validatePropTypes(element);
@ -1600,9 +1720,8 @@ function createElementWithValidation(type, props, children) {
function createFactoryWithValidation(type) {
var validatedFactory = createElementWithValidation.bind(null, type);
// Legacy hook TODO: Warn if this is accessed
validatedFactory.type = type;
// Legacy hook: remove it
{
Object.defineProperty(validatedFactory, 'type', {
enumerable: false,
@ -1637,11 +1756,17 @@ var React = {
only: onlyChild
},
createRef: createRef,
Component: Component,
PureComponent: PureComponent,
unstable_AsyncComponent: AsyncComponent,
createContext: createContext,
forwardRef: forwardRef,
Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
unstable_AsyncMode: REACT_ASYNC_MODE_TYPE,
unstable_Profiler: REACT_PROFILER_TYPE,
createElement: createElementWithValidation,
cloneElement: cloneElementWithValidation,
@ -1657,6 +1782,10 @@ var React = {
}
};
if (enableSuspense) {
React.Timeout = REACT_TIMEOUT_TYPE;
}
{
objectAssign(React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, {
// These should not be included in production.
@ -1669,7 +1798,7 @@ var React = {
var React$2 = Object.freeze({
var React$2 = ({
default: React
});
@ -1677,7 +1806,7 @@ var React$3 = ( React$2 && React ) || React$2;
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
var react = React$3['default'] ? React$3['default'] : React$3;
var react = React$3.default ? React$3.default : React$3;
return react;

21980
devtools/client/shared/vendor/react-dom-dev.js поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
/** @license React v16.2.0
/** @license React v16.4.1
* react-dom-test-utils.development.js
*
* Copyright (c) 2013-present, Facebook, Inc.
@ -19,13 +19,6 @@ var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var _assign = ReactInternals.assign;
/**
* WARNING: DO NOT manually require this module.
* This is a replacement for `invariant(...)` used by the error code system
* and will _only_ be required by the corresponding babel pass.
* It always throws.
*/
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -80,6 +73,9 @@ function invariant(condition, format, a, b, c, d, e, f) {
var invariant_1 = invariant;
// Relying on the `invariant()` implementation lets us
// have preserve the format and params in the www builds.
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -204,6 +200,9 @@ var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var ReactCurrentOwner = ReactInternals$1.ReactCurrentOwner;
var ReactDebugCurrentFrame = ReactInternals$1.ReactDebugCurrentFrame;
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
// Before we know whether it is functional or class
var FunctionalComponent = 1;
var ClassComponent = 2;
@ -212,19 +211,22 @@ var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
var HostComponent = 5;
var HostText = 6;
// Don't change these two values:
var NoEffect = 0; // 0b00000000
// 0b00000001
// Don't change these two values. They're used by React Dev Tools.
var NoEffect = /* */0;
// You can change the rest (and add more).
var Placement = 2; // 0b00000010
// 0b00000100
// 0b00000110
// 0b00001000
// 0b00010000
// 0b00100000
// 0b01000000
// 0b10000000
var Placement = /* */2;
// Union of all host effects
var MOUNTING = 1;
var MOUNTED = 2;
@ -238,15 +240,15 @@ function isFiberMountedImpl(fiber) {
if ((node.effectTag & Placement) !== NoEffect) {
return MOUNTING;
}
while (node['return']) {
node = node['return'];
while (node.return) {
node = node.return;
if ((node.effectTag & Placement) !== NoEffect) {
return MOUNTING;
}
}
} else {
while (node['return']) {
node = node['return'];
while (node.return) {
node = node.return;
}
}
if (node.tag === HostRoot) {
@ -284,7 +286,7 @@ function findCurrentFiberUsingSlowPath(fiber) {
var a = fiber;
var b = alternate;
while (true) {
var parentA = a['return'];
var parentA = a.return;
var parentB = parentA ? parentA.alternate : null;
if (!parentA || !parentB) {
// We're at the root.
@ -314,7 +316,7 @@ function findCurrentFiberUsingSlowPath(fiber) {
invariant_1(false, 'Unable to find node on an unmounted component.');
}
if (a['return'] !== b['return']) {
if (a.return !== b.return) {
// The return pointer of A and the return pointer of B point to different
// fibers. We assume that return pointers never criss-cross, so A must
// belong to the child set of A.return, and B must belong to the child
@ -382,7 +384,6 @@ function findCurrentFiberUsingSlowPath(fiber) {
/* eslint valid-typeof: 0 */
var didWarnForAddedNewProperty = false;
var isProxySupported = typeof Proxy === 'function';
var EVENT_POOL_SIZE = 10;
var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];
@ -543,24 +544,26 @@ SyntheticEvent.Interface = EventInterface;
/**
* Helper to reduce boilerplate when creating subclasses.
*
* @param {function} Class
* @param {?object} Interface
*/
SyntheticEvent.augmentClass = function (Class, Interface) {
SyntheticEvent.extend = function (Interface) {
var Super = this;
var E = function () {};
E.prototype = Super.prototype;
var prototype = new E();
function Class() {
return Super.apply(this, arguments);
}
_assign(prototype, Class.prototype);
Class.prototype = prototype;
Class.prototype.constructor = Class;
Class.Interface = _assign({}, Super.Interface, Interface);
Class.augmentClass = Super.augmentClass;
Class.extend = Super.extend;
addEventPoolingTo(Class);
return Class;
};
/** Proxying after everything set on SyntheticEvent
@ -568,6 +571,10 @@ SyntheticEvent.augmentClass = function (Class, Interface) {
* in which some Event properties are set to undefined (GH#10010)
*/
{
var isProxySupported = typeof Proxy === 'function' &&
// https://github.com/facebook/react/issues/12011
!Object.isSealed(new Proxy({}, {}));
if (isProxySupported) {
/*eslint-disable no-func-assign */
SyntheticEvent = new Proxy(SyntheticEvent, {
@ -578,7 +585,7 @@ SyntheticEvent.augmentClass = function (Class, Interface) {
return new Proxy(constructor.apply(that, args), {
set: function (target, prop, value) {
if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {
warning_1(didWarnForAddedNewProperty || target.isPersistent(), "This synthetic event is reused for performance reasons. If you're " + "seeing this, you're adding a new property in the synthetic event object. " + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.');
!(didWarnForAddedNewProperty || target.isPersistent()) ? warning_1(false, "This synthetic event is reused for performance reasons. If you're " + "seeing this, you're adding a new property in the synthetic event object. " + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;
didWarnForAddedNewProperty = true;
}
target[prop] = value;
@ -623,7 +630,7 @@ function getPooledWarningPropertyDefinition(propName, getVal) {
function warn(action, result) {
var warningCondition = false;
warning_1(warningCondition, "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result);
!warningCondition ? warning_1(false, "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;
}
}
@ -654,6 +661,14 @@ function addEventPoolingTo(EventConstructor) {
var SyntheticEvent$1 = SyntheticEvent;
// Do not uses the below two methods directly!
// Instead use constants exported from DOMTopLevelEventTypes in ReactDOM.
// (It is the only module that is allowed to access these methods.)
function unsafeCastStringToDOMTopLevelType(topLevelType) {
return topLevelType;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -770,90 +785,101 @@ function getVendorPrefixedEventName(eventName) {
}
}
return '';
return eventName;
}
/**
* Types of raw signals from the browser caught at the top level.
*
* For events like 'submit' which don't consistently bubble (which we
* trap at a lower node than `document`), binding at `document` would
* cause duplicate events so we don't include them here.
* To identify top level events in ReactDOM, we use constants defined by this
* module. This is the only module that uses the unsafe* methods to express
* that the constants actually correspond to the browser event names. This lets
* us save some bundle size by avoiding a top level type -> event name map.
* The rest of ReactDOM code should import top level types from this file.
*/
var topLevelTypes$1 = {
topAbort: 'abort',
topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
topBlur: 'blur',
topCancel: 'cancel',
topCanPlay: 'canplay',
topCanPlayThrough: 'canplaythrough',
topChange: 'change',
topClick: 'click',
topClose: 'close',
topCompositionEnd: 'compositionend',
topCompositionStart: 'compositionstart',
topCompositionUpdate: 'compositionupdate',
topContextMenu: 'contextmenu',
topCopy: 'copy',
topCut: 'cut',
topDoubleClick: 'dblclick',
topDrag: 'drag',
topDragEnd: 'dragend',
topDragEnter: 'dragenter',
topDragExit: 'dragexit',
topDragLeave: 'dragleave',
topDragOver: 'dragover',
topDragStart: 'dragstart',
topDrop: 'drop',
topDurationChange: 'durationchange',
topEmptied: 'emptied',
topEncrypted: 'encrypted',
topEnded: 'ended',
topError: 'error',
topFocus: 'focus',
topInput: 'input',
topKeyDown: 'keydown',
topKeyPress: 'keypress',
topKeyUp: 'keyup',
topLoadedData: 'loadeddata',
topLoad: 'load',
topLoadedMetadata: 'loadedmetadata',
topLoadStart: 'loadstart',
topMouseDown: 'mousedown',
topMouseMove: 'mousemove',
topMouseOut: 'mouseout',
topMouseOver: 'mouseover',
topMouseUp: 'mouseup',
topPaste: 'paste',
topPause: 'pause',
topPlay: 'play',
topPlaying: 'playing',
topProgress: 'progress',
topRateChange: 'ratechange',
topScroll: 'scroll',
topSeeked: 'seeked',
topSeeking: 'seeking',
topSelectionChange: 'selectionchange',
topStalled: 'stalled',
topSuspend: 'suspend',
topTextInput: 'textInput',
topTimeUpdate: 'timeupdate',
topToggle: 'toggle',
topTouchCancel: 'touchcancel',
topTouchEnd: 'touchend',
topTouchMove: 'touchmove',
topTouchStart: 'touchstart',
topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
topVolumeChange: 'volumechange',
topWaiting: 'waiting',
topWheel: 'wheel'
};
var TOP_ABORT = unsafeCastStringToDOMTopLevelType('abort');
var TOP_ANIMATION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationend'));
var TOP_ANIMATION_ITERATION = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationiteration'));
var TOP_ANIMATION_START = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationstart'));
var TOP_BLUR = unsafeCastStringToDOMTopLevelType('blur');
var TOP_CAN_PLAY = unsafeCastStringToDOMTopLevelType('canplay');
var TOP_CAN_PLAY_THROUGH = unsafeCastStringToDOMTopLevelType('canplaythrough');
var TOP_CANCEL = unsafeCastStringToDOMTopLevelType('cancel');
var TOP_CHANGE = unsafeCastStringToDOMTopLevelType('change');
var TOP_CLICK = unsafeCastStringToDOMTopLevelType('click');
var TOP_CLOSE = unsafeCastStringToDOMTopLevelType('close');
var TOP_COMPOSITION_END = unsafeCastStringToDOMTopLevelType('compositionend');
var TOP_COMPOSITION_START = unsafeCastStringToDOMTopLevelType('compositionstart');
var TOP_COMPOSITION_UPDATE = unsafeCastStringToDOMTopLevelType('compositionupdate');
var TOP_CONTEXT_MENU = unsafeCastStringToDOMTopLevelType('contextmenu');
var TOP_COPY = unsafeCastStringToDOMTopLevelType('copy');
var TOP_CUT = unsafeCastStringToDOMTopLevelType('cut');
var TOP_DOUBLE_CLICK = unsafeCastStringToDOMTopLevelType('dblclick');
var TOP_DRAG = unsafeCastStringToDOMTopLevelType('drag');
var TOP_DRAG_END = unsafeCastStringToDOMTopLevelType('dragend');
var TOP_DRAG_ENTER = unsafeCastStringToDOMTopLevelType('dragenter');
var TOP_DRAG_EXIT = unsafeCastStringToDOMTopLevelType('dragexit');
var TOP_DRAG_LEAVE = unsafeCastStringToDOMTopLevelType('dragleave');
var TOP_DRAG_OVER = unsafeCastStringToDOMTopLevelType('dragover');
var TOP_DRAG_START = unsafeCastStringToDOMTopLevelType('dragstart');
var TOP_DROP = unsafeCastStringToDOMTopLevelType('drop');
var TOP_DURATION_CHANGE = unsafeCastStringToDOMTopLevelType('durationchange');
var TOP_EMPTIED = unsafeCastStringToDOMTopLevelType('emptied');
var TOP_ENCRYPTED = unsafeCastStringToDOMTopLevelType('encrypted');
var TOP_ENDED = unsafeCastStringToDOMTopLevelType('ended');
var TOP_ERROR = unsafeCastStringToDOMTopLevelType('error');
var TOP_FOCUS = unsafeCastStringToDOMTopLevelType('focus');
var BrowserEventConstants = {
topLevelTypes: topLevelTypes$1
};
var TOP_INPUT = unsafeCastStringToDOMTopLevelType('input');
var TOP_KEY_DOWN = unsafeCastStringToDOMTopLevelType('keydown');
var TOP_KEY_PRESS = unsafeCastStringToDOMTopLevelType('keypress');
var TOP_KEY_UP = unsafeCastStringToDOMTopLevelType('keyup');
var TOP_LOAD = unsafeCastStringToDOMTopLevelType('load');
var TOP_LOAD_START = unsafeCastStringToDOMTopLevelType('loadstart');
var TOP_LOADED_DATA = unsafeCastStringToDOMTopLevelType('loadeddata');
var TOP_LOADED_METADATA = unsafeCastStringToDOMTopLevelType('loadedmetadata');
var TOP_MOUSE_DOWN = unsafeCastStringToDOMTopLevelType('mousedown');
var TOP_MOUSE_MOVE = unsafeCastStringToDOMTopLevelType('mousemove');
var TOP_MOUSE_OUT = unsafeCastStringToDOMTopLevelType('mouseout');
var TOP_MOUSE_OVER = unsafeCastStringToDOMTopLevelType('mouseover');
var TOP_MOUSE_UP = unsafeCastStringToDOMTopLevelType('mouseup');
var TOP_PASTE = unsafeCastStringToDOMTopLevelType('paste');
var TOP_PAUSE = unsafeCastStringToDOMTopLevelType('pause');
var TOP_PLAY = unsafeCastStringToDOMTopLevelType('play');
var TOP_PLAYING = unsafeCastStringToDOMTopLevelType('playing');
var TOP_PROGRESS = unsafeCastStringToDOMTopLevelType('progress');
var TOP_RATE_CHANGE = unsafeCastStringToDOMTopLevelType('ratechange');
var TOP_SCROLL = unsafeCastStringToDOMTopLevelType('scroll');
var TOP_SEEKED = unsafeCastStringToDOMTopLevelType('seeked');
var TOP_SEEKING = unsafeCastStringToDOMTopLevelType('seeking');
var TOP_SELECTION_CHANGE = unsafeCastStringToDOMTopLevelType('selectionchange');
var TOP_STALLED = unsafeCastStringToDOMTopLevelType('stalled');
var TOP_SUSPEND = unsafeCastStringToDOMTopLevelType('suspend');
var TOP_TEXT_INPUT = unsafeCastStringToDOMTopLevelType('textInput');
var TOP_TIME_UPDATE = unsafeCastStringToDOMTopLevelType('timeupdate');
var TOP_TOGGLE = unsafeCastStringToDOMTopLevelType('toggle');
var TOP_TOUCH_CANCEL = unsafeCastStringToDOMTopLevelType('touchcancel');
var TOP_TOUCH_END = unsafeCastStringToDOMTopLevelType('touchend');
var TOP_TOUCH_MOVE = unsafeCastStringToDOMTopLevelType('touchmove');
var TOP_TOUCH_START = unsafeCastStringToDOMTopLevelType('touchstart');
var TOP_TRANSITION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('transitionend'));
var TOP_VOLUME_CHANGE = unsafeCastStringToDOMTopLevelType('volumechange');
var TOP_WAITING = unsafeCastStringToDOMTopLevelType('waiting');
var TOP_WHEEL = unsafeCastStringToDOMTopLevelType('wheel');
// List of events that need to be individually attached to media elements.
// Note that events in this list will *not* be listened to at the top level
// unless they're explicitly whitelisted in `ReactBrowserEventEmitter.listenTo`.
var findDOMNode = ReactDOM.findDOMNode;
var _ReactDOM$__SECRET_IN = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
@ -865,14 +891,35 @@ var ReactDOMComponentTree = _ReactDOM$__SECRET_IN.ReactDOMComponentTree;
var ReactDOMEventListener = _ReactDOM$__SECRET_IN.ReactDOMEventListener;
var topLevelTypes = BrowserEventConstants.topLevelTypes;
function Event(suffix) {}
/**
* @class ReactTestUtils
*/
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on an `Element` node.
* @param {number} topLevelType A number from `TopLevelEventTypes`
* @param {!Element} node The dom to simulate an event occurring on.
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
function simulateNativeEventOnNode(topLevelType, node, fakeNativeEvent) {
fakeNativeEvent.target = node;
ReactDOMEventListener.dispatchEvent(topLevelType, fakeNativeEvent);
}
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on the `ReactDOMComponent` `comp`.
* @param {Object} topLevelType A type from `BrowserEventConstants.topLevelTypes`.
* @param {!ReactDOMComponent} comp
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
function simulateNativeEventOnDOMComponent(topLevelType, comp, fakeNativeEvent) {
simulateNativeEventOnNode(topLevelType, findDOMNode(comp), fakeNativeEvent);
}
function findAllInRenderedFiberTreeInternal(fiber, test) {
if (!fiber) {
return [];
@ -891,7 +938,7 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
}
}
if (node.child) {
node.child['return'] = node;
node.child.return = node;
node = node.child;
continue;
}
@ -899,12 +946,12 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
return ret;
}
while (!node.sibling) {
if (!node['return'] || node['return'] === currentParent) {
if (!node.return || node.return === currentParent) {
return ret;
}
node = node['return'];
node = node.return;
}
node.sibling['return'] = node['return'];
node.sibling.return = node.return;
node = node.sibling;
}
}
@ -1085,29 +1132,6 @@ var ReactTestUtils = {
return this;
},
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on an `Element` node.
* @param {Object} topLevelType A type from `BrowserEventConstants.topLevelTypes`
* @param {!Element} node The dom to simulate an event occurring on.
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
simulateNativeEventOnNode: function (topLevelType, node, fakeNativeEvent) {
fakeNativeEvent.target = node;
ReactDOMEventListener.dispatchEvent(topLevelType, fakeNativeEvent);
},
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on the `ReactDOMComponent` `comp`.
* @param {Object} topLevelType A type from `BrowserEventConstants.topLevelTypes`.
* @param {!ReactDOMComponent} comp
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
simulateNativeEventOnDOMComponent: function (topLevelType, comp, fakeNativeEvent) {
ReactTestUtils.simulateNativeEventOnNode(topLevelType, findDOMNode(comp), fakeNativeEvent);
},
nativeTouchData: function (x, y) {
return {
touches: [{ pageX: x, pageY: y }]
@ -1157,17 +1181,16 @@ function makeSimulator(eventType) {
// Normally extractEvent enqueues a state restore, but we'll just always
// do that since we we're by-passing it here.
ReactControlledComponent.enqueueStateRestore(domNode);
EventPluginHub.enqueueEvents(event);
EventPluginHub.processEventQueue(true);
EventPluginHub.runEventsInBatch(event, true);
});
ReactControlledComponent.restoreStateIfNeeded();
};
}
function buildSimulators() {
ReactTestUtils.Simulate = {};
var eventType;
var eventType = void 0;
for (eventType in EventPluginRegistry.eventNameDispatchConfigs) {
/**
* @param {!Element|ReactDOMComponent} domComponentOrNode
@ -1207,32 +1230,33 @@ buildSimulators();
* to dispatch synthetic events.
*/
function makeNativeSimulator(eventType) {
function makeNativeSimulator(eventType, topLevelType) {
return function (domComponentOrNode, nativeEventData) {
var fakeNativeEvent = new Event(eventType);
_assign(fakeNativeEvent, nativeEventData);
if (ReactTestUtils.isDOMComponent(domComponentOrNode)) {
ReactTestUtils.simulateNativeEventOnDOMComponent(eventType, domComponentOrNode, fakeNativeEvent);
simulateNativeEventOnDOMComponent(topLevelType, domComponentOrNode, fakeNativeEvent);
} else if (domComponentOrNode.tagName) {
// Will allow on actual dom nodes.
ReactTestUtils.simulateNativeEventOnNode(eventType, domComponentOrNode, fakeNativeEvent);
simulateNativeEventOnNode(topLevelType, domComponentOrNode, fakeNativeEvent);
}
};
}
Object.keys(topLevelTypes).forEach(function (eventType) {
// Event type is stored as 'topClick' - we transform that to 'click'
var convenienceName = eventType.indexOf('top') === 0 ? eventType.charAt(3).toLowerCase() + eventType.substr(4) : eventType;
[[TOP_ABORT, 'abort'], [TOP_ANIMATION_END, 'animationEnd'], [TOP_ANIMATION_ITERATION, 'animationIteration'], [TOP_ANIMATION_START, 'animationStart'], [TOP_BLUR, 'blur'], [TOP_CAN_PLAY_THROUGH, 'canPlayThrough'], [TOP_CAN_PLAY, 'canPlay'], [TOP_CANCEL, 'cancel'], [TOP_CHANGE, 'change'], [TOP_CLICK, 'click'], [TOP_CLOSE, 'close'], [TOP_COMPOSITION_END, 'compositionEnd'], [TOP_COMPOSITION_START, 'compositionStart'], [TOP_COMPOSITION_UPDATE, 'compositionUpdate'], [TOP_CONTEXT_MENU, 'contextMenu'], [TOP_COPY, 'copy'], [TOP_CUT, 'cut'], [TOP_DOUBLE_CLICK, 'doubleClick'], [TOP_DRAG_END, 'dragEnd'], [TOP_DRAG_ENTER, 'dragEnter'], [TOP_DRAG_EXIT, 'dragExit'], [TOP_DRAG_LEAVE, 'dragLeave'], [TOP_DRAG_OVER, 'dragOver'], [TOP_DRAG_START, 'dragStart'], [TOP_DRAG, 'drag'], [TOP_DROP, 'drop'], [TOP_DURATION_CHANGE, 'durationChange'], [TOP_EMPTIED, 'emptied'], [TOP_ENCRYPTED, 'encrypted'], [TOP_ENDED, 'ended'], [TOP_ERROR, 'error'], [TOP_FOCUS, 'focus'], [TOP_INPUT, 'input'], [TOP_KEY_DOWN, 'keyDown'], [TOP_KEY_PRESS, 'keyPress'], [TOP_KEY_UP, 'keyUp'], [TOP_LOAD_START, 'loadStart'], [TOP_LOAD_START, 'loadStart'], [TOP_LOAD, 'load'], [TOP_LOADED_DATA, 'loadedData'], [TOP_LOADED_METADATA, 'loadedMetadata'], [TOP_MOUSE_DOWN, 'mouseDown'], [TOP_MOUSE_MOVE, 'mouseMove'], [TOP_MOUSE_OUT, 'mouseOut'], [TOP_MOUSE_OVER, 'mouseOver'], [TOP_MOUSE_UP, 'mouseUp'], [TOP_PASTE, 'paste'], [TOP_PAUSE, 'pause'], [TOP_PLAY, 'play'], [TOP_PLAYING, 'playing'], [TOP_PROGRESS, 'progress'], [TOP_RATE_CHANGE, 'rateChange'], [TOP_SCROLL, 'scroll'], [TOP_SEEKED, 'seeked'], [TOP_SEEKING, 'seeking'], [TOP_SELECTION_CHANGE, 'selectionChange'], [TOP_STALLED, 'stalled'], [TOP_SUSPEND, 'suspend'], [TOP_TEXT_INPUT, 'textInput'], [TOP_TIME_UPDATE, 'timeUpdate'], [TOP_TOGGLE, 'toggle'], [TOP_TOUCH_CANCEL, 'touchCancel'], [TOP_TOUCH_END, 'touchEnd'], [TOP_TOUCH_MOVE, 'touchMove'], [TOP_TOUCH_START, 'touchStart'], [TOP_TRANSITION_END, 'transitionEnd'], [TOP_VOLUME_CHANGE, 'volumeChange'], [TOP_WAITING, 'waiting'], [TOP_WHEEL, 'wheel']].forEach(function (_ref) {
var topLevelType = _ref[0],
eventType = _ref[1];
/**
* @param {!Element|ReactDOMComponent} domComponentOrNode
* @param {?Event} nativeEventData Fake native event to use in SyntheticEvent.
*/
ReactTestUtils.SimulateNative[convenienceName] = makeNativeSimulator(eventType);
ReactTestUtils.SimulateNative[eventType] = makeNativeSimulator(eventType, topLevelType);
});
var ReactTestUtils$2 = Object.freeze({
var ReactTestUtils$2 = ({
default: ReactTestUtils
});
@ -1240,7 +1264,7 @@ var ReactTestUtils$3 = ( ReactTestUtils$2 && ReactTestUtils ) || ReactTestUtils$
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
var testUtils = ReactTestUtils$3['default'] ? ReactTestUtils$3['default'] : ReactTestUtils$3;
var testUtils = ReactTestUtils$3.default ? ReactTestUtils$3.default : ReactTestUtils$3;
return testUtils;

Просмотреть файл

@ -1,4 +1,4 @@
/** @license React v16.2.0
/** @license React v16.4.1
* react-dom-test-utils.production.min.js
*
* Copyright (c) 2013-present, Facebook, Inc.
@ -16,6 +16,39 @@ var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var _assign = ReactInternals.assign;
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
function invariant(condition, format, a, b, c, d, e, f) {
if (!condition) {
var error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(format.replace(/%s/g, function () {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
}
var invariant_1 = invariant;
// Relying on the `invariant()` implementation lets us
// have preserve the format and params in the www builds.
/**
* WARNING: DO NOT manually require this module.
* This is a replacement for `invariant(...)` used by the error code system
@ -24,30 +57,20 @@ var _assign = ReactInternals.assign;
*/
function reactProdInvariant(code) {
var argCount = arguments.length - 1;
var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;
var url = 'https://reactjs.org/docs/error-decoder.html?invariant=' + code;
for (var argIdx = 0; argIdx < argCount; argIdx++) {
message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
url += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
}
message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';
var error = new Error(message);
error.name = 'Invariant Violation';
error.framesToPop = 1; // we don't care about reactProdInvariant's own frame
throw error;
// Rename it so that our build transform doesn't atttempt
// to replace this invariant() call with reactProdInvariant().
var i = invariant_1;
i(false,
// The error code is intentionally part of the message (and
// not the format argument) so that we could deduplicate
// different errors in logs based on the code.
'Minified React error #' + code + '; visit %s ' + 'for the full message or use the non-minified dev environment ' + 'for full errors and additional helpful warnings. ', url);
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -116,6 +139,9 @@ var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var ReactCurrentOwner = ReactInternals$1.ReactCurrentOwner;
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
// Before we know whether it is functional or class
var FunctionalComponent = 1;
var ClassComponent = 2;
@ -124,19 +150,22 @@ var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
var HostComponent = 5;
var HostText = 6;
// Don't change these two values:
var NoEffect = 0; // 0b00000000
// 0b00000001
// Don't change these two values. They're used by React Dev Tools.
var NoEffect = /* */0;
// You can change the rest (and add more).
var Placement = 2; // 0b00000010
// 0b00000100
// 0b00000110
// 0b00001000
// 0b00010000
// 0b00100000
// 0b01000000
// 0b10000000
var Placement = /* */2;
// Union of all host effects
var MOUNTING = 1;
var MOUNTED = 2;
@ -150,15 +179,15 @@ function isFiberMountedImpl(fiber) {
if ((node.effectTag & Placement) !== NoEffect) {
return MOUNTING;
}
while (node['return']) {
node = node['return'];
while (node.return) {
node = node.return;
if ((node.effectTag & Placement) !== NoEffect) {
return MOUNTING;
}
}
} else {
while (node['return']) {
node = node['return'];
while (node.return) {
node = node.return;
}
}
if (node.tag === HostRoot) {
@ -196,7 +225,7 @@ function findCurrentFiberUsingSlowPath(fiber) {
var a = fiber;
var b = alternate;
while (true) {
var parentA = a['return'];
var parentA = a.return;
var parentB = parentA ? parentA.alternate : null;
if (!parentA || !parentB) {
// We're at the root.
@ -226,7 +255,7 @@ function findCurrentFiberUsingSlowPath(fiber) {
reactProdInvariant('188');
}
if (a['return'] !== b['return']) {
if (a.return !== b.return) {
// The return pointer of A and the return pointer of B point to different
// fibers. We assume that return pointers never criss-cross, so A must
// belong to the child set of A.return, and B must belong to the child
@ -439,24 +468,26 @@ SyntheticEvent.Interface = EventInterface;
/**
* Helper to reduce boilerplate when creating subclasses.
*
* @param {function} Class
* @param {?object} Interface
*/
SyntheticEvent.augmentClass = function (Class, Interface) {
SyntheticEvent.extend = function (Interface) {
var Super = this;
var E = function () {};
E.prototype = Super.prototype;
var prototype = new E();
function Class() {
return Super.apply(this, arguments);
}
_assign(prototype, Class.prototype);
Class.prototype = prototype;
Class.prototype.constructor = Class;
Class.Interface = _assign({}, Super.Interface, Interface);
Class.augmentClass = Super.augmentClass;
Class.extend = Super.extend;
addEventPoolingTo(Class);
return Class;
};
/** Proxying after everything set on SyntheticEvent
@ -490,6 +521,14 @@ function addEventPoolingTo(EventConstructor) {
EventConstructor.release = releasePooledEvent;
}
// Do not uses the below two methods directly!
// Instead use constants exported from DOMTopLevelEventTypes in ReactDOM.
// (It is the only module that is allowed to access these methods.)
function unsafeCastStringToDOMTopLevelType(topLevelType) {
return topLevelType;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -606,90 +645,101 @@ function getVendorPrefixedEventName(eventName) {
}
}
return '';
return eventName;
}
/**
* Types of raw signals from the browser caught at the top level.
*
* For events like 'submit' which don't consistently bubble (which we
* trap at a lower node than `document`), binding at `document` would
* cause duplicate events so we don't include them here.
* To identify top level events in ReactDOM, we use constants defined by this
* module. This is the only module that uses the unsafe* methods to express
* that the constants actually correspond to the browser event names. This lets
* us save some bundle size by avoiding a top level type -> event name map.
* The rest of ReactDOM code should import top level types from this file.
*/
var topLevelTypes$1 = {
topAbort: 'abort',
topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
topBlur: 'blur',
topCancel: 'cancel',
topCanPlay: 'canplay',
topCanPlayThrough: 'canplaythrough',
topChange: 'change',
topClick: 'click',
topClose: 'close',
topCompositionEnd: 'compositionend',
topCompositionStart: 'compositionstart',
topCompositionUpdate: 'compositionupdate',
topContextMenu: 'contextmenu',
topCopy: 'copy',
topCut: 'cut',
topDoubleClick: 'dblclick',
topDrag: 'drag',
topDragEnd: 'dragend',
topDragEnter: 'dragenter',
topDragExit: 'dragexit',
topDragLeave: 'dragleave',
topDragOver: 'dragover',
topDragStart: 'dragstart',
topDrop: 'drop',
topDurationChange: 'durationchange',
topEmptied: 'emptied',
topEncrypted: 'encrypted',
topEnded: 'ended',
topError: 'error',
topFocus: 'focus',
topInput: 'input',
topKeyDown: 'keydown',
topKeyPress: 'keypress',
topKeyUp: 'keyup',
topLoadedData: 'loadeddata',
topLoad: 'load',
topLoadedMetadata: 'loadedmetadata',
topLoadStart: 'loadstart',
topMouseDown: 'mousedown',
topMouseMove: 'mousemove',
topMouseOut: 'mouseout',
topMouseOver: 'mouseover',
topMouseUp: 'mouseup',
topPaste: 'paste',
topPause: 'pause',
topPlay: 'play',
topPlaying: 'playing',
topProgress: 'progress',
topRateChange: 'ratechange',
topScroll: 'scroll',
topSeeked: 'seeked',
topSeeking: 'seeking',
topSelectionChange: 'selectionchange',
topStalled: 'stalled',
topSuspend: 'suspend',
topTextInput: 'textInput',
topTimeUpdate: 'timeupdate',
topToggle: 'toggle',
topTouchCancel: 'touchcancel',
topTouchEnd: 'touchend',
topTouchMove: 'touchmove',
topTouchStart: 'touchstart',
topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
topVolumeChange: 'volumechange',
topWaiting: 'waiting',
topWheel: 'wheel'
};
var TOP_ABORT = unsafeCastStringToDOMTopLevelType('abort');
var TOP_ANIMATION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationend'));
var TOP_ANIMATION_ITERATION = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationiteration'));
var TOP_ANIMATION_START = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationstart'));
var TOP_BLUR = unsafeCastStringToDOMTopLevelType('blur');
var TOP_CAN_PLAY = unsafeCastStringToDOMTopLevelType('canplay');
var TOP_CAN_PLAY_THROUGH = unsafeCastStringToDOMTopLevelType('canplaythrough');
var TOP_CANCEL = unsafeCastStringToDOMTopLevelType('cancel');
var TOP_CHANGE = unsafeCastStringToDOMTopLevelType('change');
var TOP_CLICK = unsafeCastStringToDOMTopLevelType('click');
var TOP_CLOSE = unsafeCastStringToDOMTopLevelType('close');
var TOP_COMPOSITION_END = unsafeCastStringToDOMTopLevelType('compositionend');
var TOP_COMPOSITION_START = unsafeCastStringToDOMTopLevelType('compositionstart');
var TOP_COMPOSITION_UPDATE = unsafeCastStringToDOMTopLevelType('compositionupdate');
var TOP_CONTEXT_MENU = unsafeCastStringToDOMTopLevelType('contextmenu');
var TOP_COPY = unsafeCastStringToDOMTopLevelType('copy');
var TOP_CUT = unsafeCastStringToDOMTopLevelType('cut');
var TOP_DOUBLE_CLICK = unsafeCastStringToDOMTopLevelType('dblclick');
var TOP_DRAG = unsafeCastStringToDOMTopLevelType('drag');
var TOP_DRAG_END = unsafeCastStringToDOMTopLevelType('dragend');
var TOP_DRAG_ENTER = unsafeCastStringToDOMTopLevelType('dragenter');
var TOP_DRAG_EXIT = unsafeCastStringToDOMTopLevelType('dragexit');
var TOP_DRAG_LEAVE = unsafeCastStringToDOMTopLevelType('dragleave');
var TOP_DRAG_OVER = unsafeCastStringToDOMTopLevelType('dragover');
var TOP_DRAG_START = unsafeCastStringToDOMTopLevelType('dragstart');
var TOP_DROP = unsafeCastStringToDOMTopLevelType('drop');
var TOP_DURATION_CHANGE = unsafeCastStringToDOMTopLevelType('durationchange');
var TOP_EMPTIED = unsafeCastStringToDOMTopLevelType('emptied');
var TOP_ENCRYPTED = unsafeCastStringToDOMTopLevelType('encrypted');
var TOP_ENDED = unsafeCastStringToDOMTopLevelType('ended');
var TOP_ERROR = unsafeCastStringToDOMTopLevelType('error');
var TOP_FOCUS = unsafeCastStringToDOMTopLevelType('focus');
var BrowserEventConstants = {
topLevelTypes: topLevelTypes$1
};
var TOP_INPUT = unsafeCastStringToDOMTopLevelType('input');
var TOP_KEY_DOWN = unsafeCastStringToDOMTopLevelType('keydown');
var TOP_KEY_PRESS = unsafeCastStringToDOMTopLevelType('keypress');
var TOP_KEY_UP = unsafeCastStringToDOMTopLevelType('keyup');
var TOP_LOAD = unsafeCastStringToDOMTopLevelType('load');
var TOP_LOAD_START = unsafeCastStringToDOMTopLevelType('loadstart');
var TOP_LOADED_DATA = unsafeCastStringToDOMTopLevelType('loadeddata');
var TOP_LOADED_METADATA = unsafeCastStringToDOMTopLevelType('loadedmetadata');
var TOP_MOUSE_DOWN = unsafeCastStringToDOMTopLevelType('mousedown');
var TOP_MOUSE_MOVE = unsafeCastStringToDOMTopLevelType('mousemove');
var TOP_MOUSE_OUT = unsafeCastStringToDOMTopLevelType('mouseout');
var TOP_MOUSE_OVER = unsafeCastStringToDOMTopLevelType('mouseover');
var TOP_MOUSE_UP = unsafeCastStringToDOMTopLevelType('mouseup');
var TOP_PASTE = unsafeCastStringToDOMTopLevelType('paste');
var TOP_PAUSE = unsafeCastStringToDOMTopLevelType('pause');
var TOP_PLAY = unsafeCastStringToDOMTopLevelType('play');
var TOP_PLAYING = unsafeCastStringToDOMTopLevelType('playing');
var TOP_PROGRESS = unsafeCastStringToDOMTopLevelType('progress');
var TOP_RATE_CHANGE = unsafeCastStringToDOMTopLevelType('ratechange');
var TOP_SCROLL = unsafeCastStringToDOMTopLevelType('scroll');
var TOP_SEEKED = unsafeCastStringToDOMTopLevelType('seeked');
var TOP_SEEKING = unsafeCastStringToDOMTopLevelType('seeking');
var TOP_SELECTION_CHANGE = unsafeCastStringToDOMTopLevelType('selectionchange');
var TOP_STALLED = unsafeCastStringToDOMTopLevelType('stalled');
var TOP_SUSPEND = unsafeCastStringToDOMTopLevelType('suspend');
var TOP_TEXT_INPUT = unsafeCastStringToDOMTopLevelType('textInput');
var TOP_TIME_UPDATE = unsafeCastStringToDOMTopLevelType('timeupdate');
var TOP_TOGGLE = unsafeCastStringToDOMTopLevelType('toggle');
var TOP_TOUCH_CANCEL = unsafeCastStringToDOMTopLevelType('touchcancel');
var TOP_TOUCH_END = unsafeCastStringToDOMTopLevelType('touchend');
var TOP_TOUCH_MOVE = unsafeCastStringToDOMTopLevelType('touchmove');
var TOP_TOUCH_START = unsafeCastStringToDOMTopLevelType('touchstart');
var TOP_TRANSITION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('transitionend'));
var TOP_VOLUME_CHANGE = unsafeCastStringToDOMTopLevelType('volumechange');
var TOP_WAITING = unsafeCastStringToDOMTopLevelType('waiting');
var TOP_WHEEL = unsafeCastStringToDOMTopLevelType('wheel');
// List of events that need to be individually attached to media elements.
// Note that events in this list will *not* be listened to at the top level
// unless they're explicitly whitelisted in `ReactBrowserEventEmitter.listenTo`.
var findDOMNode = ReactDOM.findDOMNode;
var _ReactDOM$__SECRET_IN = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
@ -701,14 +751,35 @@ var ReactDOMComponentTree = _ReactDOM$__SECRET_IN.ReactDOMComponentTree;
var ReactDOMEventListener = _ReactDOM$__SECRET_IN.ReactDOMEventListener;
var topLevelTypes = BrowserEventConstants.topLevelTypes;
function Event(suffix) {}
/**
* @class ReactTestUtils
*/
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on an `Element` node.
* @param {number} topLevelType A number from `TopLevelEventTypes`
* @param {!Element} node The dom to simulate an event occurring on.
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
function simulateNativeEventOnNode(topLevelType, node, fakeNativeEvent) {
fakeNativeEvent.target = node;
ReactDOMEventListener.dispatchEvent(topLevelType, fakeNativeEvent);
}
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on the `ReactDOMComponent` `comp`.
* @param {Object} topLevelType A type from `BrowserEventConstants.topLevelTypes`.
* @param {!ReactDOMComponent} comp
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
function simulateNativeEventOnDOMComponent(topLevelType, comp, fakeNativeEvent) {
simulateNativeEventOnNode(topLevelType, findDOMNode(comp), fakeNativeEvent);
}
function findAllInRenderedFiberTreeInternal(fiber, test) {
if (!fiber) {
return [];
@ -727,7 +798,7 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
}
}
if (node.child) {
node.child['return'] = node;
node.child.return = node;
node = node.child;
continue;
}
@ -735,12 +806,12 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
return ret;
}
while (!node.sibling) {
if (!node['return'] || node['return'] === currentParent) {
if (!node.return || node.return === currentParent) {
return ret;
}
node = node['return'];
node = node.return;
}
node.sibling['return'] = node['return'];
node.sibling.return = node.return;
node = node.sibling;
}
}
@ -921,29 +992,6 @@ var ReactTestUtils = {
return this;
},
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on an `Element` node.
* @param {Object} topLevelType A type from `BrowserEventConstants.topLevelTypes`
* @param {!Element} node The dom to simulate an event occurring on.
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
simulateNativeEventOnNode: function (topLevelType, node, fakeNativeEvent) {
fakeNativeEvent.target = node;
ReactDOMEventListener.dispatchEvent(topLevelType, fakeNativeEvent);
},
/**
* Simulates a top level event being dispatched from a raw event that occurred
* on the `ReactDOMComponent` `comp`.
* @param {Object} topLevelType A type from `BrowserEventConstants.topLevelTypes`.
* @param {!ReactDOMComponent} comp
* @param {?Event} fakeNativeEvent Fake native event to use in SyntheticEvent.
*/
simulateNativeEventOnDOMComponent: function (topLevelType, comp, fakeNativeEvent) {
ReactTestUtils.simulateNativeEventOnNode(topLevelType, findDOMNode(comp), fakeNativeEvent);
},
nativeTouchData: function (x, y) {
return {
touches: [{ pageX: x, pageY: y }]
@ -993,17 +1041,16 @@ function makeSimulator(eventType) {
// Normally extractEvent enqueues a state restore, but we'll just always
// do that since we we're by-passing it here.
ReactControlledComponent.enqueueStateRestore(domNode);
EventPluginHub.enqueueEvents(event);
EventPluginHub.processEventQueue(true);
EventPluginHub.runEventsInBatch(event, true);
});
ReactControlledComponent.restoreStateIfNeeded();
};
}
function buildSimulators() {
ReactTestUtils.Simulate = {};
var eventType;
var eventType = void 0;
for (eventType in EventPluginRegistry.eventNameDispatchConfigs) {
/**
* @param {!Element|ReactDOMComponent} domComponentOrNode
@ -1043,32 +1090,33 @@ buildSimulators();
* to dispatch synthetic events.
*/
function makeNativeSimulator(eventType) {
function makeNativeSimulator(eventType, topLevelType) {
return function (domComponentOrNode, nativeEventData) {
var fakeNativeEvent = new Event(eventType);
_assign(fakeNativeEvent, nativeEventData);
if (ReactTestUtils.isDOMComponent(domComponentOrNode)) {
ReactTestUtils.simulateNativeEventOnDOMComponent(eventType, domComponentOrNode, fakeNativeEvent);
simulateNativeEventOnDOMComponent(topLevelType, domComponentOrNode, fakeNativeEvent);
} else if (domComponentOrNode.tagName) {
// Will allow on actual dom nodes.
ReactTestUtils.simulateNativeEventOnNode(eventType, domComponentOrNode, fakeNativeEvent);
simulateNativeEventOnNode(topLevelType, domComponentOrNode, fakeNativeEvent);
}
};
}
Object.keys(topLevelTypes).forEach(function (eventType) {
// Event type is stored as 'topClick' - we transform that to 'click'
var convenienceName = eventType.indexOf('top') === 0 ? eventType.charAt(3).toLowerCase() + eventType.substr(4) : eventType;
[[TOP_ABORT, 'abort'], [TOP_ANIMATION_END, 'animationEnd'], [TOP_ANIMATION_ITERATION, 'animationIteration'], [TOP_ANIMATION_START, 'animationStart'], [TOP_BLUR, 'blur'], [TOP_CAN_PLAY_THROUGH, 'canPlayThrough'], [TOP_CAN_PLAY, 'canPlay'], [TOP_CANCEL, 'cancel'], [TOP_CHANGE, 'change'], [TOP_CLICK, 'click'], [TOP_CLOSE, 'close'], [TOP_COMPOSITION_END, 'compositionEnd'], [TOP_COMPOSITION_START, 'compositionStart'], [TOP_COMPOSITION_UPDATE, 'compositionUpdate'], [TOP_CONTEXT_MENU, 'contextMenu'], [TOP_COPY, 'copy'], [TOP_CUT, 'cut'], [TOP_DOUBLE_CLICK, 'doubleClick'], [TOP_DRAG_END, 'dragEnd'], [TOP_DRAG_ENTER, 'dragEnter'], [TOP_DRAG_EXIT, 'dragExit'], [TOP_DRAG_LEAVE, 'dragLeave'], [TOP_DRAG_OVER, 'dragOver'], [TOP_DRAG_START, 'dragStart'], [TOP_DRAG, 'drag'], [TOP_DROP, 'drop'], [TOP_DURATION_CHANGE, 'durationChange'], [TOP_EMPTIED, 'emptied'], [TOP_ENCRYPTED, 'encrypted'], [TOP_ENDED, 'ended'], [TOP_ERROR, 'error'], [TOP_FOCUS, 'focus'], [TOP_INPUT, 'input'], [TOP_KEY_DOWN, 'keyDown'], [TOP_KEY_PRESS, 'keyPress'], [TOP_KEY_UP, 'keyUp'], [TOP_LOAD_START, 'loadStart'], [TOP_LOAD_START, 'loadStart'], [TOP_LOAD, 'load'], [TOP_LOADED_DATA, 'loadedData'], [TOP_LOADED_METADATA, 'loadedMetadata'], [TOP_MOUSE_DOWN, 'mouseDown'], [TOP_MOUSE_MOVE, 'mouseMove'], [TOP_MOUSE_OUT, 'mouseOut'], [TOP_MOUSE_OVER, 'mouseOver'], [TOP_MOUSE_UP, 'mouseUp'], [TOP_PASTE, 'paste'], [TOP_PAUSE, 'pause'], [TOP_PLAY, 'play'], [TOP_PLAYING, 'playing'], [TOP_PROGRESS, 'progress'], [TOP_RATE_CHANGE, 'rateChange'], [TOP_SCROLL, 'scroll'], [TOP_SEEKED, 'seeked'], [TOP_SEEKING, 'seeking'], [TOP_SELECTION_CHANGE, 'selectionChange'], [TOP_STALLED, 'stalled'], [TOP_SUSPEND, 'suspend'], [TOP_TEXT_INPUT, 'textInput'], [TOP_TIME_UPDATE, 'timeUpdate'], [TOP_TOGGLE, 'toggle'], [TOP_TOUCH_CANCEL, 'touchCancel'], [TOP_TOUCH_END, 'touchEnd'], [TOP_TOUCH_MOVE, 'touchMove'], [TOP_TOUCH_START, 'touchStart'], [TOP_TRANSITION_END, 'transitionEnd'], [TOP_VOLUME_CHANGE, 'volumeChange'], [TOP_WAITING, 'waiting'], [TOP_WHEEL, 'wheel']].forEach(function (_ref) {
var topLevelType = _ref[0],
eventType = _ref[1];
/**
* @param {!Element|ReactDOMComponent} domComponentOrNode
* @param {?Event} nativeEventData Fake native event to use in SyntheticEvent.
*/
ReactTestUtils.SimulateNative[convenienceName] = makeNativeSimulator(eventType);
ReactTestUtils.SimulateNative[eventType] = makeNativeSimulator(eventType, topLevelType);
});
var ReactTestUtils$2 = Object.freeze({
var ReactTestUtils$2 = ({
default: ReactTestUtils
});
@ -1076,7 +1124,7 @@ var ReactTestUtils$3 = ( ReactTestUtils$2 && ReactTestUtils ) || ReactTestUtils$
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
var testUtils = ReactTestUtils$3['default'] ? ReactTestUtils$3['default'] : ReactTestUtils$3;
var testUtils = ReactTestUtils$3.default ? ReactTestUtils$3.default : ReactTestUtils$3;
return testUtils;

18446
devtools/client/shared/vendor/react-dom.js поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

238
devtools/client/shared/vendor/react.js поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
/** @license React v16.2.0
/** @license React v16.4.1
* react.production.min.js
*
* Copyright (c) 2013-present, Facebook, Inc.
@ -105,17 +105,22 @@ var objectAssign = shouldUseNative() ? Object.assign : function (target, source)
// TODO: this is special because it gets imported during build.
var ReactVersion = '16.2.0';
var ReactVersion = '16.4.1';
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
var hasSymbol = typeof Symbol === 'function' && Symbol['for'];
var hasSymbol = typeof Symbol === 'function' && Symbol.for;
var REACT_ELEMENT_TYPE = hasSymbol ? Symbol['for']('react.element') : 0xeac7;
var REACT_CALL_TYPE = hasSymbol ? Symbol['for']('react.call') : 0xeac8;
var REACT_RETURN_TYPE = hasSymbol ? Symbol['for']('react.return') : 0xeac9;
var REACT_PORTAL_TYPE = hasSymbol ? Symbol['for']('react.portal') : 0xeaca;
var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol['for']('react.fragment') : 0xeacb;
var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace;
var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
var REACT_TIMEOUT_TYPE = hasSymbol ? Symbol.for('react.timeout') : 0xead1;
var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = '@@iterator';
@ -131,6 +136,39 @@ function getIteratorFn(maybeIterable) {
return null;
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
function invariant(condition, format, a, b, c, d, e, f) {
if (!condition) {
var error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(format.replace(/%s/g, function () {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
}
var invariant_1 = invariant;
// Relying on the `invariant()` implementation lets us
// have preserve the format and params in the www builds.
/**
* WARNING: DO NOT manually require this module.
* This is a replacement for `invariant(...)` used by the error code system
@ -139,22 +177,52 @@ function getIteratorFn(maybeIterable) {
*/
function reactProdInvariant(code) {
var argCount = arguments.length - 1;
var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;
var url = 'https://reactjs.org/docs/error-decoder.html?invariant=' + code;
for (var argIdx = 0; argIdx < argCount; argIdx++) {
message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
url += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
}
message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';
var error = new Error(message);
error.name = 'Invariant Violation';
error.framesToPop = 1; // we don't care about reactProdInvariant's own frame
throw error;
// Rename it so that our build transform doesn't atttempt
// to replace this invariant() call with reactProdInvariant().
var i = invariant_1;
i(false,
// The error code is intentionally part of the message (and
// not the format argument) so that we could deduplicate
// different errors in logs based on the code.
'Minified React error #' + code + '; visit %s ' + 'for the full message or use the non-minified dev environment ' + 'for full errors and additional helpful warnings. ', url);
}
// Exports ReactDOM.createRoot
// Experimental error-boundary API that can recover from errors within a single
// render phase
// Suspense
var enableSuspense = false;
// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
// In some cases, StrictMode should also double-render lifecycles.
// This can be confusing for tests though,
// And it can be bad for performance in production.
// This feature flag can be used to control the behavior:
// To preserve the "Pause on caught exceptions" behavior of the debugger, we
// replay the begin phase of a failed component inside invokeGuardedCallback.
// Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
// Warn about legacy context API
// Gather advanced timing metrics for Profiler subtrees.
// Only used in www builds.
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -169,14 +237,6 @@ var emptyObject = {};
var emptyObject_1 = emptyObject;
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
/**
* Forked from fbjs/warning:
* https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js
@ -369,46 +429,33 @@ Component.prototype.forceUpdate = function (callback) {
* we would like to deprecate them, we're not going to move them over to this
* modern base class. Instead, we define a getter that warns if it's accessed.
*/
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
/**
* Base class helpers for the updating state of a component.
* Convenience component with default shallow equality check for sCU.
*/
function PureComponent(props, context, updater) {
// Duplicated from Component.
this.props = props;
this.context = context;
this.refs = emptyObject_1;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
}
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
objectAssign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;
function AsyncComponent(props, context, updater) {
// Duplicated from Component.
this.props = props;
this.context = context;
this.refs = emptyObject_1;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
// an immutable object with a single mutable value
function createRef() {
var refObject = {
current: null
};
return refObject;
}
var asyncComponentPrototype = AsyncComponent.prototype = new ComponentDummy();
asyncComponentPrototype.constructor = AsyncComponent;
// Avoid an extra prototype jump for these methods.
objectAssign(asyncComponentPrototype, Component.prototype);
asyncComponentPrototype.unstable_isAsyncReactComponent = true;
asyncComponentPrototype.render = function () {
return this.props.children;
};
/**
* Keeps track of the current owner.
*
@ -462,7 +509,7 @@ function hasValidKey(config) {
*/
var ReactElement = function (type, key, ref, self, source, owner, props) {
var element = {
// This tag allow us to uniquely identify this as a React Element
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
@ -483,7 +530,7 @@ var ReactElement = function (type, key, ref, self, source, owner, props) {
* See https://reactjs.org/docs/react-api.html#createelement
*/
function createElement(type, config, children) {
var propName;
var propName = void 0;
// Reserved names are extracted
var props = {};
@ -546,7 +593,7 @@ function createFactory(type) {
// easily accessed on elements. E.g. `<Foo />.type === Foo`.
// This should not be named `constructor` since this may not be the function
// that created the element, and it may not even be a constructor.
// Legacy hook TODO: Warn if this is accessed
// Legacy hook: remove it
factory.type = type;
return factory;
}
@ -562,7 +609,9 @@ function cloneAndReplaceKey(oldElement, newKey) {
* See https://reactjs.org/docs/react-api.html#cloneelement
*/
function cloneElement(element, config, children) {
var propName;
!!(element === null || element === undefined) ? reactProdInvariant('267', element) : void 0;
var propName = void 0;
// Original props are copied
var props = objectAssign({}, element.props);
@ -591,7 +640,7 @@ function cloneElement(element, config, children) {
}
// Remaining properties override existing props
var defaultProps;
var defaultProps = void 0;
if (element.type && element.type.defaultProps) {
defaultProps = element.type.defaultProps;
}
@ -723,8 +772,6 @@ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
case 'object':
switch (children.$$typeof) {
case REACT_ELEMENT_TYPE:
case REACT_CALL_TYPE:
case REACT_RETURN_TYPE:
case REACT_PORTAL_TYPE:
invokeCallback = true;
}
@ -739,8 +786,8 @@ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
return 1;
}
var child;
var nextName;
var child = void 0;
var nextName = void 0;
var subtreeCount = 0; // Count of children found in the current subtree.
var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
@ -754,7 +801,7 @@ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
var iteratorFn = getIteratorFn(children);
if (typeof iteratorFn === 'function') {
var iterator = iteratorFn.call(children);
var step;
var step = void 0;
var ii = 0;
while (!(step = iterator.next()).done) {
child = step.value;
@ -823,7 +870,7 @@ function forEachSingleChild(bookKeeping, child, name) {
/**
* Iterates through children that are typically specified as `props.children`.
*
* See https://reactjs.org/docs/react-api.html#react.children.foreach
* See https://reactjs.org/docs/react-api.html#reactchildrenforeach
*
* The provided forEachFunc(child, index) will be called for each
* leaf child.
@ -875,7 +922,7 @@ function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
/**
* Maps children that are typically specified as `props.children`.
*
* See https://reactjs.org/docs/react-api.html#react.children.map
* See https://reactjs.org/docs/react-api.html#reactchildrenmap
*
* The provided mapFunction(child, key, index) will be called for each
* leaf child.
@ -898,12 +945,12 @@ function mapChildren(children, func, context) {
* Count the number of children that are typically specified as
* `props.children`.
*
* See https://reactjs.org/docs/react-api.html#react.children.count
* See https://reactjs.org/docs/react-api.html#reactchildrencount
*
* @param {?*} children Children tree container.
* @return {number} The number of children.
*/
function countChildren(children, context) {
function countChildren(children) {
return traverseAllChildren(children, emptyFunction_1.thatReturnsNull, null);
}
@ -911,7 +958,7 @@ function countChildren(children, context) {
* Flatten a children object (typically specified as `props.children`) and
* return an array with appropriately re-keyed children.
*
* See https://reactjs.org/docs/react-api.html#react.children.toarray
* See https://reactjs.org/docs/react-api.html#reactchildrentoarray
*/
function toArray(children) {
var result = [];
@ -923,7 +970,7 @@ function toArray(children) {
* Returns the first child in a collection of children and verifies that there
* is only one child in the collection.
*
* See https://reactjs.org/docs/react-api.html#react.children.only
* See https://reactjs.org/docs/react-api.html#reactchildrenonly
*
* The current implementation of this function assumes that a single child gets
* passed without a wrapper, but the purpose of this helper function is to
@ -938,6 +985,47 @@ function onlyChild(children) {
return children;
}
function createContext(defaultValue, calculateChangedBits) {
if (calculateChangedBits === undefined) {
calculateChangedBits = null;
} else {
}
var context = {
$$typeof: REACT_CONTEXT_TYPE,
_calculateChangedBits: calculateChangedBits,
_defaultValue: defaultValue,
_currentValue: defaultValue,
// As a workaround to support multiple concurrent renderers, we categorize
// some renderers as primary and others as secondary. We only expect
// there to be two concurrent renderers at most: React Native (primary) and
// Fabric (secondary); React DOM (primary) and React ART (secondary).
// Secondary renderers store their context values on separate fields.
_currentValue2: defaultValue,
_changedBits: 0,
_changedBits2: 0,
// These are circular
Provider: null,
Consumer: null
};
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context
};
context.Consumer = context;
return context;
}
function forwardRef(render) {
return {
$$typeof: REACT_FORWARD_REF_TYPE,
render: render
};
}
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
@ -961,11 +1049,17 @@ var React = {
only: onlyChild
},
createRef: createRef,
Component: Component,
PureComponent: PureComponent,
unstable_AsyncComponent: AsyncComponent,
createContext: createContext,
forwardRef: forwardRef,
Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
unstable_AsyncMode: REACT_ASYNC_MODE_TYPE,
unstable_Profiler: REACT_PROFILER_TYPE,
createElement: createElement,
cloneElement: cloneElement,
@ -981,9 +1075,13 @@ var React = {
}
};
if (enableSuspense) {
React.Timeout = REACT_TIMEOUT_TYPE;
}
var React$2 = Object.freeze({
var React$2 = ({
default: React
});
@ -991,7 +1089,7 @@ var React$3 = ( React$2 && React ) || React$2;
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
var react = React$3['default'] ? React$3['default'] : React$3;
var react = React$3.default ? React$3.default : React$3;
return react;

Просмотреть файл

@ -79,12 +79,12 @@ class App extends Component {
return;
}
const inputField = this.node.querySelector(".jsterm-input-node");
const input = event.target;
// Cleanup function if notification is closed by the user.
const removeCallback = (eventType) => {
if (eventType == "removed") {
inputField.removeEventListener("keyup", pasteKeyUpHandler);
input.removeEventListener("keyup", pasteKeyUpHandler);
dispatch(actions.removeNotification("selfxss-notification"));
}
};
@ -99,18 +99,17 @@ class App extends Component {
removeCallback
));
// Remove notification automatically when the user
// types "allow pasting".
function pasteKeyUpHandler() {
const value = inputField.value || inputField.textContent;
// Remove notification automatically when the user types "allow pasting".
const pasteKeyUpHandler = (e) => {
const value = e.target.value;
if (value.includes(SELF_XSS_OK)) {
dispatch(actions.removeNotification("selfxss-notification"));
inputField.removeEventListener("keyup", pasteKeyUpHandler);
input.removeEventListener("keyup", pasteKeyUpHandler);
WebConsoleUtils.usageCount = WebConsoleUtils.CONSOLE_ENTRY_THRESHOLD;
}
}
};
inputField.addEventListener("keyup", pasteKeyUpHandler);
input.addEventListener("keyup", pasteKeyUpHandler);
}
// Rendering

Просмотреть файл

@ -277,7 +277,11 @@ class JSTerm extends Component {
}
}
});
this.editor.appendToLocalElement(this.node);
const cm = this.editor.codeMirror;
cm.on("paste", (_, event) => this.props.onPaste(event));
cm.on("drop", (_, event) => this.props.onPaste(event));
}
} else if (this.inputNode) {
this.inputNode.addEventListener("keypress", this._keyPress);

Просмотреть файл

@ -194,6 +194,7 @@ skip-if = verify
[browser_jsterm_autocomplete_inside_text.js]
[browser_jsterm_autocomplete_native_getters.js]
[browser_jsterm_autocomplete_nav_and_tab_key.js]
[browser_jsterm_autocomplete_paste_undo.js]
[browser_jsterm_autocomplete_return_key_no_selection.js]
[browser_jsterm_autocomplete_return_key.js]
[browser_jsterm_autocomplete-properties-with-non-alphanumeric-names.js]

Просмотреть файл

@ -0,0 +1,61 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,<p>test for bug 642615</p>";
XPCOMUtils.defineLazyServiceGetter(
this,
"clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
"nsIClipboardHelper"
);
const stringToCopy = "foobazbarBug642615";
add_task(async function() {
const {jsterm, ui} = await openNewTabAndConsole(TEST_URI);
ui.clearOutput();
ok(!jsterm.completeNode.value, "no completeNode.value");
jsterm.setInputValue("doc");
info("wait for completion value after typing 'docu'");
let onAutocompleteUpdated = jsterm.once("autocomplete-updated");
EventUtils.sendString("u");
await onAutocompleteUpdated;
const completionValue = jsterm.completeNode.value;
info(`Copy "${stringToCopy}" in clipboard`);
await waitForClipboardPromise(() =>
clipboardHelper.copyString(stringToCopy), stringToCopy);
jsterm.setInputValue("docu");
info("wait for completion update after clipboard paste");
onAutocompleteUpdated = jsterm.once("autocomplete-updated");
goDoCommand("cmd_paste");
await onAutocompleteUpdated;
ok(!jsterm.completeNode.value, "no completion value after paste");
info("wait for completion update after undo");
onAutocompleteUpdated = jsterm.once("autocomplete-updated");
goDoCommand("cmd_undo");
await onAutocompleteUpdated;
is(jsterm.completeNode.value, completionValue, "same completeNode.value after undo");
info("wait for completion update after clipboard paste (ctrl-v)");
onAutocompleteUpdated = jsterm.once("autocomplete-updated");
EventUtils.synthesizeKey("v", {accelKey: true});
await onAutocompleteUpdated;
ok(!jsterm.completeNode.value, "no completion value after paste (ctrl-v)");
});

Просмотреть файл

@ -5,7 +5,7 @@
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,<p>test for bug 642615 & 994134</p>";
const TEST_URI = "data:text/html;charset=utf-8,<p>Test self-XSS protection</p>";
XPCOMUtils.defineLazyServiceGetter(
this,
@ -14,90 +14,51 @@ XPCOMUtils.defineLazyServiceGetter(
"nsIClipboardHelper"
);
const WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
const stringToCopy = "foobazbarBug642615";
const stringToCopy = "EvilCommand";
add_task(async function() {
await pushPref("devtools.selfxss.count", 0);
const {jsterm, ui} = await openNewTabAndConsole(TEST_URI);
ui.clearOutput();
ok(!jsterm.completeNode.value, "no completeNode.value");
jsterm.setInputValue("doc");
info("wait for completion value after typing 'docu'");
let onAutocompleteUpdated = jsterm.once("autocomplete-updated");
EventUtils.sendString("u");
await onAutocompleteUpdated;
const completionValue = jsterm.completeNode.value;
// Arguments: expected, setup.
await waitForClipboardPromise(() =>
clipboardHelper.copyString(stringToCopy), stringToCopy);
await testSelfXss(jsterm);
jsterm.setInputValue("docu");
info("wait for completion update after clipboard paste");
updateEditUIVisibility();
onAutocompleteUpdated = jsterm.once("autocomplete-updated");
goDoCommand("cmd_paste");
await onAutocompleteUpdated;
ok(!jsterm.completeNode.value, "no completion value after paste");
info("wait for completion update after undo");
onAutocompleteUpdated = jsterm.once("autocomplete-updated");
goDoCommand("cmd_undo");
await onAutocompleteUpdated;
is(jsterm.completeNode.value, completionValue, "same completeNode.value after undo");
info("wait for completion update after clipboard paste (ctrl-v)");
onAutocompleteUpdated = jsterm.once("autocomplete-updated");
EventUtils.synthesizeKey("v", {accelKey: true});
await onAutocompleteUpdated;
ok(!jsterm.completeNode.value, "no completion value after paste (ctrl-v)");
// Run test with legacy JsTerm
await performTest();
// And then run it with the CodeMirror-powered one.
await pushPref("devtools.webconsole.jsterm.codeMirror", true);
await performTest();
});
// Self xss prevention tests (bug 994134)
async function testSelfXss(jsterm) {
async function performTest() {
await pushPref("devtools.selfxss.count", 0);
const {jsterm} = await openNewTabAndConsole(TEST_URI);
const {document} = jsterm.hud;
info("Self-xss paste tests");
WebConsoleUtils.usageCount = 0;
is(WebConsoleUtils.usageCount, 0, "Test for usage count getter");
// Input some commands to check if usage counting is working
for (let i = 0; i <= 3; i++) {
jsterm.setInputValue(i);
jsterm.setInputValue(i.toString());
jsterm.execute();
}
is(WebConsoleUtils.usageCount, 4, "Usage count incremented");
WebConsoleUtils.usageCount = 0;
updateEditUIVisibility();
const oldVal = jsterm.getInputValue();
info(`Copy "${stringToCopy}" in clipboard`);
await waitForClipboardPromise(() =>
clipboardHelper.copyString(stringToCopy), stringToCopy);
goDoCommand("cmd_paste");
const notificationbox =
jsterm.hud.document.getElementById("webconsole-notificationbox");
const notificationbox = document.getElementById("webconsole-notificationbox");
const notification = notificationbox.querySelector(".notification");
is(notification.getAttribute("data-key"), "selfxss-notification",
"Self-xss notification shown");
is(oldVal, jsterm.getInputValue(), "Paste blocked by self-xss prevention");
is(jsterm.getInputValue(), "", "Paste blocked by self-xss prevention");
// Allow pasting
jsterm.setInputValue("allow pasting");
const evt = document.createEvent("KeyboardEvent");
evt.initKeyEvent("keyup", true, true, window,
0, 0, 0, 0,
0, " ".charCodeAt(0));
jsterm.inputNode.dispatchEvent(evt);
const allowToken = "allow pasting";
for (const char of allowToken) {
EventUtils.sendString(char);
}
jsterm.setInputValue("");
goDoCommand("cmd_paste");
is(stringToCopy, jsterm.getInputValue(), "Paste works");
is(jsterm.getInputValue(), stringToCopy, "Paste works");
}

Просмотреть файл

@ -686,7 +686,7 @@ const browsingContextTargetPrototype = {
_onWorkerTargetActorListChanged() {
this._workerTargetActorList.onListChanged = null;
this.conn.sendActorEvent(this.actorID, "workerListChanged");
this.emit("workerListChanged");
},
observe(subject, topic, data) {
@ -820,9 +820,7 @@ const browsingContextTargetPrototype = {
return;
}
this.conn.send({
from: this.actorID,
type: "frameUpdate",
this.emit("frameUpdate", {
frames: windows
});
},
@ -837,9 +835,7 @@ const browsingContextTargetPrototype = {
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.outerWindowID;
this.conn.send({
from: this.actorID,
type: "frameUpdate",
this.emit("frameUpdate", {
frames: [{
id,
destroy: true
@ -848,9 +844,7 @@ const browsingContextTargetPrototype = {
},
_notifyDocShellDestroyAll() {
this.conn.send({
from: this.actorID,
type: "frameUpdate",
this.emit("frameUpdate", {
destroyAll: true
});
},
@ -933,8 +927,7 @@ const browsingContextTargetPrototype = {
this._attached = false;
this.conn.send({ from: this.actorID,
type: "tabDetached" });
this.emit("tabDetached");
return true;
},
@ -1257,9 +1250,7 @@ const browsingContextTargetPrototype = {
configurable: true
});
this.emit("changed-toplevel-document");
this.conn.send({
from: this.actorID,
type: "frameUpdate",
this.emit("frameUpdate", {
selected: this.outerWindowID
});
},
@ -1365,9 +1356,7 @@ const browsingContextTargetPrototype = {
}
threadActor.disableAllBreakpoints();
this.conn.send({
from: this.actorID,
type: "tabNavigated",
this.emit("tabNavigated", {
url: newURI,
nativeConsoleAPI: true,
state: "start",
@ -1407,9 +1396,7 @@ const browsingContextTargetPrototype = {
threadActor.dbg.enabled = true;
}
this.conn.send({
from: this.actorID,
type: "tabNavigated",
this.emit("tabNavigated", {
url: this.url,
title: this.title,
nativeConsoleAPI: this.hasNativeConsoleAPI(this.window),

Просмотреть файл

@ -30,8 +30,9 @@ types.addDictType("browsingContextTarget.listframes", {
types.addDictType("browsingContextTarget.window", {
id: "string",
parentID: "nullable:string",
url: "string",
title: "string"
url: "nullable:string", // should be present if not destroying
title: "nullable:string", // should be present if not destroying
destroy: "nullable:boolean" // not present if not destroying
});
types.addDictType("browsingContextTarget.workers", {
@ -110,6 +111,28 @@ const browsingContextTargetSpecPrototype = {
response: {}
}
},
events: {
tabNavigated: {
type: "tabNavigated",
url: Option(0, "string"),
title: Option(0, "string"),
nativeConsoleAPI: Option(0, "boolean"),
state: Option(0, "string"),
isFrameSwitching: Option(0, "boolean")
},
frameUpdate: {
type: "frameUpdate",
frames: Option(0, "nullable:array:browsingContextTarget.window"),
selected: Option(0, "nullable:number"),
destroyAll: Option(0, "nullable:boolean")
},
tabDetached: {
type: "tabDetached"
},
workerListChanged: {
type: "workerListChanged"
}
}
};
const browsingContextTargetSpec = generateActorSpec(browsingContextTargetSpecPrototype);

Просмотреть файл

@ -1251,6 +1251,7 @@ NetworkMonitor.prototype = {
charset: charset,
sentBody: null,
url: channel.URI.spec,
headersSize: null,
// needed for host specific security info
hostname: channel.URI.host,
discardRequestBody: !this.saveRequestAndResponseBodies,

Просмотреть файл

@ -12,7 +12,7 @@
#include "mozilla/Base64.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/PerformanceMetricsCollector.h"
#include "mozilla/Preferences.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/ContentParent.h"
@ -655,29 +655,27 @@ ChromeUtils::ClearRecentJSDevError(GlobalObject&)
}
#endif // NIGHTLY_BUILD
/* static */ void
ChromeUtils::RequestPerformanceMetrics(GlobalObject&)
/* static */
already_AddRefed<Promise>
ChromeUtils::RequestPerformanceMetrics(GlobalObject& aGlobal,
ErrorResult& aRv)
{
MOZ_ASSERT(XRE_IsParentProcess());
// calling all content processes via IPDL (async)
nsTArray<ContentParent*> children;
ContentParent::GetAll(children);
for (uint32_t i = 0; i < children.Length(); i++) {
mozilla::Unused << children[i]->SendRequestPerformanceMetrics();
// Creating a promise
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(global);
RefPtr<Promise> domPromise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
MOZ_ASSERT(domPromise);
// requesting metrics, that will be returned into the promise
PerformanceMetricsCollector::RequestMetrics(domPromise);
// collecting the current process counters and notifying them
nsTArray<PerformanceInfo> info;
CollectPerformanceInfo(info);
SystemGroup::Dispatch(TaskCategory::Performance,
NS_NewRunnableFunction(
"RequestPerformanceMetrics",
[info]() { mozilla::Unused << NS_WARN_IF(NS_FAILED(NotifyPerformanceInfo(info))); }
)
);
// sending back the promise instance
return domPromise.forget();
}
constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
@ -769,12 +767,20 @@ ChromeUtils::CreateError(const GlobalObject& aGlobal, const nsAString& aMessage,
aRetVal.set(retVal);
}
/* static */ void
ChromeUtils::RequestIOActivity(GlobalObject&)
/* static */ already_AddRefed<Promise>
ChromeUtils::RequestIOActivity(GlobalObject& aGlobal, ErrorResult& aRv)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(Preferences::GetBool(IO_ACTIVITY_ENABLED_PREF, false));
mozilla::Unused << mozilla::net::IOActivityMonitor::NotifyActivities();
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(global);
RefPtr<Promise> domPromise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
MOZ_ASSERT(domPromise);
mozilla::net::IOActivityMonitor::RequestActivities(domPromise);
return domPromise.forget();
}
} // namespace dom

Просмотреть файл

@ -160,7 +160,9 @@ public:
static void ClearRecentJSDevError(GlobalObject& aGlobal);
static void RequestPerformanceMetrics(GlobalObject& aGlobal);
static already_AddRefed<Promise>
RequestPerformanceMetrics(GlobalObject& aGlobal,
ErrorResult& aRv);
static void Import(const GlobalObject& aGlobal,
const nsAString& aResourceURI,
@ -183,7 +185,8 @@ public:
JS::Handle<JSObject*> stack,
JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv);
static void RequestIOActivity(GlobalObject& aGlobal);
static already_AddRefed<Promise>
RequestIOActivity(GlobalObject& aGlobal, ErrorResult& aRv);
};
} // namespace dom

Просмотреть файл

@ -22,7 +22,6 @@ XPIDL_SOURCES += [
'nsIImageLoadingContent.idl',
'nsIMessageManager.idl',
'nsIObjectLoadingContent.idl',
'nsIPerformanceMetrics.idl',
'nsIRemoteWindowContext.idl',
'nsIScriptChannel.idl',
'nsISelectionController.idl',
@ -98,7 +97,6 @@ EXPORTS += [
'nsNameSpaceManager.h',
'nsNodeInfoManager.h',
'nsNodeUtils.h',
'nsPerformanceMetrics.h',
'nsPIDOMWindow.h',
'nsPIDOMWindowInlines.h',
'nsPIWindowRoot.h',
@ -330,7 +328,6 @@ UNIFIED_SOURCES += [
'nsNodeInfoManager.cpp',
'nsNodeUtils.cpp',
'nsOpenURIInFrameParams.cpp',
'nsPerformanceMetrics.cpp',
'nsPlainTextSerializer.cpp',
'nsPropertyTable.cpp',
'nsQueryContentEventResult.cpp',

Просмотреть файл

@ -1,49 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "nsISupports.idl"
#include "nsIArray.idl"
/*
* nsIPerformanceMetricsData is used to store performance data collected
* in all content processes by nsThread and nsWorkerThread.
*
* Each (host, category, pid, wid, pwid) is unique to a given DocGroup or
* Worker, and we collect the number of dispatches and execution duration.
*
* This XPCOM interface reflects the data collected in Performance counters.
* see xpcom/threads/PerformanceCounter.h
*/
[scriptable, builtinclass, uuid(1f9a58c9-be37-4463-8996-c7f5b9a5bef8)]
interface nsIPerformanceMetricsDispatchCategory : nsISupports
{
// DispatchCategory value
readonly attribute unsigned long category;
// Number of dispatch.
readonly attribute unsigned long count;
};
[scriptable, builtinclass, uuid(02b0cdc6-4be2-4154-a8a9-e8d462073200)]
interface nsIPerformanceMetricsData : nsISupports
{
// Host of the document, if any
readonly attribute AUTF8String host;
// process id
readonly attribute unsigned long pid;
// window id
readonly attribute unsigned long long wid;
// "parent" window id
readonly attribute unsigned long long pwid;
// Execution time in microseconds
readonly attribute unsigned long long duration;
// True if the data is collected in a worker
readonly attribute bool worker;
// Dispatch Category counters
readonly attribute nsIArray items;
};

Просмотреть файл

@ -1,125 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* 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/. */
#include <nsIMutableArray.h>
#include <nsArrayUtils.h>
#include <nsPerformanceMetrics.h>
#include "nsComponentManagerUtils.h"
/* ------------------------------------------------------
*
* class PerformanceMetricsDispatchCategory
*
*/
PerformanceMetricsDispatchCategory::PerformanceMetricsDispatchCategory(uint32_t aCategory, uint32_t aCount)
: mCategory(aCategory), mCount(aCount)
{
}
NS_IMPL_ISUPPORTS(PerformanceMetricsDispatchCategory,
nsIPerformanceMetricsDispatchCategory);
NS_IMETHODIMP
PerformanceMetricsDispatchCategory::GetCategory(uint32_t* aCategory)
{
*aCategory = mCategory;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsDispatchCategory::GetCount(uint32_t* aCount)
{
*aCount = mCount;
return NS_OK;
};
/* ------------------------------------------------------
*
* class PerformanceMetricsData
*
*/
PerformanceMetricsData::PerformanceMetricsData(uint32_t aPid, uint64_t aWid,
uint64_t aPwid, const nsCString& aHost,
uint64_t aDuration, bool aWorker,
nsIArray* aItems)
: mPid(aPid), mWid(aWid), mPwid(aPwid), mHost(aHost)
, mDuration(aDuration), mWorker(aWorker)
{
uint32_t len;
nsresult rv = aItems->GetLength(&len);
if (NS_FAILED(rv)) {
NS_ASSERTION(rv == NS_OK, "Failed to ge the length");
}
for (uint32_t i = 0; i < len; i++) {
nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item = do_QueryElementAt(aItems, i);
mItems.AppendElement(item);
}
};
NS_IMPL_ISUPPORTS(PerformanceMetricsData, nsIPerformanceMetricsData);
NS_IMETHODIMP
PerformanceMetricsData::GetHost(nsACString& aHost)
{
aHost = mHost;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsData::GetWorker(bool* aWorker)
{
*aWorker = mWorker;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsData::GetPid(uint32_t* aPid)
{
*aPid = mPid;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsData::GetWid(uint64_t* aWid)
{
*aWid = mWid;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsData::GetDuration(uint64_t* aDuration)
{
*aDuration = mDuration;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsData::GetPwid(uint64_t* aPwid)
{
*aPwid = mPwid;
return NS_OK;
};
NS_IMETHODIMP
PerformanceMetricsData::GetItems(nsIArray** aItems)
{
NS_ENSURE_ARG_POINTER(aItems);
*aItems = nullptr;
nsresult rv = NS_OK;
nsCOMPtr<nsIMutableArray> items =
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t len = mItems.Length();
for (uint32_t i = 0; i < len; i++) {
items->AppendElement(mItems[i]);
}
items.forget(aItems);
return NS_OK;
}

Просмотреть файл

@ -1,48 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef nsPerformanceMetrics_h___
#define nsPerformanceMetrics_h___
#include "nsCOMArray.h"
#include "nsIPerformanceMetrics.h"
#include "nsString.h"
class PerformanceMetricsDispatchCategory final : public nsIPerformanceMetricsDispatchCategory
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPERFORMANCEMETRICSDISPATCHCATEGORY
PerformanceMetricsDispatchCategory(uint32_t aCategory, uint32_t aCount);
private:
~PerformanceMetricsDispatchCategory() = default;
uint32_t mCategory;
uint32_t mCount;
};
class PerformanceMetricsData final : public nsIPerformanceMetricsData
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPERFORMANCEMETRICSDATA
PerformanceMetricsData(uint32_t aPid, uint64_t aWid, uint64_t aPwid, const nsCString& aHost,
uint64_t aDuration, bool aWorker, nsIArray* aItems);
private:
~PerformanceMetricsData() = default;
uint32_t mPid;
uint64_t mWid;
uint64_t mPwid;
nsCString mHost;
uint64_t mDuration;
bool mWorker;
nsCOMArray<nsIPerformanceMetricsDispatchCategory> mItems;
};
#endif // end nsPerformanceMetrics_h__

Просмотреть файл

@ -345,14 +345,48 @@ partial namespace ChromeUtils {
object createError(DOMString message, optional object? stack = null);
/**
* Request performance metrics to the current process & all ontent processes.
* Request performance metrics to the current process & all content processes.
*/
void requestPerformanceMetrics();
[Throws]
Promise<sequence<PerformanceInfoDictionary>> requestPerformanceMetrics();
/**
* Request IOActivityMonitor to send a notification containing I/O activity
* Returns a Promise containing a sequence of I/O activities
*/
void requestIOActivity();
[Throws]
Promise<sequence<IOActivityDataDictionary>> requestIOActivity();
};
/**
* Dictionaries duplicating IPDL types in dom/ipc/DOMTypes.ipdlh
* Used by requestPerformanceMetrics
*/
dictionary CategoryDispatchDictionary
{
unsigned short category = 0;
unsigned short count = 0;
};
dictionary PerformanceInfoDictionary {
DOMString host = "";
unsigned long pid = 0;
unsigned long long wid = 0;
unsigned long long pwid = 0;
unsigned long long duration = 0;
boolean worker = false;
sequence<CategoryDispatchDictionary> items = [];
};
/**
* Used by requestIOActivity() to return the number of bytes
* that were read (rx) and/or written (tx) for a given location.
*
* Locations can be sockets or files.
*/
dictionary IOActivityDataDictionary {
ByteString location = "";
unsigned long long rx = 0;
unsigned long long tx = 0;
};
/**

Просмотреть файл

@ -71,6 +71,7 @@
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/CookieServiceChild.h"
#include "mozilla/net/CaptivePortalService.h"
#include "mozilla/PerformanceMetricsCollector.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h"
@ -1392,12 +1393,12 @@ ContentChild::GetResultForRenderingInitFailure(base::ProcessId aOtherPid)
}
mozilla::ipc::IPCResult
ContentChild::RecvRequestPerformanceMetrics()
ContentChild::RecvRequestPerformanceMetrics(const nsID& aID)
{
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
nsTArray<PerformanceInfo> info;
CollectPerformanceInfo(info);
SendAddPerformanceMetrics(info);
SendAddPerformanceMetrics(aID, info);
return IPC_OK();
}

Просмотреть файл

@ -192,7 +192,7 @@ public:
nsTArray<uint32_t>&& namespaces) override;
mozilla::ipc::IPCResult
RecvRequestPerformanceMetrics() override;
RecvRequestPerformanceMetrics(const nsID& aID) override;
mozilla::ipc::IPCResult
RecvReinitRendering(

Просмотреть файл

@ -188,7 +188,7 @@
#include "ContentProcessManager.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/PerformanceMetricsCollector.h"
#include "mozilla/psm/PSMContentListener.h"
#include "nsPluginHost.h"
#include "nsPluginTags.h"
@ -3339,14 +3339,16 @@ ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
}
mozilla::ipc::IPCResult
ContentParent::RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics)
ContentParent::RecvAddPerformanceMetrics(const nsID& aID,
nsTArray<PerformanceInfo>&& aMetrics)
{
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
// The pref is off, we should not get a performance metrics from the content
// child
return IPC_OK();
}
Unused << NS_WARN_IF(NS_FAILED(mozilla::NotifyPerformanceInfo(aMetrics)));
nsresult rv = PerformanceMetricsCollector::DataReceived(aID, aMetrics);
Unused << NS_WARN_IF(NS_FAILED(rv));
return IPC_OK();
}

Просмотреть файл

@ -856,7 +856,7 @@ private:
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
mozilla::ipc::IPCResult RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics) override;
mozilla::ipc::IPCResult RecvAddPerformanceMetrics(const nsID& aID, nsTArray<PerformanceInfo>&& aMetrics) override;
virtual bool
DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;

Просмотреть файл

@ -408,7 +408,7 @@ child:
bool anonymize,
bool minimizeMemoryUsage,
MaybeFileDesc DMDFile);
async RequestPerformanceMetrics();
async RequestPerformanceMetrics(nsID aID);
/**
* Communication between the PuppetBidiKeyboard and the actual
@ -1150,7 +1150,7 @@ parent:
async BHRThreadHang(HangDetails aHangDetails);
async AddPerformanceMetrics(PerformanceInfo[] aMetrics);
async AddPerformanceMetrics(nsID aID, PerformanceInfo[] aMetrics);
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
Principal aPrincipal, ClonedMessageData aData);

Просмотреть файл

@ -1471,6 +1471,19 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(Event* aFocusEvent)
nsresult nsPluginInstanceOwner::ProcessKeyPress(Event* aKeyEvent)
{
// ProcessKeyPress() may be called twice with same eKeyPress event. One is
// by the event listener in the default event group and the other is by the
// event listener in the system event group. When this is called in the
// latter case and the event must be fired in the default event group too,
// we don't need to do nothing anymore.
// XXX Do we need to check whether the document is in chrome? In strictly
// speaking, it must be yes. However, our UI must not use plugin in
// chrome.
if (!aKeyEvent->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatchInContent &&
aKeyEvent->WidgetEventPtr()->mFlags.mInSystemGroup) {
return NS_OK;
}
#ifdef XP_MACOSX
return DispatchKeyToPlugin(aKeyEvent);
#else
@ -2548,6 +2561,7 @@ nsPluginInstanceOwner::Destroy()
content->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, false);
content->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
content->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
content->RemoveSystemEventListener(NS_LITERAL_STRING("keypress"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("drop"), this, true);
@ -2875,7 +2889,11 @@ nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
false);
aContent->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false,
false);
// "keypress" event should be handled when it's in the default event group
// if the event is fired in content. Otherwise, it should be handled when
// it's in the system event group.
aContent->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
aContent->AddSystemEventListener(NS_LITERAL_STRING("keypress"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("drop"), this, true);

Просмотреть файл

@ -68,12 +68,8 @@ add_task(async function test() {
let duration = 0;
let total = 0;
function getInfoFromService(subject, topic, value) {
subject = subject.QueryInterface(Ci.nsIMutableArray);
let enumerator = subject.enumerate();
while (enumerator.hasMoreElements()) {
let entry = enumerator.getNext();
entry = entry.QueryInterface(Ci.nsIPerformanceMetricsData);
function exploreResults(data) {
for (let entry of data) {
if (entry.pid == Services.appinfo.processID) {
parent_process_event = true;
}
@ -83,12 +79,8 @@ add_task(async function test() {
} else {
duration += entry.duration;
}
// let's look at the XPCOM data we got back
let items = entry.items.QueryInterface(Ci.nsIMutableArray);
let enumerator2 = items.enumerate();
while (enumerator2.hasMoreElements()) {
let item = enumerator2.getNext();
item = item.QueryInterface(Ci.nsIPerformanceMetricsDispatchCategory);
// let's look at the data we got back
for (let item of entry.items) {
if (entry.worker) {
worker_total += item.count;
} else {
@ -98,17 +90,9 @@ add_task(async function test() {
}
}
Services.obs.addObserver(getInfoFromService, "performance-metrics");
// wait until we get some events back by triggering requestPerformanceMetrics
await BrowserTestUtils.waitForCondition(() => {
ChromeUtils.requestPerformanceMetrics();
return worker_duration > 0 && duration > 0 && parent_process_event;
}, "wait for events to come in", 250, 20);
BrowserTestUtils.removeTab(page1);
BrowserTestUtils.removeTab(page2);
BrowserTestUtils.removeTab(page3);
// get all metrics via the promise
let results = await ChromeUtils.requestPerformanceMetrics();
exploreResults(results);
Assert.ok(worker_duration > 0, "Worker duration should be positive");
Assert.ok(worker_total > 0, "Worker count should be positive");
@ -117,5 +101,8 @@ add_task(async function test() {
Assert.ok(parent_process_event, "parent process sent back some events");
});
BrowserTestUtils.removeTab(page1);
BrowserTestUtils.removeTab(page2);
BrowserTestUtils.removeTab(page3);
SpecialPowers.clearUserPref('dom.performance.enable_scheduler_timing');
});

Просмотреть файл

@ -478,6 +478,7 @@ PerformanceInfo
WorkerDebugger::ReportPerformanceInfo()
{
AssertIsOnMainThread();
#if defined(XP_WIN)
uint32_t pid = GetCurrentProcessId();
#else
@ -495,22 +496,29 @@ WorkerDebugger::ReportPerformanceInfo()
}
}
}
RefPtr<PerformanceCounter> perf = mWorkerPrivate->GetPerformanceCounter();
uint16_t count = perf->GetTotalDispatchCount();
uint64_t duration = perf->GetExecutionDuration();
RefPtr<nsIURI> uri = mWorkerPrivate->GetResolvedScriptURI();
// Workers only produce metrics for a single category - DispatchCategory::Worker.
// We still return an array of CategoryDispatch so the PerformanceInfo
// struct is common to all performance counters throughout Firefox.
FallibleTArray<CategoryDispatch> items;
CategoryDispatch item = CategoryDispatch(DispatchCategory::Worker.GetValue(), count);
if (!items.AppendElement(item, fallible)) {
NS_ERROR("Could not complete the operation");
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
uint64_t duration = 0;
uint16_t count = 0;
RefPtr<nsIURI> uri = mWorkerPrivate->GetResolvedScriptURI();
RefPtr<PerformanceCounter> perf = mWorkerPrivate->GetPerformanceCounter();
if (perf) {
count = perf->GetTotalDispatchCount();
duration = perf->GetExecutionDuration();
CategoryDispatch item = CategoryDispatch(DispatchCategory::Worker.GetValue(), count);
if (!items.AppendElement(item, fallible)) {
NS_ERROR("Could not complete the operation");
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
true, items);
}
perf->ResetPerformanceCounters();
}
perf->ResetPerformanceCounters();
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
true, items);
}

Просмотреть файл

@ -29,7 +29,7 @@
#include "gfxVRPuppet.h"
#include "ipc/VRLayerParent.h"
#if !defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
#include "service/VRService.h"
#endif
@ -78,7 +78,7 @@ VRManager::VRManager()
* to support everyone else.
*/
#if !defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
// The VR Service accesses all hardware from a separate process
// and replaces the other VRSystemManager when enabled.
mVRService = VRService::Create();
@ -157,7 +157,7 @@ VRManager::Shutdown()
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
mManagers[i]->Shutdown();
}
#if !defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
if (mVRService) {
mVRService->Stop();
}
@ -348,7 +348,7 @@ VRManager::RefreshVRDisplays(bool aMustDispatch)
* or interrupt other VR activities.
*/
if (mVRDisplaysRequested || aMustDispatch) {
#if !defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
if (mVRService) {
mVRService->Start();
}

Просмотреть файл

@ -23,7 +23,7 @@ namespace gfx {
class VRLayerParent;
class VRManagerParent;
class VRDisplayHost;
#if !defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
class VRService;
#endif
class VRSystemManagerPuppet;
@ -95,7 +95,7 @@ private:
TimeStamp mLastActiveTime;
RefPtr<VRSystemManagerPuppet> mPuppetManager;
RefPtr<VRSystemManagerExternal> mExternalManager;
#if !defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
RefPtr<VRService> mVRService;
#endif
bool mVRDisplaysRequested;

Просмотреть файл

@ -10,12 +10,14 @@
#include "nsSocketTransport2.h"
#include "nsSocketTransportService2.h"
#include "nsThreadUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/Services.h"
#include "prerror.h"
#include "prio.h"
#include "prmem.h"
#include <vector>
using namespace mozilla;
using namespace mozilla::net;
mozilla::StaticRefPtr<IOActivityMonitor> gInstance;
@ -277,146 +279,58 @@ nsNetMon_AcceptRead(PRFileDesc *listenSock,
}
//
// Class IOActivityData
//
NS_IMPL_ISUPPORTS(IOActivityData, nsIIOActivityData);
NS_IMETHODIMP
IOActivityData::GetLocation(nsACString& aLocation) {
aLocation = mActivity.location;
return NS_OK;
};
NS_IMETHODIMP
IOActivityData::GetRx(int32_t* aRx) {
*aRx = mActivity.rx;
return NS_OK;
};
NS_IMETHODIMP
IOActivityData::GetTx(int32_t* aTx) {
*aTx = mActivity.tx;
return NS_OK;
};
//
// Class NotifyIOActivity
//
// Runnable that takes the activities per FD and location
// and converts them into IOActivity elements.
//
// These elements get notified.
//
class NotifyIOActivity : public mozilla::Runnable {
public:
static already_AddRefed<nsIRunnable>
Create(Activities& aActivities, const mozilla::MutexAutoLock& aProofOfLock)
{
RefPtr<NotifyIOActivity> runnable = new NotifyIOActivity();
for (auto iter = aActivities.Iter(); !iter.Done(); iter.Next()) {
IOActivity* activity = iter.Data();
if (!activity->Inactive()) {
if (NS_WARN_IF(!runnable->mActivities.AppendElement(*activity, mozilla::fallible))) {
return nullptr;
}
}
}
nsCOMPtr<nsIRunnable> result(runnable);
return result.forget();
}
NS_IMETHODIMP
Run() override
{
MOZ_ASSERT(NS_IsMainThread());
if (mActivities.Length() == 0) {
return NS_OK;
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (NS_WARN_IF(!array)) {
return NS_ERROR_FAILURE;
}
for (unsigned long i = 0; i < mActivities.Length(); i++) {
nsCOMPtr<nsIIOActivityData> data = new IOActivityData(mActivities[i]);
nsresult rv = array->AppendElement(data);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
obs->NotifyObservers(array, NS_IO_ACTIVITY, nullptr);
return NS_OK;
}
private:
explicit NotifyIOActivity()
: mozilla::Runnable("NotifyIOActivity")
{
}
FallibleTArray<IOActivity> mActivities;
};
//
// Class IOActivityMonitor
//
NS_IMPL_ISUPPORTS(IOActivityMonitor, nsITimerCallback, nsINamed)
NS_IMPL_ISUPPORTS(IOActivityMonitor, nsINamed)
IOActivityMonitor::IOActivityMonitor()
: mInterval(PR_INTERVAL_NO_TIMEOUT)
, mLock("IOActivityMonitor::mLock")
: mLock("IOActivityMonitor::mLock")
{
RefPtr<IOActivityMonitor> mon(gInstance);
MOZ_ASSERT(!mon, "multiple IOActivityMonitor instances!");
}
NS_IMETHODIMP
IOActivityMonitor::Notify(nsITimer* aTimer)
{
return NotifyActivities();
}
// static
nsresult
IOActivityMonitor::NotifyActivities()
void
IOActivityMonitor::RequestActivities(dom::Promise* aPromise)
{
MOZ_ASSERT(aPromise);
RefPtr<IOActivityMonitor> mon(gInstance);
if (!IsActive()) {
return NS_ERROR_FAILURE;
aPromise->MaybeReject(NS_ERROR_FAILURE);
return;
}
return mon->NotifyActivities_Internal();
mon->RequestActivitiesInternal(aPromise);
}
nsresult
IOActivityMonitor::NotifyActivities_Internal()
void
IOActivityMonitor::RequestActivitiesInternal(dom::Promise* aPromise)
{
mozilla::MutexAutoLock lock(mLock);
nsCOMPtr<nsIRunnable> ev = NotifyIOActivity::Create(mActivities, lock);
nsresult rv = SystemGroup::EventTargetFor(TaskCategory::Performance)->Dispatch(ev.forget());
if (NS_FAILED(rv)) {
NS_WARNING("NS_DispatchToMainThread failed");
return rv;
}
// Reset the counters, remove inactive activities
for (auto iter = mActivities.Iter(); !iter.Done(); iter.Next()) {
IOActivity* activity = iter.Data();
if (activity->Inactive()) {
iter.Remove();
} else {
activity->Reset();
nsresult result = NS_OK;
FallibleTArray<dom::IOActivityDataDictionary> activities;
{
mozilla::MutexAutoLock lock(mLock);
// Remove inactive activities
for (auto iter = mActivities.Iter(); !iter.Done(); iter.Next()) {
dom::IOActivityDataDictionary* activity = &iter.Data();
if (activity->mRx == 0 && activity->mTx == 0) {
iter.Remove();
} else {
if (NS_WARN_IF(!activities.AppendElement(iter.Data(), fallible))) {
result = NS_ERROR_OUT_OF_MEMORY;
break;
}
}
}
}
return NS_OK;
if (NS_WARN_IF(NS_FAILED(result))) {
aPromise->MaybeReject(result);
return;
}
aPromise->MaybeResolve(activities);
}
// static
@ -434,13 +348,13 @@ IOActivityMonitor::IsActive()
}
nsresult
IOActivityMonitor::Init(int32_t aInterval)
IOActivityMonitor::Init()
{
if (IsActive()) {
return NS_ERROR_ALREADY_INITIALIZED;
}
RefPtr<IOActivityMonitor> mon = new IOActivityMonitor();
nsresult rv = mon->Init_Internal(aInterval);
nsresult rv = mon->InitInternal();
if (NS_SUCCEEDED(rv)) {
gInstance = mon;
}
@ -448,7 +362,7 @@ IOActivityMonitor::Init(int32_t aInterval)
}
nsresult
IOActivityMonitor::Init_Internal(int32_t aInterval)
IOActivityMonitor::InitInternal()
{
// wraps the socket APIs
if (!sNetActivityMonitorLayerMethodsPtr) {
@ -468,20 +382,7 @@ IOActivityMonitor::Init_Internal(int32_t aInterval)
sNetActivityMonitorLayerMethodsPtr = &sNetActivityMonitorLayerMethods;
}
mInterval = aInterval;
// if the interval is 0, the timer is not fired
// and calls are done explicitely via NotifyActivities
if (mInterval == 0) {
return NS_OK;
}
// create and fire the timer
mTimer = NS_NewTimer();
if (!mTimer) {
return NS_ERROR_FAILURE;
}
return mTimer->InitWithCallback(this, mInterval, nsITimer::TYPE_REPEATING_SLACK);
return NS_OK;
}
nsresult
@ -491,16 +392,13 @@ IOActivityMonitor::Shutdown()
if (!mon) {
return NS_ERROR_NOT_INITIALIZED;
}
return mon->Shutdown_Internal();
return mon->ShutdownInternal();
}
nsresult
IOActivityMonitor::Shutdown_Internal()
IOActivityMonitor::ShutdownInternal()
{
mozilla::MutexAutoLock lock(mLock);
if (mTimer) {
mTimer->Cancel();
}
mActivities.Clear();
gInstance = nullptr;
return NS_OK;
@ -561,13 +459,15 @@ IOActivityMonitor::MonitorFile(PRFileDesc *aFd, const char* aPath)
return NS_OK;
}
IOActivity*
IOActivityMonitor::GetActivity(const nsACString& aLocation)
bool
IOActivityMonitor::IncrementActivity(const nsACString& aLocation, uint32_t aRx, uint32_t aTx)
{
mLock.AssertCurrentThreadOwns();
if (auto entry = mActivities.Lookup(aLocation)) {
// already registered
return entry.Data();
entry.Data().mTx += aTx;
entry.Data().mRx += aRx;
return true;
}
// Creating a new IOActivity. Notice that mActivities will
// grow indefinitely, which is OK since we won't have
@ -575,13 +475,15 @@ IOActivityMonitor::GetActivity(const nsACString& aLocation)
// want to assert we have at the most 1000 entries
MOZ_ASSERT(mActivities.Count() < MAX_ACTIVITY_ENTRIES);
// Entries are removed in the timer when they are inactive.
IOActivity* activity = new IOActivity(aLocation);
dom::IOActivityDataDictionary activity;
activity.mLocation.Assign(aLocation);
activity.mTx = aTx;
activity.mRx = aRx;
if (NS_WARN_IF(!mActivities.Put(aLocation, activity, fallible))) {
delete activity;
return nullptr;
return false;
}
return activity;
return true;
}
nsresult
@ -591,7 +493,7 @@ IOActivityMonitor::Write(const nsACString& aLocation, uint32_t aAmount)
if (!mon) {
return NS_ERROR_FAILURE;
}
return mon->Write_Internal(aLocation, aAmount);
return mon->WriteInternal(aLocation, aAmount);
}
nsresult
@ -605,14 +507,12 @@ IOActivityMonitor::Write(PRFileDesc *fd, uint32_t aAmount)
}
nsresult
IOActivityMonitor::Write_Internal(const nsACString& aLocation, uint32_t aAmount)
IOActivityMonitor::WriteInternal(const nsACString& aLocation, uint32_t aAmount)
{
mozilla::MutexAutoLock lock(mLock);
IOActivity* activity = GetActivity(aLocation);
if (!activity) {
if (!IncrementActivity(aLocation, aAmount, 0)) {
return NS_ERROR_FAILURE;
}
activity->tx += aAmount;
return NS_OK;
}
@ -633,17 +533,15 @@ IOActivityMonitor::Read(const nsACString& aLocation, uint32_t aAmount)
if (!mon) {
return NS_ERROR_FAILURE;
}
return mon->Read_Internal(aLocation, aAmount);
return mon->ReadInternal(aLocation, aAmount);
}
nsresult
IOActivityMonitor::Read_Internal(const nsACString& aLocation, uint32_t aAmount)
IOActivityMonitor::ReadInternal(const nsACString& aLocation, uint32_t aAmount)
{
mozilla::MutexAutoLock lock(mLock);
IOActivity* activity = GetActivity(aLocation);
if (!activity) {
if (!IncrementActivity(aLocation, 0, aAmount)) {
return NS_ERROR_FAILURE;
}
activity->rx += aAmount;
return NS_OK;
}

Просмотреть файл

@ -7,88 +7,45 @@
#ifndef IOActivityMonitor_h___
#define IOActivityMonitor_h___
#include "mozilla/dom/ChromeUtilsBinding.h"
#include "nsCOMPtr.h"
#include "nscore.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsIIOActivityData.h"
#include "nsISupports.h"
#include "nsITimer.h"
#include "prinrval.h"
#include "prio.h"
#include "private/pprio.h"
#include <stdint.h>
namespace mozilla { namespace net {
namespace mozilla {
namespace dom {
class Promise;
}
namespace net {
#define IO_ACTIVITY_ENABLED_PREF "io.activity.enabled"
#define IO_ACTIVITY_INTERVAL_PREF "io.activity.intervalMilliseconds"
//
// IOActivity keeps track of the amount of data
// sent and received for an FD / Location
//
struct IOActivity {
// the resource location, can be:
// - socket://ip:port
// - file://absolute/path
nsCString location;
typedef nsDataHashtable<nsCStringHashKey, dom::IOActivityDataDictionary> Activities;
// bytes received/read (rx) and sent/written (tx)
uint32_t rx;
uint32_t tx;
explicit IOActivity(const nsACString& aLocation) {
location.Assign(aLocation);
rx = 0;
tx = 0;
}
// Returns true if no data was transferred
bool Inactive() {
return rx == 0 && tx == 0;
}
// Sets the data to zero
void Reset() {
rx = 0;
tx = 0;
}
};
typedef nsClassHashtable<nsCStringHashKey, IOActivity> Activities;
// XPCOM Wrapper for an IOActivity
class IOActivityData final : public nsIIOActivityData
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIIOACTIVITYDATA
explicit IOActivityData(IOActivity aActivity)
: mActivity(aActivity) {}
private:
~IOActivityData() = default;
IOActivity mActivity;
};
// IOActivityMonitor has several roles:
// - maintains an IOActivity per resource and updates it
// - sends a dump of the activities to observers that wants
// to get that info, via a timer
// - sends a dump of the activities to a promise via RequestActivities
class IOActivityMonitor final
: public nsITimerCallback
, public nsINamed
: public nsINamed
{
public:
IOActivityMonitor();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITIMERCALLBACK
NS_DECL_NSINAMED
// initializes and destroys the singleton
static nsresult Init(int32_t aInterval);
static nsresult Init();
static nsresult Shutdown();
// collect amounts of data that are written/read by location
@ -101,25 +58,17 @@ public:
static nsresult Write(PRFileDesc *fd, uint32_t aAmount);
static bool IsActive();
// collects activities and notifies observers
// this method can be called manually or via the timer callback
static nsresult NotifyActivities();
static void RequestActivities(dom::Promise* aPromise);
private:
virtual ~IOActivityMonitor() = default;
nsresult Init_Internal(int32_t aInterval);
nsresult Shutdown_Internal();
IOActivity* GetActivity(const nsACString& location);
nsresult Write_Internal(const nsACString& location, uint32_t aAmount);
nsresult Read_Internal(const nsACString& location, uint32_t aAmount);
nsresult NotifyActivities_Internal();
~IOActivityMonitor() = default;
nsresult InitInternal();
nsresult ShutdownInternal();
bool IncrementActivity(const nsACString& location, uint32_t aRx, uint32_t aTx);
nsresult WriteInternal(const nsACString& location, uint32_t aAmount);
nsresult ReadInternal(const nsACString& location, uint32_t aAmount);
void RequestActivitiesInternal(dom::Promise* aPromise);
Activities mActivities;
// timer used to send notifications
uint32_t mInterval;
nsCOMPtr<nsITimer> mTimer;
// protects mActivities accesses
Mutex mLock;
};

Просмотреть файл

@ -52,7 +52,6 @@ XPIDL_SOURCES += [
'nsIIncrementalStreamLoader.idl',
'nsIInputStreamChannel.idl',
'nsIInputStreamPump.idl',
'nsIIOActivityData.idl',
'nsIIOService.idl',
'nsILoadContextInfo.idl',
'nsILoadGroup.idl',

Просмотреть файл

@ -1,19 +0,0 @@
/* 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/. */
#include "nsISupports.idl"
/**
* Keep tracks of the bytes that are sent (tx) and received (rx)
* into a socket identified by its file descriptor (fd)
* for a given host & port.
*/
[scriptable, builtinclass, uuid(30d5f743-939e-46c6-808a-7ea07c77028e)]
interface nsIIOActivityData : nsISupports
{
readonly attribute AUTF8String location;
readonly attribute long rx;
readonly attribute long tx;
};

Просмотреть файл

@ -1448,7 +1448,7 @@ nsSocketTransportService::Observe(nsISupports *subject,
if (!Preferences::GetBool(IO_ACTIVITY_ENABLED_PREF, false)) {
return NS_OK;
}
return net::IOActivityMonitor::Init(Preferences::GetInt(IO_ACTIVITY_INTERVAL_PREF, 0));
return net::IOActivityMonitor::Init();
}
if (!strcmp(topic, "last-pb-context-exited")) {

Просмотреть файл

@ -1,6 +1,7 @@
[DEFAULT]
support-files =
dummy.html
ioactivity.html
[browser_about_cache.js]
[browser_NetUtil.js]

Просмотреть файл

@ -4,80 +4,45 @@
* 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/. */
const TEST_URL = "http://example.com/browser/dom/tests/browser/dummy.html";
const ROOT_URL = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
"https://example.com/");
const TEST_URL = "about:license";
const TEST_URL2 = ROOT_URL + "ioactivity.html";
var gotSocket = false;
var gotFile = false;
var gotSqlite = false;
var gotEmptyData = false;
var networkActivity = function(subject, topic, value) {
subject.QueryInterface(Ci.nsIMutableArray);
let enumerator = subject.enumerate();
while (enumerator.hasMoreElements()) {
let data = enumerator.getNext();
data = data.QueryInterface(Ci.nsIIOActivityData);
function processResults(results) {
for (let data of results) {
console.log(data.location);
gotEmptyData = data.rx == 0 && data.tx == 0 && !gotEmptyData
gotSocket = data.location.startsWith("socket://127.0.0.1:") || gotSocket;
gotFile = data.location.endsWith(".js") || gotFile;
gotFile = data.location.endsWith("aboutLicense.css") || gotFile;
gotSqlite = data.location.endsWith("places.sqlite") || gotSqlite;
}
};
function startObserver() {
gotSocket = gotFile = gotSqlite = gotEmptyData = false;
Services.obs.addObserver(networkActivity, "io-activity");
// why do I have to do this ??
add_task(async function testRequestIOActivity() {
await SpecialPowers.pushPrefEnv({
"set": [
["io.activity.enabled", true],
]
});
waitForExplicitFinish();
Services.obs.notifyObservers(null, "profile-initial-state", null);
}
// this test activates the timer and checks the results as they come in
add_task(async function testWithTimer() {
await SpecialPowers.pushPrefEnv({
"set": [
["io.activity.enabled", true],
["io.activity.intervalMilliseconds", 50]
]
});
waitForExplicitFinish();
startObserver();
await BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
async function(browser) {
// wait until we get the events back
await BrowserTestUtils.waitForCondition(() => {
return gotSocket && gotFile && gotSqlite && !gotEmptyData;
}, "wait for events to come in", 500);
await BrowserTestUtils.withNewTab(TEST_URL, async function(browser) {
await BrowserTestUtils.withNewTab(TEST_URL2, async function(browser) {
let results = await ChromeUtils.requestIOActivity();
processResults(results);
ok(gotSocket, "A socket was used");
ok(gotFile, "A file was used");
ok(gotSqlite, "A sqlite DB was used");
ok(!gotEmptyData, "Every I/O event had data");
});
});
// this test manually triggers notifications via ChromeUtils.requestIOActivity()
add_task(async function testWithManualCall() {
await SpecialPowers.pushPrefEnv({
"set": [
["io.activity.enabled", true],
]
});
waitForExplicitFinish();
startObserver();
await BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
async function(browser) {
// wait until we get the events back
await BrowserTestUtils.waitForCondition(() => {
ChromeUtils.requestIOActivity();
return gotSocket && gotFile && gotSqlite && !gotEmptyData;
}, "wait for events to come in", 500);
ok(gotSocket, "A socket was used");
ok(gotFile, "A file was used");
// test deactivated for now
// ok(gotFile, "A file was used");
ok(gotSqlite, "A sqlite DB was used");
ok(!gotEmptyData, "Every I/O event had data");
});
});
});

Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<html>
<body>
<p>IOActivity Test Page</p>
</body>
</html>

Просмотреть файл

@ -5,19 +5,15 @@
from mozbuild.pythonutil import iter_modules_in_path
from mozunit import main
import os
import unittest
class TestIterModules(unittest.TestCase):
def test_iter_modules_in_path(self):
mozbuild_path = os.path.normcase(os.path.dirname(os.path.dirname(__file__)))
paths = list(iter_modules_in_path(mozbuild_path))
self.assertEquals(set(paths), set([
os.path.join(os.path.abspath(mozbuild_path), '__init__.py'),
os.path.join(os.path.abspath(mozbuild_path), 'pythonutil.py'),
os.path.join(os.path.abspath(mozbuild_path), 'test', '__init__.py'),
os.path.join(os.path.abspath(mozbuild_path), 'test', 'test_pythonutil.py'),
]))
def test_iter_modules_in_path():
tests_path = os.path.normcase(os.path.dirname(__file__))
paths = list(iter_modules_in_path(tests_path))
assert set(paths) == set([
os.path.join(os.path.abspath(tests_path), '__init__.py'),
os.path.join(os.path.abspath(tests_path), 'test_pythonutil.py'),
])
if __name__ == '__main__':

Просмотреть файл

@ -15,11 +15,11 @@ logger = logging.getLogger(__name__)
@register_callback_action(
title='Purge Caches',
name='purge-caches',
title='Purge Worker Caches',
name='purge-cache',
symbol='purge-cache',
kind='hook',
generic=True,
symbol='purge-caches',
description=(
'Purge any caches associated with this task '
'across all workers of the same workertype as the task.'

Просмотреть файл

@ -156,11 +156,13 @@ class TestTab(PuppeteerMixin, MarionetteTestCase):
for trigger in close_strategies:
new_tab = tabbar.open_tab()
self.assertEqual(len(tabbar.tabs), 2)
self.assertEqual(len(self.marionette.window_handles), 2)
self.assertEqual(new_tab.handle, self.marionette.current_window_handle)
self.assertEqual(new_tab.handle, tabbar.tabs[1].handle)
new_tab.close(trigger=trigger)
self.assertEqual(len(tabbar.tabs), 1)
self.assertEqual(len(self.marionette.window_handles), 1)
self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle)
self.assertNotEqual(new_tab.handle, tabbar.tabs[0].handle)

Просмотреть файл

@ -6,7 +6,16 @@ RUST_PROGRAMS += ["geckodriver"]
# https://bugzil.la/1425365
if CONFIG["OS_ARCH"] != "WINNT":
RUST_TESTS = ["geckodriver"]
RUST_TESTS = [
"geckodriver",
"webdriver",
# TODO: Move to mozbase/rust/moz.build once those crates can be
# tested separately.
"mozprofile",
"mozrunner",
"mozversion",
]
with Files("**"):
BUG_COMPONENT = ("Testing", "geckodriver")

Просмотреть файл

@ -117,6 +117,10 @@ class TabBar(UIBaseLib):
automatically be performed. But if it opens in the background, the current
tab will keep its focus.
It will first verify that a new `<tab>` element has been
introduced in the tabbar, and then that a new content
browser has been created.
:param trigger: Optional, method to open the new tab. This can
be a string with one of `menu`, `button` or `shortcut`, or a callback
which gets triggered with the current :class:`Tab` as parameter.
@ -125,6 +129,7 @@ class TabBar(UIBaseLib):
:returns: :class:`Tab` instance for the opened tab.
"""
start_handles = self.marionette.window_handles
start_tabs = self.window.tabbar.tabs
# Prepare action which triggers the opening of the browser window
if callable(trigger):
@ -132,19 +137,21 @@ class TabBar(UIBaseLib):
elif trigger == 'button':
self.window.tabbar.newtab_button.click()
elif trigger == 'menu':
self.window.menubar.select_by_id('file-menu',
'menu_newNavigatorTab')
self.window.menubar.select_by_id('file-menu', 'menu_newNavigatorTab')
elif trigger == 'shortcut':
self.window.send_shortcut(self.window.localize_entity('tabCmd.commandkey'),
accel=True)
self.window.send_shortcut(
self.window.localize_entity('tabCmd.commandkey'),
accel=True)
# elif - need to add other cases
else:
raise ValueError('Unknown opening method: "%s"' % trigger)
# TODO: Needs to be replaced with event handling code (bug 1121705)
Wait(self.marionette).until(
lambda _: len(self.window.tabbar.tabs) == len(start_tabs) + 1,
message='No new tab present in tabbar')
Wait(self.marionette).until(
lambda mn: len(mn.window_handles) == len(start_handles) + 1,
message='No new tab has been opened.')
message='No new content browser created')
handles = self.marionette.window_handles
[new_handle] = list(set(handles) - set(start_handles))
@ -291,6 +298,10 @@ class Tab(UIBaseLib):
def close(self, trigger='menu', force=False):
"""Closes the tab by using the specified trigger.
To ensure the tab was closed, it will first ensure the
`<tab>` element is removed from the tabbar, and then confirm
that the content browser was discarded.
When the tab is closed a :func:`switch_to` call is automatically performed, so that
the new selected tab becomes active.
@ -303,6 +314,7 @@ class Tab(UIBaseLib):
"""
handle = self.handle
start_handles = self.marionette.window_handles
start_tabs = self.window.tabbar.tabs
self.switch_to()
@ -321,8 +333,11 @@ class Tab(UIBaseLib):
raise ValueError('Unknown closing method: "%s"' % trigger)
Wait(self.marionette).until(
lambda _: len(self.window.tabbar.tabs) == len(start_handles) - 1,
message='Tab with handle "%s" has not been closed.' % handle)
lambda _: len(self.window.tabbar.tabs) == len(start_tabs) - 1,
message='Tab"%s" has not been closed' % handle)
Wait(self.marionette).until(
lambda mn: len(mn.window_handles) == len(start_handles) - 1,
message='Content browser "%s" has not been closed' % handle)
# Ensure to switch to the window handle which represents the new selected tab
self.window.tabbar.selected_tab.switch_to()

Просмотреть файл

@ -117,7 +117,7 @@ class RaptorControlServer():
self.kill_thread.daemon = True
self.kill_thread.start()
def wait_for_quit(self, timeout=75):
def wait_for_quit(self, timeout=15):
"""Wait timeout seconds for the process to exit. If it hasn't
exited by then, kill it.
"""

Просмотреть файл

@ -0,0 +1,56 @@
<html>
<head>
<style>
div {
opacity: 0.95;
width:10px;
height:10px;
background-color:green;
display: inline-block;
}
</style>
</head>
<body id="body">
</body>
<script>
var start = null;
var divCount = 2500;
var maxIterations = 600;
for (var i = 0; i < divCount; i++) {
var div = document.createElement("div");
div.id = i;
document.getElementById("body").appendChild(div);
}
var iteration = 0;
function runFrame() {
if (document.getElementById(iteration).style.backgroundColor == "red") {
document.getElementById(iteration).style.backgroundColor = "green";
} else {
document.getElementById(iteration).style.backgroundColor = "red";
}
iteration++;
iteration = iteration % divCount;
if (--maxIterations == 0) {
var end = performance.now();
if (window.tpRecordTime) {
window.tpRecordTime(end - start, start);
}
return;
}
window.requestAnimationFrame(runFrame);
}
addEventListener("load", function() {
TalosContentProfiler.resume("displaylist_flattened_mutate.html loaded", true).then(() => {
start = performance.now();
window.requestAnimationFrame(runFrame);
});
});
</script>
<script type="text/javascript" src="chrome://talos-powers-content/content/TalosContentProfiler.js"></script>
</html>

Просмотреть файл

@ -1,2 +1,3 @@
% http://localhost/tests/layout/benchmarks/displaylist_mutate.html
% http://localhost/tests/layout/benchmarks/displaylist_inactive_mutate.html
% http://localhost/tests/layout/benchmarks/displaylist_flattened_mutate.html

Просмотреть файл

@ -9,26 +9,19 @@ this.topSites = class extends ExtensionAPI {
getAPI(context) {
return {
topSites: {
get: function(options) {
return new Promise((resolve) => {
NewTabUtils.links.populateCache(async () => {
let urls;
// The placesProvider is a superset of activityStream if sites are blocked, etc.,
// there is no need to attempt a merge of multiple provider lists.
if (options.providers.includes("places")) {
urls = NewTabUtils.getProviderLinks(NewTabUtils.placesProvider).slice();
} else {
urls = await NewTabUtils.activityStreamLinks.getTopSites();
}
resolve(urls.filter(link => !!link)
.map(link => {
return {
url: link.url,
title: link.title,
};
}));
}, false);
get: async function(options) {
let links = await NewTabUtils.activityStreamLinks.getTopSites({
ignoreBlocked: options.includeBlocked,
onePerDomain: options.onePerDomain,
numItems: options.limit,
includeFavicon: options.includeFavicon,
});
return links.map(link => {
return {
url: link.url,
title: link.title,
favicon: link.favicon,
};
});
},
},

Просмотреть файл

@ -35,6 +35,11 @@
"type": "string",
"optional": true,
"description": "The title of the page."
},
"favicon": {
"type": "string",
"optional": true,
"description": "Data URL for the favicon, if available."
}
}
}
@ -53,9 +58,35 @@
"providers": {
"type": "array",
"items": { "type": "string" },
"description": "Which providers to get top sites from. Possible values are \"places\" and \"activityStream\".",
"deprecated": "Please use the other options to tune the results received from topSites.",
"default": [],
"optional": true
},
"limit": {
"type": "integer",
"default": 12,
"maximum": 100,
"minimum": 1,
"optional": true,
"description": "The number of top sites to return, defaults to the value used by Firefox"
},
"onePerDomain": {
"type": "boolean",
"default": true,
"optional": true,
"description": "Limit the result to a single top site link per domain"
},
"includeBlocked": {
"type": "boolean",
"default": false,
"optional": true,
"description": "Include sites that the user has blocked from appearing on the Firefox new tab."
},
"includeFavicon": {
"type": "boolean",
"default": false,
"optional": true,
"description": "Include sites favicon if available."
}
},
"default": {},

Просмотреть файл

@ -269,6 +269,16 @@
"description": "The cipher suite used in this request if state is \"secure\".",
"optional": true
},
"keaGroupName": {
"type": "string",
"description": "The key exchange algorithm used in this request if state is \"secure\".",
"optional": true
},
"signatureSchemeName": {
"type": "string",
"description": "The signature scheme used in this request if state is \"secure\".",
"optional": true
},
"certificates": {
"description": "Certificate data if state is \"secure\". Will only contain one entry unless <code>certificateChain</code> is passed as an option.",
"type": "array",

Просмотреть файл

@ -2,35 +2,51 @@
ChromeUtils.import("resource://gre/modules/PlacesUtils.jsm");
ChromeUtils.import("resource://gre/modules/NewTabUtils.jsm");
ChromeUtils.import("resource://testing-common/PlacesTestUtils.jsm");
// A small 1x1 test png
const IMAGE_1x1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==";
add_task(async function test_topSites() {
let visits = [];
const numVisits = 15; // To make sure we get frecency.
let visitDate = new Date(1999, 9, 9, 9, 9).getTime();
// Stick a couple sites into history.
for (let i = 0; i < 2; ++i) {
let visit = {
url: `http://example.com${i}/`,
title: `visit${i}`,
visits: [],
};
function setVisit(visit) {
for (let j = 0; j < numVisits; ++j) {
visitDate -= 1000;
visit.visits.push({date: new Date(visitDate)});
}
visits.push(visit);
}
// Stick a couple sites into history.
for (let i = 0; i < 2; ++i) {
setVisit({
url: `http://example${i}.com/`,
title: `visit${i}`,
visits: [],
});
setVisit({
url: `http://www.example${i}.com/foobar`,
title: `visit${i}-www`,
visits: [],
});
}
NewTabUtils.init();
await PlacesUtils.history.insertMany(visits);
// Insert a favicon to show that favicons are not returned by default.
let faviconData = new Map();
faviconData.set("http://example0.com", IMAGE_1x1);
await PlacesTestUtils.addFavicons(faviconData);
// Ensure our links show up in activityStream.
let links = await NewTabUtils.activityStreamLinks.getTopSites();
let links = await NewTabUtils.activityStreamLinks.getTopSites({onePerDomain: false, topsiteFrecency: 1});
equal(links.length, visits.length, "Top sites has been successfully initialized");
// Drop the visits.visits for later testing.
visits = visits.map(v => { return {url: v.url, title: v.title}; });
visits = visits.map(v => { return {url: v.url, title: v.title, favicon: undefined}; });
// Test that results from all providers are returned by default.
let extension = ExtensionTestUtils.loadExtension({
@ -40,11 +56,10 @@ add_task(async function test_topSites() {
],
},
background() {
// Tests consistent behaviour when no providers are specified.
browser.test.onMessage.addListener(async providers => {
browser.test.onMessage.addListener(async options => {
let sites;
if (typeof providers !== undefined) {
sites = await browser.topSites.get(providers);
if (typeof options !== undefined) {
sites = await browser.topSites.get(options);
} else {
sites = await browser.topSites.get();
}
@ -55,16 +70,33 @@ add_task(async function test_topSites() {
await extension.startup();
function getSites(providers) {
extension.sendMessage(providers);
function getSites(options) {
extension.sendMessage(options);
return extension.awaitMessage("sites");
}
Assert.deepEqual(visits, await getSites(), "got topSites");
Assert.deepEqual(visits, await getSites({}), "got topSites");
Assert.deepEqual(visits, await getSites({providers: ["places"]}), "got topSites");
Assert.deepEqual(visits, await getSites({providers: ["activityStream"]}), "got topSites");
Assert.deepEqual(visits, await getSites({providers: ["places", "activityStream"]}), "got topSites");
Assert.deepEqual([visits[0], visits[2]],
await getSites(),
"got topSites default");
Assert.deepEqual(visits,
await getSites({onePerDomain: false}),
"got topSites all links");
NewTabUtils.activityStreamLinks.blockURL(visits[0]);
ok(NewTabUtils.blockedLinks.isBlocked(visits[0]), `link ${visits[0].url} is blocked`);
Assert.deepEqual([visits[2], visits[1]],
await getSites(),
"got topSites with blocked links filtered out");
Assert.deepEqual([visits[0], visits[2]],
await getSites({includeBlocked: true}),
"got topSites with blocked links included");
// Test favicon result
let topSites = await getSites({includeBlocked: true, includeFavicon: true});
equal(topSites[0].favicon, IMAGE_1x1, "received favicon");
equal(1, (await getSites({limit: 1, includeBlocked: true})).length, "limit 1 topSite");
NewTabUtils.uninit();
await extension.unload();

Просмотреть файл

@ -0,0 +1,220 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "nsThreadUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/PerformanceMetricsCollector.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/WorkerDebugger.h"
#include "mozilla/dom/WorkerDebuggerManager.h"
using namespace mozilla;
using namespace mozilla::dom;
static mozilla::LazyLogModule sPerfLog("PerformanceMetricsCollector");
#ifdef LOG
#undef LOG
#endif
#define LOG(args) MOZ_LOG(sPerfLog, mozilla::LogLevel::Debug, args)
namespace mozilla {
//
// class AggregatedResults
//
AggregatedResults::AggregatedResults(nsID aUUID,
PerformanceMetricsCollector* aCollector,
dom::Promise* aPromise)
: mPromise(aPromise)
, mPendingResults(0)
, mCollector(aCollector)
, mUUID(aUUID)
{
MOZ_ASSERT(aCollector);
MOZ_ASSERT(aPromise);
}
void
AggregatedResults::Abort(nsresult aReason)
{
MOZ_ASSERT(mPromise);
MOZ_ASSERT(NS_FAILED(aReason));
mPromise->MaybeReject(aReason);
mPromise = nullptr;
mPendingResults = 0;
}
void
AggregatedResults::AppendResult(const nsTArray<dom::PerformanceInfo>& aMetrics)
{
if (!mPromise) {
// A previous call failed and the promise was already rejected
return;
}
MOZ_ASSERT(mPendingResults > 0);
// Each PerformanceInfo is converted into a PerformanceInfoDictionary
for (const PerformanceInfo& result : aMetrics) {
mozilla::dom::Sequence<mozilla::dom::CategoryDispatchDictionary> items;
for (const CategoryDispatch& entry : result.items()) {
CategoryDispatchDictionary* item = items.AppendElement(fallible);
if (NS_WARN_IF(!item)) {
Abort(NS_ERROR_OUT_OF_MEMORY);
return;
}
item->mCategory = entry.category();
item->mCount = entry.count();
}
PerformanceInfoDictionary* data = mData.AppendElement(fallible);
if (NS_WARN_IF(!data)) {
Abort(NS_ERROR_OUT_OF_MEMORY);
return;
}
data->mPid = result.pid();
data->mWid = result.wid();
data->mPwid = result.pwid();
data->mHost = *result.host().get();
data->mDuration = result.pid();
data->mWorker = result.worker();
data->mItems = items;
}
mPendingResults--;
if (mPendingResults) {
return;
}
LOG(("[%s] All data collected, resolving promise", nsIDToCString(mUUID).get()));
mPromise->MaybeResolve(mData);
mCollector->ForgetAggregatedResults(mUUID);
}
void
AggregatedResults::SetNumResultsRequired(uint32_t aNumResultsRequired)
{
MOZ_ASSERT(!mPendingResults && aNumResultsRequired);
mPendingResults = aNumResultsRequired;
}
//
// class PerformanceMetricsCollector (singleton)
//
// raw pointer for the singleton
PerformanceMetricsCollector* gInstance = nullptr;
PerformanceMetricsCollector::~PerformanceMetricsCollector()
{
MOZ_ASSERT(gInstance == this);
gInstance = nullptr;
}
void
PerformanceMetricsCollector::ForgetAggregatedResults(const nsID& aUUID)
{
MOZ_ASSERT(gInstance);
MOZ_ASSERT(XRE_IsParentProcess());
// This Remove() call will trigger AggregatedResults DTOR and if its
// the last in the table, the DTOR of PerformanceMetricsCollector.
// That's why we need to make sure we hold a reference here before the call
RefPtr<PerformanceMetricsCollector> kungFuDeathGrip = this;
LOG(("[%s] Removing from the table", nsIDToCString(aUUID).get()));
mAggregatedResults.Remove(aUUID);
}
// static
void
PerformanceMetricsCollector::RequestMetrics(dom::Promise* aPromise)
{
MOZ_ASSERT(aPromise);
MOZ_ASSERT(XRE_IsParentProcess());
RefPtr<PerformanceMetricsCollector> pmc = gInstance;
if (!pmc) {
pmc = new PerformanceMetricsCollector();
gInstance = pmc;
}
pmc->RequestMetricsInternal(aPromise);
}
void
PerformanceMetricsCollector::RequestMetricsInternal(dom::Promise* aPromise)
{
// each request has its own UUID
nsID uuid;
nsresult rv = nsContentUtils::GenerateUUIDInPlace(uuid);
if (NS_WARN_IF(NS_FAILED(rv))) {
aPromise->MaybeReject(rv);
return;
}
LOG(("[%s] Requesting Performance Metrics", nsIDToCString(uuid).get()));
// Getting all content processes
nsTArray<ContentParent*> children;
ContentParent::GetAll(children);
uint32_t numChildren = children.Length();
LOG(("[%s] Expecting %d results back", nsIDToCString(uuid).get(), numChildren + 1));
// keep track of all results in an AggregatedResults instance
UniquePtr<AggregatedResults> results = MakeUnique<AggregatedResults>(uuid, this, aPromise);
// We want to get back as many results as children, plus the result
// from the content parent itself
results->SetNumResultsRequired(numChildren + 1);
mAggregatedResults.Put(uuid, std::move(results));
// calling all content processes via IPDL (async)
for (uint32_t i = 0; i < numChildren; i++) {
if (NS_WARN_IF(!children[i]->SendRequestPerformanceMetrics(uuid))) {
LOG(("[%s] Failed to send request to child %d", nsIDToCString(uuid).get(), i));
mAggregatedResults.GetValue(uuid)->get()->Abort(NS_ERROR_FAILURE);
return;
}
}
// collecting the current process PerformanceInfo
nsTArray<PerformanceInfo> info;
CollectPerformanceInfo(info);
DataReceived(uuid, info);
}
// static
nsresult
PerformanceMetricsCollector::DataReceived(const nsID& aUUID,
const nsTArray<PerformanceInfo>& aMetrics)
{
MOZ_ASSERT(gInstance);
MOZ_ASSERT(XRE_IsParentProcess());
return gInstance->DataReceivedInternal(aUUID, aMetrics);
}
nsresult
PerformanceMetricsCollector::DataReceivedInternal(const nsID& aUUID,
const nsTArray<PerformanceInfo>& aMetrics)
{
MOZ_ASSERT(gInstance == this);
UniquePtr<AggregatedResults>* results = mAggregatedResults.GetValue(aUUID);
if (!results) {
return NS_ERROR_FAILURE;
}
LOG(("[%s] Received one PerformanceInfo array", nsIDToCString(aUUID).get()));
AggregatedResults* aggregatedResults = results->get();
MOZ_ASSERT(aggregatedResults);
// If this is the last result, APpendResult() will trigger the deletion
// of this collector, nothing should be done after this line.
aggregatedResults->AppendResult(aMetrics);
return NS_OK;
}
} // namespace

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef PerformanceMetricsCollector_h
#define PerformanceMetricsCollector_h
#include "nsID.h"
#include "mozilla/dom/ChromeUtilsBinding.h" // defines PerformanceInfoDictionary
#include "mozilla/dom/DOMTypes.h" // defines PerformanceInfo
namespace mozilla {
namespace dom {
class Promise;
}
class PerformanceMetricsCollector;
// AggregatedResults receives PerformanceInfo results that are collected
// via IPDL from all content processes and the main process. They
// are converted into an array of PerformanceInfoDictionary dictionaries (webidl)
//
// The class is instanciated with a Promise and a number of processes
// that are supposed to send back results.
//
// Once every process have sent back its results, AggregatedResults will
// resolve the promise with all the collected data and send back the
// dictionnary.
//
class AggregatedResults final
{
public:
AggregatedResults(nsID aUUID, PerformanceMetricsCollector* aCollector,
dom::Promise* aPromise);
~AggregatedResults() = default;
void AppendResult(const nsTArray<dom::PerformanceInfo>& aMetrics);
void SetNumResultsRequired(uint32_t aNumResultsRequired);
void Abort(nsresult aReason);
private:
RefPtr<dom::Promise> mPromise;
uint32_t mPendingResults;
FallibleTArray<dom::PerformanceInfoDictionary> mData;
// AggregatedResults keeps a reference on the collector
// so it gets destructed when all pending AggregatedResults
// are themselves destructed when removed from
// PerformanceMetricsCollector::mAggregatedResults.
//
// This lifecycle ensures that everything is released once
// all pending results are sent.
RefPtr<PerformanceMetricsCollector> mCollector;
nsID mUUID;
};
//
// PerformanceMetricsCollector is instanciated as a singleton, and creates
// one AggregatedResults instance everytime metrics are requested.
//
// Each AggregatedResults has a unique identifier (UUID) that is used
// to send metrics requests via IPDL. When metrics are back in an
// asynchronous fashion, the UUID is used to append the data to the
// right AggregatedResults instance and eventually let it resolve the
// linked promise.
//
class PerformanceMetricsCollector final
{
public:
NS_INLINE_DECL_REFCOUNTING(PerformanceMetricsCollector)
static void RequestMetrics(dom::Promise* aPromise);
static nsresult DataReceived(const nsID& aUUID,
const nsTArray<dom::PerformanceInfo>& aMetrics);
void ForgetAggregatedResults(const nsID& aUUID);
private:
~PerformanceMetricsCollector();
void RequestMetricsInternal(dom::Promise* aPromise);
nsresult DataReceivedInternal(const nsID& aUUID,
const nsTArray<dom::PerformanceInfo>& aMetrics);
nsDataHashtable<nsIDHashKey, UniquePtr<AggregatedResults>> mAggregatedResults;
};
} // namespace mozilla
#endif // PerformanceMetricsCollector_h

Просмотреть файл

@ -4,8 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIMutableArray.h"
#include "nsPerformanceMetrics.h"
#include "nsThreadUtils.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/dom/DocGroup.h"
@ -41,50 +39,4 @@ CollectPerformanceInfo(nsTArray<PerformanceInfo>& aMetrics)
}
}
nsresult
NotifyPerformanceInfo(const nsTArray<PerformanceInfo>& aMetrics)
{
nsresult rv;
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (NS_WARN_IF(!array)) {
return NS_ERROR_FAILURE;
}
// Each PerformanceInfo is converted into a nsIPerformanceMetricsData
for (const PerformanceInfo& info : aMetrics) {
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (NS_WARN_IF(!items)) {
return rv;
}
for (const CategoryDispatch& entry : info.items()) {
nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item =
new PerformanceMetricsDispatchCategory(entry.category(),
entry.count());
rv = items->AppendElement(item);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
nsCOMPtr<nsIPerformanceMetricsData> data;
data = new PerformanceMetricsData(info.pid(), info.wid(), info.pwid(),
info.host(), info.duration(),
info.worker(), items);
rv = array->AppendElement(data);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (NS_WARN_IF(!obs)) {
return NS_ERROR_FAILURE;
}
rv = obs->NotifyObservers(array, "performance-metrics", nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
} // namespace

Просмотреть файл

@ -3,8 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef PerformanceCollector_h
#define PerformanceCollector_h
#ifndef PerformanceUtils_h
#define PerformanceUtils_h
#include "mozilla/dom/DOMTypes.h" // defines PerformanceInfo
@ -12,15 +12,9 @@ namespace mozilla {
/**
* Collects all performance info in the current process
* and adds then in the aMetrics arrey
* and adds then in the aMetrics array
*/
void CollectPerformanceInfo(nsTArray<dom::PerformanceInfo>& aMetrics);
/**
* Converts a PerformanceInfo array into a nsIPerformanceMetricsData and
* sends a performance-metrics notification with it
*/
nsresult NotifyPerformanceInfo(const nsTArray<dom::PerformanceInfo>& aMetrics);
} // namespace mozilla
#endif // PerformanceCollector_h
#endif // PerformanceUtils_h

Просмотреть файл

@ -27,10 +27,12 @@ UNIFIED_SOURCES += [
]
UNIFIED_SOURCES += [
'PerformanceMetricsCollector.cpp',
'PerformanceUtils.cpp'
]
EXPORTS.mozilla += [
'PerformanceMetricsCollector.h',
'PerformanceUtils.h'
]

Просмотреть файл

@ -339,6 +339,10 @@ To enable Hybrid Content Telemetry on ``https://example.mozilla.org``, execute t
Afterwards load the page on ``https://example.mozilla.org`` and it will be able to record Telemetry data.
.. note::
Manual testing requires a host that handles HTTPS connections, as this kind of collection is only allowed on secure hosts. To allow for local testing, a local proxy capable of handling HTTPS connection is required.
Automated testing
-----------------

Просмотреть файл

@ -118,6 +118,7 @@ function LightweightThemeConsumer(aDocument) {
this._win.addEventListener("resolutionchange", this);
this._win.addEventListener("unload", this, { once: true });
this._win.addEventListener("EndSwapDocShells", this, true);
this._win.messageManager.addMessageListener("LightweightTheme:Request", this);
let darkThemeMediaQuery = this._win.matchMedia("(-moz-system-dark-theme)");
@ -163,8 +164,13 @@ LightweightThemeConsumer.prototype = {
case "unload":
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
this._win.removeEventListener("resolutionchange", this);
this._win.removeEventListener("EndSwapDocShells", this, true);
this._win = this._doc = null;
break;
case "EndSwapDocShells":
let contentThemeData = _getContentProperties(this._doc, this._active, this._lastData);
aEvent.target.messageManager.sendAsyncMessage("LightweightTheme:Update", contentThemeData);
break;
}
},

Просмотреть файл

@ -1089,6 +1089,8 @@ var ActivityStreamProvider = {
* {bool} ignoreBlocked: Do not filter out blocked links.
* {int} numItems: Maximum number of items to return.
* {int} topsiteFrecency: Minimum amount of frecency for a site.
* {bool} onePerDomain: Dedupe the resulting list.
* {bool} includeFavicon: Include favicons if available.
*
* @returns {Promise} Returns a promise with the array of links as payload.
*/
@ -1096,13 +1098,17 @@ var ActivityStreamProvider = {
const options = Object.assign({
ignoreBlocked: false,
numItems: ACTIVITY_STREAM_DEFAULT_LIMIT,
topsiteFrecency: ACTIVITY_STREAM_DEFAULT_FRECENCY
topsiteFrecency: ACTIVITY_STREAM_DEFAULT_FRECENCY,
onePerDomain: true,
includeFavicon: true,
}, aOptions || {});
// Double the item count in case the host is deduped between with www or
// not-www (i.e., 2 hosts) and an extra buffer for multiple pages per host.
const origNumItems = options.numItems;
options.numItems *= 2 * 10;
if (options.onePerDomain) {
options.numItems *= 2 * 10;
}
// Keep this query fast with frecency-indexed lookups (even with excess
// rows) and shift the more complex logic to post-processing afterwards
@ -1114,7 +1120,8 @@ var ActivityStreamProvider = {
last_visit_date / 1000 AS lastVisitDate,
rev_host,
title,
url
url,
"history" as type
FROM moz_places h
WHERE frecency >= :frecencyThreshold
${this._commonPlacesWhere}
@ -1129,7 +1136,8 @@ var ActivityStreamProvider = {
"guid",
"lastVisitDate",
"title",
"url"
"url",
"type"
],
params: this._getCommonParams(options, {
frecencyThreshold: options.topsiteFrecency
@ -1157,32 +1165,37 @@ var ActivityStreamProvider = {
map.set(host, link);
}
// Clean up the returned links by removing blocked, deduping, etc.
const exactHosts = new Map();
for (const link of links) {
if (!options.ignoreBlocked && BlockedLinks.isBlocked(link)) {
continue;
// Remove any blocked links.
if (!options.ignoreBlocked) {
links = links.filter(link => !BlockedLinks.isBlocked(link));
}
if (options.onePerDomain) {
// De-dup the links.
const exactHosts = new Map();
for (const link of links) {
// First we want to find the best link for an exact host
setBetterLink(exactHosts, link, url => url.match(/:\/\/([^\/]+)/));
}
link.type = "history";
// Clean up exact hosts to dedupe as non-www hosts
const hosts = new Map();
for (const link of exactHosts.values()) {
setBetterLink(hosts, link, url => url.match(/:\/\/(?:www\.)?([^\/]+)/),
// Combine frecencies when deduping these links
(targetLink, otherLink) => {
targetLink.frecency = link.frecency + otherLink.frecency;
});
}
// First we want to find the best link for an exact host
setBetterLink(exactHosts, link, url => url.match(/:\/\/([^\/]+)/));
links = [...hosts.values()];
}
// Clean up exact hosts to dedupe as non-www hosts
const hosts = new Map();
for (const link of exactHosts.values()) {
setBetterLink(hosts, link, url => url.match(/:\/\/(?:www\.)?([^\/]+)/),
// Combine frecencies when deduping these links
(targetLink, otherLink) => {
targetLink.frecency = link.frecency + otherLink.frecency;
});
}
// Pick out the top links using the same comparer as before
links = [...hosts.values()].sort(isOtherBetter).slice(0, origNumItems);
links = links.sort(isOtherBetter).slice(0, origNumItems);
if (!options.includeFavicon) {
return links;
}
// Get the favicons as data URI for now (until we use the favicon protocol)
return this._faviconBytesToDataURI(await this._addFavicons(links));
},
@ -1289,14 +1302,15 @@ var ActivityStreamLinks = {
* @param {Object} aData
* aData.url The url to bookmark
* aData.title The title of the page to bookmark
* @param {Browser} aBrowser
* a <browser> element
* @param {Window} aBrowserWindow
* The current browser chrome window
*
* @returns {Promise} Returns a promise set to an object representing the bookmark
*/
addBookmark(aData, aBrowser) {
addBookmark(aData, aBrowserWindow) {
const {url, title} = aData;
return aBrowser.ownerGlobal.PlacesCommandHook.bookmarkPage(
return aBrowserWindow.PlacesCommandHook.bookmarkLink(
PlacesUtils.bookmarksMenuFolderId,
url,
title);
},

Просмотреть файл

@ -137,10 +137,14 @@ const SecurityInfo = {
info.cipherSuite = SSLStatus.cipherName;
// Key exchange group name.
info.keaGroupName = SSLStatus.keaGroupName;
if (SSLStatus.keaGroupName !== "none") {
info.keaGroupName = SSLStatus.keaGroupName;
}
// Certificate signature scheme.
info.signatureSchemeName = SSLStatus.signatureSchemeName;
if (SSLStatus.signatureSchemeName !== "none") {
info.signatureSchemeName = SSLStatus.signatureSchemeName;
}
info.isDomainMismatch = SSLStatus.isDomainMismatch;
info.isExtendedValidation = SSLStatus.isExtendedValidation;

Просмотреть файл

@ -679,6 +679,31 @@ add_task(async function getTopFrecentSites() {
Assert.equal(links[0].url, testURI, "added visit corresponds to added url");
});
add_task(async function getTopFrecentSites_no_dedup() {
await setUpActivityStreamTest();
let provider = NewTabUtils.activityStreamLinks;
let links = await provider.getTopSites({topsiteFrecency: 100});
Assert.equal(links.length, 0, "empty history yields empty links");
// Add a visits in reverse order they will be returned in when not deduped.
let testURIs = [{uri: "http://www.mozilla.com/"}, {uri: "http://mozilla.com/"}];
await PlacesTestUtils.addVisits(testURIs);
links = await provider.getTopSites();
Assert.equal(links.length, 0, "adding a single visit doesn't exceed default threshold");
links = await provider.getTopSites({topsiteFrecency: 100});
Assert.equal(links.length, 1, "adding a visit yields a link");
// Plain domain is returned when deduped.
Assert.equal(links[0].url, testURIs[1].uri, "added visit corresponds to added url");
links = await provider.getTopSites({topsiteFrecency: 100, onePerDomain: false});
Assert.equal(links.length, 2, "adding a visit yields a link");
Assert.equal(links[0].url, testURIs[1].uri, "added visit corresponds to added url");
Assert.equal(links[1].url, testURIs[0].uri, "added visit corresponds to added url");
});
add_task(async function getTopFrecentSites_dedupeWWW() {
await setUpActivityStreamTest();

Просмотреть файл

@ -124,6 +124,7 @@ def lint(paths, config, **lintargs):
os.path.join(bindir, 'flake8'),
'--format', '{"path":"%(path)s","lineno":%(row)s,'
'"column":%(col)s,"rule":"%(code)s","message":"%(text)s"}',
'--filename', ','.join(['*.{}'.format(e) for e in config['extensions']]),
]
fix_cmdargs = [

Просмотреть файл

@ -0,0 +1,2 @@
# unused import
import os

Просмотреть файл

@ -80,5 +80,10 @@ def test_lint_excluded_file(lint, paths):
assert len(results) == 0
def test_lint_uses_custom_extensions(lint, paths):
assert len(lint(paths('ext'))) == 1
assert len(lint(paths('ext/bad.configure'))) == 1
if __name__ == '__main__':
mozunit.main()

Просмотреть файл

@ -891,7 +891,8 @@ NS_IMETHODIMP nsXULWindow::SetVisibility(bool aVisibility)
nsCOMPtr<nsIObserverService> obssvc = services::GetObserverService();
NS_ASSERTION(obssvc, "Couldn't get observer service.");
if (obssvc) {
obssvc->NotifyObservers(nullptr, "xul-window-visible", nullptr);
obssvc->NotifyObservers(static_cast<nsIXULWindow*>(this),
"xul-window-visible", nullptr);
}
mDebuting = false;