зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: Gc5JIILUrPi
This commit is contained in:
Коммит
20d769ea9c
|
@ -9,6 +9,8 @@
|
|||
#include "mozilla/a11y/HandlerProvider.h"
|
||||
|
||||
#include "Accessible2_3.h"
|
||||
#include "AccessibleTable.h"
|
||||
#include "AccessibleTable2.h"
|
||||
#include "HandlerData.h"
|
||||
#include "HandlerData_i.c"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
@ -214,6 +216,18 @@ HandlerProvider::MarshalAs(REFIID 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
|
||||
HandlerProvider::NewInstance(REFIID aIid,
|
||||
mscom::InterceptorTargetPtr<IUnknown> aTarget,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef mozilla_a11y_HandlerProvider_h
|
||||
#define mozilla_a11y_HandlerProvider_h
|
||||
|
||||
#include "handler/AccessibleHandler.h"
|
||||
#include "mozilla/a11y/AccessibleHandler.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/mscom/IHandlerProvider.h"
|
||||
|
@ -44,6 +44,8 @@ public:
|
|||
STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override;
|
||||
STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override;
|
||||
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
|
||||
STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
|
||||
ULONG aCallMethod) override;
|
||||
STDMETHODIMP NewInstance(REFIID aIid,
|
||||
mscom::InterceptorTargetPtr<IUnknown> aTarget,
|
||||
NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;
|
||||
|
|
|
@ -297,15 +297,28 @@ Sanitizer.prototype = {
|
|||
Services.obs.notifyObservers(null, "extension:purge-localStorage");
|
||||
|
||||
// ServiceWorkers
|
||||
let promises = [];
|
||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||
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
|
||||
let promises = [];
|
||||
promises = [];
|
||||
await new Promise(resolve => {
|
||||
quotaManagerService.getUsage(request => {
|
||||
if (request.resultCode != Cr.NS_OK) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* 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
|
||||
* 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
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
|
||||
// Bypass click-to-play
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
|
||||
|
||||
// Clear out any minidumps we create from plugins - we really don't care
|
||||
// about them.
|
||||
let crashObserver = (subject, topic, data) => {
|
||||
if (topic != "plugin-crashed") {
|
||||
return;
|
||||
}
|
||||
// Deferred promise object used by the test to wait for the crash handler
|
||||
let crashDeferred = null;
|
||||
|
||||
let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
|
||||
let minidumpID = propBag.getPropertyAsAString("pluginDumpID");
|
||||
// Clear out any minidumps we create from plugins - we really don't care
|
||||
// about them.
|
||||
let crashObserver = (subject, topic, data) => {
|
||||
if (topic != "plugin-crashed") {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => {
|
||||
let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
minidumpDir.append("minidumps");
|
||||
let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
|
||||
let minidumpID = propBag.getPropertyAsAString("pluginDumpID");
|
||||
|
||||
let pluginDumpFile = minidumpDir.clone();
|
||||
pluginDumpFile.append(minidumpID + ".dmp");
|
||||
Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => {
|
||||
let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
minidumpDir.append("minidumps");
|
||||
|
||||
let extraFile = minidumpDir.clone();
|
||||
extraFile.append(minidumpID + ".extra");
|
||||
let pluginDumpFile = minidumpDir.clone();
|
||||
pluginDumpFile.append(minidumpID + ".dmp");
|
||||
|
||||
ok(pluginDumpFile.exists(), "Found minidump");
|
||||
ok(extraFile.exists(), "Found extra file");
|
||||
let extraFile = minidumpDir.clone();
|
||||
extraFile.append(minidumpID + ".extra");
|
||||
|
||||
pluginDumpFile.remove(false);
|
||||
extraFile.remove(false);
|
||||
});
|
||||
};
|
||||
ok(pluginDumpFile.exists(), "Found minidump");
|
||||
ok(extraFile.exists(), "Found extra file");
|
||||
|
||||
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");
|
||||
pluginDumpFile.remove(false);
|
||||
extraFile.remove(false);
|
||||
crashDeferred.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
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.
|
||||
*/
|
||||
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
|
||||
// enabled by default.
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
|
||||
|
@ -183,12 +190,16 @@ add_task(async function testChromeHearsPluginCrashFirst() {
|
|||
"Should have been showing crash report UI");
|
||||
});
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await crashDeferred.promise;
|
||||
});
|
||||
|
||||
/**
|
||||
* In this case, the content process hears about the crash first.
|
||||
*/
|
||||
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
|
||||
// enabled by default.
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
|
||||
|
@ -253,4 +264,5 @@ add_task(async function testContentHearsCrashFirst() {
|
|||
});
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await crashDeferred.promise;
|
||||
});
|
||||
|
|
|
@ -34,7 +34,9 @@ add_task(async function test_clear_email() {
|
|||
prefs.setBoolPref("emailMe", true);
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
await BrowserTestUtils.crashBrowser(browser);
|
||||
await BrowserTestUtils.crashBrowser(browser,
|
||||
/* shouldShowTabCrashPage */ true,
|
||||
/* shouldClearMinidumps */ false);
|
||||
let doc = browser.contentDocument;
|
||||
|
||||
// Since about:tabcrashed will run in the parent process, we can safely
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Taken from upstream commit: 455e7e3f2de29113e37de8c03052de110f5fb106
|
||||
Taken from upstream commit: aa6b25cc7dc645b8c1d76af58b99012e40b80848
|
||||
|
||||
Packages:
|
||||
- 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
|
||||
* 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 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
@ -275,144 +410,10 @@
|
|||
padding-left: 3px;
|
||||
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 {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -423,13 +424,12 @@ body {
|
|||
}
|
||||
|
||||
.modal {
|
||||
top: 0;
|
||||
margin: auto;
|
||||
width: 500px;
|
||||
width: 80%;
|
||||
height: auto;
|
||||
overflow-y: scroll;
|
||||
background-color: var(--theme-toolbar-background);
|
||||
transform: translateY(-250px);
|
||||
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,
|
||||
|
@ -439,13 +439,24 @@ body {
|
|||
|
||||
.modal.entered,
|
||||
.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 {
|
||||
width: 80%;
|
||||
left: 10%;
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 340px) {
|
||||
.modal {
|
||||
height: auto;
|
||||
max-height: 80vh;
|
||||
}
|
||||
.modal.entered,
|
||||
.modal.exiting {
|
||||
transform: translateY(30px);
|
||||
}
|
||||
}
|
||||
.shortcuts-content {
|
||||
|
@ -490,10 +501,6 @@ body {
|
|||
width: calc(100% - 1px); /* 1px fixes the hidden right border */
|
||||
}
|
||||
|
||||
.shortcuts-modal {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.shortcuts-list li {
|
||||
font-size: 12px;
|
||||
color: var(--theme-body-color);
|
||||
|
@ -1696,10 +1703,10 @@ html .toggle-button-end.vertical svg {
|
|||
transition: opacity 200ms;
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 6px 0.7em;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.source-footer > .commands > .action i {
|
||||
.source-footer > .commands > .action img {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -1718,9 +1725,18 @@ html .toggle-button-end.vertical svg {
|
|||
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;
|
||||
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 {
|
||||
|
@ -1733,8 +1749,8 @@ html .toggle-button-end.vertical svg {
|
|||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.source-footer .black-box.blackboxed svg {
|
||||
fill: var(--theme-highlight-blue);
|
||||
.source-footer > .commands > .blackboxed > img.blackBox {
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.source-footer .blackbox-summary {
|
||||
|
@ -2188,12 +2204,19 @@ html[dir="rtl"] .arrow svg,
|
|||
box-shadow: 1px 2px 3px var(--popup-shadow-color);
|
||||
}
|
||||
|
||||
.popover .preview-popup .header {
|
||||
.popover .preview-popup .header-container {
|
||||
width: 100%;
|
||||
line-height: 20px;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
display: flex;
|
||||
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 {
|
||||
|
@ -2492,8 +2515,9 @@ html[dir="rtl"] .editor-mount {
|
|||
}
|
||||
|
||||
.CodeMirror-linenumber {
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.folding-enabled .CodeMirror-linenumber {
|
||||
|
@ -3149,6 +3173,18 @@ html .command-bar > button:disabled {
|
|||
.command-bar > button {
|
||||
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 {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -3373,13 +3409,13 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
fill: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.source-tab .prettyPrint {
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.source-tab .prettyPrint svg {
|
||||
.source-tab img.prettyPrint {
|
||||
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
padding-top: 12px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.source-tab .prettyPrint path {
|
||||
|
@ -3388,13 +3424,16 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
|
||||
.source-tab .blackBox,
|
||||
.source-tab .prettyPrint {
|
||||
line-height: 0;
|
||||
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;
|
||||
width: 12px;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.source-tab .blackBox path {
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -78,12 +78,201 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
/***/ 1282:
|
||||
/***/ (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__) {
|
||||
|
||||
"use strict";
|
||||
|
@ -93,19 +282,14 @@ var _prettyFast = __webpack_require__(802);
|
|||
|
||||
var _prettyFast2 = _interopRequireDefault(_prettyFast);
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(900);
|
||||
var _devtoolsUtils = __webpack_require__(1363);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
|
||||
const { workerHandler } = _devtoolsUtils.workerUtils;
|
||||
|
||||
|
||||
function prettyPrint(_ref) {
|
||||
var url = _ref.url,
|
||||
indent = _ref.indent,
|
||||
source = _ref.source;
|
||||
|
||||
var prettified = (0, _prettyFast2.default)(source, {
|
||||
function prettyPrint({ url, indent, source }) {
|
||||
const prettified = (0, _prettyFast2.default)(source, {
|
||||
url: url,
|
||||
indent: " ".repeat(indent)
|
||||
});
|
||||
|
@ -118,7 +302,7 @@ function prettyPrint(_ref) {
|
|||
|
||||
function invertMappings(mappings) {
|
||||
return mappings._array.map(m => {
|
||||
var mapping = {
|
||||
const mapping = {
|
||||
generated: {
|
||||
line: m.originalLine,
|
||||
column: m.originalColumn
|
||||
|
@ -7411,184 +7595,6 @@ SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSou
|
|||
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-toggling-tools.js]
|
||||
[browser_dbg-wasm-sourcemaps.js]
|
||||
skip-if = true
|
||||
skip-if = asan
|
||||
[browser_dbg-reload.js]
|
||||
|
|
|
@ -39,21 +39,21 @@ add_task(async function() {
|
|||
const dbg = await initDebugger("doc-scripts.html");
|
||||
await selectSource(dbg, "simple2");
|
||||
|
||||
dump('Adding a conditional Breakpoint\n')
|
||||
dump("Adding a conditional Breakpoint\n");
|
||||
await setConditionalBreakpoint(dbg, 5, "1");
|
||||
await waitForDispatch(dbg, "ADD_BREAKPOINT");
|
||||
let bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.condition, "1", "breakpoint is created with the condition");
|
||||
assertEditorBreakpoint(dbg, 5, true);
|
||||
|
||||
dump('Editing a conditional breakpoint\n')
|
||||
dump("Editing a conditional breakpoint\n");
|
||||
await setConditionalBreakpoint(dbg, 5, "2");
|
||||
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
|
||||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.condition, "12", "breakpoint is created with the condition");
|
||||
assertEditorBreakpoint(dbg, 5, true);
|
||||
|
||||
dump("Removing a conditional breakpoint\n")
|
||||
dump("Removing a conditional breakpoint\n");
|
||||
clickElement(dbg, "gutter", 5);
|
||||
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
|
||||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
* 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) {
|
||||
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() {
|
||||
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 waitForPaused(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
|
|
@ -362,11 +362,11 @@ function createDebuggerContext(toolbox) {
|
|||
store: store,
|
||||
client: client,
|
||||
toolbox: toolbox,
|
||||
win: win
|
||||
win: win,
|
||||
panel: panel
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear all the debugger related preferences.
|
||||
*/
|
||||
|
@ -511,7 +511,7 @@ function stepOut(dbg) {
|
|||
function resume(dbg) {
|
||||
info("Resuming");
|
||||
dbg.actions.resume();
|
||||
return waitForState(dbg, (state) => !dbg.selectors.isPaused(state));
|
||||
return waitForState(dbg, state => !dbg.selectors.isPaused(state));
|
||||
}
|
||||
|
||||
function deleteExpression(dbg, input) {
|
||||
|
|
|
@ -299,3 +299,5 @@ devtools.jar:
|
|||
|
||||
# Debugger
|
||||
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.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
|
||||
# context menu to copy the function the user selected
|
||||
copyFunction.label=Copy function
|
||||
|
@ -367,6 +372,7 @@ editor.addBreakpoint=Add breakpoint
|
|||
# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item
|
||||
# for disabling a breakpoint on a line.
|
||||
editor.disableBreakpoint=Disable breakpoint
|
||||
editor.disableBreakpoint.accesskey=D
|
||||
|
||||
# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item
|
||||
# for enabling a breakpoint on a line.
|
||||
|
@ -381,8 +387,9 @@ editor.removeBreakpoint=Remove breakpoint
|
|||
editor.editBreakpoint=Edit breakpoint
|
||||
|
||||
# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context
|
||||
# menu item for adding a breakpoint condition on a line.
|
||||
editor.addConditionalBreakpoint=Add conditional breakpoint
|
||||
# menu item for adding/editing a breakpoint condition on a line.
|
||||
editor.addConditionalBreakpoint=Add/Edit conditional breakpoint
|
||||
editor.addConditionalBreakpoint.accesskey=c
|
||||
|
||||
# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for
|
||||
# input element inside ConditionalPanel component
|
||||
|
@ -395,6 +402,7 @@ editor.conditionalPanel.close=Cancel edit breakpoint and close
|
|||
# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
|
||||
# for navigating to a source mapped location
|
||||
editor.jumpToMappedLocation1=Jump to %S location
|
||||
editor.jumpToMappedLocation1.accesskey=m
|
||||
|
||||
# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
|
||||
# context menu to disable framework grouping.
|
||||
|
@ -415,6 +423,7 @@ original=original
|
|||
# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
|
||||
# input element
|
||||
expressions.placeholder=Add watch expression
|
||||
expressions.placeholder.accesskey=e
|
||||
|
||||
# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item
|
||||
# for closing the selected tab below the mouse.
|
||||
|
@ -468,10 +477,6 @@ sourceFooter.codeCoverage=Code coverage
|
|||
# for close tab button in source tabs.
|
||||
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.
|
||||
scopes.header=Scopes
|
||||
|
||||
|
@ -754,6 +759,7 @@ anonymous=(anonymous)
|
|||
# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing
|
||||
# keyboard shortcut action for toggling breakpoint
|
||||
shortcuts.toggleBreakpoint=Toggle Breakpoint
|
||||
shortcuts.toggleBreakpoint.accesskey=B
|
||||
|
||||
# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing
|
||||
# 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-regex-match", false);
|
||||
pref("devtools.debugger.features.async-stepping", true);
|
||||
|
||||
pref("devtools.debugger.features.project-text-search", 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
|
||||
DOMParser::ParseFromStream(nsIInputStream *stream,
|
||||
const char *charset,
|
||||
int32_t contentLength,
|
||||
const char *contentType,
|
||||
nsIDOMDocument **aResult)
|
||||
DOMParser::ParseFromStream(nsIInputStream* aStream,
|
||||
const char* aCharset,
|
||||
int32_t aContentLength,
|
||||
const char* aContentType,
|
||||
nsIDOMDocument** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(stream);
|
||||
NS_ENSURE_ARG(contentType);
|
||||
NS_ENSURE_ARG(aStream);
|
||||
NS_ENSURE_ARG(aContentType);
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*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.
|
||||
//XXXsmaug Should we create an HTMLDocument (in XHTML mode)
|
||||
// for "application/xhtml+xml"?
|
||||
if ((nsCRT::strcmp(contentType, "text/xml") != 0) &&
|
||||
(nsCRT::strcmp(contentType, "application/xml") != 0) &&
|
||||
(nsCRT::strcmp(contentType, "application/xhtml+xml") != 0) &&
|
||||
if ((nsCRT::strcmp(aContentType, "text/xml") != 0) &&
|
||||
(nsCRT::strcmp(aContentType, "application/xml") != 0) &&
|
||||
(nsCRT::strcmp(aContentType, "application/xhtml+xml") != 0) &&
|
||||
!svg)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// 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)) {
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream,
|
||||
4096);
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
stream.forget(), 4096);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
stream = bufferedStream;
|
||||
|
@ -243,11 +244,11 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
|
|||
mPrincipal,
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
nsDependentCString(contentType));
|
||||
nsDependentCString(aContentType));
|
||||
NS_ENSURE_STATE(parserChannel);
|
||||
|
||||
if (charset) {
|
||||
parserChannel->SetContentCharset(nsDependentCString(charset));
|
||||
if (aCharset) {
|
||||
parserChannel->SetContentCharset(nsDependentCString(aCharset));
|
||||
}
|
||||
|
||||
// Tell the document to start loading
|
||||
|
@ -284,7 +285,7 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
|
|||
|
||||
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
||||
rv = listener->OnDataAvailable(parserChannel, nullptr, stream, 0,
|
||||
contentLength);
|
||||
aContentLength);
|
||||
if (NS_FAILED(rv))
|
||||
parserChannel->Cancel(rv);
|
||||
parserChannel->GetStatus(&status);
|
||||
|
|
|
@ -252,7 +252,8 @@ nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mLoading = true;
|
||||
rv = nsSyncLoadService::PushSyncStreamToListener(in, aListener, mChannel);
|
||||
rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), aListener,
|
||||
mChannel);
|
||||
mLoading = false;
|
||||
|
||||
return rv;
|
||||
|
@ -338,14 +339,16 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI,
|
|||
|
||||
/* static */
|
||||
nsresult
|
||||
nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
||||
nsSyncLoadService::PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
|
||||
nsIStreamListener* aListener,
|
||||
nsIChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> in = Move(aIn);
|
||||
|
||||
// Set up buffering stream
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
if (!NS_InputStreamIsBuffered(aIn)) {
|
||||
if (!NS_InputStreamIsBuffered(in)) {
|
||||
int64_t chunkSize;
|
||||
rv = aChannel->GetContentLength(&chunkSize);
|
||||
if (NS_FAILED(rv) || chunkSize < 1) {
|
||||
|
@ -353,11 +356,11 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
|||
}
|
||||
chunkSize = std::min(int64_t(UINT16_MAX), chunkSize);
|
||||
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
|
||||
chunkSize);
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
in.forget(), chunkSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aIn = bufferedStream;
|
||||
in = bufferedStream;
|
||||
}
|
||||
|
||||
// Load
|
||||
|
@ -366,7 +369,7 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
|||
uint64_t sourceOffset = 0;
|
||||
while (1) {
|
||||
uint64_t readCount = 0;
|
||||
rv = aIn->Available(&readCount);
|
||||
rv = in->Available(&readCount);
|
||||
if (NS_FAILED(rv) || !readCount) {
|
||||
if (rv == NS_BASE_STREAM_CLOSED) {
|
||||
// End of file, but not an error
|
||||
|
@ -378,7 +381,7 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
|||
if (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)readCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -51,13 +51,13 @@ public:
|
|||
/**
|
||||
* 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
|
||||
* OnStartRequest/OnDataAvailable/OnStopRequest
|
||||
* notifications.
|
||||
* @param aChannel The channel that aIn was opened from.
|
||||
*/
|
||||
static nsresult PushSyncStreamToListener(nsIInputStream* aIn,
|
||||
static nsresult PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
|
||||
nsIStreamListener* aListener,
|
||||
nsIChannel* aChannel);
|
||||
};
|
||||
|
|
|
@ -2122,7 +2122,17 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
|
|||
rv = state->GetIsNull(6, &nullPadding);
|
||||
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) {
|
||||
#endif // NIGHTLY_BUILD
|
||||
MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() !=
|
||||
ResponseType::Opaque);
|
||||
aSavedResponseOut->mValue.paddingSize() =
|
||||
|
@ -2141,6 +2151,20 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
|
|||
rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo());
|
||||
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(
|
||||
"SELECT "
|
||||
"name, "
|
||||
|
|
|
@ -737,7 +737,8 @@ LockedDirectoryPaddingGet(nsIFile* aBaseDir, int64_t* aPaddingSizeOut)
|
|||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
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; }
|
||||
|
||||
nsCOMPtr<nsIObjectInputStream> objectStream =
|
||||
|
|
|
@ -31,17 +31,8 @@ namespace dom {
|
|||
* that add and remove fake gamepads, avoiding the platform-specific backends.
|
||||
*/
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest)
|
||||
|
||||
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_IMPL_CYCLE_COLLECTION_INHERITED(GamepadServiceTest, DOMEventTargetHelper,
|
||||
mWindow)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadServiceTest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
|
||||
|
|
|
@ -529,7 +529,7 @@ FSMultipartFormData::AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob)
|
|||
// Create buffered stream (for efficiency)
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
fileStream, 8192);
|
||||
fileStream.forget(), 8192);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
fileStream = bufferedStream;
|
||||
|
|
|
@ -766,21 +766,11 @@ HTMLContentSink::~HTMLContentSink()
|
|||
delete mHeadContext;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLContentSink)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLContentSink, nsContentSink)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHTMLDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
|
||||
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_CYCLE_COLLECTION_INHERITED(HTMLContentSink, nsContentSink,
|
||||
mHTMLDocument,
|
||||
mRoot,
|
||||
mBody,
|
||||
mHead)
|
||||
|
||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLContentSink,
|
||||
nsContentSink,
|
||||
|
|
|
@ -186,16 +186,13 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
// Testing
|
||||
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.
|
||||
nsIArray getAllRegistrations();
|
||||
|
||||
// Note: This is meant to be used only by about:serviceworkers.
|
||||
// It calls softUpdate() for each child process.
|
||||
[implicit_jscontext] void propagateSoftUpdate(in jsval aOriginAttributes,
|
||||
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
|
||||
// inform when unregister() is completed on the current process.
|
||||
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()
|
||||
|
@ -43,9 +45,9 @@ public:
|
|||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId);
|
||||
|
||||
const InputEventType* GetCoalescedEvent()
|
||||
UniquePtr<InputEventType> TakeCoalescedEvent()
|
||||
{
|
||||
return mCoalescedInputEvent.get();
|
||||
return Move(mCoalescedInputEvent);
|
||||
}
|
||||
|
||||
ScrollableLayerGuid GetScrollableLayerGuid()
|
||||
|
|
|
@ -55,8 +55,8 @@ void
|
|||
CoalescedMouseMoveFlusher::WillRefresh(mozilla::TimeStamp aTime)
|
||||
{
|
||||
MOZ_ASSERT(mRefreshDriver);
|
||||
mTabChild->MaybeDispatchCoalescedMouseMoveEvents();
|
||||
RemoveObserver();
|
||||
mTabChild->FlushAllCoalescedMouseData();
|
||||
mTabChild->ProcessPendingCoalescedMouseDataAndDispatchEvents();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1059,6 +1059,15 @@ TabChild::DestroyWindow()
|
|||
mCoalescedMouseEventFlusher->RemoveObserver();
|
||||
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());
|
||||
if (baseWindow)
|
||||
baseWindow->Destroy();
|
||||
|
@ -1591,28 +1600,62 @@ TabChild::RecvMouseEvent(const nsString& aType,
|
|||
}
|
||||
|
||||
void
|
||||
TabChild::MaybeDispatchCoalescedMouseMoveEvents()
|
||||
TabChild::ProcessPendingCoalescedMouseDataAndDispatchEvents()
|
||||
{
|
||||
if (!mCoalesceMouseMoveEvents) {
|
||||
if (!mCoalesceMouseMoveEvents || !mCoalescedMouseEventFlusher) {
|
||||
// We don't enable mouse coalescing or we are destroying TabChild.
|
||||
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()) {
|
||||
CoalescedMouseData* data = iter.UserData();
|
||||
if (!data || data->IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
const WidgetMouseEvent* event = data->GetCoalescedEvent();
|
||||
MOZ_ASSERT(event);
|
||||
// Dispatch the coalesced mousemove event. Using RecvRealMouseButtonEvent to
|
||||
// bypass the coalesce handling in RecvRealMouseMoveEvent.
|
||||
RecvRealMouseButtonEvent(*event,
|
||||
data->GetScrollableLayerGuid(),
|
||||
data->GetInputBlockId());
|
||||
data->Reset();
|
||||
}
|
||||
if (mCoalescedMouseEventFlusher) {
|
||||
mCoalescedMouseEventFlusher->RemoveObserver();
|
||||
UniquePtr<CoalescedMouseData> dispatchData =
|
||||
MakeUnique<CoalescedMouseData>();
|
||||
|
||||
dispatchData->RetrieveDataFrom(*data);
|
||||
mToBeDispatchedMouseData.Push(dispatchData.release());
|
||||
}
|
||||
mCoalescedMouseData.Clear();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
@ -1632,10 +1675,23 @@ TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& aEvent,
|
|||
mCoalescedMouseEventFlusher->StartObserver();
|
||||
return IPC_OK();
|
||||
}
|
||||
// Can't coalesce current mousemove event. Dispatch the coalesced mousemove
|
||||
// event and coalesce the current one.
|
||||
MaybeDispatchCoalescedMouseMoveEvents();
|
||||
data->Coalesce(aEvent, aGuid, aInputBlockId);
|
||||
// Can't coalesce current mousemove event. Put the coalesced mousemove data
|
||||
// with the same pointer id to mToBeDispatchedMouseData, coalesce the
|
||||
// current one, and process all pending data in mToBeDispatchedMouseData.
|
||||
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();
|
||||
} else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
|
@ -1675,16 +1731,35 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
|||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId)
|
||||
{
|
||||
if (aEvent.mMessage != eMouseMove) {
|
||||
// Flush the coalesced mousemove event before dispatching other mouse
|
||||
// events.
|
||||
MaybeDispatchCoalescedMouseMoveEvents();
|
||||
if (aEvent.mMessage == eMouseEnterIntoWidget) {
|
||||
mCoalescedMouseData.Put(aEvent.pointerId, new CoalescedMouseData());
|
||||
} else if (aEvent.mMessage == eMouseExitFromWidget) {
|
||||
mCoalescedMouseData.Remove(aEvent.pointerId);
|
||||
}
|
||||
if (mCoalesceMouseMoveEvents && mCoalescedMouseEventFlusher &&
|
||||
aEvent.mMessage != eMouseMove) {
|
||||
// When receiving a mouse event other than mousemove, we have to dispatch
|
||||
// all coalesced events before it. However, we can't dispatch all pending
|
||||
// coalesced events directly because we may reentry the event loop while
|
||||
// dispatching. To make sure we won't dispatch disorder events, we move all
|
||||
// coalesced mousemove events and current event to a deque to dispatch them.
|
||||
// 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
|
||||
// process EventStateManager code, have an input block id which they get from
|
||||
// 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) {
|
||||
mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
@ -1779,13 +1853,12 @@ TabChild::MaybeDispatchCoalescedWheelEvent()
|
|||
if (mCoalescedWheelData.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
const WidgetWheelEvent* wheelEvent =
|
||||
mCoalescedWheelData.GetCoalescedEvent();
|
||||
UniquePtr<WidgetWheelEvent> wheelEvent =
|
||||
mCoalescedWheelData.TakeCoalescedEvent();
|
||||
MOZ_ASSERT(wheelEvent);
|
||||
DispatchWheelEvent(*wheelEvent,
|
||||
mCoalescedWheelData.GetScrollableLayerGuid(),
|
||||
mCoalescedWheelData.GetInputBlockId());
|
||||
mCoalescedWheelData.Reset();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "AudioChannelService.h"
|
||||
#include "PuppetWidget.h"
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsISHistoryListener.h"
|
||||
#include "nsIPartialSHistoryListener.h"
|
||||
|
||||
|
@ -761,8 +762,17 @@ public:
|
|||
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()
|
||||
{
|
||||
|
@ -948,7 +958,12 @@ private:
|
|||
// takes time, some repeated events can be skipped to not flood child process.
|
||||
mozilla::TimeStamp mLastWheelProcessedTimeFromParent;
|
||||
mozilla::TimeDuration mLastWheelProcessingDuration;
|
||||
|
||||
// Hash table to track coalesced mousemove events for different pointers.
|
||||
nsClassHashtable<nsUint32HashKey, CoalescedMouseData> mCoalescedMouseData;
|
||||
|
||||
nsDeque mToBeDispatchedMouseData;
|
||||
|
||||
CoalescedWheelData mCoalescedWheelData;
|
||||
RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
skip-if = os == 'android'
|
||||
support-files =
|
||||
process_error.xul
|
||||
process_error_contentscript.js
|
||||
|
||||
[test_process_error.xul]
|
||||
skip-if = !crashreporter
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<browser id="thebrowser" type="content" remote="true" />
|
||||
<script type="application/javascript"><![CDATA[
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||
|
||||
const ok = window.opener.wrappedJSObject.ok;
|
||||
const is = window.opener.wrappedJSObject.is;
|
||||
|
@ -18,24 +19,19 @@
|
|||
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
|
||||
'Subject implements nsIPropertyBag2.');
|
||||
|
||||
var waitCrash = Promise.resolve();
|
||||
var dumpID;
|
||||
if ('nsICrashReporter' in Components.interfaces) {
|
||||
dumpID = subject.getPropertyAsAString('dumpID');
|
||||
ok(dumpID, "dumpID is present and not an empty string");
|
||||
waitCrash = Services.crashmanager.ensureCrashIsPresent(dumpID);
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
|
||||
waitCrash.then(done);
|
||||
done();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(crashObserver, 'ipc:content-shutdown');
|
||||
|
||||
document.getElementById('thebrowser')
|
||||
.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager
|
||||
.loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true);
|
||||
BrowserTestUtils.crashBrowser(document.getElementById('thebrowser'));
|
||||
]]></script>
|
||||
|
||||
</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(',');
|
||||
ok(additionalDumps.indexOf('browser') >= 0, "browser in additional_minidumps");
|
||||
|
||||
let additionalDumpFiles = [];
|
||||
for (let name of additionalDumps) {
|
||||
let file = profD.clone();
|
||||
file.append(pluginId + "-" + name + ".dmp");
|
||||
ok(file.exists(), "additional dump '"+name+"' exists");
|
||||
if (file.exists()) {
|
||||
additionalDumpFiles.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
// check cpu usage field
|
||||
|
@ -103,7 +99,5 @@ function onPluginCrashed(aEvent) {
|
|||
getService(Ci.nsIObserverService);
|
||||
os.removeObserver(testObserver, "plugin-crashed");
|
||||
|
||||
Services.crashmanager.ensureCrashIsPresent(aEvent.pluginDumpID).then(() => {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
</body>
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.expectChildProcessCrash();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</body>
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.expectChildProcessCrash();
|
||||
|
@ -23,6 +23,8 @@ SimpleTest.expectChildProcessCrash();
|
|||
var success = false;
|
||||
|
||||
var observerFired = false;
|
||||
var observerDeferred = PromiseUtils.defer();
|
||||
var eventListenerDeferred = PromiseUtils.defer();
|
||||
|
||||
var testObserver = {
|
||||
observe: function(subject, topic, data) {
|
||||
|
@ -46,6 +48,8 @@ var testObserver = {
|
|||
let extraFile = profD.clone();
|
||||
extraFile.append(id + ".extra");
|
||||
ok(extraFile.exists(), "extra file exists");
|
||||
|
||||
observerDeferred.resolve();
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
|
@ -84,9 +88,7 @@ function onPluginCrashed(aEvent) {
|
|||
getService(Components.interfaces.nsIObserverService);
|
||||
os.removeObserver(testObserver, "plugin-crashed");
|
||||
|
||||
Services.crashmanager.ensureCrashIsPresent(aEvent.pluginDumpID).then(() => {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
eventListenerDeferred.resolve();
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
|
@ -101,6 +103,13 @@ function runTests() {
|
|||
pluginElement.crash();
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
observerDeferred.promise,
|
||||
eventListenerDeferred.promise
|
||||
]).then(() => {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
</body>
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.expectChildProcessCrash();
|
||||
|
||||
|
|
|
@ -2454,7 +2454,8 @@ GetBinaryInputStream(nsIFile* aDirectory,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -5235,46 +5236,11 @@ QuotaManager::EnsureOriginIsInitializedInternal(
|
|||
*aCreated = false;
|
||||
return NS_OK;
|
||||
}
|
||||
} else if (!mTemporaryStorageInitialized) {
|
||||
rv = InitializeRepository(aPersistenceType);
|
||||
} else {
|
||||
rv = EnsureTemporaryStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// We have to cleanup partially initialized quota.
|
||||
RemoveQuota();
|
||||
|
||||
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;
|
||||
|
@ -5337,6 +5303,60 @@ QuotaManager::EnsureOriginIsInitializedInternal(
|
|||
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
|
||||
QuotaManager::OriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin)
|
||||
|
@ -7147,14 +7167,16 @@ GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager)
|
|||
nsresult rv;
|
||||
|
||||
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
|
||||
// temporary storage including origins belonging to our group.
|
||||
rv = aQuotaManager->EnsureOriginIsInitialized(PERSISTENCE_TYPE_TEMPORARY,
|
||||
mSuffix, mGroup,
|
||||
mOriginScope.GetOrigin(),
|
||||
getter_AddRefs(directory));
|
||||
rv = aQuotaManager->EnsureTemporaryStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -298,6 +298,9 @@ public:
|
|||
nsIFile** aDirectory,
|
||||
bool* aCreated);
|
||||
|
||||
nsresult
|
||||
EnsureTemporaryStorageIsInitialized();
|
||||
|
||||
void
|
||||
OriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin);
|
||||
|
|
|
@ -1491,7 +1491,8 @@ nsresult nsWebBrowserPersist::SaveChannelInternal(
|
|||
getter_AddRefs(fileInputStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
|
||||
fileInputStream, BUFFERED_OUTPUT_SIZE);
|
||||
fileInputStream.forget(),
|
||||
BUFFERED_OUTPUT_SIZE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString contentType;
|
||||
aChannel->GetContentType(contentType);
|
||||
|
|
|
@ -215,7 +215,7 @@ FileReaderSync::ReadAsText(Blob& aBlob,
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> syncStream;
|
||||
aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream,
|
||||
aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream.forget(),
|
||||
getter_AddRefs(syncStream));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
|
@ -269,7 +269,8 @@ FileReaderSync::ReadAsDataURL(Blob& aBlob, nsAString& aResult,
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> syncStream;
|
||||
aRv = ConvertAsyncToSyncStream(blobSize, stream, getter_AddRefs(syncStream));
|
||||
aRv = ConvertAsyncToSyncStream(blobSize, stream.forget(),
|
||||
getter_AddRefs(syncStream));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
@ -475,13 +476,15 @@ FileReaderSync::SyncRead(nsIInputStream* aStream, char* aBuffer,
|
|||
|
||||
nsresult
|
||||
FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
||||
nsIInputStream* aAsyncStream,
|
||||
already_AddRefed<nsIInputStream> aAsyncStream,
|
||||
nsIInputStream** aSyncStream)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> asyncInputStream = Move(aAsyncStream);
|
||||
|
||||
// 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) {
|
||||
return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096);
|
||||
return NS_NewBufferedInputStream(aSyncStream, asyncInputStream.forget(), 4096);
|
||||
}
|
||||
|
||||
nsAutoCString buffer;
|
||||
|
@ -491,7 +494,7 @@ FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
|||
|
||||
uint32_t read;
|
||||
nsresult rv =
|
||||
SyncRead(aAsyncStream, buffer.BeginWriting(), aStreamSize, &read);
|
||||
SyncRead(asyncInputStream, buffer.BeginWriting(), aStreamSize, &read);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ private:
|
|||
nsAString &aResult);
|
||||
|
||||
nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
||||
nsIInputStream* aAsyncStream,
|
||||
already_AddRefed<nsIInputStream> aAsyncStream,
|
||||
nsIInputStream** aSyncStream);
|
||||
|
||||
nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,
|
||||
|
|
|
@ -1116,7 +1116,8 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
|
|||
rv = channel->Open2(getter_AddRefs(in));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel);
|
||||
rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), listener,
|
||||
channel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
doc.swap(*aResult);
|
||||
|
|
|
@ -2561,11 +2561,12 @@ XMLHttpRequestMainThread::MaybeLowerChannelPriority()
|
|||
}
|
||||
|
||||
nsresult
|
||||
XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
||||
XMLHttpRequestMainThread::InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
|
||||
int64_t aUploadLength,
|
||||
nsACString& aUploadContentType)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIInputStream> uploadStream = Move(aUploadStream);
|
||||
|
||||
// nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
|
||||
// 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
|
||||
// support for our upload when calling ExplicitSetUploadStream.
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
if (!NS_InputStreamIsBuffered(aUploadStream)) {
|
||||
if (!NS_InputStreamIsBuffered(uploadStream)) {
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
aUploadStream, 4096);
|
||||
uploadStream.forget(), 4096);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aUploadStream = bufferedStream;
|
||||
uploadStream = bufferedStream;
|
||||
}
|
||||
|
||||
// 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
|
||||
NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2");
|
||||
if (uploadChannel2) {
|
||||
uploadChannel2->ExplicitSetUploadStream(aUploadStream,
|
||||
uploadChannel2->ExplicitSetUploadStream(uploadStream,
|
||||
aUploadContentType,
|
||||
mUploadTotal, mRequestMethod,
|
||||
false);
|
||||
|
@ -2645,7 +2646,7 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
|||
}
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel =
|
||||
do_QueryInterface(httpChannel);
|
||||
uploadChannel->SetUploadStream(aUploadStream, aUploadContentType,
|
||||
uploadChannel->SetUploadStream(uploadStream, aUploadContentType,
|
||||
mUploadTotal);
|
||||
// Reset the method to its original value
|
||||
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);
|
||||
|
||||
// Start our timeout
|
||||
|
|
|
@ -261,7 +261,7 @@ public:
|
|||
|
||||
// request
|
||||
nsresult CreateChannel();
|
||||
nsresult InitiateFetch(nsIInputStream* aUploadStream,
|
||||
nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
|
||||
int64_t aUploadLength,
|
||||
nsACString& aUploadContentType);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
52368
|
||||
52371
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
|
@ -16621,6 +16621,7 @@ billycan/S
|
|||
bimbo/MS
|
||||
bimetallic/SM
|
||||
bimetallism/M
|
||||
bimodal
|
||||
bimonthly/SM
|
||||
bin/SM
|
||||
binary/SM
|
||||
|
@ -36405,6 +36406,8 @@ nondepreciating
|
|||
nondescript
|
||||
nondestructive
|
||||
nondetachable
|
||||
nondeterminism
|
||||
nondeterministic
|
||||
nondisciplinary
|
||||
nondisclosure/M
|
||||
nondiscrimination/M
|
||||
|
|
|
@ -333,7 +333,8 @@ CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
|
|||
|
||||
nsCOMPtr<nsIInputStream> aBufferedStream;
|
||||
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);
|
||||
stream = aBufferedStream;
|
||||
}
|
||||
|
|
|
@ -100,20 +100,20 @@ private:
|
|||
};
|
||||
|
||||
/* 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;
|
||||
|
||||
// Prepare the input stream.
|
||||
nsCOMPtr<nsIInputStream> inputStream = aInputStream;
|
||||
if (!NS_InputStreamIsBuffered(aInputStream)) {
|
||||
if (!NS_InputStreamIsBuffered(inputStream)) {
|
||||
nsCOMPtr<nsIInputStream> bufStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||
aInputStream, 1024);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
inputStream = bufStream;
|
||||
inputStream.forget(), 1024);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,11 +145,12 @@ ImageOps::CreateImageBuffer(nsIInputStream* aInputStream)
|
|||
}
|
||||
|
||||
/* static */ nsresult
|
||||
ImageOps::DecodeMetadata(nsIInputStream* aInputStream,
|
||||
ImageOps::DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsACString& aMimeType,
|
||||
ImageMetadata& aMetadata)
|
||||
{
|
||||
RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
|
||||
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
|
||||
RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
|
||||
return DecodeMetadata(buffer, aMimeType, aMetadata);
|
||||
}
|
||||
|
||||
|
@ -193,12 +194,13 @@ ImageOps::DecodeMetadata(ImageBuffer* aBuffer,
|
|||
}
|
||||
|
||||
/* static */ already_AddRefed<gfx::SourceSurface>
|
||||
ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
|
||||
ImageOps::DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsACString& aMimeType,
|
||||
uint32_t aFlags,
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,23 +93,25 @@ public:
|
|||
* an ImageBuffer representing the given input stream is more efficient if one
|
||||
* 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.
|
||||
*/
|
||||
static already_AddRefed<ImageBuffer>
|
||||
CreateImageBuffer(nsIInputStream* aInputStream);
|
||||
CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream);
|
||||
|
||||
/**
|
||||
* Decodes an image's metadata from an nsIInputStream into the given
|
||||
* 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 aMetadata Where the image metadata is stored upon success.
|
||||
* @return The status of the operation.
|
||||
*/
|
||||
static nsresult
|
||||
DecodeMetadata(nsIInputStream* aInputStream,
|
||||
DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsACString& aMimeType,
|
||||
ImageMetadata& aMetadata);
|
||||
|
||||
|
@ -127,14 +129,15 @@ public:
|
|||
* main-thread-only). That means that 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. The
|
||||
* ownership is taken.
|
||||
* @param aMimeType The MIME type of the image.
|
||||
* @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
|
||||
* @return A SourceSurface containing the first frame of the image at its
|
||||
* intrinsic size, or nullptr if the image cannot be decoded.
|
||||
*/
|
||||
static already_AddRefed<gfx::SourceSurface>
|
||||
DecodeToSurface(nsIInputStream* aInputStream,
|
||||
DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsACString& aMimeType,
|
||||
uint32_t aFlags,
|
||||
const Maybe<gfx::IntSize>& aSize = Nothing());
|
||||
|
|
|
@ -61,7 +61,8 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
|
|||
nsCOMPtr<nsIInputStream> inStream = aInStr;
|
||||
if (!NS_InputStreamIsBuffered(aInStr)) {
|
||||
nsCOMPtr<nsIInputStream> bufStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024);
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||
inStream.forget(), 1024);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
inStream = bufStream;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
void Go()
|
||||
{
|
||||
mSurface =
|
||||
ImageOps::DecodeToSurface(mInputStream,
|
||||
ImageOps::DecodeToSurface(mInputStream.forget(),
|
||||
nsDependentCString(mimeType.c_str()),
|
||||
imgIContainer::DECODE_FLAGS_DEFAULT);
|
||||
if (!mSurface)
|
||||
|
|
|
@ -125,7 +125,7 @@ LoadFile(const char* aRelativePath)
|
|||
if (!NS_InputStreamIsBuffered(inputStream)) {
|
||||
nsCOMPtr<nsIInputStream> bufStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||
inputStream, 1024);
|
||||
inputStream.forget(), 1024);
|
||||
ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
|
||||
inputStream = bufStream;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
outputSize);
|
||||
} else {
|
||||
mSurface =
|
||||
ImageOps::DecodeToSurface(mInputStream,
|
||||
ImageOps::DecodeToSurface(mInputStream.forget(),
|
||||
nsDependentCString(mTestCase.mMimeType),
|
||||
imgIContainer::DECODE_FLAGS_DEFAULT,
|
||||
outputSize);
|
||||
|
@ -144,7 +144,7 @@ TEST_F(ImageDecodeToSurface, Corrupt)
|
|||
ASSERT_TRUE(inputStream != nullptr);
|
||||
|
||||
RefPtr<SourceSurface> surface =
|
||||
ImageOps::DecodeToSurface(inputStream,
|
||||
ImageOps::DecodeToSurface(inputStream.forget(),
|
||||
nsDependentCString(testCase.mMimeType),
|
||||
imgIContainer::DECODE_FLAGS_DEFAULT);
|
||||
EXPECT_TRUE(surface == nullptr);
|
||||
|
@ -158,7 +158,7 @@ TEST_F(ImageDecodeToSurface, ICOMultipleSizes)
|
|||
ASSERT_TRUE(inputStream != nullptr);
|
||||
|
||||
RefPtr<ImageOps::ImageBuffer> buffer =
|
||||
ImageOps::CreateImageBuffer(inputStream);
|
||||
ImageOps::CreateImageBuffer(inputStream.forget());
|
||||
ASSERT_TRUE(buffer != nullptr);
|
||||
|
||||
ImageMetadata metadata;
|
||||
|
|
|
@ -26,6 +26,8 @@ struct HandlerProvider
|
|||
struct IHandlerProvider : public IUnknown
|
||||
, public HandlerProvider
|
||||
{
|
||||
virtual STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
|
||||
ULONG aCallMethod) = 0;
|
||||
virtual STDMETHODIMP NewInstance(REFIID aIid,
|
||||
InterceptorTargetPtr<IUnknown> aTarget,
|
||||
NotNull<IHandlerProvider**> aOutNewPayload) = 0;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/mscom/Utils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
|
@ -154,6 +155,52 @@ private:
|
|||
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
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -338,6 +385,8 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame)
|
|||
return hr;
|
||||
}
|
||||
} else {
|
||||
SavedCallFrame savedFrame(WrapNotNull(aFrame));
|
||||
|
||||
// (7) Scan the outputs looking for any outparam interfaces that need wrapping.
|
||||
// NB: WalkFrame does not correctly handle array outparams. It processes the
|
||||
// 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;
|
||||
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),
|
||||
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
|
@ -585,7 +651,8 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
|||
return hr;
|
||||
}
|
||||
|
||||
REFIID interceptorIid = payload ? payload->MarshalAs(aIid) : aIid;
|
||||
REFIID interceptorIid = payload ? payload->MarshalAs(effectiveIid) :
|
||||
effectiveIid;
|
||||
|
||||
RefPtr<IUnknown> wrapped;
|
||||
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))
|
||||
return false;
|
||||
return emit3(op, ARGC_HI(argc), ARGC_LO(argc));
|
||||
return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2687,7 +2687,7 @@ bool
|
|||
BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
|
||||
{
|
||||
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;
|
||||
checkTypeSet(op);
|
||||
return true;
|
||||
|
@ -10214,10 +10214,7 @@ BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
|
|||
|
||||
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
|
||||
code[0] = JSOP_NEWOBJECT;
|
||||
code[1] = jsbytecode(index >> 24);
|
||||
code[2] = jsbytecode(index >> 16);
|
||||
code[3] = jsbytecode(index >> 8);
|
||||
code[4] = jsbytecode(index);
|
||||
SET_UINT32(code, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ class AutoRunParallelTask;
|
|||
class AutoTraceSession;
|
||||
class MarkingValidator;
|
||||
struct MovingTracer;
|
||||
class SweepGroupsIter;
|
||||
class WeakCacheSweepIterator;
|
||||
|
||||
enum IncrementalProgress
|
||||
|
@ -1073,27 +1074,24 @@ class GCRuntime
|
|||
void groupZonesForSweeping(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
|
||||
MOZ_MUST_USE bool findInterZoneEdges();
|
||||
void getNextSweepGroup();
|
||||
void endMarkingSweepGroup();
|
||||
void beginSweepingSweepGroup();
|
||||
IncrementalProgress endMarkingSweepGroup(FreeOp* fop, SliceBudget& budget);
|
||||
IncrementalProgress beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget);
|
||||
#ifdef JS_GC_ZEAL
|
||||
IncrementalProgress maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget);
|
||||
#endif
|
||||
bool shouldReleaseObservedTypes();
|
||||
void sweepDebuggerOnMainThread(FreeOp* fop);
|
||||
void sweepJitDataOnMainThread(FreeOp* fop);
|
||||
void endSweepingSweepGroup();
|
||||
IncrementalProgress performSweepActions(SliceBudget& sliceBudget,
|
||||
AutoLockForExclusiveAccess& lock);
|
||||
static IncrementalProgress sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
||||
Zone* zone);
|
||||
static IncrementalProgress mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
||||
Zone* zone);
|
||||
static IncrementalProgress sweepAtomsTable(GCRuntime* gc, FreeOp* fop, SliceBudget& budget);
|
||||
IncrementalProgress endSweepingSweepGroup(FreeOp* fop, SliceBudget& budget);
|
||||
IncrementalProgress performSweepActions(SliceBudget& sliceBudget, AutoLockForExclusiveAccess& lock);
|
||||
IncrementalProgress sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone);
|
||||
IncrementalProgress mergeSweptObjectArenas(FreeOp* fop, SliceBudget& budget, Zone* zone);
|
||||
void startSweepingAtomsTable();
|
||||
IncrementalProgress sweepAtomsTable(SliceBudget& budget);
|
||||
static IncrementalProgress sweepWeakCaches(GCRuntime* gc, FreeOp* fop, SliceBudget& budget);
|
||||
IncrementalProgress sweepWeakCaches(SliceBudget& budget);
|
||||
static IncrementalProgress finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
||||
Zone* zone, AllocKind kind);
|
||||
static IncrementalProgress sweepShapeTree(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
||||
Zone* zone);
|
||||
IncrementalProgress sweepAtomsTable(FreeOp* fop, SliceBudget& budget);
|
||||
IncrementalProgress sweepWeakCaches(FreeOp* fop, SliceBudget& budget);
|
||||
IncrementalProgress finalizeAllocKind(FreeOp* fop, SliceBudget& budget, Zone* zone,
|
||||
AllocKind kind);
|
||||
IncrementalProgress sweepShapeTree(FreeOp* fop, SliceBudget& budget, Zone* zone);
|
||||
void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
|
||||
bool allCCVisibleZonesWereCollected() const;
|
||||
void sweepZones(FreeOp* fop, ZoneGroup* group, bool lastGC);
|
||||
|
@ -1285,9 +1283,20 @@ class GCRuntime
|
|||
*/
|
||||
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. */
|
||||
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. */
|
||||
ActiveThreadData<bool> sweepOnBackgroundThread;
|
||||
|
||||
|
@ -1319,6 +1328,7 @@ class GCRuntime
|
|||
ActiveThreadOrGCTaskData<JS::detail::WeakCacheBase*> sweepCache;
|
||||
ActiveThreadData<bool> abortSweepAfterCurrentGroup;
|
||||
|
||||
friend class SweepGroupsIter;
|
||||
friend class WeakCacheSweepIterator;
|
||||
|
||||
/*
|
||||
|
|
|
@ -2494,7 +2494,7 @@ GCMarker::enterWeakMarkingMode()
|
|||
if (weakMapAction() == ExpandWeakMaps) {
|
||||
tag_ = TracerKindTag::WeakMarking;
|
||||
|
||||
for (GCSweepGroupIter zone(runtime()); !zone.done(); zone.next()) {
|
||||
for (SweepGroupZonesIter zone(runtime()); !zone.done(); zone.next()) {
|
||||
for (WeakMapBase* m : zone->gcWeakMapList()) {
|
||||
if (m->marked)
|
||||
(void) m->markIteratively(this);
|
||||
|
|
|
@ -3568,6 +3568,19 @@ Simulator::branchDelayInstructionDecode(SimInstruction* 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>
|
||||
void
|
||||
Simulator::execute()
|
||||
|
@ -3581,6 +3594,8 @@ Simulator::execute()
|
|||
MipsDebugger dbg(this);
|
||||
dbg.debug();
|
||||
} else {
|
||||
if (MOZ_UNLIKELY(JitOptions.simulatorAlwaysInterrupt))
|
||||
FakeInterruptHandler();
|
||||
SimInstruction* instr = reinterpret_cast<SimInstruction*>(program_counter);
|
||||
instructionDecode(instr);
|
||||
icount_++;
|
||||
|
|
|
@ -3733,6 +3733,19 @@ Simulator::disable_single_stepping()
|
|||
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>
|
||||
void
|
||||
Simulator::execute()
|
||||
|
@ -3751,6 +3764,8 @@ Simulator::execute()
|
|||
} else {
|
||||
if (single_stepping_)
|
||||
single_step_callback_(single_step_callback_arg_, this, (void*)program_counter);
|
||||
if (MOZ_UNLIKELY(JitOptions.simulatorAlwaysInterrupt))
|
||||
FakeInterruptHandler();
|
||||
SimInstruction* instr = reinterpret_cast<SimInstruction *>(program_counter);
|
||||
instructionDecode(instr);
|
||||
icount_++;
|
||||
|
|
|
@ -465,6 +465,7 @@ class AutoLeaveZeal
|
|||
JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
|
||||
}
|
||||
~AutoLeaveZeal() {
|
||||
JS_SetGCZeal(cx_, 0, 0);
|
||||
for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
|
||||
if (zealBits_ & (1 << i))
|
||||
JS_SetGCZeal(cx_, i, frequency_);
|
||||
|
|
372
js/src/jsgc.cpp
372
js/src/jsgc.cpp
|
@ -914,7 +914,12 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
|
|||
number(0),
|
||||
isFull(false),
|
||||
incrementalState(gc::State::NotActive),
|
||||
initialState(gc::State::NotActive),
|
||||
#ifdef JS_GC_ZEAL
|
||||
useZeal(false),
|
||||
#endif
|
||||
lastMarkSlice(false),
|
||||
safeToYield(true),
|
||||
sweepOnBackgroundThread(false),
|
||||
blocksToFreeAfterSweeping((size_t) JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
sweepGroupIndex(0),
|
||||
|
@ -4389,7 +4394,7 @@ GCRuntime::markWeakReferences(gcstats::PhaseKind phase)
|
|||
void
|
||||
GCRuntime::markWeakReferencesInCurrentGroup(gcstats::PhaseKind phase)
|
||||
{
|
||||
markWeakReferences<GCSweepGroupIter>(phase);
|
||||
markWeakReferences<SweepGroupZonesIter>(phase);
|
||||
}
|
||||
|
||||
template <class ZoneIterT, class CompartmentIterT>
|
||||
|
@ -4412,7 +4417,7 @@ GCRuntime::markGrayReferences(gcstats::PhaseKind phase)
|
|||
void
|
||||
GCRuntime::markGrayReferencesInCurrentGroup(gcstats::PhaseKind phase)
|
||||
{
|
||||
markGrayReferences<GCSweepGroupIter, GCCompartmentGroupIter>(phase);
|
||||
markGrayReferences<SweepGroupZonesIter, SweepGroupCompartmentsIter>(phase);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4907,14 +4912,14 @@ GCRuntime::getNextSweepGroup()
|
|||
|
||||
if (abortSweepAfterCurrentGroup) {
|
||||
MOZ_ASSERT(!isIncremental);
|
||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
||||
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
MOZ_ASSERT(!zone->gcNextGraphComponent);
|
||||
zone->setNeedsIncrementalBarrier(false);
|
||||
zone->changeGCState(Zone::Mark, Zone::NoGC);
|
||||
zone->gcGrayRoots().clearAndFree();
|
||||
}
|
||||
|
||||
for (GCCompartmentGroupIter comp(rt); !comp.done(); comp.next())
|
||||
for (SweepGroupCompartmentsIter comp(rt); !comp.done(); comp.next())
|
||||
ResetGrayList(comp);
|
||||
|
||||
abortSweepAfterCurrentGroup = false;
|
||||
|
@ -5049,7 +5054,7 @@ MarkIncomingCrossCompartmentPointers(JSRuntime* rt, MarkColor color)
|
|||
|
||||
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::Black, c->zone()->isGCMarkingBlack());
|
||||
MOZ_ASSERT_IF(c->gcIncomingGrayPointers, IsGrayListObject(c->gcIncomingGrayPointers));
|
||||
|
@ -5162,8 +5167,8 @@ js::NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned removedFlags)
|
|||
DelayCrossCompartmentGrayMarking(a);
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::endMarkingSweepGroup()
|
||||
IncrementalProgress
|
||||
GCRuntime::endMarkingSweepGroup(FreeOp* fop, SliceBudget& budget)
|
||||
{
|
||||
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
|
||||
* MarkCrossCompartmentXXX.
|
||||
*/
|
||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
||||
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||
zone->changeGCState(Zone::Mark, Zone::MarkGray);
|
||||
marker.setMarkColorGray();
|
||||
|
||||
|
@ -5193,10 +5198,15 @@ GCRuntime::endMarkingSweepGroup()
|
|||
markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK);
|
||||
|
||||
/* 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);
|
||||
MOZ_ASSERT(marker.isDrained());
|
||||
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.
|
||||
|
@ -5245,28 +5255,28 @@ UpdateAtomsBitmap(JSRuntime* runtime)
|
|||
static void
|
||||
SweepCCWrappers(JSRuntime* runtime)
|
||||
{
|
||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
|
||||
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
|
||||
c->sweepCrossCompartmentWrappers();
|
||||
}
|
||||
|
||||
static void
|
||||
SweepObjectGroups(JSRuntime* runtime)
|
||||
{
|
||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
|
||||
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
|
||||
c->objectGroups.sweep(runtime->defaultFreeOp());
|
||||
}
|
||||
|
||||
static void
|
||||
SweepRegExps(JSRuntime* runtime)
|
||||
{
|
||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
|
||||
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
|
||||
c->sweepRegExps();
|
||||
}
|
||||
|
||||
static void
|
||||
SweepMisc(JSRuntime* runtime)
|
||||
{
|
||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) {
|
||||
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next()) {
|
||||
c->sweepGlobalObject();
|
||||
c->sweepTemplateObjects();
|
||||
c->sweepSavedStacks();
|
||||
|
@ -5303,7 +5313,7 @@ SweepCompressionTasks(JSRuntime* runtime)
|
|||
static void
|
||||
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. */
|
||||
for (auto edge : zone->gcWeakRefs()) {
|
||||
/* Edges may be present multiple times, so may already be nulled. */
|
||||
|
@ -5325,7 +5335,7 @@ static void
|
|||
SweepUniqueIds(JSRuntime* runtime)
|
||||
{
|
||||
FreeOp fop(nullptr);
|
||||
for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next())
|
||||
for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next())
|
||||
zone->sweepUniqueIds(&fop);
|
||||
}
|
||||
|
||||
|
@ -5363,7 +5373,7 @@ GCRuntime::sweepDebuggerOnMainThread(FreeOp* fop)
|
|||
// table.
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -5371,7 +5381,7 @@ GCRuntime::sweepDebuggerOnMainThread(FreeOp* fop)
|
|||
// although note that it can cause JIT code to be patched.
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -5385,10 +5395,10 @@ GCRuntime::sweepJitDataOnMainThread(FreeOp* fop)
|
|||
// Cancel any active or pending off thread compilations.
|
||||
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);
|
||||
|
||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
||||
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (jit::JitZone* jitZone = zone->jitZone())
|
||||
jitZone->sweep(fop);
|
||||
}
|
||||
|
@ -5403,14 +5413,14 @@ GCRuntime::sweepJitDataOnMainThread(FreeOp* fop)
|
|||
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -5429,7 +5439,7 @@ template <typename Functor>
|
|||
static inline bool
|
||||
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()) {
|
||||
if (!f(cache, ZoneWeakCache))
|
||||
return false;
|
||||
|
@ -5484,8 +5494,8 @@ SweepWeakCachesOnMainThread(JSRuntime* rt)
|
|||
});
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::beginSweepingSweepGroup()
|
||||
IncrementalProgress
|
||||
GCRuntime::beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
|
||||
{
|
||||
/*
|
||||
* Begin sweeping the group of zones in currentSweepGroup, performing
|
||||
|
@ -5497,7 +5507,7 @@ GCRuntime::beginSweepingSweepGroup()
|
|||
AutoSCC scc(stats(), sweepGroupIndex);
|
||||
|
||||
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. */
|
||||
zone->changeGCState(Zone::Mark, Zone::Sweep);
|
||||
|
||||
|
@ -5514,26 +5524,24 @@ GCRuntime::beginSweepingSweepGroup()
|
|||
|
||||
validateIncrementalMarking();
|
||||
|
||||
FreeOp fop(rt);
|
||||
|
||||
{
|
||||
AutoPhase ap(stats(), PhaseKind::FINALIZE_START);
|
||||
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_PREPARE);
|
||||
callFinalizeCallbacks(fop, JSFINALIZE_GROUP_PREPARE);
|
||||
{
|
||||
AutoPhase ap2(stats(), PhaseKind::WEAK_ZONES_CALLBACK);
|
||||
callWeakPointerZonesCallbacks();
|
||||
}
|
||||
{
|
||||
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())
|
||||
callWeakPointerCompartmentCallbacks(comp);
|
||||
}
|
||||
}
|
||||
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_START);
|
||||
callFinalizeCallbacks(fop, JSFINALIZE_GROUP_START);
|
||||
}
|
||||
|
||||
sweepDebuggerOnMainThread(&fop);
|
||||
sweepDebuggerOnMainThread(fop);
|
||||
|
||||
{
|
||||
AutoLockHelperThreadState lock;
|
||||
|
@ -5561,7 +5569,7 @@ GCRuntime::beginSweepingSweepGroup()
|
|||
|
||||
{
|
||||
AutoUnlockHelperThreadState unlock(lock);
|
||||
sweepJitDataOnMainThread(&fop);
|
||||
sweepJitDataOnMainThread(fop);
|
||||
}
|
||||
|
||||
for (auto& task : sweepCacheTasks)
|
||||
|
@ -5574,25 +5582,45 @@ GCRuntime::beginSweepingSweepGroup()
|
|||
// Queue all GC things in all zones for sweeping, either on the foreground
|
||||
// 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, ForegroundNonObjectFinalizePhase);
|
||||
zone->arenas.queueForForegroundSweep(fop, ForegroundObjectFinalizePhase);
|
||||
zone->arenas.queueForForegroundSweep(fop, ForegroundNonObjectFinalizePhase);
|
||||
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;
|
||||
sweepActions->assertFinished();
|
||||
safeToYield = true;
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::endSweepingSweepGroup()
|
||||
#ifdef JS_GC_ZEAL
|
||||
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);
|
||||
FreeOp fop(rt);
|
||||
|
@ -5600,7 +5628,7 @@ GCRuntime::endSweepingSweepGroup()
|
|||
}
|
||||
|
||||
/* 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);
|
||||
zone->changeGCState(Zone::Sweep, Zone::Finished);
|
||||
zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables,
|
||||
|
@ -5609,7 +5637,7 @@ GCRuntime::endSweepingSweepGroup()
|
|||
|
||||
/* Start background thread to sweep zones if required. */
|
||||
ZoneList zones;
|
||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
||||
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||
zones.append(zone);
|
||||
if (sweepOnBackgroundThread)
|
||||
queueZonesForBackgroundSweep(zones);
|
||||
|
@ -5621,6 +5649,8 @@ GCRuntime::endSweepingSweepGroup()
|
|||
arenasAllocatedDuringSweep = arena->getNextAllocDuringSweep();
|
||||
arena->unsetAllocDuringSweep();
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5653,8 +5683,12 @@ GCRuntime::beginSweepPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcce
|
|||
DropStringWrappers(rt);
|
||||
|
||||
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
|
||||
|
@ -5737,8 +5771,8 @@ SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget, Args... args)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* static */ IncrementalProgress
|
||||
GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||
IncrementalProgress
|
||||
GCRuntime::sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||
{
|
||||
// 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
|
||||
|
@ -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 zone are live.
|
||||
|
||||
gcstats::AutoPhase ap1(gc->stats(), gcstats::PhaseKind::SWEEP_COMPARTMENTS);
|
||||
gcstats::AutoPhase ap2(gc->stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
||||
gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_COMPARTMENTS);
|
||||
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
||||
|
||||
ArenaLists& al = zone->arenas;
|
||||
|
||||
|
@ -5763,15 +5797,16 @@ GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
|||
|
||||
// Finish sweeping type information in the zone.
|
||||
{
|
||||
gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::SWEEP_TYPES_END);
|
||||
zone->types.endSweep(gc->rt);
|
||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_TYPES_END);
|
||||
zone->types.endSweep(rt);
|
||||
}
|
||||
|
||||
return Finished;
|
||||
}
|
||||
|
||||
/* static */ IncrementalProgress
|
||||
GCRuntime::mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||
IncrementalProgress
|
||||
GCRuntime::mergeSweptObjectArenas(FreeOp* fop, SliceBudget& budget,
|
||||
Zone* zone)
|
||||
{
|
||||
// Foreground finalized objects have already been finalized, and now their
|
||||
// arenas can be reclaimed by freeing empty ones and making non-empty ones
|
||||
|
@ -5802,18 +5837,12 @@ GCRuntime::startSweepingAtomsTable()
|
|||
maybeAtoms.emplace(*atomsTable);
|
||||
}
|
||||
|
||||
/* static */ IncrementalProgress
|
||||
GCRuntime::sweepAtomsTable(GCRuntime* gc, FreeOp* fop, SliceBudget& budget)
|
||||
IncrementalProgress
|
||||
GCRuntime::sweepAtomsTable(FreeOp* fop, SliceBudget& budget)
|
||||
{
|
||||
if (!gc->atomsZone->isGCSweeping())
|
||||
if (!atomsZone->isGCSweeping())
|
||||
return Finished;
|
||||
|
||||
return gc->sweepAtomsTable(budget);
|
||||
}
|
||||
|
||||
IncrementalProgress
|
||||
GCRuntime::sweepAtomsTable(SliceBudget& budget)
|
||||
{
|
||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_ATOMS_TABLE);
|
||||
|
||||
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 size_t
|
||||
|
@ -5959,7 +5982,7 @@ WeakCacheSweepTaskCount()
|
|||
}
|
||||
|
||||
IncrementalProgress
|
||||
GCRuntime::sweepWeakCaches(SliceBudget& budget)
|
||||
GCRuntime::sweepWeakCaches(FreeOp* fop, SliceBudget& budget)
|
||||
{
|
||||
WeakCacheSweepIterator work(this);
|
||||
|
||||
|
@ -5978,13 +6001,12 @@ GCRuntime::sweepWeakCaches(SliceBudget& budget)
|
|||
return work.empty(lock) ? Finished : NotFinished;
|
||||
}
|
||||
|
||||
/* static */ IncrementalProgress
|
||||
GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone,
|
||||
AllocKind kind)
|
||||
IncrementalProgress
|
||||
GCRuntime::finalizeAllocKind(FreeOp* fop, SliceBudget& budget, Zone* zone, AllocKind kind)
|
||||
{
|
||||
// Set the number of things per arena for this AllocKind.
|
||||
size_t thingsPerArena = Arena::thingsPerArena(kind);
|
||||
auto& sweepList = gc->incrementalSweepList.ref();
|
||||
auto& sweepList = incrementalSweepList.ref();
|
||||
sweepList.setThingsPerArena(thingsPerArena);
|
||||
|
||||
if (!zone->arenas.foregroundFinalize(fop, kind, budget, sweepList))
|
||||
|
@ -5996,12 +6018,12 @@ GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zo
|
|||
return Finished;
|
||||
}
|
||||
|
||||
/* static */ IncrementalProgress
|
||||
GCRuntime::sweepShapeTree(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||
IncrementalProgress
|
||||
GCRuntime::sweepShapeTree(FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||
{
|
||||
// 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;
|
||||
|
||||
|
@ -6084,20 +6106,46 @@ struct IncrementalIter
|
|||
}
|
||||
};
|
||||
|
||||
namespace sweepaction {
|
||||
|
||||
// Implementation of the SweepAction interface that calls a function.
|
||||
template <typename... Args>
|
||||
class SweepActionFunc final : public SweepAction<Args...>
|
||||
// Iterate through the sweep groups created by GCRuntime::groupZonesForSweeping().
|
||||
class js::gc::SweepGroupsIter
|
||||
{
|
||||
using Func = IncrementalProgress (*)(Args...);
|
||||
|
||||
Func func;
|
||||
GCRuntime* gc;
|
||||
|
||||
public:
|
||||
explicit SweepActionFunc(Func f) : func(f) {}
|
||||
IncrementalProgress run(Args... args) override {
|
||||
return func(args...);
|
||||
explicit SweepGroupsIter(JSRuntime* rt)
|
||||
: gc(&rt->gc)
|
||||
{
|
||||
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 { }
|
||||
};
|
||||
|
@ -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
|
||||
// a variadic template. For example:
|
||||
//
|
||||
|
@ -6206,9 +6284,9 @@ class RemoveLastTemplateParameter<Target<Args...>>
|
|||
};
|
||||
|
||||
template <typename... Args>
|
||||
static UniquePtr<SweepAction<Args...>>
|
||||
Func(IncrementalProgress (*func)(Args...)) {
|
||||
return MakeUnique<SweepActionFunc<Args...>>(func);
|
||||
static UniquePtr<SweepAction<GCRuntime*, Args...>>
|
||||
Call(IncrementalProgress (GCRuntime::*method)(Args...)) {
|
||||
return MakeUnique<SweepActionCall<Args...>>(method);
|
||||
}
|
||||
|
||||
template <typename... Args, typename... Rest>
|
||||
|
@ -6223,6 +6301,17 @@ Sequence(UniquePtr<SweepAction<Args...>> first, Rest... rest)
|
|||
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>
|
||||
static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type>
|
||||
ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
|
||||
|
@ -6231,7 +6320,7 @@ ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
|
|||
return nullptr;
|
||||
|
||||
using Action = typename RemoveLastTemplateParameter<
|
||||
SweepActionForEach<GCSweepGroupIter, JSRuntime*, Args...>>::Type;
|
||||
SweepActionForEach<SweepGroupZonesIter, JSRuntime*, Args...>>::Type;
|
||||
return js::MakeUnique<Action>(rt, Move(action));
|
||||
}
|
||||
|
||||
|
@ -6253,22 +6342,31 @@ bool
|
|||
GCRuntime::initSweepActions()
|
||||
{
|
||||
using namespace sweepaction;
|
||||
using sweepaction::Call;
|
||||
|
||||
sweepActions.ref() = Sequence(
|
||||
Func(sweepAtomsTable),
|
||||
Func(sweepWeakCaches),
|
||||
ForEachZoneInSweepGroup(rt,
|
||||
ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
|
||||
Func(finalizeAllocKind))),
|
||||
ForEachZoneInSweepGroup(rt,
|
||||
sweepActions.ref() =
|
||||
RepeatForSweepGroup(rt,
|
||||
Sequence(
|
||||
Func(sweepTypeInformation),
|
||||
Func(mergeSweptObjectArenas))),
|
||||
ForEachZoneInSweepGroup(rt,
|
||||
ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
|
||||
Func(finalizeAllocKind))),
|
||||
ForEachZoneInSweepGroup(rt,
|
||||
Func(sweepShapeTree)));
|
||||
Call(&GCRuntime::endMarkingSweepGroup),
|
||||
Call(&GCRuntime::beginSweepingSweepGroup),
|
||||
#ifdef JS_GC_ZEAL
|
||||
Call(&GCRuntime::maybeYieldForSweepingZeal),
|
||||
#endif
|
||||
Call(&GCRuntime::sweepAtomsTable),
|
||||
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;
|
||||
}
|
||||
|
@ -6281,21 +6379,17 @@ GCRuntime::performSweepActions(SliceBudget& budget, AutoLockForExclusiveAccess&
|
|||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
|
||||
FreeOp fop(rt);
|
||||
|
||||
if (drainMarkStack(budget, gcstats::PhaseKind::SWEEP_MARK) == NotFinished)
|
||||
return NotFinished;
|
||||
|
||||
for (;;) {
|
||||
if (sweepActions->run(this, &fop, budget) == NotFinished)
|
||||
return NotFinished;
|
||||
|
||||
endSweepingSweepGroup();
|
||||
getNextSweepGroup();
|
||||
if (!currentSweepGroup)
|
||||
return Finished;
|
||||
|
||||
endMarkingSweepGroup();
|
||||
beginSweepingSweepGroup();
|
||||
// Drain the mark stack, except in the first sweep slice where we must not
|
||||
// yield to the mutator until we've starting sweeping a sweep group.
|
||||
MOZ_ASSERT(initialState <= State::Sweep);
|
||||
if (initialState != State::Sweep) {
|
||||
MOZ_ASSERT(marker.isDrained());
|
||||
} else {
|
||||
if (drainMarkStack(budget, gcstats::PhaseKind::SWEEP_MARK) == NotFinished)
|
||||
return NotFinished;
|
||||
}
|
||||
|
||||
return sweepActions->run(this, &fop, budget);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -6331,6 +6425,8 @@ GCRuntime::allCCVisibleZonesWereCollected() const
|
|||
void
|
||||
GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
sweepActions->assertFinished();
|
||||
|
||||
AutoSetThreadIsSweeping threadIsSweeping;
|
||||
|
||||
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);
|
||||
|
||||
gc::State initialState = incrementalState;
|
||||
initialState = incrementalState;
|
||||
|
||||
bool useZeal = false;
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited()) {
|
||||
/*
|
||||
* Do the incremental collection type specified by zeal mode if the
|
||||
* collection was triggered by runDebugGC() and incremental GC has not
|
||||
* been cancelled by resetIncrementalGC().
|
||||
*/
|
||||
useZeal = true;
|
||||
}
|
||||
/*
|
||||
* Do the incremental collection type specified by zeal mode if the
|
||||
* collection was triggered by runDebugGC() and incremental GC has not been
|
||||
* cancelled by resetIncrementalGC().
|
||||
*/
|
||||
useZeal = reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited();
|
||||
#else
|
||||
bool useZeal = false;
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
|
||||
|
@ -6860,24 +6955,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
|||
|
||||
incrementalState = State::Sweep;
|
||||
|
||||
/*
|
||||
* This runs to completion, but we don't continue if the budget is
|
||||
* now exhasted.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -6956,6 +7034,8 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
|||
incrementalState = State::NotActive;
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(safeToYield);
|
||||
}
|
||||
|
||||
gc::AbortReason
|
||||
|
|
|
@ -437,11 +437,11 @@ class GCZonesIter
|
|||
typedef CompartmentsIterT<GCZonesIter> GCCompartmentsIter;
|
||||
|
||||
/* Iterates over all zones in the current sweep group. */
|
||||
class GCSweepGroupIter {
|
||||
class SweepGroupZonesIter {
|
||||
JS::Zone* current;
|
||||
|
||||
public:
|
||||
explicit GCSweepGroupIter(JSRuntime* rt) {
|
||||
explicit SweepGroupZonesIter(JSRuntime* rt) {
|
||||
MOZ_ASSERT(CurrentThreadIsPerformingGC());
|
||||
current = rt->gc.getCurrentSweepGroup();
|
||||
}
|
||||
|
@ -462,7 +462,7 @@ class GCSweepGroupIter {
|
|||
JS::Zone* operator->() const { return get(); }
|
||||
};
|
||||
|
||||
typedef CompartmentsIterT<GCSweepGroupIter> GCCompartmentGroupIter;
|
||||
typedef CompartmentsIterT<SweepGroupZonesIter> SweepGroupCompartmentsIter;
|
||||
|
||||
inline void
|
||||
RelocationOverlay::forwardTo(Cell* cell)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
|
||||
#include "jsbytecode.h"
|
||||
#include "jstypes.h"
|
||||
|
@ -136,17 +137,26 @@ UINT16_LO(uint16_t i)
|
|||
static MOZ_ALWAYS_INLINE uint16_t
|
||||
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
|
||||
SET_UINT16(jsbytecode* pc, uint16_t i)
|
||||
{
|
||||
pc[1] = UINT16_HI(i);
|
||||
pc[2] = UINT16_LO(i);
|
||||
#if MOZ_LITTLE_ENDIAN
|
||||
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;
|
||||
|
||||
/* 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_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
|
||||
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)
|
||||
{
|
||||
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
|
||||
SET_UINT24(jsbytecode* pc, unsigned i)
|
||||
SET_UINT24(jsbytecode* pc, uint32_t i)
|
||||
{
|
||||
MOZ_ASSERT(i < (1 << 24));
|
||||
pc[1] = UINT24_HI(i);
|
||||
pc[2] = UINT24_MID(i);
|
||||
pc[3] = UINT24_LO(i);
|
||||
|
||||
#if MOZ_LITTLE_ENDIAN
|
||||
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
|
||||
|
@ -228,19 +201,29 @@ GET_INT8(const jsbytecode* pc)
|
|||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
GET_UINT32(const jsbytecode* pc)
|
||||
{
|
||||
return (uint32_t(pc[1]) << 24) |
|
||||
(uint32_t(pc[2]) << 16) |
|
||||
(uint32_t(pc[3]) << 8) |
|
||||
uint32_t(pc[4]);
|
||||
#if MOZ_LITTLE_ENDIAN
|
||||
uint32_t result;
|
||||
memcpy(&result, pc + 1, sizeof(result));
|
||||
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
|
||||
SET_UINT32(jsbytecode* pc, uint32_t u)
|
||||
{
|
||||
pc[1] = jsbytecode(u >> 24);
|
||||
pc[2] = jsbytecode(u >> 16);
|
||||
pc[3] = jsbytecode(u >> 8);
|
||||
pc[4] = jsbytecode(u);
|
||||
#if MOZ_LITTLE_ENDIAN
|
||||
memcpy(pc + 1, &u, sizeof(u));
|
||||
#else
|
||||
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
|
||||
|
@ -255,6 +238,32 @@ SET_INT32(jsbytecode* pc, int32_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. */
|
||||
static const unsigned INDEX_LIMIT_LOG2 = 31;
|
||||
static const uint32_t INDEX_LIMIT = uint32_t(1) << INDEX_LIMIT_LOG2;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/OperatorNewExtensions.h"
|
||||
|
||||
#include "threading/ConditionVariable.h"
|
||||
#include "threading/Mutex.h"
|
||||
|
@ -99,7 +100,7 @@ class ExclusiveData
|
|||
explicit ExclusiveData(const MutexId& id, U&& u)
|
||||
: 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)
|
||||
: lock_(id)
|
||||
{
|
||||
new (value_.addr()) T(mozilla::Forward<Args>(args)...);
|
||||
new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
|
||||
~ExclusiveData() {
|
||||
|
@ -122,12 +123,12 @@ class ExclusiveData
|
|||
lock_(mozilla::Move(rhs.lock))
|
||||
{
|
||||
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) {
|
||||
this->~ExclusiveData();
|
||||
new (this) ExclusiveData(mozilla::Move(rhs));
|
||||
new (mozilla::KnownNotNull, this) ExclusiveData(mozilla::Move(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -265,7 +265,7 @@ class ElementSpecific
|
|||
}
|
||||
|
||||
// Inhibit unaligned accesses on ARM (bug 1097253, a compiler bug).
|
||||
#ifdef __arm__
|
||||
#if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
|
||||
# define JS_VOLATILE_ARM volatile
|
||||
#else
|
||||
# define JS_VOLATILE_ARM
|
||||
|
|
|
@ -246,6 +246,7 @@ static const unsigned PushedFP = 5;
|
|||
static const unsigned SetFP = 8;
|
||||
static const unsigned PoppedFP = 4;
|
||||
static const unsigned PoppedExitReason = 2;
|
||||
static const unsigned PoppedTLSReg = 0;
|
||||
#elif defined(JS_CODEGEN_X86)
|
||||
static const unsigned PushedRetAddr = 0;
|
||||
static const unsigned PushedTLS = 1;
|
||||
|
@ -254,6 +255,7 @@ static const unsigned PushedFP = 4;
|
|||
static const unsigned SetFP = 6;
|
||||
static const unsigned PoppedFP = 2;
|
||||
static const unsigned PoppedExitReason = 1;
|
||||
static const unsigned PoppedTLSReg = 0;
|
||||
#elif defined(JS_CODEGEN_ARM)
|
||||
static const unsigned BeforePushRetAddr = 0;
|
||||
static const unsigned PushedRetAddr = 4;
|
||||
|
@ -263,6 +265,7 @@ static const unsigned PushedFP = 20;
|
|||
static const unsigned SetFP = 24;
|
||||
static const unsigned PoppedFP = 8;
|
||||
static const unsigned PoppedExitReason = 4;
|
||||
static const unsigned PoppedTLSReg = 0;
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
static const unsigned BeforePushRetAddr = 0;
|
||||
static const unsigned PushedRetAddr = 0;
|
||||
|
@ -272,6 +275,7 @@ static const unsigned PushedFP = 0;
|
|||
static const unsigned SetFP = 0;
|
||||
static const unsigned PoppedFP = 0;
|
||||
static const unsigned PoppedExitReason = 0;
|
||||
static const unsigned PoppedTLSReg = 0;
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
static const unsigned BeforePushRetAddr = 0;
|
||||
static const unsigned PushedRetAddr = 8;
|
||||
|
@ -279,8 +283,9 @@ static const unsigned PushedTLS = 16;
|
|||
static const unsigned PushedExitReason = 28;
|
||||
static const unsigned PushedFP = 36;
|
||||
static const unsigned SetFP = 40;
|
||||
static const unsigned PoppedFP = 16;
|
||||
static const unsigned PoppedExitReason = 8;
|
||||
static const unsigned PoppedFP = 24;
|
||||
static const unsigned PoppedExitReason = 16;
|
||||
static const unsigned PoppedTLSReg = 8;
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
static const unsigned PushedRetAddr = 0;
|
||||
static const unsigned PushedTLS = 1;
|
||||
|
@ -289,6 +294,7 @@ static const unsigned PushedFP = 0;
|
|||
static const unsigned SetFP = 0;
|
||||
static const unsigned PoppedFP = 0;
|
||||
static const unsigned PoppedExitReason = 0;
|
||||
static const unsigned PoppedTLSReg = 0;
|
||||
#else
|
||||
# error "Unknown architecture!"
|
||||
#endif
|
||||
|
@ -448,11 +454,20 @@ GenerateCallableEpilogue(MacroAssembler& masm, unsigned framePushed, ExitReason
|
|||
DebugOnly<uint32_t> poppedExitReason = masm.currentOffset();
|
||||
|
||||
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();
|
||||
masm.ret();
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT_IF(!masm.oom(), PoppedFP == *ret - poppedFP);
|
||||
MOZ_ASSERT_IF(!masm.oom(), PoppedExitReason == *ret - poppedExitReason);
|
||||
MOZ_ASSERT_IF(!masm.oom(), PoppedTLSReg == *ret - poppedTlsReg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -734,7 +749,21 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
|
|||
case CodeRange::BuiltinThunk:
|
||||
case CodeRange::TrapExit:
|
||||
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()) {
|
||||
// The return address is still in lr and fp holds the caller's fp.
|
||||
fixedPC = (uint8_t*) registers.lr;
|
||||
|
@ -766,24 +795,45 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
|
|||
fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress;
|
||||
fixedFP = fp;
|
||||
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
|
||||
// exit reason hasn't been popped yet.
|
||||
fixedPC = sp[2];
|
||||
fixedFP = fp;
|
||||
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
|
||||
// exit reason has been popped.
|
||||
fixedPC = sp[1];
|
||||
fixedFP = fp;
|
||||
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()) {
|
||||
// Both the TLS and fixedFP fields have been popped and fp now
|
||||
// points to the caller's frame.
|
||||
fixedPC = sp[0];
|
||||
fixedFP = fp;
|
||||
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||
#endif
|
||||
} else {
|
||||
if (codeRange->kind() == CodeRange::ImportJitExit) {
|
||||
// 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 RFP_sig(p) ((p)->uc_mcontext.gregs[30])
|
||||
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
|
||||
# define R31_sig(p) ((p)->uc_mcontext.gregs[31])
|
||||
# endif
|
||||
#elif defined(__NetBSD__)
|
||||
# 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 FP_sig(p) RFP_sig(p)
|
||||
# define SP_sig(p) RSP_sig(p)
|
||||
# define LR_sig(p) R31_sig(p)
|
||||
#endif
|
||||
|
||||
static uint8_t**
|
||||
|
@ -447,7 +449,7 @@ ContextToSP(CONTEXT* context)
|
|||
return reinterpret_cast<uint8_t*>(SP_sig(context));
|
||||
}
|
||||
|
||||
# if defined(__arm__) || defined(__aarch64__)
|
||||
# if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
|
||||
static uint8_t*
|
||||
ContextToLR(CONTEXT* context)
|
||||
{
|
||||
|
@ -538,7 +540,7 @@ ToRegisterState(CONTEXT* context)
|
|||
state.fp = ContextToFP(context);
|
||||
state.pc = *ContextToPC(context);
|
||||
state.sp = ContextToSP(context);
|
||||
# if defined(__arm__) || defined(__aarch64__)
|
||||
# if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
|
||||
state.lr = ContextToLR(context);
|
||||
# endif
|
||||
return state;
|
||||
|
|
|
@ -1404,7 +1404,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
|
|||
// This will call back into OnStreamComplete
|
||||
// and thence to ParseSheet. Regardless of whether this fails,
|
||||
// SheetComplete has been called.
|
||||
return nsSyncLoadService::PushSyncStreamToListener(stream,
|
||||
return nsSyncLoadService::PushSyncStreamToListener(stream.forget(),
|
||||
streamLoader,
|
||||
channel);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine, const
|
|||
vprintf(format, args);
|
||||
#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...
|
||||
if (!MOZ_LOG_TEST(gSignalingLog, level)) {
|
||||
|
@ -82,6 +82,6 @@ void CSFLog( CSFLogLevel priority, const char* sourceFile, int sourceLine, const
|
|||
|
||||
int CSFLogTestLevel(CSFLogLevel priority)
|
||||
{
|
||||
mozilla::LogLevel level = static_cast<mozilla::LogLevel>(priority);
|
||||
return MOZ_LOG_TEST(gSignalingLog, level);
|
||||
return MOZ_LOG_TEST(gSignalingLog,
|
||||
static_cast<mozilla::LogLevel>(static_cast<unsigned int>(priority)));
|
||||
}
|
||||
|
|
|
@ -510,6 +510,9 @@ public class CustomTabsActivity extends AppCompatActivity
|
|||
* Callback for Open-in menu item.
|
||||
*/
|
||||
private void onOpenInClicked() {
|
||||
if (TextUtils.isEmpty(mCurrentUrl)) {
|
||||
return;
|
||||
}
|
||||
final Intent intent = new Intent();
|
||||
intent.setData(Uri.parse(mCurrentUrl));
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
|
|
|
@ -1216,7 +1216,7 @@ PREF_RegisterCallback(const char* aPrefNode,
|
|||
NS_PRECONDITION(aPrefNode, "aPrefNode 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->mFunc = aCallback;
|
||||
node->mData = aData;
|
||||
|
@ -2975,7 +2975,7 @@ nsPrefBranch::GetChildList(const char* aStartingAt,
|
|||
numPrefs = prefArray.Length();
|
||||
|
||||
if (numPrefs) {
|
||||
outArray = new char*[numPrefs];
|
||||
outArray = (char**)moz_xmalloc(numPrefs * sizeof(char*));
|
||||
|
||||
for (dwIndex = 0; dwIndex < numPrefs; ++dwIndex) {
|
||||
// we need to lop off mPrefRoot in case the user is planning to pass this
|
||||
|
|
|
@ -727,8 +727,9 @@ nsInputStreamPump::CreateBufferedStreamIfNeeded()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAsyncInputStream> stream = mAsyncStream;
|
||||
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
|
||||
mAsyncStream, 4096);
|
||||
stream.forget(), 4096);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1370,38 +1370,24 @@ NS_BufferOutputStream(nsIOutputStream *aOutputStream,
|
|||
}
|
||||
|
||||
MOZ_MUST_USE nsresult
|
||||
NS_NewBufferedInputStream(nsIInputStream **result,
|
||||
nsIInputStream *str,
|
||||
uint32_t bufferSize)
|
||||
NS_NewBufferedInputStream(nsIInputStream** aResult,
|
||||
already_AddRefed<nsIInputStream> aInputStream,
|
||||
uint32_t aBufferSize)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIBufferedInputStream> in =
|
||||
do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = in->Init(str, bufferSize);
|
||||
rv = in->Init(inputStream, aBufferSize);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
in.forget(result);
|
||||
in.forget(aResult);
|
||||
}
|
||||
}
|
||||
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
|
||||
NS_NewPostDataStream(nsIInputStream **result,
|
||||
bool isFile,
|
||||
|
@ -1418,7 +1404,8 @@ NS_NewPostDataStream(nsIInputStream **result,
|
|||
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// wrap the file stream with a buffered input stream
|
||||
rv = NS_NewBufferedInputStream(result, fileStream, 8192);
|
||||
rv = NS_NewBufferedInputStream(result, fileStream.forget(),
|
||||
8192);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
|
|
@ -511,9 +511,9 @@ nsresult NS_NewLocalFileStream(nsIFileStream **result,
|
|||
int32_t behaviorFlags = 0);
|
||||
|
||||
MOZ_MUST_USE nsresult
|
||||
NS_NewBufferedInputStream(nsIInputStream **result,
|
||||
nsIInputStream *str,
|
||||
uint32_t bufferSize);
|
||||
NS_NewBufferedInputStream(nsIInputStream** aResult,
|
||||
already_AddRefed<nsIInputStream> aInputStream,
|
||||
uint32_t aBufferSize);
|
||||
|
||||
// note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
|
||||
// provided stream supports it.
|
||||
|
@ -535,9 +535,6 @@ nsresult NS_NewBufferedOutputStream(nsIOutputStream **result,
|
|||
already_AddRefed<nsIOutputStream>
|
||||
NS_BufferOutputStream(nsIOutputStream *aOutputStream,
|
||||
uint32_t aBufferSize);
|
||||
already_AddRefed<nsIInputStream>
|
||||
NS_BufferInputStream(nsIInputStream *aInputStream,
|
||||
uint32_t aBufferSize);
|
||||
|
||||
// returns an input stream compatible with nsIUploadChannel::SetUploadStream()
|
||||
nsresult NS_NewPostDataStream(nsIInputStream **result,
|
||||
|
|
|
@ -929,7 +929,8 @@ HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
|
|||
if (NS_InputStreamIsBuffered(mUploadStream)) {
|
||||
source = mUploadStream;
|
||||
} else {
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096);
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(source),
|
||||
mUploadStream.forget(), 4096);
|
||||
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
|
||||
// necessary to workaround some common server bugs (see bug 137155).
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi));
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), stream,
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream),
|
||||
stream.forget(),
|
||||
nsIOService::gDefaultSegmentSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
} else {
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
#include "nsEscape.h"
|
||||
#include "nsIDirIndex.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsITextToSubURI.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nsString.h"
|
||||
#include <algorithm>
|
||||
#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
|
||||
// 2. query part may not be encoded in UTF-8 (see bug 261929)
|
||||
// so try the platform's default if this is file url
|
||||
if (NS_FAILED(rv) && isSchemeFile) {
|
||||
nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv) && isSchemeFile && !NS_IsNativeUTF8()) {
|
||||
auto encoding = mozilla::dom::FallbackEncoding::FromLocale();
|
||||
nsAutoCString charset;
|
||||
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
encoding->Name(charset);
|
||||
rv = mTextToSubURI->UnEscapeAndConvert(charset, titleUri, unEscapeSpec);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
|
|
@ -474,24 +474,25 @@ nsSAXXMLReader::ParseFromString(const nsAString &aStr,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
||||
nsSAXXMLReader::ParseFromStream(nsIInputStream *aStreamPtr,
|
||||
const char *aCharset,
|
||||
const char *aContentType)
|
||||
{
|
||||
// Don't call this in the middle of an async parse
|
||||
NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
|
||||
|
||||
NS_ENSURE_ARG(aStream);
|
||||
NS_ENSURE_ARG(aStreamPtr);
|
||||
NS_ENSURE_ARG(aContentType);
|
||||
|
||||
// Put the nsCOMPtr out here so we hold a ref to the stream as needed
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
if (!NS_InputStreamIsBuffered(aStream)) {
|
||||
nsCOMPtr<nsIInputStream> stream = aStreamPtr;
|
||||
if (!NS_InputStreamIsBuffered(stream)) {
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
aStream, 4096);
|
||||
stream.forget(), 4096);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aStream = bufferedStream;
|
||||
stream = bufferedStream;
|
||||
}
|
||||
|
||||
rv = EnsureBaseURI();
|
||||
|
@ -504,7 +505,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
|||
nsCOMPtr<nsIChannel> parserChannel;
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
|
||||
mBaseURI,
|
||||
aStream,
|
||||
stream,
|
||||
nullPrincipal,
|
||||
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
|
@ -536,7 +537,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
|||
uint64_t offset = 0;
|
||||
while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
||||
uint64_t available;
|
||||
rv = aStream->Available(&available);
|
||||
rv = stream->Available(&available);
|
||||
if (rv == NS_BASE_STREAM_CLOSED) {
|
||||
rv = NS_OK;
|
||||
available = 0;
|
||||
|
@ -552,7 +553,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
|||
available = UINT32_MAX;
|
||||
|
||||
rv = mListener->OnDataAvailable(parserChannel, nullptr,
|
||||
aStream,
|
||||
stream,
|
||||
offset,
|
||||
(uint32_t)available);
|
||||
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
|
||||
// ReadSegments is implemented (which OnDataAvailable expects).
|
||||
nsCOMPtr<nsIInputStream> bufStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in,
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in.forget(),
|
||||
4096 /* buffer size */);
|
||||
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
|
||||
* for this browser. If so, the Promise will only resolve once the
|
||||
* tab crash page has loaded.
|
||||
* @param (bool) shouldClearMinidumps
|
||||
* True if the minidumps left behind by the crash should be removed.
|
||||
*
|
||||
* @returns (Promise)
|
||||
* @resolves An Object with key-value pairs representing the data from the
|
||||
* crash report's extra file (if applicable).
|
||||
*/
|
||||
async crashBrowser(browser, shouldShowTabCrashPage=true) {
|
||||
async crashBrowser(browser, shouldShowTabCrashPage=true,
|
||||
shouldClearMinidumps=true) {
|
||||
let extra = {};
|
||||
let KeyValueParser = {};
|
||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
|
@ -1107,8 +1110,10 @@ this.BrowserTestUtils = {
|
|||
}
|
||||
}
|
||||
|
||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
||||
if (shouldClearMinidumps) {
|
||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -638,8 +638,13 @@ TestRunner.testFinished = function(tests) {
|
|||
}
|
||||
|
||||
SpecialPowers.executeAfterFlushingMessageQueue(function() {
|
||||
cleanUpCrashDumpFiles();
|
||||
SpecialPowers.flushPermissions(function () { SpecialPowers.flushPrefEnv(runNextTest); });
|
||||
SpecialPowers.waitForCrashes(TestRunner._expectingProcessCrash)
|
||||
.then(() => {
|
||||
cleanUpCrashDumpFiles();
|
||||
SpecialPowers.flushPermissions(function () {
|
||||
SpecialPowers.flushPrefEnv(runNextTest);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -330,10 +330,23 @@ function expectedException(actual, expected) {
|
|||
* 11. Expected to throw an error:
|
||||
* 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
|
||||
* (function) Function block to evaluate and catch eventual thrown errors
|
||||
* @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)
|
||||
* (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) {
|
||||
compareNumbers.call(this, lhs > rhs, lhs, rhs, message, "<=");
|
||||
};
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ SpecialPowersObserver.prototype._loadFrameScript = function() {
|
|||
if (!this._isFrameScriptLoaded) {
|
||||
// Register for any messages our API needs us to handle
|
||||
this._messageManager.addMessageListener("SPPrefService", this);
|
||||
this._messageManager.addMessageListener("SPProcessCrashManagerWait", this);
|
||||
this._messageManager.addMessageListener("SPProcessCrashService", this);
|
||||
this._messageManager.addMessageListener("SPPingService", this);
|
||||
this._messageManager.addMessageListener("SpecialPowers.Quit", this);
|
||||
|
@ -140,6 +141,7 @@ SpecialPowersObserver.prototype.uninit = function() {
|
|||
|
||||
if (this._isFrameScriptLoaded) {
|
||||
this._messageManager.removeMessageListener("SPPrefService", this);
|
||||
this._messageManager.removeMessageListener("SPProcessCrashManagerWait", this);
|
||||
this._messageManager.removeMessageListener("SPProcessCrashService", this);
|
||||
this._messageManager.removeMessageListener("SPPingService", this);
|
||||
this._messageManager.removeMessageListener("SpecialPowers.Quit", this);
|
||||
|
|
|
@ -117,6 +117,10 @@ SpecialPowersObserverAPI.prototype = {
|
|||
}
|
||||
}
|
||||
} else { // ipc:content-shutdown
|
||||
if (!aSubject.hasKey("abnormal")) {
|
||||
return; // This is a normal shutdown, ignore it
|
||||
}
|
||||
|
||||
addDumpIDToMessage("dumpID");
|
||||
}
|
||||
this._sendAsyncMessage("SPProcessCrashService", message);
|
||||
|
@ -393,6 +397,17 @@ SpecialPowersObserverAPI.prototype = {
|
|||
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": {
|
||||
let msg = aMessage.json;
|
||||
let principal = msg.principal;
|
||||
|
|
|
@ -49,6 +49,7 @@ function SpecialPowers(window) {
|
|||
"SpecialPowers.RemoveFiles",
|
||||
"SPPingService",
|
||||
"SPLoadExtension",
|
||||
"SPProcessCrashManagerWait",
|
||||
"SPStartupExtension",
|
||||
"SPUnloadExtension",
|
||||
"SPExtensionMessage"];
|
||||
|
|
|
@ -670,6 +670,31 @@ SpecialPowersAPI.prototype = {
|
|||
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) {
|
||||
var success = true;
|
||||
if (aExpectingProcessCrash) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/memory.h"
|
||||
#include "common/memory_allocator.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
|
|
@ -1295,7 +1295,7 @@ FetchAndConvertUnsupportedPayloads::ConvertPayload(int64_t aId,
|
|||
|
||||
// Decode the input stream to a surface.
|
||||
RefPtr<gfx::SourceSurface> surface =
|
||||
image::ImageOps::DecodeToSurface(stream,
|
||||
image::ImageOps::DecodeToSurface(stream.forget(),
|
||||
aMimeType,
|
||||
imgIContainer::DECODE_FLAGS_DEFAULT);
|
||||
NS_ENSURE_STATE(surface);
|
||||
|
|
|
@ -339,7 +339,9 @@ HashStore::Open()
|
|||
}
|
||||
|
||||
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();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -239,7 +239,10 @@ VariableLengthPrefixSet::LoadFromFile(nsIFile* aFile)
|
|||
MAX_BUFFER_SIZE);
|
||||
|
||||
// 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);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -352,7 +352,10 @@ nsUrlClassifierPrefixSet::LoadFromFile(nsIFile* aFile)
|
|||
MAX_BUFFER_SIZE);
|
||||
|
||||
// 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);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <sys/user.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"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <sys/user.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"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
|
||||
#include "common/basictypes.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/memory.h"
|
||||
#include "common/memory_allocator.h"
|
||||
#include "linux/log/log.h"
|
||||
#include "linux/microdump_writer/microdump_writer.h"
|
||||
#include "linux/minidump_writer/linux_dumper.h"
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче