Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2016-06-09 12:14:03 +02:00
Родитель 1bdb5bec87 733a4f6de5
Коммит 2273c7b9f8
182 изменённых файлов: 4656 добавлений и 1720 удалений

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

@ -271,7 +271,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
if (text.mString.IsEmpty()) {
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eTree | logging::eText)) {
logging::MsgBegin("TREE", "text node lost its content");
logging::MsgBegin("TREE", "text node lost its content; doc: %p", mDocument);
logging::Node("container", containerElm);
logging::Node("content", textNode);
logging::MsgEnd();
@ -285,7 +285,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
// Update text of the accessible and fire text change events.
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eText)) {
logging::MsgBegin("TEXT", "text may be changed");
logging::MsgBegin("TEXT", "text may be changed; doc: %p", mDocument);
logging::Node("container", containerElm);
logging::Node("content", textNode);
logging::MsgEntry("old text '%s'",
@ -304,7 +304,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
if (!text.mString.IsEmpty()) {
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eTree | logging::eText)) {
logging::MsgBegin("TREE", "text node gains new content");
logging::MsgBegin("TREE", "text node gains new content; doc: %p", mDocument);
logging::Node("container", containerElm);
logging::Node("content", textNode);
logging::MsgEnd();

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

@ -558,9 +558,10 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
nsIContent* aStartChild,
nsIContent* aEndChild)
{
DocAccessible* document = GetDocAccessible(aPresShell);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eTree)) {
logging::MsgBegin("TREE", "content inserted");
logging::MsgBegin("TREE", "content inserted; doc: %p", document);
logging::Node("container", aContainer);
for (nsIContent* child = aStartChild; child != aEndChild;
child = child->GetNextSibling()) {
@ -571,25 +572,25 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
}
#endif
DocAccessible* docAccessible = GetDocAccessible(aPresShell);
if (docAccessible)
docAccessible->ContentInserted(aContainer, aStartChild, aEndChild);
if (document) {
document->ContentInserted(aContainer, aStartChild, aEndChild);
}
}
void
nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
nsIContent* aChildNode)
{
DocAccessible* document = GetDocAccessible(aPresShell);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eTree)) {
logging::MsgBegin("TREE", "content removed");
logging::MsgBegin("TREE", "content removed; doc: %p", document);
logging::Node("container node", aChildNode->GetFlattenedTreeParent());
logging::Node("content node", aChildNode);
logging::MsgEnd();
}
#endif
DocAccessible* document = GetDocAccessible(aPresShell);
if (document) {
// Flatten hierarchy may be broken at this point so we cannot get a true
// container by traversing up the DOM tree. Find a parent of first accessible

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

@ -1814,6 +1814,15 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, nsIContent* aNode)
return;
}
#ifdef A11Y_LOG
logging::TreeInfo("children before insertion", logging::eVerbose, aContainer);
#endif
#ifdef A11Y_LOG
logging::TreeInfo("traversing an inserted node", logging::eVerbose,
"container", aContainer, "node", aNode);
#endif
TreeWalker walker(aContainer);
if (aContainer->IsAcceptableChild(aNode) && walker.Seek(aNode)) {
Accessible* child = GetAccessible(aNode);
@ -1831,6 +1840,10 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, nsIContent* aNode)
FireEventsOnInsertion(aContainer);
}
}
#ifdef A11Y_LOG
logging::TreeInfo("children after insertion", logging::eVerbose, aContainer);
#endif
}
void

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

@ -138,7 +138,7 @@ GetAppIni(int argc, const char *argv[])
char appEnv[MAXPATHLEN];
snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
if (putenv(appEnv)) {
if (putenv(strdup(appEnv))) {
return nullptr;
}
}

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

@ -137,7 +137,7 @@ static int do_main(int argc, char* argv[])
char appEnv[MAXPATHLEN];
snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
if (putenv(appEnv)) {
if (putenv(strdup(appEnv))) {
Output("Couldn't set %s.\n", appEnv);
return 255;
}

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

@ -183,7 +183,7 @@ static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
char appEnv[MAXPATHLEN];
snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
if (putenv(appEnv)) {
if (putenv(strdup(appEnv))) {
Output("Couldn't set %s.\n", appEnv);
return 255;
}

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

@ -25,6 +25,7 @@ LOCAL_INCLUDES += [
if CONFIG['OS_ARCH'] == 'WINNT':
OS_LIBS += [
'esent',
'netapi32',
'ole32',
'shell32',
'shlwapi',
@ -32,6 +33,7 @@ if CONFIG['OS_ARCH'] == 'WINNT':
]
DELAYLOAD_DLLS += [
'esent.dll',
'netapi32.dll',
]
# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)

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

@ -878,6 +878,7 @@ BrowserGlue.prototype = {
label: win.gNavigatorBundle.getString("pendingCrashReports.viewAll"),
callback: function() {
win.openUILinkIn("about:crashes", "tab");
return true;
}
}
];

219
browser/extensions/flyweb/bootstrap.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,219 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Console",
"resource://gre/modules/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "gFlyWebBundle", function() {
const tns = {
"flyweb-button.label": "FlyWeb",
"flyweb-button.tooltiptext": "Discover nearby FlyWeb services",
"flyweb-items-empty": "There are no FlyWeb services currently nearby"
};
return {
GetStringFromName(name) {
return tns[name];
}
};
});
const FLYWEB_ENABLED_PREF = "dom.flyweb.enabled";
function install(aData, aReason) {}
function uninstall(aData, aReason) {}
function startup(aData, aReason) {
// Observe pref changes and enable/disable as necessary.
Services.prefs.addObserver(FLYWEB_ENABLED_PREF, prefObserver, false);
// Only initialize if pref is enabled.
let enabled = Services.prefs.getBoolPref(FLYWEB_ENABLED_PREF);
if (enabled) {
FlyWebView.init();
}
}
function shutdown(aData, aReason) {
Services.prefs.removeObserver(FLYWEB_ENABLED_PREF, prefObserver);
let enabled = Services.prefs.getBoolPref(FLYWEB_ENABLED_PREF);
if (enabled) {
FlyWebView.uninit();
}
}
// use enabled pref as a way for tests (e.g. test_contextmenu.html) to disable
// the addon when running.
function prefObserver(aSubject, aTopic, aData) {
let enabled = Services.prefs.getBoolPref(FLYWEB_ENABLED_PREF);
if (enabled) {
FlyWebView.init();
} else {
FlyWebView.uninit();
}
}
let gDiscoveryManagerInstance;
class DiscoveryManager {
constructor(aWindow) {
this._discoveryManager = new aWindow.FlyWebDiscoveryManager();
}
destroy() {
if (this._id) {
this.stop();
}
this._discoveryManager = null;
}
start(callback) {
if (!this._id) {
this._id = this._discoveryManager.startDiscovery(this);
}
this._callback = callback;
}
stop() {
this._discoveryManager.stopDiscovery(this._id);
this._id = null;
}
pairWith(serviceId, callback) {
this._discoveryManager.pairWithService(serviceId, {
pairingSucceeded(service) {
callback(service);
},
pairingFailed(error) {
console.error("FlyWeb failed to pair with service " + serviceId, error);
}
});
}
onDiscoveredServicesChanged(services) {
if (!this._id || !this._callback) {
return;
}
this._callback(services);
}
}
let FlyWebView = {
init() {
// Create widget and add it to the menu panel.
CustomizableUI.createWidget({
id: "flyweb-button",
type: "view",
viewId: "flyweb-panel",
label: gFlyWebBundle.GetStringFromName("flyweb-button.label"),
tooltiptext: gFlyWebBundle.GetStringFromName("flyweb-button.tooltiptext"),
onBeforeCreated(aDocument) {
let panel = aDocument.createElement("panelview");
panel.id = "flyweb-panel";
panel.setAttribute("class", "PanelUI-subView");
panel.setAttribute("flex", "1");
let label = aDocument.createElement("label");
label.setAttribute("class", "panel-subview-header");
label.setAttribute("value", gFlyWebBundle.GetStringFromName("flyweb-button.label"));
let empty = aDocument.createElement("description");
empty.id = "flyweb-items-empty";
empty.setAttribute("mousethrough", "always");
empty.textContent = gFlyWebBundle.GetStringFromName("flyweb-items-empty");
let items = aDocument.createElement("vbox");
items.id = "flyweb-items";
items.setAttribute("class", "panel-subview-body");
panel.appendChild(label);
panel.appendChild(empty);
panel.appendChild(items);
panel.addEventListener("command", this);
aDocument.getElementById("PanelUI-multiView").appendChild(panel);
this._sheetURI = Services.io.newURI("chrome://flyweb/skin/flyweb.css", null, null);
aDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).loadSheet(this._sheetURI, 1);
},
onDestroyed(aDocument) {
aDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).removeSheet(this._sheetURI, 1);
},
onViewShowing(aEvent) {
let doc = aEvent.target.ownerDocument;
let panel = doc.getElementById("flyweb-panel");
let items = doc.getElementById("flyweb-items");
let empty = doc.getElementById("flyweb-items-empty");
if (!gDiscoveryManagerInstance) {
gDiscoveryManagerInstance = new DiscoveryManager(doc.defaultView);
}
gDiscoveryManagerInstance.start((services) => {
while (items.firstChild) {
items.firstChild.remove();
}
let fragment = doc.createDocumentFragment();
for (let service of services) {
let button = doc.createElement("toolbarbutton");
button.setAttribute("class", "subviewbutton cui-withicon");
button.setAttribute("label", service.displayName);
button.setAttribute("data-service-id", service.serviceId);
fragment.appendChild(button);
}
items.appendChild(fragment);
empty.hidden = services.length > 0;
});
},
onViewHiding(aEvent) {
gDiscoveryManagerInstance.stop();
},
handleEvent(aEvent) {
if (aEvent.type === "command") {
let serviceId = aEvent.target.getAttribute("data-service-id");
gDiscoveryManagerInstance.pairWith(serviceId, (service) => {
aEvent.view.openUILinkIn(service.uiUrl, "tab");
});
}
}
});
},
uninit() {
CustomizableUI.destroyWidget("flyweb-button");
if (gDiscoveryManagerInstance) {
gDiscoveryManagerInstance.destroy();
gDiscoveryManagerInstance = null;
}
}
};

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

@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
#filter substitution
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>flyweb@mozilla.org</em:id>
<em:version>1.0.0</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<!-- Target Application this theme can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>@FIREFOX_VERSION@</em:minVersion>
<em:maxVersion>@FIREFOX_VERSION@</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>FlyWeb</em:name>
<em:description>Discover nearby services in the browser</em:description>
</Description>
</RDF>

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

@ -0,0 +1,10 @@
# 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/.
[features/flyweb@mozilla.org] chrome.jar:
% skin flyweb classic/1.0 %skin/linux/
% skin flyweb classic/1.0 %skin/osx/ os=Darwin
% skin flyweb classic/1.0 %skin/windows/ os=WINNT
% skin flyweb-shared classic/1.0 %skin/shared/
skin/ (skin/*)

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

@ -0,0 +1,15 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
FINAL_TARGET_FILES.features['flyweb@mozilla.org'] += [
'bootstrap.js'
]
FINAL_TARGET_PP_FILES.features['flyweb@mozilla.org'] += [
'install.rdf.in'
]
JAR_MANIFESTS += ['jar.mn']

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

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<circle fill="#797C80" cx="32" cy="52" r="6"/>
<g>
<path fill="#797C80" d="M6.894,15.255c-2.254,1.547-4.386,3.304-6.361,5.279L0.18,20.887l3.536,3.536l0.354-0.354
c1.621-1.62,3.363-3.072,5.196-4.369C8.126,18.464,7.296,16.943,6.894,15.255z"/>
<path fill="#797C80" d="M63.465,20.532C55.061,12.128,43.887,7.5,32,7.5c-2.265,0-4.504,0.17-6.703,0.501
c0.822,1.44,1.3,3.1,1.312,4.87C28.382,12.631,30.181,12.5,32,12.5c10.55,0,20.468,4.108,27.928,11.567l0.354,0.354l3.537-3.535
L63.465,20.532z"/>
</g>
<g>
<path fill="#797C80" d="M16.613,10.94c1.103,0,2,0.897,2,2s-0.897,2-2,2s-2-0.897-2-2S15.51,10.94,16.613,10.94 M16.613,6.94
c-3.313,0-6,2.687-6,6s2.687,6,6,6s6-2.687,6-6S19.926,6.94,16.613,6.94L16.613,6.94z"/>
</g>
<g>
<path fill="#797C80" d="M46.492,37.502c-1.853-1.852-4.002-3.292-6.334-4.305c0.031,0.324,0.05,0.652,0.05,0.984
c0,1.477-0.33,2.874-0.906,4.137c1.329,0.712,2.561,1.623,3.657,2.719l0.354,0.354l3.533-3.535L46.492,37.502z"/>
<path fill="#797C80" d="M20.262,35.207c-0.972,0.683-1.9,1.439-2.758,2.297l-0.354,0.354l3.536,3.537l0.354-0.354
c0.35-0.35,0.715-0.679,1.091-0.99C21.118,38.66,20.446,37.007,20.262,35.207z"/>
</g>
<g>
<path fill="#797C80" d="M30.209,32.182c1.102,0,1.999,0.897,1.999,2s-0.896,2-1.999,2c-1.103,0-2-0.897-2-2
S29.106,32.182,30.209,32.182 M30.209,28.182c-3.313,0-6,2.686-6,6c0,3.312,2.687,6,6,6c3.313,0,5.999-2.688,5.999-6
C36.208,30.867,33.522,28.182,30.209,28.182L30.209,28.182z"/>
</g>
<g>
<path fill="#797C80" d="M32.207,23.716c0-1.497,0.34-2.912,0.932-4.188C32.76,19.515,32.381,19.5,32,19.5
c-8.681,0-16.843,3.381-22.981,9.52l-0.354,0.354l3.535,3.535l0.354-0.354C17.748,27.36,24.654,24.5,32,24.5
c0.083,0,0.165,0.005,0.247,0.006C32.227,24.245,32.207,23.982,32.207,23.716z"/>
<path fill="#797C80" d="M54.98,29.018c-0.987-0.987-2.033-1.896-3.119-2.738c-0.447,1.68-1.313,3.188-2.491,4.399
c0.717,0.586,1.409,1.21,2.073,1.874l0.354,0.354l3.537-3.535L54.98,29.018z"/>
</g>
<g>
<path fill="#797C80" d="M42.207,21.716c1.103,0,2,0.897,2,2s-0.897,2-2,2s-2-0.897-2-2S41.104,21.716,42.207,21.716 M42.207,17.716
c-3.313,0-6,2.687-6,6s2.687,6,6,6s6-2.687,6-6S45.521,17.716,42.207,17.716L42.207,17.716z"/>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 2.6 KiB

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

@ -0,0 +1,5 @@
/* 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/. */
@import url("chrome://flyweb-shared/skin/flyweb.css");

Двоичные данные
browser/extensions/flyweb/skin/linux/icon-16.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
browser/extensions/flyweb/skin/linux/icon-32-anchored.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.6 KiB

Двоичные данные
browser/extensions/flyweb/skin/linux/icon-32.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 699 B

Двоичные данные
browser/extensions/flyweb/skin/linux/icon-64-anchored.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.3 KiB

Двоичные данные
browser/extensions/flyweb/skin/linux/icon-64.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

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

@ -0,0 +1,5 @@
/* 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/. */
@import url("chrome://flyweb-shared/skin/flyweb.css");

Двоичные данные
browser/extensions/flyweb/skin/osx/icon-16.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичные данные
browser/extensions/flyweb/skin/osx/icon-32-anchored.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.6 KiB

Двоичные данные
browser/extensions/flyweb/skin/osx/icon-32.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.5 KiB

Двоичные данные
browser/extensions/flyweb/skin/osx/icon-64-anchored.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.3 KiB

Двоичные данные
browser/extensions/flyweb/skin/osx/icon-64.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.1 KiB

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

@ -0,0 +1,54 @@
/* 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/. */
#flyweb-panel {
width: 20em;
}
#flyweb-items-empty {
box-sizing: border-box;
color: GrayText;
padding: 10px 20px;
text-align: center;
}
#flyweb-button {
list-style-image: url("chrome://flyweb/skin/icon-16.png");
}
#flyweb-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #flyweb-button {
list-style-image: url("chrome://flyweb/skin/icon-32.png");
}
#flyweb-button[cui-areatype="menu-panel"][panel-multiview-anchor="true"] {
list-style-image: url("chrome://flyweb/skin/icon-32-anchored.png");
}
#flyweb-items > toolbarbutton {
list-style-image: url("chrome://flyweb/skin/icon-16.png");
}
@media (min-resolution: 2dppx) {
#flyweb-button {
list-style-image: url("chrome://flyweb/skin/icon-32.png");
}
#flyweb-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #flyweb-button {
list-style-image: url("chrome://flyweb/skin/icon-64.png");
}
#flyweb-button[cui-areatype="menu-panel"][panel-multiview-anchor="true"] {
list-style-image: url("chrome://flyweb/skin/icon-64-anchored.png");
}
#flyweb-items > toolbarbutton {
list-style-image: url("chrome://flyweb/skin/icon-32.png");
}
#flyweb-items > toolbarbutton > .toolbarbutton-icon {
width: 16px;
}
}

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

@ -0,0 +1,5 @@
/* 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/. */
@import url("chrome://flyweb-shared/skin/flyweb.css");

Двоичные данные
browser/extensions/flyweb/skin/windows/icon-16.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
browser/extensions/flyweb/skin/windows/icon-32-anchored.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.6 KiB

Двоичные данные
browser/extensions/flyweb/skin/windows/icon-32.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 699 B

Двоичные данные
browser/extensions/flyweb/skin/windows/icon-64-anchored.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.3 KiB

Двоичные данные
browser/extensions/flyweb/skin/windows/icon-64.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

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

@ -11,3 +11,9 @@ DIRS += [
'pocket',
'webcompat',
]
# Only include the following system add-ons if building Aurora or Nightly
if 'a' in CONFIG['GRE_MILESTONE']:
DIRS += [
'flyweb',
]

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

@ -96,6 +96,7 @@ leak:libdricore.so
leak:libdricore9.2.1.so
leak:libGL.so
leak:libglib-2.0.so
leak:libglsl.so
leak:libp11-kit.so
leak:libpixman-1.so
leak:libpulse.so

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

@ -1436,7 +1436,7 @@ nsScriptSecurityManager::InitStatics()
RefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
nsresult rv = ssManager->Init();
if (NS_FAILED(rv)) {
MOZ_CRASH();
MOZ_CRASH("ssManager->Init() failed");
}
ClearOnShutdown(&gScriptSecMan);

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

@ -18,8 +18,6 @@ add_task(function* () {
reload(target);
let destroyed = getN(gAudioNodes, "remove", 10);
let [created] = yield Promise.all([
getNSpread(gAudioNodes, "add", 13),
waitForGraphRendered(panelWin, 13, 2)
@ -32,8 +30,10 @@ add_task(function* () {
// Click a soon-to-be dead buffer node
yield clickGraphNode(panelWin, actorIDs[5]);
let destroyed = getN(gAudioNodes, "remove", 10);
// Force a CC in the child process to collect the orphaned nodes.
forceCC();
forceNodeCollection();
// Wait for destruction and graph to re-render
yield Promise.all([destroyed, waitForGraphRendered(panelWin, 3, 2)]);

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

@ -8,20 +8,18 @@
add_task(function* () {
let { target, front } = yield initBackend(DESTROY_NODES_URL);
let waitUntilDestroyed = getN(front, "destroy-node", 10);
let [, , created] = yield Promise.all([
front.setup({ reload: true }),
once(front, "start-context"),
// Should create 1 destination node and 10 disposable buffer nodes
// Should create dest, gain, and oscillator node and 10
// disposable buffer nodes
getN(front, "create-node", 13)
]);
// Wait for a tick before gc to prevent this test from intermittent timeout
// where the node never get collected.
yield DevToolsUtils.waitForTick();
let waitUntilDestroyed = getN(front, "destroy-node", 10);
// Force CC so we can ensure it's run to clear out dead AudioNodes
forceCC();
forceNodeCollection();
let destroyed = yield waitUntilDestroyed;

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

@ -12,13 +12,17 @@
<script type="text/javascript;version=1.8">
"use strict";
// Keep the nodes we want to GC alive until we are ready for them to
// be collected. We will zero this reference by force from the devtools
// side.
var keepAlive = [];
(function () {
let ctx = new AudioContext();
let osc = ctx.createOscillator();
let gain = ctx.createGain();
for (let i = 0; i < 10; i++) {
ctx.createBufferSource();
keepAlive.push(ctx.createBufferSource());
}
osc.connect(gain);

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

@ -420,8 +420,12 @@ function countGraphObjects(win) {
/**
* Forces cycle collection and GC, used in AudioNode destruction tests.
*/
function forceCC() {
function forceNodeCollection() {
ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() {
// Kill the reference keeping stuff alive.
content.wrappedJSObject.keepAlive = null;
// Collect the now-deceased nodes.
Cu.forceGC();
Cu.forceCC();
Cu.forceGC();

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

@ -957,9 +957,6 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext,
std::stable_sort(aEntries.begin(), aEntries.end(),
&KeyframeValueEntry::PropertyOffsetComparator::LessThan);
MOZ_ASSERT(aEntries[0].mOffset == 0.0f);
MOZ_ASSERT(aEntries.LastElement().mOffset == 1.0f);
// For a given index i, we want to generate a segment from aEntries[i]
// to aEntries[j], if:
//
@ -974,13 +971,56 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext,
// offset 1, if we have multiple values for a given property at that offset,
// since we need to retain the very first and very last value so they can
// be used for reverse and forward filling.
//
// Typically, for each property in |aEntries|, we expect there to be at least
// one KeyframeValueEntry with offset 0.0, and at least one with offset 1.0.
// However, since it is possible that when building |aEntries|, the call to
// StyleAnimationValue::ComputeValues might fail, this can't be guaranteed.
// Furthermore, since we don't yet implement additive animation and hence
// don't have sensible fallback behavior when these values are missing, the
// following loop takes care to identify properties that lack a value at
// offset 0.0/1.0 and drops those properties from |aResult|.
nsCSSProperty lastProperty = eCSSProperty_UNKNOWN;
AnimationProperty* animationProperty = nullptr;
size_t i = 0, n = aEntries.Length();
while (i + 1 < n) {
while (i < n) {
// Check that the last property ends with an entry at offset 1.
if (i + 1 == n) {
if (aEntries[i].mOffset != 1.0f && animationProperty) {
aResult.RemoveElementAt(aResult.Length() - 1);
animationProperty = nullptr;
}
break;
}
MOZ_ASSERT(aEntries[i].mProperty != eCSSProperty_UNKNOWN &&
aEntries[i + 1].mProperty != eCSSProperty_UNKNOWN,
"Each entry should specify a valid property");
// Skip properties that don't have an entry with offset 0.
if (aEntries[i].mProperty != lastProperty &&
aEntries[i].mOffset != 0.0f) {
// Since the entries are sorted by offset for a given property, and
// since we don't update |lastProperty|, we will keep hitting this
// condition until we change property.
++i;
continue;
}
// Drop properties that don't end with an entry with offset 1.
if (aEntries[i].mProperty != aEntries[i + 1].mProperty &&
aEntries[i].mOffset != 1.0f) {
if (animationProperty) {
aResult.RemoveElementAt(aResult.Length() - 1);
animationProperty = nullptr;
}
++i;
continue;
}
// Starting from i, determine the next [i, j] interval from which to
// generate a segment.
size_t j;
@ -988,23 +1028,24 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext,
// We need to generate an initial zero-length segment.
MOZ_ASSERT(aEntries[i].mProperty == aEntries[i + 1].mProperty);
j = i + 1;
while (aEntries[j + 1].mOffset == 0.0f) {
MOZ_ASSERT(aEntries[j].mProperty == aEntries[j + 1].mProperty);
while (aEntries[j + 1].mOffset == 0.0f &&
aEntries[j + 1].mProperty == aEntries[j].mProperty) {
++j;
}
} else if (aEntries[i].mOffset == 1.0f) {
if (aEntries[i + 1].mOffset == 1.0f) {
if (aEntries[i + 1].mOffset == 1.0f &&
aEntries[i + 1].mProperty == aEntries[i].mProperty) {
// We need to generate a final zero-length segment.
MOZ_ASSERT(aEntries[i].mProperty == aEntries[i].mProperty);
j = i + 1;
while (j + 1 < n && aEntries[j + 1].mOffset == 1.0f) {
MOZ_ASSERT(aEntries[j].mProperty == aEntries[j + 1].mProperty);
while (j + 1 < n &&
aEntries[j + 1].mOffset == 1.0f &&
aEntries[j + 1].mProperty == aEntries[j].mProperty) {
++j;
}
} else {
// New property.
MOZ_ASSERT(aEntries[i + 1].mOffset == 0.0f);
MOZ_ASSERT(aEntries[i].mProperty != aEntries[i + 1].mProperty);
animationProperty = nullptr;
++i;
continue;
}
@ -1020,6 +1061,7 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext,
// to insert segments into.
if (aEntries[i].mProperty != lastProperty) {
MOZ_ASSERT(aEntries[i].mOffset == 0.0f);
MOZ_ASSERT(!animationProperty);
animationProperty = aResult.AppendElement();
animationProperty->mProperty = aEntries[i].mProperty;
lastProperty = aEntries[i].mProperty;

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

@ -112,8 +112,11 @@ enum {
ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS |
ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR,
// Set if this element is marked as 'scrollgrab' (see bug 912666)
ELEMENT_HAS_SCROLLGRAB = ELEMENT_FLAG_BIT(5),
// Remaining bits are for subclasses
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 5
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 6
};
#undef ELEMENT_FLAG_BIT

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

@ -98,3 +98,4 @@ MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")

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

@ -71,14 +71,12 @@ class InitializeRunnable final : public WorkerMainThreadRunnable
{
public:
InitializeRunnable(WorkerPrivate* aWorkerPrivate, nsACString& aOrigin,
PrincipalInfo& aPrincipalInfo, bool& aPrivateBrowsing,
ErrorResult& aRv)
PrincipalInfo& aPrincipalInfo, ErrorResult& aRv)
: WorkerMainThreadRunnable(aWorkerPrivate,
NS_LITERAL_CSTRING("BroadcastChannel :: Initialize"))
, mWorkerPrivate(GetCurrentThreadWorkerPrivate())
, mOrigin(aOrigin)
, mPrincipalInfo(aPrincipalInfo)
, mPrivateBrowsing(aPrivateBrowsing)
, mRv(aRv)
{
MOZ_ASSERT(mWorkerPrivate);
@ -127,11 +125,6 @@ public:
return true;
}
nsIDocument* doc = window->GetExtantDoc();
if (doc) {
mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
}
return true;
}
@ -139,7 +132,6 @@ private:
WorkerPrivate* mWorkerPrivate;
nsACString& mOrigin;
PrincipalInfo& mPrincipalInfo;
bool& mPrivateBrowsing;
ErrorResult& mRv;
};
@ -306,14 +298,12 @@ private:
BroadcastChannel::BroadcastChannel(nsPIDOMWindowInner* aWindow,
const PrincipalInfo& aPrincipalInfo,
const nsACString& aOrigin,
const nsAString& aChannel,
bool aPrivateBrowsing)
const nsAString& aChannel)
: DOMEventTargetHelper(aWindow)
, mWorkerFeature(nullptr)
, mPrincipalInfo(new PrincipalInfo(aPrincipalInfo))
, mOrigin(aOrigin)
, mChannel(aChannel)
, mPrivateBrowsing(aPrivateBrowsing)
, mIsKeptAlive(false)
, mInnerID(0)
, mState(StateActive)
@ -344,7 +334,6 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
nsAutoCString origin;
PrincipalInfo principalInfo;
bool privateBrowsing = false;
WorkerPrivate* workerPrivate = nullptr;
if (NS_IsMainThread()) {
@ -381,19 +370,13 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
nsIDocument* doc = window->GetExtantDoc();
if (doc) {
privateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
}
} else {
JSContext* cx = aGlobal.Context();
workerPrivate = GetWorkerPrivateFromContext(cx);
MOZ_ASSERT(workerPrivate);
RefPtr<InitializeRunnable> runnable =
new InitializeRunnable(workerPrivate, origin, principalInfo,
privateBrowsing, aRv);
new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
runnable->Dispatch(aRv);
}
@ -402,8 +385,7 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
}
RefPtr<BroadcastChannel> bc =
new BroadcastChannel(window, principalInfo, origin, aChannel,
privateBrowsing);
new BroadcastChannel(window, principalInfo, origin, aChannel);
// Register this component to PBackground.
PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
@ -522,8 +504,7 @@ BroadcastChannel::ActorCreated(PBackgroundChild* aActor)
}
PBroadcastChannelChild* actor =
aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel,
mPrivateBrowsing);
aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel);
mActor = static_cast<BroadcastChannelChild*>(actor);
MOZ_ASSERT(mActor);

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

@ -88,8 +88,7 @@ private:
BroadcastChannel(nsPIDOMWindowInner* aWindow,
const PrincipalInfo& aPrincipalInfo,
const nsACString& aOrigin,
const nsAString& aChannel,
bool aPrivateBrowsing);
const nsAString& aChannel);
~BroadcastChannel();
@ -116,7 +115,6 @@ private:
nsCString mOrigin;
nsString mChannel;
bool mPrivateBrowsing;
bool mIsKeptAlive;

3
dom/cache/DBSchema.cpp поставляемый
Просмотреть файл

@ -220,7 +220,8 @@ static_assert(int(RequestCache::Default) == 0 &&
int(RequestCache::Reload) == 2 &&
int(RequestCache::No_cache) == 3 &&
int(RequestCache::Force_cache) == 4 &&
int(RequestCache::EndGuard_) == 5,
int(RequestCache::Only_if_cached) == 5 &&
int(RequestCache::EndGuard_) == 6,
"RequestCache values are as expected");
static_assert(int(RequestRedirect::Follow) == 0 &&
int(RequestRedirect::Error) == 1 &&

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

@ -172,7 +172,7 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
case WebGLExtensionID::EXT_frag_depth:
return WebGLExtensionFragDepth::IsSupported(this);
case WebGLExtensionID::EXT_shader_texture_lod:
return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
return gl->IsSupported(gl::GLFeature::shader_texture_lod);
case WebGLExtensionID::EXT_sRGB:
return WebGLExtensionSRGB::IsSupported(this);

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

@ -15,7 +15,8 @@
// iframe with the right preference setting so that the
// createImageBitmap() will be visible.
SpecialPowers.pushPrefEnv({'set': [
['canvas.imagebitmap_extensions.enabled', true]
['canvas.imagebitmap_extensions.enabled', true],
['gfx.ycbcr.accurate-conversion', true]
]}, function() {
var div = document.getElementById("content");
ok(div, "Parent exists");

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

@ -21,7 +21,7 @@ fail-if = (os == 'android')
[ensure-exts/test_EXT_sRGB.html]
fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') || (os == 'win')
[ensure-exts/test_EXT_shader_texture_lod.html]
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
fail-if = (os == 'android')
[ensure-exts/test_EXT_texture_filter_anisotropic.html]
fail-if = (os == 'android') || (os == 'linux')
[ensure-exts/test_OES_standard_derivatives.html]

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

@ -267,10 +267,13 @@ TextComposition::DispatchCompositionEvent(
aCompositionEvent->mRanges = nullptr;
NS_ASSERTION(aCompositionEvent->mData.IsEmpty(),
"mData of eCompositionCommitAsIs should be empty string");
if (mLastData == IDEOGRAPHIC_SPACE) {
// If the last data is an ideographic space (FullWidth space), it must be
bool removePlaceholderCharacter =
Preferences::GetBool("intl.ime.remove_placeholder_character_at_commit",
false);
if (removePlaceholderCharacter && mLastData == IDEOGRAPHIC_SPACE) {
// If the last data is an ideographic space (FullWidth space), it might be
// a placeholder character of some Chinese IME. So, committing with
// this data must not be expected by users. Let's use empty string.
// this data might not be expected by users. Let's use empty string.
aCompositionEvent->mData.Truncate();
} else {
aCompositionEvent->mData = mLastData;

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

@ -428,6 +428,14 @@ Request::Constructor(const GlobalObject& aGlobal,
RequestCache cache = aInit.mCache.WasPassed() ?
aInit.mCache.Value() : fallbackCache;
if (cache != RequestCache::EndGuard_) {
if (cache == RequestCache::Only_if_cached &&
request->Mode() != RequestMode::Same_origin) {
uint32_t t = static_cast<uint32_t>(request->Mode());
NS_ConvertASCIItoUTF16 modeString(RequestModeValues::strings[t].value,
RequestModeValues::strings[t].length);
aRv.ThrowTypeError<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN>(modeString);
return nullptr;
}
request->ClearCreatedByFetchEvent();
request->SetCacheMode(cache);
}

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

@ -52,8 +52,7 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase,
{
public:
explicit nsGenericHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElementBase(aNodeInfo),
mScrollgrab(false)
: nsGenericHTMLElementBase(aNodeInfo)
{
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
"Unexpected namespace");
@ -194,11 +193,15 @@ public:
}
bool Scrollgrab() const
{
return mScrollgrab;
return HasFlag(ELEMENT_HAS_SCROLLGRAB);
}
void SetScrollgrab(bool aValue)
{
mScrollgrab = aValue;
if (aValue) {
SetFlags(ELEMENT_HAS_SCROLLGRAB);
} else {
UnsetFlags(ELEMENT_HAS_SCROLLGRAB);
}
}
void GetInnerText(mozilla::dom::DOMString& aValue, mozilla::ErrorResult& aError);
@ -1167,8 +1170,6 @@ protected:
private:
void ChangeEditableState(int32_t aChange);
bool mScrollgrab;
};
namespace mozilla {

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

@ -1037,18 +1037,19 @@ ContentChild::InitXPCOM()
if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
NS_WARNING("Couldn't register console listener for child process");
bool isOffline, isLangRTL;
bool isOffline, isLangRTL, haveBidiKeyboards;
bool isConnected;
ClipboardCapabilities clipboardCaps;
DomainPolicyClone domainPolicy;
StructuredCloneData initialData;
SendGetXPCOMProcessAttributes(&isOffline, &isConnected,
&isLangRTL, &mAvailableDictionaries,
&isLangRTL, &haveBidiKeyboards,
&mAvailableDictionaries,
&clipboardCaps, &domainPolicy, &initialData);
RecvSetOffline(isOffline);
RecvSetConnectivity(isConnected);
RecvBidiKeyboardNotify(isLangRTL);
RecvBidiKeyboardNotify(isLangRTL, haveBidiKeyboards);
// Create the CPOW manager as soon as possible.
SendPJavaScriptConstructor();
@ -1511,13 +1512,14 @@ ContentChild::RecvSpeakerManagerNotify()
}
bool
ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL)
ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL,
const bool& aHaveBidiKeyboards)
{
// bidi is always of type PuppetBidiKeyboard* (because in the child, the only
// possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
PuppetBidiKeyboard* bidi = static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
if (bidi) {
bidi->SetIsLangRTL(aIsLangRTL);
bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards);
}
return true;
}
@ -3075,6 +3077,24 @@ ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
bool
ContentChild::RecvShutdown()
{
// If we receive the shutdown message from within a nested event loop, we want
// to wait for that event loop to finish. Otherwise we could prematurely
// terminate an "unload" or "pagehide" event handler (which might be doing a
// sync XHR, for example).
nsCOMPtr<nsIThread> thread;
nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
if (NS_SUCCEEDED(rv) && thread) {
RefPtr<nsThread> mainThread(thread.forget().downcast<nsThread>());
if (mainThread->RecursionDepth() > 1) {
// We're in a nested event loop. Let's delay for an arbitrary period of
// time (100ms) in the hopes that the event loop will have finished by
// then.
MessageLoop::current()->PostDelayedTask(
NewRunnableMethod(this, &ContentChild::RecvShutdown), 100);
return true;
}
}
if (mPolicy) {
mPolicy->Deactivate();
mPolicy = nullptr;

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

@ -401,7 +401,8 @@ public:
virtual bool RecvSpeakerManagerNotify() override;
virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) override;
virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL,
const bool& haveBidiKeyboards) override;
virtual bool RecvNotifyVisited(const URIParams& aURI) override;

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

@ -3388,6 +3388,7 @@ bool
ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
bool* aIsConnected,
bool* aIsLangRTL,
bool* aHaveBidiKeyboards,
InfallibleTArray<nsString>* dictionaries,
ClipboardCapabilities* clipboardCaps,
DomainPolicyClone* domainPolicy,
@ -3404,8 +3405,10 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard();
*aIsLangRTL = false;
*aHaveBidiKeyboards = false;
if (bidi) {
bidi->IsLangRTL(aIsLangRTL);
bidi->GetHaveBidiKeyboards(aHaveBidiKeyboards);
}
nsCOMPtr<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));

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

@ -707,6 +707,7 @@ private:
RecvGetXPCOMProcessAttributes(bool* aIsOffline,
bool* aIsConnected,
bool* aIsLangRTL,
bool* aHaveBidiKeyboards,
InfallibleTArray<nsString>* dictionaries,
ClipboardCapabilities* clipboardCaps,
DomainPolicyClone* domainPolicy,

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

@ -494,7 +494,7 @@ child:
* Communication between the PuppetBidiKeyboard and the actual
* BidiKeyboard hosted by the parent
*/
async BidiKeyboardNotify(bool isLangRTL);
async BidiKeyboardNotify(bool isLangRTL, bool haveBidiKeyboards);
/**
* Dump this process's GC and CC logs to the provided files.
@ -702,7 +702,8 @@ parent:
sync GetProcessAttributes()
returns (ContentParentId cpId, bool isForApp, bool isForBrowser);
sync GetXPCOMProcessAttributes()
returns (bool isOffline, bool isConnected, bool isLangRTL, nsString[] dictionaries,
returns (bool isOffline, bool isConnected, bool isLangRTL,
bool haveBidiKeyboards, nsString[] dictionaries,
ClipboardCapabilities clipboardCaps,
DomainPolicyClone domainPolicy,
StructuredCloneData initialData);

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

@ -340,6 +340,27 @@ TabParent::CacheFrameLoader(nsFrameLoader* aFrameLoader)
mFrameLoader = aFrameLoader;
}
/**
* Will return nullptr if there is no outer window available for the
* document hosting the owner element of this TabParent. Also will return
* nullptr if that outer window is in the process of closing.
*/
already_AddRefed<nsPIDOMWindowOuter>
TabParent::GetParentWindowOuter()
{
nsCOMPtr<nsIContent> frame = do_QueryInterface(GetOwnerElement());
if (!frame) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowOuter> parent = frame->OwnerDoc()->GetWindow();
if (!parent || parent->Closed()) {
return nullptr;
}
return parent.forget();
}
void
TabParent::SetOwnerElement(Element* aElement)
{

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

@ -143,6 +143,7 @@ public:
uint32_t aChromeFlags);
Element* GetOwnerElement() const { return mFrameElement; }
already_AddRefed<nsPIDOMWindowOuter> GetParentWindowOuter();
void SetOwnerElement(Element* aElement);

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

@ -9,11 +9,14 @@
#include "MediaResource.h"
#include "VideoUtils.h"
#include "ImageContainer.h"
#include "MediaPrefs.h"
#include "nsPrintfCString.h"
#include "mozilla/mozalloc.h"
#include "mozilla/Mutex.h"
#include <stdint.h>
#include <algorithm>
#include <list>
using namespace mozilla::media;
@ -62,6 +65,154 @@ public:
size_t mSize;
};
// The ReaderQueue is used to keep track of the numer of active readers to
// enforce a given limit on the number of simultaneous active decoders.
// Readers are added/removed during construction/destruction and are
// suspended and resumed by the queue. The max number of active decoders is
// controlled by the "media.decoder.limit" pref.
class ReaderQueue
{
public:
static ReaderQueue& Instance()
{
static StaticMutex sMutex;
StaticMutexAutoLock lock(sMutex);
if (!sInstance) {
sInstance = new ReaderQueue;
sInstance->MaxNumActive(MediaPrefs::MediaDecoderLimit());
ClearOnShutdown(&sInstance);
}
MOZ_ASSERT(sInstance);
return *sInstance;
}
void MaxNumActive(int32_t aNumActive)
{
MutexAutoLock lock(mMutex);
if (aNumActive < 0) {
mNumMaxActive = std::numeric_limits<uint32_t>::max();
} else {
mNumMaxActive = aNumActive;
}
}
void Add(MediaDecoderReader* aReader)
{
MutexAutoLock lock(mMutex);
if (mActive.Length() < mNumMaxActive) {
// Below active limit, resume the new reader.
mActive.AppendElement(aReader);
DispatchResume(aReader);
} else if (mActive.IsEmpty()) {
MOZ_ASSERT(mNumMaxActive == 0);
mSuspended.AppendElement(aReader);
} else {
// We're past the active limit, suspend an old reader and resume the new.
mActive.AppendElement(aReader);
MediaDecoderReader* suspendReader = mActive.ElementAt(0);
mSuspended.AppendElement(suspendReader);
mActive.RemoveElementAt(0);
DispatchSuspendResume(suspendReader, aReader);
}
}
void Remove(MediaDecoderReader* aReader)
{
MutexAutoLock lock(mMutex);
if (aReader->IsSuspended()) {
// Removing suspended readers has no immediate side-effects.
DebugOnly<bool> result = mSuspended.RemoveElement(aReader);
MOZ_ASSERT(result, "Suspended reader must be in mSuspended");
} else {
// For each removed active reader, we resume a suspended one.
DebugOnly<bool> result = mActive.RemoveElement(aReader);
MOZ_ASSERT(result, "Non-suspended reader must be in mActive");
if (mSuspended.IsEmpty()) {
return;
}
MediaDecoderReader* resumeReader = mSuspended.LastElement();
mActive.AppendElement(resumeReader);
mSuspended.RemoveElementAt(mSuspended.Length() - 1);
DispatchResume(resumeReader);
}
}
private:
ReaderQueue()
: mNumMaxActive(std::numeric_limits<uint32_t>::max())
, mMutex("ReaderQueue:mMutex")
{
}
static void Resume(MediaDecoderReader* aReader)
{
if (!aReader->IsSuspended()) {
return;
}
aReader->SetIsSuspended(false);
}
static void Suspend(MediaDecoderReader* aReader)
{
if (aReader->IsSuspended()) {
return;
}
aReader->SetIsSuspended(true);
aReader->ReleaseMediaResources();
}
static void DispatchResume(MediaDecoderReader* aReader)
{
RefPtr<MediaDecoderReader> reader = aReader;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
[reader]() {
Resume(reader);
});
reader->OwnerThread()->Dispatch(task.forget());
}
static void DispatchSuspend(MediaDecoderReader* aReader)
{
RefPtr<MediaDecoderReader> reader = aReader;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
[reader]() {
Suspend(reader);
});
reader->OwnerThread()->Dispatch(task.forget());
}
static void DispatchSuspendResume(MediaDecoderReader* aSuspend,
MediaDecoderReader* aResume)
{
RefPtr<MediaDecoderReader> suspend = aSuspend;
RefPtr<MediaDecoderReader> resume = aResume;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
[suspend, resume] () {
Suspend(suspend);
DispatchResume(resume);
});
suspend->OwnerThread()->Dispatch(task.forget());
}
static StaticAutoPtr<ReaderQueue> sInstance;
nsTArray<RefPtr<MediaDecoderReader>> mActive;
nsTArray<RefPtr<MediaDecoderReader>> mSuspended;
uint32_t mNumMaxActive;
mutable Mutex mMutex;
};
StaticAutoPtr<ReaderQueue> ReaderQueue::sInstance;
MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
: mAudioCompactor(mAudioQueue)
, mDecoder(aDecoder)
@ -75,6 +226,8 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
, mShutdown(false)
, mAudioDiscontinuity(false)
, mVideoDiscontinuity(false)
, mIsSuspended(mTaskQueue, true,
"MediaDecoderReader::mIsSuspended (Canonical)")
{
MOZ_COUNT_CTOR(MediaDecoderReader);
MOZ_ASSERT(NS_IsMainThread());
@ -84,6 +237,8 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
mTaskQueue, this, &MediaDecoderReader::NotifyDataArrived);
}
ReaderQueue::Instance().Add(this);
// Dispatch initialization that needs to happen on that task queue.
mTaskQueue->Dispatch(NewRunnableMethod(this, &MediaDecoderReader::InitializationTask));
}
@ -368,6 +523,7 @@ MediaDecoderReader::Shutdown()
ReleaseMediaResources();
mDuration.DisconnectIfConnected();
mBuffered.DisconnectAll();
mIsSuspended.DisconnectAll();
// Shut down the watch manager before shutting down our task queue.
mWatchManager.Shutdown();
@ -376,6 +532,8 @@ MediaDecoderReader::Shutdown()
mDecoder = nullptr;
ReaderQueue::Instance().Remove(this);
return mTaskQueue->BeginShutdown();
}

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

@ -290,6 +290,22 @@ public:
// Notified by the OggReader during playback when chained ogg is detected.
MediaEventSource<void>& OnMediaNotSeekable() { return mOnMediaNotSeekable; }
bool IsSuspended() const
{
MOZ_ASSERT(OnTaskQueue());
return mIsSuspended;
}
void SetIsSuspended(bool aState)
{
MOZ_ASSERT(OnTaskQueue());
mIsSuspended = aState;
}
AbstractCanonical<bool>* CanonicalIsSuspended() {
return &mIsSuspended;
}
protected:
virtual ~MediaDecoderReader();
@ -435,6 +451,7 @@ private:
// "discontinuity" in the stream. For example after a seek.
bool mAudioDiscontinuity;
bool mVideoDiscontinuity;
Canonical<bool> mIsSuspended;
MediaEventListener mDataArrivedListener;
};

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

@ -415,6 +415,9 @@ public:
AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
return mReader->CanonicalBuffered();
}
AbstractCanonical<bool>* CanonicalIsSuspended() {
return mReader->CanonicalIsSuspended();
}
#ifdef MOZ_EME
void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }

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

@ -262,6 +262,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mAudioOffloading(false),
mBuffered(mTaskQueue, TimeIntervals(),
"MediaDecoderStateMachine::mBuffered (Mirror)"),
mIsReaderSuspended(mTaskQueue, true,
"MediaDecoderStateMachine::mIsReaderSuspended (Mirror)"),
mEstimatedDuration(mTaskQueue, NullableTimeUnit(),
"MediaDecoderStateMachine::mEstimatedDuration (Mirror)"),
mExplicitDuration(mTaskQueue, Maybe<double>(),
@ -339,6 +341,7 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
// Connect mirrors.
mBuffered.Connect(mReader->CanonicalBuffered());
mIsReaderSuspended.Connect(mReader->CanonicalIsSuspended());
mEstimatedDuration.Connect(aDecoder->CanonicalEstimatedDuration());
mExplicitDuration.Connect(aDecoder->CanonicalExplicitDuration());
mPlayState.Connect(aDecoder->CanonicalPlayState());
@ -357,6 +360,7 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
// Initialize watchers.
mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated);
mWatchManager.Watch(mIsReaderSuspended, &MediaDecoderStateMachine::ReaderSuspendedChanged);
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVideoCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
@ -1342,8 +1346,9 @@ void MediaDecoderStateMachine::PlayStateChanged()
void MediaDecoderStateMachine::VisibilityChanged()
{
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("VisibilityChanged: is visible = %d, video decode suspended = %d",
mIsVisible.Ref(), mVideoDecodeSuspended);
DECODER_LOG("VisibilityChanged: is visible = %d, video decode suspended = %d, "
"reader suspended = %d",
mIsVisible.Ref(), mVideoDecodeSuspended, mIsReaderSuspended.Ref());
// Not suspending background videos so there's nothing to do.
if (!MediaPrefs::MDSMSuspendBackgroundVideoEnabled()) {
@ -1378,6 +1383,10 @@ void MediaDecoderStateMachine::VisibilityChanged()
if (mVideoDecodeSuspended) {
mVideoDecodeSuspended = false;
if (mIsReaderSuspended) {
return;
}
// If an existing seek is in flight don't bother creating a new
// one to catch up.
if (mSeekTask || mQueuedSeek.Exists()) {
@ -1385,23 +1394,31 @@ void MediaDecoderStateMachine::VisibilityChanged()
}
// Start video-only seek to the current time...
InitiateVideoDecodeRecoverySeek();
InitiateDecodeRecoverySeek(TrackSet(TrackInfo::kVideoTrack));
}
}
// InitiateVideoDecodeRecoverySeek is responsible for setting up a video-only
// seek using the seek task. When suspension of decoding for videos that are in
// InitiateDecodeRecoverySeek is responsible for setting up a seek using the
// seek task for the following situations:
// 1. When suspension of decoding for videos that are in
// background tabs (ie. invisible) is enabled, the audio keeps playing and when
// switching back to decoding video, it is highly desirable to not cause the
// audio to pause as the video is seeked else there be a noticeable audio glitch
// as the tab becomes visible.
void MediaDecoderStateMachine::InitiateVideoDecodeRecoverySeek()
// 2. When there is a decoder limit set, suspended videos may be resumed and
// require the seek to recover the original seek position for both audio and
// video.
void MediaDecoderStateMachine::InitiateDecodeRecoverySeek(TrackSet aTracks)
{
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("InitiateDecodeRecoverySeek");
SeekJob seekJob;
seekJob.mTarget = SeekTarget(GetMediaTime(),
SeekTarget::Type::AccurateVideoOnly,
SeekTarget::Type seekTargetType = aTracks.contains(TrackInfo::kAudioTrack)
? SeekTarget::Type::Accurate
: SeekTarget::Type::AccurateVideoOnly;
seekJob.mTarget = SeekTarget(GetMediaTime(), seekTargetType,
MediaDecoderEventVisibility::Suppressed);
SetState(DECODER_STATE_SEEKING);
@ -1423,7 +1440,7 @@ void MediaDecoderStateMachine::InitiateVideoDecodeRecoverySeek()
// Reset our state machine and decoding pipeline before seeking.
if (mSeekTask->NeedToResetMDSM()) {
Reset(TrackInfo::kVideoTrack);
Reset(aTracks);
}
// Do the seek.
@ -1456,6 +1473,19 @@ void MediaDecoderStateMachine::BufferedRangeUpdated()
}
}
void MediaDecoderStateMachine::ReaderSuspendedChanged()
{
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("ReaderSuspendedChanged: suspended = %d", mIsReaderSuspended.Ref());
if (!HasVideo() || mIsReaderSuspended || IsDecodingFirstFrame()) {
return;
}
InitiateDecodeRecoverySeek(TrackSet(TrackInfo::kAudioTrack,
TrackInfo::kVideoTrack));
}
void
MediaDecoderStateMachine::ReadMetadata()
{
@ -2222,6 +2252,7 @@ MediaDecoderStateMachine::FinishShutdown()
// Disconnect canonicals and mirrors before shutting down our task queue.
mBuffered.DisconnectIfConnected();
mIsReaderSuspended.DisconnectIfConnected();
mEstimatedDuration.DisconnectIfConnected();
mExplicitDuration.DisconnectIfConnected();
mPlayState.DisconnectIfConnected();
@ -2636,7 +2667,8 @@ bool MediaDecoderStateMachine::IsStateMachineScheduled() const
bool MediaDecoderStateMachine::IsVideoDecodeSuspended() const
{
MOZ_ASSERT(OnTaskQueue());
return MediaPrefs::MDSMSuspendBackgroundVideoEnabled() && mVideoDecodeSuspended;
return (MediaPrefs::MDSMSuspendBackgroundVideoEnabled() && mVideoDecodeSuspended) ||
mIsReaderSuspended;
}
void

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

@ -381,6 +381,8 @@ protected:
void BufferedRangeUpdated();
void ReaderSuspendedChanged();
// Inserts MediaData* samples into their respective MediaQueues.
// aSample must not be null.
@ -518,10 +520,11 @@ protected:
// The decoder monitor must be held.
void InitiateSeek(SeekJob aSeekJob);
// Clears any previous seeking state and initiates a video-only seek on the
// decoder to catch up the video to the current audio position, when recovering
// from video decoding being suspended in background.
void InitiateVideoDecodeRecoverySeek();
// Clears any previous seeking state and initiates a seek on the decoder to
// resync the video and audio positions, when recovering from video decoding
// being suspended in background or from audio and video decoding being
// suspended due to the decoder limit.
void InitiateDecodeRecoverySeek(TrackSet aTracks);
nsresult DispatchAudioDecodeTaskIfNeeded();
@ -975,6 +978,8 @@ private:
// The buffered range. Mirrored from the decoder thread.
Mirror<media::TimeIntervals> mBuffered;
Mirror<bool> mIsReaderSuspended;
// The duration according to the demuxer's current estimate, mirrored from the main thread.
Mirror<media::NullableTimeUnit> mEstimatedDuration;

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

@ -135,7 +135,6 @@ MediaFormatReader::Shutdown()
MOZ_ASSERT(!mVideo.HasPromise());
mDemuxer = nullptr;
mPlatform = nullptr;
return MediaDecoderReader::Shutdown();
@ -459,6 +458,11 @@ MediaFormatReader::EnsureDecoderInitialized(TrackType aTrack)
[self] (TrackType aTrack) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mInitPromise.Complete();
if (self->IsSuspended()) {
return;
}
decoder.mDecoderInitialized = true;
MonitorAutoLock mon(decoder.mMonitor);
decoder.mDescription = decoder.mDecoder->GetDescriptionName();
@ -533,6 +537,10 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
}
if (IsSuspended()) {
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
}
media::TimeUnit timeThreshold{media::TimeUnit::FromMicroseconds(aTimeThreshold)};
// Ensure we have no pending seek going as ShouldSkip could return out of date
// information.
@ -624,6 +632,10 @@ MediaFormatReader::RequestAudioData()
return MediaDataPromise::CreateAndReject(DECODE_ERROR, __func__);
}
if (IsSuspended()) {
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
}
if (IsSeeking()) {
LOG("called mid-seek. Rejecting.");
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
@ -918,6 +930,7 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
AbstractMediaDecoder::AutoNotifyDecoded& aA)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
if (decoder.mQueuedSamples.IsEmpty()) {
@ -1884,6 +1897,9 @@ void MediaFormatReader::ReleaseMediaResources()
}
mVideo.mInitPromise.DisconnectIfExists();
mVideo.ShutdownDecoder();
mAudio.mInitPromise.DisconnectIfExists();
mAudio.ShutdownDecoder();
}
bool

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

@ -101,6 +101,7 @@ public:
void GetMozDebugReaderData(nsAString& aString);
private:
bool HasVideo() { return mVideo.mTrackDemuxer; }
bool HasAudio() { return mAudio.mTrackDemuxer; }

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

@ -120,6 +120,7 @@ private:
DECL_MEDIA_PREF("media.webspeech.recognition.force_enable", WebSpeechRecognitionForceEnabled, bool, false);
DECL_MEDIA_PREF("media.num-decode-threads", MediaThreadPoolDefaultCount, uint32_t, 4);
DECL_MEDIA_PREF("media.decoder.limit", MediaDecoderLimit, uint32_t, -1);
public:
// Manage the singleton:

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

@ -59,6 +59,6 @@ enum RequestContext {
enum RequestMode { "same-origin", "no-cors", "cors", "navigate" };
enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" };
enum RequestRedirect { "follow", "error", "manual" };
enum ReferrerPolicy { "", "no-referrer", "no-referrer-when-downgrade", "origin", "origin-when-cross-origin", "unsafe-url" };

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

@ -126,7 +126,9 @@ static_assert(nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE == static_cast<u
"RequestCache enumeration value should match Necko Cache mode value.");
static_assert(nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE == static_cast<uint32_t>(RequestCache::Force_cache),
"RequestCache enumeration value should match Necko Cache mode value.");
static_assert(5 == static_cast<uint32_t>(RequestCache::EndGuard_),
static_assert(nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED == static_cast<uint32_t>(RequestCache::Only_if_cached),
"RequestCache enumeration value should match Necko Cache mode value.");
static_assert(6 == static_cast<uint32_t>(RequestCache::EndGuard_),
"RequestCache enumeration value should match Necko Cache mode value.");
static StaticRefPtr<ServiceWorkerManager> gInstance;

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

@ -14,6 +14,11 @@
#include "nsTArray.h"
#include "nscore.h"
// Workaround for windows headers
#ifdef SetProp
#undef SetProp
#endif
class nsIAtom;
class nsIDOMNode;
namespace mozilla {

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

@ -498,25 +498,11 @@ nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
}
#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
#include <windows.h>
// Undo the windows.h damage
#undef GetMessage
#undef CreateEvent
#undef GetClassName
#undef GetBinaryType
#undef RemoveDirectory
#undef SetProp
namespace {
// This function is borrowed from Chromium's ImeInput::IsCtrlShiftPressed
bool IsCtrlShiftPressed(bool& isRTL)
bool IsCtrlShiftPressed(nsIDOMKeyEvent* aEvent, bool& isRTL)
{
BYTE keystate[256];
if (!::GetKeyboardState(keystate)) {
return false;
}
// To check if a user is pressing only a control key and a right-shift key
// (or a left-shift key), we use the steps below:
// 1. Check if a user is pressing a control key and a right-shift key (or
@ -525,16 +511,19 @@ bool IsCtrlShiftPressed(bool& isRTL)
// keys pressed at the same time.
// To ignore the keys checked in 1, we set their status to 0 before
// checking the key status.
const int kKeyDownMask = 0x80;
if ((keystate[VK_CONTROL] & kKeyDownMask) == 0) {
WidgetKeyboardEvent* keyboardEvent =
aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
MOZ_ASSERT(keyboardEvent,
"DOM key event's internal event must be WidgetKeyboardEvent");
if (!keyboardEvent->IsControl()) {
return false;
}
if (keystate[VK_RSHIFT] & kKeyDownMask) {
keystate[VK_RSHIFT] = 0;
uint32_t location = keyboardEvent->mLocation;
if (location == nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT) {
isRTL = true;
} else if (keystate[VK_LSHIFT] & kKeyDownMask) {
keystate[VK_LSHIFT] = 0;
} else if (location == nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT) {
isRTL = false;
} else {
return false;
@ -542,19 +531,10 @@ bool IsCtrlShiftPressed(bool& isRTL)
// Scan the key status to find pressed keys. We should abandon changing the
// text direction when there are other pressed keys.
// This code is executed only when a user is pressing a control key and a
// right-shift key (or a left-shift key), i.e. we should ignore the status of
// the keys: VK_SHIFT, VK_CONTROL, VK_RCONTROL, and VK_LCONTROL.
// So, we reset their status to 0 and ignore them.
keystate[VK_SHIFT] = 0;
keystate[VK_CONTROL] = 0;
keystate[VK_RCONTROL] = 0;
keystate[VK_LCONTROL] = 0;
for (int i = 0; i <= VK_PACKET; ++i) {
if (keystate[i] & kKeyDownMask) {
return false;
}
if (keyboardEvent->IsAlt() || keyboardEvent->IsOS()) {
return false;
}
return true;
}
@ -598,7 +578,7 @@ nsEditorEventListener::KeyDown(nsIDOMKeyEvent* aKeyEvent)
aKeyEvent->GetKeyCode(&keyCode);
if (keyCode == nsIDOMKeyEvent::DOM_VK_SHIFT) {
bool switchToRTL;
if (IsCtrlShiftPressed(switchToRTL)) {
if (IsCtrlShiftPressed(aKeyEvent, switchToRTL)) {
mShouldSwitchTextDirection = true;
mSwitchToRTL = switchToRTL;
}

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

@ -54,6 +54,11 @@
#include "nsWSRunObject.h"
#include <algorithm>
// Workaround for windows headers
#ifdef SetProp
#undef SetProp
#endif
class nsISupports;
class nsRulesInfo;

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

@ -100,6 +100,7 @@ static const char* const sExtensionNames[] = {
"GL_ARB_robustness",
"GL_ARB_sampler_objects",
"GL_ARB_seamless_cube_map",
"GL_ARB_shader_texture_lod",
"GL_ARB_sync",
"GL_ARB_texture_compression",
"GL_ARB_texture_float",

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

@ -128,6 +128,7 @@ enum class GLFeature {
sRGB_texture,
sampler_objects,
seamless_cube_map_opt_in,
shader_texture_lod,
split_framebuffer,
standard_derivatives,
sync,
@ -423,6 +424,7 @@ public:
ARB_robustness,
ARB_sampler_objects,
ARB_seamless_cube_map,
ARB_shader_texture_lod,
ARB_sync,
ARB_texture_compression,
ARB_texture_float,

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

@ -567,6 +567,17 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLContext::Extensions_End
}
},
{
"shader_texture_lod",
GLVersion::NONE,
GLESVersion::NONE,
GLContext::Extension_None,
{
GLContext::ARB_shader_texture_lod,
GLContext::EXT_shader_texture_lod,
GLContext::Extensions_End
}
},
{
// Do we have separate DRAW and READ framebuffer bind points?
"split_framebuffer",

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

@ -169,6 +169,12 @@ GLXLibrary::EnsureInitialized()
{ nullptr, { nullptr } }
};
GLLibraryLoader::SymLoadStruct symbols_videosync[] = {
{ (PRFuncPtr*) &xGetVideoSyncInternal, { "glXGetVideoSyncSGI", nullptr } },
{ (PRFuncPtr*) &xWaitVideoSyncInternal, { "glXWaitVideoSyncSGI", nullptr } },
{ nullptr, { nullptr } }
};
if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
NS_WARNING("Couldn't find required entry point in OpenGL shared library");
return false;
@ -246,6 +252,13 @@ GLXLibrary::EnsureInitialized()
mHasRobustness = true;
}
if (HasExtension(extensionsStr, "GLX_SGI_video_sync") &&
GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_videosync,
(GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress))
{
mHasVideoSync = true;
}
mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
@ -269,6 +282,16 @@ GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
return true;
}
bool
GLXLibrary::SupportsVideoSync()
{
if (!EnsureInitialized()) {
return false;
}
return mHasVideoSync;
}
GLXPixmap
GLXLibrary::CreatePixmap(gfxASurface* aSurface)
{
@ -737,6 +760,24 @@ GLXLibrary::xCreateContextAttribs(Display* display,
return result;
}
int
GLXLibrary::xGetVideoSync(unsigned int* count)
{
BEFORE_GLX_CALL;
int result = xGetVideoSyncInternal(count);
AFTER_GLX_CALL;
return result;
}
int
GLXLibrary::xWaitVideoSync(int divisor, int remainder, unsigned int* count)
{
BEFORE_GLX_CALL;
int result = xWaitVideoSyncInternal(divisor, remainder, count);
AFTER_GLX_CALL;
return result;
}
already_AddRefed<GLContextGLX>
GLContextGLX::CreateGLContext(
const SurfaceCaps& caps,

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

@ -54,9 +54,12 @@ public:
, xWaitGLInternal(nullptr)
, xWaitXInternal(nullptr)
, xCreateContextAttribsInternal(nullptr)
, xGetVideoSyncInternal(nullptr)
, xWaitVideoSyncInternal(nullptr)
, mInitialized(false), mTriedInitializing(false)
, mUseTextureFromPixmap(false), mDebug(false)
, mHasRobustness(false), mHasCreateContextAttribs(false)
, mHasVideoSync(false)
, mIsATI(false), mIsNVIDIA(false)
, mClientIsMesa(false), mGLXMajorVersion(0)
, mGLXMinorVersion(0)
@ -120,6 +123,9 @@ public:
Bool direct,
const int* attrib_list);
int xGetVideoSync(unsigned int* count);
int xWaitVideoSync(int divisor, int remainder, unsigned int* count);
bool EnsureInitialized();
GLXPixmap CreatePixmap(gfxASurface* aSurface);
@ -132,6 +138,7 @@ public:
bool HasRobustness() { return mHasRobustness; }
bool HasCreateContextAttribs() { return mHasCreateContextAttribs; }
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
bool SupportsVideoSync();
bool IsATI() { return mIsATI; }
bool GLXVersionCheck(int aMajor, int aMinor);
@ -225,6 +232,12 @@ private:
const int *);
PFNGLXCREATECONTEXTATTRIBS xCreateContextAttribsInternal;
typedef int (GLAPIENTRY *PFNGLXGETVIDEOSYNCSGI) (unsigned int *count);
PFNGLXGETVIDEOSYNCSGI xGetVideoSyncInternal;
typedef int (GLAPIENTRY *PFNGLXWAITVIDEOSYNCSGI) (int divisor, int remainder, unsigned int *count);
PFNGLXWAITVIDEOSYNCSGI xWaitVideoSyncInternal;
#ifdef DEBUG
void BeforeGLXCall();
void AfterGLXCall();
@ -236,6 +249,7 @@ private:
bool mDebug;
bool mHasRobustness;
bool mHasCreateContextAttribs;
bool mHasVideoSync;
bool mIsATI;
bool mIsNVIDIA;
bool mClientIsMesa;

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

@ -732,25 +732,6 @@ gfxContext::Mask(SourceSurface* aSurface, Float aAlpha, const Matrix& aTransform
ChangeTransform(old);
}
void
gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset)
{
PROFILER_LABEL("gfxContext", "Mask",
js::ProfileEntry::Category::GRAPHICS);
// Lifetime needs to be limited here as we may simply wrap surface's data.
RefPtr<SourceSurface> sourceSurf =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface);
if (!sourceSurf) {
return;
}
gfxPoint pt = surface->GetDeviceOffset();
Mask(sourceSurf, 1.0f, Point(offset.x - pt.x, offset.y - pt.y));
}
void
gfxContext::Mask(SourceSurface *surface, float alpha, const Point& offset)
{

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

@ -304,13 +304,6 @@ public:
*/
void Mask(mozilla::gfx::SourceSurface *aSurface, mozilla::gfx::Float aAlpha, const mozilla::gfx::Matrix& aTransform);
void Mask(mozilla::gfx::SourceSurface *aSurface, const mozilla::gfx::Matrix& aTransform) { Mask(aSurface, 1.0f, aTransform); }
/**
* Shorthand for creating a pattern and calling the pattern-taking
* variant of Mask.
*/
void Mask(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0));
void Mask(mozilla::gfx::SourceSurface *surface, float alpha = 1.0f, const mozilla::gfx::Point& offset = mozilla::gfx::Point());
/**

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

@ -21,7 +21,7 @@ namespace mozilla {
* between unquoted and quoted names for serializaiton
*/
enum FontFamilyType {
enum FontFamilyType : uint32_t {
eFamily_none = 0, // used when finding generics
// explicitly named font family (e.g. Helvetica)

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

@ -20,6 +20,13 @@
#include "gfxUtils.h"
#include "gfxFT2FontBase.h"
#include "gfxPrefs.h"
#include "VsyncSource.h"
#include "mozilla/Atomics.h"
#include "mozilla/Monitor.h"
#include "base/task.h"
#include "base/thread.h"
#include "base/message_loop.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/2D.h"
@ -34,6 +41,12 @@
#include "mozilla/Preferences.h"
#include "mozilla/X11Util.h"
#ifdef GL_PROVIDER_GLX
#include "GLContextProvider.h"
#include "GLContextGLX.h"
#include "GLXLibrary.h"
#endif
/* Undefine the Status from Xlib since it will conflict with system headers on OSX */
#if defined(__APPLE__) && defined(Status)
#undef Status
@ -583,3 +596,230 @@ gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
{
return GetScaledFontForFontWithCairoSkia(aTarget, aFont);
}
#ifdef GL_PROVIDER_GLX
class GLXVsyncSource final : public VsyncSource
{
public:
GLXVsyncSource()
{
MOZ_ASSERT(NS_IsMainThread());
mGlobalDisplay = new GLXDisplay();
}
virtual ~GLXVsyncSource()
{
MOZ_ASSERT(NS_IsMainThread());
}
virtual Display& GetGlobalDisplay() override
{
return *mGlobalDisplay;
}
class GLXDisplay final : public VsyncSource::Display
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLXDisplay)
public:
GLXDisplay() : mGLContext(nullptr)
, mSetupLock("GLXVsyncSetupLock")
, mVsyncThread("GLXVsyncThread")
, mVsyncTask(nullptr)
, mVsyncEnabledLock("GLXVsyncEnabledLock")
, mVsyncEnabled(false)
{
}
// Sets up the display's GL context on a worker thread.
// Required as GLContexts may only be used by the creating thread.
// Returns true if setup was a success.
bool Setup()
{
MonitorAutoLock lock(mSetupLock);
MOZ_ASSERT(NS_IsMainThread());
if (!mVsyncThread.Start())
return false;
RefPtr<Runnable> vsyncSetup = NewRunnableMethod(this, &GLXDisplay::SetupGLContext);
mVsyncThread.message_loop()->PostTask(vsyncSetup.forget());
// Wait until the setup has completed.
lock.Wait();
return mGLContext != nullptr;
}
// Called on the Vsync thread to setup the GL context.
void SetupGLContext()
{
MonitorAutoLock lock(mSetupLock);
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mGLContext, "GLContext already setup!");
// Create video sync timer on a separate Display to prevent locking the
// main thread X display.
mXDisplay = XOpenDisplay(nullptr);
if (!mXDisplay) {
lock.NotifyAll();
return;
}
// Most compositors wait for vsync events on the root window.
Window root = DefaultRootWindow(mXDisplay);
int screen = DefaultScreen(mXDisplay);
ScopedXFree<GLXFBConfig> cfgs;
GLXFBConfig config;
int visid;
if (!gl::GLContextGLX::FindFBConfigForWindow(mXDisplay, screen, root,
&cfgs, &config, &visid)) {
lock.NotifyAll();
return;
}
mGLContext = gl::GLContextGLX::CreateGLContext(
gl::SurfaceCaps::Any(),
nullptr,
false,
mXDisplay,
root,
config,
false);
mGLContext->MakeCurrent();
// Test that SGI_video_sync lets us get the counter.
unsigned int syncCounter = 0;
if (gl::sGLXLibrary.xGetVideoSync(&syncCounter) != 0) {
mGLContext = nullptr;
}
lock.NotifyAll();
}
virtual void EnableVsync() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGLContext, "GLContext not setup!");
MonitorAutoLock lock(mVsyncEnabledLock);
if (mVsyncEnabled) {
return;
}
mVsyncEnabled = true;
// If the task has not nulled itself out, it hasn't yet realized
// that vsync was disabled earlier, so continue its execution.
if (!mVsyncTask) {
mVsyncTask = NewRunnableMethod(this, &GLXDisplay::RunVsync);
RefPtr<Runnable> addrefedTask = mVsyncTask;
mVsyncThread.message_loop()->PostTask(addrefedTask.forget());
}
}
virtual void DisableVsync() override
{
MonitorAutoLock lock(mVsyncEnabledLock);
mVsyncEnabled = false;
}
virtual bool IsVsyncEnabled() override
{
MonitorAutoLock lock(mVsyncEnabledLock);
return mVsyncEnabled;
}
virtual void Shutdown() override
{
MOZ_ASSERT(NS_IsMainThread());
DisableVsync();
// Cleanup thread-specific resources before shutting down.
RefPtr<Runnable> shutdownTask = NewRunnableMethod(this, &GLXDisplay::Cleanup);
mVsyncThread.message_loop()->PostTask(shutdownTask.forget());
// Stop, waiting for the cleanup task to finish execution.
mVsyncThread.Stop();
}
private:
virtual ~GLXDisplay()
{
}
void RunVsync()
{
MOZ_ASSERT(!NS_IsMainThread());
mGLContext->MakeCurrent();
unsigned int syncCounter = 0;
gl::sGLXLibrary.xGetVideoSync(&syncCounter);
for (;;) {
{
MonitorAutoLock lock(mVsyncEnabledLock);
if (!mVsyncEnabled) {
mVsyncTask = nullptr;
return;
}
}
TimeStamp lastVsync = TimeStamp::Now();
// Wait until the video sync counter reaches the next value by waiting
// until the parity of the counter value changes.
unsigned int nextSync = syncCounter + 1;
if (gl::sGLXLibrary.xWaitVideoSync(2, nextSync % 2,
&syncCounter) == 0) {
if (syncCounter == (nextSync - 1)) {
gfxWarning() << "GLX sync counter failed to increment after glXWaitVideoSync!\n";
// If we failed to block until the next sync, fallback to software.
double remaining = (1000.f / 60.f) -
(TimeStamp::Now() - lastVsync).ToMilliseconds();
if (remaining > 0) {
PlatformThread::Sleep(remaining);
}
}
lastVsync = TimeStamp::Now();
NotifyVsync(lastVsync);
}
}
}
void Cleanup() {
MOZ_ASSERT(!NS_IsMainThread());
mGLContext = nullptr;
XCloseDisplay(mXDisplay);
}
// Owned by the vsync thread.
RefPtr<gl::GLContextGLX> mGLContext;
_XDisplay* mXDisplay;
Monitor mSetupLock;
base::Thread mVsyncThread;
RefPtr<Runnable> mVsyncTask;
Monitor mVsyncEnabledLock;
bool mVsyncEnabled;
};
private:
// We need a refcounted VsyncSource::Display to use chromium IPC runnables.
RefPtr<GLXDisplay> mGlobalDisplay;
};
already_AddRefed<gfx::VsyncSource>
gfxPlatformGtk::CreateHardwareVsyncSource()
{
if (gl::sGLXLibrary.SupportsVideoSync()) {
RefPtr<VsyncSource> vsyncSource = new GLXVsyncSource();
VsyncSource::Display& display = vsyncSource->GetGlobalDisplay();
if (!static_cast<GLXVsyncSource::GLXDisplay&>(display).Setup()) {
NS_WARNING("Failed to setup GLContext, falling back to software vsync.");
return gfxPlatform::CreateHardwareVsyncSource();
}
return vsyncSource.forget();
}
NS_WARNING("SGI_video_sync unsupported. Falling back to software vsync.");
return gfxPlatform::CreateHardwareVsyncSource();
}
#endif

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

@ -132,6 +132,10 @@ public:
return true;
}
#ifdef GL_PROVIDER_GLX
already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
#endif
protected:
static gfxFontconfigUtils *sFontconfigUtils;

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

@ -273,6 +273,7 @@ private:
DECL_GFX_PREF(Live, "gfx.SurfaceTexture.detach.enabled", SurfaceTextureDetachEnabled, bool, true);
DECL_GFX_PREF(Live, "gfx.testing.device-reset", DeviceResetForTesting, int32_t, 0);
DECL_GFX_PREF(Live, "gfx.testing.device-fail", DeviceFailForTesting, bool, false);
DECL_GFX_PREF(Live, "gfx.ycbcr.accurate-conversion", YCbCrAccurateConversion, bool, false);
DECL_GFX_PREF(Live, "gfx.content.use-native-pushlayer", UseNativePushLayer, bool, false);

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

@ -31,8 +31,6 @@
#include "nsPresContext.h"
#include "nsRegion.h"
#include "nsServiceManagerUtils.h"
#include "yuv_convert.h"
#include "ycbcr_to_rgb565.h"
#include "GeckoProfiler.h"
#include "ImageContainer.h"
#include "ImageRegion.h"

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

@ -7,14 +7,7 @@
#include <stdint.h>
// On Windows, protypes.h is #included, which defines these types. This sucks!
#ifndef PROTYPES_H
typedef uint8_t uint8;
typedef int8_t int8;
typedef int16_t int16;
typedef uint16_t uint16;
typedef uint32_t uint32;
#endif
#include "libyuv/basic_types.h"
// From Chromium build_config.h:
// Processor architecture detection. For more info on what's defined, see:

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

@ -5,11 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'chromium_types.h',
'ycbcr_to_rgb565.h',
'YCbCrUtils.h',
'yuv_convert.h',
'yuv_row.h',
]
UNIFIED_SOURCES += [
@ -63,4 +59,6 @@ if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['HAVE_ARM_NEON']:
'yuv_convert_arm.cpp',
]
LOCAL_INCLUDES += ['/media/libyuv/include']
FINAL_LIBRARY = 'xul'

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

@ -18,6 +18,8 @@
#include "yuv_convert.h"
#include "gfxPrefs.h"
#include "libyuv.h"
// Header for low level row functions.
#include "yuv_row.h"
#include "mozilla/SSE.h"
@ -60,6 +62,72 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
int uv_pitch,
int rgb_pitch,
YUVType yuv_type) {
// Deprecated function's conversion is accurate.
// libyuv converion is a bit inaccurate to get performance. It dynamically
// calculates RGB from YUV to use simd. In it, signed byte is used for conversion's
// coefficient, but it requests 129. libyuv cut 129 to 127. And only 6 bits are
// used for a decimal part during the dynamic calculation.
//
// The function is still fast on some old intel chips.
// See Bug 1256475.
bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
(supports_mmx() && supports_sse() && !supports_sse3());
if (use_deprecated) {
ConvertYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, rgb_buf,
pic_x, pic_y, pic_width, pic_height,
y_pitch, uv_pitch, rgb_pitch, yuv_type);
return;
}
if (yuv_type == YV24) {
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x;
const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x;
DebugOnly<int> err = libyuv::I444ToARGB(src_y, y_pitch,
src_u, uv_pitch,
src_v, uv_pitch,
rgb_buf, rgb_pitch,
pic_width, pic_height);
MOZ_ASSERT(!err);
} else if (yuv_type == YV16) {
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x / 2;
const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x / 2;
DebugOnly<int> err = libyuv::I422ToARGB(src_y, y_pitch,
src_u, uv_pitch,
src_v, uv_pitch,
rgb_buf, rgb_pitch,
pic_width, pic_height);
MOZ_ASSERT(!err);
} else {
MOZ_ASSERT(yuv_type == YV12);
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch,
src_u, uv_pitch,
src_v, uv_pitch,
rgb_buf, rgb_pitch,
pic_width, pic_height);
MOZ_ASSERT(!err);
}
}
// Convert a frame of YUV to 32 bit ARGB.
void ConvertYCbCrToRGB32_deprecated(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int pic_x,
int pic_y,
int pic_width,
int pic_height,
int y_pitch,
int uv_pitch,
int rgb_pitch,
YUVType yuv_type) {
unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
// Test for SSE because the optimized code uses movntq, which is not part of MMX.

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

@ -57,6 +57,19 @@ void ConvertYCbCrToRGB32(const uint8* yplane,
int rgbstride,
YUVType yuv_type);
void ConvertYCbCrToRGB32_deprecated(const uint8* yplane,
const uint8* uplane,
const uint8* vplane,
uint8* rgbframe,
int pic_x,
int pic_y,
int pic_width,
int pic_height,
int ystride,
int uvstride,
int rgbstride,
YUVType yuv_type);
// Scale a frame of YUV to 32 bit ARGB.
// Supports rotation and mirroring.
void ScaleYCbCrToRGB32(const uint8* yplane,

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

@ -15,44 +15,10 @@ enum { GIF_TRAILER = 0x3B }; // ';'
enum { GIF_IMAGE_SEPARATOR = 0x2C }; // ','
enum { GIF_EXTENSION_INTRODUCER = 0x21 }; // '!'
enum { GIF_GRAPHIC_CONTROL_LABEL = 0xF9 };
enum { GIF_COMMENT_LABEL = 0xFE };
enum { GIF_PLAIN_TEXT_LABEL = 0x01 };
enum { GIF_APPLICATION_EXTENSION_LABEL = 0xFF };
// gif2.h
// The interface for the GIF87/89a decoder.
// List of possible parsing states
typedef enum {
gif_type,
gif_global_header,
gif_global_colormap,
gif_image_start,
gif_image_header,
gif_image_colormap,
gif_lzw_start,
gif_lzw,
gif_sub_block,
gif_extension,
gif_control_extension,
gif_consume_block,
gif_skip_block,
gif_done,
gif_error,
gif_comment_extension,
gif_application_extension,
gif_netscape_extension_block,
gif_consume_netscape_extension,
gif_consume_comment
} gstate;
// A GIF decoder's state
typedef struct gif_struct {
// Parsing state machine
gstate state; // Current decoder master state
uint32_t bytes_to_consume; // Number of bytes to accumulate
uint32_t bytes_in_hold; // bytes accumulated so far
// LZW decoder state machine
uint8_t* stackp; // Current stack pointer
int datasize;
@ -61,7 +27,6 @@ typedef struct gif_struct {
int avail; // Index of next available slot in dictionary
int oldcode;
uint8_t firstchar;
int count; // Remaining # bytes in sub-block
int bits; // Number of unread bits in "datum"
int32_t datum; // 32-bit input buffer
@ -80,7 +45,8 @@ typedef struct gif_struct {
int version; // Either 89 for GIF89 or 87 for GIF87
int32_t screen_width; // Logical screen width & height
int32_t screen_height;
uint32_t global_colormap_depth; // Depth of global colormap array
uint8_t global_colormap_depth; // Depth of global colormap array
uint16_t global_colormap_count; // Number of colors in global colormap
int images_decoded; // Counts images for multi-part GIFs
int loop_count; // Netscape specific extension block to control
// the number of animation loops a GIF
@ -89,7 +55,6 @@ typedef struct gif_struct {
bool is_transparent; // TRUE, if tpixel is valid
uint16_t prefix[MAX_BITS]; // LZW decoding tables
uint8_t* hold; // Accumulation buffer
uint32_t global_colormap[MAX_COLORS]; // Default colormap if local not
// supplied
uint8_t suffix[MAX_BITS]; // LZW decoding tables

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

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

@ -9,6 +9,7 @@
#include "Decoder.h"
#include "GIF2.h"
#include "StreamingLexer.h"
#include "SurfacePipe.h"
namespace mozilla {
@ -54,25 +55,70 @@ private:
/// Called when we finish decoding the entire image.
void FlushImageData();
nsresult GifWrite(const uint8_t* buf, uint32_t numbytes);
/// Transforms a palette index into a pixel.
template <typename PixelSize> PixelSize
ColormapIndexToPixel(uint8_t aIndex);
/// A generator function that performs LZW decompression and yields pixels.
template <typename PixelSize> NextPixel<PixelSize>
YieldPixel(const uint8_t*& aCurrentByte);
YieldPixel(const uint8_t* aData, size_t aLength, size_t* aBytesReadOut);
/// The entry point for LZW decompression.
bool DoLzw(const uint8_t* aData);
/// Checks if we have transparency, either because the header indicates that
/// there's alpha, or because the frame rect doesn't cover the entire image.
bool CheckForTransparency(const gfx::IntRect& aFrameRect);
bool SetHold(const uint8_t* buf, uint32_t count,
const uint8_t* buf2 = nullptr, uint32_t count2 = 0);
bool CheckForTransparency(const gfx::IntRect& aFrameRect);
gfx::IntRect ClampToImageRect(const gfx::IntRect& aFrameRect);
// @return the clear code used for LZW decompression.
int ClearCode() const { return 1 << mGIFStruct.datasize; }
inline int ClearCode() const { return 1 << mGIFStruct.datasize; }
enum class State
{
FAILURE,
SUCCESS,
GIF_HEADER,
SCREEN_DESCRIPTOR,
GLOBAL_COLOR_TABLE,
FINISHED_GLOBAL_COLOR_TABLE,
BLOCK_HEADER,
EXTENSION_HEADER,
GRAPHIC_CONTROL_EXTENSION,
APPLICATION_IDENTIFIER,
NETSCAPE_EXTENSION_SUB_BLOCK,
NETSCAPE_EXTENSION_DATA,
IMAGE_DESCRIPTOR,
LOCAL_COLOR_TABLE,
FINISHED_LOCAL_COLOR_TABLE,
IMAGE_DATA_BLOCK,
IMAGE_DATA_SUB_BLOCK,
LZW_DATA,
FINISHED_LZW_DATA,
SKIP_SUB_BLOCKS,
SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
FINISHED_SKIPPING_DATA
};
LexerTransition<State> ReadGIFHeader(const char* aData);
LexerTransition<State> ReadScreenDescriptor(const char* aData);
LexerTransition<State> ReadGlobalColorTable(const char* aData, size_t aLength);
LexerTransition<State> FinishedGlobalColorTable();
LexerTransition<State> ReadBlockHeader(const char* aData);
LexerTransition<State> ReadExtensionHeader(const char* aData);
LexerTransition<State> ReadGraphicControlExtension(const char* aData);
LexerTransition<State> ReadApplicationIdentifier(const char* aData);
LexerTransition<State> ReadNetscapeExtensionSubBlock(const char* aData);
LexerTransition<State> ReadNetscapeExtensionData(const char* aData);
LexerTransition<State> ReadImageDescriptor(const char* aData);
LexerTransition<State> ReadLocalColorTable(const char* aData, size_t aLength);
LexerTransition<State> FinishedLocalColorTable();
LexerTransition<State> ReadImageDataBlock(const char* aData);
LexerTransition<State> ReadImageDataSubBlock(const char* aData);
LexerTransition<State> ReadLZWData(const char* aData, size_t aLength);
LexerTransition<State> SkipSubBlocks(const char* aData);
// The StreamingLexer used to manage input. The initial size of the buffer is
// chosen as a little larger than the maximum size of any fixed-length data we
// have to read for a state. We read variable-length data in unbuffered mode
// so the buffer shouldn't have to be resized during decoding.
StreamingLexer<State, 16> mLexer;
uint32_t mOldColor; // The old value of the transparent pixel
@ -80,6 +126,11 @@ private:
// of decoding it, and -1 otherwise.
int32_t mCurrentFrameIndex;
// When we're reading in the global or local color table, this records our
// current position - i.e., the offset into which the next byte should be
// written.
size_t mColorTablePos;
uint8_t mColorMask; // Apply this to the pixel to keep within colormap
bool mGIFOpen;
bool mSawTransparency;

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

@ -29,8 +29,6 @@ namespace base {
typedef ::Lock Lock;
typedef ::AutoLock AutoLock;
using mozilla::OffTheBooksMutexAutoLock;
// Static table of checksums for all possible 8 bit bytes.
const uint32_t Histogram::kCrcTable[256] = {0x0, 0x77073096L, 0xee0e612cL,
0x990951baL, 0x76dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0xedb8832L,
@ -177,24 +175,20 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
SampleSet snapshot;
SnapshotSample(&snapshot);
// For the rest of the routine, we hold |snapshot|'s lock so as to
// be able to examine it atomically.
OffTheBooksMutexAutoLock locker(snapshot.mutex());
Count sample_count = snapshot.TotalCount();
Count sample_count = snapshot.TotalCount(locker);
WriteAsciiHeader(snapshot, locker, sample_count, output);
WriteAsciiHeader(snapshot, sample_count, output);
output->append(newline);
// Prepare to normalize graphical rendering of bucket contents.
double max_size = 0;
if (graph_it)
max_size = GetPeakBucketSize(snapshot, locker);
max_size = GetPeakBucketSize(snapshot);
// Calculate space needed to print bucket range numbers. Leave room to print
// nearly the largest bucket range without sliding over the histogram.
size_t largest_non_empty_bucket = bucket_count() - 1;
while (0 == snapshot.counts(locker, largest_non_empty_bucket)) {
while (0 == snapshot.counts(largest_non_empty_bucket)) {
if (0 == largest_non_empty_bucket)
break; // All buckets are empty.
--largest_non_empty_bucket;
@ -203,7 +197,7 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
// Calculate largest print width needed for any of our bucket range displays.
size_t print_width = 1;
for (size_t i = 0; i < bucket_count(); ++i) {
if (snapshot.counts(locker, i)) {
if (snapshot.counts(i)) {
size_t width = GetAsciiBucketRange(i).size() + 1;
if (width > print_width)
print_width = width;
@ -214,7 +208,7 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
int64_t past = 0;
// Output the actual histogram graph.
for (size_t i = 0; i < bucket_count(); ++i) {
Count current = snapshot.counts(locker, i);
Count current = snapshot.counts(i);
if (!current && !PrintEmptyBucket(i))
continue;
remaining -= current;
@ -223,8 +217,8 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
for (size_t j = 0; range.size() + j < print_width + 1; ++j)
output->push_back(' ');
if (0 == current &&
i < bucket_count() - 1 && 0 == snapshot.counts(locker, i + 1)) {
while (i < bucket_count() - 1 && 0 == snapshot.counts(locker, i + 1))
i < bucket_count() - 1 && 0 == snapshot.counts(i + 1)) {
while (i < bucket_count() - 1 && 0 == snapshot.counts(i + 1))
++i;
output->append("... ");
output->append(newline);
@ -244,14 +238,14 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
// Methods for the validating a sample and a related histogram.
//------------------------------------------------------------------------------
Histogram::Inconsistencies Histogram::FindCorruption(
const SampleSet& snapshot,
const OffTheBooksMutexAutoLock& snapshotLockEvidence) const {
Histogram::Inconsistencies
Histogram::FindCorruption(const SampleSet& snapshot) const
{
int inconsistencies = NO_INCONSISTENCIES;
Sample previous_range = -1; // Bottom range is always 0.
int64_t count = 0;
for (size_t index = 0; index < bucket_count(); ++index) {
count += snapshot.counts(snapshotLockEvidence, index);
count += snapshot.counts(index);
int new_range = ranges(index);
if (previous_range >= new_range)
inconsistencies |= BUCKET_ORDER_ERROR;
@ -261,7 +255,7 @@ Histogram::Inconsistencies Histogram::FindCorruption(
if (!HasValidRangeChecksum())
inconsistencies |= RANGE_CHECKSUM_ERROR;
int64_t delta64 = snapshot.redundant_count(snapshotLockEvidence) - count;
int64_t delta64 = snapshot.redundant_count() - count;
if (delta64 != 0) {
int delta = static_cast<int>(delta64);
if (delta != delta64)
@ -302,7 +296,6 @@ size_t Histogram::bucket_count() const {
}
void Histogram::SnapshotSample(SampleSet* sample) const {
OffTheBooksMutexAutoLock locker(sample_.mutex());
*sample = sample_;
}
@ -336,9 +329,9 @@ size_t Histogram::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
return n;
}
size_t Histogram::SampleSet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
size_t
Histogram::SampleSet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
OffTheBooksMutexAutoLock locker(mutex_);
// We're not allowed to do deep dives into STL data structures. This
// is as close as we can get to measuring this array.
return aMallocSizeOf(&counts_[0]);
@ -556,13 +549,11 @@ uint32_t Histogram::Crc32(uint32_t sum, Histogram::Sample range) {
//------------------------------------------------------------------------------
// Private methods
double Histogram::GetPeakBucketSize(const SampleSet& snapshot,
const OffTheBooksMutexAutoLock&
snapshotLockEvidence) const {
double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const {
double max = 0;
for (size_t i = 0; i < bucket_count() ; ++i) {
double current_size
= GetBucketSize(snapshot.counts(snapshotLockEvidence, i), i);
= GetBucketSize(snapshot.counts(i), i);
if (current_size > max)
max = current_size;
}
@ -570,15 +561,13 @@ double Histogram::GetPeakBucketSize(const SampleSet& snapshot,
}
void Histogram::WriteAsciiHeader(const SampleSet& snapshot,
const OffTheBooksMutexAutoLock&
snapshotLockEvidence,
Count sample_count,
std::string* output) const {
StringAppendF(output,
"Histogram: %s recorded %d samples",
histogram_name().c_str(),
sample_count);
int64_t snapshot_sum = snapshot.sum(snapshotLockEvidence);
int64_t snapshot_sum = snapshot.sum();
if (0 == sample_count) {
DCHECK_EQ(snapshot_sum, 0);
} else {
@ -629,20 +618,17 @@ void Histogram::WriteAsciiBucketGraph(double current_size, double max_size,
Histogram::SampleSet::SampleSet()
: counts_(),
sum_(0),
redundant_count_(0),
mutex_("Histogram::SampleSet::SampleSet") {
redundant_count_(0) {
}
Histogram::SampleSet::~SampleSet() {
}
void Histogram::SampleSet::Resize(const Histogram& histogram) {
OffTheBooksMutexAutoLock locker(mutex_);
counts_.resize(histogram.bucket_count(), 0);
}
void Histogram::SampleSet::Accumulate(const OffTheBooksMutexAutoLock& ev,
Sample value, Count count,
void Histogram::SampleSet::Accumulate(Sample value, Count count,
size_t index) {
DCHECK(count == 1 || count == -1);
counts_[index] += count;
@ -653,15 +639,7 @@ void Histogram::SampleSet::Accumulate(const OffTheBooksMutexAutoLock& ev,
DCHECK_GE(redundant_count_, 0);
}
void Histogram::SampleSet::Accumulate(Sample value,
Count count,
size_t index) {
OffTheBooksMutexAutoLock locker(mutex_);
Accumulate(locker, value, count, index);
}
Count Histogram::SampleSet::TotalCount(const OffTheBooksMutexAutoLock& ev)
const {
Count Histogram::SampleSet::TotalCount() const {
Count total = 0;
for (Counts::const_iterator it = counts_.begin();
it != counts_.end();
@ -672,7 +650,6 @@ Count Histogram::SampleSet::TotalCount(const OffTheBooksMutexAutoLock& ev)
}
void Histogram::SampleSet::Add(const SampleSet& other) {
OffTheBooksMutexAutoLock locker(mutex_);
DCHECK_EQ(counts_.size(), other.counts_.size());
sum_ += other.sum_;
redundant_count_ += other.redundant_count_;
@ -874,8 +851,7 @@ FlagHistogram::Accumulate(Sample value, Count count, size_t index)
void
FlagHistogram::AddSampleSet(const SampleSet& sample) {
OffTheBooksMutexAutoLock locker(sample.mutex());
DCHECK_EQ(bucket_count(), sample.size(locker));
DCHECK_EQ(bucket_count(), sample.size());
// We can't be sure the SampleSet provided came from another FlagHistogram,
// so we take the following steps:
// - If our flag has already been set do nothing.
@ -889,12 +865,12 @@ FlagHistogram::AddSampleSet(const SampleSet& sample) {
return;
}
if (sample.sum(locker) != 1) {
if (sample.sum() != 1) {
return;
}
size_t one_index = BucketIndex(1);
if (sample.counts(locker, one_index) == 1) {
if (sample.counts(one_index) == 1) {
Accumulate(1, 1, one_index);
}
}
@ -946,20 +922,18 @@ CountHistogram::Accumulate(Sample value, Count count, size_t index)
void
CountHistogram::AddSampleSet(const SampleSet& sample) {
OffTheBooksMutexAutoLock locker(sample.mutex());
DCHECK_EQ(bucket_count(), sample.size(locker));
DCHECK_EQ(bucket_count(), sample.size());
// We can't be sure the SampleSet provided came from another CountHistogram,
// so we at least check that the unused buckets are empty.
const size_t indices[] = { BucketIndex(0), BucketIndex(1), BucketIndex(2) };
if (sample.counts(locker, indices[1]) != 0 ||
sample.counts(locker, indices[2]) != 0) {
if (sample.counts(indices[1]) != 0 || sample.counts(indices[2]) != 0) {
return;
}
if (sample.counts(locker, indices[0]) != 0) {
Accumulate(1, sample.counts(locker, indices[0]), indices[0]);
if (sample.counts(indices[0]) != 0) {
Accumulate(1, sample.counts(indices[0]), indices[0]);
}
}

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

@ -45,7 +45,6 @@
#include "mozilla/Atomics.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
#include <map>
#include <string>
@ -56,9 +55,6 @@
namespace base {
using mozilla::OffTheBooksMutex;
using mozilla::OffTheBooksMutexAutoLock;
//------------------------------------------------------------------------------
// Provide easy general purpose histogram in a macro, just like stats counters.
// The first four macros use 50 buckets.
@ -327,20 +323,8 @@ class Histogram {
explicit SampleSet();
~SampleSet();
// This class contains a mozilla::OffTheBooksMutex, |mutex_|.
// Most of the methods are thread-safe: they acquire and release
// the mutex themselves. A few are not thread-safe, and require
// the caller to provide evidence that the object is locked, by
// supplying a const OffTheBooksMutexAutoLock& parameter. The
// parameter is ignored but must be present. |mutex_| must be an
// OffTheBooks variant because some of the containing SampleSet
// objects are leaked until shutdown, so a standard Mutex can't be
// used, since that does leak checking, and causes test failures.
//---------------- THREAD SAFE METHODS ----------------//
//
// The caller must not already hold |this.mutex_|, otherwise we
// will end up deadlocking.
// None of the methods in this class are thread-safe. Callers
// must deal with locking themselves.
// Adjust size of counts_ for use with given histogram.
void Resize(const Histogram& histogram);
@ -353,38 +337,20 @@ class Histogram {
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);
//---------------- THREAD UNSAFE METHODS ----------------//
//
// The caller must hold |this.mutex_|, and must supply evidence by passing
// a const reference to the relevant OffTheBooksMutexAutoLock used.
Count counts(const OffTheBooksMutexAutoLock& ev, size_t i) const {
Count counts(size_t i) const {
return counts_[i];
}
Count TotalCount(const OffTheBooksMutexAutoLock& ev) const;
int64_t sum(const OffTheBooksMutexAutoLock& ev) const {
Count TotalCount() const;
int64_t sum() const {
return sum_;
}
int64_t redundant_count(const OffTheBooksMutexAutoLock& ev) const {
int64_t redundant_count() const {
return redundant_count_;
}
size_t size(const OffTheBooksMutexAutoLock& ev) const {
size_t size() const {
return counts_.size();
}
// An assignment operator. The presence of mozilla::OffTheBooksMutex
// in this class causes the default assignment operator to be deleted.
const SampleSet& operator=(const SampleSet& other) {
counts_ = other.counts_;
sum_ = other.sum_;
redundant_count_ = other.redundant_count_;
return *this;
}
private:
void Accumulate(const OffTheBooksMutexAutoLock& ev,
Sample value, Count count, size_t index);
protected:
// Actual histogram data is stored in buckets, showing the count of values
// that fit into each bucket.
@ -402,13 +368,6 @@ class Histogram {
// and also the snapshotting code may asynchronously get a mismatch (though
// generally either race based mismatch cause is VERY rare).
int64_t redundant_count_;
private:
// Protects all data fields.
mutable OffTheBooksMutex mutex_;
public:
OffTheBooksMutex& mutex() const { return mutex_; }
};
//----------------------------------------------------------------------------
@ -466,9 +425,7 @@ class Histogram {
// produce a false-alarm if a race occurred in the reading of the data during
// a SnapShot process, but should otherwise be false at all times (unless we
// have memory over-writes, or DRAM failures).
virtual Inconsistencies FindCorruption(const SampleSet& snapshot,
const OffTheBooksMutexAutoLock&
snapshotLockEvidence) const;
virtual Inconsistencies FindCorruption(const SampleSet& snapshot) const;
//----------------------------------------------------------------------------
// Accessors for factory constuction, serialization and testing.
@ -483,7 +440,7 @@ class Histogram {
// Do a safe atomic snapshot of sample data. The caller is assumed to
// have exclusive access to the destination, |*sample|, and no locking
// of it is done here. This routine does lock the source sample though.
// of it is done here.
virtual void SnapshotSample(SampleSet* sample) const;
virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
@ -559,13 +516,10 @@ class Histogram {
// Helpers for emitting Ascii graphic. Each method appends data to output.
// Find out how large the (graphically) the largest bucket will appear to be.
double GetPeakBucketSize(const SampleSet& snapshot,
const OffTheBooksMutexAutoLock&
snapshotLockEvidence) const;
double GetPeakBucketSize(const SampleSet& snapshot) const;
// Write a common header message describing this histogram.
void WriteAsciiHeader(const SampleSet& snapshot,
const OffTheBooksMutexAutoLock& snapshotLockEvidence,
Count sample_count, std::string* output) const;
// Write information about previous, current, and next buckets.

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

@ -276,8 +276,7 @@ BackgroundChildImpl::DeallocPUDPSocketChild(PUDPSocketChild* child)
dom::PBroadcastChannelChild*
BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOrigin,
const nsString& aChannel,
const bool& aPrivateBrowsing)
const nsString& aChannel)
{
RefPtr<dom::BroadcastChannelChild> agent =
new dom::BroadcastChannelChild(aOrigin);

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

@ -104,8 +104,7 @@ protected:
virtual PBroadcastChannelChild*
AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOrigin,
const nsString& aChannel,
const bool& aPrivateBrowsing) override;
const nsString& aChannel) override;
virtual bool
DeallocPBroadcastChannelChild(PBroadcastChannelChild* aActor) override;

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

@ -467,8 +467,7 @@ mozilla::dom::PBroadcastChannelParent*
BackgroundParentImpl::AllocPBroadcastChannelParent(
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOrigin,
const nsString& aChannel,
const bool& aPrivateBrowsing)
const nsString& aChannel)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
@ -476,15 +475,11 @@ BackgroundParentImpl::AllocPBroadcastChannelParent(
nsString originChannelKey;
// The format of originChannelKey is:
// <channelName>|pb={true,false}|<origin+OriginAttributes>
// <channelName>|<origin+OriginAttributes>
originChannelKey.Assign(aChannel);
if (aPrivateBrowsing) {
originChannelKey.AppendLiteral("|pb=true|");
} else {
originChannelKey.AppendLiteral("|pb=false|");
}
originChannelKey.AppendLiteral("|");
originChannelKey.Append(NS_ConvertUTF8toUTF16(aOrigin));
@ -648,8 +643,7 @@ BackgroundParentImpl::RecvPBroadcastChannelConstructor(
PBroadcastChannelParent* actor,
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOrigin,
const nsString& aChannel,
const bool& aPrivateBrowsing)
const nsString& aChannel)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();

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

@ -90,15 +90,13 @@ protected:
virtual PBroadcastChannelParent*
AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOrigin,
const nsString& aChannel,
const bool& aPrivateBrowsing) override;
const nsString& aChannel) override;
virtual bool
RecvPBroadcastChannelConstructor(PBroadcastChannelParent* actor,
const PrincipalInfo& aPrincipalInfo,
const nsCString& origin,
const nsString& channel,
const bool& aPrivateBrowsing) override;
const nsString& channel) override;
virtual bool
DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override;

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

@ -79,8 +79,7 @@ parent:
async PCameras();
async PUDPSocket(OptionalPrincipalInfo pInfo, nsCString filter);
async PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel,
bool privateBrowsing);
async PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel);
async PServiceWorkerManager();

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

@ -0,0 +1,30 @@
g = newGlobal();
g.parent = this;
g.eval("(" + function() {
Debugger(parent).onExceptionUnwind = function(frame) {
frame.older
}
} + ")()")
function check_one(expected, f, err) {
try {
f()
} catch (ex) {
s = ex.toString()
assertEq(s.slice(11, -err.length), expected)
}
}
ieval = eval
function check(expr, expected = expr) {
var end, err
for ([end, err] of[[".random_prop", " is undefined" ]])
statement = "o = {};" + expr + end;
cases = [
function() ieval("var undef;" + statement),
Function(statement)
]
for (f of cases)
check_one(expected, f, err)
}
check("undef");
check("o.b");

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

@ -7,6 +7,8 @@
#ifndef jit_RematerializedFrame_h
#define jit_RematerializedFrame_h
#include <algorithm>
#include "jsfun.h"
#include "jit/JitFrameIterator.h"
@ -180,12 +182,15 @@ class RematerializedFrame
unsigned numActualArgs() const {
return numActualArgs_;
}
unsigned numArgSlots() const {
return (std::max)(numFormalArgs(), numActualArgs());
}
Value* argv() {
return slots_;
}
Value* locals() {
return slots_ + numActualArgs_ + isConstructing_;
return slots_ + numArgSlots() + isConstructing_;
}
Value& unaliasedLocal(unsigned i) {

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

@ -458,14 +458,27 @@ ShellInterruptCallback(JSContext* cx)
bool result;
if (sr->haveInterruptFunc) {
bool wasAlreadyThrowing = cx->isExceptionPending();
JS::AutoSaveExceptionState savedExc(cx);
JSAutoCompartment ac(cx, &sr->interruptFunc.toObject());
RootedValue rval(cx);
if (!JS_CallFunctionValue(cx, nullptr, sr->interruptFunc,
JS::HandleValueArray::empty(), &rval))
// Report any exceptions thrown by the JS interrupt callback, but do
// *not* keep it on the cx. The interrupt handler is invoked at points
// that are not expected to throw catchable exceptions, like at
// JSOP_RETRVAL.
//
// If the interrupted JS code was already throwing, any exceptions
// thrown by the interrupt handler are silently swallowed.
{
return false;
Maybe<AutoReportException> are;
if (!wasAlreadyThrowing)
are.emplace(cx);
result = JS_CallFunctionValue(cx, nullptr, sr->interruptFunc,
JS::HandleValueArray::empty(), &rval);
}
savedExc.restore();
if (rval.isBoolean())
result = rval.toBoolean();
else

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