This commit is contained in:
Ryan VanderMeulen 2013-06-07 11:13:25 -04:00
Родитель c4ee024ee1 1c6e0c1045
Коммит 1dbd23c907
415 изменённых файлов: 5156 добавлений и 2471 удалений

Просмотреть файл

@ -17,4 +17,4 @@
#
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 875929 removed a file from js/src/moz.build and apparently the build system didn't notice.
Bug 879831 needed to clobber for the removal of jsprobes.cpp

Просмотреть файл

@ -553,10 +553,7 @@ pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
pref("javascript.options.mem.gc_low_frequency_heap_growth", 120);
pref("javascript.options.mem.high_water_mark", 6);
pref("javascript.options.mem.gc_allocation_threshold_mb", 3);
// Allocation Threshold for workers
pref("dom.workers.mem.gc_allocation_threshold_mb", 3);
pref("javascript.options.mem.gc_allocation_threshold_mb", 1);
// Show/Hide scrollbars when active/inactive
pref("ui.showHideScrollbars", 1);

Просмотреть файл

@ -1 +0,0 @@
../panda/README

Просмотреть файл

@ -1,25 +0,0 @@
{
"config_version": 1,
"tooltool_manifest": "releng-pandaboard.tt",
"mock_target": "mozilla-centos6-i386",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
"build_targets": ["boottarball", "systemtarball", "userdatatarball", "package-tests"],
"upload_files": [
"{workdir}/out/target/product/panda/*.tar.bz2",
"{workdir}/out/target/product/panda/tests/*.zip",
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{srcdir}/b2g/config/panda/README",
"{workdir}/sources.xml"
],
"gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
"gaia": {
"vcs": "hgtool",
"repo": "http://hg.mozilla.org/integration/gaia-central",
"l10n": {
"vcs": "hgtool",
"root": "http://hg.mozilla.org/gaia-l10n"
}
},
"upload_platform": "panda_gaia_central"
}

Просмотреть файл

@ -1 +0,0 @@
../panda/releng-pandaboard.tt

Просмотреть файл

@ -393,7 +393,11 @@ pref("browser.link.open_newwindow.override.external", -1);
// 2: don't divert window.open with features
pref("browser.link.open_newwindow.restriction", 2);
// Disable opening a new window via window.open if browser is in fullscreen mode
// If true, this pref causes windows opened by window.open to be forced into new
// tabs (rather than potentially opening separate windows, depending on
// window.open arguments) when the browser is in fullscreen mode.
// We set this differently on Mac because the fullscreen implementation there is
// different.
#ifdef XP_MACOSX
pref("browser.link.open_newwindow.disabled_in_fullscreen", true);
#else

Просмотреть файл

@ -432,14 +432,22 @@ var FullZoom = {
* currently selected browser is used.
*/
_getState: function FullZoom__getState(browser) {
let browser = browser || gBrowser.selectedBrowser;
return { uri: browser.currentURI, token: this._zoomChangeToken };
browser = browser || gBrowser.selectedBrowser;
return {
// Due to async content pref service callbacks, this method can get called
// after the window has closed, so gBrowser.selectedBrowser may be null.
uri: browser ? browser.currentURI : null,
token: this._zoomChangeToken,
};
},
/**
* Returns true if the given state is current.
*/
_isStateCurrent: function FullZoom__isStateCurrent(state) {
// If either state has no URI, then the given state can't be current.
// currState.uri will be null when this method is called after the window
// has closed, which can happen due to async content pref service callbacks.
let currState = this._getState();
return currState.token === state.token &&
currState.uri && state.uri &&

Просмотреть файл

@ -1380,6 +1380,12 @@
t._tPos = position;
this.tabContainer._setPositionalAttributes();
// Prevent the superfluous initial load of a blank document
// if we're going to load something other than about:blank.
if (!uriIsAboutBlank) {
b.setAttribute("nodefaultsrc", "true");
}
// NB: this appendChild call causes us to run constructors for the
// browser element, which fires off a bunch of notifications. Some
// of those notifications can cause code to run that inspects our
@ -1389,13 +1395,6 @@
this.tabContainer.updateVisibility();
if (!uriIsAboutBlank) {
// Stop the existing about:blank load. Otherwise, if aURI
// doesn't stop in-progress loads on its own, we'll get into
// trouble with multiple parallel loads running at once.
b.stop();
}
// wire up a progress listener for the new browser object.
var tabListener = this.mTabProgressListener(t, b, uriIsAboutBlank);
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]

Просмотреть файл

@ -35,10 +35,10 @@ function test() {
}
function load(aTab, aUrl, aCallback) {
aTab.linkedBrowser.addEventListener("pageshow", function onpageshow(aEvent) {
aEvent.currentTarget.removeEventListener("pageshow", onpageshow, false);
aTab.linkedBrowser.addEventListener("load", function onload(aEvent) {
aEvent.currentTarget.removeEventListener("load", onload, true);
waitForFocus(aCallback, content);
}, false);
}, true);
aTab.linkedBrowser.loadURI(aUrl);
}

Просмотреть файл

@ -8,10 +8,6 @@ XPCOMUtils.defineLazyGetter(this, "docShell", () => {
});
const EXPECTED_REFLOWS = [
// b.stop() call in tabbrowser.addTab()
"stop@chrome://global/content/bindings/browser.xml|" +
"addTab@chrome://browser/content/tabbrowser.xml|",
// tabbrowser.adjustTabstrip() call after tabopen animation has finished
"adjustTabstrip@chrome://browser/content/tabbrowser.xml|" +
"_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
@ -30,7 +26,20 @@ const EXPECTED_REFLOWS = [
"get_scrollPosition@chrome://global/content/bindings/scrollbox.xml|" +
"_fillTrailingGap@chrome://browser/content/tabbrowser.xml|" +
"_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
"onxbltransitionend@chrome://browser/content/tabbrowser.xml|"
"onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
// The TabView iframe causes reflows in the parent document.
"iQClass_height@chrome://browser/content/tabview.js|" +
"GroupItem_getContentBounds@chrome://browser/content/tabview.js|" +
"GroupItem_shouldStack@chrome://browser/content/tabview.js|" +
"GroupItem_arrange@chrome://browser/content/tabview.js|" +
"GroupItem_add@chrome://browser/content/tabview.js|" +
"GroupItems_newTab@chrome://browser/content/tabview.js|" +
"TabItem__reconnect@chrome://browser/content/tabview.js|" +
"TabItem@chrome://browser/content/tabview.js|" +
"TabItems_link@chrome://browser/content/tabview.js|" +
"@chrome://browser/content/tabview.js|" +
"addTab@chrome://browser/content/tabbrowser.xml|"
];
const PREF_PRELOAD = "browser.newtab.preload";

Просмотреть файл

@ -1,23 +1,7 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
. "$topsrcdir/browser/config/mozconfigs/linux32/common-opt"
ac_add_options --enable-official-branding
. $topsrcdir/build/unix/mozconfig.linux32
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
mk_add_options MOZ_PGO=1
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,13 +1,7 @@
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
# This file is sourced by nightly, beta, and release mozconfigs.
# Options for rpm versions of mozconfigs
PREFIX=/usr
LIBDIR=${PREFIX}/lib
ac_add_options --with-app-name=mozilla-nightly
ac_add_options --disable-updater
ac_add_options --prefix=$PREFIX
ac_add_options --libdir=$LIBDIR
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
. $topsrcdir/build/unix/mozconfig.linux32
@ -19,10 +13,8 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
. "$topsrcdir/build/mozconfig.common.override"
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

Просмотреть файл

@ -1,5 +1,5 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
. "$topsrcdir/browser/config/mozconfigs/linux32/common-opt"
ac_add_options --enable-codesighs
ac_add_options --enable-signmar
ac_add_options --enable-profiling
@ -7,28 +7,12 @@ ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
. $topsrcdir/build/unix/mozconfig.linux32
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# This will overwrite the default of stripping everything and keep the symbol table.
# This is useful for profiling and debugging and only increases the package size
# by 2 MBs.
STRIP_FLAGS="--strip-debug"
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,24 +0,0 @@
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
. $topsrcdir/build/unix/mozconfig.linux32
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# QT Options
export PKG_CONFIG_PATH=/tools/qt-4.6.3/qt/lib/pkgconfig
ac_add_options --with-qtdir=/tools/qt-4.6.3/qt
ac_add_options --enable-default-toolkit=cairo-qt
ac_add_options --disable-crashreporter
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,7 +1,13 @@
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/linux32/beta"
. "$topsrcdir/browser/config/mozconfigs/linux32/common-opt"
ac_add_options --enable-official-branding
mk_add_options MOZ_PGO=1
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,23 +1,7 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
. "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
ac_add_options --enable-official-branding
. $topsrcdir/build/unix/mozconfig.linux
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
mk_add_options MOZ_PGO=1
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,13 +1,7 @@
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
# This file is sourced by the nightly, beta, and release mozconfigs.
# Options for rpm versions of mozconfigs
PREFIX=/usr
LIBDIR=${PREFIX}/lib64
ac_add_options --with-app-name=mozilla-nightly
ac_add_options --disable-updater
ac_add_options --prefix=$PREFIX
ac_add_options --libdir=$LIBDIR
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
. $topsrcdir/build/unix/mozconfig.linux
@ -19,10 +13,8 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
. "$topsrcdir/build/mozconfig.common.override"
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

Просмотреть файл

@ -1,5 +1,5 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
. "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
ac_add_options --enable-codesighs
ac_add_options --enable-signmar
ac_add_options --enable-profiling
@ -7,28 +7,12 @@ ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
. $topsrcdir/build/unix/mozconfig.linux
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# This will overwrite the default of stripping everything and keep the symbol table.
# This is useful for profiling and debugging and only increases the package size
# by 2 MBs.
STRIP_FLAGS="--strip-debug"
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,7 +1,13 @@
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/linux64/beta"
. "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
ac_add_options --enable-official-branding
mk_add_options MOZ_PGO=1
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,21 +1,5 @@
. $topsrcdir/build/macosx/universal/mozconfig
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/common-opt"
# Universal builds override the default of browser (bug 575283 comment 29)
ac_add_options --enable-application=browser
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -0,0 +1,20 @@
# This file is sourced by the nightly, beta, and release mozconfigs.
. $topsrcdir/build/macosx/universal/mozconfig
# Universal builds override the default of browser (bug 575283 comment 29)
ac_add_options --enable-application=browser
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

Просмотреть файл

@ -1,10 +1,5 @@
. $topsrcdir/build/macosx/universal/mozconfig
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/common-opt"
# Universal builds override the default of browser (bug 575283 comment 29)
ac_add_options --enable-application=browser
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
ac_add_options --disable-install-strip
ac_add_options --enable-signmar
@ -15,17 +10,6 @@ ac_add_options --enable-dtrace
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,7 +1,11 @@
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/beta"
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/common-opt"
ac_add_options --enable-official-branding
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,25 +0,0 @@
# Just like nightlies, but without tests, not on an update channel, and with
# shark and dtrace enabled
. $topsrcdir/build/macosx/universal/mozconfig
# Universal builds override the default of browser (bug 575283 comment 29)
ac_add_options --enable-application=browser
ac_add_options --disable-tests
ac_add_options --disable-install-strip
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
# shark specific options
ac_add_options --enable-shark
ac_add_options --enable-dtrace
# Need this to prevent name conflicts with the normal nightly build packages
export MOZ_PKG_SPECIAL="shark"
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
ac_add_options --with-ccache
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,31 +1,7 @@
. "$topsrcdir/browser/config/mozconfigs/common"
. "$topsrcdir/browser/config/mozconfigs/win32/common-opt"
mk_add_options MOZ_PGO=1
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-official-branding
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -0,0 +1,28 @@
# This file is sourced by the nightly, beta, and release mozconfigs.
. "$topsrcdir/browser/config/mozconfigs/common"
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

Просмотреть файл

@ -1,8 +1,5 @@
. "$topsrcdir/browser/config/mozconfigs/common"
. "$topsrcdir/browser/config/mozconfigs/win32/common-opt"
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-signmar
ac_add_options --enable-profiling
ac_add_options --enable-metro
@ -10,25 +7,4 @@ ac_add_options --enable-metro
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -1,7 +1,13 @@
# This make file should be identical to the beta mozconfig, apart from the
# safeguard below
. "$topsrcdir/browser/config/mozconfigs/win32/beta"
. "$topsrcdir/browser/config/mozconfigs/win32/common-opt"
mk_add_options MOZ_PGO=1
ac_add_options --enable-official-branding
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
# defines.sh during the beta cycle
export BUILDING_RELEASE=1
. "$topsrcdir/build/mozconfig.common.override"

Просмотреть файл

@ -579,7 +579,7 @@ StackFrames.prototype = {
this._addFrame(frame);
}
if (this.currentFrame == null) {
this.selectFrame(0);
DebuggerView.StackFrames.selectedDepth = 0;
}
if (this.activeThread.moreFrames) {
DebuggerView.StackFrames.dirty = true;
@ -639,8 +639,6 @@ StackFrames.prototype = {
// Move the editor's caret to the proper url and line.
DebuggerView.updateEditor(url, line);
// Highlight the stack frame at the specified depth.
DebuggerView.StackFrames.highlightFrame(aDepth);
// Highlight the breakpoint at the specified url and line if it exists.
DebuggerView.Sources.highlightBreakpoint(url, line);
// Don't display the watch expressions textbox inputs in the pane.

Просмотреть файл

@ -55,6 +55,8 @@ create({ constructor: SourcesView, proto: MenuContainer.prototype }, {
this._cbTextbox.addEventListener("input", this._onConditionalTextboxInput, false);
this._cbTextbox.addEventListener("keypress", this._onConditionalTextboxKeyPress, false);
this.autoFocusOnSelection = false;
// Show an empty label by default.
this.empty();
},

Просмотреть файл

@ -348,10 +348,9 @@ function StackFramesView() {
this._framesCache = new Map(); // Can't use a WeakMap because keys are numbers.
this._onStackframeRemoved = this._onStackframeRemoved.bind(this);
this._onClick = this._onClick.bind(this);
this._onSelect = this._onSelect.bind(this);
this._onScroll = this._onScroll.bind(this);
this._afterScroll = this._afterScroll.bind(this);
this._selectFrame = this._selectFrame.bind(this);
}
create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
@ -370,9 +369,12 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
document.getElementById("debuggerCommands").appendChild(commandset);
this.node = new BreadcrumbsWidget(document.getElementById("stackframes"));
this.node.addEventListener("mousedown", this._onClick, false);
this.node.addEventListener("select", this._onSelect, false);
this.node.addEventListener("scroll", this._onScroll, true);
window.addEventListener("resize", this._onScroll, true);
this.autoFocusOnFirstItem = false;
this.autoFocusOnSelection = false;
},
/**
@ -381,7 +383,7 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
destroy: function() {
dumpn("Destroying the StackFramesView");
this.node.removeEventListener("mousedown", this._onClick, false);
this.node.removeEventListener("select", this._onSelect, false);
this.node.removeEventListener("scroll", this._onScroll, true);
window.removeEventListener("resize", this._onScroll, true);
},
@ -423,21 +425,11 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
},
/**
* Highlights a frame in this stackframes container.
*
* Selects the frame at the specified depth in this container.
* @param number aDepth
* The frame depth specified by the debugger controller.
*/
highlightFrame: function(aDepth) {
let selectedItem = this.selectedItem = this._framesCache.get(aDepth);
for (let item in this) {
if (item != selectedItem) {
item.attachment.popup.menuitem.removeAttribute("checked");
} else {
item.attachment.popup.menuitem.setAttribute("checked", "");
}
}
set selectedDepth(aDepth) {
this.selectedItem = this._framesCache.get(aDepth);
},
/**
@ -511,7 +503,7 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
let command = document.createElement("command");
command.id = commandId;
command.addEventListener("command", this._selectFrame.bind(this, aDepth), false);
command.addEventListener("command", () => this.selectedDepth = aDepth, false);
let menuitem = document.createElement("menuitem");
menuitem.id = menuitemId;
@ -572,17 +564,21 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
},
/**
* The click listener for the stackframes container.
* The select listener for the stackframes container.
*/
_onClick: function(e) {
if (e && e.button != 0) {
// Only allow left-click to trigger this event.
return;
}
let item = this.getItemForElement(e.target);
if (item) {
// The container is not empty and we clicked on an actual item.
this._selectFrame(item.attachment.depth);
_onSelect: function(e) {
let stackframeItem = this.selectedItem;
if (stackframeItem) {
// The container is not empty and an actual item was selected.
gStackFrames.selectFrame(stackframeItem.attachment.depth);
for (let otherItem in this) {
if (otherItem != stackframeItem) {
otherItem.attachment.popup.menuitem.removeAttribute("checked");
} else {
otherItem.attachment.popup.menuitem.setAttribute("checked", "");
}
}
}
},
@ -617,16 +613,6 @@ create({ constructor: StackFramesView, proto: MenuContainer.prototype }, {
}
},
/**
* Requests selection of a frame from the controller.
*
* @param number aDepth
* The depth of the frame in the stack.
*/
_selectFrame: function(aDepth) {
DebuggerController.StackFrames.selectFrame(aDepth);
},
_framesCache: null,
_commandset: null,
_menupopup: null,

Просмотреть файл

@ -354,9 +354,7 @@ let DebuggerView = {
}
// If the requested source exists, display it and update.
else if (this.Sources.containsValue(aUrl) && !aFlags.noSwitch) {
this.Sources.node.preventFocusOnSelection = true;
this.Sources.selectedValue = aUrl;
this.Sources.node.preventFocusOnSelection = false;
set(aLine);
}
// Dumb request, invalidate the caret position and debug location.

Просмотреть файл

@ -54,6 +54,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_reload-preferred-script.js \
browser_dbg_pane-collapse.js \
browser_dbg_panesize-inner.js \
browser_dbg_breadcrumbs-access.js \
browser_dbg_stack-01.js \
browser_dbg_stack-02.js \
browser_dbg_stack-03.js \

Просмотреть файл

@ -0,0 +1,154 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest()
{
let editor = gDebugger.DebuggerView.editor;
let sources = gDebugger.DebuggerView.Sources;
let stackframes = gDebugger.DebuggerView.StackFrames;
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (1).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (1).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (1).");
EventUtils.sendKey("DOWN", gDebugger);
is(editor.getCaretPosition().line, 6,
"The source editor caret position was incorrect (2).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (2).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (2).");
EventUtils.sendKey("UP", gDebugger);
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (3).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (3).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (3).");
EventUtils.sendMouseEvent({ type: "mousedown" },
stackframes.selectedItem.target,
gDebugger);
EventUtils.sendKey("UP", gDebugger);
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (4).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (4).");
is(stackframes.selectedIndex, 2,
"The currently selected stackframe is incorrect (4).");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(editor.getCaretPosition().line, 4,
"The source editor caret position was incorrect (5).");
is(sources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (5).");
is(stackframes.selectedIndex, 1,
"The currently selected stackframe is incorrect (5).");
EventUtils.sendKey("UP", gDebugger);
is(editor.getCaretPosition().line, 4,
"The source editor caret position was incorrect (6).");
is(sources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (6).");
is(stackframes.selectedIndex, 0,
"The currently selected stackframe is incorrect (6).");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (7).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (7).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (7).");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(editor.getCaretPosition().line, 4,
"The source editor caret position was incorrect (8).");
is(sources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (8).");
is(stackframes.selectedIndex, 0,
"The currently selected stackframe is incorrect (8).");
closeDebuggerAndFinish();
});
EventUtils.sendKey("HOME", gDebugger);
});
EventUtils.sendKey("END", gDebugger);
});
EventUtils.sendKey("UP", gDebugger);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});
}

Просмотреть файл

@ -530,6 +530,14 @@ let Prefs = new ViewHelpers.Prefs("devtools.netmonitor", {
networkDetailsHeight: ["Int", "panes-network-details-height"]
});
/**
* Returns true if this is document is in RTL mode.
* @return boolean
*/
XPCOMUtils.defineLazyGetter(window, "isRTL", function() {
return window.getComputedStyle(document.documentElement, null).direction == "rtl";
});
/**
* Convenient way of emitting events from the panel window.
*/

Просмотреть файл

@ -897,10 +897,11 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
let startCapNode = $(".requests-menu-timings-cap.start", target);
let endCapNode = $(".requests-menu-timings-cap.end", target);
let totalNode = $(".requests-menu-timings-total", target);
let direction = window.isRTL ? -1 : 1;
// Render the timing information at a specific horizontal translation
// based on the delta to the first monitored event network.
let translateX = "translateX(" + attachment.startedDeltaMillis + "px)";
let translateX = "translateX(" + (direction * attachment.startedDeltaMillis) + "px)";
// Based on the total time passed until the last request, rescale
// all the waterfalls to a reasonable size.
@ -911,8 +912,8 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
let revScaleX = "scaleX(" + (1 / scale) + ")";
timingsNode.style.transform = scaleX + " " + translateX;
startCapNode.style.transform = revScaleX + " translateX(0.5px)";
endCapNode.style.transform = revScaleX + " translateX(-0.5px)";
startCapNode.style.transform = revScaleX + " translateX(" + (direction * 0.5) + "px)";
endCapNode.style.transform = revScaleX + " translateX(" + (direction * -0.5) + "px)";
totalNode.style.transform = revScaleX;
}
},
@ -947,10 +948,11 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
// Insert one label for each division on the current scale.
let fragment = document.createDocumentFragment();
let direction = window.isRTL ? -1 : 1;
for (let x = 0; x < availableWidth; x += scaledStep) {
let divisionMS = (x / aScale).toFixed(0);
let translateX = "translateX(" + (x | 0) + "px)";
let translateX = "translateX(" + ((direction * x) | 0) + "px)";
let node = document.createElement("label");
let text = L10N.getFormatStr("networkMenu.divisionMS", divisionMS);
@ -1009,7 +1011,8 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
for (let i = 1; i <= REQUESTS_WATERFALL_BACKGROUND_TICKS_SCALES; i++) {
let increment = scaledStep * Math.pow(2, i);
for (let x = 0; x < canvasWidth; x += increment) {
data32[x | 0] = (alphaComponent << 24) | (b << 16) | (g << 8) | r;
let position = (window.isRTL ? canvasWidth - x : x) | 0;
data32[position] = (alphaComponent << 24) | (b << 16) | (g << 8) | r;
}
alphaComponent += REQUESTS_WATERFALL_BACKGROUND_TICKS_OPACITY_ADD;
}
@ -1035,6 +1038,9 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
* Hides the overflowing columns in the requests table.
*/
_hideOverflowingColumns: function() {
if (window.isRTL) {
return;
}
let table = $("#network-table");
let toolbar = $("#requests-menu-toolbar");
let columns = [
@ -1202,7 +1208,11 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
let waterfall = $("#requests-menu-waterfall-header-box");
let containerBounds = container.getBoundingClientRect();
let waterfallBounds = waterfall.getBoundingClientRect();
this._cachedWaterfallWidth = containerBounds.width - waterfallBounds.left;
if (!window.isRTL) {
this._cachedWaterfallWidth = containerBounds.width - waterfallBounds.left;
} else {
this._cachedWaterfallWidth = waterfallBounds.right;
}
}
return this._cachedWaterfallWidth;
},

Просмотреть файл

@ -3,6 +3,10 @@
* 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/. */
#toolbar-labels {
overflow: hidden;
}
#details-pane-toggle[disabled] {
visibility: hidden;
}

Просмотреть файл

@ -11,6 +11,7 @@ const Cu = Components.utils;
const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
this.EXPORTED_SYMBOLS = ["BreadcrumbsWidget"];
@ -45,6 +46,8 @@ this.BreadcrumbsWidget = function BreadcrumbsWidget(aNode) {
this._list.setAttribute("flex", "1");
this._list.setAttribute("orient", "horizontal");
this._list.setAttribute("clicktoscroll", "true")
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
this._parent.appendChild(this._list);
// By default, hide the arrows. We let the arrowscrollbox show them
@ -54,6 +57,9 @@ this.BreadcrumbsWidget = function BreadcrumbsWidget(aNode) {
this._list.addEventListener("underflow", this._onUnderflow.bind(this), false);
this._list.addEventListener("overflow", this._onOverflow.bind(this), false);
// This widget emits events that can be handled in a MenuContainer.
EventEmitter.decorate(this);
// Delegate some of the associated node's methods to satisfy the interface
// required by MenuContainer instances.
ViewHelpers.delegateWidgetAttributeMethods(this, aNode);

Просмотреть файл

@ -78,14 +78,6 @@ SideMenuWidget.prototype = {
*/
sortedGroups: true,
/**
* Specifies if when an item is selected in this container (via the
* selectedItem setter), that respective item should be focused as well.
* You can enable this flag, for example, to maintain a certain node
* selected but visually indicate a different selection in this container.
*/
preventFocusOnSelection: false,
/**
* Specifies if this container should try to keep the selected item visible.
* (For example, when new items are added the selection is brought into view).
@ -142,9 +134,6 @@ SideMenuWidget.prototype = {
if (this.maintainSelectionVisible) {
this.ensureSelectionIsVisible({ withGroup: true, delayed: true });
}
if (this._orderedMenuElementsArray.length == 1) {
this._list.focus();
}
if (maintainScrollAtBottom) {
this._list.scrollTop = this._list.scrollHeight;
}
@ -226,7 +215,6 @@ SideMenuWidget.prototype = {
node.classList.add("selected");
node.parentNode.classList.add("selected");
this._selectedItem = node;
!this.preventFocusOnSelection && node.focus();
} else {
node.classList.remove("selected");
node.parentNode.classList.remove("selected");

Просмотреть файл

@ -587,7 +587,7 @@ MenuContainer.prototype = {
/**
* Prepares an item to be added to this container. This allows for a large
* number of items to be batched up before alphabetically sorted and added.
* number of items to be batched up before being sorted and added.
*
* If the "staged" flag is not set to true, the item will be immediately
* inserted at the correct position in this container, so that all the items
@ -625,13 +625,13 @@ MenuContainer.prototype = {
// Batch the item to be added later.
if (aOptions.staged) {
// Commit operations will ignore any specified index.
// An ulterior commit operation will ignore any specified index.
delete aOptions.index;
return void this._stagedItems.push({ item: item, options: aOptions });
}
// Find the target position in this container and insert the item there.
if (!("index" in aOptions)) {
return this._insertItemAt(this._findExpectedIndex(item), item, aOptions);
return this._insertItemAt(this._findExpectedIndexFor(item), item, aOptions);
}
// Insert the item at the specified index. If negative or out of bounds,
// the item will be simply appended.
@ -669,14 +669,13 @@ MenuContainer.prototype = {
* True if a selected item was available, false otherwise.
*/
refresh: function() {
let selectedValue = this.selectedValue;
if (!selectedValue) {
let selectedItem = this.selectedItem;
if (!selectedItem) {
return false;
}
let entangledLabel = this.getItemByValue(selectedValue)._label;
this._container.removeAttribute("notice");
this._container.setAttribute("label", entangledLabel);
this._container.setAttribute("tooltiptext", selectedValue);
this._container.setAttribute("label", selectedItem._label);
this._container.setAttribute("tooltiptext", selectedItem._value);
return true;
},
@ -946,7 +945,13 @@ MenuContainer.prototype = {
let targetElement = aItem ? aItem._target : null;
let prevElement = this._container.selectedItem;
// Prevent selecting the same item again, so return early.
// Make sure the currently selected item's target element is also focused.
if (this.autoFocusOnSelection && targetElement) {
targetElement.focus();
}
// Prevent selecting the same item again and avoid dispatching
// a redundant selection event, so return early.
if (targetElement == prevElement) {
return;
}
@ -981,6 +986,42 @@ MenuContainer.prototype = {
set selectedValue(aValue)
this.selectedItem = this._itemsByValue.get(aValue),
/**
* Focus this container the first time an element is inserted?
*
* If this flag is set to true, then when the first item is inserted in
* this container (and thus it's the only item available), its corresponding
* target element is focused as well.
*/
autoFocusOnFirstItem: true,
/**
* Focus on selection?
*
* If this flag is set to true, then whenever an item is selected in
* this container (e.g. via the selectedIndex or selectedItem setters),
* its corresponding target element is focused as well.
*
* You can disable this flag, for example, to maintain a certain node
* focused but visually indicate a different selection in this container.
*/
autoFocusOnSelection: true,
/**
* Focus on input (e.g. mouse click)?
*
* If this flag is set to true, then whenever an item receives user input in
* this container, its corresponding target element is focused as well.
*/
autoFocusOnInput: true,
/**
* The number of elements in this container to jump when Page Up or Page Down
* keys are pressed. If falsy, then the page size will be based on the
* number of visible items in the container.
*/
pageSize: 0,
/**
* Focuses the first visible item in this container.
*/
@ -1323,7 +1364,7 @@ MenuContainer.prototype = {
* @return number
* The expected item index.
*/
_findExpectedIndex: function(aItem) {
_findExpectedIndexFor: function(aItem) {
let itemCount = this.itemCount;
for (let i = 0; i < itemCount; i++) {
@ -1367,6 +1408,9 @@ MenuContainer.prototype = {
if (!this._currentFilterPredicate(aItem)) {
aItem._target.hidden = true;
}
if (this.autoFocusOnFirstItem && this._itemsByElement.size == 1) {
aItem._target.focus();
}
if (aOptions.attributes) {
aItem.setAttributes(aOptions.attributes, aItem._target);
}
@ -1424,13 +1468,6 @@ MenuContainer.prototype = {
this._itemsByElement.delete(aItem._target);
},
/**
* The number of elements in this container to jump when Page Up or Page Down
* keys are pressed. If falsy, then the page size will be based on the
* number of visible items in the container.
*/
pageSize: 0,
/**
* The keyPress event listener for this container.
* @param string aName
@ -1442,9 +1479,11 @@ MenuContainer.prototype = {
switch (aEvent.keyCode) {
case aEvent.DOM_VK_UP:
case aEvent.DOM_VK_LEFT:
this.focusPrevItem();
return;
case aEvent.DOM_VK_DOWN:
case aEvent.DOM_VK_RIGHT:
this.focusNextItem();
return;
case aEvent.DOM_VK_PAGE_UP:
@ -1472,10 +1511,13 @@ MenuContainer.prototype = {
// Only allow left-click to trigger this event.
return;
}
let item = this.getItemForElement(aEvent.target);
if (item) {
// The container is not empty and we clicked on an actual item.
this.selectedItem = item;
// Make sure the current event's target element is also focused.
this.autoFocusOnInput && item._target.focus();
}
},

Просмотреть файл

@ -9,6 +9,10 @@
direction: ltr;
}
.breadcrumbs-widget-item {
-moz-user-focus: normal;
}
/* SideMenuWidget */
.side-menu-widget-container {

Просмотреть файл

@ -1192,14 +1192,34 @@ WebConsoleFrame.prototype = {
severity = SEVERITY_WARNING;
}
let objectActors = new Set();
// Gather the actor IDs.
for (let prop of ["errorMessage", "lineText"]) {
let grip = aScriptError[prop];
if (WebConsoleUtils.isActorGrip(grip)) {
objectActors.add(grip.actor);
}
}
let errorMessage = aScriptError.errorMessage;
if (errorMessage.type && errorMessage.type == "longString") {
errorMessage = errorMessage.initial;
}
let node = this.createMessageNode(aCategory, severity,
aScriptError.errorMessage,
errorMessage,
aScriptError.sourceName,
aScriptError.lineNumber, null, null,
aScriptError.timeStamp);
if (aScriptError.private) {
node.setAttribute("private", true);
}
if (objectActors.size > 0) {
node._objectActors = objectActors;
}
return node;
},
@ -1225,10 +1245,32 @@ WebConsoleFrame.prototype = {
*/
handleLogMessage: function WCF_handleLogMessage(aPacket)
{
this.outputMessage(CATEGORY_JS, () => {
return this.createMessageNode(CATEGORY_JS, SEVERITY_LOG, aPacket.message,
null, null, null, null, aPacket.timeStamp);
});
if (aPacket.message) {
this.outputMessage(CATEGORY_JS, this._reportLogMessage, [aPacket]);
}
},
/**
* Display log messages received from the server.
*
* @private
* @param object aPacket
* The message packet received from the server.
* @return nsIDOMElement
* The message element to render for the given log message.
*/
_reportLogMessage: function WCF__reportLogMessage(aPacket)
{
let msg = aPacket.message;
if (msg.type && msg.type == "longString") {
msg = msg.initial;
}
let node = this.createMessageNode(CATEGORY_JS, SEVERITY_LOG, msg, null,
null, null, null, aPacket.timeStamp);
if (WebConsoleUtils.isActorGrip(aPacket.message)) {
node._objectActors = new Set([aPacket.message.actor]);
}
return node;
},
/**
@ -1992,6 +2034,22 @@ WebConsoleFrame.prototype = {
}
});
}
else if (category == CATEGORY_JS &&
methodOrNode == this.reportPageError) {
let pageError = args[1];
for (let prop of ["errorMessage", "lineText"]) {
let grip = pageError[prop];
if (WebConsoleUtils.isActorGrip(grip)) {
this._releaseObject(grip.actor);
}
}
}
else if (category == CATEGORY_JS &&
methodOrNode == this._reportLogMessage) {
if (WebConsoleUtils.isActorGrip(args[0].message)) {
this._releaseObject(args[0].message.actor);
}
}
},
/**

Просмотреть файл

@ -40,6 +40,9 @@ var FindHandler = {
return;
}
if (!this._fastFind.currentWindow)
return;
let selection = this._fastFind.currentWindow.getSelection();
if (!selection.rangeCount || selection.isCollapsed) {
// The selection can be into an input or a textarea element

Просмотреть файл

@ -3,6 +3,10 @@
* 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/. */
/* We don't support zooming yet, disable Animated zoom by clamping it to the default zoom. */
const kBrowserFindZoomLevelMin = 1;
const kBrowserFindZoomLevelMax = 1;
var FindHelperUI = {
type: "find",
commands: {
@ -175,8 +179,8 @@ var FindHelperUI = {
// Clamp the zoom level relatively to the default zoom level of the page
let defaultZoomLevel = Browser.selectedTab.getDefaultZoomLevel();
zoomLevel = Util.clamp(zoomLevel, (defaultZoomLevel * kBrowserFormZoomLevelMin),
(defaultZoomLevel * kBrowserFormZoomLevelMax));
zoomLevel = Util.clamp(zoomLevel, (defaultZoomLevel * kBrowserFindZoomLevelMin),
(defaultZoomLevel * kBrowserFindZoomLevelMax));
zoomLevel = Browser.selectedTab.clampZoomLevel(zoomLevel);
let zoomRect = Browser._getZoomRectForPoint(aElementRect.center().x, aElementRect.y, zoomLevel);

Просмотреть файл

@ -8,9 +8,6 @@
* - Provides autocomplete box for input fields.
*/
const kBrowserFormZoomLevelMin = 0.8;
const kBrowserFormZoomLevelMax = 2.0;
var FormHelperUI = {
_debugEvents: false,
_currentBrowser: null,

Двоичные данные
browser/themes/linux/devtools/arrows.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 804 B

Просмотреть файл

@ -29,12 +29,18 @@
padding: 4px;
}
.requests-menu-header:not(:last-child),
.requests-menu-subitem:not(:last-child) {
.requests-menu-header:not(:last-child):-moz-locale-dir(ltr),
.requests-menu-subitem:not(:last-child):-moz-locale-dir(ltr) {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
}
.requests-menu-header:not(:last-child):-moz-locale-dir(rtl),
.requests-menu-subitem:not(:last-child):-moz-locale-dir(rtl) {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
box-shadow: -1px 0 0 hsla(210,16%,76%,.1);
}
.requests-menu-header-button {
-moz-appearance: none;
background: none;
@ -171,7 +177,6 @@ box.requests-menu-status[code^="5"] {
-moz-padding-start: 4px;
-moz-border-start: 1px dotted #999;
font-size: 75%;
text-align: left;
pointer-events: none;
}
@ -179,6 +184,14 @@ box.requests-menu-status[code^="5"] {
-moz-margin-start: -100px !important; /* Don't affect layout. */
}
.requests-menu-timings-division:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings-division:-moz-locale-dir(rtl) {
transform-origin: right center;
}
/* Network requests table: waterfall items */
.requests-menu-subitem.requests-menu-waterfall {
@ -189,15 +202,30 @@ box.requests-menu-status[code^="5"] {
margin-bottom: -1px;
}
.requests-menu-timings {
.requests-menu-subitem.requests-menu-waterfall:-moz-locale-dir(rtl) {
background-position: right center;
}
.requests-menu-timings:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings:-moz-locale-dir(rtl) {
transform-origin: right center;
}
.requests-menu-timings-total:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings-total:-moz-locale-dir(rtl) {
transform-origin: right center;
}
.requests-menu-timings-total {
-moz-padding-start: 8px;
font-size: 85%;
font-weight: 600;
transform-origin: left center;
}
.requests-menu-timings-cap {
@ -208,16 +236,32 @@ box.requests-menu-status[code^="5"] {
.requests-menu-timings-cap.start {
-moz-border-end: none;
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.end {
-moz-border-start: none;
}
.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-box {
height: 10px;
border-top: 1px solid #fff;

Просмотреть файл

@ -123,7 +123,6 @@ browser.jar:
* skin/classic/browser/devtools/common.css (devtools/common.css)
skin/classic/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)

Двоичные данные
browser/themes/osx/devtools/arrows.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 804 B

Просмотреть файл

@ -29,12 +29,18 @@
padding: 4px;
}
.requests-menu-header:not(:last-child),
.requests-menu-subitem:not(:last-child) {
.requests-menu-header:not(:last-child):-moz-locale-dir(ltr),
.requests-menu-subitem:not(:last-child):-moz-locale-dir(ltr) {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
}
.requests-menu-header:not(:last-child):-moz-locale-dir(rtl),
.requests-menu-subitem:not(:last-child):-moz-locale-dir(rtl) {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
box-shadow: -1px 0 0 hsla(210,16%,76%,.1);
}
.requests-menu-header-button {
-moz-appearance: none;
background: none;
@ -171,7 +177,6 @@ box.requests-menu-status[code^="5"] {
-moz-padding-start: 4px;
-moz-border-start: 1px dotted #999;
font-size: 75%;
text-align: left;
pointer-events: none;
}
@ -179,6 +184,14 @@ box.requests-menu-status[code^="5"] {
-moz-margin-start: -100px !important; /* Don't affect layout. */
}
.requests-menu-timings-division:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings-division:-moz-locale-dir(rtl) {
transform-origin: right center;
}
/* Network requests table: waterfall items */
.requests-menu-subitem.requests-menu-waterfall {
@ -189,15 +202,30 @@ box.requests-menu-status[code^="5"] {
margin-bottom: -1px;
}
.requests-menu-timings {
.requests-menu-subitem.requests-menu-waterfall:-moz-locale-dir(rtl) {
background-position: right center;
}
.requests-menu-timings:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings:-moz-locale-dir(rtl) {
transform-origin: right center;
}
.requests-menu-timings-total:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings-total:-moz-locale-dir(rtl) {
transform-origin: right center;
}
.requests-menu-timings-total {
-moz-padding-start: 8px;
font-size: 85%;
font-weight: 600;
transform-origin: left center;
}
.requests-menu-timings-cap {
@ -208,16 +236,32 @@ box.requests-menu-status[code^="5"] {
.requests-menu-timings-cap.start {
-moz-border-end: none;
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.end {
-moz-border-start: none;
}
.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-box {
height: 10px;
border-top: 1px solid #fff;

Просмотреть файл

@ -212,7 +212,6 @@ browser.jar:
skin/classic/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)

Двоичные данные
browser/themes/windows/devtools/arrows.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 804 B

Просмотреть файл

@ -29,12 +29,18 @@
padding: 4px;
}
.requests-menu-header:not(:last-child),
.requests-menu-subitem:not(:last-child) {
.requests-menu-header:not(:last-child):-moz-locale-dir(ltr),
.requests-menu-subitem:not(:last-child):-moz-locale-dir(ltr) {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
}
.requests-menu-header:not(:last-child):-moz-locale-dir(rtl),
.requests-menu-subitem:not(:last-child):-moz-locale-dir(rtl) {
-moz-border-end: 1px solid hsla(210,8%,5%,.25);
box-shadow: -1px 0 0 hsla(210,16%,76%,.1);
}
.requests-menu-header-button {
-moz-appearance: none;
background: none;
@ -171,7 +177,6 @@ box.requests-menu-status[code^="5"] {
-moz-padding-start: 4px;
-moz-border-start: 1px dotted #999;
font-size: 90%;
text-align: left;
pointer-events: none;
}
@ -179,6 +184,14 @@ box.requests-menu-status[code^="5"] {
-moz-margin-start: -100px !important; /* Don't affect layout. */
}
.requests-menu-timings-division:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings-division:-moz-locale-dir(rtl) {
transform-origin: right center;
}
/* Network requests table: waterfall items */
.requests-menu-subitem.requests-menu-waterfall {
@ -189,15 +202,30 @@ box.requests-menu-status[code^="5"] {
margin-bottom: -1px;
}
.requests-menu-timings {
.requests-menu-subitem.requests-menu-waterfall:-moz-locale-dir(rtl) {
background-position: right center;
}
.requests-menu-timings:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings:-moz-locale-dir(rtl) {
transform-origin: right center;
}
.requests-menu-timings-total:-moz-locale-dir(ltr) {
transform-origin: left center;
}
.requests-menu-timings-total:-moz-locale-dir(rtl) {
transform-origin: right center;
}
.requests-menu-timings-total {
-moz-padding-start: 8px;
font-size: 85%;
font-weight: 600;
transform-origin: left center;
}
.requests-menu-timings-cap {
@ -208,16 +236,32 @@ box.requests-menu-status[code^="5"] {
.requests-menu-timings-cap.start {
-moz-border-end: none;
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.end {
-moz-border-start: none;
}
.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-box {
height: 10px;
border-top: 1px solid #fff;

Просмотреть файл

@ -150,7 +150,6 @@ browser.jar:
skin/classic/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
@ -403,7 +402,6 @@ browser.jar:
skin/classic/aero/browser/devtools/dark-theme.css (devtools/dark-theme.css)
skin/classic/aero/browser/devtools/light-theme.css (devtools/light-theme.css)
skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/aero/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/aero/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/aero/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/aero/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)

Просмотреть файл

@ -318,6 +318,15 @@ nsFrameLoader::LoadFrame()
src.Trim(" \t\n\r");
if (src.IsEmpty()) {
// If the frame is a XUL element and has the attribute 'nodefaultsrc=true'
// then we will not use 'about:blank' as fallback but return early without
// starting a load if no 'src' attribute is given (or it's empty).
if (mOwnerContent->IsXUL() &&
mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::nodefaultsrc,
nsGkAtoms::_true, eCaseMatters)) {
return NS_OK;
}
src.AssignLiteral("about:blank");
}

Просмотреть файл

@ -607,6 +607,7 @@ GK_ATOM(no, "no")
GK_ATOM(noautohide, "noautohide")
GK_ATOM(nobr, "nobr")
GK_ATOM(node, "node")
GK_ATOM(nodefaultsrc, "nodefaultsrc")
GK_ATOM(nodeSet, "node-set")
GK_ATOM(noembed, "noembed")
GK_ATOM(noframes, "noframes")

Просмотреть файл

@ -662,6 +662,11 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
gravitateEnd = true;
}
if (!mEnableGravitationOnElementRemoval) {
// Do not gravitate.
return;
}
if (gravitateStart || gravitateEnd) {
DoSetRange(gravitateStart ? container : mStartParent.get(),
gravitateStart ? aIndexInContainer : mStartOffset,

Просмотреть файл

@ -48,6 +48,7 @@ public:
, mInSelection(false)
, mStartOffsetWasIncremented(false)
, mEndOffsetWasIncremented(false)
, mEnableGravitationOnElementRemoval(true)
#ifdef DEBUG
, mAssertNextInsertOrAppendIndex(-1)
, mAssertNextInsertOrAppendNode(nullptr)
@ -72,6 +73,20 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
/**
* The DOM Range spec requires that when a node is removed from its parent,
* and the node's subtree contains the start or end point of a range, that
* start or end point is moved up to where the node was removed from its
* parent.
* For some internal uses of Ranges it's useful to disable that behavior,
* so that a range of children within a single parent is preserved even if
* that parent is removed from the document tree.
*/
void SetEnableGravitationOnElementRemoval(bool aEnable)
{
mEnableGravitationOnElementRemoval = aEnable;
}
// nsIDOMRange interface
NS_DECL_NSIDOMRANGE
@ -299,6 +314,7 @@ protected:
bool mInSelection;
bool mStartOffsetWasIncremented;
bool mEndOffsetWasIncremented;
bool mEnableGravitationOnElementRemoval;
#ifdef DEBUG
int32_t mAssertNextInsertOrAppendIndex;
nsINode* mAssertNextInsertOrAppendNode;

Просмотреть файл

@ -621,6 +621,7 @@ WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f, uint32_t aFl
if (surf->CairoStatus() != 0)
return NS_ERROR_FAILURE;
gl->MakeCurrent();
gl->ReadScreenIntoImageSurface(surf);
bool srcPremultAlpha = mOptions.premultipliedAlpha;

Просмотреть файл

@ -44,6 +44,7 @@ class MediaDecoder;
}
class nsITimer;
class nsRange;
namespace mozilla {
namespace dom {
@ -882,7 +883,7 @@ protected:
// Points to the child source elements, used to iterate through the children
// when selecting a resource to load.
nsCOMPtr<nsIDOMRange> mSourcePointer;
nsRefPtr<nsRange> mSourcePointer;
// Points to the document whose load we're blocking. This is the document
// we're bound to when loading starts.

Просмотреть файл

@ -3359,6 +3359,9 @@ nsIContent* HTMLMediaElement::GetNextSource()
if (!mSourcePointer) {
// First time this has been run, create a selection to cover children.
mSourcePointer = new nsRange(this);
// If this media element is removed from the DOM, don't gravitate the
// range up to its ancestor, leave it attached to the media element.
mSourcePointer->SetEnableGravitationOnElementRemoval(false);
rv = mSourcePointer->SelectNodeContents(thisDomNode);
if (NS_FAILED(rv)) return nullptr;

Просмотреть файл

@ -113,12 +113,12 @@ AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
if (aIsOnTheLeft) {
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
*aOutputL++ = *aInputL++ + *aInputR++ * aGainL;
*aOutputL++ = *aInputL++ + *aInputR * aGainL;
*aOutputR++ = *aInputR++ * aGainR;
}
} else {
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
*aOutputL++ = *aInputL++ * aGainL;
*aOutputL++ = *aInputL * aGainL;
*aOutputR++ = *aInputR++ + *aInputL++ * aGainR;
}
}

Просмотреть файл

@ -12,6 +12,15 @@
namespace MPAPI {
struct VideoPlane {
VideoPlane() :
mData(nullptr),
mStride(0),
mWidth(0),
mHeight(0),
mOffset(0),
mSkip(0)
{}
void *mData;
int32_t mStride;
int32_t mWidth;
@ -34,6 +43,17 @@ struct VideoFrame {
VideoPlane Cr;
nsRefPtr<mozilla::layers::GraphicBufferLocked> mGraphicBuffer;
VideoFrame() :
mTimeUs(0),
mKeyFrame(false),
mShouldSkip(false),
mData(nullptr),
mSize(0),
mStride(0),
mSliceHeight(0),
mRotation(0)
{}
void Set(int64_t aTimeUs, bool aKeyFrame,
void *aData, size_t aSize, int32_t aStride, int32_t aSliceHeight, int32_t aRotation,
void *aYData, int32_t aYStride, int32_t aYWidth, int32_t aYHeight, int32_t aYOffset, int32_t aYSkip,

Просмотреть файл

@ -140,6 +140,11 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
return false;
}
// Ignore empty buffer which stagefright media read will sporadically return
if (frame.mSize == 0 && !frame.mGraphicBuffer) {
return true;
}
parsed++;
if (frame.mShouldSkip && mSkipCount < MAX_DROPPED_FRAMES) {
mSkipCount++;

Просмотреть файл

@ -561,11 +561,15 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
mIsVideoSeeking = false;
ReleaseAllPendingVideoBuffersLocked();
}
aDoSeek = false;
} else {
err = mVideoSource->read(&mVideoBuffer);
}
if (err == OK && mVideoBuffer->range_length() > 0) {
aFrame->mSize = 0;
if (err == OK) {
int64_t timeUs;
int32_t unreadable;
int32_t keyFrame;
@ -602,7 +606,7 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
aFrame->mKeyFrame = keyFrame;
aFrame->Y.mWidth = mVideoWidth;
aFrame->Y.mHeight = mVideoHeight;
} else {
} else if (mVideoBuffer->range_length() > 0) {
char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
size_t length = mVideoBuffer->range_length();
@ -618,7 +622,6 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
if (aKeyframeSkip && timeUs < aTimeUs) {
aFrame->mShouldSkip = true;
}
}
else if (err == INFO_FORMAT_CHANGED) {
// If the format changed, update our cached info.
@ -631,12 +634,14 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
else if (err == ERROR_END_OF_STREAM) {
return false;
}
else if (err == UNKNOWN_ERROR) {
// This sometimes is used to mean "out of memory", but regardless,
// don't keep trying to decode if the decoder doesn't want to.
return false;
else if (err == -ETIMEDOUT) {
LOG(PR_LOG_DEBUG, "OmxDecoder::ReadVideo timed out, will retry");
return true;
}
else if (err != OK && err != -ETIMEDOUT) {
else {
// UNKNOWN_ERROR is sometimes is used to mean "out of memory", but
// regardless, don't keep trying to decode if the decoder doesn't want to.
LOG(PR_LOG_DEBUG, "OmxDecoder::ReadVideo failed, err=%d", err);
return false;
}
@ -664,6 +669,7 @@ bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
mAudioMetadataRead = false;
aSeekTimeUs = -1;
aFrame->mSize = 0;
if (err == OK && mAudioBuffer && mAudioBuffer->range_length() != 0) {
int64_t timeUs;
@ -689,10 +695,12 @@ bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
return false;
}
}
else if (err == UNKNOWN_ERROR) {
return false;
else if (err == -ETIMEDOUT) {
LOG(PR_LOG_DEBUG, "OmxDecoder::ReadAudio timed out, will retry");
return true;
}
else if (err != OK && err != -ETIMEDOUT) {
else if (err != OK) {
LOG(PR_LOG_DEBUG, "OmxDecoder::ReadAudio failed, err=%d", err);
return false;
}

Просмотреть файл

@ -26,6 +26,15 @@ public:
};
struct VideoPlane {
VideoPlane() :
mData(0),
mStride(0),
mWidth(0),
mHeight(0),
mOffset(0),
mSkip(0)
{}
void *mData;
int32_t mStride;
int32_t mWidth;
@ -46,6 +55,16 @@ struct VideoFrame {
VideoPlane Cb;
VideoPlane Cr;
VideoFrame() :
mTimeUs(0),
mKeyFrame(false),
mData(0),
mSize(0),
mStride(0),
mSliceHeight(0),
mRotation(0)
{}
void Set(int64_t aTimeUs, bool aKeyFrame,
void *aData, size_t aSize, int32_t aStride, int32_t aSliceHeight, int32_t aRotation,
void *aYData, int32_t aYStride, int32_t aYWidth, int32_t aYHeight, int32_t aYOffset, int32_t aYSkip,

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<body onload="doTest()">
<base href="../unknown">
<div id="test3"></div>
<video id="test4"><source src="white.webm"></video>
<script>
function doTest() {
test3.appendChild(test4);
}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,9 @@
<script>
try { o1 = new window.AudioContext(3, 2, 44100); } catch(e) { }
try { o6 = o1.createBufferSource(); } catch(e) { }
try { o15 = o1.createAnalyser(); } catch(e) { }
try { o15.fftSize = 32; } catch(e) { }
try { o6.connect(o15,0,0) } catch(e) { }
try { o27 = o1.createPanner(); } catch(e) { }
try { o6.buffer = function(){var buffer = o1.createBuffer(2, 1148, o1.sampleRate);for(var c=0; c<2; c++) {for(var i=0; i<1148; i++) {buffer.getChannelData(c)[i] = 0;}}return buffer;}() } catch(e) { }
</script>

Просмотреть файл

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html class="reftest-wait">
<script>
var Context0= new window.OfflineAudioContext(15,12119,44100)
var BufferSource1=Context0.createBufferSource();
var Gain0=Context0.createGain();
var Panner0=Context0.createPanner();
Context0.listener.setPosition(29,135,158);
BufferSource1.connect(Gain0);
BufferSource1.buffer=function(){
var channels=3;
var length=53325;
var Buffer=Context0.createBuffer(channels,length,Context0.sampleRate);
for(var y=0;y<channels;y++){
var bufferData= Buffer.getChannelData(y);
for (var i = 0; i < length; ++i) {
bufferData[i] = i*(270);
}
};
return Buffer;
}();
Gain0.connect(Panner0);
Panner0.panningModel=0;
setTimeout(function(){
document.documentElement.removeAttribute("class");
},500)
</script>

Просмотреть файл

@ -15,6 +15,7 @@ skip-if(Android||B2G) load 789075-1.html # load failed, bug 833371 for B2G
load 844563.html
load 846612.html
load 852838.html
load 865537-1.html
load 868504.html
load 874869.html
load 874915.html
@ -37,3 +38,5 @@ load 878328.html
load 878407.html
load 878478.html
load 877527.html
load 880129.html
skip-if(B2G) load 880202.html # load failed, bug 833371 for B2G

Просмотреть файл

@ -9,6 +9,7 @@
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "mozilla/Mutex.h"
#include "mozilla/PodOperations.h"
#include "kiss_fft/kiss_fftr.h"
namespace mozilla {
@ -275,12 +276,17 @@ AnalyserNode::AppendChunk(const AudioChunk& aChunk)
{
const uint32_t bufferSize = mBuffer.Length();
const uint32_t channelCount = aChunk.mChannelData.Length();
const uint32_t chunkCount = aChunk.mDuration;
uint32_t chunkDuration = aChunk.mDuration;
MOZ_ASSERT((bufferSize & (bufferSize - 1)) == 0); // Must be a power of two!
MOZ_ASSERT(channelCount > 0);
MOZ_ASSERT(chunkCount == WEBAUDIO_BLOCK_SIZE);
MOZ_ASSERT(chunkDuration == WEBAUDIO_BLOCK_SIZE);
memcpy(mBuffer.Elements() + mWriteIndex, aChunk.mChannelData[0], sizeof(float) * chunkCount);
if (chunkDuration > bufferSize) {
// Copy a maximum bufferSize samples.
chunkDuration = bufferSize;
}
PodCopy(mBuffer.Elements() + mWriteIndex, static_cast<const float*>(aChunk.mChannelData[0]), chunkDuration);
for (uint32_t i = 1; i < channelCount; ++i) {
AudioBlockAddChannelWithScale(static_cast<const float*>(aChunk.mChannelData[i]), 1.0f,
mBuffer.Elements() + mWriteIndex);
@ -289,7 +295,7 @@ AnalyserNode::AppendChunk(const AudioChunk& aChunk)
AudioBlockInPlaceScale(mBuffer.Elements() + mWriteIndex, 1,
1.0f / aChunk.mChannelData.Length());
}
mWriteIndex += chunkCount;
mWriteIndex += chunkDuration;
MOZ_ASSERT(mWriteIndex <= bufferSize);
if (mWriteIndex >= bufferSize) {
mWriteIndex = 0;

Просмотреть файл

@ -1457,9 +1457,11 @@ nsGlobalWindow::FreeInnerObjects()
// Kill all of the workers for this window.
// We push a cx so that exceptions get reported in the right DOM Window.
nsIScriptContext *scx = GetContextInternal();
AutoPushJSContext cx(scx ? scx->GetNativeContext() : nsContentUtils::GetSafeJSContext());
mozilla::dom::workers::CancelWorkersForWindow(cx, this);
{
nsIScriptContext *scx = GetContextInternal();
AutoPushJSContext cx(scx ? scx->GetNativeContext() : nsContentUtils::GetSafeJSContext());
mozilla::dom::workers::CancelWorkersForWindow(cx, this);
}
// Close all offline storages for this window.
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
@ -10939,10 +10941,12 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
DisableGamepadUpdates();
// Suspend all of the workers for this window.
// We push a cx so that exceptions get reported in the right DOM Window.
nsIScriptContext *scx = GetContextInternal();
AutoPushJSContext cx(scx ? scx->GetNativeContext() : nsContentUtils::GetSafeJSContext());
mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
// We push a cx so that exceptions get reported in the right DOM Window.
{
nsIScriptContext *scx = GetContextInternal();
AutoPushJSContext cx(scx ? scx->GetNativeContext() : nsContentUtils::GetSafeJSContext());
mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
}
TimeStamp now = TimeStamp::Now();
for (nsTimeout *t = mTimeouts.getFirst(); t; t = t->getNext()) {
@ -11034,7 +11038,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
// We push a cx so that exceptions get reported in the right DOM Window.
nsIScriptContext *scx = GetContextInternal();
AutoPushJSContext cx(scx ? scx->GetNativeContext() : nsContentUtils::GetSafeJSContext());
mozilla::dom::workers::ResumeWorkersForWindow(cx, this);
mozilla::dom::workers::ResumeWorkersForWindow(scx, this);
// Restore all of the timeouts, using the stored time remaining
// (stored in timeout->mTimeRemaining).

Просмотреть файл

@ -35,8 +35,8 @@ DefineStaticJSVals(JSContext* cx)
int HandlerFamily;
js::ListBaseShadowsResult
DOMListShadows(JSContext* cx, JSHandleObject proxy, JSHandleId id)
js::DOMProxyShadowsResult
DOMProxyShadows(JSContext* cx, JSHandleObject proxy, JSHandleId id)
{
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
if (v.isObject()) {
@ -59,15 +59,15 @@ DOMListShadows(JSContext* cx, JSHandleObject proxy, JSHandleId id)
}
// Store the information for the specialized ICs.
struct SetListBaseInformation
struct SetDOMProxyInformation
{
SetListBaseInformation() {
js::SetListBaseInformation((void*) &HandlerFamily,
js::JSSLOT_PROXY_EXTRA + JSPROXYSLOT_EXPANDO, DOMListShadows);
SetDOMProxyInformation() {
js::SetDOMProxyInformation((void*) &HandlerFamily,
js::JSSLOT_PROXY_EXTRA + JSPROXYSLOT_EXPANDO, DOMProxyShadow);
}
};
SetListBaseInformation gSetListBaseInformation;
SetDOMProxyInformation gSetDOMProxyInformation;
// static
JSObject*

Просмотреть файл

@ -765,10 +765,29 @@ RTCPeerConnection.prototype = {
sdp: sdp });
},
get signalingState() { return "stable"; }, // not yet implemented
get iceGatheringState() { return this._iceGatheringState; },
get iceConnectionState() { return this._iceConnectionState; },
// Corresponds to constants in IPeerConnection.idl
_signalingStateMap: [
'invalid',
'stable',
'have-local-offer',
'have-remote-offer',
'have-local-pranswer',
'have-remote-pranswer',
'closed'
],
get signalingState() {
// checking for our local pc closed indication
// before invoking the pc methods.
if(this._closed) {
return "closed";
}
return this._signalingStateMap[this._getPC().signalingState];
},
changeIceGatheringState: function(state) {
this._iceGatheringState = state;
},
@ -990,14 +1009,10 @@ PeerConnectionObserver.prototype = {
this._dompc._executeNext();
},
onStateChange: function(state) {
if (state != Ci.IPeerConnectionObserver.kIceState) {
return;
}
switch (this._dompc._pc.iceState) {
handleIceStateChanges: function(iceState) {
switch (iceState) {
case Ci.IPeerConnection.kIceWaiting:
this._dompc.changeIceConnectionState("completed");
this._dompc.changeIceConnectionState("new");
this.callCB(this._dompc.ongatheringchange, "complete");
this.callCB(this._onicechange, "starting");
// Now that the PC is ready to go, execute any pending operations.
@ -1021,7 +1036,33 @@ PeerConnectionObserver.prototype = {
this.callCB(this._onicechange, "failed");
break;
default:
// Unknown state!
// Unknown ICE state!
this._dompc.reportWarning("Unhandled ice state: " + iceState, null, 0);
break;
}
},
onStateChange: function(state) {
switch (state) {
case Ci.IPeerConnectionObserver.kSignalingState:
this.callCB(this._dompc.onsignalingstatechange,
this._dompc.signalingState);
break;
case Ci.IPeerConnectionObserver.kIceState:
this.handleIceStateChanges(this._dompc._pc.iceState);
break;
case Ci.IPeerConnectionObserver.kSdpState:
// No-op
break;
case Ci.IPeerConnectionObserver.kSipccState:
// No-op
break;
default:
this._dompc.reportWarning("Unhandled state type: " + state, null, 0);
break;
}
},

Просмотреть файл

@ -32,6 +32,7 @@ interface IPeerConnectionObserver : nsISupports
const long kIceState = 0x2;
const long kSdpState = 0x3;
const long kSipccState = 0x4;
const long kSignalingState = 0x5;
/* JSEP callbacks */
void onCreateOfferSuccess(in string offer);
@ -91,6 +92,15 @@ interface IPeerConnection : nsISupports
const long kClosing = 3;
const long kClosed = 4;
/* RTCSignalingState from WebRTC spec */
const long kSignalingInvalid = 0;
const long kSignalingStable = 1;
const long kSignalingHaveLocalOffer = 2;
const long kSignalingHaveRemoteOffer = 3;
const long kSignalingHaveLocalPranswer = 4;
const long kSignalingHaveRemotePranswer = 5;
const long kSignalingClosed = 6;
/* for 'type' in DataChannelInit dictionary */
const unsigned short kDataChannelReliable = 0;
const unsigned short kDataChannelPartialReliableRexmit = 1;
@ -144,6 +154,7 @@ interface IPeerConnection : nsISupports
readonly attribute unsigned long iceState;
readonly attribute unsigned long readyState;
readonly attribute unsigned long signalingState;
readonly attribute unsigned long sipccState;
/* Data channels */

Просмотреть файл

@ -35,6 +35,13 @@ MOCHITEST_FILES = \
test_peerConnection_offerRequiresReceiveVideo.html \
test_peerConnection_offerRequiresReceiveVideoAudio.html \
test_peerConnection_throwInCallbacks.html \
test_peerConnection_setLocalAnswerInStable.html \
test_peerConnection_setRemoteAnswerInStable.html \
test_peerConnection_setLocalAnswerInHaveLocalOffer.html \
test_peerConnection_setRemoteOfferInHaveLocalOffer.html \
test_peerConnection_setLocalOfferInHaveRemoteOffer.html \
test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html \
test_peerConnection_addCandidateInHaveLocalOffer.html \
test_peerConnection_bug822674.html \
test_peerConnection_bug825703.html \
test_peerConnection_bug827843.html \

Просмотреть файл

@ -182,11 +182,23 @@ function unexpectedCallbackAndFinish(error) {
return function(aObj) {
var where = error.fileName + ":" + error.lineNumber;
if (aObj && aObj.name && aObj.message) {
ok(false, "Unexpected error callback from " + where + " with name = '" +
ok(false, "Unexpected callback/event from " + where + " with name = '" +
aObj.name + "', message = '" + aObj.message + "'");
} else {
ok(false, "Unexpected error callback from " + where + " with " + aObj);
ok(false, "Unexpected callback/event from " + where + " with " + aObj);
}
SimpleTest.finish();
}
}
/**
* Generates a callback function suitable for putting int a success
* callback in circumstances where success is unexpected. The callback,
* if activated, will kill off the test gracefully.
*/
function unexpectedSuccessCallbackAndFinish(error, reason) {
return function() {
unexpectedCallbackAndFinish(error)(message);
}
}

Просмотреть файл

@ -246,10 +246,19 @@ var commandsPeerConnection = [
});
}
],
[
'PC_CHECK_INITIAL_SIGNALINGSTATE',
function (test) {
is(test.pcLocal.signalingState,"stable", "Initial local signalingState is stable");
is(test.pcRemote.signalingState,"stable", "Initial remote signalingState is stable");
test.next();
}
],
[
'PC_LOCAL_CREATE_OFFER',
function (test) {
test.pcLocal.createOffer(function () {
is(test.pcLocal.signalingState, "stable", "Local create offer does not change signaling state");
test.next();
});
}
@ -257,23 +266,24 @@ var commandsPeerConnection = [
[
'PC_LOCAL_SET_LOCAL_DESCRIPTION',
function (test) {
test.pcLocal.setLocalDescription(test.pcLocal._last_offer, function () {
test.next();
});
test.expectStateChange(test.pcLocal, "have-local-offer", test);
test.pcLocal.setLocalDescription(test.pcLocal._last_offer,
test.checkStateInCallback(test.pcLocal, "have-local-offer", test));
}
],
[
'PC_REMOTE_SET_REMOTE_DESCRIPTION',
function (test) {
test.pcRemote.setRemoteDescription(test.pcLocal._last_offer, function () {
test.next();
});
test.expectStateChange(test.pcRemote, "have-remote-offer", test);
test.pcRemote.setRemoteDescription(test.pcLocal._last_offer,
test.checkStateInCallback(test.pcRemote, "have-remote-offer", test));
}
],
[
'PC_REMOTE_CREATE_ANSWER',
function (test) {
test.pcRemote.createAnswer(function () {
is(test.pcRemote.signalingState, "have-remote-offer", "Remote create offer does not change signaling state");
test.next();
});
}
@ -281,17 +291,17 @@ var commandsPeerConnection = [
[
'PC_LOCAL_SET_REMOTE_DESCRIPTION',
function (test) {
test.pcLocal.setRemoteDescription(test.pcRemote._last_answer, function () {
test.next();
});
test.expectStateChange(test.pcLocal, "stable", test);
test.pcLocal.setRemoteDescription(test.pcRemote._last_answer,
test.checkStateInCallback(test.pcLocal, "stable", test));
}
],
[
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
function (test) {
test.pcRemote.setLocalDescription(test.pcRemote._last_answer, function () {
test.next();
});
test.expectStateChange(test.pcRemote, "stable", test);
test.pcRemote.setLocalDescription(test.pcRemote._last_answer,
test.checkStateInCallback(test.pcRemote, "stable", test));
}
],
[
@ -394,6 +404,64 @@ PeerConnectionTest.prototype.teardown = function PCT_teardown() {
SimpleTest.finish();
};
/**
* Sets up the "onsignalingstatechange" handler for the indicated peerconnection
* as a one-shot test. If the test.commandSuccess flag is set when the event
* happens, then the next test in the command chain is triggered. After
* running, this sets the event handler so that it will fail the test if
* it fires again before we expect it. This is intended to be used in
* conjunction with checkStateInCallback, below.
*
* @param {pcw} PeerConnectionWrapper
* The peer connection to expect a state change on
* @param {state} string
* The state that we expect to change to
* @param {test} PeerConnectionTest
* The test strucure currently in use.
*/
PeerConnectionTest.prototype.expectStateChange =
function PCT_expectStateChange(pcw, state, test) {
pcw.signalingChangeEvent = false;
pcw._pc.onsignalingstatechange = function() {
pcw._pc.onsignalingstatechange = unexpectedCallbackAndFinish(new Error);
is(pcw._pc.signalingState, state, pcw.label + ": State is " + state + " in onsignalingstatechange");
pcw.signalingChangeEvent = true;
if (pcw.commandSuccess) {
test.next();
} else {
info("Waiting for success callback...");
}
};
}
/**
* Returns a function, suitable for use as a success callback, that
* checks the signaling state of the PC; and, if the signalingstatechange
* event has already fired, moves on to the next test case. This is
* intended to be used in conjunction with expectStateChange, above.
*
* @param {pcw} PeerConnectionWrapper
* The peer connection to expect a state change on
* @param {state} string
* The state that we expect to change to
* @param {test} PeerConnectionTest
* The test strucure currently in use.
*/
PeerConnectionTest.prototype.checkStateInCallback =
function PCT_checkStateInCallback(pcw, state, test) {
pcw.commandSuccess = false;
return function() {
pcw.commandSuccess = true;
is(pcw.signalingState, state, pcw.label + ": State is " + state + " in success callback");
if (pcw.signalingChangeEvent) {
test.next();
} else {
info("Waiting for signalingstatechange event...");
}
};
}
/**
* This class handles acts as a wrapper around a PeerConnection instance.
@ -420,6 +488,9 @@ function PeerConnectionWrapper(label, configuration) {
// Bug 834835: Assume type is video until we get get{Audio,Video}Tracks.
self.attachMedia(event.stream, 'video', 'remote');
};
// Make sure no signaling state changes are fired until we expect them to
this._pc.onsignalingstatechange = unexpectedCallbackAndFinish(new Error);
}
PeerConnectionWrapper.prototype = {
@ -462,6 +533,15 @@ PeerConnectionWrapper.prototype = {
this._pc.remoteDescription = desc;
},
/**
* Returns the remote signaling state.
*
* @returns {object} The local description
*/
get signalingState() {
return this._pc.signalingState;
},
/**
* Callback when we get media from either side. Also an appropriate
* HTML media element will be created.
@ -571,6 +651,25 @@ PeerConnectionWrapper.prototype = {
}, unexpectedCallbackAndFinish(new Error));
},
/**
* Tries to set the local description and expect failure. Automatically
* causes the test case to fail if the call succeeds.
*
* @param {object} desc
* mozRTCSessionDescription for the local description request
* @param {function} onFailure
* Callback to execute if the call fails.
*/
setLocalDescriptionAndFail : function PCW_setLocalDescriptionAndFail(desc, onFailure) {
var self = this;
this._pc.setLocalDescription(desc,
unexpectedSuccessCallbackAndFinish(new Error, "setLocalDescription should have failed."),
function (err) {
info("As expected, failed to set the local description for " + self.label);
onFailure(err);
});
},
/**
* Sets the remote description and automatically handles the failure case.
*
@ -587,6 +686,62 @@ PeerConnectionWrapper.prototype = {
}, unexpectedCallbackAndFinish(new Error));
},
/**
* Tries to set the remote description and expect failure. Automatically
* causes the test case to fail if the call succeeds.
*
* @param {object} desc
* mozRTCSessionDescription for the remote description request
* @param {function} onFailure
* Callback to execute if the call fails.
*/
setRemoteDescriptionAndFail : function PCW_setRemoteDescriptionAndFail(desc, onFailure) {
var self = this;
this._pc.setRemoteDescription(desc,
unexpectedSuccessCallbackAndFinish(new Error, "setRemoteDescription should have failed."),
function (err) {
info("As expected, failed to set the remote description for " + self.label);
onFailure(err);
});
},
/**
* Adds an ICE candidate and automatically handles the failure case.
*
* @param {object} candidate
* SDP candidate
* @param {function} onSuccess
* Callback to execute if the local description was set successfully
*/
addIceCandidate : function PCW_addIceCandidate(candidate, onSuccess) {
var self = this;
this._pc.addIceCandidate(candidate, function () {
info("Successfully added an ICE candidate to " + self.label);
onSuccess();
}, unexpectedCallbackAndFinish(new Error));
},
/**
* Tries to add an ICE candidate and expects failure. Automatically
* causes the test case to fail if the call succeeds.
*
* @param {object} candidate
* SDP candidate
* @param {function} onFailure
* Callback to execute if the call fails.
*/
addIceCandidateAndFail : function PCW_addIceCandidateAndFail(candidate, onFailure) {
var self = this;
this._pc.addIceCandidate(candidate,
unexpectedSuccessCallbackAndFinish(new Error, "addIceCandidate should have failed."),
function (err) {
info("As expected, failed to add an ICE candidate to " + self.label);
onFailure(err);
}) ;
},
/**
* Checks that we are getting the media we expect.
*

Просмотреть файл

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "addCandidate (answer) in 'have-local-offer'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION");
test.chain.append([[
"PC_LOCAL_ADD_CANDIDATE",
function (test) {
test.pcLocal.addIceCandidateAndFail(
mozRTCIceCandidate(
{candidate:"1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMLineIndex: 1}),
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -54,7 +54,7 @@
{ url:"stun:0.0.0.0" },
{ url:"stuns:x.net", foo:"" },
{ url:"turn:[::192.9.5.5]:42", username:"p", credential:"p" },
{ url:"turns:x.org:42", username:"p", credential:"p" }
{ url:"turns:x.org:42?transport=udp", username:"p", credential:"p" }
]}, true);
pcs = null;

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "setLocalDescription (answer) in 'have-local-offer'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION");
test.chain.append([[
"PC_LOCAL_SET_LOCAL_ANSWER",
function (test) {
test.pcLocal._last_offer.type="answer";
test.pcLocal.setLocalDescriptionAndFail(test.pcLocal._last_offer,
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "setLocalDescription (answer) in 'stable'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_LOCAL_CREATE_OFFER");
test.chain.append([[
"PC_LOCAL_SET_LOCAL_ANSWER",
function (test) {
test.pcLocal._last_offer.type="answer";
test.pcLocal.setLocalDescriptionAndFail(test.pcLocal._last_offer,
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "setLocalDescription (offer) in 'have-remote-offer'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_REMOTE_SET_REMOTE_DESCRIPTION");
test.chain.append([[
"PC_REMOTE_SET_LOCAL_OFFER",
function (test) {
test.pcRemote.setLocalDescriptionAndFail(test.pcLocal._last_offer,
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "setRemoteDescription (answer) in 'have-remote-offer'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_REMOTE_SET_REMOTE_DESCRIPTION");
test.chain.append([[
"PC_REMOTE_SET_REMOTE_ANSWER",
function (test) {
test.pcLocal._last_offer.type="answer";
test.pcRemote.setRemoteDescriptionAndFail(test.pcLocal._last_offer,
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "setRemoteDescription (answer) in 'stable'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_LOCAL_CREATE_OFFER");
test.chain.append([[
"PC_LOCAL_SET_REMOTE_ANSWER",
function (test) {
test.pcLocal._last_offer.type="answer";
test.pcLocal.setRemoteDescriptionAndFail(test.pcLocal._last_offer,
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "784519",
title: "setRemoteDescription (offer) in 'have-local-offer'"
});
var test;
runTest(function () {
test = new PeerConnectionTest();
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.chain.removeAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION");
test.chain.append([[
"PC_LOCAL_SET_REMOTE_OFFER",
function (test) {
test.pcLocal.setRemoteDescriptionAndFail(test.pcLocal._last_offer,
function(err) {
is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
test.next();
} );
}
]]);
test.run();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -4,8 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Util.h"
#include "RuntimeService.h"
#include "nsIContentSecurityPolicy.h"
@ -18,32 +16,32 @@
#include "nsISupportsPriority.h"
#include "nsITimer.h"
#include "nsPIDOMWindow.h"
#include "nsLayoutStatics.h"
#include <algorithm>
#include "GeckoProfiler.h"
#include "jsdbgapi.h"
#include "jsfriendapi.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Preferences.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsDOMJSUtils.h"
#include "mozilla/Util.h"
#include <Navigator.h>
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
#include "nsLayoutStatics.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
#include "nsXPCOMPrivate.h"
#include "OSFileConstants.h"
#include "xpcpublic.h"
#include "Events.h"
#include "Worker.h"
#include "WorkerPrivate.h"
#include "OSFileConstants.h"
#include <algorithm>
#include "GeckoProfiler.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -72,7 +70,8 @@ using mozilla::Preferences;
MOZ_STATIC_ASSERT(MAX_WORKERS_PER_DOMAIN >= 1,
"We should allow at least one worker per domain.");
// The default number of seconds that close handlers will be allowed to run.
// The default number of seconds that close handlers will be allowed to run for
// content workers.
#define MAX_SCRIPT_RUN_TIME_SEC 10
// The number of seconds that idle threads can hang around before being killed.
@ -81,10 +80,12 @@ MOZ_STATIC_ASSERT(MAX_WORKERS_PER_DOMAIN >= 1,
// The maximum number of threads that can be idle at one time.
#define MAX_IDLE_THREADS 20
#define PREF_WORKERS_ENABLED "dom.workers.enabled"
#define PREF_WORKERS_MAX_PER_DOMAIN "dom.workers.maxPerDomain"
#define PREF_WORKERS_GCZEAL "dom.workers.gczeal"
#define PREF_MAX_SCRIPT_RUN_TIME "dom.max_script_run_time"
#define PREF_WORKERS_PREFIX "dom.workers."
#define PREF_WORKERS_ENABLED PREF_WORKERS_PREFIX "enabled"
#define PREF_WORKERS_MAX_PER_DOMAIN PREF_WORKERS_PREFIX "maxPerDomain"
#define PREF_MAX_SCRIPT_RUN_TIME_CONTENT "dom.max_script_run_time"
#define PREF_MAX_SCRIPT_RUN_TIME_CHROME "dom.max_chrome_script_run_time"
#define GC_REQUEST_OBSERVER_TOPIC "child-gc-request"
#define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
@ -109,6 +110,13 @@ MOZ_STATIC_ASSERT(MAX_WORKERS_PER_DOMAIN >= 1,
} \
PR_END_MACRO
// Prefixes for observing preference changes.
#define PREF_JS_OPTIONS_PREFIX "javascript.options."
#define PREF_WORKERS_OPTIONS_PREFIX PREF_WORKERS_PREFIX "options."
#define PREF_MEM_OPTIONS_PREFIX "mem."
#define PREF_JIT_HARDENING "jit_hardening"
#define PREF_GCZEAL "gcZeal"
namespace {
const uint32_t kNoIndex = uint32_t(-1);
@ -121,6 +129,9 @@ uint32_t gMaxWorkersPerDomain = MAX_WORKERS_PER_DOMAIN;
// Does not hold an owning reference.
RuntimeService* gRuntimeService = nullptr;
// Only non-null during the call to Init.
RuntimeService* gRuntimeServiceDuringInit = nullptr;
enum {
ID_Worker = 0,
ID_ChromeWorker,
@ -148,100 +159,428 @@ const char* gStringChars[] = {
MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(gStringChars) == ID_COUNT,
"gStringChars should have the right length.");
enum {
PREF_strict = 0,
PREF_werror,
PREF_typeinference,
PREF_jit_hardening,
PREF_mem_max,
PREF_baselinejit,
PREF_ion,
PREF_asmjs,
PREF_mem_gc_allocation_threshold_mb,
#ifdef JS_GC_ZEAL
PREF_gczeal,
#endif
PREF_COUNT
class LiteralRebindingCString : public nsDependentCString
{
public:
template<int N>
void RebindLiteral(const char (&aStr)[N])
{
Rebind(aStr, N-1);
}
};
#define JS_OPTIONS_DOT_STR "javascript.options."
template <typename T>
struct PrefTraits;
const char* gPrefsToWatch[] = {
JS_OPTIONS_DOT_STR "strict",
JS_OPTIONS_DOT_STR "werror",
JS_OPTIONS_DOT_STR "typeinference",
JS_OPTIONS_DOT_STR "jit_hardening",
JS_OPTIONS_DOT_STR "mem.max",
JS_OPTIONS_DOT_STR "baselinejit.content",
JS_OPTIONS_DOT_STR "ion.content",
JS_OPTIONS_DOT_STR "asmjs",
"dom.workers.mem.gc_allocation_threshold_mb"
template <>
struct PrefTraits<bool>
{
typedef bool PrefValueType;
#ifdef JS_GC_ZEAL
, PREF_WORKERS_GCZEAL
#endif
static const PrefValueType kDefaultValue = false;
static inline PrefValueType
Get(const char* aPref)
{
AssertIsOnMainThread();
return Preferences::GetBool(aPref);
}
static inline bool
Exists(const char* aPref)
{
AssertIsOnMainThread();
return Preferences::GetType(aPref) == nsIPrefBranch::PREF_BOOL;
}
};
MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(gPrefsToWatch) == PREF_COUNT,
"gPrefsToWatch should have the right length.");
template <>
struct PrefTraits<int32_t>
{
typedef int32_t PrefValueType;
int
PrefCallback(const char* aPrefName, void* aClosure)
static const PrefValueType kDefaultValue = 0;
static inline PrefValueType
Get(const char* aPref)
{
AssertIsOnMainThread();
return Preferences::GetInt(aPref);
}
static inline bool
Exists(const char* aPref)
{
AssertIsOnMainThread();
return Preferences::GetType(aPref) == nsIPrefBranch::PREF_INT;
}
};
template <typename T>
T
GetWorkerPref(const nsACString& aPref,
const T aDefault = PrefTraits<T>::kDefaultValue)
{
AssertIsOnMainThread();
RuntimeService* rts = static_cast<RuntimeService*>(aClosure);
NS_ASSERTION(rts, "This should never be null!");
typedef PrefTraits<T> PrefHelper;
NS_NAMED_LITERAL_CSTRING(jsOptionStr, JS_OPTIONS_DOT_STR);
T result;
if (!strcmp(aPrefName, gPrefsToWatch[PREF_mem_max])) {
int32_t pref = Preferences::GetInt(aPrefName, -1);
uint32_t maxBytes = (pref <= 0 || pref >= 0x1000) ?
uint32_t(-1) :
uint32_t(pref) * 1024 * 1024;
RuntimeService::SetDefaultJSWorkerMemoryParameter(JSGC_MAX_BYTES, maxBytes);
rts->UpdateAllWorkerMemoryParameter(JSGC_MAX_BYTES);
} else if (!strcmp(aPrefName, gPrefsToWatch[PREF_mem_gc_allocation_threshold_mb])) {
int32_t pref = Preferences::GetInt(aPrefName, 30);
uint32_t threshold = (pref <= 0 || pref >= 0x1000) ?
uint32_t(30) :
uint32_t(pref);
RuntimeService::SetDefaultJSWorkerMemoryParameter(JSGC_ALLOCATION_THRESHOLD, threshold);
rts->UpdateAllWorkerMemoryParameter(JSGC_ALLOCATION_THRESHOLD);
} else if (StringBeginsWith(nsDependentCString(aPrefName), jsOptionStr)) {
uint32_t newOptions = kRequiredJSContextOptions;
if (Preferences::GetBool(gPrefsToWatch[PREF_strict])) {
newOptions |= JSOPTION_STRICT;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_werror])) {
newOptions |= JSOPTION_WERROR;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_typeinference])) {
newOptions |= JSOPTION_TYPE_INFERENCE;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_baselinejit])) {
newOptions |= JSOPTION_BASELINE;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_ion])) {
newOptions |= JSOPTION_ION;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_asmjs])) {
newOptions |= JSOPTION_ASMJS;
}
nsAutoCString prefName;
prefName.AssignLiteral(PREF_WORKERS_OPTIONS_PREFIX);
prefName.Append(aPref);
RuntimeService::SetDefaultJSContextOptions(newOptions);
rts->UpdateAllWorkerJSContextOptions();
if (PrefHelper::Exists(prefName.get())) {
result = PrefHelper::Get(prefName.get());
}
else {
prefName.AssignLiteral(PREF_JS_OPTIONS_PREFIX);
prefName.Append(aPref);
if (PrefHelper::Exists(prefName.get())) {
result = PrefHelper::Get(prefName.get());
}
else {
result = aDefault;
}
}
return result;
}
int
LoadJSContextOptions(const char* aPrefName, void* /* aClosure */)
{
AssertIsOnMainThread();
RuntimeService* rts = RuntimeService::GetService();
if (!rts && !gRuntimeServiceDuringInit) {
// May be shutting down, just bail.
return 0;
}
const nsDependentCString prefName(aPrefName);
// Several other pref branches will get included here so bail out if there is
// another callback that will handle this change.
if (StringBeginsWith(prefName,
NS_LITERAL_CSTRING(PREF_JS_OPTIONS_PREFIX
PREF_MEM_OPTIONS_PREFIX)) ||
StringBeginsWith(prefName,
NS_LITERAL_CSTRING(PREF_WORKERS_OPTIONS_PREFIX
PREF_MEM_OPTIONS_PREFIX)) ||
prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_JIT_HARDENING) ||
prefName.EqualsLiteral(PREF_WORKERS_OPTIONS_PREFIX PREF_JIT_HARDENING)) {
return 0;
}
#ifdef JS_GC_ZEAL
else if (!strcmp(aPrefName, gPrefsToWatch[PREF_gczeal])) {
int32_t gczeal = Preferences::GetInt(gPrefsToWatch[PREF_gczeal]);
RuntimeService::SetDefaultGCZeal(uint8_t(clamped(gczeal, 0, 3)));
rts->UpdateAllWorkerGCZeal();
if (prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL) ||
prefName.EqualsLiteral(PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL)) {
return 0;
}
#endif
// Common options.
uint32_t commonOptions = kRequiredJSContextOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict"))) {
commonOptions |= JSOPTION_STRICT;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror"))) {
commonOptions |= JSOPTION_WERROR;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("typeinference"))) {
commonOptions |= JSOPTION_TYPE_INFERENCE;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs"))) {
commonOptions |= JSOPTION_ASMJS;
}
// Content options.
uint32_t contentOptions = commonOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("pccounts.content"))) {
contentOptions |= JSOPTION_PCCOUNT;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit.content"))) {
contentOptions |= JSOPTION_BASELINE;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion.content"))) {
contentOptions |= JSOPTION_ION;
}
// Chrome options.
uint32_t chromeOptions = commonOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("pccounts.chrome"))) {
chromeOptions |= JSOPTION_PCCOUNT;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit.chrome"))) {
chromeOptions |= JSOPTION_BASELINE;
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion.chrome"))) {
chromeOptions |= JSOPTION_ION;
}
#ifdef DEBUG
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict.debug"))) {
chromeOptions |= JSOPTION_STRICT;
}
#endif
RuntimeService::SetDefaultJSContextOptions(contentOptions, chromeOptions);
if (rts) {
rts->UpdateAllWorkerJSContextOptions();
}
return 0;
}
#ifdef JS_GC_ZEAL
int
LoadGCZealOptions(const char* /* aPrefName */, void* /* aClosure */)
{
AssertIsOnMainThread();
RuntimeService* rts = RuntimeService::GetService();
if (!rts && !gRuntimeServiceDuringInit) {
// May be shutting down, just bail.
return 0;
}
int32_t gczeal = GetWorkerPref<int32_t>(NS_LITERAL_CSTRING(PREF_GCZEAL), -1);
if (gczeal < 0) {
gczeal = 0;
}
int32_t frequency =
GetWorkerPref<int32_t>(NS_LITERAL_CSTRING("gcZeal.frequency"), -1);
if (frequency < 0) {
frequency = JS_DEFAULT_ZEAL_FREQ;
}
RuntimeService::SetDefaultGCZeal(uint8_t(gczeal), uint32_t(frequency));
if (rts) {
rts->UpdateAllWorkerGCZeal();
}
return 0;
}
#endif
void
UpdateCommonJSGCMemoryOption(RuntimeService* aRuntimeService,
const nsACString& aPrefName, JSGCParamKey aKey)
{
AssertIsOnMainThread();
NS_ASSERTION(!aPrefName.IsEmpty(), "Empty pref name!");
int32_t prefValue = GetWorkerPref(aPrefName, -1);
uint32_t value =
(prefValue <= 0 || prefValue >= 10000) ? 0 : uint32_t(prefValue);
RuntimeService::SetDefaultJSGCSettings(aKey, value);
if (aRuntimeService) {
aRuntimeService->UpdateAllWorkerMemoryParameter(aKey, value);
}
}
void
UpdatOtherJSGCMemoryOption(RuntimeService* aRuntimeService,
JSGCParamKey aKey, uint32_t aValue)
{
AssertIsOnMainThread();
RuntimeService::SetDefaultJSGCSettings(aKey, aValue);
if (aRuntimeService) {
aRuntimeService->UpdateAllWorkerMemoryParameter(aKey, aValue);
}
}
int
LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */)
{
AssertIsOnMainThread();
RuntimeService* rts = RuntimeService::GetService();
if (!rts && !gRuntimeServiceDuringInit) {
// May be shutting down, just bail.
return 0;
}
NS_NAMED_LITERAL_CSTRING(jsPrefix, PREF_JS_OPTIONS_PREFIX);
NS_NAMED_LITERAL_CSTRING(workersPrefix, PREF_WORKERS_OPTIONS_PREFIX);
const nsDependentCString fullPrefName(aPrefName);
// Pull out the string that actually distinguishes the parameter we need to
// change.
nsDependentCSubstring memPrefName;
if (StringBeginsWith(fullPrefName, jsPrefix)) {
memPrefName.Rebind(fullPrefName, jsPrefix.Length());
}
else if (StringBeginsWith(fullPrefName, workersPrefix)) {
memPrefName.Rebind(fullPrefName, workersPrefix.Length());
}
else {
NS_ERROR("Unknown pref name!");
return 0;
}
#ifdef DEBUG
// During Init() we get called back with a branch string here, so there should
// be no just a "mem." pref here.
if (!rts) {
NS_ASSERTION(memPrefName.EqualsLiteral(PREF_MEM_OPTIONS_PREFIX), "Huh?!");
}
#endif
// If we're running in Init() then do this for every pref we care about.
// Otherwise we just want to update the parameter that changed.
for (uint32_t index = rts ? JSSettings::kGCSettingsArraySize - 1 : 0;
index < JSSettings::kGCSettingsArraySize;
index++) {
LiteralRebindingCString matchName;
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "max");
if (memPrefName == matchName || (!rts && index == 0)) {
int32_t prefValue = GetWorkerPref(matchName, -1);
uint32_t value = (prefValue <= 0 || prefValue >= 0x1000) ?
uint32_t(-1) :
uint32_t(prefValue) * 1024 * 1024;
UpdatOtherJSGCMemoryOption(rts, JSGC_MAX_BYTES, value);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "high_water_mark");
if (memPrefName == matchName || (!rts && index == 1)) {
int32_t prefValue = GetWorkerPref(matchName, 128);
UpdatOtherJSGCMemoryOption(rts, JSGC_MAX_MALLOC_BYTES,
uint32_t(prefValue) * 1024 * 1024);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_high_frequency_time_limit_ms");
if (memPrefName == matchName || (!rts && index == 2)) {
UpdateCommonJSGCMemoryOption(rts, matchName,
JSGC_HIGH_FREQUENCY_TIME_LIMIT);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_low_frequency_heap_growth");
if (memPrefName == matchName || (!rts && index == 3)) {
UpdateCommonJSGCMemoryOption(rts, matchName,
JSGC_LOW_FREQUENCY_HEAP_GROWTH);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_high_frequency_heap_growth_min");
if (memPrefName == matchName || (!rts && index == 4)) {
UpdateCommonJSGCMemoryOption(rts, matchName,
JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_high_frequency_heap_growth_max");
if (memPrefName == matchName || (!rts && index == 5)) {
UpdateCommonJSGCMemoryOption(rts, matchName,
JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_high_frequency_low_limit_mb");
if (memPrefName == matchName || (!rts && index == 6)) {
UpdateCommonJSGCMemoryOption(rts, matchName,
JSGC_HIGH_FREQUENCY_LOW_LIMIT);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_high_frequency_high_limit_mb");
if (memPrefName == matchName || (!rts && index == 7)) {
UpdateCommonJSGCMemoryOption(rts, matchName,
JSGC_HIGH_FREQUENCY_HIGH_LIMIT);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "analysis_purge_mb");
if (memPrefName == matchName || (!rts && index == 8)) {
UpdateCommonJSGCMemoryOption(rts, matchName, JSGC_ANALYSIS_PURGE_TRIGGER);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX
"gc_allocation_threshold_mb");
if (memPrefName == matchName || (!rts && index == 9)) {
UpdateCommonJSGCMemoryOption(rts, matchName, JSGC_ALLOCATION_THRESHOLD);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_incremental_slice_ms");
if (memPrefName == matchName || (!rts && index == 10)) {
int32_t prefValue = GetWorkerPref(matchName, -1);
uint32_t value =
(prefValue <= 0 || prefValue >= 100000) ? 0 : uint32_t(prefValue);
UpdatOtherJSGCMemoryOption(rts, JSGC_SLICE_TIME_BUDGET, value);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_heap_growth");
if (memPrefName == matchName || (!rts && index == 11)) {
bool prefValue = GetWorkerPref(matchName, false);
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_HEAP_GROWTH,
prefValue ? 0 : 1);
continue;
}
matchName.RebindLiteral(PREF_MEM_OPTIONS_PREFIX "gc_dynamic_mark_slice");
if (memPrefName == matchName || (!rts && index == 12)) {
bool prefValue = GetWorkerPref(matchName, false);
UpdatOtherJSGCMemoryOption(rts, JSGC_DYNAMIC_MARK_SLICE,
prefValue ? 0 : 1);
continue;
}
#ifdef DEBUG
nsAutoCString message("Workers don't support the 'mem.");
message.Append(memPrefName);
message.AppendLiteral("' preference!");
NS_WARNING(message.get());
#endif
}
return 0;
}
int
LoadJITHardeningOption(const char* /* aPrefName */, void* /* aClosure */)
{
AssertIsOnMainThread();
RuntimeService* rts = RuntimeService::GetService();
if (!rts && !gRuntimeServiceDuringInit) {
// May be shutting down, just bail.
return 0;
}
bool value = GetWorkerPref(NS_LITERAL_CSTRING(PREF_JIT_HARDENING), false);
RuntimeService::SetDefaultJITHardening(value);
if (rts) {
rts->UpdateAllWorkerJITHardening(value);
}
return 0;
}
@ -422,17 +761,33 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
// The number passed here doesn't matter, we're about to change it in the call
// to JS_SetGCParameter.
JSRuntime* runtime = JS_NewRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE, JS_NO_HELPER_THREADS);
JSRuntime* runtime =
JS_NewRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE, JS_NO_HELPER_THREADS);
if (!runtime) {
NS_WARNING("Could not create new runtime!");
return nullptr;
}
JSSettings settings;
aWorkerPrivate->CopyJSSettings(settings);
NS_ASSERTION((settings.chrome.options & kRequiredJSContextOptions) ==
kRequiredJSContextOptions,
"Somehow we lost our required chrome options!");
NS_ASSERTION((settings.content.options & kRequiredJSContextOptions) ==
kRequiredJSContextOptions,
"Somehow we lost our required content options!");
JSSettings::JSGCSettingsArray& gcSettings = settings.gcSettings;
// This is the real place where we set the max memory for the runtime.
JS_SetGCParameter(runtime, JSGC_MAX_BYTES,
aWorkerPrivate->GetJSRuntimeHeapSize());
JS_SetGCParameter(runtime, JSGC_ALLOCATION_THRESHOLD,
aWorkerPrivate->GetJSWorkerAllocationThreshold());
for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
const JSSettings::JSGCSetting& setting = gcSettings[index];
if (setting.IsSet()) {
NS_ASSERTION(setting.value, "Can't handle 0 values!");
JS_SetGCParameter(runtime, setting.key, setting.value);
}
}
JS_SetNativeStackQuota(runtime, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
@ -464,19 +819,14 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
js::SetCTypesActivityCallback(runtime, CTypesActivityCallback);
NS_ASSERTION((aWorkerPrivate->GetJSContextOptions() &
kRequiredJSContextOptions) == kRequiredJSContextOptions,
"Somehow we lost our required options!");
JS_SetOptions(workerCx, aWorkerPrivate->GetJSContextOptions());
JS_SetOptions(workerCx,
aWorkerPrivate->IsChromeWorker() ? settings.chrome.options :
settings.content.options);
JS_SetJitHardening(runtime, settings.jitHardening);
#ifdef JS_GC_ZEAL
{
uint8_t zeal = aWorkerPrivate->GetGCZeal();
NS_ASSERTION(zeal <= 3, "Bad zeal value!");
uint32_t frequency = zeal <= 2 ? JS_DEFAULT_ZEAL_FREQ : 1;
JS_SetGCZeal(workerCx, zeal, frequency);
}
JS_SetGCZeal(workerCx, settings.gcZeal, settings.gcZealFrequency);
#endif
if (aWorkerPrivate->IsChromeWorker()) {
@ -650,7 +1000,7 @@ SuspendWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow)
}
void
ResumeWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow)
ResumeWorkersForWindow(nsIScriptContext* aCx, nsPIDOMWindow* aWindow)
{
AssertIsOnMainThread();
RuntimeService* runtime = RuntimeService::GetService();
@ -707,19 +1057,8 @@ WorkerCrossThreadDispatcher::PostTask(WorkerTask* aTask)
END_WORKERS_NAMESPACE
uint32_t RuntimeService::sDefaultJSContextOptions = kRequiredJSContextOptions;
uint32_t RuntimeService::sDefaultJSRuntimeHeapSize =
WORKER_DEFAULT_RUNTIME_HEAPSIZE;
uint32_t RuntimeService::sDefaultJSAllocationThreshold =
WORKER_DEFAULT_ALLOCATION_THRESHOLD;
int32_t RuntimeService::sCloseHandlerTimeoutSeconds = MAX_SCRIPT_RUN_TIME_SEC;
#ifdef JS_GC_ZEAL
uint8_t RuntimeService::sDefaultGCZeal = 0;
#endif
// This is only touched on the main thread. Initialized in Init() below.
JSSettings RuntimeService::sDefaultJSSettings;
RuntimeService::RuntimeService()
: mMutex("RuntimeService::mMutex"), mObserved(false),
@ -972,12 +1311,15 @@ RuntimeService::ScheduleWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
JS_ReportError(aCx, "Could not create new thread!");
return false;
}
}
nsCOMPtr<nsISupportsPriority> priority = do_QueryInterface(thread);
if (!priority ||
NS_FAILED(priority->SetPriority(nsISupportsPriority::PRIORITY_LOW))) {
NS_WARNING("Could not lower the new thread's priority!");
}
int32_t priority = aWorkerPrivate->IsChromeWorker() ?
nsISupportsPriority::PRIORITY_NORMAL :
nsISupportsPriority::PRIORITY_LOW;
nsCOMPtr<nsISupportsPriority> threadPriority = do_QueryInterface(thread);
if (!threadPriority || NS_FAILED(threadPriority->SetPriority(priority))) {
NS_WARNING("Could not set the thread's priority!");
}
#ifdef DEBUG
@ -1058,8 +1400,24 @@ nsresult
RuntimeService::Init()
{
AssertIsOnMainThread();
nsLayoutStatics::AddRef();
// Initialize JSSettings.
if (!sDefaultJSSettings.gcSettings[0].IsSet()) {
sDefaultJSSettings.chrome.options = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.maxScriptRuntime = -1;
sDefaultJSSettings.content.options = kRequiredJSContextOptions;
sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
#ifdef JS_GC_ZEAL
sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
sDefaultJSSettings.gcZeal = 0;
#endif
SetDefaultJSGCSettings(JSGC_MAX_BYTES, WORKER_DEFAULT_RUNTIME_HEAPSIZE);
SetDefaultJSGCSettings(JSGC_ALLOCATION_THRESHOLD,
WORKER_DEFAULT_ALLOCATION_THRESHOLD);
}
mIdleThreadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_STATE(mIdleThreadTimer);
@ -1084,21 +1442,59 @@ RuntimeService::Init()
NS_WARNING("Failed to register for memory pressure notifications!");
}
for (uint32_t index = 0; index < ArrayLength(gPrefsToWatch); index++) {
if (NS_FAILED(Preferences::RegisterCallback(PrefCallback,
gPrefsToWatch[index], this))) {
NS_WARNING("Failed to register pref callback?!");
}
PrefCallback(gPrefsToWatch[index], this);
NS_ASSERTION(!gRuntimeServiceDuringInit, "This should be null!");
gRuntimeServiceDuringInit = this;
if (NS_FAILED(Preferences::RegisterCallback(
LoadJSGCMemoryOptions,
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadJSGCMemoryOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallback(
LoadJITHardeningOption,
PREF_JS_OPTIONS_PREFIX PREF_JIT_HARDENING,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadJITHardeningOption,
PREF_WORKERS_OPTIONS_PREFIX PREF_JIT_HARDENING,
nullptr)) ||
#ifdef JS_GC_ZEAL
NS_FAILED(Preferences::RegisterCallback(
LoadGCZealOptions,
PREF_JS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadGCZealOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
#endif
NS_FAILED(Preferences::RegisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr))) {
NS_WARNING("Failed to register pref callbacks!");
}
NS_ASSERTION(gRuntimeServiceDuringInit == this, "Should be 'this'!");
gRuntimeServiceDuringInit = nullptr;
// We assume atomic 32bit reads/writes. If this assumption doesn't hold on
// some wacky platform then the worst that could happen is that the close
// handler will run for a slightly different amount of time.
if (NS_FAILED(Preferences::AddIntVarCache(&sCloseHandlerTimeoutSeconds,
PREF_MAX_SCRIPT_RUN_TIME,
MAX_SCRIPT_RUN_TIME_SEC))) {
NS_WARNING("Failed to register timeout cache?!");
if (NS_FAILED(Preferences::AddIntVarCache(
&sDefaultJSSettings.content.maxScriptRuntime,
PREF_MAX_SCRIPT_RUN_TIME_CONTENT,
MAX_SCRIPT_RUN_TIME_SEC)) ||
NS_FAILED(Preferences::AddIntVarCache(
&sDefaultJSSettings.chrome.maxScriptRuntime,
PREF_MAX_SCRIPT_RUN_TIME_CHROME, -1))) {
NS_WARNING("Failed to register timeout cache!");
}
int32_t maxPerDomain = Preferences::GetInt(PREF_WORKERS_MAX_PER_DOMAIN,
@ -1215,8 +1611,39 @@ RuntimeService::Cleanup()
}
if (mObserved) {
for (uint32_t index = 0; index < ArrayLength(gPrefsToWatch); index++) {
Preferences::UnregisterCallback(PrefCallback, gPrefsToWatch[index], this);
if (NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
#ifdef JS_GC_ZEAL
NS_FAILED(Preferences::UnregisterCallback(
LoadGCZealOptions,
PREF_JS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
LoadGCZealOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
#endif
NS_FAILED(Preferences::UnregisterCallback(
LoadJSGCMemoryOptions,
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
LoadJSGCMemoryOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
LoadJITHardeningOption,
PREF_JS_OPTIONS_PREFIX PREF_JIT_HARDENING,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
LoadJITHardeningOption,
PREF_WORKERS_OPTIONS_PREFIX PREF_JIT_HARDENING,
nullptr))) {
NS_WARNING("Failed to unregister pref callbacks!");
}
if (obs) {
@ -1321,7 +1748,7 @@ RuntimeService::SuspendWorkersForWindow(JSContext* aCx,
}
void
RuntimeService::ResumeWorkersForWindow(JSContext* aCx,
RuntimeService::ResumeWorkersForWindow(nsIScriptContext* aCx,
nsPIDOMWindow* aWindow)
{
AssertIsOnMainThread();
@ -1331,7 +1758,7 @@ RuntimeService::ResumeWorkersForWindow(JSContext* aCx,
if (!workers.IsEmpty()) {
for (uint32_t index = 0; index < workers.Length(); index++) {
if (!workers[index]->Resume(aCx)) {
if (!workers[index]->SynchronizeAndResume(aCx)) {
NS_WARNING("Failed to cancel worker!");
}
}
@ -1387,25 +1814,33 @@ RuntimeService::NoteIdleThread(nsIThread* aThread)
void
RuntimeService::UpdateAllWorkerJSContextOptions()
{
BROADCAST_ALL_WORKERS(UpdateJSContextOptions, GetDefaultJSContextOptions());
BROADCAST_ALL_WORKERS(UpdateJSContextOptions,
sDefaultJSSettings.content.options,
sDefaultJSSettings.chrome.options);
}
void
RuntimeService::UpdateAllWorkerMemoryParameter(JSGCParamKey key)
RuntimeService::UpdateAllWorkerMemoryParameter(JSGCParamKey aKey,
uint32_t aValue)
{
BROADCAST_ALL_WORKERS(UpdateJSWorkerMemoryParameter,
key,
GetDefaultJSWorkerMemoryParameter(key));
BROADCAST_ALL_WORKERS(UpdateJSWorkerMemoryParameter, aKey, aValue);
}
#ifdef JS_GC_ZEAL
void
RuntimeService::UpdateAllWorkerGCZeal()
{
BROADCAST_ALL_WORKERS(UpdateGCZeal, GetDefaultGCZeal());
BROADCAST_ALL_WORKERS(UpdateGCZeal, sDefaultJSSettings.gcZeal,
sDefaultJSSettings.gcZealFrequency);
}
#endif
void
RuntimeService::UpdateAllWorkerJITHardening(bool aJITHardening)
{
BROADCAST_ALL_WORKERS(UpdateJITHardening, aJITHardening);
}
void
RuntimeService::GarbageCollectAllWorkers(bool aShrinking)
{

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsIObserver.h"
#include "jsapi.h"
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "nsAutoPtr.h"
@ -20,7 +21,6 @@
#include "nsHashKeys.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
#include "mozilla/Attributes.h"
class nsIThread;
class nsITimer;
@ -71,14 +71,7 @@ class RuntimeService MOZ_FINAL : public nsIObserver
nsCString mDetectorName;
nsCString mSystemCharset;
static uint32_t sDefaultJSContextOptions;
static uint32_t sDefaultJSRuntimeHeapSize;
static uint32_t sDefaultJSAllocationThreshold;
static int32_t sCloseHandlerTimeoutSeconds;
#ifdef JS_GC_ZEAL
static uint8_t sDefaultGCZeal;
#endif
static JSSettings sDefaultJSSettings;
public:
struct NavigatorStrings
@ -120,7 +113,7 @@ public:
SuspendWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
void
ResumeWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
ResumeWorkersForWindow(nsIScriptContext* aCx, nsPIDOMWindow* aWindow);
const nsACString&
GetDetectorName() const
@ -143,81 +136,69 @@ public:
void
NoteIdleThread(nsIThread* aThread);
static uint32_t
GetDefaultJSContextOptions()
static void
GetDefaultJSSettings(JSSettings& aSettings)
{
AssertIsOnMainThread();
return sDefaultJSContextOptions;
aSettings = sDefaultJSSettings;
}
static void
SetDefaultJSContextOptions(uint32_t aOptions)
SetDefaultJSContextOptions(uint32_t aContentOptions, uint32_t aChromeOptions)
{
AssertIsOnMainThread();
sDefaultJSContextOptions = aOptions;
sDefaultJSSettings.content.options = aContentOptions;
sDefaultJSSettings.chrome.options = aChromeOptions;
}
void
UpdateAllWorkerJSContextOptions();
static uint32_t
GetDefaultJSWorkerMemoryParameter(JSGCParamKey aKey)
{
AssertIsOnMainThread();
switch (aKey) {
case JSGC_ALLOCATION_THRESHOLD:
return sDefaultJSAllocationThreshold;
case JSGC_MAX_BYTES:
return sDefaultJSRuntimeHeapSize;
default:
MOZ_NOT_REACHED("Unknown Worker Memory Parameter.");
}
}
static void
SetDefaultJSWorkerMemoryParameter(JSGCParamKey aKey, uint32_t aValue)
SetDefaultJSGCSettings(JSGCParamKey aKey, uint32_t aValue)
{
AssertIsOnMainThread();
switch(aKey) {
case JSGC_ALLOCATION_THRESHOLD:
sDefaultJSAllocationThreshold = aValue;
break;
case JSGC_MAX_BYTES:
sDefaultJSRuntimeHeapSize = aValue;
break;
default:
MOZ_NOT_REACHED("Unknown Worker Memory Parameter.");
}
sDefaultJSSettings.ApplyGCSetting(aKey, aValue);
}
void
UpdateAllWorkerMemoryParameter(JSGCParamKey aKey);
UpdateAllWorkerMemoryParameter(JSGCParamKey aKey, uint32_t aValue);
static uint32_t
GetCloseHandlerTimeoutSeconds()
GetContentCloseHandlerTimeoutSeconds()
{
return sCloseHandlerTimeoutSeconds > 0 ? sCloseHandlerTimeoutSeconds : 0;
return sDefaultJSSettings.content.maxScriptRuntime;
}
static uint32_t
GetChromeCloseHandlerTimeoutSeconds()
{
return sDefaultJSSettings.chrome.maxScriptRuntime;
}
#ifdef JS_GC_ZEAL
static uint8_t
GetDefaultGCZeal()
{
AssertIsOnMainThread();
return sDefaultGCZeal;
}
static void
SetDefaultGCZeal(uint8_t aGCZeal)
SetDefaultGCZeal(uint8_t aGCZeal, uint32_t aFrequency)
{
AssertIsOnMainThread();
sDefaultGCZeal = aGCZeal;
sDefaultJSSettings.gcZeal = aGCZeal;
sDefaultJSSettings.gcZealFrequency = aFrequency;
}
void
UpdateAllWorkerGCZeal();
#endif
static void
SetDefaultJITHardening(bool aJITHardening)
{
AssertIsOnMainThread();
sDefaultJSSettings.jitHardening = aJITHardening;
}
void
UpdateAllWorkerJITHardening(bool aJITHardening);
void
GarbageCollectAllWorkers(bool aShrinking);

Просмотреть файл

@ -26,11 +26,14 @@
#include "nsIXPCScriptNotify.h"
#include "nsPrintfCString.h"
#include <algorithm>
#include "jsfriendapi.h"
#include "jsdbgapi.h"
#include "jsfriendapi.h"
#include "jsprf.h"
#include "js/MemoryMetrics.h"
#include "mozilla/Attributes.h"
#include "mozilla/Likely.h"
#include "nsAlgorithm.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
@ -44,9 +47,6 @@
#include "nsSandboxFlags.h"
#include "nsThreadUtils.h"
#include "xpcpublic.h"
#include "mozilla/Attributes.h"
#include "mozilla/Likely.h"
#include <algorithm>
#ifdef ANDROID
#include <android/log.h>
@ -63,10 +63,6 @@
#include "WorkerFeature.h"
#include "WorkerScope.h"
#if 0 // Define to run GC more often.
#define EXTRA_GC
#endif
// GC will run once every thirty seconds during normal execution.
#define NORMAL_GC_TIMER_DELAY_MS 30000
@ -77,6 +73,7 @@ using mozilla::MutexAutoLock;
using mozilla::TimeDuration;
using mozilla::TimeStamp;
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
using mozilla::AutoPushJSContext;
using mozilla::AutoSafeJSContext;
USING_WORKERS_NAMESPACE
@ -1307,19 +1304,22 @@ public:
class UpdateJSContextOptionsRunnable : public WorkerControlRunnable
{
uint32_t mOptions;
uint32_t mContentOptions;
uint32_t mChromeOptions;
public:
UpdateJSContextOptionsRunnable(WorkerPrivate* aWorkerPrivate,
uint32_t aOptions)
uint32_t aContentOptions,
uint32_t aChromeOptions)
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
mOptions(aOptions)
mContentOptions(aContentOptions), mChromeOptions(aChromeOptions)
{ }
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aWorkerPrivate->UpdateJSContextOptionsInternal(aCx, mOptions);
aWorkerPrivate->UpdateJSContextOptionsInternal(aCx, mContentOptions,
mChromeOptions);
return true;
}
};
@ -1349,23 +1349,43 @@ public:
class UpdateGCZealRunnable : public WorkerControlRunnable
{
uint8_t mGCZeal;
uint32_t mFrequency;
public:
UpdateGCZealRunnable(WorkerPrivate* aWorkerPrivate,
uint8_t aGCZeal)
uint8_t aGCZeal,
uint32_t aFrequency)
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
mGCZeal(aGCZeal)
mGCZeal(aGCZeal), mFrequency(aFrequency)
{ }
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aWorkerPrivate->UpdateGCZealInternal(aCx, mGCZeal);
aWorkerPrivate->UpdateGCZealInternal(aCx, mGCZeal, mFrequency);
return true;
}
};
#endif
class UpdateJITHardeningRunnable : public WorkerControlRunnable
{
bool mJITHardening;
public:
UpdateJITHardeningRunnable(WorkerPrivate* aWorkerPrivate, bool aJITHardening)
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
mJITHardening(aJITHardening)
{ }
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aWorkerPrivate->UpdateJITHardeningInternal(aCx, mJITHardening);
return true;
}
};
class GarbageCollectRunnable : public WorkerControlRunnable
{
protected:
@ -1403,6 +1423,33 @@ public:
}
};
class SynchronizeAndResumeRunnable : public nsRunnable
{
protected:
WorkerPrivate* mWorkerPrivate;
nsCOMPtr<nsIScriptContext> mCx;
public:
SynchronizeAndResumeRunnable(WorkerPrivate* aWorkerPrivate,
nsIScriptContext* aCx)
: mWorkerPrivate(aWorkerPrivate), mCx(aCx)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
}
NS_IMETHOD Run()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AutoPushJSContext cx(mCx ? mCx->GetNativeContext() :
nsContentUtils::GetSafeJSContext());
JSAutoRequest ar(cx);
mWorkerPrivate->Resume(cx);
return NS_OK;
}
};
class WorkerJSRuntimeStats : public JS::RuntimeStats
{
const nsACString& mRtPath;
@ -1812,9 +1859,7 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
mJSObject(aObject), mParent(aParent), mParentJSContext(aParentJSContext),
mScriptURL(aScriptURL), mDomain(aDomain), mBusyCount(0),
mParentStatus(Pending), mJSContextOptions(0),
mJSRuntimeHeapSize(0), mJSWorkerAllocationThreshold(3),
mGCZeal(0), mJSObjectRooted(false), mParentSuspended(false),
mParentStatus(Pending), mJSObjectRooted(false), mParentSuspended(false),
mIsChromeWorker(aIsChromeWorker), mPrincipalIsSystem(false),
mMainThreadObjectsForgotten(false), mEvalAllowed(aEvalAllowed),
mReportCSPViolations(aReportCSPViolations)
@ -1836,32 +1881,17 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
if (aParent) {
aParent->AssertIsOnWorkerThread();
NS_ASSERTION(JS_GetOptions(aCx) == aParent->GetJSContextOptions(),
aParent->CopyJSSettings(mJSSettings);
NS_ASSERTION(JS_GetOptions(aCx) == (aParent->IsChromeWorker() ?
mJSSettings.chrome.options :
mJSSettings.content.options),
"Options mismatch!");
mJSContextOptions = aParent->GetJSContextOptions();
NS_ASSERTION(JS_GetGCParameter(JS_GetRuntime(aCx), JSGC_MAX_BYTES) ==
aParent->GetJSRuntimeHeapSize(),
"Runtime heap size mismatch!");
mJSRuntimeHeapSize = aParent->GetJSRuntimeHeapSize();
mJSWorkerAllocationThreshold = aParent->GetJSWorkerAllocationThreshold();
#ifdef JS_GC_ZEAL
mGCZeal = aParent->GetGCZeal();
#endif
}
else {
AssertIsOnMainThread();
mJSContextOptions = RuntimeService::GetDefaultJSContextOptions();
mJSRuntimeHeapSize =
RuntimeService::GetDefaultJSWorkerMemoryParameter(JSGC_MAX_BYTES);
mJSWorkerAllocationThreshold =
RuntimeService::GetDefaultJSWorkerMemoryParameter(JSGC_ALLOCATION_THRESHOLD);
#ifdef JS_GC_ZEAL
mGCZeal = RuntimeService::GetDefaultGCZeal();
#endif
RuntimeService::GetDefaultJSSettings(mJSSettings);
}
}
@ -1959,7 +1989,7 @@ WorkerPrivateParent<Derived>::Suspend(JSContext* aCx)
}
template <class Derived>
bool
void
WorkerPrivateParent<Derived>::Resume(JSContext* aCx)
{
AssertIsOnParentThread();
@ -1971,11 +2001,11 @@ WorkerPrivateParent<Derived>::Resume(JSContext* aCx)
MutexAutoLock lock(mMutex);
if (mParentStatus >= Terminating) {
return true;
return;
}
}
// Dispatch queued runnables before waking up the worker, otherwise the worker
// Execute queued runnables before waking up the worker, otherwise the worker
// could post new messages before we run those that have been queued.
if (!mQueuedRunnables.IsEmpty()) {
AssertIsOnMainThread();
@ -1985,19 +2015,31 @@ WorkerPrivateParent<Derived>::Resume(JSContext* aCx)
for (uint32_t index = 0; index < runnables.Length(); index++) {
nsRefPtr<WorkerRunnable>& runnable = runnables[index];
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
NS_WARNING("Failed to dispatch queued runnable!");
}
runnable->Run();
}
}
nsRefPtr<ResumeRunnable> runnable =
new ResumeRunnable(ParentAsWorkerPrivate());
if (!runnable->Dispatch(aCx)) {
return false;
}
runnable->Dispatch(aCx);
}
return true;
template <class Derived>
bool
WorkerPrivateParent<Derived>::SynchronizeAndResume(nsIScriptContext* aCx)
{
AssertIsOnParentThread();
NS_ASSERTION(mParentSuspended, "Not yet suspended!");
// NB: There may be pending unqueued messages. If we resume here we will
// execute those messages out of order. Instead we post an event to the
// end of the event queue, allowing all of the outstanding messages to be
// queued up in order on the worker. Then and only then we execute all of
// the messages.
nsRefPtr<SynchronizeAndResumeRunnable> runnable =
new SynchronizeAndResumeRunnable(ParentAsWorkerPrivate(), aCx);
return NS_SUCCEEDED(NS_DispatchToCurrentThread(runnable));
}
template <class Derived>
@ -2210,14 +2252,20 @@ WorkerPrivateParent<Derived>::GetInnerWindowId()
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateJSContextOptions(JSContext* aCx,
uint32_t aOptions)
uint32_t aContentOptions,
uint32_t aChromeOptions)
{
AssertIsOnParentThread();
mJSContextOptions = aOptions;
{
MutexAutoLock lock(mMutex);
mJSSettings.content.options = aContentOptions;
mJSSettings.chrome.options = aChromeOptions;
}
nsRefPtr<UpdateJSContextOptionsRunnable> runnable =
new UpdateJSContextOptionsRunnable(ParentAsWorkerPrivate(), aOptions);
new UpdateJSContextOptionsRunnable(ParentAsWorkerPrivate(), aContentOptions,
aChromeOptions);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update worker context options!");
JS_ClearPendingException(aCx);
@ -2231,38 +2279,41 @@ WorkerPrivateParent<Derived>::UpdateJSWorkerMemoryParameter(JSContext* aCx,
uint32_t aValue)
{
AssertIsOnParentThread();
switch(aKey) {
case JSGC_ALLOCATION_THRESHOLD:
mJSWorkerAllocationThreshold = aValue;
break;
case JSGC_MAX_BYTES:
mJSRuntimeHeapSize = aValue;
break;
default:
break;
bool found = false;
{
MutexAutoLock lock(mMutex);
found = mJSSettings.ApplyGCSetting(aKey, aValue);
}
nsRefPtr<UpdateJSWorkerMemoryParameterRunnable> runnable =
new UpdateJSWorkerMemoryParameterRunnable(ParentAsWorkerPrivate(),
aKey,
aValue);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update memory parameter!");
JS_ClearPendingException(aCx);
if (found) {
nsRefPtr<UpdateJSWorkerMemoryParameterRunnable> runnable =
new UpdateJSWorkerMemoryParameterRunnable(ParentAsWorkerPrivate(), aKey,
aValue);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update memory parameter!");
JS_ClearPendingException(aCx);
}
}
}
#ifdef JS_GC_ZEAL
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal)
WorkerPrivateParent<Derived>::UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal,
uint32_t aFrequency)
{
AssertIsOnParentThread();
mGCZeal = aGCZeal;
{
MutexAutoLock lock(mMutex);
mJSSettings.gcZeal = aGCZeal;
mJSSettings.gcZealFrequency = aFrequency;
}
nsRefPtr<UpdateGCZealRunnable> runnable =
new UpdateGCZealRunnable(ParentAsWorkerPrivate(), aGCZeal);
new UpdateGCZealRunnable(ParentAsWorkerPrivate(), aGCZeal, aFrequency);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update worker gczeal!");
JS_ClearPendingException(aCx);
@ -2270,6 +2321,26 @@ WorkerPrivateParent<Derived>::UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal)
}
#endif
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateJITHardening(JSContext* aCx,
bool aJITHardening)
{
AssertIsOnParentThread();
{
MutexAutoLock lock(mMutex);
mJSSettings.jitHardening = aJITHardening;
}
nsRefPtr<UpdateJITHardeningRunnable> runnable =
new UpdateJITHardeningRunnable(ParentAsWorkerPrivate(), aJITHardening);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update worker jit hardening!");
JS_ClearPendingException(aCx);
}
}
template <class Derived>
void
WorkerPrivateParent<Derived>::GarbageCollect(JSContext* aCx, bool aShrinking)
@ -2752,11 +2823,6 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
}
}
#ifdef EXTRA_GC
// Find GC bugs...
JS_GC(aCx);
#endif
// Keep track of whether or not this is the idle GC event.
eventIsNotIdleGCEvent = event != idleGCEvent;
@ -2767,7 +2833,8 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
currentStatus = mStatus;
scheduleIdleGC = mControlQueue.IsEmpty() &&
mQueue.IsEmpty() &&
eventIsNotIdleGCEvent;
eventIsNotIdleGCEvent &&
JS_GetGlobalForScopeChain(aCx);
}
// Take care of the GC timer. If we're starting the close sequence then we
@ -2783,6 +2850,12 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
}
if (scheduleIdleGC) {
NS_ASSERTION(JS_GetGlobalForScopeChain(aCx), "Should have global here!");
// Now *might* be a good time to GC. Let the JS engine make the decision.
JSAutoCompartment ac(aCx, JS_GetGlobalForScopeChain(aCx));
JS_MaybeGC(aCx);
if (NS_SUCCEEDED(gcTimer->SetTarget(idleGCEventTarget)) &&
NS_SUCCEEDED(gcTimer->InitWithFuncCallback(
DummyCallback, nullptr,
@ -2794,11 +2867,6 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
}
}
#ifdef EXTRA_GC
// Find GC bugs...
JS_GC(aCx);
#endif
if (currentStatus != Running && !HasActiveFeatures()) {
// If the close handler has finished and all features are done then we can
// kill this thread.
@ -3462,19 +3530,9 @@ WorkerPrivate::RunSyncLoop(JSContext* aCx, uint32_t aSyncLoopKey)
}
}
#ifdef EXTRA_GC
// Find GC bugs...
JS_GC(mJSContext);
#endif
static_cast<nsIRunnable*>(event)->Run();
NS_RELEASE(event);
#ifdef EXTRA_GC
// Find GC bugs...
JS_GC(mJSContext);
#endif
if (syncQueue->mComplete) {
NS_ASSERTION(mSyncQueues.Length() - 1 == aSyncLoopKey,
"Mismatched calls!");
@ -3646,7 +3704,10 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
previousStatus == Terminating,
"Bad previous status!");
uint32_t killSeconds = RuntimeService::GetCloseHandlerTimeoutSeconds();
uint32_t killSeconds = IsChromeWorker() ?
RuntimeService::GetChromeCloseHandlerTimeoutSeconds() :
RuntimeService::GetContentCloseHandlerTimeoutSeconds();
if (killSeconds) {
mKillTime = TimeStamp::Now() + TimeDuration::FromSeconds(killSeconds);
@ -4061,14 +4122,17 @@ WorkerPrivate::RescheduleTimeoutTimer(JSContext* aCx)
}
void
WorkerPrivate::UpdateJSContextOptionsInternal(JSContext* aCx, uint32_t aOptions)
WorkerPrivate::UpdateJSContextOptionsInternal(JSContext* aCx,
uint32_t aContentOptions,
uint32_t aChromeOptions)
{
AssertIsOnWorkerThread();
JS_SetOptions(aCx, aOptions);
JS_SetOptions(aCx, IsChromeWorker() ? aChromeOptions : aContentOptions);
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateJSContextOptions(aCx, aOptions);
mChildWorkers[index]->UpdateJSContextOptions(aCx, aContentOptions,
aChromeOptions);
}
}
@ -4078,7 +4142,14 @@ WorkerPrivate::UpdateJSWorkerMemoryParameterInternal(JSContext* aCx,
uint32_t aValue)
{
AssertIsOnWorkerThread();
JS_SetGCParameter(JS_GetRuntime(aCx), aKey, aValue);
// XXX aValue might be 0 here (telling us to unset a previous value for child
// workers). Calling JS_SetGCParameter with a value of 0 isn't actually
// supported though. We really need some way to revert to a default value
// here.
if (aValue) {
JS_SetGCParameter(JS_GetRuntime(aCx), aKey, aValue);
}
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateJSWorkerMemoryParameter(aCx, aKey, aValue);
@ -4087,32 +4158,53 @@ WorkerPrivate::UpdateJSWorkerMemoryParameterInternal(JSContext* aCx,
#ifdef JS_GC_ZEAL
void
WorkerPrivate::UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal)
WorkerPrivate::UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
uint32_t aFrequency)
{
AssertIsOnWorkerThread();
uint32_t frequency = aGCZeal <= 2 ? JS_DEFAULT_ZEAL_FREQ : 1;
JS_SetGCZeal(aCx, aGCZeal, frequency);
JS_SetGCZeal(aCx, aGCZeal, aFrequency);
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateGCZeal(aCx, aGCZeal);
mChildWorkers[index]->UpdateGCZeal(aCx, aGCZeal, aFrequency);
}
}
#endif
void
WorkerPrivate::UpdateJITHardeningInternal(JSContext* aCx, bool aJITHardening)
{
AssertIsOnWorkerThread();
JS_SetJitHardening(JS_GetRuntime(aCx), aJITHardening);
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateJITHardening(aCx, aJITHardening);
}
}
void
WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
bool aCollectChildren)
{
AssertIsOnWorkerThread();
JSRuntime *rt = JS_GetRuntime(aCx);
JS::PrepareForFullGC(rt);
if (aShrinking) {
JS::ShrinkingGC(rt, JS::gcreason::DOM_WORKER);
if (aCollectChildren) {
JSRuntime* rt = JS_GetRuntime(aCx);
JS::PrepareForFullGC(rt);
if (aShrinking) {
JS::ShrinkingGC(rt, JS::gcreason::DOM_WORKER);
}
else {
JS::GCForReason(rt, JS::gcreason::DOM_WORKER);
}
}
else {
JS::GCForReason(rt, JS::gcreason::DOM_WORKER);
// If aCollectChildren is false then it means this collection request was
// not generated by the main thread. At the moment only the periodic GC
// timer can end up here, so rather than force a collection let the JS
// engine decide if we need one.
JS_MaybeGC(aCx);
}
if (aCollectChildren) {

Просмотреть файл

@ -42,7 +42,10 @@ class nsIURI;
class nsPIDOMWindow;
class nsITimer;
class nsIXPCScriptNotify;
namespace JS { struct RuntimeStats; }
namespace JS {
class RuntimeStats;
}
BEGIN_WORKERS_NAMESPACE
@ -109,7 +112,7 @@ protected:
void NotifyScriptExecutedIfNeeded() const;
private:
public:
NS_DECL_NSIRUNNABLE
};
@ -274,12 +277,11 @@ private:
// Only used for top level workers.
nsTArray<nsRefPtr<WorkerRunnable> > mQueuedRunnables;
// Protected by mMutex.
JSSettings mJSSettings;
uint64_t mBusyCount;
Status mParentStatus;
uint32_t mJSContextOptions;
uint32_t mJSRuntimeHeapSize;
uint32_t mJSWorkerAllocationThreshold;
uint8_t mGCZeal;
bool mJSObjectRooted;
bool mParentSuspended;
bool mIsChromeWorker;
@ -348,9 +350,12 @@ public:
bool
Suspend(JSContext* aCx);
bool
void
Resume(JSContext* aCx);
bool
SynchronizeAndResume(nsIScriptContext* aCx);
virtual void
_trace(JSTracer* aTrc) MOZ_OVERRIDE;
@ -391,16 +396,21 @@ public:
GetInnerWindowId();
void
UpdateJSContextOptions(JSContext* aCx, uint32_t aOptions);
UpdateJSContextOptions(JSContext* aCx, uint32_t aChromeOptions,
uint32_t aContentOptions);
void
UpdateJSWorkerMemoryParameter(JSContext* aCx, JSGCParamKey key, uint32_t value);
UpdateJSWorkerMemoryParameter(JSContext* aCx, JSGCParamKey key,
uint32_t value);
#ifdef JS_GC_ZEAL
void
UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal);
UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency);
#endif
void
UpdateJITHardening(JSContext* aCx, bool aJITHardening);
void
GarbageCollect(JSContext* aCx, bool aShrinking);
@ -577,32 +587,13 @@ public:
return mLocationInfo;
}
uint32_t
GetJSContextOptions() const
void
CopyJSSettings(JSSettings& aSettings)
{
return mJSContextOptions;
mozilla::MutexAutoLock lock(mMutex);
aSettings = mJSSettings;
}
uint32_t
GetJSRuntimeHeapSize() const
{
return mJSRuntimeHeapSize;
}
uint32_t
GetJSWorkerAllocationThreshold() const
{
return mJSWorkerAllocationThreshold;
}
#ifdef JS_GC_ZEAL
uint8_t
GetGCZeal() const
{
return mGCZeal;
}
#endif
bool
IsChromeWorker() const
{
@ -815,7 +806,8 @@ public:
}
void
UpdateJSContextOptionsInternal(JSContext* aCx, uint32_t aOptions);
UpdateJSContextOptionsInternal(JSContext* aCx, uint32_t aContentOptions,
uint32_t aChromeOptions);
void
UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue);
@ -840,9 +832,12 @@ public:
#ifdef JS_GC_ZEAL
void
UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal);
UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency);
#endif
void
UpdateJITHardeningInternal(JSContext* aCx, bool aJITHardening);
void
GarbageCollectInternal(JSContext* aCx, bool aShrinking,
bool aCollectChildren);

Просмотреть файл

@ -24,6 +24,7 @@
#define WORKERS_SHUTDOWN_TOPIC "web-workers-shutdown"
class nsIScriptContext;
class nsPIDOMWindow;
BEGIN_WORKERS_NAMESPACE
@ -42,10 +43,130 @@ AssertIsOnMainThread()
{ }
#endif
struct JSSettings
{
enum {
// All the GC parameters that we support.
JSSettings_JSGC_MAX_BYTES = 0,
JSSettings_JSGC_MAX_MALLOC_BYTES,
JSSettings_JSGC_HIGH_FREQUENCY_TIME_LIMIT,
JSSettings_JSGC_LOW_FREQUENCY_HEAP_GROWTH,
JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN,
JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX,
JSSettings_JSGC_HIGH_FREQUENCY_LOW_LIMIT,
JSSettings_JSGC_HIGH_FREQUENCY_HIGH_LIMIT,
JSSettings_JSGC_ANALYSIS_PURGE_TRIGGER,
JSSettings_JSGC_ALLOCATION_THRESHOLD,
JSSettings_JSGC_SLICE_TIME_BUDGET,
JSSettings_JSGC_DYNAMIC_HEAP_GROWTH,
JSSettings_JSGC_DYNAMIC_MARK_SLICE,
// JSGC_MODE not supported
// This must be last so that we get an accurate count.
kGCSettingsArraySize
};
struct JSGCSetting
{
JSGCParamKey key;
uint32_t value;
JSGCSetting()
: key(static_cast<JSGCParamKey>(-1)), value(0)
{ }
bool
IsSet() const
{
return key != static_cast<JSGCParamKey>(-1);
}
void
Unset()
{
key = static_cast<JSGCParamKey>(-1);
value = 0;
}
};
// There are several settings that we know we need so it makes sense to
// preallocate here.
typedef JSGCSetting JSGCSettingsArray[kGCSettingsArraySize];
// Settings that change based on chrome/content context.
struct JSContentChromeSettings
{
uint32_t options;
int32_t maxScriptRuntime;
JSContentChromeSettings()
: options(0), maxScriptRuntime(0)
{ }
};
JSContentChromeSettings chrome;
JSContentChromeSettings content;
JSGCSettingsArray gcSettings;
bool jitHardening;
#ifdef JS_GC_ZEAL
uint8_t gcZeal;
uint32_t gcZealFrequency;
#endif
JSSettings()
: jitHardening(false)
#ifdef JS_GC_ZEAL
, gcZeal(0), gcZealFrequency(0)
#endif
{
for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
new (gcSettings + index) JSGCSetting();
}
}
bool
ApplyGCSetting(JSGCParamKey aKey, uint32_t aValue)
{
JSSettings::JSGCSetting* firstEmptySetting = nullptr;
JSSettings::JSGCSetting* foundSetting = nullptr;
for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
JSSettings::JSGCSetting& setting = gcSettings[index];
if (setting.key == aKey) {
foundSetting = &setting;
break;
}
if (!firstEmptySetting && !setting.IsSet()) {
firstEmptySetting = &setting;
}
}
if (aValue) {
if (!foundSetting) {
foundSetting = firstEmptySetting;
if (!foundSetting) {
NS_ERROR("Not enough space for this value!");
return false;
}
}
foundSetting->key = aKey;
foundSetting->value = aValue;
return true;
}
if (foundSetting) {
foundSetting->Unset();
return true;
}
return false;
}
};
// All of these are implemented in RuntimeService.cpp
JSBool
ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
JS::MutableHandle<JSObject*> aObjp);
ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId,
unsigned aFlags, JS::MutableHandle<JSObject*> aObjp);
void
CancelWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
@ -54,7 +175,7 @@ void
SuspendWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
void
ResumeWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
ResumeWorkersForWindow(nsIScriptContext* aCx, nsPIDOMWindow* aWindow);
class WorkerTask {
public:

Просмотреть файл

@ -4,10 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsPermission.h"
#include "nsIClassInfoImpl.h"
// nsPermission Implementation
NS_IMPL_ISUPPORTS1(nsPermission, nsIPermission)
NS_IMPL_CLASSINFO(nsPermission, nullptr, 0, {0})
NS_IMPL_ISUPPORTS1_CI(nsPermission, nsIPermission)
nsPermission::nsPermission(const nsACString &aHost,
uint32_t aAppId,

Просмотреть файл

@ -618,8 +618,10 @@ nsPermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
aExpireType == nsIPermissionManager::EXPIRE_SESSION,
NS_ERROR_INVALID_ARG);
// Skip addition if the permission is already expired.
if (aExpireType == nsIPermissionManager::EXPIRE_TIME &&
// Skip addition if the permission is already expired. Note that EXPIRE_SESSION only
// honors expireTime if it is nonzero.
if ((aExpireType == nsIPermissionManager::EXPIRE_TIME ||
(aExpireType == nsIPermissionManager::EXPIRE_SESSION && aExpireTime != 0)) &&
aExpireTime <= (PR_Now() / 1000)) {
return NS_OK;
}
@ -702,7 +704,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
// only thing changed is the expire time.
if (aPermission == oldPermissionEntry.mPermission &&
aExpireType == oldPermissionEntry.mExpireType &&
(aExpireType != nsIPermissionManager::EXPIRE_TIME ||
(aExpireType == nsIPermissionManager::EXPIRE_NEVER ||
aExpireTime == oldPermissionEntry.mExpireTime))
op = eOperationNone;
else if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
@ -801,14 +803,16 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
aExpireType == nsIPermissionManager::EXPIRE_SESSION) {
entry->GetPermissions()[index].mNonSessionPermission = entry->GetPermissions()[index].mPermission;
entry->GetPermissions()[index].mNonSessionExpireType = entry->GetPermissions()[index].mExpireType;
entry->GetPermissions()[index].mNonSessionExpireTime = entry->GetPermissions()[index].mExpireTime;
} else if (aExpireType != nsIPermissionManager::EXPIRE_SESSION) {
entry->GetPermissions()[index].mNonSessionPermission = aPermission;
entry->GetPermissions()[index].mNonSessionExpireType = aExpireType;
entry->GetPermissions()[index].mExpireTime = aExpireTime;
entry->GetPermissions()[index].mNonSessionExpireTime = aExpireTime;
}
entry->GetPermissions()[index].mPermission = aPermission;
entry->GetPermissions()[index].mExpireType = aExpireType;
entry->GetPermissions()[index].mExpireTime = aExpireTime;
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
// We care only about the id, the permission and expireType/expireTime here.
@ -1018,6 +1022,63 @@ nsPermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
return CommonTestPermission(aPrincipal, aType, aPermission, false, true);
}
NS_IMETHODIMP
nsPermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
const char* aType,
bool aExactHostMatch,
nsIPermission** aResult)
{
NS_ENSURE_ARG_POINTER(aPrincipal);
NS_ENSURE_ARG_POINTER(aType);
*aResult = nullptr;
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
return NS_OK;
}
nsAutoCString host;
nsresult rv = GetHostForPrincipal(aPrincipal, host);
NS_ENSURE_SUCCESS(rv, rv);
int32_t typeIndex = GetTypeIndex(aType, false);
// If type == -1, the type isn't known,
// so just return NS_OK
if (typeIndex == -1) return NS_OK;
uint32_t appId;
rv = aPrincipal->GetAppId(&appId);
NS_ENSURE_SUCCESS(rv, rv);
bool isInBrowserElement;
rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
NS_ENSURE_SUCCESS(rv, rv);
PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement,
typeIndex, aExactHostMatch);
if (!entry) {
return NS_OK;
}
// We don't call GetPermission(typeIndex) because that returns a fake
// UNKNOWN_ACTION entry if there is no match.
int32_t idx = entry->GetPermissionIndex(typeIndex);
if (-1 == idx) {
return NS_OK;
}
PermissionEntry& perm = entry->GetPermissions()[idx];
nsCOMPtr<nsIPermission> r = new nsPermission(entry->GetKey()->mHost,
entry->GetKey()->mAppId,
entry->GetKey()->mIsInBrowserElement,
mTypeArray.ElementAt(perm.mType),
perm.mPermission,
perm.mExpireType,
perm.mExpireTime);
r.forget(aResult);
return NS_OK;
}
nsresult
nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal,
const char *aType,
@ -1086,7 +1147,10 @@ nsPermissionManager::GetPermissionHashKey(const nsACString& aHost,
PermissionEntry permEntry = entry->GetPermission(aType);
// if the entry is expired, remove and keep looking for others.
if (permEntry.mExpireType == nsIPermissionManager::EXPIRE_TIME &&
// Note that EXPIRE_SESSION only honors expireTime if it is nonzero.
if ((permEntry.mExpireType == nsIPermissionManager::EXPIRE_TIME ||
(permEntry.mExpireType == nsIPermissionManager::EXPIRE_SESSION &&
permEntry.mExpireTime != 0)) &&
permEntry.mExpireTime <= (PR_Now() / 1000)) {
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(GetPrincipal(aHost, aAppId, aIsInBrowserElement, getter_AddRefs(principal)))) {
@ -1318,6 +1382,7 @@ nsPermissionManager::RemoveExpiredPermissionsForAppEnumerator(
permEntry.mPermission = permEntry.mNonSessionPermission;
permEntry.mExpireType = permEntry.mNonSessionExpireType;
permEntry.mExpireTime = permEntry.mNonSessionExpireTime;
gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
entry->GetKey()->mAppId,

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
@ -45,6 +45,7 @@ public:
, mExpireTime(aExpireTime)
, mNonSessionPermission(aPermission)
, mNonSessionExpireType(aExpireType)
, mNonSessionExpireTime(aExpireTime)
{}
int64_t mID;
@ -54,6 +55,7 @@ public:
int64_t mExpireTime;
uint32_t mNonSessionPermission;
uint32_t mNonSessionExpireType;
uint32_t mNonSessionExpireTime;
};
/**

Просмотреть файл

@ -27,29 +27,41 @@ function do_run_test() {
// add a permission with *now* expiration
pm.addFromPrincipal(principal, "test/expiration-perm-exp", 1, pm.EXPIRE_TIME, now);
pm.addFromPrincipal(principal, "test/expiration-session-exp", 1, pm.EXPIRE_SESSION, now);
// add a permission with future expiration (100 milliseconds)
pm.addFromPrincipal(principal, "test/expiration-perm-exp2", 1, pm.EXPIRE_TIME, now + 100);
pm.addFromPrincipal(principal, "test/expiration-session-exp2", 1, pm.EXPIRE_SESSION, now + 100);
// add a permission with future expiration (1000 seconds)
pm.addFromPrincipal(principal, "test/expiration-perm-exp3", 1, pm.EXPIRE_TIME, now + 1e6);
pm.addFromPrincipal(principal, "test/expiration-session-exp3", 1, pm.EXPIRE_SESSION, now + 1e6);
// add a permission without expiration
pm.addFromPrincipal(principal, "test/expiration-perm-nexp", 1, pm.EXPIRE_NEVER, 0);
// check that the second two haven't expired yet
do_check_eq(1, pm.testPermissionFromPrincipal(principal, "test/expiration-perm-exp3"));
do_check_eq(1, pm.testPermissionFromPrincipal(principal, "test/expiration-session-exp3"));
do_check_eq(1, pm.testPermissionFromPrincipal(principal, "test/expiration-perm-nexp"));
// ... and the first one has
do_timeout(10, continue_test);
yield;
do_check_eq(0, pm.testPermissionFromPrincipal(principal, "test/expiration-perm-exp"));
do_check_eq(0, pm.testPermissionFromPrincipal(principal, "test/expiration-session-exp"));
// ... and that the short-term one will
do_timeout(200, continue_test);
yield;
do_check_eq(0, pm.testPermissionFromPrincipal(principal, "test/expiration-perm-exp2"));
do_check_eq(0, pm.testPermissionFromPrincipal(principal, "test/expiration-perm-exp2"));
do_check_eq(0, pm.testPermissionFromPrincipal(principal, "test/expiration-session-exp2"));
// Check that .getPermission returns a matching result
do_check_null(pm.getPermissionObject(principal, "test/expiration-perm-exp", false));
do_check_null(pm.getPermissionObject(principal, "test/expiration-session-exp", false));
do_check_null(pm.getPermissionObject(principal, "test/expiration-perm-exp2", false));
do_check_null(pm.getPermissionObject(principal, "test/expiration-session-exp2", false));
do_finish_generator_test(test_generator);
}

Просмотреть файл

@ -0,0 +1,94 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function getPrincipalFromURI(uri) {
return Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(NetUtil.newURI(uri));
}
function getSystemPrincipal() {
return Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getSystemPrincipal();
}
function run_test() {
var pm = Cc["@mozilla.org/permissionmanager;1"].
getService(Ci.nsIPermissionManager);
do_check_null(pm.getPermissionObject(getSystemPrincipal(), "test/pobject", false));
let principal = getPrincipalFromURI("http://example.com");
let subPrincipal = getPrincipalFromURI("http://sub.example.com");
let subSubPrincipal = getPrincipalFromURI("http://sub.sub.example.com");
do_check_null(pm.getPermissionObject(principal, "test/pobject", false));
do_check_null(pm.getPermissionObject(principal, "test/pobject", true));
pm.addFromPrincipal(principal, "test/pobject", pm.ALLOW_ACTION);
var rootPerm = pm.getPermissionObject(principal, "test/pobject", false);
do_check_true(rootPerm != null);
do_check_eq(rootPerm.host, "example.com");
do_check_eq(rootPerm.type, "test/pobject");
do_check_eq(rootPerm.capability, pm.ALLOW_ACTION);
do_check_eq(rootPerm.expireType, pm.EXPIRE_NEVER);
var rootPerm2 = pm.getPermissionObject(principal, "test/pobject", true);
do_check_true(rootPerm != null);
do_check_eq(rootPerm.host, "example.com");
var subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", true);
do_check_null(subPerm);
subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", false);
do_check_true(subPerm != null);
do_check_eq(subPerm.host, "example.com");
do_check_eq(subPerm.type, "test/pobject");
do_check_eq(subPerm.capability, pm.ALLOW_ACTION);
subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", true);
do_check_null(subPerm);
subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", false);
do_check_true(subPerm != null);
do_check_eq(subPerm.host, "example.com");
pm.addFromPrincipal(principal, "test/pobject", pm.DENY_ACTION, pm.EXPIRE_SESSION);
// make sure permission objects are not dynamic
do_check_eq(rootPerm.capability, pm.ALLOW_ACTION);
// but do update on change
rootPerm = pm.getPermissionObject(principal, "test/pobject", true);
do_check_eq(rootPerm.capability, pm.DENY_ACTION);
do_check_eq(rootPerm.expireType, pm.EXPIRE_SESSION);
subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", false);
do_check_eq(subPerm.host, "example.com");
do_check_eq(subPerm.capability, pm.DENY_ACTION);
do_check_eq(subPerm.expireType, pm.EXPIRE_SESSION);
pm.addFromPrincipal(subPrincipal, "test/pobject", pm.PROMPT_ACTION);
rootPerm = pm.getPermissionObject(principal, "test/pobject", true);
do_check_eq(rootPerm.host, "example.com");
do_check_eq(rootPerm.capability, pm.DENY_ACTION);
subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", true);
do_check_eq(subPerm.host, "sub.example.com");
do_check_eq(subPerm.capability, pm.PROMPT_ACTION);
subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", false);
do_check_eq(subPerm.host, "sub.example.com");
do_check_eq(subPerm.capability, pm.PROMPT_ACTION);
subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", true);
do_check_null(subPerm);
subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", false);
do_check_eq(subPerm.host, "sub.example.com");
do_check_eq(subPerm.capability, pm.PROMPT_ACTION);
pm.removeFromPrincipal(principal, "test/pobject");
rootPerm = pm.getPermissionObject(principal, "test/pobject", true);
do_check_null(rootPerm);
}

Просмотреть файл

@ -16,6 +16,7 @@ tail =
[test_domain_eviction.js]
[test_eviction.js]
[test_permmanager_expiration.js]
[test_permmanager_getPermissionObject.js]
[test_permmanager_notifications.js]
[test_permmanager_removeall.js]
[test_permmanager_load_invalid_entries.js]

Просмотреть файл

@ -9197,387 +9197,389 @@
> cookie/SM
18467a24273
> could've
19246c25052
19035a24842
> cul-de-sac
19246c25053
< cysteine
---
> cysteine/M
20196,20197c26002,26003
20196,20197c26003,26004
< dialog/SM
< dialogue/SM
---
> dialog/SMGD
> dialogue/SMRGD
20481a26288
20481a26289
> disclose/DSG
20830c26637
20830c26638
< dogie/M
---
> dogie/SM
20895a26703
20895a26704
> donator/MS
21820a27629
21820a27630
> elicitor/MS
22071a27881
22071a27882
> encyclopaedia
22556a28367
22556a28368
> estoppel
22638c28449
22638c28450
< euthanize
---
> euthanize/DSG
22719a28531
22719a28532
> exabyte/MS
22947a28760
22947a28761
> experimentalism
23207,23208d29019
23207,23208d29020
< faecal
< faeces/M
23215c29026
23215c29027
< faggoting's
---
> faggot/SMG
23701a29513
23701a29514
> filesystem/MS
24155c29967
24155c29968
< fluidized
---
> fluidize/DSG
24216a30029
24216a30030
> foci
24736d30548
24736d30549
< frier/M
24855,24856c30667,30668
24855,24856c30668,30669
< fucker/M!
< fuckhead/S!
---
> fucker/SM!
> fuckhead/SM!
24953d30764
24953d30765
< furore/MS
25125c30936
25125c30937
< gaolbird/S
---
> gaolbirds
25180d30990
25180d30991
< gasolene/M
25190a31001
25190a31002
> gastroenterologist/M
25262c31073
25262c31074
< geezer/M
---
> geezer/MS
25327c31138
25327c31139
< genomic
---
> genomic/S
25462a31274
25462a31275
> gigabit/MS
25464a31277,31279
25464a31278,31280
> gigajoule/MS
> gigapixel/MS
> gigawatt/MS
25560d31374
25560d31375
< glamourize/DSG
25674c31488
25674c31489
< glycerine's
---
> glycerine/M
25905c31719
25905c31720
< gram/MS
---
> gram/KMS
25909d31722
25909d31723
< gramme/SM
26063c31876,31877
26063c31877,31878
< greybeard
---
> grey/MDRTGSP
> greybeard/SM
26066c31880
26066c31881
< greyness
---
> greyness/M
26246,26247d32059
26246,26247d32060
< guerilla's
< guerillas
26432,26436d32243
26432,26436d32244
< haemoglobin's
< haemophilia/M
< haemorrhage/DSMG
< haemorrhoid/S
< haemorrhoids/M
27167c32974
27167c32975
< hexane
---
> hexane/SM
27273a33081
27273a33082
> hippopotami
27875d33682
27875d33683
< hyaena/SM
28017c33824
28017c33825
< iPod/M
---
> iPod/MS
28105a33913
28105a33914
> idolator/SM
28513c34321
28513c34322
< inbound
---
> inbound/s
28650a34459
28650a34460
> indices
28812d34620
28812d34621
< inflexion/SM
29216a35025
29216a35026
> intern/GDL
29272a35082,35085
29272a35083,35086
> intersex
> intersexual/MS
> intersexualism
> intersexuality
29724c35537
29724c35538
< jewellery's
---
> jewellery/M
29870a35684
29870a35685
> judgement/MS
30066c35880
30066c35881
< kiddie/M
---
> kiddie/SM
30262,30263c36076
30262,30263c36077
< kraut's
< kraut/S!
---
> kraut/MS!
30665a36479
30665a36480
> lector/MS
31031c36845
31031c36846
< linguini's
---
> linguini/M
31151,31152c36965
31151,31152c36966
< liver's
< liver/S
---
> liver/MS
32230c38043
32230c38044
< meanie/M
---
> meanie/MS
32317,32318c38130
32317,32318c38131
< megadeath/M
< megadeaths
---
> megadeath/SM
32320c38132
32320c38133
< megajoules
---
> megajoule/SM
32329c38141
32329c38142
< megapixel/S
---
> megapixel/MS
32708a38521
32708a38522
> might've
32777d38589
32777d38590
< millionnaire/M
32934a38747
32934a38748
> miscommunication/S
32991a38805
32991a38806
> misjudgement/MS
33784a39599
33784a39600
> must've
33963c39778
33963c39779
< native/MS
---
> native/MSY
34169,34171c39984,39985
34169,34171c39985,39986
< neurone/S
< neurophysiology
< neuroscience
---
> neurophysiology/M
> neuroscience/MS
34275c40089
34275c40090
< nightie/M
---
> nightie/SM
35104a40919
35104a40920
> octopi
35219d41033
35219d41034
< oleomargarin/M
35226a41041
35226a41042
> oligo
35913c41728
35913c41729
< oversize/D
---
> oversize
36056,36059d41870
36056,36059d41871
< paederast/S
< paediatrician's
< paediatricians
< paediatrics/M
36291a42103
36291a42104
> paralyses
36403d42214
36403d42215
< parrakeet/MS
36449d42259
36449d42260
< partizan/SM
37093a42904
37093a42905
> petabyte/MS
37102c42913
37102c42914
< petitioner/M
---
> petitioner/MS
37264a43076
37264a43077
> phosphorylate/DSGN
37316d43127
37316d43128
< phrenetic
37796a43608
37796a43609
> plugin/MS
37987c43799
37987c43800
< polypeptide/S
---
> polypeptide/MS
38291d44102
38291d44103
< practise's
38451a44263
38451a44264
> prejudgement/MS
38891a44704,44705
38891a44705,44706
> pronate/DSGN
> pronator/MS
38951c44765
38951c44766
< proprietorship/M
---
> proprietorship/MS
39039a44854
39039a44855
> provender/M
39564a45380
39564a45381
> quinoa
40036a45853
40036a45854
> recency
40141a45959
40141a45960
> recuse/DGS
40208a46027
40208a46028
> refactor/SMDG
40244d46062
40244d46063
< reflexion/SM
40829c46647
40829c46648
< reverie/M
---
> reverie/MS
41415a47234
41415a47235
> sabre/MS
41914c47733
41914c47734
< schnaps's
---
> schnaps/M
41949c47768
41949c47769
< schrod's
---
> schrod/SM
41998a47818
41998a47819
> scot-free
42883,42885c48703
42883,42885c48704
< shit's
< shit/S!
< shite/S!
---
> shit/MS!
42887,42888c48705,48706
42887,42888c48706,48707
< shithead/S!
< shitload/!
---
> shithead/MS!
> shitload/MS!
42891c48709
42891c48710
< shitty/RT!
---
> shitty/TR!
42976a48795
42976a48796
> should've
43008c48827
43008c48828
< showtime
---
> showtime/MS
43724,43726c49543
43724,43726c49544
< smoulder's
< smouldered
< smoulders
---
> smoulder/GSMD
44062c49879
44062c49880
< sonofabitch
---
> sonofabitch/!
44346a50164
44346a50165
> spelled
44348a50167
44348a50168
> spelt
44371a50191
44371a50192
> spick/S!
44383c50203
44383c50204
< spik/S
---
> spik/S!
46106a51927
46106a51928
> syllabi
46160c51981
46160c51982
< synch/GMD
---
> synch/GMDS
46167d51987
46167d51988
< synchs
46203,46204c52023,52024
46203,46204c52024,52025
< sysadmin/S
< sysop/S
---
> sysadmin/MS
> sysop/MS
46752a52573
46752a52574
> terabit/MS
46753a52575,52576
46753a52576,52577
> terahertz/M
> terapixel/MS
46817a52641
46817a52642
> testcase/MS
46831a52656
46831a52657
> testsuite/MS
46925a52751
46925a52752
> theremin/MS
47755a53582
47755a53583
> transfect/DSMG
47774a53602,53603
47774a53603,53604
> transgenderism
> transgene/MS
47951c53780
47951c53781
< triage/M
---
> triage/MG
48869a54699
48869a54700
> unlikeable
49211c55041
49211c55042
< vagina/M
---
> vagina/MS
49368,49369c55198
49368,49369c55199
< velour's
< velours's
---
> velour/MS
49478a55308
49478a55309
> vertices
50148a55979
50148a55980
> weaponize/DSG
50260,50261d56090
50260,50261d56091
< werwolf/M
< werwolves
50728c56557
50728c56558
< women
---
> women/M
50794c56623
50794c56624
< wop/S!
---
> wop/MS!

Просмотреть файл

@ -1,4 +1,4 @@
57445
57446
0/nm
0th/pt
1/n1
@ -25106,6 +25106,7 @@ cue/DSMG
cuff/MDGS
cufflink/SM
cuisine/SM
cul-de-sac
culinary
cull/MDGS
cullender/MS

Просмотреть файл

@ -385,18 +385,14 @@ GLScreenBuffer::Swap(const gfxIntSize& size)
{
SharedSurface* nextSurf = mStream->SwapProducer(mFactory, size);
if (!nextSurf) {
SurfaceFactory_GL* basicFactory =
new SurfaceFactory_Basic(mGL, mFactory->Caps());
nextSurf = mStream->SwapProducer(basicFactory, size);
if (!nextSurf) {
delete basicFactory;
return false;
}
SurfaceFactory_Basic basicFactory(mGL, mFactory->Caps());
nextSurf = mStream->SwapProducer(&basicFactory, size);
if (!nextSurf)
return false;
// Swap out the apparently defective old factory.
delete mFactory;
mFactory = basicFactory;
NS_WARNING("SwapProd failed for sophisticated Factory type, fell back to Basic.");
}
MOZ_ASSERT(nextSurf);
Attach(nextSurf, size);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше