зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c. a=merge
This commit is contained in:
Коммит
287f684182
|
@ -248,16 +248,6 @@ toolbar[customizing] > .overflow-button {
|
|||
-moz-appearance: -moz-mac-fullscreen-button;
|
||||
}
|
||||
|
||||
/* Because these buttons don't move, they should always be aligned the same,
|
||||
* left and right were deprecated, so we have to do work to get it to mean that: */
|
||||
#titlebar-buttonbox-container:-moz-locale-dir(ltr) {
|
||||
-moz-box-align: start;
|
||||
}
|
||||
|
||||
#titlebar-buttonbox-container:-moz-locale-dir(rtl) {
|
||||
-moz-box-align: end;
|
||||
}
|
||||
|
||||
/* Fullscreen and caption buttons don't move with RTL on OS X so override the automatic ordering. */
|
||||
#titlebar-secondary-buttonbox:-moz-locale-dir(ltr),
|
||||
#titlebar-buttonbox-container:-moz-locale-dir(rtl),
|
||||
|
|
|
@ -388,7 +388,8 @@ function GetCookiesResource(aProfileFolder) {
|
|||
row.getResultByName("secure"),
|
||||
row.getResultByName("httponly"),
|
||||
false,
|
||||
parseInt(expiresUtc));
|
||||
parseInt(expiresUtc),
|
||||
{});
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
|
|
@ -646,7 +646,8 @@ Cookies.prototype = {
|
|||
Number(flags) & 0x1, // secure
|
||||
false, // httpOnly
|
||||
false, // session
|
||||
expireTime);
|
||||
expireTime,
|
||||
{});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ add_task(function* () {
|
|||
"Migrated the expected number of encrypted cookies");
|
||||
|
||||
// Now check the cookie details.
|
||||
let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host);
|
||||
let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host, {});
|
||||
Assert.ok(enumerator.hasMoreElements(), "Cookies available");
|
||||
let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ add_task(function* () {
|
|||
"Migrated the expected number of cookies");
|
||||
|
||||
// Now check the cookie details.
|
||||
let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host);
|
||||
let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host, {});
|
||||
Assert.ok(enumerator.hasMoreElements());
|
||||
let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ var SessionCookiesInternal = {
|
|||
if (!Services.cookies.cookieExists(cookieObj)) {
|
||||
Services.cookies.add(cookie.host, cookie.path || "", cookie.name || "",
|
||||
cookie.value, !!cookie.secure, !!cookie.httponly,
|
||||
/* isSession = */ true, expiry);
|
||||
/* isSession = */ true, expiry, cookie.originAttributes || {});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -417,6 +417,10 @@ var CookieStore = {
|
|||
jscookie.expiry = cookie.expiry;
|
||||
}
|
||||
|
||||
if (cookie.originAttributes) {
|
||||
jscookie.originAttributes = cookie.originAttributes;
|
||||
}
|
||||
|
||||
this._ensureMap(cookie).set(cookie.name, jscookie);
|
||||
},
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ skip-if = buildapp == 'mulet'
|
|||
skip-if = e10s # Bug 1271024
|
||||
[browser_replace_load.js]
|
||||
[browser_restore_redirect.js]
|
||||
[browser_restore_cookies_noOriginAttributes.js]
|
||||
[browser_scrollPositions.js]
|
||||
[browser_scrollPositionsReaderMode.js]
|
||||
[browser_sessionHistory.js]
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Bug 1267910 - The regression test case for session cookies.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_HOST = "www.example.com";
|
||||
const COOKIE =
|
||||
{
|
||||
name: "test1",
|
||||
value: "yes1",
|
||||
path: "/browser/browser/components/sessionstore/test/"
|
||||
};
|
||||
const SESSION_DATA = `
|
||||
{
|
||||
"version": ["sessionrestore", 1],
|
||||
"windows": [{
|
||||
"tabs": [{
|
||||
"entries": [],
|
||||
"lastAccessed": 1463893009797,
|
||||
"hidden": false,
|
||||
"attributes": {},
|
||||
"image": null
|
||||
}, {
|
||||
"entries": [{
|
||||
"url": "http://www.example.com/browser/browser/components/sessionstore/test/browser_1267910_page.html",
|
||||
\"charset": "UTF-8",
|
||||
"ID": 0,
|
||||
"docshellID": 2,
|
||||
"originalURI": "http://www.example.com/browser/browser/components/sessionstore/test/browser_1267910_page.html",
|
||||
\"docIdentifier": 0,
|
||||
"persist": true
|
||||
}],
|
||||
"lastAccessed": 1463893009321,
|
||||
"hidden": false,
|
||||
"attributes": {},
|
||||
"userContextId": 0,
|
||||
"index": 1,
|
||||
"image": "http://www.example.com/favicon.ico"
|
||||
}],
|
||||
"selected": 1,
|
||||
"_closedTabs": [],
|
||||
"busy": false,
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"screenX": 4,
|
||||
"screenY": 23,
|
||||
"sizemode": "normal",
|
||||
"cookies": [{
|
||||
"host": "www.example.com",
|
||||
"value": "yes1",
|
||||
"path": "/browser/browser/components/sessionstore/test/",
|
||||
"name": "test1"
|
||||
}]
|
||||
}],
|
||||
"selectedWindow": 1,
|
||||
"_closedWindows": [],
|
||||
"session": {
|
||||
"lastUpdate": 1463893009801,
|
||||
"startTime": 1463893007134,
|
||||
"recentCrashes": 0
|
||||
},
|
||||
"global": {}
|
||||
}`;
|
||||
const SESSION_DATA_OA = `
|
||||
{
|
||||
"version": ["sessionrestore", 1],
|
||||
"windows": [{
|
||||
"tabs": [{
|
||||
"entries": [],
|
||||
"lastAccessed": 1463893009797,
|
||||
"hidden": false,
|
||||
"attributes": {},
|
||||
"image": null
|
||||
}, {
|
||||
"entries": [{
|
||||
"url": "http://www.example.com/browser/browser/components/sessionstore/test/browser_1267910_page.html",
|
||||
\"charset": "UTF-8",
|
||||
"ID": 0,
|
||||
"docshellID": 2,
|
||||
"originalURI": "http://www.example.com/browser/browser/components/sessionstore/test/browser_1267910_page.html",
|
||||
\"docIdentifier": 0,
|
||||
"persist": true
|
||||
}],
|
||||
"lastAccessed": 1463893009321,
|
||||
"hidden": false,
|
||||
"attributes": {},
|
||||
"userContextId": 0,
|
||||
"index": 1,
|
||||
"image": "http://www.example.com/favicon.ico"
|
||||
}],
|
||||
"selected": 1,
|
||||
"_closedTabs": [],
|
||||
"busy": false,
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"screenX": 4,
|
||||
"screenY": 23,
|
||||
"sizemode": "normal",
|
||||
"cookies": [{
|
||||
"host": "www.example.com",
|
||||
"value": "yes1",
|
||||
"path": "/browser/browser/components/sessionstore/test/",
|
||||
"name": "test1",
|
||||
"originAttributes": {
|
||||
"addonId": "",
|
||||
"appId": 0,
|
||||
"inIsolatedMozBrowser": false,
|
||||
"signedPkg": "",
|
||||
"userContextId": 0
|
||||
}
|
||||
}]
|
||||
}],
|
||||
"selectedWindow": 1,
|
||||
"_closedWindows": [],
|
||||
"session": {
|
||||
"lastUpdate": 1463893009801,
|
||||
"startTime": 1463893007134,
|
||||
"recentCrashes": 0
|
||||
},
|
||||
"global": {}
|
||||
}`;
|
||||
|
||||
add_task(function* run_test() {
|
||||
// Wait until initialization is complete.
|
||||
yield SessionStore.promiseInitialized;
|
||||
|
||||
// Clear cookies.
|
||||
Services.cookies.removeAll();
|
||||
|
||||
// Open a new window.
|
||||
let win = yield promiseNewWindowLoaded();
|
||||
|
||||
// Restore window with session cookies that have no originAttributes.
|
||||
ss.setWindowState(win, SESSION_DATA, true);
|
||||
|
||||
let enumerator = Services.cookies.getCookiesFromHost(TEST_HOST, {});
|
||||
let cookie;
|
||||
let cookieCount = 0;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
|
||||
cookieCount++;
|
||||
}
|
||||
|
||||
// Check that the cookie is restored successfully.
|
||||
is(cookieCount, 1, "expected one cookie");
|
||||
is(cookie.name, COOKIE.name, "cookie name successfully restored");
|
||||
is(cookie.value, COOKIE.value, "cookie value successfully restored");
|
||||
is(cookie.path, COOKIE.path, "cookie path successfully restored");
|
||||
|
||||
// Clear cookies.
|
||||
Services.cookies.removeAll();
|
||||
|
||||
// Restore window with session cookies that have originAttributes within.
|
||||
ss.setWindowState(win, SESSION_DATA_OA, true);
|
||||
|
||||
enumerator = Services.cookies.getCookiesFromHost(TEST_HOST, {});
|
||||
cookieCount = 0;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
|
||||
cookieCount++;
|
||||
}
|
||||
|
||||
// Check that the cookie is restored successfully.
|
||||
is(cookieCount, 1, "expected one cookie");
|
||||
is(cookie.name, COOKIE.name, "cookie name successfully restored");
|
||||
is(cookie.value, COOKIE.value, "cookie value successfully restored");
|
||||
is(cookie.path, COOKIE.path, "cookie path successfully restored");
|
||||
|
||||
// Close our window.
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
});
|
|
@ -161,7 +161,7 @@ var pktApi = (function() {
|
|||
function getCookiesFromPocket() {
|
||||
|
||||
var cookieManager = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
|
||||
var pocketCookies = cookieManager.getCookiesFromHost(pocketSiteHost);
|
||||
var pocketCookies = cookieManager.getCookiesFromHost(pocketSiteHost, {});
|
||||
var cookies = {};
|
||||
while (pocketCookies.hasMoreElements()) {
|
||||
var cookie = pocketCookies.getNext().QueryInterface(Ci.nsICookie2);
|
||||
|
|
|
@ -66,13 +66,17 @@ p {
|
|||
}
|
||||
|
||||
.list-row > ul > li {
|
||||
float: inline-start;
|
||||
float: left;
|
||||
width: 220px;
|
||||
line-height: 1.5em;
|
||||
margin-inline-start: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.list-row > ul > li:dir(rtl) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.title {
|
||||
background-image: url("chrome://browser/skin/privatebrowsing/private-browsing.svg");
|
||||
background-size: 64px;
|
||||
|
@ -161,7 +165,7 @@ a.button {
|
|||
}
|
||||
|
||||
.toggle + .toggle-btn::before {
|
||||
float: inline-start;
|
||||
float: left;
|
||||
left: 9px;
|
||||
visibility: hidden;
|
||||
background-size: 16px;
|
||||
|
@ -177,6 +181,7 @@ a.button {
|
|||
}
|
||||
|
||||
.toggle + .toggle-btn:dir(rtl)::before {
|
||||
float: right;
|
||||
left: auto;
|
||||
right: 9px;
|
||||
}
|
||||
|
|
|
@ -465,8 +465,10 @@ StorageActors.createActor({
|
|||
|
||||
populateStoresForHost(host) {
|
||||
this.hostVsStores.set(host, new Map());
|
||||
let doc = this.storageActor.document;
|
||||
|
||||
let cookies = this.getCookiesFromHost(host);
|
||||
let cookies = this.getCookiesFromHost(host, doc.nodePrincipal
|
||||
.originAttributes);
|
||||
|
||||
for (let cookie of cookies) {
|
||||
if (this.isCookieAtHost(cookie, host)) {
|
||||
|
@ -570,15 +572,22 @@ StorageActors.createActor({
|
|||
* See editCookie() for format details.
|
||||
*/
|
||||
editItem: Task.async(function* (data) {
|
||||
let doc = this.storageActor.document;
|
||||
data.originAttributes = doc.nodePrincipal
|
||||
.originAttributes;
|
||||
this.editCookie(data);
|
||||
}),
|
||||
|
||||
removeItem: Task.async(function* (host, name) {
|
||||
this.removeCookie(host, name);
|
||||
let doc = this.storageActor.document;
|
||||
this.removeCookie(host, name, doc.nodePrincipal
|
||||
.originAttributes);
|
||||
}),
|
||||
|
||||
removeAll: Task.async(function* (host, domain) {
|
||||
this.removeAllCookies(host, domain);
|
||||
let doc = this.storageActor.document;
|
||||
this.removeAllCookies(host, domain, doc.nodePrincipal
|
||||
.originAttributes);
|
||||
}),
|
||||
|
||||
maybeSetupChildProcess() {
|
||||
|
@ -648,13 +657,13 @@ StorageActors.createActor({
|
|||
});
|
||||
|
||||
var cookieHelpers = {
|
||||
getCookiesFromHost(host) {
|
||||
getCookiesFromHost(host, originAttributes) {
|
||||
// Local files have no host.
|
||||
if (host.startsWith("file:///")) {
|
||||
host = "";
|
||||
}
|
||||
|
||||
let cookies = Services.cookies.getCookiesFromHost(host);
|
||||
let cookies = Services.cookies.getCookiesFromHost(host, originAttributes);
|
||||
let store = [];
|
||||
|
||||
while (cookies.hasMoreElements()) {
|
||||
|
@ -698,7 +707,7 @@ var cookieHelpers = {
|
|||
let origPath = field === "path" ? oldValue : data.items.path;
|
||||
let cookie = null;
|
||||
|
||||
let enumerator = Services.cookies.getCookiesFromHost(origHost);
|
||||
let enumerator = Services.cookies.getCookiesFromHost(origHost, data.originAttributes || {});
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let nsiCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
if (nsiCookie.name === origName && nsiCookie.host === origHost) {
|
||||
|
@ -769,7 +778,8 @@ var cookieHelpers = {
|
|||
cookie.isSecure,
|
||||
cookie.isHttpOnly,
|
||||
cookie.isSession,
|
||||
cookie.isSession ? MAX_COOKIE_EXPIRY : cookie.expires
|
||||
cookie.isSession ? MAX_COOKIE_EXPIRY : cookie.expires,
|
||||
cookie.originAttributes
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -784,7 +794,7 @@ var cookieHelpers = {
|
|||
return cookieHost == host;
|
||||
}
|
||||
|
||||
let enumerator = Services.cookies.getCookiesFromHost(host);
|
||||
let enumerator = Services.cookies.getCookiesFromHost(host, opts.originAttributes || {});
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
if (hostMatches(cookie.host, host) &&
|
||||
|
@ -801,14 +811,14 @@ var cookieHelpers = {
|
|||
}
|
||||
},
|
||||
|
||||
removeCookie(host, name) {
|
||||
removeCookie(host, name, originAttributes) {
|
||||
if (name !== undefined) {
|
||||
this._removeCookies(host, { name });
|
||||
this._removeCookies(host, { name, originAttributes });
|
||||
}
|
||||
},
|
||||
|
||||
removeAllCookies(host, domain) {
|
||||
this._removeCookies(host, { domain });
|
||||
removeAllCookies(host, domain, originAttributes) {
|
||||
this._removeCookies(host, { domain, originAttributes });
|
||||
},
|
||||
|
||||
addCookieObservers() {
|
||||
|
@ -861,7 +871,8 @@ var cookieHelpers = {
|
|||
switch (msg.json.method) {
|
||||
case "getCookiesFromHost": {
|
||||
let host = msg.data.args[0];
|
||||
let cookies = cookieHelpers.getCookiesFromHost(host);
|
||||
let originAttributes = msg.data.args[1];
|
||||
let cookies = cookieHelpers.getCookiesFromHost(host, originAttributes);
|
||||
return JSON.stringify(cookies);
|
||||
}
|
||||
case "addCookieObservers": {
|
||||
|
@ -877,12 +888,14 @@ var cookieHelpers = {
|
|||
case "removeCookie": {
|
||||
let host = msg.data.args[0];
|
||||
let name = msg.data.args[1];
|
||||
return cookieHelpers.removeCookie(host, name);
|
||||
let originAttributes = msg.data.args[2];
|
||||
return cookieHelpers.removeCookie(host, name, originAttributes);
|
||||
}
|
||||
case "removeAllCookies": {
|
||||
let host = msg.data.args[0];
|
||||
let domain = msg.data.args[1];
|
||||
return cookieHelpers.removeAllCookies(host, domain);
|
||||
let originAttributes = msg.data.args[2];
|
||||
return cookieHelpers.removeAllCookies(host, domain, originAttributes);
|
||||
}
|
||||
default:
|
||||
console.error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD", msg.json.method);
|
||||
|
|
|
@ -85,8 +85,11 @@ exports.items = [
|
|||
"see bug 1221488");
|
||||
}
|
||||
let host = new URL(context.environment.target.url).host;
|
||||
let contentWindow = context.environment.window;
|
||||
host = sanitizeHost(host);
|
||||
let enm = cookieMgr.getCookiesFromHost(host);
|
||||
let enm = cookieMgr.getCookiesFromHost(host, contentWindow.document.
|
||||
nodePrincipal.
|
||||
originAttributes);
|
||||
|
||||
let cookies = [];
|
||||
while (enm.hasMoreElements()) {
|
||||
|
@ -127,8 +130,11 @@ exports.items = [
|
|||
"see bug 1221488");
|
||||
}
|
||||
let host = new URL(context.environment.target.url).host;
|
||||
let contentWindow = context.environment.window;
|
||||
host = sanitizeHost(host);
|
||||
let enm = cookieMgr.getCookiesFromHost(host);
|
||||
let enm = cookieMgr.getCookiesFromHost(host, contentWindow.document.
|
||||
nodePrincipal.
|
||||
originAttributes);
|
||||
|
||||
while (enm.hasMoreElements()) {
|
||||
let cookie = enm.getNext().QueryInterface(Ci.nsICookie);
|
||||
|
@ -270,7 +276,7 @@ exports.items = [
|
|||
let host = new URL(context.environment.target.url).host;
|
||||
host = sanitizeHost(host);
|
||||
let time = Date.parse(args.expires) / 1000;
|
||||
|
||||
let contentWindow = context.environment.window;
|
||||
cookieMgr.add(args.domain ? "." + args.domain : host,
|
||||
args.path ? args.path : "/",
|
||||
args.name,
|
||||
|
@ -278,7 +284,10 @@ exports.items = [
|
|||
args.secure,
|
||||
args.httpOnly,
|
||||
args.session,
|
||||
time);
|
||||
time,
|
||||
contentWindow.document.
|
||||
nodePrincipal.
|
||||
originAttributes);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -30,8 +30,8 @@ StepTiming(uint32_t aSteps,
|
|||
nsTimingFunction::Type aType)
|
||||
{
|
||||
MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range");
|
||||
MOZ_ASSERT(aType != nsTimingFunction::Type::StepStart ||
|
||||
aType != nsTimingFunction::Type::StepEnd, "invalid type");
|
||||
MOZ_ASSERT(aType == nsTimingFunction::Type::StepStart ||
|
||||
aType == nsTimingFunction::Type::StepEnd, "invalid type");
|
||||
|
||||
if (aPortion == 1.0) {
|
||||
return 1.0;
|
||||
|
|
|
@ -319,6 +319,11 @@ public:
|
|||
nsIntRegion fillPaintNeededRegion;
|
||||
nsIntRegion strokePaintNeededRegion;
|
||||
|
||||
if (aCtx->CurrentState().updateFilterOnWriteOnly) {
|
||||
aCtx->UpdateFilter();
|
||||
aCtx->CurrentState().updateFilterOnWriteOnly = false;
|
||||
}
|
||||
|
||||
FilterSupport::ComputeSourceNeededRegions(
|
||||
aCtx->CurrentState().filter, mPostFilterBounds,
|
||||
sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion);
|
||||
|
@ -405,6 +410,12 @@ public:
|
|||
mCtx->CurrentState().filterAdditionalImages,
|
||||
mPostFilterBounds.TopLeft() - mOffset,
|
||||
DrawOptions(1.0f, mCompositionOp));
|
||||
|
||||
const gfx::FilterDescription& filter = mCtx->CurrentState().filter;
|
||||
MOZ_ASSERT(!filter.mPrimitives.IsEmpty());
|
||||
if (filter.mPrimitives.LastElement().IsTainted() && mCtx->mCanvasElement) {
|
||||
mCtx->mCanvasElement->SetWriteOnly();
|
||||
}
|
||||
}
|
||||
|
||||
DrawTarget* DT()
|
||||
|
@ -2468,6 +2479,9 @@ CanvasRenderingContext2D::SetFilter(const nsAString& aFilter, ErrorResult& aErro
|
|||
UpdateFilter();
|
||||
}
|
||||
}
|
||||
if (mCanvasElement && !mCanvasElement->IsWriteOnly()) {
|
||||
CurrentState().updateFilterOnWriteOnly = true;
|
||||
}
|
||||
}
|
||||
|
||||
class CanvasUserSpaceMetrics : public UserSpaceMetricsWithSize
|
||||
|
|
|
@ -912,6 +912,7 @@ protected:
|
|||
lineCap(mozilla::gfx::CapStyle::BUTT),
|
||||
lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
|
||||
filterString(MOZ_UTF16("none")),
|
||||
updateFilterOnWriteOnly(false),
|
||||
imageSmoothingEnabled(true),
|
||||
fontExplicitLanguage(false)
|
||||
{ }
|
||||
|
@ -944,6 +945,7 @@ protected:
|
|||
filterChainObserver(aOther.filterChainObserver),
|
||||
filter(aOther.filter),
|
||||
filterAdditionalImages(aOther.filterAdditionalImages),
|
||||
updateFilterOnWriteOnly(aOther.updateFilterOnWriteOnly),
|
||||
imageSmoothingEnabled(aOther.imageSmoothingEnabled),
|
||||
fontExplicitLanguage(aOther.fontExplicitLanguage)
|
||||
{ }
|
||||
|
@ -1021,6 +1023,7 @@ protected:
|
|||
RefPtr<nsSVGFilterChainObserver> filterChainObserver;
|
||||
mozilla::gfx::FilterDescription filter;
|
||||
nsTArray<RefPtr<mozilla::gfx::SourceSurface>> filterAdditionalImages;
|
||||
bool updateFilterOnWriteOnly;
|
||||
|
||||
bool imageSmoothingEnabled;
|
||||
bool fontExplicitLanguage;
|
||||
|
|
|
@ -256,6 +256,14 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
|
|||
[test_createPattern_broken.html]
|
||||
[test_setlinedash.html]
|
||||
[test_filter.html]
|
||||
skip-if = (e10s && debug && os == 'win')
|
||||
[test_filter_tainted.html]
|
||||
skip-if = (e10s && debug && os == 'win')
|
||||
[test_filter_tainted_source_graphics.html]
|
||||
skip-if = (e10s && debug && os == 'win')
|
||||
[test_filter_tainted_displacement_map.html]
|
||||
skip-if = (e10s && debug && os == 'win')
|
||||
[test_filter_tainted_displacement_map_source_graphics.html]
|
||||
[test_offscreencanvas_toblob.html]
|
||||
subsuite = gpu
|
||||
tags = offscreencanvas
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE HTML>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<body onload="runTest()">
|
||||
<svg style="display: block; width: 0; height: 0">
|
||||
<defs>
|
||||
<filter id="tainted">
|
||||
<feImage xlink:href="http://example.com/tests/dom/canvas/test/crossorigin/image.png" />
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<script>
|
||||
|
||||
function runTest() {
|
||||
|
||||
SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.filter = 'url(#tainted)';
|
||||
ctx.rect(0, 0, 16, 16);
|
||||
ctx.fill();
|
||||
|
||||
var expected_error = 'SecurityError';
|
||||
|
||||
var data;
|
||||
try {
|
||||
data = ctx.getImageData(0, 0, 16, 16);
|
||||
actual_error = "";
|
||||
} catch (e) {
|
||||
actual_error = e.name;
|
||||
}
|
||||
|
||||
is(actual_error, expected_error, 'Canvas should have been tainted and throw a SecurityError');
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE HTML>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<body onload="runTest()" style="margin: 0; padding: 0">
|
||||
<svg style="display: block; width: 0; height: 0">
|
||||
<defs>
|
||||
<filter id="tainted">
|
||||
<feImage xlink:href="http://example.com/tests/dom/canvas/test/image_red-16x16.png"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="c" width="16" height="16"></canvas>
|
||||
<script>
|
||||
|
||||
function isPixel(ctx, x,y, r,g,b,a, pos, color, d) {
|
||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||
var pr = pixel.data[0],
|
||||
pg = pixel.data[1],
|
||||
pb = pixel.data[2],
|
||||
pa = pixel.data[3];
|
||||
ok(r - d <= pr && pr <= r + d &&
|
||||
g - d <= pg && pg <= g + d &&
|
||||
b - d <= pb && pb <= b + d &&
|
||||
a - d <= pa && pa <= a + d,
|
||||
'pixel ' + pos + ' is ' + pr + ',' + pg + ',' + pb + ',' + pa + '; expected ' + color + ' +/- ' + d);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
|
||||
|
||||
var canvas = document.getElementById('c');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.filter = 'url(#tainted)';
|
||||
ctx.rect(0, 0, 16, 16);
|
||||
ctx.fill();
|
||||
|
||||
var canvas2 = document.createElement('canvas');
|
||||
var ctx2 = SpecialPowers.wrap(canvas2.getContext('2d'));
|
||||
ctx2.drawWindow(window, 0, 0, 16, 16, 'rgb(255,255,255)', 0);
|
||||
isPixel(ctx2, 8,8, 255,0,0,255, '8,8', "255,0,0,255", 5);
|
||||
|
||||
var expected_error = 'SecurityError';
|
||||
var data;
|
||||
try {
|
||||
data = ctx.getImageData(0, 0, 16, 16);
|
||||
actual_error = "";
|
||||
} catch (e) {
|
||||
actual_error = e.name;
|
||||
}
|
||||
is(actual_error, expected_error, 'canvas should have been tainted and throw a SecurityError');
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE HTML>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<body onload="runTest()" style="margin: 0; padding: 0">
|
||||
<svg style="display: block; width: 0; height: 0">
|
||||
<defs>
|
||||
<filter id="tainted">
|
||||
<feImage xlink:href='image_red-16x16.png' result='img'/>
|
||||
<feImage xlink:href='http://example.com/tests/dom/canvas/test/image_green-16x16.png' result='map'/>
|
||||
<feDisplacementMap in="img" in2="map" scale="20"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="c" width="16" height="16"></canvas>
|
||||
<script>
|
||||
|
||||
function isPixel(ctx, x,y, r,g,b,a, pos, color, d) {
|
||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||
var pr = pixel.data[0],
|
||||
pg = pixel.data[1],
|
||||
pb = pixel.data[2],
|
||||
pa = pixel.data[3];
|
||||
ok(r - d <= pr && pr <= r + d &&
|
||||
g - d <= pg && pg <= g + d &&
|
||||
b - d <= pb && pb <= b + d &&
|
||||
a - d <= pa && pa <= a + d,
|
||||
'pixel ' + pos + ' is ' + pr + ',' + pg + ',' + pb + ',' + pa + '; expected ' + color + ' +/- ' + d);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
|
||||
|
||||
var canvas = document.getElementById('c');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.filter = 'url(#tainted)';
|
||||
ctx.rect(0, 0, 16, 16);
|
||||
ctx.fill();
|
||||
|
||||
var canvas2 = document.createElement('canvas');
|
||||
var ctx2 = SpecialPowers.wrap(canvas2.getContext('2d'));
|
||||
ctx2.drawWindow(window, 0, 0, 16, 16, 'rgb(255,255,255)', 0);
|
||||
isPixel(ctx2, 8,8, 255,0,0,255, '8,8', "255,0,0,255", 5);
|
||||
|
||||
var expected_error = 'SecurityError';
|
||||
var data;
|
||||
try {
|
||||
data = ctx.getImageData(0, 0, 16, 16);
|
||||
actual_error = "";
|
||||
} catch (e) {
|
||||
actual_error = e.name;
|
||||
}
|
||||
is(actual_error, expected_error, 'canvas should have been tainted and throw a SecurityError');
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE HTML>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<body onload="runTest()" style="margin: 0; padding: 0">
|
||||
<svg style="display: block; width: 0; height: 0">
|
||||
<defs>
|
||||
<filter id="tainted1">
|
||||
<feImage xlink:href='image_red-16x16.png' result='img'/>
|
||||
<feDisplacementMap in="img" in2="SourceGraphic" scale="20"/>
|
||||
</filter>
|
||||
<filter id="tainted2">
|
||||
<feImage xlink:href='http://example.com/tests/dom/canvas/test/image_red-16x16.png' result='img'/>
|
||||
<feDisplacementMap in="SourceGraphic" in2="img" scale="20"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="c" width="16" height="16"></canvas>
|
||||
<img id="i" src="http://example.com/tests/dom/canvas/test/image_green-16x16.png"/>
|
||||
<script>
|
||||
|
||||
function isPixel(ctx, x,y, r,g,b,a, pos, color, d) {
|
||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||
var pr = pixel.data[0],
|
||||
pg = pixel.data[1],
|
||||
pb = pixel.data[2],
|
||||
pa = pixel.data[3];
|
||||
ok(r - d <= pr && pr <= r + d &&
|
||||
g - d <= pg && pg <= g + d &&
|
||||
b - d <= pb && pb <= b + d &&
|
||||
a - d <= pa && pa <= a + d,
|
||||
'pixel ' + pos + ' is ' + pr + ',' + pg + ',' + pb + ',' + pa + '; expected ' + color + ' +/- ' + d);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
|
||||
|
||||
var canvas = document.getElementById('c');
|
||||
var ctx = canvas.getContext('2d');
|
||||
var img = document.getElementById('i');
|
||||
ctx.filter = 'url(#tainted1)';
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
var canvas2 = document.createElement('canvas');
|
||||
var ctx2 = SpecialPowers.wrap(canvas2.getContext('2d'));
|
||||
ctx2.drawWindow(window, 0, 0, 16, 16, 'rgb(255, 255, 255)', 0);
|
||||
isPixel(ctx2, 8,8, 255,0,0,255, '8,8', "255,0,0,255", 5);
|
||||
|
||||
ctx.filter = 'url(#tainted2)';
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
ctx2.drawWindow(window, 0, 0, 16, 16, 'rgb(255, 255, 255)', 0);
|
||||
isPixel(ctx2, 8,8, 0,255,0,255, '8,8', "0,255,0,255", 5);
|
||||
|
||||
var expected_error = 'SecurityError';
|
||||
var data;
|
||||
try {
|
||||
data = ctx.getImageData(0, 0, 16, 16);
|
||||
actual_error = "";
|
||||
} catch (e) {
|
||||
actual_error = e.name;
|
||||
}
|
||||
is(actual_error, expected_error, 'canvas should have been tainted and throw a SecurityError');
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE HTML>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<body onload="runTest()" style="margin: 0; padding: 0">
|
||||
<svg style="display: block; width: 0; height: 0">
|
||||
<defs>
|
||||
<filter id="tainted">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0
|
||||
1 1 1 1 0
|
||||
0 0 0 0 0
|
||||
0 0 0 1 0"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="c" width="16" height="16"></canvas>
|
||||
<img id="i" src="http://example.com/tests/dom/canvas/test/image_red-16x16.png"/>
|
||||
<script>
|
||||
|
||||
function isPixel(ctx, x,y, r,g,b,a, pos, color, d) {
|
||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||
var pr = pixel.data[0],
|
||||
pg = pixel.data[1],
|
||||
pb = pixel.data[2],
|
||||
pa = pixel.data[3];
|
||||
ok(r - d <= pr && pr <= r + d &&
|
||||
g - d <= pg && pg <= g + d &&
|
||||
b - d <= pb && pb <= b + d &&
|
||||
a - d <= pa && pa <= a + d,
|
||||
'pixel ' + pos + ' is ' + pr + ',' + pg + ',' + pb + ',' + pa + '; expected ' + color + ' +/- ' + d);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
|
||||
|
||||
var canvas = document.getElementById('c');
|
||||
var ctx = canvas.getContext('2d');
|
||||
var img = document.getElementById('i');
|
||||
ctx.filter = 'url(#tainted)';
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
var canvas2 = document.createElement('canvas');
|
||||
var ctx2 = SpecialPowers.wrap(canvas2.getContext('2d'));
|
||||
ctx2.drawWindow(window, 0, 0, 16, 16, 'rgb(255,255,255)', 0);
|
||||
isPixel(ctx2, 8,8, 0,255,0,255, '8,8', "0,255,0,255", 5);
|
||||
|
||||
var expected_error = 'SecurityError';
|
||||
var data;
|
||||
try {
|
||||
data = ctx.getImageData(0, 0, 16, 16);
|
||||
actual_error = "";
|
||||
} catch (e) {
|
||||
actual_error = e.name;
|
||||
}
|
||||
is(actual_error, expected_error, 'canvas should have been tainted and throw a SecurityError');
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
|
@ -146,11 +146,10 @@ this.ManifestProcessor = { // jshint ignore:line
|
|||
trim: true
|
||||
};
|
||||
const value = extractor.extractValue(spec);
|
||||
if (this.orientationTypes.has(value)) {
|
||||
return value;
|
||||
if (value && typeof value === "string" && this.orientationTypes.has(value.toLowerCase())) {
|
||||
return value.toLowerCase();
|
||||
}
|
||||
// The spec special-cases orientation to return the empty string.
|
||||
return '';
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function processDisplayMember() {
|
||||
|
@ -162,8 +161,8 @@ this.ManifestProcessor = { // jshint ignore:line
|
|||
trim: true
|
||||
};
|
||||
const value = extractor.extractValue(spec);
|
||||
if (displayModes.has(value)) {
|
||||
return value;
|
||||
if (value && typeof value === "string" && displayModes.has(value.toLowerCase())) {
|
||||
return value.toLowerCase();
|
||||
}
|
||||
return this.defaultDisplayMode;
|
||||
}
|
||||
|
|
|
@ -25,15 +25,24 @@ typeTests.forEach((type) => {
|
|||
is(result.display, 'browser', expected);
|
||||
});
|
||||
|
||||
/*Test valid modes*/
|
||||
var validModes = ['fullscreen', 'standalone', 'minimal-ui', 'browser']
|
||||
/*Test valid modes - case insensitive*/
|
||||
var validModes = [
|
||||
'fullscreen',
|
||||
'standalone',
|
||||
'minimal-ui',
|
||||
'browser',
|
||||
'FullScreen',
|
||||
'standAlone',
|
||||
'minimal-UI',
|
||||
'BROWSER',
|
||||
]
|
||||
validModes.forEach((mode) => {
|
||||
var expected = `Expect display mode to be ${mode}.`;
|
||||
var expected = `Expect display mode to be ${mode.toLowerCase()}.`;
|
||||
data.jsonText = JSON.stringify({
|
||||
display: mode
|
||||
});
|
||||
var result = processor.process(data);
|
||||
is(result.display, mode, expected);
|
||||
is(result.display, mode.toLowerCase(), expected);
|
||||
});
|
||||
|
||||
//trim tests
|
||||
|
@ -44,11 +53,19 @@ validModes.forEach((display) => {
|
|||
display: expandedDisplay
|
||||
});
|
||||
var result = processor.process(data);
|
||||
is(result.display, display, expected);
|
||||
is(result.display, display.toLowerCase(), expected);
|
||||
});
|
||||
|
||||
//Unknown modes
|
||||
var invalidModes = ['foo', `fooo${whiteSpace}`, '', 'fullscreen,standalone', 'standalone fullscreen', 'FULLSCreEN'];
|
||||
var invalidModes = [
|
||||
'foo',
|
||||
`fooo${whiteSpace}`,
|
||||
'',
|
||||
'fullscreen,standalone',
|
||||
'standalone fullscreen',
|
||||
'FULLSCreENS',
|
||||
];
|
||||
|
||||
invalidModes.forEach((invalidMode) => {
|
||||
var expected = `Expect default display mode "browser" to be returned: '${invalidMode}'`;
|
||||
data.jsonText = JSON.stringify({
|
||||
|
|
|
@ -22,10 +22,9 @@ typeTests.forEach((type) => {
|
|||
orientation: type
|
||||
});
|
||||
var result = processor.process(data);
|
||||
is(result.orientation, '', expected);
|
||||
is(result.orientation, undefined, expected);
|
||||
});
|
||||
|
||||
|
||||
var validOrientations = [
|
||||
'any',
|
||||
'natural',
|
||||
|
@ -34,22 +33,28 @@ var validOrientations = [
|
|||
'portrait-primary',
|
||||
'portrait-secondary',
|
||||
'landscape-primary',
|
||||
'landscape-secondary'
|
||||
'landscape-secondary',
|
||||
'aNy',
|
||||
'NaTuRal',
|
||||
'LANDsCAPE',
|
||||
'PORTRAIT',
|
||||
'portrait-PRIMARY',
|
||||
'portrait-SECONDARY',
|
||||
'LANDSCAPE-primary',
|
||||
'LANDSCAPE-secondary',
|
||||
];
|
||||
|
||||
validOrientations.forEach((orientation) => {
|
||||
var expected = `Expect orientation to be returned: ${orientation}.`;
|
||||
data.jsonText = JSON.stringify({
|
||||
orientation: orientation
|
||||
});
|
||||
data.jsonText = JSON.stringify({ orientation });
|
||||
var result = processor.process(data);
|
||||
is(result.orientation, orientation, expected);
|
||||
is(result.orientation, orientation.toLowerCase(), expected);
|
||||
});
|
||||
|
||||
var invalidOrientations = [
|
||||
'all',
|
||||
'ANY',
|
||||
'NaTuRal',
|
||||
'ANYMany',
|
||||
'NaTuRalle',
|
||||
'portrait-primary portrait-secondary',
|
||||
'portrait-primary,portrait-secondary',
|
||||
'any-natural',
|
||||
|
@ -58,15 +63,13 @@ var invalidOrientations = [
|
|||
'secondary-portrait',
|
||||
'landscape-landscape',
|
||||
'secondary-primary'
|
||||
]
|
||||
];
|
||||
|
||||
invalidOrientations.forEach((orientation) => {
|
||||
var expected = `Expect orientation to be empty string: ${orientation}.`;
|
||||
data.jsonText = JSON.stringify({
|
||||
orientation: orientation
|
||||
});
|
||||
data.jsonText = JSON.stringify({ orientation });
|
||||
var result = processor.process(data);
|
||||
is(result.orientation, "", expected);
|
||||
is(result.orientation, undefined, expected);
|
||||
});
|
||||
|
||||
//Trim tests
|
||||
|
@ -77,7 +80,7 @@ validOrientations.forEach((orientation) => {
|
|||
orientation: expandedOrientation
|
||||
});
|
||||
var result = processor.process(data);
|
||||
is(result.orientation, orientation, expected);
|
||||
is(result.orientation, orientation.toLowerCase(), expected);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -520,6 +520,13 @@ struct TrackBound
|
|||
* for those objects in arbitrary order and the MediaStreamGraph has to be able
|
||||
* to handle this.
|
||||
*/
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount() and conflicts with MediaStream::GetCurrentTime.
|
||||
#ifdef GetCurrentTime
|
||||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
class MediaStream : public mozilla::LinkedListElement<MediaStream>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
mozilla::LogModule* GetPDMLog() {
|
||||
static mozilla::LazyLogModule log("PlatformDecoderModule");
|
||||
return log;
|
||||
}
|
|
@ -30,6 +30,8 @@ class MediaDataDecoderCallback;
|
|||
class TaskQueue;
|
||||
class CDMProxy;
|
||||
|
||||
static LazyLogModule sPDMLog("PlatformDecoderModule");
|
||||
|
||||
// The PlatformDecoderModule interface is used by the MediaFormatReader to
|
||||
// abstract access to decoders provided by various
|
||||
// platforms.
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
#include <stdint.h>
|
||||
#include <inttypes.h> // For PRId64
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define OPUS_DEBUG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, \
|
||||
#define OPUS_DEBUG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \
|
||||
("OpusDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#undef LOG
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("VPXDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("VPXDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
#include "nsAutoPtr.h"
|
||||
|
||||
#undef LOG
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(type, msg) MOZ_LOG(GetPDMLog(), type, msg)
|
||||
#define LOG(type, msg) MOZ_LOG(sPDMLog, type, msg)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define FourCC2Str(n) ((char[5]){(char)(n >> 24), (char)(n >> 16), (char)(n >> 8), (char)(n), 0})
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
#include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
#include "MacIOSurfaceImage.h"
|
||||
#endif
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
//#define LOG_MEDIA_SHA1
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
#include "AppleVDALinker.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
#include "VideoUtils.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define FFMPEG_LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define FFMPEG_LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
#endif // __FFmpegLog_h__
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include <android/log.h>
|
||||
#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__)
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
using namespace android;
|
||||
typedef android::MediaCodecProxy MediaCodecProxy;
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
#include <utils/AndroidThreads.h>
|
||||
#endif
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
using namespace android;
|
||||
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
#include <android/log.h>
|
||||
#define GVDM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkVideoDecoderManager", __VA_ARGS__)
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
using namespace mozilla::layers;
|
||||
using namespace android;
|
||||
typedef android::MediaCodecProxy MediaCodecProxy;
|
||||
|
|
|
@ -24,7 +24,6 @@ UNIFIED_SOURCES += [
|
|||
'agnostic/VPXDecoder.cpp',
|
||||
'agnostic/WAVDecoder.cpp',
|
||||
'PDMFactory.cpp',
|
||||
'PlatformDecoderModule.cpp',
|
||||
'wrappers/FuzzingWrapper.cpp',
|
||||
'wrappers/H264Converter.cpp'
|
||||
]
|
||||
|
|
|
@ -21,13 +21,12 @@
|
|||
#include "MediaInfo.h"
|
||||
#include "OmxDataDecoder.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
|
||||
#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
|
||||
#define CHECK_ERR(err) \
|
||||
if (err != OK) { \
|
||||
|
|
|
@ -12,19 +12,18 @@
|
|||
|
||||
#include "OmxPlatformLayer.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#undef LOGL
|
||||
#endif
|
||||
|
||||
#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("OmxDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
|
||||
#define LOGL(arg, ...) \
|
||||
{ \
|
||||
void* p = self; \
|
||||
MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, \
|
||||
MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \
|
||||
("OmxDataDecoder(%p)::%s: " arg, p, __func__, ##__VA_ARGS__)); \
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,12 @@
|
|||
#include "GonkOmxPlatformLayer.h"
|
||||
#endif
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
|
||||
#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxPlatformLayer -- %s: " arg, __func__, ##__VA_ARGS__))
|
||||
#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("OmxPlatformLayer -- %s: " arg, __func__, ##__VA_ARGS__))
|
||||
|
||||
#define RETURN_IF_ERR(err) \
|
||||
if (err != OMX_ErrorNone) { \
|
||||
|
|
|
@ -11,13 +11,12 @@
|
|||
#include "OmxDataDecoder.h"
|
||||
#include "OmxPlatformLayer.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
|
||||
#define LOG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, ("OmxPromiseLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("OmxPromiseLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
#include "WMFUtils.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -30,8 +30,7 @@
|
|||
#include "MediaTelemetryConstants.h"
|
||||
#include "GMPUtils.h" // For SplitAt. TODO: Move SplitAt to a central place.
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
using mozilla::layers::Image;
|
||||
using mozilla::layers::IMFYCbCrImage;
|
||||
|
|
|
@ -77,6 +77,103 @@ UnwrapPromise(JS::Handle<JSObject*> aPromise, ErrorResult& aRv)
|
|||
}
|
||||
return promise;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
/* static */ void
|
||||
PromiseDebugging::GetState(GlobalObject& aGlobal, JS::Handle<JSObject*> aPromise,
|
||||
PromiseDebuggingStateHolder& aState,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aPromise));
|
||||
if (!obj || !JS::IsPromiseObject(obj)) {
|
||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING(
|
||||
"Argument of PromiseDebugging.getState"));
|
||||
return;
|
||||
}
|
||||
switch (JS::GetPromiseState(obj)) {
|
||||
case JS::PromiseState::Pending:
|
||||
aState.mState = PromiseDebuggingState::Pending;
|
||||
break;
|
||||
case JS::PromiseState::Fulfilled:
|
||||
aState.mState = PromiseDebuggingState::Fulfilled;
|
||||
aState.mValue = JS::GetPromiseResult(obj);
|
||||
break;
|
||||
case JS::PromiseState::Rejected:
|
||||
aState.mState = PromiseDebuggingState::Rejected;
|
||||
aState.mReason = JS::GetPromiseResult(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetPromiseID(GlobalObject& aGlobal,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
nsString& aID,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aPromise));
|
||||
if (!obj || !JS::IsPromiseObject(obj)) {
|
||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING(
|
||||
"Argument of PromiseDebugging.getState"));
|
||||
return;
|
||||
}
|
||||
uint64_t promiseID = JS::GetPromiseID(obj);
|
||||
aID = sIDPrefix;
|
||||
aID.AppendInt(promiseID);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetAllocationStack(GlobalObject& aGlobal,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aPromise));
|
||||
if (!obj || !JS::IsPromiseObject(obj)) {
|
||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING(
|
||||
"Argument of PromiseDebugging.getAllocationStack"));
|
||||
return;
|
||||
}
|
||||
aStack.set(JS::GetPromiseAllocationSite(obj));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetRejectionStack(GlobalObject& aGlobal,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aPromise));
|
||||
if (!obj || !JS::IsPromiseObject(obj)) {
|
||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING(
|
||||
"Argument of PromiseDebugging.getRejectionStack"));
|
||||
return;
|
||||
}
|
||||
aStack.set(JS::GetPromiseResolutionSite(obj));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetFullfillmentStack(GlobalObject& aGlobal,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aPromise));
|
||||
if (!obj || !JS::IsPromiseObject(obj)) {
|
||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING(
|
||||
"Argument of PromiseDebugging.getFulfillmentStack"));
|
||||
return;
|
||||
}
|
||||
aStack.set(JS::GetPromiseResolutionSite(obj));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetState(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
|
|
|
@ -32,11 +32,13 @@ public:
|
|||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
static void GetState(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
PromiseDebuggingStateHolder& aState,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void GetPromiseID(GlobalObject&, JS::Handle<JSObject*>, nsString&,
|
||||
ErrorResult&);
|
||||
|
||||
static void GetAllocationStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv);
|
||||
|
@ -47,6 +49,8 @@ public:
|
|||
JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv);
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
static void GetDependentPromises(GlobalObject&,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
nsTArray<RefPtr<Promise>>& aPromises,
|
||||
|
@ -56,9 +60,6 @@ public:
|
|||
ErrorResult& aRv);
|
||||
static double GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void GetPromiseID(GlobalObject&, JS::Handle<JSObject*>, nsString&,
|
||||
ErrorResult&);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
// Mechanism for watching uncaught instances of Promise.
|
||||
|
|
|
@ -222,7 +222,7 @@ partial interface Document {
|
|||
// https://fullscreen.spec.whatwg.org/#api
|
||||
partial interface Document {
|
||||
// Note: Per spec the 'S' in these two is lowercase, but the "Moz"
|
||||
// versions hve it uppercase.
|
||||
// versions have it uppercase.
|
||||
[LenientSetter, Func="nsDocument::IsUnprefixedFullscreenEnabled"]
|
||||
readonly attribute boolean fullscreen;
|
||||
[BinaryName="fullscreen", Deprecated="PrefixedFullscreenAPI"]
|
||||
|
|
|
@ -52,7 +52,6 @@ callback interface UncaughtRejectionObserver {
|
|||
|
||||
[ChromeOnly, Exposed=(Window,System)]
|
||||
interface PromiseDebugging {
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
/**
|
||||
* The various functions on this interface all expect to take promises but
|
||||
* don't want the WebIDL behavior of assimilating random passed-in objects
|
||||
|
@ -68,6 +67,13 @@ interface PromiseDebugging {
|
|||
[Throws]
|
||||
static PromiseDebuggingStateHolder getState(object p);
|
||||
|
||||
/**
|
||||
* Return an identifier for a promise. This identifier is guaranteed
|
||||
* to be unique to the current process.
|
||||
*/
|
||||
[Throws]
|
||||
static DOMString getPromiseID(object p);
|
||||
|
||||
/**
|
||||
* Return the stack to the promise's allocation point. This can
|
||||
* return null if the promise was not created from script.
|
||||
|
@ -91,13 +97,7 @@ interface PromiseDebugging {
|
|||
[Throws]
|
||||
static object? getFullfillmentStack(object p);
|
||||
|
||||
/**
|
||||
* Return an identifier for a promise. This identifier is guaranteed
|
||||
* to be unique to this instance of Firefox.
|
||||
*/
|
||||
[Throws]
|
||||
static DOMString getPromiseID(object p);
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
/**
|
||||
* Get the promises directly depending on a given promise. These are:
|
||||
*
|
||||
|
|
|
@ -1019,7 +1019,7 @@ nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent)
|
|||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
if (eventType.EqualsLiteral("dragover")) {
|
||||
bool canDropLink;
|
||||
bool canDropLink = false;
|
||||
handler->CanDropLink(dragEvent, false, &canDropLink);
|
||||
if (canDropLink) {
|
||||
aEvent->PreventDefault();
|
||||
|
|
|
@ -86,7 +86,7 @@ addMessageListener("init", ({ domain }) => {
|
|||
info(count + " cookies");
|
||||
|
||||
cs.removeAll();
|
||||
cs.add(domain, "", "oh", "hai", false, false, true, Math.pow(2, 62));
|
||||
cs.add(domain, "", "oh", "hai", false, false, true, Math.pow(2, 62), {});
|
||||
is(cs.countCookiesFromHost(domain), 1, "number of cookies for domain " + domain);
|
||||
|
||||
gObs = new obs();
|
||||
|
|
|
@ -13,7 +13,7 @@ function run_test() {
|
|||
|
||||
// test that variants of 'baz.com' get normalized appropriately, but that
|
||||
// malformed hosts are rejected
|
||||
cm.add("baz.com", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("baz.com", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("baz.com"), 1);
|
||||
do_check_eq(cm.countCookiesFromHost("BAZ.com"), 1);
|
||||
do_check_eq(cm.countCookiesFromHost(".baz.com"), 1);
|
||||
|
@ -34,7 +34,7 @@ function run_test() {
|
|||
do_check_eq(cm.countCookiesFromHost("baz.com"), 0);
|
||||
|
||||
// Test that 'baz.com' and 'baz.com.' are treated differently
|
||||
cm.add("baz.com.", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("baz.com.", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("baz.com"), 0);
|
||||
do_check_eq(cm.countCookiesFromHost("BAZ.com"), 0);
|
||||
do_check_eq(cm.countCookiesFromHost(".baz.com"), 0);
|
||||
|
@ -47,7 +47,7 @@ function run_test() {
|
|||
|
||||
// test that domain cookies are illegal for IP addresses, aliases such as
|
||||
// 'localhost', and eTLD's such as 'co.uk'
|
||||
cm.add("192.168.0.1", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("192.168.0.1", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("192.168.0.1"), 1);
|
||||
do_check_eq(cm.countCookiesFromHost("192.168.0.1."), 0);
|
||||
do_check_throws(function() {
|
||||
|
@ -57,7 +57,7 @@ function run_test() {
|
|||
cm.countCookiesFromHost(".192.168.0.1.");
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
cm.add("localhost", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("localhost", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("localhost"), 1);
|
||||
do_check_eq(cm.countCookiesFromHost("localhost."), 0);
|
||||
do_check_throws(function() {
|
||||
|
@ -67,7 +67,7 @@ function run_test() {
|
|||
cm.countCookiesFromHost(".localhost.");
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
cm.add("co.uk", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("co.uk", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("co.uk"), 1);
|
||||
do_check_eq(cm.countCookiesFromHost("co.uk."), 0);
|
||||
do_check_throws(function() {
|
||||
|
@ -105,26 +105,26 @@ function run_test() {
|
|||
cm.countCookiesFromHost("..");
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
var e = cm.getCookiesFromHost("");
|
||||
var e = cm.getCookiesFromHost("", {});
|
||||
do_check_false(e.hasMoreElements());
|
||||
do_check_throws(function() {
|
||||
cm.getCookiesFromHost(".");
|
||||
cm.getCookiesFromHost(".", {});
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
do_check_throws(function() {
|
||||
cm.getCookiesFromHost("..");
|
||||
cm.getCookiesFromHost("..", {});
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
e = cm.getCookiesFromHost("baz.com");
|
||||
e = cm.getCookiesFromHost("baz.com", {});
|
||||
do_check_true(e.hasMoreElements());
|
||||
do_check_eq(e.getNext().QueryInterface(Ci.nsICookie2).name, "foo");
|
||||
do_check_false(e.hasMoreElements());
|
||||
e = cm.getCookiesFromHost("");
|
||||
e = cm.getCookiesFromHost("", {});
|
||||
do_check_false(e.hasMoreElements());
|
||||
do_check_throws(function() {
|
||||
cm.getCookiesFromHost(".");
|
||||
cm.getCookiesFromHost(".", {});
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
do_check_throws(function() {
|
||||
cm.getCookiesFromHost("..");
|
||||
cm.getCookiesFromHost("..", {});
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
cm.removeAll();
|
||||
|
@ -151,26 +151,26 @@ function run_test() {
|
|||
cm.countCookiesFromHost(".");
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
e = cm.getCookiesFromHost("baz.com");
|
||||
e = cm.getCookiesFromHost("baz.com", {});
|
||||
do_check_false(e.hasMoreElements());
|
||||
e = cm.getCookiesFromHost("");
|
||||
e = cm.getCookiesFromHost("", {});
|
||||
do_check_true(e.hasMoreElements());
|
||||
e.getNext();
|
||||
do_check_true(e.hasMoreElements());
|
||||
e.getNext();
|
||||
do_check_false(e.hasMoreElements());
|
||||
do_check_throws(function() {
|
||||
cm.getCookiesFromHost(".");
|
||||
cm.getCookiesFromHost(".", {});
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
cm.removeAll();
|
||||
|
||||
// test that an empty host to add() or remove() works,
|
||||
// but a host of '.' doesn't
|
||||
cm.add("", "/", "foo2", "bar", false, false, true, expiry);
|
||||
cm.add("", "/", "foo2", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(getCookieCount(), 1);
|
||||
do_check_throws(function() {
|
||||
cm.add(".", "/", "foo3", "bar", false, false, true, expiry);
|
||||
cm.add(".", "/", "foo3", "bar", false, false, true, expiry, {});
|
||||
}, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
do_check_eq(getCookieCount(), 1);
|
||||
|
||||
|
@ -216,13 +216,13 @@ function testDomainCookie(uriString, domain) {
|
|||
|
||||
var uri = NetUtil.newURI(uriString);
|
||||
cs.setCookieString(uri, null, "foo=bar; domain=" + domain, null);
|
||||
var e = cm.getCookiesFromHost(domain);
|
||||
var e = cm.getCookiesFromHost(domain, {});
|
||||
do_check_true(e.hasMoreElements());
|
||||
do_check_eq(e.getNext().QueryInterface(Ci.nsICookie2).host, domain);
|
||||
cm.removeAll();
|
||||
|
||||
cs.setCookieString(uri, null, "foo=bar; domain=." + domain, null);
|
||||
e = cm.getCookiesFromHost(domain);
|
||||
e = cm.getCookiesFromHost(domain, {});
|
||||
do_check_true(e.hasMoreElements());
|
||||
do_check_eq(e.getNext().QueryInterface(Ci.nsICookie2).host, domain);
|
||||
cm.removeAll();
|
||||
|
|
|
@ -10,7 +10,7 @@ function run_test() {
|
|||
|
||||
// Test our handling of host names with a single character at the beginning
|
||||
// followed by a dot.
|
||||
cm.add("e.mail.com", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("e.mail.com", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("e.mail.com"), 1);
|
||||
do_check_eq(cs.getCookieString(NetUtil.newURI("http://e.mail.com"), null), "foo=bar");
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ function run_test() {
|
|||
|
||||
// Test our handling of host names with a single character consisting only
|
||||
// of a single character
|
||||
cm.add("a", "/", "foo", "bar", false, false, true, expiry);
|
||||
cm.add("a", "/", "foo", "bar", false, false, true, expiry, {});
|
||||
do_check_eq(cm.countCookiesFromHost("a"), 1);
|
||||
do_check_eq(cs.getCookieString(NetUtil.newURI("http://a"), null), "foo=bar");
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ function run_test_1(generator)
|
|||
|
||||
// Attempt to insert a cookie with the same (name, host, path) triplet.
|
||||
Services.cookiemgr.add(cookie.host, cookie.path, cookie.name, "hallo",
|
||||
cookie.isSecure, cookie.isHttpOnly, cookie.isSession, cookie.expiry);
|
||||
cookie.isSecure, cookie.isHttpOnly, cookie.isSession, cookie.expiry, {});
|
||||
|
||||
// Check that the cookie service accepted the new cookie.
|
||||
do_check_eq(Services.cookiemgr.countCookiesFromHost(cookie.host), 1);
|
||||
|
@ -189,7 +189,7 @@ function run_test_1(generator)
|
|||
do_load_profile();
|
||||
|
||||
do_check_eq(Services.cookiemgr.countCookiesFromHost("foo.com"), 1);
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost(cookie.host);
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost(cookie.host, {});
|
||||
do_check_true(enumerator.hasMoreElements());
|
||||
let dbcookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
do_check_eq(dbcookie.value, "hallo");
|
||||
|
|
|
@ -54,7 +54,7 @@ function do_run_test() {
|
|||
}, Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
do_check_throws(function() {
|
||||
Services.cookiemgr.add("foo.com", "", "oh4", "hai", false, false, false, 0);
|
||||
Services.cookiemgr.add("foo.com", "", "oh4", "hai", false, false, false, 0, {});
|
||||
}, Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
do_check_throws(function() {
|
||||
|
@ -76,7 +76,7 @@ function do_run_test() {
|
|||
}, Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
do_check_throws(function() {
|
||||
Services.cookies.getCookiesFromHost("foo.com");
|
||||
Services.cookies.getCookiesFromHost("foo.com", {});
|
||||
}, Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// Wait for the database to finish closing.
|
||||
|
|
|
@ -68,16 +68,16 @@ function do_run_test()
|
|||
let shortExpiry = Math.floor(Date.now() / 1000 + 2);
|
||||
setCookies("captchart.com", 49, futureExpiry);
|
||||
Services.cookiemgr.add("captchart.com", "", "test100", "eviction",
|
||||
false, false, false, shortExpiry);
|
||||
false, false, false, shortExpiry, {});
|
||||
do_timeout(2100, continue_test);
|
||||
yield;
|
||||
|
||||
do_check_eq(countCookies("captchart.com", "captchart.com"), 50);
|
||||
Services.cookiemgr.add("captchart.com", "", "test200", "eviction",
|
||||
false, false, false, futureExpiry);
|
||||
false, false, false, futureExpiry, {});
|
||||
do_check_eq(countCookies("captchart.com", "captchart.com"), 50);
|
||||
|
||||
enumerator = Services.cookiemgr.getCookiesFromHost("captchart.com");
|
||||
enumerator = Services.cookiemgr.getCookiesFromHost("captchart.com", {});
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
do_check_true(cookie.expiry == futureExpiry);
|
||||
|
@ -92,7 +92,7 @@ setCookies(aHost, aNumber, aExpiry)
|
|||
{
|
||||
for (let i = 0; i < aNumber; ++i)
|
||||
Services.cookiemgr.add(aHost, "", "test" + i, "eviction",
|
||||
false, false, false, aExpiry);
|
||||
false, false, false, aExpiry, {});
|
||||
}
|
||||
|
||||
// count how many cookies are within domain 'aBaseDomain', using three
|
||||
|
@ -123,7 +123,7 @@ countCookies(aBaseDomain, aHost)
|
|||
cookies.length);
|
||||
do_check_eq(Services.cookiemgr.countCookiesFromHost(aHost), cookies.length);
|
||||
|
||||
enumerator = Services.cookiemgr.getCookiesFromHost(aHost);
|
||||
enumerator = Services.cookiemgr.getCookiesFromHost(aHost, {});
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ function set_cookies(begin, end, expiry)
|
|||
for (let i = begin; i < end; ++i) {
|
||||
let host = "eviction." + i + ".tests";
|
||||
Services.cookiemgr.add(host, "", "test", "eviction", false, false, false,
|
||||
expiry);
|
||||
expiry, {});
|
||||
|
||||
if (i == begin)
|
||||
beginTime = get_creationTime(i);
|
||||
|
@ -219,7 +219,7 @@ function set_cookies(begin, end, expiry)
|
|||
function get_creationTime(i)
|
||||
{
|
||||
let host = "eviction." + i + ".tests";
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost(host);
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost(host, {});
|
||||
do_check_true(enumerator.hasMoreElements());
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
return cookie.creationTime;
|
||||
|
|
|
@ -88,7 +88,7 @@ function do_run_test() {
|
|||
// 3) Only one cookie remains, and it's the one with the highest expiration
|
||||
// time.
|
||||
do_check_eq(Services.cookiemgr.countCookiesFromHost("baz.com"), 1);
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost("baz.com");
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost("baz.com", {});
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
do_check_eq(cookie.expiry, futureExpiry + 44);
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ function do_run_test() {
|
|||
// 3) Only one cookie remains, and it's the one with the highest expiration
|
||||
// time.
|
||||
do_check_eq(Services.cookiemgr.countCookiesFromHost("baz.com"), 1);
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost("baz.com");
|
||||
let enumerator = Services.cookiemgr.getCookiesFromHost("baz.com", {});
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
do_check_eq(cookie.expiry, futureExpiry + 44);
|
||||
|
||||
|
@ -116,7 +116,7 @@ function do_run_test() {
|
|||
|
||||
// Test the expected set of cookies.
|
||||
do_check_eq(Services.cookiemgr.countCookiesFromHost("cat.com"), 20);
|
||||
enumerator = Services.cookiemgr.getCookiesFromHost("cat.com");
|
||||
enumerator = Services.cookiemgr.getCookiesFromHost("cat.com", {});
|
||||
cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
do_check_eq(cookie.creationTime, 0);
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ template <typename Next>
|
|||
class DownscalingFilter final : public SurfaceFilter
|
||||
{
|
||||
public:
|
||||
uint8_t* AdvanceRow() override { MOZ_CRASH(); return nullptr; }
|
||||
Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); }
|
||||
|
||||
template <typename... Rest>
|
||||
|
@ -83,6 +82,7 @@ public:
|
|||
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override { MOZ_CRASH(); return nullptr; }
|
||||
uint8_t* DoAdvanceRow() override { MOZ_CRASH(); return nullptr; }
|
||||
};
|
||||
|
||||
#else
|
||||
|
@ -215,7 +215,19 @@ public:
|
|||
return invalidRect;
|
||||
}
|
||||
|
||||
uint8_t* AdvanceRow() override
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override
|
||||
{
|
||||
mNext.ResetToFirstRow();
|
||||
|
||||
mInputRow = 0;
|
||||
mOutputRow = 0;
|
||||
mRowsInWindow = 0;
|
||||
|
||||
return GetRowPointer();
|
||||
}
|
||||
|
||||
uint8_t* DoAdvanceRow() override
|
||||
{
|
||||
if (mInputRow >= mInputSize.height) {
|
||||
NS_WARNING("Advancing DownscalingFilter past the end of the input");
|
||||
|
@ -260,18 +272,6 @@ public:
|
|||
: nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override
|
||||
{
|
||||
mNext.ResetToFirstRow();
|
||||
|
||||
mInputRow = 0;
|
||||
mOutputRow = 0;
|
||||
mRowsInWindow = 0;
|
||||
|
||||
return GetRowPointer();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* GetRowPointer() const { return mRowBuffer.get(); }
|
||||
|
||||
|
|
|
@ -119,7 +119,17 @@ public:
|
|||
return mNext.TakeInvalidRect();
|
||||
}
|
||||
|
||||
uint8_t* AdvanceRow() override
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override
|
||||
{
|
||||
mNext.ResetToFirstRow();
|
||||
mPass = 0;
|
||||
mInputRow = 0;
|
||||
mOutputRow = InterlaceOffset(mPass);
|
||||
return GetRowPointer(mOutputRow);
|
||||
}
|
||||
|
||||
uint8_t* DoAdvanceRow() override
|
||||
{
|
||||
if (mPass >= 4) {
|
||||
return nullptr; // We already finished all passes.
|
||||
|
@ -147,9 +157,6 @@ public:
|
|||
while (nextOutputRow >= InputSize().height) {
|
||||
// Copy any remaining rows from the buffer.
|
||||
if (!advancedPass) {
|
||||
DuplicateRows(HaeberliOutputUntilRow(mPass, mProgressiveDisplay,
|
||||
InputSize(), mOutputRow),
|
||||
InputSize().height);
|
||||
OutputRows(HaeberliOutputUntilRow(mPass, mProgressiveDisplay,
|
||||
InputSize(), mOutputRow),
|
||||
InputSize().height);
|
||||
|
@ -211,16 +218,6 @@ public:
|
|||
return GetRowPointer(nextHaeberliOutputRow);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override
|
||||
{
|
||||
mNext.ResetToFirstRow();
|
||||
mPass = 0;
|
||||
mInputRow = 0;
|
||||
mOutputRow = InterlaceOffset(mPass);;
|
||||
return GetRowPointer(mOutputRow);
|
||||
}
|
||||
|
||||
private:
|
||||
static uint32_t InterlaceOffset(uint32_t aPass)
|
||||
{
|
||||
|
@ -413,7 +410,53 @@ public:
|
|||
return mNext.TakeInvalidRect();
|
||||
}
|
||||
|
||||
uint8_t* AdvanceRow() override
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override
|
||||
{
|
||||
uint8_t* rowPtr = mNext.ResetToFirstRow();
|
||||
if (rowPtr == nullptr) {
|
||||
mRow = mFrameRect.YMost();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRow = mUnclampedFrameRect.y;
|
||||
|
||||
// Advance the next pipeline stage to the beginning of the frame rect,
|
||||
// outputting blank rows.
|
||||
if (mFrameRect.y > 0) {
|
||||
int32_t rowsToWrite = mFrameRect.y;
|
||||
mNext.template WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength)
|
||||
-> Maybe<WriteState> {
|
||||
memset(aRow, 0, aLength * sizeof(uint32_t));
|
||||
rowsToWrite--;
|
||||
return rowsToWrite > 0 ? Nothing()
|
||||
: Some(WriteState::NEED_MORE_DATA);
|
||||
});
|
||||
}
|
||||
|
||||
// We're at the beginning of the frame rect now, so return if we're either
|
||||
// ready for input or we're already done.
|
||||
rowPtr = mBuffer ? mBuffer.get() : mNext.CurrentRowPointer();
|
||||
if (!mFrameRect.IsEmpty() || rowPtr == nullptr) {
|
||||
// Note that the pointer we're returning is for the next row we're
|
||||
// actually going to write to, but we may discard writes before that point
|
||||
// if mRow < mFrameRect.y.
|
||||
return AdjustRowPointer(rowPtr);
|
||||
}
|
||||
|
||||
// We've finished the region specified by the frame rect, but the frame rect
|
||||
// is empty, so we need to output the rest of the image immediately. Advance
|
||||
// to the end of the next pipeline stage's buffer, outputting blank rows.
|
||||
mNext.template WriteRows<uint32_t>([](uint32_t* aRow, uint32_t aLength) {
|
||||
memset(aRow, 0, aLength * sizeof(uint32_t));
|
||||
return Nothing();
|
||||
});
|
||||
|
||||
mRow = mFrameRect.YMost();
|
||||
return nullptr; // We're done.
|
||||
}
|
||||
|
||||
uint8_t* DoAdvanceRow() override
|
||||
{
|
||||
uint8_t* rowPtr = nullptr;
|
||||
|
||||
|
@ -469,59 +512,12 @@ public:
|
|||
|
||||
// We've finished the region specified by the frame rect. Advance to the end
|
||||
// of the next pipeline stage's buffer, outputting blank rows.
|
||||
mNext.template WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
memset(rowPtr, 0, aLength * sizeof(uint32_t));
|
||||
return Nothing();
|
||||
});
|
||||
|
||||
return nullptr; // We're done.
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override
|
||||
{
|
||||
uint8_t* rowPtr = mNext.ResetToFirstRow();
|
||||
if (rowPtr == nullptr) {
|
||||
mRow = InputSize().height;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRow = mUnclampedFrameRect.y;
|
||||
|
||||
// Advance the next pipeline stage to the beginning of the frame rect,
|
||||
// outputting blank rows.
|
||||
if (mFrameRect.y > 0) {
|
||||
int32_t rowsToWrite = mFrameRect.y;
|
||||
mNext.template WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength)
|
||||
-> Maybe<WriteState> {
|
||||
memset(aRow, 0, aLength * sizeof(uint32_t));
|
||||
rowsToWrite--;
|
||||
return rowsToWrite > 0 ? Nothing()
|
||||
: Some(WriteState::NEED_MORE_DATA);
|
||||
});
|
||||
}
|
||||
|
||||
// We're at the beginning of the frame rect now, so return if we're either
|
||||
// ready for input or we're already done.
|
||||
rowPtr = mBuffer ? mBuffer.get() : mNext.CurrentRowPointer();
|
||||
if (!mFrameRect.IsEmpty() || rowPtr == nullptr) {
|
||||
// Note that the pointer we're returning is for the next row we're
|
||||
// actually going to write to, but we may discard writes before that point
|
||||
// if mRow < mFrameRect.y.
|
||||
return AdjustRowPointer(rowPtr);
|
||||
}
|
||||
|
||||
// We've finished the region specified by the frame rect, but the frame rect
|
||||
// is empty, so we need to output the rest of the image immediately. Advance
|
||||
// to the end of the next pipeline stage's buffer, outputting blank rows.
|
||||
int32_t rowsWritten = 0;
|
||||
mNext.template WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
rowsWritten++;
|
||||
mNext.template WriteRows<uint32_t>([](uint32_t* aRow, uint32_t aLength) {
|
||||
memset(aRow, 0, aLength * sizeof(uint32_t));
|
||||
return Nothing();
|
||||
});
|
||||
|
||||
mRow = InputSize().height;
|
||||
mRow = mFrameRect.YMost();
|
||||
return nullptr; // We're done.
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ AbstractSurfaceSink::DoResetToFirstRow()
|
|||
}
|
||||
|
||||
uint8_t*
|
||||
AbstractSurfaceSink::AdvanceRow()
|
||||
AbstractSurfaceSink::DoAdvanceRow()
|
||||
{
|
||||
if (mRow >= uint32_t(InputSize().height)) {
|
||||
return nullptr;
|
||||
|
|
|
@ -119,6 +119,20 @@ public:
|
|||
return mRowPointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by WritePixels() and WriteRows() to advance this filter to the next
|
||||
* row.
|
||||
*
|
||||
* @return a pointer to the buffer for the next row, or nullptr to indicate
|
||||
* that we've finished the entire surface.
|
||||
*/
|
||||
uint8_t* AdvanceRow()
|
||||
{
|
||||
mCol = 0;
|
||||
mRowPointer = DoAdvanceRow();
|
||||
return mRowPointer;
|
||||
}
|
||||
|
||||
/// @return a pointer to the buffer for the current row.
|
||||
uint8_t* CurrentRowPointer() const { return mRowPointer; }
|
||||
|
||||
|
@ -191,9 +205,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// We've finished the row.
|
||||
mRowPointer = AdvanceRow();
|
||||
mCol = 0;
|
||||
AdvanceRow(); // We've finished the row.
|
||||
}
|
||||
|
||||
// We've finished the entire surface.
|
||||
|
@ -244,8 +256,7 @@ public:
|
|||
|
||||
Maybe<WriteState> result = aFunc(rowPtr, mInputSize.width);
|
||||
if (result != Some(WriteState::FAILURE)) {
|
||||
mCol = 0;
|
||||
mRowPointer = AdvanceRow(); // We've finished the row.
|
||||
AdvanceRow(); // We've finished the row.
|
||||
}
|
||||
|
||||
if (IsSurfaceFinished()) {
|
||||
|
@ -275,15 +286,6 @@ public:
|
|||
/// @return true if this SurfaceFilter can be used with paletted surfaces.
|
||||
virtual bool IsValidPalettedPipe() const { return false; }
|
||||
|
||||
/**
|
||||
* Called by WritePixels() and WriteRows() to advance this filter to the next
|
||||
* row.
|
||||
*
|
||||
* @return a pointer to the buffer for the next row, or nullptr to indicate
|
||||
* that we've finished the entire surface.
|
||||
*/
|
||||
virtual uint8_t* AdvanceRow() = 0;
|
||||
|
||||
/**
|
||||
* @return a SurfaceInvalidRect representing the region of the surface that
|
||||
* has been written to since the last time TakeInvalidRect() was
|
||||
|
@ -301,6 +303,14 @@ protected:
|
|||
*/
|
||||
virtual uint8_t* DoResetToFirstRow() = 0;
|
||||
|
||||
/**
|
||||
* Called by AdvanceRow() to actually advance this filter to the next row.
|
||||
*
|
||||
* @return a pointer to the buffer for the next row, or nullptr to indicate
|
||||
* that we've finished the entire surface.
|
||||
*/
|
||||
virtual uint8_t* DoAdvanceRow() = 0;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Methods For Internal Use By Subclasses
|
||||
|
@ -360,10 +370,10 @@ public:
|
|||
nsresult Configure(const NullSurfaceConfig& aConfig);
|
||||
|
||||
Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); }
|
||||
uint8_t* AdvanceRow() override { return nullptr; }
|
||||
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override { return nullptr; }
|
||||
uint8_t* DoAdvanceRow() override { return nullptr; }
|
||||
|
||||
private:
|
||||
static UniquePtr<NullSurfaceSink> sSingleton; /// The singleton instance.
|
||||
|
@ -478,10 +488,10 @@ public:
|
|||
{ }
|
||||
|
||||
Maybe<SurfaceInvalidRect> TakeInvalidRect() override final;
|
||||
uint8_t* AdvanceRow() override final;
|
||||
|
||||
protected:
|
||||
uint8_t* DoResetToFirstRow() override final;
|
||||
uint8_t* DoAdvanceRow() override final;
|
||||
virtual uint8_t* GetRowPointer() const = 0;
|
||||
|
||||
gfx::IntRect mInvalidRect; /// The region of the surface that has been written
|
||||
|
|
|
@ -115,34 +115,30 @@ public:
|
|||
if (downscale) {
|
||||
if (removeFrameRect) {
|
||||
if (deinterlace) {
|
||||
pipe = MakePipe(aFrameRect.Size(), deinterlacingConfig,
|
||||
removeFrameRectConfig, downscalingConfig,
|
||||
surfaceConfig);
|
||||
} else { // (deinterlace is false)
|
||||
pipe = MakePipe(aFrameRect.Size(), removeFrameRectConfig,
|
||||
pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig,
|
||||
downscalingConfig, surfaceConfig);
|
||||
} else { // (deinterlace is false)
|
||||
pipe = MakePipe(removeFrameRectConfig, downscalingConfig, surfaceConfig);
|
||||
}
|
||||
} else { // (removeFrameRect is false)
|
||||
if (deinterlace) {
|
||||
pipe = MakePipe(aInputSize, deinterlacingConfig,
|
||||
downscalingConfig, surfaceConfig);
|
||||
pipe = MakePipe(deinterlacingConfig, downscalingConfig, surfaceConfig);
|
||||
} else { // (deinterlace is false)
|
||||
pipe = MakePipe(aInputSize, downscalingConfig, surfaceConfig);
|
||||
pipe = MakePipe(downscalingConfig, surfaceConfig);
|
||||
}
|
||||
}
|
||||
} else { // (downscale is false)
|
||||
if (removeFrameRect) {
|
||||
if (deinterlace) {
|
||||
pipe = MakePipe(aFrameRect.Size(), deinterlacingConfig,
|
||||
removeFrameRectConfig, surfaceConfig);
|
||||
pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig, surfaceConfig);
|
||||
} else { // (deinterlace is false)
|
||||
pipe = MakePipe(aFrameRect.Size(), removeFrameRectConfig, surfaceConfig);
|
||||
pipe = MakePipe(removeFrameRectConfig, surfaceConfig);
|
||||
}
|
||||
} else { // (removeFrameRect is false)
|
||||
if (deinterlace) {
|
||||
pipe = MakePipe(aInputSize, deinterlacingConfig, surfaceConfig);
|
||||
pipe = MakePipe(deinterlacingConfig, surfaceConfig);
|
||||
} else { // (deinterlace is false)
|
||||
pipe = MakePipe(aInputSize, surfaceConfig);
|
||||
pipe = MakePipe(surfaceConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,10 +191,9 @@ public:
|
|||
Maybe<SurfacePipe> pipe;
|
||||
|
||||
if (deinterlace) {
|
||||
pipe = MakePipe(aFrameRect.Size(), deinterlacingConfig,
|
||||
palettedSurfaceConfig);
|
||||
pipe = MakePipe(deinterlacingConfig, palettedSurfaceConfig);
|
||||
} else {
|
||||
pipe = MakePipe(aFrameRect.Size(), palettedSurfaceConfig);
|
||||
pipe = MakePipe(palettedSurfaceConfig);
|
||||
}
|
||||
|
||||
return pipe;
|
||||
|
@ -207,7 +202,7 @@ public:
|
|||
private:
|
||||
template <typename... Configs>
|
||||
static Maybe<SurfacePipe>
|
||||
MakePipe(const nsIntSize& aInputSize, Configs... aConfigs)
|
||||
MakePipe(Configs... aConfigs)
|
||||
{
|
||||
auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>();
|
||||
nsresult rv = pipe->Configure(aConfigs...);
|
||||
|
|
|
@ -76,11 +76,11 @@ nsIconDecoder::ReadHeader(const char* aData)
|
|||
|
||||
MOZ_ASSERT(!mImageData, "Already have a buffer allocated?");
|
||||
IntSize targetSize = mDownscaler ? mDownscaler->TargetSize() : GetSize();
|
||||
IntRect targetFrameRect(IntPoint(0, 0), targetSize);
|
||||
IntRect frameRect(IntPoint(0, 0), GetSize());
|
||||
|
||||
Maybe<SurfacePipe> pipe =
|
||||
SurfacePipeFactory::CreateSurfacePipe(this, 0, GetSize(), targetSize,
|
||||
targetFrameRect, SurfaceFormat::B8G8R8A8,
|
||||
frameRect, SurfaceFormat::B8G8R8A8,
|
||||
SurfacePipeFlags());
|
||||
if (!pipe) {
|
||||
return Transition::TerminateFailure();
|
||||
|
|
|
@ -195,6 +195,112 @@ TEST(ImageDeinterlacingFilter, PalettedWriteRows)
|
|||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixelsNonProgressiveOutput51_52)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(51, 52), /* aProgressiveDisplay = */ false,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be green for even rows and red for odd
|
||||
// rows but we need to write the rows in the order that the deinterlacer
|
||||
// expects them.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WritePixels<uint32_t>([&]() {
|
||||
uint32_t row = count / 51; // Integer division.
|
||||
++count;
|
||||
|
||||
// Note that we use a switch statement here, even though it's quite
|
||||
// verbose, because it's useful to have the mappings between input and
|
||||
// output rows available when debugging these tests.
|
||||
|
||||
switch (row) {
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
case 0: // Output row 0.
|
||||
case 1: // Output row 8.
|
||||
case 2: // Output row 16.
|
||||
case 3: // Output row 24.
|
||||
case 4: // Output row 32.
|
||||
case 5: // Output row 40.
|
||||
case 6: // Output row 48.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Second pass. Rows are positioned at 8n + 4.
|
||||
case 7: // Output row 4.
|
||||
case 8: // Output row 12.
|
||||
case 9: // Output row 20.
|
||||
case 10: // Output row 28.
|
||||
case 11: // Output row 36.
|
||||
case 12: // Output row 44.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Third pass. Rows are positioned at 4n + 2.
|
||||
case 13: // Output row 2.
|
||||
case 14: // Output row 6.
|
||||
case 15: // Output row 10.
|
||||
case 16: // Output row 14.
|
||||
case 17: // Output row 18.
|
||||
case 18: // Output row 22.
|
||||
case 19: // Output row 26.
|
||||
case 20: // Output row 30.
|
||||
case 21: // Output row 34.
|
||||
case 22: // Output row 38.
|
||||
case 23: // Output row 42.
|
||||
case 24: // Output row 46.
|
||||
case 25: // Output row 50.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Fourth pass. Rows are positioned at 2n + 1.
|
||||
case 26: // Output row 1.
|
||||
case 27: // Output row 3.
|
||||
case 28: // Output row 5.
|
||||
case 29: // Output row 7.
|
||||
case 30: // Output row 9.
|
||||
case 31: // Output row 11.
|
||||
case 32: // Output row 13.
|
||||
case 33: // Output row 15.
|
||||
case 34: // Output row 17.
|
||||
case 35: // Output row 19.
|
||||
case 36: // Output row 21.
|
||||
case 37: // Output row 23.
|
||||
case 38: // Output row 25.
|
||||
case 39: // Output row 27.
|
||||
case 40: // Output row 29.
|
||||
case 41: // Output row 31.
|
||||
case 42: // Output row 33.
|
||||
case 43: // Output row 35.
|
||||
case 44: // Output row 37.
|
||||
case 45: // Output row 39.
|
||||
case 46: // Output row 41.
|
||||
case 47: // Output row 43.
|
||||
case 48: // Output row 45.
|
||||
case 49: // Output row 47.
|
||||
case 50: // Output row 49.
|
||||
case 51: // Output row 51.
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected row");
|
||||
return AsVariant(BGRAColor::Transparent().AsPixel());
|
||||
}
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(51u * 52u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 51, 52),
|
||||
IntRect(0, 0, 51, 52));
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// even rows to be green and odd rows to be red.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = 0; row < 52; ++row) {
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1,
|
||||
row % 2 == 0 ? BGRAColor::Green()
|
||||
: BGRAColor::Red()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixelsOutput20_20)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(20, 20), /* aProgressiveDisplay = */ true,
|
||||
|
@ -207,6 +313,10 @@ TEST(ImageDeinterlacingFilter, WritePixelsOutput20_20)
|
|||
uint32_t row = count / 20; // Integer division.
|
||||
++count;
|
||||
|
||||
// Note that we use a switch statement here, even though it's quite
|
||||
// verbose, because it's useful to have the mappings between input and
|
||||
// output rows available when debugging these tests.
|
||||
|
||||
switch (row) {
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
case 0: // Output row 0.
|
||||
|
@ -276,6 +386,7 @@ TEST(ImageDeinterlacingFilter, WriteRowsOutput7_7)
|
|||
uint32_t row = 0;
|
||||
auto result = aFilter->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
uint32_t color = 0;
|
||||
|
||||
switch (row) {
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
case 0: // Output row 0.
|
||||
|
|
|
@ -124,8 +124,20 @@ TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWriteRows)
|
|||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWritePixels)
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWritePixels)
|
||||
{
|
||||
// This test case uses a frame rect that extends beyond the borders of the
|
||||
// image to the bottom and to the right. It looks roughly like this (with the
|
||||
// box made of '#'s representing the frame rect):
|
||||
//
|
||||
// +------------+
|
||||
// + +
|
||||
// + +------------+
|
||||
// + +############+
|
||||
// +------+############+
|
||||
// +############+
|
||||
// +------------+
|
||||
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
|
@ -168,7 +180,7 @@ TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWritePixels)
|
|||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWriteRows)
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWriteRows)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
@ -193,6 +205,63 @@ TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWriteRows)
|
|||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWritePixels)
|
||||
{
|
||||
// This test case uses a frame rect that extends beyond the borders of the
|
||||
// image to the top and to the left. It looks roughly like this (with the
|
||||
// box made of '#'s representing the frame rect):
|
||||
//
|
||||
// +------------+
|
||||
// +############+
|
||||
// +############+------+
|
||||
// +############+ +
|
||||
// +------------+ +
|
||||
// + +
|
||||
// +------------+
|
||||
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 20, 20)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 10, 10)),
|
||||
/* aFuzz = */ 0x21);
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
RemoveFrameRectConfig { IntRect(-50, -50, 100, 100) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWriteRows)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 20, 20)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 10, 10)),
|
||||
/* aFuzz = */ 0x21);
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
RemoveFrameRectConfig { IntRect(-50, -50, 100, 100) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
|
|
|
@ -492,22 +492,24 @@ GeckoChildProcessHost::DissociateActor()
|
|||
int32_t GeckoChildProcessHost::mChildCounter = 0;
|
||||
|
||||
void
|
||||
GeckoChildProcessHost::SetChildLogName(const char* varName, const char* origLogName)
|
||||
GeckoChildProcessHost::SetChildLogName(const char* varName, const char* origLogName,
|
||||
nsACString &buffer)
|
||||
{
|
||||
// We currently have no portable way to launch child with environment
|
||||
// different than parent. So temporarily change NSPR_LOG_FILE so child
|
||||
// inherits value we want it to have. (NSPR only looks at NSPR_LOG_FILE at
|
||||
// startup, so it's 'safe' to play with the parent's environment this way.)
|
||||
nsAutoCString setChildLogName(varName);
|
||||
setChildLogName.Append(origLogName);
|
||||
buffer.Assign(varName);
|
||||
buffer.Append(origLogName);
|
||||
|
||||
// Append child-specific postfix to name
|
||||
setChildLogName.AppendLiteral(".child-");
|
||||
setChildLogName.AppendInt(mChildCounter);
|
||||
buffer.AppendLiteral(".child-");
|
||||
buffer.AppendInt(mChildCounter);
|
||||
|
||||
// Passing temporary to PR_SetEnv is ok here because env gets copied
|
||||
// by exec, etc., to permanent storage in child when process launched.
|
||||
PR_SetEnv(setChildLogName.get());
|
||||
// Passing temporary to PR_SetEnv is ok here if we keep the temporary
|
||||
// for the time we launch the sub-process. It's copied to the new
|
||||
// environment.
|
||||
PR_SetEnv(buffer.BeginReading());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -528,19 +530,24 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts, b
|
|||
static nsAutoCString restoreOrigNSPRLogName;
|
||||
static nsAutoCString restoreOrigMozLogName;
|
||||
|
||||
// Must keep these on the same stack where from we call PerformAsyncLaunchInternal
|
||||
// so that PR_DuplicateEnvironment() still sees a valid memory.
|
||||
nsAutoCString nsprLogName;
|
||||
nsAutoCString mozLogName;
|
||||
|
||||
if (origNSPRLogName) {
|
||||
if (restoreOrigNSPRLogName.IsEmpty()) {
|
||||
restoreOrigNSPRLogName.AssignLiteral("NSPR_LOG_FILE=");
|
||||
restoreOrigNSPRLogName.Append(origNSPRLogName);
|
||||
}
|
||||
SetChildLogName("NSPR_LOG_FILE=", origNSPRLogName);
|
||||
SetChildLogName("NSPR_LOG_FILE=", origNSPRLogName, nsprLogName);
|
||||
}
|
||||
if (origMozLogName) {
|
||||
if (restoreOrigMozLogName.IsEmpty()) {
|
||||
restoreOrigMozLogName.AssignLiteral("MOZ_LOG_FILE=");
|
||||
restoreOrigMozLogName.Append(origMozLogName);
|
||||
}
|
||||
SetChildLogName("MOZ_LOG_FILE=", origMozLogName);
|
||||
SetChildLogName("MOZ_LOG_FILE=", origMozLogName, mozLogName);
|
||||
}
|
||||
|
||||
bool retval = PerformAsyncLaunchInternal(aExtraOpts, arch);
|
||||
|
|
|
@ -200,7 +200,10 @@ private:
|
|||
|
||||
static void GetPathToBinary(FilePath& exePath);
|
||||
|
||||
void SetChildLogName(const char* varName, const char* origLogName);
|
||||
// The buffer is passed to preserve its lifetime until we are done
|
||||
// with launching the sub-process.
|
||||
void SetChildLogName(const char* varName, const char* origLogName,
|
||||
nsACString &buffer);
|
||||
|
||||
// In between launching the subprocess and handing off its IPC
|
||||
// channel, there's a small window of time in which *we* might still
|
||||
|
|
|
@ -1730,11 +1730,12 @@ ParseFloatLiteral(WasmParseContext& c, WasmToken token, Float* result)
|
|||
// Call into JS' strtod. Tokenization has already required that the
|
||||
// string is well-behaved.
|
||||
LifoAlloc::Mark mark = c.lifo.mark();
|
||||
char* buffer = c.lifo.newArray<char>(end - begin + 1);
|
||||
char* buffer = c.lifo.newArray<char>(end - cur + 1);
|
||||
if (!buffer)
|
||||
return false;
|
||||
for (ptrdiff_t i = 0; i < end - cur; ++i)
|
||||
buffer[i] = char(cur[i]);
|
||||
buffer[end - cur] = '\0';
|
||||
char* strtod_end;
|
||||
int err;
|
||||
Float d = (Float)js_strtod_harder(c.dtoaState, buffer, &strtod_end, &err);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "gc/Heap.h"
|
||||
#include "js/Date.h"
|
||||
#include "js/Debug.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
@ -40,7 +41,39 @@ static const JSPropertySpec promise_static_properties[] = {
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
// ES6, 25.4.3.1. steps 3-11.
|
||||
static Value
|
||||
Now()
|
||||
{
|
||||
return JS::TimeValue(JS::TimeClip(static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_MSEC));
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateResolvingFunctions(JSContext* cx, HandleValue promise,
|
||||
MutableHandleValue resolveVal,
|
||||
MutableHandleValue rejectVal)
|
||||
{
|
||||
FixedInvokeArgs<1> args(cx);
|
||||
args[0].set(promise);
|
||||
|
||||
RootedValue rval(cx);
|
||||
|
||||
if (!CallSelfHostedFunction(cx, cx->names().CreateResolvingFunctions, UndefinedHandleValue,
|
||||
args, &rval))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject resolvingFunctions(cx, &args.rval().toObject().as<ArrayObject>());
|
||||
resolveVal.set(resolvingFunctions->getDenseElement(0));
|
||||
rejectVal.set(resolvingFunctions->getDenseElement(1));
|
||||
|
||||
MOZ_ASSERT(IsCallable(resolveVal));
|
||||
MOZ_ASSERT(IsCallable(rejectVal));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES2016, February 12 draft, 25.4.3.1. steps 3-11.
|
||||
PromiseObject*
|
||||
PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
|
||||
{
|
||||
|
@ -73,33 +106,38 @@ PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /
|
|||
ac.emplace(cx, usedProto);
|
||||
|
||||
promise = &NewObjectWithClassProto(cx, &class_, usedProto)->as<PromiseObject>();
|
||||
|
||||
// Step 4.
|
||||
if (!promise)
|
||||
return nullptr;
|
||||
|
||||
// Step 5.
|
||||
// Step 4.
|
||||
promise->setFixedSlot(PROMISE_STATE_SLOT, Int32Value(PROMISE_STATE_PENDING));
|
||||
|
||||
// Step 6.
|
||||
// Step 5.
|
||||
RootedArrayObject reactions(cx, NewDenseEmptyArray(cx));
|
||||
if (!reactions)
|
||||
return nullptr;
|
||||
promise->setFixedSlot(PROMISE_FULFILL_REACTIONS_SLOT, ObjectValue(*reactions));
|
||||
|
||||
// Step 7.
|
||||
// Step 6.
|
||||
reactions = NewDenseEmptyArray(cx);
|
||||
if (!reactions)
|
||||
return nullptr;
|
||||
promise->setFixedSlot(PROMISE_REJECT_REACTIONS_SLOT, ObjectValue(*reactions));
|
||||
|
||||
// Step 7.
|
||||
promise->setFixedSlot(PROMISE_IS_HANDLED_SLOT,
|
||||
Int32Value(PROMISE_IS_HANDLED_STATE_UNHANDLED));
|
||||
|
||||
// Store an allocation stack so we can later figure out what the
|
||||
// control flow was for some unexpected results. Frightfully expensive,
|
||||
// but oh well.
|
||||
RootedObject stack(cx);
|
||||
if (!JS::CaptureCurrentStack(cx, &stack, 0))
|
||||
return nullptr;
|
||||
promise->setFixedSlot(PROMISE_ALLOCATION_SITE_SLOT, ObjectValue(*stack));
|
||||
Value now = JS::TimeValue(JS::TimeClip(static_cast<double>(PRMJ_Now()) /
|
||||
PRMJ_USEC_PER_MSEC));
|
||||
promise->setFixedSlot(PROMISE_ALLOCATION_TIME_SLOT, now);
|
||||
if (cx->runtime()->options().asyncStack() || cx->compartment()->isDebuggee()) {
|
||||
if (!JS::CaptureCurrentStack(cx, &stack, 0))
|
||||
return nullptr;
|
||||
}
|
||||
promise->setFixedSlot(PROMISE_ALLOCATION_SITE_SLOT, ObjectOrNullValue(stack));
|
||||
promise->setFixedSlot(PROMISE_ALLOCATION_TIME_SLOT, Now());
|
||||
}
|
||||
|
||||
RootedValue promiseVal(cx, ObjectValue(*promise));
|
||||
|
@ -110,30 +148,10 @@ PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /
|
|||
// The resolving functions are created in the compartment active when the
|
||||
// (maybe wrapped) Promise constructor was called. They contain checks and
|
||||
// can unwrap the Promise if required.
|
||||
RootedValue resolvingFunctionsVal(cx);
|
||||
if (!GlobalObject::getIntrinsicValue(cx, cx->global(), cx->names().CreateResolvingFunctions,
|
||||
&resolvingFunctionsVal))
|
||||
{
|
||||
RootedValue resolveVal(cx);
|
||||
RootedValue rejectVal(cx);
|
||||
if (!CreateResolvingFunctions(cx, promiseVal, &resolveVal, &rejectVal))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedArrayObject resolvingFunctions(cx);
|
||||
{
|
||||
FixedInvokeArgs<1> args(cx);
|
||||
|
||||
args[0].set(promiseVal);
|
||||
|
||||
RootedValue rval(cx);
|
||||
if (!Call(cx, resolvingFunctionsVal, UndefinedHandleValue, args, &rval))
|
||||
return nullptr;
|
||||
|
||||
resolvingFunctions = &rval.toObject().as<ArrayObject>();
|
||||
}
|
||||
|
||||
RootedValue resolveVal(cx, resolvingFunctions->getDenseElement(0));
|
||||
MOZ_ASSERT(IsCallable(resolveVal));
|
||||
RootedValue rejectVal(cx, resolvingFunctions->getDenseElement(1));
|
||||
MOZ_ASSERT(IsCallable(rejectVal));
|
||||
|
||||
// Need to wrap the resolution functions before storing them on the Promise.
|
||||
if (wrappedProto) {
|
||||
|
@ -181,6 +199,7 @@ PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Let the Debugger know about this Promise.
|
||||
JS::dbg::onNewPromise(cx, promise);
|
||||
|
||||
// Step 11.
|
||||
|
@ -192,7 +211,7 @@ namespace {
|
|||
mozilla::Atomic<uint64_t> gIDGenerator(0);
|
||||
} // namespace
|
||||
|
||||
double
|
||||
uint64_t
|
||||
PromiseObject::getID()
|
||||
{
|
||||
Value idVal(getReservedSlot(PROMISE_ID_SLOT));
|
||||
|
@ -200,7 +219,7 @@ PromiseObject::getID()
|
|||
idVal.setDouble(++gIDGenerator);
|
||||
setReservedSlot(PROMISE_ID_SLOT, idVal);
|
||||
}
|
||||
return idVal.toNumber();
|
||||
return uint64_t(idVal.toNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -391,6 +410,124 @@ PromiseObject::reject(JSContext* cx, HandleValue rejectionValue)
|
|||
return Call(cx, funVal, UndefinedHandleValue, args, &dummy);
|
||||
}
|
||||
|
||||
void PromiseObject::onSettled(JSContext* cx)
|
||||
{
|
||||
Rooted<PromiseObject*> promise(cx, this);
|
||||
RootedObject stack(cx);
|
||||
if (cx->runtime()->options().asyncStack() || cx->compartment()->isDebuggee()) {
|
||||
if (!JS::CaptureCurrentStack(cx, &stack, 0)) {
|
||||
cx->clearPendingException();
|
||||
return;
|
||||
}
|
||||
}
|
||||
promise->setFixedSlot(PROMISE_RESOLUTION_SITE_SLOT, ObjectOrNullValue(stack));
|
||||
promise->setFixedSlot(PROMISE_RESOLUTION_TIME_SLOT, Now());
|
||||
|
||||
if (promise->state() == JS::PromiseState::Rejected &&
|
||||
promise->getFixedSlot(PROMISE_IS_HANDLED_SLOT).toInt32() !=
|
||||
PROMISE_IS_HANDLED_STATE_HANDLED)
|
||||
{
|
||||
cx->runtime()->addUnhandledRejectedPromise(cx, promise);
|
||||
}
|
||||
|
||||
JS::dbg::onPromiseSettled(cx, promise);
|
||||
}
|
||||
|
||||
// ES6, 25.4.2.1.
|
||||
bool
|
||||
PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedFunction job(cx, &args.callee().as<JSFunction>());
|
||||
RootedNativeObject jobArgs(cx, &job->getExtendedSlot(0).toObject().as<NativeObject>());
|
||||
|
||||
RootedValue argument(cx, jobArgs->getDenseElement(1));
|
||||
|
||||
// Step 1 (omitted).
|
||||
|
||||
// Steps 2-3.
|
||||
RootedValue handlerVal(cx, jobArgs->getDenseElement(0));
|
||||
RootedValue handlerResult(cx);
|
||||
bool shouldReject = false;
|
||||
|
||||
// Steps 4-7.
|
||||
if (handlerVal.isNumber()) {
|
||||
int32_t handlerNum = int32_t(handlerVal.toNumber());
|
||||
// Step 4.
|
||||
if (handlerNum == PROMISE_HANDLER_IDENTITY) {
|
||||
handlerResult = argument;
|
||||
} else {
|
||||
// Step 5.
|
||||
MOZ_ASSERT(handlerNum == PROMISE_HANDLER_THROWER);
|
||||
shouldReject = true;
|
||||
handlerResult = argument;
|
||||
}
|
||||
} else {
|
||||
// Step 6.
|
||||
FixedInvokeArgs<1> args2(cx);
|
||||
args2[0].set(argument);
|
||||
if (!Call(cx, handlerVal, UndefinedHandleValue, args2, &handlerResult)) {
|
||||
shouldReject = true;
|
||||
// Not much we can do about uncatchable exceptions, so just bail
|
||||
// for those.
|
||||
if (!cx->isExceptionPending() || !GetAndClearException(cx, &handlerResult))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 7-9.
|
||||
FixedInvokeArgs<1> args2(cx);
|
||||
args2[0].set(handlerResult);
|
||||
RootedValue calleeOrRval(cx);
|
||||
if (shouldReject) {
|
||||
calleeOrRval = jobArgs->getDenseElement(3);
|
||||
} else {
|
||||
calleeOrRval = jobArgs->getDenseElement(2);
|
||||
}
|
||||
bool result = Call(cx, calleeOrRval, UndefinedHandleValue, args2, &calleeOrRval);
|
||||
|
||||
args.rval().set(calleeOrRval);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ES6, 25.4.2.2.
|
||||
bool
|
||||
PromiseResolveThenableJob(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedFunction job(cx, &args.callee().as<JSFunction>());
|
||||
RootedNativeObject jobArgs(cx, &job->getExtendedSlot(0).toObject().as<NativeObject>());
|
||||
|
||||
RootedValue promise(cx, jobArgs->getDenseElement(2));
|
||||
RootedValue then(cx, jobArgs->getDenseElement(0));
|
||||
RootedValue thenable(cx, jobArgs->getDenseElement(1));
|
||||
|
||||
// Step 1.
|
||||
RootedValue resolveVal(cx);
|
||||
RootedValue rejectVal(cx);
|
||||
if (!CreateResolvingFunctions(cx, promise, &resolveVal, &rejectVal))
|
||||
return false;
|
||||
|
||||
// Step 2.
|
||||
FixedInvokeArgs<2> args2(cx);
|
||||
args2[0].set(resolveVal);
|
||||
args2[1].set(rejectVal);
|
||||
|
||||
RootedValue rval(cx);
|
||||
|
||||
// In difference to the usual pattern, we return immediately on success.
|
||||
if (Call(cx, then, thenable, args2, &rval))
|
||||
return true;
|
||||
|
||||
if (!GetAndClearException(cx, &rval))
|
||||
return false;
|
||||
|
||||
FixedInvokeArgs<1> rejectArgs(cx);
|
||||
rejectArgs[0].set(rval);
|
||||
|
||||
return Call(cx, rejectVal, UndefinedHandleValue, rejectArgs, &rval);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
static JSObject*
|
||||
|
|
|
@ -19,7 +19,7 @@ class AutoSetNewObjectMetadata;
|
|||
class PromiseObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 11;
|
||||
static const unsigned RESERVED_SLOTS = 12;
|
||||
static const Class class_;
|
||||
static const Class protoClass_;
|
||||
static PromiseObject* create(JSContext* cx, HandleObject executor,
|
||||
|
@ -42,10 +42,16 @@ class PromiseObject : public NativeObject
|
|||
MOZ_MUST_USE bool resolve(JSContext* cx, HandleValue resolutionValue);
|
||||
MOZ_MUST_USE bool reject(JSContext* cx, HandleValue rejectionValue);
|
||||
|
||||
void onSettled(JSContext* cx);
|
||||
|
||||
double allocationTime() { return getFixedSlot(PROMISE_ALLOCATION_TIME_SLOT).toNumber(); }
|
||||
double resolutionTime() { return getFixedSlot(PROMISE_RESOLUTION_TIME_SLOT).toNumber(); }
|
||||
JSObject* allocationSite() { return &getFixedSlot(PROMISE_ALLOCATION_SITE_SLOT).toObject(); }
|
||||
JSObject* resolutionSite() { return &getFixedSlot(PROMISE_RESOLUTION_SITE_SLOT).toObject(); }
|
||||
JSObject* allocationSite() {
|
||||
return getFixedSlot(PROMISE_ALLOCATION_SITE_SLOT).toObjectOrNull();
|
||||
}
|
||||
JSObject* resolutionSite() {
|
||||
return getFixedSlot(PROMISE_RESOLUTION_SITE_SLOT).toObjectOrNull();
|
||||
}
|
||||
double lifetime() {
|
||||
double now = JS::TimeClip(static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_MSEC).toDouble();
|
||||
return now - allocationTime();
|
||||
|
@ -55,9 +61,23 @@ class PromiseObject : public NativeObject
|
|||
return resolutionTime() - allocationTime();
|
||||
}
|
||||
MOZ_MUST_USE bool dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values);
|
||||
double getID();
|
||||
uint64_t getID();
|
||||
bool markedAsUncaught() {
|
||||
return getFixedSlot(PROMISE_IS_HANDLED_SLOT).toInt32() != PROMISE_IS_HANDLED_STATE_HANDLED;
|
||||
}
|
||||
void markAsReported() {
|
||||
MOZ_ASSERT(getFixedSlot(PROMISE_IS_HANDLED_SLOT).toInt32() ==
|
||||
PROMISE_IS_HANDLED_STATE_UNHANDLED);
|
||||
setFixedSlot(PROMISE_IS_HANDLED_SLOT, Int32Value(PROMISE_IS_HANDLED_STATE_REPORTED));
|
||||
}
|
||||
};
|
||||
|
||||
// ES6, 25.4.2.1.
|
||||
bool PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// ES6, 25.4.2.2.
|
||||
bool PromiseResolveThenableJob(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_Promise_h */
|
||||
|
|
|
@ -124,6 +124,7 @@ function FulfillUnwrappedPromise(value) {
|
|||
}
|
||||
|
||||
// Commoned-out implementation of 25.4.1.4. and 25.4.1.7.
|
||||
// ES2016 February 12 draft.
|
||||
function ResolvePromise(promise, valueOrReason, reactionsSlot, state) {
|
||||
// Step 1.
|
||||
assert(GetPromiseState(promise) === PROMISE_STATE_PENDING,
|
||||
|
@ -151,12 +152,11 @@ function ResolvePromise(promise, valueOrReason, reactionsSlot, state) {
|
|||
UnsafeSetReservedSlot(promise, PROMISE_REJECT_FUNCTION_SLOT, null);
|
||||
|
||||
// Now that everything else is done, do the things the debugger needs.
|
||||
let site = _dbg_captureCurrentStack(0);
|
||||
UnsafeSetReservedSlot(promise, PROMISE_RESOLUTION_SITE_SLOT, site);
|
||||
UnsafeSetReservedSlot(promise, PROMISE_RESOLUTION_TIME_SLOT, std_Date_now());
|
||||
// Step 7 of RejectPromise implemented in the debugger intrinsic.
|
||||
_dbg_onPromiseSettled(promise);
|
||||
|
||||
// Step 7.
|
||||
// Step 7 of FulfillPromise.
|
||||
// Step 8 of RejectPromise.
|
||||
return TriggerPromiseReactions(reactions, valueOrReason);
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ function NewPromiseCapability(C) {
|
|||
|
||||
// ES6, 25.4.1.6. is implemented as an intrinsic in SelfHosting.cpp.
|
||||
|
||||
// ES6, 25.4.1.7.
|
||||
// ES2016, February 12 draft, 25.4.1.7.
|
||||
function RejectPromise(promise, reason) {
|
||||
return ResolvePromise(promise, reason, PROMISE_REJECT_REACTIONS_SLOT, PROMISE_STATE_REJECTED);
|
||||
}
|
||||
|
@ -222,66 +222,26 @@ function TriggerPromiseReactions(reactions, argument) {
|
|||
// Step 2 (implicit).
|
||||
}
|
||||
|
||||
// ES2016, February 12 draft 25.4.1.9, implemented in SelfHosting.cpp.
|
||||
|
||||
// ES6, 25.4.2.1.
|
||||
function EnqueuePromiseReactionJob(reaction, argument) {
|
||||
_EnqueuePromiseJob(function PromiseReactionJob() {
|
||||
// Step 1.
|
||||
assert(IsPromiseReaction(reaction), "Invalid promise reaction record");
|
||||
|
||||
// Step 2.
|
||||
let promiseCapability = reaction.capabilities;
|
||||
|
||||
// Step 3.
|
||||
let handler = reaction.handler;
|
||||
let handlerResult = argument;
|
||||
let shouldReject = false;
|
||||
|
||||
// Steps 4-6.
|
||||
if (handler === PROMISE_HANDLER_IDENTITY) {
|
||||
// handlerResult = argument; (implicit)
|
||||
} else if (handler === PROMISE_HANDLER_THROWER) {
|
||||
// handlerResult = argument; (implicit)
|
||||
shouldReject = true;
|
||||
} else {
|
||||
try {
|
||||
handlerResult = callContentFunction(handler, undefined, argument);
|
||||
} catch (e) {
|
||||
handlerResult = e;
|
||||
shouldReject = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7.
|
||||
if (shouldReject) {
|
||||
// Step 7.a.
|
||||
callContentFunction(promiseCapability.reject, undefined, handlerResult);
|
||||
|
||||
// Step 7.b.
|
||||
return;
|
||||
}
|
||||
|
||||
// Steps 8-9.
|
||||
return callContentFunction(promiseCapability.resolve, undefined, handlerResult);
|
||||
});
|
||||
let capabilities = reaction.capabilities;
|
||||
_EnqueuePromiseReactionJob([reaction.handler,
|
||||
argument,
|
||||
capabilities.resolve,
|
||||
capabilities.reject
|
||||
],
|
||||
capabilities.promise);
|
||||
}
|
||||
|
||||
// ES6, 25.4.2.2.
|
||||
function EnqueuePromiseResolveThenableJob(promiseToResolve, thenable, then) {
|
||||
_EnqueuePromiseJob(function PromiseResolveThenableJob() {
|
||||
// Step 1.
|
||||
let {0: resolve, 1: reject} = CreateResolvingFunctions(promiseToResolve);
|
||||
|
||||
// Steps 2-3.
|
||||
try {
|
||||
// Step 2.
|
||||
callContentFunction(then, thenable, resolve, reject);
|
||||
} catch (thenCallResult) {
|
||||
// Steps 3.a-b.
|
||||
callFunction(reject, undefined, thenCallResult);
|
||||
}
|
||||
|
||||
// Step 4 (implicit, no need to return anything).
|
||||
});
|
||||
_EnqueuePromiseResolveThenableJob([then,
|
||||
thenable,
|
||||
promiseToResolve
|
||||
],
|
||||
promiseToResolve);
|
||||
}
|
||||
|
||||
// ES6, 25.4.3.1. (Implemented in C++).
|
||||
|
@ -901,7 +861,7 @@ function UnwrappedPerformPromiseThen(fulfilledHandler, rejectedHandler, promise,
|
|||
resultCapability);
|
||||
}
|
||||
|
||||
// ES6, 25.4.5.3.1.
|
||||
// ES2016, March 1, 2016 draft, 25.4.5.3.1.
|
||||
function PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability) {
|
||||
// Step 1.
|
||||
assert(IsPromise(promise), "Can't call PerformPromiseThen on non-Promise objects");
|
||||
|
@ -955,15 +915,28 @@ function PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)
|
|||
}
|
||||
|
||||
// Step 9.
|
||||
else if (state === PROMISE_STATE_REJECTED) {
|
||||
else {
|
||||
// Step 9.a.
|
||||
let reason = UnsafeGetReservedSlot(promise, PROMISE_RESULT_SLOT);
|
||||
assert(state === PROMISE_STATE_REJECTED, "Invalid Promise state " + state);
|
||||
|
||||
// Step 9.b.
|
||||
let reason = UnsafeGetReservedSlot(promise, PROMISE_RESULT_SLOT);
|
||||
|
||||
// Step 9.c.
|
||||
if (UnsafeGetInt32FromReservedSlot(promise, PROMISE_IS_HANDLED_SLOT) !==
|
||||
PROMISE_IS_HANDLED_STATE_HANDLED)
|
||||
{
|
||||
HostPromiseRejectionTracker(promise, PROMISE_REJECTION_TRACKER_OPERATION_HANDLE);
|
||||
}
|
||||
|
||||
// Step 9.d.
|
||||
EnqueuePromiseReactionJob(rejectReaction, reason);
|
||||
}
|
||||
|
||||
// Step 10.
|
||||
UnsafeSetReservedSlot(promise, PROMISE_IS_HANDLED_SLOT, PROMISE_IS_HANDLED_STATE_HANDLED);
|
||||
|
||||
// Step 11.
|
||||
return resultCapability.promise;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,22 @@
|
|||
#define PROMISE_ALLOCATION_TIME_SLOT 8
|
||||
#define PROMISE_RESOLUTION_TIME_SLOT 9
|
||||
#define PROMISE_ID_SLOT 10
|
||||
#define PROMISE_IS_HANDLED_SLOT 11
|
||||
|
||||
#define PROMISE_STATE_PENDING 0
|
||||
#define PROMISE_STATE_FULFILLED 1
|
||||
#define PROMISE_STATE_REJECTED 2
|
||||
|
||||
#define PROMISE_IS_HANDLED_STATE_HANDLED 0
|
||||
#define PROMISE_IS_HANDLED_STATE_UNHANDLED 1
|
||||
#define PROMISE_IS_HANDLED_STATE_REPORTED 2
|
||||
|
||||
#define PROMISE_HANDLER_IDENTITY 0
|
||||
#define PROMISE_HANDLER_THROWER 1
|
||||
|
||||
#define PROMISE_REJECTION_TRACKER_OPERATION_REJECT false
|
||||
#define PROMISE_REJECTION_TRACKER_OPERATION_HANDLE true
|
||||
|
||||
// NB: keep these in sync with the copy in jsfriendapi.h.
|
||||
#define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
|
||||
#define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
|
||||
|
|
|
@ -853,9 +853,10 @@ class GCRuntime
|
|||
bool isVerifyPreBarriersEnabled() const { return false; }
|
||||
#endif
|
||||
|
||||
// Free certain LifoAlloc blocks from the background sweep thread.
|
||||
// Free certain LifoAlloc blocks when it is safe to do so.
|
||||
void freeUnusedLifoBlocksAfterSweeping(LifoAlloc* lifo);
|
||||
void freeAllLifoBlocksAfterSweeping(LifoAlloc* lifo);
|
||||
void freeAllLifoBlocksAfterMinorGC(LifoAlloc* lifo);
|
||||
|
||||
// Public here for ReleaseArenaLists and FinalizeTypedArenas.
|
||||
void releaseArena(Arena* arena, const AutoLockGC& lock);
|
||||
|
@ -1169,9 +1170,15 @@ class GCRuntime
|
|||
|
||||
/*
|
||||
* Free LIFO blocks are transferred to this allocator before being freed on
|
||||
* the background GC thread.
|
||||
* the background GC thread after sweeping.
|
||||
*/
|
||||
LifoAlloc freeLifoAlloc;
|
||||
LifoAlloc blocksToFreeAfterSweeping;
|
||||
|
||||
/*
|
||||
* Free LIFO blocks are transferred to this allocator before being freed
|
||||
* after minor GC.
|
||||
*/
|
||||
LifoAlloc blocksToFreeAfterMinorGC;
|
||||
|
||||
/* Index of current zone group (for stats). */
|
||||
unsigned zoneGroupIndex;
|
||||
|
|
|
@ -219,12 +219,6 @@ Zone::discardJitCode(FreeOp* fop)
|
|||
/* Only mark OSI points if code is being discarded. */
|
||||
jit::InvalidateAll(fop, this);
|
||||
|
||||
/* The storebuffer may contain pointers into data owned by BaselineScript. */
|
||||
JSRuntime* rt = runtimeFromMainThread();
|
||||
if (!rt->isHeapCollecting())
|
||||
rt->gc.evictNursery();
|
||||
MOZ_ASSERT(rt->gc.nursery.isEmpty());
|
||||
|
||||
for (ZoneCellIter i(this, AllocKind::SCRIPT); !i.done(); i.next()) {
|
||||
JSScript* script = i.get<JSScript>();
|
||||
jit::FinishInvalidation(fop, script);
|
||||
|
@ -243,7 +237,15 @@ Zone::discardJitCode(FreeOp* fop)
|
|||
script->resetWarmUpCounter();
|
||||
}
|
||||
|
||||
jitZone()->optimizedStubSpace()->free();
|
||||
/*
|
||||
* When scripts contains pointers to nursery things, the store buffer
|
||||
* can contain entries that point into the optimized stub space. Since
|
||||
* this method can be called outside the context of a GC, this situation
|
||||
* could result in us trying to mark invalid store buffer entries.
|
||||
*
|
||||
* Defer freeing any allocated blocks until after the next minor GC.
|
||||
*/
|
||||
jitZone()->optimizedStubSpace()->freeAllAfterMinorGC(fop->runtime());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
options("strict", "werror");
|
||||
|
||||
var o = {};
|
||||
var failureCode = 0;
|
||||
|
||||
try {
|
||||
// Don't throw here.
|
||||
if (o.a || o.b)
|
||||
failureCode = 1;
|
||||
} catch (e) {
|
||||
failureCode = 2
|
||||
}
|
||||
assertEq(failureCode, 0);
|
|
@ -0,0 +1,36 @@
|
|||
if (typeof Promise === "undefined")
|
||||
quit(0);
|
||||
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger();
|
||||
let gw = dbg.addDebuggee(g);
|
||||
|
||||
g.promise = Promise.resolve(42);
|
||||
|
||||
let promiseDO = gw.getOwnPropertyDescriptor('promise').value;
|
||||
|
||||
assertEq(promiseDO.isPromise, true);
|
||||
|
||||
let state = promiseDO.promiseState;
|
||||
assertEq(state.state, "fulfilled");
|
||||
assertEq(state.value, 42);
|
||||
assertEq("reason" in state, true);
|
||||
assertEq(state.reason, undefined);
|
||||
|
||||
let allocationSite = promiseDO.promiseAllocationSite;
|
||||
// Depending on whether async stacks are activated, this can be null, which
|
||||
// has typeof null.
|
||||
assertEq(typeof allocationSite === "object", true);
|
||||
|
||||
let resolutionSite = promiseDO.promiseResolutionSite;
|
||||
// Depending on whether async stacks are activated, this can be null, which
|
||||
// has typeof null.
|
||||
assertEq(typeof resolutionSite === "object", true);
|
||||
|
||||
assertEq(promiseDO.promiseID, 1);
|
||||
|
||||
assertEq(typeof promiseDO.promiseDependentPromises, "object");
|
||||
assertEq(promiseDO.promiseDependentPromises.length, 0);
|
||||
|
||||
assertEq(typeof promiseDO.promiseLifetime, "number");
|
||||
assertEq(typeof promiseDO.promiseTimeToResolution, "number");
|
|
@ -208,7 +208,8 @@ BaselineCompiler::compile()
|
|||
pcMappingIndexEntries.length(),
|
||||
pcEntries.length(),
|
||||
bytecodeTypeMapEntries,
|
||||
yieldOffsets_.length()));
|
||||
yieldOffsets_.length()),
|
||||
JS::DeletePolicy<BaselineScript>(cx->runtime()));
|
||||
if (!baselineScript) {
|
||||
ReportOutOfMemory(cx);
|
||||
return Method_Error;
|
||||
|
|
|
@ -871,9 +871,6 @@ jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext* cx,
|
|||
if (entries.empty())
|
||||
return true;
|
||||
|
||||
// Scripts can entrain nursery things. See note in js::ReleaseAllJITCode.
|
||||
cx->runtime()->gc.evictNursery();
|
||||
|
||||
// When the profiler is enabled, we need to have suppressed sampling,
|
||||
// since the basline jit scripts are in a state of flux.
|
||||
MOZ_ASSERT(!cx->runtime()->isProfilerSamplingEnabled());
|
||||
|
|
|
@ -45,6 +45,12 @@ PCMappingSlotInfo::ToSlotLocation(const StackValue* stackVal)
|
|||
return SlotIgnore;
|
||||
}
|
||||
|
||||
void
|
||||
ICStubSpace::freeAllAfterMinorGC(JSRuntime* rt)
|
||||
{
|
||||
rt->gc.freeAllLifoBlocksAfterMinorGC(&allocator_);
|
||||
}
|
||||
|
||||
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
|
@ -482,22 +488,29 @@ BaselineScript::Trace(JSTracer* trc, BaselineScript* script)
|
|||
void
|
||||
BaselineScript::Destroy(FreeOp* fop, BaselineScript* script)
|
||||
{
|
||||
/*
|
||||
* When the script contains pointers to nursery things, the store buffer
|
||||
* will contain entries refering to the referenced things. Since we can
|
||||
* destroy scripts outside the context of a GC, this situation can result
|
||||
* in invalid store buffer entries. Assert that if we do destroy scripts
|
||||
* outside of a GC that we at least emptied the nursery first.
|
||||
*/
|
||||
MOZ_ASSERT(fop->runtime()->gc.nursery.isEmpty());
|
||||
|
||||
MOZ_ASSERT(!script->hasPendingIonBuilder());
|
||||
|
||||
script->unlinkDependentWasmModules(fop);
|
||||
|
||||
/*
|
||||
* When the script contains pointers to nursery things, the store buffer can
|
||||
* contain entries that point into the fallback stub space. Since we can
|
||||
* destroy scripts outside the context of a GC, this situation could result
|
||||
* in us trying to mark invalid store buffer entries.
|
||||
*
|
||||
* Defer freeing any allocated blocks until after the next minor GC.
|
||||
*/
|
||||
script->fallbackStubSpace_.freeAllAfterMinorGC(fop->runtime());
|
||||
|
||||
fop->delete_(script);
|
||||
}
|
||||
|
||||
void
|
||||
JS::DeletePolicy<js::jit::BaselineScript>::operator()(const js::jit::BaselineScript* script)
|
||||
{
|
||||
BaselineScript::Destroy(rt_->defaultFreeOp(), const_cast<BaselineScript*>(script));
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::clearDependentWasmModules()
|
||||
{
|
||||
|
|
|
@ -245,6 +245,12 @@ struct BaselineScript
|
|||
uint32_t traceLoggerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset);
|
||||
|
||||
~BaselineScript() {
|
||||
// The contents of the fallback stub space are removed and freed
|
||||
// separately after the next minor GC. See BaselineScript::Destroy.
|
||||
MOZ_ASSERT(fallbackStubSpace_.isEmpty());
|
||||
}
|
||||
|
||||
static BaselineScript* New(JSScript* jsscript, uint32_t prologueOffset,
|
||||
uint32_t epilogueOffset, uint32_t postDebugPrologueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
|
@ -599,4 +605,18 @@ BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumentation
|
|||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
namespace JS {
|
||||
|
||||
template <>
|
||||
struct DeletePolicy<js::jit::BaselineScript>
|
||||
{
|
||||
explicit DeletePolicy(JSRuntime* rt) : rt_(rt) {}
|
||||
void operator()(const js::jit::BaselineScript* script);
|
||||
|
||||
private:
|
||||
JSRuntime* rt_;
|
||||
};
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* jit_BaselineJIT_h */
|
||||
|
|
|
@ -3470,20 +3470,8 @@ CodeGenerator::emitPostWriteBarrier(Register objreg)
|
|||
void
|
||||
CodeGenerator::visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier* ool)
|
||||
{
|
||||
const LAllocation* obj = ool->object();
|
||||
|
||||
// Check whether the object is a global that we have already barriered
|
||||
// before calling into the VM.
|
||||
if (obj->isConstant()) {
|
||||
JSObject* object = &obj->toConstant()->toObject();
|
||||
if (object->is<GlobalObject>()) {
|
||||
JSCompartment* comp = object->compartment();
|
||||
AbsoluteAddress addr(&comp->globalWriteBarriered);
|
||||
masm.branch32(Assembler::NotEqual, addr, Imm32(0), ool->rejoin());
|
||||
}
|
||||
}
|
||||
|
||||
saveLiveVolatile(ool->lir());
|
||||
const LAllocation* obj = ool->object();
|
||||
emitPostWriteBarrier(obj);
|
||||
restoreLiveVolatile(ool->lir());
|
||||
|
||||
|
|
|
@ -35,6 +35,14 @@ class ICStubSpace
|
|||
|
||||
JS_DECLARE_NEW_METHODS(allocate, alloc, inline)
|
||||
|
||||
void freeAllAfterMinorGC(JSRuntime* rt);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool isEmpty() const {
|
||||
return allocator_.isEmpty();
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return allocator_.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
@ -50,10 +58,6 @@ struct OptimizedICStubSpace : public ICStubSpace
|
|||
OptimizedICStubSpace()
|
||||
: ICStubSpace(STUB_DEFAULT_CHUNK_SIZE)
|
||||
{}
|
||||
|
||||
void free() {
|
||||
allocator_.freeAll();
|
||||
}
|
||||
};
|
||||
|
||||
// Space for fallback stubs. Every BaselineScript has a
|
||||
|
|
|
@ -1220,9 +1220,26 @@ void
|
|||
IonScript::Destroy(FreeOp* fop, IonScript* script)
|
||||
{
|
||||
script->unlinkFromRuntime(fop);
|
||||
|
||||
/*
|
||||
* When the script contains pointers to nursery things, the store buffer can
|
||||
* contain entries that point into the fallback stub space. Since we can
|
||||
* destroy scripts outside the context of a GC, this situation could result
|
||||
* in us trying to mark invalid store buffer entries.
|
||||
*
|
||||
* Defer freeing any allocated blocks until after the next minor GC.
|
||||
*/
|
||||
script->fallbackStubSpace_.freeAllAfterMinorGC(fop->runtime());
|
||||
|
||||
fop->delete_(script);
|
||||
}
|
||||
|
||||
void
|
||||
JS::DeletePolicy<js::jit::IonScript>::operator()(const js::jit::IonScript* script)
|
||||
{
|
||||
IonScript::Destroy(rt_->defaultFreeOp(), const_cast<IonScript*>(script));
|
||||
}
|
||||
|
||||
void
|
||||
IonScript::toggleBarriers(bool enabled, ReprotectCode reprotect)
|
||||
{
|
||||
|
|
|
@ -331,6 +331,12 @@ struct IonScript
|
|||
// Do not call directly, use IonScript::New. This is public for cx->new_.
|
||||
IonScript();
|
||||
|
||||
~IonScript() {
|
||||
// The contents of the fallback stub space are removed and freed
|
||||
// separately after the next minor GC. See IonScript::Destroy.
|
||||
MOZ_ASSERT(fallbackStubSpace_.isEmpty());
|
||||
}
|
||||
|
||||
static IonScript* New(JSContext* cx, RecompileInfo recompileInfo,
|
||||
uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
|
||||
size_t snapshotsListSize, size_t snapshotsRVATableSize,
|
||||
|
@ -798,6 +804,17 @@ struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
|
|||
};
|
||||
|
||||
} // namespace ubi
|
||||
|
||||
template <>
|
||||
struct DeletePolicy<js::jit::IonScript>
|
||||
{
|
||||
explicit DeletePolicy(JSRuntime* rt) : rt_(rt) {}
|
||||
void operator()(const js::jit::IonScript* script);
|
||||
|
||||
private:
|
||||
JSRuntime* rt_;
|
||||
};
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* jit_IonCode_h */
|
||||
|
|
|
@ -632,7 +632,7 @@ PostGlobalWriteBarrier(JSRuntime* rt, JSObject* obj)
|
|||
MOZ_ASSERT(obj->is<GlobalObject>());
|
||||
if (!obj->compartment()->globalWriteBarriered) {
|
||||
PostWriteBarrier(rt, obj);
|
||||
obj->compartment()->globalWriteBarriered = 1;
|
||||
obj->compartment()->globalWriteBarriered = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4777,6 +4777,14 @@ JS::SetEnqueuePromiseJobCallback(JSRuntime* rt, JSEnqueuePromiseJobCallback call
|
|||
rt->enqueuePromiseJobCallbackData = data;
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS::SetPromiseRejectionTrackerCallback(JSRuntime* rt, JSPromiseRejectionTrackerCallback callback,
|
||||
void* data /* = nullptr */)
|
||||
{
|
||||
rt->promiseRejectionTrackerCallback = callback;
|
||||
rt->promiseRejectionTrackerCallbackData = data;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
|
||||
{
|
||||
|
@ -4818,7 +4826,7 @@ JS::GetPromiseState(JS::HandleObject obj)
|
|||
return promise->as<PromiseObject>().state();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(double)
|
||||
JS_PUBLIC_API(uint64_t)
|
||||
JS::GetPromiseID(JS::HandleObject promise)
|
||||
{
|
||||
return promise->as<PromiseObject>().getID();
|
||||
|
@ -5055,8 +5063,6 @@ JS_NewStringCopyN(JSContext* cx, const char* s, size_t n)
|
|||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
if (!n)
|
||||
return cx->names().empty;
|
||||
return NewStringCopyN<CanGC>(cx, s, n);
|
||||
}
|
||||
|
||||
|
@ -5065,7 +5071,7 @@ JS_NewStringCopyZ(JSContext* cx, const char* s)
|
|||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
if (!s || !*s)
|
||||
if (!s)
|
||||
return cx->runtime()->emptyString;
|
||||
return NewStringCopyZ<CanGC>(cx, s);
|
||||
}
|
||||
|
|
|
@ -603,7 +603,20 @@ typedef bool
|
|||
(* JSInterruptCallback)(JSContext* cx);
|
||||
|
||||
typedef bool
|
||||
(* JSEnqueuePromiseJobCallback)(JSContext* cx, JS::HandleObject job, void* data);
|
||||
(* JSEnqueuePromiseJobCallback)(JSContext* cx, JS::HandleObject job,
|
||||
JS::HandleObject allocationSite, void* data);
|
||||
|
||||
enum class PromiseRejectionHandlingState {
|
||||
Unhandled,
|
||||
Handled
|
||||
};
|
||||
|
||||
typedef void
|
||||
(* JSPromiseRejectionTrackerCallback)(JSContext* cx, JS::HandleObject promise,
|
||||
PromiseRejectionHandlingState state, void* data);
|
||||
|
||||
typedef void
|
||||
(* JSProcessPromiseCallback)(JSContext* cx, JS::HandleObject promise);
|
||||
|
||||
typedef void
|
||||
(* JSErrorReporter)(JSContext* cx, const char* message, JSErrorReport* report);
|
||||
|
@ -4402,13 +4415,23 @@ namespace JS {
|
|||
*
|
||||
* SpiderMonkey doesn't schedule Promise resolution jobs itself; instead,
|
||||
* using this function the embedding can provide a callback to do that
|
||||
* scheduling. The provided `callback` is invoked with the promise job
|
||||
* and the `data` pointer passed here as arguments.
|
||||
* scheduling. The provided `callback` is invoked with the promise job,
|
||||
* the corresponding Promise's allocation stack, and the `data` pointer
|
||||
* passed here as arguments.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
SetEnqueuePromiseJobCallback(JSRuntime* rt, JSEnqueuePromiseJobCallback callback,
|
||||
void* data = nullptr);
|
||||
|
||||
/**
|
||||
* Sets the callback that's invoked whenever a Promise is rejected without
|
||||
* a rejection handler, and when a Promise that was previously rejected
|
||||
* without a handler gets a handler attached.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
SetPromiseRejectionTrackerCallback(JSRuntime* rt, JSPromiseRejectionTrackerCallback callback,
|
||||
void* data = nullptr);
|
||||
|
||||
/**
|
||||
* Returns a new instance of the Promise builtin class in the current
|
||||
* compartment, with the right slot layout. If a `proto` is passed, that gets
|
||||
|
@ -4453,7 +4476,7 @@ GetPromiseState(JS::HandleObject promise);
|
|||
/**
|
||||
* Returns the given Promise's process-unique ID.
|
||||
*/
|
||||
JS_PUBLIC_API(double)
|
||||
JS_PUBLIC_API(uint64_t)
|
||||
GetPromiseID(JS::HandleObject promise);
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,7 +63,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
|
|||
allocationMetadataBuilder(nullptr),
|
||||
lastAnimationTime(0),
|
||||
regExps(runtime_),
|
||||
globalWriteBarriered(0),
|
||||
globalWriteBarriered(false),
|
||||
detachedTypedObjects(0),
|
||||
objectMetadataState(ImmediateMetadata()),
|
||||
propertyTree(thisForCtor()),
|
||||
|
@ -680,7 +680,7 @@ JSCompartment::traceRoots(JSTracer* trc, js::gc::GCRuntime::TraceOrMarkRuntime t
|
|||
void
|
||||
JSCompartment::sweepAfterMinorGC()
|
||||
{
|
||||
globalWriteBarriered = 0;
|
||||
globalWriteBarriered = false;
|
||||
|
||||
if (innerViews.needsSweepAfterMinorGC())
|
||||
innerViews.sweepAfterMinorGC();
|
||||
|
|
|
@ -427,10 +427,10 @@ struct JSCompartment
|
|||
* For generational GC, record whether a write barrier has added this
|
||||
* compartment's global to the store buffer since the last minor GC.
|
||||
*
|
||||
* This is used to avoid calling into the VM every time a nursery object is
|
||||
* written to a property of the global.
|
||||
* This is used to avoid adding it to the store buffer on every write, which
|
||||
* can quickly fill the buffer and also cause performance problems.
|
||||
*/
|
||||
uint32_t globalWriteBarriered;
|
||||
bool globalWriteBarriered;
|
||||
|
||||
// Non-zero if the storage underlying any typed object in this compartment
|
||||
// might be detached.
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче