Merge m-i to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2015-11-14 13:22:10 -08:00
commit 0cccf0ed58
269 changed files with 3669 additions and 2905 deletions

View File

@ -1494,34 +1494,34 @@ HyperTextAccessible::CaretLineNumber()
return lineNumber;
}
nsIntRect
LayoutDeviceIntRect
HyperTextAccessible::GetCaretRect(nsIWidget** aWidget)
{
*aWidget = nullptr;
RefPtr<nsCaret> caret = mDoc->PresShell()->GetCaret();
NS_ENSURE_TRUE(caret, nsIntRect());
NS_ENSURE_TRUE(caret, LayoutDeviceIntRect());
bool isVisible = caret->IsVisible();
if (!isVisible)
return nsIntRect();
return LayoutDeviceIntRect();
nsRect rect;
nsIFrame* frame = caret->GetGeometry(&rect);
if (!frame || rect.IsEmpty())
return nsIntRect();
return LayoutDeviceIntRect();
nsPoint offset;
// Offset from widget origin to the frame origin, which includes chrome
// on the widget.
*aWidget = frame->GetNearestWidget(offset);
NS_ENSURE_TRUE(*aWidget, nsIntRect());
NS_ENSURE_TRUE(*aWidget, LayoutDeviceIntRect());
rect.MoveBy(offset);
nsIntRect caretRect;
caretRect = rect.ToOutsidePixels(frame->PresContext()->AppUnitsPerDevPixel());
LayoutDeviceIntRect caretRect = LayoutDeviceIntRect::FromUnknownRect(
rect.ToOutsidePixels(frame->PresContext()->AppUnitsPerDevPixel()));
// ((content screen origin) - (content offset in the widget)) = widget origin on the screen
caretRect.MoveBy((*aWidget)->WidgetToScreenOffsetUntyped() - (*aWidget)->GetClientOffset());
caretRect.MoveBy((*aWidget)->WidgetToScreenOffset() - (*aWidget)->GetClientOffset());
// Correct for character size, so that caret always matches the size of
// the character. This is important for font size transitions, and is

View File

@ -335,7 +335,7 @@ public:
* @param [out] the widget containing the caret
* @return the caret rect
*/
nsIntRect GetCaretRect(nsIWidget** aWidget);
mozilla::LayoutDeviceIntRect GetCaretRect(nsIWidget** aWidget);
/**
* Return selected regions count within the accessible.

View File

@ -1633,7 +1633,7 @@ AccessibleWrap::UpdateSystemCaretFor(Accessible* aAccessible)
return;
nsIWidget* widget = nullptr;
nsIntRect caretRect = text->GetCaretRect(&widget);
LayoutDeviceIntRect caretRect = text->GetCaretRect(&widget);
HWND caretWnd;
if (caretRect.IsEmpty() || !(caretWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW))) {
return;

View File

@ -0,0 +1,84 @@
/* global Services, Preferences, EventEmitter, XPCOMUtils */
/* exported NewTabPrefsProvider */
"use strict";
this.EXPORTED_SYMBOLS = ["NewTabPrefsProvider"];
const {interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
return EventEmitter;
});
// Supported prefs and data type
const gPrefsMap = new Map([
["browser.newtabpage.enabled", "bool"],
["browser.newtabpage.enhanced", "bool"],
["browser.newtabpage.pinned", "str"],
["intl.locale.matchOS", "bool"],
["general.useragent.locale", "localized"],
]);
let PrefsProvider = function PrefsProvider() {
EventEmitter.decorate(this);
};
PrefsProvider.prototype = {
observe(subject, topic, data) { // jshint ignore:line
if (topic === "nsPref:changed") {
if (gPrefsMap.has(data)) {
switch (gPrefsMap.get(data)) {
case "bool":
this.emit(data, Preferences.get(data, false));
break;
case "str":
this.emit(data, Preferences.get(data, ""));
break;
case "localized":
try {
this.emit(data, Preferences.get(data, "", Ci.nsIPrefLocalizedString));
} catch (e) {
this.emit(data, Preferences.get(data, ""));
}
break;
default:
this.emit(data);
break;
}
}
} else {
Cu.reportError(new Error("NewTabPrefsProvider observing unknown topic"));
}
},
get prefsMap() {
return gPrefsMap;
},
init() {
for (let pref of gPrefsMap.keys()) {
Services.prefs.addObserver(pref, this, false);
}
},
uninit() {
for (let pref of gPrefsMap.keys()) {
Services.prefs.removeObserver(pref, this, false);
}
}
};
/**
* Singleton that serves as the default new tab pref provider for the grid.
*/
const gPrefs = new PrefsProvider();
let NewTabPrefsProvider = {
prefs: gPrefs,
};

View File

