зеркало из 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 "mozilla/a11y/HandlerProvider.h"
|
||||||
|
|
||||||
#include "Accessible2_3.h"
|
#include "Accessible2_3.h"
|
||||||
|
#include "AccessibleTable.h"
|
||||||
|
#include "AccessibleTable2.h"
|
||||||
#include "HandlerData.h"
|
#include "HandlerData.h"
|
||||||
#include "HandlerData_i.c"
|
#include "HandlerData_i.c"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
|
@ -214,6 +216,18 @@ HandlerProvider::MarshalAs(REFIID aIid)
|
||||||
return aIid;
|
return aIid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REFIID
|
||||||
|
HandlerProvider::GetEffectiveOutParamIid(REFIID aCallIid,
|
||||||
|
ULONG aCallMethod)
|
||||||
|
{
|
||||||
|
if (aCallIid == IID_IAccessibleTable || aCallIid == IID_IAccessibleTable2) {
|
||||||
|
return IID_IAccessible2_3;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
return IID_IUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
HandlerProvider::NewInstance(REFIID aIid,
|
HandlerProvider::NewInstance(REFIID aIid,
|
||||||
mscom::InterceptorTargetPtr<IUnknown> aTarget,
|
mscom::InterceptorTargetPtr<IUnknown> aTarget,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef mozilla_a11y_HandlerProvider_h
|
#ifndef mozilla_a11y_HandlerProvider_h
|
||||||
#define mozilla_a11y_HandlerProvider_h
|
#define mozilla_a11y_HandlerProvider_h
|
||||||
|
|
||||||
#include "handler/AccessibleHandler.h"
|
#include "mozilla/a11y/AccessibleHandler.h"
|
||||||
#include "mozilla/AlreadyAddRefed.h"
|
#include "mozilla/AlreadyAddRefed.h"
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/mscom/IHandlerProvider.h"
|
#include "mozilla/mscom/IHandlerProvider.h"
|
||||||
|
@ -44,6 +44,8 @@ public:
|
||||||
STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override;
|
STDMETHODIMP GetHandlerPayloadSize(NotNull<DWORD*> aOutPayloadSize) override;
|
||||||
STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override;
|
STDMETHODIMP WriteHandlerPayload(NotNull<IStream*> aStream) override;
|
||||||
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
|
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
|
||||||
|
STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
|
||||||
|
ULONG aCallMethod) override;
|
||||||
STDMETHODIMP NewInstance(REFIID aIid,
|
STDMETHODIMP NewInstance(REFIID aIid,
|
||||||
mscom::InterceptorTargetPtr<IUnknown> aTarget,
|
mscom::InterceptorTargetPtr<IUnknown> aTarget,
|
||||||
NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;
|
NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;
|
||||||
|
|
|
@ -297,15 +297,28 @@ Sanitizer.prototype = {
|
||||||
Services.obs.notifyObservers(null, "extension:purge-localStorage");
|
Services.obs.notifyObservers(null, "extension:purge-localStorage");
|
||||||
|
|
||||||
// ServiceWorkers
|
// ServiceWorkers
|
||||||
|
let promises = [];
|
||||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||||
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||||
let host = sw.principal.URI.host;
|
|
||||||
serviceWorkerManager.removeAndPropagate(host);
|
promises.push(new Promise(resolve => {
|
||||||
|
let unregisterCallback = {
|
||||||
|
unregisterSucceeded: () => { resolve(true); },
|
||||||
|
// We don't care about failures.
|
||||||
|
unregisterFailed: () => { resolve(true); },
|
||||||
|
QueryInterface: XPCOMUtils.generateQI(
|
||||||
|
[Ci.nsIServiceWorkerUnregisterCallback])
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceWorkerManager.propagateUnregister(sw.principal, unregisterCallback, sw.scope);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
// QuotaManager
|
// QuotaManager
|
||||||
let promises = [];
|
promises = [];
|
||||||
await new Promise(resolve => {
|
await new Promise(resolve => {
|
||||||
quotaManagerService.getUsage(request => {
|
quotaManagerService.getUsage(request => {
|
||||||
if (request.resultCode != Cr.NS_OK) {
|
if (request.resultCode != Cr.NS_OK) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/PromiseUtils.jsm");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With e10s, plugins must run in their own process. This means we have
|
* With e10s, plugins must run in their own process. This means we have
|
||||||
* three processes at a minimum when we're running a plugin:
|
* three processes at a minimum when we're running a plugin:
|
||||||
|
@ -79,51 +81,56 @@ function preparePlugin(browser, pluginFallbackState) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
add_task(async function setup() {
|
// Bypass click-to-play
|
||||||
// Bypass click-to-play
|
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
|
||||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
|
|
||||||
|
|
||||||
// Clear out any minidumps we create from plugins - we really don't care
|
// Deferred promise object used by the test to wait for the crash handler
|
||||||
// about them.
|
let crashDeferred = null;
|
||||||
let crashObserver = (subject, topic, data) => {
|
|
||||||
if (topic != "plugin-crashed") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
|
// Clear out any minidumps we create from plugins - we really don't care
|
||||||
let minidumpID = propBag.getPropertyAsAString("pluginDumpID");
|
// about them.
|
||||||
|
let crashObserver = (subject, topic, data) => {
|
||||||
|
if (topic != "plugin-crashed") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => {
|
let propBag = subject.QueryInterface(Ci.nsIPropertyBag2);
|
||||||
let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
let minidumpID = propBag.getPropertyAsAString("pluginDumpID");
|
||||||
minidumpDir.append("minidumps");
|
|
||||||
|
|
||||||
let pluginDumpFile = minidumpDir.clone();
|
Services.crashmanager.ensureCrashIsPresent(minidumpID).then(() => {
|
||||||
pluginDumpFile.append(minidumpID + ".dmp");
|
let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||||
|
minidumpDir.append("minidumps");
|
||||||
|
|
||||||
let extraFile = minidumpDir.clone();
|
let pluginDumpFile = minidumpDir.clone();
|
||||||
extraFile.append(minidumpID + ".extra");
|
pluginDumpFile.append(minidumpID + ".dmp");
|
||||||
|
|
||||||
ok(pluginDumpFile.exists(), "Found minidump");
|
let extraFile = minidumpDir.clone();
|
||||||
ok(extraFile.exists(), "Found extra file");
|
extraFile.append(minidumpID + ".extra");
|
||||||
|
|
||||||
pluginDumpFile.remove(false);
|
ok(pluginDumpFile.exists(), "Found minidump");
|
||||||
extraFile.remove(false);
|
ok(extraFile.exists(), "Found extra file");
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Services.obs.addObserver(crashObserver, "plugin-crashed");
|
pluginDumpFile.remove(false);
|
||||||
// plugins.testmode will make BrowserPlugins:Test:ClearCrashData work.
|
extraFile.remove(false);
|
||||||
Services.prefs.setBoolPref("plugins.testmode", true);
|
crashDeferred.resolve();
|
||||||
registerCleanupFunction(() => {
|
|
||||||
Services.prefs.clearUserPref("plugins.testmode");
|
|
||||||
Services.obs.removeObserver(crashObserver, "plugin-crashed");
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Services.obs.addObserver(crashObserver, "plugin-crashed");
|
||||||
|
// plugins.testmode will make BrowserPlugins:Test:ClearCrashData work.
|
||||||
|
Services.prefs.setBoolPref("plugins.testmode", true);
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
Services.prefs.clearUserPref("plugins.testmode");
|
||||||
|
Services.obs.removeObserver(crashObserver, "plugin-crashed");
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this case, the chrome process hears about the crash first.
|
* In this case, the chrome process hears about the crash first.
|
||||||
*/
|
*/
|
||||||
add_task(async function testChromeHearsPluginCrashFirst() {
|
add_task(async function testChromeHearsPluginCrashFirst() {
|
||||||
|
// Setup the crash observer promise
|
||||||
|
crashDeferred = PromiseUtils.defer();
|
||||||
|
|
||||||
// Open a remote window so that we can run this test even if e10s is not
|
// Open a remote window so that we can run this test even if e10s is not
|
||||||
// enabled by default.
|
// enabled by default.
|
||||||
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
|
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
|
||||||
|
@ -183,12 +190,16 @@ add_task(async function testChromeHearsPluginCrashFirst() {
|
||||||
"Should have been showing crash report UI");
|
"Should have been showing crash report UI");
|
||||||
});
|
});
|
||||||
await BrowserTestUtils.closeWindow(win);
|
await BrowserTestUtils.closeWindow(win);
|
||||||
|
await crashDeferred.promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this case, the content process hears about the crash first.
|
* In this case, the content process hears about the crash first.
|
||||||
*/
|
*/
|
||||||
add_task(async function testContentHearsCrashFirst() {
|
add_task(async function testContentHearsCrashFirst() {
|
||||||
|
// Setup the crash observer promise
|
||||||
|
crashDeferred = PromiseUtils.defer();
|
||||||
|
|
||||||
// Open a remote window so that we can run this test even if e10s is not
|
// Open a remote window so that we can run this test even if e10s is not
|
||||||
// enabled by default.
|
// enabled by default.
|
||||||
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
|
let win = await BrowserTestUtils.openNewBrowserWindow({remote: true});
|
||||||
|
@ -253,4 +264,5 @@ add_task(async function testContentHearsCrashFirst() {
|
||||||
});
|
});
|
||||||
|
|
||||||
await BrowserTestUtils.closeWindow(win);
|
await BrowserTestUtils.closeWindow(win);
|
||||||
|
await crashDeferred.promise;
|
||||||
});
|
});
|
||||||
|
|
|
@ -34,7 +34,9 @@ add_task(async function test_clear_email() {
|
||||||
prefs.setBoolPref("emailMe", true);
|
prefs.setBoolPref("emailMe", true);
|
||||||
|
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
let tab = gBrowser.getTabForBrowser(browser);
|
||||||
await BrowserTestUtils.crashBrowser(browser);
|
await BrowserTestUtils.crashBrowser(browser,
|
||||||
|
/* shouldShowTabCrashPage */ true,
|
||||||
|
/* shouldClearMinidumps */ false);
|
||||||
let doc = browser.contentDocument;
|
let doc = browser.contentDocument;
|
||||||
|
|
||||||
// Since about:tabcrashed will run in the parent process, we can safely
|
// Since about:tabcrashed will run in the parent process, we can safely
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
This is the debugger.html project output.
|
This is the debugger.html project output.
|
||||||
See https://github.com/devtools-html/debugger.html
|
See https://github.com/devtools-html/debugger.html
|
||||||
|
|
||||||
Taken from upstream commit: 455e7e3f2de29113e37de8c03052de110f5fb106
|
Taken from upstream commit: aa6b25cc7dc645b8c1d76af58b99012e40b80848
|
||||||
|
|
||||||
Packages:
|
Packages:
|
||||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||||
|
|
|
@ -2,6 +2,141 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
menu {
|
||||||
|
display: inline;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu > menuitem::after {
|
||||||
|
content: "\25BA";
|
||||||
|
float: right;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu > menupopup {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu > menuitem:hover + menupopup,
|
||||||
|
menu > menupopup:hover {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
menupopup {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 10000;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
padding: 5px 0;
|
||||||
|
background: #f2f2f2;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #585858;
|
||||||
|
box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8);
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem {
|
||||||
|
display: block;
|
||||||
|
padding: 0 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 13px;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem:hover {
|
||||||
|
background: #3780fb;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem[disabled=true] {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem[disabled=true]:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem[type=checkbox]::before {
|
||||||
|
content: "";
|
||||||
|
width: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem[type=checkbox][checked=true]::before {
|
||||||
|
content: "\2713";
|
||||||
|
left: -8px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuseparator {
|
||||||
|
border-bottom: 1px solid #cacdd3;
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contextmenu-mask.show {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
:root.theme-light,
|
||||||
|
:root .theme-light {
|
||||||
|
--theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mount {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
border-radius: 8px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(113, 113, 113, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.theme-dark .CodeMirror-scrollbar-filler {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
.landing-page {
|
.landing-page {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -275,144 +410,10 @@
|
||||||
padding-left: 3px;
|
padding-left: 3px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
menu {
|
|
||||||
display: inline;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu > menuitem::after {
|
|
||||||
content: "\25BA";
|
|
||||||
float: right;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu > menupopup {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu > menuitem:hover + menupopup,
|
|
||||||
menu > menupopup:hover {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
menupopup {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 10000;
|
|
||||||
background: white;
|
|
||||||
border: 1px solid #cccccc;
|
|
||||||
padding: 5px 0;
|
|
||||||
background: #f2f2f2;
|
|
||||||
border-radius: 5px;
|
|
||||||
color: #585858;
|
|
||||||
box-shadow: 0 0 4px 0 rgba(190, 190, 190, 0.8);
|
|
||||||
min-width: 130px;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem {
|
|
||||||
display: block;
|
|
||||||
padding: 0 20px;
|
|
||||||
line-height: 20px;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 13px;
|
|
||||||
-moz-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem:hover {
|
|
||||||
background: #3780fb;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem[disabled=true] {
|
|
||||||
color: #cccccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem[disabled=true]:hover {
|
|
||||||
background-color: transparent;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem[type=checkbox]::before {
|
|
||||||
content: "";
|
|
||||||
width: 10px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem[type=checkbox][checked=true]::before {
|
|
||||||
content: "\2713";
|
|
||||||
left: -8px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuseparator {
|
|
||||||
border-bottom: 1px solid #cacdd3;
|
|
||||||
width: 100%;
|
|
||||||
height: 5px;
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#contextmenu-mask.show {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
z-index: 999;
|
|
||||||
}
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
:root.theme-light,
|
|
||||||
:root .theme-light {
|
|
||||||
--theme-search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mount {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
border-radius: 8px;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: 8px;
|
|
||||||
background: rgba(113, 113, 113, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.theme-dark .CodeMirror-scrollbar-filler {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
.modal-wrapper {
|
.modal-wrapper {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -423,13 +424,12 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
top: 0;
|
width: 80%;
|
||||||
margin: auto;
|
height: auto;
|
||||||
width: 500px;
|
overflow-y: scroll;
|
||||||
background-color: var(--theme-toolbar-background);
|
background-color: var(--theme-toolbar-background);
|
||||||
transform: translateY(-250px);
|
|
||||||
transition: transform 150ms cubic-bezier(0.07, 0.95, 0, 1);
|
transition: transform 150ms cubic-bezier(0.07, 0.95, 0, 1);
|
||||||
box-shadow: 0 0 10px 2px var(--popup-shadow-color);
|
box-shadow: 1px 1px 3px 1px var(--popup-shadow-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.entering,
|
.modal.entering,
|
||||||
|
@ -439,13 +439,24 @@ body {
|
||||||
|
|
||||||
.modal.entered,
|
.modal.entered,
|
||||||
.modal.exiting {
|
.modal.exiting {
|
||||||
transform: translateY(0px);
|
transform: translateY(5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 520px) {
|
/* This rule is active when the screen is not short and narrow */
|
||||||
|
@media (min-width: 580px) and (min-height: 340px) {
|
||||||
.modal {
|
.modal {
|
||||||
width: 80%;
|
width: 50%;
|
||||||
left: 10%;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-height: 340px) {
|
||||||
|
.modal {
|
||||||
|
height: auto;
|
||||||
|
max-height: 80vh;
|
||||||
|
}
|
||||||
|
.modal.entered,
|
||||||
|
.modal.exiting {
|
||||||
|
transform: translateY(30px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.shortcuts-content {
|
.shortcuts-content {
|
||||||
|
@ -490,10 +501,6 @@ body {
|
||||||
width: calc(100% - 1px); /* 1px fixes the hidden right border */
|
width: calc(100% - 1px); /* 1px fixes the hidden right border */
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcuts-modal {
|
|
||||||
width: 45%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcuts-list li {
|
.shortcuts-list li {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--theme-body-color);
|
color: var(--theme-body-color);
|
||||||
|
@ -1696,10 +1703,10 @@ html .toggle-button-end.vertical svg {
|
||||||
transition: opacity 200ms;
|
transition: opacity 200ms;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 6px 0.7em;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-footer > .commands > .action i {
|
.source-footer > .commands > .action img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -1718,9 +1725,18 @@ html .toggle-button-end.vertical svg {
|
||||||
fill: var(--theme-selection-color);
|
fill: var(--theme-selection-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-footer > .commands > .action svg {
|
.source-footer > .commands > .action > img.prettyPrint {
|
||||||
|
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
background: var(--theme-body-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-footer > .commands > .action > img.blackBox {
|
||||||
|
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
background: var(--theme-body-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-footer .commands .coverage {
|
.source-footer .commands .coverage {
|
||||||
|
@ -1733,8 +1749,8 @@ html .toggle-button-end.vertical svg {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-footer .black-box.blackboxed svg {
|
.source-footer > .commands > .blackboxed > img.blackBox {
|
||||||
fill: var(--theme-highlight-blue);
|
background: var(--theme-highlight-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-footer .blackbox-summary {
|
.source-footer .blackbox-summary {
|
||||||
|
@ -2188,12 +2204,19 @@ html[dir="rtl"] .arrow svg,
|
||||||
box-shadow: 1px 2px 3px var(--popup-shadow-color);
|
box-shadow: 1px 2px 3px var(--popup-shadow-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover .preview-popup .header {
|
.popover .preview-popup .header-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
border-bottom: 1px solid #cccccc;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popover .preview-popup .header-container h3 {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover .preview-popup .header .link {
|
.popover .preview-popup .header .link {
|
||||||
|
@ -2492,8 +2515,9 @@ html[dir="rtl"] .editor-mount {
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-linenumber {
|
.CodeMirror-linenumber {
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
line-height: 14px;
|
line-height: 15px;
|
||||||
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folding-enabled .CodeMirror-linenumber {
|
.folding-enabled .CodeMirror-linenumber {
|
||||||
|
@ -3149,6 +3173,18 @@ html .command-bar > button:disabled {
|
||||||
.command-bar > button {
|
.command-bar > button {
|
||||||
padding: 6px 5px;
|
padding: 6px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.command-bar.bottom {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-bar.bottom > button {
|
||||||
|
color: var(--theme-comment);
|
||||||
|
width: 26px;
|
||||||
|
}
|
||||||
|
.command-bar.bottom > button:hover {
|
||||||
|
color: var(--theme-body-color);
|
||||||
|
}
|
||||||
.object-node.default-property {
|
.object-node.default-property {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
@ -3373,13 +3409,13 @@ html .welcomebox .toggle-button-end.collapsed {
|
||||||
fill: var(--theme-body-color);
|
fill: var(--theme-body-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-tab .prettyPrint {
|
.source-tab img.prettyPrint {
|
||||||
line-height: 0;
|
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
|
||||||
}
|
mask-size: 100%;
|
||||||
|
padding-top: 12px;
|
||||||
.source-tab .prettyPrint svg {
|
|
||||||
height: 12px;
|
height: 12px;
|
||||||
width: 12px;
|
width: 12px;
|
||||||
|
background: var(--theme-highlight-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-tab .prettyPrint path {
|
.source-tab .prettyPrint path {
|
||||||
|
@ -3388,13 +3424,16 @@ html .welcomebox .toggle-button-end.collapsed {
|
||||||
|
|
||||||
.source-tab .blackBox,
|
.source-tab .blackBox,
|
||||||
.source-tab .prettyPrint {
|
.source-tab .prettyPrint {
|
||||||
line-height: 0;
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-tab .blackBox svg {
|
.source-tab img.blackBox {
|
||||||
|
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
|
||||||
|
mask-size: 100%;
|
||||||
|
padding-top: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
width: 12px;
|
width: 12px;
|
||||||
|
background: var(--theme-highlight-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.source-tab .blackBox path {
|
.source-tab .blackBox path {
|
||||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -78,12 +78,201 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||||
/***/ 1282:
|
/***/ 1282:
|
||||||
/***/ (function(module, exports, __webpack_require__) {
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
module.exports = __webpack_require__(1283);
|
module.exports = __webpack_require__(1630);
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 1283:
|
/***/ 1363:
|
||||||
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
const networkRequest = __webpack_require__(1367);
|
||||||
|
const workerUtils = __webpack_require__(1368);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
networkRequest,
|
||||||
|
workerUtils
|
||||||
|
};
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 1367:
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
function networkRequest(url, opts) {
|
||||||
|
return fetch(url, {
|
||||||
|
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||||
|
}).then(res => {
|
||||||
|
if (res.status >= 200 && res.status < 300) {
|
||||||
|
return res.text().then(text => ({ content: text }));
|
||||||
|
}
|
||||||
|
return Promise.reject(`request failed with status ${res.status}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = networkRequest;
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 1368:
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
||||||
|
|
||||||
|
function WorkerDispatcher() {
|
||||||
|
this.msgId = 1;
|
||||||
|
this.worker = null;
|
||||||
|
} /* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
const mark = typeof window == "object" && window.performance && window.performance.mark ? window.performance.mark.bind(window.performance) : () => {};
|
||||||
|
|
||||||
|
const measure = typeof window == "object" && window.performance && window.performance.measure ? window.performance.measure.bind(window.performance) : () => {};
|
||||||
|
|
||||||
|
WorkerDispatcher.prototype = {
|
||||||
|
start(url) {
|
||||||
|
this.worker = new Worker(url);
|
||||||
|
this.worker.onerror = () => {
|
||||||
|
console.error(`Error in worker ${url}`);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if (!this.worker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.worker.terminate();
|
||||||
|
this.worker = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
task(method) {
|
||||||
|
return (...args) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const id = this.msgId++;
|
||||||
|
|
||||||
|
mark(`${method}_start`);
|
||||||
|
|
||||||
|
this.worker.postMessage({ id, method, args });
|
||||||
|
|
||||||
|
const listener = ({ data: result }) => {
|
||||||
|
if (result.id !== id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.worker) {
|
||||||
|
reject("Oops, The worker has shutdown!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.worker.removeEventListener("message", listener);
|
||||||
|
|
||||||
|
mark(`${method}_end`);
|
||||||
|
measure(`${method}`, `${method}_start`, `${method}_end`);
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
reject(result.error);
|
||||||
|
} else {
|
||||||
|
resolve(result.response);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.worker.addEventListener("message", listener);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function workerHandler(publicInterface) {
|
||||||
|
return function (msg) {
|
||||||
|
const { id, method, args } = msg.data;
|
||||||
|
try {
|
||||||
|
const response = publicInterface[method].apply(undefined, args);
|
||||||
|
if (response instanceof Promise) {
|
||||||
|
response.then(val => self.postMessage({ id, response: val }),
|
||||||
|
// Error can't be sent via postMessage, so be sure to
|
||||||
|
// convert to string.
|
||||||
|
err => self.postMessage({ id, error: err.toString() }));
|
||||||
|
} else {
|
||||||
|
self.postMessage({ id, response });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Error can't be sent via postMessage, so be sure to convert to
|
||||||
|
// string.
|
||||||
|
self.postMessage({ id, error: error.toString() });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
|
||||||
|
let streamingWorker = (() => {
|
||||||
|
var _ref = _asyncToGenerator(function* (id, tasks) {
|
||||||
|
let isWorking = true;
|
||||||
|
|
||||||
|
const intervalId = setTimeout(function () {
|
||||||
|
isWorking = false;
|
||||||
|
}, timeout);
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
while (tasks.length !== 0 && isWorking) {
|
||||||
|
const { callback, context, args } = tasks.shift();
|
||||||
|
const result = yield callback.call(context, args);
|
||||||
|
results.push(result);
|
||||||
|
}
|
||||||
|
worker.postMessage({ id, status: "pending", data: results });
|
||||||
|
clearInterval(intervalId);
|
||||||
|
|
||||||
|
if (tasks.length !== 0) {
|
||||||
|
yield streamingWorker(id, tasks);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return function streamingWorker(_x, _x2) {
|
||||||
|
return _ref.apply(this, arguments);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
return (() => {
|
||||||
|
var _ref2 = _asyncToGenerator(function* (msg) {
|
||||||
|
const { id, method, args } = msg.data;
|
||||||
|
const workerMethod = publicInterface[method];
|
||||||
|
if (!workerMethod) {
|
||||||
|
console.error(`Could not find ${method} defined in worker.`);
|
||||||
|
}
|
||||||
|
worker.postMessage({ id, status: "start" });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tasks = workerMethod(args);
|
||||||
|
yield streamingWorker(id, tasks);
|
||||||
|
worker.postMessage({ id, status: "done" });
|
||||||
|
} catch (error) {
|
||||||
|
worker.postMessage({ id, status: "error", error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return function (_x3) {
|
||||||
|
return _ref2.apply(this, arguments);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
WorkerDispatcher,
|
||||||
|
workerHandler,
|
||||||
|
streamingWorkerHandler
|
||||||
|
};
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 1630:
|
||||||
/***/ (function(module, exports, __webpack_require__) {
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
@ -93,19 +282,14 @@ var _prettyFast = __webpack_require__(802);
|
||||||
|
|
||||||
var _prettyFast2 = _interopRequireDefault(_prettyFast);
|
var _prettyFast2 = _interopRequireDefault(_prettyFast);
|
||||||
|
|
||||||
var _devtoolsUtils = __webpack_require__(900);
|
var _devtoolsUtils = __webpack_require__(1363);
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
|
const { workerHandler } = _devtoolsUtils.workerUtils;
|
||||||
|
|
||||||
|
function prettyPrint({ url, indent, source }) {
|
||||||
function prettyPrint(_ref) {
|
const prettified = (0, _prettyFast2.default)(source, {
|
||||||
var url = _ref.url,
|
|
||||||
indent = _ref.indent,
|
|
||||||
source = _ref.source;
|
|
||||||
|
|
||||||
var prettified = (0, _prettyFast2.default)(source, {
|
|
||||||
url: url,
|
url: url,
|
||||||
indent: " ".repeat(indent)
|
indent: " ".repeat(indent)
|
||||||
});
|
});
|
||||||
|
@ -118,7 +302,7 @@ function prettyPrint(_ref) {
|
||||||
|
|
||||||
function invertMappings(mappings) {
|
function invertMappings(mappings) {
|
||||||
return mappings._array.map(m => {
|
return mappings._array.map(m => {
|
||||||
var mapping = {
|
const mapping = {
|
||||||
generated: {
|
generated: {
|
||||||
line: m.originalLine,
|
line: m.originalLine,
|
||||||
column: m.originalColumn
|
column: m.originalColumn
|
||||||
|
@ -7411,184 +7595,6 @@ SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSou
|
||||||
exports.SourceNode = SourceNode;
|
exports.SourceNode = SourceNode;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
|
|
||||||
/***/ 900:
|
|
||||||
/***/ (function(module, exports, __webpack_require__) {
|
|
||||||
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
const networkRequest = __webpack_require__(901);
|
|
||||||
const workerUtils = __webpack_require__(902);
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
networkRequest,
|
|
||||||
workerUtils
|
|
||||||
};
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
|
|
||||||
/***/ 901:
|
|
||||||
/***/ (function(module, exports) {
|
|
||||||
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
function networkRequest(url, opts) {
|
|
||||||
return fetch(url, {
|
|
||||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
|
||||||
}).then(res => {
|
|
||||||
if (res.status >= 200 && res.status < 300) {
|
|
||||||
return res.text().then(text => ({ content: text }));
|
|
||||||
}
|
|
||||||
return Promise.reject(`request failed with status ${res.status}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = networkRequest;
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
|
|
||||||
/***/ 902:
|
|
||||||
/***/ (function(module, exports) {
|
|
||||||
|
|
||||||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
|
||||||
|
|
||||||
function WorkerDispatcher() {
|
|
||||||
this.msgId = 1;
|
|
||||||
this.worker = null;
|
|
||||||
} /* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
WorkerDispatcher.prototype = {
|
|
||||||
start(url) {
|
|
||||||
this.worker = new Worker(url);
|
|
||||||
this.worker.onerror = () => {
|
|
||||||
console.error(`Error in worker ${url}`);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
if (!this.worker) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.worker.terminate();
|
|
||||||
this.worker = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
task(method) {
|
|
||||||
return (...args) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const id = this.msgId++;
|
|
||||||
this.worker.postMessage({ id, method, args });
|
|
||||||
|
|
||||||
const listener = ({ data: result }) => {
|
|
||||||
if (result.id !== id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.worker) {
|
|
||||||
reject("Oops, The worker has shutdown!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.worker.removeEventListener("message", listener);
|
|
||||||
if (result.error) {
|
|
||||||
reject(result.error);
|
|
||||||
} else {
|
|
||||||
resolve(result.response);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.worker.addEventListener("message", listener);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function workerHandler(publicInterface) {
|
|
||||||
return function (msg) {
|
|
||||||
const { id, method, args } = msg.data;
|
|
||||||
try {
|
|
||||||
const response = publicInterface[method].apply(undefined, args);
|
|
||||||
if (response instanceof Promise) {
|
|
||||||
response.then(val => self.postMessage({ id, response: val }),
|
|
||||||
// Error can't be sent via postMessage, so be sure to
|
|
||||||
// convert to string.
|
|
||||||
err => self.postMessage({ id, error: err.toString() }));
|
|
||||||
} else {
|
|
||||||
self.postMessage({ id, response });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// Error can't be sent via postMessage, so be sure to convert to
|
|
||||||
// string.
|
|
||||||
self.postMessage({ id, error: error.toString() });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
|
|
||||||
let streamingWorker = (() => {
|
|
||||||
var _ref = _asyncToGenerator(function* (id, tasks) {
|
|
||||||
let isWorking = true;
|
|
||||||
|
|
||||||
const intervalId = setTimeout(function () {
|
|
||||||
isWorking = false;
|
|
||||||
}, timeout);
|
|
||||||
|
|
||||||
const results = [];
|
|
||||||
while (tasks.length !== 0 && isWorking) {
|
|
||||||
const { callback, context, args } = tasks.shift();
|
|
||||||
const result = yield callback.call(context, args);
|
|
||||||
results.push(result);
|
|
||||||
}
|
|
||||||
worker.postMessage({ id, status: "pending", data: results });
|
|
||||||
clearInterval(intervalId);
|
|
||||||
|
|
||||||
if (tasks.length !== 0) {
|
|
||||||
yield streamingWorker(id, tasks);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return function streamingWorker(_x, _x2) {
|
|
||||||
return _ref.apply(this, arguments);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
return (() => {
|
|
||||||
var _ref2 = _asyncToGenerator(function* (msg) {
|
|
||||||
const { id, method, args } = msg.data;
|
|
||||||
const workerMethod = publicInterface[method];
|
|
||||||
if (!workerMethod) {
|
|
||||||
console.error(`Could not find ${method} defined in worker.`);
|
|
||||||
}
|
|
||||||
worker.postMessage({ id, status: "start" });
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tasks = workerMethod(args);
|
|
||||||
yield streamingWorker(id, tasks);
|
|
||||||
worker.postMessage({ id, status: "done" });
|
|
||||||
} catch (error) {
|
|
||||||
worker.postMessage({ id, status: "error", error });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return function (_x3) {
|
|
||||||
return _ref2.apply(this, arguments);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
WorkerDispatcher,
|
|
||||||
workerHandler,
|
|
||||||
streamingWorkerHandler
|
|
||||||
};
|
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
||||||
/******/ });
|
/******/ });
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -109,5 +109,5 @@ skip-if = true # Bug 1393121, 1393299
|
||||||
[browser_dbg-tabs.js]
|
[browser_dbg-tabs.js]
|
||||||
[browser_dbg-toggling-tools.js]
|
[browser_dbg-toggling-tools.js]
|
||||||
[browser_dbg-wasm-sourcemaps.js]
|
[browser_dbg-wasm-sourcemaps.js]
|
||||||
skip-if = true
|
skip-if = asan
|
||||||
[browser_dbg-reload.js]
|
[browser_dbg-reload.js]
|
||||||
|
|
|
@ -39,21 +39,21 @@ add_task(async function() {
|
||||||
const dbg = await initDebugger("doc-scripts.html");
|
const dbg = await initDebugger("doc-scripts.html");
|
||||||
await selectSource(dbg, "simple2");
|
await selectSource(dbg, "simple2");
|
||||||
|
|
||||||
dump('Adding a conditional Breakpoint\n')
|
dump("Adding a conditional Breakpoint\n");
|
||||||
await setConditionalBreakpoint(dbg, 5, "1");
|
await setConditionalBreakpoint(dbg, 5, "1");
|
||||||
await waitForDispatch(dbg, "ADD_BREAKPOINT");
|
await waitForDispatch(dbg, "ADD_BREAKPOINT");
|
||||||
let bp = findBreakpoint(dbg, "simple2", 5);
|
let bp = findBreakpoint(dbg, "simple2", 5);
|
||||||
is(bp.condition, "1", "breakpoint is created with the condition");
|
is(bp.condition, "1", "breakpoint is created with the condition");
|
||||||
assertEditorBreakpoint(dbg, 5, true);
|
assertEditorBreakpoint(dbg, 5, true);
|
||||||
|
|
||||||
dump('Editing a conditional breakpoint\n')
|
dump("Editing a conditional breakpoint\n");
|
||||||
await setConditionalBreakpoint(dbg, 5, "2");
|
await setConditionalBreakpoint(dbg, 5, "2");
|
||||||
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
|
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
|
||||||
bp = findBreakpoint(dbg, "simple2", 5);
|
bp = findBreakpoint(dbg, "simple2", 5);
|
||||||
is(bp.condition, "12", "breakpoint is created with the condition");
|
is(bp.condition, "12", "breakpoint is created with the condition");
|
||||||
assertEditorBreakpoint(dbg, 5, true);
|
assertEditorBreakpoint(dbg, 5, true);
|
||||||
|
|
||||||
dump("Removing a conditional breakpoint\n")
|
dump("Removing a conditional breakpoint\n");
|
||||||
clickElement(dbg, "gutter", 5);
|
clickElement(dbg, "gutter", 5);
|
||||||
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
|
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
|
||||||
bp = findBreakpoint(dbg, "simple2", 5);
|
bp = findBreakpoint(dbg, "simple2", 5);
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
* Tests that the debugger is succesfully loaded in the Browser Content Toolbox.
|
* Tests that the debugger is succesfully loaded in the Browser Content Toolbox.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
|
const {
|
||||||
|
gDevToolsBrowser
|
||||||
|
} = require("devtools/client/framework/devtools-browser");
|
||||||
|
|
||||||
function toggleBreakpoint(dbg, index) {
|
function toggleBreakpoint(dbg, index) {
|
||||||
const bp = findElement(dbg, "breakpointItem", index);
|
const bp = findElement(dbg, "breakpointItem", index);
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This if the debugger's layout is correctly modified when the toolbox's
|
||||||
|
* host changes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var gDefaultHostType = Services.prefs.getCharPref("devtools.toolbox.host");
|
||||||
|
|
||||||
|
add_task(async function() {
|
||||||
|
// test is too slow on some platforms due to the number of test cases
|
||||||
|
requestLongerTimeout(2);
|
||||||
|
|
||||||
|
const dbg = await initDebugger("doc-iframes.html");
|
||||||
|
|
||||||
|
const layouts = [
|
||||||
|
["horizontal", "bottom"],
|
||||||
|
["vertical", "side"],
|
||||||
|
["horizontal", "window:big"],
|
||||||
|
["vertical", "window:small"]
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let layout of layouts) {
|
||||||
|
const [orientation, host] = layout;
|
||||||
|
await testLayout(dbg, orientation, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(true, "Orientations are correct");
|
||||||
|
});
|
||||||
|
|
||||||
|
async function testLayout(dbg, orientation, host) {
|
||||||
|
const { panel, toolbox } = dbg;
|
||||||
|
info(`Switching to ${host} ${orientation}.`);
|
||||||
|
|
||||||
|
await switchHost(dbg, host);
|
||||||
|
await resizeToolboxWindow(dbg, host);
|
||||||
|
return waitForState(
|
||||||
|
dbg,
|
||||||
|
state => dbg.selectors.getOrientation(state) == orientation
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHost(host) {
|
||||||
|
if (host.indexOf("window") == 0) {
|
||||||
|
return "window";
|
||||||
|
}
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function switchHost(dbg, hostType) {
|
||||||
|
const { toolbox } = dbg;
|
||||||
|
await toolbox.switchHost(getHost(hostType));
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeToolboxWindow(dbg, host) {
|
||||||
|
const { panel, toolbox } = dbg;
|
||||||
|
let sizeOption = host.split(":")[1];
|
||||||
|
let win = toolbox.win.parent;
|
||||||
|
|
||||||
|
let breakpoint = 700;
|
||||||
|
if (sizeOption == "big" && win.outerWidth <= breakpoint) {
|
||||||
|
return resizeWindow(dbg, breakpoint + 300);
|
||||||
|
} else if (sizeOption == "small" && win.outerWidth >= breakpoint) {
|
||||||
|
return resizeWindow(dbg, breakpoint - 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeWindow(dbg, width) {
|
||||||
|
const { panel, toolbox } = dbg;
|
||||||
|
let win = toolbox.win.parent;
|
||||||
|
const currentWidth = win.screen.width;
|
||||||
|
win.resizeTo(width, window.screen.availHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
Services.prefs.setCharPref("devtools.toolbox.host", gDefaultHostType);
|
||||||
|
gDefaultHostType = null;
|
||||||
|
});
|
|
@ -7,6 +7,10 @@
|
||||||
add_task(async function() {
|
add_task(async function() {
|
||||||
const dbg = await initDebugger("doc-wasm-sourcemaps.html");
|
const dbg = await initDebugger("doc-wasm-sourcemaps.html");
|
||||||
|
|
||||||
|
// NOTE: wait for page load -- attempt to fight the intermittent failure:
|
||||||
|
// "A promise chain failed to handle a rejection: Debugger.Frame is not live"
|
||||||
|
await waitForSource(dbg, "doc-wasm-sourcemaps");
|
||||||
|
|
||||||
await reload(dbg);
|
await reload(dbg);
|
||||||
await waitForPaused(dbg);
|
await waitForPaused(dbg);
|
||||||
assertPausedLocation(dbg);
|
assertPausedLocation(dbg);
|
||||||
|
|
|
@ -362,11 +362,11 @@ function createDebuggerContext(toolbox) {
|
||||||
store: store,
|
store: store,
|
||||||
client: client,
|
client: client,
|
||||||
toolbox: toolbox,
|
toolbox: toolbox,
|
||||||
win: win
|
win: win,
|
||||||
|
panel: panel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all the debugger related preferences.
|
* Clear all the debugger related preferences.
|
||||||
*/
|
*/
|
||||||
|
@ -511,7 +511,7 @@ function stepOut(dbg) {
|
||||||
function resume(dbg) {
|
function resume(dbg) {
|
||||||
info("Resuming");
|
info("Resuming");
|
||||||
dbg.actions.resume();
|
dbg.actions.resume();
|
||||||
return waitForState(dbg, (state) => !dbg.selectors.isPaused(state));
|
return waitForState(dbg, state => !dbg.selectors.isPaused(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteExpression(dbg, input) {
|
function deleteExpression(dbg, input) {
|
||||||
|
|
|
@ -299,3 +299,5 @@ devtools.jar:
|
||||||
|
|
||||||
# Debugger
|
# Debugger
|
||||||
skin/images/debugger/arrow.svg (themes/images/debugger/arrow.svg)
|
skin/images/debugger/arrow.svg (themes/images/debugger/arrow.svg)
|
||||||
|
skin/images/debugger/blackBox.svg (themes/images/debugger/blackBox.svg)
|
||||||
|
skin/images/debugger/prettyPrint.svg (themes/images/debugger/prettyPrint.svg)
|
||||||
|
|
|
@ -24,6 +24,11 @@ copySource.accesskey=y
|
||||||
copySourceUri2=Copy source URI
|
copySourceUri2=Copy source URI
|
||||||
copySourceUri2.accesskey=u
|
copySourceUri2.accesskey=u
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (setDirectoryRoot): This is the text that appears in the
|
||||||
|
# context menu to set a directory as root directory
|
||||||
|
setDirectoryRoot.label=Set directory root
|
||||||
|
setDirectoryRoot.accesskey=r
|
||||||
|
|
||||||
# LOCALIZATION NOTE (copyFunction): This is the text that appears in the
|
# LOCALIZATION NOTE (copyFunction): This is the text that appears in the
|
||||||
# context menu to copy the function the user selected
|
# context menu to copy the function the user selected
|
||||||
copyFunction.label=Copy function
|
copyFunction.label=Copy function
|
||||||
|
@ -367,6 +372,7 @@ editor.addBreakpoint=Add breakpoint
|
||||||
# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item
|
# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item
|
||||||
# for disabling a breakpoint on a line.
|
# for disabling a breakpoint on a line.
|
||||||
editor.disableBreakpoint=Disable breakpoint
|
editor.disableBreakpoint=Disable breakpoint
|
||||||
|
editor.disableBreakpoint.accesskey=D
|
||||||
|
|
||||||
# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item
|
# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item
|
||||||
# for enabling a breakpoint on a line.
|
# for enabling a breakpoint on a line.
|
||||||
|
@ -381,8 +387,9 @@ editor.removeBreakpoint=Remove breakpoint
|
||||||
editor.editBreakpoint=Edit breakpoint
|
editor.editBreakpoint=Edit breakpoint
|
||||||
|
|
||||||
# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context
|
# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context
|
||||||
# menu item for adding a breakpoint condition on a line.
|
# menu item for adding/editing a breakpoint condition on a line.
|
||||||
editor.addConditionalBreakpoint=Add conditional breakpoint
|
editor.addConditionalBreakpoint=Add/Edit conditional breakpoint
|
||||||
|
editor.addConditionalBreakpoint.accesskey=c
|
||||||
|
|
||||||
# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for
|
# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for
|
||||||
# input element inside ConditionalPanel component
|
# input element inside ConditionalPanel component
|
||||||
|
@ -395,6 +402,7 @@ editor.conditionalPanel.close=Cancel edit breakpoint and close
|
||||||
# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
|
# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
|
||||||
# for navigating to a source mapped location
|
# for navigating to a source mapped location
|
||||||
editor.jumpToMappedLocation1=Jump to %S location
|
editor.jumpToMappedLocation1=Jump to %S location
|
||||||
|
editor.jumpToMappedLocation1.accesskey=m
|
||||||
|
|
||||||
# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
|
# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
|
||||||
# context menu to disable framework grouping.
|
# context menu to disable framework grouping.
|
||||||
|
@ -415,6 +423,7 @@ original=original
|
||||||
# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
|
# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
|
||||||
# input element
|
# input element
|
||||||
expressions.placeholder=Add watch expression
|
expressions.placeholder=Add watch expression
|
||||||
|
expressions.placeholder.accesskey=e
|
||||||
|
|
||||||
# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item
|
# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item
|
||||||
# for closing the selected tab below the mouse.
|
# for closing the selected tab below the mouse.
|
||||||
|
@ -468,10 +477,6 @@ sourceFooter.codeCoverage=Code coverage
|
||||||
# for close tab button in source tabs.
|
# for close tab button in source tabs.
|
||||||
sourceTabs.closeTabButtonTooltip=Close tab
|
sourceTabs.closeTabButtonTooltip=Close tab
|
||||||
|
|
||||||
# LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for
|
|
||||||
# new tab button in source tabs.
|
|
||||||
sourceTabs.newTabButtonTooltip=Search for sources (%S)
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.
|
# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.
|
||||||
scopes.header=Scopes
|
scopes.header=Scopes
|
||||||
|
|
||||||
|
@ -754,6 +759,7 @@ anonymous=(anonymous)
|
||||||
# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing
|
# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing
|
||||||
# keyboard shortcut action for toggling breakpoint
|
# keyboard shortcut action for toggling breakpoint
|
||||||
shortcuts.toggleBreakpoint=Toggle Breakpoint
|
shortcuts.toggleBreakpoint=Toggle Breakpoint
|
||||||
|
shortcuts.toggleBreakpoint.accesskey=B
|
||||||
|
|
||||||
# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing
|
# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing
|
||||||
# keyboard shortcut action for toggling conditional panel keyboard
|
# keyboard shortcut action for toggling conditional panel keyboard
|
||||||
|
|
|
@ -37,5 +37,10 @@ pref("devtools.debugger.file-search-case-sensitive", false);
|
||||||
pref("devtools.debugger.file-search-whole-word", false);
|
pref("devtools.debugger.file-search-whole-word", false);
|
||||||
pref("devtools.debugger.file-search-regex-match", false);
|
pref("devtools.debugger.file-search-regex-match", false);
|
||||||
pref("devtools.debugger.features.async-stepping", true);
|
pref("devtools.debugger.features.async-stepping", true);
|
||||||
|
|
||||||
pref("devtools.debugger.features.project-text-search", true);
|
pref("devtools.debugger.features.project-text-search", true);
|
||||||
pref("devtools.debugger.features.wasm", true);
|
pref("devtools.debugger.features.wasm", true);
|
||||||
|
pref("devtools.debugger.features.shortcuts", true);
|
||||||
|
pref("devtools.debugger.project-directory-root", "");
|
||||||
|
pref("devtools.debugger.features.root", false);
|
||||||
|
pref("devtools.debugger.features.column-breakpoints", false);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g fill-rule="evenodd">
|
||||||
|
<circle cx="8" cy="8.5" r="1.5"/>
|
||||||
|
<path d="M15.498 8.28l-.001-.03v-.002-.004l-.002-.018-.004-.031c0-.002 0-.002 0 0l-.004-.035.006.082c-.037-.296-.133-.501-.28-.661-.4-.522-.915-1.042-1.562-1.604-1.36-1.182-2.74-1.975-4.178-2.309a6.544 6.544 0 0 0-2.755-.042c-.78.153-1.565.462-2.369.91C3.252 5.147 2.207 6 1.252 7.035c-.216.233-.36.398-.499.577-.338.437-.338 1 0 1.437.428.552.941 1.072 1.59 1.635 1.359 1.181 2.739 1.975 4.177 2.308.907.21 1.829.223 2.756.043.78-.153 1.564-.462 2.369-.91 1.097-.612 2.141-1.464 3.097-2.499.217-.235.36-.398.498-.578.12-.128.216-.334.248-.554 0 .01 0 .01-.008.04l.013-.079-.001.011.003-.031.001-.017v.005l.001-.02v.008l.002-.03.001-.05-.001-.044v-.004-.004zm-.954.045v.007l.001.004V8.33v.012l-.001.01v-.005-.005l.002-.015-.001.008c-.002.014-.002.014 0 0l-.007.084c.003-.057-.004-.041-.014-.031-.143.182-.27.327-.468.543-.89.963-1.856 1.752-2.86 2.311-.724.404-1.419.677-2.095.81a5.63 5.63 0 0 1-2.374-.036c-1.273-.295-2.523-1.014-3.774-2.101-.604-.525-1.075-1.001-1.457-1.496-.054-.07-.054-.107 0-.177.117-.152.244-.298.442-.512.89-.963 1.856-1.752 2.86-2.311.724-.404 1.419-.678 2.095-.81a5.631 5.631 0 0 1 2.374.036c1.272.295 2.523 1.014 3.774 2.101.603.524 1.074 1 1.457 1.496.035.041.043.057.046.076 0 .01 0 .01.008.043l-.009-.047.003.02-.002-.013v-.008.016c0-.004 0-.004 0 0v-.004z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 1.6 KiB |
|
@ -0,0 +1,6 @@
|
||||||
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4.525 13.21h-.472c-.574 0-.987-.154-1.24-.463-.253-.31-.38-.882-.38-1.719v-.573c0-.746-.097-1.265-.292-1.557-.196-.293-.51-.44-.945-.44v-.974c.435 0 .75-.146.945-.44.195-.292.293-.811.293-1.556v-.58c0-.833.126-1.404.379-1.712.253-.31.666-.464 1.24-.464h.472v.783h-.179c-.37 0-.628.08-.774.24-.145.159-.218.54-.218 1.141v.383c0 .824-.096 1.432-.287 1.823-.191.39-.516.679-.974.866.458.191.783.482.974.873.191.39.287.998.287 1.823v.382c0 .602.073.982.218 1.142.146.16.404.239.774.239h.18v.783zm9.502-4.752c-.43 0-.744.147-.942.44-.197.292-.296.811-.296 1.557v.573c0 .837-.125 1.41-.376 1.719-.251.309-.664.463-1.237.463h-.478v-.783h.185c.37 0 .628-.08.774-.24.145-.159.218-.539.218-1.14v-.383c0-.825.096-1.433.287-1.823.191-.39.516-.682.974-.873-.458-.187-.783-.476-.974-.866-.191-.391-.287-.999-.287-1.823v-.383c0-.602-.073-.982-.218-1.142-.146-.159-.404-.239-.774-.239h-.185v-.783h.478c.573 0 .986.155 1.237.464.25.308.376.88.376 1.712v.58c0 .673.088 1.174.263 1.503.176.329.5.493.975.493v.974z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 1.3 KiB |
|
@ -196,35 +196,36 @@ DOMParser::ParseFromStream(nsIInputStream* aStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
DOMParser::ParseFromStream(nsIInputStream *stream,
|
DOMParser::ParseFromStream(nsIInputStream* aStream,
|
||||||
const char *charset,
|
const char* aCharset,
|
||||||
int32_t contentLength,
|
int32_t aContentLength,
|
||||||
const char *contentType,
|
const char* aContentType,
|
||||||
nsIDOMDocument **aResult)
|
nsIDOMDocument** aResult)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG(stream);
|
NS_ENSURE_ARG(aStream);
|
||||||
NS_ENSURE_ARG(contentType);
|
NS_ENSURE_ARG(aContentType);
|
||||||
NS_ENSURE_ARG_POINTER(aResult);
|
NS_ENSURE_ARG_POINTER(aResult);
|
||||||
*aResult = nullptr;
|
*aResult = nullptr;
|
||||||
|
|
||||||
bool svg = nsCRT::strcmp(contentType, "image/svg+xml") == 0;
|
bool svg = nsCRT::strcmp(aContentType, "image/svg+xml") == 0;
|
||||||
|
|
||||||
// For now, we can only create XML documents.
|
// For now, we can only create XML documents.
|
||||||
//XXXsmaug Should we create an HTMLDocument (in XHTML mode)
|
//XXXsmaug Should we create an HTMLDocument (in XHTML mode)
|
||||||
// for "application/xhtml+xml"?
|
// for "application/xhtml+xml"?
|
||||||
if ((nsCRT::strcmp(contentType, "text/xml") != 0) &&
|
if ((nsCRT::strcmp(aContentType, "text/xml") != 0) &&
|
||||||
(nsCRT::strcmp(contentType, "application/xml") != 0) &&
|
(nsCRT::strcmp(aContentType, "application/xml") != 0) &&
|
||||||
(nsCRT::strcmp(contentType, "application/xhtml+xml") != 0) &&
|
(nsCRT::strcmp(aContentType, "application/xhtml+xml") != 0) &&
|
||||||
!svg)
|
!svg)
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
// Put the nsCOMPtr out here so we hold a ref to the stream as needed
|
// Put the nsCOMPtr out here so we hold a ref to the stream as needed
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
nsCOMPtr<nsIInputStream> stream = aStream;
|
||||||
if (!NS_InputStreamIsBuffered(stream)) {
|
if (!NS_InputStreamIsBuffered(stream)) {
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream,
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
4096);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
|
stream.forget(), 4096);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
stream = bufferedStream;
|
stream = bufferedStream;
|
||||||
|
@ -243,11 +244,11 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
|
||||||
mPrincipal,
|
mPrincipal,
|
||||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||||
nsIContentPolicy::TYPE_OTHER,
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
nsDependentCString(contentType));
|
nsDependentCString(aContentType));
|
||||||
NS_ENSURE_STATE(parserChannel);
|
NS_ENSURE_STATE(parserChannel);
|
||||||
|
|
||||||
if (charset) {
|
if (aCharset) {
|
||||||
parserChannel->SetContentCharset(nsDependentCString(charset));
|
parserChannel->SetContentCharset(nsDependentCString(aCharset));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the document to start loading
|
// Tell the document to start loading
|
||||||
|
@ -284,7 +285,7 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
||||||
rv = listener->OnDataAvailable(parserChannel, nullptr, stream, 0,
|
rv = listener->OnDataAvailable(parserChannel, nullptr, stream, 0,
|
||||||
contentLength);
|
aContentLength);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
parserChannel->Cancel(rv);
|
parserChannel->Cancel(rv);
|
||||||
parserChannel->GetStatus(&status);
|
parserChannel->GetStatus(&status);
|
||||||
|
|
|
@ -252,7 +252,8 @@ nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
mLoading = true;
|
mLoading = true;
|
||||||
rv = nsSyncLoadService::PushSyncStreamToListener(in, aListener, mChannel);
|
rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), aListener,
|
||||||
|
mChannel);
|
||||||
mLoading = false;
|
mLoading = false;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -338,14 +339,16 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI,
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
nsresult
|
nsresult
|
||||||
nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
nsSyncLoadService::PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
|
||||||
nsIStreamListener* aListener,
|
nsIStreamListener* aListener,
|
||||||
nsIChannel* aChannel)
|
nsIChannel* aChannel)
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIInputStream> in = Move(aIn);
|
||||||
|
|
||||||
// Set up buffering stream
|
// Set up buffering stream
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
if (!NS_InputStreamIsBuffered(aIn)) {
|
if (!NS_InputStreamIsBuffered(in)) {
|
||||||
int64_t chunkSize;
|
int64_t chunkSize;
|
||||||
rv = aChannel->GetContentLength(&chunkSize);
|
rv = aChannel->GetContentLength(&chunkSize);
|
||||||
if (NS_FAILED(rv) || chunkSize < 1) {
|
if (NS_FAILED(rv) || chunkSize < 1) {
|
||||||
|
@ -353,11 +356,11 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
||||||
}
|
}
|
||||||
chunkSize = std::min(int64_t(UINT16_MAX), chunkSize);
|
chunkSize = std::min(int64_t(UINT16_MAX), chunkSize);
|
||||||
|
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
chunkSize);
|
in.forget(), chunkSize);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
aIn = bufferedStream;
|
in = bufferedStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
|
@ -366,7 +369,7 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
||||||
uint64_t sourceOffset = 0;
|
uint64_t sourceOffset = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
uint64_t readCount = 0;
|
uint64_t readCount = 0;
|
||||||
rv = aIn->Available(&readCount);
|
rv = in->Available(&readCount);
|
||||||
if (NS_FAILED(rv) || !readCount) {
|
if (NS_FAILED(rv) || !readCount) {
|
||||||
if (rv == NS_BASE_STREAM_CLOSED) {
|
if (rv == NS_BASE_STREAM_CLOSED) {
|
||||||
// End of file, but not an error
|
// End of file, but not an error
|
||||||
|
@ -378,7 +381,7 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
||||||
if (readCount > UINT32_MAX)
|
if (readCount > UINT32_MAX)
|
||||||
readCount = UINT32_MAX;
|
readCount = UINT32_MAX;
|
||||||
|
|
||||||
rv = aListener->OnDataAvailable(aChannel, nullptr, aIn,
|
rv = aListener->OnDataAvailable(aChannel, nullptr, in,
|
||||||
(uint32_t)std::min(sourceOffset, (uint64_t)UINT32_MAX),
|
(uint32_t)std::min(sourceOffset, (uint64_t)UINT32_MAX),
|
||||||
(uint32_t)readCount);
|
(uint32_t)readCount);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
|
|
@ -51,13 +51,13 @@ public:
|
||||||
/**
|
/**
|
||||||
* Read input stream aIn in chunks and deliver synchronously to aListener.
|
* Read input stream aIn in chunks and deliver synchronously to aListener.
|
||||||
*
|
*
|
||||||
* @param aIn The stream to be read.
|
* @param aIn The stream to be read. The ownership of this stream is taken.
|
||||||
* @param aListener The listener that will receive
|
* @param aListener The listener that will receive
|
||||||
* OnStartRequest/OnDataAvailable/OnStopRequest
|
* OnStartRequest/OnDataAvailable/OnStopRequest
|
||||||
* notifications.
|
* notifications.
|
||||||
* @param aChannel The channel that aIn was opened from.
|
* @param aChannel The channel that aIn was opened from.
|
||||||
*/
|
*/
|
||||||
static nsresult PushSyncStreamToListener(nsIInputStream* aIn,
|
static nsresult PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
|
||||||
nsIStreamListener* aListener,
|
nsIStreamListener* aListener,
|
||||||
nsIChannel* aChannel);
|
nsIChannel* aChannel);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2122,7 +2122,17 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
|
||||||
rv = state->GetIsNull(6, &nullPadding);
|
rv = state->GetIsNull(6, &nullPadding);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
|
|
||||||
|
#ifdef NIGHTLY_BUILD
|
||||||
|
bool shouldUpdateTo26 = false;
|
||||||
|
if (nullPadding && aSavedResponseOut->mValue.type() == ResponseType::Opaque) {
|
||||||
|
// XXXtt: This should be removed in the future (e.g. Nightly 58) by
|
||||||
|
// bug 1398167.
|
||||||
|
shouldUpdateTo26 = true;
|
||||||
|
aSavedResponseOut->mValue.paddingSize() = 0;
|
||||||
|
} else if (nullPadding) {
|
||||||
|
#else
|
||||||
if (nullPadding) {
|
if (nullPadding) {
|
||||||
|
#endif // NIGHTLY_BUILD
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() !=
|
MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() !=
|
||||||
ResponseType::Opaque);
|
ResponseType::Opaque);
|
||||||
aSavedResponseOut->mValue.paddingSize() =
|
aSavedResponseOut->mValue.paddingSize() =
|
||||||
|
@ -2141,6 +2151,20 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
|
||||||
rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo());
|
rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo());
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
|
|
||||||
|
#ifdef NIGHTLY_BUILD
|
||||||
|
if (shouldUpdateTo26) {
|
||||||
|
// XXXtt: This is a quick fix for not updating properly in Nightly 57.
|
||||||
|
// Note: This should be removed in the future (e.g. Nightly 58) by
|
||||||
|
// bug 1398167.
|
||||||
|
rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
|
"UPDATE entries SET response_padding_size = 0 "
|
||||||
|
"WHERE response_type = 4 " // opaque response
|
||||||
|
"AND response_padding_size IS NULL"
|
||||||
|
));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
|
}
|
||||||
|
#endif // NIGHTLY_BUILD
|
||||||
|
|
||||||
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"SELECT "
|
"SELECT "
|
||||||
"name, "
|
"name, "
|
||||||
|
|
|
@ -737,7 +737,8 @@ LockedDirectoryPaddingGet(nsIFile* aBaseDir, int64_t* aPaddingSizeOut)
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream.forget(),
|
||||||
|
512);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
|
|
||||||
nsCOMPtr<nsIObjectInputStream> objectStream =
|
nsCOMPtr<nsIObjectInputStream> objectStream =
|
||||||
|
|
|
@ -31,17 +31,8 @@ namespace dom {
|
||||||
* that add and remove fake gamepads, avoiding the platform-specific backends.
|
* that add and remove fake gamepads, avoiding the platform-specific backends.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest)
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(GamepadServiceTest, DOMEventTargetHelper,
|
||||||
|
mWindow)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GamepadServiceTest,
|
|
||||||
DOMEventTargetHelper)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GamepadServiceTest,
|
|
||||||
DOMEventTargetHelper)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadServiceTest)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadServiceTest)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
|
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
|
||||||
|
|
|
@ -529,7 +529,7 @@ FSMultipartFormData::AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob)
|
||||||
// Create buffered stream (for efficiency)
|
// Create buffered stream (for efficiency)
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
fileStream, 8192);
|
fileStream.forget(), 8192);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
fileStream = bufferedStream;
|
fileStream = bufferedStream;
|
||||||
|
|
|
@ -766,21 +766,11 @@ HTMLContentSink::~HTMLContentSink()
|
||||||
delete mHeadContext;
|
delete mHeadContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLContentSink)
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLContentSink, nsContentSink,
|
||||||
|
mHTMLDocument,
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLContentSink, nsContentSink)
|
mRoot,
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHTMLDocument)
|
mBody,
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
|
mHead)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBody)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHead)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLContentSink,
|
|
||||||
nsContentSink)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHTMLDocument)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBody)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHead)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLContentSink,
|
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLContentSink,
|
||||||
nsContentSink,
|
nsContentSink,
|
||||||
|
|
|
@ -186,16 +186,13 @@ interface nsIServiceWorkerManager : nsISupports
|
||||||
// Testing
|
// Testing
|
||||||
DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath);
|
DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath);
|
||||||
|
|
||||||
// Note: This is meant to be used only by about:serviceworkers.
|
|
||||||
// It returns an array of nsIServiceWorkerRegistrationInfos.
|
// It returns an array of nsIServiceWorkerRegistrationInfos.
|
||||||
nsIArray getAllRegistrations();
|
nsIArray getAllRegistrations();
|
||||||
|
|
||||||
// Note: This is meant to be used only by about:serviceworkers.
|
|
||||||
// It calls softUpdate() for each child process.
|
// It calls softUpdate() for each child process.
|
||||||
[implicit_jscontext] void propagateSoftUpdate(in jsval aOriginAttributes,
|
[implicit_jscontext] void propagateSoftUpdate(in jsval aOriginAttributes,
|
||||||
in DOMString aScope);
|
in DOMString aScope);
|
||||||
|
|
||||||
// Note: This is meant to be used only by about:serviceworkers.
|
|
||||||
// It calls unregister() in each child process. The callback is used to
|
// It calls unregister() in each child process. The callback is used to
|
||||||
// inform when unregister() is completed on the current process.
|
// inform when unregister() is completed on the current process.
|
||||||
void propagateUnregister(in nsIPrincipal aPrincipal,
|
void propagateUnregister(in nsIPrincipal aPrincipal,
|
||||||
|
|
|
@ -29,9 +29,11 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void RetrieveDataFrom(CoalescedInputData& aSource)
|
||||||
{
|
{
|
||||||
mCoalescedInputEvent = nullptr;
|
mCoalescedInputEvent = Move(aSource.mCoalescedInputEvent);
|
||||||
|
mGuid = aSource.mGuid;
|
||||||
|
mInputBlockId = aSource.mInputBlockId;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty()
|
bool IsEmpty()
|
||||||
|
@ -43,9 +45,9 @@ public:
|
||||||
const ScrollableLayerGuid& aGuid,
|
const ScrollableLayerGuid& aGuid,
|
||||||
const uint64_t& aInputBlockId);
|
const uint64_t& aInputBlockId);
|
||||||
|
|
||||||
const InputEventType* GetCoalescedEvent()
|
UniquePtr<InputEventType> TakeCoalescedEvent()
|
||||||
{
|
{
|
||||||
return mCoalescedInputEvent.get();
|
return Move(mCoalescedInputEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollableLayerGuid GetScrollableLayerGuid()
|
ScrollableLayerGuid GetScrollableLayerGuid()
|
||||||
|
|
|
@ -55,8 +55,8 @@ void
|
||||||
CoalescedMouseMoveFlusher::WillRefresh(mozilla::TimeStamp aTime)
|
CoalescedMouseMoveFlusher::WillRefresh(mozilla::TimeStamp aTime)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mRefreshDriver);
|
MOZ_ASSERT(mRefreshDriver);
|
||||||
mTabChild->MaybeDispatchCoalescedMouseMoveEvents();
|
mTabChild->FlushAllCoalescedMouseData();
|
||||||
RemoveObserver();
|
mTabChild->ProcessPendingCoalescedMouseDataAndDispatchEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1059,6 +1059,15 @@ TabChild::DestroyWindow()
|
||||||
mCoalescedMouseEventFlusher->RemoveObserver();
|
mCoalescedMouseEventFlusher->RemoveObserver();
|
||||||
mCoalescedMouseEventFlusher = nullptr;
|
mCoalescedMouseEventFlusher = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case we don't have chance to process all entries, clean all data in
|
||||||
|
// the queue.
|
||||||
|
while (mToBeDispatchedMouseData.GetSize() > 0) {
|
||||||
|
UniquePtr<CoalescedMouseData> data(
|
||||||
|
static_cast<CoalescedMouseData*>(mToBeDispatchedMouseData.PopFront()));
|
||||||
|
data.reset();
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
|
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
|
||||||
if (baseWindow)
|
if (baseWindow)
|
||||||
baseWindow->Destroy();
|
baseWindow->Destroy();
|
||||||
|
@ -1591,28 +1600,62 @@ TabChild::RecvMouseEvent(const nsString& aType,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TabChild::MaybeDispatchCoalescedMouseMoveEvents()
|
TabChild::ProcessPendingCoalescedMouseDataAndDispatchEvents()
|
||||||
{
|
{
|
||||||
if (!mCoalesceMouseMoveEvents) {
|
if (!mCoalesceMouseMoveEvents || !mCoalescedMouseEventFlusher) {
|
||||||
|
// We don't enable mouse coalescing or we are destroying TabChild.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We may reentry the event loop and push more data to
|
||||||
|
// mToBeDispatchedMouseData while dispatching an event.
|
||||||
|
|
||||||
|
// We may have some pending coalesced data while dispatch an event and reentry
|
||||||
|
// the event loop. In that case we don't have chance to consume the remainding
|
||||||
|
// pending data until we get new mouse events. Get some helps from
|
||||||
|
// mCoalescedMouseEventFlusher to trigger it.
|
||||||
|
mCoalescedMouseEventFlusher->StartObserver();
|
||||||
|
|
||||||
|
while (mToBeDispatchedMouseData.GetSize() > 0) {
|
||||||
|
UniquePtr<CoalescedMouseData> data(
|
||||||
|
static_cast<CoalescedMouseData*>(mToBeDispatchedMouseData.PopFront()));
|
||||||
|
|
||||||
|
UniquePtr<WidgetMouseEvent> event = data->TakeCoalescedEvent();
|
||||||
|
if (event) {
|
||||||
|
// Dispatch the pending events. Using HandleRealMouseButtonEvent
|
||||||
|
// to bypass the coalesce handling in RecvRealMouseMoveEvent. Can't use
|
||||||
|
// RecvRealMouseButtonEvent because we may also put some mouse events
|
||||||
|
// other than mousemove.
|
||||||
|
HandleRealMouseButtonEvent(*event,
|
||||||
|
data->GetScrollableLayerGuid(),
|
||||||
|
data->GetInputBlockId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mCoalescedMouseEventFlusher may be destroyed when reentrying the event
|
||||||
|
// loop.
|
||||||
|
if (mCoalescedMouseEventFlusher) {
|
||||||
|
mCoalescedMouseEventFlusher->RemoveObserver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TabChild::FlushAllCoalescedMouseData()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mCoalesceMouseMoveEvents);
|
||||||
|
|
||||||
|
// Move all entries from mCoalescedMouseData to mToBeDispatchedMouseData.
|
||||||
for (auto iter = mCoalescedMouseData.Iter(); !iter.Done(); iter.Next()) {
|
for (auto iter = mCoalescedMouseData.Iter(); !iter.Done(); iter.Next()) {
|
||||||
CoalescedMouseData* data = iter.UserData();
|
CoalescedMouseData* data = iter.UserData();
|
||||||
if (!data || data->IsEmpty()) {
|
if (!data || data->IsEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const WidgetMouseEvent* event = data->GetCoalescedEvent();
|
UniquePtr<CoalescedMouseData> dispatchData =
|
||||||
MOZ_ASSERT(event);
|
MakeUnique<CoalescedMouseData>();
|
||||||
// Dispatch the coalesced mousemove event. Using RecvRealMouseButtonEvent to
|
|
||||||
// bypass the coalesce handling in RecvRealMouseMoveEvent.
|
dispatchData->RetrieveDataFrom(*data);
|
||||||
RecvRealMouseButtonEvent(*event,
|
mToBeDispatchedMouseData.Push(dispatchData.release());
|
||||||
data->GetScrollableLayerGuid(),
|
|
||||||
data->GetInputBlockId());
|
|
||||||
data->Reset();
|
|
||||||
}
|
|
||||||
if (mCoalescedMouseEventFlusher) {
|
|
||||||
mCoalescedMouseEventFlusher->RemoveObserver();
|
|
||||||
}
|
}
|
||||||
|
mCoalescedMouseData.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
|
@ -1632,10 +1675,23 @@ TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& aEvent,
|
||||||
mCoalescedMouseEventFlusher->StartObserver();
|
mCoalescedMouseEventFlusher->StartObserver();
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
// Can't coalesce current mousemove event. Dispatch the coalesced mousemove
|
// Can't coalesce current mousemove event. Put the coalesced mousemove data
|
||||||
// event and coalesce the current one.
|
// with the same pointer id to mToBeDispatchedMouseData, coalesce the
|
||||||
MaybeDispatchCoalescedMouseMoveEvents();
|
// current one, and process all pending data in mToBeDispatchedMouseData.
|
||||||
data->Coalesce(aEvent, aGuid, aInputBlockId);
|
MOZ_ASSERT(data);
|
||||||
|
UniquePtr<CoalescedMouseData> dispatchData =
|
||||||
|
MakeUnique<CoalescedMouseData>();
|
||||||
|
|
||||||
|
dispatchData->RetrieveDataFrom(*data);
|
||||||
|
mToBeDispatchedMouseData.Push(dispatchData.release());
|
||||||
|
|
||||||
|
// Put new data to replace the old one in the hash table.
|
||||||
|
CoalescedMouseData* newData = new CoalescedMouseData();
|
||||||
|
mCoalescedMouseData.Put(aEvent.pointerId, newData);
|
||||||
|
newData->Coalesce(aEvent, aGuid, aInputBlockId);
|
||||||
|
|
||||||
|
// Dispatch all pending mouse events.
|
||||||
|
ProcessPendingCoalescedMouseDataAndDispatchEvents();
|
||||||
mCoalescedMouseEventFlusher->StartObserver();
|
mCoalescedMouseEventFlusher->StartObserver();
|
||||||
} else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
|
} else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
|
||||||
return IPC_FAIL_NO_REASON(this);
|
return IPC_FAIL_NO_REASON(this);
|
||||||
|
@ -1675,16 +1731,35 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
||||||
const ScrollableLayerGuid& aGuid,
|
const ScrollableLayerGuid& aGuid,
|
||||||
const uint64_t& aInputBlockId)
|
const uint64_t& aInputBlockId)
|
||||||
{
|
{
|
||||||
if (aEvent.mMessage != eMouseMove) {
|
if (mCoalesceMouseMoveEvents && mCoalescedMouseEventFlusher &&
|
||||||
// Flush the coalesced mousemove event before dispatching other mouse
|
aEvent.mMessage != eMouseMove) {
|
||||||
// events.
|
// When receiving a mouse event other than mousemove, we have to dispatch
|
||||||
MaybeDispatchCoalescedMouseMoveEvents();
|
// all coalesced events before it. However, we can't dispatch all pending
|
||||||
if (aEvent.mMessage == eMouseEnterIntoWidget) {
|
// coalesced events directly because we may reentry the event loop while
|
||||||
mCoalescedMouseData.Put(aEvent.pointerId, new CoalescedMouseData());
|
// dispatching. To make sure we won't dispatch disorder events, we move all
|
||||||
} else if (aEvent.mMessage == eMouseExitFromWidget) {
|
// coalesced mousemove events and current event to a deque to dispatch them.
|
||||||
mCoalescedMouseData.Remove(aEvent.pointerId);
|
// When reentrying the event loop and dispatching more events, we put new
|
||||||
}
|
// events in the end of the nsQueue and dispatch events from the beginning.
|
||||||
|
FlushAllCoalescedMouseData();
|
||||||
|
|
||||||
|
UniquePtr<CoalescedMouseData> dispatchData =
|
||||||
|
MakeUnique<CoalescedMouseData>();
|
||||||
|
|
||||||
|
dispatchData->Coalesce(aEvent, aGuid, aInputBlockId);
|
||||||
|
mToBeDispatchedMouseData.Push(dispatchData.release());
|
||||||
|
|
||||||
|
ProcessPendingCoalescedMouseDataAndDispatchEvents();
|
||||||
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
HandleRealMouseButtonEvent(aEvent, aGuid, aInputBlockId);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TabChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
||||||
|
const ScrollableLayerGuid& aGuid,
|
||||||
|
const uint64_t& aInputBlockId)
|
||||||
|
{
|
||||||
// Mouse events like eMouseEnterIntoWidget, that are created in the parent
|
// Mouse events like eMouseEnterIntoWidget, that are created in the parent
|
||||||
// process EventStateManager code, have an input block id which they get from
|
// process EventStateManager code, have an input block id which they get from
|
||||||
// the InputAPZContext in the parent process stack. However, they did not
|
// the InputAPZContext in the parent process stack. However, they did not
|
||||||
|
@ -1714,7 +1789,6 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
||||||
if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
|
if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
|
||||||
mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
|
mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
|
||||||
}
|
}
|
||||||
return IPC_OK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
|
@ -1779,13 +1853,12 @@ TabChild::MaybeDispatchCoalescedWheelEvent()
|
||||||
if (mCoalescedWheelData.IsEmpty()) {
|
if (mCoalescedWheelData.IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const WidgetWheelEvent* wheelEvent =
|
UniquePtr<WidgetWheelEvent> wheelEvent =
|
||||||
mCoalescedWheelData.GetCoalescedEvent();
|
mCoalescedWheelData.TakeCoalescedEvent();
|
||||||
MOZ_ASSERT(wheelEvent);
|
MOZ_ASSERT(wheelEvent);
|
||||||
DispatchWheelEvent(*wheelEvent,
|
DispatchWheelEvent(*wheelEvent,
|
||||||
mCoalescedWheelData.GetScrollableLayerGuid(),
|
mCoalescedWheelData.GetScrollableLayerGuid(),
|
||||||
mCoalescedWheelData.GetInputBlockId());
|
mCoalescedWheelData.GetInputBlockId());
|
||||||
mCoalescedWheelData.Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "AudioChannelService.h"
|
#include "AudioChannelService.h"
|
||||||
#include "PuppetWidget.h"
|
#include "PuppetWidget.h"
|
||||||
#include "mozilla/layers/GeckoContentController.h"
|
#include "mozilla/layers/GeckoContentController.h"
|
||||||
|
#include "nsDeque.h"
|
||||||
#include "nsISHistoryListener.h"
|
#include "nsISHistoryListener.h"
|
||||||
#include "nsIPartialSHistoryListener.h"
|
#include "nsIPartialSHistoryListener.h"
|
||||||
|
|
||||||
|
@ -761,8 +762,17 @@ public:
|
||||||
return mWidgetNativeData;
|
return mWidgetNativeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare to dispatch all coalesced mousemove events. We'll move all data
|
||||||
|
// in mCoalescedMouseData to a nsDeque; then we start processing them. We
|
||||||
|
// can't fetch the coalesced event one by one and dispatch it because we may
|
||||||
|
// reentry the event loop and access to the same hashtable. It's called when
|
||||||
|
// dispatching some mouse events other than mousemove.
|
||||||
|
void FlushAllCoalescedMouseData();
|
||||||
|
void ProcessPendingCoalescedMouseDataAndDispatchEvents();
|
||||||
|
|
||||||
void MaybeDispatchCoalescedMouseMoveEvents();
|
void HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
||||||
|
const ScrollableLayerGuid& aGuid,
|
||||||
|
const uint64_t& aInputBlockId);
|
||||||
|
|
||||||
static bool HasActiveTabs()
|
static bool HasActiveTabs()
|
||||||
{
|
{
|
||||||
|
@ -948,7 +958,12 @@ private:
|
||||||
// takes time, some repeated events can be skipped to not flood child process.
|
// takes time, some repeated events can be skipped to not flood child process.
|
||||||
mozilla::TimeStamp mLastWheelProcessedTimeFromParent;
|
mozilla::TimeStamp mLastWheelProcessedTimeFromParent;
|
||||||
mozilla::TimeDuration mLastWheelProcessingDuration;
|
mozilla::TimeDuration mLastWheelProcessingDuration;
|
||||||
|
|
||||||
|
// Hash table to track coalesced mousemove events for different pointers.
|
||||||
nsClassHashtable<nsUint32HashKey, CoalescedMouseData> mCoalescedMouseData;
|
nsClassHashtable<nsUint32HashKey, CoalescedMouseData> mCoalescedMouseData;
|
||||||
|
|
||||||
|
nsDeque mToBeDispatchedMouseData;
|
||||||
|
|
||||||
CoalescedWheelData mCoalescedWheelData;
|
CoalescedWheelData mCoalescedWheelData;
|
||||||
RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher;
|
RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
skip-if = os == 'android'
|
skip-if = os == 'android'
|
||||||
support-files =
|
support-files =
|
||||||
process_error.xul
|
process_error.xul
|
||||||
process_error_contentscript.js
|
|
||||||
|
|
||||||
[test_process_error.xul]
|
[test_process_error.xul]
|
||||||
skip-if = !crashreporter
|
skip-if = !crashreporter
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<browser id="thebrowser" type="content" remote="true" />
|
<browser id="thebrowser" type="content" remote="true" />
|
||||||
<script type="application/javascript"><![CDATA[
|
<script type="application/javascript"><![CDATA[
|
||||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
|
Components.utils.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||||
|
|
||||||
const ok = window.opener.wrappedJSObject.ok;
|
const ok = window.opener.wrappedJSObject.ok;
|
||||||
const is = window.opener.wrappedJSObject.is;
|
const is = window.opener.wrappedJSObject.is;
|
||||||
|
@ -18,24 +19,19 @@
|
||||||
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
|
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
|
||||||
'Subject implements nsIPropertyBag2.');
|
'Subject implements nsIPropertyBag2.');
|
||||||
|
|
||||||
var waitCrash = Promise.resolve();
|
|
||||||
var dumpID;
|
var dumpID;
|
||||||
if ('nsICrashReporter' in Components.interfaces) {
|
if ('nsICrashReporter' in Components.interfaces) {
|
||||||
dumpID = subject.getPropertyAsAString('dumpID');
|
dumpID = subject.getPropertyAsAString('dumpID');
|
||||||
ok(dumpID, "dumpID is present and not an empty string");
|
ok(dumpID, "dumpID is present and not an empty string");
|
||||||
waitCrash = Services.crashmanager.ensureCrashIsPresent(dumpID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
|
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
|
||||||
waitCrash.then(done);
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.addObserver(crashObserver, 'ipc:content-shutdown');
|
Services.obs.addObserver(crashObserver, 'ipc:content-shutdown');
|
||||||
|
|
||||||
document.getElementById('thebrowser')
|
BrowserTestUtils.crashBrowser(document.getElementById('thebrowser'));
|
||||||
.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
|
|
||||||
.frameLoader.messageManager
|
|
||||||
.loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true);
|
|
||||||
]]></script>
|
]]></script>
|
||||||
|
|
||||||
</window>
|
</window>
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
|
||||||
|
|
||||||
privateNoteIntentionalCrash();
|
|
||||||
|
|
||||||
var zero = new ctypes.intptr_t(8);
|
|
||||||
var badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
|
|
||||||
var crash = badptr.contents;
|
|
|
@ -42,14 +42,10 @@ var testObserver = {
|
||||||
let additionalDumps = extraData.additional_minidumps.split(',');
|
let additionalDumps = extraData.additional_minidumps.split(',');
|
||||||
ok(additionalDumps.indexOf('browser') >= 0, "browser in additional_minidumps");
|
ok(additionalDumps.indexOf('browser') >= 0, "browser in additional_minidumps");
|
||||||
|
|
||||||
let additionalDumpFiles = [];
|
|
||||||
for (let name of additionalDumps) {
|
for (let name of additionalDumps) {
|
||||||
let file = profD.clone();
|
let file = profD.clone();
|
||||||
file.append(pluginId + "-" + name + ".dmp");
|
file.append(pluginId + "-" + name + ".dmp");
|
||||||
ok(file.exists(), "additional dump '"+name+"' exists");
|
ok(file.exists(), "additional dump '"+name+"' exists");
|
||||||
if (file.exists()) {
|
|
||||||
additionalDumpFiles.push(file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check cpu usage field
|
// check cpu usage field
|
||||||
|
@ -103,7 +99,5 @@ function onPluginCrashed(aEvent) {
|
||||||
getService(Ci.nsIObserverService);
|
getService(Ci.nsIObserverService);
|
||||||
os.removeObserver(testObserver, "plugin-crashed");
|
os.removeObserver(testObserver, "plugin-crashed");
|
||||||
|
|
||||||
Services.crashmanager.ensureCrashIsPresent(aEvent.pluginDumpID).then(() => {
|
SimpleTest.finish();
|
||||||
SimpleTest.finish();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
</body>
|
</body>
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
SimpleTest.expectChildProcessCrash();
|
SimpleTest.expectChildProcessCrash();
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
</body>
|
</body>
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
Components.utils.import("resource://gre/modules/PromiseUtils.jsm");
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
SimpleTest.expectChildProcessCrash();
|
SimpleTest.expectChildProcessCrash();
|
||||||
|
@ -23,6 +23,8 @@ SimpleTest.expectChildProcessCrash();
|
||||||
var success = false;
|
var success = false;
|
||||||
|
|
||||||
var observerFired = false;
|
var observerFired = false;
|
||||||
|
var observerDeferred = PromiseUtils.defer();
|
||||||
|
var eventListenerDeferred = PromiseUtils.defer();
|
||||||
|
|
||||||
var testObserver = {
|
var testObserver = {
|
||||||
observe: function(subject, topic, data) {
|
observe: function(subject, topic, data) {
|
||||||
|
@ -46,6 +48,8 @@ var testObserver = {
|
||||||
let extraFile = profD.clone();
|
let extraFile = profD.clone();
|
||||||
extraFile.append(id + ".extra");
|
extraFile.append(id + ".extra");
|
||||||
ok(extraFile.exists(), "extra file exists");
|
ok(extraFile.exists(), "extra file exists");
|
||||||
|
|
||||||
|
observerDeferred.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
QueryInterface: function(iid) {
|
QueryInterface: function(iid) {
|
||||||
|
@ -84,9 +88,7 @@ function onPluginCrashed(aEvent) {
|
||||||
getService(Components.interfaces.nsIObserverService);
|
getService(Components.interfaces.nsIObserverService);
|
||||||
os.removeObserver(testObserver, "plugin-crashed");
|
os.removeObserver(testObserver, "plugin-crashed");
|
||||||
|
|
||||||
Services.crashmanager.ensureCrashIsPresent(aEvent.pluginDumpID).then(() => {
|
eventListenerDeferred.resolve();
|
||||||
SimpleTest.finish();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
|
@ -101,6 +103,13 @@ function runTests() {
|
||||||
pluginElement.crash();
|
pluginElement.crash();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
observerDeferred.promise,
|
||||||
|
eventListenerDeferred.promise
|
||||||
|
]).then(() => {
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
</body>
|
</body>
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
SimpleTest.expectChildProcessCrash();
|
SimpleTest.expectChildProcessCrash();
|
||||||
|
|
||||||
|
|
|
@ -2454,7 +2454,8 @@ GetBinaryInputStream(nsIFile* aDirectory,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
|
stream.forget(), 512);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -5235,46 +5236,11 @@ QuotaManager::EnsureOriginIsInitializedInternal(
|
||||||
*aCreated = false;
|
*aCreated = false;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
} else if (!mTemporaryStorageInitialized) {
|
} else {
|
||||||
rv = InitializeRepository(aPersistenceType);
|
rv = EnsureTemporaryStorageIsInitialized();
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
// We have to cleanup partially initialized quota.
|
|
||||||
RemoveQuota();
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = InitializeRepository(ComplementaryPersistenceType(aPersistenceType));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
// We have to cleanup partially initialized quota.
|
|
||||||
RemoveQuota();
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gFixedLimitKB >= 0) {
|
|
||||||
mTemporaryStorageLimit = static_cast<uint64_t>(gFixedLimitKB) * 1024;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nsCOMPtr<nsIFile> storageDir =
|
|
||||||
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = storageDir->InitWithPath(GetStoragePath());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = GetTemporaryStorageLimit(storageDir, mTemporaryStorageUsage,
|
|
||||||
&mTemporaryStorageLimit);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
mTemporaryStorageInitialized = true;
|
|
||||||
|
|
||||||
CheckTemporaryStorageLimits();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool created;
|
bool created;
|
||||||
|
@ -5337,6 +5303,60 @@ QuotaManager::EnsureOriginIsInitializedInternal(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
QuotaManager::EnsureTemporaryStorageIsInitialized()
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
MOZ_ASSERT(mStorageInitialized);
|
||||||
|
|
||||||
|
if (mTemporaryStorageInitialized) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = InitializeRepository(PERSISTENCE_TYPE_DEFAULT);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
// We have to cleanup partially initialized quota.
|
||||||
|
RemoveQuota();
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = InitializeRepository(PERSISTENCE_TYPE_TEMPORARY);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
// We have to cleanup partially initialized quota.
|
||||||
|
RemoveQuota();
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gFixedLimitKB >= 0) {
|
||||||
|
mTemporaryStorageLimit = static_cast<uint64_t>(gFixedLimitKB) * 1024;
|
||||||
|
} else {
|
||||||
|
nsCOMPtr<nsIFile> storageDir =
|
||||||
|
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = storageDir->InitWithPath(GetStoragePath());
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = GetTemporaryStorageLimit(storageDir, mTemporaryStorageUsage,
|
||||||
|
&mTemporaryStorageLimit);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mTemporaryStorageInitialized = true;
|
||||||
|
|
||||||
|
CheckTemporaryStorageLimits();
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QuotaManager::OriginClearCompleted(PersistenceType aPersistenceType,
|
QuotaManager::OriginClearCompleted(PersistenceType aPersistenceType,
|
||||||
const nsACString& aOrigin)
|
const nsACString& aOrigin)
|
||||||
|
@ -7147,14 +7167,16 @@ GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager)
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
if (mGetGroupUsage) {
|
if (mGetGroupUsage) {
|
||||||
nsCOMPtr<nsIFile> directory;
|
// Ensure temporary storage is initialized first. It will initialize all
|
||||||
|
// origins for temporary storage including origins belonging to our group by
|
||||||
|
// traversing the repositories. EnsureStorageIsInitialized is needed before
|
||||||
|
// EnsureTemporaryStorageIsInitialized.
|
||||||
|
rv = aQuotaManager->EnsureStorageIsInitialized();
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure origin is initialized first. It will initialize all origins for
|
rv = aQuotaManager->EnsureTemporaryStorageIsInitialized();
|
||||||
// temporary storage including origins belonging to our group.
|
|
||||||
rv = aQuotaManager->EnsureOriginIsInitialized(PERSISTENCE_TYPE_TEMPORARY,
|
|
||||||
mSuffix, mGroup,
|
|
||||||
mOriginScope.GetOrigin(),
|
|
||||||
getter_AddRefs(directory));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,9 @@ public:
|
||||||
nsIFile** aDirectory,
|
nsIFile** aDirectory,
|
||||||
bool* aCreated);
|
bool* aCreated);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EnsureTemporaryStorageIsInitialized();
|
||||||
|
|
||||||
void
|
void
|
||||||
OriginClearCompleted(PersistenceType aPersistenceType,
|
OriginClearCompleted(PersistenceType aPersistenceType,
|
||||||
const nsACString& aOrigin);
|
const nsACString& aOrigin);
|
||||||
|
|
|
@ -1491,7 +1491,8 @@ nsresult nsWebBrowserPersist::SaveChannelInternal(
|
||||||
getter_AddRefs(fileInputStream));
|
getter_AddRefs(fileInputStream));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
|
||||||
fileInputStream, BUFFERED_OUTPUT_SIZE);
|
fileInputStream.forget(),
|
||||||
|
BUFFERED_OUTPUT_SIZE);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
nsAutoCString contentType;
|
nsAutoCString contentType;
|
||||||
aChannel->GetContentType(contentType);
|
aChannel->GetContentType(contentType);
|
||||||
|
|
|
@ -215,7 +215,7 @@ FileReaderSync::ReadAsText(Blob& aBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> syncStream;
|
nsCOMPtr<nsIInputStream> syncStream;
|
||||||
aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream,
|
aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream.forget(),
|
||||||
getter_AddRefs(syncStream));
|
getter_AddRefs(syncStream));
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return;
|
return;
|
||||||
|
@ -269,7 +269,8 @@ FileReaderSync::ReadAsDataURL(Blob& aBlob, nsAString& aResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> syncStream;
|
nsCOMPtr<nsIInputStream> syncStream;
|
||||||
aRv = ConvertAsyncToSyncStream(blobSize, stream, getter_AddRefs(syncStream));
|
aRv = ConvertAsyncToSyncStream(blobSize, stream.forget(),
|
||||||
|
getter_AddRefs(syncStream));
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -475,13 +476,15 @@ FileReaderSync::SyncRead(nsIInputStream* aStream, char* aBuffer,
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
||||||
nsIInputStream* aAsyncStream,
|
already_AddRefed<nsIInputStream> aAsyncStream,
|
||||||
nsIInputStream** aSyncStream)
|
nsIInputStream** aSyncStream)
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIInputStream> asyncInputStream = Move(aAsyncStream);
|
||||||
|
|
||||||
// If the stream is not async, we just need it to be bufferable.
|
// If the stream is not async, we just need it to be bufferable.
|
||||||
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aAsyncStream);
|
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(asyncInputStream);
|
||||||
if (!asyncStream) {
|
if (!asyncStream) {
|
||||||
return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096);
|
return NS_NewBufferedInputStream(aSyncStream, asyncInputStream.forget(), 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString buffer;
|
nsAutoCString buffer;
|
||||||
|
@ -491,7 +494,7 @@ FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
||||||
|
|
||||||
uint32_t read;
|
uint32_t read;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
SyncRead(aAsyncStream, buffer.BeginWriting(), aStreamSize, &read);
|
SyncRead(asyncInputStream, buffer.BeginWriting(), aStreamSize, &read);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ private:
|
||||||
nsAString &aResult);
|
nsAString &aResult);
|
||||||
|
|
||||||
nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
|
||||||
nsIInputStream* aAsyncStream,
|
already_AddRefed<nsIInputStream> aAsyncStream,
|
||||||
nsIInputStream** aSyncStream);
|
nsIInputStream** aSyncStream);
|
||||||
|
|
||||||
nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,
|
nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,
|
||||||
|
|
|
@ -1116,7 +1116,8 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
|
||||||
rv = channel->Open2(getter_AddRefs(in));
|
rv = channel->Open2(getter_AddRefs(in));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel);
|
rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), listener,
|
||||||
|
channel);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
doc.swap(*aResult);
|
doc.swap(*aResult);
|
||||||
|
|
|
@ -2561,11 +2561,12 @@ XMLHttpRequestMainThread::MaybeLowerChannelPriority()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
XMLHttpRequestMainThread::InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
|
||||||
int64_t aUploadLength,
|
int64_t aUploadLength,
|
||||||
nsACString& aUploadContentType)
|
nsACString& aUploadContentType)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIInputStream> uploadStream = Move(aUploadStream);
|
||||||
|
|
||||||
// nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
|
// nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
|
||||||
// in turn keeps STOP button from becoming active. If the consumer passed in
|
// in turn keeps STOP button from becoming active. If the consumer passed in
|
||||||
|
@ -2615,16 +2616,16 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aUploadStream) {
|
if (uploadStream) {
|
||||||
// If necessary, wrap the stream in a buffered stream so as to guarantee
|
// If necessary, wrap the stream in a buffered stream so as to guarantee
|
||||||
// support for our upload when calling ExplicitSetUploadStream.
|
// support for our upload when calling ExplicitSetUploadStream.
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
if (!NS_InputStreamIsBuffered(uploadStream)) {
|
||||||
if (!NS_InputStreamIsBuffered(aUploadStream)) {
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
aUploadStream, 4096);
|
uploadStream.forget(), 4096);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
aUploadStream = bufferedStream;
|
uploadStream = bufferedStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to use a newer version of the upload channel that won't
|
// We want to use a newer version of the upload channel that won't
|
||||||
|
@ -2633,7 +2634,7 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
||||||
// This assertion will fire if buggy extensions are installed
|
// This assertion will fire if buggy extensions are installed
|
||||||
NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2");
|
NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2");
|
||||||
if (uploadChannel2) {
|
if (uploadChannel2) {
|
||||||
uploadChannel2->ExplicitSetUploadStream(aUploadStream,
|
uploadChannel2->ExplicitSetUploadStream(uploadStream,
|
||||||
aUploadContentType,
|
aUploadContentType,
|
||||||
mUploadTotal, mRequestMethod,
|
mUploadTotal, mRequestMethod,
|
||||||
false);
|
false);
|
||||||
|
@ -2645,7 +2646,7 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIUploadChannel> uploadChannel =
|
nsCOMPtr<nsIUploadChannel> uploadChannel =
|
||||||
do_QueryInterface(httpChannel);
|
do_QueryInterface(httpChannel);
|
||||||
uploadChannel->SetUploadStream(aUploadStream, aUploadContentType,
|
uploadChannel->SetUploadStream(uploadStream, aUploadContentType,
|
||||||
mUploadTotal);
|
mUploadTotal);
|
||||||
// Reset the method to its original value
|
// Reset the method to its original value
|
||||||
rv = httpChannel->SetRequestMethod(mRequestMethod);
|
rv = httpChannel->SetRequestMethod(mRequestMethod);
|
||||||
|
@ -3053,7 +3054,7 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = InitiateFetch(uploadStream, mUploadTotal, uploadContentType);
|
rv = InitiateFetch(uploadStream.forget(), mUploadTotal, uploadContentType);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Start our timeout
|
// Start our timeout
|
||||||
|
|
|
@ -261,7 +261,7 @@ public:
|
||||||
|
|
||||||
// request
|
// request
|
||||||
nsresult CreateChannel();
|
nsresult CreateChannel();
|
||||||
nsresult InitiateFetch(nsIInputStream* aUploadStream,
|
nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
|
||||||
int64_t aUploadLength,
|
int64_t aUploadLength,
|
||||||
nsACString& aUploadContentType);
|
nsACString& aUploadContentType);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
52368
|
52371
|
||||||
0/nm
|
0/nm
|
||||||
0th/pt
|
0th/pt
|
||||||
1/n1
|
1/n1
|
||||||
|
@ -16621,6 +16621,7 @@ billycan/S
|
||||||
bimbo/MS
|
bimbo/MS
|
||||||
bimetallic/SM
|
bimetallic/SM
|
||||||
bimetallism/M
|
bimetallism/M
|
||||||
|
bimodal
|
||||||
bimonthly/SM
|
bimonthly/SM
|
||||||
bin/SM
|
bin/SM
|
||||||
binary/SM
|
binary/SM
|
||||||
|
@ -36405,6 +36406,8 @@ nondepreciating
|
||||||
nondescript
|
nondescript
|
||||||
nondestructive
|
nondestructive
|
||||||
nondetachable
|
nondetachable
|
||||||
|
nondeterminism
|
||||||
|
nondeterministic
|
||||||
nondisciplinary
|
nondisciplinary
|
||||||
nondisclosure/M
|
nondisclosure/M
|
||||||
nondiscrimination/M
|
nondiscrimination/M
|
||||||
|
|
|
@ -333,7 +333,8 @@ CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> aBufferedStream;
|
nsCOMPtr<nsIInputStream> aBufferedStream;
|
||||||
if (!NS_InputStreamIsBuffered(stream)) {
|
if (!NS_InputStreamIsBuffered(stream)) {
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream), stream, 4096);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream),
|
||||||
|
stream.forget(), 4096);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
stream = aBufferedStream;
|
stream = aBufferedStream;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,20 +100,20 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/* static */ already_AddRefed<ImageOps::ImageBuffer>
|
/* static */ already_AddRefed<ImageOps::ImageBuffer>
|
||||||
ImageOps::CreateImageBuffer(nsIInputStream* aInputStream)
|
ImageOps::CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aInputStream);
|
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
|
||||||
|
MOZ_ASSERT(inputStream);
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
// Prepare the input stream.
|
// Prepare the input stream.
|
||||||
nsCOMPtr<nsIInputStream> inputStream = aInputStream;
|
if (!NS_InputStreamIsBuffered(inputStream)) {
|
||||||
if (!NS_InputStreamIsBuffered(aInputStream)) {
|
|
||||||
nsCOMPtr<nsIInputStream> bufStream;
|
nsCOMPtr<nsIInputStream> bufStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||||
aInputStream, 1024);
|
inputStream.forget(), 1024);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
inputStream = bufStream;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +145,12 @@ ImageOps::CreateImageBuffer(nsIInputStream* aInputStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ nsresult
|
/* static */ nsresult
|
||||||
ImageOps::DecodeMetadata(nsIInputStream* aInputStream,
|
ImageOps::DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
|
||||||
const nsACString& aMimeType,
|
const nsACString& aMimeType,
|
||||||
ImageMetadata& aMetadata)
|
ImageMetadata& aMetadata)
|
||||||
{
|
{
|
||||||
RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
|
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
|
||||||
|
RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
|
||||||
return DecodeMetadata(buffer, aMimeType, aMetadata);
|
return DecodeMetadata(buffer, aMimeType, aMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,12 +194,13 @@ ImageOps::DecodeMetadata(ImageBuffer* aBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ already_AddRefed<gfx::SourceSurface>
|
/* static */ already_AddRefed<gfx::SourceSurface>
|
||||||
ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
|
ImageOps::DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
|
||||||
const nsACString& aMimeType,
|
const nsACString& aMimeType,
|
||||||
uint32_t aFlags,
|
uint32_t aFlags,
|
||||||
const Maybe<IntSize>& aSize /* = Nothing() */)
|
const Maybe<IntSize>& aSize /* = Nothing() */)
|
||||||
{
|
{
|
||||||
RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
|
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
|
||||||
|
RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
|
||||||
return DecodeToSurface(buffer, aMimeType, aFlags, aSize);
|
return DecodeToSurface(buffer, aMimeType, aFlags, aSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,23 +93,25 @@ public:
|
||||||
* an ImageBuffer representing the given input stream is more efficient if one
|
* an ImageBuffer representing the given input stream is more efficient if one
|
||||||
* has multiple Decode* calls to make on that stream.
|
* has multiple Decode* calls to make on that stream.
|
||||||
*
|
*
|
||||||
* @param aInputStream An input stream containing an encoded image.
|
* @param aInputStream An input stream containing an encoded image. The
|
||||||
|
* ownership is taken.
|
||||||
* @return An image buffer derived from the input stream.
|
* @return An image buffer derived from the input stream.
|
||||||
*/
|
*/
|
||||||
static already_AddRefed<ImageBuffer>
|
static already_AddRefed<ImageBuffer>
|
||||||
CreateImageBuffer(nsIInputStream* aInputStream);
|
CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes an image's metadata from an nsIInputStream into the given
|
* Decodes an image's metadata from an nsIInputStream into the given
|
||||||
* structure. This function may be called off-main-thread.
|
* structure. This function may be called off-main-thread.
|
||||||
*
|
*
|
||||||
* @param aInputStream An input stream containing an encoded image.
|
* @param aInputStream An input stream containing an encoded image. Ownership
|
||||||
|
* is taken.
|
||||||
* @param aMimeType The MIME type of the image.
|
* @param aMimeType The MIME type of the image.
|
||||||
* @param aMetadata Where the image metadata is stored upon success.
|
* @param aMetadata Where the image metadata is stored upon success.
|
||||||
* @return The status of the operation.
|
* @return The status of the operation.
|
||||||
*/
|
*/
|
||||||
static nsresult
|
static nsresult
|
||||||
DecodeMetadata(nsIInputStream* aInputStream,
|
DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
|
||||||
const nsACString& aMimeType,
|
const nsACString& aMimeType,
|
||||||
ImageMetadata& aMetadata);
|
ImageMetadata& aMetadata);
|
||||||
|
|
||||||
|
@ -127,14 +129,15 @@ public:
|
||||||
* main-thread-only). That means that this function may be called
|
* main-thread-only). That means that this function may be called
|
||||||
* off-main-thread.
|
* off-main-thread.
|
||||||
*
|
*
|
||||||
* @param aInputStream An input stream containing an encoded image.
|
* @param aInputStream An input stream containing an encoded image. The
|
||||||
|
* ownership is taken.
|
||||||
* @param aMimeType The MIME type of the image.
|
* @param aMimeType The MIME type of the image.
|
||||||
* @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
|
* @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
|
||||||
* @return A SourceSurface containing the first frame of the image at its
|
* @return A SourceSurface containing the first frame of the image at its
|
||||||
* intrinsic size, or nullptr if the image cannot be decoded.
|
* intrinsic size, or nullptr if the image cannot be decoded.
|
||||||
*/
|
*/
|
||||||
static already_AddRefed<gfx::SourceSurface>
|
static already_AddRefed<gfx::SourceSurface>
|
||||||
DecodeToSurface(nsIInputStream* aInputStream,
|
DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
|
||||||
const nsACString& aMimeType,
|
const nsACString& aMimeType,
|
||||||
uint32_t aFlags,
|
uint32_t aFlags,
|
||||||
const Maybe<gfx::IntSize>& aSize = Nothing());
|
const Maybe<gfx::IntSize>& aSize = Nothing());
|
||||||
|
|
|
@ -61,7 +61,8 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
|
||||||
nsCOMPtr<nsIInputStream> inStream = aInStr;
|
nsCOMPtr<nsIInputStream> inStream = aInStr;
|
||||||
if (!NS_InputStreamIsBuffered(aInStr)) {
|
if (!NS_InputStreamIsBuffered(aInStr)) {
|
||||||
nsCOMPtr<nsIInputStream> bufStream;
|
nsCOMPtr<nsIInputStream> bufStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||||
|
inStream.forget(), 1024);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
inStream = bufStream;
|
inStream = bufStream;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
void Go()
|
void Go()
|
||||||
{
|
{
|
||||||
mSurface =
|
mSurface =
|
||||||
ImageOps::DecodeToSurface(mInputStream,
|
ImageOps::DecodeToSurface(mInputStream.forget(),
|
||||||
nsDependentCString(mimeType.c_str()),
|
nsDependentCString(mimeType.c_str()),
|
||||||
imgIContainer::DECODE_FLAGS_DEFAULT);
|
imgIContainer::DECODE_FLAGS_DEFAULT);
|
||||||
if (!mSurface)
|
if (!mSurface)
|
||||||
|
|
|
@ -125,7 +125,7 @@ LoadFile(const char* aRelativePath)
|
||||||
if (!NS_InputStreamIsBuffered(inputStream)) {
|
if (!NS_InputStreamIsBuffered(inputStream)) {
|
||||||
nsCOMPtr<nsIInputStream> bufStream;
|
nsCOMPtr<nsIInputStream> bufStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||||
inputStream, 1024);
|
inputStream.forget(), 1024);
|
||||||
ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
|
ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
|
||||||
inputStream = bufStream;
|
inputStream = bufStream;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
outputSize);
|
outputSize);
|
||||||
} else {
|
} else {
|
||||||
mSurface =
|
mSurface =
|
||||||
ImageOps::DecodeToSurface(mInputStream,
|
ImageOps::DecodeToSurface(mInputStream.forget(),
|
||||||
nsDependentCString(mTestCase.mMimeType),
|
nsDependentCString(mTestCase.mMimeType),
|
||||||
imgIContainer::DECODE_FLAGS_DEFAULT,
|
imgIContainer::DECODE_FLAGS_DEFAULT,
|
||||||
outputSize);
|
outputSize);
|
||||||
|
@ -144,7 +144,7 @@ TEST_F(ImageDecodeToSurface, Corrupt)
|
||||||
ASSERT_TRUE(inputStream != nullptr);
|
ASSERT_TRUE(inputStream != nullptr);
|
||||||
|
|
||||||
RefPtr<SourceSurface> surface =
|
RefPtr<SourceSurface> surface =
|
||||||
ImageOps::DecodeToSurface(inputStream,
|
ImageOps::DecodeToSurface(inputStream.forget(),
|
||||||
nsDependentCString(testCase.mMimeType),
|
nsDependentCString(testCase.mMimeType),
|
||||||
imgIContainer::DECODE_FLAGS_DEFAULT);
|
imgIContainer::DECODE_FLAGS_DEFAULT);
|
||||||
EXPECT_TRUE(surface == nullptr);
|
EXPECT_TRUE(surface == nullptr);
|
||||||
|
@ -158,7 +158,7 @@ TEST_F(ImageDecodeToSurface, ICOMultipleSizes)
|
||||||
ASSERT_TRUE(inputStream != nullptr);
|
ASSERT_TRUE(inputStream != nullptr);
|
||||||
|
|
||||||
RefPtr<ImageOps::ImageBuffer> buffer =
|
RefPtr<ImageOps::ImageBuffer> buffer =
|
||||||
ImageOps::CreateImageBuffer(inputStream);
|
ImageOps::CreateImageBuffer(inputStream.forget());
|
||||||
ASSERT_TRUE(buffer != nullptr);
|
ASSERT_TRUE(buffer != nullptr);
|
||||||
|
|
||||||
ImageMetadata metadata;
|
ImageMetadata metadata;
|
||||||
|
|
|
@ -26,6 +26,8 @@ struct HandlerProvider
|
||||||
struct IHandlerProvider : public IUnknown
|
struct IHandlerProvider : public IUnknown
|
||||||
, public HandlerProvider
|
, public HandlerProvider
|
||||||
{
|
{
|
||||||
|
virtual STDMETHODIMP_(REFIID) GetEffectiveOutParamIid(REFIID aCallIid,
|
||||||
|
ULONG aCallMethod) = 0;
|
||||||
virtual STDMETHODIMP NewInstance(REFIID aIid,
|
virtual STDMETHODIMP NewInstance(REFIID aIid,
|
||||||
InterceptorTargetPtr<IUnknown> aTarget,
|
InterceptorTargetPtr<IUnknown> aTarget,
|
||||||
NotNull<IHandlerProvider**> aOutNewPayload) = 0;
|
NotNull<IHandlerProvider**> aOutNewPayload) = 0;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "mozilla/mscom/Utils.h"
|
#include "mozilla/mscom/Utils.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
|
#include "mozilla/ThreadLocal.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsProxyRelease.h"
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
|
@ -154,6 +155,52 @@ private:
|
||||||
HRESULT mResult;
|
HRESULT mResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MOZ_RAII SavedCallFrame final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SavedCallFrame(mozilla::NotNull<ICallFrame*> aFrame)
|
||||||
|
: mCallFrame(aFrame)
|
||||||
|
{
|
||||||
|
static const bool sIsInit = tlsFrame.init();
|
||||||
|
MOZ_ASSERT(sIsInit);
|
||||||
|
MOZ_ASSERT(!tlsFrame.get());
|
||||||
|
tlsFrame.set(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~SavedCallFrame()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(tlsFrame.get());
|
||||||
|
tlsFrame.set(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT GetIidAndMethod(mozilla::NotNull<IID*> aIid,
|
||||||
|
mozilla::NotNull<ULONG*> aMethod) const
|
||||||
|
{
|
||||||
|
return mCallFrame->GetIIDAndMethod(aIid, aMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const SavedCallFrame& Get()
|
||||||
|
{
|
||||||
|
SavedCallFrame* saved = tlsFrame.get();
|
||||||
|
MOZ_ASSERT(saved);
|
||||||
|
|
||||||
|
return *saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
SavedCallFrame(const SavedCallFrame&) = delete;
|
||||||
|
SavedCallFrame(SavedCallFrame&&) = delete;
|
||||||
|
SavedCallFrame& operator=(const SavedCallFrame&) = delete;
|
||||||
|
SavedCallFrame& operator=(SavedCallFrame&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ICallFrame* mCallFrame;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static MOZ_THREAD_LOCAL(SavedCallFrame*) tlsFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
MOZ_THREAD_LOCAL(SavedCallFrame*) SavedCallFrame::tlsFrame;
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -338,6 +385,8 @@ MainThreadHandoff::OnCall(ICallFrame* aFrame)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
SavedCallFrame savedFrame(WrapNotNull(aFrame));
|
||||||
|
|
||||||
// (7) Scan the outputs looking for any outparam interfaces that need wrapping.
|
// (7) Scan the outputs looking for any outparam interfaces that need wrapping.
|
||||||
// NB: WalkFrame does not correctly handle array outparams. It processes the
|
// NB: WalkFrame does not correctly handle array outparams. It processes the
|
||||||
// first element of an array but not the remaining elements (if any).
|
// first element of an array but not the remaining elements (if any).
|
||||||
|
@ -566,9 +615,26 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IID effectiveIid = aIid;
|
||||||
|
|
||||||
RefPtr<IHandlerProvider> payload;
|
RefPtr<IHandlerProvider> payload;
|
||||||
if (mHandlerProvider) {
|
if (mHandlerProvider) {
|
||||||
hr = mHandlerProvider->NewInstance(aIid,
|
if (aIid == IID_IUnknown) {
|
||||||
|
const SavedCallFrame& curFrame = SavedCallFrame::Get();
|
||||||
|
|
||||||
|
IID callIid;
|
||||||
|
ULONG callMethod;
|
||||||
|
hr = curFrame.GetIidAndMethod(WrapNotNull(&callIid),
|
||||||
|
WrapNotNull(&callMethod));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectiveIid = mHandlerProvider->GetEffectiveOutParamIid(callIid,
|
||||||
|
callMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = mHandlerProvider->NewInstance(effectiveIid,
|
||||||
ToInterceptorTargetPtr(origInterface),
|
ToInterceptorTargetPtr(origInterface),
|
||||||
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
|
WrapNotNull((IHandlerProvider**)getter_AddRefs(payload)));
|
||||||
MOZ_ASSERT(SUCCEEDED(hr));
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
|
@ -585,7 +651,8 @@ MainThreadHandoff::OnWalkInterface(REFIID aIid, PVOID* aInterface,
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
REFIID interceptorIid = payload ? payload->MarshalAs(aIid) : aIid;
|
REFIID interceptorIid = payload ? payload->MarshalAs(effectiveIid) :
|
||||||
|
effectiveIid;
|
||||||
|
|
||||||
RefPtr<IUnknown> wrapped;
|
RefPtr<IUnknown> wrapped;
|
||||||
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,
|
hr = Interceptor::Create(Move(origInterface), handoff, interceptorIid,
|
||||||
|
|
|
@ -2504,7 +2504,7 @@ BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
|
||||||
{
|
{
|
||||||
if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
|
if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
|
||||||
return false;
|
return false;
|
||||||
return emit3(op, ARGC_HI(argc), ARGC_LO(argc));
|
return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -2687,7 +2687,7 @@ bool
|
||||||
BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
|
BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(operand <= UINT16_MAX);
|
MOZ_ASSERT(operand <= UINT16_MAX);
|
||||||
if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand)))
|
if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand)))
|
||||||
return false;
|
return false;
|
||||||
checkTypeSet(op);
|
checkTypeSet(op);
|
||||||
return true;
|
return true;
|
||||||
|
@ -10214,10 +10214,7 @@ BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
|
||||||
|
|
||||||
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
|
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
|
||||||
code[0] = JSOP_NEWOBJECT;
|
code[0] = JSOP_NEWOBJECT;
|
||||||
code[1] = jsbytecode(index >> 24);
|
SET_UINT32(code, index);
|
||||||
code[2] = jsbytecode(index >> 16);
|
|
||||||
code[3] = jsbytecode(index >> 8);
|
|
||||||
code[4] = jsbytecode(index);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ class AutoRunParallelTask;
|
||||||
class AutoTraceSession;
|
class AutoTraceSession;
|
||||||
class MarkingValidator;
|
class MarkingValidator;
|
||||||
struct MovingTracer;
|
struct MovingTracer;
|
||||||
|
class SweepGroupsIter;
|
||||||
class WeakCacheSweepIterator;
|
class WeakCacheSweepIterator;
|
||||||
|
|
||||||
enum IncrementalProgress
|
enum IncrementalProgress
|
||||||
|
@ -1073,27 +1074,24 @@ class GCRuntime
|
||||||
void groupZonesForSweeping(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
|
void groupZonesForSweeping(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
|
||||||
MOZ_MUST_USE bool findInterZoneEdges();
|
MOZ_MUST_USE bool findInterZoneEdges();
|
||||||
void getNextSweepGroup();
|
void getNextSweepGroup();
|
||||||
void endMarkingSweepGroup();
|
IncrementalProgress endMarkingSweepGroup(FreeOp* fop, SliceBudget& budget);
|
||||||
void beginSweepingSweepGroup();
|
IncrementalProgress beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget);
|
||||||
|
#ifdef JS_GC_ZEAL
|
||||||
|
IncrementalProgress maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget);
|
||||||
|
#endif
|
||||||
bool shouldReleaseObservedTypes();
|
bool shouldReleaseObservedTypes();
|
||||||
void sweepDebuggerOnMainThread(FreeOp* fop);
|
void sweepDebuggerOnMainThread(FreeOp* fop);
|
||||||
void sweepJitDataOnMainThread(FreeOp* fop);
|
void sweepJitDataOnMainThread(FreeOp* fop);
|
||||||
void endSweepingSweepGroup();
|
IncrementalProgress endSweepingSweepGroup(FreeOp* fop, SliceBudget& budget);
|
||||||
IncrementalProgress performSweepActions(SliceBudget& sliceBudget,
|
IncrementalProgress performSweepActions(SliceBudget& sliceBudget, AutoLockForExclusiveAccess& lock);
|
||||||
AutoLockForExclusiveAccess& lock);
|
IncrementalProgress sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone);
|
||||||
static IncrementalProgress sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
IncrementalProgress mergeSweptObjectArenas(FreeOp* fop, SliceBudget& budget, Zone* zone);
|
||||||
Zone* zone);
|
|
||||||
static IncrementalProgress mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
|
||||||
Zone* zone);
|
|
||||||
static IncrementalProgress sweepAtomsTable(GCRuntime* gc, FreeOp* fop, SliceBudget& budget);
|
|
||||||
void startSweepingAtomsTable();
|
void startSweepingAtomsTable();
|
||||||
IncrementalProgress sweepAtomsTable(SliceBudget& budget);
|
IncrementalProgress sweepAtomsTable(FreeOp* fop, SliceBudget& budget);
|
||||||
static IncrementalProgress sweepWeakCaches(GCRuntime* gc, FreeOp* fop, SliceBudget& budget);
|
IncrementalProgress sweepWeakCaches(FreeOp* fop, SliceBudget& budget);
|
||||||
IncrementalProgress sweepWeakCaches(SliceBudget& budget);
|
IncrementalProgress finalizeAllocKind(FreeOp* fop, SliceBudget& budget, Zone* zone,
|
||||||
static IncrementalProgress finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
AllocKind kind);
|
||||||
Zone* zone, AllocKind kind);
|
IncrementalProgress sweepShapeTree(FreeOp* fop, SliceBudget& budget, Zone* zone);
|
||||||
static IncrementalProgress sweepShapeTree(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
|
||||||
Zone* zone);
|
|
||||||
void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
|
void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
|
||||||
bool allCCVisibleZonesWereCollected() const;
|
bool allCCVisibleZonesWereCollected() const;
|
||||||
void sweepZones(FreeOp* fop, ZoneGroup* group, bool lastGC);
|
void sweepZones(FreeOp* fop, ZoneGroup* group, bool lastGC);
|
||||||
|
@ -1285,9 +1283,20 @@ class GCRuntime
|
||||||
*/
|
*/
|
||||||
ActiveThreadOrGCTaskData<State> incrementalState;
|
ActiveThreadOrGCTaskData<State> incrementalState;
|
||||||
|
|
||||||
|
/* The incremental state at the start of this slice. */
|
||||||
|
ActiveThreadData<State> initialState;
|
||||||
|
|
||||||
|
#ifdef JS_GC_ZEAL
|
||||||
|
/* Whether to pay attention the zeal settings in this incremental slice. */
|
||||||
|
ActiveThreadData<bool> useZeal;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Indicates that the last incremental slice exhausted the mark stack. */
|
/* Indicates that the last incremental slice exhausted the mark stack. */
|
||||||
ActiveThreadData<bool> lastMarkSlice;
|
ActiveThreadData<bool> lastMarkSlice;
|
||||||
|
|
||||||
|
/* Whether it's currently safe to yield to the mutator in an incremental GC. */
|
||||||
|
ActiveThreadData<bool> safeToYield;
|
||||||
|
|
||||||
/* Whether any sweeping will take place in the separate GC helper thread. */
|
/* Whether any sweeping will take place in the separate GC helper thread. */
|
||||||
ActiveThreadData<bool> sweepOnBackgroundThread;
|
ActiveThreadData<bool> sweepOnBackgroundThread;
|
||||||
|
|
||||||
|
@ -1319,6 +1328,7 @@ class GCRuntime
|
||||||
ActiveThreadOrGCTaskData<JS::detail::WeakCacheBase*> sweepCache;
|
ActiveThreadOrGCTaskData<JS::detail::WeakCacheBase*> sweepCache;
|
||||||
ActiveThreadData<bool> abortSweepAfterCurrentGroup;
|
ActiveThreadData<bool> abortSweepAfterCurrentGroup;
|
||||||
|
|
||||||
|
friend class SweepGroupsIter;
|
||||||
friend class WeakCacheSweepIterator;
|
friend class WeakCacheSweepIterator;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2494,7 +2494,7 @@ GCMarker::enterWeakMarkingMode()
|
||||||
if (weakMapAction() == ExpandWeakMaps) {
|
if (weakMapAction() == ExpandWeakMaps) {
|
||||||
tag_ = TracerKindTag::WeakMarking;
|
tag_ = TracerKindTag::WeakMarking;
|
||||||
|
|
||||||
for (GCSweepGroupIter zone(runtime()); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(runtime()); !zone.done(); zone.next()) {
|
||||||
for (WeakMapBase* m : zone->gcWeakMapList()) {
|
for (WeakMapBase* m : zone->gcWeakMapList()) {
|
||||||
if (m->marked)
|
if (m->marked)
|
||||||
(void) m->markIteratively(this);
|
(void) m->markIteratively(this);
|
||||||
|
|
|
@ -3568,6 +3568,19 @@ Simulator::branchDelayInstructionDecode(SimInstruction* instr)
|
||||||
instructionDecode(instr);
|
instructionDecode(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FakeInterruptHandler()
|
||||||
|
{
|
||||||
|
JSContext* cx = TlsContext.get();
|
||||||
|
uint8_t* pc = cx->simulator()->get_pc_as<uint8_t*>();
|
||||||
|
|
||||||
|
const wasm::CodeSegment* cs = nullptr;
|
||||||
|
if (!wasm::InInterruptibleCode(cx, pc, &cs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cx->simulator()->trigger_wasm_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
template<bool enableStopSimAt>
|
template<bool enableStopSimAt>
|
||||||
void
|
void
|
||||||
Simulator::execute()
|
Simulator::execute()
|
||||||
|
@ -3581,6 +3594,8 @@ Simulator::execute()
|
||||||
MipsDebugger dbg(this);
|
MipsDebugger dbg(this);
|
||||||
dbg.debug();
|
dbg.debug();
|
||||||
} else {
|
} else {
|
||||||
|
if (MOZ_UNLIKELY(JitOptions.simulatorAlwaysInterrupt))
|
||||||
|
FakeInterruptHandler();
|
||||||
SimInstruction* instr = reinterpret_cast<SimInstruction*>(program_counter);
|
SimInstruction* instr = reinterpret_cast<SimInstruction*>(program_counter);
|
||||||
instructionDecode(instr);
|
instructionDecode(instr);
|
||||||
icount_++;
|
icount_++;
|
||||||
|
|
|
@ -3733,6 +3733,19 @@ Simulator::disable_single_stepping()
|
||||||
single_step_callback_arg_ = nullptr;
|
single_step_callback_arg_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FakeInterruptHandler()
|
||||||
|
{
|
||||||
|
JSContext* cx = TlsContext.get();
|
||||||
|
uint8_t* pc = cx->simulator()->get_pc_as<uint8_t*>();
|
||||||
|
|
||||||
|
const wasm::CodeSegment* cs = nullptr;
|
||||||
|
if (!wasm::InInterruptibleCode(cx, pc, &cs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cx->simulator()->trigger_wasm_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
template<bool enableStopSimAt>
|
template<bool enableStopSimAt>
|
||||||
void
|
void
|
||||||
Simulator::execute()
|
Simulator::execute()
|
||||||
|
@ -3751,6 +3764,8 @@ Simulator::execute()
|
||||||
} else {
|
} else {
|
||||||
if (single_stepping_)
|
if (single_stepping_)
|
||||||
single_step_callback_(single_step_callback_arg_, this, (void*)program_counter);
|
single_step_callback_(single_step_callback_arg_, this, (void*)program_counter);
|
||||||
|
if (MOZ_UNLIKELY(JitOptions.simulatorAlwaysInterrupt))
|
||||||
|
FakeInterruptHandler();
|
||||||
SimInstruction* instr = reinterpret_cast<SimInstruction *>(program_counter);
|
SimInstruction* instr = reinterpret_cast<SimInstruction *>(program_counter);
|
||||||
instructionDecode(instr);
|
instructionDecode(instr);
|
||||||
icount_++;
|
icount_++;
|
||||||
|
|
|
@ -465,6 +465,7 @@ class AutoLeaveZeal
|
||||||
JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
|
JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
|
||||||
}
|
}
|
||||||
~AutoLeaveZeal() {
|
~AutoLeaveZeal() {
|
||||||
|
JS_SetGCZeal(cx_, 0, 0);
|
||||||
for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
|
for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
|
||||||
if (zealBits_ & (1 << i))
|
if (zealBits_ & (1 << i))
|
||||||
JS_SetGCZeal(cx_, i, frequency_);
|
JS_SetGCZeal(cx_, i, frequency_);
|
||||||
|
|
372
js/src/jsgc.cpp
372
js/src/jsgc.cpp
|
@ -914,7 +914,12 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
|
||||||
number(0),
|
number(0),
|
||||||
isFull(false),
|
isFull(false),
|
||||||
incrementalState(gc::State::NotActive),
|
incrementalState(gc::State::NotActive),
|
||||||
|
initialState(gc::State::NotActive),
|
||||||
|
#ifdef JS_GC_ZEAL
|
||||||
|
useZeal(false),
|
||||||
|
#endif
|
||||||
lastMarkSlice(false),
|
lastMarkSlice(false),
|
||||||
|
safeToYield(true),
|
||||||
sweepOnBackgroundThread(false),
|
sweepOnBackgroundThread(false),
|
||||||
blocksToFreeAfterSweeping((size_t) JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
blocksToFreeAfterSweeping((size_t) JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||||
sweepGroupIndex(0),
|
sweepGroupIndex(0),
|
||||||
|
@ -4389,7 +4394,7 @@ GCRuntime::markWeakReferences(gcstats::PhaseKind phase)
|
||||||
void
|
void
|
||||||
GCRuntime::markWeakReferencesInCurrentGroup(gcstats::PhaseKind phase)
|
GCRuntime::markWeakReferencesInCurrentGroup(gcstats::PhaseKind phase)
|
||||||
{
|
{
|
||||||
markWeakReferences<GCSweepGroupIter>(phase);
|
markWeakReferences<SweepGroupZonesIter>(phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ZoneIterT, class CompartmentIterT>
|
template <class ZoneIterT, class CompartmentIterT>
|
||||||
|
@ -4412,7 +4417,7 @@ GCRuntime::markGrayReferences(gcstats::PhaseKind phase)
|
||||||
void
|
void
|
||||||
GCRuntime::markGrayReferencesInCurrentGroup(gcstats::PhaseKind phase)
|
GCRuntime::markGrayReferencesInCurrentGroup(gcstats::PhaseKind phase)
|
||||||
{
|
{
|
||||||
markGrayReferences<GCSweepGroupIter, GCCompartmentGroupIter>(phase);
|
markGrayReferences<SweepGroupZonesIter, SweepGroupCompartmentsIter>(phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -4907,14 +4912,14 @@ GCRuntime::getNextSweepGroup()
|
||||||
|
|
||||||
if (abortSweepAfterCurrentGroup) {
|
if (abortSweepAfterCurrentGroup) {
|
||||||
MOZ_ASSERT(!isIncremental);
|
MOZ_ASSERT(!isIncremental);
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
MOZ_ASSERT(!zone->gcNextGraphComponent);
|
MOZ_ASSERT(!zone->gcNextGraphComponent);
|
||||||
zone->setNeedsIncrementalBarrier(false);
|
zone->setNeedsIncrementalBarrier(false);
|
||||||
zone->changeGCState(Zone::Mark, Zone::NoGC);
|
zone->changeGCState(Zone::Mark, Zone::NoGC);
|
||||||
zone->gcGrayRoots().clearAndFree();
|
zone->gcGrayRoots().clearAndFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GCCompartmentGroupIter comp(rt); !comp.done(); comp.next())
|
for (SweepGroupCompartmentsIter comp(rt); !comp.done(); comp.next())
|
||||||
ResetGrayList(comp);
|
ResetGrayList(comp);
|
||||||
|
|
||||||
abortSweepAfterCurrentGroup = false;
|
abortSweepAfterCurrentGroup = false;
|
||||||
|
@ -5049,7 +5054,7 @@ MarkIncomingCrossCompartmentPointers(JSRuntime* rt, MarkColor color)
|
||||||
|
|
||||||
bool unlinkList = color == MarkColor::Gray;
|
bool unlinkList = color == MarkColor::Gray;
|
||||||
|
|
||||||
for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) {
|
for (SweepGroupCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||||
MOZ_ASSERT_IF(color == MarkColor::Gray, c->zone()->isGCMarkingGray());
|
MOZ_ASSERT_IF(color == MarkColor::Gray, c->zone()->isGCMarkingGray());
|
||||||
MOZ_ASSERT_IF(color == MarkColor::Black, c->zone()->isGCMarkingBlack());
|
MOZ_ASSERT_IF(color == MarkColor::Black, c->zone()->isGCMarkingBlack());
|
||||||
MOZ_ASSERT_IF(c->gcIncomingGrayPointers, IsGrayListObject(c->gcIncomingGrayPointers));
|
MOZ_ASSERT_IF(c->gcIncomingGrayPointers, IsGrayListObject(c->gcIncomingGrayPointers));
|
||||||
|
@ -5162,8 +5167,8 @@ js::NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned removedFlags)
|
||||||
DelayCrossCompartmentGrayMarking(a);
|
DelayCrossCompartmentGrayMarking(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
IncrementalProgress
|
||||||
GCRuntime::endMarkingSweepGroup()
|
GCRuntime::endMarkingSweepGroup(FreeOp* fop, SliceBudget& budget)
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_MARK);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_MARK);
|
||||||
|
|
||||||
|
@ -5181,7 +5186,7 @@ GCRuntime::endMarkingSweepGroup()
|
||||||
* these will be marked through, as they are not marked with
|
* these will be marked through, as they are not marked with
|
||||||
* MarkCrossCompartmentXXX.
|
* MarkCrossCompartmentXXX.
|
||||||
*/
|
*/
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||||
zone->changeGCState(Zone::Mark, Zone::MarkGray);
|
zone->changeGCState(Zone::Mark, Zone::MarkGray);
|
||||||
marker.setMarkColorGray();
|
marker.setMarkColorGray();
|
||||||
|
|
||||||
|
@ -5193,10 +5198,15 @@ GCRuntime::endMarkingSweepGroup()
|
||||||
markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK);
|
markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK);
|
||||||
|
|
||||||
/* Restore marking state. */
|
/* Restore marking state. */
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||||
zone->changeGCState(Zone::MarkGray, Zone::Mark);
|
zone->changeGCState(Zone::MarkGray, Zone::Mark);
|
||||||
MOZ_ASSERT(marker.isDrained());
|
MOZ_ASSERT(marker.isDrained());
|
||||||
marker.setMarkColorBlack();
|
marker.setMarkColorBlack();
|
||||||
|
|
||||||
|
/* We must not yield after this point before we start sweeping the group. */
|
||||||
|
safeToYield = false;
|
||||||
|
|
||||||
|
return Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Causes the given WeakCache to be swept when run.
|
// Causes the given WeakCache to be swept when run.
|
||||||
|
@ -5245,28 +5255,28 @@ UpdateAtomsBitmap(JSRuntime* runtime)
|
||||||
static void
|
static void
|
||||||
SweepCCWrappers(JSRuntime* runtime)
|
SweepCCWrappers(JSRuntime* runtime)
|
||||||
{
|
{
|
||||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
|
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
|
||||||
c->sweepCrossCompartmentWrappers();
|
c->sweepCrossCompartmentWrappers();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SweepObjectGroups(JSRuntime* runtime)
|
SweepObjectGroups(JSRuntime* runtime)
|
||||||
{
|
{
|
||||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
|
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
|
||||||
c->objectGroups.sweep(runtime->defaultFreeOp());
|
c->objectGroups.sweep(runtime->defaultFreeOp());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SweepRegExps(JSRuntime* runtime)
|
SweepRegExps(JSRuntime* runtime)
|
||||||
{
|
{
|
||||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
|
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next())
|
||||||
c->sweepRegExps();
|
c->sweepRegExps();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SweepMisc(JSRuntime* runtime)
|
SweepMisc(JSRuntime* runtime)
|
||||||
{
|
{
|
||||||
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) {
|
for (SweepGroupCompartmentsIter c(runtime); !c.done(); c.next()) {
|
||||||
c->sweepGlobalObject();
|
c->sweepGlobalObject();
|
||||||
c->sweepTemplateObjects();
|
c->sweepTemplateObjects();
|
||||||
c->sweepSavedStacks();
|
c->sweepSavedStacks();
|
||||||
|
@ -5303,7 +5313,7 @@ SweepCompressionTasks(JSRuntime* runtime)
|
||||||
static void
|
static void
|
||||||
SweepWeakMaps(JSRuntime* runtime)
|
SweepWeakMaps(JSRuntime* runtime)
|
||||||
{
|
{
|
||||||
for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next()) {
|
||||||
/* Clear all weakrefs that point to unmarked things. */
|
/* Clear all weakrefs that point to unmarked things. */
|
||||||
for (auto edge : zone->gcWeakRefs()) {
|
for (auto edge : zone->gcWeakRefs()) {
|
||||||
/* Edges may be present multiple times, so may already be nulled. */
|
/* Edges may be present multiple times, so may already be nulled. */
|
||||||
|
@ -5325,7 +5335,7 @@ static void
|
||||||
SweepUniqueIds(JSRuntime* runtime)
|
SweepUniqueIds(JSRuntime* runtime)
|
||||||
{
|
{
|
||||||
FreeOp fop(nullptr);
|
FreeOp fop(nullptr);
|
||||||
for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next())
|
||||||
zone->sweepUniqueIds(&fop);
|
zone->sweepUniqueIds(&fop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5363,7 +5373,7 @@ GCRuntime::sweepDebuggerOnMainThread(FreeOp* fop)
|
||||||
// table.
|
// table.
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_MISC);
|
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_MISC);
|
||||||
for (GCCompartmentGroupIter c(rt); !c.done(); c.next())
|
for (SweepGroupCompartmentsIter c(rt); !c.done(); c.next())
|
||||||
c->sweepDebugEnvironments();
|
c->sweepDebugEnvironments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5371,7 +5381,7 @@ GCRuntime::sweepDebuggerOnMainThread(FreeOp* fop)
|
||||||
// although note that it can cause JIT code to be patched.
|
// although note that it can cause JIT code to be patched.
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_BREAKPOINT);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_BREAKPOINT);
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||||
zone->sweepBreakpoints(fop);
|
zone->sweepBreakpoints(fop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5385,10 +5395,10 @@ GCRuntime::sweepJitDataOnMainThread(FreeOp* fop)
|
||||||
// Cancel any active or pending off thread compilations.
|
// Cancel any active or pending off thread compilations.
|
||||||
js::CancelOffThreadIonCompile(rt, JS::Zone::Sweep);
|
js::CancelOffThreadIonCompile(rt, JS::Zone::Sweep);
|
||||||
|
|
||||||
for (GCCompartmentGroupIter c(rt); !c.done(); c.next())
|
for (SweepGroupCompartmentsIter c(rt); !c.done(); c.next())
|
||||||
c->sweepJitCompartment(fop);
|
c->sweepJitCompartment(fop);
|
||||||
|
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
if (jit::JitZone* jitZone = zone->jitZone())
|
if (jit::JitZone* jitZone = zone->jitZone())
|
||||||
jitZone->sweep(fop);
|
jitZone->sweep(fop);
|
||||||
}
|
}
|
||||||
|
@ -5403,14 +5413,14 @@ GCRuntime::sweepJitDataOnMainThread(FreeOp* fop)
|
||||||
|
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase apdc(stats(), gcstats::PhaseKind::SWEEP_DISCARD_CODE);
|
gcstats::AutoPhase apdc(stats(), gcstats::PhaseKind::SWEEP_DISCARD_CODE);
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||||
zone->discardJitCode(fop);
|
zone->discardJitCode(fop);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
||||||
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES_BEGIN);
|
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES_BEGIN);
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||||
zone->beginSweepTypes(fop, releaseObservedTypes && !zone->isPreservingCode());
|
zone->beginSweepTypes(fop, releaseObservedTypes && !zone->isPreservingCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5429,7 +5439,7 @@ template <typename Functor>
|
||||||
static inline bool
|
static inline bool
|
||||||
IterateWeakCaches(JSRuntime* rt, Functor f)
|
IterateWeakCaches(JSRuntime* rt, Functor f)
|
||||||
{
|
{
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
for (JS::detail::WeakCacheBase* cache : zone->weakCaches()) {
|
for (JS::detail::WeakCacheBase* cache : zone->weakCaches()) {
|
||||||
if (!f(cache, ZoneWeakCache))
|
if (!f(cache, ZoneWeakCache))
|
||||||
return false;
|
return false;
|
||||||
|
@ -5484,8 +5494,8 @@ SweepWeakCachesOnMainThread(JSRuntime* rt)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
IncrementalProgress
|
||||||
GCRuntime::beginSweepingSweepGroup()
|
GCRuntime::beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Begin sweeping the group of zones in currentSweepGroup, performing
|
* Begin sweeping the group of zones in currentSweepGroup, performing
|
||||||
|
@ -5497,7 +5507,7 @@ GCRuntime::beginSweepingSweepGroup()
|
||||||
AutoSCC scc(stats(), sweepGroupIndex);
|
AutoSCC scc(stats(), sweepGroupIndex);
|
||||||
|
|
||||||
bool sweepingAtoms = false;
|
bool sweepingAtoms = false;
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
/* Set the GC state to sweeping. */
|
/* Set the GC state to sweeping. */
|
||||||
zone->changeGCState(Zone::Mark, Zone::Sweep);
|
zone->changeGCState(Zone::Mark, Zone::Sweep);
|
||||||
|
|
||||||
|
@ -5514,26 +5524,24 @@ GCRuntime::beginSweepingSweepGroup()
|
||||||
|
|
||||||
validateIncrementalMarking();
|
validateIncrementalMarking();
|
||||||
|
|
||||||
FreeOp fop(rt);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoPhase ap(stats(), PhaseKind::FINALIZE_START);
|
AutoPhase ap(stats(), PhaseKind::FINALIZE_START);
|
||||||
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_PREPARE);
|
callFinalizeCallbacks(fop, JSFINALIZE_GROUP_PREPARE);
|
||||||
{
|
{
|
||||||
AutoPhase ap2(stats(), PhaseKind::WEAK_ZONES_CALLBACK);
|
AutoPhase ap2(stats(), PhaseKind::WEAK_ZONES_CALLBACK);
|
||||||
callWeakPointerZonesCallbacks();
|
callWeakPointerZonesCallbacks();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AutoPhase ap2(stats(), PhaseKind::WEAK_COMPARTMENT_CALLBACK);
|
AutoPhase ap2(stats(), PhaseKind::WEAK_COMPARTMENT_CALLBACK);
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
|
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
|
||||||
callWeakPointerCompartmentCallbacks(comp);
|
callWeakPointerCompartmentCallbacks(comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_START);
|
callFinalizeCallbacks(fop, JSFINALIZE_GROUP_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
sweepDebuggerOnMainThread(&fop);
|
sweepDebuggerOnMainThread(fop);
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoLockHelperThreadState lock;
|
AutoLockHelperThreadState lock;
|
||||||
|
@ -5561,7 +5569,7 @@ GCRuntime::beginSweepingSweepGroup()
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoUnlockHelperThreadState unlock(lock);
|
AutoUnlockHelperThreadState unlock(lock);
|
||||||
sweepJitDataOnMainThread(&fop);
|
sweepJitDataOnMainThread(fop);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& task : sweepCacheTasks)
|
for (auto& task : sweepCacheTasks)
|
||||||
|
@ -5574,25 +5582,45 @@ GCRuntime::beginSweepingSweepGroup()
|
||||||
// Queue all GC things in all zones for sweeping, either on the foreground
|
// Queue all GC things in all zones for sweeping, either on the foreground
|
||||||
// or on the background thread.
|
// or on the background thread.
|
||||||
|
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
|
|
||||||
zone->arenas.queueForForegroundSweep(&fop, ForegroundObjectFinalizePhase);
|
zone->arenas.queueForForegroundSweep(fop, ForegroundObjectFinalizePhase);
|
||||||
zone->arenas.queueForForegroundSweep(&fop, ForegroundNonObjectFinalizePhase);
|
zone->arenas.queueForForegroundSweep(fop, ForegroundNonObjectFinalizePhase);
|
||||||
for (unsigned i = 0; i < ArrayLength(BackgroundFinalizePhases); ++i)
|
for (unsigned i = 0; i < ArrayLength(BackgroundFinalizePhases); ++i)
|
||||||
zone->arenas.queueForBackgroundSweep(&fop, BackgroundFinalizePhases[i]);
|
zone->arenas.queueForBackgroundSweep(fop, BackgroundFinalizePhases[i]);
|
||||||
|
|
||||||
zone->arenas.queueForegroundThingsForSweep(&fop);
|
zone->arenas.queueForegroundThingsForSweep(fop);
|
||||||
}
|
}
|
||||||
|
|
||||||
sweepCache = nullptr;
|
sweepCache = nullptr;
|
||||||
sweepActions->assertFinished();
|
safeToYield = true;
|
||||||
|
|
||||||
|
return Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#ifdef JS_GC_ZEAL
|
||||||
GCRuntime::endSweepingSweepGroup()
|
IncrementalProgress
|
||||||
|
GCRuntime::maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget)
|
||||||
{
|
{
|
||||||
sweepActions->assertFinished();
|
/*
|
||||||
|
* Check whether we need to yield for GC zeal. We always yield when running
|
||||||
|
* in incremental multi-slice zeal mode so RunDebugGC can reset the slice
|
||||||
|
* budget.
|
||||||
|
*/
|
||||||
|
if (isIncremental && useZeal && initialState != State::Sweep &&
|
||||||
|
(hasZealMode(ZealMode::IncrementalMultipleSlices) ||
|
||||||
|
hasZealMode(ZealMode::IncrementalSweepThenFinish)))
|
||||||
|
{
|
||||||
|
return NotFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Finished;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IncrementalProgress
|
||||||
|
GCRuntime::endSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::FINALIZE_END);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::FINALIZE_END);
|
||||||
FreeOp fop(rt);
|
FreeOp fop(rt);
|
||||||
|
@ -5600,7 +5628,7 @@ GCRuntime::endSweepingSweepGroup()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the GC state for zones we have swept. */
|
/* Update the GC state for zones we have swept. */
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||||
AutoLockGC lock(rt);
|
AutoLockGC lock(rt);
|
||||||
zone->changeGCState(Zone::Sweep, Zone::Finished);
|
zone->changeGCState(Zone::Sweep, Zone::Finished);
|
||||||
zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables,
|
zone->threshold.updateAfterGC(zone->usage.gcBytes(), invocationKind, tunables,
|
||||||
|
@ -5609,7 +5637,7 @@ GCRuntime::endSweepingSweepGroup()
|
||||||
|
|
||||||
/* Start background thread to sweep zones if required. */
|
/* Start background thread to sweep zones if required. */
|
||||||
ZoneList zones;
|
ZoneList zones;
|
||||||
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next())
|
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
|
||||||
zones.append(zone);
|
zones.append(zone);
|
||||||
if (sweepOnBackgroundThread)
|
if (sweepOnBackgroundThread)
|
||||||
queueZonesForBackgroundSweep(zones);
|
queueZonesForBackgroundSweep(zones);
|
||||||
|
@ -5621,6 +5649,8 @@ GCRuntime::endSweepingSweepGroup()
|
||||||
arenasAllocatedDuringSweep = arena->getNextAllocDuringSweep();
|
arenasAllocatedDuringSweep = arena->getNextAllocDuringSweep();
|
||||||
arena->unsetAllocDuringSweep();
|
arena->unsetAllocDuringSweep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -5653,8 +5683,12 @@ GCRuntime::beginSweepPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcce
|
||||||
DropStringWrappers(rt);
|
DropStringWrappers(rt);
|
||||||
|
|
||||||
groupZonesForSweeping(reason, lock);
|
groupZonesForSweeping(reason, lock);
|
||||||
endMarkingSweepGroup();
|
|
||||||
beginSweepingSweepGroup();
|
sweepActions->assertFinished();
|
||||||
|
|
||||||
|
// We must not yield after this point until we start sweeping the first sweep
|
||||||
|
// group.
|
||||||
|
safeToYield = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -5737,8 +5771,8 @@ SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget, Args... args)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone)
|
GCRuntime::sweepTypeInformation(FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||||
{
|
{
|
||||||
// Sweep dead type information stored in scripts and object groups, but
|
// Sweep dead type information stored in scripts and object groups, but
|
||||||
// don't finalize them yet. We have to sweep dead information from both live
|
// don't finalize them yet. We have to sweep dead information from both live
|
||||||
|
@ -5748,8 +5782,8 @@ GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
||||||
// the sweep group finishes we won't be able to determine which things in
|
// the sweep group finishes we won't be able to determine which things in
|
||||||
// the zone are live.
|
// the zone are live.
|
||||||
|
|
||||||
gcstats::AutoPhase ap1(gc->stats(), gcstats::PhaseKind::SWEEP_COMPARTMENTS);
|
gcstats::AutoPhase ap1(stats(), gcstats::PhaseKind::SWEEP_COMPARTMENTS);
|
||||||
gcstats::AutoPhase ap2(gc->stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
gcstats::AutoPhase ap2(stats(), gcstats::PhaseKind::SWEEP_TYPES);
|
||||||
|
|
||||||
ArenaLists& al = zone->arenas;
|
ArenaLists& al = zone->arenas;
|
||||||
|
|
||||||
|
@ -5763,15 +5797,16 @@ GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, SliceBudget& budget,
|
||||||
|
|
||||||
// Finish sweeping type information in the zone.
|
// Finish sweeping type information in the zone.
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::SWEEP_TYPES_END);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_TYPES_END);
|
||||||
zone->types.endSweep(gc->rt);
|
zone->types.endSweep(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Finished;
|
return Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone)
|
GCRuntime::mergeSweptObjectArenas(FreeOp* fop, SliceBudget& budget,
|
||||||
|
Zone* zone)
|
||||||
{
|
{
|
||||||
// Foreground finalized objects have already been finalized, and now their
|
// Foreground finalized objects have already been finalized, and now their
|
||||||
// arenas can be reclaimed by freeing empty ones and making non-empty ones
|
// arenas can be reclaimed by freeing empty ones and making non-empty ones
|
||||||
|
@ -5802,18 +5837,12 @@ GCRuntime::startSweepingAtomsTable()
|
||||||
maybeAtoms.emplace(*atomsTable);
|
maybeAtoms.emplace(*atomsTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::sweepAtomsTable(GCRuntime* gc, FreeOp* fop, SliceBudget& budget)
|
GCRuntime::sweepAtomsTable(FreeOp* fop, SliceBudget& budget)
|
||||||
{
|
{
|
||||||
if (!gc->atomsZone->isGCSweeping())
|
if (!atomsZone->isGCSweeping())
|
||||||
return Finished;
|
return Finished;
|
||||||
|
|
||||||
return gc->sweepAtomsTable(budget);
|
|
||||||
}
|
|
||||||
|
|
||||||
IncrementalProgress
|
|
||||||
GCRuntime::sweepAtomsTable(SliceBudget& budget)
|
|
||||||
{
|
|
||||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_ATOMS_TABLE);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_ATOMS_TABLE);
|
||||||
|
|
||||||
auto& maybeAtoms = maybeAtomsToSweep.ref();
|
auto& maybeAtoms = maybeAtomsToSweep.ref();
|
||||||
|
@ -5943,12 +5972,6 @@ class IncrementalSweepWeakCacheTask : public GCParallelTask
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* static */ IncrementalProgress
|
|
||||||
GCRuntime::sweepWeakCaches(GCRuntime* gc, FreeOp* fop, SliceBudget& budget)
|
|
||||||
{
|
|
||||||
return gc->sweepWeakCaches(budget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const size_t MaxWeakCacheSweepTasks = 8;
|
static const size_t MaxWeakCacheSweepTasks = 8;
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
|
@ -5959,7 +5982,7 @@ WeakCacheSweepTaskCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::sweepWeakCaches(SliceBudget& budget)
|
GCRuntime::sweepWeakCaches(FreeOp* fop, SliceBudget& budget)
|
||||||
{
|
{
|
||||||
WeakCacheSweepIterator work(this);
|
WeakCacheSweepIterator work(this);
|
||||||
|
|
||||||
|
@ -5978,13 +6001,12 @@ GCRuntime::sweepWeakCaches(SliceBudget& budget)
|
||||||
return work.empty(lock) ? Finished : NotFinished;
|
return work.empty(lock) ? Finished : NotFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone,
|
GCRuntime::finalizeAllocKind(FreeOp* fop, SliceBudget& budget, Zone* zone, AllocKind kind)
|
||||||
AllocKind kind)
|
|
||||||
{
|
{
|
||||||
// Set the number of things per arena for this AllocKind.
|
// Set the number of things per arena for this AllocKind.
|
||||||
size_t thingsPerArena = Arena::thingsPerArena(kind);
|
size_t thingsPerArena = Arena::thingsPerArena(kind);
|
||||||
auto& sweepList = gc->incrementalSweepList.ref();
|
auto& sweepList = incrementalSweepList.ref();
|
||||||
sweepList.setThingsPerArena(thingsPerArena);
|
sweepList.setThingsPerArena(thingsPerArena);
|
||||||
|
|
||||||
if (!zone->arenas.foregroundFinalize(fop, kind, budget, sweepList))
|
if (!zone->arenas.foregroundFinalize(fop, kind, budget, sweepList))
|
||||||
|
@ -5996,12 +6018,12 @@ GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zo
|
||||||
return Finished;
|
return Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::sweepShapeTree(GCRuntime* gc, FreeOp* fop, SliceBudget& budget, Zone* zone)
|
GCRuntime::sweepShapeTree(FreeOp* fop, SliceBudget& budget, Zone* zone)
|
||||||
{
|
{
|
||||||
// Remove dead shapes from the shape tree, but don't finalize them yet.
|
// Remove dead shapes from the shape tree, but don't finalize them yet.
|
||||||
|
|
||||||
gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::SWEEP_SHAPE);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_SHAPE);
|
||||||
|
|
||||||
ArenaLists& al = zone->arenas;
|
ArenaLists& al = zone->arenas;
|
||||||
|
|
||||||
|
@ -6084,20 +6106,46 @@ struct IncrementalIter
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace sweepaction {
|
// Iterate through the sweep groups created by GCRuntime::groupZonesForSweeping().
|
||||||
|
class js::gc::SweepGroupsIter
|
||||||
// Implementation of the SweepAction interface that calls a function.
|
|
||||||
template <typename... Args>
|
|
||||||
class SweepActionFunc final : public SweepAction<Args...>
|
|
||||||
{
|
{
|
||||||
using Func = IncrementalProgress (*)(Args...);
|
GCRuntime* gc;
|
||||||
|
|
||||||
Func func;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SweepActionFunc(Func f) : func(f) {}
|
explicit SweepGroupsIter(JSRuntime* rt)
|
||||||
IncrementalProgress run(Args... args) override {
|
: gc(&rt->gc)
|
||||||
return func(args...);
|
{
|
||||||
|
MOZ_ASSERT(gc->currentSweepGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool done() const {
|
||||||
|
return !gc->currentSweepGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zone* get() const {
|
||||||
|
return gc->currentSweepGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next() {
|
||||||
|
MOZ_ASSERT(!done());
|
||||||
|
gc->getNextSweepGroup();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace sweepaction {
|
||||||
|
|
||||||
|
// Implementation of the SweepAction interface that calls a method on GCRuntime.
|
||||||
|
template <typename... Args>
|
||||||
|
class SweepActionCall final : public SweepAction<GCRuntime*, Args...>
|
||||||
|
{
|
||||||
|
using Method = IncrementalProgress (GCRuntime::*)(Args...);
|
||||||
|
|
||||||
|
Method method;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SweepActionCall(Method m) : method(m) {}
|
||||||
|
IncrementalProgress run(GCRuntime* gc, Args... args) override {
|
||||||
|
return (gc->*method)(args...);
|
||||||
}
|
}
|
||||||
void assertFinished() const override { }
|
void assertFinished() const override { }
|
||||||
};
|
};
|
||||||
|
@ -6168,6 +6216,36 @@ class SweepActionForEach final : public SweepAction<Args...>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Iter, typename Init, typename... Args>
|
||||||
|
class SweepActionRepeatFor final : public SweepAction<Args...>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
using Action = SweepAction<Args...>;
|
||||||
|
using IncrIter = IncrementalIter<Iter>;
|
||||||
|
|
||||||
|
Init iterInit;
|
||||||
|
UniquePtr<Action> action;
|
||||||
|
typename IncrIter::State iterState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SweepActionRepeatFor(const Init& init, UniquePtr<Action> action)
|
||||||
|
: iterInit(init), action(Move(action))
|
||||||
|
{}
|
||||||
|
|
||||||
|
IncrementalProgress run(Args... args) override {
|
||||||
|
for (IncrIter iter(iterState, iterInit); !iter.done(); iter.next()) {
|
||||||
|
if (action->run(args...) == NotFinished)
|
||||||
|
return NotFinished;
|
||||||
|
}
|
||||||
|
return Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertFinished() const override {
|
||||||
|
MOZ_ASSERT(iterState.isNothing());
|
||||||
|
action->assertFinished();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Helper class to remove the last template parameter from the instantiation of
|
// Helper class to remove the last template parameter from the instantiation of
|
||||||
// a variadic template. For example:
|
// a variadic template. For example:
|
||||||
//
|
//
|
||||||
|
@ -6206,9 +6284,9 @@ class RemoveLastTemplateParameter<Target<Args...>>
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static UniquePtr<SweepAction<Args...>>
|
static UniquePtr<SweepAction<GCRuntime*, Args...>>
|
||||||
Func(IncrementalProgress (*func)(Args...)) {
|
Call(IncrementalProgress (GCRuntime::*method)(Args...)) {
|
||||||
return MakeUnique<SweepActionFunc<Args...>>(func);
|
return MakeUnique<SweepActionCall<Args...>>(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args, typename... Rest>
|
template <typename... Args, typename... Rest>
|
||||||
|
@ -6223,6 +6301,17 @@ Sequence(UniquePtr<SweepAction<Args...>> first, Rest... rest)
|
||||||
return UniquePtr<SweepAction<Args...>>(Move(seq));
|
return UniquePtr<SweepAction<Args...>>(Move(seq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static UniquePtr<SweepAction<Args...>>
|
||||||
|
RepeatForSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
|
||||||
|
{
|
||||||
|
if (!action)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
using Action = SweepActionRepeatFor<SweepGroupsIter, JSRuntime*, Args...>;
|
||||||
|
return js::MakeUnique<Action>(rt, Move(action));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type>
|
static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type>
|
||||||
ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
|
ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
|
||||||
|
@ -6231,7 +6320,7 @@ ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
using Action = typename RemoveLastTemplateParameter<
|
using Action = typename RemoveLastTemplateParameter<
|
||||||
SweepActionForEach<GCSweepGroupIter, JSRuntime*, Args...>>::Type;
|
SweepActionForEach<SweepGroupZonesIter, JSRuntime*, Args...>>::Type;
|
||||||
return js::MakeUnique<Action>(rt, Move(action));
|
return js::MakeUnique<Action>(rt, Move(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6253,22 +6342,31 @@ bool
|
||||||
GCRuntime::initSweepActions()
|
GCRuntime::initSweepActions()
|
||||||
{
|
{
|
||||||
using namespace sweepaction;
|
using namespace sweepaction;
|
||||||
|
using sweepaction::Call;
|
||||||
|
|
||||||
sweepActions.ref() = Sequence(
|
sweepActions.ref() =
|
||||||
Func(sweepAtomsTable),
|
RepeatForSweepGroup(rt,
|
||||||
Func(sweepWeakCaches),
|
|
||||||
ForEachZoneInSweepGroup(rt,
|
|
||||||
ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
|
|
||||||
Func(finalizeAllocKind))),
|
|
||||||
ForEachZoneInSweepGroup(rt,
|
|
||||||
Sequence(
|
Sequence(
|
||||||
Func(sweepTypeInformation),
|
Call(&GCRuntime::endMarkingSweepGroup),
|
||||||
Func(mergeSweptObjectArenas))),
|
Call(&GCRuntime::beginSweepingSweepGroup),
|
||||||
ForEachZoneInSweepGroup(rt,
|
#ifdef JS_GC_ZEAL
|
||||||
ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
|
Call(&GCRuntime::maybeYieldForSweepingZeal),
|
||||||
Func(finalizeAllocKind))),
|
#endif
|
||||||
ForEachZoneInSweepGroup(rt,
|
Call(&GCRuntime::sweepAtomsTable),
|
||||||
Func(sweepShapeTree)));
|
Call(&GCRuntime::sweepWeakCaches),
|
||||||
|
ForEachZoneInSweepGroup(rt,
|
||||||
|
ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
|
||||||
|
Call(&GCRuntime::finalizeAllocKind))),
|
||||||
|
ForEachZoneInSweepGroup(rt,
|
||||||
|
Sequence(
|
||||||
|
Call(&GCRuntime::sweepTypeInformation),
|
||||||
|
Call(&GCRuntime::mergeSweptObjectArenas))),
|
||||||
|
ForEachZoneInSweepGroup(rt,
|
||||||
|
ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
|
||||||
|
Call(&GCRuntime::finalizeAllocKind))),
|
||||||
|
ForEachZoneInSweepGroup(rt,
|
||||||
|
Call(&GCRuntime::sweepShapeTree)),
|
||||||
|
Call(&GCRuntime::endSweepingSweepGroup)));
|
||||||
|
|
||||||
return sweepActions != nullptr;
|
return sweepActions != nullptr;
|
||||||
}
|
}
|
||||||
|
@ -6281,21 +6379,17 @@ GCRuntime::performSweepActions(SliceBudget& budget, AutoLockForExclusiveAccess&
|
||||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
|
||||||
FreeOp fop(rt);
|
FreeOp fop(rt);
|
||||||
|
|
||||||
if (drainMarkStack(budget, gcstats::PhaseKind::SWEEP_MARK) == NotFinished)
|
// Drain the mark stack, except in the first sweep slice where we must not
|
||||||
return NotFinished;
|
// yield to the mutator until we've starting sweeping a sweep group.
|
||||||
|
MOZ_ASSERT(initialState <= State::Sweep);
|
||||||
for (;;) {
|
if (initialState != State::Sweep) {
|
||||||
if (sweepActions->run(this, &fop, budget) == NotFinished)
|
MOZ_ASSERT(marker.isDrained());
|
||||||
return NotFinished;
|
} else {
|
||||||
|
if (drainMarkStack(budget, gcstats::PhaseKind::SWEEP_MARK) == NotFinished)
|
||||||
endSweepingSweepGroup();
|
return NotFinished;
|
||||||
getNextSweepGroup();
|
|
||||||
if (!currentSweepGroup)
|
|
||||||
return Finished;
|
|
||||||
|
|
||||||
endMarkingSweepGroup();
|
|
||||||
beginSweepingSweepGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sweepActions->run(this, &fop, budget);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -6331,6 +6425,8 @@ GCRuntime::allCCVisibleZonesWereCollected() const
|
||||||
void
|
void
|
||||||
GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& lock)
|
GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& lock)
|
||||||
{
|
{
|
||||||
|
sweepActions->assertFinished();
|
||||||
|
|
||||||
AutoSetThreadIsSweeping threadIsSweeping;
|
AutoSetThreadIsSweeping threadIsSweeping;
|
||||||
|
|
||||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
|
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP);
|
||||||
|
@ -6766,18 +6862,17 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||||
|
|
||||||
bool destroyingRuntime = (reason == JS::gcreason::DESTROY_RUNTIME);
|
bool destroyingRuntime = (reason == JS::gcreason::DESTROY_RUNTIME);
|
||||||
|
|
||||||
gc::State initialState = incrementalState;
|
initialState = incrementalState;
|
||||||
|
|
||||||
bool useZeal = false;
|
|
||||||
#ifdef JS_GC_ZEAL
|
#ifdef JS_GC_ZEAL
|
||||||
if (reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited()) {
|
/*
|
||||||
/*
|
* Do the incremental collection type specified by zeal mode if the
|
||||||
* Do the incremental collection type specified by zeal mode if the
|
* collection was triggered by runDebugGC() and incremental GC has not been
|
||||||
* collection was triggered by runDebugGC() and incremental GC has not
|
* cancelled by resetIncrementalGC().
|
||||||
* been cancelled by resetIncrementalGC().
|
*/
|
||||||
*/
|
useZeal = reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited();
|
||||||
useZeal = true;
|
#else
|
||||||
}
|
bool useZeal = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
|
MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
|
||||||
|
@ -6860,24 +6955,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||||
|
|
||||||
incrementalState = State::Sweep;
|
incrementalState = State::Sweep;
|
||||||
|
|
||||||
/*
|
|
||||||
* This runs to completion, but we don't continue if the budget is
|
|
||||||
* now exhasted.
|
|
||||||
*/
|
|
||||||
beginSweepPhase(reason, lock);
|
beginSweepPhase(reason, lock);
|
||||||
if (budget.isOverBudget())
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Always yield here when running in incremental multi-slice zeal
|
|
||||||
* mode, so RunDebugGC can reset the slice buget.
|
|
||||||
*/
|
|
||||||
if (isIncremental && useZeal &&
|
|
||||||
(hasZealMode(ZealMode::IncrementalMultipleSlices) ||
|
|
||||||
hasZealMode(ZealMode::IncrementalSweepThenFinish)))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_FALLTHROUGH;
|
MOZ_FALLTHROUGH;
|
||||||
|
|
||||||
|
@ -6956,6 +7034,8 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||||
incrementalState = State::NotActive;
|
incrementalState = State::NotActive;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(safeToYield);
|
||||||
}
|
}
|
||||||
|
|
||||||
gc::AbortReason
|
gc::AbortReason
|
||||||
|
|
|
@ -437,11 +437,11 @@ class GCZonesIter
|
||||||
typedef CompartmentsIterT<GCZonesIter> GCCompartmentsIter;
|
typedef CompartmentsIterT<GCZonesIter> GCCompartmentsIter;
|
||||||
|
|
||||||
/* Iterates over all zones in the current sweep group. */
|
/* Iterates over all zones in the current sweep group. */
|
||||||
class GCSweepGroupIter {
|
class SweepGroupZonesIter {
|
||||||
JS::Zone* current;
|
JS::Zone* current;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GCSweepGroupIter(JSRuntime* rt) {
|
explicit SweepGroupZonesIter(JSRuntime* rt) {
|
||||||
MOZ_ASSERT(CurrentThreadIsPerformingGC());
|
MOZ_ASSERT(CurrentThreadIsPerformingGC());
|
||||||
current = rt->gc.getCurrentSweepGroup();
|
current = rt->gc.getCurrentSweepGroup();
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ class GCSweepGroupIter {
|
||||||
JS::Zone* operator->() const { return get(); }
|
JS::Zone* operator->() const { return get(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef CompartmentsIterT<GCSweepGroupIter> GCCompartmentGroupIter;
|
typedef CompartmentsIterT<SweepGroupZonesIter> SweepGroupCompartmentsIter;
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
RelocationOverlay::forwardTo(Cell* cell)
|
RelocationOverlay::forwardTo(Cell* cell)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/EndianUtils.h"
|
||||||
|
|
||||||
#include "jsbytecode.h"
|
#include "jsbytecode.h"
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
|
@ -136,17 +137,26 @@ UINT16_LO(uint16_t i)
|
||||||
static MOZ_ALWAYS_INLINE uint16_t
|
static MOZ_ALWAYS_INLINE uint16_t
|
||||||
GET_UINT16(const jsbytecode* pc)
|
GET_UINT16(const jsbytecode* pc)
|
||||||
{
|
{
|
||||||
return uint16_t((pc[1] << 8) | pc[2]);
|
#if MOZ_LITTLE_ENDIAN
|
||||||
|
uint16_t result;
|
||||||
|
memcpy(&result, pc + 1, sizeof(result));
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return uint16_t((pc[2] << 8) | pc[1]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE void
|
static MOZ_ALWAYS_INLINE void
|
||||||
SET_UINT16(jsbytecode* pc, uint16_t i)
|
SET_UINT16(jsbytecode* pc, uint16_t i)
|
||||||
{
|
{
|
||||||
pc[1] = UINT16_HI(i);
|
#if MOZ_LITTLE_ENDIAN
|
||||||
pc[2] = UINT16_LO(i);
|
memcpy(pc + 1, &i, sizeof(i));
|
||||||
|
#else
|
||||||
|
pc[1] = UINT16_LO(i);
|
||||||
|
pc[2] = UINT16_HI(i);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned UINT16_LEN = 2;
|
|
||||||
static const unsigned UINT16_LIMIT = 1 << 16;
|
static const unsigned UINT16_LIMIT = 1 << 16;
|
||||||
|
|
||||||
/* Helpers for accessing the offsets of jump opcodes. */
|
/* Helpers for accessing the offsets of jump opcodes. */
|
||||||
|
@ -154,69 +164,32 @@ static const unsigned JUMP_OFFSET_LEN = 4;
|
||||||
static const int32_t JUMP_OFFSET_MIN = INT32_MIN;
|
static const int32_t JUMP_OFFSET_MIN = INT32_MIN;
|
||||||
static const int32_t JUMP_OFFSET_MAX = INT32_MAX;
|
static const int32_t JUMP_OFFSET_MAX = INT32_MAX;
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE int32_t
|
|
||||||
GET_JUMP_OFFSET(jsbytecode* pc)
|
|
||||||
{
|
|
||||||
return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE void
|
|
||||||
SET_JUMP_OFFSET(jsbytecode* pc, int32_t off)
|
|
||||||
{
|
|
||||||
pc[1] = jsbytecode(off >> 24);
|
|
||||||
pc[2] = jsbytecode(off >> 16);
|
|
||||||
pc[3] = jsbytecode(off >> 8);
|
|
||||||
pc[4] = jsbytecode(off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned UINT32_INDEX_LEN = 4;
|
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE uint32_t
|
static MOZ_ALWAYS_INLINE uint32_t
|
||||||
GET_UINT32_INDEX(const jsbytecode* pc)
|
|
||||||
{
|
|
||||||
return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE void
|
|
||||||
SET_UINT32_INDEX(jsbytecode* pc, uint32_t index)
|
|
||||||
{
|
|
||||||
pc[1] = jsbytecode(index >> 24);
|
|
||||||
pc[2] = jsbytecode(index >> 16);
|
|
||||||
pc[3] = jsbytecode(index >> 8);
|
|
||||||
pc[4] = jsbytecode(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline jsbytecode
|
|
||||||
UINT24_HI(unsigned i)
|
|
||||||
{
|
|
||||||
return jsbytecode(i >> 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline jsbytecode
|
|
||||||
UINT24_MID(unsigned i)
|
|
||||||
{
|
|
||||||
return jsbytecode(i >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline jsbytecode
|
|
||||||
UINT24_LO(unsigned i)
|
|
||||||
{
|
|
||||||
return jsbytecode(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE unsigned
|
|
||||||
GET_UINT24(const jsbytecode* pc)
|
GET_UINT24(const jsbytecode* pc)
|
||||||
{
|
{
|
||||||
return unsigned((pc[1] << 16) | (pc[2] << 8) | pc[3]);
|
#if MOZ_LITTLE_ENDIAN
|
||||||
|
// Do a single 32-bit load (for opcode and operand), then shift off the
|
||||||
|
// opcode.
|
||||||
|
uint32_t result;
|
||||||
|
memcpy(&result, pc, 4);
|
||||||
|
return result >> 8;
|
||||||
|
#else
|
||||||
|
return unsigned((pc[3] << 16) | (pc[2] << 8) | pc[1]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE void
|
static MOZ_ALWAYS_INLINE void
|
||||||
SET_UINT24(jsbytecode* pc, unsigned i)
|
SET_UINT24(jsbytecode* pc, uint32_t i)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(i < (1 << 24));
|
MOZ_ASSERT(i < (1 << 24));
|
||||||
pc[1] = UINT24_HI(i);
|
|
||||||
pc[2] = UINT24_MID(i);
|
#if MOZ_LITTLE_ENDIAN
|
||||||
pc[3] = UINT24_LO(i);
|
memcpy(pc + 1, &i, 3);
|
||||||
|
#else
|
||||||
|
pc[1] = jsbytecode(i);
|
||||||
|
pc[2] = jsbytecode(i >> 8);
|
||||||
|
pc[3] = jsbytecode(i >> 16);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE int8_t
|
static MOZ_ALWAYS_INLINE int8_t
|
||||||
|
@ -228,19 +201,29 @@ GET_INT8(const jsbytecode* pc)
|
||||||
static MOZ_ALWAYS_INLINE uint32_t
|
static MOZ_ALWAYS_INLINE uint32_t
|
||||||
GET_UINT32(const jsbytecode* pc)
|
GET_UINT32(const jsbytecode* pc)
|
||||||
{
|
{
|
||||||
return (uint32_t(pc[1]) << 24) |
|
#if MOZ_LITTLE_ENDIAN
|
||||||
(uint32_t(pc[2]) << 16) |
|
uint32_t result;
|
||||||
(uint32_t(pc[3]) << 8) |
|
memcpy(&result, pc + 1, sizeof(result));
|
||||||
uint32_t(pc[4]);
|
return result;
|
||||||
|
#else
|
||||||
|
return (uint32_t(pc[4]) << 24) |
|
||||||
|
(uint32_t(pc[3]) << 16) |
|
||||||
|
(uint32_t(pc[2]) << 8) |
|
||||||
|
uint32_t(pc[1]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE void
|
static MOZ_ALWAYS_INLINE void
|
||||||
SET_UINT32(jsbytecode* pc, uint32_t u)
|
SET_UINT32(jsbytecode* pc, uint32_t u)
|
||||||
{
|
{
|
||||||
pc[1] = jsbytecode(u >> 24);
|
#if MOZ_LITTLE_ENDIAN
|
||||||
pc[2] = jsbytecode(u >> 16);
|
memcpy(pc + 1, &u, sizeof(u));
|
||||||
pc[3] = jsbytecode(u >> 8);
|
#else
|
||||||
pc[4] = jsbytecode(u);
|
pc[1] = jsbytecode(u);
|
||||||
|
pc[2] = jsbytecode(u >> 8);
|
||||||
|
pc[3] = jsbytecode(u >> 16);
|
||||||
|
pc[4] = jsbytecode(u >> 24);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE int32_t
|
static MOZ_ALWAYS_INLINE int32_t
|
||||||
|
@ -255,6 +238,32 @@ SET_INT32(jsbytecode* pc, int32_t i)
|
||||||
SET_UINT32(pc, static_cast<uint32_t>(i));
|
SET_UINT32(pc, static_cast<uint32_t>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MOZ_ALWAYS_INLINE int32_t
|
||||||
|
GET_JUMP_OFFSET(jsbytecode* pc)
|
||||||
|
{
|
||||||
|
return GET_INT32(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOZ_ALWAYS_INLINE void
|
||||||
|
SET_JUMP_OFFSET(jsbytecode* pc, int32_t off)
|
||||||
|
{
|
||||||
|
SET_INT32(pc, off);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned UINT32_INDEX_LEN = 4;
|
||||||
|
|
||||||
|
static MOZ_ALWAYS_INLINE uint32_t
|
||||||
|
GET_UINT32_INDEX(const jsbytecode* pc)
|
||||||
|
{
|
||||||
|
return GET_UINT32(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MOZ_ALWAYS_INLINE void
|
||||||
|
SET_UINT32_INDEX(jsbytecode* pc, uint32_t index)
|
||||||
|
{
|
||||||
|
SET_UINT32(pc, index);
|
||||||
|
}
|
||||||
|
|
||||||
/* Index limit is determined by SN_4BYTE_OFFSET_FLAG, see frontend/BytecodeEmitter.h. */
|
/* Index limit is determined by SN_4BYTE_OFFSET_FLAG, see frontend/BytecodeEmitter.h. */
|
||||||
static const unsigned INDEX_LIMIT_LOG2 = 31;
|
static const unsigned INDEX_LIMIT_LOG2 = 31;
|
||||||
static const uint32_t INDEX_LIMIT = uint32_t(1) << INDEX_LIMIT_LOG2;
|
static const uint32_t INDEX_LIMIT = uint32_t(1) << INDEX_LIMIT_LOG2;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "mozilla/Alignment.h"
|
#include "mozilla/Alignment.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
|
#include "mozilla/OperatorNewExtensions.h"
|
||||||
|
|
||||||
#include "threading/ConditionVariable.h"
|
#include "threading/ConditionVariable.h"
|
||||||
#include "threading/Mutex.h"
|
#include "threading/Mutex.h"
|
||||||
|
@ -99,7 +100,7 @@ class ExclusiveData
|
||||||
explicit ExclusiveData(const MutexId& id, U&& u)
|
explicit ExclusiveData(const MutexId& id, U&& u)
|
||||||
: lock_(id)
|
: lock_(id)
|
||||||
{
|
{
|
||||||
new (value_.addr()) T(mozilla::Forward<U>(u));
|
new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Forward<U>(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,7 +110,7 @@ class ExclusiveData
|
||||||
explicit ExclusiveData(const MutexId& id, Args&&... args)
|
explicit ExclusiveData(const MutexId& id, Args&&... args)
|
||||||
: lock_(id)
|
: lock_(id)
|
||||||
{
|
{
|
||||||
new (value_.addr()) T(mozilla::Forward<Args>(args)...);
|
new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ExclusiveData() {
|
~ExclusiveData() {
|
||||||
|
@ -122,12 +123,12 @@ class ExclusiveData
|
||||||
lock_(mozilla::Move(rhs.lock))
|
lock_(mozilla::Move(rhs.lock))
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(&rhs != this, "self-move disallowed!");
|
MOZ_ASSERT(&rhs != this, "self-move disallowed!");
|
||||||
new (value_.addr()) T(mozilla::Move(*rhs.value_.addr()));
|
new (mozilla::KnownNotNull, value_.addr()) T(mozilla::Move(*rhs.value_.addr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusiveData& operator=(ExclusiveData&& rhs) {
|
ExclusiveData& operator=(ExclusiveData&& rhs) {
|
||||||
this->~ExclusiveData();
|
this->~ExclusiveData();
|
||||||
new (this) ExclusiveData(mozilla::Move(rhs));
|
new (mozilla::KnownNotNull, this) ExclusiveData(mozilla::Move(rhs));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,7 @@ class ElementSpecific
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inhibit unaligned accesses on ARM (bug 1097253, a compiler bug).
|
// Inhibit unaligned accesses on ARM (bug 1097253, a compiler bug).
|
||||||
#ifdef __arm__
|
#if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
|
||||||
# define JS_VOLATILE_ARM volatile
|
# define JS_VOLATILE_ARM volatile
|
||||||
#else
|
#else
|
||||||
# define JS_VOLATILE_ARM
|
# define JS_VOLATILE_ARM
|
||||||
|
|
|
@ -246,6 +246,7 @@ static const unsigned PushedFP = 5;
|
||||||
static const unsigned SetFP = 8;
|
static const unsigned SetFP = 8;
|
||||||
static const unsigned PoppedFP = 4;
|
static const unsigned PoppedFP = 4;
|
||||||
static const unsigned PoppedExitReason = 2;
|
static const unsigned PoppedExitReason = 2;
|
||||||
|
static const unsigned PoppedTLSReg = 0;
|
||||||
#elif defined(JS_CODEGEN_X86)
|
#elif defined(JS_CODEGEN_X86)
|
||||||
static const unsigned PushedRetAddr = 0;
|
static const unsigned PushedRetAddr = 0;
|
||||||
static const unsigned PushedTLS = 1;
|
static const unsigned PushedTLS = 1;
|
||||||
|
@ -254,6 +255,7 @@ static const unsigned PushedFP = 4;
|
||||||
static const unsigned SetFP = 6;
|
static const unsigned SetFP = 6;
|
||||||
static const unsigned PoppedFP = 2;
|
static const unsigned PoppedFP = 2;
|
||||||
static const unsigned PoppedExitReason = 1;
|
static const unsigned PoppedExitReason = 1;
|
||||||
|
static const unsigned PoppedTLSReg = 0;
|
||||||
#elif defined(JS_CODEGEN_ARM)
|
#elif defined(JS_CODEGEN_ARM)
|
||||||
static const unsigned BeforePushRetAddr = 0;
|
static const unsigned BeforePushRetAddr = 0;
|
||||||
static const unsigned PushedRetAddr = 4;
|
static const unsigned PushedRetAddr = 4;
|
||||||
|
@ -263,6 +265,7 @@ static const unsigned PushedFP = 20;
|
||||||
static const unsigned SetFP = 24;
|
static const unsigned SetFP = 24;
|
||||||
static const unsigned PoppedFP = 8;
|
static const unsigned PoppedFP = 8;
|
||||||
static const unsigned PoppedExitReason = 4;
|
static const unsigned PoppedExitReason = 4;
|
||||||
|
static const unsigned PoppedTLSReg = 0;
|
||||||
#elif defined(JS_CODEGEN_ARM64)
|
#elif defined(JS_CODEGEN_ARM64)
|
||||||
static const unsigned BeforePushRetAddr = 0;
|
static const unsigned BeforePushRetAddr = 0;
|
||||||
static const unsigned PushedRetAddr = 0;
|
static const unsigned PushedRetAddr = 0;
|
||||||
|
@ -272,6 +275,7 @@ static const unsigned PushedFP = 0;
|
||||||
static const unsigned SetFP = 0;
|
static const unsigned SetFP = 0;
|
||||||
static const unsigned PoppedFP = 0;
|
static const unsigned PoppedFP = 0;
|
||||||
static const unsigned PoppedExitReason = 0;
|
static const unsigned PoppedExitReason = 0;
|
||||||
|
static const unsigned PoppedTLSReg = 0;
|
||||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||||
static const unsigned BeforePushRetAddr = 0;
|
static const unsigned BeforePushRetAddr = 0;
|
||||||
static const unsigned PushedRetAddr = 8;
|
static const unsigned PushedRetAddr = 8;
|
||||||
|
@ -279,8 +283,9 @@ static const unsigned PushedTLS = 16;
|
||||||
static const unsigned PushedExitReason = 28;
|
static const unsigned PushedExitReason = 28;
|
||||||
static const unsigned PushedFP = 36;
|
static const unsigned PushedFP = 36;
|
||||||
static const unsigned SetFP = 40;
|
static const unsigned SetFP = 40;
|
||||||
static const unsigned PoppedFP = 16;
|
static const unsigned PoppedFP = 24;
|
||||||
static const unsigned PoppedExitReason = 8;
|
static const unsigned PoppedExitReason = 16;
|
||||||
|
static const unsigned PoppedTLSReg = 8;
|
||||||
#elif defined(JS_CODEGEN_NONE)
|
#elif defined(JS_CODEGEN_NONE)
|
||||||
static const unsigned PushedRetAddr = 0;
|
static const unsigned PushedRetAddr = 0;
|
||||||
static const unsigned PushedTLS = 1;
|
static const unsigned PushedTLS = 1;
|
||||||
|
@ -289,6 +294,7 @@ static const unsigned PushedFP = 0;
|
||||||
static const unsigned SetFP = 0;
|
static const unsigned SetFP = 0;
|
||||||
static const unsigned PoppedFP = 0;
|
static const unsigned PoppedFP = 0;
|
||||||
static const unsigned PoppedExitReason = 0;
|
static const unsigned PoppedExitReason = 0;
|
||||||
|
static const unsigned PoppedTLSReg = 0;
|
||||||
#else
|
#else
|
||||||
# error "Unknown architecture!"
|
# error "Unknown architecture!"
|
||||||
#endif
|
#endif
|
||||||
|
@ -448,11 +454,20 @@ GenerateCallableEpilogue(MacroAssembler& masm, unsigned framePushed, ExitReason
|
||||||
DebugOnly<uint32_t> poppedExitReason = masm.currentOffset();
|
DebugOnly<uint32_t> poppedExitReason = masm.currentOffset();
|
||||||
|
|
||||||
masm.pop(WasmTlsReg);
|
masm.pop(WasmTlsReg);
|
||||||
|
DebugOnly<uint32_t> poppedTlsReg = masm.currentOffset();
|
||||||
|
|
||||||
|
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||||
|
masm.pop(ra);
|
||||||
|
*ret = masm.currentOffset();
|
||||||
|
masm.branch(ra);
|
||||||
|
#else
|
||||||
*ret = masm.currentOffset();
|
*ret = masm.currentOffset();
|
||||||
masm.ret();
|
masm.ret();
|
||||||
|
#endif
|
||||||
|
|
||||||
MOZ_ASSERT_IF(!masm.oom(), PoppedFP == *ret - poppedFP);
|
MOZ_ASSERT_IF(!masm.oom(), PoppedFP == *ret - poppedFP);
|
||||||
MOZ_ASSERT_IF(!masm.oom(), PoppedExitReason == *ret - poppedExitReason);
|
MOZ_ASSERT_IF(!masm.oom(), PoppedExitReason == *ret - poppedExitReason);
|
||||||
|
MOZ_ASSERT_IF(!masm.oom(), PoppedTLSReg == *ret - poppedTlsReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -734,7 +749,21 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
|
||||||
case CodeRange::BuiltinThunk:
|
case CodeRange::BuiltinThunk:
|
||||||
case CodeRange::TrapExit:
|
case CodeRange::TrapExit:
|
||||||
case CodeRange::DebugTrap:
|
case CodeRange::DebugTrap:
|
||||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||||
|
if ((offsetFromEntry >= BeforePushRetAddr && offsetFromEntry < PushedFP) || codeRange->isThunk()) {
|
||||||
|
// See BUG 1407986.
|
||||||
|
// On MIPS push is emulated by two instructions: adjusting the sp
|
||||||
|
// and storing the value to sp.
|
||||||
|
// Execution might be interrupted in between the two operation so we
|
||||||
|
// have to relay on register state instead of state saved on stack
|
||||||
|
// until the wasm::Frame is completely built.
|
||||||
|
// On entry the return address is in ra (registers.lr) and
|
||||||
|
// fp holds the caller's fp.
|
||||||
|
fixedPC = (uint8_t*) registers.lr;
|
||||||
|
fixedFP = fp;
|
||||||
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
|
} else
|
||||||
|
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
|
||||||
if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) {
|
if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) {
|
||||||
// The return address is still in lr and fp holds the caller's fp.
|
// The return address is still in lr and fp holds the caller's fp.
|
||||||
fixedPC = (uint8_t*) registers.lr;
|
fixedPC = (uint8_t*) registers.lr;
|
||||||
|
@ -766,24 +795,45 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
|
||||||
fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress;
|
fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress;
|
||||||
fixedFP = fp;
|
fixedFP = fp;
|
||||||
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
} else if (offsetInCode == codeRange->ret() - PoppedFP) {
|
} else if (offsetInCode >= codeRange->ret() - PoppedFP &&
|
||||||
|
offsetInCode < codeRange->ret() - PoppedExitReason)
|
||||||
|
{
|
||||||
// The fixedFP field of the Frame has been popped into fp, but the
|
// The fixedFP field of the Frame has been popped into fp, but the
|
||||||
// exit reason hasn't been popped yet.
|
// exit reason hasn't been popped yet.
|
||||||
fixedPC = sp[2];
|
fixedPC = sp[2];
|
||||||
fixedFP = fp;
|
fixedFP = fp;
|
||||||
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
} else if (offsetInCode == codeRange->ret() - PoppedExitReason) {
|
} else if (offsetInCode >= codeRange->ret() - PoppedExitReason &&
|
||||||
|
offsetInCode < codeRange->ret() - PoppedTLSReg)
|
||||||
|
{
|
||||||
// The fixedFP field of the Frame has been popped into fp, and the
|
// The fixedFP field of the Frame has been popped into fp, and the
|
||||||
// exit reason has been popped.
|
// exit reason has been popped.
|
||||||
fixedPC = sp[1];
|
fixedPC = sp[1];
|
||||||
fixedFP = fp;
|
fixedFP = fp;
|
||||||
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
|
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||||
|
} else if (offsetInCode >= codeRange->ret() - PoppedTLSReg &&
|
||||||
|
offsetInCode < codeRange->ret())
|
||||||
|
{
|
||||||
|
// The fixedFP field of the Frame has been popped into fp, but the
|
||||||
|
// exit reason hasn't been popped yet.
|
||||||
|
fixedPC = sp[0];
|
||||||
|
fixedFP = fp;
|
||||||
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
|
} else if (offsetInCode == codeRange->ret()) {
|
||||||
|
// Both the TLS, fixedFP and ra have been popped and fp now
|
||||||
|
// points to the caller's frame.
|
||||||
|
fixedPC = (uint8_t*) registers.lr;;
|
||||||
|
fixedFP = fp;
|
||||||
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
|
#else
|
||||||
} else if (offsetInCode == codeRange->ret()) {
|
} else if (offsetInCode == codeRange->ret()) {
|
||||||
// Both the TLS and fixedFP fields have been popped and fp now
|
// Both the TLS and fixedFP fields have been popped and fp now
|
||||||
// points to the caller's frame.
|
// points to the caller's frame.
|
||||||
fixedPC = sp[0];
|
fixedPC = sp[0];
|
||||||
fixedFP = fp;
|
fixedFP = fp;
|
||||||
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
AssertMatchesCallSite(activation, fixedPC, fixedFP);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (codeRange->kind() == CodeRange::ImportJitExit) {
|
if (codeRange->kind() == CodeRange::ImportJitExit) {
|
||||||
// The jit exit contains a range where the value of FP can't be
|
// The jit exit contains a range where the value of FP can't be
|
||||||
|
|
|
@ -173,6 +173,7 @@ class AutoSetHandlingSegFault
|
||||||
# define EPC_sig(p) ((p)->uc_mcontext.pc)
|
# define EPC_sig(p) ((p)->uc_mcontext.pc)
|
||||||
# define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
|
# define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
|
||||||
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
|
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
|
||||||
|
# define R31_sig(p) ((p)->uc_mcontext.gregs[31])
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
# define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
|
# define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
|
||||||
|
@ -418,6 +419,7 @@ struct macos_arm_context {
|
||||||
# define PC_sig(p) EPC_sig(p)
|
# define PC_sig(p) EPC_sig(p)
|
||||||
# define FP_sig(p) RFP_sig(p)
|
# define FP_sig(p) RFP_sig(p)
|
||||||
# define SP_sig(p) RSP_sig(p)
|
# define SP_sig(p) RSP_sig(p)
|
||||||
|
# define LR_sig(p) R31_sig(p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t**
|
static uint8_t**
|
||||||
|
@ -447,7 +449,7 @@ ContextToSP(CONTEXT* context)
|
||||||
return reinterpret_cast<uint8_t*>(SP_sig(context));
|
return reinterpret_cast<uint8_t*>(SP_sig(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
# if defined(__arm__) || defined(__aarch64__)
|
# if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
|
||||||
static uint8_t*
|
static uint8_t*
|
||||||
ContextToLR(CONTEXT* context)
|
ContextToLR(CONTEXT* context)
|
||||||
{
|
{
|
||||||
|
@ -538,7 +540,7 @@ ToRegisterState(CONTEXT* context)
|
||||||
state.fp = ContextToFP(context);
|
state.fp = ContextToFP(context);
|
||||||
state.pc = *ContextToPC(context);
|
state.pc = *ContextToPC(context);
|
||||||
state.sp = ContextToSP(context);
|
state.sp = ContextToSP(context);
|
||||||
# if defined(__arm__) || defined(__aarch64__)
|
# if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
|
||||||
state.lr = ContextToLR(context);
|
state.lr = ContextToLR(context);
|
||||||
# endif
|
# endif
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -1404,7 +1404,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
|
||||||
// This will call back into OnStreamComplete
|
// This will call back into OnStreamComplete
|
||||||
// and thence to ParseSheet. Regardless of whether this fails,
|
// and thence to ParseSheet. Regardless of whether this fails,
|
||||||
// SheetComplete has been called.
|
// SheetComplete has been called.
|
||||||
return nsSyncLoadService::PushSyncStreamToListener(stream,
|
return nsSyncLoadService::PushSyncStreamToListener(stream.forget(),
|
||||||
streamLoader,
|
streamLoader,
|
||||||
channel);
|
channel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine, const
|
||||||
vprintf(format, args);
|
vprintf(format, args);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
mozilla::LogLevel level = static_cast<mozilla::LogLevel>(priority);
|
mozilla::LogLevel level = static_cast<mozilla::LogLevel>(static_cast<unsigned int>(priority));
|
||||||
|
|
||||||
// Skip doing any of this work if we're not logging the indicated level...
|
// Skip doing any of this work if we're not logging the indicated level...
|
||||||
if (!MOZ_LOG_TEST(gSignalingLog, level)) {
|
if (!MOZ_LOG_TEST(gSignalingLog, level)) {
|
||||||
|
@ -82,6 +82,6 @@ void CSFLog( CSFLogLevel priority, const char* sourceFile, int sourceLine, const
|
||||||
|
|
||||||
int CSFLogTestLevel(CSFLogLevel priority)
|
int CSFLogTestLevel(CSFLogLevel priority)
|
||||||
{
|
{
|
||||||
mozilla::LogLevel level = static_cast<mozilla::LogLevel>(priority);
|
return MOZ_LOG_TEST(gSignalingLog,
|
||||||
return MOZ_LOG_TEST(gSignalingLog, level);
|
static_cast<mozilla::LogLevel>(static_cast<unsigned int>(priority)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,6 +510,9 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||||
* Callback for Open-in menu item.
|
* Callback for Open-in menu item.
|
||||||
*/
|
*/
|
||||||
private void onOpenInClicked() {
|
private void onOpenInClicked() {
|
||||||
|
if (TextUtils.isEmpty(mCurrentUrl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
intent.setData(Uri.parse(mCurrentUrl));
|
intent.setData(Uri.parse(mCurrentUrl));
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
|
|
|
@ -1216,7 +1216,7 @@ PREF_RegisterCallback(const char* aPrefNode,
|
||||||
NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
|
NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
|
||||||
NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
|
NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
|
||||||
|
|
||||||
auto node = new CallbackNode();
|
auto node = (CallbackNode*)moz_xmalloc(sizeof(CallbackNode));
|
||||||
node->mDomain = moz_xstrdup(aPrefNode);
|
node->mDomain = moz_xstrdup(aPrefNode);
|
||||||
node->mFunc = aCallback;
|
node->mFunc = aCallback;
|
||||||
node->mData = aData;
|
node->mData = aData;
|
||||||
|
@ -2975,7 +2975,7 @@ nsPrefBranch::GetChildList(const char* aStartingAt,
|
||||||
numPrefs = prefArray.Length();
|
numPrefs = prefArray.Length();
|
||||||
|
|
||||||
if (numPrefs) {
|
if (numPrefs) {
|
||||||
outArray = new char*[numPrefs];
|
outArray = (char**)moz_xmalloc(numPrefs * sizeof(char*));
|
||||||
|
|
||||||
for (dwIndex = 0; dwIndex < numPrefs; ++dwIndex) {
|
for (dwIndex = 0; dwIndex < numPrefs; ++dwIndex) {
|
||||||
// we need to lop off mPrefRoot in case the user is planning to pass this
|
// we need to lop off mPrefRoot in case the user is planning to pass this
|
||||||
|
|
|
@ -727,8 +727,9 @@ nsInputStreamPump::CreateBufferedStreamIfNeeded()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAsyncInputStream> stream = mAsyncStream;
|
||||||
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
|
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
|
||||||
mAsyncStream, 4096);
|
stream.forget(), 4096);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -1370,38 +1370,24 @@ NS_BufferOutputStream(nsIOutputStream *aOutputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_MUST_USE nsresult
|
MOZ_MUST_USE nsresult
|
||||||
NS_NewBufferedInputStream(nsIInputStream **result,
|
NS_NewBufferedInputStream(nsIInputStream** aResult,
|
||||||
nsIInputStream *str,
|
already_AddRefed<nsIInputStream> aInputStream,
|
||||||
uint32_t bufferSize)
|
uint32_t aBufferSize)
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIBufferedInputStream> in =
|
nsCOMPtr<nsIBufferedInputStream> in =
|
||||||
do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
|
do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
rv = in->Init(str, bufferSize);
|
rv = in->Init(inputStream, aBufferSize);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
in.forget(result);
|
in.forget(aResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIInputStream>
|
|
||||||
NS_BufferInputStream(nsIInputStream *aInputStream,
|
|
||||||
uint32_t aBufferSize)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(aInputStream, "No input stream given!");
|
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> bis;
|
|
||||||
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bis), aInputStream,
|
|
||||||
aBufferSize);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
return bis.forget();
|
|
||||||
|
|
||||||
bis = aInputStream;
|
|
||||||
return bis.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
NS_NewPostDataStream(nsIInputStream **result,
|
NS_NewPostDataStream(nsIInputStream **result,
|
||||||
bool isFile,
|
bool isFile,
|
||||||
|
@ -1418,7 +1404,8 @@ NS_NewPostDataStream(nsIInputStream **result,
|
||||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
|
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
// wrap the file stream with a buffered input stream
|
// wrap the file stream with a buffered input stream
|
||||||
rv = NS_NewBufferedInputStream(result, fileStream, 8192);
|
rv = NS_NewBufferedInputStream(result, fileStream.forget(),
|
||||||
|
8192);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -511,9 +511,9 @@ nsresult NS_NewLocalFileStream(nsIFileStream **result,
|
||||||
int32_t behaviorFlags = 0);
|
int32_t behaviorFlags = 0);
|
||||||
|
|
||||||
MOZ_MUST_USE nsresult
|
MOZ_MUST_USE nsresult
|
||||||
NS_NewBufferedInputStream(nsIInputStream **result,
|
NS_NewBufferedInputStream(nsIInputStream** aResult,
|
||||||
nsIInputStream *str,
|
already_AddRefed<nsIInputStream> aInputStream,
|
||||||
uint32_t bufferSize);
|
uint32_t aBufferSize);
|
||||||
|
|
||||||
// note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
|
// note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
|
||||||
// provided stream supports it.
|
// provided stream supports it.
|
||||||
|
@ -535,9 +535,6 @@ nsresult NS_NewBufferedOutputStream(nsIOutputStream **result,
|
||||||
already_AddRefed<nsIOutputStream>
|
already_AddRefed<nsIOutputStream>
|
||||||
NS_BufferOutputStream(nsIOutputStream *aOutputStream,
|
NS_BufferOutputStream(nsIOutputStream *aOutputStream,
|
||||||
uint32_t aBufferSize);
|
uint32_t aBufferSize);
|
||||||
already_AddRefed<nsIInputStream>
|
|
||||||
NS_BufferInputStream(nsIInputStream *aInputStream,
|
|
||||||
uint32_t aBufferSize);
|
|
||||||
|
|
||||||
// returns an input stream compatible with nsIUploadChannel::SetUploadStream()
|
// returns an input stream compatible with nsIUploadChannel::SetUploadStream()
|
||||||
nsresult NS_NewPostDataStream(nsIInputStream **result,
|
nsresult NS_NewPostDataStream(nsIInputStream **result,
|
||||||
|
|
|
@ -929,7 +929,8 @@ HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
|
||||||
if (NS_InputStreamIsBuffered(mUploadStream)) {
|
if (NS_InputStreamIsBuffered(mUploadStream)) {
|
||||||
source = mUploadStream;
|
source = mUploadStream;
|
||||||
} else {
|
} else {
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(source),
|
||||||
|
mUploadStream.forget(), 4096);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,8 @@ nsHttpTransaction::Init(uint32_t caps,
|
||||||
// that we write data in the largest chunks possible. this is actually
|
// that we write data in the largest chunks possible. this is actually
|
||||||
// necessary to workaround some common server bugs (see bug 137155).
|
// necessary to workaround some common server bugs (see bug 137155).
|
||||||
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi));
|
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi));
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), stream,
|
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream),
|
||||||
|
stream.forget(),
|
||||||
nsIOService::gDefaultSegmentSize);
|
nsIOService::gDefaultSegmentSize);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
#include "nsEscape.h"
|
#include "nsEscape.h"
|
||||||
#include "nsIDirIndex.h"
|
#include "nsIDirIndex.h"
|
||||||
#include "nsURLHelper.h"
|
#include "nsURLHelper.h"
|
||||||
#include "nsIPlatformCharset.h"
|
|
||||||
#include "nsIPrefService.h"
|
#include "nsIPrefService.h"
|
||||||
#include "nsIPrefBranch.h"
|
#include "nsIPrefBranch.h"
|
||||||
#include "nsIPrefLocalizedString.h"
|
#include "nsIPrefLocalizedString.h"
|
||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
#include "nsITextToSubURI.h"
|
#include "nsITextToSubURI.h"
|
||||||
|
#include "nsNativeCharsetUtils.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "nsIChannel.h"
|
#include "nsIChannel.h"
|
||||||
|
@ -500,13 +500,10 @@ nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
|
||||||
// 1. file URL may be encoded in platform charset for backward compatibility
|
// 1. file URL may be encoded in platform charset for backward compatibility
|
||||||
// 2. query part may not be encoded in UTF-8 (see bug 261929)
|
// 2. query part may not be encoded in UTF-8 (see bug 261929)
|
||||||
// so try the platform's default if this is file url
|
// so try the platform's default if this is file url
|
||||||
if (NS_FAILED(rv) && isSchemeFile) {
|
if (NS_FAILED(rv) && isSchemeFile && !NS_IsNativeUTF8()) {
|
||||||
nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
|
auto encoding = mozilla::dom::FallbackEncoding::FromLocale();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
nsAutoCString charset;
|
nsAutoCString charset;
|
||||||
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset);
|
encoding->Name(charset);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = mTextToSubURI->UnEscapeAndConvert(charset, titleUri, unEscapeSpec);
|
rv = mTextToSubURI->UnEscapeAndConvert(charset, titleUri, unEscapeSpec);
|
||||||
}
|
}
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
|
@ -474,24 +474,25 @@ nsSAXXMLReader::ParseFromString(const nsAString &aStr,
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
nsSAXXMLReader::ParseFromStream(nsIInputStream *aStreamPtr,
|
||||||
const char *aCharset,
|
const char *aCharset,
|
||||||
const char *aContentType)
|
const char *aContentType)
|
||||||
{
|
{
|
||||||
// Don't call this in the middle of an async parse
|
// Don't call this in the middle of an async parse
|
||||||
NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
NS_ENSURE_ARG(aStream);
|
NS_ENSURE_ARG(aStreamPtr);
|
||||||
NS_ENSURE_ARG(aContentType);
|
NS_ENSURE_ARG(aContentType);
|
||||||
|
|
||||||
// Put the nsCOMPtr out here so we hold a ref to the stream as needed
|
// Put the nsCOMPtr out here so we hold a ref to the stream as needed
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
nsCOMPtr<nsIInputStream> stream = aStreamPtr;
|
||||||
if (!NS_InputStreamIsBuffered(aStream)) {
|
if (!NS_InputStreamIsBuffered(stream)) {
|
||||||
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
aStream, 4096);
|
stream.forget(), 4096);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
aStream = bufferedStream;
|
stream = bufferedStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = EnsureBaseURI();
|
rv = EnsureBaseURI();
|
||||||
|
@ -504,7 +505,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
||||||
nsCOMPtr<nsIChannel> parserChannel;
|
nsCOMPtr<nsIChannel> parserChannel;
|
||||||
rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
|
rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
|
||||||
mBaseURI,
|
mBaseURI,
|
||||||
aStream,
|
stream,
|
||||||
nullPrincipal,
|
nullPrincipal,
|
||||||
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
||||||
nsIContentPolicy::TYPE_OTHER,
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
@ -536,7 +537,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
||||||
uint64_t offset = 0;
|
uint64_t offset = 0;
|
||||||
while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
|
||||||
uint64_t available;
|
uint64_t available;
|
||||||
rv = aStream->Available(&available);
|
rv = stream->Available(&available);
|
||||||
if (rv == NS_BASE_STREAM_CLOSED) {
|
if (rv == NS_BASE_STREAM_CLOSED) {
|
||||||
rv = NS_OK;
|
rv = NS_OK;
|
||||||
available = 0;
|
available = 0;
|
||||||
|
@ -552,7 +553,7 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
|
||||||
available = UINT32_MAX;
|
available = UINT32_MAX;
|
||||||
|
|
||||||
rv = mListener->OnDataAvailable(parserChannel, nullptr,
|
rv = mListener->OnDataAvailable(parserChannel, nullptr,
|
||||||
aStream,
|
stream,
|
||||||
offset,
|
offset,
|
||||||
(uint32_t)available);
|
(uint32_t)available);
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
|
|
|
@ -497,7 +497,7 @@ RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
|
||||||
// Wrap the channel's input stream in a buffered stream to ensure that
|
// Wrap the channel's input stream in a buffered stream to ensure that
|
||||||
// ReadSegments is implemented (which OnDataAvailable expects).
|
// ReadSegments is implemented (which OnDataAvailable expects).
|
||||||
nsCOMPtr<nsIInputStream> bufStream;
|
nsCOMPtr<nsIInputStream> bufStream;
|
||||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in,
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in.forget(),
|
||||||
4096 /* buffer size */);
|
4096 /* buffer size */);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
|
|
@ -1001,12 +1001,15 @@ this.BrowserTestUtils = {
|
||||||
* True if it is expected that the tab crashed page will be shown
|
* True if it is expected that the tab crashed page will be shown
|
||||||
* for this browser. If so, the Promise will only resolve once the
|
* for this browser. If so, the Promise will only resolve once the
|
||||||
* tab crash page has loaded.
|
* tab crash page has loaded.
|
||||||
|
* @param (bool) shouldClearMinidumps
|
||||||
|
* True if the minidumps left behind by the crash should be removed.
|
||||||
*
|
*
|
||||||
* @returns (Promise)
|
* @returns (Promise)
|
||||||
* @resolves An Object with key-value pairs representing the data from the
|
* @resolves An Object with key-value pairs representing the data from the
|
||||||
* crash report's extra file (if applicable).
|
* crash report's extra file (if applicable).
|
||||||
*/
|
*/
|
||||||
async crashBrowser(browser, shouldShowTabCrashPage=true) {
|
async crashBrowser(browser, shouldShowTabCrashPage=true,
|
||||||
|
shouldClearMinidumps=true) {
|
||||||
let extra = {};
|
let extra = {};
|
||||||
let KeyValueParser = {};
|
let KeyValueParser = {};
|
||||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||||
|
@ -1107,8 +1110,10 @@ this.BrowserTestUtils = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
if (shouldClearMinidumps) {
|
||||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
removeFile(minidumpDirectory, dumpID + '.dmp');
|
||||||
|
removeFile(minidumpDirectory, dumpID + '.extra');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -638,8 +638,13 @@ TestRunner.testFinished = function(tests) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SpecialPowers.executeAfterFlushingMessageQueue(function() {
|
SpecialPowers.executeAfterFlushingMessageQueue(function() {
|
||||||
cleanUpCrashDumpFiles();
|
SpecialPowers.waitForCrashes(TestRunner._expectingProcessCrash)
|
||||||
SpecialPowers.flushPermissions(function () { SpecialPowers.flushPrefEnv(runNextTest); });
|
.then(() => {
|
||||||
|
cleanUpCrashDumpFiles();
|
||||||
|
SpecialPowers.flushPermissions(function () {
|
||||||
|
SpecialPowers.flushPrefEnv(runNextTest);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -330,10 +330,23 @@ function expectedException(actual, expected) {
|
||||||
* 11. Expected to throw an error:
|
* 11. Expected to throw an error:
|
||||||
* assert.throws(block, Error_opt, message_opt);
|
* assert.throws(block, Error_opt, message_opt);
|
||||||
*
|
*
|
||||||
|
* Example:
|
||||||
|
* ```js
|
||||||
|
* // The following will verify that an error of type TypeError was thrown:
|
||||||
|
* Assert.throws(() => testBody(), TypeError);
|
||||||
|
* // The following will verify that an error was thrown with an error message matching "hello":
|
||||||
|
* Assert.throws(() => testBody(), /hello/);
|
||||||
|
* // The following will verify that any error was thrown and will use "hello" in the test report:
|
||||||
|
* Assert.throws(() => testBody(), "hello");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @param block
|
* @param block
|
||||||
* (function) Function block to evaluate and catch eventual thrown errors
|
* (function) Function block to evaluate and catch eventual thrown errors
|
||||||
* @param expected (optional)
|
* @param expected (optional)
|
||||||
* (mixed) Test reference to evaluate against the thrown result from `block`
|
* (mixed) This parameter can be either a RegExp, a function, or a string. The
|
||||||
|
* function is either the error type's constructor, or it's a method that returns a boolean
|
||||||
|
* that describes the test outcome. When string value is provided, it will be used as if it
|
||||||
|
* was provided as the message parameter.
|
||||||
* @param message (optional)
|
* @param message (optional)
|
||||||
* (string) Short explanation of the expected result
|
* (string) Short explanation of the expected result
|
||||||
*/
|
*/
|
||||||
|
@ -473,4 +486,3 @@ proto.less = function less(lhs, rhs, message) {
|
||||||
proto.lessOrEqual = function lessOrEqual(lhs, rhs, message) {
|
proto.lessOrEqual = function lessOrEqual(lhs, rhs, message) {
|
||||||
compareNumbers.call(this, lhs > rhs, lhs, rhs, message, "<=");
|
compareNumbers.call(this, lhs > rhs, lhs, rhs, message, "<=");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ SpecialPowersObserver.prototype._loadFrameScript = function() {
|
||||||
if (!this._isFrameScriptLoaded) {
|
if (!this._isFrameScriptLoaded) {
|
||||||
// Register for any messages our API needs us to handle
|
// Register for any messages our API needs us to handle
|
||||||
this._messageManager.addMessageListener("SPPrefService", this);
|
this._messageManager.addMessageListener("SPPrefService", this);
|
||||||
|
this._messageManager.addMessageListener("SPProcessCrashManagerWait", this);
|
||||||
this._messageManager.addMessageListener("SPProcessCrashService", this);
|
this._messageManager.addMessageListener("SPProcessCrashService", this);
|
||||||
this._messageManager.addMessageListener("SPPingService", this);
|
this._messageManager.addMessageListener("SPPingService", this);
|
||||||
this._messageManager.addMessageListener("SpecialPowers.Quit", this);
|
this._messageManager.addMessageListener("SpecialPowers.Quit", this);
|
||||||
|
@ -140,6 +141,7 @@ SpecialPowersObserver.prototype.uninit = function() {
|
||||||
|
|
||||||
if (this._isFrameScriptLoaded) {
|
if (this._isFrameScriptLoaded) {
|
||||||
this._messageManager.removeMessageListener("SPPrefService", this);
|
this._messageManager.removeMessageListener("SPPrefService", this);
|
||||||
|
this._messageManager.removeMessageListener("SPProcessCrashManagerWait", this);
|
||||||
this._messageManager.removeMessageListener("SPProcessCrashService", this);
|
this._messageManager.removeMessageListener("SPProcessCrashService", this);
|
||||||
this._messageManager.removeMessageListener("SPPingService", this);
|
this._messageManager.removeMessageListener("SPPingService", this);
|
||||||
this._messageManager.removeMessageListener("SpecialPowers.Quit", this);
|
this._messageManager.removeMessageListener("SpecialPowers.Quit", this);
|
||||||
|
|
|
@ -117,6 +117,10 @@ SpecialPowersObserverAPI.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // ipc:content-shutdown
|
} else { // ipc:content-shutdown
|
||||||
|
if (!aSubject.hasKey("abnormal")) {
|
||||||
|
return; // This is a normal shutdown, ignore it
|
||||||
|
}
|
||||||
|
|
||||||
addDumpIDToMessage("dumpID");
|
addDumpIDToMessage("dumpID");
|
||||||
}
|
}
|
||||||
this._sendAsyncMessage("SPProcessCrashService", message);
|
this._sendAsyncMessage("SPProcessCrashService", message);
|
||||||
|
@ -393,6 +397,17 @@ SpecialPowersObserverAPI.prototype = {
|
||||||
return undefined; // See comment at the beginning of this function.
|
return undefined; // See comment at the beginning of this function.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "SPProcessCrashManagerWait": {
|
||||||
|
let promises = aMessage.json.crashIds.map((crashId) => {
|
||||||
|
return Services.crashmanager.ensureCrashIsPresent(crashId);
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
this._sendReply(aMessage, "SPProcessCrashManagerWait", {});
|
||||||
|
});
|
||||||
|
return undefined; // See comment at the beginning of this function.
|
||||||
|
}
|
||||||
|
|
||||||
case "SPPermissionManager": {
|
case "SPPermissionManager": {
|
||||||
let msg = aMessage.json;
|
let msg = aMessage.json;
|
||||||
let principal = msg.principal;
|
let principal = msg.principal;
|
||||||
|
|
|
@ -49,6 +49,7 @@ function SpecialPowers(window) {
|
||||||
"SpecialPowers.RemoveFiles",
|
"SpecialPowers.RemoveFiles",
|
||||||
"SPPingService",
|
"SPPingService",
|
||||||
"SPLoadExtension",
|
"SPLoadExtension",
|
||||||
|
"SPProcessCrashManagerWait",
|
||||||
"SPStartupExtension",
|
"SPStartupExtension",
|
||||||
"SPUnloadExtension",
|
"SPUnloadExtension",
|
||||||
"SPExtensionMessage"];
|
"SPExtensionMessage"];
|
||||||
|
|
|
@ -670,6 +670,31 @@ SpecialPowersAPI.prototype = {
|
||||||
return bindDOMWindowUtils(aWindow);
|
return bindDOMWindowUtils(aWindow);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
waitForCrashes(aExpectingProcessCrash) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!aExpectingProcessCrash) {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
var crashIds = this._encounteredCrashDumpFiles.filter((filename) => {
|
||||||
|
return ((filename.length === 40) && filename.endsWith(".dmp"));
|
||||||
|
}).map((id) => {
|
||||||
|
return id.slice(0, -4); // Strip the .dmp extension to get the ID
|
||||||
|
});
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
function messageListener(msg) {
|
||||||
|
self._removeMessageListener("SPProcessCrashManagerWait", messageListener);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._addMessageListener("SPProcessCrashManagerWait", messageListener);
|
||||||
|
this._sendAsyncMessage("SPProcessCrashManagerWait", {
|
||||||
|
crashIds
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
removeExpectedCrashDumpFiles(aExpectingProcessCrash) {
|
removeExpectedCrashDumpFiles(aExpectingProcessCrash) {
|
||||||
var success = true;
|
var success = true;
|
||||||
if (aExpectingProcessCrash) {
|
if (aExpectingProcessCrash) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "common/linux/file_id.h"
|
#include "common/linux/file_id.h"
|
||||||
#include "common/memory.h"
|
#include "common/memory_allocator.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|
|
@ -1295,7 +1295,7 @@ FetchAndConvertUnsupportedPayloads::ConvertPayload(int64_t aId,
|
||||||
|
|
||||||
// Decode the input stream to a surface.
|
// Decode the input stream to a surface.
|
||||||
RefPtr<gfx::SourceSurface> surface =
|
RefPtr<gfx::SourceSurface> surface =
|
||||||
image::ImageOps::DecodeToSurface(stream,
|
image::ImageOps::DecodeToSurface(stream.forget(),
|
||||||
aMimeType,
|
aMimeType,
|
||||||
imgIContainer::DECODE_FLAGS_DEFAULT);
|
imgIContainer::DECODE_FLAGS_DEFAULT);
|
||||||
NS_ENSURE_STATE(surface);
|
NS_ENSURE_STATE(surface);
|
||||||
|
|
|
@ -339,7 +339,9 @@ HashStore::Open()
|
||||||
}
|
}
|
||||||
|
|
||||||
mFileSize = static_cast<uint32_t>(fileSize);
|
mFileSize = static_cast<uint32_t>(fileSize);
|
||||||
mInputStream = NS_BufferInputStream(origStream, mFileSize);
|
rv = NS_NewBufferedInputStream(getter_AddRefs(mInputStream),
|
||||||
|
origStream.forget(), mFileSize);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = ReadHeader();
|
rv = ReadHeader();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -239,7 +239,10 @@ VariableLengthPrefixSet::LoadFromFile(nsIFile* aFile)
|
||||||
MAX_BUFFER_SIZE);
|
MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
// Convert to buffered stream
|
// Convert to buffered stream
|
||||||
nsCOMPtr<nsIInputStream> in = NS_BufferInputStream(localInFile, bufferSize);
|
nsCOMPtr<nsIInputStream> in;
|
||||||
|
rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(),
|
||||||
|
bufferSize);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = mFixedPrefixSet->LoadPrefixes(in);
|
rv = mFixedPrefixSet->LoadPrefixes(in);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -352,7 +352,10 @@ nsUrlClassifierPrefixSet::LoadFromFile(nsIFile* aFile)
|
||||||
MAX_BUFFER_SIZE);
|
MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
// Convert to buffered stream
|
// Convert to buffered stream
|
||||||
nsCOMPtr<nsIInputStream> in = NS_BufferInputStream(localInFile, bufferSize);
|
nsCOMPtr<nsIInputStream> in;
|
||||||
|
rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(),
|
||||||
|
bufferSize);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = LoadPrefixes(in);
|
rv = LoadPrefixes(in);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
|
|
||||||
#include "linux/dump_writer_common/raw_context_cpu.h"
|
#include "linux/dump_writer_common/raw_context_cpu.h"
|
||||||
#include "common/memory.h"
|
#include "common/memory_allocator.h"
|
||||||
#include "google_breakpad/common/minidump_format.h"
|
#include "google_breakpad/common/minidump_format.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
|
|
||||||
#include "linux/dump_writer_common/raw_context_cpu.h"
|
#include "linux/dump_writer_common/raw_context_cpu.h"
|
||||||
#include "common/memory.h"
|
#include "common/memory_allocator.h"
|
||||||
#include "google_breakpad/common/minidump_format.h"
|
#include "google_breakpad/common/minidump_format.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
|
|
||||||
#include "common/basictypes.h"
|
#include "common/basictypes.h"
|
||||||
#include "common/linux/linux_libc_support.h"
|
#include "common/linux/linux_libc_support.h"
|
||||||
#include "common/memory.h"
|
#include "common/memory_allocator.h"
|
||||||
#include "linux/log/log.h"
|
#include "linux/log/log.h"
|
||||||
#include "linux/microdump_writer/microdump_writer.h"
|
#include "linux/microdump_writer/microdump_writer.h"
|
||||||
#include "linux/minidump_writer/linux_dumper.h"
|
#include "linux/minidump_writer/linux_dumper.h"
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче