merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-02-25 12:05:55 +01:00
commit 6ae1b98d2e
93 changed files with 1869 additions and 422 deletions

View File

@ -148,6 +148,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
"resource:///modules/ReaderParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonWatcher",
"resource://gre/modules/AddonWatcher.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -587,6 +590,76 @@ BrowserGlue.prototype = {
this._distributionCustomizer.applyPrefDefaults();
},
_notifySlowAddon: function BG_notifySlowAddon(addonId) {
let addonCallback = function(addon) {
if (!addon) {
Cu.reportError("couldn't look up addon: " + addonId);
return;
}
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win) {
return;
}
let brandBundle = win.document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
let message = win.gNavigatorBundle.getFormattedString("addonwatch.slow", [addon.name, brandShortName]);
let notificationBox = win.document.getElementById("global-notificationbox");
let notificationId = 'addon-slow:' + addonId;
let notification = notificationBox.getNotificationWithValue(notificationId);
if(notification) {
notification.label = message;
} else {
let buttons = [
{
label: win.gNavigatorBundle.getFormattedString("addonwatch.disable.label", [addon.name]),
accessKey: win.gNavigatorBundle.getString("addonwatch.disable.accesskey"),
callback: function() {
addon.userDisabled = true;
if (addon.pendingOperations != addon.PENDING_NONE) {
let restartMessage = win.gNavigatorBundle.getFormattedString("addonwatch.restart.message", [addon.name, brandShortName]);
let restartButton = [
{
label: win.gNavigatorBundle.getFormattedString("addonwatch.restart.label", [brandShortName]),
accessKey: win.gNavigatorBundle.getString("addonwatch.restart.accesskey"),
callback: function() {
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
.getService(Ci.nsIAppStartup);
appStartup.quit(appStartup.eForceQuit | appStartup.eRestart);
}
}
];
const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
notificationBox.appendNotification(restartMessage, "restart-" + addonId, "",
priority, restartButton);
}
}
},
{
label: win.gNavigatorBundle.getString("addonwatch.ignoreSession.label"),
accessKey: win.gNavigatorBundle.getString("addonwatch.ignoreSession.accesskey"),
callback: function() {
AddonWatcher.ignoreAddonForSession(addonId);
}
},
{
label: win.gNavigatorBundle.getString("addonwatch.ignorePerm.label"),
accessKey: win.gNavigatorBundle.getString("addonwatch.ignorePerm.accesskey"),
callback: function() {
AddonWatcher.ignoreAddonPermanently(addonId);
}
},
];
const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
notificationBox.appendNotification(message, notificationId, "",
priority, buttons);
}
};
AddonManager.getAddonByID(addonId, addonCallback);
},
// runs on startup, before the first command line handler is invoked
// (i.e. before the first window is opened)
_finalUIStartup: function BG__finalUIStartup() {
@ -642,6 +715,8 @@ BrowserGlue.prototype = {
#endif
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
AddonWatcher.init(this._notifySlowAddon);
},
_checkForOldBuildUpdates: function () {
@ -907,6 +982,7 @@ BrowserGlue.prototype = {
#endif
webrtcUI.uninit();
FormValidationHandler.uninit();
AddonWatcher.uninit();
},
_initServiceDiscovery: function () {

View File

@ -103,71 +103,45 @@ support-files =
[browser_dbg_aaa_run_first_leaktest.js]
skip-if = e10s && debug
[browser_dbg_addonactor.js]
skip-if = e10s && debug
[browser_dbg_addon-sources.js]
skip-if = e10s && debug
[browser_dbg_addon-modules.js]
skip-if = e10s # TODO
[browser_dbg_addon-modules-unpacked.js]
skip-if = e10s # TODO
[browser_dbg_addon-panels.js]
skip-if = e10s && debug
[browser_dbg_addon-console.js]
skip-if = e10s && debug || os == 'win' # bug 1005274
[browser_dbg_auto-pretty-print-01.js]
skip-if = e10s && debug
[browser_dbg_auto-pretty-print-02.js]
skip-if = e10s && debug
[browser_dbg_bfcache.js]
skip-if = e10s || true # bug 1113935
[browser_dbg_blackboxing-01.js]
skip-if = e10s && debug
[browser_dbg_blackboxing-02.js]
skip-if = e10s && debug
[browser_dbg_blackboxing-03.js]
skip-if = e10s && debug
[browser_dbg_blackboxing-04.js]
skip-if = e10s && debug
[browser_dbg_blackboxing-05.js]
skip-if = e10s && debug
[browser_dbg_blackboxing-06.js]
skip-if = e10s && debug
[browser_dbg_breadcrumbs-access.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-01.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-02.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-03.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-04.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-05.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-06.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-07.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-08.js]
skip-if = e10s && debug
[browser_dbg_break-on-dom-event-01.js]
skip-if = e10s || os == "mac" || e10s # Bug 895426
[browser_dbg_break-on-dom-event-02.js]
skip-if = e10s # TODO
[browser_dbg_breakpoints-actual-location.js]
skip-if = e10s && debug
[browser_dbg_breakpoints-actual-location2.js]
skip-if = e10s && debug
[browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js]
skip-if = e10s # Bug 1093535
[browser_dbg_breakpoints-button-01.js]
skip-if = e10s && debug
[browser_dbg_breakpoints-button-02.js]
skip-if = e10s && debug
[browser_dbg_breakpoints-contextmenu-add.js]
skip-if = e10s && debug
[browser_dbg_breakpoints-contextmenu.js]
skip-if = e10s && debug
[browser_dbg_breakpoints-disabled-reload.js]
skip-if = e10s # Bug 1093535
[browser_dbg_breakpoints-editor.js]

View File

@ -40,6 +40,17 @@ addonDownloadRestart=Restart Download;Restart Downloads
addonDownloadRestart.accessKey=R
addonDownloadCancelTooltip=Cancel
addonwatch.slow=%1$S might be making %2$S run slowly
addonwatch.disable.label=Disable %S
addonwatch.disable.accesskey=D
addonwatch.ignoreSession.label=Ignore for now
addonwatch.ignoreSession.accesskey=I
addonwatch.ignorePerm.label=Ignore permanently
addonwatch.ignorePerm.accesskey=p
addonwatch.restart.message=To disable %1$S you must restart %2$S
addonwatch.restart.label=Restart %S
addonwatch.restart.accesskey=R
# LOCALIZATION NOTE (addonsInstalled, addonsInstalledNeedsRestart):
# Semicolon-separated list of plural forms. See:
# http://developer.mozilla.org/en/docs/Localization_and_Plurals

View File

@ -42,16 +42,11 @@ endif
endif
# Put a useful .gdbinit in the bin directory, to be picked up automatically
# by GDB when we debug executables there.
# NOTE: Keep .gdbinit in the topsrcdir for people who run gdb from the topsrcdir.
GDBINIT_FILES := $(topsrcdir)/.gdbinit
GDBINIT_OBJDIR_FILES = $(topsrcdir)/.gdbinit
GDBINIT_DEST = $(FINAL_TARGET)
# needs to be absolute to be distinct from $(topsrcdir)/.gdbinit
GDBINIT_OBJDIR_FILES = $(topsrcdir)/.gdbinit
GDBINIT_OBJDIR_DEST = $(abspath $(DEPTH))
INSTALL_TARGETS += GDBINIT GDBINIT_OBJDIR
INSTALL_TARGETS += GDBINIT_OBJDIR
# Put a .lldbinit in the bin directory and the objdir, to be picked up
# automatically by LLDB when we debug executables using either of those two
@ -66,13 +61,6 @@ LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit
LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET)
INSTALL_TARGETS += LLDBINIT_FINAL_TARGET
ifeq (1_1,$(MOZ_ASAN)_$(CLANG_CL))
# Install the clang-cl runtime library for ASAN next to the binaries we produce.
CLANG_RT_ASAN_FILES := $(MOZ_CLANG_RT_ASAN_LIB_PATH)
CLANG_RT_ASAN_DEST = $(FINAL_TARGET)
INSTALL_TARGETS += CLANG_RT_ASAN
endif
ifdef MOZTTDIR
# Install the Firefox OS fonts.
include $(MOZTTDIR)/fonts.mk
@ -81,6 +69,19 @@ MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/
INSTALL_TARGETS += MOZTT
endif
ifdef MOZ_VALGRIND
_VALGRIND_DIR = $(DEPTH)/_valgrind
GARBAGE_DIRS += $(_VALGRIND_DIR)
_VALGRIND_FILES = \
$(topsrcdir)/build/valgrind/cross-architecture.sup \
$(topsrcdir)/build/valgrind/i386-redhat-linux-gnu.sup \
$(topsrcdir)/build/valgrind/x86_64-redhat-linux-gnu.sup \
$(NULL)
_VALGRIND_DEST = $(_VALGRIND_DIR)
INSTALL_TARGETS += _VALGRIND
endif
include $(topsrcdir)/config/rules.mk
TARGET_DEPTH = ..
@ -99,41 +100,6 @@ endif
libs:: automation.py
ifdef MOZ_VALGRIND
_VALGRIND_DIR = $(DEPTH)/_valgrind
GARBAGE_DIRS += $(_VALGRIND_DIR)
_VALGRIND_FILES = \
$(topsrcdir)/build/valgrind/cross-architecture.sup \
$(topsrcdir)/build/valgrind/i386-redhat-linux-gnu.sup \
$(topsrcdir)/build/valgrind/x86_64-redhat-linux-gnu.sup \
$(NULL)
libs:: $(_VALGRIND_FILES)
$(INSTALL) $^ $(_VALGRIND_DIR)
endif
ifneq (,$(ENABLE_TESTS)$(MOZ_DMD))
libs:: $(topsrcdir)/tools/rb/fix_stack_using_bpsyms.py
$(INSTALL) $< $(DIST)/bin
ifeq ($(OS_ARCH),Darwin)
libs:: $(topsrcdir)/tools/rb/fix_macosx_stack.py
$(INSTALL) $< $(DIST)/bin
endif
ifeq ($(OS_ARCH),Linux)
libs:: $(topsrcdir)/tools/rb/fix_linux_stack.py
$(INSTALL) $< $(DIST)/bin
endif
endif # ENABLE_TESTS or MOZ_DMD
ifdef ENABLE_TESTS
GARBAGE += $(srcdir)/automationutils.pyc
endif # ENABLE_TESTS
ifdef MOZ_DMD
libs:: $(topsrcdir)/memory/replace/dmd/dmd.py
$(INSTALL) $< $(DIST)/bin
endif

View File

@ -445,7 +445,7 @@ class ShutdownLeaks(object):
self.leakedWindows = {}
self.leakedDocShells = set()
self.currentTest = None
self.seenShutdown = False
self.seenShutdown = set()
def log(self, message):
if message['action'] == 'log':
@ -454,8 +454,9 @@ class ShutdownLeaks(object):
self._logWindow(line)
elif line[2:10] == "DOCSHELL":
self._logDocShell(line)
elif line.startswith("TEST-START | Shutdown"):
self.seenShutdown = True
elif line.startswith("Completed ShutdownLeaks collections in process"):
pid = int(line.split()[-1])
self.seenShutdown.add(pid)
elif message['action'] == 'test_start':
fileName = message['test'].replace("chrome://mochitests/content/browser/", "")
self.currentTest = {"fileName": fileName, "windows": set(), "docShells": set()}
@ -499,7 +500,7 @@ class ShutdownLeaks(object):
windows.add(key)
else:
windows.discard(key)
elif self.seenShutdown and not created:
elif int(pid) in self.seenShutdown and not created:
self.leakedWindows[key] = self._parseValue(line, "url")
def _logDocShell(self, line):
@ -520,7 +521,7 @@ class ShutdownLeaks(object):
docShells.add(key)
else:
docShells.discard(key)
elif self.seenShutdown and not created:
elif int(pid) in self.seenShutdown and not created:
self.leakedDocShells.add(key)
def _parseValue(self, line, name):

View File

@ -48,3 +48,22 @@ if CONFIG['MOZ_BUILD_APP'] == 'browser':
PYTHON_UNIT_TESTS += [
'compare-mozconfig/compare-mozconfigs-wrapper.py',
]
if CONFIG['ENABLE_TESTS'] or CONFIG['MOZ_DMD']:
tools_dir = TOPSRCDIR + '/tools/rb/'
FINAL_TARGET_FILES += [tools_dir + 'fix_stack_using_bpsyms.py']
if CONFIG['OS_ARCH'] == 'Darwin':
FINAL_TARGET_FILES += [tools_dir + 'fix_macosx_stack.py']
if CONFIG['OS_ARCH'] == 'Linux':
FINAL_TARGET_FILES += [tools_dir + 'fix_linux_stack.py']
if CONFIG['MOZ_DMD']:
FINAL_TARGET_FILES += [TOPSRCDIR + '/memory/replace/dmd/dmd.py']
# Put a useful .gdbinit in the bin directory, to be picked up automatically
# by GDB when we debug executables there.
FINAL_TARGET_FILES += [TOPSRCDIR + '/.gdbinit']
# Install the clang-cl runtime library for ASAN next to the binaries we produce.
if CONFIG['MOZ_ASAN'] and CONFIG['CLANG_CL']:
FINAL_TARGET_FILES += [CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']]

View File

@ -17,6 +17,7 @@ XPIDL_MODULE = 'caps'
EXPORTS += [
'nsJSPrincipals.h',
'nsNullPrincipal.h',
'nsNullPrincipalURI.h',
]
UNIFIED_SOURCES += [
@ -36,6 +37,8 @@ LOCAL_INCLUDES += [
'/js/xpconnect/src',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 sts=2 ts=2 et tw=80: */
/* 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/. */
@ -86,6 +87,24 @@ nsNullPrincipal::Init(uint32_t aAppId, bool aInMozBrowser)
mAppId = aAppId;
mInMozBrowser = aInMozBrowser;
nsCString str;
nsresult rv = GenerateNullPrincipalURI(str);
NS_ENSURE_SUCCESS(rv, rv);
mURI = new nsNullPrincipalURI(str);
return NS_OK;
}
void
nsNullPrincipal::GetScriptLocation(nsACString &aStr)
{
mURI->GetSpec(aStr);
}
nsresult
nsNullPrincipal::GenerateNullPrincipalURI(nsACString &aStr)
{
// FIXME: bug 327161 -- make sure the uuid generator is reseeding-resistant.
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen =
@ -104,28 +123,19 @@ nsNullPrincipal::Init(uint32_t aAppId, bool aInMozBrowser)
// Use an nsCString so we only do the allocation once here and then share
// with nsJSPrincipals
nsCString str;
str.SetCapacity(prefixLen + suffixLen);
aStr.SetCapacity(prefixLen + suffixLen);
str.Append(NS_NULLPRINCIPAL_PREFIX);
str.Append(chars);
aStr.Append(NS_NULLPRINCIPAL_PREFIX);
aStr.Append(chars);
if (str.Length() != prefixLen + suffixLen) {
if (aStr.Length() != prefixLen + suffixLen) {
NS_WARNING("Out of memory allocating null-principal URI");
return NS_ERROR_OUT_OF_MEMORY;
}
mURI = new nsNullPrincipalURI(str);
return NS_OK;
}
void
nsNullPrincipal::GetScriptLocation(nsACString &aStr)
{
mURI->GetSpec(aStr);
}
#ifdef DEBUG
void nsNullPrincipal::dumpImpl()
{

View File

@ -31,7 +31,7 @@ class nsNullPrincipal MOZ_FINAL : public nsJSPrincipals
{
public:
nsNullPrincipal();
// Our refcount is managed by nsJSPrincipals. Use this macro to avoid an
// extra refcount member.
@ -49,6 +49,8 @@ public:
virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
static nsresult GenerateNullPrincipalURI(nsACString &aStr);
#ifdef DEBUG
virtual void dumpImpl() MOZ_OVERRIDE;
#endif

View File

@ -9,6 +9,8 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/ipc/URIParams.h"
#include "nsNetUtil.h"
#include "nsEscape.h"
#include "nsCRT.h"
@ -17,6 +19,12 @@
//// nsNullPrincipalURI
nsNullPrincipalURI::nsNullPrincipalURI(const nsCString &aSpec)
{
InitializeFromSpec(aSpec);
}
void
nsNullPrincipalURI::InitializeFromSpec(const nsCString &aSpec)
{
int32_t dividerPosition = aSpec.FindChar(':');
NS_ASSERTION(dividerPosition != -1, "Malformed URI!");
@ -44,6 +52,7 @@ NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
else
NS_INTERFACE_MAP_ENTRY(nsIURI)
NS_INTERFACE_MAP_ENTRY(nsISizeOf)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
NS_INTERFACE_MAP_END
////////////////////////////////////////////////////////////////////////////////
@ -272,6 +281,31 @@ nsNullPrincipalURI::SchemeIs(const char *aScheme, bool *_schemeIs)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// nsIIPCSerializableURI
void
nsNullPrincipalURI::Serialize(mozilla::ipc::URIParams &aParams)
{
aParams = mozilla::ipc::NullPrincipalURIParams();
}
bool
nsNullPrincipalURI::Deserialize(const mozilla::ipc::URIParams &aParams)
{
if (aParams.type() != mozilla::ipc::URIParams::TNullPrincipalURIParams) {
MOZ_ASSERT_UNREACHABLE("unexpected URIParams type");
return false;
}
nsCString str;
nsresult rv = nsNullPrincipal::GenerateNullPrincipalURI(str);
NS_ENSURE_SUCCESS(rv, false);
InitializeFromSpec(str);
return true;
}
////////////////////////////////////////////////////////////////////////////////
//// nsISizeOf

View File

@ -16,6 +16,7 @@
#include "nsAutoPtr.h"
#include "nsString.h"
#include "mozilla/Attributes.h"
#include "nsIIPCSerializableURI.h"
#include "mozilla/MemoryReporting.h"
// {51fcd543-3b52-41f7-b91b-6b54102236e6}
@ -25,10 +26,12 @@
class nsNullPrincipalURI MOZ_FINAL : public nsIURI
, public nsISizeOf
, public nsIIPCSerializableURI
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURI
NS_DECL_NSIIPCSERIALIZABLEURI
// nsISizeOf
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
@ -36,9 +39,14 @@ public:
explicit nsNullPrincipalURI(const nsCString &aSpec);
// NB: This constructor exists only for deserialization.
nsNullPrincipalURI() { }
private:
~nsNullPrincipalURI() {}
void InitializeFromSpec(const nsCString &aSpec);
nsCString mScheme;
nsCString mPath;
};

View File

@ -13,13 +13,11 @@
# Valid fields for all descriptors:
# * nativeType - The native type (concrete class or XPCOM interface) that
# instances of this interface will unwrap to. If not
# specified, defaults to 'mozilla::dom::InterfaceName' for
# non-worker non-external-or-callback interfaces, to
# specified, defaults to 'nsIDOM' followed by the interface
# name for external interfaces,
# 'mozilla::dom::workers::InterfaceName' for worker
# non-external interfaces, to 'nsIDOM' followed by the
# interface name for non-worker external-or-callback
# interfaces, and to 'JSObject' for worker external-or-callback
# interfaces.
# non-callback interfaces, and 'mozilla::dom::InterfaceName'
# for everything else.
# * headerFile - The file in which the nativeType is declared (defaults
# to an educated guess).
# * concrete - Indicates whether there exist JS objects with this interface as
@ -31,6 +29,7 @@
# will not be made available on the main thread.
# * notflattened - The native type does not have nsIClassInfo, so when
# wrapping it the right IID needs to be passed in.
# Only relevant for callback interfaces.
# * register - True if this binding should be registered. Defaults to true.
# * binaryNames - Dict for mapping method and attribute names to different
# names when calling the native methods (defaults to an empty
@ -606,14 +605,10 @@ DOMInterfaces = {
'headerFile': 'IDBEvents.h',
},
'IID': [
{
'IID': {
'nativeType': 'nsIJSID',
'headerFile': 'xpcjsid.h',
},
{
'workers': True,
}],
'ImageCapture': {
'binaryNames': { 'videoStreamTrack': 'GetVideoStreamTrack' }
@ -623,14 +618,10 @@ DOMInterfaces = {
'wrapperCache': False,
},
'InputStream': [
{
'InputStream': {
'nativeType': 'nsIInputStream',
'notflattened': True
},
{
'workers': True,
}],
'InstallEvent': {
'headerFile': 'ServiceWorkerEvents.h',
@ -1484,16 +1475,10 @@ DOMInterfaces = {
},
},
'WindowProxy': [
{
'WindowProxy': {
'nativeType': 'nsIDOMWindow',
'concrete': False
},
{
# We need a worker descriptor for WindowProxy because EventTarget exists in
# workers. But it's an external interface, so it'll just map to JSObject*.
'workers': True
}],
'WindowRoot': {
'nativeType': 'nsWindowRoot'

View File

@ -381,7 +381,7 @@ class CGDOMJSClass(CGThing):
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS"
traceHook = "JS_GlobalObjectTraceHook"
reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS"
if not self.descriptor.workers:
if self.descriptor.interface.identifier.name == "Window":
classExtensionAndObjectOps = fill(
"""
{
@ -4635,10 +4635,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
descriptor = descriptorProvider.getDescriptor(
type.unroll().inner.identifier.name)
if descriptor.nativeType == 'JSObject':
# XXXbz Workers code does this sometimes
assert descriptor.workers
return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
assert descriptor.nativeType != 'JSObject'
if descriptor.interface.isCallback():
name = descriptor.interface.identifier.name
@ -4715,9 +4712,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
exceptionCode,
isCallbackReturnValue,
firstCap(sourceDescription)))
elif descriptor.workers:
return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
else:
# Worker descriptors can't end up here, because all of our
# "external" stuff is not exposed in workers.
assert not descriptor.workers
# Either external, or new-binding non-castable. We always have a
# holder for these, because we don't actually know whether we have
# to addref when unwrapping or not. So we just pass an

View File

@ -305,10 +305,8 @@ class Descriptor(DescriptorProvider):
# Read the desc, and fill in the relevant defaults.
ifaceName = self.interface.identifier.name
if self.interface.isExternal():
if self.workers:
nativeTypeDefault = "JSObject"
else:
nativeTypeDefault = "nsIDOM" + ifaceName
assert not self.workers
nativeTypeDefault = "nsIDOM" + ifaceName
elif self.interface.isCallback():
nativeTypeDefault = "mozilla::dom::" + ifaceName
else:

View File

@ -1852,6 +1852,12 @@ WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
return ok;
}
size_t mozilla::RoundUpToMultipleOf(size_t value, size_t multiple)
{
size_t overshoot = value + multiple - 1;
return overshoot - (overshoot % multiple);
}
////////////////////////////////////////////////////////////////////////////////
WebGLContext::ScopedMaskWorkaround::ScopedMaskWorkaround(WebGLContext& webgl)
@ -1875,6 +1881,7 @@ WebGLContext::ScopedMaskWorkaround::~ScopedMaskWorkaround()
mWebGL.mColorWriteMask[3]);
}
}
////////////////////////////////////////////////////////////////////////////////
// XPCOM goop

View File

@ -1092,9 +1092,7 @@ protected:
GLenum pname);
// Returns x rounded to the next highest multiple of y.
static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x,
CheckedUint32 y)
{
static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
return ((x + y - 1) / y) * y;
}
@ -1693,6 +1691,8 @@ private:
WebGLContext* mWebGL;
};
size_t RoundUpToMultipleOf(size_t value, size_t multiple);
} // namespace mozilla
#endif

View File

@ -49,8 +49,8 @@ WebGLContext::Clear(GLbitfield mask)
mShouldPresent = true;
}
static GLclampf
GLClampFloat(GLclampf val)
static GLfloat
GLClampFloat(GLfloat val)
{
if (val < 0.0)
return 0.0;
@ -62,18 +62,28 @@ GLClampFloat(GLclampf val)
}
void
WebGLContext::ClearColor(GLclampf r, GLclampf g,
GLclampf b, GLclampf a)
WebGLContext::ClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
if (IsContextLost())
return;
MakeContextCurrent();
mColorClearValue[0] = GLClampFloat(r);
mColorClearValue[1] = GLClampFloat(g);
mColorClearValue[2] = GLClampFloat(b);
mColorClearValue[3] = GLClampFloat(a);
const bool supportsFloatColorBuffers = (IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float) ||
IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float));
if (!supportsFloatColorBuffers) {
r = GLClampFloat(r);
g = GLClampFloat(g);
b = GLClampFloat(b);
a = GLClampFloat(a);
}
gl->fClearColor(r, g, b, a);
mColorClearValue[0] = r;
mColorClearValue[1] = g;
mColorClearValue[2] = b;
mColorClearValue[3] = a;
}
void

View File

@ -1863,6 +1863,84 @@ SetFullAlpha(void* data, GLenum format, GLenum type, size_t width,
return false;
}
static void
ReadPixelsAndConvert(gl::GLContext* gl, GLint x, GLint y, GLsizei width, GLsizei height,
GLenum readFormat, GLenum readType, size_t pixelStorePackAlignment,
GLenum destFormat, GLenum destType, void* destBytes)
{
if (readFormat == destFormat && readType == destType) {
gl->fReadPixels(x, y, width, height, destFormat, destType, destBytes);
return;
}
if (readFormat == LOCAL_GL_RGBA &&
readType == LOCAL_GL_HALF_FLOAT &&
destFormat == LOCAL_GL_RGBA &&
destType == LOCAL_GL_FLOAT)
{
size_t readBytesPerPixel = sizeof(uint16_t) * 4;
size_t destBytesPerPixel = sizeof(float) * 4;
size_t readBytesPerRow = readBytesPerPixel * width;
size_t readStride = RoundUpToMultipleOf(readBytesPerRow, pixelStorePackAlignment);
size_t destStride = RoundUpToMultipleOf(destBytesPerPixel * width,
pixelStorePackAlignment);
size_t bytesNeeded = ((height - 1) * readStride) + readBytesPerRow;
UniquePtr<uint8_t[]> readBuffer(new uint8_t[bytesNeeded]);
gl->fReadPixels(x, y, width, height, readFormat, readType, readBuffer.get());
size_t channelsPerRow = width * 4;
for (size_t j = 0; j < (size_t)height; j++) {
uint16_t* src = (uint16_t*)(readBuffer.get()) + j*readStride;
float* dst = (float*)(destBytes) + j*destStride;
uint16_t* srcEnd = src + channelsPerRow;
while (src != srcEnd) {
*dst = unpackFromFloat16(*src);
++src;
++dst;
}
}
return;
}
MOZ_CRASH("bad format/type");
}
static bool
IsFormatAndTypeUnpackable(GLenum format, GLenum type)
{
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_FLOAT:
case LOCAL_GL_HALF_FLOAT:
case LOCAL_GL_HALF_FLOAT_OES:
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_RGB:
case LOCAL_GL_RGBA:
return true;
default:
return false;
}
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
return format == LOCAL_GL_RGBA;
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
return format == LOCAL_GL_RGB;
default:
return false;
}
}
void
WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
GLsizei height, GLenum format,
@ -1883,59 +1961,61 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (pixels.IsNull())
return ErrorInvalidValue("readPixels: null destination buffer");
if (!IsFormatAndTypeUnpackable(format, type))
return ErrorInvalidEnum("readPixels: Bad format or type.");
const WebGLRectangleObject* framebufferRect = CurValidReadFBRectObject();
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
uint32_t channels = 0;
int channels = 0;
// Check the format param
switch (format) {
case LOCAL_GL_ALPHA:
channels = 1;
break;
case LOCAL_GL_RGB:
channels = 3;
break;
case LOCAL_GL_RGBA:
channels = 4;
break;
default:
return ErrorInvalidEnum("readPixels: Bad format");
case LOCAL_GL_ALPHA:
channels = 1;
break;
case LOCAL_GL_RGB:
channels = 3;
break;
case LOCAL_GL_RGBA:
channels = 4;
break;
default:
MOZ_CRASH("bad `format`");
}
uint32_t bytesPerPixel = 0;
int requiredDataType = 0;
// Check the type param
bool isReadTypeValid = false;
bool isReadTypeFloat = false;
int bytesPerPixel;
int requiredDataType;
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
isReadTypeValid = true;
bytesPerPixel = 1*channels;
requiredDataType = js::Scalar::Uint8;
break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
isReadTypeValid = true;
bytesPerPixel = 2;
requiredDataType = js::Scalar::Uint16;
break;
case LOCAL_GL_FLOAT:
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float) ||
IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float))
{
isReadTypeValid = true;
isReadTypeFloat = true;
bytesPerPixel = 4*channels;
requiredDataType = js::Scalar::Float32;
}
break;
case LOCAL_GL_UNSIGNED_BYTE:
bytesPerPixel = 1*channels;
requiredDataType = js::Scalar::Uint8;
break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
bytesPerPixel = 2;
requiredDataType = js::Scalar::Uint16;
break;
case LOCAL_GL_FLOAT:
bytesPerPixel = 4*channels;
requiredDataType = js::Scalar::Float32;
break;
case LOCAL_GL_HALF_FLOAT:
case LOCAL_GL_HALF_FLOAT_OES:
bytesPerPixel = 2*channels;
requiredDataType = js::Scalar::Uint16;
break;
default:
MOZ_CRASH("bad `type`");
}
if (!isReadTypeValid)
return ErrorInvalidEnum("readPixels: Bad type", type);
const ArrayBufferView& pixbuf = pixels.Value();
int dataType = JS_GetArrayBufferViewType(pixbuf.Obj());
@ -1988,43 +2068,38 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
isSourceTypeFloat = false;
}
if (isReadTypeFloat != isSourceTypeFloat)
return ErrorInvalidOperation("readPixels: Invalid type floatness");
// Check the format and type params to assure they are an acceptable pair (as per spec)
bool isFormatAndTypeValid = false;
const GLenum mainReadFormat = LOCAL_GL_RGBA;
const GLenum mainReadType = isSourceTypeFloat ? LOCAL_GL_FLOAT
: LOCAL_GL_UNSIGNED_BYTE;
GLenum auxReadFormat = mainReadFormat;
GLenum auxReadType = mainReadType;
// OpenGL ES 2.0 $4.3.1 - IMPLEMENTATION_COLOR_READ_{TYPE/FORMAT} is a valid
// combination for glReadPixels().
if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
GLenum implType = 0;
GLenum implFormat = 0;
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE,
reinterpret_cast<GLint*>(&implType));
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT,
reinterpret_cast<GLint*>(&implFormat));
if (type == implType && format == implFormat) {
isFormatAndTypeValid = true;
}
reinterpret_cast<GLint*>(&auxReadFormat));
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE,
reinterpret_cast<GLint*>(&auxReadType));
}
switch (format) {
case LOCAL_GL_RGBA: {
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_FLOAT:
isFormatAndTypeValid = true;
break;
}
break;
}
}
if (!isFormatAndTypeValid) {
const bool mainMatches = (format == mainReadFormat && type == mainReadType);
const bool auxMatches = (format == auxReadFormat && type == auxReadType);
const bool isValid = mainMatches || auxMatches;
if (!isValid)
return ErrorInvalidOperation("readPixels: Invalid format/type pair");
GLenum readType = type;
if (gl->WorkAroundDriverBugs() && gl->IsANGLE()) {
if (type == LOCAL_GL_FLOAT &&
auxReadFormat == format &&
auxReadType == LOCAL_GL_HALF_FLOAT)
{
readType = auxReadType;
}
}
// Now that the errors are out of the way, on to actually reading
@ -2035,7 +2110,10 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, framebufferWidth, framebufferHeight)) {
// the easy case: we're not reading out-of-range pixels
gl->fReadPixels(x, y, width, height, format, type, data);
// Effectively: gl->fReadPixels(x, y, width, height, format, type, dest);
ReadPixelsAndConvert(gl, x, y, width, height, format, readType,
mPixelStorePackAlignment, format, type, data);
} else {
// the rectangle doesn't fit entirely in the bound buffer. We then have to set to zero the part
// of the buffer that correspond to out-of-range pixels. We don't want to rely on system OpenGL
@ -2084,8 +2162,11 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (!subrect_data)
return ErrorOutOfMemory("readPixels: subrect_data");
gl->fReadPixels(subrect_x, subrect_y, subrect_width, subrect_height,
format, type, subrect_data.get());
// Effectively: gl->fReadPixels(subrect_x, subrect_y, subrect_width,
// subrect_height, format, type, subrect_data.get());
ReadPixelsAndConvert(gl, subrect_x, subrect_y, subrect_width, subrect_height,
format, readType, mPixelStorePackAlignment, format, type,
subrect_data.get());
// notice that this for loop terminates because we already checked that subrect_height is at most height
for (GLint y_inside_subrect = 0; y_inside_subrect < subrect_height; ++y_inside_subrect) {
@ -3597,7 +3678,7 @@ mozilla::GetWebGLTexelFormat(TexInternalFormat effectiveInternalFormat)
}
void
WebGLContext::BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
WebGLContext::BlendColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
if (IsContextLost())
return;
MakeContextCurrent();

View File

@ -266,6 +266,16 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::NumberValue(uint32_t(i));
}
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
if (mBoundReadFramebuffer) {
FBStatus status = mBoundReadFramebuffer->CheckFramebufferStatus();
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
ErrorInvalidOperation("getParameter: Read framebuffer must be"
" complete before querying"
" IMPLEMENTATION_COLOR_READ_TYPE.");
return JS::NullValue();
}
}
GLint i = 0;
if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
gl->fGetIntegerv(pname, &i);
@ -275,6 +285,16 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::NumberValue(uint32_t(i));
}
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
if (mBoundReadFramebuffer) {
FBStatus status = mBoundReadFramebuffer->CheckFramebufferStatus();
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
ErrorInvalidOperation("getParameter: Read framebuffer must be"
" complete before querying"
" IMPLEMENTATION_COLOR_READ_FORMAT.");
return JS::NullValue();
}
}
GLint i = 0;
if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
gl->fGetIntegerv(pname, &i);

View File

@ -26,7 +26,8 @@ WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* webgl)
gl::GLContext* gl = webgl->GL();
// ANGLE doesn't support ReadPixels from a RGBA16F with RGBA/FLOAT.
return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float);
return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float) ||
gl->IsANGLE();
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat)

View File

@ -129,6 +129,7 @@ WebGLFramebuffer::Attachment::IsReadableFloat() const
MOZ_ASSERT(internalformat != LOCAL_GL_NONE);
TexType type = TypeFromInternalFormat(internalformat);
return type == LOCAL_GL_FLOAT ||
type == LOCAL_GL_HALF_FLOAT_OES ||
type == LOCAL_GL_HALF_FLOAT;
}
@ -803,6 +804,7 @@ WebGLFramebuffer::CheckFramebufferStatus() const
// Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
FinalizeAttachments();
// TODO: This should not be unconditionally GL_FRAMEBUFFER.
mStatus = mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
return mStatus;
}

View File

@ -105,7 +105,7 @@ unpackFromFloat16(uint16_t v)
uint16_t exp = (v >> 10) & 0x001F;
uint16_t mantissa = v & 0x03FF;
if (exp) {
if (!exp) {
// Handle denormalized numbers
// Adapted from: OpenGL ES 2.0 Programming Guide Appx.
// Converting Float to Half-Float

View File

@ -22,6 +22,8 @@ skip-if = android_version == '10' #Android 2.3 aws only; bug 1030942
[webgl-mochitest/test_texsubimage_float.html]
[webgl-mochitest/test_webgl_available.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
#[webgl-mochitest/test_webgl_color_buffer_float.html]
# We haven't cleaned up the Try results yet, but let's get this on the books first.
[webgl-mochitest/test_webgl_conformance.html]
skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl_request_context.html]

View File

@ -0,0 +1,486 @@
<html>
<head>
<meta charset='UTF-8'>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
</head>
<body>
<script id='vs' type='x-shader/x-vertex'>
attribute vec2 aVertCoord;
void main(void) {
gl_Position = vec4(aVertCoord, 0.0, 1.0);
}
</script>
<script id='fs' type='x-shader/x-fragment'>
precision mediump float; // 💩
uniform vec4 uFragColor;
void main(void) {
gl_FragColor = uFragColor;
}
</script>
<canvas id='c' width='200' height='200'></canvas>
<script>
function GetGLSLByElemId(elemId) {
var elem = document.getElementById(elemId);
if (!elem)
throw 'Bad `elemId`: ' + elemId;
return elem.innerHTML.trim();
}
function ProgramByElemIds(gl, vsId, fsId) {
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, GetGLSLByElemId(vsId));
gl.compileShader(vs);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, GetGLSLByElemId(fsId));
gl.compileShader(fs);
var prog = gl.createProgram();
gl.attachShader(prog, vs);
gl.attachShader(prog, fs);
gl.linkProgram(prog);
var success = gl.getProgramParameter(prog, gl.LINK_STATUS);
if (success)
return prog;
console.log('Error linking program for \'' + vsId + '\' and \'' + fsId + '\'.');
console.log('\nLink log: ' + gl.getProgramInfoLog(prog));
console.log('\nVert shader log: ' + gl.getShaderInfoLog(vs));
console.log('\nFrag shader log: ' + gl.getShaderInfoLog(fs));
return null;
}
var RGBA = 0x1908;
var UNSIGNED_BYTE = 0x1401;
var FLOAT = 0x1406;
var HALF_FLOAT_OES = 0x8D61;
var HALF_FLOAT = 0x140B;
var RGBA4 = 0x8056;
var RGBA8 = 0x8058;
var RGBA32F = 0x8814;
var RGBA16F = 0x881A;
function EnumName(val) {
switch (val) {
case RGBA:
return 'RGBA';
case UNSIGNED_BYTE:
return 'UNSIGNED_BYTE';
case FLOAT:
return 'FLOAT';
case HALF_FLOAT_OES:
return 'HALF_FLOAT_OES';
case HALF_FLOAT:
return 'HALF_FLOAT';
case RGBA4:
return 'RGBA4';
case RGBA32F:
return 'RGBA32F';
default:
throw 'Unknown enum: 0x' + val.toString(16);
}
}
var gl;
function RGBAToString(arr) {
return '[' + arr[0].toPrecision(4) + ', ' +
arr[1].toPrecision(4) + ', ' +
arr[2].toPrecision(4) + ', ' +
arr[3].toPrecision(4) + ']';
}
function TestScreenColor(gl, isFBFloat, r, g, b, a) {
var readType = isFBFloat ? FLOAT : UNSIGNED_BYTE;
var arr;
switch (readType) {
case gl.UNSIGNED_BYTE:
arr = new Uint8Array(4);
break;
case gl.FLOAT:
arr = new Float32Array(4);
break;
default:
throw 'Bad `readType`.';
}
gl.readPixels(0, 0, 1, 1, gl.RGBA, readType, arr);
var err = gl.getError();
ok(err == 0, 'Should be no errors.');
if (err)
return;
var floatArr;
switch (readType) {
case gl.UNSIGNED_BYTE:
floatArr = new Float32Array(4);
floatArr[0] = arr[0] / 255.0;
floatArr[1] = arr[1] / 255.0;
floatArr[2] = arr[2] / 255.0;
floatArr[3] = arr[3] / 255.0;
break;
case gl.FLOAT:
floatArr = arr;
break;
default:
throw 'Bad `readType`.';
}
var testText = RGBAToString(floatArr);
var refText = RGBAToString([r, g, b, a]);
var eps = 1.0 / 255.0;
var isSame = (Math.abs(floatArr[0] - r) < eps &&
Math.abs(floatArr[1] - g) < eps &&
Math.abs(floatArr[2] - b) < eps &&
Math.abs(floatArr[3] - a) < eps);
ok(isSame, 'Should be ' + refText + ', was ' + testText + ',');
}
function TestReadFormat(gl, isFBFloat, format, type) {
var err = gl.getError();
if (err) {
ok(false, 'Should be no error at start of TestReadFormat(). (0x' + err.toString(16) + ')');
return;
}
var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
var err = gl.getError();
if (err) {
ok(false, 'Should be no error at start2 of TestReadFormat(). (0x' + err.toString(16) + ')');
return;
}
var defaultReadType = isFBFloat ? FLOAT : UNSIGNED_BYTE;
var formatOk = (format == gl.RGBA &&
type == defaultReadType);
if (format == implFormat &&
type == implType)
{
formatOk = true;
}
var w = 1;
var h = 1;
var channels = 4;
var arrSize = w * h * channels;
var arr;
switch (type) {
case UNSIGNED_BYTE:
arr = new Uint8Array(arrSize);
break;
case FLOAT:
arr = new Float32Array(arrSize);
break;
case HALF_FLOAT_OES:
case HALF_FLOAT:
arr = new Uint16Array(arrSize);
break;
default:
throw 'Bad `type`: 0x' + type.toString(16);
}
gl.readPixels(0, 0, 1, 1, format, type, arr);
var wasOk = gl.getError() == 0;
var text = 'Should ' + (formatOk ? '' : 'not ') + 'allow reading with ' +
EnumName(format) + '/' + EnumName(type) + '.'
ok(wasOk == formatOk, text);
}
function TestError(gl, expectedErr, descText) {
var err = gl.getError();
while (gl.getError()) {}
ok(err == expectedErr,
descText + ': Error should be 0x' + expectedErr.toString(16) + ', was 0x' +
err.toString(16) + '.');
return err;
}
function AttachRBToCurFB(gl, sizedFormat) {
var isSupported;
switch (sizedFormat) {
case RGBA4:
isSupported = true;
break;
case RGBA16F:
isSupported = !!gl.getExtension('EXT_color_buffer_half_float');
break;
case RGBA32F:
isSupported = !!gl.getExtension('WEBGL_color_buffer_float');
break;
default:
throw 'Bad `sizedFormat`.';
}
var rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, sizedFormat, 1, 1);
var correctError = isSupported ? 0 : gl.INVALID_ENUM;
var err = TestError(gl, correctError, 'RB specification with supported format');
if (err)
return false;
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
var isComplete = (status == gl.FRAMEBUFFER_COMPLETE);
ok(isComplete, 'Framebuffer should be complete after RB attachment.');
return isComplete;
}
function AttachTexToCurFB(gl, sizedFormat) {
var canCreate;
var isAttachGuaranteed;
var format;
var type;
switch (sizedFormat) {
case RGBA8:
canCreate = true;
isAttachGuaranteed = true;
format = RGBA;
type = UNSIGNED_BYTE;
break;
case RGBA16F:
canCreate = !!gl.getExtension('OES_texture_half_float');
isAttachGuaranteed = !!gl.getExtension('EXT_color_buffer_half_float');
format = RGBA;
type = HALF_FLOAT_OES;
break;
case RGBA32F:
canCreate = !!gl.getExtension('OES_texture_float');
isAttachGuaranteed = !!gl.getExtension('WEBGL_color_buffer_float');
format = RGBA;
type = FLOAT;
break;
default:
throw 'Bad `sizedFormat`.';
}
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, format, 1, 1, 0, format, type, null);
var correctError = canCreate ? 0 : gl.INVALID_ENUM;
var err = TestError(gl, correctError, 'Tex specification with supported format');
if (err)
return false;
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
var isComplete = (status == gl.FRAMEBUFFER_COMPLETE);
if (!isAttachGuaranteed && !isComplete)
todo(false, 'Framebuffer needn\'t be complete after tex attachment.');
else
ok(isComplete, 'Framebuffer should be complete after tex attachment.');
return isComplete;
}
function IsFormatFloat(sizedFormat) {
switch (sizedFormat) {
case RGBA4:
case RGBA8:
return false;
case RGBA16F:
case RGBA32F:
return true;
default:
throw 'Bad `sizedFormat`.';
}
}
function TestType(gl, prog, isTex, sizedFormat) {
TestError(gl, 0, 'At start of TestRB()');
var isAttached = isTex ? AttachTexToCurFB(gl, sizedFormat)
: AttachRBToCurFB(gl, sizedFormat);
if (!isAttached)
return;
var isFormatFloat = IsFormatFloat(sizedFormat);
TestReadFormat(gl, isFormatFloat, gl.RGBA, gl.UNSIGNED_BYTE);
TestReadFormat(gl, isFormatFloat, gl.RGBA, gl.FLOAT);
TestReadFormat(gl, isFormatFloat, gl.RGBA, HALF_FLOAT);
TestReadFormat(gl, isFormatFloat, gl.RGBA, HALF_FLOAT_OES);
//////////////////////////////////////
ok(true, 'Drawing:');
gl.clearColor(0.0, 1.5, 0.5, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
if (isFormatFloat)
TestScreenColor(gl, isFormatFloat, 0, 1.5, 0.5, 1);
else
TestScreenColor(gl, isFormatFloat, 0, 1, 0.5, 1);
////////
ok(true, 'Clearing:');
gl.uniform4f(prog.uFragColor, 0, 0.5, 1.5, 1);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
if (isFormatFloat)
TestScreenColor(gl, isFormatFloat, 0, 0.5, 1.5, 1);
else
TestScreenColor(gl, isFormatFloat, 0, 0.5, 1.0, 1);
////////
ok(true, 'Blending:');
gl.enable(gl.BLEND);
gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
gl.blendColor(0, 10, 0.1, 1);
gl.uniform4f(prog.uFragColor, 0, 0.5, 15.0, 1);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
if (isFormatFloat)
TestScreenColor(gl, isFormatFloat, 0, 5.0, 1.5, 1);
else
TestScreenColor(gl, isFormatFloat, 0, 0.5, 0.1, 1);
gl.disable(gl.BLEND);
//////////////////////////////////////
}
// Give ourselves a scope to return early from:
(function() {
var canvas = document.getElementById('c');
var attribs = {
antialias: false,
depth: false,
};
gl = canvas.getContext('experimental-webgl', attribs);
if (!gl) {
todo(false, 'WebGL is unavailable.');
return;
}
var cbf = gl.getExtension('WEBGL_color_buffer_float');
var cbhf = gl.getExtension('EXT_color_buffer_half_float');
//////////////////////////////////////
gl.viewport(0, 0, 1, 1);
var prog = ProgramByElemIds(gl, 'vs', 'fs');
ok(prog, 'Program should link.');
if (!prog)
return;
prog.aVertCoord = gl.getAttribLocation(prog, 'aVertCoord');
prog.uFragColor = gl.getUniformLocation(prog, 'uFragColor');
gl.useProgram(prog);
var arr = new Float32Array([
-1, -1,
1, -1,
-1, 1,
1, 1,
]);
var vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, arr, gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
//////////////////////////////////////
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
error = gl.getError();
ok(error == 0, 'Should be no errors after setup. (0x' + error.toString(16) + ')');
//////////////////////////////////////
ok(true, '---------------------------------------------------------------------------');
ok(true, 'RGBA8 texture');
TestType(gl, prog, true, RGBA8);
ok(true, '---------------------------------------------------------------------------');
ok(true, 'RGBA16F texture');
TestType(gl, prog, true, RGBA16F);
ok(true, '---------------------------------------------------------------------------');
ok(true, 'RGBA32F texture');
TestType(gl, prog, true, RGBA32F);
////////
ok(true, '---------------------------------------------------------------------------');
ok(true, 'RGBA4 renderbuffer');
TestType(gl, prog, false, RGBA4);
ok(true, '---------------------------------------------------------------------------');
ok(true, 'RGBA16F renderbuffer');
TestType(gl, prog, false, RGBA16F);
ok(true, '---------------------------------------------------------------------------');
ok(true, 'RGBA32F renderbuffer');
TestType(gl, prog, false, RGBA32F);
ok(true, '---------------------------------------------------------------------------');
//////////////////////////////////////
error = gl.getError();
ok(error == 0, 'Should be no errors after test.');
ok(true, 'TEST COMPLETE');
})();
</script>
</body>
</html>

View File

@ -4,6 +4,8 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
[test_blob_sliced_from_parent_process.html]
# This test is only supposed to run in the main process.
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
[test_cpow_cookies.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
[test_NuwaProcessCreation.html]
skip-if = toolkit != 'gonk'
[test_NuwaProcessDeadlock.html]

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for recursive CPOW-getting-cookie bug</title>
<script type="application/javascript"
src="/tests/SimpleTest/SimpleTest.js">
</script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.8">
"use strict";
SimpleTest.waitForExplicitFinish();
const childFrameURL =
"data:text/html,<!DOCTYPE HTML><html><body></body></html>";
function childFrameScript() {
"use strict";
const Ci = Components.interfaces;
function test1(message) {
// NB: This is a no-op because we're a data: document with a null
// principal.
content.document.cookie = "a=b";
message.target.sendAsyncMessage("testCPOWCookies:test1Finished", { pass: true });
}
addMessageListener("testCPOWCookies:test1", function(message) {
test1(message);
});
}
let test;
function* testStructure(mm) {
let lastResult;
function testDone(msg) {
test.next(msg.data);
}
mm.addMessageListener("testCPOWCookies:test1Finished", testDone);
mm.sendAsyncMessage("testCPOWCookies:test1", {});
lastResult = yield;
ok(lastResult.pass, "got the right answer and didn't crash");
SimpleTest.finish();
}
function runTests() {
info("Browser prefs set.");
let iframe = document.createElement("iframe");
SpecialPowers.wrap(iframe).mozbrowser = true;
iframe.id = "iframe";
iframe.src = childFrameURL;
iframe.addEventListener("mozbrowserloadend", function() {
info("Got iframe load event.");
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.loadFrameScript("data:,(" + encodeURI(childFrameScript.toString()) + ")();",
false);
test = testStructure(mm);
test.next();
});
document.body.appendChild(iframe);
}
addEventListener("load", function() {
info("Got load event.");
SpecialPowers.addPermission("browser", true, document);
SpecialPowers.pushPrefEnv({
"set": [
["dom.ipc.browser_frames.oop_by_default", true],
["dom.mozBrowserFramesEnabled", true],
["browser.pagethumbnails.capturing_disabled", true]
]
}, runTests);
});
</script>
</body>
</html>

View File

@ -43,6 +43,6 @@ partial interface EventTarget {
// chrome easier. This returns the window which can be used to create
// events to fire at this EventTarget, or null if there isn't one.
partial interface EventTarget {
[ChromeOnly]
[ChromeOnly, Exposed=Window]
readonly attribute WindowProxy? ownerGlobal;
};

View File

@ -520,7 +520,7 @@ interface WebGLRenderingContext {
void bindFramebuffer(GLenum target, WebGLFramebuffer? framebuffer);
void bindRenderbuffer(GLenum target, WebGLRenderbuffer? renderbuffer);
void bindTexture(GLenum target, WebGLTexture? texture);
void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void blendEquation(GLenum mode);
void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
void blendFunc(GLenum sfactor, GLenum dfactor);
@ -535,7 +535,7 @@ interface WebGLRenderingContext {
[WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target);
void clear(GLbitfield mask);
void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void clearDepth(GLclampf depth);
void clearStencil(GLint s);
void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);

View File

@ -42,55 +42,21 @@ NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(nsIDOMWindow *parent,
nsIObserver *openDialogObserver,
bool *notifyOnOpen)
{
m_observer = openDialogObserver;
nsresult rv = NS_ERROR_FAILURE;
if (m_dialog)
return NS_ERROR_ALREADY_INITIALIZED;
if (!dialogURL || !*dialogURL)
return NS_ERROR_INVALID_ARG;
if (parent)
{
// Set up window.arguments[0]...
nsCOMPtr<nsISupportsArray> array;
rv = NS_NewISupportsArray(getter_AddRefs(array));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
ifptr->SetData(static_cast<nsIPrintProgress*>(this));
ifptr->SetDataIID(&NS_GET_IID(nsIPrintProgress));
array->AppendElement(ifptr);
array->AppendElement(parameters);
// Open the dialog.
nsCOMPtr<nsIDOMWindow> newWindow;
rv = parent->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
if (NS_SUCCEEDED(rv)) {
*notifyOnOpen = true;
}
}
return rv;
MOZ_ASSERT_UNREACHABLE("The nsPrintingPromptService::ShowProgress "
"implementation for OS X returns "
"NS_ERROR_NOT_IMPLEMENTED, so we should never get "
"here.");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void closeProgressDialog (in boolean forceClose); */
NS_IMETHODIMP nsPrintProgress::CloseProgressDialog(bool forceClose)
{
m_closeProgress = true;
// XXX Casting bool to nsresult
return OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP,
static_cast<nsresult>(forceClose));
MOZ_ASSERT_UNREACHABLE("The nsPrintingPromptService::ShowProgress "
"implementation for OS X returns "
"NS_ERROR_NOT_IMPLEMENTED, so we should never get "
"here.");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIPrompt GetPrompter (); */

View File

@ -6,10 +6,16 @@
#include "nsPrintProgress.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsISupportsArray.h"
#include "nsIXULWindow.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsPIDOMWindow.h"
NS_IMPL_ADDREF(nsPrintProgress)
NS_IMPL_RELEASE(nsPrintProgress)
@ -71,12 +77,29 @@ NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(nsIDOMWindow *parent,
array->AppendElement(parameters);
// We will set the opener of the dialog to be the nsIDOMWindow for the
// browser XUL window itself, as opposed to the content. That way, the
// progress window has access to the opener.
nsCOMPtr<nsPIDOMWindow> pParentWindow = do_QueryInterface(parent);
NS_ENSURE_STATE(pParentWindow);
nsCOMPtr<nsIDocShell> docShell = pParentWindow->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsIDocShellTreeOwner> owner;
docShell->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIXULWindow> ownerXULWindow = do_GetInterface(owner);
nsCOMPtr<nsIDOMWindow> ownerWindow = do_GetInterface(ownerXULWindow);
NS_ENSURE_STATE(ownerWindow);
// Open the dialog.
nsCOMPtr<nsIDOMWindow> newWindow;
rv = parent->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
rv = ownerWindow->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
}
return rv;

View File

@ -6,11 +6,16 @@
#include "nsPrintProgress.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsISupportsArray.h"
#include "nsIXULWindow.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsPIDOMWindow.h"
#if 0
NS_IMPL_ADDREF(nsPrintProgress)
@ -100,12 +105,28 @@ NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(nsIDOMWindow *parent,
array->AppendElement(parameters);
// We will set the opener of the dialog to be the nsIDOMWindow for the
// browser XUL window itself, as opposed to the content. That way, the
// progress window has access to the opener.
nsCOMPtr<nsPIDOMWindow> pParentWindow = do_QueryInterface(parent);
NS_ENSURE_STATE(pParentWindow);
nsCOMPtr<nsIDocShell> docShell = pParentWindow->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsIDocShellTreeOwner> owner;
docShell->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIXULWindow> ownerXULWindow = do_GetInterface(owner);
nsCOMPtr<nsIDOMWindow> ownerWindow = do_GetInterface(ownerXULWindow);
NS_ENSURE_STATE(ownerWindow);
// Open the dialog.
nsCOMPtr<nsIDOMWindow> newWindow;
rv = parent->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
rv = ownerWindow->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
}
return rv;

View File

@ -1166,6 +1166,8 @@ public:
// This is a little hacky at the moment, but we want to have this data. Bug 1068613.
static void SetLogForwarder(LogForwarder* aLogFwd);
static uint32_t GetMaxSurfaceSize(BackendType aType);
static LogForwarder* GetLogForwarder() { return mLogForwarder; }
private:

View File

@ -111,8 +111,8 @@ struct BaseRect {
Sub result;
result.x = std::max<T>(x, aRect.x);
result.y = std::max<T>(y, aRect.y);
result.width = std::min<T>(XMost(), aRect.XMost()) - result.x;
result.height = std::min<T>(YMost(), aRect.YMost()) - result.y;
result.width = std::min<T>(x - result.x + width, aRect.x - result.x + aRect.width);
result.height = std::min<T>(y - result.y + height, aRect.y - result.y + aRect.height);
if (result.width < 0 || result.height < 0) {
result.SizeTo(0, 0);
}

View File

@ -1693,10 +1693,11 @@ DrawTargetCG::Init(BackendType aType,
{
// XXX: we should come up with some consistent semantics for dealing
// with zero area drawtargets
if (aSize.width <= 0 || aSize.height <= 0 ||
// 32767 is the maximum size supported by cairo
// we clamp to that to make it easier to interoperate
aSize.width > 32767 || aSize.height > 32767) {
if (aSize.width <= 0 ||
aSize.height <= 0 ||
size_t(aSize.width) > GetMaxSurfaceSize() ||
size_t(aSize.height) > GetMaxSurfaceSize())
{
gfxWarning() << "Failed to Init() DrawTargetCG because of bad size.";
mColorSpace = nullptr;
mCg = nullptr;

View File

@ -183,6 +183,13 @@ public:
CGContextRef GetCGContext() {
return mCg;
}
// 32767 is the maximum size supported by cairo. We clamp to that to make it
// easier to interoperate.
static size_t GetMaxSurfaceSize() {
return 32767;
}
private:
void MarkChanged();

View File

@ -170,6 +170,11 @@ public:
static cairo_surface_t *GetDummySurface();
// Cairo hardcodes this as its maximum surface size.
static size_t GetMaxSurfaceSize() {
return 32767;
}
private: // methods
// Init cairo surface without doing a cairo_surface_reference() call.
bool InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr);

View File

@ -145,6 +145,10 @@ public:
static IDWriteFactory *GetDWriteFactory();
ID2D1RenderTarget *GetRT() { return mRT; }
static uint32_t GetMaxSurfaceSize() {
return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
}
operator std::string() const {
std::stringstream stream;
stream << "DrawTargetD2D(" << this << ")";

View File

@ -144,6 +144,10 @@ public:
return stream.str();
}
static uint32_t GetMaxSurfaceSize() {
return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
}
static uint64_t mVRAMUsageDT;
static uint64_t mVRAMUsageSS;

View File

@ -449,6 +449,30 @@ Factory::DoesBackendSupportDataDrawtarget(BackendType aType)
return false;
}
uint32_t
Factory::GetMaxSurfaceSize(BackendType aType)
{
switch (aType) {
case BackendType::CAIRO:
case BackendType::COREGRAPHICS:
return DrawTargetCairo::GetMaxSurfaceSize();
#ifdef XP_MACOSX
case BackendType::COREGRAPHICS_ACCELERATED:
return DrawTargetCG::GetMaxSurfaceSize();
#endif
case BackendType::SKIA:
return INT_MAX;
#ifdef WIN32
case BackendType::DIRECT2D:
return DrawTargetD2D::GetMaxSurfaceSize();
case BackendType::DIRECT2D1_1:
return DrawTargetD2D1::GetMaxSurfaceSize();
#endif
default:
return 0;
}
}
TemporaryRef<ScaledFont>
Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize)
{

View File

@ -295,7 +295,7 @@ void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLcla
if (context)
{
context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
context->getState().setBlendColor(red, green, blue, alpha);
}
}

View File

@ -886,7 +886,7 @@ public:
AFTER_GL_CALL;
}
void fBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
void fBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
BEFORE_GL_CALL;
mSymbols.fBlendColor(red, green, blue, alpha);
AFTER_GL_CALL;
@ -986,7 +986,7 @@ public:
AFTER_GL_CALL;
}
void fClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
void fClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
BEFORE_GL_CALL;
mSymbols.fClearColor(r, g, b, a);
AFTER_GL_CALL;

View File

@ -49,7 +49,7 @@ struct GLContextSymbols
PFNGLBINDTEXTUREPROC fBindTexture;
typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array);
PFNGLBINDVERTEXARRAYPROC fBindVertexArray;
typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
PFNGLBLENDCOLORPROC fBlendColor;
typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode);
PFNGLBLENDEQUATIONPROC fBlendEquation;
@ -73,7 +73,7 @@ struct GLContextSymbols
PFNGLCLEARBUFFERIVPROC fClearBufferiv;
typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint* value);
PFNGLCLEARBUFFERUIVPROC fClearBufferuiv;
typedef void (GLAPIENTRY * PFNGLCLEARCOLORPROC) (GLclampf, GLclampf, GLclampf, GLclampf);
typedef void (GLAPIENTRY * PFNGLCLEARCOLORPROC) (GLfloat, GLfloat, GLfloat, GLfloat);
PFNGLCLEARCOLORPROC fClearColor;
typedef void (GLAPIENTRY * PFNGLCLEARSTENCILPROC) (GLint);
PFNGLCLEARSTENCILPROC fClearStencil;

View File

@ -67,6 +67,9 @@ BasicCompositor::BasicCompositor(nsIWidget *aWidget)
{
MOZ_COUNT_CTOR(BasicCompositor);
SetBackend(LayersBackend::LAYERS_BASIC);
mMaxTextureSize =
Factory::GetMaxSurfaceSize(gfxPlatform::GetPlatform()->GetContentBackend());
}
BasicCompositor::~BasicCompositor()
@ -74,6 +77,12 @@ BasicCompositor::~BasicCompositor()
MOZ_COUNT_DTOR(BasicCompositor);
}
int32_t
BasicCompositor::GetMaxTextureSize() const
{
return mMaxTextureSize;
}
void
BasicCompositingRenderTarget::BindRenderTarget()
{

View File

@ -103,7 +103,7 @@ public:
virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE { return true; }
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE { return true; }
virtual int32_t GetMaxTextureSize() const MOZ_OVERRIDE { return INT32_MAX; }
virtual int32_t GetMaxTextureSize() const MOZ_OVERRIDE;
virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE { }
virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) MOZ_OVERRIDE {
@ -140,6 +140,8 @@ private:
gfx::IntRect mInvalidRect;
nsIntRegion mInvalidRegion;
uint32_t mMaxTextureSize;
};
} // namespace layers

View File

@ -219,6 +219,12 @@ ClientTiledPaintedLayer::IsScrollingOnCompositor(const FrameMetrics& aParentMetr
bool
ClientTiledPaintedLayer::UseFastPath()
{
// The fast path doesn't allow rendering at low resolution. It will draw the low-res
// area at full resolution and cause OOM.
if (gfxPrefs::UseLowPrecisionBuffer()) {
return false;
}
LayerMetricsWrapper scrollAncestor;
GetAncestorLayers(&scrollAncestor, nullptr);
if (!scrollAncestor) {
@ -227,16 +233,35 @@ ClientTiledPaintedLayer::UseFastPath()
const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint()
|| gfxPrefs::UseLowPrecisionBuffer()
|| !parentMetrics.GetCriticalDisplayPort().IsEmpty();
bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition();
bool isScrollable = parentMetrics.IsScrollable();
return !multipleTransactionsNeeded || isFixed || !isScrollable
#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
|| !IsScrollingOnCompositor(parentMetrics)
return !multipleTransactionsNeeded || isFixed || !isScrollable;
}
bool
ClientTiledPaintedLayer::UseProgressiveDraw() {
// Don't draw progressively in a reftest scenario (that's what the HasShadowTarget() check is for).
if (!gfxPlatform::GetPlatform()->UseProgressivePaint() || ClientManager()->HasShadowTarget()) {
return false;
}
// XXX We probably want to disable progressive drawing for non active APZ layers in the future
// but we should wait for a proper test case before making this change.
#if 0 //!defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
LayerMetricsWrapper scrollAncestor;
GetAncestorLayers(&scrollAncestor, nullptr);
if (!scrollAncestor) {
return true;
}
const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
return !IsScrollingOnCompositor(parentMetrics);
#else
return true;
#endif
;
}
bool
@ -251,10 +276,8 @@ ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
return false;
}
// Only draw progressively when the resolution is unchanged, and we're not
// in a reftest scenario (that's what the HasShadowManager() check is for).
if (gfxPlatform::GetPlatform()->UseProgressivePaint() &&
!ClientManager()->HasShadowTarget() &&
// Only draw progressively when the resolution is unchanged
if (UseProgressiveDraw() &&
mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
@ -418,36 +441,20 @@ ClientTiledPaintedLayer::RenderLayer()
ToClientLayer(GetMaskLayer())->RenderLayer();
}
// For more complex cases we need to calculate a bunch of metrics before we
// can do the paint.
BeginPaint();
if (mPaintData.mPaintFinished) {
return;
}
// In some cases we can take a fast path and just be done with it.
if (UseFastPath()) {
TILING_LOG("TILING %p: Taking fast-path\n", this);
mValidRegion = neededRegion;
// Make sure that tiles that fall outside of the visible region or outside of the
// critical displayport are discarded on the first update. Also make sure that we
// only draw stuff inside the critical displayport on the first update.
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
}
if (invalidRegion.IsEmpty()) {
EndPaint();
return;
}
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
ClientManager()->Hold(this);
mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
EndPaint();
return;
}
// For more complex cases we need to calculate a bunch of metrics before we
// can do the paint.
BeginPaint();
if (mPaintData.mPaintFinished) {
return;
}

View File

@ -106,6 +106,13 @@ private:
*/
bool IsScrollingOnCompositor(const FrameMetrics& aParentMetrics);
/**
* Check if we should use progressive draw on this layer. We will
* disable progressive draw based on a preference or if the layer
* is not being scrolled.
*/
bool UseProgressiveDraw();
/**
* Helper function to do the high-precision paint.
* This function returns true if it updated the paint buffer.

View File

@ -745,7 +745,7 @@ BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFla
}
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
if (!Allocate(bufSize)) {
if (!bufSize || !Allocate(bufSize)) {
return false;
}

View File

@ -547,7 +547,7 @@ static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag
}
num_in_channels = read_u8(src, offset + 8);
num_out_channels = read_u8(src, offset + 8);
num_out_channels = read_u8(src, offset + 9);
if (num_in_channels > MAX_CHANNELS || num_out_channels > MAX_CHANNELS)
return NULL;

View File

@ -400,6 +400,25 @@ TestFiniteGfx()
return true;
}
// We want to test nsRect values that are still in range but where
// the implementation is at risk of overflowing
template <class RectType>
static bool
TestBug1135677()
{
RectType rect1(1073741344, 1073741344, 1073756696, 1073819936);
RectType rect2(1073741820, 1073741820, 14400, 77640);
RectType dest;
dest = rect1.Intersect(rect2);
EXPECT_TRUE(dest.x == 1073741820 && dest.y == 1073741820 &&
dest.width == 14400 && dest.height == 77640) <<
"[1] Operation should not overflow internally.";
return true;
}
TEST(Gfx, nsRect) {
TestConstructors<nsRect>();
TestEqualityOperator<nsRect>();
@ -407,6 +426,7 @@ TEST(Gfx, nsRect) {
TestIntersects<nsRect>();
TestIntersection<nsRect>();
TestUnion<nsRect>();
TestBug1135677<nsRect>();
}
TEST(Gfx, nsIntRect) {
@ -416,6 +436,7 @@ TEST(Gfx, nsIntRect) {
TestIntersects<nsIntRect>();
TestIntersection<nsIntRect>();
TestUnion<nsIntRect>();
TestBug1135677<nsIntRect>();
}
TEST(Gfx, gfxRect) {
@ -425,5 +446,6 @@ TEST(Gfx, gfxRect) {
TestIntersects<gfxRect>();
TestIntersection<gfxRect>();
TestUnion<gfxRect>();
TestBug1135677<gfxRect>();
TestFiniteGfx();
}

View File

@ -312,7 +312,7 @@ private:
DECL_GFX_PREF(Once, "layers.d3d11.force-warp", LayersD3D11ForceWARP, bool, false);
DECL_GFX_PREF(Once, "layers.prefer-d3d9", LayersPreferD3D9, bool, false);
DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false);
DECL_GFX_PREF(Once, "layers.progressive-paint", ProgressivePaintDoNotUseDirectly, bool, false);
DECL_GFX_PREF(Live, "layers.progressive-paint", ProgressivePaintDoNotUseDirectly, bool, false);
DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false);
DECL_GFX_PREF(Once, "layers.gralloc.disable", DisableGralloc, bool, false);

View File

@ -64,12 +64,18 @@ struct IconURIParams
int32_t iconState;
};
struct NullPrincipalURIParams
{
// Purposefully empty. Null principal URIs do not round-trip.
};
union URIParams
{
SimpleURIParams;
StandardURLParams;
JARURIParams;
IconURIParams;
NullPrincipalURIParams;
};
union OptionalURIParams

View File

@ -13,6 +13,7 @@
#include "nsID.h"
#include "nsJARURI.h"
#include "nsIIconURI.h"
#include "nsNullPrincipalURI.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
@ -41,7 +42,7 @@ SerializeURI(nsIURI* aURI,
nsCOMPtr<nsIIPCSerializableURI> serializable = do_QueryInterface(aURI);
if (!serializable) {
MOZ_CRASH("All IPDL URIs must be serializable scheme!");
MOZ_CRASH("All IPDL URIs must be serializable!");
}
serializable->Serialize(aParams);
@ -90,6 +91,10 @@ DeserializeURI(const URIParams& aParams)
serializable = do_CreateInstance(kIconURICID);
break;
case URIParams::TNullPrincipalURIParams:
serializable = new nsNullPrincipalURI();
break;
default:
MOZ_CRASH("Unknown params!");
}

View File

@ -355,7 +355,7 @@ class JS_FRIEND_API(BaseProxyHandler)
* to add an override in CrossCompartmentWrapper. If you don't, you risk
* compartment mismatches. See bug 945826 comment 0.
*/
class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
{
public:
explicit MOZ_CONSTEXPR DirectProxyHandler(const void *aFamily, bool aHasPrototype = false,

View File

@ -29,7 +29,7 @@ const Class SymbolObject::class_ = {
};
SymbolObject *
SymbolObject::create(JSContext *cx, JS::Symbol *symbol)
SymbolObject::create(JSContext *cx, JS::HandleSymbol symbol)
{
JSObject *obj = NewBuiltinClassInstance(cx, &class_);
if (!obj)

View File

@ -28,7 +28,7 @@ class SymbolObject : public NativeObject
* Creates a new Symbol object boxing the given primitive Symbol. The
* object's [[Prototype]] is determined from context.
*/
static SymbolObject *create(JSContext *cx, JS::Symbol *symbol);
static SymbolObject *create(JSContext *cx, JS::HandleSymbol symbol);
JS::Symbol *unbox() const {
return getFixedSlot(PRIMITIVE_VALUE_SLOT).toSymbol();

View File

@ -183,6 +183,18 @@ GetBuildConfiguration(JSContext *cx, unsigned argc, jsval *vp)
if (!JS_SetProperty(cx, info, "intl-api", value))
return false;
#if defined(XP_WIN)
value = BooleanValue(false);
#elif defined(SOLARIS)
value = BooleanValue(false);
#elif defined(XP_UNIX)
value = BooleanValue(true);
#else
value = BooleanValue(false);
#endif
if (!JS_SetProperty(cx, info, "mapped-array-buffer", value))
return false;
args.rval().setObject(*info);
return true;
}

View File

@ -2568,7 +2568,7 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun, Fu
}
funbox->bufEnd = pos().begin + 1;
} else {
#if not JS_HAS_EXPR_CLOSURES
#if !JS_HAS_EXPR_CLOSURES
MOZ_ASSERT(kind == Arrow);
#endif
if (tokenStream.hadError())

View File

@ -1612,8 +1612,8 @@ RegExpCompiler::Assemble(JSContext *cx,
return RegExpCode();
if (reg_exp_too_big_) {
JS_ReportError(cx, "regexp too big");
code.destroy();
JS_ReportError(cx, "regexp too big");
return RegExpCode();
}

View File

@ -33,6 +33,7 @@
#include "jit/arm/Simulator-arm.h"
#include "jit/mips/Simulator-mips.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@ -250,8 +251,11 @@ class ExecutableAllocator {
void releasePoolPages(ExecutablePool *pool) {
MOZ_ASSERT(pool->m_allocation.pages);
if (destroyCallback)
if (destroyCallback) {
// Do not allow GC during the page release callback.
JS::AutoSuppressGCAnalysis nogc;
destroyCallback(pool->m_allocation.pages, pool->m_allocation.size);
}
systemRelease(pool->m_allocation);
MOZ_ASSERT(m_pools.initialized());
m_pools.remove(m_pools.lookup(pool)); // this asserts if |pool| is not in m_pools

View File

@ -34,7 +34,7 @@ OptimizationInfo::initNormalOptimizationInfo()
loopUnrolling_ = true;
autoTruncate_ = true;
sink_ = true;
registerAllocator_ = RegisterAllocator_LSRA;
registerAllocator_ = RegisterAllocator_Backtracking;
inlineMaxTotalBytecodeLength_ = 1000;
inliningMaxCallerBytecodeLength_ = 10000;

View File

@ -145,6 +145,14 @@ JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, HandleObject pro
return obj;
}
JS_FRIEND_API(JSObject *)
JS_NewObjectWithoutMetadata(JSContext *cx, const JSClass *clasp, JS::Handle<JSObject*> proto)
{
// Use an AutoEnterAnalysis to suppress invocation of the metadata callback.
AutoEnterAnalysis enter(cx);
return JS_NewObjectWithGivenProto(cx, clasp, proto);
}
JS_FRIEND_API(JSPrincipals *)
JS_GetCompartmentPrincipals(JSCompartment *compartment)
{

View File

@ -60,6 +60,13 @@ extern JS_FRIEND_API(JSObject *)
JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, JS::HandleObject proto,
JS::HandleObject parent);
// Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
// without invoking the metadata callback on it. This allows creation of
// internal bookkeeping objects that are guaranteed to not have metadata
// attached to them.
extern JS_FRIEND_API(JSObject *)
JS_NewObjectWithoutMetadata(JSContext *cx, const JSClass *clasp, JS::Handle<JSObject*> proto);
extern JS_FRIEND_API(uint32_t)
JS_ObjectCountDynamicSlots(JS::HandleObject obj);
@ -144,6 +151,24 @@ extern JS_FRIEND_API(JSObject *)
JS_CloneObject(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto,
JS::HandleObject parent);
/*
* Copy the own properties of src to dst in a fast way. src and dst must both
* be native and must be in the compartment of cx. They must have the same
* class, the same parent, and the same prototype. Class reserved slots will
* NOT be copied.
*
* dst must not have any properties on it before this function is called.
*
* src must have been allocated via JS_NewObjectWithoutMetadata so that we can
* be sure it has no metadata that needs copying to dst. This also means that
* dst needs to have the compartment global as its parent. This function will
* preserve the existing metadata on dst, if any.
*/
extern JS_FRIEND_API(bool)
JS_InitializePropertiesFromCompatibleNativeObject(JSContext *cx,
JS::HandleObject dst,
JS::HandleObject src);
extern JS_FRIEND_API(JSString *)
JS_BasicObjectToString(JSContext *cx, JS::HandleObject obj);

View File

@ -1267,11 +1267,16 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
* the parent of the prototype's constructor. If there is no
* prototype, use the global.
*/
RootedObject parent(cxArg, parentArg);
if (!parent && proto.isObject())
parent = proto.toObject()->getParent();
if (!parent) {
if (proto.isObject())
parent = proto.toObject()->getParent();
else
parent = cxArg->global();
}
RootedObject obj(cxArg, NewObject(cxArg, group, parent, allocKind, newKind));
if (!obj)
@ -1864,7 +1869,8 @@ js::DeepCloneObjectLiteral(JSContext *cx, HandleNativeObject obj, NewObjectKind
MOZ_ASSERT(!obj->hasPrivate());
RootedShape shape(cx, obj->lastProperty());
size_t span = shape->slotSpan();
clone->setLastProperty(cx, shape);
if (!clone->setLastProperty(cx, shape))
return nullptr;
for (size_t i = 0; i < span; i++) {
v = obj->getSlot(i);
if (v.isObject()) {
@ -1894,6 +1900,58 @@ js::DeepCloneObjectLiteral(JSContext *cx, HandleNativeObject obj, NewObjectKind
return clone;
}
static bool
InitializePropertiesFromCompatibleNativeObject(JSContext *cx,
HandleNativeObject dst,
HandleNativeObject src)
{
assertSameCompartment(cx, src, dst);
MOZ_ASSERT(src->getClass() == dst->getClass());
MOZ_ASSERT(src->getParent() == dst->getParent());
MOZ_ASSERT(dst->getParent() == cx->global());
MOZ_ASSERT(src->getProto() == dst->getProto());
MOZ_ASSERT(dst->lastProperty()->getObjectFlags() == 0);
MOZ_ASSERT(!src->getMetadata());
MOZ_ASSERT(!src->isSingleton());
// Save the dst metadata, if any, before we start messing with its shape.
RootedObject dstMetadata(cx, dst->getMetadata());
if (!dst->ensureElements(cx, src->getDenseInitializedLength()))
return false;
uint32_t initialized = src->getDenseInitializedLength();
for (uint32_t i = 0; i < initialized; ++i) {
dst->setDenseInitializedLength(i + 1);
dst->initDenseElement(i, src->getDenseElement(i));
}
MOZ_ASSERT(!src->hasPrivate());
RootedShape shape(cx, src->lastProperty());
size_t span = shape->slotSpan();
if (!dst->setLastProperty(cx, shape))
return false;
for (size_t i = JSCLASS_RESERVED_SLOTS(src->getClass()); i < span; i++)
dst->setSlot(i, src->getSlot(i));
if (dstMetadata) {
if (!js::SetObjectMetadata(cx, dst, dstMetadata))
return false;
}
return true;
}
JS_FRIEND_API(bool)
JS_InitializePropertiesFromCompatibleNativeObject(JSContext *cx,
HandleObject dst,
HandleObject src)
{
return InitializePropertiesFromCompatibleNativeObject(cx,
dst.as<NativeObject>(),
src.as<NativeObject>());
}
template<XDRMode mode>
bool
js::XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleNativeObject obj)
@ -3556,7 +3614,8 @@ js::PrimitiveToObject(JSContext *cx, const Value &v)
if (v.isBoolean())
return BooleanObject::create(cx, v.toBoolean());
MOZ_ASSERT(v.isSymbol());
return SymbolObject::create(cx, v.toSymbol());
RootedSymbol symbol(cx, v.toSymbol());
return SymbolObject::create(cx, symbol);
}
/*

View File

@ -494,6 +494,11 @@ if CONFIG['_MSC_VER']:
# Prevent floating point errors caused by VC++ optimizations
# XXX We should add this to CXXFLAGS, too?
CFLAGS += ['-fp:precise']
# C4805 warns mixing bool with other integral types in computation.
# But given the conversion from bool is specified, and this is a
# pattern widely used in code in js/src, suppress this warning here.
CXXFLAGS += ['-wd4805']
CXXFLAGS += ['-we4067', '-we4258', '-we4275']
if CONFIG['OS_ARCH'] not in ('WINNT', 'HP-UX'):
OS_LIBS += [

View File

@ -36,5 +36,6 @@ function test() {
assertThrows(() => createMappedArrayBuffer("empty.txt", 0, 8), Error);
}
test();
if (getBuildConfiguration()["mapped-array-buffer"])
test();
reportCompare(0, 0, 'ok');

View File

@ -252,7 +252,7 @@ class ObjectGroup : public gc::TenuredCell
}
TypeNewScript *anyNewScript();
void detachNewScript(bool writeBarrier);
void detachNewScript(bool writeBarrier, ObjectGroup *replacement);
ObjectGroupFlags flagsDontCheckGeneration() {
return flags_;
@ -480,7 +480,7 @@ class ObjectGroup : public gc::TenuredCell
void setFlags(ExclusiveContext *cx, ObjectGroupFlags flags);
void markUnknown(ExclusiveContext *cx);
void maybeClearNewScriptOnOOM();
void clearNewScript(ExclusiveContext *cx);
void clearNewScript(ExclusiveContext *cx, ObjectGroup *replacement = nullptr);
bool isPropertyNonData(jsid id);
bool isPropertyNonWritable(jsid id);

View File

@ -2765,7 +2765,7 @@ ObjectGroup::anyNewScript()
}
void
ObjectGroup::detachNewScript(bool writeBarrier)
ObjectGroup::detachNewScript(bool writeBarrier, ObjectGroup *replacement)
{
// Clear the TypeNewScript from this ObjectGroup and, if it has been
// analyzed, remove it from the newObjectGroups table so that it will not be
@ -2775,8 +2775,16 @@ ObjectGroup::detachNewScript(bool writeBarrier)
MOZ_ASSERT(newScript);
if (newScript->analyzed()) {
newScript->function()->compartment()->objectGroups.removeDefaultNewGroup(nullptr, proto(),
newScript->function());
ObjectGroupCompartment &objectGroups = newScript->function()->compartment()->objectGroups;
if (replacement) {
MOZ_ASSERT(replacement->newScript()->function() == newScript->function());
objectGroups.replaceDefaultNewGroup(nullptr, proto(), newScript->function(),
replacement);
} else {
objectGroups.removeDefaultNewGroup(nullptr, proto(), newScript->function());
}
} else {
MOZ_ASSERT(!replacement);
}
if (this->newScript())
@ -2800,13 +2808,13 @@ ObjectGroup::maybeClearNewScriptOnOOM()
addFlags(OBJECT_FLAG_NEW_SCRIPT_CLEARED);
// This method is called during GC sweeping, so don't trigger pre barriers.
detachNewScript(/* writeBarrier = */ false);
detachNewScript(/* writeBarrier = */ false, nullptr);
js_delete(newScript);
}
void
ObjectGroup::clearNewScript(ExclusiveContext *cx)
ObjectGroup::clearNewScript(ExclusiveContext *cx, ObjectGroup *replacement /* = nullptr*/)
{
TypeNewScript *newScript = anyNewScript();
if (!newScript)
@ -2814,15 +2822,17 @@ ObjectGroup::clearNewScript(ExclusiveContext *cx)
AutoEnterAnalysis enter(cx);
// Invalidate any Ion code constructing objects of this type.
setFlags(cx, OBJECT_FLAG_NEW_SCRIPT_CLEARED);
if (!replacement) {
// Invalidate any Ion code constructing objects of this type.
setFlags(cx, OBJECT_FLAG_NEW_SCRIPT_CLEARED);
// Mark the constructing function as having its 'new' script cleared, so we
// will not try to construct another one later.
if (!newScript->function()->setNewScriptCleared(cx))
cx->recoverFromOutOfMemory();
// Mark the constructing function as having its 'new' script cleared, so we
// will not try to construct another one later.
if (!newScript->function()->setNewScriptCleared(cx))
cx->recoverFromOutOfMemory();
}
detachNewScript(/* writeBarrier = */ true);
detachNewScript(/* writeBarrier = */ true, replacement);
if (cx->isJSContext()) {
bool found = newScript->rollbackPartiallyInitializedObjects(cx->asJSContext(), this);
@ -3268,6 +3278,33 @@ TypeNewScript::make(JSContext *cx, ObjectGroup *group, JSFunction *fun)
gc::TraceTypeNewScript(group);
}
// Make a TypeNewScript with the same initializer list as |newScript| but with
// a new template object.
/* static */ TypeNewScript *
TypeNewScript::makeNativeVersion(JSContext *cx, TypeNewScript *newScript,
PlainObject *templateObject)
{
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
ScopedJSDeletePtr<TypeNewScript> nativeNewScript(cx->new_<TypeNewScript>());
if (!nativeNewScript)
return nullptr;
nativeNewScript->function_ = newScript->function();
nativeNewScript->templateObject_ = templateObject;
Initializer *cursor = newScript->initializerList;
while (cursor->kind != Initializer::DONE) { cursor++; }
size_t initializerLength = cursor - newScript->initializerList + 1;
nativeNewScript->initializerList = cx->zone()->pod_calloc<Initializer>(initializerLength);
if (!nativeNewScript->initializerList)
return nullptr;
PodCopy(nativeNewScript->initializerList, newScript->initializerList, initializerLength);
return nativeNewScript.forget();
}
size_t
TypeNewScript::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{

View File

@ -827,8 +827,6 @@ class TypeNewScript
private:
// Scripted function which this information was computed for.
// If instances of the associated group are created without calling
// 'new' on this function, the new script information is cleared.
HeapPtrFunction function_;
// Any preliminary objects with the type. The analyses are not performed
@ -902,6 +900,8 @@ class TypeNewScript
bool rollbackPartiallyInitializedObjects(JSContext *cx, ObjectGroup *group);
static void make(JSContext *cx, ObjectGroup *group, JSFunction *fun);
static TypeNewScript *makeNativeVersion(JSContext *cx, TypeNewScript *newScript,
PlainObject *templateObject);
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
};

View File

@ -35,6 +35,9 @@ UnboxedLayout::trace(JSTracer *trc)
if (nativeShape_)
MarkShape(trc, &nativeShape_, "unboxed_layout_nativeShape");
if (replacementNewGroup_)
MarkObjectGroup(trc, &replacementNewGroup_, "unboxed_layout_replacementNewGroup");
}
size_t
@ -172,18 +175,49 @@ UnboxedPlainObject::trace(JSTracer *trc, JSObject *obj)
/* static */ bool
UnboxedLayout::makeNativeGroup(JSContext *cx, ObjectGroup *group)
{
AutoEnterAnalysis enter(cx);
UnboxedLayout &layout = group->unboxedLayout();
Rooted<TaggedProto> proto(cx, group->proto());
MOZ_ASSERT(!layout.nativeGroup());
// Immediately clear any new script on the group, as
// rollbackPartiallyInitializedObjects() will be confused by the type
// changes we make later on.
group->clearNewScript(cx);
// Immediately clear any new script on the group. This is done by replacing
// the existing new script with one for a replacement default new group.
// This is done so that the size of the replacment group's objects is the
// same as that for the unboxed group, so that we do not see polymorphic
// slot accesses later on for sites that see converted objects from this
// group and objects that were allocated using the replacement new group.
RootedObjectGroup replacementNewGroup(cx);
if (layout.newScript()) {
replacementNewGroup = ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto);
if (!replacementNewGroup)
return false;
AutoEnterAnalysis enter(cx);
PlainObject *templateObject = NewObjectWithGroup<PlainObject>(cx, replacementNewGroup,
cx->global(), layout.getAllocKind(),
MaybeSingletonObject);
if (!templateObject)
return false;
Rooted<TaggedProto> proto(cx, group->proto());
for (size_t i = 0; i < layout.properties().length(); i++) {
const UnboxedLayout::Property &property = layout.properties()[i];
if (!templateObject->addDataProperty(cx, NameToId(property.name), i, JSPROP_ENUMERATE))
return false;
MOZ_ASSERT(templateObject->slotSpan() == i + 1);
MOZ_ASSERT(!templateObject->inDictionaryMode());
}
TypeNewScript *replacementNewScript =
TypeNewScript::makeNativeVersion(cx, layout.newScript(), templateObject);
if (!replacementNewScript)
return false;
replacementNewGroup->setNewScript(replacementNewScript);
gc::TraceTypeNewScript(replacementNewGroup);
group->clearNewScript(cx, replacementNewGroup);
}
size_t nfixed = gc::GetGCKindSlots(layout.getAllocKind());
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &PlainObject::class_, proto,
@ -214,8 +248,8 @@ UnboxedLayout::makeNativeGroup(JSContext *cx, ObjectGroup *group)
TypeSet::TypeList types;
if (!property->types.enumerateTypes(&types))
return false;
for (size_t i = 0; i < types.length(); i++)
AddTypePropertyId(cx, nativeGroup, property->id, types[i]);
for (size_t j = 0; j < types.length(); j++)
AddTypePropertyId(cx, nativeGroup, property->id, types[j]);
HeapTypeSet *nativeProperty = nativeGroup->maybeGetProperty(property->id);
if (nativeProperty->canSetDefinite(i))
nativeProperty->setDefinite(i);
@ -224,6 +258,7 @@ UnboxedLayout::makeNativeGroup(JSContext *cx, ObjectGroup *group)
layout.nativeGroup_ = nativeGroup;
layout.nativeShape_ = shape;
layout.replacementNewGroup_ = replacementNewGroup;
nativeGroup->setOriginalUnboxedGroup(group);

View File

@ -71,10 +71,18 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
HeapPtrObjectGroup nativeGroup_;
HeapPtrShape nativeShape_;
// If nativeGroup is set and this object originally had a TypeNewScript,
// this points to the default 'new' group which replaced this one (and
// which might itself have been cleared since). This link is only needed to
// keep the replacement group from being GC'ed. If it were GC'ed and a new
// one regenerated later, that new group might have a different allocation
// kind from this group.
HeapPtrObjectGroup replacementNewGroup_;
public:
UnboxedLayout(const PropertyVector &properties, size_t size)
: size_(size), newScript_(nullptr), traceList_(nullptr),
nativeGroup_(nullptr), nativeShape_(nullptr)
nativeGroup_(nullptr), nativeShape_(nullptr), replacementNewGroup_(nullptr)
{
properties_.appendAll(properties);
}

View File

@ -4319,9 +4319,8 @@ FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
float aXScale, float aYScale,
int32_t aCommonClipCount)
{
#ifdef MOZ_DUMP_PAINTING
DrawTarget& aDrawTarget = *aRC->GetDrawTarget();
#endif
int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
nsRect boundRect = aRect.ToAppUnits(appUnitsPerDevPixel);
boundRect.MoveBy(NSIntPixelsToAppUnits(aOffset.x, appUnitsPerDevPixel),
@ -4371,7 +4370,9 @@ FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
}
if (cdi->mInactiveLayerManager) {
bool saved = aDrawTarget.GetPermitSubpixelAA();
PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
aDrawTarget.SetPermitSubpixelAA(saved);
} else {
nsIFrame* frame = cdi->mItem->Frame();
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);

View File

@ -433,7 +433,7 @@ load 835056.html
load 836990-1.html
load 840480.html
load 847242.html
load 852293.html
pref(layers.progressive-paint,false) pref(layers.low-precision-buffer,false) load 852293.html
load 860579-1.html
pref(layers.force-active,true) load 859526-1.html
pref(layers.force-active,true) load 859630-1.html

View File

@ -2773,12 +2773,40 @@ nsTreeBodyFrame::HandleEvent(nsPresContext* aPresContext,
return NS_OK;
}
static void
PaintTreeBody(nsIFrame* aFrame, nsRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
static_cast<nsTreeBodyFrame*>(aFrame)->PaintTreeBody(*aCtx, aDirtyRect, aPt);
}
class nsDisplayTreeBody MOZ_FINAL : public nsDisplayItem {
public:
nsDisplayTreeBody(nsDisplayListBuilder* aBuilder, nsFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame),
mDisableSubpixelAA(false) {
MOZ_COUNT_CTOR(nsDisplayTreeBody);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayTreeBody() {
MOZ_COUNT_DTOR(nsDisplayTreeBody);
}
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE
{
gfxContext* ctx = aCtx->ThebesContext();
gfxContextAutoDisableSubpixelAntialiasing disable(ctx, mDisableSubpixelAA);
static_cast<nsTreeBodyFrame*>(mFrame)->
PaintTreeBody(*aCtx, mVisibleRect, ToReferenceFrame());
}
NS_DISPLAY_DECL_NAME("XULTreeBody", TYPE_XUL_TREE_BODY)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
{
bool snap;
return GetBounds(aBuilder, &snap);
}
virtual void DisableComponentAlpha() MOZ_OVERRIDE {
mDisableSubpixelAA = true;
}
bool mDisableSubpixelAA;
};
// Painting routines
void
@ -2799,8 +2827,7 @@ nsTreeBodyFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
return;
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(aBuilder, this, ::PaintTreeBody, "XULTreeBody",
nsDisplayItem::TYPE_XUL_TREE_BODY));
nsDisplayTreeBody(aBuilder, this));
}
void

View File

@ -5,15 +5,3 @@
#else
#define SOUNDTOUCH_INTEGER_SAMPLES 1
#endif
#ifndef MOZILLA_PRESUME_SSE
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
#define SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS 1
#endif
#endif
#ifndef MOZILLA_PRESUME_MMX
#ifdef MOZ_SAMPLE_TYPE_S16
#define SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS 1
#endif
#endif

View File

@ -265,7 +265,13 @@ public:
explicit Fake_DOMMediaStream(Fake_MediaStream *stream = nullptr)
: mMediaStream(stream ? stream : new Fake_MediaStream())
, mVideoTrack(new Fake_MediaStreamTrack(true, this))
, mAudioTrack(new Fake_MediaStreamTrack(false, this)) {}
, mAudioTrack(new Fake_MediaStreamTrack(false, this))
{
static size_t counter = 0;
std::ostringstream os;
os << counter++;
mID = os.str();
}
NS_DECL_THREADSAFE_ISUPPORTS

View File

@ -4477,6 +4477,16 @@ pref("dom.mozSettings.SettingsService.verbose.enabled", false);
// readwrite.
pref("dom.mozSettings.allowForceReadOnly", false);
// The interval at which to check for slow running addons
#ifdef NIGHTLY_BUILD
pref("browser.addon-watch.interval", 15000);
#else
pref("browser.addon-watch.interval", -1);
#endif
pref("browser.addon-watch.ignore", "[\"mochikit@mozilla.org\",\"special-powers@mozilla.org\"]");
// the percentage of time addons are allowed to use without being labeled slow
pref("browser.addon-watch.percentage-limit", 5);
// RequestSync API is disabled by default.
pref("dom.requestSync.enabled", false);

View File

@ -109,6 +109,13 @@ CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI,
*aCookieString = nullptr;
// Fast past: don't bother sending IPC messages about nullprincipal'd
// documents.
nsAutoCString scheme;
aHostURI->GetScheme(scheme);
if (scheme.EqualsLiteral("moz-nullprincipal"))
return NS_OK;
// Determine whether the request is foreign. Failure is acceptable.
bool isForeign = true;
if (RequireThirdPartyCheck())
@ -137,6 +144,13 @@ CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI,
NS_ENSURE_ARG(aHostURI);
NS_ENSURE_ARG_POINTER(aCookieString);
// Fast past: don't bother sending IPC messages about nullprincipal'd
// documents.
nsAutoCString scheme;
aHostURI->GetScheme(scheme);
if (scheme.EqualsLiteral("moz-nullprincipal"))
return NS_OK;
// Determine whether the request is foreign. Failure is acceptable.
bool isForeign = true;
if (RequireThirdPartyCheck())

View File

@ -60,11 +60,11 @@ class Context(KeyedDefaultDict):
lots of empty/default values, you have a data structure with only the
values that were read or touched.
Instances of variables classes are created by invoking class_name(),
except when class_name derives from ContextDerivedValue, in which
case class_name(instance_of_the_context) is invoked.
A value is added to those calls when instances are created during
assignment (setitem).
Instances of variables classes are created by invoking ``class_name()``,
except when class_name derives from ``ContextDerivedValue`` or
``SubContext``, in which case ``class_name(instance_of_the_context)`` or
``class_name(self)`` is invoked. A value is added to those calls when
instances are created during assignment (setitem).
allowed_variables is a dict of the variables that can be set and read in
this context instance. Keys in this dict are the strings representing keys
@ -84,6 +84,7 @@ class Context(KeyedDefaultDict):
self._all_paths = []
self.config = config
self.execution_time = 0
self._sandbox = None
KeyedDefaultDict.__init__(self, self._factory)
def push_source(self, path):
@ -272,6 +273,35 @@ class TemplateContext(Context):
return Context._validate(self, key, value, True)
class SubContext(Context, ContextDerivedValue):
"""A Context derived from another Context.
Sub-contexts are intended to be used as context managers.
Sub-contexts inherit paths and other relevant state from the parent
context.
"""
def __init__(self, parent):
assert isinstance(parent, Context)
Context.__init__(self, allowed_variables=self.VARIABLES,
config=parent.config)
# Copy state from parent.
for p in parent.source_stack:
self.push_source(p)
self._sandbox = parent._sandbox
def __enter__(self):
if not self._sandbox or self._sandbox() is None:
raise Exception('a sandbox is required')
self._sandbox().push_subcontext(self)
def __exit__(self, exc_type, exc_value, traceback):
self._sandbox().pop_subcontext(self)
class FinalTargetValue(ContextDerivedValue, unicode):
def __new__(cls, context, value=""):
if not value:
@ -366,6 +396,27 @@ def ContextDerivedTypedList(type, base_class=List):
return _TypedList
# This defines functions that create sub-contexts.
#
# Values are classes that are SubContexts. The class name will be turned into
# a function that when called emits an instance of that class.
#
# Arbitrary arguments can be passed to the class constructor. The first
# argument is always the parent context. It is up to each class to perform
# argument validation.
SUBCONTEXTS = [
]
for cls in SUBCONTEXTS:
if not issubclass(cls, SubContext):
raise ValueError('SUBCONTEXTS entry not a SubContext class: %s' % cls)
if not hasattr(cls, 'VARIABLES'):
raise ValueError('SUBCONTEXTS entry does not have VARIABLES: %s' % cls)
SUBCONTEXTS = {cls.__name__: cls for cls in SUBCONTEXTS}
# This defines the set of mutable global variables.
#
# Each variable is a tuple of:

View File

@ -62,6 +62,7 @@ from .context import (
VARIABLES,
DEPRECATION_HINTS,
SPECIAL_VARIABLES,
SUBCONTEXTS,
TemplateContext,
)
@ -140,12 +141,14 @@ class MozbuildSandbox(Sandbox):
return SPECIAL_VARIABLES[key][0](self._context)
if key in FUNCTIONS:
return self._create_function(FUNCTIONS[key])
if key in SUBCONTEXTS:
return self._create_subcontext(SUBCONTEXTS[key])
if key in self.templates:
return self._create_template_function(self.templates[key])
return Sandbox.__getitem__(self, key)
def __setitem__(self, key, value):
if key in SPECIAL_VARIABLES or key in FUNCTIONS:
if key in SPECIAL_VARIABLES or key in FUNCTIONS or key in SUBCONTEXTS:
raise KeyError()
if key in self.exports:
self._context[key] = value
@ -310,6 +313,14 @@ class MozbuildSandbox(Sandbox):
self.templates[name] = func, code, self._context.current_path
@memoize
def _create_subcontext(self, cls):
"""Return a function object that creates SubContext instances."""
def fn(*args, **kwargs):
return cls(self._context, *args, **kwargs)
return fn
@memoize
def _create_function(self, function_def):
"""Returns a function object for use within the sandbox for the given
@ -736,7 +747,7 @@ class BuildReader(object):
read, a new Context is created and emitted.
"""
path = mozpath.join(self.config.topsrcdir, 'moz.build')
return self.read_mozbuild(path, self.config, read_tiers=True)
return self.read_mozbuild(path, self.config)
def all_mozbuild_paths(self):
"""Iterator over all available moz.build files.
@ -872,8 +883,7 @@ class BuildReader(object):
for name, key, value in assignments:
yield p, name, key, value
def read_mozbuild(self, path, config, read_tiers=False, descend=True,
metadata={}):
def read_mozbuild(self, path, config, descend=True, metadata={}):
"""Read and process a mozbuild file, descending into children.
This starts with a single mozbuild file, executes it, and descends into
@ -884,10 +894,6 @@ class BuildReader(object):
directory, we will open the moz.build file located in that
directory in a new Sandbox and process it.
If read_tiers is True (it should only be True for the top-level
mozbuild file in a project), the TIERS variable will be used for
traversal as well.
If descend is True (the default), we will descend into child
directories and files per variable values.
@ -900,8 +906,8 @@ class BuildReader(object):
"""
self._execution_stack.append(path)
try:
for s in self._read_mozbuild(path, config, read_tiers=read_tiers,
descend=descend, metadata=metadata):
for s in self._read_mozbuild(path, config, descend=descend,
metadata=metadata):
yield s
except BuildReaderError as bre:
@ -927,7 +933,7 @@ class BuildReader(object):
raise BuildReaderError(list(self._execution_stack),
sys.exc_info()[2], other_error=e)
def _read_mozbuild(self, path, config, read_tiers, descend, metadata):
def _read_mozbuild(self, path, config, descend, metadata):
path = mozpath.normpath(path)
log(self._log, logging.DEBUG, 'read_mozbuild', {'path': path},
'Reading file: {path}')
@ -1008,11 +1014,12 @@ class BuildReader(object):
for gyp_context in gyp_contexts:
context['DIRS'].append(mozpath.relpath(gyp_context.objdir, context.objdir))
sandbox.subcontexts.append(gyp_context)
yield context
for gyp_context in gyp_contexts:
yield gyp_context
for subcontext in sandbox.subcontexts:
yield subcontext
# Traverse into referenced files.
@ -1051,7 +1058,7 @@ class BuildReader(object):
continue
for res in self.read_mozbuild(child_path, context.config,
read_tiers=False, metadata=child_metadata):
metadata=child_metadata):
yield res
self._execution_stack.pop()

View File

@ -22,6 +22,7 @@ from __future__ import unicode_literals
import copy
import os
import sys
import weakref
from contextlib import contextmanager
@ -116,12 +117,22 @@ class Sandbox(dict):
assert isinstance(self._builtins, ReadOnlyDict)
assert isinstance(context, Context)
self._context = context
# Contexts are modeled as a stack because multiple context managers
# may be active.
self._active_contexts = [context]
# Seen sub-contexts. Will be populated with other Context instances
# that were related to execution of this instance.
self.subcontexts = []
# We need to record this because it gets swallowed as part of
# evaluation.
self._last_name_error = None
@property
def _context(self):
return self._active_contexts[-1]
def exec_file(self, path):
"""Execute code at a path in the sandbox.
@ -153,6 +164,9 @@ class Sandbox(dict):
if path:
self._context.push_source(path)
old_sandbox = self._context._sandbox
self._context._sandbox = weakref.ref(self)
# We don't have to worry about bytecode generation here because we are
# too low-level for that. However, we could add bytecode generation via
# the marshall module if parsing performance were ever an issue.
@ -190,9 +204,31 @@ class Sandbox(dict):
raise SandboxExecutionError(self._context.source_stack, exc[0],
exc[1], exc[2])
finally:
self._context._sandbox = old_sandbox
if path:
self._context.pop_source()
def push_subcontext(self, context):
"""Push a SubContext onto the execution stack.
When called, the active context will be set to the specified context,
meaning all variable accesses will go through it. We also record this
SubContext as having been executed as part of this sandbox.
"""
self._active_contexts.append(context)
if context not in self.subcontexts:
self.subcontexts.append(context)
def pop_subcontext(self, context):
"""Pop a SubContext off the execution stack.
SubContexts must be pushed and popped in opposite order. This is
validated as part of the function call to ensure proper consumer API
use.
"""
popped = self._active_contexts.pop()
assert popped == context
def __getitem__(self, key):
if key.isupper():
try:

View File

@ -101,6 +101,21 @@ def special_reference(v, func, typ, doc):
def format_module(m):
lines = []
for subcontext, cls in sorted(m.SUBCONTEXTS.items()):
lines.extend([
'.. _mozbuild_subcontext_%s:' % subcontext,
'',
'Sub-Context: %s' % subcontext,
'=============' + '=' * len(subcontext),
'',
prepare_docstring(cls.__doc__)[0],
'',
])
for k, v in sorted(cls.VARIABLES.items()):
lines.extend(variable_reference(k, *v))
lines.extend([
'Variables',
'=========',

View File

@ -11,6 +11,7 @@ from mozbuild.frontend.context import (
Context,
FUNCTIONS,
SPECIAL_VARIABLES,
SUBCONTEXTS,
VARIABLES,
)
@ -256,6 +257,12 @@ class TestSymbols(unittest.TestCase):
for func, typ, doc in SPECIAL_VARIABLES.values():
self._verify_doc(doc)
for name, cls in SUBCONTEXTS.items():
self._verify_doc(cls.__doc__)
for name, v in cls.VARIABLES.items():
self._verify_doc(v[2])
if __name__ == '__main__':
main()

View File

@ -99,12 +99,12 @@ def match(path, pattern):
'''
if not pattern:
return True
if not pattern in re_cache:
pattern = re.escape(pattern)
pattern = re.sub(r'(^|\\\/)\\\*\\\*\\\/', r'\1(?:.+/)?', pattern)
pattern = re.sub(r'(^|\\\/)\\\*\\\*$', r'(?:\1.+)?', pattern)
pattern = pattern.replace(r'\*', '[^/]*') + '(?:/.*)?$'
re_cache[pattern] = re.compile(pattern)
if pattern not in re_cache:
p = re.escape(pattern)
p = re.sub(r'(^|\\\/)\\\*\\\*\\\/', r'\1(?:.+/)?', p)
p = re.sub(r'(^|\\\/)\\\*\\\*$', r'(?:\1.+)?', p)
p = p.replace(r'\*', '[^/]*') + '(?:/.*)?$'
re_cache[pattern] = re.compile(p)
return re_cache[pattern].match(path) is not None

View File

@ -1447,16 +1447,11 @@ MarionetteServerConnection.prototype = {
return this._browserIds.get(permKey);
}
let contentWindow = browser.contentWindowAsCPOW;
if (contentWindow !== null && !Cu.isDeadWrapper(contentWindow)) {
let winId = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.outerWindowID;
if (winId) {
winId += "";
this._browserIds.set(permKey, winId);
return winId;
}
let winId = browser.outerWindowID;
if (winId) {
winId += "";
this._browserIds.set(permKey, winId);
return winId;
}
return null;
},

View File

@ -0,0 +1,48 @@
/* 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/. */
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
this.EXPORTED_SYMBOLS = ["ContentCollector"];
// This listens for the message "browser-test:collect-request". When it gets it,
// it runs some GCs and CCs, then prints out a message indicating the collections
// are complete. Mochitest uses this information to determine when windows and
// docshells should be destroyed.
var ContentCollector = {
init: function() {
let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
cpmm.addMessageListener("browser-test:collect-request", this);
},
receiveMessage: function(aMessage) {
switch (aMessage.name) {
case "browser-test:collect-request":
Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");
Cu.forceGC();
Cu.forceCC();
Cu.schedulePreciseShrinkingGC(() => {
Cu.forceCC();
let pid = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).processID;
dump("Completed ShutdownLeaks collections in process " + pid + "\n")});
let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
cpmm.removeMessageListener("browser-test:collect-request", this);
break;
}
}
};
ContentCollector.init();

View File

@ -88,6 +88,12 @@ function testInit() {
}
if (gConfig.e10s) {
e10s_init();
let globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);
globalMM.loadFrameScript("chrome://mochikit/content/shutdown-leaks-collector.js", true);
} else {
// In non-e10s, only run the ShutdownLeaksCollector in the parent process.
Components.utils.import("chrome://mochikit/content/ShutdownLeaksCollector.jsm");
}
}
@ -575,6 +581,10 @@ Tester.prototype = {
// and thus get rid of more false leaks like already terminated workers.
Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster);
ppmm.broadcastAsyncMessage("browser-test:collect-request");
checkForLeakedGlobalWindows(aResults => {
if (aResults.length == 0) {
this.finish();

View File

@ -10,6 +10,8 @@ mochikit.jar:
content/cc-analyzer.js (cc-analyzer.js)
content/chrome-harness.js (chrome-harness.js)
content/mochitest-e10s-utils.js (mochitest-e10s-utils.js)
content/shutdown-leaks-collector.js (shutdown-leaks-collector.js)
content/ShutdownLeaksCollector.jsm (ShutdownLeaksCollector.jsm)
content/harness.xul (harness.xul)
content/redirect.html (redirect.html)
content/server.js (server.js)

View File

@ -0,0 +1,7 @@
/* 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/. */
// We run this code in a .jsm rather than here to avoid keeping the current
// compartment alive.
Components.utils.import("chrome://mochikit/content/ShutdownLeaksCollector.jsm");

View File

@ -30,10 +30,12 @@ required_files = [("testharness_runner.html", "", False),
def do_delayed_imports():
global marionette
global errors
try:
import marionette
from marionette import errors
except ImportError:
import marionette_driver.marionette as marionette
from marionette_driver import marionette, errors
class MarionetteTestExecutor(TestExecutor):
@ -153,13 +155,13 @@ class MarionetteTestExecutor(TestExecutor):
try:
self.marionette.set_script_timeout((timeout + extra_timeout) * 1000)
except IOError, marionette.errors.InvalidResponseException:
except IOError, errors.InvalidResponseException:
self.logger.error("Lost marionette connection before starting test")
return Stop
try:
result = self.convert_result(test, self.do_test(test, timeout))
except marionette.errors.ScriptTimeoutException:
except errors.ScriptTimeoutException:
with result_lock:
if not result_flag.is_set():
result_flag.set()
@ -179,7 +181,7 @@ class MarionetteTestExecutor(TestExecutor):
# else:
# break
# Now need to check if the browser is still responsive and restart it if not
except (socket.timeout, marionette.errors.InvalidResponseException, IOError):
except (socket.timeout, errors.InvalidResponseException, IOError):
# This can happen on a crash
# Also, should check after the test if the firefox process is still running
# and otherwise ignore any other result and set it to crash
@ -250,7 +252,7 @@ class MarionetteReftestExecutor(MarionetteTestExecutor):
full_url = urlparse.urljoin(self.http_server_url, url)
try:
self.marionette.navigate(full_url)
except marionette.errors.MarionetteException:
except errors.MarionetteException:
return {"status": "ERROR",
"message": "Failed to load url %s" % (full_url,)}
if url_type == "test":

View File

@ -124,6 +124,13 @@ class HgTree(object):
def commit_patch(self):
self.hg("qfinish")
def contains_commit(self, commit):
try:
self.hg("identify", "-r", commit.sha1)
return True
except subprocess.CalledProcessError:
return False
class GitTree(object):
name = "git"

View File

@ -0,0 +1,96 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/. */
"use strict";
this.EXPORTED_SYMBOLS = ["AddonWatcher"];
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
let AddonWatcher = {
_lastAddonTime: {},
_timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
_callback: null,
_interval: 1500,
_ignoreList: null,
init: function(callback) {
if (!callback) {
return;
}
if (this._callback) {
return;
}
this._interval = Preferences.get("browser.addon-watch.interval", 15000);
if (this._interval == -1) {
return;
}
this._callback = callback;
try {
this._ignoreList = new Set(JSON.parse(Preferences.get("browser.addon-watch.ignore", null)));
} catch (ex) {
// probably some malformed JSON, ignore and carry on
this._ignoreList = new Set();
}
this._timer.initWithCallback(this._checkAddons.bind(this), this._interval, Ci.nsITimer.TYPE_REPEATING_SLACK);
},
uninit: function() {
if (this._timer) {
this._timer.cancel();
this._timer = null;
}
},
_checkAddons: function() {
let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
.getService(Ci.nsICompartmentInfo);
let compartments = compartmentInfo.getCompartments();
let count = compartments.length;
let addons = {};
for (let i = 0; i < count; i++) {
let compartment = compartments.queryElementAt(i, Ci.nsICompartment);
if (compartment.addonId) {
if (addons[compartment.addonId]) {
addons[compartment.addonId] += compartment.time;
} else {
addons[compartment.addonId] = compartment.time;
}
}
}
let limit = this._interval * Preferences.get("browser.addon-watch.percentage-limit", 75) * 10;
for (let addonId in addons) {
if (!this._ignoreList.has(addonId)) {
if (!this._lastAddonTime[addonId]) {
this._lastAddonTime[addonId] = 0;
}
if ((addons[addonId] - this._lastAddonTime[addonId]) > limit) {
this._callback(addonId);
}
this._lastAddonTime[addonId] = addons[addonId];
}
}
},
ignoreAddonForSession: function(addonid) {
this._ignoreList.add(addonid);
},
ignoreAddonPermanently: function(addonid) {
this._ignoreList.add(addonid);
try {
let ignoreList = JSON.parse(Preferences.get("browser.addon-watch.ignore", "[]"))
if (!ignoreList.includes(addonid)) {
ignoreList.push(addonid);
Preferences.set("browser.addon-watch.ignore", JSON.stringify(ignoreList));
}
} catch (ex) {
Preferences.set("browser.addon-watch.ignore", JSON.stringify([addonid]));
}
}
};

View File

@ -12,6 +12,7 @@ MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
SPHINX_TREES['toolkit_modules'] = 'docs'
EXTRA_JS_MODULES += [
'AddonWatcher.jsm',
'Battery.jsm',
'BinarySearch.jsm',
'BrowserUtils.jsm',

View File

@ -83,9 +83,20 @@ XPCOMUtils.defineLazyGetter(this, "gPref", function bls_gPref() {
QueryInterface(Ci.nsIPrefBranch);
});
// From appinfo in Services.jsm. It is not possible to use the one in
// Services.jsm since it will not successfully QueryInterface nsIXULAppInfo in
// xpcshell tests due to other code calling Services.appinfo before the
// nsIXULAppInfo is created by the tests.
XPCOMUtils.defineLazyGetter(this, "gApp", function bls_gApp() {
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime);
let appinfo = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime);
try {
appinfo.QueryInterface(Ci.nsIXULAppInfo);
} catch (ex if ex instanceof Components.Exception &&
ex.result == Cr.NS_NOINTERFACE) {
// Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
}
return appinfo;
});
XPCOMUtils.defineLazyGetter(this, "gABI", function bls_gABI() {
@ -396,6 +407,10 @@ Blocklist.prototype = {
if (!gBlocklistEnabled)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
// Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
if (!appVersion && !gApp.version)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
if (!appVersion)
appVersion = gApp.version;
if (!toolkitVersion)
@ -529,9 +544,13 @@ Blocklist.prototype = {
pingCountTotal = 1;
dsURI = dsURI.replace(/%APP_ID%/g, gApp.ID);
dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version);
// Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
if (gApp.version)
dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version);
dsURI = dsURI.replace(/%PRODUCT%/g, gApp.name);
dsURI = dsURI.replace(/%VERSION%/g, gApp.version);
// Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
if (gApp.version)
dsURI = dsURI.replace(/%VERSION%/g, gApp.version);
dsURI = dsURI.replace(/%BUILD_ID%/g, gApp.appBuildID);
dsURI = dsURI.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI);
dsURI = dsURI.replace(/%OS_VERSION%/g, gOSVersion);
@ -1048,6 +1067,10 @@ Blocklist.prototype = {
if (!gBlocklistEnabled)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
// Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
if (!appVersion && !gApp.version)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
if (!appVersion)
appVersion = gApp.version;
if (!toolkitVersion)