Merge autoland to mozilla-central a=merge

This commit is contained in:
Razvan Maries 2019-06-20 12:45:34 +03:00
Родитель 288befd88a d0441eaece
Коммит da14c413ef
201 изменённых файлов: 3712 добавлений и 1805 удалений

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

@ -1212,7 +1212,6 @@ pref("services.sync.prefs.sync.browser.safebrowsing.downloads.enabled", true);
pref("services.sync.prefs.sync.browser.safebrowsing.passwords.enabled", true);
pref("services.sync.prefs.sync.browser.search.update", true);
pref("services.sync.prefs.sync.browser.search.widget.inNavBar", true);
pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
pref("services.sync.prefs.sync.browser.startup.homepage", true);
pref("services.sync.prefs.sync.browser.startup.page", true);
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);

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

@ -1946,6 +1946,10 @@ var gBrowserInit = {
DownloadsCommon.initializeAllDataLinks();
ChromeUtils.import("resource:///modules/DownloadsTaskbar.jsm", {})
.DownloadsTaskbar.registerIndicator(window);
if (AppConstants.platform == "macosx") {
ChromeUtils.import("resource:///modules/DownloadsMacFinderProgress.jsm")
.DownloadsMacFinderProgress.register();
}
} catch (ex) {
Cu.reportError(ex);
}

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

@ -11,7 +11,7 @@ const {RemotePages} = ChromeUtils.import("resource://gre/modules/remotepagemanag
var AboutProtectionsHandler = {
_inited: false,
_topics: [
"ArrivedOnPage",
"openContentBlockingPreferences",
],
init() {
@ -33,11 +33,11 @@ var AboutProtectionsHandler = {
},
receiveMessage(aMessage) {
let win = aMessage.target.browser.ownerGlobal;
switch (aMessage.name) {
case "ArrivedOnPage": {
// Successfully recieved a message
case "openContentBlockingPreferences":
win.openPreferences("privacy-trackingprotection", {origin: "about-protections"});
break;
}
}
},
};

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

@ -0,0 +1,87 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
/* 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/. */
/**
* Handles the download progress indicator of the macOS Finder.
*/
"use strict";
var EXPORTED_SYMBOLS = [
"DownloadsMacFinderProgress",
];
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
Downloads: "resource://gre/modules/Downloads.jsm",
});
var DownloadsMacFinderProgress = {
/**
* Maps the path of the download, to the according progress indicator instance.
*/
_finderProgresses: null,
/**
* This method is called after a new browser window on macOS is opened, it
* registers for receiving download events for the progressbar of the Finder.
*/
register() {
// Ensure to register only once per process and not for every window.
if (!this._finderProgresses) {
this._finderProgresses = new Map();
Downloads.getList(Downloads.ALL).then(list => list.addView(this));
}
},
onDownloadAdded(download) {
if (download.stopped) {
return;
}
let finderProgress = Cc["@mozilla.org/widget/macfinderprogress;1"]
.createInstance(Ci.nsIMacFinderProgress);
let path = download.target.path;
finderProgress.init(path, () => {
download.cancel().catch(Cu.reportError);
download.removePartialData().catch(Cu.reportError);
});
if (download.hasProgress) {
finderProgress.updateProgress(download.currentBytes, download.totalBytes);
} else {
finderProgress.updateProgress(0, 0);
}
this._finderProgresses.set(path, finderProgress);
},
onDownloadChanged(download) {
let path = download.target.path;
let finderProgress = this._finderProgresses.get(path);
if (!finderProgress) {
// The download is not tracked, it may have been restarted,
// thus forward the call to onDownloadAdded to check if it should be tracked.
this.onDownloadAdded(download);
} else if (download.stopped) {
finderProgress.end();
this._finderProgresses.delete(path);
} else {
finderProgress.updateProgress(download.currentBytes, download.totalBytes);
}
},
onDownloadRemoved(download) {
let path = download.target.path;
let finderProgress = this._finderProgresses.get(path);
if (finderProgress) {
finderProgress.end();
this._finderProgresses.delete(path);
}
},
};

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

@ -18,5 +18,10 @@ EXTRA_JS_MODULES += [
'DownloadsViewUI.jsm',
]
toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
if toolkit == 'cocoa':
EXTRA_JS_MODULES += ['DownloadsMacFinderProgress.jsm']
with Files('**'):
BUG_COMPONENT = ('Firefox', 'Downloads Panel')

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

@ -107,7 +107,6 @@ Preferences.addAll([
{ id: "browser.tabs.loadInBackground", type: "bool", inverted: true },
{ id: "browser.tabs.warnOnClose", type: "bool" },
{ id: "browser.tabs.warnOnOpen", type: "bool" },
{ id: "browser.sessionstore.restore_on_demand", type: "bool" },
{ id: "browser.ctrlTab.recentlyUsedOrder", type: "bool" },
// CFR

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

@ -1,12 +1,94 @@
/* 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/. */
.under-construction {
background-image: url("chrome://browser/content/illustrations/under-construction.svg");
background-repeat: no-repeat;
background-position: center;
min-height: 300px;
min-width: 300px;
/* Move the image down a bit - should be slightly higher than halfway down the page */
margin-top: -10%;
:root {
--card-box-shadow: 0 1px 4px 0 rgba(12,12,13,0.1), 0 1px 0 0 rgba(0,0,0,0.05);
--card-background: #FFF;
--clickable-text-hover: hsla(0,0%,70%,.2);
--clickable-text-active: hsla(0,0%,70%,.3);
--card-divider: rgba(12,12,13,0.1) 1px solid;
--report-background: #FAFAFC;
--card-padding: 22px;
}
body {
background-color: var(--report-background);
font: message-box;
margin-top: 82px;
}
#report-title {
font-size: 20px;
font-weight: 300;
margin-bottom: 22px;
}
#report-content {
width: 763px;
margin: 0 auto;
}
.etp-card .icon {
width: 60px;
height: 60px;
background: url("chrome://browser/skin/controlcenter/tracking-protection.svg") no-repeat center/cover;
grid-column: 1;
margin: 0 auto;
}
.report-card {
display: grid;
grid-template-columns: 100%;
grid-template-rows: 20% auto;
border-radius: 3px;
background-color: var(--card-background);
box-shadow: var(--card-box-shadow);
}
.report-card .card-header {
display: grid;
grid-template-columns: 1fr 7fr;
padding: var(--card-padding);
grid-gap: var(--card-padding);
}
.report-card .card-title {
font-size: 16px;
line-height: 22px;
margin: 0;
cursor: default;
}
.report-card .content {
margin-bottom: 24px;
margin-top: 5px;
font-size: 14px;
cursor: default;
}
#protection-details {
background: url("chrome://browser/skin/settings.svg") no-repeat 3px 3px;
padding: 4px 4px 4px 24px;
font-size: 12px;
display: inline;
cursor: default;
}
#protection-details:hover {
background-color: var(--clickable-text-hover);
}
#protection-details:hover:active {
background-color: var(--clickable-text-active);
}
#protection-details span {
font-weight: bold;
}
.card-body {
border-top: var(--card-divider);
grid-column: span 2;
grid-row: 2;
margin-bottom: 24px;
}

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

@ -7,8 +7,6 @@
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src chrome: blob:">
<link rel="stylesheet" media="screen, projection" type="text/css"
href="chrome://global/skin/in-content/info-pages.css" title="infop">
<link rel="stylesheet" type="text/css"
href="chrome://browser/content/protections.css">
<link rel="icon" href="chrome://global/skin/icons/warning.svg">
@ -17,6 +15,26 @@
</head>
<body>
<div class="under-construction"><div/>
<div id="report-content">
<h2 id="report-title">Privacy Protections</h2>
<div class="report-card etp-card">
<div class="card-header">
<div class="icon"></div>
<div class="wrapper">
<h3 class="card-title">
Enhanced Tracking Protection
</h3>
<p class="content">
Trackers follow you around online to collect information about your browsing habits and interests. Firefox blocks many of these trackers and other malicious scripts.
</p>
<p id="protection-details">
Protection Level is set to <span>Standard</span>
</p>
</div>
</div>
<div class="card-body">
</div>
</div>
</div>
</body>
</html>

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

@ -5,5 +5,8 @@
/* eslint-env mozilla/frame-script */
document.addEventListener("DOMContentLoaded", (e) => {
RPMSendAsyncMessage("ArrivedOnPage");
let protectionDetails = document.getElementById("protection-details");
protectionDetails.addEventListener("click", () => {
RPMSendAsyncMessage("openContentBlockingPreferences");
});
});

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

@ -17,10 +17,14 @@ var RemotePrompt = {
receiveMessage(message) {
switch (message.name) {
case "Prompt:Open":
if (message.data.uri) {
this.openModalWindow(message.data, message.target);
} else {
const COMMON_DIALOG = "chrome://global/content/commonDialog.xul";
const SELECT_DIALOG = "chrome://global/content/selectDialog.xul";
if (message.data.tabPrompt) {
this.openTabPrompt(message.data, message.target);
} else {
let uri = (message.data.promptType == "select") ? SELECT_DIALOG : COMMON_DIALOG;
this.openModalWindow(uri, message.data, message.target);
}
break;
}
@ -85,13 +89,13 @@ var RemotePrompt = {
}
},
openModalWindow(args, browser) {
openModalWindow(uri, args, browser) {
let window = browser.ownerGlobal;
try {
PromptUtils.fireDialogEvent(window, "DOMWillOpenModalDialog", browser);
let bag = PromptUtils.objectToPropBag(args);
Services.ww.openWindow(window, args.uri, "_blank",
Services.ww.openWindow(window, uri, "_blank",
"centerscreen,chrome,modal,titlebar", bag);
PromptUtils.propBagToObject(bag, args);

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

@ -1122,7 +1122,7 @@ panelview .toolbarbutton-1,
transform: translateY(1px);
}
#main-window:not([customizing]) .subviewbutton-nav[disabled=true]::after {
:root:not([customizing]) .subviewbutton-nav[disabled=true]::after {
opacity: 0.4;
}

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

@ -24,7 +24,7 @@ async function updateBreakpoints(dispatch, client, newEvents: string[]) {
active: newEvents,
};
client.setEventListenerBreakpoints(newEvents);
await client.setEventListenerBreakpoints(newEvents);
}
async function updateExpanded(dispatch, newExpanded: string[]) {
@ -46,7 +46,7 @@ export function addEventListenerBreakpoints(eventsToAdd: string[]) {
const newEvents = uniq([...eventsToAdd, ...activeListenerBreakpoints]);
updateBreakpoints(dispatch, client, newEvents);
await updateBreakpoints(dispatch, client, newEvents);
};
}
@ -59,7 +59,7 @@ export function removeEventListenerBreakpoints(eventsToRemove: string[]) {
event => !eventsToRemove.includes(event)
);
updateBreakpoints(dispatch, client, newEvents);
await updateBreakpoints(dispatch, client, newEvents);
};
}

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

@ -48,7 +48,11 @@ export async function onConnect(connection: any, actions: Object) {
});
// Retrieve possible event listener breakpoints
actions.getEventListenerBreakpointTypes();
actions.getEventListenerBreakpointTypes().catch(e => console.error(e));
// Initialize the event breakpoints on the thread up front so that
// they are active once attached.
actions.addEventListenerBreakpoints([]).catch(e => console.error(e));
// In Firefox, we need to initially request all of the sources. This
// usually fires off individual `newSource` notifications as the

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

@ -35,7 +35,10 @@ import type {
SourcesPacket,
} from "./types";
import type { EventListenerCategoryList } from "../../actions/types";
import type {
EventListenerCategoryList,
EventListenerActiveList,
} from "../../actions/types";
let workerClients: Object;
let threadClient: ThreadClient;
@ -43,6 +46,7 @@ let tabTarget: TabTarget;
let debuggerClient: DebuggerClient;
let sourceActors: { [ActorId]: SourceId };
let breakpoints: { [string]: Object };
let eventBreakpoints: ?EventListenerActiveList;
let supportsWasm: boolean;
let shouldWaitForWorkers = false;
@ -363,6 +367,8 @@ function interrupt(thread: string): Promise<*> {
}
async function setEventListenerBreakpoints(ids: string[]) {
eventBreakpoints = ids;
await threadClient.setActiveEventBreakpoints(ids);
await forEachWorkerThread(thread => thread.setActiveEventBreakpoints(ids));
}
@ -371,8 +377,7 @@ async function setEventListenerBreakpoints(ids: string[]) {
async function getEventListenerBreakpointTypes(): Promise<
EventListenerCategoryList
> {
const { value } = await threadClient.getAvailableEventBreakpoints();
return value;
return threadClient.getAvailableEventBreakpoints();
}
function pauseGrip(thread: string, func: Function): ObjectClient {
@ -406,6 +411,7 @@ async function fetchWorkers(): Promise<Worker[]> {
if (features.windowlessWorkers) {
const options = {
breakpoints,
eventBreakpoints,
observeAsmJS: true,
};

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

@ -368,9 +368,7 @@ export type ThreadClient = {
request: (payload: Object) => Promise<*>,
url: string,
setActiveEventBreakpoints: (string[]) => void,
getAvailableEventBreakpoints: () => Promise<{|
value: EventListenerCategoryList,
|}>,
getAvailableEventBreakpoints: () => Promise<EventListenerCategoryList>,
skipBreakpoints: boolean => Promise<{| skip: boolean |}>,
};

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

@ -91,7 +91,14 @@ class EventListeners extends Component<Props> {
<input
type="checkbox"
value={category.name}
onChange={e => this.onCategoryClick(category, e.target.checked)}
onChange={e => {
this.onCategoryClick(
category,
// Clicking an indeterminate checkbox should always have the
// effect of disabling any selected items.
indeterminate ? false : e.target.checked
);
}}
checked={checked}
ref={el => el && (el.indeterminate = indeterminate)}
/>

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

@ -46,19 +46,19 @@ function update(
}
export function getActiveEventListeners(state: State): EventListenerActiveList {
return state.eventListenerBreakpoints.active;
return state.eventListenerBreakpoints.active || [];
}
export function getEventListenerBreakpointTypes(
state: State
): EventListenerCategoryList {
return state.eventListenerBreakpoints.categories;
return state.eventListenerBreakpoints.categories || [];
}
export function getEventListenerExpanded(
state: State
): EventListenerExpandedList {
return state.eventListenerBreakpoints.expanded;
return state.eventListenerBreakpoints.expanded || [];
}
export default update;

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

@ -16,6 +16,7 @@ const reasons = {
exception: "whyPaused.exception",
resumeLimit: "whyPaused.resumeLimit",
breakpointConditionThrown: "whyPaused.breakpointConditionThrown",
eventBreakpoint: "whyPaused.eventBreakpoint",
// V8
DOM: "whyPaused.breakpoint",

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

@ -593,6 +593,8 @@ support-files =
examples/html-breakpoints-slow.js
examples/sjs_slow-load.sjs
examples/fetch.js
examples/doc-event-breakpoints.html
examples/event-breakpoints.js
examples/doc-xhr.html
examples/doc-xhr-run-to-completion.html
examples/doc-scroll-run-to-completion.html
@ -806,6 +808,7 @@ skip-if = true
[browser_dbg-worker-scopes.js]
skip-if = (os == 'linux' && debug) || ccov #Bug 1456013
[browser_dbg-event-handler.js]
[browser_dbg-event-breakpoints.js]
[browser_dbg-eval-throw.js]
[browser_dbg-sourceURL-breakpoint.js]
[browser_dbg-old-breakpoint.js]

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

@ -0,0 +1,48 @@
/* 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/>. */
function assertPauseLocation(dbg, line) {
const { location } = dbg.selectors.getVisibleSelectedFrame();
const source = findSource(dbg, "event-breakpoints.js");
is(location.sourceId, source.id, `correct sourceId`);
is(location.line, line, `correct line`);
assertPausedLocation(dbg);
}
add_task(async function() {
await pushPref("devtools.debugger.features.event-listeners-breakpoints", true);
const dbg = await initDebugger("doc-event-breakpoints.html", "event-breakpoints");
await selectSource(dbg, "event-breakpoints");
await waitForSelectedSource(dbg, "event-breakpoints");
await dbg.actions.addEventListenerBreakpoints([
"event.mouse.click",
"event.xhr.load",
"timer.timeout.set",
"timer.timeout.fire",
]);
invokeInTab("clickHandler");
await waitForPaused(dbg);
assertPauseLocation(dbg, 12);
await resume(dbg);
invokeInTab("xhrHandler");
await waitForPaused(dbg);
assertPauseLocation(dbg, 20);
await resume(dbg);
invokeInTab("timerHandler");
await waitForPaused(dbg);
assertPauseLocation(dbg, 27);
await resume(dbg);
await waitForPaused(dbg);
assertPauseLocation(dbg, 29);
await resume(dbg);
});

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

@ -0,0 +1,20 @@
<!-- 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/. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Debugger event bp test page</title>
</head>
<body>
<button id="click-button">Run Click Handler</button>
<button id="xhr-button">Run XHR Handler</button>
<button id="timer-button">Run Timer Handler</button>
<div id="click-target" style="margin: 50px; background-color: green;">
Click Target
</div>
<script src="event-breakpoints.js"></script>
</body>
</html>

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

@ -0,0 +1,34 @@
/* 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/>. */
document.getElementById("click-button").onmousedown = clickHandler;
function clickHandler() {
document.getElementById("click-target").click();
}
document.getElementById("click-target").onclick = clickTargetClicked;
function clickTargetClicked() {
console.log("clicked");
}
document.getElementById("xhr-button").onmousedown = xhrHandler;
function xhrHandler() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "doc-event-breakpoints.html", true);
xhr.onload = function(){
console.log("xhr load");
};
xhr.send();
}
document.getElementById("timer-button").onmousedown = timerHandler;
function timerHandler() {
setTimeout(
() => {
console.log("timer callback");
},
50
);
console.log("timer set");
}

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

@ -983,6 +983,11 @@ whyPaused.debuggerStatement=Paused on debugger statement
# in a info block explaining how the debugger is currently paused on a breakpoint
whyPaused.breakpoint=Paused on breakpoint
# LOCALIZATION NOTE (whyPaused.eventBreakpoint): The text that is displayed
# in a info block explaining how the debugger is currently paused on an event
# breakpoint.
whyPaused.eventBreakpoint=Paused on event breakpoint
# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed
# in a info block explaining how the debugger is currently paused on an exception
whyPaused.exception=Paused on exception

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

@ -66,6 +66,10 @@ headersEmptyText=No headers for this request
# headers tab of the network details pane for the filtering input.
headersFilterText=Filter headers
# LOCALIZATION NOTE (webSocketsEmptyText): This is the text displayed in the
# WebSockets tab of the network details pane when there are no frames available.
webSocketsEmptyText=No WebSocket frames for this request
# LOCALIZATION NOTE (cookiesEmptyText): This is the text displayed in the
# cookies tab of the network details pane when there are no cookies available.
cookiesEmptyText=No cookies for this request
@ -637,6 +641,10 @@ netmonitor.toolbar.waterfall=Timeline
# in the network details pane identifying the headers tab.
netmonitor.tab.headers=Headers
# LOCALIZATION NOTE (netmonitor.tab.webSockets): This is the label displayed
# in the network details pane identifying the webSockets tab.
netmonitor.tab.webSockets=WebSockets
# LOCALIZATION NOTE (netmonitor.tab.cookies): This is the label displayed
# in the network details pane identifying the cookies tab.
netmonitor.tab.cookies=Cookies

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

@ -11,6 +11,7 @@ const selection = require("./selection");
const sort = require("./sort");
const timingMarkers = require("./timing-markers");
const ui = require("./ui");
const webSockets = require("./web-sockets");
Object.assign(exports,
batching,
@ -19,5 +20,6 @@ Object.assign(exports,
selection,
sort,
timingMarkers,
ui
ui,
webSockets,
);

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

@ -11,4 +11,5 @@ DevToolsModules(
'sort.js',
'timing-markers.js',
'ui.js',
'web-sockets.js',
)

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

@ -0,0 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { WS_ADD_FRAME } = require("../constants");
function addFrame(httpChannelId, data) {
return {
type: WS_ADD_FRAME,
httpChannelId,
data,
};
}
module.exports = {
addFrame,
};

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

@ -4,6 +4,7 @@
"use strict";
const Services = require("Services");
const {
Component,
createFactory,
@ -17,6 +18,7 @@ const Tabbar = createFactory(require("devtools/client/shared/components/tabs/Tab
const TabPanel = createFactory(require("devtools/client/shared/components/tabs/Tabs").TabPanel);
const CookiesPanel = createFactory(require("./CookiesPanel"));
const HeadersPanel = createFactory(require("./HeadersPanel"));
const WebSocketsPanel = createFactory(require("./WebSocketsPanel"));
const ParamsPanel = createFactory(require("./ParamsPanel"));
const CachePanel = createFactory(require("./CachePanel"));
const ResponsePanel = createFactory(require("./ResponsePanel"));
@ -28,6 +30,7 @@ const COLLAPSE_DETAILS_PANE = L10N.getStr("collapseDetailsPane");
const CACHE_TITLE = L10N.getStr("netmonitor.tab.cache");
const COOKIES_TITLE = L10N.getStr("netmonitor.tab.cookies");
const HEADERS_TITLE = L10N.getStr("netmonitor.tab.headers");
const WEBSOCKETS_TITLE = L10N.getStr("netmonitor.tab.webSockets");
const PARAMS_TITLE = L10N.getStr("netmonitor.tab.params");
const RESPONSE_TITLE = L10N.getStr("netmonitor.tab.response");
const SECURITY_TITLE = L10N.getStr("netmonitor.tab.security");
@ -87,6 +90,11 @@ class TabboxPanel extends Component {
return null;
}
const channelId = request.channelId;
const showWebSocketsPanel =
request.cause.type === "websocket" &&
Services.prefs.getBoolPref(
"devtools.netmonitor.features.webSockets");
return (
Tabbar({
activeTabId,
@ -113,6 +121,14 @@ class TabboxPanel extends Component {
request,
}),
),
showWebSocketsPanel && TabPanel({
id: PANELS.WEBSOCKETS,
title: WEBSOCKETS_TITLE,
},
WebSocketsPanel({
channelId,
}),
),
TabPanel({
id: PANELS.COOKIES,
title: COOKIES_TITLE,

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

@ -0,0 +1,85 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {
connect,
} = require("devtools/client/shared/redux/visibility-handler-connect");
const { getFramesByChannelId } = require("../selectors/index");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { table, tbody, thead, tr, td, th, div } = dom;
const { L10N } = require("../utils/l10n");
const FRAMES_EMPTY_TEXT = L10N.getStr("webSocketsEmptyText");
class WebSocketsPanel extends Component {
static get propTypes() {
return {
channelId: PropTypes.number,
frames: PropTypes.array,
};
}
constructor(props) {
super(props);
}
render() {
const { frames } = this.props;
if (!frames) {
return div({ className: "empty-notice" },
FRAMES_EMPTY_TEXT
);
}
const rows = [];
frames.forEach((frame, index) => {
rows.push(
tr(
{ key: index,
className: "frames-row" },
td({ className: "frames-cell" }, frame.type),
td({ className: "frames-cell" }, frame.httpChannelId),
td({ className: "frames-cell" }, frame.payload),
td({ className: "frames-cell" }, frame.opCode),
td({ className: "frames-cell" }, frame.maskBit.toString()),
td({ className: "frames-cell" }, frame.finBit.toString()),
td({ className: "frames-cell" }, frame.timeStamp)
)
);
});
return table(
{ className: "frames-list-table" },
thead(
{ className: "frames-head" },
tr(
{ className: "frames-row" },
th({ className: "frames-headerCell" }, "Type"),
th({ className: "frames-headerCell" }, "Channel ID"),
th({ className: "frames-headerCell" }, "Payload"),
th({ className: "frames-headerCell" }, "OpCode"),
th({ className: "frames-headerCell" }, "MaskBit"),
th({ className: "frames-headerCell" }, "FinBit"),
th({ className: "frames-headerCell" }, "Time")
)
),
tbody(
{
className: "frames-list-tableBody",
},
rows
)
);
}
}
module.exports = connect((state, props) => ({
frames: getFramesByChannelId(state, props.channelId),
}))(WebSocketsPanel);

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

@ -47,4 +47,5 @@ DevToolsModules(
'TabboxPanel.js',
'TimingsPanel.js',
'Toolbar.js',
'WebSocketsPanel.js',
)

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

@ -79,6 +79,7 @@ class FirefoxDataProvider {
isThirdPartyTrackingResource,
referrerPolicy,
blockedReason,
channelId,
} = data;
// Insert blocked reason in the payload queue as well, as we'll need it later
@ -106,6 +107,7 @@ class FirefoxDataProvider {
isThirdPartyTrackingResource,
referrerPolicy,
blockedReason,
channelId,
}, true);
}
@ -343,6 +345,7 @@ class FirefoxDataProvider {
isThirdPartyTrackingResource,
referrerPolicy,
blockedReason,
channelId,
} = networkInfo;
await this.addRequest(actor, {
@ -356,6 +359,7 @@ class FirefoxDataProvider {
isThirdPartyTrackingResource,
referrerPolicy,
blockedReason,
channelId,
});
this.emit(EVENTS.NETWORK_EVENT, actor);
@ -426,11 +430,6 @@ class FirefoxDataProvider {
* @param {string} extensions
*/
async onWebSocketOpened(httpChannelId, effectiveURI, protocols, extensions) {
console.log("FirefoxDataProvider onWebSocketOpened: " +
" httpChannelId: " + httpChannelId +
" effectiveURI: " + effectiveURI +
" protocols: " + protocols +
" extensions: " + extensions);
}
/**
@ -441,10 +440,6 @@ class FirefoxDataProvider {
* @param {string} reason
*/
async onWebSocketClosed(wasClean, code, reason) {
console.log("FirefoxDataProvider onWebSocketClosed: " +
" wasClean: " + wasClean +
" code: " + code +
" reason: " + reason);
}
/**
@ -454,11 +449,7 @@ class FirefoxDataProvider {
* @param {object} data websocket frame information
*/
async onFrameSent(httpChannelId, data) {
await this.getLongString(data.payload).then(payload => {
console.log("FirefoxDataProvider onFrameSent: " +
" httpChannelId: " + httpChannelId +
" onFrameSent: " + payload);
});
this.addFrame(httpChannelId, data);
}
/**
@ -468,11 +459,20 @@ class FirefoxDataProvider {
* @param {object} data websocket frame information
*/
async onFrameReceived(httpChannelId, data) {
await this.getLongString(data.payload).then(payload => {
console.log("FirefoxDataProvider onFrameReceived: " +
" httpChannelId: " + httpChannelId +
" onFrameSent: " + payload);
});
this.addFrame(httpChannelId, data);
}
/**
* Add a new WebSocket frame to application state.
*
* @param {number} httpChannelId the channel ID
* @param {object} data websocket frame information
*/
async addFrame(httpChannelId, data) {
if (this.actionsEnabled && this.actions.addFrame) {
await this.actions.addFrame(httpChannelId, data);
}
// TODO: Emit an event for test here
}
/**

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

@ -34,6 +34,7 @@ const actionTypes = {
UPDATE_REQUEST: "UPDATE_REQUEST",
WATERFALL_RESIZE: "WATERFALL_RESIZE",
SET_COLUMNS_WIDTH: "SET_COLUMNS_WIDTH",
WS_ADD_FRAME: "WS_ADD_FRAME",
};
// Descriptions for what this frontend is currently doing.
@ -154,11 +155,13 @@ const UPDATE_PROPS = [
"isThirdPartyTrackingResource",
"referrerPolicy",
"blockedReason",
"channelId",
];
const PANELS = {
COOKIES: "cookies",
HEADERS: "headers",
WEBSOCKETS: "webSockets",
PARAMS: "params",
RESPONSE: "response",
CACHE: "cache",

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

@ -27,6 +27,7 @@ const { Requests } = require("./reducers/requests");
const { Sort } = require("./reducers/sort");
const { TimingMarkers } = require("./reducers/timing-markers");
const { UI, Columns, ColumnsData } = require("./reducers/ui");
const { WebSockets } = require("./reducers/web-sockets");
/**
* Configure state and middleware for the Network monitor tool.
@ -44,6 +45,7 @@ function configureStore(connector, telemetry) {
columns: getColumnState(),
columnsData: getColumnsData(),
}),
webSockets: new WebSockets(),
};
// Prepare middleware.

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

@ -11,12 +11,14 @@ const { sortReducer } = require("./sort");
const { filters } = require("./filters");
const { timingMarkers } = require("./timing-markers");
const { ui } = require("./ui");
const { webSocketsReducer } = require("./web-sockets");
const networkThrottling = require("devtools/client/shared/components/throttling/reducer");
module.exports = batchingReducer(
combineReducers({
requests: requestsReducer,
sort: sortReducer,
webSockets: webSocketsReducer,
filters,
timingMarkers,
ui,

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

@ -10,4 +10,5 @@ DevToolsModules(
'sort.js',
'timing-markers.js',
'ui.js',
'web-sockets.js',
)

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

@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
WS_ADD_FRAME,
} = require("../constants");
/**
* This structure stores list of all WebSocket frames received
* from the backend.
*/
function WebSockets() {
return {
// Map with all requests (key = channelId, value = array of frame objects)
frames: new Map(),
};
}
/**
* This reducer is responsible for maintaining list of
* WebSocket frames within the Network panel.
*/
function webSocketsReducer(state = WebSockets(), action) {
switch (action.type) {
// Appending new frame into the map.
case WS_ADD_FRAME: {
const nextState = { ...state };
const newFrame = {
httpChannelId: action.httpChannelId,
...action.data,
};
nextState.frames = mapSet(state.frames, newFrame.httpChannelId, newFrame);
return nextState;
}
default:
return state;
}
}
/**
* Append new item into existing map and return new map.
*/
function mapSet(map, key, value) {
const newMap = new Map(map);
if (newMap.has(key)) {
const framesArray = [...newMap.get(key)];
framesArray.push(value);
newMap.set(key, framesArray);
return newMap;
}
return newMap.set(key, [value]);
}
module.exports = {
WebSockets,
webSocketsReducer,
};

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

@ -7,9 +7,11 @@
const requests = require("./requests");
const timingMarkers = require("./timing-markers");
const ui = require("./ui");
const webSockets = require("./web-sockets");
Object.assign(exports,
requests,
timingMarkers,
ui
ui,
webSockets,
);

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

@ -7,4 +7,5 @@ DevToolsModules(
'requests.js',
'timing-markers.js',
'ui.js',
'web-sockets.js',
)

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

@ -0,0 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
function getFramesByChannelId(state, channelId) {
return state.webSockets.frames.get(channelId);
}
module.exports = {
getFramesByChannelId,
};

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

@ -71,7 +71,7 @@ body {
.variable-or-property .token-number,
.variable-or-property[return] > .title > .name,
.variable-or-property[scope] > .title > .name {
color: #6B89FF;
color: #709AFF;
}
.CodeMirror-Tern-completion-number:before {
@ -124,7 +124,7 @@ body {
.cm-s-mozilla .cm-string-2,
.variable-or-property .token-string,
.CodeMirror-Tern-farg {
color: #6B89FF;
color: #709AFF;
}
.CodeMirror-Tern-completion-string:before,

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

@ -75,6 +75,10 @@ function getCleanedPacket(key, packet) {
res.actor = existingPacket.actor;
}
if (res.channelId) {
res.channelId = existingPacket.channelId;
}
if (res.message) {
// Clean timeStamp on the message prop.
res.message.timeStamp = existingPacket.message.timeStamp;

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

@ -265,6 +265,7 @@ stubPackets.set(`GET request`, {
"private": false,
"isThirdPartyTrackingResource": false,
"referrerPolicy": "no-referrer-when-downgrade",
"channelId": 22673132355586,
"from": "server1.conn0.child1/consoleActor2"
});
@ -315,6 +316,7 @@ stubPackets.set(`XHR GET request`, {
"private": false,
"isThirdPartyTrackingResource": false,
"referrerPolicy": "no-referrer-when-downgrade",
"channelId": 22673132355587,
"from": "server1.conn1.child1/consoleActor2"
});
@ -365,6 +367,7 @@ stubPackets.set(`XHR POST request`, {
"private": false,
"isThirdPartyTrackingResource": false,
"referrerPolicy": "no-referrer-when-downgrade",
"channelId": 22673132355588,
"from": "server1.conn2.child1/consoleActor2"
});

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

@ -68,6 +68,7 @@ const NetworkEventActor = protocol.ActorClassWithSpec(networkEventSpec, {
isThirdPartyTrackingResource: this._isThirdPartyTrackingResource,
referrerPolicy: this._referrerPolicy,
blockedReason: this._blockedReason,
channelId: this._channelId,
};
},

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

@ -6,6 +6,7 @@
"use strict";
const DebuggerNotificationObserver = require("DebuggerNotificationObserver");
const Services = require("Services");
const { Cr, Ci } = require("chrome");
const { ActorPool } = require("devtools/server/actors/common");
@ -16,6 +17,8 @@ const { assert, dumpn } = DevToolsUtils;
const { threadSpec } = require("devtools/shared/specs/thread");
const {
getAvailableEventBreakpoints,
eventBreakpointForNotification,
makeEventBreakpointMessage,
} = require("devtools/server/actors/utils/event-breakpoints");
loader.lazyRequireGetter(this, "EnvironmentActor", "devtools/server/actors/environment", true);
@ -61,7 +64,8 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this._scripts = null;
this._xhrBreakpoints = [];
this._observingNetwork = false;
this._eventBreakpoints = [];
this._activeEventBreakpoints = new Set();
this._activeEventPause = null;
this._priorPause = null;
@ -94,6 +98,10 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this.objectGrip = this.objectGrip.bind(this);
this.pauseObjectGrip = this.pauseObjectGrip.bind(this);
this._onOpeningRequest = this._onOpeningRequest.bind(this);
this._onNewDebuggee = this._onNewDebuggee.bind(this);
this._eventBreakpointListener = this._eventBreakpointListener.bind(this);
this._debuggerNotificationObserver = new DebuggerNotificationObserver();
if (Services.obs) {
// Set a wrappedJSObject property so |this| can be sent via the observer svc
@ -112,6 +120,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this._dbg.uncaughtExceptionHook = this.uncaughtExceptionHook;
this._dbg.onDebuggerStatement = this.onDebuggerStatement;
this._dbg.onNewScript = this.onNewScript;
this._dbg.onNewDebuggee = this._onNewDebuggee;
if (this._dbg.replaying) {
this._dbg.replayingOnForcedPause = this.replayingOnForcedPause.bind(this);
const sendProgress = throttle((recording, executionPoint) => {
@ -223,6 +232,16 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this._xhrBreakpoints = [];
this._updateNetworkObserver();
this._activeEventBreakpoints = new Set();
this._debuggerNotificationObserver.removeListener(
this._eventBreakpointListener);
for (const global of this.dbg.getDebuggees()) {
try {
this._debuggerNotificationObserver.disconnect(global);
} catch (e) { }
}
this.sources.off("newSource", this.onNewSourceEvent);
this.clearDebuggees();
this.conn.removeActorPool(this._threadLifetimePool);
@ -285,6 +304,9 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
if (options.breakpoints) {
this._setBreakpointsOnAttach(options.breakpoints);
}
if (options.eventBreakpoints) {
this.setActiveEventBreakpoints(options.eventBreakpoints);
}
this.dbg.addDebuggees();
this.dbg.enabled = true;
@ -400,10 +422,24 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return getAvailableEventBreakpoints();
},
getActiveEventBreakpoints: function() {
return this._eventBreakpoints;
return Array.from(this._activeEventBreakpoints);
},
setActiveEventBreakpoints: function(ids) {
this._eventBreakpoints = ids;
this._activeEventBreakpoints = new Set(ids);
if (this._activeEventBreakpoints.size === 0) {
this._debuggerNotificationObserver.removeListener(
this._eventBreakpointListener);
} else {
this._debuggerNotificationObserver.addListener(
this._eventBreakpointListener);
}
},
_onNewDebuggee(global) {
try {
this._debuggerNotificationObserver.connect(global);
} catch (e) { }
},
_updateNetworkObserver() {
@ -513,6 +549,81 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return {};
},
_eventBreakpointListener(notification) {
if (this._state === "paused" || this._state === "detached") {
return;
}
const eventBreakpoint =
eventBreakpointForNotification(this.dbg, notification);
if (!this._activeEventBreakpoints.has(eventBreakpoint)) {
return;
}
if (notification.phase === "pre" && !this._activeEventPause) {
this._activeEventPause = this._captureDebuggerHooks();
this.dbg.onEnterFrame =
this._makeEventBreakpointEnterFrame(eventBreakpoint);
} else if (notification.phase === "post" && this._activeEventPause) {
this._restoreDebuggerHooks(this._activeEventPause);
this._activeEventPause = null;
} else if (!notification.phase && !this._activeEventPause) {
const frame = this.dbg.getNewestFrame();
if (frame) {
const { sourceActor } = this.sources.getFrameLocation(frame);
const url = sourceActor.url;
if (this.sources.isBlackBoxed(url)) {
return;
}
this._pauseAndRespondEventBreakpoint(frame, eventBreakpoint);
}
}
},
_makeEventBreakpointEnterFrame(eventBreakpoint) {
return frame => {
const { sourceActor } = this.sources.getFrameLocation(frame);
const url = sourceActor.url;
if (this.sources.isBlackBoxed(url)) {
return undefined;
}
this._restoreDebuggerHooks(this._activeEventPause);
this._activeEventPause = null;
return this._pauseAndRespondEventBreakpoint(frame, eventBreakpoint);
};
},
_pauseAndRespondEventBreakpoint(frame, eventBreakpoint) {
if (this.skipBreakpoints) {
return undefined;
}
return this._pauseAndRespond(frame, {
type: "eventBreakpoint",
breakpoint: eventBreakpoint,
message: makeEventBreakpointMessage(eventBreakpoint),
});
},
_captureDebuggerHooks() {
return {
onEnterFrame: this.dbg.onEnterFrame,
onStep: this.dbg.onStep,
onPop: this.dbg.onPop,
};
},
_restoreDebuggerHooks(hooks) {
this.dbg.onEnterFrame = hooks.onEnterFrame;
this.dbg.onStep = hooks.onStep;
this.dbg.onPop = hooks.onPop;
},
/**
* Pause the debuggee, by entering a nested event loop, and return a 'paused'
* packet to the client.
@ -575,7 +686,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return this._parentClosed ? null : undefined;
},
_makeOnEnterFrame: function({ thread, pauseAndRespond }) {
_makeOnEnterFrame: function({ pauseAndRespond }) {
return frame => {
const { sourceActor } = this.sources.getFrameLocation(frame);
@ -590,13 +701,13 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
}
// Continue forward until we get to a valid step target.
const { onStep, onPop } = thread._makeSteppingHooks(
const { onStep, onPop } = this._makeSteppingHooks(
null, "next", false, null
);
if (thread.dbg.replaying) {
if (this.dbg.replaying) {
const offsets =
thread._findReplayingStepOffsets(null, frame,
this._findReplayingStepOffsets(null, frame,
/* rewinding = */ false);
frame.setReplayingOnStep(onStep, offsets);
} else {
@ -608,7 +719,8 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
};
},
_makeOnPop: function({ thread, pauseAndRespond, startLocation, steppingType }) {
_makeOnPop: function({ pauseAndRespond, startLocation, steppingType }) {
const thread = this;
const result = function(completion) {
// onPop is called with 'this' set to the current frame.
const location = thread.sources.getFrameLocation(this);
@ -728,8 +840,9 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return script.getOffsetMetadata(offset).isStepStart;
},
_makeOnStep: function({ thread, pauseAndRespond, startFrame,
_makeOnStep: function({ pauseAndRespond, startFrame,
startLocation, steppingType, completion, rewinding }) {
const thread = this;
return function() {
// onStep is called with 'this' set to the current frame.
@ -828,7 +941,6 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
{ type: "resumeLimit" },
onPacket
),
thread: this,
startFrame: this.youngestFrame,
startLocation: startLocation,
steppingType: steppingType,

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

@ -6,6 +6,401 @@
"use strict";
function generalEvent(groupID, eventType) {
return {
id: `event.${groupID}.${eventType}`,
type: "event",
name: eventType,
message: `DOM '${eventType}' event`,
eventType,
filter: "general",
};
}
function nodeEvent(groupID, eventType) {
return {
...generalEvent(groupID, eventType),
filter: "node",
};
}
function mediaNodeEvent(groupID, eventType) {
return {
...generalEvent(groupID, eventType),
filter: "media",
};
}
function globalEvent(groupID, eventType) {
return {
...generalEvent(groupID, eventType),
message: `Global '${eventType}' event`,
filter: "global",
};
}
function xhrEvent(groupID, eventType) {
return {
...generalEvent(groupID, eventType),
message: `XHR '${eventType}' event`,
filter: "xhr",
};
}
function workerEvent(eventType) {
return {
...generalEvent("worker", eventType),
message: `Worker '${eventType}' event`,
filter: "worker",
};
}
function timerEvent(type, operation, name, notificationType) {
return {
id: `timer.${type}.${operation}`,
type: "simple",
name,
message: name,
notificationType,
};
}
function animationEvent(operation, name, notificationType) {
return {
id: `animationframe.${operation}`,
type: "simple",
name,
message: name,
notificationType,
};
}
const AVAILABLE_BREAKPOINTS = [
{
name: "Animation",
items: [
animationEvent(
"request",
"Request Animation Frame",
"requestAnimationFrame"
),
animationEvent(
"cancel",
"Cancel Animation Frame",
"cancelAnimationFrame"
),
animationEvent(
"fire",
"Animation Frame fired",
"requestAnimationFrameCallback"
),
],
},
{
name: "Clipboard",
items: [
generalEvent("clipboard", "copy"),
generalEvent("clipboard", "cut"),
generalEvent("clipboard", "paste"),
generalEvent("clipboard", "beforecopy"),
generalEvent("clipboard", "beforecut"),
generalEvent("clipboard", "beforepaste"),
],
},
{
name: "Control",
items: [
generalEvent("control", "resize"),
generalEvent("control", "scroll"),
generalEvent("control", "zoom"),
generalEvent("control", "focus"),
generalEvent("control", "blur"),
generalEvent("control", "select"),
generalEvent("control", "change"),
generalEvent("control", "submit"),
generalEvent("control", "reset"),
],
},
{
name: "DOM Mutation",
items: [
// Deprecated DOM events.
nodeEvent("dom-mutation", "DOMActivate"),
nodeEvent("dom-mutation", "DOMFocusIn"),
nodeEvent("dom-mutation", "DOMFocusOut"),
// Standard DOM mutation events.
nodeEvent("dom-mutation", "DOMAttrModified"),
nodeEvent("dom-mutation", "DOMCharacterDataModified"),
nodeEvent("dom-mutation", "DOMNodeInserted"),
nodeEvent("dom-mutation", "DOMNodeInsertedIntoDocument"),
nodeEvent("dom-mutation", "DOMNodeRemoved"),
nodeEvent("dom-mutation", "DOMNodeRemovedIntoDocument"),
nodeEvent("dom-mutation", "DOMSubtreeModified"),
// DOM load events.
nodeEvent("dom-mutation", "DOMContentLoaded"),
],
},
{
name: "Device",
items: [
globalEvent("device", "deviceorientation"),
globalEvent("device", "devicemotion"),
],
},
{
name: "Drag and Drop",
items: [
generalEvent("drag-and-drop", "drag"),
generalEvent("drag-and-drop", "dragstart"),
generalEvent("drag-and-drop", "dragend"),
generalEvent("drag-and-drop", "dragenter"),
generalEvent("drag-and-drop", "dragover"),
generalEvent("drag-and-drop", "dragleave"),
generalEvent("drag-and-drop", "drop"),
],
},
{
name: "Keyboard",
items: [
generalEvent("keyboard", "keydown"),
generalEvent("keyboard", "keyup"),
generalEvent("keyboard", "keypress"),
generalEvent("keyboard", "input"),
],
},
{
name: "Load",
items: [
globalEvent("load", "load"),
globalEvent("load", "beforeunload"),
globalEvent("load", "unload"),
globalEvent("load", "abort"),
globalEvent("load", "error"),
globalEvent("load", "hashchange"),
globalEvent("load", "popstate"),
],
},
{
name: "Media",
items: [
mediaNodeEvent("media", "play"),
mediaNodeEvent("media", "pause"),
mediaNodeEvent("media", "playing"),
mediaNodeEvent("media", "canplay"),
mediaNodeEvent("media", "canplaythrough"),
mediaNodeEvent("media", "seeking"),
mediaNodeEvent("media", "seeked"),
mediaNodeEvent("media", "timeupdate"),
mediaNodeEvent("media", "ended"),
mediaNodeEvent("media", "ratechange"),
mediaNodeEvent("media", "durationchange"),
mediaNodeEvent("media", "volumechange"),
mediaNodeEvent("media", "loadstart"),
mediaNodeEvent("media", "progress"),
mediaNodeEvent("media", "suspend"),
mediaNodeEvent("media", "abort"),
mediaNodeEvent("media", "error"),
mediaNodeEvent("media", "emptied"),
mediaNodeEvent("media", "stalled"),
mediaNodeEvent("media", "loadedmetadata"),
mediaNodeEvent("media", "loadeddata"),
mediaNodeEvent("media", "waiting"),
],
},
{
name: "Mouse",
items: [
generalEvent("mouse", "auxclick"),
generalEvent("mouse", "click"),
generalEvent("mouse", "dblclick"),
generalEvent("mouse", "mousedown"),
generalEvent("mouse", "mouseup"),
generalEvent("mouse", "mouseover"),
generalEvent("mouse", "mousemove"),
generalEvent("mouse", "mouseout"),
generalEvent("mouse", "mouseenter"),
generalEvent("mouse", "mouseleave"),
generalEvent("mouse", "mousewheel"),
generalEvent("mouse", "wheel"),
generalEvent("mouse", "contextmenu"),
],
},
{
name: "Pointer",
items: [
generalEvent("pointer", "pointerover"),
generalEvent("pointer", "pointerout"),
generalEvent("pointer", "pointerenter"),
generalEvent("pointer", "pointerleave"),
generalEvent("pointer", "pointerdown"),
generalEvent("pointer", "pointerup"),
generalEvent("pointer", "pointermove"),
generalEvent("pointer", "pointercancel"),
generalEvent("pointer", "gotpointercapture"),
generalEvent("pointer", "lostpointercapture"),
],
},
{
name: "Timer",
items: [
timerEvent("timeout", "set", "setTimeout", "setTimeout"),
timerEvent("timeout", "clear", "clearTimeout", "clearTimeout"),
timerEvent("timeout", "fire", "setTimeout fired", "setTimeoutCallback"),
timerEvent("interval", "set", "setInterval", "setInterval"),
timerEvent("interval", "clear", "clearInterval", "clearInterval"),
timerEvent(
"interval",
"fire",
"setInterval fired",
"setIntervalCallback"
),
],
},
{
name: "Touch",
items: [
generalEvent("touch", "touchstart"),
generalEvent("touch", "touchmove"),
generalEvent("touch", "touchend"),
generalEvent("touch", "touchcancel"),
],
},
{
name: "Worker",
items: [
workerEvent("message"),
workerEvent("messageerror"),
],
},
{
name: "XHR",
items: [
xhrEvent("xhr", "readystatechange"),
xhrEvent("xhr", "load"),
xhrEvent("xhr", "loadstart"),
xhrEvent("xhr", "loadend"),
xhrEvent("xhr", "abort"),
xhrEvent("xhr", "error"),
xhrEvent("xhr", "progress"),
xhrEvent("xhr", "timeout"),
],
},
];
const FLAT_EVENTS = [];
for (const category of AVAILABLE_BREAKPOINTS) {
for (const event of category.items) {
FLAT_EVENTS.push(event);
}
}
const EVENTS_BY_ID = {};
for (const event of FLAT_EVENTS) {
if (EVENTS_BY_ID[event.id]) {
throw new Error("Duplicate event ID detected: " + event.id);
}
EVENTS_BY_ID[event.id] = event;
}
const SIMPLE_EVENTS = {};
const DOM_EVENTS = {};
for (const eventBP of FLAT_EVENTS) {
if (eventBP.type === "simple") {
const { notificationType } = eventBP;
if (SIMPLE_EVENTS[notificationType]) {
throw new Error("Duplicate simple event");
}
SIMPLE_EVENTS[notificationType] = eventBP.id;
} else if (eventBP.type === "event") {
const { eventType, filter } = eventBP;
let targetTypes;
if (filter === "global") {
targetTypes = ["global"];
} else if (filter === "xhr") {
targetTypes = ["xhr"];
} else if (filter === "worker") {
targetTypes = ["worker"];
} else if (filter === "general") {
targetTypes = ["global", "node"];
} else if (filter === "node" || filter === "media") {
targetTypes = ["node"];
} else {
throw new Error("Unexpected filter type");
}
for (const targetType of targetTypes) {
let byEventType = DOM_EVENTS[targetType];
if (!byEventType) {
byEventType = {};
DOM_EVENTS[targetType] = byEventType;
}
if (byEventType[eventType]) {
throw new Error("Duplicate dom event: " + eventType);
}
byEventType[eventType] = eventBP.id;
}
} else {
throw new Error("Unknown type: " + eventBP.type);
}
}
exports.eventBreakpointForNotification = eventBreakpointForNotification;
function eventBreakpointForNotification(dbg, notification) {
const notificationType = notification.type;
if (notification.type === "domEvent") {
const domEventNotification = DOM_EVENTS[notification.targetType];
if (!domEventNotification) {
return null;
}
// The 'event' value is a cross-compartment wrapper for the DOM Event object.
// While we could use that directly in the main thread as an Xray wrapper,
// when debugging workers we can't, because it is an opaque wrapper.
// To make things work, we have to always interact with the Event object via
// the Debugger.Object interface.
const evt = dbg
.makeGlobalObjectReference(notification.global)
.makeDebuggeeValue(notification.event);
const eventType = evt.getProperty("type").return;
const id = domEventNotification[eventType];
if (!id) {
return null;
}
const eventBreakpoint = EVENTS_BY_ID[id];
if (eventBreakpoint.filter === "media") {
const currentTarget = evt.getProperty("currentTarget").return;
if (!currentTarget) {
return null;
}
const nodeType = currentTarget.getProperty("nodeType").return;
const namespaceURI = currentTarget.getProperty("namespaceURI").return;
if (
nodeType !== 1 /* ELEMENT_NODE */ ||
namespaceURI !== "http://www.w3.org/1999/xhtml"
) {
return null;
}
const nodeName =
currentTarget.getProperty("nodeName").return.toLowerCase();
if (nodeName !== "audio" && nodeName !== "video") {
return null;
}
}
return id;
}
return SIMPLE_EVENTS[notificationType] || null;
}
exports.makeEventBreakpointMessage = makeEventBreakpointMessage;
function makeEventBreakpointMessage(id) {
return EVENTS_BY_ID[id].message;
}
exports.getAvailableEventBreakpoints = getAvailableEventBreakpoints;
function getAvailableEventBreakpoints() {
const available = [];
@ -14,196 +409,9 @@ function getAvailableEventBreakpoints() {
name,
events: items.map(item => ({
id: item.id,
name: item.eventType,
name: item.name,
})),
});
}
return available;
}
function event(groupID, name, filter = "content") {
return {
id: `${groupID}.event.${name}`,
type: "event",
eventType: name,
filter,
};
}
const AVAILABLE_BREAKPOINTS = [
{
name: "Clipboard",
items: [
event("clipboard", "copy"),
event("clipboard", "cut"),
event("clipboard", "paste"),
event("clipboard", "beforecopy"),
event("clipboard", "beforecut"),
event("clipboard", "beforepaste"),
],
},
{
name: "Control",
items: [
event("control", "resize"),
event("control", "scroll"),
event("control", "zoom"),
event("control", "focus"),
event("control", "blur"),
event("control", "select"),
event("control", "change"),
event("control", "submit"),
event("control", "reset"),
],
},
{
name: "DOM Mutation",
items: [
// Deprecated DOM events.
event("dom-mutation", "DOMActivate"),
event("dom-mutation", "DOMFocusIn"),
event("dom-mutation", "DOMFocusOut"),
// Standard DOM mutation events.
event("dom-mutation", "DOMAttrModified"),
event("dom-mutation", "DOMCharacterDataModified"),
event("dom-mutation", "DOMNodeInserted"),
event("dom-mutation", "DOMNodeInsertedIntoDocument"),
event("dom-mutation", "DOMNodeRemoved"),
event("dom-mutation", "DOMNodeRemovedIntoDocument"),
event("dom-mutation", "DOMSubtreeModified"),
// DOM load events.
event("dom-mutation", "DOMContentLoaded"),
],
},
{
name: "Device",
items: [
event("device", "deviceorientation"),
event("device", "devicemotion"),
],
},
{
name: "Drag and Drop",
items: [
event("drag-and-drop", "drag"),
event("drag-and-drop", "dragstart"),
event("drag-and-drop", "dragend"),
event("drag-and-drop", "dragenter"),
event("drag-and-drop", "dragover"),
event("drag-and-drop", "dragleave"),
event("drag-and-drop", "drop"),
],
},
{
name: "Keyboard",
items: [
event("keyboard", "keydown"),
event("keyboard", "keyup"),
event("keyboard", "keypress"),
event("keyboard", "input"),
],
},
{
name: "Load",
items: [
event("load", "load", "global"),
event("load", "beforeunload", "global"),
event("load", "unload", "global"),
event("load", "abort", "global"),
event("load", "error", "global"),
event("load", "hashchange", "global"),
event("load", "popstate", "global"),
],
},
{
name: "Media",
items: [
event("media", "play", "media"),
event("media", "pause", "media"),
event("media", "playing", "media"),
event("media", "canplay", "media"),
event("media", "canplaythrough", "media"),
event("media", "seeking", "media"),
event("media", "seeked", "media"),
event("media", "timeupdate", "media"),
event("media", "ended", "media"),
event("media", "ratechange", "media"),
event("media", "durationchange", "media"),
event("media", "volumechange", "media"),
event("media", "loadstart", "media"),
event("media", "progress", "media"),
event("media", "suspend", "media"),
event("media", "abort", "media"),
event("media", "error", "media"),
event("media", "emptied", "media"),
event("media", "stalled", "media"),
event("media", "loadedmetadata", "media"),
event("media", "loadeddata", "media"),
event("media", "waiting", "media"),
],
},
{
name: "Mouse",
items: [
event("mouse", "auxclick"),
event("mouse", "click"),
event("mouse", "dblclick"),
event("mouse", "mousedown"),
event("mouse", "mouseup"),
event("mouse", "mouseover"),
event("mouse", "mousemove"),
event("mouse", "mouseout"),
event("mouse", "mouseenter"),
event("mouse", "mouseleave"),
event("mouse", "mousewheel"),
event("mouse", "wheel"),
event("mouse", "contextmenu"),
],
},
{
name: "Pointer",
items: [
event("pointer", "pointerover"),
event("pointer", "pointerout"),
event("pointer", "pointerenter"),
event("pointer", "pointerleave"),
event("pointer", "pointerdown"),
event("pointer", "pointerup"),
event("pointer", "pointermove"),
event("pointer", "pointercancel"),
event("pointer", "gotpointercapture"),
event("pointer", "lostpointercapture"),
],
},
{
name: "Touch",
items: [
event("touch", "touchstart"),
event("touch", "touchmove"),
event("touch", "touchend"),
event("touch", "touchcancel"),
],
},
{
name: "Worker",
items: [
event("worker", "message", "global"),
event("worker", "messageerror", "global"),
],
},
{
name: "XHR",
items: [
event("xhr", "readystatechange", "xhr"),
event("xhr", "load", "xhr"),
event("xhr", "loadstart", "xhr"),
event("xhr", "loadend", "xhr"),
event("xhr", "abort", "xhr"),
event("xhr", "error", "xhr"),
event("xhr", "progress", "xhr"),
event("xhr", "timeout", "xhr"),
],
},
];

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

@ -64,15 +64,23 @@ module.exports = function makeDebugger({ findDebuggees, shouldAddNewGlobalAsDebu
dbg.allowUnobservedAsmJS = true;
dbg.uncaughtExceptionHook = reportDebuggerHookException;
function onNewDebuggee(global) {
if (dbg.onNewDebuggee) {
dbg.onNewDebuggee(global);
}
}
dbg.onNewGlobalObject = function(global) {
if (shouldAddNewGlobalAsDebuggee(global)) {
safeAddDebuggee(this, global);
onNewDebuggee(global);
}
};
dbg.addDebuggees = function() {
for (const global of findDebuggees(this)) {
safeAddDebuggee(this, global);
onNewDebuggee(global);
}
};

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

@ -23,6 +23,7 @@ const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
// Steal various globals only available in JSM scope (and not Sandbox one)
const {
console,
DebuggerNotificationObserver,
DOMPoint,
DOMQuad,
DOMRect,
@ -229,6 +230,7 @@ function lazyRequireGetter(obj, property, module, destructure) {
// List of pseudo modules exposed to all devtools modules.
exports.modules = {
ChromeUtils,
DebuggerNotificationObserver,
HeapSnapshot,
promise,
// Expose "chrome" Promise, which aren't related to any document

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

@ -44,6 +44,7 @@ const UnsolicitedPauses = {
breakpoint: "breakpoint",
DOMEvent: "DOMEvent",
watchpoint: "watchpoint",
eventBreakpoint: "eventBreakpoint",
exception: "exception",
replayForcedPause: "replayForcedPause",
};

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

@ -97,6 +97,7 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
isThirdPartyTrackingResource: actor.isThirdPartyTrackingResource,
referrerPolicy: actor.referrerPolicy,
blockedReason: actor.blockedReason,
channelId: actor.channelId,
};
this._networkRequests.set(actor.actor, networkInfo);

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

@ -4,7 +4,7 @@
"use strict";
/* global worker */
/* global worker, DebuggerNotificationObserver */
// A CommonJS module loader that is designed to run inside a worker debugger.
// We can't simply use the SDK module loader, because it relies heavily on
@ -576,6 +576,7 @@ this.worker = new WorkerDebuggerLoader({
"chrome": chrome,
"xpcInspector": xpcInspector,
"ChromeUtils": ChromeUtils,
"DebuggerNotificationObserver": DebuggerNotificationObserver,
},
paths: {
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠

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

@ -42,9 +42,9 @@ already_AddRefed<DOMMatrixReadOnly> DOMMatrixReadOnly::Constructor(
const GlobalObject& aGlobal,
const Optional<StringOrUnrestrictedDoubleSequence>& aArg,
ErrorResult& aRv) {
RefPtr<DOMMatrixReadOnly> rval =
new DOMMatrixReadOnly(aGlobal.GetAsSupports());
if (!aArg.WasPassed()) {
RefPtr<DOMMatrixReadOnly> rval =
new DOMMatrixReadOnly(aGlobal.GetAsSupports());
return rval.forget();
}
@ -56,12 +56,18 @@ already_AddRefed<DOMMatrixReadOnly> DOMMatrixReadOnly::Constructor(
aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
return nullptr;
}
RefPtr<DOMMatrixReadOnly> rval =
new DOMMatrixReadOnly(aGlobal.GetAsSupports());
rval->SetMatrixValue(arg.GetAsString(), aRv);
} else {
const auto& sequence = arg.GetAsUnrestrictedDoubleSequence();
SetDataInMatrix(rval, sequence.Elements(), sequence.Length(), aRv);
return rval.forget();
}
const auto& sequence = arg.GetAsUnrestrictedDoubleSequence();
const int length = sequence.Length();
const bool is2D = length == 6;
RefPtr<DOMMatrixReadOnly> rval =
new DOMMatrixReadOnly(aGlobal.GetAsSupports(), is2D);
SetDataInMatrix(rval, sequence.Elements(), length, aRv);
return rval.forget();
}
@ -509,9 +515,12 @@ static void SetDataInMatrix(DOMMatrixReadOnly* aMatrix, const T* aData,
already_AddRefed<DOMMatrix> DOMMatrix::Constructor(const GlobalObject& aGlobal,
const Float32Array& aArray32,
ErrorResult& aRv) {
RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports());
aArray32.ComputeLengthAndData();
SetDataInMatrix(obj, aArray32.Data(), aArray32.Length(), aRv);
const int length = aArray32.Length();
const bool is2D = length == 6;
RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports(), is2D);
SetDataInMatrix(obj, aArray32.Data(), length, aRv);
return obj.forget();
}
@ -519,9 +528,12 @@ already_AddRefed<DOMMatrix> DOMMatrix::Constructor(const GlobalObject& aGlobal,
already_AddRefed<DOMMatrix> DOMMatrix::Constructor(const GlobalObject& aGlobal,
const Float64Array& aArray64,
ErrorResult& aRv) {
RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports());
aArray64.ComputeLengthAndData();
SetDataInMatrix(obj, aArray64.Data(), aArray64.Length(), aRv);
const int length = aArray64.Length();
const bool is2D = length == 6;
RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports(), is2D);
SetDataInMatrix(obj, aArray64.Data(), length, aRv);
return obj.forget();
}
@ -529,9 +541,10 @@ already_AddRefed<DOMMatrix> DOMMatrix::Constructor(const GlobalObject& aGlobal,
already_AddRefed<DOMMatrix> DOMMatrix::Constructor(
const GlobalObject& aGlobal, const Sequence<double>& aNumberSequence,
ErrorResult& aRv) {
RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports());
SetDataInMatrix(obj, aNumberSequence.Elements(), aNumberSequence.Length(),
aRv);
const int length = aNumberSequence.Length();
const bool is2D = length == 6;
RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports(), is2D);
SetDataInMatrix(obj, aNumberSequence.Elements(), length, aRv);
return obj.forget();
}
@ -770,7 +783,9 @@ DOMMatrixReadOnly* DOMMatrixReadOnly::SetMatrixValue(
if (!contains3dTransform) {
mMatrix3D = nullptr;
mMatrix2D = new gfx::MatrixDouble();
if (!mMatrix2D) {
mMatrix2D = new gfx::MatrixDouble();
}
SetA(transform._11);
SetB(transform._12);

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

@ -2431,7 +2431,7 @@ class MethodDefiner(PropertyDefiner):
self.regular.append({
"name": "@@iterator",
"methodInfo": False,
"selfHostedName": "ArrayValues",
"selfHostedName": "$ArrayValues",
"length": 0,
"flags": "0", # Not enumerable, per spec.
"condition": MemberCondition()
@ -2457,7 +2457,7 @@ class MethodDefiner(PropertyDefiner):
self.regular.append({
"name": "values",
"methodInfo": False,
"selfHostedName": "ArrayValues",
"selfHostedName": "$ArrayValues",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": PropertyDefiner.getControllingCondition(m,

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

@ -70,6 +70,9 @@ Gamepad::Gamepad(nsISupports* aParent, const nsAString& aID, uint32_t aIndex,
mTouchEvents.AppendElement(new GamepadTouch(mParent));
}
// Mapping touchId(0) to touchIdHash(0) by default.
mTouchIdHash.Put(0, mTouchIdHashValue);
++mTouchIdHashValue;
UpdateTimestamp();
}

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

@ -361,6 +361,11 @@ class StadiaControllerRemapper final : public GamepadRemapper {
class Dualshock4Remapper final : public GamepadRemapper {
public:
Dualshock4Remapper() {
mLastTouches.SetLength(TOUCH_EVENT_COUNT);
mLastTouchId.SetLength(TOUCH_EVENT_COUNT);
}
virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
virtual uint32_t GetButtonCount() const override {
@ -403,45 +408,43 @@ class Dualshock4Remapper final : public GamepadRemapper {
touches.SetLength(TOUCH_EVENT_COUNT);
uint8_t* rawData = (uint8_t*)aInput;
const uint32_t kTouchDimensionX = 1920;
const uint32_t kTouchDimensionY = 942;
bool touch0Pressed = (((rawData[35] & 0xff) >> 7) == 0);
bool touch1Pressed = (((rawData[39] & 0xff) >> 7) == 0);
if (!touch0Pressed && !touch1Pressed) {
return;
}
if ((touch0Pressed && (rawData[35] & 0xff) < mLastTouch0Id) ||
(touch1Pressed && (rawData[39] & 0xff) < mLastTouch1Id)) {
if ((touch0Pressed && (rawData[35] & 0xff) < mLastTouchId[0]) ||
(touch1Pressed && (rawData[39] & 0xff) < mLastTouchId[1])) {
mTouchIdBase += 128;
}
const uint32_t kTouchDimensionX = 1920;
const uint32_t kTouchDimensionY = 942;
touches[0].touchId = mTouchIdBase + (rawData[35] & 0x7f);
touches[0].surfaceId = 0;
touches[0].position[0] = NormalizeTouch(
((rawData[37] & 0xf) << 8) | rawData[36], 0, (kTouchDimensionX - 1));
touches[0].position[1] =
NormalizeTouch(rawData[38] << 4 | ((rawData[37] & 0xf0) >> 4), 0,
(kTouchDimensionY - 1));
touches[0].surfaceDimensions[0] = kTouchDimensionX;
touches[0].surfaceDimensions[1] = kTouchDimensionY;
touches[0].isSurfaceDimensionsValid = true;
mLastTouch0Id = rawData[35] & 0x7f;
touches[1].touchId = mTouchIdBase + (rawData[39] & 0x7f);
touches[1].surfaceId = 0;
touches[1].position[0] =
NormalizeTouch((((rawData[41] & 0xf) << 8) | rawData[40]) + 1, 0,
(kTouchDimensionX - 1));
touches[1].position[1] =
NormalizeTouch(rawData[42] << 4 | ((rawData[41] & 0xf0) >> 4), 0,
(kTouchDimensionY - 1));
touches[1].surfaceDimensions[0] = kTouchDimensionX;
touches[1].surfaceDimensions[1] = kTouchDimensionY;
touches[1].isSurfaceDimensionsValid = true;
mLastTouch1Id = rawData[39] & 0x7f;
if (touch0Pressed) {
touches[0].touchId = mTouchIdBase + (rawData[35] & 0x7f);
touches[0].surfaceId = 0;
touches[0].position[0] = NormalizeTouch(
((rawData[37] & 0xf) << 8) | rawData[36], 0, (kTouchDimensionX - 1));
touches[0].position[1] =
NormalizeTouch(rawData[38] << 4 | ((rawData[37] & 0xf0) >> 4), 0,
(kTouchDimensionY - 1));
touches[0].surfaceDimensions[0] = kTouchDimensionX;
touches[0].surfaceDimensions[1] = kTouchDimensionY;
touches[0].isSurfaceDimensionsValid = true;
mLastTouchId[0] = rawData[35] & 0x7f;
}
if (touch1Pressed) {
touches[1].touchId = mTouchIdBase + (rawData[39] & 0x7f);
touches[1].surfaceId = 0;
touches[1].position[0] =
NormalizeTouch((((rawData[41] & 0xf) << 8) | rawData[40]) + 1, 0,
(kTouchDimensionX - 1));
touches[1].position[1] =
NormalizeTouch(rawData[42] << 4 | ((rawData[41] & 0xf0) >> 4), 0,
(kTouchDimensionY - 1));
touches[1].surfaceDimensions[0] = kTouchDimensionX;
touches[1].surfaceDimensions[1] = kTouchDimensionY;
touches[1].isSurfaceDimensionsValid = true;
mLastTouchId[1] = rawData[39] & 0x7f;
}
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
@ -449,8 +452,15 @@ class Dualshock4Remapper final : public GamepadRemapper {
return;
}
service->NewMultiTouchEvent(aIndex, 0, touches[0]);
service->NewMultiTouchEvent(aIndex, 1, touches[1]);
// Avoid to send duplicate untouched events to the gamepad service.
if ((mLastTouches[0] != touch0Pressed) || touch0Pressed) {
service->NewMultiTouchEvent(aIndex, 0, touches[0]);
}
if ((mLastTouches[1] != touch1Pressed) || touch1Pressed) {
service->NewMultiTouchEvent(aIndex, 1, touches[1]);
}
mLastTouches[0] = touch0Pressed;
mLastTouches[1] = touch1Pressed;
}
virtual void RemapAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
@ -537,8 +547,8 @@ class Dualshock4Remapper final : public GamepadRemapper {
static const uint32_t LIGHT_INDICATOR_COUNT = 1;
static const uint32_t TOUCH_EVENT_COUNT = 2;
unsigned long mLastTouch0Id = 0;
unsigned long mLastTouch1Id = 0;
nsTArray<unsigned long> mLastTouchId;
nsTArray<bool> mLastTouches;
unsigned long mTouchIdBase = 0;
};

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

@ -4061,10 +4061,6 @@ nsresult HTMLMediaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
NotifyUAWidgetSetupOrChange();
}
// FIXME(emilio, bug 1555946): mUnboundFromTree doesn't make any sense, should
// just use IsInComposedDoc() in the relevant places or something.
mUnboundFromTree = false;
if (IsInUncomposedDoc()) {
// The preload action depends on the value of the autoplay attribute.
// It's value may have changed, so update it.
@ -4278,7 +4274,6 @@ void HTMLMediaElement::ReportTelemetry() {
}
void HTMLMediaElement::UnbindFromTree(bool aNullParent) {
mUnboundFromTree = true;
mVisibilityState = Visibility::Untracked;
if (IsInComposedDoc()) {
@ -4290,14 +4285,21 @@ void HTMLMediaElement::UnbindFromTree(bool aNullParent) {
MOZ_ASSERT(IsHidden());
NotifyDecoderActivityChanges();
RefPtr<HTMLMediaElement> self(this);
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction("dom::HTMLMediaElement::UnbindFromTree", [self]() {
if (self->mUnboundFromTree) {
self->Pause();
}
});
RunInStableState(task);
// Dispatch a task to run once we're in a stable state which ensures we're
// paused if we're no longer in a document. Note we set a flag here to
// ensure we don't dispatch redundant tasks.
if (!mDispatchedTaskToPauseIfNotInDocument) {
mDispatchedTaskToPauseIfNotInDocument = true;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
"dom::HTMLMediaElement::UnbindFromTree",
[self = RefPtr<HTMLMediaElement>(this)]() {
self->mDispatchedTaskToPauseIfNotInDocument = false;
if (!self->IsInComposedDoc()) {
self->Pause();
}
});
RunInStableState(task);
}
}
/* static */
@ -5696,7 +5698,7 @@ bool HTMLMediaElement::IsActive() const {
}
bool HTMLMediaElement::IsHidden() const {
return mUnboundFromTree || OwnerDoc()->Hidden();
return !IsInComposedDoc() || OwnerDoc()->Hidden();
}
VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer() {

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

@ -1671,10 +1671,11 @@ class HTMLMediaElement : public nsGenericHTMLElement,
// MediaStream.
nsCOMPtr<nsIPrincipal> mSrcStreamVideoPrincipal;
// True if UnbindFromTree() is called on the element.
// Note this flag is false when the element is in a phase after creation and
// before attaching to the DOM tree.
bool mUnboundFromTree = false;
// True if we've dispatched a task in UnbindFromTree() which runs in a
// stable state and attempts to pause playback if we're not in a composed
// document. The flag stops us dispatching multiple tasks if the element
// is involved in a series of append/remove cycles.
bool mDispatchedTaskToPauseIfNotInDocument = false;
// True if the autoplay media was blocked because it hadn't loaded metadata
// yet.

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

@ -386,13 +386,13 @@ void HTMLVideoElement::ReleaseVideoWakeLockIfExists() {
bool HTMLVideoElement::SetVisualCloneTarget(
HTMLVideoElement* aVisualCloneTarget) {
MOZ_DIAGNOSTIC_ASSERT(
!aVisualCloneTarget || !aVisualCloneTarget->mUnboundFromTree,
!aVisualCloneTarget || aVisualCloneTarget->IsInComposedDoc(),
"Can't set the clone target to a disconnected video "
"element.");
MOZ_DIAGNOSTIC_ASSERT(!mVisualCloneSource,
"Can't clone a video element that is already a clone.");
if (!aVisualCloneTarget ||
(!aVisualCloneTarget->mUnboundFromTree && !mVisualCloneSource)) {
(aVisualCloneTarget->IsInComposedDoc() && !mVisualCloneSource)) {
mVisualCloneTarget = aVisualCloneTarget;
return true;
}
@ -402,14 +402,14 @@ bool HTMLVideoElement::SetVisualCloneTarget(
bool HTMLVideoElement::SetVisualCloneSource(
HTMLVideoElement* aVisualCloneSource) {
MOZ_DIAGNOSTIC_ASSERT(
!aVisualCloneSource || !aVisualCloneSource->mUnboundFromTree,
!aVisualCloneSource || aVisualCloneSource->IsInComposedDoc(),
"Can't set the clone source to a disconnected video "
"element.");
MOZ_DIAGNOSTIC_ASSERT(!mVisualCloneTarget,
"Can't clone a video element that is already a "
"clone.");
if (!aVisualCloneSource ||
(!aVisualCloneSource->mUnboundFromTree && !mVisualCloneTarget)) {
(aVisualCloneSource->IsInComposedDoc() && !mVisualCloneTarget)) {
mVisualCloneSource = aVisualCloneSource;
return true;
}
@ -452,11 +452,11 @@ double HTMLVideoElement::TotalPlayTime() const {
void HTMLVideoElement::CloneElementVisually(HTMLVideoElement& aTargetVideo,
ErrorResult& rv) {
MOZ_ASSERT(!mUnboundFromTree,
MOZ_ASSERT(IsInComposedDoc(),
"Can't clone a video that's not bound to a DOM tree.");
MOZ_ASSERT(!aTargetVideo.mUnboundFromTree,
MOZ_ASSERT(aTargetVideo.IsInComposedDoc(),
"Can't clone to a video that's not bound to a DOM tree.");
if (mUnboundFromTree || aTargetVideo.mUnboundFromTree) {
if (!IsInComposedDoc() || !aTargetVideo.IsInComposedDoc()) {
rv.Throw(NS_ERROR_UNEXPECTED);
return;
}

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

@ -3332,14 +3332,16 @@ ScreenIntSize BrowserChild::GetInnerSize() {
innerSize, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
};
nsRect BrowserChild::GetVisibleRect() {
LayoutDeviceIntRect BrowserChild::GetVisibleRect() {
CSSRect visibleRect;
if (mIsTopLevel) {
// We are conservative about visible rects for top-level browsers to avoid
// artifacts when resizing
return nsRect(nsPoint(), CSSPixel::ToAppUnits(mUnscaledInnerSize));
visibleRect = CSSRect(CSSPoint(), mUnscaledInnerSize);
} else {
return mEffectsInfo.mVisibleRect;
visibleRect = CSSPixel::FromAppUnits(mEffectsInfo.mVisibleRect);
}
return RoundedToInt(visibleRect * mPuppetWidget->GetDefaultScale());
}
ScreenIntRect BrowserChild::GetOuterRect() {

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

@ -549,7 +549,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
ScreenIntSize GetInnerSize();
nsRect GetVisibleRect();
LayoutDeviceIntRect GetVisibleRect();
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow(const ShowInfo& aShowInfo);

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

@ -14,7 +14,8 @@ namespace mozilla {
namespace dom {
MediaElementAudioSourceNode::MediaElementAudioSourceNode(AudioContext* aContext)
: MediaStreamAudioSourceNode(aContext) {}
: MediaStreamAudioSourceNode(aContext, TrackChangeBehavior::FollowChanges) {
}
/* static */
already_AddRefed<MediaElementAudioSourceNode>

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

@ -13,6 +13,7 @@
#include "mozilla/CORSMode.h"
#include "nsContentUtils.h"
#include "nsIScriptError.h"
#include "nsID.h"
namespace mozilla {
namespace dom {
@ -37,9 +38,11 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(MediaStreamAudioSourceNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(MediaStreamAudioSourceNode, AudioNode)
MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* aContext)
MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(
AudioContext* aContext, TrackChangeBehavior aBehavior)
: AudioNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers) {}
ChannelInterpretation::Speakers),
mBehavior(aBehavior) {}
/* static */
already_AddRefed<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::Create(
@ -63,7 +66,7 @@ already_AddRefed<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::Create(
}
RefPtr<MediaStreamAudioSourceNode> node =
new MediaStreamAudioSourceNode(&aAudioContext);
new MediaStreamAudioSourceNode(&aAudioContext, LockOnTrackPicked);
node->Init(aOptions.mMediaStream, aRv);
if (aRv.Failed()) {
@ -96,7 +99,7 @@ void MediaStreamAudioSourceNode::Init(DOMMediaStream* aMediaStream,
if (mInputStream->Active()) {
NotifyActive();
}
AttachToFirstTrack(mInputStream);
AttachToRightTrack(mInputStream, aRv);
}
void MediaStreamAudioSourceNode::Destroy() {
@ -137,14 +140,35 @@ void MediaStreamAudioSourceNode::DetachFromTrack() {
}
}
void MediaStreamAudioSourceNode::AttachToFirstTrack(
const RefPtr<DOMMediaStream>& aMediaStream) {
static int AudioTrackCompare(const RefPtr<AudioStreamTrack>& aLhs,
const RefPtr<AudioStreamTrack>& aRhs) {
nsAutoStringN<NSID_LENGTH> IDLhs;
nsAutoStringN<NSID_LENGTH> IDRhs;
aLhs->GetId(IDLhs);
aRhs->GetId(IDRhs);
return NS_ConvertUTF16toUTF8(IDLhs).Compare(
NS_ConvertUTF16toUTF8(IDRhs).get());
}
void MediaStreamAudioSourceNode::AttachToRightTrack(
const RefPtr<DOMMediaStream>& aMediaStream, ErrorResult& aRv) {
nsTArray<RefPtr<AudioStreamTrack>> tracks;
aMediaStream->GetAudioTracks(tracks);
if (tracks.IsEmpty() && mBehavior == LockOnTrackPicked) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
// Sort the track to have a stable order, on their ID by lexicographic
// ordering on sequences of code unit values.
tracks.Sort(AudioTrackCompare);
for (const RefPtr<AudioStreamTrack>& track : tracks) {
if (track->Ended()) {
continue;
if (mBehavior == FollowChanges) {
if (track->Ended()) {
continue;
}
}
AttachToTrack(track);
@ -158,6 +182,9 @@ void MediaStreamAudioSourceNode::AttachToFirstTrack(
void MediaStreamAudioSourceNode::NotifyTrackAdded(
const RefPtr<MediaStreamTrack>& aTrack) {
if (mBehavior != FollowChanges) {
return;
}
if (mInputTrack) {
return;
}
@ -171,12 +198,14 @@ void MediaStreamAudioSourceNode::NotifyTrackAdded(
void MediaStreamAudioSourceNode::NotifyTrackRemoved(
const RefPtr<MediaStreamTrack>& aTrack) {
if (aTrack != mInputTrack) {
return;
}
if (mBehavior == FollowChanges) {
if (aTrack != mInputTrack) {
return;
}
DetachFromTrack();
AttachToFirstTrack(mInputStream);
DetachFromTrack();
AttachToRightTrack(mInputStream, IgnoreErrors());
}
}
void MediaStreamAudioSourceNode::NotifyActive() {

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

@ -80,8 +80,10 @@ class MediaStreamAudioSourceNode
// Detaches from the currently attached track if there is one.
void DetachFromTrack();
// Attaches to the first available audio track in aMediaStream.
void AttachToFirstTrack(const RefPtr<DOMMediaStream>& aMediaStream);
// Attaches to the first audio track in the MediaStream, when the tracks are
// ordered by id.
void AttachToRightTrack(const RefPtr<DOMMediaStream>& aMediaStream,
ErrorResult& aRv);
// From DOMMediaStream::TrackListener.
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override;
@ -91,13 +93,27 @@ class MediaStreamAudioSourceNode
// From PrincipalChangeObserver<MediaStreamTrack>.
void PrincipalChanged(MediaStreamTrack* aMediaStreamTrack) override;
// This allows implementing the correct behaviour for both
// MediaElementAudioSourceNode and MediaStreamAudioSourceNode, that have most
// of their behaviour shared.
enum TrackChangeBehavior {
// MediaStreamAudioSourceNode locks on the track it picked, and never
// changes.
LockOnTrackPicked,
// MediaElementAudioSourceNode can change track, depending on what the
// HTMLMediaElement does.
FollowChanges
};
protected:
explicit MediaStreamAudioSourceNode(AudioContext* aContext);
MediaStreamAudioSourceNode(AudioContext* aContext,
TrackChangeBehavior aBehavior);
void Init(DOMMediaStream* aMediaStream, ErrorResult& aRv);
virtual void Destroy();
virtual ~MediaStreamAudioSourceNode();
private:
const TrackChangeBehavior mBehavior;
RefPtr<MediaInputPort> mInputPort;
RefPtr<DOMMediaStream> mInputStream;

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

@ -104,7 +104,6 @@ tags=capturestream
[test_bug1118372.html]
[test_bug1027864.html]
[test_bug1056032.html]
skip-if = toolkit == 'android' # bug 1056706
[test_bug1255618.html]
skip-if = (os == "win" && processor == "aarch64") # aarch64 due to 1538360
[test_bug1267579.html]
@ -140,7 +139,6 @@ skip-if = !asan && toolkit != android
[test_delayNode.html]
[test_delayNodeAtMax.html]
[test_delayNodeChannelChanges.html]
skip-if = toolkit == 'android' # bug 1056706
[test_delayNodeCycles.html]
[test_delayNodePassThrough.html]
[test_delayNodeSmallMaxDelay.html]

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

@ -33,7 +33,7 @@ function tryToCreateNodeOnClosedContext(ctx) {
args: [new Audio()],
onOfflineAudioContext: false },
{ name: "createMediaStreamSource",
args: [new Audio().mozCaptureStream()],
args: [(new AudioContext()).createMediaStreamDestination().stream],
onOfflineAudioContext: false } ].forEach(function(e) {
if (e.onOfflineAudioContext == false &&
@ -74,7 +74,6 @@ function tryLegalOpeerationsOnClosedContext(ctx) {
loadFile("ting-44.1k-1ch.ogg", function(buf) {
ctx.decodeAudioData(buf).then(function(decodedBuf) {
ok(true, "decodeAudioData on a closed context should work, it did.")
todo(false, "0 " + (ctx instanceof OfflineAudioContext ? "Offline" : "Realtime"));
finish();
}).catch(function(e){
ok(false, "decodeAudioData on a closed context should work, it did not");
@ -121,8 +120,6 @@ function testMultiContextOutput() {
}
}
todo(false, "input buffer is " + (silent ? "silent" : "noisy"));
if (silent) {
silentBuffersInARow++;
if (silentBuffersInARow == 10) {
@ -131,7 +128,6 @@ function testMultiContextOutput() {
sp2.onaudioprocess = null;
ac1.close();
ac2.close();
todo(false,"1");
finish();
}
} else {
@ -182,7 +178,6 @@ function testMultiContextInput() {
ac2.close();
sp1.onaudioprocess = null;
sp2.onaudioprocess = null;
todo(false, "2");
finish();
}
}
@ -231,7 +226,6 @@ function testScriptProcessNodeSuspended() {
}
} else {
sp.onaudioprocess = null;
todo(false,"3");
finish();
}
}

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

@ -12,45 +12,48 @@
SimpleTest.waitForExplicitFinish();
var audio = new Audio("http://example.org:80/tests/dom/media/webaudio/test/small-shot.ogg");
audio.load();
var context = new AudioContext();
var node = context.createMediaStreamSource(audio.mozCaptureStreamUntilEnded());
var sp = context.createScriptProcessor(2048, 1);
node.connect(sp);
var nonzeroSampleCount = 0;
var complete = false;
var iterationCount = 0;
audio.onloadedmetadata = function() {
var node = context.createMediaStreamSource(audio.mozCaptureStreamUntilEnded());
var sp = context.createScriptProcessor(2048, 1);
node.connect(sp);
var nonzeroSampleCount = 0;
var complete = false;
var iterationCount = 0;
// This test ensures we receive at least expectedSampleCount nonzero samples
function processSamples(e) {
if (complete) {
return;
}
// This test ensures we receive at least expectedSampleCount nonzero samples
function processSamples(e) {
if (complete) {
return;
}
if (iterationCount == 0) {
// Don't start playing the audio until the AudioContext stuff is connected
// and running.
audio.play();
}
++iterationCount;
if (iterationCount == 0) {
// Don't start playing the audio until the AudioContext stuff is connected
// and running.
audio.play();
}
++iterationCount;
var buf = e.inputBuffer.getChannelData(0);
var nonzeroSamplesThisBuffer = 0;
for (var i = 0; i < buf.length; ++i) {
if (buf[i] != 0) {
++nonzeroSamplesThisBuffer;
var buf = e.inputBuffer.getChannelData(0);
var nonzeroSamplesThisBuffer = 0;
for (var i = 0; i < buf.length; ++i) {
if (buf[i] != 0) {
++nonzeroSamplesThisBuffer;
}
}
is(nonzeroSamplesThisBuffer, 0,
"Checking all samples are zero");
if (iterationCount >= 20) {
SimpleTest.finish();
complete = true;
}
}
is(nonzeroSamplesThisBuffer, 0,
"Checking all samples are zero");
if (iterationCount >= 20) {
SimpleTest.finish();
complete = true;
}
}
audio.oncanplaythrough = function() {
sp.onaudioprocess = processSamples;
};
audio.oncanplaythrough = function() {
sp.onaudioprocess = processSamples;
};
}
</script>
</pre>
</body>

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

@ -15,6 +15,7 @@
#include "SVGEllipseElement.h"
#include "SVGGeometryProperty.h"
#include "SVGRectElement.h"
#include "mozilla/dom/DOMPointBinding.h"
#include "mozilla/dom/SVGLengthBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
@ -114,6 +115,18 @@ already_AddRefed<Path> SVGGeometryElement::GetOrBuildPathForMeasuring() {
return GetOrBuildPath(drawTarget, fillRule);
}
// This helper is currently identical to GetOrBuildPathForMeasuring.
// We keep it a separate method because for length measuring purpose,
// fillRule isn't really needed. Derived class (e.g. SVGPathElement)
// may override GetOrBuildPathForMeasuring() to ignore fillRule. And
// GetOrBuildPathForMeasuring() itself may be modified in the future.
already_AddRefed<Path> SVGGeometryElement::GetOrBuildPathForHitTest() {
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
FillRule fillRule = mCachedPath ? mCachedPath->GetFillRule() : GetFillRule();
return GetOrBuildPath(drawTarget, fillRule);
}
bool SVGGeometryElement::IsGeometryChangedViaCSS(
ComputedStyle const& aNewStyle, ComputedStyle const& aOldStyle) const {
if (IsSVGElement(nsGkAtoms::rect)) {
@ -153,6 +166,54 @@ FillRule SVGGeometryElement::GetFillRule() {
return fillRule;
}
static Point GetPointFrom(const DOMPointInit& aPoint) {
return Point(aPoint.mX, aPoint.mY);
}
bool SVGGeometryElement::IsPointInFill(const DOMPointInit& aPoint) {
auto point = GetPointFrom(aPoint);
RefPtr<Path> path = GetOrBuildPathForHitTest();
if (!path) {
return false;
}
return path->ContainsPoint(point, {});
}
bool SVGGeometryElement::IsPointInStroke(const DOMPointInit& aPoint) {
auto point = GetPointFrom(aPoint);
RefPtr<Path> path = GetOrBuildPathForHitTest();
if (!path) {
return false;
}
bool res = false;
SVGGeometryProperty::DoForComputedStyle(this, [&](const ComputedStyle* s) {
// Per spec, we should take vector-effect into account.
if (s->StyleSVGReset()->HasNonScalingStroke()) {
auto mat = SVGContentUtils::GetCTM(this, true);
if (mat.HasNonTranslation()) {
// We have non-scaling-stroke as well as a non-translation transform.
// We should transform the path first then apply the stroke on the
// transformed path to preserve the stroke-width.
RefPtr<PathBuilder> builder = path->TransformedCopyToBuilder(mat);
path = builder->Finish();
point = mat.TransformPoint(point);
}
}
SVGContentUtils::AutoStrokeOptions strokeOptions;
SVGContentUtils::GetStrokeOptions(&strokeOptions, this, s, nullptr);
res = path->StrokeContainsPoint(strokeOptions, point, {});
});
return res;
}
float SVGGeometryElement::GetTotalLength() {
RefPtr<Path> flat = GetOrBuildPathForMeasuring();
return flat ? flat->ComputeLength() : 0.f;

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

@ -216,6 +216,8 @@ class SVGGeometryElement : public SVGGeometryElementBase {
// WebIDL
already_AddRefed<DOMSVGAnimatedNumber> PathLength();
bool IsPointInFill(const DOMPointInit& aPoint);
bool IsPointInStroke(const DOMPointInit& aPoint);
float GetTotalLength();
already_AddRefed<nsISVGPoint> GetPointAtLength(float distance,
ErrorResult& rv);
@ -227,6 +229,9 @@ class SVGGeometryElement : public SVGGeometryElementBase {
SVGAnimatedNumber mPathLength;
static NumberInfo sNumberInfo;
mutable RefPtr<Path> mCachedPath;
private:
already_AddRefed<Path> GetOrBuildPathForHitTest();
};
} // namespace dom

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

@ -462,7 +462,7 @@ function testCreateMatrix3D()
// Should be initialised to identity
cmpMatrix(m, [1, 0, 0, 1, 0, 0],
"DOMMatrix should produce identity matrix");
is(m.is2D, true, "should not produce 3d matrix");
is(m.is2D, false, "should produce 3d matrix");
m = new DOMMatrix([1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]);
@ -707,16 +707,16 @@ function testParsing()
}
function testStringify() {
var m = new DOMMatrix();
var s = "" + m;
ok(s == "matrix" + formatMatrix(m), "stringifier 1 produced wrong result: " + s);
m.a = 100;
s = "" + m;
ok(s == "matrix" + formatMatrix(m), "stringifier 2 produced wrong result: " + s);
m.m43 = 200;
s = "" + m;
ok(s == "matrix3d" + formatMatrix(m), "stringifier 3 produced wrong result:" + s);
function testStringify() {
var m = new DOMMatrix();
var s = "" + m;
ok(s == "matrix" + formatMatrix(m), "stringifier 1 produced wrong result: " + s);
m.a = 100;
s = "" + m;
ok(s == "matrix" + formatMatrix(m), "stringifier 2 produced wrong result: " + s);
m.m43 = 200;
s = "" + m;
ok(s == "matrix3d" + formatMatrix(m), "stringifier 3 produced wrong result:" + s);
}
window.addEventListener("load", main);

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

@ -14,6 +14,9 @@ interface SVGGeometryElement : SVGGraphicsElement {
[SameObject]
readonly attribute SVGAnimatedNumber pathLength;
boolean isPointInFill(optional DOMPointInit point);
boolean isPointInStroke(optional DOMPointInit point);
float getTotalLength();
[NewObject, Throws]
SVGPoint getPointAtLength(float distance);

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

@ -11,16 +11,22 @@
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#if defined(MOZ_WIDGET_ANDROID)
# include "mozilla/widget/nsWindow.h"
#endif // defined(MOZ_WIDGET_ANDROID)
namespace mozilla {
namespace layers {
using namespace gfx;
using namespace widget;
CompositorSession::CompositorSession(CompositorWidgetDelegate* aDelegate,
CompositorSession::CompositorSession(nsBaseWidget* aWidget,
CompositorWidgetDelegate* aDelegate,
CompositorBridgeChild* aChild,
const LayersId& aRootLayerTreeId)
: mCompositorWidgetDelegate(aDelegate),
: mWidget(aWidget),
mCompositorWidgetDelegate(aDelegate),
mCompositorBridgeChild(aChild),
mRootLayerTreeId(aRootLayerTreeId) {}
@ -30,5 +36,15 @@ CompositorBridgeChild* CompositorSession::GetCompositorBridgeChild() {
return mCompositorBridgeChild;
}
#if defined(MOZ_WIDGET_ANDROID)
void CompositorSession::NotifyDisablingWebRender() {
if (!mWidget) {
return;
}
nsWindow* window = static_cast<nsWindow*>(mWidget);
window->NotifyDisablingWebRender();
}
#endif // defined(MOZ_WIDGET_ANDROID)
} // namespace layers
} // namespace mozilla

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

@ -14,7 +14,7 @@
# include "mozilla/layers/UiCompositorControllerChild.h"
#endif // defined(MOZ_WIDGET_ANDROID)
class nsIWidget;
class nsBaseWidget;
namespace mozilla {
namespace widget {
@ -80,14 +80,17 @@ class CompositorSession {
RefPtr<UiCompositorControllerChild> GetUiCompositorControllerChild() {
return mUiCompositorControllerChild;
}
void NotifyDisablingWebRender();
#endif // defined(MOZ_WIDGET_ANDROID)
protected:
CompositorSession(CompositorWidgetDelegate* aDelegate,
CompositorSession(nsBaseWidget* aWidget, CompositorWidgetDelegate* aDelegate,
CompositorBridgeChild* aChild,
const LayersId& aRootLayerTreeId);
virtual ~CompositorSession();
protected:
nsBaseWidget* mWidget;
CompositorWidgetDelegate* mCompositorWidgetDelegate;
RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
LayersId mRootLayerTreeId;

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

@ -455,6 +455,15 @@ void GPUProcessManager::DisableWebRender(wr::WebRenderError aError) {
}
gfx::gfxVars::SetUseWebRender(false);
#if defined(MOZ_WIDGET_ANDROID)
// If aError is not wr::WebRenderError::INITIALIZE, nsWindow does not
// re-create LayerManager. Needs to trigger re-creating LayerManager on
// android
if (aError != wr::WebRenderError::INITIALIZE) {
NotifyDisablingWebRender();
}
#endif
if (mProcess) {
OnRemoteProcessDeviceReset(mProcess);
} else {
@ -641,6 +650,18 @@ void GPUProcessManager::RebuildInProcessSessions() {
}
}
void GPUProcessManager::NotifyDisablingWebRender() {
#if defined(MOZ_WIDGET_ANDROID)
for (const auto& session : mRemoteSessions) {
session->NotifyDisablingWebRender();
}
for (const auto& session : mInProcessSessions) {
session->NotifyDisablingWebRender();
}
#endif
}
void GPUProcessManager::NotifyRemoteActorDestroyed(
const uint64_t& aProcessToken) {
if (!NS_IsMainThread()) {

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

@ -210,6 +210,8 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
void RebuildRemoteSessions();
void RebuildInProcessSessions();
void NotifyDisablingWebRender();
void FallbackToSoftware(const char* aMessage);
private:

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

@ -13,13 +13,12 @@ namespace mozilla {
namespace layers {
InProcessCompositorSession::InProcessCompositorSession(
widget::CompositorWidget* aWidget, nsBaseWidget* baseWidget,
nsBaseWidget* aWidget, widget::CompositorWidget* aCompositorWidget,
CompositorBridgeChild* aChild, CompositorBridgeParent* aParent)
: CompositorSession(aWidget->AsDelegate(), aChild,
: CompositorSession(aWidget, aCompositorWidget->AsDelegate(), aChild,
aParent->RootLayerTreeId()),
mWidget(baseWidget),
mCompositorBridgeParent(aParent),
mCompositorWidget(aWidget) {
mCompositorWidget(aCompositorWidget) {
GPUProcessManager::Get()->RegisterInProcessSession(this);
}
@ -45,7 +44,7 @@ RefPtr<InProcessCompositorSession> InProcessCompositorSession::Create(
aLayerManager, aNamespace);
MOZ_ASSERT(child);
return new InProcessCompositorSession(widget, aWidget, child, parent);
return new InProcessCompositorSession(aWidget, widget, child, parent);
}
void InProcessCompositorSession::NotifySessionLost() {

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

@ -34,13 +34,12 @@ class InProcessCompositorSession final : public CompositorSession {
void NotifySessionLost();
private:
InProcessCompositorSession(widget::CompositorWidget* aWidget,
nsBaseWidget* baseWidget,
InProcessCompositorSession(nsBaseWidget* aWidget,
widget::CompositorWidget* aCompositorWidget,
CompositorBridgeChild* aChild,
CompositorBridgeParent* aParent);
private:
nsBaseWidget* mWidget;
RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
RefPtr<CompositorWidget> mCompositorWidget;
};

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

@ -24,8 +24,7 @@ RemoteCompositorSession::RemoteCompositorSession(
nsBaseWidget* aWidget, CompositorBridgeChild* aChild,
CompositorWidgetDelegate* aWidgetDelegate, APZCTreeManagerChild* aAPZ,
const LayersId& aRootLayerTreeId)
: CompositorSession(aWidgetDelegate, aChild, aRootLayerTreeId),
mWidget(aWidget),
: CompositorSession(aWidget, aWidgetDelegate, aChild, aRootLayerTreeId),
mAPZ(aAPZ) {
MOZ_ASSERT(!gfxPlatform::IsHeadless());
GPUProcessManager::Get()->RegisterRemoteProcessSession(this);

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

@ -31,7 +31,6 @@ class RemoteCompositorSession final : public CompositorSession {
void NotifySessionLost();
private:
nsBaseWidget* mWidget;
RefPtr<APZCTreeManagerChild> mAPZ;
RefPtr<GeckoContentController> mContentController;
};

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

@ -103,6 +103,12 @@ void RenderAndroidSurfaceTextureHostOGL::DeleteTextureHandle() {
}
bool RenderAndroidSurfaceTextureHostOGL::EnsureAttachedToGLContext() {
// During handling WebRenderError, GeckoSurfaceTexture should not be attached
// to GLContext.
if (RenderThread::Get()->IsHandlingWebRenderError()) {
return false;
}
if (mAttachedToGLContext) {
return true;
}
@ -197,7 +203,9 @@ void RenderAndroidSurfaceTextureHostOGL::NofityForUse() {
// WebRender, instead rendered to WebGL.
// It is not a good way. But it is same to Compositor rendering.
MOZ_ASSERT(!mSurfTex || !mSurfTex->IsSingleBuffer());
EnsureAttachedToGLContext();
if (!EnsureAttachedToGLContext()) {
return;
}
mPrepareStatus = STATUS_PREPARE_NEEDED;
}
}
@ -207,7 +215,9 @@ void RenderAndroidSurfaceTextureHostOGL::NotifyNotUsed() {
if (mSurfTex && mSurfTex->IsSingleBuffer() &&
mPrepareStatus == STATUS_PREPARED) {
EnsureAttachedToGLContext();
if (!EnsureAttachedToGLContext()) {
return;
}
// Release SurfaceTexture's buffer to client side.
mGL->MakeCurrent();
mSurfTex->ReleaseTexImage();
@ -215,7 +225,9 @@ void RenderAndroidSurfaceTextureHostOGL::NotifyNotUsed() {
// This could happen when video frame was skipped. UpdateTexImage() neeeds
// to be called for adjusting SurfaceTexture's buffer status.
MOZ_ASSERT(!mSurfTex->IsSingleBuffer());
EnsureAttachedToGLContext();
if (!EnsureAttachedToGLContext()) {
return;
}
mSurfTex->UpdateTexImage();
}

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

@ -55,7 +55,13 @@ RenderCompositorEGL::RenderCompositorEGL(
RefPtr<widget::CompositorWidget> aWidget)
: RenderCompositor(std::move(aWidget)), mEGLSurface(EGL_NO_SURFACE) {}
RenderCompositorEGL::~RenderCompositorEGL() { DestroyEGLSurface(); }
RenderCompositorEGL::~RenderCompositorEGL() {
#ifdef MOZ_WIDGET_ANDROID
java::GeckoSurfaceTexture::DestroyUnused((int64_t)gl());
java::GeckoSurfaceTexture::DetachAllFromGLContext((int64_t)gl());
#endif
DestroyEGLSurface();
}
bool RenderCompositorEGL::BeginFrame() {
#ifdef MOZ_WAYLAND

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

@ -13,6 +13,7 @@
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorManagerParent.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/SharedSurfacesParent.h"
#include "mozilla/StaticPtr.h"
@ -28,6 +29,7 @@
#ifdef MOZ_WIDGET_ANDROID
# include "GLLibraryEGL.h"
# include "GeneratedJNIWrappers.h"
#endif
using namespace mozilla;
@ -46,7 +48,8 @@ RenderThread::RenderThread(base::Thread* aThread)
mWindowInfos("RenderThread.mWindowInfos"),
mRenderTextureMapLock("RenderThread.mRenderTextureMapLock"),
mHasShutdown(false),
mHandlingDeviceReset(false) {}
mHandlingDeviceReset(false),
mHandlingWebRenderError(false) {}
RenderThread::~RenderThread() {
MOZ_ASSERT(mRenderTexturesDeferred.empty());
@ -808,6 +811,34 @@ void RenderThread::SimulateDeviceReset() {
}
}
static void DoNotifyWebRenderError(WebRenderError aError) {
layers::CompositorManagerParent::NotifyWebRenderError(aError);
}
void RenderThread::HandleWebRenderError(WebRenderError aError) {
if (mHandlingWebRenderError) {
return;
}
layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
"DoNotifyWebRenderErrorRunnable", &DoNotifyWebRenderError, aError));
{
MutexAutoLock lock(mRenderTextureMapLock);
mRenderTexturesDeferred.clear();
for (const auto& entry : mRenderTextures) {
entry.second->ClearCachedResources();
}
}
mHandlingWebRenderError = true;
// WebRender is going to be disabled by
// GPUProcessManager::NotifyWebRenderError()
}
bool RenderThread::IsHandlingWebRenderError() {
MOZ_ASSERT(IsInRenderThread());
return mHandlingWebRenderError;
}
gl::GLContext* RenderThread::SharedGL() {
MOZ_ASSERT(IsInRenderThread());
if (!mSharedGL) {

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

@ -255,6 +255,11 @@ class RenderThread final {
/// Can be called from any thread.
void SimulateDeviceReset();
/// Can only be called from the render thread.
void HandleWebRenderError(WebRenderError aError);
/// Can only be called from the render thread.
bool IsHandlingWebRenderError();
size_t RendererCount();
void SetCompositionRecorderForWindow(
@ -314,6 +319,7 @@ class RenderThread final {
bool mHasShutdown;
bool mHandlingDeviceReset;
bool mHandlingWebRenderError;
};
} // namespace wr

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

@ -10,7 +10,6 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorManagerParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/webrender/RenderCompositor.h"
@ -120,7 +119,8 @@ bool RendererOGL::UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize,
if (!wr_renderer_render(mRenderer, size.width, size.height, aHadSlowFrame,
aOutStats)) {
NotifyWebRenderError(WebRenderError::RENDER);
RenderThread::Get()->HandleWebRenderError(WebRenderError::RENDER);
return false;
}
if (aReadbackBuffer.isSome()) {
@ -216,14 +216,5 @@ void RendererOGL::AccumulateMemoryReport(MemoryReport* aReport) {
aReport->swap_chain += swapChainSize;
}
static void DoNotifyWebRenderError(WebRenderError aError) {
layers::CompositorManagerParent::NotifyWebRenderError(aError);
}
void RendererOGL::NotifyWebRenderError(WebRenderError aError) {
layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
"DoNotifyWebRenderErrorRunnable", &DoNotifyWebRenderError, aError));
}
} // namespace wr
} // namespace mozilla

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

@ -104,8 +104,6 @@ class RendererOGL {
gl::GLContext* gl() const;
protected:
void NotifyWebRenderError(WebRenderError aError);
RefPtr<RenderThread> mThread;
UniquePtr<RenderCompositor> mCompositor;
wr::Renderer* mRenderer;

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

@ -247,6 +247,8 @@ struct Symbol {
*/
class JS_FRIEND_API GCCellPtr {
public:
GCCellPtr() : GCCellPtr(nullptr) {}
// Construction from a void* and trace kind.
GCCellPtr(void* gcthing, JS::TraceKind traceKind)
: ptr(checkedCast(gcthing, traceKind)) {}

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

@ -3765,10 +3765,10 @@ static const JSFunctionSpec array_methods[] = {
JS_SELF_HOSTED_FN("fill", "ArrayFill", 3, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "$ArrayValues", 0, 0),
JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0, 0),
JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0, 0),
JS_SELF_HOSTED_FN("values", "ArrayValues", 0, 0),
JS_SELF_HOSTED_FN("values", "$ArrayValues", 0, 0),
/* ES7 additions */
JS_SELF_HOSTED_FN("includes", "ArrayIncludes", 2, 0),
@ -3806,7 +3806,7 @@ static const JSFunctionSpec array_static_methods[] = {
JS_FS_END};
const JSPropertySpec array_static_props[] = {
JS_SELF_HOSTED_SYM_GET(species, "ArraySpecies", 0), JS_PS_END};
JS_SELF_HOSTED_SYM_GET(species, "$ArraySpecies", 0), JS_PS_END};
static inline bool ArrayConstructorImpl(JSContext* cx, CallArgs& args,
bool isConstructor) {

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

@ -789,10 +789,12 @@ function ArrayIteratorNext() {
return result;
}
function ArrayValues() {
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $ArrayValues() {
return CreateArrayIterator(this, ITEM_KIND_VALUE);
}
_SetCanonicalName(ArrayValues, "values");
_SetCanonicalName($ArrayValues, "values");
function ArrayEntries() {
return CreateArrayIterator(this, ITEM_KIND_KEY_AND_VALUE);
@ -973,11 +975,11 @@ function ArrayToLocaleString(locales, options) {
}
// ES 2016 draft Mar 25, 2016 22.1.2.5.
function ArraySpecies() {
function $ArraySpecies() {
// Step 1.
return this;
}
_SetCanonicalName(ArraySpecies, "get [Symbol.species]");
_SetCanonicalName($ArraySpecies, "get [Symbol.species]");
// ES 2016 draft Mar 25, 2016 9.4.2.3.
function ArraySpeciesCreate(originalArray, length) {

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

@ -43,10 +43,23 @@ static void AssertInnerizedEnvironmentChain(JSContext* cx, JSObject& env) {
}
static bool IsEvalCacheCandidate(JSScript* script) {
if (!script->isDirectEvalInFunction()) {
return false;
}
// Make sure there are no inner objects which might use the wrong parent
// and/or call scope by reusing the previous eval's script.
return script->isDirectEvalInFunction() && !script->hasSingletons() &&
!script->hasObjects();
if (script->hasSingletons()) {
return false;
}
for (JS::GCCellPtr gcThing : script->gcthings()) {
if (gcThing.is<JSObject>()) {
return false;
}
}
return true;
}
/* static */

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

@ -63,10 +63,12 @@ function MapForEach(callbackfn, thisArg = undefined) {
}
}
function MapEntries() {
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $MapEntries() {
return callFunction(std_Map_iterator, this);
}
_SetCanonicalName(MapEntries, "entries");
_SetCanonicalName($MapEntries, "entries");
var iteratorTemp = { mapIterationResultPair: null };
@ -121,8 +123,8 @@ function MapIteratorNext() {
}
// ES6 final draft 23.1.2.2.
function MapSpecies() {
function $MapSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(MapSpecies, "get [Symbol.species]");
_SetCanonicalName($MapSpecies, "get [Symbol.species]");

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

@ -411,11 +411,11 @@ const JSFunctionSpec MapObject::methods[] = {
JS_SELF_HOSTED_FN("forEach", "MapForEach", 2, 0),
// MapEntries only exists to preseve the equal identity of
// entries and @@iterator.
JS_SELF_HOSTED_FN("entries", "MapEntries", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "MapEntries", 0, 0), JS_FS_END};
JS_SELF_HOSTED_FN("entries", "$MapEntries", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "$MapEntries", 0, 0), JS_FS_END};
const JSPropertySpec MapObject::staticProperties[] = {
JS_SELF_HOSTED_SYM_GET(species, "MapSpecies", 0), JS_PS_END};
JS_SELF_HOSTED_SYM_GET(species, "$MapSpecies", 0), JS_PS_END};
template <class Range>
static void TraceKey(Range& r, const HashableValue& key, JSTracer* trc) {
@ -1160,12 +1160,12 @@ const JSFunctionSpec SetObject::methods[] = {
JS_SELF_HOSTED_FN("forEach", "SetForEach", 2, 0),
// SetValues only exists to preseve the equal identity of
// values, keys and @@iterator.
JS_SELF_HOSTED_FN("values", "SetValues", 0, 0),
JS_SELF_HOSTED_FN("keys", "SetValues", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "SetValues", 0, 0), JS_FS_END};
JS_SELF_HOSTED_FN("values", "$SetValues", 0, 0),
JS_SELF_HOSTED_FN("keys", "$SetValues", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "$SetValues", 0, 0), JS_FS_END};
const JSPropertySpec SetObject::staticProperties[] = {
JS_SELF_HOSTED_SYM_GET(species, "SetSpecies", 0), JS_PS_END};
JS_SELF_HOSTED_SYM_GET(species, "$SetSpecies", 0), JS_PS_END};
bool SetObject::keys(JSContext* cx, HandleObject obj,
JS::MutableHandle<GCVector<JS::Value>> keys) {

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

@ -328,7 +328,6 @@ function ModuleInstantiate()
// Step 8
return undefined;
}
_SetCanonicalName(ModuleInstantiate, "ModuleInstantiate");
// 15.2.1.16.4.1 InnerModuleInstantiation(module, stack, index)
function InnerModuleInstantiation(module, stack, index)
@ -552,7 +551,6 @@ function ModuleEvaluate()
return undefined;
}
_SetCanonicalName(ModuleEvaluate, "ModuleEvaluate");
// 15.2.1.16.5.1 InnerModuleEvaluation(module, stack, index)
function InnerModuleEvaluation(module, stack, index)

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

@ -771,7 +771,7 @@ bool js::regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp) {
}
const JSPropertySpec js::regexp_properties[] = {
JS_SELF_HOSTED_GET("flags", "RegExpFlagsGetter", 0),
JS_SELF_HOSTED_GET("flags", "$RegExpFlagsGetter", 0),
JS_PSG("global", regexp_global, 0),
JS_PSG("ignoreCase", regexp_ignoreCase, 0),
JS_PSG("multiline", regexp_multiline, 0),
@ -781,8 +781,8 @@ const JSPropertySpec js::regexp_properties[] = {
JS_PS_END};
const JSFunctionSpec js::regexp_methods[] = {
JS_SELF_HOSTED_FN(js_toSource_str, "RegExpToString", 0, 0),
JS_SELF_HOSTED_FN(js_toString_str, "RegExpToString", 0, 0),
JS_SELF_HOSTED_FN(js_toSource_str, "$RegExpToString", 0, 0),
JS_SELF_HOSTED_FN(js_toString_str, "$RegExpToString", 0, 0),
JS_FN("compile", regexp_compile, 2, 0),
JS_SELF_HOSTED_FN("exec", "RegExp_prototype_Exec", 1, 0),
JS_SELF_HOSTED_FN("test", "RegExpTest", 1, 0),
@ -890,7 +890,7 @@ const JSPropertySpec js::regexp_static_props[] = {
JS_PSG("$+", static_lastParen_getter, JSPROP_PERMANENT),
JS_PSG("$`", static_leftContext_getter, JSPROP_PERMANENT),
JS_PSG("$'", static_rightContext_getter, JSPROP_PERMANENT),
JS_SELF_HOSTED_SYM_GET(species, "RegExpSpecies", 0),
JS_SELF_HOSTED_SYM_GET(species, "$RegExpSpecies", 0),
JS_PS_END};
template <typename CharT>

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

@ -3,7 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags
function RegExpFlagsGetter() {
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $RegExpFlagsGetter() {
// Steps 1-2.
var R = this;
if (!IsObject(R))
@ -35,10 +37,10 @@ function RegExpFlagsGetter() {
// Step 19.
return result;
}
_SetCanonicalName(RegExpFlagsGetter, "get flags");
_SetCanonicalName($RegExpFlagsGetter, "get flags");
// ES 2017 draft 40edb3a95a475c1b251141ac681b8793129d9a6d 21.2.5.14.
function RegExpToString()
function $RegExpToString()
{
// Step 1.
var R = this;
@ -56,7 +58,7 @@ function RegExpToString()
// Steps 5-6.
return "/" + pattern + "/" + flags;
}
_SetCanonicalName(RegExpToString, "toString");
_SetCanonicalName($RegExpToString, "toString");
// ES 2016 draft Mar 25, 2016 21.2.5.2.3.
function AdvanceStringIndex(S, index) {
@ -1070,11 +1072,11 @@ function RegExpTest(string) {
}
// ES 2016 draft Mar 25, 2016 21.2.4.2.
function RegExpSpecies() {
function $RegExpSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(RegExpSpecies, "get [Symbol.species]");
_SetCanonicalName($RegExpSpecies, "get [Symbol.species]");
function IsRegExpMatchAllOptimizable(rx, C) {
if (!IsRegExpObject(rx))

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

@ -63,8 +63,12 @@
#define PROP_DESC_GETTER_INDEX 1
#define PROP_DESC_SETTER_INDEX 2
// The extended slot in which the self-hosted name for self-hosted builtins is
// stored.
// The extended slot of uncloned self-hosted function, in which the original
// name for self-hosted builtins is stored by `_SetCanonicalName`.
#define ORIGINAL_FUNCTION_NAME_SLOT 0
// The extended slot of cloned self-hosted function, in which the self-hosted
// name for self-hosted builtins is stored.
#define LAZY_FUNCTION_NAME_SLOT 0
// Stores the length for bound functions, so the .length property doesn't need

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

@ -53,17 +53,19 @@ function SetForEach(callbackfn, thisArg = undefined) {
}
}
function SetValues() {
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $SetValues() {
return callFunction(std_Set_iterator, this);
}
_SetCanonicalName(SetValues, "values");
_SetCanonicalName($SetValues, "values");
// ES6 final draft 23.2.2.2.
function SetSpecies() {
function $SetSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(SetSpecies, "get [Symbol.species]");
_SetCanonicalName($SetSpecies, "get [Symbol.species]");
var setIteratorTemp = { setIterationResult: null };

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

@ -1445,7 +1445,10 @@ function TypedArraySubarray(begin, end) {
}
// ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values()
function TypedArrayValues() {
//
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $TypedArrayValues() {
// Step 1.
var O = this;
@ -1455,7 +1458,7 @@ function TypedArrayValues() {
// Step 7.
return CreateArrayIterator(O, ITEM_KIND_VALUE);
}
_SetCanonicalName(TypedArrayValues, "values");
_SetCanonicalName($TypedArrayValues, "values");
// Proposed for ES7:
// https://github.com/tc39/Array.prototype.includes/blob/7c023c19a0/spec.md
@ -1551,7 +1554,7 @@ function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) {
// constructor is a built-in TypedArray constructor.
if (!mapping && IsTypedArrayConstructor(C) && IsObject(source)) {
// The source is a TypedArray using the default iterator.
if (usingIterator === TypedArrayValues && IsTypedArray(source) &&
if (usingIterator === $TypedArrayValues && IsTypedArray(source) &&
ArrayIteratorPrototypeOptimizable())
{
// Step 7.a.
@ -1574,7 +1577,7 @@ function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) {
}
// The source is a packed array using the default iterator.
if (usingIterator === ArrayValues && IsPackedArray(source) &&
if (usingIterator === $ArrayValues && IsPackedArray(source) &&
ArrayIteratorPrototypeOptimizable())
{
// Steps 7.b-c.
@ -1674,11 +1677,11 @@ function TypedArrayStaticOf(/*...items*/) {
}
// ES 2016 draft Mar 25, 2016 22.2.2.4.
function TypedArraySpecies() {
function $TypedArraySpecies() {
// Step 1.
return this;
}
_SetCanonicalName(TypedArraySpecies, "get [Symbol.species]");
_SetCanonicalName($TypedArraySpecies, "get [Symbol.species]");
// ES2018 draft rev 0525bb33861c7f4e9850f8a222c89642947c4b9c
// 22.2.2.1.1 Runtime Semantics: IterableToList( items, method )
@ -1806,18 +1809,18 @@ function IsDetachedBufferThis() {
}
// ES 2016 draft Mar 25, 2016 24.1.3.3.
function ArrayBufferSpecies() {
function $ArrayBufferSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(ArrayBufferSpecies, "get [Symbol.species]");
_SetCanonicalName($ArrayBufferSpecies, "get [Symbol.species]");
// Shared memory and atomics proposal (30 Oct 2016)
function SharedArrayBufferSpecies() {
function $SharedArrayBufferSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(SharedArrayBufferSpecies, "get [Symbol.species]");
_SetCanonicalName($SharedArrayBufferSpecies, "get [Symbol.species]");
// Shared memory and atomics proposal 6.2.1.5.3 (30 Oct 2016)
// http://tc39.github.io/ecmascript_sharedmem/shmem.html

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

@ -68,7 +68,7 @@ static const JSFunctionSpec collator_methods[] = {
JS_FN(js_toSource_str, collator_toSource, 0, 0), JS_FS_END};
static const JSPropertySpec collator_properties[] = {
JS_SELF_HOSTED_GET("compare", "Intl_Collator_compare_get", 0),
JS_SELF_HOSTED_GET("compare", "$Intl_Collator_compare_get", 0),
JS_STRING_SYM_PS(toStringTag, "Object", JSPROP_READONLY), JS_PS_END};
/**

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

@ -348,13 +348,15 @@ function collatorCompareToBind(x, y) {
*
* Spec: ECMAScript Internationalization API Specification, 10.3.3.
*/
function Intl_Collator_compare_get() {
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $Intl_Collator_compare_get() {
// Step 1.
var collator = this;
// Steps 2-3.
if (!IsObject(collator) || (collator = GuardToCollator(collator)) === null)
return callFunction(CallCollatorMethodIfWrapped, this, "Intl_Collator_compare_get");
return callFunction(CallCollatorMethodIfWrapped, this, "$Intl_Collator_compare_get");
var internals = getCollatorInternals(collator);
@ -370,7 +372,7 @@ function Intl_Collator_compare_get() {
// Step 5.
return internals.boundCompare;
}
_SetCanonicalName(Intl_Collator_compare_get, "get compare");
_SetCanonicalName($Intl_Collator_compare_get, "get compare");
/**
* Returns the resolved options for a Collator object.

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

@ -79,7 +79,7 @@ static const JSFunctionSpec dateTimeFormat_methods[] = {
JS_FN(js_toSource_str, dateTimeFormat_toSource, 0, 0), JS_FS_END};
static const JSPropertySpec dateTimeFormat_properties[] = {
JS_SELF_HOSTED_GET("format", "Intl_DateTimeFormat_format_get", 0),
JS_SELF_HOSTED_GET("format", "$Intl_DateTimeFormat_format_get", 0),
JS_STRING_SYM_PS(toStringTag, "Object", JSPROP_READONLY), JS_PS_END};
/**

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

@ -791,13 +791,15 @@ function dateTimeFormatFormatToBind(date) {
*
* Spec: ECMAScript Internationalization API Specification, 12.4.3.
*/
function Intl_DateTimeFormat_format_get() {
// Uncloned functions with `$` prefix are allocated as extended function
// to store the original name in `_SetCanonicalName`.
function $Intl_DateTimeFormat_format_get() {
// Steps 1-3.
var thisArg = UnwrapDateTimeFormat(this);
var dtf = thisArg;
if (!IsObject(dtf) || (dtf = GuardToDateTimeFormat(dtf)) === null) {
return callFunction(CallDateTimeFormatMethodIfWrapped, thisArg,
"Intl_DateTimeFormat_format_get");
"$Intl_DateTimeFormat_format_get");
}
var internals = getDateTimeFormatInternals(dtf);
@ -814,7 +816,7 @@ function Intl_DateTimeFormat_format_get() {
// Step 5.
return internals.boundFormat;
}
_SetCanonicalName(Intl_DateTimeFormat_format_get, "get format");
_SetCanonicalName($Intl_DateTimeFormat_format_get, "get format");
/**
* Intl.DateTimeFormat.prototype.formatToParts ( date )

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

@ -78,7 +78,7 @@ static const JSFunctionSpec numberFormat_methods[] = {
JS_FN(js_toSource_str, numberFormat_toSource, 0, 0), JS_FS_END};
static const JSPropertySpec numberFormat_properties[] = {
JS_SELF_HOSTED_GET("format", "Intl_NumberFormat_format_get", 0),
JS_SELF_HOSTED_GET("format", "$Intl_NumberFormat_format_get", 0),
JS_STRING_SYM_PS(toStringTag, "Object", JSPROP_READONLY), JS_PS_END};
/**

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше