merge mozilla-inbound to mozilla-central. r=merge a=merge

MozReview-Commit-ID: Gc5JIILUrPi
This commit is contained in:
Sebastian Hengst 2017-10-20 00:05:39 +02:00
Родитель 378936755e 47b2d43b88
Коммит 20d769ea9c
115 изменённых файлов: 33576 добавлений и 34482 удалений

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

@ -9,6 +9,8 @@
#include "mozilla/a11y/HandlerProvider.h" #include "mozilla/a11y/HandlerProvider.h"
#include "Accessible2_3.h" #include "Accessible2_3.h"
#include "AccessibleTable.h"
#include "AccessibleTable2.h"
#include "HandlerData.h" #include "HandlerData.h"
#include "HandlerData_i.c" #include "HandlerData_i.c"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
@ -214,6 +216,18 @@ HandlerProvider::MarshalAs(REFIID aIid)
return aIid; return aIid;
} }
REFIID
HandlerProvider::GetEffectiveOutParamIid(REFIID aCallIid,
ULONG aCallMethod)
{
if (aCallIid == IID_IAccessibleTable || aCallIid == IID_IAccessibleTable2) {
return IID_IAccessible2_3;
}
MOZ_ASSERT(false);
return IID_IUnknown;
}
HRESULT HRESULT
HandlerProvider::NewInstance(REFIID aIid, HandlerProvider::NewInstance(REFIID aIid,
mscom::InterceptorTargetPtr<IUnknown> aTarget, mscom::InterceptorTargetPtr<IUnknown> aTarget,

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

@ -7,7 +7,7 @@
#ifndef mozilla_a11y_HandlerProvider_h #ifndef mozilla_a11y_HandlerProvider_h
#define mozilla_a11y_HandlerProvider_h #define mozilla_a11y_HandlerProvider_h
#include "handler/AccessibleHandler.h" #include "mozilla/a11y/AccessibleHandler.h"
#include "mozilla/AlreadyAddRefed.h" #include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "mozilla/mscom/IHandlerProvider.h" #include "mozilla/mscom/IHandlerProvider.h"
@ -44,6 +44,8 @@ public:
STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override; STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override;
STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override; STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override;
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override; STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
ULONG aCallMethod) override;
STDMETHODIMP NewInstance(REFIID aIid, STDMETHODIMP NewInstance(REFIID aIid,
mscom::InterceptorTargetPtr<IUnknown> aTarget, mscom::InterceptorTargetPtr<IUnknown> aTarget,
NotNull<mscom::IHandlerProvider**> aOutNewPayload) override; NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;

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

@ -297,15 +297,28 @@ Sanitizer.prototype = {
Services.obs.notifyObservers(null, "extension:purge-localStorage"); Services.obs.notifyObservers(null, "extension:purge-localStorage");
// ServiceWorkers // ServiceWorkers
let promises = [];
let serviceWorkers = serviceWorkerManager.getAllRegistrations(); let serviceWorkers = serviceWorkerManager.getAllRegistrations();
for (let i = 0; i < serviceWorkers.length; i++) { for (let i = 0; i < serviceWorkers.length; i++) {
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo); let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
let host = sw.principal.URI.host;
serviceWorkerManager.removeAndPropagate(host); promises.push(new Promise(resolve => {
let unregisterCallback = {
unregisterSucceeded: () => { resolve(true); },
// We don't care about failures.
unregisterFailed: () => { resolve(true); },
QueryInterface: XPCOMUtils.generateQI(
[Ci.nsIServiceWorkerUnregisterCallback])
};
serviceWorkerManager.propagateUnregister(sw.principal, unregisterCallback, sw.scope);
}));
} }
await Promise.all(promises);
// QuotaManager // QuotaManager
let promises = []; promises = [];
await new Promise(resolve => { await new Promise(resolve => {
quotaManagerService.getUsage(request => { quotaManagerService.getUsage(request => {
if (request.resultCode != Cr.NS_OK) { if (request.resultCode != Cr.NS_OK) {

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

@ -1,6 +1,8 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */ * http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/PromiseUtils.jsm");
/** /**
* With e10s, plugins must run in their own process. This means we have * With e10s, plugins must run in their own process. This means we have
* three processes at a minimum when we're running a plugin: * three processes at a minimum when we're running a plugin:
@ -79,51 +81,56 @@ function preparePlugin(browser, pluginFallbackState) {
}); });
} }
add_task(async function setup() { // Bypass click-to-play
// Bypass click-to-play setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
// Clear out any minidumps we create from plugins - we really don't care // Deferred promise object used by the test to wait for the crash handler
// about them. let crashDeferred = null;
let crashObserver = (subject, topic, data) => {
if (topic != "plugin-crashed") {
return;
}
let propBag = subject.QueryInterface(Ci.nsIPropertyBag2); // Clear out any minidumps we create from plugins - we really don't care
let minidumpID = propBag.getPropertyAsAString("pluginDumpID"); // about them.
let crashObserver = (subject, topic, data) => {
if (topic != "plugin-crashed") {
return;
}
Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => { let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile); let minidumpID = propBag.getPropertyAsAString("pluginDumpID");
minidumpDir.append("minidumps");
let pluginDumpFile = minidumpDir.clone(); Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => {
pluginDumpFile.append(minidumpID + ".dmp"); let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
minidumpDir.append("minidumps");
let extraFile = minidumpDir.clone(); let pluginDumpFile = minidumpDir.clone();
extraFile.append(minidumpID + ".extra"); pluginDumpFile.append(minidumpID + ".dmp");
ok(pluginDumpFile.exists(), "Found minidump"); let extraFile = minidumpDir.clone();
ok(extraFile.exists(), "Found extra file"); extraFile.append(minidumpID + ".extra");
pluginDumpFile.remove(false); ok(pluginDumpFile.exists(), "Found minidump");
extraFile.remove(false); ok(extraFile.exists(), "Found extra file");
});
};
Services.obs.addObserver(crashObserver, "plugin-crashed"); pluginDumpFile.remove(false);
// plugins.testmode will make BrowserPlugins:Test:ClearCrashData work. extraFile.remove(false);
Services.prefs.setBoolPref("plugins.testmode", true); crashDeferred.resolve();
registerCleanupFunction(() => {
Services.prefs.clearUserPref("plugins.testmode");
Services.obs.removeObserver(crashObserver, "plugin-crashed");
}); });
};
Services.obs.addObserver(crashObserver, "plugin-crashed");
// plugins.testmode will make BrowserPlugins:Test:ClearCrashData work.
Services.prefs.setBoolPref("plugins.testmode", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("plugins.testmode");
Services.obs.removeObserver(crashObserver, "plugin-crashed");
}); });
/** /**
* In this case, the chrome process hears about the crash first. * In this case, the chrome process hears about the crash first.
*/ */
add_task(async function testChromeHearsPluginCrashFirst() { add_task(async function testChromeHearsPluginCrashFirst() {
// Setup the crash observer promise
crashDeferred = PromiseUtils.defer();
// Open a remote window so that we can run this test even if e10s is not // Open a remote window so that we can run this test even if e10s is not
// enabled by default. // enabled by default.
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true}); let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
@ -183,12 +190,16 @@ add_task(async function testChromeHearsPluginCrashFirst() {
"Should have been showing crash report UI"); "Should have been showing crash report UI");
}); });
await BrowserTestUtils.closeWindow(win); await BrowserTestUtils.closeWindow(win);
await crashDeferred.promise;
}); });
/** /**
* In this case, the content process hears about the crash first. * In this case, the content process hears about the crash first.
*/ */
add_task(async function testContentHearsCrashFirst() { add_task(async function testContentHearsCrashFirst() {
// Setup the crash observer promise
crashDeferred = PromiseUtils.defer();
// Open a remote window so that we can run this test even if e10s is not // Open a remote window so that we can run this test even if e10s is not
// enabled by default. // enabled by default.
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true}); let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
@ -253,4 +264,5 @@ add_task(async function testContentHearsCrashFirst() {
}); });
await BrowserTestUtils.closeWindow(win); await BrowserTestUtils.closeWindow(win);
await crashDeferred.promise;
}); });

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

@ -34,7 +34,9 @@ add_task(async function test_clear_email() {
prefs.setBoolPref("emailMe", true); prefs.setBoolPref("emailMe", true);
let tab = gBrowser.getTabForBrowser(browser); let tab = gBrowser.getTabForBrowser(browser);
await BrowserTestUtils.crashBrowser(browser); await BrowserTestUtils.crashBrowser(browser,
/* shouldShowTabCrashPage */ true,
/* shouldClearMinidumps */ false);
let doc = browser.contentDocument; let doc = browser.contentDocument;
// Since about:tabcrashed will run in the parent process, we can safely // Since about:tabcrashed will run in the parent process, we can safely

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

@ -1,7 +1,7 @@
This is the debugger.html project output. This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html See https://github.com/devtools-html/debugger.html
Taken from upstream commit: 455e7e3f2de29113e37de8c03052de110f5fb106 Taken from upstream commit: aa6b25cc7dc645b8c1d76af58b99012e40b80848
Packages: Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.0 - babel-plugin-transform-es2015-modules-commonjs @6.26.0

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

@ -2,6 +2,141 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
menu {
display: inline;
padding: 0;
}
menu > menuitem::after {
content: "\25BA";
float: right;
padding-left: 5px;
}
menu > menupopup {
display: none;
}
menu > menuitem:hover + menupopup,
menu > menupopup:hover {
display: block;
}
menupopup {
position: fixed;
z-index: 10000;
background: white;
border: 1px solid #cccccc;
padding: 5px 0;
background: #f2f2f2;
border-radius: 5px;
color: #585858;
box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8);
min-width: 130px;
}
menuitem {
display: block;
padding: 0 20px;
line-height: 20px;
font-weight: 500;
font-size: 13px;
-moz-user-select: none;
user-select: none;
}
menuitem:hover {
background: #3780fb;
color: white;
cursor: pointer;
}
menuitem[disabled=true] {
color: #cccccc;
}
menuitem[disabled=true]:hover {
background-color: transparent;
cursor: default;
}
menuitem[type=checkbox]::before {
content: "";
width: 10px;
display: inline-block;
}
menuitem[type=checkbox][checked=true]::before {
content: "\2713";
left: -8px;
position: relative;
}
menuseparator {
border-bottom: 1px solid #cacdd3;
width: 100%;
height: 5px;
display: block;
margin-bottom: 5px;
}
#contextmenu-mask.show {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
/* 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/. */
:root.theme-light,
:root .theme-light {
--theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
#mount {
display: flex;
height: 100%;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
background: transparent;
}
::-webkit-scrollbar-track {
border-radius: 8px;
background: transparent;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
background: rgba(113, 113, 113, 0.5);
}
:root.theme-dark .CodeMirror-scrollbar-filler {
background: transparent;
}
/* 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/. */
.landing-page { .landing-page {
flex: 1; flex: 1;
display: flex; display: flex;
@ -275,144 +410,10 @@
padding-left: 3px; padding-left: 3px;
font-weight: normal; font-weight: normal;
} }
/* 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/. */
menu {
display: inline;
padding: 0;
}
menu > menuitem::after {
content: "\25BA";
float: right;
padding-left: 5px;
}
menu > menupopup {
display: none;
}
menu > menuitem:hover + menupopup,
menu > menupopup:hover {
display: block;
}
menupopup {
position: fixed;
z-index: 10000;
background: white;
border: 1px solid #cccccc;
padding: 5px 0;
background: #f2f2f2;
border-radius: 5px;
color: #585858;
box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8);
min-width: 130px;
}
menuitem {
display: block;
padding: 0 20px;
line-height: 20px;
font-weight: 500;
font-size: 13px;
-moz-user-select: none;
user-select: none;
}
menuitem:hover {
background: #3780fb;
color: white;
cursor: pointer;
}
menuitem[disabled=true] {
color: #cccccc;
}
menuitem[disabled=true]:hover {
background-color: transparent;
cursor: default;
}
menuitem[type=checkbox]::before {
content: "";
width: 10px;
display: inline-block;
}
menuitem[type=checkbox][checked=true]::before {
content: "\2713";
left: -8px;
position: relative;
}
menuseparator {
border-bottom: 1px solid #cacdd3;
width: 100%;
height: 5px;
display: block;
margin-bottom: 5px;
}
#contextmenu-mask.show {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
/* 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/. */
:root.theme-light,
:root .theme-light {
--theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
#mount {
display: flex;
height: 100%;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
background: transparent;
}
::-webkit-scrollbar-track {
border-radius: 8px;
background: transparent;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
background: rgba(113, 113, 113, 0.5);
}
:root.theme-dark .CodeMirror-scrollbar-filler {
background: transparent;
}
.modal-wrapper { .modal-wrapper {
position: fixed; position: fixed;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -423,13 +424,12 @@ body {
} }
.modal { .modal {
top: 0; width: 80%;
margin: auto; height: auto;
width: 500px; overflow-y: scroll;
background-color: var(--theme-toolbar-background); background-color: var(--theme-toolbar-background);
transform: translateY(-250px);
transition: transform 150ms cubic-bezier(0.07, 0.95, 0, 1); transition: transform 150ms cubic-bezier(0.07, 0.95, 0, 1);
box-shadow: 0 0 10px 2px var(--popup-shadow-color); box-shadow: 1px 1px 3px 1px var(--popup-shadow-color);
} }
.modal.entering, .modal.entering,
@ -439,13 +439,24 @@ body {
.modal.entered, .modal.entered,
.modal.exiting { .modal.exiting {
transform: translateY(0px); transform: translateY(5px);
} }
@media (max-width: 520px) { /* This rule is active when the screen is not short and narrow */
@media (min-width: 580px) and (min-height: 340px) {
.modal { .modal {
width: 80%; width: 50%;
left: 10%; }
}
@media (min-height: 340px) {
.modal {
height: auto;
max-height: 80vh;
}
.modal.entered,
.modal.exiting {
transform: translateY(30px);
} }
} }
.shortcuts-content { .shortcuts-content {
@ -490,10 +501,6 @@ body {
width: calc(100% - 1px); /* 1px fixes the hidden right border */ width: calc(100% - 1px); /* 1px fixes the hidden right border */
} }
.shortcuts-modal {
width: 45%;
}
.shortcuts-list li { .shortcuts-list li {
font-size: 12px; font-size: 12px;
color: var(--theme-body-color); color: var(--theme-body-color);
@ -1696,10 +1703,10 @@ html .toggle-button-end.vertical svg {
transition: opacity 200ms; transition: opacity 200ms;
border: none; border: none;
background: transparent; background: transparent;
padding: 6px 0.7em; padding: 6px;
} }
.source-footer > .commands > .action i { .source-footer > .commands > .action img {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -1718,9 +1725,18 @@ html .toggle-button-end.vertical svg {
fill: var(--theme-selection-color); fill: var(--theme-selection-color);
} }
.source-footer > .commands > .action svg { .source-footer > .commands > .action > img.prettyPrint {
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
height: 16px; height: 16px;
width: 16px; width: 16px;
background: var(--theme-body-color);
}
.source-footer > .commands > .action > img.blackBox {
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
height: 16px;
width: 16px;
background: var(--theme-body-color);
} }
.source-footer .commands .coverage { .source-footer .commands .coverage {
@ -1733,8 +1749,8 @@ html .toggle-button-end.vertical svg {
border-radius: 2px; border-radius: 2px;
} }
.source-footer .black-box.blackboxed svg { .source-footer > .commands > .blackboxed > img.blackBox {
fill: var(--theme-highlight-blue); background: var(--theme-highlight-blue);
} }
.source-footer .blackbox-summary { .source-footer .blackbox-summary {
@ -2188,12 +2204,19 @@ html[dir="rtl"] .arrow svg,
box-shadow: 1px 2px 3px var(--popup-shadow-color); box-shadow: 1px 2px 3px var(--popup-shadow-color);
} }
.popover .preview-popup .header { .popover .preview-popup .header-container {
width: 100%; width: 100%;
line-height: 20px; line-height: 20px;
border-bottom: 1px solid #cccccc;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-bottom: 5px;
}
.popover .preview-popup .header-container h3 {
margin: 0;
margin-bottom: 5px;
font-weight: normal;
font-size: 14px;
} }
.popover .preview-popup .header .link { .popover .preview-popup .header .link {
@ -2492,8 +2515,9 @@ html[dir="rtl"] .editor-mount {
} }
.CodeMirror-linenumber { .CodeMirror-linenumber {
font-size: 11px; font-size: 12px;
line-height: 14px; line-height: 15px;
font-family: monospace;
} }
.folding-enabled .CodeMirror-linenumber { .folding-enabled .CodeMirror-linenumber {
@ -3149,6 +3173,18 @@ html .command-bar > button:disabled {
.command-bar > button { .command-bar > button {
padding: 6px 5px; padding: 6px 5px;
} }
.command-bar.bottom {
justify-content: flex-end;
}
.command-bar.bottom > button {
color: var(--theme-comment);
width: 26px;
}
.command-bar.bottom > button:hover {
color: var(--theme-body-color);
}
.object-node.default-property { .object-node.default-property {
opacity: 0.6; opacity: 0.6;
} }
@ -3373,13 +3409,13 @@ html .welcomebox .toggle-button-end.collapsed {
fill: var(--theme-body-color); fill: var(--theme-body-color);
} }
.source-tab .prettyPrint { .source-tab img.prettyPrint {
line-height: 0; mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
} mask-size: 100%;
padding-top: 12px;
.source-tab .prettyPrint svg {
height: 12px; height: 12px;
width: 12px; width: 12px;
background: var(--theme-highlight-blue);
} }
.source-tab .prettyPrint path { .source-tab .prettyPrint path {
@ -3388,13 +3424,16 @@ html .welcomebox .toggle-button-end.collapsed {
.source-tab .blackBox, .source-tab .blackBox,
.source-tab .prettyPrint { .source-tab .prettyPrint {
line-height: 0;
align-self: center; align-self: center;
} }
.source-tab .blackBox svg { .source-tab img.blackBox {
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
mask-size: 100%;
padding-top: 12px;
height: 12px; height: 12px;
width: 12px; width: 12px;
background: var(--theme-highlight-blue);
} }
.source-tab .blackBox path { .source-tab .blackBox path {

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

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

@ -78,12 +78,201 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ 1282: /***/ 1282:
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1283); module.exports = __webpack_require__(1630);
/***/ }), /***/ }),
/***/ 1283: /***/ 1363:
/***/ (function(module, exports, __webpack_require__) {
/* 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 networkRequest = __webpack_require__(1367);
const workerUtils = __webpack_require__(1368);
module.exports = {
networkRequest,
workerUtils
};
/***/ }),
/***/ 1367:
/***/ (function(module, exports) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function networkRequest(url, opts) {
return fetch(url, {
cache: opts.loadFromCache ? "default" : "no-cache"
}).then(res => {
if (res.status >= 200 && res.status < 300) {
return res.text().then(text => ({ content: text }));
}
return Promise.reject(`request failed with status ${res.status}`);
});
}
module.exports = networkRequest;
/***/ }),
/***/ 1368:
/***/ (function(module, exports) {
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function WorkerDispatcher() {
this.msgId = 1;
this.worker = null;
} /* 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 mark = typeof window == "object" && window.performance && window.performance.mark ? window.performance.mark.bind(window.performance) : () => {};
const measure = typeof window == "object" && window.performance && window.performance.measure ? window.performance.measure.bind(window.performance) : () => {};
WorkerDispatcher.prototype = {
start(url) {
this.worker = new Worker(url);
this.worker.onerror = () => {
console.error(`Error in worker ${url}`);
};
},
stop() {
if (!this.worker) {
return;
}
this.worker.terminate();
this.worker = null;
},
task(method) {
return (...args) => {
return new Promise((resolve, reject) => {
const id = this.msgId++;
mark(`${method}_start`);
this.worker.postMessage({ id, method, args });
const listener = ({ data: result }) => {
if (result.id !== id) {
return;
}
if (!this.worker) {
reject("Oops, The worker has shutdown!");
return;
}
this.worker.removeEventListener("message", listener);
mark(`${method}_end`);
measure(`${method}`, `${method}_start`, `${method}_end`);
if (result.error) {
reject(result.error);
} else {
resolve(result.response);
}
};
this.worker.addEventListener("message", listener);
});
};
}
};
function workerHandler(publicInterface) {
return function (msg) {
const { id, method, args } = msg.data;
try {
const response = publicInterface[method].apply(undefined, args);
if (response instanceof Promise) {
response.then(val => self.postMessage({ id, response: val }),
// Error can't be sent via postMessage, so be sure to
// convert to string.
err => self.postMessage({ id, error: err.toString() }));
} else {
self.postMessage({ id, response });
}
} catch (error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
self.postMessage({ id, error: error.toString() });
}
};
}
function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
let streamingWorker = (() => {
var _ref = _asyncToGenerator(function* (id, tasks) {
let isWorking = true;
const intervalId = setTimeout(function () {
isWorking = false;
}, timeout);
const results = [];
while (tasks.length !== 0 && isWorking) {
const { callback, context, args } = tasks.shift();
const result = yield callback.call(context, args);
results.push(result);
}
worker.postMessage({ id, status: "pending", data: results });
clearInterval(intervalId);
if (tasks.length !== 0) {
yield streamingWorker(id, tasks);
}
});
return function streamingWorker(_x, _x2) {
return _ref.apply(this, arguments);
};
})();
return (() => {
var _ref2 = _asyncToGenerator(function* (msg) {
const { id, method, args } = msg.data;
const workerMethod = publicInterface[method];
if (!workerMethod) {
console.error(`Could not find ${method} defined in worker.`);
}
worker.postMessage({ id, status: "start" });
try {
const tasks = workerMethod(args);
yield streamingWorker(id, tasks);
worker.postMessage({ id, status: "done" });
} catch (error) {
worker.postMessage({ id, status: "error", error });
}
});
return function (_x3) {
return _ref2.apply(this, arguments);
};
})();
}
module.exports = {
WorkerDispatcher,
workerHandler,
streamingWorkerHandler
};
/***/ }),
/***/ 1630:
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
"use strict"; "use strict";
@ -93,19 +282,14 @@ var _prettyFast = __webpack_require__(802);
var _prettyFast2 = _interopRequireDefault(_prettyFast); var _prettyFast2 = _interopRequireDefault(_prettyFast);
var _devtoolsUtils = __webpack_require__(900); var _devtoolsUtils = __webpack_require__(1363);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var workerHandler = _devtoolsUtils.workerUtils.workerHandler; const { workerHandler } = _devtoolsUtils.workerUtils;
function prettyPrint({ url, indent, source }) {
function prettyPrint(_ref) { const prettified = (0, _prettyFast2.default)(source, {
var url = _ref.url,
indent = _ref.indent,
source = _ref.source;
var prettified = (0, _prettyFast2.default)(source, {
url: url, url: url,
indent: " ".repeat(indent) indent: " ".repeat(indent)
}); });
@ -118,7 +302,7 @@ function prettyPrint(_ref) {
function invertMappings(mappings) { function invertMappings(mappings) {
return mappings._array.map(m => { return mappings._array.map(m => {
var mapping = { const mapping = {
generated: { generated: {
line: m.originalLine, line: m.originalLine,
column: m.originalColumn column: m.originalColumn
@ -7411,184 +7595,6 @@ SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSou
exports.SourceNode = SourceNode; exports.SourceNode = SourceNode;
/***/ }),
/***/ 900:
/***/ (function(module, exports, __webpack_require__) {
/* 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 networkRequest = __webpack_require__(901);
const workerUtils = __webpack_require__(902);
module.exports = {
networkRequest,
workerUtils
};
/***/ }),
/***/ 901:
/***/ (function(module, exports) {
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function networkRequest(url, opts) {
return fetch(url, {
cache: opts.loadFromCache ? "default" : "no-cache"
}).then(res => {
if (res.status >= 200 && res.status < 300) {
return res.text().then(text => ({ content: text }));
}
return Promise.reject(`request failed with status ${res.status}`);
});
}
module.exports = networkRequest;
/***/ }),
/***/ 902:
/***/ (function(module, exports) {
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function WorkerDispatcher() {
this.msgId = 1;
this.worker = null;
} /* 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/. */
WorkerDispatcher.prototype = {
start(url) {
this.worker = new Worker(url);
this.worker.onerror = () => {
console.error(`Error in worker ${url}`);
};
},
stop() {
if (!this.worker) {
return;
}
this.worker.terminate();
this.worker = null;
},
task(method) {
return (...args) => {
return new Promise((resolve, reject) => {
const id = this.msgId++;
this.worker.postMessage({ id, method, args });
const listener = ({ data: result }) => {
if (result.id !== id) {
return;
}
if (!this.worker) {
reject("Oops, The worker has shutdown!");
return;
}
this.worker.removeEventListener("message", listener);
if (result.error) {
reject(result.error);
} else {
resolve(result.response);
}
};
this.worker.addEventListener("message", listener);
});
};
}
};
function workerHandler(publicInterface) {
return function (msg) {
const { id, method, args } = msg.data;
try {
const response = publicInterface[method].apply(undefined, args);
if (response instanceof Promise) {
response.then(val => self.postMessage({ id, response: val }),
// Error can't be sent via postMessage, so be sure to
// convert to string.
err => self.postMessage({ id, error: err.toString() }));
} else {
self.postMessage({ id, response });
}
} catch (error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
self.postMessage({ id, error: error.toString() });
}
};
}
function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
let streamingWorker = (() => {
var _ref = _asyncToGenerator(function* (id, tasks) {
let isWorking = true;
const intervalId = setTimeout(function () {
isWorking = false;
}, timeout);
const results = [];
while (tasks.length !== 0 && isWorking) {
const { callback, context, args } = tasks.shift();
const result = yield callback.call(context, args);
results.push(result);
}
worker.postMessage({ id, status: "pending", data: results });
clearInterval(intervalId);
if (tasks.length !== 0) {
yield streamingWorker(id, tasks);
}
});
return function streamingWorker(_x, _x2) {
return _ref.apply(this, arguments);
};
})();
return (() => {
var _ref2 = _asyncToGenerator(function* (msg) {
const { id, method, args } = msg.data;
const workerMethod = publicInterface[method];
if (!workerMethod) {
console.error(`Could not find ${method} defined in worker.`);
}
worker.postMessage({ id, status: "start" });
try {
const tasks = workerMethod(args);
yield streamingWorker(id, tasks);
worker.postMessage({ id, status: "done" });
} catch (error) {
worker.postMessage({ id, status: "error", error });
}
});
return function (_x3) {
return _ref2.apply(this, arguments);
};
})();
}
module.exports = {
WorkerDispatcher,
workerHandler,
streamingWorkerHandler
};
/***/ }) /***/ })
/******/ }); /******/ });

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

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

@ -109,5 +109,5 @@ skip-if = true # Bug 1393121, 1393299
[browser_dbg-tabs.js] [browser_dbg-tabs.js]
[browser_dbg-toggling-tools.js] [browser_dbg-toggling-tools.js]
[browser_dbg-wasm-sourcemaps.js] [browser_dbg-wasm-sourcemaps.js]
skip-if = true skip-if = asan
[browser_dbg-reload.js] [browser_dbg-reload.js]

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

@ -39,21 +39,21 @@ add_task(async function() {
const dbg = await initDebugger("doc-scripts.html"); const dbg = await initDebugger("doc-scripts.html");
await selectSource(dbg, "simple2"); await selectSource(dbg, "simple2");
dump('Adding a conditional Breakpoint\n') dump("Adding a conditional Breakpoint\n");
await setConditionalBreakpoint(dbg, 5, "1"); await setConditionalBreakpoint(dbg, 5, "1");
await waitForDispatch(dbg, "ADD_BREAKPOINT"); await waitForDispatch(dbg, "ADD_BREAKPOINT");
let bp = findBreakpoint(dbg, "simple2", 5); let bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition"); is(bp.condition, "1", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true); assertEditorBreakpoint(dbg, 5, true);
dump('Editing a conditional breakpoint\n') dump("Editing a conditional breakpoint\n");
await setConditionalBreakpoint(dbg, 5, "2"); await setConditionalBreakpoint(dbg, 5, "2");
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION"); await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
bp = findBreakpoint(dbg, "simple2", 5); bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "12", "breakpoint is created with the condition"); is(bp.condition, "12", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true); assertEditorBreakpoint(dbg, 5, true);
dump("Removing a conditional breakpoint\n") dump("Removing a conditional breakpoint\n");
clickElement(dbg, "gutter", 5); clickElement(dbg, "gutter", 5);
await waitForDispatch(dbg, "REMOVE_BREAKPOINT"); await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
bp = findBreakpoint(dbg, "simple2", 5); bp = findBreakpoint(dbg, "simple2", 5);

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

@ -9,7 +9,9 @@
* Tests that the debugger is succesfully loaded in the Browser Content Toolbox. * Tests that the debugger is succesfully loaded in the Browser Content Toolbox.
*/ */
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser"); const {
gDevToolsBrowser
} = require("devtools/client/framework/devtools-browser");
function toggleBreakpoint(dbg, index) { function toggleBreakpoint(dbg, index) {
const bp = findElement(dbg, "breakpointItem", index); const bp = findElement(dbg, "breakpointItem", index);

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

@ -0,0 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This if the debugger's layout is correctly modified when the toolbox's
* host changes.
*/
"use strict";
var gDefaultHostType = Services.prefs.getCharPref("devtools.toolbox.host");
add_task(async function() {
// test is too slow on some platforms due to the number of test cases
requestLongerTimeout(2);
const dbg = await initDebugger("doc-iframes.html");
const layouts = [
["horizontal", "bottom"],
["vertical", "side"],
["horizontal", "window:big"],
["vertical", "window:small"]
];
for (let layout of layouts) {
const [orientation, host] = layout;
await testLayout(dbg, orientation, host);
}
ok(true, "Orientations are correct");
});
async function testLayout(dbg, orientation, host) {
const { panel, toolbox } = dbg;
info(`Switching to ${host} ${orientation}.`);
await switchHost(dbg, host);
await resizeToolboxWindow(dbg, host);
return waitForState(
dbg,
state => dbg.selectors.getOrientation(state) == orientation
);
}
function getHost(host) {
if (host.indexOf("window") == 0) {
return "window";
}
return host;
}
async function switchHost(dbg, hostType) {
const { toolbox } = dbg;
await toolbox.switchHost(getHost(hostType));
}
function resizeToolboxWindow(dbg, host) {
const { panel, toolbox } = dbg;
let sizeOption = host.split(":")[1];
let win = toolbox.win.parent;
let breakpoint = 700;
if (sizeOption == "big" && win.outerWidth <= breakpoint) {
return resizeWindow(dbg, breakpoint + 300);
} else if (sizeOption == "small" && win.outerWidth >= breakpoint) {
return resizeWindow(dbg, breakpoint - 300);
}
}
function resizeWindow(dbg, width) {
const { panel, toolbox } = dbg;
let win = toolbox.win.parent;
const currentWidth = win.screen.width;
win.resizeTo(width, window.screen.availHeight);
}
registerCleanupFunction(function() {
Services.prefs.setCharPref("devtools.toolbox.host", gDefaultHostType);
gDefaultHostType = null;
});

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

@ -7,6 +7,10 @@
add_task(async function() { add_task(async function() {
const dbg = await initDebugger("doc-wasm-sourcemaps.html"); const dbg = await initDebugger("doc-wasm-sourcemaps.html");
// NOTE: wait for page load -- attempt to fight the intermittent failure:
// "A promise chain failed to handle a rejection: Debugger.Frame is not live"
await waitForSource(dbg, "doc-wasm-sourcemaps");
await reload(dbg); await reload(dbg);
await waitForPaused(dbg); await waitForPaused(dbg);
assertPausedLocation(dbg); assertPausedLocation(dbg);

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

@ -362,11 +362,11 @@ function createDebuggerContext(toolbox) {
store: store, store: store,
client: client, client: client,
toolbox: toolbox, toolbox: toolbox,
win: win win: win,
panel: panel
}; };
} }
/** /**
* Clear all the debugger related preferences. * Clear all the debugger related preferences.
*/ */
@ -511,7 +511,7 @@ function stepOut(dbg) {
function resume(dbg) { function resume(dbg) {
info("Resuming"); info("Resuming");
dbg.actions.resume(); dbg.actions.resume();
return waitForState(dbg, (state) => !dbg.selectors.isPaused(state)); return waitForState(dbg, state => !dbg.selectors.isPaused(state));
} }
function deleteExpression(dbg, input) { function deleteExpression(dbg, input) {

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

@ -299,3 +299,5 @@ devtools.jar:
# Debugger # Debugger
skin/images/debugger/arrow.svg (themes/images/debugger/arrow.svg) skin/images/debugger/arrow.svg (themes/images/debugger/arrow.svg)
skin/images/debugger/blackBox.svg (themes/images/debugger/blackBox.svg)
skin/images/debugger/prettyPrint.svg (themes/images/debugger/prettyPrint.svg)

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

@ -24,6 +24,11 @@ copySource.accesskey=y
copySourceUri2=Copy source URI copySourceUri2=Copy source URI
copySourceUri2.accesskey=u copySourceUri2.accesskey=u
# LOCALIZATION NOTE (setDirectoryRoot): This is the text that appears in the
# context menu to set a directory as root directory
setDirectoryRoot.label=Set directory root
setDirectoryRoot.accesskey=r
# LOCALIZATION NOTE (copyFunction): This is the text that appears in the # LOCALIZATION NOTE (copyFunction): This is the text that appears in the
# context menu to copy the function the user selected # context menu to copy the function the user selected
copyFunction.label=Copy function copyFunction.label=Copy function
@ -367,6 +372,7 @@ editor.addBreakpoint=Add breakpoint
# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item # LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item
# for disabling a breakpoint on a line. # for disabling a breakpoint on a line.
editor.disableBreakpoint=Disable breakpoint editor.disableBreakpoint=Disable breakpoint
editor.disableBreakpoint.accesskey=D
# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item # LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item
# for enabling a breakpoint on a line. # for enabling a breakpoint on a line.
@ -381,8 +387,9 @@ editor.removeBreakpoint=Remove breakpoint
editor.editBreakpoint=Edit breakpoint editor.editBreakpoint=Edit breakpoint
# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context # LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context
# menu item for adding a breakpoint condition on a line. # menu item for adding/editing a breakpoint condition on a line.
editor.addConditionalBreakpoint=Add conditional breakpoint editor.addConditionalBreakpoint=Add/Edit conditional breakpoint
editor.addConditionalBreakpoint.accesskey=c
# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for # LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for
# input element inside ConditionalPanel component # input element inside ConditionalPanel component
@ -395,6 +402,7 @@ editor.conditionalPanel.close=Cancel edit breakpoint and close
# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item # LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
# for navigating to a source mapped location # for navigating to a source mapped location
editor.jumpToMappedLocation1=Jump to %S location editor.jumpToMappedLocation1=Jump to %S location
editor.jumpToMappedLocation1.accesskey=m
# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the # LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
# context menu to disable framework grouping. # context menu to disable framework grouping.
@ -415,6 +423,7 @@ original=original
# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression # LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
# input element # input element
expressions.placeholder=Add watch expression expressions.placeholder=Add watch expression
expressions.placeholder.accesskey=e
# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item # LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item
# for closing the selected tab below the mouse. # for closing the selected tab below the mouse.
@ -468,10 +477,6 @@ sourceFooter.codeCoverage=Code coverage
# for close tab button in source tabs. # for close tab button in source tabs.
sourceTabs.closeTabButtonTooltip=Close tab sourceTabs.closeTabButtonTooltip=Close tab
# LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for
# new tab button in source tabs.
sourceTabs.newTabButtonTooltip=Search for sources (%S)
# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header. # LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.
scopes.header=Scopes scopes.header=Scopes
@ -754,6 +759,7 @@ anonymous=(anonymous)
# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing # LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing
# keyboard shortcut action for toggling breakpoint # keyboard shortcut action for toggling breakpoint
shortcuts.toggleBreakpoint=Toggle Breakpoint shortcuts.toggleBreakpoint=Toggle Breakpoint
shortcuts.toggleBreakpoint.accesskey=B
# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing # LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing
# keyboard shortcut action for toggling conditional panel keyboard # keyboard shortcut action for toggling conditional panel keyboard

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

@ -37,5 +37,10 @@ pref("devtools.debugger.file-search-case-sensitive", false);
pref("devtools.debugger.file-search-whole-word", false); pref("devtools.debugger.file-search-whole-word", false);
pref("devtools.debugger.file-search-regex-match", false); pref("devtools.debugger.file-search-regex-match", false);
pref("devtools.debugger.features.async-stepping", true); pref("devtools.debugger.features.async-stepping", true);
pref("devtools.debugger.features.project-text-search", true); pref("devtools.debugger.features.project-text-search", true);
pref("devtools.debugger.features.wasm", true); pref("devtools.debugger.features.wasm", true);
pref("devtools.debugger.features.shortcuts", true);
pref("devtools.debugger.project-directory-root", "");
pref("devtools.debugger.features.root", false);
pref("devtools.debugger.features.column-breakpoints", false);

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

@ -0,0 +1,9 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill-rule="evenodd">
<circle cx="8" cy="8.5" r="1.5"/>
<path d="M15.498 8.28l-.001-.03v-.002-.004l-.002-.018-.004-.031c0-.002 0-.002 0 0l-.004-.035.006.082c-.037-.296-.133-.501-.28-.661-.4-.522-.915-1.042-1.562-1.604-1.36-1.182-2.74-1.975-4.178-2.309a6.544 6.544 0 0 0-2.755-.042c-.78.153-1.565.462-2.369.91C3.252 5.147 2.207 6 1.252 7.035c-.216.233-.36.398-.499.577-.338.437-.338 1 0 1.437.428.552.941 1.072 1.59 1.635 1.359 1.181 2.739 1.975 4.177 2.308.907.21 1.829.223 2.756.043.78-.153 1.564-.462 2.369-.91 1.097-.612 2.141-1.464 3.097-2.499.217-.235.36-.398.498-.578.12-.128.216-.334.248-.554 0 .01 0 .01-.008.04l.013-.079-.001.011.003-.031.001-.017v.005l.001-.02v.008l.002-.03.001-.05-.001-.044v-.004-.004zm-.954.045v.007l.001.004V8.33v.012l-.001.01v-.005-.005l.002-.015-.001.008c-.002.014-.002.014 0 0l-.007.084c.003-.057-.004-.041-.014-.031-.143.182-.27.327-.468.543-.89.963-1.856 1.752-2.86 2.311-.724.404-1.419.677-2.095.81a5.63 5.63 0 0 1-2.374-.036c-1.273-.295-2.523-1.014-3.774-2.101-.604-.525-1.075-1.001-1.457-1.496-.054-.07-.054-.107 0-.177.117-.152.244-.298.442-.512.89-.963 1.856-1.752 2.86-2.311.724-.404 1.419-.678 2.095-.81a5.631 5.631 0 0 1 2.374.036c1.272.295 2.523 1.014 3.774 2.101.603.524 1.074 1 1.457 1.496.035.041.043.057.046.076 0 .01 0 .01.008.043l-.009-.047.003.02-.002-.013v-.008.016c0-.004 0-.004 0 0v-.004z"/>
</g>
</svg>

После

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

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

@ -0,0 +1,6 @@
<!-- 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/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M4.525 13.21h-.472c-.574 0-.987-.154-1.24-.463-.253-.31-.38-.882-.38-1.719v-.573c0-.746-.097-1.265-.292-1.557-.196-.293-.51-.44-.945-.44v-.974c.435 0 .75-.146.945-.44.195-.292.293-.811.293-1.556v-.58c0-.833.126-1.404.379-1.712.253-.31.666-.464 1.24-.464h.472v.783h-.179c-.37 0-.628.08-.774.24-.145.159-.218.54-.218 1.141v.383c0 .824-.096 1.432-.287 1.823-.191.39-.516.679-.974.866.458.191.783.482.974.873.191.39.287.998.287 1.823v.382c0 .602.073.982.218 1.142.146.16.404.239.774.239h.18v.783zm9.502-4.752c-.43 0-.744.147-.942.44-.197.292-.296.811-.296 1.557v.573c0 .837-.125 1.41-.376 1.719-.251.309-.664.463-1.237.463h-.478v-.783h.185c.37 0 .628-.08.774-.24.145-.159.218-.539.218-1.14v-.383c0-.825.096-1.433.287-1.823.191-.39.516-.682.974-.873-.458-.187-.783-.476-.974-.866-.191-.391-.287-.999-.287-1.823v-.383c0-.602-.073-.982-.218-1.142-.146-.159-.404-.239-.774-.239h-.185v-.783h.478c.573 0 .986.155 1.237.464.25.308.376.88.376 1.712v.58c0 .673.088 1.174.263 1.503.176.329.5.493.975.493v.974z" fill-rule="evenodd"/>
</svg>

После

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

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

@ -196,35 +196,36 @@ DOMParser::ParseFromStream(nsIInputStream* aStream,
} }
NS_IMETHODIMP NS_IMETHODIMP
DOMParser::ParseFromStream(nsIInputStream *stream, DOMParser::ParseFromStream(nsIInputStream* aStream,
const char *charset, const char* aCharset,
int32_t contentLength, int32_t aContentLength,
const char *contentType, const char* aContentType,
nsIDOMDocument **aResult) nsIDOMDocument** aResult)
{ {
NS_ENSURE_ARG(stream); NS_ENSURE_ARG(aStream);
NS_ENSURE_ARG(contentType); NS_ENSURE_ARG(aContentType);
NS_ENSURE_ARG_POINTER(aResult); NS_ENSURE_ARG_POINTER(aResult);
*aResult = nullptr; *aResult = nullptr;
bool svg = nsCRT::strcmp(contentType, "image/svg+xml") == 0; bool svg = nsCRT::strcmp(aContentType, "image/svg+xml") == 0;
// For now, we can only create XML documents. // For now, we can only create XML documents.
//XXXsmaug Should we create an HTMLDocument (in XHTML mode) //XXXsmaug Should we create an HTMLDocument (in XHTML mode)
// for "application/xhtml+xml"? // for "application/xhtml+xml"?
if ((nsCRT::strcmp(contentType, "text/xml") != 0) && if ((nsCRT::strcmp(aContentType, "text/xml") != 0) &&
(nsCRT::strcmp(contentType, "application/xml") != 0) && (nsCRT::strcmp(aContentType, "application/xml") != 0) &&
(nsCRT::strcmp(contentType, "application/xhtml+xml") != 0) && (nsCRT::strcmp(aContentType, "application/xhtml+xml") != 0) &&
!svg) !svg)
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv; nsresult rv;
// Put the nsCOMPtr out here so we hold a ref to the stream as needed // Put the nsCOMPtr out here so we hold a ref to the stream as needed
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> stream = aStream;
if (!NS_InputStreamIsBuffered(stream)) { if (!NS_InputStreamIsBuffered(stream)) {
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, nsCOMPtr<nsIInputStream> bufferedStream;
4096); rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
stream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
stream = bufferedStream; stream = bufferedStream;
@ -243,11 +244,11 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
mPrincipal, mPrincipal,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL, nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_OTHER, nsIContentPolicy::TYPE_OTHER,
nsDependentCString(contentType)); nsDependentCString(aContentType));
NS_ENSURE_STATE(parserChannel); NS_ENSURE_STATE(parserChannel);
if (charset) { if (aCharset) {
parserChannel->SetContentCharset(nsDependentCString(charset)); parserChannel->SetContentCharset(nsDependentCString(aCharset));
} }
// Tell the document to start loading // Tell the document to start loading
@ -284,7 +285,7 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
rv = listener->OnDataAvailable(parserChannel, nullptr, stream, 0, rv = listener->OnDataAvailable(parserChannel, nullptr, stream, 0,
contentLength); aContentLength);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
parserChannel->Cancel(rv); parserChannel->Cancel(rv);
parserChannel->GetStatus(&status); parserChannel->GetStatus(&status);

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

@ -252,7 +252,8 @@ nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mLoading = true; mLoading = true;
rv = nsSyncLoadService::PushSyncStreamToListener(in, aListener, mChannel); rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), aListener,
mChannel);
mLoading = false; mLoading = false;
return rv; return rv;
@ -338,14 +339,16 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI,
/* static */ /* static */
nsresult nsresult
nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn, nsSyncLoadService::PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
nsIStreamListener* aListener, nsIStreamListener* aListener,
nsIChannel* aChannel) nsIChannel* aChannel)
{ {
nsCOMPtr<nsIInputStream> in = Move(aIn);
// Set up buffering stream // Set up buffering stream
nsresult rv; nsresult rv;
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> bufferedStream;
if (!NS_InputStreamIsBuffered(aIn)) { if (!NS_InputStreamIsBuffered(in)) {
int64_t chunkSize; int64_t chunkSize;
rv = aChannel->GetContentLength(&chunkSize); rv = aChannel->GetContentLength(&chunkSize);
if (NS_FAILED(rv) || chunkSize < 1) { if (NS_FAILED(rv) || chunkSize < 1) {
@ -353,11 +356,11 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
} }
chunkSize = std::min(int64_t(UINT16_MAX), chunkSize); chunkSize = std::min(int64_t(UINT16_MAX), chunkSize);
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn, rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
chunkSize); in.forget(), chunkSize);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
aIn = bufferedStream; in = bufferedStream;
} }
// Load // Load
@ -366,7 +369,7 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
uint64_t sourceOffset = 0; uint64_t sourceOffset = 0;
while (1) { while (1) {
uint64_t readCount = 0; uint64_t readCount = 0;
rv = aIn->Available(&readCount); rv = in->Available(&readCount);
if (NS_FAILED(rv) || !readCount) { if (NS_FAILED(rv) || !readCount) {
if (rv == NS_BASE_STREAM_CLOSED) { if (rv == NS_BASE_STREAM_CLOSED) {
// End of file, but not an error // End of file, but not an error
@ -378,7 +381,7 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
if (readCount > UINT32_MAX) if (readCount > UINT32_MAX)
readCount = UINT32_MAX; readCount = UINT32_MAX;
rv = aListener->OnDataAvailable(aChannel, nullptr, aIn, rv = aListener->OnDataAvailable(aChannel, nullptr, in,
(uint32_t)std::min(sourceOffset, (uint64_t)UINT32_MAX), (uint32_t)std::min(sourceOffset, (uint64_t)UINT32_MAX),
(uint32_t)readCount); (uint32_t)readCount);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

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

@ -51,13 +51,13 @@ public:
/** /**
* Read input stream aIn in chunks and deliver synchronously to aListener. * Read input stream aIn in chunks and deliver synchronously to aListener.
* *
* @param aIn The stream to be read. * @param aIn The stream to be read. The ownership of this stream is taken.
* @param aListener The listener that will receive * @param aListener The listener that will receive
* OnStartRequest/OnDataAvailable/OnStopRequest * OnStartRequest/OnDataAvailable/OnStopRequest
* notifications. * notifications.
* @param aChannel The channel that aIn was opened from. * @param aChannel The channel that aIn was opened from.
*/ */
static nsresult PushSyncStreamToListener(nsIInputStream* aIn, static nsresult PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
nsIStreamListener* aListener, nsIStreamListener* aListener,
nsIChannel* aChannel); nsIChannel* aChannel);
}; };

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

@ -2122,7 +2122,17 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
rv = state->GetIsNull(6, &nullPadding); rv = state->GetIsNull(6, &nullPadding);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
#ifdef NIGHTLY_BUILD
bool shouldUpdateTo26 = false;
if (nullPadding && aSavedResponseOut->mValue.type() == ResponseType::Opaque) {
// XXXtt: This should be removed in the future (e.g. Nightly 58) by
// bug 1398167.
shouldUpdateTo26 = true;
aSavedResponseOut->mValue.paddingSize() = 0;
} else if (nullPadding) {
#else
if (nullPadding) { if (nullPadding) {
#endif // NIGHTLY_BUILD
MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() != MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() !=
ResponseType::Opaque); ResponseType::Opaque);
aSavedResponseOut->mValue.paddingSize() = aSavedResponseOut->mValue.paddingSize() =
@ -2141,6 +2151,20 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo()); rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
#ifdef NIGHTLY_BUILD
if (shouldUpdateTo26) {
// XXXtt: This is a quick fix for not updating properly in Nightly 57.
// Note: This should be removed in the future (e.g. Nightly 58) by
// bug 1398167.
rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"UPDATE entries SET response_padding_size = 0 "
"WHERE response_type = 4 " // opaque response
"AND response_padding_size IS NULL"
));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
}
#endif // NIGHTLY_BUILD
rv = aConn->CreateStatement(NS_LITERAL_CSTRING( rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT " "SELECT "
"name, " "name, "

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

@ -737,7 +737,8 @@ LockedDirectoryPaddingGet(nsIFile* aBaseDir, int64_t* aPaddingSizeOut)
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512); rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream.forget(),
512);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsCOMPtr<nsIObjectInputStream> objectStream = nsCOMPtr<nsIObjectInputStream> objectStream =

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

@ -31,17 +31,8 @@ namespace dom {
* that add and remove fake gamepads, avoiding the platform-specific backends. * that add and remove fake gamepads, avoiding the platform-specific backends.
*/ */
NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest) NS_IMPL_CYCLE_COLLECTION_INHERITED(GamepadServiceTest, DOMEventTargetHelper,
mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GamepadServiceTest,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GamepadServiceTest,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadServiceTest) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadServiceTest)
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback) NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)

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

@ -529,7 +529,7 @@ FSMultipartFormData::AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob)
// Create buffered stream (for efficiency) // Create buffered stream (for efficiency)
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
fileStream, 8192); fileStream.forget(), 8192);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
fileStream = bufferedStream; fileStream = bufferedStream;

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

@ -766,21 +766,11 @@ HTMLContentSink::~HTMLContentSink()
delete mHeadContext; delete mHeadContext;
} }
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLContentSink) NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLContentSink, nsContentSink,
mHTMLDocument,
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLContentSink, nsContentSink) mRoot,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHTMLDocument) mBody,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot) mHead)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBody)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHead)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLContentSink,
nsContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHTMLDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBody)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHead)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLContentSink, NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLContentSink,
nsContentSink, nsContentSink,

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