@ -1,9 +1,8 @@
/* 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/. */
/* globals Services, XPCOMUtils, RemotePages, RemoteNewTabLocation, RemoteNewTabUtils, Task */
/* globals BackgroundPageThumbs, PageThumbs, DirectoryLinksProvider */
/* globals BackgroundPageThumbs, PageThumbs, DirectoryLinksProvider, PlacesProvider, NewTabPrefsProvider */
/* exported RemoteAboutNewTab */
"use strict";
@ -31,6 +30,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "DirectoryLinksProvider",
"resource:///modules/DirectoryLinksProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabLocation",
"resource:///modules/RemoteNewTabLocation.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider",
"resource:///modules/PlacesProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
"resource:///modules/NewTabPrefsProvider.jsm");
let RemoteAboutNewTab = {
@ -43,6 +46,7 @@ let RemoteAboutNewTab = {
this.pageListener = new RemotePages("about:remote-newtab");
this.pageListener.addMessageListener("NewTab:InitializeGrid", this.initializeGrid.bind(this));
this.pageListener.addMessageListener("NewTab:UpdateGrid", this.updateGrid.bind(this));
this.pageListener.addMessageListener("NewTab:Customize", this.customize.bind(this));
this.pageListener.addMessageListener("NewTab:CaptureBackgroundPageThumbs",
this.captureBackgroundPageThumb.bind(this));
this.pageListener.addMessageListener("NewTab:PageThumbs", this.createPageThumb.bind(this));
@ -51,6 +55,43 @@ let RemoteAboutNewTab = {
this._addObservers();
},
customize: function(message) {
if (message.data.enabled !== undefined) {
Services.prefs.setBoolPref("browser.newtabpage.enabled", message.data.enabled);
}
if (message.data.enhanced !== undefined) {
Services.prefs.setBoolPref("browser.newtabpage.enhanced", message.data.enhanced);
}
},
/**
* Notifies when history is cleared
*/
placesClearHistory: function() {
this.pageListener.sendAsyncMessage("NewTab:PlacesClearHistory");
},
/**
* Notifies when a link has changed
*/
placesLinkChanged: function(name, data) { // jshint ignore:line
this.pageListener.sendAsyncMessage("NewTab:PlacesLinkChanged", data);
},
/**
* Notifies when many links have changed
*/
placesManyLinksChanged: function() {
this.pageListener.sendAsyncMessage("NewTab:PlacesManyLinksChanged");
},
/**
* Notifies when one URL has been deleted
*/
placesDeleteURI: function(name, data) { // jshint ignore:line
this.pageListener.sendAsyncMessage("NewTab:PlacesDeleteURI", data.url);
},
/**
* Initializes the grid for the first time when the page loads.
* Fetch all the links and send them down to the child to populate
@ -186,7 +227,6 @@ let RemoteAboutNewTab = {
*/
observe: function(aSubject, aTopic, aData) { // jshint ignore:line
let extraData;
let refreshPage = false;
if (aTopic === "browser:purge-session-history") {
RemoteNewTabUtils.links.resetCache();
RemoteNewTabUtils.links.populateCache(() => {
@ -206,12 +246,31 @@ let RemoteAboutNewTab = {
}
},
setEnabled: function(name, data) { // jshint ignore:line
this.pageListener.sendAsyncMessage("NewTab:setEnabled", data);
},
setEnhanced: function(name, data) { // jshint ignore:line
this.pageListener.sendAsyncMessage("NewTab:setEnhanced", data);
},
setPinned: function(name, data) { // jshint ignore:line
this.pageListener.sendAsyncMessage("NewTab:setPinnedLinks", data);
},
/**
* Add all observers that about:newtab page must listen for.
*/
_addObservers: function() {
Services.obs.addObserver(this, "page-thumbnail:create", true);
Services.obs.addObserver(this, "browser:purge-session-history", true);
PlacesProvider.links.on("deleteURI", this.placesDeleteURI.bind(this));
PlacesProvider.links.on("clearHistory", this.placesClearHistory.bind(this));
PlacesProvider.links.on("linkChanged", this.placesLinkChanged.bind(this));
PlacesProvider.links.on("manyLinksChanged", this.placesManyLinksChanged.bind(this));
NewTabPrefsProvider.prefs.on("browser.newtabpage.enabled", this.setEnabled.bind(this));
NewTabPrefsProvider.prefs.on("browser.newtabpage.enhanced", this.setEnhanced.bind(this));
NewTabPrefsProvider.prefs.on("browser.newtabpage.pinned", this.setPinned.bind(this));
},
/**
@ -220,6 +279,13 @@ let RemoteAboutNewTab = {
_removeObservers: function() {
Services.obs.removeObserver(this, "page-thumbnail:create");
Services.obs.removeObserver(this, "browser:purge-session-history");
PlacesProvider.links.off("deleteURI", this.placesDeleteURI);
PlacesProvider.links.off("clearHistory", this.placesClearHistory);
PlacesProvider.links.off("linkChanged", this.placesLinkChanged);
PlacesProvider.links.off("manyLinksChanged", this.placesManyLinksChanged);
NewTabPrefsProvider.prefs.off("browser.newtabpage.enabled", this.setEnabled.bind(this));
NewTabPrefsProvider.prefs.off("browser.newtabpage.enhanced", this.setEnhanced.bind(this));
NewTabPrefsProvider.prefs.off("browser.newtabpage.pinned", this.setPinned.bind(this));
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,

View File

@ -11,6 +11,7 @@ XPCSHELL_TESTS_MANIFESTS += [
]
EXTRA_JS_MODULES += [
'NewTabPrefsProvider.jsm',
'NewTabURL.jsm',
'PlacesProvider.jsm',
'RemoteAboutNewTab.jsm',

View File

@ -0,0 +1,51 @@
"use strict";
/* global XPCOMUtils, equal, Preferences, NewTabPrefsProvider, run_next_test */
/* exported run_test */
/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
"resource:///modules/NewTabPrefsProvider.jsm");
function run_test() {
run_next_test();
}
add_task(function* test_observe() {
let prefsMap = NewTabPrefsProvider.prefs.prefsMap;
for (let prefName of prefsMap.keys()) {
let prefValueType = prefsMap.get(prefName);
let beforeVal;
let afterVal;
switch (prefValueType) {
case "bool":
beforeVal = false;
afterVal = true;
Preferences.set(prefName, beforeVal);
break;
case "localized":
case "str":
beforeVal = "";
afterVal = "someStr";
Preferences.set(prefName, beforeVal);
break;
}
NewTabPrefsProvider.prefs.init();
let promise = new Promise(resolve => {
NewTabPrefsProvider.prefs.once(prefName, (name, data) => { // jshint ignore:line
resolve([name, data]);
});
});
Preferences.set(prefName, afterVal);
let [actualName, actualData] = yield promise;
equal(prefName, actualName, `emitter sent the correct pref: ${prefName}`);
equal(afterVal, actualData, `emitter collected correct pref data for ${prefName}`);
NewTabPrefsProvider.prefs.uninit();
}
});

View File

@ -5,6 +5,7 @@ firefox-appdir = browser
skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_AboutNewTabService.js]
[test_NewTabPrefsProvider.js]
[test_NewTabURL.js]
[test_PlacesProvider.js]
[test_RemoteNewTabLocation.js]

View File

@ -32,6 +32,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "RemoteAboutNewTab",
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
"resource:///modules/RemoteNewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
"resource:///modules/NewTabPrefsProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
"resource:///modules/UITour.jsm");
@ -849,6 +852,7 @@ BrowserGlue.prototype = {
RemoteNewTabUtils.init();
RemoteNewTabUtils.links.addProvider(DirectoryLinksProvider);
RemoteAboutNewTab.init();
NewTabPrefsProvider.prefs.init();
SessionStore.init();
BrowserUITelemetry.init();
@ -1170,6 +1174,7 @@ BrowserGlue.prototype = {
WebappManager.uninit();
RemoteAboutNewTab.uninit();
NewTabPrefsProvider.prefs.uninit();
AboutNewTab.uninit();
#ifdef NIGHTLY_BUILD
if (Services.prefs.getBoolPref("dom.identity.enabled")) {

View File

@ -1,12 +1,10 @@
[DEFAULT]
support-files = file_pdfjs_test.pdf
support-files =
file_pdfjs_test.pdf
head.js
[browser_pdfjs_main.js]
skip-if = e10s # Bug 1159385
[browser_pdfjs_navigation.js]
skip-if = e10s # Bug 1159385
[browser_pdfjs_savedialog.js]
[browser_pdfjs_views.js]
skip-if = e10s # Bug 1159385
[browser_pdfjs_zoom.js]
skip-if = e10s # Bug 1159385

View File

@ -4,9 +4,7 @@
const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
function test() {
var tab;
add_task(function* test() {
let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
@ -17,82 +15,53 @@ function test() {
info('Pref action: ' + handlerInfo.preferredAction);
waitForExplicitFinish();
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
yield BrowserTestUtils.withNewTab({ gBrowser: gBrowser, url: TESTROOT + "file_pdfjs_test.pdf" },
function* (newTabBrowser) {
ok(gBrowser.isFindBarInitialized(), "Browser FindBar initialized!");
tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
var newTabBrowser = gBrowser.getBrowserForTab(tab);
newTabBrowser.addEventListener("load", function eventHandler() {
newTabBrowser.removeEventListener("load", eventHandler, true);
yield waitForPdfJS(newTabBrowser);
var document = newTabBrowser.contentDocument,
window = newTabBrowser.contentWindow;
yield ContentTask.spawn(newTabBrowser, null, function* () {
//
// Overall sanity tests
//
ok(content.document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in content.wrappedJSObject, "window content has PDFJS object");
// Runs tests after all 'load' event handlers have fired off
window.addEventListener("documentload", function() {
runTests(document, window, tab, function () {
closePDFViewer(window, finish);
//
// Sidebar: open
//
var sidebar = content.document.querySelector('button#sidebarToggle'),
outerContainer = content.document.querySelector('div#outerContainer');
sidebar.click();
ok(outerContainer.classList.contains('sidebarOpen'), "sidebar opens on click");
//
// Sidebar: close
//
sidebar.click();
ok(!outerContainer.classList.contains('sidebarOpen'), "sidebar closes on click");
//
// Page change from prev/next buttons
//
var prevPage = content.document.querySelector('button#previous'),
nextPage = content.document.querySelector('button#next');
var pgNumber = content.document.querySelector('input#pageNumber').value;
is(parseInt(pgNumber, 10), 1, 'initial page is 1');
//
// Bookmark button
//
var viewBookmark = content.document.querySelector('a#viewBookmark');
viewBookmark.click();
ok(viewBookmark.href.length > 0, "viewBookmark button has href");
var viewer = content.wrappedJSObject.PDFViewerApplication;
yield viewer.close();
});
}, false, true);
}, true);
}
function runTests(document, window, tab, callback) {
//
// Overall sanity tests
//
ok(document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in window.wrappedJSObject, "window content has PDFJS object");
ok('PDFViewerApplication' in window.wrappedJSObject,
"window content has viewer object");
//
// Browser Find
//
ok(gBrowser.isFindBarInitialized(tab), "Browser FindBar initialized!");
//
// Sidebar: open
//
var sidebar = document.querySelector('button#sidebarToggle'),
outerContainer = document.querySelector('div#outerContainer');
sidebar.click();
ok(outerContainer.classList.contains('sidebarOpen'), 'sidebar opens on click');
//
// Sidebar: close
//
sidebar.click();
ok(!outerContainer.classList.contains('sidebarOpen'), 'sidebar closes on click');
//
// Page change from prev/next buttons
//
var prevPage = document.querySelector('button#previous'),
nextPage = document.querySelector('button#next');
var pageNumber = document.querySelector('input#pageNumber');
is(parseInt(pageNumber.value), 1, 'initial page is 1');
//
// Bookmark button
//
var viewBookmark = document.querySelector('a#viewBookmark');
viewBookmark.click();
ok(viewBookmark.href.length > 0, 'viewBookmark button has href');
callback();
}
/**
* Destroys PDF.js viewer opened document.
*/
function closePDFViewer(window, callback) {
var viewer = window.wrappedJSObject.PDFViewerApplication;
viewer.close().then(callback);
}
});
});

View File

@ -139,9 +139,7 @@ const TESTS = [
}
];
function test() {
var tab;
add_task(function* test() {
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
@ -151,51 +149,73 @@ function test() {
info('Pref action: ' + handlerInfo.preferredAction);
waitForExplicitFinish();
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
yield BrowserTestUtils.withNewTab({ gBrowser, url: TESTROOT + "file_pdfjs_test.pdf" },
function* (newTabBrowser) {
yield waitForPdfJS(newTabBrowser);
tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
gBrowser.selectedTab = tab;
var newTabBrowser = gBrowser.getBrowserForTab(tab);
newTabBrowser.addEventListener("load", function eventHandler() {
newTabBrowser.removeEventListener("load", eventHandler, true);
var document = newTabBrowser.contentDocument,
window = newTabBrowser.contentWindow;
// Runs tests after all 'load' event handlers have fired off
window.addEventListener("documentload", function() {
runTests(document, window, function () {
var pageNumber = document.querySelector('input#pageNumber');
is(pageNumber.value, pageNumber.max, "Document is left on the last page");
finish();
yield ContentTask.spawn(newTabBrowser, null, function* () {
// Check if PDF is opened with internal viewer
ok(content.document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in content.wrappedJSObject, "window content has PDFJS object");
});
}, false, true);
}, true);
}
function runTests(document, window, finish) {
// Check if PDF is opened with internal viewer
ok(document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in window.wrappedJSObject, "window content has PDFJS object");
yield ContentTask.spawn(newTabBrowser, null, contentSetUp);
// Wait for outline items, the start the navigation actions
waitForOutlineItems(document).then(function () {
// The key navigation has to happen in page-fit, otherwise it won't scroll
// trough a complete page
setZoomToPageFit(document).then(function () {
runNextTest(document, window, finish);
}, function () {
ok(false, "Current scale has been set to 'page-fit'");
finish();
yield Task.spawn(runTests(newTabBrowser));
yield ContentTask.spawn(newTabBrowser, null, function*() {
let pageNumber = content.document.querySelector('input#pageNumber');
is(pageNumber.value, pageNumber.max, "Document is left on the last page");
});
});
}, function () {
ok(false, "Outline items have been found");
finish();
});
});
function* contentSetUp() {
/**
* Outline Items gets appended to the document later on we have to
* wait for them before we start to navigate though document
*
* @param document
* @returns {deferred.promise|*}
*/
function waitForOutlineItems(document) {
return new Promise((resolve, reject) => {
document.addEventListener("outlineloaded", function outlineLoaded(evt) {
document.removeEventListener("outlineloaded", outlineLoaded);
var outlineCount = evt.detail.outlineCount;
if (document.querySelectorAll(".outlineItem").length === outlineCount) {
resolve();
} else {
reject();
}
});
});
}
/**
* The key navigation has to happen in page-fit, otherwise it won't scroll
* through a complete page
*
* @param document
* @returns {deferred.promise|*}
*/
function setZoomToPageFit(document) {
return new Promise((resolve) => {
document.addEventListener("pagerendered", function onZoom(e) {
document.removeEventListener("pagerendered", onZoom);
document.querySelector("#viewer").click();
resolve();
});
var select = document.querySelector("select#scaleSelect");
select.selectedIndex = 2;
select.dispatchEvent(new Event("change"));
});
}
yield waitForOutlineItems(content.document);
yield setZoomToPageFit(content.document);
}
/**
@ -207,99 +227,55 @@ function runTests(document, window, finish) {
* @param test
* @param callback
*/
function runNextTest(document, window, endCallback) {
var test = TESTS.shift(),
deferred = Promise.defer(),
pageNumber = document.querySelector('input#pageNumber');
function* runTests(browser) {
yield ContentTask.spawn(browser, TESTS, function* (TESTS) {
let window = content;
let document = window.document;
// Add an event-listener to wait for page to change, afterwards resolve the promise
var timeout = window.setTimeout(() => deferred.reject(), 5000);
window.addEventListener('pagechange', function pageChange() {
if (pageNumber.value == test.expectedPage) {
window.removeEventListener('pagechange', pageChange);
window.clearTimeout(timeout);
deferred.resolve(pageNumber.value);
for (let test of TESTS) {
let deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
let pageNumber = document.querySelector('input#pageNumber');
// Add an event-listener to wait for page to change, afterwards resolve the promise
let timeout = window.setTimeout(() => deferred.reject(), 5000);
window.addEventListener('pagechange', function pageChange() {
if (pageNumber.value == test.expectedPage) {
window.removeEventListener('pagechange', pageChange);
window.clearTimeout(timeout);
deferred.resolve(+pageNumber.value);
}
});
// Get the element and trigger the action for changing the page
var el = document.querySelector(test.action.selector);
ok(el, "Element '" + test.action.selector + "' has been found");
// The value option is for input case
if (test.action.value)
el.value = test.action.value;
// Dispatch the event for changing the page
if (test.action.event == "keydown") {
var ev = document.createEvent("KeyboardEvent");
ev.initKeyEvent("keydown", true, true, null, false, false, false, false,
test.action.keyCode, 0);
el.dispatchEvent(ev);
}
else {
var ev = new Event(test.action.event);
}
el.dispatchEvent(ev);
let pgNumber = yield deferred.promise;
is(pgNumber, test.expectedPage, test.message);
}
});
// Get the element and trigger the action for changing the page
var el = document.querySelector(test.action.selector);
ok(el, "Element '" + test.action.selector + "' has been found");
// The value option is for input case
if (test.action.value)
el.value = test.action.value;
// Dispatch the event for changing the page
if (test.action.event == "keydown") {
var ev = document.createEvent("KeyboardEvent");
ev.initKeyEvent("keydown", true, true, null, false, false, false, false,
test.action.keyCode, 0);
el.dispatchEvent(ev);
}
else {
var ev = new Event(test.action.event);
}
el.dispatchEvent(ev);
// When the promise gets resolved we call the next test if there are any left
// or else we call the final callback which will end the test
deferred.promise.then(function (pgNumber) {
is(pgNumber, test.expectedPage, test.message);
if (TESTS.length)
runNextTest(document, window, endCallback);
else
endCallback();
}, function () {
ok(false, "Test '" + test.message + "' failed with timeout.");
endCallback();
var viewer = content.wrappedJSObject.PDFViewerApplication;
yield viewer.close();
});
}
/**
* Outline Items gets appended to the document latter on we have to
* wait for them before we start to navigate though document
*
* @param document
* @returns {deferred.promise|*}
*/
function waitForOutlineItems(document) {
var deferred = Promise.defer();
document.addEventListener("outlineloaded", function outlineLoaded(evt) {
document.removeEventListener("outlineloaded", outlineLoaded);
var outlineCount = evt.detail.outlineCount;
if (document.querySelectorAll(".outlineItem").length === outlineCount) {
deferred.resolve();
} else {
deferred.reject();
}
});
return deferred.promise;
}
/**
* The key navigation has to happen in page-fit, otherwise it won't scroll
* trough a complete page
*
* @param document
* @returns {deferred.promise|*}
*/
function setZoomToPageFit(document) {
var deferred = Promise.defer();
document.addEventListener("pagerendered", function onZoom(e) {
document.removeEventListener("pagerendered", onZoom);
document.querySelector("#viewer").click();
deferred.resolve();
});
var select = document.querySelector("select#scaleSelect");
select.selectedIndex = 2;
select.dispatchEvent(new Event("change"));
return deferred.promise;
}

View File

@ -4,9 +4,7 @@
const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
function test() {
var tab;
add_task(function* test() {
let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
@ -17,70 +15,47 @@ function test() {
info('Pref action: ' + handlerInfo.preferredAction);
waitForExplicitFinish();
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
yield BrowserTestUtils.withNewTab({ gBrowser, url: TESTROOT + "file_pdfjs_test.pdf" },
function* (browser) {
// check that PDF is opened with internal viewer
yield waitForPdfJS(browser);
tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
var newTabBrowser = gBrowser.getBrowserForTab(tab);
newTabBrowser.addEventListener("load", function eventHandler() {
newTabBrowser.removeEventListener("load", eventHandler, true);
yield ContentTask.spawn(browser, null, function* () {
ok(content.document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in content.wrappedJSObject, "window content has PDFJS object");
var document = newTabBrowser.contentDocument,
window = newTabBrowser.contentWindow;
//open sidebar
var sidebar = content.document.querySelector('button#sidebarToggle');
var outerContainer = content.document.querySelector('div#outerContainer');
// Runs tests after all 'load' event handlers have fired off
window.addEventListener("documentload", function() {
runTests(document, window, function () {
closePDFViewer(window, finish);
sidebar.click();
ok(outerContainer.classList.contains('sidebarOpen'), 'sidebar opens on click');
// check that thumbnail view is open
var thumbnailView = content.document.querySelector('div#thumbnailView');
var outlineView = content.document.querySelector('div#outlineView');
is(thumbnailView.getAttribute('class'), null, 'Initial view is thumbnail view');
is(outlineView.getAttribute('class'), 'hidden', 'Outline view is hidden initially');
//switch to outline view
var viewOutlineButton = content.document.querySelector('button#viewOutline');
viewOutlineButton.click();
is(thumbnailView.getAttribute('class'), 'hidden', 'Thumbnail view is hidden when outline is selected');
is(outlineView.getAttribute('class'), '', 'Outline view is visible when selected');
//switch back to thumbnail view
var viewThumbnailButton = content.document.querySelector('button#viewThumbnail');
viewThumbnailButton.click();
is(thumbnailView.getAttribute('class'), '', 'Thumbnail view is visible when selected');
is(outlineView.getAttribute('class'), 'hidden', 'Outline view is hidden when thumbnail is selected');
sidebar.click();
var viewer = content.wrappedJSObject.PDFViewerApplication;
yield viewer.close();
});
}, false, true);
}, true);
}
function runTests(document, window, callback) {
// check that PDF is opened with internal viewer
ok(document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in window.wrappedJSObject, "window content has PDFJS object");
//open sidebar
var sidebar = document.querySelector('button#sidebarToggle');
var outerContainer = document.querySelector('div#outerContainer');
sidebar.click();
ok(outerContainer.classList.contains('sidebarOpen'), 'sidebar opens on click');
// check that thumbnail view is open
var thumbnailView = document.querySelector('div#thumbnailView');
var outlineView = document.querySelector('div#outlineView');
is(thumbnailView.getAttribute('class'), null, 'Initial view is thumbnail view');
is(outlineView.getAttribute('class'), 'hidden', 'Outline view is hidden initially');
//switch to outline view
var viewOutlineButton = document.querySelector('button#viewOutline');
viewOutlineButton.click();
is(outlineView.getAttribute('class'), '', 'Outline view is visible when selected');
is(thumbnailView.getAttribute('class'), 'hidden', 'Thumbnail view is hidden when outline is selected');
//switch back to thumbnail view
var viewThumbnailButton = document.querySelector('button#viewThumbnail');
viewThumbnailButton.click();
is(thumbnailView.getAttribute('class'), '', 'Thumbnail view is visible when selected');
is(outlineView.getAttribute('class'), 'hidden', 'Outline view is hidden when thumbnail is selected');
sidebar.click();
callback();
}
/**
* Destroys PDF.js viewer opened document.
*/
function closePDFViewer(window, callback) {
var viewer = window.wrappedJSObject.PDFViewerApplication;
viewer.close().then(callback);
}
});
});

View File

@ -28,6 +28,7 @@ const TESTS = [
{
action: {
keyboard: true,
keyCode: 61,
event: "+"
},
expectedZoom: 1, // 1 - zoom in
@ -37,6 +38,7 @@ const TESTS = [
{
action: {
keyboard: true,
keyCode: 109,
event: "-"
},
expectedZoom: -1, // -1 - zoom out
@ -54,11 +56,7 @@ const TESTS = [
}
];
var initialWidth; // the initial width of the PDF document
var previousWidth; // the width of the PDF document at previous step/test
function test() {
var tab;
add_task(function* test() {
let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"]
.getService(Ci.nsIHandlerService);
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
@ -72,114 +70,83 @@ function test() {
info('Pref action: ' + handlerInfo.preferredAction);
waitForExplicitFinish();
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
yield BrowserTestUtils.withNewTab({ gBrowser, url: TESTROOT + "file_pdfjs_test.pdf" + "#zoom=100" },
function* (newTabBrowser) {
yield waitForPdfJS(newTabBrowser);
tab = gBrowser.selectedTab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
var newTabBrowser = gBrowser.getBrowserForTab(tab);
yield ContentTask.spawn(newTabBrowser, TESTS, function* (TESTS) {
let document = content.document;
newTabBrowser.addEventListener("load", function eventHandler() {
newTabBrowser.removeEventListener("load", eventHandler, true);
function waitForRender() {
return new Promise((resolve) => {
document.addEventListener("pagerendered", function onPageRendered(e) {
if(e.detail.pageNumber !== 1) {
return;
}
var document = newTabBrowser.contentDocument,
window = newTabBrowser.contentWindow;
document.removeEventListener("pagerendered", onPageRendered, true);
resolve();
}, true);
});
}
// Runs tests after all 'load' event handlers have fired off
window.addEventListener("documentload", function() {
initialWidth = parseInt(document.querySelector("div#pageContainer1").style.width);
previousWidth = initialWidth;
runTests(document, window, function () {
closePDFViewer(window, finish);
// check that PDF is opened with internal viewer
ok(content.document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in content.wrappedJSObject, "window content has PDFJS object");
let initialWidth, previousWidth;
initialWidth = previousWidth =
parseInt(content.document.querySelector("div#pageContainer1").style.width);
for (let test of TESTS) {
// We zoom using an UI element
var ev;
if (test.action.selector) {
// Get the element and trigger the action for changing the zoom
var el = document.querySelector(test.action.selector);
ok(el, "Element '" + test.action.selector + "' has been found");
if (test.action.index){
el.selectedIndex = test.action.index;
}
// Dispatch the event for changing the zoom
ev = new Event(test.action.event);
}
// We zoom using keyboard
else {
// Simulate key press
ev = new content.KeyboardEvent("keydown",
{ key: test.action.event,
keyCode: test.action.keyCode,
ctrlKey: true });
el = content;
}
el.dispatchEvent(ev);
yield waitForRender();
var pageZoomScale = content.document.querySelector('select#scaleSelect');
// The zoom value displayed in the zoom select
var zoomValue = pageZoomScale.options[pageZoomScale.selectedIndex].innerHTML;
let pageContainer = content.document.querySelector('div#pageContainer1');
let actualWidth = parseInt(pageContainer.style.width);
// the actual zoom of the PDF document
let computedZoomValue = parseInt(((actualWidth/initialWidth).toFixed(2))*100) + "%";
is(computedZoomValue, zoomValue, "Content has correct zoom");
// Check that document zooms in the expected way (in/out)
let zoom = (actualWidth - previousWidth) * test.expectedZoom;
ok(zoom > 0, test.message);
previousWidth = actualWidth;
}
var viewer = content.wrappedJSObject.PDFViewerApplication;
yield viewer.close();
});
}, false, true);
}, true);
}
function runTests(document, window, callback) {
// check that PDF is opened with internal viewer
ok(document.querySelector('div#viewer'), "document content has viewer UI");
ok('PDFJS' in window.wrappedJSObject, "window content has PDFJS object");
// Start the zooming tests after the document is loaded
waitForDocumentLoad(document).then(function () {
zoomPDF(document, window, TESTS.shift(), callback);
});
}
function waitForDocumentLoad(document) {
var deferred = Promise.defer();
var interval = setInterval(function () {
if (document.querySelector("div#pageContainer1") != null){
clearInterval(interval);
deferred.resolve();
}
}, 500);
return deferred.promise;
}
function zoomPDF(document, window, test, endCallback) {
var renderedPage;
document.addEventListener("pagerendered", function onPageRendered(e) {
if(e.detail.pageNumber !== 1) {
return;
}
document.removeEventListener("pagerendered", onPageRendered, true);
var pageZoomScale = document.querySelector('select#scaleSelect');
// The zoom value displayed in the zoom select
var zoomValue = pageZoomScale.options[pageZoomScale.selectedIndex].innerHTML;
let pageContainer = document.querySelector('div#pageContainer1');
let actualWidth = parseInt(pageContainer.style.width);
// the actual zoom of the PDF document
let computedZoomValue = parseInt(((actualWidth/initialWidth).toFixed(2))*100) + "%";
is(computedZoomValue, zoomValue, "Content has correct zoom");
// Check that document zooms in the expected way (in/out)
let zoom = (actualWidth - previousWidth) * test.expectedZoom;
ok(zoom > 0, test.message);
// Go to next test (if there is any) or finish
var nextTest = TESTS.shift();
if (nextTest) {
previousWidth = actualWidth;
zoomPDF(document, window, nextTest, endCallback);
}
else
endCallback();
}, true);
// We zoom using an UI element
if (test.action.selector) {
// Get the element and trigger the action for changing the zoom
var el = document.querySelector(test.action.selector);
ok(el, "Element '" + test.action.selector + "' has been found");
if (test.action.index){
el.selectedIndex = test.action.index;
}
// Dispatch the event for changing the zoom
el.dispatchEvent(new Event(test.action.event));
}
// We zoom using keyboard
else {
// Simulate key press
EventUtils.synthesizeKey(test.action.event, { ctrlKey: true });
}
}
/**
* Destroys PDF.js viewer opened document.
*/
function closePDFViewer(window, callback) {
var viewer = window.wrappedJSObject.PDFViewerApplication;
viewer.close().then(callback);
}
});
});

View File

@ -0,0 +1,11 @@
function waitForPdfJS(browser) {
// Runs tests after all 'load' event handlers have fired off
return ContentTask.spawn(browser, null, function* () {
yield new Promise((resolve) => {
content.addEventListener("documentload", function listener() {
content.removeEventListener("documentload", listener, false);
resolve();
}, false, true);
});
});
}

View File

@ -349,7 +349,7 @@ var ShumwayCom = {
},
getWeakMapKeys: function (weakMap) {
var keys = Components.utils.nondeterministicGetWeakMapKeys(weakMap);
var keys = ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys(weakMap);
var result = new content.Array();
keys.forEach(function (key) {
result.push(key);

View File

@ -101,7 +101,7 @@ FINAL_TARGET ?= $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIS
FINAL_TARGET_FROZEN := '$(FINAL_TARGET)'
ifdef XPI_NAME
DEFINES += -DXPI_NAME=$(XPI_NAME)
ACDEFINES += -DXPI_NAME=$(XPI_NAME)
endif
# The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
@ -533,7 +533,7 @@ sysinstall_cmd = install_cmd
# overridden by the command line. (Besides, AB_CD is prettier).
AB_CD = $(MOZ_UI_LOCALE)
# Many locales directories want this definition.
DEFINES += -DAB_CD=$(AB_CD)
ACDEFINES += -DAB_CD=$(AB_CD)
ifndef L10NBASEDIR
L10NBASEDIR = $(error L10NBASEDIR not defined by configure)
@ -689,5 +689,3 @@ export CL_INCLUDES_PREFIX
# in environment variables to prevent it from breking silently on
# non-English systems.
export NONASCII
DEFINES += -DNO_NSPR_10_SUPPORT

View File

@ -213,7 +213,7 @@ DEFAULT_GMAKE_FLAGS += \
OS_PTHREAD= \
$(NULL)
DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(CFLAGS) -DCHECK_FORK_GETPID $(addprefix -DANDROID_VERSION=,$(ANDROID_VERSION)) -include $(topsrcdir)/security/manager/android_stub.h'
DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(filter-out -W%,$(CFLAGS)) -DCHECK_FORK_GETPID $(addprefix -DANDROID_VERSION=,$(ANDROID_VERSION)) -include $(topsrcdir)/security/manager/android_stub.h'
endif
endif
@ -241,7 +241,7 @@ ifdef MOZ_NO_WLZDEFS
DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG=
endif
ifdef MOZ_CFLAGS_NSS
DEFAULT_GMAKE_FLAGS += XCFLAGS='$(CFLAGS)'
DEFAULT_GMAKE_FLAGS += XCFLAGS='$(filter-out -W%,$(CFLAGS))'
DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS='-compatibility_version 1 -current_version 1 $(LDFLAGS)'
endif
ifeq (1_1,$(CLANG_CL)_$(MOZ_ASAN))
@ -267,7 +267,10 @@ ifdef MOZ_FOLD_LIBS_FLAGS
DEFAULT_GMAKE_FLAGS += XCFLAGS='$(MOZ_FOLD_LIBS_FLAGS)'
endif
ifeq (1,$(ALLOW_COMPILER_WARNINGS))
ifndef WARNINGS_AS_ERRORS
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
endif
ifeq ($(OS_TARGET),Android)
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
endif

View File

@ -35,8 +35,8 @@ process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
%.xpt:
@echo "$(@F)"
$(PYTHON_PATH) $(PLY_INCLUDE) -I$(IDL_PARSER_DIR) -I$(IDL_PARSER_CACHE_DIR) \
$(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) $(dist_idl_dir) \
$(dist_include_dir) $(@D) $(idl_deps_dir) $(libxul_sdk_includes) \
$(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) --depsdir $(idl_deps_dir) \
$(dist_idl_dir) $(dist_include_dir) $(@D) $(libxul_sdk_includes) \
$(basename $(notdir $@)) $($(basename $(notdir $@))_deps)
# When some IDL is added or removed, if the actual IDL file was already, or
# still is, in the tree, simple dependencies can't detect that the XPT needs

View File

@ -13,7 +13,7 @@ include $(topsrcdir)/config/config.mk
XPI_NAME = test_jar_mn
DEFINES += \
ACDEFINES += \
-DAB_CD=ab-X-stuff \
$(NULL)

View File

@ -9172,6 +9172,9 @@ if test -z "$JS_SHARED_LIBRARY"; then
fi
AC_SUBST(JS_SHARED_LIBRARY)
# Avoid using obsolete NSPR features
AC_DEFINE(NO_NSPR_10_SUPPORT)
MOZ_CREATE_CONFIG_STATUS()
if test "$COMPILE_ENVIRONMENT"; then

View File

@ -138,8 +138,8 @@ function test() {
is([...variables].length, 0,
"VariablesView should have been emptied.");
is(Cu.nondeterministicGetWeakMapKeys(variables._itemsByElement).length, 0,
"VariablesView _itemsByElement map has been emptied.");
is(ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys(variables._itemsByElement).length,
0, "VariablesView _itemsByElement map has been emptied.");
is(variables._currHierarchy.size, 0,
"VariablesView _currHierarchy map has been emptied.");
is(variables._list.children.length, 0,

View File

@ -91,7 +91,7 @@ HeapSnapshot::Create(JSContext* cx,
ErrorResult& rv)
{
RefPtr<HeapSnapshot> snapshot = new HeapSnapshot(cx, global.GetAsSupports());
if (!snapshot->init(buffer, size)) {
if (!snapshot->init(cx, buffer, size)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
@ -203,7 +203,7 @@ HeapSnapshot::getOrInternString(InternedStringSet& internedStrings,
: Nothing())
bool
HeapSnapshot::saveNode(const protobuf::Node& node)
HeapSnapshot::saveNode(const protobuf::Node& node, NodeIdSet& edgeReferents)
{
// NB: de-duplicated string properties must be read back and interned in the
// same order here as they are written and serialized in
@ -248,6 +248,9 @@ HeapSnapshot::saveNode(const protobuf::Node& node)
return false;
NodeId referent = protoEdge.referent();
if (NS_WARN_IF(!edgeReferents.put(referent)))
return false;
const char16_t* edgeName = nullptr;
if (protoEdge.EdgeNameOrRef_case() != protobuf::Edge::EDGENAMEORREF_NOT_SET) {
Maybe<StringOrRef> edgeNameOrRef = GET_STRING_OR_REF(protoEdge, name);
@ -402,7 +405,7 @@ StreamHasData(GzipInputStream& stream)
}
bool
HeapSnapshot::init(const uint8_t* buffer, uint32_t size)
HeapSnapshot::init(JSContext* cx, const uint8_t* buffer, uint32_t size)
{
if (!nodes.init() || !frames.init())
return false;
@ -430,7 +433,12 @@ HeapSnapshot::init(const uint8_t* buffer, uint32_t size)
return false;
rootId = root.id();
if (NS_WARN_IF(!saveNode(root)))
// The set of all node ids we've found edges pointing to.
NodeIdSet edgeReferents(cx);
if (NS_WARN_IF(!edgeReferents.init()))
return false;
if (NS_WARN_IF(!saveNode(root, edgeReferents)))
return false;
// Finally, the rest of the nodes in the core dump.
@ -439,7 +447,15 @@ HeapSnapshot::init(const uint8_t* buffer, uint32_t size)
protobuf::Node node;
if (!parseMessage(gzipStream, node))
return false;
if (NS_WARN_IF(!saveNode(node)))
if (NS_WARN_IF(!saveNode(node, edgeReferents)))
return false;
}
// Check the set of node ids referred to by edges we found and ensure that we
// have the node corresponding to each id. If we don't have all of them, it is
// unsafe to perform analyses of this heap snapshot.
for (auto range = edgeReferents.all(); !range.empty(); range.popFront()) {
if (NS_WARN_IF(!nodes.has(range.front())))
return false;
}

View File

@ -59,11 +59,13 @@ class HeapSnapshot final : public nsISupports
// Initialize this HeapSnapshot from the given buffer that contains a
// serialized core dump. Do NOT take ownership of the buffer, only borrow it
// for the duration of the call. Return false on failure.
bool init(const uint8_t* buffer, uint32_t size);
bool init(JSContext* cx, const uint8_t* buffer, uint32_t size);
using NodeIdSet = js::HashSet<NodeId>;
// Save the given `protobuf::Node` message in this `HeapSnapshot` as a
// `DeserializedNode`.
bool saveNode(const protobuf::Node& node);
bool saveNode(const protobuf::Node& node, NodeIdSet& edgeReferents);
// Save the given `protobuf::StackFrame` message in this `HeapSnapshot` as a
// `DeserializedStackFrame`. The saved stack frame's id is returned via the

View File

@ -5,6 +5,9 @@
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"DTD/xhtml1-strict.dtd">
%htmlDTD;
<!ENTITY % netErrorAppDTD
SYSTEM "chrome://global/locale/netErrorApp.dtd">
%netErrorAppDTD;
<!ENTITY % netErrorDTD
SYSTEM "chrome://global/locale/netError.dtd">
%netErrorDTD;

View File

@ -11,6 +11,26 @@ namespace mozilla {
namespace dom {
/* static */ void
ThreadSafeChromeUtils::NondeterministicGetWeakMapKeys(GlobalObject& aGlobal,
JS::Handle<JS::Value> aMap,
JS::MutableHandle<JS::Value> aRetval,
ErrorResult& aRv)
{
if (!aMap.isObject()) {
aRetval.setUndefined();
} else {
JSContext* cx = aGlobal.Context();
JS::Rooted<JSObject*> objRet(cx);
JS::Rooted<JSObject*> mapObj(cx, &aMap.toObject());
if (!JS_NondeterministicGetWeakMapKeys(cx, mapObj, &objRet)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
} else {
aRetval.set(objRet ? JS::ObjectValue(*objRet) : JS::UndefinedValue());
}
}
}
/* static */ void
ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,
nsCString& aSuffix)

View File

@ -35,6 +35,11 @@ public:
JSContext* cx,
const nsAString& filePath,
ErrorResult& rv);
static void NondeterministicGetWeakMapKeys(GlobalObject& aGlobal,
JS::Handle<JS::Value> aMap,
JS::MutableHandle<JS::Value> aRetval,
ErrorResult& aRv);
};
class ChromeUtils : public ThreadSafeChromeUtils

View File

@ -527,8 +527,9 @@ nsContentList::NamedItem(const nsAString& aName, bool aDoFlush)
nsIContent *content = mElements[i];
// XXX Should this pass eIgnoreCase?
if (content &&
(content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
name, eCaseMatters) ||
((content->IsHTMLElement() &&
content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
name, eCaseMatters)) ||
content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
name, eCaseMatters))) {
return content->AsElement();

View File

@ -3641,7 +3641,7 @@ nsDOMWindowUtils::SetChromeMargin(int32_t aTop,
nsCOMPtr<nsIWidget> widget;
baseWindow->GetMainWidget(getter_AddRefs(widget));
if (widget) {
nsIntMargin margins(aTop, aRight, aBottom, aLeft);
LayoutDeviceIntMargin margins(aTop, aRight, aBottom, aLeft);
return widget->SetNonClientMargins(margins);
}
}

View File

@ -13325,7 +13325,8 @@ nsGlobalWindow::NotifyDefaultButtonLoaded(Element& aDefaultButton,
aError.Throw(NS_ERROR_FAILURE);
return;
}
nsIntRect buttonRect = frame->GetScreenRect();
LayoutDeviceIntRect buttonRect =
LayoutDeviceIntRect::FromUnknownRect(frame->GetScreenRect());
// Get the widget rect in screen coordinates.
nsIWidget *widget = GetNearestWidget();
@ -13333,8 +13334,8 @@ nsGlobalWindow::NotifyDefaultButtonLoaded(Element& aDefaultButton,
aError.Throw(NS_ERROR_FAILURE);
return;
}
nsIntRect widgetRect;
aError = widget->GetScreenBoundsUntyped(widgetRect);
LayoutDeviceIntRect widgetRect;
aError = widget->GetScreenBounds(widgetRect);
if (aError.Failed()) {
return;
}

View File

@ -42,7 +42,7 @@ function getIntPref(prefName, def) {
function handleWindowEvent(e) {
if (this._browserElementParents) {
let beps = Cu.nondeterministicGetWeakMapKeys(this._browserElementParents);
let beps = ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys(this._browserElementParents);
beps.forEach(bep => bep._handleOwnerEvent(e));
}
}

View File

@ -933,34 +933,37 @@ protected:
{
}
void DoCreateImageBitmapFromBlob(ErrorResult& aRv)
// Returns true on success, false on failure.
bool DoCreateImageBitmapFromBlob()
{
RefPtr<ImageBitmap> imageBitmap = CreateImageBitmap(aRv);
RefPtr<ImageBitmap> imageBitmap = CreateImageBitmap();
// handle errors while creating ImageBitmap
// (1) error occurs during reading of the object
// (2) the image data is not in a supported file format
// (3) the image data is corrupted
// All these three cases should reject promise with null value
if (aRv.Failed()) {
mPromise->MaybeReject(aRv);
return;
if (!imageBitmap) {
return false;
}
if (imageBitmap && mCropRect.isSome()) {
imageBitmap->SetPictureRect(mCropRect.ref(), aRv);
ErrorResult rv;
imageBitmap->SetPictureRect(mCropRect.ref(), rv);
if (aRv.Failed()) {
mPromise->MaybeReject(aRv);
return;
if (rv.Failed()) {
mPromise->MaybeReject(rv);
return false;
}
}
mPromise->MaybeResolve(imageBitmap);
return;
return true;
}
virtual already_AddRefed<ImageBitmap> CreateImageBitmap(ErrorResult& aRv) = 0;
// Will return null on failure. In that case, mPromise will already
// be rejected with the right thing.
virtual already_AddRefed<ImageBitmap> CreateImageBitmap() = 0;
RefPtr<Promise> mPromise;
nsCOMPtr<nsIGlobalObject> mGlobalObject;
@ -982,17 +985,18 @@ public:
NS_IMETHOD Run() override
{
ErrorResult error;
DoCreateImageBitmapFromBlob(error);
DoCreateImageBitmapFromBlob();
return NS_OK;
}
private:
already_AddRefed<ImageBitmap> CreateImageBitmap(ErrorResult& aRv) override
already_AddRefed<ImageBitmap> CreateImageBitmap() override
{
RefPtr<layers::Image> data = DecodeAndCropBlob(*mBlob, mCropRect, aRv);
ErrorResult rv;
RefPtr<layers::Image> data = DecodeAndCropBlob(*mBlob, mCropRect, rv);
if (NS_WARN_IF(aRv.Failed())) {
if (NS_WARN_IF(rv.Failed())) {
mPromise->MaybeReject(rv);
return nullptr;
}
@ -1054,23 +1058,22 @@ public:
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
ErrorResult error;
DoCreateImageBitmapFromBlob(error);
return !(error.Failed());
return DoCreateImageBitmapFromBlob();
}
private:
already_AddRefed<ImageBitmap> CreateImageBitmap(ErrorResult& aRv) override
already_AddRefed<ImageBitmap> CreateImageBitmap() override
{
RefPtr<layers::Image> data;
ErrorResult rv;
RefPtr<DecodeBlobInMainThreadSyncTask> task =
new DecodeBlobInMainThreadSyncTask(mWorkerPrivate, *mBlob, mCropRect,
aRv, getter_AddRefs(data));
rv, getter_AddRefs(data));
task->Dispatch(mWorkerPrivate->GetJSContext()); // This is a synchronous call.
if (NS_WARN_IF(aRv.Failed())) {
mPromise->MaybeReject(aRv);
if (NS_WARN_IF(rv.Failed())) {
mPromise->MaybeReject(rv);
return nullptr;
}

View File

@ -260,6 +260,7 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
// if it is an app that is always precise, skip it
nsAutoJSString origin;
if (!origin.init(cx, id)) {
JS_ClearPendingException(cx); // catch and ignore any exceptions
continue;
}
if (mAlwaysPreciseApps.Contains(origin)) {
@ -268,7 +269,8 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
// get the app setting object
JS::RootedValue propertyValue(cx);
if (!JS_GetPropertyById(cx, obj, id, &propertyValue) || !propertyValue.isObject()) {
if (!JS_GetPropertyById(cx, obj, id, &propertyValue)) {
JS_ClearPendingException(cx); // catch and ignore any exceptions
continue;
}
JS::RootedObject settingObj(cx, &propertyValue.toObject());
@ -280,6 +282,8 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
JS::RootedValue fm(cx);
if (JS_GetProperty(cx, settingObj, "type", &fm)) {
settings->HandleTypeChange(fm);
} else {
JS_ClearPendingException(cx); // catch and ignore any exceptions
}
#ifdef MOZ_APPROX_LOCATION
@ -287,6 +291,8 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
JS::RootedValue distance(cx);
if (JS_GetProperty(cx, settingObj, "distance", &distance)) {
settings->HandleApproxDistanceChange(distance);
} else {
JS_ClearPendingException(cx); // catch and ignore any exceptions
}
#endif
@ -294,6 +300,8 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
JS::RootedValue coords(cx);
if (JS_GetProperty(cx, settingObj, "coords", &coords)) {
settings->HandleFixedCoordsChange(coords);
} else {
JS_ClearPendingException(cx); // catch and ignore any exceptions
}
// add the per-app setting object to the hashtable
@ -337,11 +345,13 @@ nsGeolocationSettings::HandleGeolocationAlwaysPreciseChange(const JS::Value& aVa
JS::RootedValue value(cx);
if (!JS_GetElement(cx, obj, i, &value) || !value.isString()) {
JS_ClearPendingException(cx); // catch and ignore any exceptions
continue;
}
nsAutoJSString origin;
if (!origin.init(cx, value)) {
JS_ClearPendingException(cx); // catch and ignore any exceptions
continue;
}

View File

@ -1235,7 +1235,7 @@ nsresult HTMLMediaElement::LoadResource()
#ifdef MOZ_EME
if (mMediaKeys &&
!IsMediaStreamURI(mLoadingSrc) &&
!IsMediaSourceURI(mLoadingSrc) &&
Preferences::GetBool("media.eme.mse-only", true)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}

View File

@ -28,7 +28,13 @@ interface nsIServiceWorkerInfo : nsISupports
readonly attribute DOMString cacheName;
};
[scriptable, builtinclass, uuid(e908bc07-0a4c-443f-a546-2109bf1f4A01)]
[scriptable, uuid(87e63548-d440-4b8a-b158-65ad1de0211E)]
interface nsIServiceWorkerRegistrationInfoListener : nsISupports
{
void onChange();
};
[scriptable, builtinclass, uuid(72faba24-0a1b-4284-bad3-d44c044d6d95)]
interface nsIServiceWorkerRegistrationInfo : nsISupports
{
readonly attribute nsIPrincipal principal;
@ -39,6 +45,10 @@ interface nsIServiceWorkerRegistrationInfo : nsISupports
readonly attribute nsIServiceWorkerInfo installingWorker;
readonly attribute nsIServiceWorkerInfo waitingWorker;
readonly attribute nsIServiceWorkerInfo activeWorker;
void addListener(in nsIServiceWorkerRegistrationInfoListener listener);
void removeListener(in nsIServiceWorkerRegistrationInfoListener listener);
};
[scriptable, uuid(9e523e7c-ad6f-4df0-8077-c74aebbc679d)]

View File

@ -92,6 +92,12 @@
<p>These types of web forgeries are used in scams known as phishing attacks, in which fraudulent web pages and emails are used to imitate sources you may trust.</p>
">
<!ENTITY securityOverride.linkText "Or you can add an exception…">
<!ENTITY securityOverride.warningContent "
<p>You should not add an exception if you are using an internet connection that you do not trust completely or if you are not used to seeing a warning for this server.</p>
<p>If you still wish to add an exception for this site, you can do so in your advanced encryption settings.</p>
">
<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
<!ENTITY cspBlocked.longDesc "<p>The browser prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
@ -100,10 +106,3 @@
<!ENTITY remoteXUL.title "Remote XUL">
<!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">
<!-- Include app-specific error messages - do not change this in localization!
Some applications might override netErrorApp.dtd with their specific version,
this inclusion needs to be intact for that approach to work correctly.
Please, try to keep this at the end of the file. -->
<!ENTITY % netErrorAppDTD SYSTEM "chrome://global/locale/netErrorApp.dtd">
%netErrorAppDTD;

View File

@ -2,12 +2,22 @@
- 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/. -->
<!-- Error messages that are likely to be overridden by applications go in this
file, all messages that likely don't need to tie into app-specific UI
should go into netError.dtd -->
<!-- This file exists to allow applications to override one or more messages
from netError.dtd; Applications which want to do this should override
this file with their own version of netErrorApp.dtd -->
<!-- An example (from Firefox):
<!ENTITY securityOverride.linkText "Or you can add an exception…">
<!ENTITY securityOverride.getMeOutOfHereButton "Get me out of here!">
<!ENTITY securityOverride.exceptionButtonLabel "Add Exception…">
<!ENTITY securityOverride.warningContent "
<p>You should not add an exception if you are using an internet connection that you do not trust completely or if you are not used to seeing a warning for this server.</p>
<p>If you still wish to add an exception for this site, you can do so in your advanced encryption settings.</p>
<button id='getMeOutOfHereButton'>&securityOverride.getMeOutOfHereButton;</button>
<button id='exceptionDialogButton'>&securityOverride.exceptionButtonLabel;</button>
">
-->

View File

@ -629,6 +629,8 @@ skip-if = toolkit == 'android' # bug 1149374
skip-if = toolkit == 'android' || toolkit == 'gonk' # android: bug 1149374; gonk: bug 1193351
[test_eme_requestKeySystemAccess.html]
skip-if = toolkit == 'android' # bug 1149374
[test_eme_setMediaKeys_before_attach_MediaSource.html]
skip-if = toolkit == 'android' # bug 1149374
[test_eme_stream_capture_blocked_case1.html]
tags=msg capturestream
skip-if = toolkit == 'android' || toolkit == 'gonk' # android: bug 1149374; gonk: bug 1193351

View File

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test Encrypted Media Extensions</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="eme.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
function beginTest() {
var video = document.createElement("video");
navigator.requestMediaKeySystemAccess("org.w3.clearkey", [{initDataTypes: ["cenc"]}])
.then(function(keySystemAccess) {
return keySystemAccess.createMediaKeys();
})
.then(mediaKeys => {
return video.setMediaKeys(mediaKeys);
})
.then(() => {
var ms = new MediaSource();
ms.addEventListener("sourceopen", ()=>{ok(true, "MediaSource should open"); SimpleTest.finish();});
video.addEventListener("error", ()=>{ok(false, "Shouldn't error."); SimpleTest.finish();});
video.src = URL.createObjectURL(ms);
});
}
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>
</html>

View File

@ -2526,35 +2526,30 @@ QuotaManager::UpdateOriginAccessTime(PersistenceType aPersistenceType,
}
}
// static
PLDHashOperator
QuotaManager::RemoveQuotaCallback(const nsACString& aKey,
nsAutoPtr<GroupInfoPair>& aValue,
void* aUserArg)
{
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
NS_ASSERTION(aValue, "Null pointer!");
RefPtr<GroupInfo> groupInfo =
aValue->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
if (groupInfo) {
groupInfo->LockedRemoveOriginInfos();
}
groupInfo = aValue->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
if (groupInfo) {
groupInfo->LockedRemoveOriginInfos();
}
return PL_DHASH_REMOVE;
}
void
QuotaManager::RemoveQuota()
{
MutexAutoLock lock(mQuotaMutex);
mGroupInfoPairs.Enumerate(RemoveQuotaCallback, nullptr);
for (auto iter = mGroupInfoPairs.Iter(); !iter.Done(); iter.Next()) {
nsAutoPtr<GroupInfoPair>& pair = iter.Data();
MOZ_ASSERT(!iter.Key().IsEmpty(), "Empty key!");
MOZ_ASSERT(pair, "Null pointer!");
RefPtr<GroupInfo> groupInfo =
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
if (groupInfo) {
groupInfo->LockedRemoveOriginInfos();
}
groupInfo = pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
if (groupInfo) {
groupInfo->LockedRemoveOriginInfos();
}
iter.Remove();
}
NS_ASSERTION(mTemporaryStorageUsage == 0, "Should be zero!");
}

View File

@ -461,11 +461,6 @@ private:
const nsACString& aOrigin,
nsAutoCString& _retval);
static PLDHashOperator
RemoveQuotaCallback(const nsACString& aKey,
nsAutoPtr<GroupInfoPair>& aValue,
void* aUserArg);
mozilla::Mutex mQuotaMutex;
nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;

View File

@ -31,6 +31,18 @@ interface ThreadSafeChromeUtils {
*/
[Throws, NewObject]
static HeapSnapshot readHeapSnapshot(DOMString filePath);
/**
* Return the keys in a weak map. This operation is
* non-deterministic because it is affected by the scheduling of the
* garbage collector and the cycle collector.
*
* @param aMap weak map or other JavaScript value
* @returns If aMap is a weak map object, return the keys of the weak
* map as an array. Otherwise, return undefined.
*/
[Throws, NewObject]
static any nondeterministicGetWeakMapKeys(any map);
};
/**

View File

@ -158,12 +158,6 @@ ServiceWorkerContainer::Register(const nsAString& aScriptURL,
}
}
if (!baseURI) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
nsresult rv;
nsCOMPtr<nsIURI> scriptURI;
rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptURL, nullptr, baseURI);

View File

@ -436,6 +436,36 @@ ServiceWorkerRegistrationInfo::GetActiveWorker(nsIServiceWorkerInfo **aResult)
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerRegistrationInfo::AddListener(
nsIServiceWorkerRegistrationInfoListener *aListener)
{
AssertIsOnMainThread();
if (!aListener || mListeners.Contains(aListener)) {
return NS_ERROR_INVALID_ARG;
}
mListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerRegistrationInfo::RemoveListener(
nsIServiceWorkerRegistrationInfoListener *aListener)
{
AssertIsOnMainThread();
if (!aListener || !mListeners.Contains(aListener)) {
return NS_ERROR_INVALID_ARG;
}
mListeners.RemoveElement(aListener);
return NS_OK;
}
already_AddRefed<ServiceWorkerInfo>
ServiceWorkerRegistrationInfo::GetServiceWorkerInfoById(uint64_t aId)
{
@ -970,6 +1000,7 @@ public:
}
mRegistration->mScriptSpec = mScriptSpec;
mRegistration->NotifyListenersOnChange();
swm->StoreRegistration(mPrincipal, mRegistration);
} else {
MOZ_ASSERT(mJobType == UPDATE_JOB);
@ -1162,6 +1193,7 @@ public:
mRegistration->mInstallingWorker = mUpdateAndInstallInfo.forget();
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
mRegistration->NotifyListenersOnChange();
Succeed();
// The job should NOT call fail from this point on.
@ -1329,6 +1361,7 @@ private:
mRegistration->mWaitingWorker = mRegistration->mInstallingWorker.forget();
mRegistration->mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
mRegistration->NotifyListenersOnChange();
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER);
@ -1648,6 +1681,7 @@ ServiceWorkerRegistrationInfo::Activate()
mActiveWorker = activatingWorker.forget();
mWaitingWorker = nullptr;
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
NotifyListenersOnChange();
// FIXME(nsm): Unlink appcache if there is one.
@ -2462,6 +2496,15 @@ ServiceWorkerRegistrationInfo::IsLastUpdateCheckTimeOverOneDay() const
return false;
}
void
ServiceWorkerRegistrationInfo::NotifyListenersOnChange()
{
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> listeners(mListeners);
for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnChange();
}
}
void
ServiceWorkerManager::LoadRegistration(
const ServiceWorkerRegistrationData& aRegistration)
@ -3883,7 +3926,7 @@ ServiceWorkerManager::AddListener(nsIServiceWorkerManagerListener* aListener)
{
AssertIsOnMainThread();
if (mListeners.Contains(aListener)) {
if (!aListener || mListeners.Contains(aListener)) {
return NS_ERROR_INVALID_ARG;
}
@ -3897,7 +3940,7 @@ ServiceWorkerManager::RemoveListener(nsIServiceWorkerManagerListener* aListener)
{
AssertIsOnMainThread();
if (!mListeners.Contains(aListener)) {
if (!aListener || !mListeners.Contains(aListener)) {
return NS_ERROR_INVALID_ARG;
}

View File

@ -72,6 +72,8 @@ public:
RefPtr<ServiceWorkerInfo> mWaitingWorker;
RefPtr<ServiceWorkerInfo> mInstallingWorker;
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> mListeners;
uint64_t mLastUpdateCheckTime;
// When unregister() is called on a registration, it is not immediately
@ -138,6 +140,9 @@ public:
bool
IsLastUpdateCheckTimeOverOneDay() const;
void
NotifyListenersOnChange();
};
class ServiceWorkerUpdateFinishCallback

View File

@ -3,11 +3,15 @@ skip-if = buildapp == 'b2g' || os == 'android'
support-files =
app/*
app2/*
chrome_helpers.js
serviceworkermanager_iframe.html
serviceworkerregistrationinfo_iframe.html
worker.js
worker2.js
[test_aboutserviceworkers.html]
skip-if = true #bug 1193319
[test_app_installation.html]
[test_privateBrowsing.html]
[test_serviceworkermanager.xul]
[test_serviceworkerregistrationinfo.xul]

View File

@ -0,0 +1,59 @@
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Task.jsm");
let swm = Cc["@mozilla.org/serviceworkers/manager;1"].
getService(Ci.nsIServiceWorkerManager);
let EXAMPLE_URL = "https://example.com/chrome/dom/workers/test/serviceworkers/";
function waitForIframeLoad(iframe) {
return new Promise(function (resolve) {
iframe.onload = resolve;
});
}
function waitForRegister(scope, callback) {
return new Promise(function (resolve) {
let listener = {
onRegister: function (registration) {
if (registration.scope !== scope) {
return;
}
swm.removeListener(listener);
resolve(callback ? callback(registration) : registration);
}
};
swm.addListener(listener);
});
}
function waitForUnregister(scope) {
return new Promise(function (resolve) {
let listener = {
onUnregister: function (registration) {
if (registration.scope !== scope) {
return;
}
swm.removeListener(listener);
resolve(registration);
}
};
swm.addListener(listener);
});
}
function waitForServiceWorkerRegistrationChange(registration, callback) {
return new Promise(function (resolve) {
let listener = {
onChange: function () {
registration.removeListener(listener);
if (callback) {
callback();
}
resolve(callback ? callback() : undefined);
}
};
registration.addListener(listener);
});
}

View File

@ -9,13 +9,21 @@
}
var promise = navigator.serviceWorker.register("worker.js");
window.onmessage = function (event) {
if (event.data !== "unregister") {
if (event.data !== "register") {
return;
}
promise.then(function (registration) {
registration.unregister();
promise = promise.then(function (registration) {
return navigator.serviceWorker.register("worker2.js");
});
window.onmessage = null;
window.onmessage = function (event) {
if (event.data !== "unregister") {
return;
}
promise.then(function (registration) {
registration.unregister();
});
window.onmessage = null;
};
};
};
</script>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script>
window.onmessage = function (event) {
if (event.data !== "register") {
return;
}
var promise = navigator.serviceWorker.register("worker.js");
window.onmessage = function (event) {
if (event.data !== "register") {
return;
}
promise.then(function (registration) {
return navigator.serviceWorker.register("worker2.js");
});
};
};
</script>
</head>
<body>
This is a test page.
</body>
<html>

View File

@ -8,53 +8,10 @@
onload="test();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript" src="chrome_helpers.js"/>
<script type="application/javascript">
<![CDATA[
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Task.jsm");
let swm = Cc["@mozilla.org/serviceworkers/manager;1"].
getService(Ci.nsIServiceWorkerManager);
function waitForIframeLoad(iframe) {
return new Promise(function (resolve) {
iframe.onload = resolve;
});
}
function waitForRegister(scope) {
return new Promise(function (resolve) {
let listener = {
onRegister: function (registration) {
if (registration.scope !== scope) {
return;
}
swm.removeListener(listener);
resolve(registration);
}
};
swm.addListener(listener);
});
}
function waitForUnregister(scope) {
return new Promise(function (resolve) {
let listener = {
onUnregister: function (registration) {
if (registration.scope !== scope) {
return;
}
swm.removeListener(listener);
resolve(registration);
}
};
swm.addListener(listener);
});
}
let EXAMPLE_URL = "https://example.com/chrome/dom/workers/test/serviceworkers/";
let IFRAME_URL = EXAMPLE_URL + "serviceworkermanager_iframe.html";
function test() {
@ -64,7 +21,7 @@
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]}, function () {
Task.spawn(function *() {
Task.spawn(function* () {
let registrations = swm.getAllRegistrations();
is(registrations.length, 0);
@ -84,11 +41,23 @@
is(registrations.queryElementAt(0, Ci.nsIServiceWorkerRegistrationInfo),
registration);
info("Check that the service worker manager does not notify its " +
"listeners when a service worker is registered with the same " +
"scope as an existing registration.");
let listener = {
onRegister: function () {
ok(false, "Listener should not have been notified.");
}
};
swm.addListener(listener);
iframe.contentWindow.postMessage("register", "*");
info("Check that the service worker manager notifies its listeners " +
"when a service worker is unregistered.");
promise = waitForUnregister(EXAMPLE_URL);
iframe.contentWindow.postMessage("unregister", "*");
registration = yield promise;
swm.removeListener(listener);
registrations = swm.getAllRegistrations();
is(registrations.length, 0);

View File

@ -0,0 +1,117 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<window title="Test for ServiceWorkerRegistrationInfo"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript" src="chrome_helpers.js"/>
<script type="application/javascript">
<![CDATA[
let IFRAME_URL = EXAMPLE_URL + "serviceworkerregistrationinfo_iframe.html";
function test() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]}, function () {
Task.spawn(function* () {
let iframe = $("iframe");
let promise = waitForIframeLoad(iframe);
iframe.src = IFRAME_URL;
yield promise;
// The change handler is not guaranteed to be called within the same
// tick of the event loop as the one in which the change happened.
// Because of this, the exact state of the service worker registration
// is only known until the handler returns.
//
// Because then-handlers are resolved asynchronously, the following
// checks are done using callbacks, which are called synchronously
// when then handler is called. These callbacks can return a promise,
// which is used to resolve the promise returned by the function.
info("Check that a service worker registration notifies its " +
"listeners when its state changes.");
promise = waitForRegister(EXAMPLE_URL, function (registration) {
is(registration.scriptSpec, "");
ok(registration.installingWorker === null);
ok(registration.waitingWorker === null);
ok(registration.activeWorker === null);
return waitForServiceWorkerRegistrationChange(registration, function () {
is(registration.scriptSpec, EXAMPLE_URL + "worker.js");
return waitForServiceWorkerRegistrationChange(registration, function () {
ok(registration.installingWorker !== null);
ok(registration.waitingWorker === null);
ok(registration.activeWorker === null);
return waitForServiceWorkerRegistrationChange(registration, function () {
ok(registration.installingWorker === null);
ok(registration.waitingWorker !== null);
ok(registration.activeWorker === null);
return waitForServiceWorkerRegistrationChange(registration, function () {
ok(registration.installingWorker === null);
ok(registration.waitingWorker === null);
ok(registration.activeWorker !== null);
return registration;
});
});
});
});
});
iframe.contentWindow.postMessage("register", "*");
let registration = yield promise;
promise = waitForServiceWorkerRegistrationChange(registration, function () {
is(registration.scriptSpec, EXAMPLE_URL + "worker2.js");
return waitForServiceWorkerRegistrationChange(registration, function () {
ok(registration.installingWorker !== null);
ok(registration.waitingWorker === null);
ok(registration.activeWorker !== null);
return waitForServiceWorkerRegistrationChange(registration, function () {
ok(registration.installingWorker === null);
ok(registration.waitingWorker !== null);
ok(registration.activeWorker !== null);
return waitForServiceWorkerRegistrationChange(registration, function () {
ok(registration.installingWorker === null);
ok(registration.waitingWorker === null);
ok(registration.activeWorker !== null);
return registration;
});
});
});
});
iframe.contentWindow.postMessage("register", "*");
yield promise;
SimpleTest.finish();
});
});
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display:none;"></div>
<pre id="test"></pre>
<iframe id="iframe"></iframe>
</body>
<label id="test-result"/>
</window>

View File

@ -2007,7 +2007,7 @@ public:
explicit MarginSetter(nsIWidget* aWidget) :
mWidget(aWidget), mMargin(-1, -1, -1, -1)
{}
MarginSetter(nsIWidget *aWidget, const nsIntMargin& aMargin) :
MarginSetter(nsIWidget *aWidget, const LayoutDeviceIntMargin& aMargin) :
mWidget(aWidget), mMargin(aMargin)
{}
@ -2021,7 +2021,7 @@ public:
private:
nsCOMPtr<nsIWidget> mWidget;
nsIntMargin mMargin;
LayoutDeviceIntMargin mMargin;
};
void
@ -2046,7 +2046,9 @@ nsXULElement::SetChromeMargins(const nsAttrValue* aValue)
gotMargins = nsContentUtils::ParseIntMarginValue(tmp, margins);
}
if (gotMargins) {
nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget, margins));
nsContentUtils::AddScriptRunner(
new MarginSetter(
mainWidget, LayoutDeviceIntMargin::FromUnknownMargin(margins)));
}
}

View File

@ -32,6 +32,19 @@ struct IntMarginTyped:
IntMarginTyped() : Super() {}
IntMarginTyped(int32_t aTop, int32_t aRight, int32_t aBottom, int32_t aLeft) :
Super(aTop, aRight, aBottom, aLeft) {}
// XXX When all of the code is ported, the following functions to convert
// to and from unknown types should be removed.
static IntMarginTyped<units> FromUnknownMargin(const IntMarginTyped<UnknownUnits>& aMargin) {
return IntMarginTyped<units>(aMargin.top, aMargin.right,
aMargin.bottom, aMargin.left);
}
IntMarginTyped<UnknownUnits> ToUnknownMargin() const {
return IntMarginTyped<UnknownUnits>(this->top, this->right,
this->bottom, this->left);
}
};
typedef IntMarginTyped<UnknownUnits> IntMargin;
@ -83,8 +96,8 @@ struct IntRectTyped :
void RoundIn() {}
void RoundOut() {}
// XXX When all of the code is ported, the following functions to convert to and from
// unknown types should be removed.
// XXX When all of the code is ported, the following functions to convert
// to and from unknown types should be removed.
static IntRectTyped<units> FromUnknownRect(const IntRectTyped<UnknownUnits>& rect) {
return IntRectTyped<units>(rect.x, rect.y, rect.width, rect.height);

View File

@ -12,6 +12,7 @@
#include "ImageContainer.h"
#include "HeapCopyOfStackArray.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/UniquePtr.h"
#ifdef MOZ_WIDGET_GONK
#include "GrallocImages.h"
@ -330,8 +331,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
break;
}
nsAutoArrayPtr<char> buffer(new char[length]);
mGL->fGetShaderInfoLog(mTexBlit_VertShader, length, nullptr, buffer);
auto buffer = MakeUnique<char[]>(length);
mGL->fGetShaderInfoLog(mTexBlit_VertShader, length, nullptr, buffer.get());
printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get());
break;
@ -349,8 +350,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
break;
}
nsAutoArrayPtr<char> buffer(new char[length]);
mGL->fGetShaderInfoLog(fragShader, length, nullptr, buffer);
auto buffer = MakeUnique<char[]>(length);
mGL->fGetShaderInfoLog(fragShader, length, nullptr, buffer.get());
printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get());
break;
@ -369,8 +370,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
break;
}
nsAutoArrayPtr<char> buffer(new char[length]);
mGL->fGetProgramInfoLog(program, length, nullptr, buffer);
auto buffer = MakeUnique<char[]>(length);
mGL->fGetProgramInfoLog(program, length, nullptr, buffer.get());
printf_stderr("Program info log (%d bytes): %s\n", length, buffer.get());
}

View File

@ -116,7 +116,7 @@ BufferRecycleBin::BufferRecycleBin()
}
void
BufferRecycleBin::RecycleBuffer(uint8_t* aBuffer, uint32_t aSize)
BufferRecycleBin::RecycleBuffer(UniquePtr<uint8_t[]> aBuffer, uint32_t aSize)
{
MutexAutoLock lock(mLock);
@ -124,19 +124,19 @@ BufferRecycleBin::RecycleBuffer(uint8_t* aBuffer, uint32_t aSize)
mRecycledBuffers.Clear();
}
mRecycledBufferSize = aSize;
mRecycledBuffers.AppendElement(aBuffer);
mRecycledBuffers.AppendElement(Move(aBuffer));
}
uint8_t*
UniquePtr<uint8_t[]>
BufferRecycleBin::GetBuffer(uint32_t aSize)
{
MutexAutoLock lock(mLock);
if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
return new uint8_t[aSize];
return MakeUnique<uint8_t[]>(aSize);
uint32_t last = mRecycledBuffers.Length() - 1;
uint8_t* result = mRecycledBuffers[last].forget();
UniquePtr<uint8_t[]> result = Move(mRecycledBuffers[last]);
mRecycledBuffers.RemoveElementAt(last);
return result;
}
@ -439,7 +439,7 @@ PlanarYCbCrImage::PlanarYCbCrImage()
RecyclingPlanarYCbCrImage::~RecyclingPlanarYCbCrImage()
{
if (mBuffer) {
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
mRecycleBin->RecycleBuffer(Move(mBuffer), mBufferSize);
}
}
@ -454,7 +454,7 @@ RecyclingPlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
// - mImplData is not used
// Not owned:
// - mRecycleBin
size_t size = mBuffer.SizeOfExcludingThis(aMallocSizeOf);
size_t size = aMallocSizeOf(mBuffer.get());
// Could add in the future:
// - mBackendData (from base class)
@ -462,7 +462,7 @@ RecyclingPlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
return size;
}
uint8_t*
UniquePtr<uint8_t[]>
RecyclingPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
{
return mRecycleBin->GetBuffer(aSize);
@ -509,7 +509,7 @@ RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
// update buffer size
mBufferSize = size;
mData.mYChannel = mBuffer;
mData.mYChannel = mBuffer.get();
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
@ -555,7 +555,7 @@ RecyclingPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
// update buffer size
mBufferSize = aSize;
}
return mBuffer;
return mBuffer.get();
}
already_AddRefed<gfx::SourceSurface>

View File

@ -30,6 +30,7 @@
#include "mozilla/gfx/2D.h"
#include "nsDataHashtable.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/UniquePtr.h"
#ifndef XPCOM_GLUE_AVOID_NSPR
/**
@ -203,9 +204,9 @@ class BufferRecycleBin final {
public:
BufferRecycleBin();
void RecycleBuffer(uint8_t* aBuffer, uint32_t aSize);
void RecycleBuffer(mozilla::UniquePtr<uint8_t[]> aBuffer, uint32_t aSize);
// Returns a recycled buffer of the right size, or allocates a new buffer.
uint8_t* GetBuffer(uint32_t aSize);
mozilla::UniquePtr<uint8_t[]> GetBuffer(uint32_t aSize);
private:
typedef mozilla::Mutex Mutex;
@ -221,7 +222,7 @@ private:
// We should probably do something to prune this list on a timer so we don't
// eat excess memory while video is paused...
nsTArray<nsAutoArrayPtr<uint8_t> > mRecycledBuffers;
nsTArray<mozilla::UniquePtr<uint8_t[]>> mRecycledBuffers;
// This is only valid if mRecycledBuffers is non-empty
uint32_t mRecycledBufferSize;
};
@ -733,13 +734,11 @@ protected:
/**
* Return a buffer to store image data in.
* The default implementation returns memory that can
* be freed wit delete[]
*/
uint8_t* AllocateBuffer(uint32_t aSize);
mozilla::UniquePtr<uint8_t[]> AllocateBuffer(uint32_t aSize);
RefPtr<BufferRecycleBin> mRecycleBin;
nsAutoArrayPtr<uint8_t> mBuffer;
mozilla::UniquePtr<uint8_t[]> mBuffer;
};
/**

View File

@ -1914,8 +1914,9 @@ Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
}
if (GetIsFixedPosition()) {
LayerPoint anchor = GetFixedPositionAnchor();
aStream << nsPrintfCString(" [isFixedPosition scrollId=%lld anchor=%s%s]",
aStream << nsPrintfCString(" [isFixedPosition scrollId=%lld sides=0x%x anchor=%s%s]",
GetFixedPositionScrollContainerId(),
GetFixedPositionSides(),
ToString(anchor).c_str(),
IsClipFixed() ? "" : " scrollingClip").get();
}

View File

@ -7,6 +7,7 @@
#include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/MacIOSurfaceTextureClientOGL.h"
#include "mozilla/UniquePtr.h"
#include "YCbCrUtils.h"
using namespace mozilla;
@ -55,12 +56,12 @@ MacIOSurfaceImage::GetAsSourceSurface()
size_t cbCrWidth = mSurface->GetDevicePixelWidth(1);
size_t cbCrHeight = mSurface->GetDevicePixelHeight(1);
nsAutoArrayPtr<uint8_t> cbPlane(new uint8_t[cbCrWidth * cbCrHeight]);
nsAutoArrayPtr<uint8_t> crPlane(new uint8_t[cbCrWidth * cbCrHeight]);
auto cbPlane = MakeUnique<uint8_t[]>(cbCrWidth * cbCrHeight);
auto crPlane = MakeUnique<uint8_t[]>(cbCrWidth * cbCrHeight);
uint8_t* src = (uint8_t*)mSurface->GetBaseAddressOfPlane(1);
uint8_t* cbDest = cbPlane;
uint8_t* crDest = crPlane;
uint8_t* cbDest = cbPlane.get();
uint8_t* crDest = crPlane.get();
for (size_t i = 0; i < cbCrHeight; i++) {
uint8_t* rowSrc = src + cbCrStride * i;
@ -79,8 +80,8 @@ MacIOSurfaceImage::GetAsSourceSurface()
data.mYChannel = (uint8_t*)mSurface->GetBaseAddressOfPlane(0);
data.mYStride = mSurface->GetBytesPerRow(0);
data.mYSize = IntSize(mSurface->GetDevicePixelWidth(0), mSurface->GetDevicePixelHeight(0));
data.mCbChannel = cbPlane;
data.mCrChannel = crPlane;
data.mCbChannel = cbPlane.get();
data.mCrChannel = crPlane.get();
data.mCbCrStride = cbCrWidth;
data.mCbCrSize = IntSize(cbCrWidth, cbCrHeight);
data.mPicSize = data.mYSize;

View File

@ -231,9 +231,12 @@ APZEventState::ProcessLongTap(const nsCOMPtr<nsIPresShell>& aPresShell,
nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
APZES_LOG("Contextmenu event handled: %d\n", eventHandled);
// If no one handle context menu, fire MOZLONGTAP event
if (!eventHandled) {
if (eventHandled) {
// If the contextmenu event was handled then we're showing a contextmenu,
// and so we should remove any activation
mActiveElementManager->ClearActivation();
} else {
// If no one handle context menu, fire MOZLONGTAP event
LayoutDevicePoint currentPoint =
APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid)
* widget->GetDefaultScale();
@ -407,7 +410,8 @@ APZEventState::ProcessAPZStateChange(const nsCOMPtr<nsIDocument>& aDocument,
}
case APZStateChange::StartPanning:
{
mActiveElementManager->HandlePanStart();
// The user started to pan, so we don't want anything to be :active.
mActiveElementManager->ClearActivation();
break;
}
case APZStateChange::EndTouch:
@ -423,6 +427,17 @@ APZEventState::ProcessAPZStateChange(const nsCOMPtr<nsIDocument>& aDocument,
}
}
void
APZEventState::ProcessClusterHit()
{
// If we hit a cluster of links then we shouldn't activate any of them,
// as we will be showing the zoomed view. (This is only called on Fennec).
#ifndef MOZ_ANDROID_APZ
MOZ_ASSERT(false);
#endif
mActiveElementManager->ClearActivation();
}
bool
APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault)
{

View File

@ -69,6 +69,7 @@ public:
ViewID aViewId,
APZStateChange aChange,
int aArg);
void ProcessClusterHit();
private:
~APZEventState();
bool SendPendingTouchPreventedResponse(bool aPreventDefault);

View File

@ -101,12 +101,9 @@ ActiveElementManager::TriggerElementActivation()
}
void
ActiveElementManager::HandlePanStart()
ActiveElementManager::ClearActivation()
{
AEM_LOG("Handle pan start\n");
// The user started to pan, so we don't want mTarget to be :active.
// Make it not :active, and clear any pending task to make it :active.
AEM_LOG("Clearing element activation\n");
CancelTask();
ResetActive();
}

View File

@ -45,9 +45,9 @@ public:
*/
void HandleTouchStart(bool aCanBePan);
/**
* Handle the start of panning.
* Clear the active element.
*/
void HandlePanStart();
void ClearActivation();
/**
* Handle a touch-end or touch-cancel event.
* @param aWasClick whether the touch was a click

View File

@ -28,6 +28,7 @@ class APZEventState;
// tree.
class ChromeProcessController : public mozilla::layers::GeckoContentController
{
protected:
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;

View File

@ -12,7 +12,8 @@
#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
#include "gfxUtils.h" // for gfxUtils
#include "mozilla/mozalloc.h" // for operator delete[], etc
#include "nsAutoPtr.h" // for nsRefPtr, nsAutoArrayPtr
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "nsAutoRef.h" // for nsCountedRef
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsDebug.h" // for NS_ERROR, NS_ASSERTION
@ -44,7 +45,7 @@ public:
if (mDecodedBuffer) {
// Right now this only happens if the Image was never drawn, otherwise
// this will have been tossed away at surface destruction.
mRecycleBin->RecycleBuffer(mDecodedBuffer.forget(), mSize.height * mStride);
mRecycleBin->RecycleBuffer(Move(mDecodedBuffer), mSize.height * mStride);
}
}
@ -61,12 +62,12 @@ public:
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
size_t size = RecyclingPlanarYCbCrImage::SizeOfExcludingThis(aMallocSizeOf);
size += mDecodedBuffer.SizeOfExcludingThis(aMallocSizeOf);
size += aMallocSizeOf(mDecodedBuffer.get());
return size;
}
private:
nsAutoArrayPtr<uint8_t> mDecodedBuffer;
UniquePtr<uint8_t[]> mDecodedBuffer;
gfx::IntSize mScaleHint;
int mStride;
bool mDelayedConversion;
@ -125,7 +126,7 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
return false;
}
gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride);
gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer.get(), mStride);
SetOffscreenFormat(iFormat);
mSize = size;
@ -154,7 +155,7 @@ BasicPlanarYCbCrImage::GetAsSourceSurface()
// We create the target out of mDecodedBuffer, and get a snapshot from it.
// The draw target is destroyed on scope exit and the surface owns the data.
RefPtr<gfx::DrawTarget> drawTarget
= gfxPlatform::GetPlatform()->CreateDrawTargetForData(mDecodedBuffer,
= gfxPlatform::GetPlatform()->CreateDrawTargetForData(mDecodedBuffer.get(),
mSize,
mStride,
gfx::ImageFormatToSurfaceFormat(format));
@ -165,7 +166,7 @@ BasicPlanarYCbCrImage::GetAsSourceSurface()
surface = drawTarget->Snapshot();
}
mRecycleBin->RecycleBuffer(mDecodedBuffer.forget(), mSize.height * mStride);
mRecycleBin->RecycleBuffer(Move(mDecodedBuffer), mSize.height * mStride);
mSourceSurface = surface;
return surface.forget();

View File

@ -976,7 +976,7 @@ LayerManagerComposite::RenderToPresentationSurface()
}
GLContext* gl = compositor->gl();
GLContextEGL* egl = GLContextEGL::Cast(gl);
const IntSize windowSize = mirrorScreen->GetNaturalBoundsUntyped().Size();
const IntSize windowSize = mirrorScreen->GetNaturalBounds().Size().ToUnknownSize();
#endif
if ((windowSize.width <= 0) || (windowSize.height <= 0)) {

View File

@ -149,6 +149,7 @@ CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
, mWidget(aWidget)
, mHwnd(nullptr)
, mDisableSequenceForNextFrame(false)
, mVerifyBuffersFailed(false)
{
}
@ -1219,9 +1220,10 @@ CompositorD3D11::VerifyBufferSize()
return false;
}
if ((swapDesc.BufferDesc.Width == mSize.width &&
if (((swapDesc.BufferDesc.Width == mSize.width &&
swapDesc.BufferDesc.Height == mSize.height) ||
mSize.width <= 0 || mSize.height <= 0) {
mSize.width <= 0 || mSize.height <= 0) &&
!mVerifyBuffersFailed) {
return true;
}
@ -1241,6 +1243,7 @@ CompositorD3D11::VerifyBufferSize()
if (Failed(hr)) {
gfxCriticalNote << "D3D11 swap resize buffers failed " << hexa(hr) << " on " << mSize;
}
mVerifyBuffersFailed = FAILED(hr);
return Succeeded(hr);
}

View File

@ -199,6 +199,8 @@ private:
// This is the clip rect applied to the default DrawTarget (i.e. the window)
gfx::IntRect mCurrentClip;
nsIntRegion mInvalidRegion;
bool mVerifyBuffersFailed;
};
}

View File

@ -513,7 +513,7 @@ ShadowLayerForwarder::StorePluginWidgetConfigurations(const nsTArray<nsIWidget::
const nsIWidget::Configuration& configuration = aConfigurations[idx];
mPluginWindowData.AppendElement(PluginWindowData(configuration.mWindowID,
configuration.mClipRegion,
configuration.mBounds,
configuration.mBounds.ToUnknownRect(),
configuration.mVisible));
}
}
@ -598,6 +598,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
if (mutant->GetIsFixedPosition()) {
common.fixedPositionScrollContainerId() = mutant->GetFixedPositionScrollContainerId();
common.fixedPositionAnchor() = mutant->GetFixedPositionAnchor();
common.fixedPositionSides() = mutant->GetFixedPositionSides();
common.isClipFixed() = mutant->IsClipFixed();
}
common.isStickyPosition() = mutant->GetIsStickyPosition();

View File

@ -740,13 +740,13 @@ CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, bool aCopyFromSource,
// RGBA
size_t bufferSize = clampedRect.width * clampedRect.height * 4;
nsAutoArrayPtr<uint8_t> buf(new uint8_t[bufferSize]);
auto buf = MakeUnique<uint8_t[]>(bufferSize);
mGLContext->fReadPixels(clampedRect.x, clampedRect.y,
clampedRect.width, clampedRect.height,
LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE,
buf);
buf.get());
mGLContext->fTexImage2D(mFBOTextureTarget,
0,
LOCAL_GL_RGBA,
@ -754,7 +754,7 @@ CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, bool aCopyFromSource,
0,
LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE,
buf);
buf.get());
}
GLenum error = mGLContext->fGetError();
if (error != LOCAL_GL_NO_ERROR) {

View File

@ -9,6 +9,7 @@
#include "gfxFontUtils.h"
#include "gfxTextRun.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtrExtensions.h"
#include <algorithm>
@ -247,9 +248,9 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText,
}
// retrieve the laid-out glyph data from the CTRun
nsAutoArrayPtr<CGGlyph> glyphsArray;
nsAutoArrayPtr<CGPoint> positionsArray;
nsAutoArrayPtr<CFIndex> glyphToCharArray;
UniquePtr<CGGlyph[]> glyphsArray;
UniquePtr<CGPoint[]> positionsArray;
UniquePtr<CFIndex[]> glyphToCharArray;
const CGGlyph* glyphs = nullptr;
const CGPoint* positions = nullptr;
const CFIndex* glyphToChar = nullptr;
@ -264,7 +265,7 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText,
// may become an attractive option.
glyphs = ::CTRunGetGlyphsPtr(aCTRun);
if (!glyphs) {
glyphsArray = new (std::nothrow) CGGlyph[numGlyphs];
glyphsArray = MakeUniqueFallible<CGGlyph[]>(numGlyphs);
if (!glyphsArray) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -274,7 +275,7 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText,
positions = ::CTRunGetPositionsPtr(aCTRun);
if (!positions) {
positionsArray = new (std::nothrow) CGPoint[numGlyphs];
positionsArray = MakeUniqueFallible<CGPoint[]>(numGlyphs);
if (!positionsArray) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -287,7 +288,7 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText,
// or the stringRange of the glyph run
glyphToChar = ::CTRunGetStringIndicesPtr(aCTRun);
if (!glyphToChar) {
glyphToCharArray = new (std::nothrow) CFIndex[numGlyphs];
glyphToCharArray = MakeUniqueFallible<CFIndex[]>(numGlyphs);
if (!glyphToCharArray) {
return NS_ERROR_OUT_OF_MEMORY;
}

View File

@ -10,7 +10,8 @@
#include "mozilla/dom/ContentChild.h"
#include "gfxAndroidPlatform.h"
#include "mozilla/Omnijar.h"
#include "nsAutoPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "nsIInputStream.h"
#define gfxToolkitPlatform gfxAndroidPlatform
@ -1069,12 +1070,12 @@ gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
uint32_t bufSize = item->RealSize();
// We use fallible allocation here; if there's not enough RAM, we'll simply
// ignore the bundled fonts and fall back to the device's installed fonts.
nsAutoArrayPtr<uint8_t> buf(new (fallible) uint8_t[bufSize]);
auto buf = MakeUniqueFallible<uint8_t[]>(bufSize);
if (!buf) {
return;
}
nsZipCursor cursor(item, aArchive, buf, bufSize);
nsZipCursor cursor(item, aArchive, buf.get(), bufSize);
uint8_t* data = cursor.Copy(&bufSize);
NS_ASSERTION(data && bufSize == item->RealSize(),
"error reading bundled font");
@ -1085,13 +1086,13 @@ gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
FT_Library ftLibrary = gfxAndroidPlatform::GetPlatform()->GetFTLibrary();
FT_Face dummy;
if (FT_Err_Ok != FT_New_Memory_Face(ftLibrary, buf, bufSize, 0, &dummy)) {
if (FT_Err_Ok != FT_New_Memory_Face(ftLibrary, buf.get(), bufSize, 0, &dummy)) {
return;
}
for (FT_Long i = 0; i < dummy->num_faces; i++) {
FT_Face face;
if (FT_Err_Ok != FT_New_Memory_Face(ftLibrary, buf, bufSize, i, &face)) {
if (FT_Err_Ok != FT_New_Memory_Face(ftLibrary, buf.get(), bufSize, i, &face)) {
continue;
}
AddFaceToList(aEntryName, i, kStandard, FT2FontFamily::kVisible,

View File

@ -211,7 +211,7 @@ nsresult gfxFontEntry::InitializeUVSMap()
return NS_ERROR_FAILURE;
}
uint8_t* uvsData;
UniquePtr<uint8_t[]> uvsData;
unsigned int cmapLen;
const char* cmapData = hb_blob_get_data(cmapTable, &cmapLen);
nsresult rv = gfxFontUtils::ReadCMAPTableFormat14(
@ -223,7 +223,7 @@ nsresult gfxFontEntry::InitializeUVSMap()
return rv;
}
mUVSData = uvsData;
mUVSData = Move(uvsData);
}
return NS_OK;
@ -234,7 +234,7 @@ uint16_t gfxFontEntry::GetUVSGlyph(uint32_t aCh, uint32_t aVS)
InitializeUVSMap();
if (mUVSData) {
return gfxFontUtils::MapUVSToGlyphFormat14(mUVSData, aCh, aVS);
return gfxFontUtils::MapUVSToGlyphFormat14(mUVSData.get(), aCh, aVS);
}
return 0;

View File

@ -20,6 +20,7 @@
#include "nsDataHashtable.h"
#include "harfbuzz/hb.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtr.h"
typedef struct gr_face gr_face;
@ -429,7 +430,7 @@ public:
RefPtr<gfxCharacterMap> mCharacterMap;
uint32_t mUVSOffset;
nsAutoArrayPtr<uint8_t> mUVSData;
mozilla::UniquePtr<uint8_t[]> mUVSData;
nsAutoPtr<gfxUserFontData> mUserFontData;
nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
// list of gfxFonts that are using SVG glyphs

View File

@ -289,7 +289,7 @@ gfxFontUtils::ReadCMAPTableFormat4(const uint8_t *aBuf, uint32_t aLength,
nsresult
gfxFontUtils::ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength,
uint8_t*& aTable)
UniquePtr<uint8_t[]>& aTable)
{
enum {
OffsetFormat = 0,
@ -371,8 +371,8 @@ gfxFontUtils::ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength,
}
}
aTable = new uint8_t[tablelen];
memcpy(aTable, aBuf, tablelen);
aTable = MakeUnique<uint8_t[]>(tablelen);
memcpy(aTable.get(), aBuf, tablelen);
return NS_OK;
}

View File

@ -13,6 +13,7 @@
#include "mozilla/Likely.h"
#include "mozilla/Endian.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/UniquePtr.h"
#include "zlib.h"
#include <algorithm>
@ -786,7 +787,7 @@ public:
static nsresult
ReadCMAPTableFormat14(const uint8_t *aBuf, uint32_t aLength,
uint8_t*& aTable);
mozilla::UniquePtr<uint8_t[]>& aTable);
static uint32_t
FindPreferredSubtable(const uint8_t *aBuf, uint32_t aBufLength,

View File

@ -24,6 +24,7 @@
#include "mozilla/Likely.h"
#include "gfx2DGlue.h"
#include "mozilla/gfx/Logging.h" // for gfxCriticalError
#include "mozilla/UniquePtr.h"
#if defined(MOZ_WIDGET_GTK)
#include "gfxPlatformGtk.h" // xxx - for UseFcFontList
@ -2107,7 +2108,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
// we need to do numeral processing even on 8-bit text,
// in case we're converting Western to Hindi/Arabic digits
int32_t numOption = gfxPlatform::GetPlatform()->GetBidiNumeralOption();
nsAutoArrayPtr<char16_t> transformedString;
UniquePtr<char16_t[]> transformedString;
if (numOption != IBMBIDI_NUMERAL_NOMINAL) {
// scan the string for numerals that may need to be transformed;
// if we find any, we'll make a local copy here and use that for
@ -2119,7 +2120,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
char16_t newCh = HandleNumberInChar(origCh, prevIsArabic, numOption);
if (newCh != origCh) {
if (!transformedString) {
transformedString = new char16_t[aLength];
transformedString = MakeUnique<char16_t[]>(aLength);
if (sizeof(T) == sizeof(char16_t)) {
memcpy(transformedString.get(), aString, i * sizeof(char16_t));
} else {

View File

@ -168,7 +168,8 @@ extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
namespace js {
template <> struct GCMethods<jsid>
template <>
struct GCMethods<jsid>
{
static jsid initial() { return JSID_VOID; }
static void postBarrier(jsid* idp, jsid prev, jsid next) {}

View File

@ -148,13 +148,6 @@ TryPreserveReflector(JSContext* cx, HandleObject obj)
return true;
}
static inline void
WeakMapPostWriteBarrier(JSRuntime* rt, ObjectValueMap* weakMap, JSObject* key)
{
if (key && IsInsideNursery(key))
rt->gc.storeBuffer.putGeneric(gc::HashKeyRef<ObjectValueMap, JSObject*>(weakMap, key));
}
static MOZ_ALWAYS_INLINE bool
SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
HandleObject key, HandleValue value)
@ -189,7 +182,6 @@ SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
JS_ReportOutOfMemory(cx);
return false;
}
WeakMapPostWriteBarrier(cx->runtime(), map, key.get());
return true;
}

View File

@ -3881,6 +3881,9 @@ fi
MOZ_SUBCONFIGURE_FFI()
MOZ_SUBCONFIGURE_JEMALLOC()
# Avoid using obsolete NSPR features
AC_DEFINE(NO_NSPR_10_SUPPORT)
dnl Spit out some output
dnl ========================================================
MOZ_CREATE_CONFIG_STATUS()

View File

@ -7126,12 +7126,25 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
return false;
}
// Class methods are not enumerable.
if (type == ClassBody) {
switch (op) {
case JSOP_INITPROP: op = JSOP_INITHIDDENPROP; break;
case JSOP_INITPROP_GETTER: op = JSOP_INITHIDDENPROP_GETTER; break;
case JSOP_INITPROP_SETTER: op = JSOP_INITHIDDENPROP_SETTER; break;
default: MOZ_CRASH("Invalid op");
}
}
if (isIndex) {
objp.set(nullptr);
switch (op) {
case JSOP_INITPROP: op = JSOP_INITELEM; break;
case JSOP_INITPROP_GETTER: op = JSOP_INITELEM_GETTER; break;
case JSOP_INITPROP_SETTER: op = JSOP_INITELEM_SETTER; break;
case JSOP_INITPROP: op = JSOP_INITELEM; break;
case JSOP_INITHIDDENPROP: op = JSOP_INITHIDDENELEM; break;
case JSOP_INITPROP_GETTER: op = JSOP_INITELEM_GETTER; break;
case JSOP_INITHIDDENPROP_GETTER: op = JSOP_INITHIDDENELEM_GETTER; break;
case JSOP_INITPROP_SETTER: op = JSOP_INITELEM_SETTER; break;
case JSOP_INITHIDDENPROP_SETTER: op = JSOP_INITHIDDENELEM_SETTER; break;
default: MOZ_CRASH("Invalid op");
}
if (!emit1(op))
@ -7144,6 +7157,8 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
return false;
if (objp) {
MOZ_ASSERT(type == ObjectLiteral);
MOZ_ASSERT(!IsHiddenInitOp(op));
MOZ_ASSERT(!objp->inDictionaryMode());
Rooted<jsid> id(cx, AtomToId(key->pn_atom));
RootedValue undefinedValue(cx, UndefinedValue());
@ -8466,11 +8481,9 @@ CGBlockScopeList::findEnclosingScope(uint32_t index)
// scope contains POS, it should still be open, so its length should
// be zero.
return list[index].index;
} else {
// Conversely, if the length is not zero, it should not contain
// POS.
MOZ_ASSERT_IF(inPrologue == list[index].endInPrologue, list[index].end <= pos);
}
// Conversely, if the length is not zero, it should not contain POS.
MOZ_ASSERT_IF(inPrologue == list[index].endInPrologue, list[index].end <= pos);
}
return BlockScopeNote::NoBlockScopeIndex;

View File

@ -162,7 +162,8 @@ MovableCellHasher<T>::match(const Key& k, const Lookup& l)
template struct MovableCellHasher<JSObject*>;
template struct MovableCellHasher<GlobalObject*>;
template struct MovableCellHasher<SavedFrame*>;
template struct MovableCellHasher<ReadBarriered<ScopeObject*>>;
template struct MovableCellHasher<ScopeObject*>;
template struct MovableCellHasher<JSScript*>;
} // namespace js

View File

@ -482,7 +482,9 @@ class RelocatablePtr : public WriteBarrieredBase<T>
{
public:
RelocatablePtr() : WriteBarrieredBase<T>(GCMethods<T>::initial()) {}
explicit RelocatablePtr(T v) : WriteBarrieredBase<T>(v) {
// Implicitly adding barriers is a reasonable default.
MOZ_IMPLICIT RelocatablePtr(const T& v) : WriteBarrieredBase<T>(v) {
this->post(GCMethods<T>::initial(), this->value);
}
@ -560,14 +562,18 @@ class ReadBarriered : public ReadBarrieredBase<T>
public:
ReadBarriered() : ReadBarrieredBase<T>(GCMethods<T>::initial()) {}
// It is okay to add barriers implicitly.
MOZ_IMPLICIT ReadBarriered(const T& v) : ReadBarrieredBase<T>(v) {
this->post(GCMethods<T>::initial(), v);
}
// Copy is creating a new edge, so we must read barrier the source edge.
explicit ReadBarriered(const ReadBarriered& v) : ReadBarrieredBase<T>(v) {
this->post(GCMethods<T>::initial(), v.get());
}
// Move retains the lifetime status of the source edge, so does not fire
// the read barrier of the defunct edge.
ReadBarriered(ReadBarriered&& v)
: ReadBarrieredBase<T>(mozilla::Forward<ReadBarriered<T>>(v))
{
@ -604,6 +610,7 @@ class ReadBarriered : public ReadBarrieredBase<T>
const T operator->() const { return get(); }
T* unsafeGet() { return &this->value; }
T const* unsafeGet() const { return &this->value; }
void set(const T& v)
@ -799,6 +806,41 @@ struct MovableCellHasher
static void rekey(Key& k, const Key& newKey) { k = newKey; }
};
template <typename T>
struct MovableCellHasher<PreBarriered<T>>
{
using Key = PreBarriered<T>;
using Lookup = T;
static HashNumber hash(const Lookup& l) { return MovableCellHasher<T>::hash(l); }
static bool match(const Key& k, const Lookup& l) { return MovableCellHasher<T>::match(k, l); }
static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
};
template <typename T>
struct MovableCellHasher<RelocatablePtr<T>>
{
using Key = RelocatablePtr<T>;
using Lookup = T;
static HashNumber hash(const Lookup& l) { return MovableCellHasher<T>::hash(l); }
static bool match(const Key& k, const Lookup& l) { return MovableCellHasher<T>::match(k, l); }
static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
};
template <typename T>
struct MovableCellHasher<ReadBarriered<T>>
{
using Key = ReadBarriered<T>;
using Lookup = T;
static HashNumber hash(const Lookup& l) { return MovableCellHasher<T>::hash(l); }
static bool match(const Key& k, const Lookup& l) {
return MovableCellHasher<T>::match(k.unbarrieredGet(), l);
}
static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
};
/* Useful for hashtables with a HeapPtr as key. */
template <class T>
struct HeapPtrHasher

View File

@ -1964,6 +1964,12 @@ BaselineCompiler::emit_JSOP_INITELEM()
return true;
}
bool
BaselineCompiler::emit_JSOP_INITHIDDENELEM()
{
return emit_JSOP_INITELEM();
}
typedef bool (*MutateProtoFn)(JSContext* cx, HandlePlainObject obj, HandleValue newProto);
static const VMFunction MutateProtoInfo = FunctionInfo<MutateProtoFn>(MutatePrototype);
@ -2569,7 +2575,9 @@ bool
BaselineCompiler::emitInitPropGetterSetter()
{
MOZ_ASSERT(JSOp(*pc) == JSOP_INITPROP_GETTER ||
JSOp(*pc) == JSOP_INITPROP_SETTER);
JSOp(*pc) == JSOP_INITHIDDENPROP_GETTER ||
JSOp(*pc) == JSOP_INITPROP_SETTER ||
JSOp(*pc) == JSOP_INITHIDDENPROP_SETTER);
// Keep values on the stack for the decompiler.
frame.syncStack(0);
@ -2597,12 +2605,24 @@ BaselineCompiler::emit_JSOP_INITPROP_GETTER()
return emitInitPropGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITHIDDENPROP_GETTER()
{
return emitInitPropGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITPROP_SETTER()
{
return emitInitPropGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITHIDDENPROP_SETTER()
{
return emitInitPropGetterSetter();
}
typedef bool (*InitElemGetterSetterFn)(JSContext*, jsbytecode*, HandleObject, HandleValue,
HandleObject);
static const VMFunction InitElemGetterSetterInfo =
@ -2612,7 +2632,9 @@ bool
BaselineCompiler::emitInitElemGetterSetter()
{
MOZ_ASSERT(JSOp(*pc) == JSOP_INITELEM_GETTER ||
JSOp(*pc) == JSOP_INITELEM_SETTER);
JSOp(*pc) == JSOP_INITHIDDENELEM_GETTER ||
JSOp(*pc) == JSOP_INITELEM_SETTER ||
JSOp(*pc) == JSOP_INITHIDDENELEM_SETTER);
// Load index and value in R0 and R1, but keep values on the stack for the
// decompiler.
@ -2641,12 +2663,24 @@ BaselineCompiler::emit_JSOP_INITELEM_GETTER()
return emitInitElemGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITHIDDENELEM_GETTER()
{
return emitInitElemGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITELEM_SETTER()
{
return emitInitElemGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITHIDDENELEM_SETTER()
{
return emitInitElemGetterSetter();
}
bool
BaselineCompiler::emit_JSOP_INITELEM_INC()
{

View File

@ -208,7 +208,12 @@ namespace jit {
_(JSOP_SUPERCALL) \
_(JSOP_SPREADSUPERCALL) \
_(JSOP_THROWSETCONST) \
_(JSOP_THROWSETALIASEDCONST)
_(JSOP_THROWSETALIASEDCONST) \
_(JSOP_INITHIDDENPROP_GETTER) \
_(JSOP_INITHIDDENPROP_SETTER) \
_(JSOP_INITHIDDENELEM) \
_(JSOP_INITHIDDENELEM_GETTER) \
_(JSOP_INITHIDDENELEM_SETTER)
class BaselineCompiler : public BaselineCompilerSpecific
{

View File

@ -3477,6 +3477,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
MOZ_ASSERT(op == JSOP_SETELEM ||
op == JSOP_STRICTSETELEM ||
op == JSOP_INITELEM ||
op == JSOP_INITHIDDENELEM ||
op == JSOP_INITELEM_ARRAY ||
op == JSOP_INITELEM_INC);
@ -3494,8 +3495,8 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
oldInitLength = GetAnyBoxedOrUnboxedInitializedLength(obj);
}
if (op == JSOP_INITELEM) {
if (!InitElemOperation(cx, obj, index, rhs))
if (op == JSOP_INITELEM || op == JSOP_INITHIDDENELEM) {
if (!InitElemOperation(cx, pc, obj, index, rhs))
return false;
} else if (op == JSOP_INITELEM_ARRAY) {
MOZ_ASSERT(uint32_t(index.toInt32()) <= INT32_MAX,

View File

@ -4848,7 +4848,7 @@ CodeGenerator::visitNewStringObject(LNewStringObject* lir)
masm.bind(ool->rejoin());
}
typedef bool(*InitElemFn)(JSContext* cx, HandleObject obj,
typedef bool(*InitElemFn)(JSContext* cx, jsbytecode* pc, HandleObject obj,
HandleValue id, HandleValue value);
static const VMFunction InitElemInfo =
FunctionInfo<InitElemFn>(InitElemOperation);
@ -4861,6 +4861,7 @@ CodeGenerator::visitInitElem(LInitElem* lir)
pushArg(ToValue(lir, LInitElem::ValueIndex));
pushArg(ToValue(lir, LInitElem::IdIndex));
pushArg(objReg);
pushArg(ImmPtr(lir->mir()->resumePoint()->pc()));
callVM(InitElemInfo, lir);
}

View File

@ -161,6 +161,7 @@ IonBuilder::IonBuilder(JSContext* analysisContext, CompileCompartment* comp,
maybeFallbackFunctionGetter_(nullptr)
{
script_ = info->script();
scriptHasIonScript_ = script_->hasIonScript();
pc = info->startPC();
abortReason_ = AbortReason_Disable;
@ -1838,6 +1839,7 @@ IonBuilder::inspectOpcode(JSOp op)
return jsop_newobject();
case JSOP_INITELEM:
case JSOP_INITHIDDENELEM:
return jsop_initelem();
case JSOP_INITELEM_ARRAY:
@ -1857,13 +1859,17 @@ IonBuilder::inspectOpcode(JSOp op)
}
case JSOP_INITPROP_GETTER:
case JSOP_INITPROP_SETTER: {
case JSOP_INITHIDDENPROP_GETTER:
case JSOP_INITPROP_SETTER:
case JSOP_INITHIDDENPROP_SETTER: {
PropertyName* name = info().getAtom(pc)->asPropertyName();
return jsop_initprop_getter_setter(name);
}
case JSOP_INITELEM_GETTER:
case JSOP_INITHIDDENELEM_GETTER:
case JSOP_INITELEM_SETTER:
case JSOP_INITHIDDENELEM_SETTER:
return jsop_initelem_getter_setter();
case JSOP_FUNCALL:

View File

@ -1016,6 +1016,10 @@ class IonBuilder
// A builder is inextricably tied to a particular script.
JSScript* script_;
// script->hasIonScript() at the start of the compilation. Used to avoid
// calling hasIonScript() from background compilation threads.
bool scriptHasIonScript_;
// If off thread compilation is successful, the final code generator is
// attached here. Code has been generated, but not linked (there is not yet
// an IonScript). This is heap allocated, and must be explicitly destroyed,
@ -1035,6 +1039,7 @@ class IonBuilder
JSObject* checkNurseryObject(JSObject* obj);
JSScript* script() const { return script_; }
bool scriptHasIonScript() const { return scriptHasIonScript_; }
CodeGenerator* backgroundCodegen() const { return backgroundCodegen_; }
void setBackgroundCodegen(CodeGenerator* codegen) { backgroundCodegen_ = codegen; }

View File

@ -136,7 +136,7 @@ class StringifyContext
: sb(sb),
gap(gap),
replacer(cx, replacer),
stack(cx, TraceableHashSet<JSObject*>(cx)),
stack(cx, TraceableHashSet<JSObject*, MovableCellHasher<JSObject*>>(cx)),
propertyList(propertyList),
depth(0)
{}
@ -148,7 +148,7 @@ class StringifyContext
StringBuffer& sb;
const StringBuffer& gap;
RootedObject replacer;
Rooted<TraceableHashSet<JSObject*>> stack;
Rooted<TraceableHashSet<JSObject*, MovableCellHasher<JSObject*>>> stack;
const AutoIdVector& propertyList;
uint32_t depth;
};
@ -324,7 +324,7 @@ class CycleDetector
}
private:
MutableHandle<TraceableHashSet<JSObject*>> stack;
MutableHandle<TraceableHashSet<JSObject*, MovableCellHasher<JSObject*>>> stack;
HandleObject obj_;
};

View File

@ -703,6 +703,14 @@ IsGetPropPC(jsbytecode* pc)
return op == JSOP_LENGTH || op == JSOP_GETPROP || op == JSOP_CALLPROP;
}
inline bool
IsHiddenInitOp(JSOp op)
{
return op == JSOP_INITHIDDENPROP || op == JSOP_INITHIDDENELEM ||
op == JSOP_INITHIDDENPROP_GETTER || op == JSOP_INITHIDDENELEM_GETTER ||
op == JSOP_INITHIDDENPROP_SETTER || op == JSOP_INITHIDDENELEM_SETTER;
}
inline bool
IsStrictSetPC(jsbytecode* pc)
{

View File

@ -18,9 +18,9 @@ using namespace js;
using namespace js::gc;
inline HashNumber
DefaultHasher<WatchKey>::hash(const Lookup& key)
WatchKeyHasher::hash(const Lookup& key)
{
return DefaultHasher<JSObject*>::hash(key.object.get()) ^ HashId(key.id.get());
return MovableCellHasher<PreBarrieredObject>::hash(key.object) ^ HashId(key.id);
}
namespace {

View File

@ -20,6 +20,9 @@ struct WatchKey {
WatchKey() {}
WatchKey(JSObject* obj, jsid id) : object(obj), id(id) {}
WatchKey(const WatchKey& key) : object(key.object.get()), id(key.id.get()) {}
// These are traced unconditionally during minor GC, so do not require
// post-barriers.
PreBarrieredObject object;
PreBarrieredId id;
@ -40,14 +43,14 @@ struct Watchpoint {
: handler(handler), closure(closure), held(held) {}
};
template <>
struct DefaultHasher<WatchKey>
struct WatchKeyHasher
{
typedef WatchKey Lookup;
static inline js::HashNumber hash(const Lookup& key);
static bool match(const WatchKey& k, const Lookup& l) {
return k.object == l.object && k.id.get() == l.id.get();
return MovableCellHasher<PreBarrieredObject>::match(k.object, l.object) &&
DefaultHasher<PreBarrieredId>::match(k.id, l.id);
}
static void rekey(WatchKey& k, const WatchKey& newKey) {
@ -58,7 +61,7 @@ struct DefaultHasher<WatchKey>
class WatchpointMap {
public:
typedef HashMap<WatchKey, Watchpoint, DefaultHasher<WatchKey>, SystemAllocPolicy> Map;
typedef HashMap<WatchKey, Watchpoint, WatchKeyHasher, SystemAllocPolicy> Map;
bool init();
bool watch(JSContext* cx, HandleObject obj, HandleId id,

View File

@ -188,8 +188,6 @@ ObjectWeakMap::add(JSContext* cx, JSObject* obj, JSObject* target)
ReportOutOfMemory(cx);
return false;
}
if (IsInsideNursery(obj))
cx->runtime()->gc.storeBuffer.putGeneric(StoreBufferRef(&map, obj));
return true;
}

View File

@ -392,11 +392,14 @@ extern JSObject*
InitWeakMapClass(JSContext* cx, HandleObject obj);
class ObjectValueMap : public WeakMap<PreBarrieredObject, RelocatableValue>
class ObjectValueMap : public WeakMap<RelocatablePtrObject, RelocatableValue,
MovableCellHasher<RelocatablePtrObject>>
{
public:
ObjectValueMap(JSContext* cx, JSObject* obj)
: WeakMap<PreBarrieredObject, RelocatableValue>(cx, obj) {}
: WeakMap<RelocatablePtrObject, RelocatableValue,
MovableCellHasher<RelocatablePtrObject>>(cx, obj)
{}
virtual bool findZoneEdges();
};
@ -405,9 +408,7 @@ class ObjectValueMap : public WeakMap<PreBarrieredObject, RelocatableValue>
// Generic weak map for mapping objects to other objects.
class ObjectWeakMap
{
private:
ObjectValueMap map;
typedef gc::HashKeyRef<ObjectValueMap, JSObject*> StoreBufferRef;
public:
explicit ObjectWeakMap(JSContext* cx);

View File

@ -52,20 +52,20 @@ for (let a of [testClass,
var aMethDesc = Object.getOwnPropertyDescriptor(a.prototype, \"__proto__\");
assertEq(aMethDesc.writable, true);
assertEq(aMethDesc.configurable, true);
assertEq(aMethDesc.enumerable, true);
assertEq(aMethDesc.enumerable, false);
aMethDesc.value();
assertEq(methodCalled, true);
var aGetDesc = Object.getOwnPropertyDescriptor(a.prototype, \"getter\");
assertEq(aGetDesc.configurable, true);
assertEq(aGetDesc.enumerable, true);
assertEq(aGetDesc.enumerable, false);
aGetDesc.get();
assertThrowsInstanceOf(() => new aGetDesc.get, TypeError);
assertEq(getterCalled, true);
var aSetDesc = Object.getOwnPropertyDescriptor(a.prototype, \"setter\");
assertEq(aSetDesc.configurable, true);
assertEq(aSetDesc.enumerable, true);
assertEq(aSetDesc.enumerable, false);
aSetDesc.set();
assertThrowsInstanceOf(() => new aSetDesc.set, TypeError);
assertEq(setterCalled, true);
@ -74,7 +74,7 @@ for (let a of [testClass,
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticMethod\"), undefined);
var aStaticMethDesc = Object.getOwnPropertyDescriptor(a, \"staticMethod\");
assertEq(aStaticMethDesc.configurable, true);
assertEq(aStaticMethDesc.enumerable, true);
assertEq(aStaticMethDesc.enumerable, false);
assertEq(aStaticMethDesc.writable, true);
aStaticMethDesc.value();
assertThrowsInstanceOf(() => new aStaticMethDesc.value, TypeError);
@ -83,7 +83,7 @@ for (let a of [testClass,
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticGetter\"), undefined);
var aStaticGetDesc = Object.getOwnPropertyDescriptor(a, \"staticGetter\");
assertEq(aStaticGetDesc.configurable, true);
assertEq(aStaticGetDesc.enumerable, true);
assertEq(aStaticGetDesc.enumerable, false);
aStaticGetDesc.get();
assertThrowsInstanceOf(() => new aStaticGetDesc.get, TypeError);
assertEq(staticGetterCalled, true);
@ -91,7 +91,7 @@ for (let a of [testClass,
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticSetter\"), undefined);
var aStaticSetDesc = Object.getOwnPropertyDescriptor(a, \"staticSetter\");
assertEq(aStaticSetDesc.configurable, true);
assertEq(aStaticSetDesc.enumerable, true);
assertEq(aStaticSetDesc.enumerable, false);
aStaticSetDesc.set();
assertThrowsInstanceOf(() => new aStaticSetDesc.set, TypeError);
assertEq(staticSetterCalled, true);

View File

@ -1082,6 +1082,8 @@ InnerViewTable::addView(JSContext* cx, ArrayBufferObject* buffer, ArrayBufferVie
ReportOutOfMemory(cx);
return false;
}
// ViewVector has one inline element, so the first insertion is
// guaranteed to succeed.
MOZ_ALWAYS_TRUE(p->value().append(view));
}
@ -1138,11 +1140,8 @@ InnerViewTable::sweep(JSRuntime* rt)
return;
for (Map::Enum e(map); !e.empty(); e.popFront()) {
JSObject* key = e.front().key();
if (sweepEntry(&key, e.front().value()))
if (sweepEntry(&e.front().mutableKey(), e.front().value()))
e.removeFront();
else if (key != e.front().key())
e.rekeyFront(key);
}
}
@ -1153,15 +1152,13 @@ InnerViewTable::sweepAfterMinorGC(JSRuntime* rt)
if (nurseryKeysValid) {
for (size_t i = 0; i < nurseryKeys.length(); i++) {
JSObject* key = nurseryKeys[i];
Map::Ptr p = map.lookup(key);
JSObject* buffer = MaybeForwarded(nurseryKeys[i]);
Map::Ptr p = map.lookup(buffer);
if (!p)
continue;
if (sweepEntry(&key, p->value()))
map.remove(nurseryKeys[i]);
else
map.rekeyIfMoved(nurseryKeys[i], key);
if (sweepEntry(&p->mutableKey(), p->value()))
map.remove(buffer);
}
nurseryKeys.clear();
} else {

View File

@ -501,9 +501,17 @@ class InnerViewTable
friend class ArrayBufferObject;
private:
// This key is a raw pointer and not a ReadBarriered because the post-
// barrier would hold nursery-allocated entries live unconditionally. It is
// a very common pattern in low-level and performance-oriented JavaScript
// to create hundreds or thousands of very short lived temporary views on a
// larger buffer; having to tenured all of these would be a catastrophic
// performance regression. Thus, it is vital that nursery pointers in this
// map not be held live. Special support is required in the minor GC,
// implemented in sweepAfterMinorGC.
typedef HashMap<JSObject*,
ViewVector,
DefaultHasher<JSObject*>,
MovableCellHasher<JSObject*>,
SystemAllocPolicy> Map;
// For all objects sharing their storage with some other view, this maps
@ -511,7 +519,10 @@ class InnerViewTable
Map map;
// List of keys from innerViews where either the source or at least one
// target is in the nursery.
// target is in the nursery. The raw pointer to a JSObject is allowed here
// because this vector is cleared after every minor collection. Users in
// sweepAfterMinorCollection must be careful to use MaybeForwarded before
// touching these pointers.
Vector<JSObject*, 0, SystemAllocPolicy> nurseryKeys;
// Whether nurseryKeys is a complete list.

View File

@ -1462,7 +1462,8 @@ Debugger::onTrap(JSContext* cx, MutableHandleValue vp)
* global the script is running against.
*/
Debugger* dbg = bp->debugger;
if (dbg->enabled && dbg->debuggees.lookup(scriptGlobal)) {
bool hasDebuggee = dbg->enabled && dbg->debuggees.has(scriptGlobal);
if (hasDebuggee) {
Maybe<AutoCompartment> ac;
ac.emplace(cx, dbg->object);
@ -2536,13 +2537,8 @@ Debugger::markAll(JSTracer* trc)
{
JSRuntime* rt = trc->runtime();
for (Debugger* dbg : rt->debuggerList) {
WeakGlobalObjectSet& debuggees = dbg->debuggees;
for (WeakGlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
GlobalObject* global = e.front().unbarrieredGet();
TraceManuallyBarrieredEdge(trc, &global, "Global Object");
if (global != e.front().unbarrieredGet())
e.rekeyFront(global, ReadBarrieredGlobalObject(global));
}
for (WeakGlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
TraceManuallyBarrieredEdge(trc, e.mutableFront().unsafeGet(), "Global Object");
HeapPtrNativeObject& dbgobj = dbg->toJSObjectRef();
TraceEdge(trc, &dbgobj, "Debugger Object");

View File

@ -42,7 +42,7 @@ class Breakpoint;
class DebuggerMemory;
typedef HashSet<ReadBarrieredGlobalObject,
DefaultHasher<ReadBarrieredGlobalObject>,
MovableCellHasher<ReadBarrieredGlobalObject>,
SystemAllocPolicy> WeakGlobalObjectSet;
/*
@ -70,10 +70,11 @@ typedef HashSet<ReadBarrieredGlobalObject,
* transitions.
*/
template <class UnbarrieredKey, bool InvisibleKeysOk=false>
class DebuggerWeakMap : private WeakMap<PreBarriered<UnbarrieredKey>, RelocatablePtrObject>
class DebuggerWeakMap : private WeakMap<RelocatablePtr<UnbarrieredKey>, RelocatablePtrObject,
MovableCellHasher<RelocatablePtr<UnbarrieredKey>>>
{
private:
typedef PreBarriered<UnbarrieredKey> Key;
typedef RelocatablePtr<UnbarrieredKey> Key;
typedef RelocatablePtrObject Value;
typedef HashMap<JS::Zone*,
@ -85,7 +86,7 @@ class DebuggerWeakMap : private WeakMap<PreBarriered<UnbarrieredKey>, Relocatabl
JSCompartment* compartment;
public:
typedef WeakMap<Key, Value, DefaultHasher<Key> > Base;
typedef WeakMap<Key, Value, MovableCellHasher<Key>> Base;
explicit DebuggerWeakMap(JSContext* cx)
: Base(cx),
@ -156,13 +157,9 @@ class DebuggerWeakMap : private WeakMap<PreBarriered<UnbarrieredKey>, Relocatabl
/* Override sweep method to also update our edge cache. */
void sweep() {
for (Enum e(*static_cast<Base*>(this)); !e.empty(); e.popFront()) {
Key k(e.front().key());
if (gc::IsAboutToBeFinalized(&k)) {
if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) {
decZoneCount(e.front().key()->zone());
e.removeFront();
decZoneCount(k->zone());
} else {
// markKeys() should have done any necessary relocation.
MOZ_ASSERT(k == e.front().key());
}
}
Base::assertEntriesNotAboutToBeFinalized();

View File

@ -762,8 +762,8 @@ IonBuilderHasHigherPriority(jit::IonBuilder* first, jit::IonBuilder* second)
return first->optimizationInfo().level() < second->optimizationInfo().level();
// A script without an IonScript has precedence on one with.
if (first->script()->hasIonScript() != second->script()->hasIonScript())
return !first->script()->hasIonScript();
if (first->scriptHasIonScript() != second->scriptHasIonScript())
return !first->scriptHasIonScript();
// A higher warm-up counter indicates a higher priority.
return first->script()->getWarmUpCount() / first->script()->length() >

Some files were not shown because too many files have changed in this diff Show More