mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
03e1b153e0
@ -216,8 +216,11 @@
|
||||
|
||||
this.mDialog.close();
|
||||
|
||||
ok(!isAccessibleInCache(dlgDoc),
|
||||
"The document accessible for '" + aURL + "' is in cache still!");
|
||||
// close() is asynchronous.
|
||||
SimpleTest.executeSoon(function() {
|
||||
ok(!isAccessibleInCache(dlgDoc),
|
||||
"The document accessible for '" + aURL + "' is in cache still!");
|
||||
});
|
||||
}
|
||||
|
||||
this.getID = function openDialogWnd_getID()
|
||||
|
@ -22,12 +22,6 @@
|
||||
src="../browser.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
if (navigator.platform.startsWith("Mac")) {
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
} else {
|
||||
SimpleTest.expectAssertions(1);
|
||||
}
|
||||
|
||||
function hasTabModalPrompts() {
|
||||
try {
|
||||
return SpecialPowers.getBoolPref("prompts.tab_modal.enabled");
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
const { defer } = require('../core/promise');
|
||||
const events = require('../system/events');
|
||||
const { setImmediate } = require('../timers');
|
||||
const { open: openWindow, onFocus, getToplevelWindow,
|
||||
isInteractive } = require('./utils');
|
||||
|
||||
@ -15,14 +16,18 @@ exports.open = open;
|
||||
|
||||
function close(window) {
|
||||
// We shouldn't wait for unload, as it is dispatched
|
||||
// before the window is actually closed.
|
||||
// `domwindowclosed` is a better match.
|
||||
// before the window is actually closed. 'domwindowclosed' isn't great either,
|
||||
// because it's fired midway through window teardown (see bug 874502
|
||||
// comment 15). We could go with xul-window-destroyed, but _that_ doesn't
|
||||
// provide us with a subject by which to disambiguate notifications. So we
|
||||
// end up just doing the dumb thing and round-tripping through the event loop
|
||||
// with setImmediate.
|
||||
let deferred = defer();
|
||||
let toplevelWindow = getToplevelWindow(window);
|
||||
events.on("domwindowclosed", function onclose({subject}) {
|
||||
if (subject == toplevelWindow) {
|
||||
events.off("domwindowclosed", onclose);
|
||||
deferred.resolve(window);
|
||||
setImmediate(function() deferred.resolve(window));
|
||||
}
|
||||
}, true);
|
||||
window.close();
|
||||
|
@ -325,6 +325,11 @@ exports.testTrackWindows = function(assert, done) {
|
||||
onActivate: function(window) {
|
||||
let index = windows.indexOf(window);
|
||||
|
||||
// Guard against windows that have already been removed.
|
||||
// See bug 874502 comment 32.
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
assert.equal(actions.join(),
|
||||
expects.slice(0, index*4).join(),
|
||||
"expecting " + expects[index*4]);
|
||||
@ -351,6 +356,11 @@ exports.testTrackWindows = function(assert, done) {
|
||||
onDeactivate: function(window) {
|
||||
let index = windows.indexOf(window);
|
||||
|
||||
// Guard against windows that have already been removed.
|
||||
// See bug 874502 comment 32.
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
assert.equal(actions.join(),
|
||||
expects.slice(0, index*4 + 2).join(),
|
||||
"expecting " + expects[index*4 + 2]);
|
||||
|
@ -3,7 +3,11 @@ var runs = [
|
||||
is(tabbrowser.browsers.length, 2, "test_bug462673.html has opened a second tab");
|
||||
is(tabbrowser.selectedTab, tab.nextSibling, "dependent tab is selected");
|
||||
tabbrowser.removeTab(tab);
|
||||
ok(win.closed, "Window is closed");
|
||||
// Closing a tab will also close its parent chrome window, but async
|
||||
executeSoon(function() {
|
||||
ok(win.closed, "Window is closed");
|
||||
testComplete(win);
|
||||
});
|
||||
},
|
||||
function (win, tabbrowser, tab) {
|
||||
var newTab = tabbrowser.addTab();
|
||||
@ -17,6 +21,7 @@ var runs = [
|
||||
is(tabbrowser.selectedBrowser, newBrowser, "Browser for remaining tab is selected");
|
||||
is(tabbrowser.mTabBox.selectedPanel, newBrowser.parentNode.parentNode.parentNode.parentNode, "Panel for remaining tab is selected");
|
||||
}
|
||||
testComplete(win);
|
||||
}
|
||||
];
|
||||
|
||||
@ -25,6 +30,14 @@ function test() {
|
||||
runOneTest();
|
||||
}
|
||||
|
||||
function testComplete(win) {
|
||||
win.close();
|
||||
if (runs.length)
|
||||
runOneTest();
|
||||
else
|
||||
finish();
|
||||
}
|
||||
|
||||
function runOneTest() {
|
||||
var win = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||
|
||||
@ -39,11 +52,6 @@ function runOneTest() {
|
||||
|
||||
executeSoon(function () {
|
||||
runs.shift()(win, win.gBrowser, tab);
|
||||
win.close();
|
||||
if (runs.length)
|
||||
runOneTest();
|
||||
else
|
||||
finish();
|
||||
});
|
||||
}, true);
|
||||
|
||||
|
@ -235,6 +235,9 @@ function runTest() {
|
||||
|
||||
// check that the last dir store got cleared in a new PB window
|
||||
pbWin.close();
|
||||
// And give it time to close
|
||||
executeSoon(moveAlong);
|
||||
yield;
|
||||
let pbWin = yield createWindow({private: true});
|
||||
let pbDownloadLastDir = new DownloadLastDir(pbWin);
|
||||
|
||||
|
@ -2596,6 +2596,13 @@ let SessionStoreInternal = {
|
||||
tabbrowser.unpinTab(tabbrowser.tabs[t]);
|
||||
}
|
||||
|
||||
// We need to keep track of the initially open tabs so that they
|
||||
// can be moved to the end of the restored tabs.
|
||||
let initialTabs = [];
|
||||
if (!overwriteTabs && firstWindow) {
|
||||
initialTabs = Array.slice(tabbrowser.tabs);
|
||||
}
|
||||
|
||||
// make sure that the selected tab won't be closed in order to
|
||||
// prevent unnecessary flickering
|
||||
if (overwriteTabs && tabbrowser.selectedTab._tPos >= newTabCount)
|
||||
@ -2607,10 +2614,6 @@ let SessionStoreInternal = {
|
||||
tabs.push(t < openTabCount ?
|
||||
tabbrowser.tabs[t] :
|
||||
tabbrowser.addTab("about:blank", {skipAnimation: true}));
|
||||
// when resuming at startup: add additionally requested pages to the end
|
||||
if (!overwriteTabs && firstWindow) {
|
||||
tabbrowser.moveTabTo(tabs[t], t);
|
||||
}
|
||||
|
||||
if (winData.tabs[t].pinned)
|
||||
tabbrowser.pinTab(tabs[t]);
|
||||
@ -2624,6 +2627,14 @@ let SessionStoreInternal = {
|
||||
}
|
||||
}
|
||||
|
||||
if (!overwriteTabs && firstWindow) {
|
||||
// Move the originally open tabs to the end
|
||||
let endPosition = tabbrowser.tabs.length - 1;
|
||||
for (let i = 0; i < initialTabs.length; i++) {
|
||||
tabbrowser.moveTabTo(initialTabs[i], endPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// if all tabs to be restored are hidden, make the first one visible
|
||||
if (!numVisibleTabs && winData.tabs.length) {
|
||||
winData.tabs[0].hidden = false;
|
||||
|
@ -39,48 +39,51 @@ function test() {
|
||||
|
||||
newWin.close();
|
||||
|
||||
is(ss.getClosedWindowCount(), 1,
|
||||
"The closed window was added to Recently Closed Windows");
|
||||
let data = JSON.parse(ss.getClosedWindowData())[0];
|
||||
ok(data.title == TEST_URL && JSON.stringify(data).indexOf(uniqueText) > -1,
|
||||
"The closed window data was stored correctly");
|
||||
// Now give it time to close
|
||||
executeSoon(function() {
|
||||
is(ss.getClosedWindowCount(), 1,
|
||||
"The closed window was added to Recently Closed Windows");
|
||||
let data = JSON.parse(ss.getClosedWindowData())[0];
|
||||
ok(data.title == TEST_URL && JSON.stringify(data).indexOf(uniqueText) > -1,
|
||||
"The closed window data was stored correctly");
|
||||
|
||||
// reopen the closed window and ensure its integrity
|
||||
let newWin2 = ss.undoCloseWindow(0);
|
||||
// reopen the closed window and ensure its integrity
|
||||
let newWin2 = ss.undoCloseWindow(0);
|
||||
|
||||
ok(newWin2 instanceof ChromeWindow,
|
||||
"undoCloseWindow actually returned a window");
|
||||
is(ss.getClosedWindowCount(), 0,
|
||||
"The reopened window was removed from Recently Closed Windows");
|
||||
ok(newWin2 instanceof ChromeWindow,
|
||||
"undoCloseWindow actually returned a window");
|
||||
is(ss.getClosedWindowCount(), 0,
|
||||
"The reopened window was removed from Recently Closed Windows");
|
||||
|
||||
// SSTabRestored will fire more than once, so we need to make sure we count them
|
||||
let restoredTabs = 0;
|
||||
let expectedTabs = data.tabs.length;
|
||||
newWin2.addEventListener("SSTabRestored", function sstabrestoredListener(aEvent) {
|
||||
++restoredTabs;
|
||||
info("Restored tab " + restoredTabs + "/" + expectedTabs);
|
||||
if (restoredTabs < expectedTabs) {
|
||||
return;
|
||||
}
|
||||
// SSTabRestored will fire more than once, so we need to make sure we count them
|
||||
let restoredTabs = 0;
|
||||
let expectedTabs = data.tabs.length;
|
||||
newWin2.addEventListener("SSTabRestored", function sstabrestoredListener(aEvent) {
|
||||
++restoredTabs;
|
||||
info("Restored tab " + restoredTabs + "/" + expectedTabs);
|
||||
if (restoredTabs < expectedTabs) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(restoredTabs, expectedTabs, "correct number of tabs restored");
|
||||
newWin2.removeEventListener("SSTabRestored", sstabrestoredListener, true);
|
||||
is(restoredTabs, expectedTabs, "correct number of tabs restored");
|
||||
newWin2.removeEventListener("SSTabRestored", sstabrestoredListener, true);
|
||||
|
||||
is(newWin2.gBrowser.tabs.length, 2,
|
||||
"The window correctly restored 2 tabs");
|
||||
is(newWin2.gBrowser.currentURI.spec, TEST_URL,
|
||||
"The window correctly restored the URL");
|
||||
is(newWin2.gBrowser.tabs.length, 2,
|
||||
"The window correctly restored 2 tabs");
|
||||
is(newWin2.gBrowser.currentURI.spec, TEST_URL,
|
||||
"The window correctly restored the URL");
|
||||
|
||||
let [txt, chk] = newWin2.content.document.querySelectorAll("#txt, #chk");
|
||||
ok(txt.value == uniqueText && chk.checked,
|
||||
"The window correctly restored the form");
|
||||
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
|
||||
"The window correctly restored the data associated with it");
|
||||
let [txt, chk] = newWin2.content.document.querySelectorAll("#txt, #chk");
|
||||
ok(txt.value == uniqueText && chk.checked,
|
||||
"The window correctly restored the form");
|
||||
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
|
||||
"The window correctly restored the data associated with it");
|
||||
|
||||
// clean up
|
||||
newWin2.close();
|
||||
finish();
|
||||
}, true);
|
||||
// clean up
|
||||
newWin2.close();
|
||||
finish();
|
||||
}, true);
|
||||
});
|
||||
});
|
||||
}, TEST_URL);
|
||||
}
|
||||
|
@ -40,7 +40,10 @@ function test() {
|
||||
|
||||
provideWindow(function onTestURLLoaded(win) {
|
||||
win.close();
|
||||
openWindowRec(windowsToOpen, expectedResults, recCallback);
|
||||
// Give it time to close
|
||||
executeSoon(function() {
|
||||
openWindowRec(windowsToOpen, expectedResults, recCallback);
|
||||
});
|
||||
}, url, settings);
|
||||
}
|
||||
|
||||
|
@ -68,9 +68,12 @@ function runNextTest() {
|
||||
}
|
||||
}
|
||||
|
||||
let currentTest = tests.shift();
|
||||
info("prepping for " + currentTest.name);
|
||||
waitForBrowserState(testState, currentTest);
|
||||
// If we closed a window, give it time to close
|
||||
executeSoon(function() {
|
||||
let currentTest = tests.shift();
|
||||
info("prepping for " + currentTest.name);
|
||||
waitForBrowserState(testState, currentTest);
|
||||
});
|
||||
}
|
||||
else {
|
||||
ss.setBrowserState(stateBackup);
|
||||
@ -319,15 +322,18 @@ function test_undoCloseWindow() {
|
||||
waitForBrowserState(lameMultiWindowState, function() {
|
||||
// Close the window which isn't window
|
||||
newWindow.close();
|
||||
reopenedWindow = ss.undoCloseWindow(0);
|
||||
reopenedWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
|
||||
reopenedWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
|
||||
// Now give it time to close
|
||||
executeSoon(function() {
|
||||
reopenedWindow = ss.undoCloseWindow(0);
|
||||
reopenedWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
|
||||
reopenedWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false);
|
||||
|
||||
reopenedWindow.addEventListener("load", function() {
|
||||
reopenedWindow.removeEventListener("load", arguments.callee, false);
|
||||
reopenedWindow.addEventListener("load", function() {
|
||||
reopenedWindow.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
reopenedWindow.gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
|
||||
}, false);
|
||||
reopenedWindow.gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false);
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
let busyEventCount = 0,
|
||||
@ -355,6 +361,7 @@ function test_undoCloseWindow() {
|
||||
|
||||
reopenedWindow.close();
|
||||
|
||||
runNextTest();
|
||||
// Give it time to close
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
}
|
||||
|
@ -343,15 +343,18 @@ function newWindowWithState(state, callback) {
|
||||
whenDelayedStartupFinished(win, function () {
|
||||
ss.setWindowState(win, JSON.stringify(state), true);
|
||||
win.close();
|
||||
win = ss.undoCloseWindow(0);
|
||||
// Give it time to close
|
||||
executeSoon(function() {
|
||||
win = ss.undoCloseWindow(0);
|
||||
|
||||
whenWindowLoaded(win, function () {
|
||||
whenWindowStateReady(win, function () {
|
||||
afterAllTabsLoaded(check, win);
|
||||
whenWindowLoaded(win, function () {
|
||||
whenWindowStateReady(win, function () {
|
||||
afterAllTabsLoaded(check, win);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
whenDelayedStartupFinished(win, check);
|
||||
whenDelayedStartupFinished(win, check);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -327,11 +327,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
||||
let name = representAddon(addon);
|
||||
let message = "";
|
||||
|
||||
if (addon.userDisabled) {
|
||||
message = gcli.lookupFormat("addonAlreadyDisabled", [name]);
|
||||
} else {
|
||||
// If the addon is not disabled or is set to "click to play" then
|
||||
// disable it. Otherwise display the message "Add-on is already
|
||||
// disabled."
|
||||
if (!addon.userDisabled ||
|
||||
addon.userDisabled === AddonManager.STATE_ASK_TO_ACTIVATE) {
|
||||
addon.userDisabled = true;
|
||||
message = gcli.lookupFormat("addonDisabled", [name]);
|
||||
} else {
|
||||
message = gcli.lookupFormat("addonAlreadyDisabled", [name]);
|
||||
}
|
||||
this.resolve(message);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ function test() {
|
||||
|
||||
function testWhenBreakpointEnabledAndSecondSourceShown() {
|
||||
return Task.spawn(function() {
|
||||
yield ensureSourceIs(aPanel, "-02.js");
|
||||
yield ensureSourceIs(aPanel, "-02.js", true);
|
||||
yield verifyView({ disabled: false, visible: false });
|
||||
|
||||
executeSoon(() => aDebuggee.firstCall());
|
||||
@ -95,7 +95,7 @@ function test() {
|
||||
|
||||
function testWhenBreakpointDisabledAndSecondSourceShown() {
|
||||
return Task.spawn(function() {
|
||||
yield ensureSourceIs(aPanel, "-02.js");
|
||||
yield ensureSourceIs(aPanel, "-02.js", true);
|
||||
yield verifyView({ disabled: true, visible: false });
|
||||
|
||||
executeSoon(() => aDebuggee.firstCall());
|
||||
|
@ -139,6 +139,14 @@ function testRemoveTab() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
gNewWindow.close();
|
||||
|
||||
// give it time to close
|
||||
executeSoon(function() { continue_remove_tab(deferred) });
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function continue_remove_tab(deferred)
|
||||
{
|
||||
removeTab(gNewTab);
|
||||
|
||||
gClient.listTabs(aResponse => {
|
||||
@ -153,8 +161,6 @@ function testRemoveTab() {
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function closeConnection() {
|
||||
|
@ -67,10 +67,13 @@ function onFocus() {
|
||||
window.removeEventListener("focus", onFocus, true);
|
||||
|
||||
// Check if toolbox window got focus.
|
||||
toolbox._host._window.onfocus = () => {
|
||||
let onToolboxFocusAgain = () => {
|
||||
toolbox._host._window.removeEventListener("focus", onToolboxFocusAgain, false);
|
||||
ok(true, "Toolbox window is the focused window after calling toolbox.raise()");
|
||||
cleanup();
|
||||
};
|
||||
toolbox._host._window.addEventListener("focus", onToolboxFocusAgain, false);
|
||||
|
||||
// Now raise toolbox.
|
||||
toolbox.raise();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -341,14 +341,13 @@ function waitForEvent(aSubject, aEventName, aTimeoutMs, aTarget) {
|
||||
eventDeferred.resolve(aEvent);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
function cleanup(aEventOrError) {
|
||||
// unhook listener in case of success or failure
|
||||
aSubject.removeEventListener(aEventName, listener);
|
||||
return aEventOrError;
|
||||
}
|
||||
eventDeferred.promise.then(cleanup, cleanup);
|
||||
|
||||
aSubject.addEventListener(aEventName, listener, false);
|
||||
return eventDeferred.promise;
|
||||
return eventDeferred.promise.then(cleanup, cleanup);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,7 +424,7 @@ function waitForCondition(aCondition, aTimeoutMs, aIntervalMs) {
|
||||
}
|
||||
|
||||
/**
|
||||
* same as waitForCondition but with better test output.
|
||||
* same as waitForCondition but with better test output.
|
||||
*
|
||||
* @param aCondition the callback that must return a truthy value
|
||||
* @param aTestMsg test condition message printed when the test succeeds or
|
||||
|
@ -382,11 +382,6 @@ private:
|
||||
// Returns null if a principal cannot be found; generally callers
|
||||
// should error out at that point.
|
||||
static nsIPrincipal* doGetObjectPrincipal(JS::Handle<JSObject*> obj);
|
||||
#ifdef DEBUG
|
||||
static nsIPrincipal*
|
||||
old_doGetObjectPrincipal(JS::Handle<JSObject*> obj,
|
||||
bool aAllowShortCircuit = true);
|
||||
#endif
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no JS running.
|
||||
@ -409,7 +404,8 @@ private:
|
||||
|
||||
nsresult
|
||||
LookupPolicy(nsIPrincipal* principal,
|
||||
ClassInfoData& aClassData, jsid aProperty,
|
||||
ClassInfoData& aClassData,
|
||||
JS::Handle<jsid> aProperty,
|
||||
uint32_t aAction,
|
||||
ClassPolicy** aCachedClassPolicy,
|
||||
SecurityLevel* result);
|
||||
|
@ -79,14 +79,14 @@ bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
|
||||
|
||||
// Lazily initialized. Use the getter below.
|
||||
static jsid sEnabledID = JSID_VOID;
|
||||
static jsid
|
||||
static JS::HandleId
|
||||
EnabledID()
|
||||
{
|
||||
if (sEnabledID != JSID_VOID)
|
||||
return sEnabledID;
|
||||
return JS::HandleId::fromMarkedLocation(&sEnabledID);
|
||||
AutoSafeJSContext cx;
|
||||
sEnabledID = INTERNED_STRING_TO_JSID(cx, JS_InternString(cx, "enabled"));
|
||||
return sEnabledID;
|
||||
return JS::HandleId::fromMarkedLocation(&sEnabledID);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -984,7 +984,7 @@ nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
|
||||
nsresult
|
||||
nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
|
||||
ClassInfoData& aClassData,
|
||||
jsid aProperty,
|
||||
JS::Handle<jsid> aProperty,
|
||||
uint32_t aAction,
|
||||
ClassPolicy** aCachedClassPolicy,
|
||||
SecurityLevel* result)
|
||||
@ -1957,118 +1957,9 @@ nsScriptSecurityManager::doGetObjectPrincipal(JS::Handle<JSObject*> aObj)
|
||||
{
|
||||
JSCompartment *compartment = js::GetObjectCompartment(aObj);
|
||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
||||
nsIPrincipal *principal = nsJSPrincipals::get(principals);
|
||||
|
||||
// We leave the old code in for a little while to make sure that pulling
|
||||
// object principals directly off the compartment always gives an equivalent
|
||||
// result (from a security perspective).
|
||||
#ifdef DEBUG
|
||||
nsIPrincipal *old = old_doGetObjectPrincipal(aObj);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(CheckSameOriginPrincipal(principal, old)));
|
||||
#endif
|
||||
|
||||
return principal;
|
||||
return nsJSPrincipals::get(principals);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::old_doGetObjectPrincipal(JS::Handle<JSObject*> aObj,
|
||||
bool aAllowShortCircuit)
|
||||
{
|
||||
NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
|
||||
nsIPrincipal* result = nullptr;
|
||||
|
||||
JSContext* cx = nsXPConnect::XPConnect()->GetCurrentJSContext();
|
||||
JS::RootedObject obj(cx, aObj);
|
||||
JS::RootedObject origObj(cx, obj);
|
||||
|
||||
// A common case seen in this code is that we enter this function
|
||||
// with obj being a Function object, whose parent is a Call
|
||||
// object. Neither of those have object principals, so we can skip
|
||||
// those objects here before we enter the below loop. That way we
|
||||
// avoid wasting time checking properties of their classes etc in
|
||||
// the loop.
|
||||
|
||||
if (js::IsFunctionObject(obj)) {
|
||||
obj = js::GetObjectParent(obj);
|
||||
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (js::IsCallObject(obj)) {
|
||||
obj = js::GetObjectParentMaybeScope(obj);
|
||||
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const js::Class *jsClass = js::GetObjectClass(obj);
|
||||
|
||||
do {
|
||||
// Note: jsClass is set before this loop, and also at the
|
||||
// *end* of this loop.
|
||||
|
||||
if (IS_WN_CLASS(jsClass)) {
|
||||
result = nsXPConnect::XPConnect()->GetPrincipal(obj,
|
||||
aAllowShortCircuit);
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
nsISupports *priv;
|
||||
if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
|
||||
priv = (nsISupports *) js::GetObjectPrivate(obj);
|
||||
} else {
|
||||
priv = UnwrapDOMObjectToISupports(obj);
|
||||
}
|
||||
|
||||
if (aAllowShortCircuit) {
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
|
||||
do_QueryInterface(priv);
|
||||
|
||||
NS_ASSERTION(!xpcWrapper ||
|
||||
!strcmp(jsClass->name, "XPCNativeWrapper"),
|
||||
"Uh, an nsIXPConnectWrappedNative with the "
|
||||
"wrong JSClass or getObjectOps hooks!");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
|
||||
do_QueryInterface(priv);
|
||||
|
||||
if (objPrin) {
|
||||
result = objPrin->GetPrincipal();
|
||||
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obj = js::GetObjectParentMaybeScope(obj);
|
||||
|
||||
if (!obj)
|
||||
break;
|
||||
|
||||
jsClass = js::GetObjectClass(obj);
|
||||
} while (1);
|
||||
|
||||
if (aAllowShortCircuit) {
|
||||
nsIPrincipal *principal = old_doGetObjectPrincipal(origObj, false);
|
||||
|
||||
// Because of inner window reuse, we can have objects with one principal
|
||||
// living in a scope with a different (but same-origin) principal. So
|
||||
// just check same-origin here.
|
||||
NS_ASSERTION(NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)),
|
||||
"Principal mismatch. Not good");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Methods implementing nsIXPCSecurityManager //
|
||||
////////////////////////////////////////////////
|
||||
|
@ -11,8 +11,7 @@ import os
|
||||
|
||||
def get_build_entries(root_path):
|
||||
""" Iterates through the root_path, creating a list for each file and
|
||||
directory. Excludes any path starting with extensions or distribution
|
||||
and paths ending with channel-prefs.js.
|
||||
directory. Excludes any file paths ending with channel-prefs.js.
|
||||
"""
|
||||
rel_file_path_set = set()
|
||||
rel_dir_path_set = set()
|
||||
@ -21,18 +20,14 @@ def get_build_entries(root_path):
|
||||
parent_dir_rel_path = root[len(root_path)+1:]
|
||||
rel_path_file = os.path.join(parent_dir_rel_path, file_name)
|
||||
rel_path_file = rel_path_file.replace("\\", "/")
|
||||
if not (rel_path_file.startswith("distribution/") or
|
||||
rel_path_file.startswith("extensions/") or
|
||||
rel_path_file.endswith("channel-prefs.js")):
|
||||
if not (rel_path_file.endswith("channel-prefs.js")):
|
||||
rel_file_path_set.add(rel_path_file)
|
||||
|
||||
for dir_name in dirs:
|
||||
parent_dir_rel_path = root[len(root_path)+1:]
|
||||
rel_path_dir = os.path.join(parent_dir_rel_path, dir_name)
|
||||
rel_path_dir = rel_path_dir.replace("\\", "/")+"/"
|
||||
if not (rel_path_dir.startswith("distribution/") or
|
||||
rel_path_dir.startswith("extensions/")):
|
||||
rel_dir_path_set.add(rel_path_dir)
|
||||
rel_dir_path_set.add(rel_path_dir)
|
||||
|
||||
rel_file_path_list = list(rel_file_path_set)
|
||||
rel_file_path_list.sort(reverse=True)
|
||||
|
75
configure.in
75
configure.in
@ -2592,77 +2592,6 @@ fi
|
||||
|
||||
MOZ_CXX11
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
dnl Check for usable char16_t (2 bytes, unsigned)
|
||||
dnl (we might not need the unsignedness check anymore)
|
||||
AC_CACHE_CHECK(for usable char16_t (2 bytes, unsigned),
|
||||
ac_cv_have_usable_char16_t,
|
||||
[AC_TRY_COMPILE([$configure_static_assert_macros],
|
||||
[CONFIGURE_STATIC_ASSERT(sizeof(char16_t) == 2);
|
||||
CONFIGURE_STATIC_ASSERT(char16_t(-1) > char16_t(0));
|
||||
CONFIGURE_STATIC_ASSERT(sizeof((u"hello")[0]) == 2);
|
||||
CONFIGURE_STATIC_ASSERT(sizeof(u'a') == 2);
|
||||
CONFIGURE_STATIC_ASSERT(u'\xFFFF' > u'\x0')],
|
||||
ac_cv_have_usable_char16_t="yes",
|
||||
ac_cv_have_usable_char16_t="no")])
|
||||
if test "$ac_cv_have_usable_char16_t" = "yes"; then
|
||||
AC_DEFINE(HAVE_CPP_CHAR16_T)
|
||||
HAVE_CPP_CHAR16_T=1
|
||||
elif test "$GNU_CXX"; then
|
||||
CXXFLAGS="$_SAVE_CXXFLAGS"
|
||||
fi
|
||||
|
||||
dnl Check for usable wchar_t (2 bytes, unsigned)
|
||||
dnl (we really don't need the unsignedness check anymore)
|
||||
dnl ========================================================
|
||||
|
||||
AC_CACHE_CHECK(for usable wchar_t (2 bytes, unsigned),
|
||||
ac_cv_have_usable_wchar_v2,
|
||||
[AC_TRY_COMPILE([#include <stddef.h>
|
||||
$configure_static_assert_macros],
|
||||
[CONFIGURE_STATIC_ASSERT(sizeof(wchar_t) == 2);
|
||||
CONFIGURE_STATIC_ASSERT((wchar_t)-1 > (wchar_t) 0)],
|
||||
ac_cv_have_usable_wchar_v2="yes",
|
||||
ac_cv_have_usable_wchar_v2="no")])
|
||||
if test "$ac_cv_have_usable_wchar_v2" = "yes"; then
|
||||
AC_DEFINE(HAVE_CPP_2BYTE_WCHAR_T)
|
||||
HAVE_CPP_2BYTE_WCHAR_T=1
|
||||
elif test "$ac_cv_have_usable_char16_t" != "yes"; then
|
||||
dnl This is really gcc-only
|
||||
dnl Do this test using CXX only since some versions of gcc
|
||||
dnl 2.95-2.97 have a signed wchar_t in c++ only and some versions
|
||||
dnl only have short-wchar support for c++.
|
||||
dnl Note that we assume that mac & win32 have short wchar (see nscore.h)
|
||||
|
||||
_SAVE_CXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS -fshort-wchar"
|
||||
|
||||
AC_CACHE_CHECK(for compiler -fshort-wchar option,
|
||||
ac_cv_have_usable_wchar_option_v2,
|
||||
[AC_TRY_LINK([#include <stddef.h>
|
||||
$configure_static_assert_macros],
|
||||
[CONFIGURE_STATIC_ASSERT(sizeof(wchar_t) == 2);
|
||||
CONFIGURE_STATIC_ASSERT((wchar_t)-1 > (wchar_t) 0)],
|
||||
ac_cv_have_usable_wchar_option_v2="yes",
|
||||
ac_cv_have_usable_wchar_option_v2="no")])
|
||||
|
||||
if test "$ac_cv_have_usable_wchar_option_v2" = "yes"; then
|
||||
AC_DEFINE(HAVE_CPP_2BYTE_WCHAR_T)
|
||||
HAVE_CPP_2BYTE_WCHAR_T=1
|
||||
if test "$OS_TARGET" = Android; then
|
||||
WCHAR_CFLAGS="-fshort-wchar -Wl,--no-wchar-size-warning"
|
||||
CXXFLAGS="$CXXFLAGS -Wl,--no-wchar-size-warning"
|
||||
CFLAGS="$CFLAGS -Wl,--no-wchar-size-warning"
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,--no-wchar-size-warning"
|
||||
else
|
||||
WCHAR_CFLAGS="-fshort-wchar"
|
||||
fi
|
||||
else
|
||||
CXXFLAGS=$_SAVE_CXXFLAGS
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_LANG_C
|
||||
|
||||
dnl Check for .hidden assembler directive and visibility attribute.
|
||||
@ -3155,7 +3084,7 @@ dnl Checks for library functions.
|
||||
dnl ========================================================
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_MEMCMP
|
||||
AC_CHECK_FUNCS(random strerror lchown fchmod snprintf memmove rint stat64 lstat64 truncate64 setbuf isatty)
|
||||
AC_CHECK_FUNCS(random strerror lchown fchmod snprintf memmove stat64 lstat64 truncate64 setbuf isatty)
|
||||
AC_CHECK_FUNCS(statvfs64 statvfs statfs64 statfs)
|
||||
AC_CHECK_FUNCS(flockfile getpagesize)
|
||||
AC_CHECK_FUNCS(localtime_r strtok_r)
|
||||
@ -8895,9 +8824,7 @@ dnl ========================================================
|
||||
dnl The following defines are used by xpcom
|
||||
_NON_GLOBAL_ACDEFINES="$_NON_GLOBAL_ACDEFINES
|
||||
CPP_THROW_NEW
|
||||
HAVE_CPP_2BYTE_WCHAR_T
|
||||
HAVE_CPP_AMBIGUITY_RESOLVING_USING
|
||||
HAVE_CPP_CHAR16_T
|
||||
HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
|
||||
HAVE_CPP_PARTIAL_SPECIALIZATION
|
||||
HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
|
||||
|
@ -6886,7 +6886,8 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
|
||||
}
|
||||
// Now convert the scale into device pixels per CSS pixel.
|
||||
nsIWidget *widget = nsContentUtils::WidgetForDocument(this);
|
||||
CSSToLayoutDeviceScale pixelRatio(widget ? widget->GetDefaultScale() : 1.0f);
|
||||
CSSToLayoutDeviceScale pixelRatio = widget ? widget->GetDefaultScale()
|
||||
: CSSToLayoutDeviceScale(1.0f);
|
||||
CSSToScreenScale scaleFloat = mScaleFloat * pixelRatio;
|
||||
CSSToScreenScale scaleMinFloat = mScaleMinFloat * pixelRatio;
|
||||
CSSToScreenScale scaleMaxFloat = mScaleMaxFloat * pixelRatio;
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
|
||||
// Called by the decode thread to keep track of the number of bytes read
|
||||
// from the resource.
|
||||
virtual void NotifyBytesConsumed(int64_t aBytes) = 0;
|
||||
virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) = 0;
|
||||
|
||||
// Increments the parsed and decoded frame counters by the passed in counts.
|
||||
// Can be called on any thread.
|
||||
|
@ -77,7 +77,7 @@ BufferDecoder::GetResource() const
|
||||
}
|
||||
|
||||
void
|
||||
BufferDecoder::NotifyBytesConsumed(int64_t aBytes)
|
||||
BufferDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
|
||||
MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
void NotifyBytesConsumed(int64_t aBytes) MOZ_FINAL MOZ_OVERRIDE;
|
||||
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
|
@ -1046,15 +1046,17 @@ void MediaDecoder::NotifyPrincipalChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::NotifyBytesConsumed(int64_t aBytes)
|
||||
void MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
NS_ENSURE_TRUE_VOID(mDecoderStateMachine);
|
||||
MOZ_ASSERT(OnStateMachineThread() || OnDecodeThread());
|
||||
if (!mIgnoreProgressData) {
|
||||
mDecoderPosition += aBytes;
|
||||
if (mIgnoreProgressData) {
|
||||
return;
|
||||
}
|
||||
if (aOffset >= mDecoderPosition) {
|
||||
mPlaybackStatistics.AddBytes(aBytes);
|
||||
}
|
||||
mDecoderPosition = aOffset + aBytes;
|
||||
}
|
||||
|
||||
void MediaDecoder::UpdateReadyStateForData()
|
||||
|
@ -478,9 +478,10 @@ public:
|
||||
// changed. Called on main thread only.
|
||||
virtual void NotifyPrincipalChanged();
|
||||
|
||||
// Called by the decode thread to keep track of the number of bytes read
|
||||
// from the resource.
|
||||
void NotifyBytesConsumed(int64_t aBytes) MOZ_FINAL MOZ_OVERRIDE;
|
||||
// Called by the MediaResource to keep track of the number of bytes read
|
||||
// from the resource. Called on the main by an event runner dispatched
|
||||
// by the MediaResource read functions.
|
||||
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
|
@ -803,7 +803,12 @@ nsresult ChannelMediaResource::Read(char* aBuffer,
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
return mCacheStream.Read(aBuffer, aCount, aBytes);
|
||||
int64_t offset = mCacheStream.Tell();
|
||||
nsresult rv = mCacheStream.Read(aBuffer, aCount, aBytes);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchBytesConsumed(*aBytes, offset);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult ChannelMediaResource::ReadAt(int64_t aOffset,
|
||||
@ -813,7 +818,11 @@ nsresult ChannelMediaResource::ReadAt(int64_t aOffset,
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
return mCacheStream.ReadAt(aOffset, aBuffer, aCount, aBytes);
|
||||
nsresult rv = mCacheStream.ReadAt(aOffset, aBuffer, aCount, aBytes);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchBytesConsumed(*aBytes, aOffset);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult ChannelMediaResource::Seek(int32_t aWhence, int64_t aOffset)
|
||||
@ -1597,8 +1606,17 @@ nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32
|
||||
|
||||
nsresult FileMediaResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
return UnsafeRead(aBuffer, aCount, aBytes);
|
||||
nsresult rv;
|
||||
int64_t offset = 0;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mSeekable->Tell(&offset);
|
||||
rv = UnsafeRead(aBuffer, aCount, aBytes);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchBytesConsumed(*aBytes, offset);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::UnsafeRead(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
@ -1612,10 +1630,17 @@ nsresult FileMediaResource::ReadAt(int64_t aOffset, char* aBuffer,
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
nsresult rv = UnsafeSeek(nsISeekableStream::NS_SEEK_SET, aOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return UnsafeRead(aBuffer, aCount, aBytes);
|
||||
nsresult rv;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
rv = UnsafeSeek(nsISeekableStream::NS_SEEK_SET, aOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = UnsafeRead(aBuffer, aCount, aBytes);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchBytesConsumed(*aBytes, aOffset);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::Seek(int32_t aWhence, int64_t aOffset)
|
||||
@ -1733,5 +1758,41 @@ void BaseMediaResource::ModifyLoadFlags(nsLoadFlags aFlags)
|
||||
}
|
||||
}
|
||||
|
||||
class DispatchBytesConsumedEvent : public nsRunnable {
|
||||
public:
|
||||
DispatchBytesConsumedEvent(MediaDecoder* aDecoder,
|
||||
int64_t aNumBytes,
|
||||
int64_t aOffset)
|
||||
: mDecoder(aDecoder),
|
||||
mNumBytes(aNumBytes),
|
||||
mOffset(aOffset)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DispatchBytesConsumedEvent);
|
||||
}
|
||||
|
||||
~DispatchBytesConsumedEvent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(DispatchBytesConsumedEvent);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mDecoder->NotifyBytesConsumed(mNumBytes, mOffset);
|
||||
// Drop ref to decoder on main thread, just in case this reference
|
||||
// ends up being the last owning reference somehow.
|
||||
mDecoder = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoder> mDecoder;
|
||||
int64_t mNumBytes;
|
||||
int64_t mOffset;
|
||||
};
|
||||
|
||||
void BaseMediaResource::DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset)
|
||||
{
|
||||
RefPtr<nsIRunnable> event(new DispatchBytesConsumedEvent(mDecoder, aNumBytes, aOffset));
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -429,6 +429,10 @@ protected:
|
||||
// then the request is added back to the load group.
|
||||
void ModifyLoadFlags(nsLoadFlags aFlags);
|
||||
|
||||
// Dispatches an event to call MediaDecoder::NotifyBytesConsumed(aNumBytes, aOffset)
|
||||
// on the main thread. This is called automatically after every read.
|
||||
void DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset);
|
||||
|
||||
// This is not an nsCOMPointer to prevent a circular reference
|
||||
// between the decoder to the media stream object. The stream never
|
||||
// outlives the lifetime of the decoder.
|
||||
|
@ -87,9 +87,8 @@ static void _AudioSampleCallback(void *aThis,
|
||||
* Otherwise, put as much data as is left into |aData|, set |aNumBytes| to the
|
||||
* amount of data we have left, and return false.
|
||||
*
|
||||
* This function also calls NotifyBytesConsumed() on the media resource and
|
||||
* passes the read data on to the MP3 frame parser for stream duration
|
||||
* estimation.
|
||||
* This function also passes the read data on to the MP3 frame parser for
|
||||
* stream duration estimation.
|
||||
*/
|
||||
nsresult
|
||||
AppleMP3Reader::ReadAndNotify(uint32_t *aNumBytes, char *aData)
|
||||
@ -112,8 +111,6 @@ AppleMP3Reader::ReadAndNotify(uint32_t *aNumBytes, char *aData)
|
||||
}
|
||||
} while(totalBytes < *aNumBytes && numBytes);
|
||||
|
||||
mDecoder->NotifyBytesConsumed(totalBytes);
|
||||
|
||||
// Pass the buffer to the MP3 frame parser to improve our duration estimate.
|
||||
if (mMP3FrameParser.IsMP3()) {
|
||||
mMP3FrameParser.Parse(aData, totalBytes, offset);
|
||||
|
@ -277,12 +277,6 @@ DirectShowReader::DecodeAudioData()
|
||||
numFrames,
|
||||
buffer.forget(),
|
||||
mNumChannels));
|
||||
|
||||
uint32_t bytesConsumed = mSourceFilter->GetAndResetBytesConsumedCount();
|
||||
if (bytesConsumed > 0) {
|
||||
mDecoder->NotifyBytesConsumed(bytesConsumed);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,6 @@ GStreamerReader::GStreamerReader(AbstractMediaDecoder* aDecoder)
|
||||
mAudioSinkBufferCount(0),
|
||||
mGstThreadsMonitor("media.gst.threads"),
|
||||
mReachedEos(false),
|
||||
mByteOffset(0),
|
||||
mLastReportedByteOffset(0),
|
||||
fpsNum(0),
|
||||
fpsDen(0)
|
||||
{
|
||||
@ -439,20 +437,10 @@ nsresult GStreamerReader::ResetDecode()
|
||||
mVideoSinkBufferCount = 0;
|
||||
mAudioSinkBufferCount = 0;
|
||||
mReachedEos = false;
|
||||
mLastReportedByteOffset = 0;
|
||||
mByteOffset = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void GStreamerReader::NotifyBytesConsumed()
|
||||
{
|
||||
NS_ASSERTION(mByteOffset >= mLastReportedByteOffset,
|
||||
"current byte offset less than prev offset");
|
||||
mDecoder->NotifyBytesConsumed(mByteOffset - mLastReportedByteOffset);
|
||||
mLastReportedByteOffset = mByteOffset;
|
||||
}
|
||||
|
||||
bool GStreamerReader::DecodeAudioData()
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
@ -488,7 +476,6 @@ bool GStreamerReader::DecodeAudioData()
|
||||
}
|
||||
}
|
||||
|
||||
NotifyBytesConsumed();
|
||||
buffer = gst_app_sink_pull_buffer(mAudioAppSink);
|
||||
mAudioSinkBufferCount--;
|
||||
}
|
||||
@ -552,7 +539,6 @@ bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
|
||||
}
|
||||
}
|
||||
|
||||
NotifyBytesConsumed();
|
||||
mDecoder->NotifyDecodedFrames(0, 1);
|
||||
|
||||
buffer = gst_app_sink_pull_buffer(mVideoAppSink);
|
||||
@ -679,12 +665,6 @@ nsresult GStreamerReader::GetBuffered(TimeRanges* aBuffered,
|
||||
nsTArray<MediaByteRange> ranges;
|
||||
resource->GetCachedRanges(ranges);
|
||||
|
||||
if (mDecoder->OnStateMachineThread())
|
||||
/* Report the position from here while buffering as we can't report it from
|
||||
* the gstreamer threads that are actually reading from the resource
|
||||
*/
|
||||
NotifyBytesConsumed();
|
||||
|
||||
if (resource->IsDataCachedToEndOfResource(0)) {
|
||||
/* fast path for local or completely cached files */
|
||||
gint64 duration = 0;
|
||||
@ -738,7 +718,6 @@ void GStreamerReader::ReadAndPushData(guint aLength)
|
||||
}
|
||||
|
||||
GST_BUFFER_SIZE(buffer) = bytesRead;
|
||||
mByteOffset += bytesRead;
|
||||
|
||||
GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer));
|
||||
if (ret != GST_FLOW_OK) {
|
||||
@ -831,9 +810,7 @@ gboolean GStreamerReader::SeekData(GstAppSrc* aSrc, guint64 aOffset)
|
||||
rv = resource->Seek(SEEK_SET, aOffset);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mByteOffset = mLastReportedByteOffset = aOffset;
|
||||
} else {
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_ERROR, ("seek at %lu failed", aOffset));
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,6 @@ public:
|
||||
private:
|
||||
|
||||
void ReadAndPushData(guint aLength);
|
||||
void NotifyBytesConsumed();
|
||||
int64_t QueryDuration();
|
||||
|
||||
/* Called once the pipeline is setup to check that the stream only contains
|
||||
@ -160,10 +159,6 @@ private:
|
||||
* DecodeAudioData and DecodeVideoFrame should not expect any more data
|
||||
*/
|
||||
bool mReachedEos;
|
||||
/* offset we've reached reading from the source */
|
||||
gint64 mByteOffset;
|
||||
/* the last offset we reported with NotifyBytesConsumed */
|
||||
gint64 mLastReportedByteOffset;
|
||||
int fpsNum;
|
||||
int fpsDen;
|
||||
};
|
||||
|
@ -892,7 +892,6 @@ bool OggReader::ReadOggPage(ogg_page* aPage)
|
||||
return false;
|
||||
}
|
||||
|
||||
mDecoder->NotifyBytesConsumed(bytesRead);
|
||||
// Update the synchronisation layer with the number
|
||||
// of bytes written to the buffer
|
||||
ret = ogg_sync_wrote(&mOggState, bytesRead);
|
||||
|
17
content/media/test/crashtests/910171-1.html
Normal file
17
content/media/test/crashtests/910171-1.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
var context = new window.OfflineAudioContext(1, 4096, 48000);
|
||||
context.oncomplete = function(e) {
|
||||
document.documentElement.removeAttribute("class");
|
||||
};
|
||||
var delay = context.createDelay();
|
||||
delay.connect(context.destination);
|
||||
delay.delayTime.value = 1.0;
|
||||
var buffer = context.createBuffer(1, 2048, context.sampleRate);
|
||||
var source = context.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
source.connect(delay);
|
||||
source.start();
|
||||
context.startRendering();
|
||||
</script>
|
@ -55,3 +55,4 @@ load 907986-1.html
|
||||
load 907986-2.html
|
||||
load 907986-3.html
|
||||
load 907986-4.html
|
||||
load 910171-1.html
|
||||
|
@ -309,7 +309,6 @@ WaveReader::ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead)
|
||||
if (read == 0) {
|
||||
return false;
|
||||
}
|
||||
mDecoder->NotifyBytesConsumed(read);
|
||||
got += read;
|
||||
if (aBytesRead) {
|
||||
*aBytesRead = got;
|
||||
|
@ -59,6 +59,8 @@ AudioContext::AudioContext(nsPIDOMWindow* aWindow,
|
||||
aLength, aSampleRate))
|
||||
, mNumberOfChannels(aNumberOfChannels)
|
||||
, mIsOffline(aIsOffline)
|
||||
, mIsStarted(!aIsOffline)
|
||||
, mIsShutDown(false)
|
||||
{
|
||||
// Actually play audio
|
||||
mDestination->Stream()->AddAudioOutput(&gWebAudioOutputKey);
|
||||
@ -439,6 +441,20 @@ AudioContext::RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob)
|
||||
mDecodeJobs.RemoveElement(aDecodeJob);
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::RegisterActiveNode(AudioNode* aNode)
|
||||
{
|
||||
if (!mIsShutDown) {
|
||||
mActiveNodes.PutEntry(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::UnregisterActiveNode(AudioNode* aNode)
|
||||
{
|
||||
mActiveNodes.RemoveEntry(aNode);
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode)
|
||||
{
|
||||
@ -523,8 +539,15 @@ GetHashtableElements(nsTHashtable<nsPtrHashKey<T> >& aHashtable, nsTArray<T*>& a
|
||||
void
|
||||
AudioContext::Shutdown()
|
||||
{
|
||||
mIsShutDown = true;
|
||||
|
||||
Suspend();
|
||||
|
||||
// Release references to active nodes.
|
||||
// Active AudioNodes don't unregister in destructors, at which point the
|
||||
// Node is already unregistered.
|
||||
mActiveNodes.Clear();
|
||||
|
||||
// Stop all audio buffer source nodes, to make sure that they release
|
||||
// their self-references.
|
||||
// We first gather an array of the nodes and then call Stop on each one,
|
||||
@ -595,10 +618,15 @@ AudioContext::GetJSContext() const
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::StartRendering()
|
||||
AudioContext::StartRendering(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext");
|
||||
if (mIsStarted) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
mIsStarted = true;
|
||||
mDestination->StartRendering();
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ class AudioBuffer;
|
||||
class AudioBufferSourceNode;
|
||||
class AudioDestinationNode;
|
||||
class AudioListener;
|
||||
class AudioNode;
|
||||
class BiquadFilterNode;
|
||||
class ChannelMergerNode;
|
||||
class ChannelSplitterNode;
|
||||
@ -205,13 +206,27 @@ public:
|
||||
const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback);
|
||||
|
||||
// OfflineAudioContext methods
|
||||
void StartRendering();
|
||||
void StartRendering(ErrorResult& aRv);
|
||||
IMPL_EVENT_HANDLER(complete)
|
||||
|
||||
bool IsOffline() const { return mIsOffline; }
|
||||
|
||||
MediaStreamGraph* Graph() const;
|
||||
MediaStream* DestinationStream() const;
|
||||
|
||||
// Nodes register here if they will produce sound even if they have silent
|
||||
// or no input connections. The AudioContext will keep registered nodes
|
||||
// alive until the context is collected. This takes care of "playing"
|
||||
// references and "tail-time" references.
|
||||
void RegisterActiveNode(AudioNode* aNode);
|
||||
// Nodes unregister when they have finished producing sound for the
|
||||
// foreseeable future.
|
||||
// Do NOT call UnregisterActiveNode from an AudioNode destructor.
|
||||
// If the destructor is called, then the Node has already been unregistered.
|
||||
// The destructor may be called during hashtable enumeration, during which
|
||||
// unregistering would not be safe.
|
||||
void UnregisterActiveNode(AudioNode* aNode);
|
||||
|
||||
void UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode);
|
||||
void UnregisterPannerNode(PannerNode* aNode);
|
||||
void UnregisterOscillatorNode(OscillatorNode* aNode);
|
||||
@ -239,6 +254,9 @@ private:
|
||||
nsRefPtr<AudioListener> mListener;
|
||||
MediaBufferDecoder mDecoder;
|
||||
nsTArray<nsRefPtr<WebAudioDecodeJob> > mDecodeJobs;
|
||||
// See RegisterActiveNode. These will keep the AudioContext alive while it
|
||||
// is rendering and the window remains alive.
|
||||
nsTHashtable<nsRefPtrHashKey<AudioNode> > mActiveNodes;
|
||||
// Two hashsets containing all the PannerNodes and AudioBufferSourceNodes,
|
||||
// to compute the doppler shift, and also to stop AudioBufferSourceNodes.
|
||||
// These are all weak pointers.
|
||||
@ -251,6 +269,8 @@ private:
|
||||
// Number of channels passed in the OfflineAudioContext ctor.
|
||||
uint32_t mNumberOfChannels;
|
||||
bool mIsOffline;
|
||||
bool mIsStarted;
|
||||
bool mIsShutDown;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -102,9 +102,9 @@ private:
|
||||
* real-time processing and output of this AudioNode.
|
||||
*
|
||||
* We track the incoming and outgoing connections to other AudioNodes.
|
||||
* Outgoing connections have strong ownership. Also, AudioNodes add self
|
||||
* references if they produce sound on their output even when they have silent
|
||||
* or no input.
|
||||
* Outgoing connections have strong ownership. Also, AudioNodes that will
|
||||
* produce sound on their output even when they have silent or no input ask
|
||||
* the AudioContext to keep them alive until the context is finished.
|
||||
*/
|
||||
class AudioNode : public nsDOMEventTargetHelper,
|
||||
public EnableWebAudioCheck
|
||||
@ -213,6 +213,17 @@ public:
|
||||
|
||||
virtual void NotifyInputConnected() {}
|
||||
|
||||
// MarkActive() asks the context to keep the AudioNode alive until the
|
||||
// context is finished. This takes care of "playing" references and
|
||||
// "tail-time" references.
|
||||
void MarkActive() { Context()->RegisterActiveNode(this); }
|
||||
// Active nodes call MarkInactive() when they have finished producing sound
|
||||
// for the foreseeable future.
|
||||
// Do not call MarkInactive from a node destructor. If the destructor is
|
||||
// called, then the node is already inactive.
|
||||
// MarkInactive() may delete |this|.
|
||||
void MarkInactive() { Context()->UnregisterActiveNode(this); }
|
||||
|
||||
private:
|
||||
friend class AudioBufferSourceNode;
|
||||
// This could possibly delete 'this'.
|
||||
|
@ -63,18 +63,15 @@ public:
|
||||
}
|
||||
bool AcceptPlayingRefRelease(int64_t aLastGraphUpdateIndexProcessed) const
|
||||
{
|
||||
// Reject any requests to release mPlayingRef if the request was issued
|
||||
// Reject any requests to release the playing ref if the request was issued
|
||||
// before the MediaStreamGraph was aware of the most-recently-added input
|
||||
// connection.
|
||||
return aLastGraphUpdateIndexProcessed >= mMediaStreamGraphUpdateIndexAtLastInputConnection;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PlayingRefChangeHandler<ConvolverNode>;
|
||||
|
||||
int64_t mMediaStreamGraphUpdateIndexAtLastInputConnection;
|
||||
nsRefPtr<AudioBuffer> mBuffer;
|
||||
SelfReference<ConvolverNode> mPlayingRef;
|
||||
bool mNormalize;
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
}
|
||||
bool AcceptPlayingRefRelease(int64_t aLastGraphUpdateIndexProcessed) const
|
||||
{
|
||||
// Reject any requests to release mPlayingRef if the request was issued
|
||||
// Reject any requests to release the playing ref if the request was issued
|
||||
// before the MediaStreamGraph was aware of the most-recently-added input
|
||||
// connection.
|
||||
return aLastGraphUpdateIndexProcessed >= mMediaStreamGraphUpdateIndexAtLastInputConnection;
|
||||
@ -48,12 +48,10 @@ public:
|
||||
private:
|
||||
static void SendDelayToStream(AudioNode* aNode);
|
||||
friend class DelayNodeEngine;
|
||||
friend class PlayingRefChangeHandler<DelayNode>;
|
||||
|
||||
private:
|
||||
int64_t mMediaStreamGraphUpdateIndexAtLastInputConnection;
|
||||
nsRefPtr<AudioParam> mDelay;
|
||||
SelfReference<DelayNode> mPlayingRef;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -38,10 +38,10 @@ public:
|
||||
}
|
||||
if (node) {
|
||||
if (mChange == ADDREF) {
|
||||
node->mPlayingRef.Take(node);
|
||||
node->MarkActive();
|
||||
} else if (mChange == RELEASE &&
|
||||
node->AcceptPlayingRefRelease(mLastProcessedGraphUpdateIndex)) {
|
||||
node->mPlayingRef.Drop(node);
|
||||
node->MarkInactive();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -98,6 +98,7 @@ public:
|
||||
: mOutputQueue("SharedBuffers::outputQueue")
|
||||
, mDelaySoFar(TRACK_TICKS_MAX)
|
||||
, mSampleRate(aSampleRate)
|
||||
, mLatency(0.0)
|
||||
, mDroppingBuffers(false)
|
||||
{
|
||||
}
|
||||
|
@ -54,6 +54,10 @@ addLoadEvent(function() {
|
||||
compareBuffers(e.renderedBuffer.getChannelData(0), buf.getChannelData(0));
|
||||
compareBuffers(e.renderedBuffer.getChannelData(1), buf.getChannelData(1));
|
||||
|
||||
expectException(function() {
|
||||
ctx.startRendering();
|
||||
}, DOMException.INVALID_STATE_ERR);
|
||||
|
||||
SimpleTest.finish();
|
||||
}, false);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test PannerNode directly above</title>
|
||||
<title>Test ConvolverNode channel count</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
const signalLength = 2048;
|
||||
const responseLength = 1000;
|
||||
const outputLength = 4096; // > signalLength + responseLength to work around bug 910171
|
||||
const outputLength = 2048; // < signalLength + responseLength to test bug 910171
|
||||
|
||||
var gTest = {
|
||||
length: outputLength,
|
||||
|
@ -74,7 +74,6 @@ static int webm_read(void *aBuffer, size_t aLength, void *aUserData)
|
||||
eof = true;
|
||||
break;
|
||||
}
|
||||
decoder->NotifyBytesConsumed(bytes);
|
||||
aLength -= bytes;
|
||||
p += bytes;
|
||||
}
|
||||
|
@ -106,7 +106,6 @@ WMFByteStream::WMFByteStream(MediaResource* aResource,
|
||||
mResource(aResource),
|
||||
mReentrantMonitor("WMFByteStream.Data"),
|
||||
mOffset(0),
|
||||
mBytesConsumed(0),
|
||||
mIsShutdown(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
|
||||
@ -396,15 +395,6 @@ WMFByteStream::Close()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
WMFByteStream::GetAndResetBytesConsumedCount()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
uint32_t bytesConsumed = mBytesConsumed;
|
||||
mBytesConsumed = 0;
|
||||
return bytesConsumed;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
WMFByteStream::EndRead(IMFAsyncResult* aResult, ULONG *aBytesRead)
|
||||
{
|
||||
@ -428,10 +418,6 @@ WMFByteStream::EndRead(IMFAsyncResult* aResult, ULONG *aBytesRead)
|
||||
LOG("[%p] WMFByteStream::EndRead() offset=%lld *aBytesRead=%u mOffset=%lld status=0x%x hr=0x%x eof=%d",
|
||||
this, requestState->mOffset, *aBytesRead, mOffset, aResult->GetStatus(), hr, IsEOS());
|
||||
|
||||
if (SUCCEEDED(aResult->GetStatus())) {
|
||||
mBytesConsumed += requestState->mBytesRead;
|
||||
}
|
||||
|
||||
return aResult->GetStatus();
|
||||
}
|
||||
|
||||
|
@ -112,10 +112,6 @@ public:
|
||||
void ProcessReadRequest(IMFAsyncResult* aResult,
|
||||
ReadRequest* aRequestState);
|
||||
|
||||
// Returns the number of bytes that have been consumed by the users of this
|
||||
// class since the last time we called this, and resets the internal counter.
|
||||
uint32_t GetAndResetBytesConsumedCount();
|
||||
|
||||
private:
|
||||
|
||||
// Locks the MediaResource and performs the read. The other read methods
|
||||
@ -152,11 +148,6 @@ private:
|
||||
// standard IMFAttributes class, which we store a reference to here.
|
||||
RefPtr<IMFAttributes> mAttributes;
|
||||
|
||||
// Number of bytes that have been consumed by callers of the read functions
|
||||
// on this object since the last time GetAndResetBytesConsumedCount() was
|
||||
// called.
|
||||
uint32_t mBytesConsumed;
|
||||
|
||||
// True if the resource has been shutdown, either because the WMFReader is
|
||||
// shutting down, or because the underlying MediaResource has closed.
|
||||
bool mIsShutdown;
|
||||
|
@ -763,8 +763,6 @@ WMFReader::DecodeAudioData()
|
||||
timestamp, duration, currentLength);
|
||||
#endif
|
||||
|
||||
NotifyBytesConsumed();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -993,20 +991,9 @@ WMFReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
return false;
|
||||
}
|
||||
|
||||
NotifyBytesConsumed();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WMFReader::NotifyBytesConsumed()
|
||||
{
|
||||
uint32_t bytesConsumed = mByteStream->GetAndResetBytesConsumedCount();
|
||||
if (bytesConsumed > 0) {
|
||||
mDecoder->NotifyBytesConsumed(bytesConsumed);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
WMFReader::Seek(int64_t aTargetUs,
|
||||
int64_t aStartTime,
|
||||
|
@ -76,11 +76,6 @@ private:
|
||||
// Attempt to initialize DXVA. Returns true on success.
|
||||
bool InitializeDXVA();
|
||||
|
||||
// Notifies the MediaDecoder of the number of bytes we have consumed
|
||||
// since last time we called this. We call this once per call to
|
||||
// DecodeVideoFrame() and/or DecodeAudioData().
|
||||
void NotifyBytesConsumed();
|
||||
|
||||
RefPtr<IMFSourceReader> mSourceReader;
|
||||
RefPtr<WMFByteStream> mByteStream;
|
||||
RefPtr<WMFSourceReaderCallback> mSourceReaderCallback;
|
||||
|
@ -5068,7 +5068,7 @@ NS_IMETHODIMP
|
||||
nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
|
||||
{
|
||||
if (mParentWidget) {
|
||||
*aScale = mParentWidget->GetDefaultScale();
|
||||
*aScale = mParentWidget->GetDefaultScale().scale;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -352,8 +352,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSRuleList, nsCSSRuleListSH,
|
||||
ARRAY_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSGroupRuleRuleList, nsCSSRuleListSH,
|
||||
ARRAY_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(MediaList, nsMediaListSH,
|
||||
ARRAY_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(StyleSheetList, nsStyleSheetListSH,
|
||||
@ -1082,10 +1080,6 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(CSSGroupRuleRuleList, nsIDOMCSSRuleList)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(MediaList, nsIDOMMediaList)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaList)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -19,7 +19,6 @@ DOMCI_CLASS(CSSImportRule)
|
||||
DOMCI_CLASS(CSSMediaRule)
|
||||
DOMCI_CLASS(CSSNameSpaceRule)
|
||||
DOMCI_CLASS(CSSRuleList)
|
||||
DOMCI_CLASS(CSSGroupRuleRuleList)
|
||||
DOMCI_CLASS(MediaList)
|
||||
DOMCI_CLASS(StyleSheetList)
|
||||
DOMCI_CLASS(CSSStyleSheet)
|
||||
|
@ -7268,22 +7268,14 @@ nsGlobalWindow::FinalClose()
|
||||
// broken addons. The chrome tests in toolkit/mozapps/downloads are a good
|
||||
// testing ground.
|
||||
//
|
||||
// Here are some quirks that the test suite depends on:
|
||||
//
|
||||
// * When chrome code executes |win|.close(), that close happens immediately,
|
||||
// along with the accompanying "domwindowclosed" notification. But _only_ if
|
||||
// |win|'s JSContext is not at the top of the stack. If it is, the close
|
||||
// _must not_ happen immediately.
|
||||
//
|
||||
// * If |win|'s JSContext is at the top of the stack, we must complete _two_
|
||||
// round-trips to the event loop before the call to ReallyCloseWindow. This
|
||||
// allows setTimeout handlers that are set after FinalClose() is called to
|
||||
// run before the window is torn down.
|
||||
// In particular, if |win|'s JSContext is at the top of the stack, we must
|
||||
// complete _two_ round-trips to the event loop before the call to
|
||||
// ReallyCloseWindow. This allows setTimeout handlers that are set after
|
||||
// FinalClose() is called to run before the window is torn down.
|
||||
bool indirect = GetContextInternal() && // Occasionally null. See bug 877390.
|
||||
(nsContentUtils::GetCurrentJSContext() ==
|
||||
GetContextInternal()->GetNativeContext());
|
||||
if ((!indirect && nsContentUtils::IsCallerChrome()) ||
|
||||
NS_FAILED(nsCloseEvent::PostCloseEvent(this, indirect))) {
|
||||
if (NS_FAILED(nsCloseEvent::PostCloseEvent(this, indirect))) {
|
||||
ReallyCloseWindow();
|
||||
} else {
|
||||
mHavePendingClose = true;
|
||||
|
@ -2121,8 +2121,8 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
|
||||
}
|
||||
|
||||
NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
|
||||
NS_LL("CC(T+%.1f) duration: %lums, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu waiting for GC)%s\n")
|
||||
NS_LL("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, sync: %lu ms, removed: %lu"));
|
||||
MOZ_UTF16("CC(T+%.1f) duration: %lums, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu waiting for GC)%s\n")
|
||||
MOZ_UTF16("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, sync: %lu ms, removed: %lu"));
|
||||
nsString msg;
|
||||
msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
|
||||
ccNowDuration, suspected,
|
||||
@ -2146,28 +2146,28 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
|
||||
|
||||
if (sPostGCEventsToObserver) {
|
||||
NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt,
|
||||
NS_LL("{ \"timestamp\": %llu, ")
|
||||
NS_LL("\"duration\": %llu, ")
|
||||
NS_LL("\"finish_gc_duration\": %llu, ")
|
||||
NS_LL("\"sync_skippable_duration\": %llu, ")
|
||||
NS_LL("\"suspected\": %lu, ")
|
||||
NS_LL("\"visited\": { ")
|
||||
NS_LL("\"RCed\": %lu, ")
|
||||
NS_LL("\"GCed\": %lu }, ")
|
||||
NS_LL("\"collected\": { ")
|
||||
NS_LL("\"RCed\": %lu, ")
|
||||
NS_LL("\"GCed\": %lu }, ")
|
||||
NS_LL("\"waiting_for_gc\": %lu, ")
|
||||
NS_LL("\"short_living_objects_waiting_for_gc\": %lu, ")
|
||||
NS_LL("\"forced_gc\": %d, ")
|
||||
NS_LL("\"forget_skippable\": { ")
|
||||
NS_LL("\"times_before_cc\": %lu, ")
|
||||
NS_LL("\"min\": %lu, ")
|
||||
NS_LL("\"max\": %lu, ")
|
||||
NS_LL("\"avg\": %lu, ")
|
||||
NS_LL("\"total\": %lu, ")
|
||||
NS_LL("\"removed\": %lu } ")
|
||||
NS_LL("}"));
|
||||
MOZ_UTF16("{ \"timestamp\": %llu, ")
|
||||
MOZ_UTF16("\"duration\": %llu, ")
|
||||
MOZ_UTF16("\"finish_gc_duration\": %llu, ")
|
||||
MOZ_UTF16("\"sync_skippable_duration\": %llu, ")
|
||||
MOZ_UTF16("\"suspected\": %lu, ")
|
||||
MOZ_UTF16("\"visited\": { ")
|
||||
MOZ_UTF16("\"RCed\": %lu, ")
|
||||
MOZ_UTF16("\"GCed\": %lu }, ")
|
||||
MOZ_UTF16("\"collected\": { ")
|
||||
MOZ_UTF16("\"RCed\": %lu, ")
|
||||
MOZ_UTF16("\"GCed\": %lu }, ")
|
||||
MOZ_UTF16("\"waiting_for_gc\": %lu, ")
|
||||
MOZ_UTF16("\"short_living_objects_waiting_for_gc\": %lu, ")
|
||||
MOZ_UTF16("\"forced_gc\": %d, ")
|
||||
MOZ_UTF16("\"forget_skippable\": { ")
|
||||
MOZ_UTF16("\"times_before_cc\": %lu, ")
|
||||
MOZ_UTF16("\"min\": %lu, ")
|
||||
MOZ_UTF16("\"max\": %lu, ")
|
||||
MOZ_UTF16("\"avg\": %lu, ")
|
||||
MOZ_UTF16("\"total\": %lu, ")
|
||||
MOZ_UTF16("\"removed\": %lu } ")
|
||||
MOZ_UTF16("}"));
|
||||
nsString json;
|
||||
json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(), endCCTime,
|
||||
ccNowDuration, gcDuration, skippableDuration,
|
||||
|
@ -67,7 +67,7 @@ interface nsIContentPref;
|
||||
* See nsIContentPrefCallback2 below for more information about callbacks.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(133608c7-f812-41ca-bc1c-62a4eb95e52a)]
|
||||
[scriptable, uuid(86279644-6b86-4875-a228-2d2ff2f3e33b)]
|
||||
interface nsIContentPrefService2 : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -153,7 +153,7 @@ interface nsIContentPrefService2 : nsISupports
|
||||
void getCachedBySubdomainAndName(in AString domain,
|
||||
in AString name,
|
||||
in nsILoadContext context,
|
||||
out unsigned long len,
|
||||
[optional] out unsigned long len,
|
||||
[retval,array,size_is(len)] out nsIContentPref prefs);
|
||||
|
||||
/**
|
||||
|
@ -425,7 +425,7 @@ TabChild::Observe(nsISupports *aSubject,
|
||||
mLastMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
|
||||
mLastMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
|
||||
mLastMetrics.mZoom = mLastMetrics.CalculateIntrinsicScale();
|
||||
mLastMetrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(mWidget->GetDefaultScale());
|
||||
mLastMetrics.mDevPixelsPerCSSPixel = mWidget->GetDefaultScale();
|
||||
// We use ScreenToLayerScale(1) below in order to turn the
|
||||
// async zoom amount into the gecko zoom amount.
|
||||
mLastMetrics.mCumulativeResolution =
|
||||
|
@ -1146,9 +1146,9 @@ TabParent::RecvGetDefaultScale(double* aValue)
|
||||
{
|
||||
TryCacheDPIAndScale();
|
||||
|
||||
NS_ABORT_IF_FALSE(mDefaultScale > 0,
|
||||
NS_ABORT_IF_FALSE(mDefaultScale.scale > 0,
|
||||
"Must not ask for scale before OwnerElement is received!");
|
||||
*aValue = mDefaultScale;
|
||||
*aValue = mDefaultScale.scale;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -309,7 +309,7 @@ protected:
|
||||
nsIntSize mDimensions;
|
||||
ScreenOrientation mOrientation;
|
||||
float mDPI;
|
||||
double mDefaultScale;
|
||||
CSSToLayoutDeviceScale mDefaultScale;
|
||||
bool mShown;
|
||||
bool mUpdatedDimensions;
|
||||
|
||||
|
@ -290,6 +290,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
||||
mNumCachedParams = 0;
|
||||
mCachedAttrParamNames = nullptr;
|
||||
mCachedAttrParamValues = nullptr;
|
||||
mLastMouseDownButtonType = -1;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#ifndef NP_NO_CARBON
|
||||
@ -1860,8 +1861,9 @@ nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent)
|
||||
}
|
||||
|
||||
nsEvent* event = aMouseEvent->GetInternalNSEvent();
|
||||
if (event && event->eventStructType == NS_MOUSE_EVENT) {
|
||||
nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
|
||||
if (event && event->eventStructType == NS_MOUSE_EVENT) {
|
||||
mLastMouseDownButtonType = static_cast<nsMouseEvent*>(event)->button;
|
||||
nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
|
||||
if (nsEventStatus_eConsumeNoDefault == rv) {
|
||||
return aMouseEvent->PreventDefault(); // consume event
|
||||
}
|
||||
@ -1888,6 +1890,9 @@ nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent)
|
||||
aMouseEvent->PreventDefault();
|
||||
aMouseEvent->StopPropagation();
|
||||
}
|
||||
if (event->message == NS_MOUSE_BUTTON_UP) {
|
||||
mLastMouseDownButtonType = -1;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1911,11 +1916,15 @@ nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
|
||||
return ProcessMouseDown(aEvent);
|
||||
}
|
||||
if (eventType.EqualsLiteral("mouseup")) {
|
||||
// Don't send a mouse-up event to the plugin if it isn't focused. This can
|
||||
// happen if the previous mouse-down was sent to a DOM element above the
|
||||
// plugin, the mouse is still above the plugin, and the mouse-down event
|
||||
// caused the element to disappear. See bug 627649.
|
||||
if (!mContentFocused) {
|
||||
// Don't send a mouse-up event to the plugin if its button type doesn't
|
||||
// match that of the preceding mouse-down event (if any). This kind of
|
||||
// mismatch can happen if the previous mouse-down event was sent to a DOM
|
||||
// element above the plugin, the mouse is still above the plugin, and the
|
||||
// mouse-down event caused the element to disappear. See bug 627649 and
|
||||
// bug 909678.
|
||||
nsMouseEvent *event =
|
||||
static_cast<nsMouseEvent*>(aEvent->GetInternalNSEvent());
|
||||
if (event && ((int) event->button != mLastMouseDownButtonType)) {
|
||||
aEvent->PreventDefault();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -320,6 +320,8 @@ private:
|
||||
nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
|
||||
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
|
||||
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
|
||||
|
||||
int mLastMouseDownButtonType;
|
||||
|
||||
nsresult EnsureCachedAttrParamArrays();
|
||||
|
||||
|
@ -134,7 +134,6 @@ var interfaceNamesInGlobalScope =
|
||||
"CSSFontFaceRule",
|
||||
{name: "CSSFontFeatureValuesRule", release: false},
|
||||
"CSSGroupingRule",
|
||||
"CSSGroupRuleRuleList",
|
||||
"CSSImportRule",
|
||||
"CSSMediaRule",
|
||||
"CSSMozDocumentRule",
|
||||
|
@ -233,7 +233,9 @@ function doTest() {
|
||||
|
||||
privateWin.close();
|
||||
|
||||
testOnWindow(true, function(newPrivateWin) {
|
||||
// The .close() call above will operate asynchronously, so execute the
|
||||
// code below asynchronously as well.
|
||||
function callback(newPrivateWin) {
|
||||
is(newPrivateWin.content.localStorage.getItem("must disappear"), null, "private browsing values threw away");
|
||||
is(newPrivateWin.content.localStorage.length, 0, "No items");
|
||||
|
||||
@ -245,7 +247,8 @@ function doTest() {
|
||||
prefBranch.clearUserPref("browser.startup.page")
|
||||
prefBranch.clearUserPref("browser.startup.homepage_override.mstone");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
};
|
||||
SimpleTest.executeSoon(function() testOnWindow(true, callback));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/.
|
||||
@ -16,6 +16,7 @@ callback OfflineRenderSuccessCallback = void (AudioBuffer renderedData);
|
||||
PrefControlled]
|
||||
interface OfflineAudioContext : AudioContext {
|
||||
|
||||
[Throws]
|
||||
void startRendering();
|
||||
|
||||
attribute EventHandler oncomplete;
|
||||
|
@ -1244,7 +1244,7 @@ NS_IMETHODIMP nsWebBrowser::Destroy()
|
||||
|
||||
NS_IMETHODIMP nsWebBrowser::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
|
||||
{
|
||||
*aScale = mParentWidget ? mParentWidget->GetDefaultScale() : 1.0;
|
||||
*aScale = mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -835,7 +835,8 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
|
||||
"BeginUpdate should always modify the draw region in the same way!");
|
||||
FillSurface(onBlack, result.mRegionToDraw, nsIntPoint(drawBounds.x, drawBounds.y), gfxRGBA(0.0, 0.0, 0.0, 1.0));
|
||||
FillSurface(onWhite, result.mRegionToDraw, nsIntPoint(drawBounds.x, drawBounds.y), gfxRGBA(1.0, 1.0, 1.0, 1.0));
|
||||
if (RefPtr<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize())) {
|
||||
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
|
||||
RefPtr<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize());
|
||||
RefPtr<DrawTarget> onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize());
|
||||
RefPtr<DrawTarget> dt = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
|
||||
result.mContext = new gfxContext(dt);
|
||||
@ -861,7 +862,8 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
|
||||
}
|
||||
} else {
|
||||
nsRefPtr<gfxASurface> surf = GetUpdateSurface(BUFFER_BLACK, result.mRegionToDraw);
|
||||
if (RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize())) {
|
||||
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
|
||||
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize());
|
||||
result.mContext = new gfxContext(dt);
|
||||
} else {
|
||||
result.mContext = new gfxContext(surf);
|
||||
|
@ -709,7 +709,7 @@ public:
|
||||
// see bug 865908 about fixing this.
|
||||
virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
MOZ_ASSERT(!mBuffer, "Will leak the old mBuffer");
|
||||
MOZ_ASSERT(!mBuffer || mBuffer == aBuffer, "Will leak the old mBuffer");
|
||||
mBuffer = aBuffer;
|
||||
mDeAllocator = aAllocator;
|
||||
}
|
||||
|
@ -25,9 +25,9 @@
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#ifdef MOZ_METRO
|
||||
#include "DXGI1_2.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
@ -640,17 +640,15 @@ LayerManagerD3D10::VerifyBufferSize()
|
||||
}
|
||||
|
||||
mRTView = nullptr;
|
||||
if (gfxWindowsPlatform::IsOptimus()) {
|
||||
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
#ifdef MOZ_METRO
|
||||
} else if (IsRunningInWindowsMetro()) {
|
||||
if (IsRunningInWindowsMetro()) {
|
||||
mSwapChain->ResizeBuffers(2, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
mDisableSequenceForNextFrame = true;
|
||||
#endif
|
||||
} else if (gfxWindowsPlatform::IsOptimus()) {
|
||||
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
} else {
|
||||
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
|
@ -750,17 +750,15 @@ CompositorD3D11::VerifyBufferSize()
|
||||
|
||||
mDefaultRT = nullptr;
|
||||
|
||||
if (gfxWindowsPlatform::IsOptimus()) {
|
||||
mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
#ifdef MOZ_METRO
|
||||
} else if (IsRunningInWindowsMetro()) {
|
||||
if (IsRunningInWindowsMetro()) {
|
||||
mSwapChain->ResizeBuffers(2, mSize.width, mSize.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
mDisableSequenceForNextFrame = true;
|
||||
#endif
|
||||
} else if (gfxWindowsPlatform::IsOptimus()) {
|
||||
mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
} else {
|
||||
mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
|
@ -353,7 +353,9 @@ nsDeviceContext::SetDPI()
|
||||
dpi = 96.0f;
|
||||
}
|
||||
|
||||
double devPixelsPerCSSPixel = mWidget ? mWidget->GetDefaultScale() : 1.0;
|
||||
CSSToLayoutDeviceScale scale = mWidget ? mWidget->GetDefaultScale()
|
||||
: CSSToLayoutDeviceScale(1.0);
|
||||
double devPixelsPerCSSPixel = scale.scale;
|
||||
|
||||
mAppUnitsPerDevNotScaledPixel =
|
||||
std::max(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
|
||||
|
@ -8,9 +8,7 @@
|
||||
#include "nsDeviceContext.h" // for nsDeviceContext
|
||||
#include "nsStringGlue.h" // for nsAutoString, etc
|
||||
#include "prtypes.h" // for PR_STATIC_ASSERT
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "nsMargin.h" // for nsMargin
|
||||
#include <algorithm> // for min, max
|
||||
|
||||
// the mozilla::css::Side sequence must match the nsMargin nscoord sequence
|
||||
PR_STATIC_ASSERT((NS_SIDE_TOP == 0) && (NS_SIDE_RIGHT == 1) && (NS_SIDE_BOTTOM == 2) && (NS_SIDE_LEFT == 3));
|
||||
@ -41,89 +39,3 @@ FILE* operator<<(FILE* out, const nsRect& rect)
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
nsRect
|
||||
nsRect::SaturatingUnionEdges(const nsRect& aRect) const
|
||||
{
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
return UnionEdges(aRect);
|
||||
#else
|
||||
nsRect result;
|
||||
result.x = std::min(aRect.x, x);
|
||||
int64_t w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
|
||||
if (MOZ_UNLIKELY(w > nscoord_MAX)) {
|
||||
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord width");
|
||||
// Clamp huge negative x to nscoord_MIN / 2 and try again.
|
||||
result.x = std::max(result.x, nscoord_MIN / 2);
|
||||
w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
|
||||
if (MOZ_UNLIKELY(w > nscoord_MAX)) {
|
||||
w = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
result.width = nscoord(w);
|
||||
|
||||
result.y = std::min(aRect.y, y);
|
||||
int64_t h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
|
||||
if (MOZ_UNLIKELY(h > nscoord_MAX)) {
|
||||
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord height");
|
||||
// Clamp huge negative y to nscoord_MIN / 2 and try again.
|
||||
result.y = std::max(result.y, nscoord_MIN / 2);
|
||||
h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
|
||||
if (MOZ_UNLIKELY(h > nscoord_MAX)) {
|
||||
h = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
result.height = nscoord(h);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsRect::SaturatingInflate(const nsMargin& aMargin)
|
||||
{
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
Inflate(aMargin);
|
||||
#else
|
||||
int64_t nx = int64_t(x) - aMargin.left;
|
||||
int64_t w = int64_t(width) + int64_t(aMargin.left) + aMargin.right;
|
||||
if (MOZ_UNLIKELY(w > nscoord_MAX)) {
|
||||
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord width");
|
||||
int64_t xdiff = nx - nscoord_MIN / 2;
|
||||
if (xdiff < 0) {
|
||||
// Clamp huge negative x to nscoord_MIN / 2 and try again.
|
||||
nx = nscoord_MIN / 2;
|
||||
w += xdiff;
|
||||
}
|
||||
if (MOZ_UNLIKELY(w > nscoord_MAX)) {
|
||||
w = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
width = nscoord(w);
|
||||
if (MOZ_UNLIKELY(nx < nscoord_MIN)) {
|
||||
NS_WARNING("Underflowed nscoord_MIN in conversion to nscoord x");
|
||||
nx = nscoord_MIN;
|
||||
}
|
||||
x = nscoord(nx);
|
||||
|
||||
int64_t ny = int64_t(y) - aMargin.top;
|
||||
int64_t h = int64_t(height) + int64_t(aMargin.top) + aMargin.bottom;
|
||||
if (MOZ_UNLIKELY(h > nscoord_MAX)) {
|
||||
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord height");
|
||||
int64_t ydiff = ny - nscoord_MIN / 2;
|
||||
if (ydiff < 0) {
|
||||
// Clamp huge negative y to nscoord_MIN / 2 and try again.
|
||||
ny = nscoord_MIN / 2;
|
||||
h += ydiff;
|
||||
}
|
||||
if (MOZ_UNLIKELY(h > nscoord_MAX)) {
|
||||
h = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
height = nscoord(h);
|
||||
if (MOZ_UNLIKELY(ny < nscoord_MIN)) {
|
||||
NS_WARNING("Underflowed nscoord_MIN in conversion to nscoord y");
|
||||
ny = nscoord_MIN;
|
||||
}
|
||||
y = nscoord(ny);
|
||||
#endif
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include <stdio.h> // for FILE
|
||||
#include <stdint.h> // for int32_t, int64_t
|
||||
#include <algorithm> // for min/max
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "gfxCore.h" // for NS_GFX
|
||||
#include "mozilla/Likely.h" // for MOZ_UNLIKELY
|
||||
#include "mozilla/gfx/BaseRect.h" // for BaseRect
|
||||
@ -53,11 +55,6 @@ struct NS_GFX nsRect :
|
||||
}
|
||||
#endif
|
||||
|
||||
// A version of Inflate that caps the values to the nscoord range.
|
||||
// x & y is capped at the minimum value nscoord_MIN and
|
||||
// width & height is capped at the maximum value nscoord_MAX.
|
||||
void SaturatingInflate(const nsMargin& aMargin);
|
||||
|
||||
// We have saturating versions of all the Union methods. These avoid
|
||||
// overflowing nscoord values in the 'width' and 'height' fields by
|
||||
// clamping the width and height values to nscoord_MAX if necessary.
|
||||
@ -73,7 +70,40 @@ struct NS_GFX nsRect :
|
||||
}
|
||||
}
|
||||
|
||||
nsRect SaturatingUnionEdges(const nsRect& aRect) const;
|
||||
nsRect SaturatingUnionEdges(const nsRect& aRect) const
|
||||
{
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
return UnionEdges(aRect);
|
||||
#else
|
||||
nsRect result;
|
||||
result.x = std::min(aRect.x, x);
|
||||
int64_t w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
|
||||
if (MOZ_UNLIKELY(w > nscoord_MAX)) {
|
||||
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord width");
|
||||
// Clamp huge negative x to nscoord_MIN / 2 and try again.
|
||||
result.x = std::max(result.x, nscoord_MIN / 2);
|
||||
w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
|
||||
if (MOZ_UNLIKELY(w > nscoord_MAX)) {
|
||||
w = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
result.width = nscoord(w);
|
||||
|
||||
result.y = std::min(aRect.y, y);
|
||||
int64_t h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
|
||||
if (MOZ_UNLIKELY(h > nscoord_MAX)) {
|
||||
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord height");
|
||||
// Clamp huge negative y to nscoord_MIN / 2 and try again.
|
||||
result.y = std::max(result.y, nscoord_MIN / 2);
|
||||
h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
|
||||
if (MOZ_UNLIKELY(h > nscoord_MAX)) {
|
||||
h = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
result.height = nscoord(h);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NS_COORD_IS_FLOAT
|
||||
// Make all nsRect Union methods be saturating.
|
||||
|
@ -208,6 +208,19 @@ PokeGC(JSRuntime *rt);
|
||||
extern JS_FRIEND_API(bool)
|
||||
WasIncrementalGC(JSRuntime *rt);
|
||||
|
||||
extern JS_FRIEND_API(size_t)
|
||||
GetGCNumber();
|
||||
|
||||
class AutoAssertNoGC {
|
||||
#ifdef DEBUG
|
||||
size_t gcNumber;
|
||||
|
||||
public:
|
||||
AutoAssertNoGC();
|
||||
~AutoAssertNoGC();
|
||||
#endif
|
||||
};
|
||||
|
||||
class JS_PUBLIC_API(ObjectPtr)
|
||||
{
|
||||
Heap<JSObject *> value;
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "jsatominlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/Shape-inl.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
using namespace js;
|
||||
|
@ -2560,13 +2560,14 @@ dnl ========================================================
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_MEMCMP
|
||||
AC_CHECK_FUNCS([fchmod flockfile getc_unlocked _getc_nolock getpagesize \
|
||||
lchown localtime_r lstat64 memmove random rint sbrk snprintf \
|
||||
lchown localtime_r lstat64 memmove random sbrk snprintf \
|
||||
stat64 statvfs statvfs64 strerror strtok_r truncate64])
|
||||
|
||||
|
||||
dnl Checks for math functions.
|
||||
dnl ========================================================
|
||||
AC_CHECK_FUNCS(log2 log1p expm1 sqrt1pm1 acosh asinh atanh hypot trunc cbrt)
|
||||
AC_CHECK_LIB(m, sin)
|
||||
AC_CHECK_FUNCS([log2 log1p expm1 sqrt1pm1 acosh asinh atanh hypot trunc cbrt])
|
||||
|
||||
|
||||
dnl check for wcrtomb/mbrtowc
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "jit/IonCode.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/ScopeObject.h"
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
|
||||
@ -17,7 +18,6 @@
|
||||
#include "jsinferinlines.h"
|
||||
|
||||
#include "gc/Nursery-inl.h"
|
||||
#include "vm/Shape-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -53,7 +53,7 @@ The general format in EBNF is:
|
||||
item ::= flag | attribute
|
||||
|
||||
flag ::= "slow" | "allow-oom" | "valgrind" | "tz-pacific" |
|
||||
"mjit" | "mjitalways" | "ion-eager" | "debug" |
|
||||
"ion-eager" | "debug" |
|
||||
"dump-bytecode" |
|
||||
|
||||
|
||||
@ -70,8 +70,6 @@ The meaning of the items:
|
||||
allow-oom If the test runs out of memory, it counts as passing.
|
||||
valgrind Run test under valgrind.
|
||||
tz-pacific Always run test with the Pacific time zone (TZ=PST8PDT).
|
||||
mjit Run js with -m, whether --jitflags says to or not
|
||||
mjitalways Run js with -a, whether --jitflags says to or not
|
||||
ion-eager Run js with --ion-eager, whether --jitflags says to or not
|
||||
debug Run js with -d, whether --jitflags says to or not
|
||||
dump-bytecode Run js with -D, whether --jitflags says to or not
|
||||
|
@ -63,13 +63,13 @@ def main(argv):
|
||||
help='Run all tests with valgrind, if valgrind is in $PATH.')
|
||||
op.add_option('--jitflags', dest='jitflags', default='',
|
||||
help='Example: --jitflags=m,mn to run each test with "-m" and "-m -n" [default="%default"]. ' +
|
||||
'Long flags, such as "--no-jm", should be set using --args.')
|
||||
'Long flags, such as "--ion-eager", should be set using --args.')
|
||||
op.add_option('--avoid-stdio', dest='avoid_stdio', action='store_true',
|
||||
help='Use js-shell file indirection instead of piping stdio.')
|
||||
op.add_option('--write-failure-output', dest='write_failure_output', action='store_true',
|
||||
help='With --write-failures=FILE, additionally write the output of failed tests to [FILE]')
|
||||
op.add_option('--ion', dest='ion', action='store_true',
|
||||
help='Run tests once with --ion-eager and once with --no-jm (ignores --jitflags)')
|
||||
help='Run tests once with --ion-eager and once with --baseline-eager (ignores --jitflags)')
|
||||
op.add_option('--tbpl', dest='tbpl', action='store_true',
|
||||
help='Run tests with all IonMonkey option combinations (ignores --jitflags)')
|
||||
op.add_option('-j', '--worker-count', dest='max_jobs', type=int, default=max_jobs_default,
|
||||
|
@ -1,5 +1,5 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
quit();
|
||||
|
||||
function eval() {
|
||||
yield(undefined)
|
||||
|
@ -1,4 +1,4 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
quit();
|
||||
|
||||
new StructType([])
|
||||
|
@ -1,5 +1,5 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
quit();
|
||||
|
||||
var Color = new StructType({r: uint8, g: uint8, b: uint8});
|
||||
var white2 = new Color({r: 255, toString: null, b: 253});
|
||||
|
@ -1,4 +1,4 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
quit();
|
||||
|
||||
new StructType(RegExp());
|
||||
|
@ -1,3 +1,6 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
quit();
|
||||
|
||||
var PointType2 = new StructType({x: float64,
|
||||
y: float64});
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
quit();
|
||||
|
||||
var PointType = new StructType({x: float64,
|
||||
y: float64,
|
||||
z: float64});
|
||||
|
@ -1,3 +1,6 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
quit();
|
||||
|
||||
var PointType = new StructType({x: uint32,
|
||||
y: uint32,
|
||||
z: uint32});
|
||||
|
@ -1,8 +0,0 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
|
||||
function eval() {
|
||||
yield(undefined)
|
||||
}
|
||||
new(StructType)
|
||||
(eval())
|
@ -1,8 +0,0 @@
|
||||
// |jit-test| error:Error
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new Error("type too large");
|
||||
|
||||
var AA = new ArrayType(new ArrayType(uint8, (2147483647)), 5);
|
||||
var aa = new AA();
|
||||
var aa0 = aa[0];
|
@ -1,13 +0,0 @@
|
||||
// |jit-test| error:Error
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new Error("type too large");
|
||||
|
||||
var A = new ArrayType(uint8, (2147483647));
|
||||
var S = new StructType({a: A,
|
||||
b: A,
|
||||
c: A,
|
||||
d: A,
|
||||
e: A});
|
||||
var aa = new S();
|
||||
var aa0 = aa.a;
|
@ -1,4 +0,0 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
|
||||
new StructType([])
|
@ -1,7 +0,0 @@
|
||||
// |jit-test| error:RangeError;
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new RangeError();
|
||||
|
||||
this.__proto__ = Proxy.create({});
|
||||
new StructType;
|
@ -1,10 +0,0 @@
|
||||
// |jit-test| error:Error;
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new Error();
|
||||
|
||||
var A = new ArrayType(uint8, 10);
|
||||
var a = new A();
|
||||
a.forEach(function(val, i) {
|
||||
assertEq(arguments[5], a);
|
||||
});
|
@ -1,6 +0,0 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
|
||||
var Color = new StructType({r: uint8, g: uint8, b: uint8});
|
||||
var white2 = new Color({r: 255, toString: null, b: 253});
|
||||
|
@ -1,6 +0,0 @@
|
||||
// |jit-test| error:TypeError
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new TypeError();
|
||||
|
||||
new StructType(RegExp);
|
@ -1,4 +0,0 @@
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
exit(0);
|
||||
|
||||
new StructType(RegExp());
|
@ -1,6 +0,0 @@
|
||||
// |jit-test| error:Error
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new Error();
|
||||
|
||||
new ArrayType(uint8, .0000000009);
|
@ -1,10 +0,0 @@
|
||||
// |jit-test| error: TypeError
|
||||
|
||||
if (!this.hasOwnProperty("Type"))
|
||||
throw new TypeError();
|
||||
|
||||
var Vec3 = new ArrayType(float32, 3);
|
||||
var Sprite = new ArrayType(Vec3, 3);
|
||||
var mario = new Sprite();
|
||||
mario[/\u00ee[]/] = new Vec3([1, 0, 0]);
|
||||
|
@ -1,25 +0,0 @@
|
||||
var PointType2 = new StructType({x: float64,
|
||||
y: float64});
|
||||
|
||||
var PointType3 = new StructType({x: float64,
|
||||
y: float64,
|
||||
z: float64});
|
||||
|
||||
function xPlusY(p) {
|
||||
return p.x + p.y;
|
||||
}
|
||||
|
||||
function foo() {
|
||||
var N = 30000;
|
||||
var points = [];
|
||||
for (var i = 0; i < N; i++) {
|
||||
var s;
|
||||
if ((i % 2) == 0 || true)
|
||||
s = xPlusY(new PointType2({x: i, y: i+1}));
|
||||
else
|
||||
s = xPlusY(new PointType3({x: i, y: i+1, z: i+2}));
|
||||
assertEq(s, i + i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
foo();
|
@ -1,14 +0,0 @@
|
||||
var PointType = new StructType({x: float64,
|
||||
y: float64,
|
||||
z: float64});
|
||||
|
||||
function foo() {
|
||||
for (var i = 0; i < 30000; i += 3) {
|
||||
var pt = new PointType({x: i, y: i+1, z: i+2});
|
||||
var sum = pt.x + pt.y + pt.z;
|
||||
print(pt.x, pt.y, pt.z);
|
||||
assertEq(sum, 3*i + 3);
|
||||
}
|
||||
}
|
||||
|
||||
foo();
|
@ -1,13 +0,0 @@
|
||||
var PointType = new StructType({x: uint32,
|
||||
y: uint32,
|
||||
z: uint32});
|
||||
|
||||
function foo() {
|
||||
for (var i = 0; i < 30000; i += 3) {
|
||||
var pt = new PointType({x: i, y: i+1, z: i+2});
|
||||
var sum = pt.x + pt.y + pt.z;
|
||||
assertEq(sum, 3*i + 3);
|
||||
}
|
||||
}
|
||||
|
||||
foo();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user