@ -186,16 +186,13 @@ interface nsIServiceWorkerManager : nsISupports
// Testing // Testing
DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath); DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath);
// Note: This is meant to be used only by about:serviceworkers.
// It returns an array of nsIServiceWorkerRegistrationInfos. // It returns an array of nsIServiceWorkerRegistrationInfos.
nsIArray getAllRegistrations(); nsIArray getAllRegistrations();
// Note: This is meant to be used only by about:serviceworkers.
// It calls softUpdate() for each child process. // It calls softUpdate() for each child process.
[implicit_jscontext] void propagateSoftUpdate(in jsval aOriginAttributes, [implicit_jscontext] void propagateSoftUpdate(in jsval aOriginAttributes,
in DOMString aScope); in DOMString aScope);
// Note: This is meant to be used only by about:serviceworkers.
// It calls unregister() in each child process. The callback is used to // It calls unregister() in each child process. The callback is used to
// inform when unregister() is completed on the current process. // inform when unregister() is completed on the current process.
void propagateUnregister(in nsIPrincipal aPrincipal, void propagateUnregister(in nsIPrincipal aPrincipal,

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

@ -29,9 +29,11 @@ public:
{ {
} }
void Reset() void RetrieveDataFrom(CoalescedInputData& aSource)
{ {
mCoalescedInputEvent = nullptr; mCoalescedInputEvent = Move(aSource.mCoalescedInputEvent);
mGuid = aSource.mGuid;
mInputBlockId = aSource.mInputBlockId;
} }
bool IsEmpty() bool IsEmpty()
@ -43,9 +45,9 @@ public:
const ScrollableLayerGuid& aGuid, const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId); const uint64_t& aInputBlockId);
const InputEventType* GetCoalescedEvent() UniquePtr<InputEventType> TakeCoalescedEvent()
{ {
return mCoalescedInputEvent.get(); return Move(mCoalescedInputEvent);
} }
ScrollableLayerGuid GetScrollableLayerGuid() ScrollableLayerGuid GetScrollableLayerGuid()

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

@ -55,8 +55,8 @@ void
CoalescedMouseMoveFlusher::WillRefresh(mozilla::TimeStamp aTime) CoalescedMouseMoveFlusher::WillRefresh(mozilla::TimeStamp aTime)
{ {
MOZ_ASSERT(mRefreshDriver); MOZ_ASSERT(mRefreshDriver);
mTabChild->MaybeDispatchCoalescedMouseMoveEvents(); mTabChild->FlushAllCoalescedMouseData();
RemoveObserver(); mTabChild->ProcessPendingCoalescedMouseDataAndDispatchEvents();
} }
void void

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

@ -1059,6 +1059,15 @@ TabChild::DestroyWindow()
mCoalescedMouseEventFlusher->RemoveObserver(); mCoalescedMouseEventFlusher->RemoveObserver();
mCoalescedMouseEventFlusher = nullptr; mCoalescedMouseEventFlusher = nullptr;
} }
// In case we don't have chance to process all entries, clean all data in
// the queue.
while (mToBeDispatchedMouseData.GetSize() > 0) {
UniquePtr<CoalescedMouseData> data(
static_cast<CoalescedMouseData*>(mToBeDispatchedMouseData.PopFront()));
data.reset();
}
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation()); nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
if (baseWindow) if (baseWindow)
baseWindow->Destroy(); baseWindow->Destroy();
@ -1591,28 +1600,62 @@ TabChild::RecvMouseEvent(const nsString& aType,
} }
void void
TabChild::MaybeDispatchCoalescedMouseMoveEvents() TabChild::ProcessPendingCoalescedMouseDataAndDispatchEvents()
{ {
if (!mCoalesceMouseMoveEvents) { if (!mCoalesceMouseMoveEvents || !mCoalescedMouseEventFlusher) {
// We don't enable mouse coalescing or we are destroying TabChild.
return; return;
} }
// We may reentry the event loop and push more data to
// mToBeDispatchedMouseData while dispatching an event.
// We may have some pending coalesced data while dispatch an event and reentry
// the event loop. In that case we don't have chance to consume the remainding
// pending data until we get new mouse events. Get some helps from
// mCoalescedMouseEventFlusher to trigger it.
mCoalescedMouseEventFlusher->StartObserver();
while (mToBeDispatchedMouseData.GetSize() > 0) {
UniquePtr<CoalescedMouseData> data(
static_cast<CoalescedMouseData*>(mToBeDispatchedMouseData.PopFront()));
UniquePtr<WidgetMouseEvent> event = data->TakeCoalescedEvent();
if (event) {
// Dispatch the pending events. Using HandleRealMouseButtonEvent
// to bypass the coalesce handling in RecvRealMouseMoveEvent. Can't use
// RecvRealMouseButtonEvent because we may also put some mouse events
// other than mousemove.
HandleRealMouseButtonEvent(*event,
data->GetScrollableLayerGuid(),
data->GetInputBlockId());
}
}
// mCoalescedMouseEventFlusher may be destroyed when reentrying the event
// loop.
if (mCoalescedMouseEventFlusher) {
mCoalescedMouseEventFlusher->RemoveObserver();
}
}
void
TabChild::FlushAllCoalescedMouseData()
{
MOZ_ASSERT(mCoalesceMouseMoveEvents);
// Move all entries from mCoalescedMouseData to mToBeDispatchedMouseData.
for (auto iter = mCoalescedMouseData.Iter(); !iter.Done(); iter.Next()) { for (auto iter = mCoalescedMouseData.Iter(); !iter.Done(); iter.Next()) {
CoalescedMouseData* data = iter.UserData(); CoalescedMouseData* data = iter.UserData();
if (!data || data->IsEmpty()) { if (!data || data->IsEmpty()) {
continue; continue;
} }
const WidgetMouseEvent* event = data->GetCoalescedEvent(); UniquePtr<CoalescedMouseData> dispatchData =
MOZ_ASSERT(event); MakeUnique<CoalescedMouseData>();
// Dispatch the coalesced mousemove event. Using RecvRealMouseButtonEvent to
// bypass the coalesce handling in RecvRealMouseMoveEvent. dispatchData->RetrieveDataFrom(*data);
RecvRealMouseButtonEvent(*event, mToBeDispatchedMouseData.Push(dispatchData.release());
data->GetScrollableLayerGuid(),
data->GetInputBlockId());
data->Reset();
}
if (mCoalescedMouseEventFlusher) {
mCoalescedMouseEventFlusher->RemoveObserver();
} }
mCoalescedMouseData.Clear();
} }
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
@ -1632,10 +1675,23 @@ TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& aEvent,
mCoalescedMouseEventFlusher->StartObserver(); mCoalescedMouseEventFlusher->StartObserver();
return IPC_OK(); return IPC_OK();
} }
// Can't coalesce current mousemove event. Dispatch the coalesced mousemove // Can't coalesce current mousemove event. Put the coalesced mousemove data
// event and coalesce the current one. // with the same pointer id to mToBeDispatchedMouseData, coalesce the
MaybeDispatchCoalescedMouseMoveEvents(); // current one, and process all pending data in mToBeDispatchedMouseData.
data->Coalesce(aEvent, aGuid, aInputBlockId); MOZ_ASSERT(data);
UniquePtr<CoalescedMouseData> dispatchData =
MakeUnique<CoalescedMouseData>();
dispatchData->RetrieveDataFrom(*data);
mToBeDispatchedMouseData.Push(dispatchData.release());
// Put new data to replace the old one in the hash table.
CoalescedMouseData* newData = new CoalescedMouseData();
mCoalescedMouseData.Put(aEvent.pointerId, newData);
newData->Coalesce(aEvent, aGuid, aInputBlockId);
// Dispatch all pending mouse events.
ProcessPendingCoalescedMouseDataAndDispatchEvents();
mCoalescedMouseEventFlusher->StartObserver(); mCoalescedMouseEventFlusher->StartObserver();
} else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) { } else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
return IPC_FAIL_NO_REASON(this); return IPC_FAIL_NO_REASON(this);
@ -1675,16 +1731,35 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid, const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) const uint64_t& aInputBlockId)
{ {
if (aEvent.mMessage != eMouseMove) { if (mCoalesceMouseMoveEvents && mCoalescedMouseEventFlusher &&
// Flush the coalesced mousemove event before dispatching other mouse aEvent.mMessage != eMouseMove) {
// events. // When receiving a mouse event other than mousemove, we have to dispatch
MaybeDispatchCoalescedMouseMoveEvents(); // all coalesced events before it. However, we can't dispatch all pending
if (aEvent.mMessage == eMouseEnterIntoWidget) { // coalesced events directly because we may reentry the event loop while
mCoalescedMouseData.Put(aEvent.pointerId, new CoalescedMouseData()); // dispatching. To make sure we won't dispatch disorder events, we move all
} else if (aEvent.mMessage == eMouseExitFromWidget) { // coalesced mousemove events and current event to a deque to dispatch them.
mCoalescedMouseData.Remove(aEvent.pointerId); // When reentrying the event loop and dispatching more events, we put new
} // events in the end of the nsQueue and dispatch events from the beginning.
FlushAllCoalescedMouseData();
UniquePtr<CoalescedMouseData> dispatchData =
MakeUnique<CoalescedMouseData>();
dispatchData->Coalesce(aEvent, aGuid, aInputBlockId);
mToBeDispatchedMouseData.Push(dispatchData.release());
ProcessPendingCoalescedMouseDataAndDispatchEvents();
return IPC_OK();
} }
HandleRealMouseButtonEvent(aEvent, aGuid, aInputBlockId);
return IPC_OK();
}
void
TabChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
// Mouse events like eMouseEnterIntoWidget, that are created in the parent // Mouse events like eMouseEnterIntoWidget, that are created in the parent
// process EventStateManager code, have an input block id which they get from // process EventStateManager code, have an input block id which they get from
// the InputAPZContext in the parent process stack. However, they did not // the InputAPZContext in the parent process stack. However, they did not
@ -1714,7 +1789,6 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) { if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId); mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
} }
return IPC_OK();
} }
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
@ -1779,13 +1853,12 @@ TabChild::MaybeDispatchCoalescedWheelEvent()
if (mCoalescedWheelData.IsEmpty()) { if (mCoalescedWheelData.IsEmpty()) {
return; return;
} }
const WidgetWheelEvent* wheelEvent = UniquePtr<WidgetWheelEvent> wheelEvent =
mCoalescedWheelData.GetCoalescedEvent(); mCoalescedWheelData.TakeCoalescedEvent();
MOZ_ASSERT(wheelEvent); MOZ_ASSERT(wheelEvent);
DispatchWheelEvent(*wheelEvent, DispatchWheelEvent(*wheelEvent,
mCoalescedWheelData.GetScrollableLayerGuid(), mCoalescedWheelData.GetScrollableLayerGuid(),
mCoalescedWheelData.GetInputBlockId()); mCoalescedWheelData.GetInputBlockId());
mCoalescedWheelData.Reset();
} }
void void

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

@ -41,6 +41,7 @@
#include "AudioChannelService.h" #include "AudioChannelService.h"
#include "PuppetWidget.h" #include "PuppetWidget.h"
#include "mozilla/layers/GeckoContentController.h" #include "mozilla/layers/GeckoContentController.h"
#include "nsDeque.h"
#include "nsISHistoryListener.h" #include "nsISHistoryListener.h"
#include "nsIPartialSHistoryListener.h" #include "nsIPartialSHistoryListener.h"
@ -761,8 +762,17 @@ public:
return mWidgetNativeData; return mWidgetNativeData;
} }
// Prepare to dispatch all coalesced mousemove events. We'll move all data
// in mCoalescedMouseData to a nsDeque; then we start processing them. We
// can't fetch the coalesced event one by one and dispatch it because we may
// reentry the event loop and access to the same hashtable. It's called when
// dispatching some mouse events other than mousemove.
void FlushAllCoalescedMouseData();
void ProcessPendingCoalescedMouseDataAndDispatchEvents();
void MaybeDispatchCoalescedMouseMoveEvents(); void HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
static bool HasActiveTabs() static bool HasActiveTabs()
{ {
@ -948,7 +958,12 @@ private:
// takes time, some repeated events can be skipped to not flood child process. // takes time, some repeated events can be skipped to not flood child process.
mozilla::TimeStamp mLastWheelProcessedTimeFromParent; mozilla::TimeStamp mLastWheelProcessedTimeFromParent;
mozilla::TimeDuration mLastWheelProcessingDuration; mozilla::TimeDuration mLastWheelProcessingDuration;
// Hash table to track coalesced mousemove events for different pointers.
nsClassHashtable<nsUint32HashKey, CoalescedMouseData> mCoalescedMouseData; nsClassHashtable<nsUint32HashKey, CoalescedMouseData> mCoalescedMouseData;
nsDeque mToBeDispatchedMouseData;
CoalescedWheelData mCoalescedWheelData; CoalescedWheelData mCoalescedWheelData;
RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher; RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher;

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

@ -2,7 +2,6 @@
skip-if = os == 'android' skip-if = os == 'android'
support-files = support-files =
process_error.xul process_error.xul
process_error_contentscript.js
[test_process_error.xul] [test_process_error.xul]
skip-if = !crashreporter skip-if = !crashreporter

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

@ -7,6 +7,7 @@
<browser id="thebrowser" type="content" remote="true" /> <browser id="thebrowser" type="content" remote="true" />
<script type="application/javascript"><![CDATA[ <script type="application/javascript"><![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://testing-common/BrowserTestUtils.jsm");
const ok = window.opener.wrappedJSObject.ok; const ok = window.opener.wrappedJSObject.ok;
const is = window.opener.wrappedJSObject.is; const is = window.opener.wrappedJSObject.is;
@ -18,24 +19,19 @@
ok(subject instanceof Components.interfaces.nsIPropertyBag2, ok(subject instanceof Components.interfaces.nsIPropertyBag2,
'Subject implements nsIPropertyBag2.'); 'Subject implements nsIPropertyBag2.');
var waitCrash = Promise.resolve();
var dumpID; var dumpID;
if ('nsICrashReporter' in Components.interfaces) { if ('nsICrashReporter' in Components.interfaces) {
dumpID = subject.getPropertyAsAString('dumpID'); dumpID = subject.getPropertyAsAString('dumpID');
ok(dumpID, "dumpID is present and not an empty string"); ok(dumpID, "dumpID is present and not an empty string");
waitCrash = Services.crashmanager.ensureCrashIsPresent(dumpID);
} }
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown'); Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
waitCrash.then(done); done();
} }
Services.obs.addObserver(crashObserver, 'ipc:content-shutdown'); Services.obs.addObserver(crashObserver, 'ipc:content-shutdown');
document.getElementById('thebrowser') BrowserTestUtils.crashBrowser(document.getElementById('thebrowser'));
.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
.frameLoader.messageManager
.loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true);
]]></script> ]]></script>
</window> </window>

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

@ -1,7 +0,0 @@
Components.utils.import("resource://gre/modules/ctypes.jsm");
privateNoteIntentionalCrash();
var zero = new ctypes.intptr_t(8);
var badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
var crash = badptr.contents;

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

@ -42,14 +42,10 @@ var testObserver = {
let additionalDumps = extraData.additional_minidumps.split(','); let additionalDumps = extraData.additional_minidumps.split(',');
ok(additionalDumps.indexOf('browser') >= 0, "browser in additional_minidumps"); ok(additionalDumps.indexOf('browser') >= 0, "browser in additional_minidumps");
let additionalDumpFiles = [];
for (let name of additionalDumps) { for (let name of additionalDumps) {
let file = profD.clone(); let file = profD.clone();
file.append(pluginId + "-" + name + ".dmp"); file.append(pluginId + "-" + name + ".dmp");
ok(file.exists(), "additional dump '"+name+"' exists"); ok(file.exists(), "additional dump '"+name+"' exists");
if (file.exists()) {
additionalDumpFiles.push(file);
}
} }
// check cpu usage field // check cpu usage field
@ -103,7 +99,5 @@ function onPluginCrashed(aEvent) {
getService(Ci.nsIObserverService); getService(Ci.nsIObserverService);
os.removeObserver(testObserver, "plugin-crashed"); os.removeObserver(testObserver, "plugin-crashed");
Services.crashmanager.ensureCrashIsPresent(aEvent.pluginDumpID).then(() => { SimpleTest.finish();
SimpleTest.finish();
});
} }

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

@ -19,8 +19,6 @@
</body> </body>
<script class="testbody" type="application/javascript"> <script class="testbody" type="application/javascript">
<![CDATA[ <![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm");
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
SimpleTest.expectChildProcessCrash(); SimpleTest.expectChildProcessCrash();

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

@ -15,7 +15,7 @@
</body> </body>
<script class="testbody" type="application/javascript"> <script class="testbody" type="application/javascript">
<![CDATA[ <![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/PromiseUtils.jsm");
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
SimpleTest.expectChildProcessCrash(); SimpleTest.expectChildProcessCrash();
@ -23,6 +23,8 @@ SimpleTest.expectChildProcessCrash();
var success = false; var success = false;
var observerFired = false; var observerFired = false;
var observerDeferred = PromiseUtils.defer();
var eventListenerDeferred = PromiseUtils.defer();
var testObserver = { var testObserver = {
observe: function(subject, topic, data) { observe: function(subject, topic, data) {
@ -46,6 +48,8 @@ var testObserver = {
let extraFile = profD.clone(); let extraFile = profD.clone();
extraFile.append(id + ".extra"); extraFile.append(id + ".extra");
ok(extraFile.exists(), "extra file exists"); ok(extraFile.exists(), "extra file exists");
observerDeferred.resolve();
}, },
QueryInterface: function(iid) { QueryInterface: function(iid) {
@ -84,9 +88,7 @@ function onPluginCrashed(aEvent) {
getService(Components.interfaces.nsIObserverService); getService(Components.interfaces.nsIObserverService);
os.removeObserver(testObserver, "plugin-crashed"); os.removeObserver(testObserver, "plugin-crashed");
Services.crashmanager.ensureCrashIsPresent(aEvent.pluginDumpID).then(() => { eventListenerDeferred.resolve();
SimpleTest.finish();
});
} }
function runTests() { function runTests() {
@ -101,6 +103,13 @@ function runTests() {
pluginElement.crash(); pluginElement.crash();
} catch (e) { } catch (e) {
} }
Promise.all([
observerDeferred.promise,
eventListenerDeferred.promise
]).then(() => {
SimpleTest.finish();
});
} }
]]> ]]>
</script> </script>

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

@ -19,8 +19,6 @@
</body> </body>
<script class="testbody" type="application/javascript"> <script class="testbody" type="application/javascript">
<![CDATA[ <![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm");
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
SimpleTest.expectChildProcessCrash(); SimpleTest.expectChildProcessCrash();

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

@ -2454,7 +2454,8 @@ GetBinaryInputStream(nsIFile* aDirectory,
} }
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512); rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
stream.forget(), 512);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
@ -5235,46 +5236,11 @@ QuotaManager::EnsureOriginIsInitializedInternal(
*aCreated = false; *aCreated = false;
return NS_OK; return NS_OK;
} }
} else if (!mTemporaryStorageInitialized) { } else {
rv = InitializeRepository(aPersistenceType); rv = EnsureTemporaryStorageIsInitialized();
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
// We have to cleanup partially initialized quota.
RemoveQuota();
return rv; return rv;
} }
rv = InitializeRepository(ComplementaryPersistenceType(aPersistenceType));
if (NS_WARN_IF(NS_FAILED(rv))) {
// We have to cleanup partially initialized quota.
RemoveQuota();
return rv;
}
if (gFixedLimitKB >= 0) {
mTemporaryStorageLimit = static_cast<uint64_t>(gFixedLimitKB) * 1024;
}
else {
nsCOMPtr<nsIFile> storageDir =
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = storageDir->InitWithPath(GetStoragePath());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = GetTemporaryStorageLimit(storageDir, mTemporaryStorageUsage,
&mTemporaryStorageLimit);
NS_ENSURE_SUCCESS(rv, rv);
}
mTemporaryStorageInitialized = true;
CheckTemporaryStorageLimits();
} }
bool created; bool created;
@ -5337,6 +5303,60 @@ QuotaManager::EnsureOriginIsInitializedInternal(
return NS_OK; return NS_OK;
} }
nsresult
QuotaManager::EnsureTemporaryStorageIsInitialized()
{
AssertIsOnIOThread();
MOZ_ASSERT(mStorageInitialized);
if (mTemporaryStorageInitialized) {
return NS_OK;
}
nsresult rv = InitializeRepository(PERSISTENCE_TYPE_DEFAULT);
if (NS_WARN_IF(NS_FAILED(rv))) {
// We have to cleanup partially initialized quota.
RemoveQuota();
return rv;
}
rv = InitializeRepository(PERSISTENCE_TYPE_TEMPORARY);
if (NS_WARN_IF(NS_FAILED(rv))) {
// We have to cleanup partially initialized quota.
RemoveQuota();
return rv;
}
if (gFixedLimitKB >= 0) {
mTemporaryStorageLimit = static_cast<uint64_t>(gFixedLimitKB) * 1024;
} else {
nsCOMPtr<nsIFile> storageDir =
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = storageDir->InitWithPath(GetStoragePath());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = GetTemporaryStorageLimit(storageDir, mTemporaryStorageUsage,
&mTemporaryStorageLimit);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
mTemporaryStorageInitialized = true;
CheckTemporaryStorageLimits();
return rv;
}
void void
QuotaManager::OriginClearCompleted(PersistenceType aPersistenceType, QuotaManager::OriginClearCompleted(PersistenceType aPersistenceType,
const nsACString& aOrigin) const nsACString& aOrigin)
@ -7147,14 +7167,16 @@ GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager)
nsresult rv; nsresult rv;
if (mGetGroupUsage) { if (mGetGroupUsage) {
nsCOMPtr<nsIFile> directory; // Ensure temporary storage is initialized first. It will initialize all
// origins for temporary storage including origins belonging to our group by
// traversing the repositories. EnsureStorageIsInitialized is needed before
// EnsureTemporaryStorageIsInitialized.
rv = aQuotaManager->EnsureStorageIsInitialized();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Ensure origin is initialized first. It will initialize all origins for rv = aQuotaManager->EnsureTemporaryStorageIsInitialized();
// temporary storage including origins belonging to our group.
rv = aQuotaManager->EnsureOriginIsInitialized(PERSISTENCE_TYPE_TEMPORARY,
mSuffix, mGroup,
mOriginScope.GetOrigin(),
getter_AddRefs(directory));
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }

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

@ -298,6 +298,9 @@ public:
nsIFile** aDirectory, nsIFile** aDirectory,
bool* aCreated); bool* aCreated);
nsresult
EnsureTemporaryStorageIsInitialized();
void void
OriginClearCompleted(PersistenceType aPersistenceType, OriginClearCompleted(PersistenceType aPersistenceType,
const nsACString& aOrigin); const nsACString& aOrigin);

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

@ -1491,7 +1491,8 @@ nsresult nsWebBrowserPersist::SaveChannelInternal(
getter_AddRefs(fileInputStream)); getter_AddRefs(fileInputStream));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream), rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
fileInputStream, BUFFERED_OUTPUT_SIZE); fileInputStream.forget(),
BUFFERED_OUTPUT_SIZE);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString contentType; nsAutoCString contentType;
aChannel->GetContentType(contentType); aChannel->GetContentType(contentType);

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

@ -215,7 +215,7 @@ FileReaderSync::ReadAsText(Blob& aBlob,
} }
nsCOMPtr<nsIInputStream> syncStream; nsCOMPtr<nsIInputStream> syncStream;
aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream, aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream.forget(),
getter_AddRefs(syncStream)); getter_AddRefs(syncStream));
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {
return; return;
@ -269,7 +269,8 @@ FileReaderSync::ReadAsDataURL(Blob& aBlob, nsAString& aResult,
} }
nsCOMPtr<nsIInputStream> syncStream; nsCOMPtr<nsIInputStream> syncStream;
aRv = ConvertAsyncToSyncStream(blobSize, stream, getter_AddRefs(syncStream)); aRv = ConvertAsyncToSyncStream(blobSize, stream.forget(),
getter_AddRefs(syncStream));
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {
return; return;
} }
@ -475,13 +476,15 @@ FileReaderSync::SyncRead(nsIInputStream* aStream, char* aBuffer,
nsresult nsresult
FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize, FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
nsIInputStream* aAsyncStream, already_AddRefed<nsIInputStream> aAsyncStream,
nsIInputStream** aSyncStream) nsIInputStream** aSyncStream)
{ {
nsCOMPtr<nsIInputStream> asyncInputStream = Move(aAsyncStream);
// If the stream is not async, we just need it to be bufferable. // If the stream is not async, we just need it to be bufferable.
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aAsyncStream); nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(asyncInputStream);
if (!asyncStream) { if (!asyncStream) {
return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096); return NS_NewBufferedInputStream(aSyncStream, asyncInputStream.forget(), 4096);
} }
nsAutoCString buffer; nsAutoCString buffer;
@ -491,7 +494,7 @@ FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
uint32_t read; uint32_t read;
nsresult rv = nsresult rv =
SyncRead(aAsyncStream, buffer.BeginWriting(), aStreamSize, &read); SyncRead(asyncInputStream, buffer.BeginWriting(), aStreamSize, &read);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }

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

@ -33,7 +33,7 @@ private:
nsAString &aResult); nsAString &aResult);
nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize, nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
nsIInputStream* aAsyncStream, already_AddRefed<nsIInputStream> aAsyncStream,
nsIInputStream** aSyncStream); nsIInputStream** aSyncStream);
nsresult SyncRead(nsIInputStream* aStream, char* aBuffer, nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,

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

@ -1116,7 +1116,8 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
rv = channel->Open2(getter_AddRefs(in)); rv = channel->Open2(getter_AddRefs(in));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel); rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), listener,
channel);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
doc.swap(*aResult); doc.swap(*aResult);

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

@ -2561,11 +2561,12 @@ XMLHttpRequestMainThread::MaybeLowerChannelPriority()
} }
nsresult nsresult
XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream, XMLHttpRequestMainThread::InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
int64_t aUploadLength, int64_t aUploadLength,
nsACString& aUploadContentType) nsACString& aUploadContentType)
{ {
nsresult rv; nsresult rv;
nsCOMPtr<nsIInputStream> uploadStream = Move(aUploadStream);
// nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
// in turn keeps STOP button from becoming active. If the consumer passed in // in turn keeps STOP button from becoming active. If the consumer passed in
@ -2615,16 +2616,16 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
} }
} }
if (aUploadStream) { if (uploadStream) {
// If necessary, wrap the stream in a buffered stream so as to guarantee // If necessary, wrap the stream in a buffered stream so as to guarantee
// support for our upload when calling ExplicitSetUploadStream. // support for our upload when calling ExplicitSetUploadStream.
nsCOMPtr<nsIInputStream> bufferedStream; if (!NS_InputStreamIsBuffered(uploadStream)) {
if (!NS_InputStreamIsBuffered(aUploadStream)) { nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
aUploadStream, 4096); uploadStream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
aUploadStream = bufferedStream; uploadStream = bufferedStream;
} }
// We want to use a newer version of the upload channel that won't // We want to use a newer version of the upload channel that won't
@ -2633,7 +2634,7 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
// This assertion will fire if buggy extensions are installed // This assertion will fire if buggy extensions are installed
NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2"); NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2");
if (uploadChannel2) { if (uploadChannel2) {
uploadChannel2->ExplicitSetUploadStream(aUploadStream, uploadChannel2->ExplicitSetUploadStream(uploadStream,
aUploadContentType, aUploadContentType,
mUploadTotal, mRequestMethod, mUploadTotal, mRequestMethod,
false); false);
@ -2645,7 +2646,7 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
} }
nsCOMPtr<nsIUploadChannel> uploadChannel = nsCOMPtr<nsIUploadChannel> uploadChannel =
do_QueryInterface(httpChannel); do_QueryInterface(httpChannel);
uploadChannel->SetUploadStream(aUploadStream, aUploadContentType, uploadChannel->SetUploadStream(uploadStream, aUploadContentType,
mUploadTotal); mUploadTotal);
// Reset the method to its original value // Reset the method to its original value
rv = httpChannel->SetRequestMethod(mRequestMethod); rv = httpChannel->SetRequestMethod(mRequestMethod);
@ -3053,7 +3054,7 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
} }
} }
rv = InitiateFetch(uploadStream, mUploadTotal, uploadContentType); rv = InitiateFetch(uploadStream.forget(), mUploadTotal, uploadContentType);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Start our timeout // Start our timeout

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

@ -261,7 +261,7 @@ public:
// request // request
nsresult CreateChannel(); nsresult CreateChannel();
nsresult InitiateFetch(nsIInputStream* aUploadStream, nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
int64_t aUploadLength, int64_t aUploadLength,
nsACString& aUploadContentType); nsACString& aUploadContentType);

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

@ -1,4 +1,4 @@
52368 52371
0/nm 0/nm
0th/pt 0th/pt
1/n1 1/n1
@ -16621,6 +16621,7 @@ billycan/S
bimbo/MS bimbo/MS
bimetallic/SM bimetallic/SM
bimetallism/M bimetallism/M
bimodal
bimonthly/SM bimonthly/SM
bin/SM bin/SM
binary/SM binary/SM
@ -36405,6 +36406,8 @@ nondepreciating
nondescript nondescript
nondestructive nondestructive
nondetachable nondetachable
nondeterminism
nondeterministic
nondisciplinary nondisciplinary
nondisclosure/M nondisclosure/M
nondiscrimination/M nondiscrimination/M

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

@ -333,7 +333,8 @@ CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
nsCOMPtr<nsIInputStream> aBufferedStream; nsCOMPtr<nsIInputStream> aBufferedStream;
if (!NS_InputStreamIsBuffered(stream)) { if (!NS_InputStreamIsBuffered(stream)) {
rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream), stream, 4096); rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream),
stream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
stream = aBufferedStream; stream = aBufferedStream;
} }

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

@ -100,20 +100,20 @@ private:
}; };
/* static */ already_AddRefed<ImageOps::ImageBuffer> /* static */ already_AddRefed<ImageOps::ImageBuffer>
ImageOps::CreateImageBuffer(nsIInputStream* aInputStream) ImageOps::CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream)
{ {
MOZ_ASSERT(aInputStream); nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
MOZ_ASSERT(inputStream);
nsresult rv; nsresult rv;
// Prepare the input stream. // Prepare the input stream.
nsCOMPtr<nsIInputStream> inputStream = aInputStream; if (!NS_InputStreamIsBuffered(inputStream)) {
if (!NS_InputStreamIsBuffered(aInputStream)) {
nsCOMPtr<nsIInputStream> bufStream; nsCOMPtr<nsIInputStream> bufStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
aInputStream, 1024); inputStream.forget(), 1024);
if (NS_SUCCEEDED(rv)) { if (NS_WARN_IF(NS_FAILED(rv))) {
inputStream = bufStream; return nullptr;
} }
} }
@ -145,11 +145,12 @@ ImageOps::CreateImageBuffer(nsIInputStream* aInputStream)
} }
/* static */ nsresult /* static */ nsresult
ImageOps::DecodeMetadata(nsIInputStream* aInputStream, ImageOps::DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
const nsACString& aMimeType, const nsACString& aMimeType,
ImageMetadata& aMetadata) ImageMetadata& aMetadata)
{ {
RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream); nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
return DecodeMetadata(buffer, aMimeType, aMetadata); return DecodeMetadata(buffer, aMimeType, aMetadata);
} }
@ -193,12 +194,13 @@ ImageOps::DecodeMetadata(ImageBuffer* aBuffer,
} }
/* static */ already_AddRefed<gfx::SourceSurface> /* static */ already_AddRefed<gfx::SourceSurface>
ImageOps::DecodeToSurface(nsIInputStream* aInputStream, ImageOps::DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
const nsACString& aMimeType, const nsACString& aMimeType,
uint32_t aFlags, uint32_t aFlags,
const Maybe<IntSize>& aSize /* = Nothing() */) const Maybe<IntSize>& aSize /* = Nothing() */)
{ {
RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream); nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
return DecodeToSurface(buffer, aMimeType, aFlags, aSize); return DecodeToSurface(buffer, aMimeType, aFlags, aSize);
} }

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

@ -93,23 +93,25 @@ public:
* an ImageBuffer representing the given input stream is more efficient if one * an ImageBuffer representing the given input stream is more efficient if one
* has multiple Decode* calls to make on that stream. * has multiple Decode* calls to make on that stream.
* *
* @param aInputStream An input stream containing an encoded image. * @param aInputStream An input stream containing an encoded image. The
* ownership is taken.
* @return An image buffer derived from the input stream. * @return An image buffer derived from the input stream.
*/ */
static already_AddRefed<ImageBuffer> static already_AddRefed<ImageBuffer>
CreateImageBuffer(nsIInputStream* aInputStream); CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream);
/** /**
* Decodes an image's metadata from an nsIInputStream into the given * Decodes an image's metadata from an nsIInputStream into the given
* structure. This function may be called off-main-thread. * structure. This function may be called off-main-thread.
* *
* @param aInputStream An input stream containing an encoded image. * @param aInputStream An input stream containing an encoded image. Ownership
* is taken.
* @param aMimeType The MIME type of the image. * @param aMimeType The MIME type of the image.
* @param aMetadata Where the image metadata is stored upon success. * @param aMetadata Where the image metadata is stored upon success.
* @return The status of the operation. * @return The status of the operation.
*/ */
static nsresult static nsresult
DecodeMetadata(nsIInputStream* aInputStream, DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
const nsACString& aMimeType, const nsACString& aMimeType,
ImageMetadata& aMetadata); ImageMetadata& aMetadata);
@ -127,14 +129,15 @@ public:
* main-thread-only). That means that this function may be called * main-thread-only). That means that this function may be called
* off-main-thread. * off-main-thread.
* *
* @param aInputStream An input stream containing an encoded image. * @param aInputStream An input stream containing an encoded image. The
* ownership is taken.
* @param aMimeType The MIME type of the image. * @param aMimeType The MIME type of the image.
* @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety. * @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
* @return A SourceSurface containing the first frame of the image at its * @return A SourceSurface containing the first frame of the image at its
* intrinsic size, or nullptr if the image cannot be decoded. * intrinsic size, or nullptr if the image cannot be decoded.
*/ */
static already_AddRefed<gfx::SourceSurface> static already_AddRefed<gfx::SourceSurface>
DecodeToSurface(nsIInputStream* aInputStream, DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
const nsACString& aMimeType, const nsACString& aMimeType,
uint32_t aFlags, uint32_t aFlags,
const Maybe<gfx::IntSize>& aSize = Nothing()); const Maybe<gfx::IntSize>& aSize = Nothing());

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

@ -61,7 +61,8 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
nsCOMPtr<nsIInputStream> inStream = aInStr; nsCOMPtr<nsIInputStream> inStream = aInStr;
if (!NS_InputStreamIsBuffered(aInStr)) { if (!NS_InputStreamIsBuffered(aInStr)) {
nsCOMPtr<nsIInputStream> bufStream; nsCOMPtr<nsIInputStream> bufStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024); rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
inStream.forget(), 1024);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
inStream = bufStream; inStream = bufStream;
} }

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

@ -52,7 +52,7 @@ public:
void Go() void Go()
{ {
mSurface = mSurface =
ImageOps::DecodeToSurface(mInputStream, ImageOps::DecodeToSurface(mInputStream.forget(),
nsDependentCString(mimeType.c_str()), nsDependentCString(mimeType.c_str()),
imgIContainer::DECODE_FLAGS_DEFAULT); imgIContainer::DECODE_FLAGS_DEFAULT);
if (!mSurface) if (!mSurface)

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

@ -125,7 +125,7 @@ LoadFile(const char* aRelativePath)
if (!NS_InputStreamIsBuffered(inputStream)) { if (!NS_InputStreamIsBuffered(inputStream)) {
nsCOMPtr<nsIInputStream> bufStream; nsCOMPtr<nsIInputStream> bufStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
inputStream, 1024); inputStream.forget(), 1024);
ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr); ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
inputStream = bufStream; inputStream = bufStream;
} }

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

@ -57,7 +57,7 @@ public:
outputSize); outputSize);
} else { } else {
mSurface = mSurface =
ImageOps::DecodeToSurface(mInputStream, ImageOps::DecodeToSurface(mInputStream.forget(),
nsDependentCString(mTestCase.mMimeType), nsDependentCString(mTestCase.mMimeType),
imgIContainer::DECODE_FLAGS_DEFAULT, imgIContainer::DECODE_FLAGS_DEFAULT,
outputSize); outputSize);
@ -144,7 +144,7 @@ TEST_F(ImageDecodeToSurface, Corrupt)
ASSERT_TRUE(inputStream != nullptr); ASSERT_TRUE(inputStream != nullptr);
RefPtr<SourceSurface> surface = RefPtr<SourceSurface> surface =
ImageOps::DecodeToSurface(inputStream, ImageOps::DecodeToSurface(inputStream.forget(),
nsDependentCString(testCase.mMimeType), nsDependentCString(testCase.mMimeType),
imgIContainer::DECODE_FLAGS_DEFAULT); imgIContainer::DECODE_FLAGS_DEFAULT);
EXPECT_TRUE(surface == nullptr); EXPECT_TRUE(surface == nullptr);
@ -158,7 +158,7 @@ TEST_F(ImageDecodeToSurface, ICOMultipleSizes)
ASSERT_TRUE(inputStream != nullptr); ASSERT_TRUE(inputStream != nullptr);
RefPtr<ImageOps::ImageBuffer> buffer = RefPtr<ImageOps::ImageBuffer> buffer =
ImageOps::CreateImageBuffer(inputStream); ImageOps::CreateImageBuffer(inputStream.forget());
ASSERT_TRUE(buffer != nullptr); ASSERT_TRUE(buffer != nullptr);
ImageMetadata metadata; ImageMetadata metadata;

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

@ -26,6 +26,8 @@ struct HandlerProvider
struct IHandlerProvider : public IUnknown struct IHandlerProvider : public IUnknown
, public HandlerProvider , public HandlerProvider
{ {
virtual STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
ULONG aCallMethod) = 0;
virtual STDMETHODIMP NewInstance(REFIID aIid, virtual STDMETHODIMP NewInstance(REFIID aIid,
InterceptorTargetPtr<IUnknown> aTarget, InterceptorTargetPtr<IUnknown> aTarget,
NotNull<IHandlerProvider**> aOutNewPayload) = 0; NotNull<IHandlerProvider**> aOutNewPayload) = 0;

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

@ -14,6 +14,7 @@
#include "mozilla/mscom/Utils.h" #include "mozilla/mscom/Utils.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/ThreadLocal.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
@ -154,6 +155,52 @@ private:
HRESULT mResult; HRESULT mResult;
}; };
class MOZ_RAII SavedCallFrame final
{
public:
explicit SavedCallFrame(mozilla::NotNull<ICallFrame*> aFrame)
: mCallFrame(aFrame)
{
static const bool sIsInit = tlsFrame.init();
MOZ_ASSERT(sIsInit);
MOZ_ASSERT(!tlsFrame.get());
tlsFrame.set(this);
}
~SavedCallFrame()
{
MOZ_ASSERT(tlsFrame.get());
tlsFrame.set(nullptr);
}
HRESULT GetIidAndMethod(mozilla::NotNull<IID*> aIid,
mozilla::NotNull<ULONG*> aMethod) const
{
return mCallFrame->GetIIDAndMethod(aIid, aMethod);
}
static const SavedCallFrame& Get()
{
SavedCallFrame* saved = tlsFrame.get();
MOZ_ASSERT(saved);
return *saved;
}
SavedCallFrame(const SavedCallFrame&) = delete;
SavedCallFrame(SavedCallFrame&&) = delete;
SavedCallFrame& operator=(const SavedCallFrame&) = delete;
SavedCallFrame& operator=(SavedCallFrame&&) = delete;
private:
ICallFrame* mCallFrame;
private:
static MOZ_THREAD_LOCAL(SavedCallFrame*) tlsFrame;
};
MOZ_THREAD_LOCAL(SavedCallFrame*) SavedCallFrame::tlsFrame;
} // anonymous namespace } // anonymous namespace
namespace mozilla { namespace mozilla {
@ -338,6 +385,8 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame)
return hr; return hr;
} }
} else { } else {
SavedCallFrame savedFrame(WrapNotNull(aFrame));
// (7) Scan the outputs looking for any outparam interfaces that need wrapping. // (7) Scan the outputs looking for any outparam interfaces that need wrapping.
// NB: WalkFrame does not correctly handle array outparams. It processes the // NB: WalkFrame does not correctly handle array outparams. It processes the
// first element of an array but not the remaining elements (if any). // first element of an array but not the remaining elements (if any).
@ -566,9 +615,26 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
} }
} }
IID effectiveIid = aIid;
RefPtr<IHandlerProvider> payload; RefPtr<IHandlerProvider> payload;
if (mHandlerProvider) { if (mHandlerProvider) {
hr = mHandlerProvider->NewInstance(aIid, if (aIid == IID_IUnknown) {
const SavedCallFrame& curFrame = SavedCallFrame::Get();
IID callIid;
ULONG callMethod;
hr = curFrame.GetIidAndMethod(WrapNotNull(&callIid),
WrapNotNull(&callMethod));
if (FAILED(hr)) {
return hr;
}
effectiveIid = mHandlerProvider->GetEffectiveOutParamIid(callIid,
callMethod);
}
hr = mHandlerProvider->NewInstance(effectiveIid,
ToInterceptorTargetPtr(origInterface), ToInterceptorTargetPtr(origInterface),
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload))); WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
MOZ_ASSERT(SUCCEEDED(hr)); MOZ_ASSERT(SUCCEEDED(hr));
@ -585,7 +651,8 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
return hr; return hr;
} }
REFIID interceptorIid = payload ? payload->MarshalAs(aIid) : aIid; REFIID interceptorIid = payload ? payload->MarshalAs(effectiveIid) :
effectiveIid;
RefPtr<IUnknown> wrapped; RefPtr<IUnknown> wrapped;
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid, hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,

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

@ -2504,7 +2504,7 @@ BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
{ {
if (pn && !updateSourceCoordNotes(pn->pn_pos.begin)) if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
return false; return false;
return emit3(op, ARGC_HI(argc), ARGC_LO(argc)); return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
} }
bool bool
@ -2687,7 +2687,7 @@ bool
BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
{ {
MOZ_ASSERT(operand <= UINT16_MAX); MOZ_ASSERT(operand <= UINT16_MAX);
if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand))) if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand)))
return false; return false;
checkTypeSet(op); checkTypeSet(op);
return true; return true;
@ -10214,10 +10214,7 @@ BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
MOZ_ASSERT(code[0] == JSOP_NEWINIT); MOZ_ASSERT(code[0] == JSOP_NEWINIT);
code[0] = JSOP_NEWOBJECT; code[0] = JSOP_NEWOBJECT;
code[1] = jsbytecode(index >> 24); SET_UINT32(code, index);
code[2] = jsbytecode(index >> 16);
code[3] = jsbytecode(index >> 8);
code[4] = jsbytecode(index);
return true; return true;
} }

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

@ -40,6 +40,7 @@ class AutoRunParallelTask;
class AutoTraceSession; class AutoTraceSession;
class MarkingValidator; class MarkingValidator;
struct MovingTracer; struct MovingTracer;
class SweepGroupsIter;
class WeakCacheSweepIterator; class WeakCacheSweepIterator;
enum IncrementalProgress enum IncrementalProgress
@ -1073,27 +1074,24 @@ class GCRuntime
void groupZonesForSweeping(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock); void groupZonesForSweeping(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
MOZ_MUST_USE bool findInterZoneEdges(); MOZ_MUST_USE bool findInterZoneEdges();
void getNextSweepGroup(); void getNextSweepGroup();
void endMarkingSweepGroup(); IncrementalProgress endMarkingSweepGroup(FreeOp* fop, SliceBudget& budget);
void beginSweepingSweepGroup(); IncrementalProgress beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget);
#ifdef JS_GC_ZEAL
IncrementalProgress maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget);
#endif
bool shouldReleaseObservedTypes(); bool shouldReleaseObservedTypes();
void sweepDebuggerOnMainThread(FreeOp* fop); void sweepDebuggerOnMainThread(FreeOp* fop);
void sweepJitDataOnMainThread(FreeOp* fop); void sweepJitDataOnMainThread(FreeOp* fop);
void endSweepingSweepGroup(); IncrementalProgress endSweepingSweepGroup(FreeOp* fop, SliceBudget& budget);
IncrementalProgress performSweepActions(SliceBudget& sliceBudget, IncrementalProgress performSweepActions(SliceBudget& sliceBudget, AutoLockForExclusiveAccess& lock);
AutoLockForExclusiveAccess& lock); IncrementalProgress sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone);
static IncrementalProgress sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, IncrementalProgress mergeSweptObjectArenas(FreeOp* fop, SliceBudget& budget, Zone* zone);
Zone* zone);
static IncrementalProgress mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
Zone* zone);
static IncrementalProgress sweepAtomsTable(GCRuntime* gc, FreeOp* fop, SliceBudget& budget);
void startSweepingAtomsTable(); void startSweepingAtomsTable();
IncrementalProgress sweepAtomsTable(SliceBudget& budget); IncrementalProgress sweepAtomsTable(FreeOp* fop, SliceBudget& budget);
static IncrementalProgress sweepWeakCaches(GCRuntime* gc, FreeOp* fop, SliceBudget& budget); IncrementalProgress sweepWeakCaches(FreeOp* fop, SliceBudget& budget);
IncrementalProgress sweepWeakCaches(SliceBudget& budget); IncrementalProgress finalizeAllocKind(FreeOp* fop, SliceBudget& budget, Zone* zone,
static IncrementalProgress finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, AllocKind kind);
Zone* zone, AllocKind kind); IncrementalProgress sweepShapeTree(FreeOp* fop, SliceBudget& budget, Zone* zone);
static IncrementalProgress sweepShapeTree(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
Zone* zone);
void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock); void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
bool allCCVisibleZonesWereCollected() const; bool allCCVisibleZonesWereCollected() const;
void sweepZones(FreeOp* fop, ZoneGroup* group, bool lastGC); void sweepZones(FreeOp* fop, ZoneGroup* group, bool lastGC);
@ -1285,9 +1283,20 @@ class GCRuntime
*/ */
ActiveThreadOrGCTaskData<State> incrementalState; ActiveThreadOrGCTaskData<State> incrementalState;
/* The incremental state at the start of this slice. */
ActiveThreadData<State> initialState;
#ifdef JS_GC_ZEAL
/* Whether to pay attention the zeal settings in this incremental slice. */
ActiveThreadData<bool> useZeal;
#endif
/* Indicates that the last incremental slice exhausted the mark stack. */ /* Indicates that the last incremental slice exhausted the mark stack. */
ActiveThreadData<bool> lastMarkSlice; ActiveThreadData<bool> lastMarkSlice;
/* Whether it's currently safe to yield to the mutator in an incremental GC. */
ActiveThreadData<bool> safeToYield;
/* Whether any sweeping will take place in the separate GC helper thread. */ /* Whether any sweeping will take place in the separate GC helper thread. */
ActiveThreadData<bool> sweepOnBackgroundThread; ActiveThreadData<bool> sweepOnBackgroundThread;
@ -1319,6 +1328,7 @@ class GCRuntime
ActiveThreadOrGCTaskData<JS::detail::WeakCacheBase*> sweepCache; ActiveThreadOrGCTaskData<JS::detail::WeakCacheBase*> sweepCache;
ActiveThreadData<bool> abortSweepAfterCurrentGroup; ActiveThreadData<bool> abortSweepAfterCurrentGroup;
friend class SweepGroupsIter;
friend class WeakCacheSweepIterator; friend class WeakCacheSweepIterator;
/* /*

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

@ -2494,7 +2494,7 @@ GCMarker::enterWeakMarkingMode()
if (weakMapAction() == ExpandWeakMaps) { if (weakMapAction() == ExpandWeakMaps) {
tag_ = TracerKindTag::WeakMarking; tag_ = TracerKindTag::WeakMarking;
for (GCSweepGroupIter zone(runtime()); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(runtime()); !zone.done(); zone.next()) {
for (WeakMapBase* m : zone->gcWeakMapList()) { for (WeakMapBase* m : zone->gcWeakMapList()) {
if (m->marked) if (m->marked)
(void) m->markIteratively(this); (void) m->markIteratively(this);

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

@ -3568,6 +3568,19 @@ Simulator::branchDelayInstructionDecode(SimInstruction* instr)
instructionDecode(instr); instructionDecode(instr);
} }
static void
FakeInterruptHandler()
{
JSContext* cx = TlsContext.get();
uint8_t* pc = cx->simulator()->get_pc_as<uint8_t*>();
const wasm::CodeSegment* cs = nullptr;
if (!wasm::InInterruptibleCode(cx, pc, &cs))
return;
cx->simulator()->trigger_wasm_interrupt();
}
template<bool enableStopSimAt> template<bool enableStopSimAt>
void void
Simulator::execute() Simulator::execute()
@ -3581,6 +3594,8 @@ Simulator::execute()
MipsDebugger dbg(this); MipsDebugger dbg(this);
dbg.debug(); dbg.debug();
} else { } else {
if (MOZ_UNLIKELY(JitOptions.simulatorAlwaysInterrupt))
FakeInterruptHandler();
SimInstruction* instr = reinterpret_cast<SimInstruction*>(program_counter); SimInstruction* instr = reinterpret_cast<SimInstruction*>(program_counter);
instructionDecode(instr); instructionDecode(instr);
icount_++; icount_++;

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

@ -3733,6 +3733,19 @@ Simulator::disable_single_stepping()
single_step_callback_arg_ = nullptr; single_step_callback_arg_ = nullptr;
} }
static void
FakeInterruptHandler()
{
JSContext* cx = TlsContext.get();
uint8_t* pc = cx->simulator()->get_pc_as<uint8_t*>();
const wasm::CodeSegment* cs = nullptr;
if (!wasm::InInterruptibleCode(cx, pc, &cs))
return;
cx->simulator()->trigger_wasm_interrupt();
}
template<bool enableStopSimAt> template<bool enableStopSimAt>
void void
Simulator::execute() Simulator::execute()
@ -3751,6 +3764,8 @@ Simulator::execute()
} else { } else {
if (single_stepping_) if (single_stepping_)
single_step_callback_(single_step_callback_arg_, this, (void*)program_counter); single_step_callback_(single_step_callback_arg_, this, (void*)program_counter);
if (MOZ_UNLIKELY(JitOptions.simulatorAlwaysInterrupt))
FakeInterruptHandler();
SimInstruction* instr = reinterpret_cast<SimInstruction *>(program_counter); SimInstruction* instr = reinterpret_cast<SimInstruction *>(program_counter);
instructionDecode(instr); instructionDecode(instr);
icount_++; icount_++;

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

@ -465,6 +465,7 @@ class AutoLeaveZeal
JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC); JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
} }
~AutoLeaveZeal() { ~AutoLeaveZeal() {
JS_SetGCZeal(cx_, 0, 0);
for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) { for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
if (zealBits_ & (1 << i)) if (zealBits_ & (1 << i))
JS_SetGCZeal(cx_, i, frequency_); JS_SetGCZeal(cx_, i, frequency_);

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

@ -914,7 +914,12 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
number(0), number(0),
isFull(false), isFull(false),
incrementalState(gc::State::NotActive), incrementalState(gc::State::NotActive),
initialState(gc::State::NotActive),
#ifdef JS_GC_ZEAL
useZeal(false),
#endif
lastMarkSlice(false), lastMarkSlice(false),
safeToYield(true),
sweepOnBackgroundThread(false), sweepOnBackgroundThread(false),
blocksToFreeAfterSweeping((size_t) JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), blocksToFreeAfterSweeping((size_t) JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
sweepGroupIndex(0), sweepGroupIndex(0),
@ -4389,7 +4394,7 @@ GCRuntime::markWeakReferences(gcstats::PhaseKind phase)
void void
GCRuntime::markWeakReferencesInCurrentGroup(gcstats::PhaseKind phase) GCRuntime::markWeakReferencesInCurrentGroup(gcstats::PhaseKind phase)
{ {
markWeakReferences<GCSweepGroupIter>(phase); markWeakReferences<SweepGroupZonesIter>(phase);
} }
template <class ZoneIterT, class CompartmentIterT> template <class ZoneIterT, class CompartmentIterT>
@ -4412,7 +4417,7 @@ GCRuntime::markGrayReferences(gcstats::PhaseKind phase)
void void
GCRuntime::markGrayReferencesInCurrentGroup(gcstats::PhaseKind phase) GCRuntime::markGrayReferencesInCurrentGroup(gcstats::PhaseKind phase)
{ {
markGrayReferences<GCSweepGroupIter, GCCompartmentGroupIter>(phase); markGrayReferences<SweepGroupZonesIter, SweepGroupCompartmentsIter>(phase);
} }
void void
@ -4907,14 +4912,14 @@ GCRuntime::getNextSweepGroup()
if (abortSweepAfterCurrentGroup) { if (abortSweepAfterCurrentGroup) {
MOZ_ASSERT(!isIncremental); MOZ_ASSERT(!isIncremental);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
MOZ_ASSERT(!zone->gcNextGraphComponent); MOZ_ASSERT(!zone->gcNextGraphComponent);
zone->setNeedsIncrementalBarrier(false); zone->setNeedsIncrementalBarrier(false);
zone->changeGCState(Zone::Mark, Zone::NoGC); zone->changeGCState(Zone::Mark, Zone::NoGC);
zone->gcGrayRoots().clearAndFree(); zone->gcGrayRoots().clearAndFree();
} }
for (GCCompartmentGroupIter comp(rt); !comp.done(); comp.next()) for (SweepGroupCompartmentsIter comp(rt); !comp.done(); comp.next())
ResetGrayList(comp); ResetGrayList(comp);
abortSweepAfterCurrentGroup = false; abortSweepAfterCurrentGroup = false;
@ -5049,7 +5054,7 @@ MarkIncomingCrossCompartmentPointers(JSRuntime* rt, MarkColor color)
bool unlinkList = color == MarkColor::Gray; bool unlinkList = color == MarkColor::Gray;
for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) { for (SweepGroupCompartmentsIter c(rt); !c.done(); c.next()) {
MOZ_ASSERT_IF(color == MarkColor::Gray, c->zone()->isGCMarkingGray()); MOZ_ASSERT_IF(color == MarkColor::Gray, c->zone()->isGCMarkingGray());
MOZ_ASSERT_IF(color == MarkColor::Black, c->zone()->isGCMarkingBlack()); MOZ_ASSERT_IF(color == MarkColor::Black, c->zone()->isGCMarkingBlack());
MOZ_ASSERT_IF(c->gcIncomingGrayPointers, IsGrayListObject(c->gcIncomingGrayPointers)); MOZ_ASSERT_IF(c->gcIncomingGrayPointers, IsGrayListObject(c->gcIncomingGrayPointers));
@ -5162,8 +5167,8 @@ js::NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned removedFlags)
DelayCrossCompartmentGrayMarking(a); DelayCrossCompartmentGrayMarking(a);
} }
void IncrementalProgress
GCRuntime::endMarkingSweepGroup() GCRuntime::endMarkingSweepGroup(FreeOp* fop, SliceBudget& budget)
{ {
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_MARK); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_MARK);
@ -5181,7 +5186,7 @@ GCRuntime::endMarkingSweepGroup()
* these will be marked through, as they are not marked with * these will be marked through, as they are not marked with
* MarkCrossCompartmentXXX. * MarkCrossCompartmentXXX.
*/ */
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
zone->changeGCState(Zone::Mark, Zone::MarkGray); zone->changeGCState(Zone::Mark, Zone::MarkGray);
marker.setMarkColorGray(); marker.setMarkColorGray();
@ -5193,10 +5198,15 @@ GCRuntime::endMarkingSweepGroup()
markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK); markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK);
/* Restore marking state. */ /* Restore marking state. */
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
zone->changeGCState(Zone::MarkGray, Zone::Mark); zone->changeGCState(Zone::MarkGray, Zone::Mark);
MOZ_ASSERT(marker.isDrained()); MOZ_ASSERT(marker.isDrained());
marker.setMarkColorBlack(); marker.setMarkColorBlack();
/* We must not yield after this point before we start sweeping the group. */
safeToYield = false;
return Finished;
} }
// Causes the given WeakCache to be swept when run. // Causes the given WeakCache to be swept when run.
@ -5245,28 +5255,28 @@ UpdateAtomsBitmap(JSRuntime* runtime)
static void static void
SweepCCWrappers(JSRuntime* runtime) SweepCCWrappers(JSRuntime* runtime)
{ {
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
c->sweepCrossCompartmentWrappers(); c->sweepCrossCompartmentWrappers();
} }
static void static void
SweepObjectGroups(JSRuntime* runtime) SweepObjectGroups(JSRuntime* runtime)
{ {
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
c->objectGroups.sweep(runtime->defaultFreeOp()); c->objectGroups.sweep(runtime->defaultFreeOp());
} }
static void static void
SweepRegExps(JSRuntime* runtime) SweepRegExps(JSRuntime* runtime)
{ {
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
c->sweepRegExps(); c->sweepRegExps();
} }
static void static void
SweepMisc(JSRuntime* runtime) SweepMisc(JSRuntime* runtime)
{ {
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) { for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next()) {
c->sweepGlobalObject(); c->sweepGlobalObject();
c->sweepTemplateObjects(); c->sweepTemplateObjects();
c->sweepSavedStacks(); c->sweepSavedStacks();
@ -5303,7 +5313,7 @@ SweepCompressionTasks(JSRuntime* runtime)
static void static void
SweepWeakMaps(JSRuntime* runtime) SweepWeakMaps(JSRuntime* runtime)
{ {
for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next()) {
/* Clear all weakrefs that point to unmarked things. */ /* Clear all weakrefs that point to unmarked things. */
for (auto edge : zone->gcWeakRefs()) { for (auto edge : zone->gcWeakRefs()) {
/* Edges may be present multiple times, so may already be nulled. */ /* Edges may be present multiple times, so may already be nulled. */
@ -5325,7 +5335,7 @@ static void
SweepUniqueIds(JSRuntime* runtime) SweepUniqueIds(JSRuntime* runtime)
{ {
FreeOp fop(nullptr); FreeOp fop(nullptr);
for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next())
zone->sweepUniqueIds(&fop); zone->sweepUniqueIds(&fop);
} }
@ -5363,7 +5373,7 @@ GCRuntime::sweepDebuggerOnMainThread(FreeOp* fop)
// table. // table.
{ {
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_MISC); gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_MISC);
for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) for (SweepGroupCompartmentsIter c(rt); !c.done(); c.next())
c->sweepDebugEnvironments(); c->sweepDebugEnvironments();
} }
@ -5371,7 +5381,7 @@ GCRuntime::sweepDebuggerOnMainThread(FreeOp* fop)
// although note that it can cause JIT code to be patched. // although note that it can cause JIT code to be patched.
{ {
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_BREAKPOINT); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_BREAKPOINT);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
zone->sweepBreakpoints(fop); zone->sweepBreakpoints(fop);
} }
} }
@ -5385,10 +5395,10 @@ GCRuntime::sweepJitDataOnMainThread(FreeOp* fop)
// Cancel any active or pending off thread compilations. // Cancel any active or pending off thread compilations.
js::CancelOffThreadIonCompile(rt, JS::Zone::Sweep); js::CancelOffThreadIonCompile(rt, JS::Zone::Sweep);
for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) for (SweepGroupCompartmentsIter c(rt); !c.done(); c.next())
c->sweepJitCompartment(fop); c->sweepJitCompartment(fop);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
if (jit::JitZone* jitZone = zone->jitZone()) if (jit::JitZone* jitZone = zone->jitZone())
jitZone->sweep(fop); jitZone->sweep(fop);
} }
@ -5403,14 +5413,14 @@ GCRuntime::sweepJitDataOnMainThread(FreeOp* fop)
{ {
gcstats::AutoPhase apdc(stats(), gcstats::PhaseKind::SWEEP_DISCARD_CODE); gcstats::AutoPhase apdc(stats(), gcstats::PhaseKind::SWEEP_DISCARD_CODE);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
zone->discardJitCode(fop); zone->discardJitCode(fop);
} }
{ {
gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_TYPES); gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_TYPES);
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES_BEGIN); gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES_BEGIN);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
zone->beginSweepTypes(fop, releaseObservedTypes && !zone->isPreservingCode()); zone->beginSweepTypes(fop, releaseObservedTypes && !zone->isPreservingCode());
} }
} }
@ -5429,7 +5439,7 @@ template <typename Functor>
static inline bool static inline bool
IterateWeakCaches(JSRuntime* rt, Functor f) IterateWeakCaches(JSRuntime* rt, Functor f)
{ {
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
for (JS::detail::WeakCacheBase* cache : zone->weakCaches()) { for (JS::detail::WeakCacheBase* cache : zone->weakCaches()) {
if (!f(cache, ZoneWeakCache)) if (!f(cache, ZoneWeakCache))
return false; return false;
@ -5484,8 +5494,8 @@ SweepWeakCachesOnMainThread(JSRuntime* rt)
}); });
} }
void IncrementalProgress
GCRuntime::beginSweepingSweepGroup() GCRuntime::beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
{ {
/* /*
* Begin sweeping the group of zones in currentSweepGroup, performing * Begin sweeping the group of zones in currentSweepGroup, performing
@ -5497,7 +5507,7 @@ GCRuntime::beginSweepingSweepGroup()
AutoSCC scc(stats(), sweepGroupIndex); AutoSCC scc(stats(), sweepGroupIndex);
bool sweepingAtoms = false; bool sweepingAtoms = false;
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
/* Set the GC state to sweeping. */ /* Set the GC state to sweeping. */
zone->changeGCState(Zone::Mark, Zone::Sweep); zone->changeGCState(Zone::Mark, Zone::Sweep);
@ -5514,26 +5524,24 @@ GCRuntime::beginSweepingSweepGroup()
validateIncrementalMarking(); validateIncrementalMarking();
FreeOp fop(rt);
{ {
AutoPhase ap(stats(), PhaseKind::FINALIZE_START); AutoPhase ap(stats(), PhaseKind::FINALIZE_START);
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_PREPARE); callFinalizeCallbacks(fop, JSFINALIZE_GROUP_PREPARE);
{ {
AutoPhase ap2(stats(), PhaseKind::WEAK_ZONES_CALLBACK); AutoPhase ap2(stats(), PhaseKind::WEAK_ZONES_CALLBACK);
callWeakPointerZonesCallbacks(); callWeakPointerZonesCallbacks();
} }
{ {
AutoPhase ap2(stats(), PhaseKind::WEAK_COMPARTMENT_CALLBACK); AutoPhase ap2(stats(), PhaseKind::WEAK_COMPARTMENT_CALLBACK);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
callWeakPointerCompartmentCallbacks(comp); callWeakPointerCompartmentCallbacks(comp);
} }
} }
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_START); callFinalizeCallbacks(fop, JSFINALIZE_GROUP_START);
} }
sweepDebuggerOnMainThread(&fop); sweepDebuggerOnMainThread(fop);
{ {
AutoLockHelperThreadState lock; AutoLockHelperThreadState lock;
@ -5561,7 +5569,7 @@ GCRuntime::beginSweepingSweepGroup()
{ {
AutoUnlockHelperThreadState unlock(lock); AutoUnlockHelperThreadState unlock(lock);
sweepJitDataOnMainThread(&fop); sweepJitDataOnMainThread(fop);
} }
for (auto& task : sweepCacheTasks) for (auto& task : sweepCacheTasks)
@ -5574,25 +5582,45 @@ GCRuntime::beginSweepingSweepGroup()
// Queue all GC things in all zones for sweeping, either on the foreground // Queue all GC things in all zones for sweeping, either on the foreground
// or on the background thread. // or on the background thread.
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
zone->arenas.queueForForegroundSweep(&fop, ForegroundObjectFinalizePhase); zone->arenas.queueForForegroundSweep(fop, ForegroundObjectFinalizePhase);
zone->arenas.queueForForegroundSweep(&fop, ForegroundNonObjectFinalizePhase); zone->arenas.queueForForegroundSweep(fop, ForegroundNonObjectFinalizePhase);
for (unsigned i = 0; i < ArrayLength(BackgroundFinalizePhases); ++i) for (unsigned i = 0; i < ArrayLength(BackgroundFinalizePhases); ++i)
zone->arenas.queueForBackgroundSweep(&fop, BackgroundFinalizePhases[i]); zone->arenas.queueForBackgroundSweep(fop, BackgroundFinalizePhases[i]);
zone->arenas.queueForegroundThingsForSweep(&fop); zone->arenas.queueForegroundThingsForSweep(fop);
} }
sweepCache = nullptr; sweepCache = nullptr;
sweepActions->assertFinished(); safeToYield = true;
return Finished;
} }
void #ifdef JS_GC_ZEAL
GCRuntime::endSweepingSweepGroup() IncrementalProgress
GCRuntime::maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget)
{ {
sweepActions->assertFinished(); /*
* Check whether we need to yield for GC zeal. We always yield when running
* in incremental multi-slice zeal mode so RunDebugGC can reset the slice
* budget.
*/
if (isIncremental && useZeal && initialState != State::Sweep &&
(hasZealMode(ZealMode::IncrementalMultipleSlices) ||
hasZealMode(ZealMode::IncrementalSweepThenFinish)))
{
return NotFinished;
}
return Finished;
}
#endif
IncrementalProgress
GCRuntime::endSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
{
{ {
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::FINALIZE_END); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::FINALIZE_END);
FreeOp fop(rt); FreeOp fop(rt);
@ -5600,7 +5628,7 @@ GCRuntime::endSweepingSweepGroup()
} }
/* Update the GC state for zones we have swept. */ /* Update the GC state for zones we have swept. */
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) { for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
AutoLockGC lock(rt); AutoLockGC lock(rt);
zone->changeGCState(Zone::Sweep, Zone::Finished); zone->changeGCState(Zone::Sweep, Zone::Finished);
zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables, zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables,
@ -5609,7 +5637,7 @@ GCRuntime::endSweepingSweepGroup()
/* Start background thread to sweep zones if required. */ /* Start background thread to sweep zones if required. */
ZoneList zones; ZoneList zones;
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
zones.append(zone); zones.append(zone);
if (sweepOnBackgroundThread) if (sweepOnBackgroundThread)
queueZonesForBackgroundSweep(zones); queueZonesForBackgroundSweep(zones);
@ -5621,6 +5649,8 @@ GCRuntime::endSweepingSweepGroup()
arenasAllocatedDuringSweep = arena->getNextAllocDuringSweep(); arenasAllocatedDuringSweep = arena->getNextAllocDuringSweep();
arena->unsetAllocDuringSweep(); arena->unsetAllocDuringSweep();
} }
return Finished;
} }
void void
@ -5653,8 +5683,12 @@ GCRuntime::beginSweepPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcce
DropStringWrappers(rt); DropStringWrappers(rt);
groupZonesForSweeping(reason, lock); groupZonesForSweeping(reason, lock);
endMarkingSweepGroup();
beginSweepingSweepGroup(); sweepActions->assertFinished();
// We must not yield after this point until we start sweeping the first sweep
// group.
safeToYield = false;
} }
bool bool
@ -5737,8 +5771,8 @@ SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget, Args... args)
return true; return true;
} }
/* static */ IncrementalProgress IncrementalProgress
GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone) GCRuntime::sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone)
{ {
// Sweep dead type information stored in scripts and object groups, but // Sweep dead type information stored in scripts and object groups, but
// don't finalize them yet. We have to sweep dead information from both live // don't finalize them yet. We have to sweep dead information from both live
@ -5748,8 +5782,8 @@ GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
// the sweep group finishes we won't be able to determine which things in // the sweep group finishes we won't be able to determine which things in
// the zone are live. // the zone are live.
gcstats::AutoPhase ap1(gc->stats(), gcstats::PhaseKind::SWEEP_COMPARTMENTS); gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_COMPARTMENTS);
gcstats::AutoPhase ap2(gc->stats(), gcstats::PhaseKind::SWEEP_TYPES); gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES);
ArenaLists& al = zone->arenas; ArenaLists& al = zone->arenas;
@ -5763,15 +5797,16 @@ GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
// Finish sweeping type information in the zone. // Finish sweeping type information in the zone.
{ {
gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::SWEEP_TYPES_END); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_TYPES_END);
zone->types.endSweep(gc->rt); zone->types.endSweep(rt);
} }
return Finished; return Finished;
} }
/* static */ IncrementalProgress IncrementalProgress
GCRuntime::mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone) GCRuntime::mergeSweptObjectArenas(FreeOp* fop, SliceBudget& budget,
Zone* zone)
{ {
// Foreground finalized objects have already been finalized, and now their // Foreground finalized objects have already been finalized, and now their
// arenas can be reclaimed by freeing empty ones and making non-empty ones // arenas can be reclaimed by freeing empty ones and making non-empty ones
@ -5802,18 +5837,12 @@ GCRuntime::startSweepingAtomsTable()
maybeAtoms.emplace(*atomsTable); maybeAtoms.emplace(*atomsTable);
} }
/* static */ IncrementalProgress IncrementalProgress
GCRuntime::sweepAtomsTable(GCRuntime* gc, FreeOp* fop, SliceBudget& budget) GCRuntime::sweepAtomsTable(FreeOp* fop, SliceBudget& budget)
{ {
if (!gc->atomsZone->isGCSweeping()) if (!atomsZone->isGCSweeping())
return Finished; return Finished;
return gc->sweepAtomsTable(budget);
}
IncrementalProgress
GCRuntime::sweepAtomsTable(SliceBudget& budget)
{
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_ATOMS_TABLE); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_ATOMS_TABLE);
auto& maybeAtoms = maybeAtomsToSweep.ref(); auto& maybeAtoms = maybeAtomsToSweep.ref();
@ -5943,12 +5972,6 @@ class IncrementalSweepWeakCacheTask : public GCParallelTask
} }
}; };
/* static */ IncrementalProgress
GCRuntime::sweepWeakCaches(GCRuntime* gc, FreeOp* fop, SliceBudget& budget)
{
return gc->sweepWeakCaches(budget);
}
static const size_t MaxWeakCacheSweepTasks = 8; static const size_t MaxWeakCacheSweepTasks = 8;
static size_t static size_t
@ -5959,7 +5982,7 @@ WeakCacheSweepTaskCount()
} }
IncrementalProgress IncrementalProgress
GCRuntime::sweepWeakCaches(SliceBudget& budget) GCRuntime::sweepWeakCaches(FreeOp* fop, SliceBudget& budget)
{ {
WeakCacheSweepIterator work(this); WeakCacheSweepIterator work(this);
@ -5978,13 +6001,12 @@ GCRuntime::sweepWeakCaches(SliceBudget& budget)
return work.empty(lock) ? Finished : NotFinished; return work.empty(lock) ? Finished : NotFinished;
} }
/* static */ IncrementalProgress IncrementalProgress
GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone, GCRuntime::finalizeAllocKind(FreeOp* fop, SliceBudget& budget, Zone* zone, AllocKind kind)
AllocKind kind)
{ {
// Set the number of things per arena for this AllocKind. // Set the number of things per arena for this AllocKind.
size_t thingsPerArena = Arena::thingsPerArena(kind); size_t thingsPerArena = Arena::thingsPerArena(kind);
auto& sweepList = gc->incrementalSweepList.ref(); auto& sweepList = incrementalSweepList.ref();
sweepList.setThingsPerArena(thingsPerArena); sweepList.setThingsPerArena(thingsPerArena);
if (!zone->arenas.foregroundFinalize(fop, kind, budget, sweepList)) if (!zone->arenas.foregroundFinalize(fop, kind, budget, sweepList))
@ -5996,12 +6018,12 @@ GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zo
return Finished; return Finished;
} }
/* static */ IncrementalProgress IncrementalProgress
GCRuntime::sweepShapeTree(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone) GCRuntime::sweepShapeTree(FreeOp* fop, SliceBudget& budget, Zone* zone)
{ {
// Remove dead shapes from the shape tree, but don't finalize them yet. // Remove dead shapes from the shape tree, but don't finalize them yet.
gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::SWEEP_SHAPE); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_SHAPE);
ArenaLists& al = zone->arenas; ArenaLists& al = zone->arenas;
@ -6084,20 +6106,46 @@ struct IncrementalIter
} }
}; };
namespace sweepaction { // Iterate through the sweep groups created by GCRuntime::groupZonesForSweeping().
class js::gc::SweepGroupsIter
// Implementation of the SweepAction interface that calls a function.
template <typename... Args>
class SweepActionFunc final : public SweepAction<Args...>
{ {
using Func = IncrementalProgress (*)(Args...); GCRuntime* gc;
Func func;
public: public:
explicit SweepActionFunc(Func f) : func(f) {} explicit SweepGroupsIter(JSRuntime* rt)
IncrementalProgress run(Args... args) override { : gc(&rt->gc)
return func(args...); {
MOZ_ASSERT(gc->currentSweepGroup);
}
bool done() const {
return !gc->currentSweepGroup;
}
Zone* get() const {
return gc->currentSweepGroup;
}
void next() {
MOZ_ASSERT(!done());
gc->getNextSweepGroup();
}
};
namespace sweepaction {
// Implementation of the SweepAction interface that calls a method on GCRuntime.
template <typename... Args>
class SweepActionCall final : public SweepAction<GCRuntime*, Args...>
{
using Method = IncrementalProgress (GCRuntime::*)(Args...);
Method method;
public:
explicit SweepActionCall(Method m) : method(m) {}
IncrementalProgress run(GCRuntime* gc, Args... args) override {
return (gc->*method)(args...);
} }
void assertFinished() const override { } void assertFinished() const override { }
}; };
@ -6168,6 +6216,36 @@ class SweepActionForEach final : public SweepAction<Args...>
} }
}; };
template <typename Iter, typename Init, typename... Args>
class SweepActionRepeatFor final : public SweepAction<Args...>
{
protected:
using Action = SweepAction<Args...>;
using IncrIter = IncrementalIter<Iter>;
Init iterInit;
UniquePtr<Action> action;
typename IncrIter::State iterState;
public:
SweepActionRepeatFor(const Init& init, UniquePtr<Action> action)
: iterInit(init), action(Move(action))
{}
IncrementalProgress run(Args... args) override {
for (IncrIter iter(iterState, iterInit); !iter.done(); iter.next()) {
if (action->run(args...) == NotFinished)
return NotFinished;
}
return Finished;
}
void assertFinished() const override {
MOZ_ASSERT(iterState.isNothing());
action->assertFinished();
}
};
// Helper class to remove the last template parameter from the instantiation of // Helper class to remove the last template parameter from the instantiation of
// a variadic template. For example: // a variadic template. For example:
// //
@ -6206,9 +6284,9 @@ class RemoveLastTemplateParameter<Target<Args...>>
}; };
template <typename... Args> template <typename... Args>
static UniquePtr<SweepAction<Args...>> static UniquePtr<SweepAction<GCRuntime*, Args...>>
Func(IncrementalProgress (*func)(Args...)) { Call(IncrementalProgress (GCRuntime::*method)(Args...)) {
return MakeUnique<SweepActionFunc<Args...>>(func); return MakeUnique<SweepActionCall<Args...>>(method);
} }
template <typename... Args, typename... Rest> template <typename... Args, typename... Rest>
@ -6223,6 +6301,17 @@ Sequence(UniquePtr<SweepAction<Args...>> first, Rest... rest)
return UniquePtr<SweepAction<Args...>>(Move(seq)); return UniquePtr<SweepAction<Args...>>(Move(seq));
} }
template <typename... Args>
static UniquePtr<SweepAction<Args...>>
RepeatForSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
{
if (!action)
return nullptr;
using Action = SweepActionRepeatFor<SweepGroupsIter, JSRuntime*, Args...>;
return js::MakeUnique<Action>(rt, Move(action));
}
template <typename... Args> template <typename... Args>
static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type> static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type>
ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action) ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
@ -6231,7 +6320,7 @@ ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
return nullptr; return nullptr;
using Action = typename RemoveLastTemplateParameter< using Action = typename RemoveLastTemplateParameter<
SweepActionForEach<GCSweepGroupIter, JSRuntime*, Args...>>::Type; SweepActionForEach<SweepGroupZonesIter, JSRuntime*, Args...>>::Type;
return js::MakeUnique<Action>(rt, Move(action)); return js::MakeUnique<Action>(rt, Move(action));
} }
@ -6253,22 +6342,31 @@ bool
GCRuntime::initSweepActions() GCRuntime::initSweepActions()
{ {
using namespace sweepaction; using namespace sweepaction;
using sweepaction::Call;
sweepActions.ref() = Sequence( sweepActions.ref() =
Func(sweepAtomsTable), RepeatForSweepGroup(rt,
Func(sweepWeakCaches),
ForEachZoneInSweepGroup(rt,
ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
Func(finalizeAllocKind))),
ForEachZoneInSweepGroup(rt,
Sequence( Sequence(
Func(sweepTypeInformation), Call(&GCRuntime::endMarkingSweepGroup),
Func(mergeSweptObjectArenas))), Call(&GCRuntime::beginSweepingSweepGroup),
ForEachZoneInSweepGroup(rt, #ifdef JS_GC_ZEAL
ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds, Call(&GCRuntime::maybeYieldForSweepingZeal),
Func(finalizeAllocKind))), #endif
ForEachZoneInSweepGroup(rt, Call(&GCRuntime::sweepAtomsTable),
Func(sweepShapeTree))); Call(&GCRuntime::sweepWeakCaches),
ForEachZoneInSweepGroup(rt,
ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
Call(&GCRuntime::finalizeAllocKind))),
ForEachZoneInSweepGroup(rt,
Sequence(
Call(&GCRuntime::sweepTypeInformation),
Call(&GCRuntime::mergeSweptObjectArenas))),
ForEachZoneInSweepGroup(rt,
ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
Call(&GCRuntime::finalizeAllocKind))),
ForEachZoneInSweepGroup(rt,
Call(&GCRuntime::sweepShapeTree)),
Call(&GCRuntime::endSweepingSweepGroup)));
return sweepActions != nullptr; return sweepActions != nullptr;
} }
@ -6281,21 +6379,17 @@ GCRuntime::performSweepActions(SliceBudget& budget, AutoLockForExclusiveAccess&
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
FreeOp fop(rt); FreeOp fop(rt);
if (drainMarkStack(budget, gcstats::PhaseKind::SWEEP_MARK) == NotFinished) // Drain the mark stack, except in the first sweep slice where we must not
return NotFinished; // yield to the mutator until we've starting sweeping a sweep group.
MOZ_ASSERT(initialState <= State::Sweep);
for (;;) { if (initialState != State::Sweep) {
if (sweepActions->run(this, &fop, budget) == NotFinished) MOZ_ASSERT(marker.isDrained());
return NotFinished; } else {
if (drainMarkStack(budget, gcstats::PhaseKind::SWEEP_MARK) == NotFinished)
endSweepingSweepGroup(); return NotFinished;
getNextSweepGroup();
if (!currentSweepGroup)
return Finished;
endMarkingSweepGroup();
beginSweepingSweepGroup();
} }
return sweepActions->run(this, &fop, budget);
} }
bool bool
@ -6331,6 +6425,8 @@ GCRuntime::allCCVisibleZonesWereCollected() const
void void
GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& lock) GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& lock)
{ {
sweepActions->assertFinished();
AutoSetThreadIsSweeping threadIsSweeping; AutoSetThreadIsSweeping threadIsSweeping;
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
@ -6766,18 +6862,17 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
bool destroyingRuntime = (reason == JS::gcreason::DESTROY_RUNTIME); bool destroyingRuntime = (reason == JS::gcreason::DESTROY_RUNTIME);
gc::State initialState = incrementalState; initialState = incrementalState;
bool useZeal = false;
#ifdef JS_GC_ZEAL #ifdef JS_GC_ZEAL
if (reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited()) { /*
/* * Do the incremental collection type specified by zeal mode if the
* Do the incremental collection type specified by zeal mode if the * collection was triggered by runDebugGC() and incremental GC has not been
* collection was triggered by runDebugGC() and incremental GC has not * cancelled by resetIncrementalGC().
* been cancelled by resetIncrementalGC(). */
*/ useZeal = reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited();
useZeal = true; #else
} bool useZeal = false;
#endif #endif
MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental); MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
@ -6860,24 +6955,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
incrementalState = State::Sweep; incrementalState = State::Sweep;
/*
* This runs to completion, but we don't continue if the budget is
* now exhasted.
*/
beginSweepPhase(reason, lock); beginSweepPhase(reason, lock);
if (budget.isOverBudget())
break;
/*
* Always yield here when running in incremental multi-slice zeal
* mode, so RunDebugGC can reset the slice buget.
*/
if (isIncremental && useZeal &&
(hasZealMode(ZealMode::IncrementalMultipleSlices) ||
hasZealMode(ZealMode::IncrementalSweepThenFinish)))
{
break;
}
MOZ_FALLTHROUGH; MOZ_FALLTHROUGH;
@ -6956,6 +7034,8 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
incrementalState = State::NotActive; incrementalState = State::NotActive;
break; break;
} }
MOZ_ASSERT(safeToYield);
} }
gc::AbortReason gc::AbortReason

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

@ -437,11 +437,11 @@ class GCZonesIter
typedef CompartmentsIterT<GCZonesIter> GCCompartmentsIter; typedef CompartmentsIterT<GCZonesIter> GCCompartmentsIter;
/* Iterates over all zones in the current sweep group. */ /* Iterates over all zones in the current sweep group. */
class GCSweepGroupIter { class SweepGroupZonesIter {
JS::Zone* current; JS::Zone* current;
public: public:
explicit GCSweepGroupIter(JSRuntime* rt) { explicit SweepGroupZonesIter(JSRuntime* rt) {
MOZ_ASSERT(CurrentThreadIsPerformingGC()); MOZ_ASSERT(CurrentThreadIsPerformingGC());
current = rt->gc.getCurrentSweepGroup(); current = rt->gc.getCurrentSweepGroup();
} }
@ -462,7 +462,7 @@ class GCSweepGroupIter {
JS::Zone* operator->() const { return get(); } JS::Zone* operator->() const { return get(); }
}; };
typedef CompartmentsIterT<GCSweepGroupIter> GCCompartmentGroupIter; typedef CompartmentsIterT<SweepGroupZonesIter> SweepGroupCompartmentsIter;
inline void inline void
RelocationOverlay::forwardTo(Cell* cell) RelocationOverlay::forwardTo(Cell* cell)

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

@ -12,6 +12,7 @@
*/ */
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/EndianUtils.h"
#include "jsbytecode.h" #include "jsbytecode.h"
#include "jstypes.h" #include "jstypes.h"
@ -136,17 +137,26 @@ UINT16_LO(uint16_t i)
static MOZ_ALWAYS_INLINE uint16_t static MOZ_ALWAYS_INLINE uint16_t
GET_UINT16(const jsbytecode* pc) GET_UINT16(const jsbytecode* pc)
{ {
return uint16_t((pc[1] << 8) | pc[2]); #if MOZ_LITTLE_ENDIAN
uint16_t result;
memcpy(&result, pc + 1, sizeof(result));
return result;
#else
return uint16_t((pc[2] << 8) | pc[1]);
#endif
} }
static MOZ_ALWAYS_INLINE void static MOZ_ALWAYS_INLINE void
SET_UINT16(jsbytecode* pc, uint16_t i) SET_UINT16(jsbytecode* pc, uint16_t i)
{ {
pc[1] = UINT16_HI(i); #if MOZ_LITTLE_ENDIAN
pc[2] = UINT16_LO(i); memcpy(pc + 1, &i, sizeof(i));
#else
pc[1] = UINT16_LO(i);
pc[2] = UINT16_HI(i);
#endif
} }
static const unsigned UINT16_LEN = 2;
static const unsigned UINT16_LIMIT = 1 << 16; static const unsigned UINT16_LIMIT = 1 << 16;
/* Helpers for accessing the offsets of jump opcodes. */ /* Helpers for accessing the offsets of jump opcodes. */
@ -154,69 +164,32 @@ static const unsigned JUMP_OFFSET_LEN = 4;
static const int32_t JUMP_OFFSET_MIN = INT32_MIN; static const int32_t JUMP_OFFSET_MIN = INT32_MIN;
static const int32_t JUMP_OFFSET_MAX = INT32_MAX; static const int32_t JUMP_OFFSET_MAX = INT32_MAX;
static MOZ_ALWAYS_INLINE int32_t
GET_JUMP_OFFSET(jsbytecode* pc)
{
return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
}
static MOZ_ALWAYS_INLINE void
SET_JUMP_OFFSET(jsbytecode* pc, int32_t off)
{
pc[1] = jsbytecode(off >> 24);
pc[2] = jsbytecode(off >> 16);
pc[3] = jsbytecode(off >> 8);
pc[4] = jsbytecode(off);
}
static const unsigned UINT32_INDEX_LEN = 4;
static MOZ_ALWAYS_INLINE uint32_t static MOZ_ALWAYS_INLINE uint32_t
GET_UINT32_INDEX(const jsbytecode* pc)
{
return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
}
static MOZ_ALWAYS_INLINE void
SET_UINT32_INDEX(jsbytecode* pc, uint32_t index)
{
pc[1] = jsbytecode(index >> 24);
pc[2] = jsbytecode(index >> 16);
pc[3] = jsbytecode(index >> 8);
pc[4] = jsbytecode(index);
}
static inline jsbytecode
UINT24_HI(unsigned i)
{
return jsbytecode(i >> 16);
}
static inline jsbytecode
UINT24_MID(unsigned i)
{
return jsbytecode(i >> 8);
}
static inline jsbytecode
UINT24_LO(unsigned i)
{
return jsbytecode(i);
}
static MOZ_ALWAYS_INLINE unsigned
GET_UINT24(const jsbytecode* pc) GET_UINT24(const jsbytecode* pc)
{ {
return unsigned((pc[1] << 16) | (pc[2] << 8) | pc[3]); #if MOZ_LITTLE_ENDIAN
// Do a single 32-bit load (for opcode and operand), then shift off the
// opcode.
uint32_t result;
memcpy(&result, pc, 4);
return result >> 8;
#else
return unsigned((pc[3] << 16) | (pc[2] << 8) | pc[1]);
#endif
} }
static MOZ_ALWAYS_INLINE void static MOZ_ALWAYS_INLINE void
SET_UINT24(jsbytecode* pc, unsigned i) SET_UINT24(jsbytecode* pc, uint32_t i)
{ {
MOZ_ASSERT(i < (1 << 24)); MOZ_ASSERT(i < (1 << 24));
pc[1] = UINT24_HI(i);
pc[2] = UINT24_MID(i); #if MOZ_LITTLE_ENDIAN
pc[3] = UINT24_LO(i); memcpy(pc + 1, &i, 3);
#else
pc[1] = jsbytecode(i);
pc[2] = jsbytecode(i >> 8);
pc[3] = jsbytecode(i >> 16);
#endif
} }
static MOZ_ALWAYS_INLINE int8_t static MOZ_ALWAYS_INLINE int8_t
@ -228,19 +201,29 @@ GET_INT8(const jsbytecode* pc)
static MOZ_ALWAYS_INLINE uint32_t static MOZ_ALWAYS_INLINE uint32_t
GET_UINT32(const jsbytecode* pc) GET_UINT32(const jsbytecode* pc)
{ {
return (uint32_t(pc[1]) << 24) | #if MOZ_LITTLE_ENDIAN
(uint32_t(pc[2]) << 16) | uint32_t result;
(uint32_t(pc[3]) << 8) | memcpy(&result, pc + 1, sizeof(result));
uint32_t(pc[4]); return result;
#else
return (uint32_t(pc[4]) << 24) |
(uint32_t(pc[3]) << 16) |
(uint32_t(pc[2]) << 8) |
uint32_t(pc[1]);
#endif
} }
static MOZ_ALWAYS_INLINE void static MOZ_ALWAYS_INLINE void
SET_UINT32(jsbytecode* pc, uint32_t u) SET_UINT32(jsbytecode* pc, uint32_t u)
{ {
pc[1] = jsbytecode(u >> 24); #if MOZ_LITTLE_ENDIAN
pc[2] = jsbytecode(u >> 16); memcpy(pc + 1, &u, sizeof(u));
pc[3] = jsbytecode(u >> 8); #else
pc[4] = jsbytecode(u); pc[1] = jsbytecode(u);
pc[2] = jsbytecode(u >> 8);
pc[3] = jsbytecode(u >> 16);
pc[4] = jsbytecode(u >> 24);
#endif
} }
static MOZ_ALWAYS_INLINE int32_t static MOZ_ALWAYS_INLINE int32_t
@ -255,6 +238,32 @@ SET_INT32(jsbytecode* pc, int32_t i)
SET_UINT32(pc, static_cast<uint32_t>(i)); SET_UINT32(pc, static_cast<uint32_t>(i));
} }
static MOZ_ALWAYS_INLINE int32_t
GET_JUMP_OFFSET(jsbytecode* pc)
{
return GET_INT32(pc);
}
static MOZ_ALWAYS_INLINE void
SET_JUMP_OFFSET(jsbytecode* pc, int32_t off)
{
SET_INT32(pc, off);
}
static const unsigned UINT32_INDEX_LEN = 4;
static MOZ_ALWAYS_INLINE uint32_t
GET_UINT32_INDEX(const jsbytecode* pc)
{
return GET_UINT32(pc);
}
static MOZ_ALWAYS_INLINE void
SET_UINT32_INDEX(jsbytecode* pc, uint32_t index)
{
SET_UINT32(pc, index);
}
/* Index limit is determined by SN_4BYTE_OFFSET_FLAG, see frontend/BytecodeEmitter.h. */ /* Index limit is determined by SN_4BYTE_OFFSET_FLAG, see frontend/BytecodeEmitter.h. */
static const unsigned INDEX_LIMIT_LOG2 = 31; static const unsigned INDEX_LIMIT_LOG2 = 31;
static const uint32_t INDEX_LIMIT = uint32_t(1) << INDEX_LIMIT_LOG2; static const uint32_t INDEX_LIMIT = uint32_t(1) << INDEX_LIMIT_LOG2;

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

@ -10,6 +10,7 @@
#include "mozilla/Alignment.h" #include "mozilla/Alignment.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
#include "mozilla/OperatorNewExtensions.h"
#include "threading/ConditionVariable.h" #include "threading/ConditionVariable.h"
#include "threading/Mutex.h" #include "threading/Mutex.h"
@ -99,7 +100,7 @@ class ExclusiveData
explicit ExclusiveData(const MutexId& id, U&& u) explicit ExclusiveData(const MutexId& id, U&& u)
: lock_(id) : lock_(id)
{ {
new (value_.addr()) T(mozilla::Forward<U>(u)); new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Forward<U>(u));
} }
/** /**
@ -109,7 +110,7 @@ class ExclusiveData
explicit ExclusiveData(const MutexId& id, Args&&... args) explicit ExclusiveData(const MutexId& id, Args&&... args)
: lock_(id) : lock_(id)
{ {
new (value_.addr()) T(mozilla::Forward<Args>(args)...); new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Forward<Args>(args)...);
} }
~ExclusiveData() { ~ExclusiveData() {
@ -122,12 +123,12 @@ class ExclusiveData
lock_(mozilla::Move(rhs.lock)) lock_(mozilla::Move(rhs.lock))
{ {
MOZ_ASSERT(&rhs != this, "self-move disallowed!"); MOZ_ASSERT(&rhs != this, "self-move disallowed!");
new (value_.addr()) T(mozilla::Move(*rhs.value_.addr())); new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Move(*rhs.value_.addr()));
} }
ExclusiveData& operator=(ExclusiveData&& rhs) { ExclusiveData& operator=(ExclusiveData&& rhs) {
this->~ExclusiveData(); this->~ExclusiveData();
new (this) ExclusiveData(mozilla::Move(rhs)); new (mozilla::KnownNotNull, this) ExclusiveData(mozilla::Move(rhs));
return *this; return *this;
} }

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

@ -265,7 +265,7 @@ class ElementSpecific
} }
// Inhibit unaligned accesses on ARM (bug 1097253, a compiler bug). // Inhibit unaligned accesses on ARM (bug 1097253, a compiler bug).
#ifdef __arm__ #if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
# define JS_VOLATILE_ARM volatile # define JS_VOLATILE_ARM volatile
#else #else
# define JS_VOLATILE_ARM # define JS_VOLATILE_ARM

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

@ -246,6 +246,7 @@ static const unsigned PushedFP = 5;
static const unsigned SetFP = 8; static const unsigned SetFP = 8;
static const unsigned PoppedFP = 4; static const unsigned PoppedFP = 4;
static const unsigned PoppedExitReason = 2; static const unsigned PoppedExitReason = 2;
static const unsigned PoppedTLSReg = 0;
#elif defined(JS_CODEGEN_X86) #elif defined(JS_CODEGEN_X86)
static const unsigned PushedRetAddr = 0; static const unsigned PushedRetAddr = 0;
static const unsigned PushedTLS = 1; static const unsigned PushedTLS = 1;
@ -254,6 +255,7 @@ static const unsigned PushedFP = 4;
static const unsigned SetFP = 6; static const unsigned SetFP = 6;
static const unsigned PoppedFP = 2; static const unsigned PoppedFP = 2;
static const unsigned PoppedExitReason = 1; static const unsigned PoppedExitReason = 1;
static const unsigned PoppedTLSReg = 0;
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM)
static const unsigned BeforePushRetAddr = 0; static const unsigned BeforePushRetAddr = 0;
static const unsigned PushedRetAddr = 4; static const unsigned PushedRetAddr = 4;
@ -263,6 +265,7 @@ static const unsigned PushedFP = 20;
static const unsigned SetFP = 24; static const unsigned SetFP = 24;
static const unsigned PoppedFP = 8; static const unsigned PoppedFP = 8;
static const unsigned PoppedExitReason = 4; static const unsigned PoppedExitReason = 4;
static const unsigned PoppedTLSReg = 0;
#elif defined(JS_CODEGEN_ARM64) #elif defined(JS_CODEGEN_ARM64)
static const unsigned BeforePushRetAddr = 0; static const unsigned BeforePushRetAddr = 0;
static const unsigned PushedRetAddr = 0; static const unsigned PushedRetAddr = 0;
@ -272,6 +275,7 @@ static const unsigned PushedFP = 0;
static const unsigned SetFP = 0; static const unsigned SetFP = 0;
static const unsigned PoppedFP = 0; static const unsigned PoppedFP = 0;
static const unsigned PoppedExitReason = 0; static const unsigned PoppedExitReason = 0;
static const unsigned PoppedTLSReg = 0;
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
static const unsigned BeforePushRetAddr = 0; static const unsigned BeforePushRetAddr = 0;
static const unsigned PushedRetAddr = 8; static const unsigned PushedRetAddr = 8;
@ -279,8 +283,9 @@ static const unsigned PushedTLS = 16;
static const unsigned PushedExitReason = 28; static const unsigned PushedExitReason = 28;
static const unsigned PushedFP = 36; static const unsigned PushedFP = 36;
static const unsigned SetFP = 40; static const unsigned SetFP = 40;
static const unsigned PoppedFP = 16; static const unsigned PoppedFP = 24;
static const unsigned PoppedExitReason = 8; static const unsigned PoppedExitReason = 16;
static const unsigned PoppedTLSReg = 8;
#elif defined(JS_CODEGEN_NONE) #elif defined(JS_CODEGEN_NONE)
static const unsigned PushedRetAddr = 0; static const unsigned PushedRetAddr = 0;
static const unsigned PushedTLS = 1; static const unsigned PushedTLS = 1;
@ -289,6 +294,7 @@ static const unsigned PushedFP = 0;
static const unsigned SetFP = 0; static const unsigned SetFP = 0;
static const unsigned PoppedFP = 0; static const unsigned PoppedFP = 0;
static const unsigned PoppedExitReason = 0; static const unsigned PoppedExitReason = 0;
static const unsigned PoppedTLSReg = 0;
#else #else
# error "Unknown architecture!" # error "Unknown architecture!"
#endif #endif
@ -448,11 +454,20 @@ GenerateCallableEpilogue(MacroAssembler& masm, unsigned framePushed, ExitReason
DebugOnly<uint32_t> poppedExitReason = masm.currentOffset(); DebugOnly<uint32_t> poppedExitReason = masm.currentOffset();
masm.pop(WasmTlsReg); masm.pop(WasmTlsReg);
DebugOnly<uint32_t> poppedTlsReg = masm.currentOffset();
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
masm.pop(ra);
*ret = masm.currentOffset();
masm.branch(ra);
#else
*ret = masm.currentOffset(); *ret = masm.currentOffset();
masm.ret(); masm.ret();
#endif
MOZ_ASSERT_IF(!masm.oom(), PoppedFP == *ret - poppedFP); MOZ_ASSERT_IF(!masm.oom(), PoppedFP == *ret - poppedFP);
MOZ_ASSERT_IF(!masm.oom(), PoppedExitReason == *ret - poppedExitReason); MOZ_ASSERT_IF(!masm.oom(), PoppedExitReason == *ret - poppedExitReason);
MOZ_ASSERT_IF(!masm.oom(), PoppedTLSReg == *ret - poppedTlsReg);
} }
void void
@ -734,7 +749,21 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
case CodeRange::BuiltinThunk: case CodeRange::BuiltinThunk:
case CodeRange::TrapExit: case CodeRange::TrapExit:
case CodeRange::DebugTrap: case CodeRange::DebugTrap:
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) #if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
if ((offsetFromEntry >= BeforePushRetAddr && offsetFromEntry < PushedFP) || codeRange->isThunk()) {
// See BUG 1407986.
// On MIPS push is emulated by two instructions: adjusting the sp
// and storing the value to sp.
// Execution might be interrupted in between the two operation so we
// have to relay on register state instead of state saved on stack
// until the wasm::Frame is completely built.
// On entry the return address is in ra (registers.lr) and
// fp holds the caller's fp.
fixedPC = (uint8_t*) registers.lr;
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
} else
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) { if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) {
// The return address is still in lr and fp holds the caller's fp. // The return address is still in lr and fp holds the caller's fp.
fixedPC = (uint8_t*) registers.lr; fixedPC = (uint8_t*) registers.lr;
@ -766,24 +795,45 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress; fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress;
fixedFP = fp; fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP); AssertMatchesCallSite(activation, fixedPC, fixedFP);
} else if (offsetInCode == codeRange->ret() - PoppedFP) { } else if (offsetInCode >= codeRange->ret() - PoppedFP &&
offsetInCode < codeRange->ret() - PoppedExitReason)
{
// The fixedFP field of the Frame has been popped into fp, but the // The fixedFP field of the Frame has been popped into fp, but the
// exit reason hasn't been popped yet. // exit reason hasn't been popped yet.
fixedPC = sp[2]; fixedPC = sp[2];
fixedFP = fp; fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP); AssertMatchesCallSite(activation, fixedPC, fixedFP);
} else if (offsetInCode == codeRange->ret() - PoppedExitReason) { } else if (offsetInCode >= codeRange->ret() - PoppedExitReason &&
offsetInCode < codeRange->ret() - PoppedTLSReg)
{
// The fixedFP field of the Frame has been popped into fp, and the // The fixedFP field of the Frame has been popped into fp, and the
// exit reason has been popped. // exit reason has been popped.
fixedPC = sp[1]; fixedPC = sp[1];
fixedFP = fp; fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP); AssertMatchesCallSite(activation, fixedPC, fixedFP);
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
} else if (offsetInCode >= codeRange->ret() - PoppedTLSReg &&
offsetInCode < codeRange->ret())
{
// The fixedFP field of the Frame has been popped into fp, but the
// exit reason hasn't been popped yet.
fixedPC = sp[0];
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
} else if (offsetInCode == codeRange->ret()) {
// Both the TLS, fixedFP and ra have been popped and fp now
// points to the caller's frame.
fixedPC = (uint8_t*) registers.lr;;
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
#else
} else if (offsetInCode == codeRange->ret()) { } else if (offsetInCode == codeRange->ret()) {
// Both the TLS and fixedFP fields have been popped and fp now // Both the TLS and fixedFP fields have been popped and fp now
// points to the caller's frame. // points to the caller's frame.
fixedPC = sp[0]; fixedPC = sp[0];
fixedFP = fp; fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP); AssertMatchesCallSite(activation, fixedPC, fixedFP);
#endif
} else { } else {
if (codeRange->kind() == CodeRange::ImportJitExit) { if (codeRange->kind() == CodeRange::ImportJitExit) {
// The jit exit contains a range where the value of FP can't be // The jit exit contains a range where the value of FP can't be

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

@ -173,6 +173,7 @@ class AutoSetHandlingSegFault
# define EPC_sig(p) ((p)->uc_mcontext.pc) # define EPC_sig(p) ((p)->uc_mcontext.pc)
# define RFP_sig(p) ((p)->uc_mcontext.gregs[30]) # define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29]) # define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
# define R31_sig(p) ((p)->uc_mcontext.gregs[31])
# endif # endif
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
# define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i]) # define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
@ -418,6 +419,7 @@ struct macos_arm_context {
# define PC_sig(p) EPC_sig(p) # define PC_sig(p) EPC_sig(p)
# define FP_sig(p) RFP_sig(p) # define FP_sig(p) RFP_sig(p)
# define SP_sig(p) RSP_sig(p) # define SP_sig(p) RSP_sig(p)
# define LR_sig(p) R31_sig(p)
#endif #endif
static uint8_t** static uint8_t**
@ -447,7 +449,7 @@ ContextToSP(CONTEXT* context)
return reinterpret_cast<uint8_t*>(SP_sig(context)); return reinterpret_cast<uint8_t*>(SP_sig(context));
} }
# if defined(__arm__) || defined(__aarch64__) # if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
static uint8_t* static uint8_t*
ContextToLR(CONTEXT* context) ContextToLR(CONTEXT* context)
{ {
@ -538,7 +540,7 @@ ToRegisterState(CONTEXT* context)
state.fp = ContextToFP(context); state.fp = ContextToFP(context);
state.pc = *ContextToPC(context); state.pc = *ContextToPC(context);
state.sp = ContextToSP(context); state.sp = ContextToSP(context);
# if defined(__arm__) || defined(__aarch64__) # if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
state.lr = ContextToLR(context); state.lr = ContextToLR(context);
# endif # endif
return state; return state;

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

@ -1404,7 +1404,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
// This will call back into OnStreamComplete // This will call back into OnStreamComplete
// and thence to ParseSheet. Regardless of whether this fails, // and thence to ParseSheet. Regardless of whether this fails,
// SheetComplete has been called. // SheetComplete has been called.
return nsSyncLoadService::PushSyncStreamToListener(stream, return nsSyncLoadService::PushSyncStreamToListener(stream.forget(),
streamLoader, streamLoader,
channel); channel);
} }

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

@ -26,7 +26,7 @@ void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine, const
vprintf(format, args); vprintf(format, args);
#else #else
mozilla::LogLevel level = static_cast<mozilla::LogLevel>(priority); mozilla::LogLevel level = static_cast<mozilla::LogLevel>(static_cast<unsigned int>(priority));
// Skip doing any of this work if we're not logging the indicated level... // Skip doing any of this work if we're not logging the indicated level...
if (!MOZ_LOG_TEST(gSignalingLog, level)) { if (!MOZ_LOG_TEST(gSignalingLog, level)) {
@ -82,6 +82,6 @@ void CSFLog( CSFLogLevel priority, const char* sourceFile, int sourceLine, const
int CSFLogTestLevel(CSFLogLevel priority) int CSFLogTestLevel(CSFLogLevel priority)
{ {
mozilla::LogLevel level = static_cast<mozilla::LogLevel>(priority); return MOZ_LOG_TEST(gSignalingLog,
return MOZ_LOG_TEST(gSignalingLog, level); static_cast<mozilla::LogLevel>(static_cast<unsigned int>(priority)));
} }

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

@ -510,6 +510,9 @@ public class CustomTabsActivity extends AppCompatActivity
* Callback for Open-in menu item. * Callback for Open-in menu item.
*/ */
private void onOpenInClicked() { private void onOpenInClicked() {
if (TextUtils.isEmpty(mCurrentUrl)) {
return;
}
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.setData(Uri.parse(mCurrentUrl)); intent.setData(Uri.parse(mCurrentUrl));
intent.setAction(Intent.ACTION_VIEW); intent.setAction(Intent.ACTION_VIEW);

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

@ -1216,7 +1216,7 @@ PREF_RegisterCallback(const char* aPrefNode,
NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr"); NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
NS_PRECONDITION(aCallback, "aCallback must not be nullptr"); NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
auto node = new CallbackNode(); auto node = (CallbackNode*)moz_xmalloc(sizeof(CallbackNode));
node->mDomain = moz_xstrdup(aPrefNode); node->mDomain = moz_xstrdup(aPrefNode);
node->mFunc = aCallback; node->mFunc = aCallback;
node->mData = aData; node->mData = aData;
@ -2975,7 +2975,7 @@ nsPrefBranch::GetChildList(const char* aStartingAt,
numPrefs = prefArray.Length(); numPrefs = prefArray.Length();
if (numPrefs) { if (numPrefs) {
outArray = new char*[numPrefs]; outArray = (char**)moz_xmalloc(numPrefs * sizeof(char*));
for (dwIndex = 0; dwIndex < numPrefs; ++dwIndex) { for (dwIndex = 0; dwIndex < numPrefs; ++dwIndex) {
// we need to lop off mPrefRoot in case the user is planning to pass this // we need to lop off mPrefRoot in case the user is planning to pass this

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

@ -727,8 +727,9 @@ nsInputStreamPump::CreateBufferedStreamIfNeeded()
return NS_OK; return NS_OK;
} }
nsCOMPtr<nsIAsyncInputStream> stream = mAsyncStream;
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream), nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
mAsyncStream, 4096); stream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return NS_OK; return NS_OK;

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

@ -1370,38 +1370,24 @@ NS_BufferOutputStream(nsIOutputStream *aOutputStream,
} }
MOZ_MUST_USE nsresult MOZ_MUST_USE nsresult
NS_NewBufferedInputStream(nsIInputStream **result, NS_NewBufferedInputStream(nsIInputStream** aResult,
nsIInputStream *str, already_AddRefed<nsIInputStream> aInputStream,
uint32_t bufferSize) uint32_t aBufferSize)
{ {
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
nsresult rv; nsresult rv;
nsCOMPtr<nsIBufferedInputStream> in = nsCOMPtr<nsIBufferedInputStream> in =
do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv); do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = in->Init(str, bufferSize); rv = in->Init(inputStream, aBufferSize);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
in.forget(result); in.forget(aResult);
} }
} }
return rv; return rv;
} }
already_AddRefed<nsIInputStream>
NS_BufferInputStream(nsIInputStream *aInputStream,
uint32_t aBufferSize)
{
NS_ASSERTION(aInputStream, "No input stream given!");
nsCOMPtr<nsIInputStream> bis;
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bis), aInputStream,
aBufferSize);
if (NS_SUCCEEDED(rv))
return bis.forget();
bis = aInputStream;
return bis.forget();
}
nsresult nsresult
NS_NewPostDataStream(nsIInputStream **result, NS_NewPostDataStream(nsIInputStream **result,
bool isFile, bool isFile,
@ -1418,7 +1404,8 @@ NS_NewPostDataStream(nsIInputStream **result,
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file); rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
// wrap the file stream with a buffered input stream // wrap the file stream with a buffered input stream
rv = NS_NewBufferedInputStream(result, fileStream, 8192); rv = NS_NewBufferedInputStream(result, fileStream.forget(),
8192);
} }
} }
return rv; return rv;

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

@ -511,9 +511,9 @@ nsresult NS_NewLocalFileStream(nsIFileStream **result,
int32_t behaviorFlags = 0); int32_t behaviorFlags = 0);
MOZ_MUST_USE nsresult MOZ_MUST_USE nsresult
NS_NewBufferedInputStream(nsIInputStream **result, NS_NewBufferedInputStream(nsIInputStream** aResult,
nsIInputStream *str, already_AddRefed<nsIInputStream> aInputStream,
uint32_t bufferSize); uint32_t aBufferSize);
// note: the resulting stream can be QI'ed to nsISafeOutputStream iff the // note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
// provided stream supports it. // provided stream supports it.
@ -535,9 +535,6 @@ nsresult NS_NewBufferedOutputStream(nsIOutputStream **result,
already_AddRefed<nsIOutputStream> already_AddRefed<nsIOutputStream>
NS_BufferOutputStream(nsIOutputStream *aOutputStream, NS_BufferOutputStream(nsIOutputStream *aOutputStream,
uint32_t aBufferSize); uint32_t aBufferSize);
already_AddRefed<nsIInputStream>
NS_BufferInputStream(nsIInputStream *aInputStream,
uint32_t aBufferSize);
// returns an input stream compatible with nsIUploadChannel::SetUploadStream() // returns an input stream compatible with nsIUploadChannel::SetUploadStream()
nsresult NS_NewPostDataStream(nsIInputStream **result, nsresult NS_NewPostDataStream(nsIInputStream **result,

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

@ -929,7 +929,8 @@ HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
if (NS_InputStreamIsBuffered(mUploadStream)) { if (NS_InputStreamIsBuffered(mUploadStream)) {
source = mUploadStream; source = mUploadStream;
} else { } else {
rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096); rv = NS_NewBufferedInputStream(getter_AddRefs(source),
mUploadStream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

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

@ -383,7 +383,8 @@ nsHttpTransaction::Init(uint32_t caps,
// that we write data in the largest chunks possible. this is actually // that we write data in the largest chunks possible. this is actually
// necessary to workaround some common server bugs (see bug 137155). // necessary to workaround some common server bugs (see bug 137155).
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi)); nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi));
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), stream, rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream),
stream.forget(),
nsIOService::gDefaultSegmentSize); nsIOService::gDefaultSegmentSize);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} else { } else {

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

@ -16,12 +16,12 @@
#include "nsEscape.h" #include "nsEscape.h"
#include "nsIDirIndex.h" #include "nsIDirIndex.h"
#include "nsURLHelper.h" #include "nsURLHelper.h"
#include "nsIPlatformCharset.h"
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "nsIPrefBranch.h" #include "nsIPrefBranch.h"
#include "nsIPrefLocalizedString.h" #include "nsIPrefLocalizedString.h"
#include "nsIStringBundle.h" #include "nsIStringBundle.h"
#include "nsITextToSubURI.h" #include "nsITextToSubURI.h"
#include "nsNativeCharsetUtils.h"
#include "nsString.h" #include "nsString.h"
#include <algorithm> #include <algorithm>
#include "nsIChannel.h" #include "nsIChannel.h"
@ -500,13 +500,10 @@ nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
// 1. file URL may be encoded in platform charset for backward compatibility // 1. file URL may be encoded in platform charset for backward compatibility
// 2. query part may not be encoded in UTF-8 (see bug 261929) // 2. query part may not be encoded in UTF-8 (see bug 261929)
// so try the platform's default if this is file url // so try the platform's default if this is file url
if (NS_FAILED(rv) && isSchemeFile) { if (NS_FAILED(rv) && isSchemeFile && !NS_IsNativeUTF8()) {
nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv)); auto encoding = mozilla::dom::FallbackEncoding::FromLocale();
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString charset; nsAutoCString charset;
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset); encoding->Name(charset);
NS_ENSURE_SUCCESS(rv, rv);
rv = mTextToSubURI->UnEscapeAndConvert(charset, titleUri, unEscapeSpec); rv = mTextToSubURI->UnEscapeAndConvert(charset, titleUri, unEscapeSpec);
} }
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;

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

@ -474,24 +474,25 @@ nsSAXXMLReader::ParseFromString(const nsAString &aStr,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, nsSAXXMLReader::ParseFromStream(nsIInputStream *aStreamPtr,
const char *aCharset, const char *aCharset,
const char *aContentType) const char *aContentType)
{ {
// Don't call this in the middle of an async parse // Don't call this in the middle of an async parse
NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
NS_ENSURE_ARG(aStream); NS_ENSURE_ARG(aStreamPtr);
NS_ENSURE_ARG(aContentType); NS_ENSURE_ARG(aContentType);
// Put the nsCOMPtr out here so we hold a ref to the stream as needed // Put the nsCOMPtr out here so we hold a ref to the stream as needed
nsresult rv; nsresult rv;
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> stream = aStreamPtr;
if (!NS_InputStreamIsBuffered(aStream)) { if (!NS_InputStreamIsBuffered(stream)) {
nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
aStream, 4096); stream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
aStream = bufferedStream; stream = bufferedStream;
} }
rv = EnsureBaseURI(); rv = EnsureBaseURI();
@ -504,7 +505,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
nsCOMPtr<nsIChannel> parserChannel; nsCOMPtr<nsIChannel> parserChannel;
rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
mBaseURI, mBaseURI,
aStream, stream,
nullPrincipal, nullPrincipal,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED, nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
nsIContentPolicy::TYPE_OTHER, nsIContentPolicy::TYPE_OTHER,
@ -536,7 +537,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
uint64_t offset = 0; uint64_t offset = 0;
while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
uint64_t available; uint64_t available;
rv = aStream->Available(&available); rv = stream->Available(&available);
if (rv == NS_BASE_STREAM_CLOSED) { if (rv == NS_BASE_STREAM_CLOSED) {
rv = NS_OK; rv = NS_OK;
available = 0; available = 0;
@ -552,7 +553,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
available = UINT32_MAX; available = UINT32_MAX;
rv = mListener->OnDataAvailable(parserChannel, nullptr, rv = mListener->OnDataAvailable(parserChannel, nullptr,
aStream, stream,
offset, offset,
(uint32_t)available); (uint32_t)available);
if (NS_SUCCEEDED(rv)) if (NS_SUCCEEDED(rv))

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

@ -497,7 +497,7 @@ RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
// Wrap the channel's input stream in a buffered stream to ensure that // Wrap the channel's input stream in a buffered stream to ensure that
// ReadSegments is implemented (which OnDataAvailable expects). // ReadSegments is implemented (which OnDataAvailable expects).
nsCOMPtr<nsIInputStream> bufStream; nsCOMPtr<nsIInputStream> bufStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in, rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in.forget(),
4096 /* buffer size */); 4096 /* buffer size */);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;

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

@ -1001,12 +1001,15 @@ this.BrowserTestUtils = {
* True if it is expected that the tab crashed page will be shown * True if it is expected that the tab crashed page will be shown
* for this browser. If so, the Promise will only resolve once the * for this browser. If so, the Promise will only resolve once the
* tab crash page has loaded. * tab crash page has loaded.
* @param (bool) shouldClearMinidumps
* True if the minidumps left behind by the crash should be removed.
* *
* @returns (Promise) * @returns (Promise)
* @resolves An Object with key-value pairs representing the data from the * @resolves An Object with key-value pairs representing the data from the
* crash report's extra file (if applicable). * crash report's extra file (if applicable).
*/ */
async crashBrowser(browser, shouldShowTabCrashPage=true) { async crashBrowser(browser, shouldShowTabCrashPage=true,
shouldClearMinidumps=true) {
let extra = {}; let extra = {};
let KeyValueParser = {}; let KeyValueParser = {};
if (AppConstants.MOZ_CRASHREPORTER) { if (AppConstants.MOZ_CRASHREPORTER) {
@ -1107,8 +1110,10 @@ this.BrowserTestUtils = {
} }
} }
removeFile(minidumpDirectory, dumpID + '.dmp'); if (shouldClearMinidumps) {
removeFile(minidumpDirectory, dumpID + '.extra'); removeFile(minidumpDirectory, dumpID + '.dmp');
removeFile(minidumpDirectory, dumpID + '.extra');
}
}); });
} }

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

@ -638,8 +638,13 @@ TestRunner.testFinished = function(tests) {
} }
SpecialPowers.executeAfterFlushingMessageQueue(function() { SpecialPowers.executeAfterFlushingMessageQueue(function() {
cleanUpCrashDumpFiles(); SpecialPowers.waitForCrashes(TestRunner._expectingProcessCrash)
SpecialPowers.flushPermissions(function () { SpecialPowers.flushPrefEnv(runNextTest); }); .then(() => {
cleanUpCrashDumpFiles();
SpecialPowers.flushPermissions(function () {
SpecialPowers.flushPrefEnv(runNextTest);
});
});
}); });
}; };

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

@ -330,10 +330,23 @@ function expectedException(actual, expected) {
* 11. Expected to throw an error: * 11. Expected to throw an error:
* assert.throws(block, Error_opt, message_opt); * assert.throws(block, Error_opt, message_opt);
* *
* Example:
* ```js
* // The following will verify that an error of type TypeError was thrown:
* Assert.throws(() => testBody(), TypeError);
* // The following will verify that an error was thrown with an error message matching "hello":
* Assert.throws(() => testBody(), /hello/);
* // The following will verify that any error was thrown and will use "hello" in the test report:
* Assert.throws(() => testBody(), "hello");
* ```
*
* @param block * @param block
* (function) Function block to evaluate and catch eventual thrown errors * (function) Function block to evaluate and catch eventual thrown errors
* @param expected (optional) * @param expected (optional)
* (mixed) Test reference to evaluate against the thrown result from `block` * (mixed) This parameter can be either a RegExp, a function, or a string. The
* function is either the error type's constructor, or it's a method that returns a boolean
* that describes the test outcome. When string value is provided, it will be used as if it
* was provided as the message parameter.
* @param message (optional) * @param message (optional)
* (string) Short explanation of the expected result * (string) Short explanation of the expected result
*/ */
@ -473,4 +486,3 @@ proto.less = function less(lhs, rhs, message) {
proto.lessOrEqual = function lessOrEqual(lhs, rhs, message) { proto.lessOrEqual = function lessOrEqual(lhs, rhs, message) {
compareNumbers.call(this, lhs > rhs, lhs, rhs, message, "<="); compareNumbers.call(this, lhs > rhs, lhs, rhs, message, "<=");
}; };

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

@ -70,6 +70,7 @@ SpecialPowersObserver.prototype._loadFrameScript = function() {
if (!this._isFrameScriptLoaded) { if (!this._isFrameScriptLoaded) {
// Register for any messages our API needs us to handle // Register for any messages our API needs us to handle
this._messageManager.addMessageListener("SPPrefService", this); this._messageManager.addMessageListener("SPPrefService", this);
this._messageManager.addMessageListener("SPProcessCrashManagerWait", this);
this._messageManager.addMessageListener("SPProcessCrashService", this); this._messageManager.addMessageListener("SPProcessCrashService", this);
this._messageManager.addMessageListener("SPPingService", this); this._messageManager.addMessageListener("SPPingService", this);
this._messageManager.addMessageListener("SpecialPowers.Quit", this); this._messageManager.addMessageListener("SpecialPowers.Quit", this);
@ -140,6 +141,7 @@ SpecialPowersObserver.prototype.uninit = function() {
if (this._isFrameScriptLoaded) { if (this._isFrameScriptLoaded) {
this._messageManager.removeMessageListener("SPPrefService", this); this._messageManager.removeMessageListener("SPPrefService", this);
this._messageManager.removeMessageListener("SPProcessCrashManagerWait", this);
this._messageManager.removeMessageListener("SPProcessCrashService", this); this._messageManager.removeMessageListener("SPProcessCrashService", this);
this._messageManager.removeMessageListener("SPPingService", this); this._messageManager.removeMessageListener("SPPingService", this);
this._messageManager.removeMessageListener("SpecialPowers.Quit", this); this._messageManager.removeMessageListener("SpecialPowers.Quit", this);

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

@ -117,6 +117,10 @@ SpecialPowersObserverAPI.prototype = {
} }
} }
} else { // ipc:content-shutdown } else { // ipc:content-shutdown
if (!aSubject.hasKey("abnormal")) {
return; // This is a normal shutdown, ignore it
}
addDumpIDToMessage("dumpID"); addDumpIDToMessage("dumpID");
} }
this._sendAsyncMessage("SPProcessCrashService", message); this._sendAsyncMessage("SPProcessCrashService", message);
@ -393,6 +397,17 @@ SpecialPowersObserverAPI.prototype = {
return undefined; // See comment at the beginning of this function. return undefined; // See comment at the beginning of this function.
} }
case "SPProcessCrashManagerWait": {
let promises = aMessage.json.crashIds.map((crashId) => {
return Services.crashmanager.ensureCrashIsPresent(crashId);
});
Promise.all(promises).then(() => {
this._sendReply(aMessage, "SPProcessCrashManagerWait", {});
});
return undefined; // See comment at the beginning of this function.
}
case "SPPermissionManager": { case "SPPermissionManager": {
let msg = aMessage.json; let msg = aMessage.json;
let principal = msg.principal; let principal = msg.principal;

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

@ -49,6 +49,7 @@ function SpecialPowers(window) {
"SpecialPowers.RemoveFiles", "SpecialPowers.RemoveFiles",
"SPPingService", "SPPingService",
"SPLoadExtension", "SPLoadExtension",
"SPProcessCrashManagerWait",
"SPStartupExtension", "SPStartupExtension",
"SPUnloadExtension", "SPUnloadExtension",
"SPExtensionMessage"]; "SPExtensionMessage"];

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

@ -670,6 +670,31 @@ SpecialPowersAPI.prototype = {
return bindDOMWindowUtils(aWindow); return bindDOMWindowUtils(aWindow);
}, },
waitForCrashes(aExpectingProcessCrash) {
return new Promise((resolve, reject) => {
if (!aExpectingProcessCrash) {
resolve();
}
var crashIds = this._encounteredCrashDumpFiles.filter((filename) => {
return ((filename.length === 40) && filename.endsWith(".dmp"));
}).map((id) => {
return id.slice(0, -4); // Strip the .dmp extension to get the ID
});
let self = this;
function messageListener(msg) {
self._removeMessageListener("SPProcessCrashManagerWait", messageListener);
resolve();
}
this._addMessageListener("SPProcessCrashManagerWait", messageListener);
this._sendAsyncMessage("SPProcessCrashManagerWait", {
crashIds
});
});
},
removeExpectedCrashDumpFiles(aExpectingProcessCrash) { removeExpectedCrashDumpFiles(aExpectingProcessCrash) {
var success = true; var success = true;
if (aExpectingProcessCrash) { if (aExpectingProcessCrash) {

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

@ -6,7 +6,7 @@
#include <string> #include <string>
#include "common/linux/file_id.h" #include "common/linux/file_id.h"
#include "common/memory.h" #include "common/memory_allocator.h"
using std::string; using std::string;

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

@ -1295,7 +1295,7 @@ FetchAndConvertUnsupportedPayloads::ConvertPayload(int64_t aId,
// Decode the input stream to a surface. // Decode the input stream to a surface.
RefPtr<gfx::SourceSurface> surface = RefPtr<gfx::SourceSurface> surface =
image::ImageOps::DecodeToSurface(stream, image::ImageOps::DecodeToSurface(stream.forget(),
aMimeType, aMimeType,
imgIContainer::DECODE_FLAGS_DEFAULT); imgIContainer::DECODE_FLAGS_DEFAULT);
NS_ENSURE_STATE(surface); NS_ENSURE_STATE(surface);

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

@ -339,7 +339,9 @@ HashStore::Open()
} }
mFileSize = static_cast<uint32_t>(fileSize); mFileSize = static_cast<uint32_t>(fileSize);
mInputStream = NS_BufferInputStream(origStream, mFileSize); rv = NS_NewBufferedInputStream(getter_AddRefs(mInputStream),
origStream.forget(), mFileSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadHeader(); rv = ReadHeader();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

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

@ -239,7 +239,10 @@ VariableLengthPrefixSet::LoadFromFile(nsIFile* aFile)
MAX_BUFFER_SIZE); MAX_BUFFER_SIZE);
// Convert to buffered stream // Convert to buffered stream
nsCOMPtr<nsIInputStream> in = NS_BufferInputStream(localInFile, bufferSize); nsCOMPtr<nsIInputStream> in;
rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(),
bufferSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = mFixedPrefixSet->LoadPrefixes(in); rv = mFixedPrefixSet->LoadPrefixes(in);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

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

@ -352,7 +352,10 @@ nsUrlClassifierPrefixSet::LoadFromFile(nsIFile* aFile)
MAX_BUFFER_SIZE); MAX_BUFFER_SIZE);
// Convert to buffered stream // Convert to buffered stream
nsCOMPtr<nsIInputStream> in = NS_BufferInputStream(localInFile, bufferSize); nsCOMPtr<nsIInputStream> in;
rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(),
bufferSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = LoadPrefixes(in); rv = LoadPrefixes(in);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

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

@ -34,7 +34,7 @@
#include <sys/user.h> #include <sys/user.h>
#include "linux/dump_writer_common/raw_context_cpu.h" #include "linux/dump_writer_common/raw_context_cpu.h"
#include "common/memory.h" #include "common/memory_allocator.h"
#include "google_breakpad/common/minidump_format.h" #include "google_breakpad/common/minidump_format.h"
namespace google_breakpad { namespace google_breakpad {

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

@ -34,7 +34,7 @@
#include <sys/user.h> #include <sys/user.h>
#include "linux/dump_writer_common/raw_context_cpu.h" #include "linux/dump_writer_common/raw_context_cpu.h"
#include "common/memory.h" #include "common/memory_allocator.h"
#include "google_breakpad/common/minidump_format.h" #include "google_breakpad/common/minidump_format.h"
namespace google_breakpad { namespace google_breakpad {

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

@ -89,7 +89,7 @@
#include "common/basictypes.h" #include "common/basictypes.h"
#include "common/linux/linux_libc_support.h" #include "common/linux/linux_libc_support.h"
#include "common/memory.h" #include "common/memory_allocator.h"
#include "linux/log/log.h" #include "linux/log/log.h"
#include "linux/microdump_writer/microdump_writer.h" #include "linux/microdump_writer/microdump_writer.h"
#include "linux/minidump_writer/linux_dumper.h" #include "linux/minidump_writer/linux_dumper.h"

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