Merge m-c to m-i.

This commit is contained in:
Ms2ger 2013-04-21 09:54:41 +02:00
commit 93a0f1af78
202 changed files with 3138 additions and 1364 deletions

View File

@ -20,11 +20,11 @@
#include "nsCURILoader.h"
#include "nsDocShellLoadTypes.h"
#include "nsDOMEvent.h"
#include "nsIChannel.h"
#include "nsIContentViewer.h"
#include "nsIDOMDocument.h"
#include "nsEventListenerManager.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMWindow.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIWebNavigation.h"
@ -32,6 +32,7 @@
using namespace mozilla;
using namespace mozilla::a11y;
using namespace mozilla::dom;
////////////////////////////////////////////////////////////////////////////////
// DocManager
@ -252,10 +253,8 @@ DocManager::HandleEvent(nsIDOMEvent* aEvent)
nsAutoString type;
aEvent->GetType(type);
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDocument> document(do_QueryInterface(target));
nsCOMPtr<nsIDocument> document =
do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
NS_ASSERTION(document, "pagehide or DOMContentLoaded for non document!");
if (!document)
return NS_OK;
@ -327,8 +326,8 @@ void
DocManager::AddListeners(nsIDocument* aDocument,
bool aAddDOMContentLoadedListener)
{
nsPIDOMWindow *window = aDocument->GetWindow();
nsIDOMEventTarget *target = window->GetChromeEventHandler();
nsPIDOMWindow* window = aDocument->GetWindow();
EventTarget* target = window->GetChromeEventHandler();
nsEventListenerManager* elm = target->GetListenerManager(true);
elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
dom::TrustedEventsAtCapture());
@ -355,7 +354,7 @@ DocManager::RemoveListeners(nsIDocument* aDocument)
if (!window)
return;
nsIDOMEventTarget* target = window->GetChromeEventHandler();
EventTarget* target = window->GetChromeEventHandler();
nsEventListenerManager* elm = target->GetListenerManager(true);
elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
dom::TrustedEventsAtCapture());

View File

@ -3648,10 +3648,6 @@ var XULBrowserWindow = {
// unsupported
},
setJSDefaultStatus: function () {
// unsupported
},
setDefaultStatus: function (status) {
this.defaultStatus = status;
this.updateStatusField();

View File

@ -457,6 +457,7 @@ toolbar:not([mode="icons"]) #restore-button {
}
.toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
.toolbarbutton-1[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
.toolbarbutton-1[type="menu-button"] > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#restore-button[disabled="true"] > .toolbarbutton-icon {
opacity: .4;
@ -464,12 +465,13 @@ toolbar:not([mode="icons"]) #restore-button {
@media (-moz-mac-lion-theme) {
.toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
.toolbarbutton-1[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
.toolbarbutton-1[type="menu-button"] > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#restore-button[disabled="true"] > .toolbarbutton-icon,
.toolbarbutton-1[disabled="true"] > .toolbarbutton-menu-dropmarker,
.toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-dropmarker,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-badge-container > .toolbarbutton-icon,
#restore-button:not(:hover):-moz-window-inactive > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menu-dropmarker,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menubutton-dropmarker {
@ -477,6 +479,7 @@ toolbar:not([mode="icons"]) #restore-button {
}
.toolbarbutton-1:-moz-window-inactive[disabled="true"] > .toolbarbutton-icon,
.toolbarbutton-1:-moz-window-inactive[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
.toolbarbutton-1:-moz-window-inactive[type="menu-button"] > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#restore-button:-moz-window-inactive[disabled="true"] > .toolbarbutton-icon {
opacity: .25;

View File

@ -968,6 +968,10 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
os.kill(pid, signal.SIGKILL)
def dumpScreen(self, utilityPath):
if self.haveDumpedScreen:
self.log.info("Not taking screenshot here: see the one that was previously logged")
return
self.haveDumpedScreen = True;
# Need to figure out what tool and whether it write to a file or stdout
@ -1017,10 +1021,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
def killAndGetStack(self, processPID, utilityPath, debuggerInfo):
"""Kill the process, preferrably in a way that gets us a stack trace."""
if not debuggerInfo:
if self.haveDumpedScreen:
self.log.info("Not taking screenshot here: see the one that was previously logged")
else:
self.dumpScreen(utilityPath)
self.dumpScreen(utilityPath)
if self.CRASHREPORTER and not debuggerInfo:
if self.UNIXISH:
@ -1076,10 +1077,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
if "TEST-START" in line and "|" in line:
self.lastTestSeen = line.split("|")[1].strip()
if not debuggerInfo and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line:
if self.haveDumpedScreen:
self.log.info("Not taking screenshot here: see the one that was previously logged")
else:
self.dumpScreen(utilityPath)
self.dumpScreen(utilityPath)
(line, didTimeout) = self.readWithTimeout(logsource, timeout)
if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime):

View File

@ -121,13 +121,20 @@ class RemoteAutomation(Automation):
javaException = self.checkForJavaException(logcat)
if javaException:
return True
# If crash reporting is disabled (MOZ_CRASHREPORTER!=1), we can't say
# anything.
if not self.CRASHREPORTER:
return False
try:
dumpDir = tempfile.mkdtemp()
remoteCrashDir = self._remoteProfile + '/minidumps/'
if not self._devicemanager.dirExists(remoteCrashDir):
# As of this writing, the minidumps directory is automatically
# created when fennec (first) starts, so its lack of presence
# is a hint that something went wrong.
# If crash reporting is enabled (MOZ_CRASHREPORTER=1), the
# minidumps directory is automatically created when Fennec
# (first) starts, so its lack of presence is a hint that
# something went wrong.
print "Automation Error: No crash directory (%s) found on remote device" % remoteCrashDir
# Whilst no crash was found, the run should still display as a failure
return True

View File

@ -223,6 +223,7 @@ if test -n "$gonkdir" ; then
AC_DEFINE(HAVE_PTHREADS)
CROSS_COMPILE=1
MOZ_CHROME_FILE_FORMAT=omni
NSS_NO_LIBPKIX=1
direct_nspr_config=1
else
MOZ_ANDROID_NDK
@ -8541,6 +8542,8 @@ AC_SUBST(MOZ_PERMISSIONS)
AC_SUBST(MOZ_PREF_EXTENSIONS)
AC_SUBST(MOZ_JS_LIBS)
AC_SUBST(MOZ_PSM)
AC_DEFINE(NSS_NO_LIBPKIX)
AC_SUBST(NSS_NO_LIBPKIX)
AC_SUBST(MOZ_DEBUG)
AC_SUBST(MOZ_DEBUG_SYMBOLS)
AC_SUBST(MOZ_DEBUG_ENABLE_DEFS)

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html style="position: fixed;">
<head>
<meta charset="UTF-8">
<script>
function boom()
{
var cp = document.caretPositionFromPoint(0, 1);
document.documentElement.removeChild(document.body);
cp.getClientRect();
}
</script>
</head>
<body style="margin: 0;" onload="boom();"></body>
</html>

View File

@ -133,3 +133,4 @@ load 841205.html
load 844404.html
load 847127.html
load 849601.html
load 863950.html

View File

@ -1099,10 +1099,10 @@ WebSocket::UpdateMustKeepAlive()
if (mKeepingAlive && !shouldKeepAlive) {
mKeepingAlive = false;
static_cast<nsIDOMEventTarget*>(this)->Release();
static_cast<EventTarget*>(this)->Release();
} else if (!mKeepingAlive && shouldKeepAlive) {
mKeepingAlive = true;
static_cast<nsIDOMEventTarget*>(this)->AddRef();
static_cast<EventTarget*>(this)->AddRef();
}
}
@ -1112,7 +1112,7 @@ WebSocket::DontKeepAliveAnyMore()
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
if (mKeepingAlive) {
mKeepingAlive = false;
static_cast<nsIDOMEventTarget*>(this)->Release();
static_cast<EventTarget*>(this)->Release();
}
mCheckMustKeepAlive = false;
}

View File

@ -135,7 +135,7 @@ MarkMessageManagers()
static_cast<nsFrameMessageManager*>(tabMM)->GetCallback();
if (cb) {
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
nsIDOMEventTarget* et = fl->GetTabChildGlobalAsEventTarget();
EventTarget* et = fl->GetTabChildGlobalAsEventTarget();
if (!et) {
continue;
}

View File

@ -95,7 +95,7 @@ void
nsDOMFileReader::RootResultArrayBuffer()
{
nsContentUtils::PreserveWrapper(
static_cast<nsIDOMEventTarget*>(
static_cast<EventTarget*>(
static_cast<nsDOMEventTargetHelper*>(this)), this);
}
@ -104,7 +104,7 @@ nsDOMFileReader::RootResultArrayBuffer()
nsDOMFileReader::nsDOMFileReader()
: mFileData(nullptr),
mDataLen(0), mDataFormat(FILE_AS_BINARY),
mResultArrayBuffer(nullptr)
mResultArrayBuffer(nullptr)
{
nsLayoutStatics::AddRef();
SetDOMStringToNull(mResult);

View File

@ -639,6 +639,7 @@ GK_ATOM(onanimationend, "onanimationend")
GK_ATOM(onanimationiteration, "onanimationiteration")
GK_ATOM(onanimationstart, "onanimationstart")
GK_ATOM(onAppCommand, "onAppCommand")
GK_ATOM(onaudioprocess, "onaudioprocess")
GK_ATOM(onbeforecopy, "onbeforecopy")
GK_ATOM(onbeforecut, "onbeforecut")
GK_ATOM(onbeforepaste, "onbeforepaste")

View File

@ -246,10 +246,9 @@ nsInProcessTabChildGlobal::DelayedDisconnect()
if (mListenerManager) {
mListenerManager->Disconnect();
}
if (!mLoadingScript) {
nsContentUtils::ReleaseWrapper(static_cast<nsIDOMEventTarget*>(this),
this);
nsContentUtils::ReleaseWrapper(static_cast<EventTarget*>(this), this);
if (mCx) {
DestroyCx();
}
@ -309,8 +308,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
id.AppendLiteral("?ownedBy=");
id.Append(u);
}
nsISupports* scopeSupports =
NS_ISUPPORTS_CAST(nsIDOMEventTarget*, this);
nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
NS_ENSURE_STATE(InitTabChildGlobalInternal(scopeSupports, id));
return NS_OK;
}

View File

@ -488,19 +488,19 @@ function start() {
var testsToSkip = [];
if (kIsAndroid) {
var testsToSkip = loadTextFileSynchronous('skipped_tests_android.txt')
testsToSkip = loadTextFileSynchronous('skipped_tests_android.txt')
.replace(/\r/g, '') // convert to unix line breaks
.split('\n');
}
if (kIsLinuxMesa) {
var testsToSkip = loadTextFileSynchronous('skipped_tests_linux_mesa.txt')
testsToSkip = loadTextFileSynchronous('skipped_tests_linux_mesa.txt')
.replace(/\r/g, '') // convert to unix line breaks
.split('\n');
}
if (kIsWindows && !kIsWindowsVistaOrHigher) {
var testsToSkip = loadTextFileSynchronous('skipped_tests_winxp.txt')
testsToSkip = loadTextFileSynchronous('skipped_tests_winxp.txt')
.replace(/\r/g, '') // convert to unix line breaks
.split('\n');
}

View File

@ -848,6 +848,11 @@ NON_IDL_EVENT(animationiteration,
EventNameType_None,
NS_ANIMATION_EVENT)
NON_IDL_EVENT(audioprocess,
NS_AUDIO_PROCESS,
EventNameType_None,
NS_EVENT)
#ifdef DEFINED_FORWARDED_EVENT
#undef DEFINED_FORWARDED_EVENT
#undef FORWARDED_EVENT

View File

@ -460,7 +460,7 @@ nsDOMEvent::StopImmediatePropagation()
static nsIDocument* GetDocumentForReport(nsEvent* aEvent)
{
nsIDOMEventTarget* target = aEvent->currentTarget;
EventTarget* target = aEvent->currentTarget;
if (nsCOMPtr<nsINode> node = do_QueryInterface(target)) {
return node->OwnerDoc();
}

View File

@ -21,6 +21,7 @@ nsDOMKeyboardEvent::nsDOMKeyboardEvent(mozilla::dom::EventTarget* aOwner,
mEventIsInternal = true;
mEvent->time = PR_Now();
}
SetIsDOMBinding();
}
nsDOMKeyboardEvent::~nsDOMKeyboardEvent()
@ -45,7 +46,7 @@ NS_IMETHODIMP
nsDOMKeyboardEvent::GetAltKey(bool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = static_cast<nsInputEvent*>(mEvent)->IsAlt();
*aIsDown = AltKey();
return NS_OK;
}
@ -53,7 +54,7 @@ NS_IMETHODIMP
nsDOMKeyboardEvent::GetCtrlKey(bool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = static_cast<nsInputEvent*>(mEvent)->IsControl();
*aIsDown = CtrlKey();
return NS_OK;
}
@ -61,7 +62,7 @@ NS_IMETHODIMP
nsDOMKeyboardEvent::GetShiftKey(bool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = static_cast<nsInputEvent*>(mEvent)->IsShift();
*aIsDown = ShiftKey();
return NS_OK;
}
@ -69,7 +70,7 @@ NS_IMETHODIMP
nsDOMKeyboardEvent::GetMetaKey(bool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = static_cast<nsInputEvent*>(mEvent)->IsMeta();
*aIsDown = MetaKey();
return NS_OK;
}
@ -79,7 +80,7 @@ nsDOMKeyboardEvent::GetModifierState(const nsAString& aKey,
{
NS_ENSURE_ARG_POINTER(aState);
*aState = GetModifierStateInternal(aKey);
*aState = GetModifierState(aKey);
return NS_OK;
}
@ -87,39 +88,41 @@ NS_IMETHODIMP
nsDOMKeyboardEvent::GetCharCode(uint32_t* aCharCode)
{
NS_ENSURE_ARG_POINTER(aCharCode);
*aCharCode = CharCode();
return NS_OK;
}
uint32_t
nsDOMKeyboardEvent::CharCode()
{
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_DOWN:
*aCharCode = 0;
break;
return 0;
case NS_KEY_PRESS:
*aCharCode = ((nsKeyEvent*)mEvent)->charCode;
break;
default:
*aCharCode = 0;
break;
return static_cast<nsKeyEvent*>(mEvent)->charCode;
}
return NS_OK;
return 0;
}
NS_IMETHODIMP
nsDOMKeyboardEvent::GetKeyCode(uint32_t* aKeyCode)
{
NS_ENSURE_ARG_POINTER(aKeyCode);
*aKeyCode = KeyCode();
return NS_OK;
}
uint32_t
nsDOMKeyboardEvent::KeyCode()
{
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_PRESS:
case NS_KEY_DOWN:
*aKeyCode = ((nsKeyEvent*)mEvent)->keyCode;
break;
default:
*aKeyCode = 0;
break;
return static_cast<nsKeyEvent*>(mEvent)->keyCode;
}
return NS_OK;
return 0;
}
/* virtual */
@ -127,29 +130,30 @@ nsresult
nsDOMKeyboardEvent::Which(uint32_t* aWhich)
{
NS_ENSURE_ARG_POINTER(aWhich);
*aWhich = Which();
return NS_OK;
}
uint32_t
nsDOMKeyboardEvent::Which()
{
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_DOWN:
return GetKeyCode(aWhich);
return KeyCode();
case NS_KEY_PRESS:
//Special case for 4xp bug 62878. Try to make value of which
//more closely mirror the values that 4.x gave for RETURN and BACKSPACE
{
uint32_t keyCode = ((nsKeyEvent*)mEvent)->keyCode;
if (keyCode == NS_VK_RETURN || keyCode == NS_VK_BACK) {
*aWhich = keyCode;
return NS_OK;
return keyCode;
}
return GetCharCode(aWhich);
return CharCode();
}
break;
default:
*aWhich = 0;
break;
}
return NS_OK;
return 0;
}
NS_IMETHODIMP
@ -157,7 +161,7 @@ nsDOMKeyboardEvent::GetLocation(uint32_t* aLocation)
{
NS_ENSURE_ARG_POINTER(aLocation);
*aLocation = static_cast<nsKeyEvent*>(mEvent)->location;
*aLocation = Location();
return NS_OK;
}

View File

@ -8,6 +8,7 @@
#include "nsIDOMKeyEvent.h"
#include "nsDOMUIEvent.h"
#include "mozilla/dom/KeyEventBinding.h"
class nsDOMKeyboardEvent : public nsDOMUIEvent,
public nsIDOMKeyEvent
@ -25,6 +26,56 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMUIEVENT
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope)
{
return mozilla::dom::KeyEventBinding::Wrap(aCx, aScope, this);
}
bool AltKey()
{
return static_cast<nsInputEvent*>(mEvent)->IsAlt();
}
bool CtrlKey()
{
return static_cast<nsInputEvent*>(mEvent)->IsControl();
}
bool ShiftKey()
{
return static_cast<nsInputEvent*>(mEvent)->IsShift();
}
bool MetaKey()
{
return static_cast<nsInputEvent*>(mEvent)->IsMeta();
}
bool GetModifierState(const nsAString& aKey)
{
return GetModifierStateInternal(aKey);
}
uint32_t CharCode();
uint32_t KeyCode();
virtual uint32_t Which() MOZ_OVERRIDE;
uint32_t Location()
{
return static_cast<nsKeyEvent*>(mEvent)->location;
}
void InitKeyEvent(const nsAString& aType, bool aCanBubble, bool aCancelable,
nsIDOMWindow* aView, bool aCtrlKey, bool aAltKey,
bool aShiftKey, bool aMetaKey,
uint32_t aKeyCode, uint32_t aCharCode,
mozilla::ErrorResult& aRv)
{
aRv = InitKeyEvent(aType, aCanBubble, aCancelable, aView,
aCtrlKey, aAltKey, aShiftKey,aMetaKey,
aKeyCode, aCharCode);
}
protected:
// Specific implementation for a keyboard event.
virtual nsresult Which(uint32_t* aWhich);

View File

@ -37,6 +37,13 @@ public:
JSContext* aCx, JS::Value* aVal);
// Web IDL binding methods
virtual uint32_t Which() MOZ_OVERRIDE
{
uint32_t w = 0;
Which(&w);
return w;
}
int32_t ScreenX();
int32_t ScreenY();
int32_t ClientX();

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/Touch.h"
using namespace mozilla;
using namespace mozilla::dom;
// TouchList
nsDOMTouchList::nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
@ -195,7 +196,7 @@ nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
// touch that is ending
if ((mEvent->message != NS_TOUCH_END &&
mEvent->message != NS_TOUCH_CANCEL) || !touches[i]->mChanged) {
nsIDOMEventTarget* targetPtr = touches[i]->GetTarget();
EventTarget* targetPtr = touches[i]->GetTarget();
if (targetPtr == mEvent->originalTarget) {
targetTouches.AppendElement(touches[i]);
}

View File

@ -132,7 +132,7 @@ public:
return y;
}
uint32_t Which()
virtual uint32_t Which()
{
uint32_t w;
GetWhich(&w);

View File

@ -2785,7 +2785,7 @@ IsLTR(Element* aElement)
}
bool
HTMLInputElement::ShouldPreventDOMActivateDispatch(nsIDOMEventTarget* aOriginalTarget)
HTMLInputElement::ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget)
{
/*
* For the moment, there is only one situation where we actually want to

View File

@ -1070,7 +1070,7 @@ protected:
* This is used in situations where the anonymous subtree should already have
* sent a DOMActivate and prevents firing more than once.
*/
bool ShouldPreventDOMActivateDispatch(nsIDOMEventTarget* aOriginalTarget);
bool ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget);
nsCOMPtr<nsIControllers> mControllers;

View File

@ -12,9 +12,7 @@ include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = gkcontentmathml_s
LIBXUL_LIBRARY = 1
ifndef _MSC_VER
FAIL_ON_WARNINGS = 1
endif # !_MSC_VER
CPPSRCS = \
nsMathMLElement.cpp \
@ -22,6 +20,7 @@ CPPSRCS = \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
# we don't want the shared lib, but we want to force the creation of a static
# lib.

View File

@ -3,9 +3,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Util.h"
#include "nsMathMLElement.h"
#include "base/compiler_specific.h"
#include "mozilla/Util.h"
#include "nsGkAtoms.h"
#include "nsCRT.h"
#include "nsRuleData.h"
@ -76,6 +77,14 @@ ReportParseErrorNoTag(const nsString& aValue,
"AttributeParsingErrorNoTag", argv, 2);
}
nsMathMLElement::nsMathMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsMathMLElementBase(aNodeInfo),
ALLOW_THIS_IN_INITIALIZER_LIST(Link(this)),
mIncrementScriptLevel(false)
{
SetIsDOMBinding();
}
nsresult
nsMathMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,

View File

@ -24,12 +24,7 @@ class nsMathMLElement : public nsMathMLElementBase,
public mozilla::dom::Link
{
public:
nsMathMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsMathMLElementBase(aNodeInfo), Link(this),
mIncrementScriptLevel(false)
{
SetIsDOMBinding();
}
nsMathMLElement(already_AddRefed<nsINodeInfo> aNodeInfo);
// Implementation of nsISupports is inherited from nsMathMLElementBase
NS_DECL_ISUPPORTS_INHERITED

View File

@ -12,6 +12,7 @@
namespace mozilla {
namespace dom {
class AudioNode;
struct ThreeDPoint;
}
@ -146,12 +147,15 @@ AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
*/
class AudioNodeEngine {
public:
AudioNodeEngine()
explicit AudioNodeEngine(dom::AudioNode* aNode)
: mNode(aNode)
{
MOZ_ASSERT(mNode, "The engine is constructed with a null node");
MOZ_COUNT_CTOR(AudioNodeEngine);
}
virtual ~AudioNodeEngine()
{
MOZ_ASSERT(!mNode, "The node reference must be already cleared");
MOZ_COUNT_DTOR(AudioNodeEngine);
}
@ -199,6 +203,16 @@ public:
{
*aOutput = aInput;
}
dom::AudioNode* Node() const
{
MOZ_ASSERT(NS_IsMainThread());
return mNode;
}
protected:
friend class dom::AudioNode;
dom::AudioNode* mNode;
};
}

View File

@ -193,7 +193,7 @@ AudioChunk*
AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk)
{
uint32_t inputCount = mInputs.Length();
uint32_t outputChannelCount = 0;
uint32_t outputChannelCount = mNumberOfInputChannels;
nsAutoTArray<AudioChunk*,250> inputChunks;
for (uint32_t i = 0; i < inputCount; ++i) {
MediaStream* s = mInputs[i]->GetSource();
@ -209,8 +209,10 @@ AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk)
}
inputChunks.AppendElement(chunk);
outputChannelCount =
GetAudioChannelsSuperset(outputChannelCount, chunk->mChannelData.Length());
if (!mNumberOfInputChannels) {
outputChannelCount =
GetAudioChannelsSuperset(outputChannelCount, chunk->mChannelData.Length());
}
}
uint32_t inputChunkCount = inputChunks.Length();
@ -219,7 +221,8 @@ AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk)
return aTmpChunk;
}
if (inputChunkCount == 1) {
if (inputChunkCount == 1 &&
inputChunks[0]->mChannelData.Length() == outputChannelCount) {
return inputChunks[0];
}
@ -233,6 +236,21 @@ AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk)
AudioChannelsUpMix(&channels, outputChannelCount, nullptr);
NS_ASSERTION(outputChannelCount == channels.Length(),
"We called GetAudioChannelsSuperset to avoid this");
} else if (channels.Length() > outputChannelCount) {
nsAutoTArray<float*,GUESS_AUDIO_CHANNELS> outputChannels;
outputChannels.SetLength(outputChannelCount);
for (uint32_t i = 0; i < outputChannelCount; ++i) {
outputChannels[i] =
const_cast<float*>(static_cast<const float*>(aTmpChunk->mChannelData[i]));
}
AudioChannelsDownMix(channels, outputChannels.Elements(),
outputChannelCount, WEBAUDIO_BLOCK_SIZE);
channels.SetLength(outputChannelCount);
for (uint32_t i = 0; i < channels.Length(); ++i) {
channels[i] = outputChannels[i];
}
}
for (uint32_t c = 0; c < channels.Length(); ++c) {

View File

@ -43,10 +43,12 @@ public:
* Transfers ownership of aEngine to the new AudioNodeStream.
*/
AudioNodeStream(AudioNodeEngine* aEngine,
MediaStreamGraph::AudioNodeStreamKind aKind)
MediaStreamGraph::AudioNodeStreamKind aKind,
uint32_t aNumberOfInputChannels = 0)
: ProcessedMediaStream(nullptr),
mEngine(aEngine),
mKind(aKind)
mKind(aKind),
mNumberOfInputChannels(aNumberOfInputChannels)
{
// AudioNodes are always producing data
mHasCurrentData = true;
@ -91,6 +93,8 @@ protected:
AudioChunk mLastChunk;
// Whether this is an internal or external stream
MediaStreamGraph::AudioNodeStreamKind mKind;
// The number of input channels that this stream requires. 0 means don't care.
uint32_t mNumberOfInputChannels;
};
}

View File

@ -2010,9 +2010,10 @@ MediaStreamGraph::CreateTrackUnionStream(DOMMediaStream* aWrapper)
AudioNodeStream*
MediaStreamGraph::CreateAudioNodeStream(AudioNodeEngine* aEngine,
AudioNodeStreamKind aKind)
AudioNodeStreamKind aKind,
uint32_t aNumberOfInputChannels)
{
AudioNodeStream* stream = new AudioNodeStream(aEngine, aKind);
AudioNodeStream* stream = new AudioNodeStream(aEngine, aKind, aNumberOfInputChannels);
NS_ADDREF(stream);
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
stream->SetGraphImpl(graph);

View File

@ -909,7 +909,8 @@ public:
* Takes ownership of aEngine.
*/
AudioNodeStream* CreateAudioNodeStream(AudioNodeEngine* aEngine,
AudioNodeStreamKind aKind);
AudioNodeStreamKind aKind,
uint32_t aNumberOfInputChannels = 0);
/**
* Returns the number of graph updates sent. This can be used to track
* whether a given update has been processed by the graph thread and reflected

View File

@ -21,38 +21,34 @@ class AnalyserNodeEngine : public AudioNodeEngine
class TransferBuffer : public nsRunnable
{
public:
TransferBuffer(AnalyserNode* aNode,
TransferBuffer(AudioNodeStream* aStream,
const AudioChunk& aChunk)
: mNode(aNode)
: mStream(aStream)
, mChunk(aChunk)
{
}
NS_IMETHOD Run()
{
mNode->AppendChunk(mChunk);
nsRefPtr<AnalyserNode> node = static_cast<AnalyserNode*>(mStream->Engine()->Node());
if (node) {
node->AppendChunk(mChunk);
}
return NS_OK;
}
private:
AnalyserNode* mNode;
nsRefPtr<AudioNodeStream> mStream;
AudioChunk mChunk;
};
public:
explicit AnalyserNodeEngine(AnalyserNode& aNode)
: mMutex("AnalyserNodeEngine")
, mNode(&aNode)
explicit AnalyserNodeEngine(AnalyserNode* aNode)
: AudioNodeEngine(aNode)
{
MOZ_ASSERT(NS_IsMainThread());
}
void DisconnectFromNode()
{
MutexAutoLock lock(mMutex);
mNode = nullptr;
}
virtual void ProduceAudioBlock(AudioNodeStream* aStream,
const AudioChunk& aInput,
AudioChunk* aOutput,
@ -60,17 +56,12 @@ public:
{
*aOutput = aInput;
MutexAutoLock lock(mMutex);
if (mNode &&
aInput.mChannelData.Length() > 0) {
nsRefPtr<TransferBuffer> transfer = new TransferBuffer(mNode, aInput);
nsRefPtr<TransferBuffer> transfer = new TransferBuffer(aStream, aInput);
NS_DispatchToMainThread(transfer);
}
}
private:
Mutex mMutex;
AnalyserNode* mNode; // weak pointer, cleared by AnalyserNode::DestroyMediaStream
};
AnalyserNode::AnalyserNode(AudioContext* aContext)
@ -81,7 +72,7 @@ AnalyserNode::AnalyserNode(AudioContext* aContext)
, mSmoothingTimeConstant(.8)
, mWriteIndex(0)
{
mStream = aContext->Graph()->CreateAudioNodeStream(new AnalyserNodeEngine(*this),
mStream = aContext->Graph()->CreateAudioNodeStream(new AnalyserNodeEngine(this),
MediaStreamGraph::INTERNAL_STREAM);
AllocateBuffer();
}
@ -255,11 +246,6 @@ AnalyserNode::ApplyBlackmanWindow(float* aBuffer, uint32_t aSize)
void
AnalyserNode::DestroyMediaStream()
{
if (mStream) {
AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
AnalyserNodeEngine* engine = static_cast<AnalyserNodeEngine*>(ns->Engine());
engine->DisconnectFromNode();
}
AudioNode::DestroyMediaStream();
}

View File

@ -107,6 +107,13 @@ AudioBuffer::RestoreJSChannelData(JSContext* aJSContext)
}
}
void
AudioBuffer::SetRawChannelContents(JSContext* aJSContext, uint32_t aChannel,
float* aContents)
{
memcpy(JS_GetFloat32ArrayData(mJSChannels[aChannel]), aContents, sizeof(float)*mLength);
}
JSObject*
AudioBuffer::GetChannelData(JSContext* aJSContext, uint32_t aChannel,
ErrorResult& aRv)

View File

@ -102,6 +102,14 @@ public:
uint32_t aChannel,
void* aContents);
// This replaces the contents of the JS array for the given channel.
// This function needs to be called on an AudioBuffer which has not been
// handed off to the content yet, and right after the object has been
// initialized.
void SetRawChannelContents(JSContext* aJSContext,
uint32_t aChannel,
float* aContents);
protected:
void RestoreJSChannelData(JSContext* aJSContext);
void ClearJSChannels();

View File

@ -38,7 +38,9 @@ NS_IMPL_RELEASE_INHERITED(AudioBufferSourceNode, AudioNode)
class AudioBufferSourceNodeEngine : public AudioNodeEngine
{
public:
explicit AudioBufferSourceNodeEngine(AudioDestinationNode* aDestination) :
explicit AudioBufferSourceNodeEngine(AudioNode* aNode,
AudioDestinationNode* aDestination) :
AudioNodeEngine(aNode),
mStart(0), mStop(TRACK_TICKS_MAX),
mResampler(nullptr),
mOffset(0), mDuration(0),
@ -419,7 +421,7 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
, mStartCalled(false)
{
mStream = aContext->Graph()->CreateAudioNodeStream(
new AudioBufferSourceNodeEngine(aContext->Destination()),
new AudioBufferSourceNodeEngine(this, aContext->Destination()),
MediaStreamGraph::INTERNAL_STREAM);
mStream->AddMainThreadListener(this);
}

View File

@ -19,8 +19,13 @@
#include "AudioListener.h"
#include "DynamicsCompressorNode.h"
#include "BiquadFilterNode.h"
#include "ScriptProcessorNode.h"
#include "nsNetUtil.h"
// Note that this number is an arbitrary large value to protect against OOM
// attacks.
const unsigned MAX_SCRIPT_PROCESSOR_CHANNELS = 10000;
namespace mozilla {
namespace dom {
@ -99,6 +104,46 @@ AudioContext::CreateBuffer(JSContext* aJSContext, uint32_t aNumberOfChannels,
return buffer.forget();
}
namespace {
bool IsValidBufferSize(uint32_t aBufferSize) {
switch (aBufferSize) {
case 0: // let the implementation choose the buffer size
case 256:
case 512:
case 1024:
case 2048:
case 4096:
case 8192:
case 16384:
return true;
default:
return false;
}
}
}
already_AddRefed<ScriptProcessorNode>
AudioContext::CreateScriptProcessor(uint32_t aBufferSize,
uint32_t aNumberOfInputChannels,
uint32_t aNumberOfOutputChannels,
ErrorResult& aRv)
{
if (aNumberOfInputChannels == 0 || aNumberOfOutputChannels == 0 ||
aNumberOfInputChannels > MAX_SCRIPT_PROCESSOR_CHANNELS ||
aNumberOfOutputChannels > MAX_SCRIPT_PROCESSOR_CHANNELS ||
!IsValidBufferSize(aBufferSize)) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr;
}
nsRefPtr<ScriptProcessorNode> scriptProcessor =
new ScriptProcessorNode(this, aBufferSize, aNumberOfInputChannels,
aNumberOfOutputChannels);
return scriptProcessor.forget();
}
already_AddRefed<AnalyserNode>
AudioContext::CreateAnalyser()
{

View File

@ -48,6 +48,7 @@ class DynamicsCompressorNode;
class GainNode;
class GlobalObject;
class PannerNode;
class ScriptProcessorNode;
class AudioContext MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck
@ -99,6 +100,22 @@ public:
uint32_t aLength, float aSampleRate,
ErrorResult& aRv);
already_AddRefed<ScriptProcessorNode>
CreateScriptProcessor(uint32_t aBufferSize,
uint32_t aNumberOfInputChannels,
uint32_t aNumberOfOutputChannels,
ErrorResult& aRv);
already_AddRefed<ScriptProcessorNode>
CreateJavaScriptNode(uint32_t aBufferSize,
uint32_t aNumberOfInputChannels,
uint32_t aNumberOfOutputChannels,
ErrorResult& aRv)
{
return CreateScriptProcessor(aBufferSize, aNumberOfInputChannels,
aNumberOfOutputChannels, aRv);
}
already_AddRefed<AnalyserNode>
CreateAnalyser();

View File

@ -18,7 +18,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(AudioDestinationNode, AudioNode)
AudioDestinationNode::AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph)
: AudioNode(aContext)
{
mStream = aGraph->CreateAudioNodeStream(new AudioNodeEngine(),
mStream = aGraph->CreateAudioNodeStream(new AudioNodeEngine(this),
MediaStreamGraph::EXTERNAL_STREAM);
}

View File

@ -201,5 +201,14 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
Context()->UpdatePannerSource();
}
void
AudioNode::UnbindFromEngine()
{
AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
MOZ_ASSERT(ns, "How come we don't have a stream here?");
MOZ_ASSERT(ns->Engine()->mNode == this, "Invalid node reference");
ns->Engine()->mNode = nullptr;
}
}
}

View File

@ -83,6 +83,7 @@ public:
virtual void DestroyMediaStream()
{
if (mStream) {
UnbindFromEngine();
mStream->Destroy();
mStream = nullptr;
}
@ -152,6 +153,8 @@ private:
// This could possibly delete 'this'.
void DisconnectFromGraph();
void UnbindFromEngine();
protected:
static void Callback(AudioNode* aNode) { /* not implemented */ }

View File

@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AudioProcessingEvent.h"
#include "mozilla/dom/AudioProcessingEventBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED_3(AudioProcessingEvent, nsDOMEvent,
mInputBuffer, mOutputBuffer, mNode)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioProcessingEvent)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(AudioProcessingEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(AudioProcessingEvent, nsDOMEvent)
AudioProcessingEvent::AudioProcessingEvent(ScriptProcessorNode* aOwner,
nsPresContext* aPresContext,
nsEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, aEvent)
, mPlaybackTime(0.0)
, mNode(aOwner)
{
SetIsDOMBinding();
}
JSObject*
AudioProcessingEvent::WrapObject(JSContext* aCx, JSObject* aScope)
{
return AudioProcessingEventBinding::Wrap(aCx, aScope, this);
}
void
AudioProcessingEvent::LazilyCreateBuffer(nsRefPtr<AudioBuffer>& aBuffer,
uint32_t aNumberOfChannels)
{
AutoPushJSContext cx(mNode->Context()->GetJSContext());
JSAutoRequest ar(cx);
aBuffer = new AudioBuffer(mNode->Context(), mNode->BufferSize(),
mNode->Context()->SampleRate());
aBuffer->InitializeBuffers(aNumberOfChannels, cx);
}
}
}

View File

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AudioProcessingEvent_h_
#define AudioProcessingEvent_h_
#include "nsDOMEvent.h"
#include "AudioBuffer.h"
#include "ScriptProcessorNode.h"
namespace mozilla {
namespace dom {
class AudioProcessingEvent : public nsDOMEvent,
public EnableWebAudioCheck
{
public:
AudioProcessingEvent(ScriptProcessorNode* aOwner,
nsPresContext *aPresContext,
nsEvent *aEvent);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_TO_NSDOMEVENT
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioProcessingEvent, nsDOMEvent)
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);
void InitEvent(AudioBuffer* aInputBuffer,
uint32_t aNumberOfInputChannels,
double aPlaybackTime)
{
InitEvent(NS_LITERAL_STRING("audioprocess"), false, false);
mInputBuffer = aInputBuffer;
mNumberOfInputChannels = aNumberOfInputChannels;
mPlaybackTime = aPlaybackTime;
}
double PlaybackTime() const
{
return mPlaybackTime;
}
AudioBuffer* InputBuffer()
{
if (!mInputBuffer) {
LazilyCreateBuffer(mInputBuffer, mNumberOfInputChannels);
}
return mInputBuffer;
}
AudioBuffer* OutputBuffer()
{
if (!mOutputBuffer) {
LazilyCreateBuffer(mOutputBuffer, mNode->NumberOfOutputChannels());
}
return mOutputBuffer;
}
bool HasOutputBuffer() const
{
return !!mOutputBuffer;
}
private:
void LazilyCreateBuffer(nsRefPtr<AudioBuffer>& aBuffer,
uint32_t aNumberOfChannels);
private:
double mPlaybackTime;
nsRefPtr<AudioBuffer> mInputBuffer;
nsRefPtr<AudioBuffer> mOutputBuffer;
nsRefPtr<ScriptProcessorNode> mNode;
uint32_t mNumberOfInputChannels;
};
}
}
#endif

View File

@ -26,8 +26,9 @@ NS_IMPL_RELEASE_INHERITED(BiquadFilterNode, AudioNode)
class BiquadFilterNodeEngine : public AudioNodeEngine
{
public:
explicit BiquadFilterNodeEngine(AudioDestinationNode* aDestination)
: mSource(nullptr)
BiquadFilterNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
: AudioNodeEngine(aNode)
, mSource(nullptr)
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
// Keep the default values in sync with the default values in
// BiquadFilterNode::BiquadFilterNode
@ -103,7 +104,7 @@ BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
, mQ(new AudioParam(this, SendQToStream, 1.f))
, mGain(new AudioParam(this, SendGainToStream, 0.f))
{
BiquadFilterNodeEngine* engine = new BiquadFilterNodeEngine(aContext->Destination());
BiquadFilterNodeEngine* engine = new BiquadFilterNodeEngine(this, aContext->Destination());
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
}

View File

@ -29,32 +29,35 @@ class DelayNodeEngine : public AudioNodeEngine
{
public:
enum ChangeType { ADDREF, RELEASE };
PlayingRefChanged(DelayNode& aNode, ChangeType aChange)
: mNode(aNode)
PlayingRefChanged(AudioNodeStream* aStream, ChangeType aChange)
: mStream(aStream)
, mChange(aChange)
{
}
NS_IMETHOD Run()
{
if (mChange == ADDREF) {
mNode.mPlayingRef.Take(&mNode);
} else if (mChange == RELEASE) {
mNode.mPlayingRef.Drop(&mNode);
nsRefPtr<DelayNode> node = static_cast<DelayNode*>(mStream->Engine()->Node());
if (node) {
if (mChange == ADDREF) {
node->mPlayingRef.Take(node);
} else if (mChange == RELEASE) {
node->mPlayingRef.Drop(node);
}
}
return NS_OK;
}
private:
DelayNode& mNode;
nsRefPtr<AudioNodeStream> mStream;
ChangeType mChange;
};
public:
DelayNodeEngine(AudioDestinationNode* aDestination, DelayNode& aDelay)
: mSource(nullptr)
DelayNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
: AudioNodeEngine(aNode)
, mSource(nullptr)
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
, mDelayNode(aDelay)
// Keep the default value in sync with the default value in DelayNode::DelayNode.
, mDelay(0.f)
, mMaxDelay(0.)
@ -136,7 +139,7 @@ public:
mLeftOverData = static_cast<int32_t>(mCurrentDelayTime * IdealAudioRate());
nsRefPtr<PlayingRefChanged> refchanged =
new PlayingRefChanged(mDelayNode, PlayingRefChanged::ADDREF);
new PlayingRefChanged(aStream, PlayingRefChanged::ADDREF);
NS_DispatchToMainThread(refchanged);
} else if (mLeftOverData != INT32_MIN) {
mLeftOverData -= WEBAUDIO_BLOCK_SIZE;
@ -145,7 +148,7 @@ public:
playedBackAllLeftOvers = true;
nsRefPtr<PlayingRefChanged> refchanged =
new PlayingRefChanged(mDelayNode, PlayingRefChanged::RELEASE);
new PlayingRefChanged(aStream, PlayingRefChanged::RELEASE);
NS_DispatchToMainThread(refchanged);
}
}
@ -244,7 +247,6 @@ public:
AudioNodeStream* mSource;
AudioNodeStream* mDestination;
DelayNode& mDelayNode;
AudioParamTimeline mDelay;
// Maximum delay time in seconds
double mMaxDelay;
@ -264,7 +266,7 @@ DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
: AudioNode(aContext)
, mDelay(new AudioParam(this, SendDelayToStream, 0.0f))
{
DelayNodeEngine* engine = new DelayNodeEngine(aContext->Destination(), *this);
DelayNodeEngine* engine = new DelayNodeEngine(this, aContext->Destination());
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());

View File

@ -31,8 +31,10 @@ NS_IMPL_RELEASE_INHERITED(DynamicsCompressorNode, AudioNode)
class DynamicsCompressorNodeEngine : public AudioNodeEngine
{
public:
explicit DynamicsCompressorNodeEngine(AudioDestinationNode* aDestination)
: mSource(nullptr)
explicit DynamicsCompressorNodeEngine(AudioNode* aNode,
AudioDestinationNode* aDestination)
: AudioNodeEngine(aNode)
, mSource(nullptr)
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
// Keep the default value in sync with the default value in
// DynamicsCompressorNode::DynamicsCompressorNode.
@ -120,7 +122,7 @@ DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
, mAttack(new AudioParam(this, SendAttackToStream, 0.003f))
, mRelease(new AudioParam(this, SendReleaseToStream, 0.25f))
{
DynamicsCompressorNodeEngine* engine = new DynamicsCompressorNodeEngine(aContext->Destination());
DynamicsCompressorNodeEngine* engine = new DynamicsCompressorNodeEngine(this, aContext->Destination());
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
}

View File

@ -26,8 +26,9 @@ NS_IMPL_RELEASE_INHERITED(GainNode, AudioNode)
class GainNodeEngine : public AudioNodeEngine
{
public:
explicit GainNodeEngine(AudioDestinationNode* aDestination)
: mSource(nullptr)
GainNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
: AudioNodeEngine(aNode)
, mSource(nullptr)
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
// Keep the default value in sync with the default value in GainNode::GainNode.
, mGain(1.f)
@ -97,7 +98,7 @@ GainNode::GainNode(AudioContext* aContext)
: AudioNode(aContext)
, mGain(new AudioParam(this, SendGainToStream, 1.0f))
{
GainNodeEngine* engine = new GainNodeEngine(aContext->Destination());
GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
}

View File

@ -24,6 +24,7 @@ CPPSRCS := \
AudioListener.cpp \
AudioNode.cpp \
AudioParam.cpp \
AudioProcessingEvent.cpp \
BiquadFilterNode.cpp \
DelayNode.cpp \
DynamicsCompressorNode.cpp \
@ -31,6 +32,7 @@ CPPSRCS := \
GainNode.cpp \
MediaBufferDecoder.cpp \
PannerNode.cpp \
ScriptProcessorNode.cpp \
ThreeDPoint.cpp \
WebAudioUtils.cpp \
$(NULL)

View File

@ -18,9 +18,10 @@ using namespace std;
class PannerNodeEngine : public AudioNodeEngine
{
public:
PannerNodeEngine()
explicit PannerNodeEngine(AudioNode* aNode)
: AudioNodeEngine(aNode)
// Please keep these default values consistent with PannerNode::PannerNode below.
: mPanningModel(PanningModelTypeValues::HRTF)
, mPanningModel(PanningModelTypeValues::HRTF)
, mPanningModelFunction(&PannerNodeEngine::HRTFPanningFunction)
, mDistanceModel(DistanceModelTypeValues::Inverse)
, mDistanceModelFunction(&PannerNodeEngine::InverseGainFunction)
@ -172,7 +173,7 @@ PannerNode::PannerNode(AudioContext* aContext)
, mConeOuterAngle(360.)
, mConeOuterGain(0.)
{
mStream = aContext->Graph()->CreateAudioNodeStream(new PannerNodeEngine(),
mStream = aContext->Graph()->CreateAudioNodeStream(new PannerNodeEngine(this),
MediaStreamGraph::INTERNAL_STREAM);
// We should register once we have set up our stream and engine.
Context()->Listener()->RegisterPannerNode(this);

View File

@ -0,0 +1,377 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScriptProcessorNode.h"
#include "mozilla/dom/ScriptProcessorNodeBinding.h"
#include "AudioBuffer.h"
#include "AudioDestinationNode.h"
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "AudioProcessingEvent.h"
#include "WebAudioUtils.h"
#include "mozilla/Mutex.h"
#include "mozilla/unused.h"
#include "mozilla/PodOperations.h"
#include <deque>
namespace mozilla {
namespace dom {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ScriptProcessorNode)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(ScriptProcessorNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(ScriptProcessorNode, AudioNode)
// This class manages a queue of output buffers shared between
// the main thread and the Media Stream Graph thread.
class SharedBuffers
{
private:
class OutputQueue
{
public:
explicit OutputQueue(const char* aName)
: mMutex(aName)
{}
Mutex& Lock() { return mMutex; }
size_t ReadyToConsume() const
{
mMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(!NS_IsMainThread());
return mBufferList.size();
}
// Produce one buffer
AudioChunk& Produce()
{
mMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(NS_IsMainThread());
mBufferList.push_back(AudioChunk());
return mBufferList.back();
}
// Consumes one buffer.
AudioChunk Consume()
{
mMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(ReadyToConsume() > 0);
AudioChunk front = mBufferList.front();
mBufferList.pop_front();
return front;
}
private:
typedef std::deque<AudioChunk> BufferList;
// Synchronizes access to mBufferList. Note that it's the responsibility
// of the callers to perform the required locking, and we assert that every
// time we access mBufferList.
Mutex mMutex;
// The list representing the queue.
BufferList mBufferList;
};
public:
SharedBuffers()
: mOutputQueue("SharedBuffers::outputQueue")
, mDelaySoFar(TRACK_TICKS_MAX)
{
}
// main thread
void FinishProducingOutputBuffer(ThreadSharedFloatArrayBufferList* aBuffer,
uint32_t aBufferSize)
{
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mOutputQueue.Lock());
for (uint32_t offset = 0; offset < aBufferSize; offset += WEBAUDIO_BLOCK_SIZE) {
AudioChunk& chunk = mOutputQueue.Produce();
if (aBuffer) {
chunk.mDuration = WEBAUDIO_BLOCK_SIZE;
chunk.mBuffer = aBuffer;
chunk.mChannelData.SetLength(aBuffer->GetChannels());
for (uint32_t i = 0; i < aBuffer->GetChannels(); ++i) {
chunk.mChannelData[i] = aBuffer->GetData(i) + offset;
}
chunk.mVolume = 1.0f;
chunk.mBufferFormat = AUDIO_FORMAT_FLOAT32;
} else {
chunk.SetNull(WEBAUDIO_BLOCK_SIZE);
}
}
}
// graph thread
AudioChunk GetOutputBuffer()
{
MOZ_ASSERT(!NS_IsMainThread());
AudioChunk buffer;
{
MutexAutoLock lock(mOutputQueue.Lock());
if (mOutputQueue.ReadyToConsume() > 0) {
if (mDelaySoFar == TRACK_TICKS_MAX) {
mDelaySoFar = 0;
}
buffer = mOutputQueue.Consume();
} else {
// If we're out of buffers to consume, just output silence
buffer.SetNull(WEBAUDIO_BLOCK_SIZE);
if (mDelaySoFar != TRACK_TICKS_MAX) {
// Remember the delay that we just hit
mDelaySoFar += WEBAUDIO_BLOCK_SIZE;
}
}
}
return buffer;
}
TrackTicks DelaySoFar() const
{
MOZ_ASSERT(!NS_IsMainThread());
return mDelaySoFar == TRACK_TICKS_MAX ? 0 : mDelaySoFar;
}
private:
OutputQueue mOutputQueue;
// How much delay we've seen so far. This measures the amount of delay
// caused by the main thread lagging behind in producing output buffers.
// TRACK_TICKS_MAX means that we have not received our first buffer yet.
TrackTicks mDelaySoFar;
};
class ScriptProcessorNodeEngine : public AudioNodeEngine
{
public:
typedef nsAutoTArray<nsAutoArrayPtr<float>, 2> InputChannels;
ScriptProcessorNodeEngine(ScriptProcessorNode* aNode,
AudioDestinationNode* aDestination,
uint32_t aBufferSize,
uint32_t aNumberOfInputChannels)
: AudioNodeEngine(aNode)
, mSharedBuffers(aNode->GetSharedBuffers())
, mSource(nullptr)
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
, mBufferSize(aBufferSize)
, mInputWriteIndex(0)
, mSeenNonSilenceInput(false)
{
mInputChannels.SetLength(aNumberOfInputChannels);
AllocateInputBlock();
}
void SetSourceStream(AudioNodeStream* aSource)
{
mSource = aSource;
}
virtual void ProduceAudioBlock(AudioNodeStream* aStream,
const AudioChunk& aInput,
AudioChunk* aOutput,
bool* aFinished) MOZ_OVERRIDE
{
// If our node is dead, just output silence
if (!mNode) {
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
return;
}
// First, record our input buffer
for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
if (aInput.IsNull()) {
PodZero(mInputChannels[i] + mInputWriteIndex,
aInput.GetDuration());
} else {
mSeenNonSilenceInput = true;
PodCopy(mInputChannels[i] + mInputWriteIndex,
static_cast<const float*>(aInput.mChannelData[i]),
aInput.GetDuration());
}
}
mInputWriteIndex += aInput.GetDuration();
// Now, see if we have data to output
// Note that we need to do this before sending the buffer to the main
// thread so that our delay time is updated.
*aOutput = mSharedBuffers->GetOutputBuffer();
if (mInputWriteIndex >= mBufferSize) {
SendBuffersToMainThread(aStream);
mInputWriteIndex -= mBufferSize;
mSeenNonSilenceInput = false;
AllocateInputBlock();
}
}
private:
void AllocateInputBlock()
{
for (unsigned i = 0; i < mInputChannels.Length(); ++i) {
if (!mInputChannels[i]) {
mInputChannels[i] = new float[mBufferSize];
}
}
}
void SendBuffersToMainThread(AudioNodeStream* aStream)
{
MOZ_ASSERT(!NS_IsMainThread());
// we now have a full input buffer ready to be sent to the main thread.
TrackTicks playbackTick = mSource->GetCurrentPosition();
// Add the duration of the current sample
playbackTick += WEBAUDIO_BLOCK_SIZE;
// Add the delay caused by the main thread
playbackTick += mSharedBuffers->DelaySoFar();
// Compute the playback time in the coordinate system of the destination
double playbackTime =
WebAudioUtils::StreamPositionToDestinationTime(playbackTick,
mSource,
mDestination);
class Command : public nsRunnable
{
public:
Command(AudioNodeStream* aStream,
InputChannels& aInputChannels,
double aPlaybackTime,
bool aNullInput)
: mStream(aStream)
, mPlaybackTime(aPlaybackTime)
, mNullInput(aNullInput)
{
mInputChannels.SetLength(aInputChannels.Length());
if (!aNullInput) {
for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
mInputChannels[i] = aInputChannels[i].forget();
}
}
}
NS_IMETHODIMP Run()
{
// If it's not safe to run scripts right now, schedule this to run later
if (!nsContentUtils::IsSafeToRunScript()) {
nsContentUtils::AddScriptRunner(this);
return NS_OK;
}
nsRefPtr<ScriptProcessorNode> node = static_cast<ScriptProcessorNode*>(mStream->Engine()->Node());
if (!node) {
return NS_OK;
}
AutoPushJSContext cx(node->Context()->GetJSContext());
if (cx) {
JSAutoRequest ar(cx);
// Create the input buffer
nsRefPtr<AudioBuffer> inputBuffer;
if (!mNullInput) {
inputBuffer = new AudioBuffer(node->Context(),
node->BufferSize(),
node->Context()->SampleRate());
if (!inputBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
return NS_OK;
}
// Put the channel data inside it
for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
inputBuffer->SetRawChannelContents(cx, i, mInputChannels[i]);
}
}
// Ask content to produce data in the output buffer
// Note that we always avoid creating the output buffer here, and we try to
// avoid creating the input buffer as well. The AudioProcessingEvent class
// knows how to lazily create them if needed once the script tries to access
// them. Otherwise, we may be able to get away without creating them!
nsRefPtr<AudioProcessingEvent> event = new AudioProcessingEvent(node, nullptr, nullptr);
event->InitEvent(inputBuffer,
mInputChannels.Length(),
mPlaybackTime);
node->DispatchTrustedEvent(event);
// Steal the output buffers
nsRefPtr<ThreadSharedFloatArrayBufferList> output;
if (event->HasOutputBuffer()) {
uint32_t rate, length;
output = event->OutputBuffer()->GetThreadSharedChannelsForRate(cx, &rate, &length);
unused << rate;
unused << length;
}
// Append it to our output buffer queue
node->GetSharedBuffers()->FinishProducingOutputBuffer(output, node->BufferSize());
}
return NS_OK;
}
private:
nsRefPtr<AudioNodeStream> mStream;
InputChannels mInputChannels;
double mPlaybackTime;
bool mNullInput;
};
NS_DispatchToMainThread(new Command(aStream, mInputChannels,
playbackTime,
!mSeenNonSilenceInput));
}
friend class ScriptProcessorNode;
SharedBuffers* mSharedBuffers;
AudioNodeStream* mSource;
AudioNodeStream* mDestination;
InputChannels mInputChannels;
const uint32_t mBufferSize;
// The write index into the current input buffer
uint32_t mInputWriteIndex;
bool mSeenNonSilenceInput;
};
ScriptProcessorNode::ScriptProcessorNode(AudioContext* aContext,
uint32_t aBufferSize,
uint32_t aNumberOfInputChannels,
uint32_t aNumberOfOutputChannels)
: AudioNode(aContext)
, mSharedBuffers(new SharedBuffers())
, mBufferSize(aBufferSize ?
aBufferSize : // respect what the web developer requested
4096) // choose our own buffer size -- 4KB for now
, mNumberOfOutputChannels(aNumberOfOutputChannels)
{
MOZ_ASSERT(BufferSize() % WEBAUDIO_BLOCK_SIZE == 0, "Invalid buffer size");
ScriptProcessorNodeEngine* engine =
new ScriptProcessorNodeEngine(this,
aContext->Destination(),
BufferSize(),
aNumberOfInputChannels);
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM,
aNumberOfInputChannels);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
}
ScriptProcessorNode::~ScriptProcessorNode()
{
DestroyMediaStream();
}
JSObject*
ScriptProcessorNode::WrapObject(JSContext* aCx, JSObject* aScope)
{
return ScriptProcessorNodeBinding::Wrap(aCx, aScope, this);
}
}
}

View File

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ScriptProcessorNode_h_
#define ScriptProcessorNode_h_
#include "AudioNode.h"
#include "nsAutoPtr.h"
namespace mozilla {
class AudioNodeStream;
namespace dom {
class AudioContext;
class ScriptProcessorNodeEngine;
class SharedBuffers;
class ScriptProcessorNode : public AudioNode
{
public:
ScriptProcessorNode(AudioContext* aContext,
uint32_t aBufferSize,
uint32_t aNumberOfInputChannels,
uint32_t aNumberOfOutputChannels);
virtual ~ScriptProcessorNode();
NS_DECL_ISUPPORTS_INHERITED
IMPL_EVENT_HANDLER(audioprocess)
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);
virtual bool SupportsMediaStreams() const MOZ_OVERRIDE
{
return true;
}
uint32_t BufferSize() const
{
return mBufferSize;
}
SharedBuffers* GetSharedBuffers() const
{
return mSharedBuffers;
}
uint32_t NumberOfOutputChannels() const
{
return mNumberOfOutputChannels;
}
using nsDOMEventTargetHelper::DispatchTrustedEvent;
private:
nsAutoPtr<SharedBuffers> mSharedBuffers;
const uint32_t mBufferSize;
const uint32_t mNumberOfOutputChannels;
};
}
}
#endif

View File

@ -34,6 +34,17 @@ struct ConvertTimeToTickHelper
}
};
double
WebAudioUtils::StreamPositionToDestinationTime(TrackTicks aSourcePosition,
AudioNodeStream* aSource,
AudioNodeStream* aDestination)
{
StreamTime sourceTime = TicksToTimeRoundDown(IdealAudioRate(), aSourcePosition);
GraphTime graphTime = aSource->StreamTimeToGraphTime(sourceTime);
StreamTime destinationTime = aDestination->GraphTimeToStreamTimeOptimistic(graphTime);
return MediaTimeToSeconds(destinationTime);
}
void
WebAudioUtils::ConvertAudioParamToTicks(AudioParamTimeline& aParam,
AudioNodeStream* aSource,

View File

@ -9,6 +9,7 @@
#include <cmath>
#include "AudioParamTimeline.h"
#include "MediaSegment.h"
namespace mozilla {
@ -73,6 +74,14 @@ struct WebAudioUtils {
aDouble = 0.0;
}
}
/**
* Convert a stream position into the time coordinate of the destination
* stream.
*/
static double StreamPositionToDestinationTime(TrackTicks aSourcePosition,
AudioNodeStream* aSource,
AudioNodeStream* aDestination);
};
}

View File

@ -26,11 +26,13 @@ EXPORTS.mozilla.dom += [
'AudioListener.h',
'AudioNode.h',
'AudioParam.h',
'AudioProcessingEvent.h',
'BiquadFilterNode.h',
'DelayNode.h',
'DynamicsCompressorNode.h',
'EnableWebAudioCheck.h',
'GainNode.h',
'PannerNode.h',
'ScriptProcessorNode.h',
]

View File

@ -22,6 +22,7 @@ MOCHITEST_FILES := \
test_AudioContext.html \
test_AudioListener.html \
test_AudioParam.html \
test_audioBufferSourceNode.html \
test_badConnect.html \
test_biquadFilterNode.html \
test_currentTime.html \
@ -30,6 +31,7 @@ MOCHITEST_FILES := \
test_dynamicsCompressorNode.html \
test_gainNode.html \
test_pannerNode.html \
test_scriptProcessorNode.html \
test_singleSourceDest.html \
ting.ogg \
ting-expected.wav \

View File

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test AudioBufferSourceNode</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="webaudio.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
var context = new AudioContext();
var buffer = context.createBuffer(1, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate);
}
var source = context.createBufferSource();
source.buffer = buffer;
var sp = context.createScriptProcessor(2048);
source.start(0);
source.connect(sp);
sp.connect(context.destination);
sp.onaudioprocess = function(e) {
compareBuffers(e.inputBuffer.getChannelData(0), buffer.getChannelData(0));
compareBuffers(e.inputBuffer.getChannelData(1), buffer.getChannelData(0));
// On the next iteration, we'll get a silence buffer
sp.onaudioprocess = function(e) {
var emptyBuffer = context.createBuffer(1, 2048, context.sampleRate);
compareBuffers(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
compareBuffers(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
sp.onaudioprocess = null;
sp.disconnect(context.destination);
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
};
};
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,139 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test ScriptProcessorNode</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="webaudio.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
var context = new AudioContext();
var buffer = null;
var sourceSP = context.createJavaScriptNode(2048);
sourceSP.addEventListener("audioprocess", function(e) {
// generate the audio
for (var i = 0; i < 2048; ++i) {
// Make sure our first sample won't be zero
e.outputBuffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * (i + 1) / context.sampleRate);
e.outputBuffer.getChannelData(0)[i] = Math.sin(880 * 2 * Math.PI * (i + 1) / context.sampleRate);
}
// Remember our generated audio
buffer = e.outputBuffer;
sourceSP.removeEventListener("audioprocess", arguments.callee);
}, false);
expectException(function() {
context.createScriptProcessor(1);
}, DOMException.INDEX_SIZE_ERR);
expectException(function() {
context.createScriptProcessor(2);
}, DOMException.INDEX_SIZE_ERR);
expectException(function() {
context.createScriptProcessor(128);
}, DOMException.INDEX_SIZE_ERR);
expectException(function() {
context.createScriptProcessor(255);
}, DOMException.INDEX_SIZE_ERR);
function findFirstNonZeroSample(buffer) {
for (var i = 0; i < buffer.length; ++i) {
if (buffer.getChannelData(0)[i] != 0) {
return i;
}
}
return buffer.length;
}
var sp = context.createScriptProcessor(2048);
sourceSP.connect(sp);
sp.connect(context.destination);
var lastPlaybackTime = 0;
sp.onaudioprocess = function(e) {
isnot(buffer, null, "The audioprocess handler for sourceSP must be run at this point");
is(e.target, sp, "Correct event target");
ok(e.playbackTime > lastPlaybackTime, "playbackTime correctly set");
lastPlaybackTime = e.playbackTime;
is(e.inputBuffer.numberOfChannels, 2, "Correct number of channels for the input buffer");
is(e.inputBuffer.length, 2048, "Correct length for the input buffer");
is(e.inputBuffer.sampleRate, context.sampleRate, "Correct sample rate for the input buffer");
is(e.outputBuffer.numberOfChannels, 2, "Correct number of channels for the output buffer");
is(e.outputBuffer.length, 2048, "Correct length for the output buffer");
is(e.outputBuffer.sampleRate, context.sampleRate, "Correct sample rate for the output buffer");
// Because of the initial latency added by the second script processor node,
// we will never see any generated audio frames in the first callback.
var emptyBuffer = context.createBuffer(1, 2048, context.sampleRate);
compareBuffers(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
compareBuffers(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
compareBuffers(e.outputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
compareBuffers(e.outputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
sp.onaudioprocess = function(e) {
is(e.target, sp, "Correct event target");
ok(e.playbackTime > lastPlaybackTime, "playbackTime correctly set");
lastPlaybackTime = e.playbackTime;
is(e.inputBuffer.numberOfChannels, 2, "Correct number of channels for the input buffer");
is(e.inputBuffer.length, 2048, "Correct length for the input buffer");
is(e.inputBuffer.sampleRate, context.sampleRate, "Correct sample rate for the input buffer");
is(e.outputBuffer.numberOfChannels, 2, "Correct number of channels for the output buffer");
is(e.outputBuffer.length, 2048, "Correct length for the output buffer");
is(e.outputBuffer.sampleRate, context.sampleRate, "Correct sample rate for the output buffer");
var firstNonZero = findFirstNonZeroSample(e.inputBuffer);
compareBuffers(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0), 0, Math.min(firstNonZero, 2048));
compareBuffers(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0), 0, Math.min(firstNonZero, 2048));
compareBuffers(e.inputBuffer.getChannelData(0), buffer.getChannelData(0), Math.min(firstNonZero, 2048), 2048 - firstNonZero, 0, -firstNonZero);
compareBuffers(e.inputBuffer.getChannelData(1), buffer.getChannelData(1), Math.min(firstNonZero, 2048), 2048 - firstNonZero, 0, -firstNonZero);
compareBuffers(e.outputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
compareBuffers(e.outputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
if (firstNonZero == 0) {
// If we did not experience any delays, the test is done!
sp.onaudioprocess = null;
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
} else if (firstNonZero != 2048) {
// In case we just saw a zero buffer this time, wait one more round
sp.onaudioprocess = function(e) {
is(e.target, sp, "Correct event target");
ok(e.playbackTime > lastPlaybackTime, "playbackTime correctly set");
lastPlaybackTime = e.playbackTime;
is(e.inputBuffer.numberOfChannels, 2, "Correct number of channels for the input buffer");
is(e.inputBuffer.length, 2048, "Correct length for the input buffer");
is(e.inputBuffer.sampleRate, context.sampleRate, "Correct sample rate for the input buffer");
is(e.outputBuffer.numberOfChannels, 2, "Correct number of channels for the output buffer");
is(e.outputBuffer.length, 2048, "Correct length for the output buffer");
is(e.outputBuffer.sampleRate, context.sampleRate, "Correct sample rate for the output buffer");
compareBuffers(e.inputBuffer.getChannelData(0), buffer.getChannelData(0), 0, firstNonZero, 0, 2048 - firstNonZero);
compareBuffers(e.inputBuffer.getChannelData(1), buffer.getChannelData(1), 0, firstNonZero, 0, 2048 - firstNonZero);
compareBuffers(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0), firstNonZero);
compareBuffers(e.inputBuffer.getChannelData(1), emptyBuffer.getChannelData(0), firstNonZero);
compareBuffers(e.outputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
compareBuffers(e.outputBuffer.getChannelData(1), emptyBuffer.getChannelData(0));
sp.onaudioprocess = null;
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
};
}
};
};
});
</script>
</pre>
</body>
</html>

View File

@ -22,3 +22,38 @@ function expectTypeError(func) {
}
ok(threw, "The exception was thrown");
}
function fuzzyCompare(a, b) {
return Math.abs(a - b) < 1e-5;
}
function compareBuffers(buf1, buf2,
/*optional*/ offset,
/*optional*/ length,
/*optional*/ sourceOffset,
/*optional*/ destOffset) {
is(buf1.length, buf2.length, "Buffers must have the same length");
if (length == undefined) {
length = buf1.length - (offset || 0);
}
sourceOffset = sourceOffset || 0;
destOffset = destOffset || 0;
var difference = 0;
var maxDifference = 0;
var firstBadIndex = -1;
for (var i = offset || 0; i < Math.min(buf1.length, (offset || 0) + length); ++i) {
if (!fuzzyCompare(buf1[i + sourceOffset], buf2[i + destOffset])) {
console.log(buf1[i+sourceOffset] + " " + buf2[i+destOffset]);
difference++;
maxDifference = Math.max(maxDifference, Math.abs(buf1[i + sourceOffset] - buf2[i + destOffset]));
if (firstBadIndex == -1) {
firstBadIndex = i;
}
}
};
is(difference, 0, "Found " + difference + " different samples, maxDifference: " +
maxDifference + ", first bad index: " + firstBadIndex +
" with source offset " + sourceOffset + " and desitnation offset " +
destOffset);
}

View File

@ -27,6 +27,8 @@
#include "nsXULTemplateResultXML.h"
#include "nsXULSortService.h"
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS1(nsXMLQuery, nsXMLQuery)
//----------------------------------------------------------------------
@ -175,7 +177,7 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = req->Init(docPrincipal, context,
rv = req->Init(docPrincipal, context,
scriptObject ? scriptObject : doc->GetScopeObject(),
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
@ -184,7 +186,7 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
EmptyString(), EmptyString());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(req));
nsCOMPtr<EventTarget> target(do_QueryInterface(req));
rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -1787,11 +1787,11 @@ NS_IMETHODIMP
nsDocShell::SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler)
{
// Weak reference. Don't addref.
mChromeEventHandler = aChromeEventHandler;
nsCOMPtr<EventTarget> handler = do_QueryInterface(aChromeEventHandler);
mChromeEventHandler = handler.get();
if (mScriptGlobal) {
mScriptGlobal->SetChromeEventHandler(handler);
mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
}
return NS_OK;
@ -1801,8 +1801,8 @@ NS_IMETHODIMP
nsDocShell::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler)
{
NS_ENSURE_ARG_POINTER(aChromeEventHandler);
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mChromeEventHandler);
target.swap(*aChromeEventHandler);
nsCOMPtr<EventTarget> handler = mChromeEventHandler;
handler.forget(aChromeEventHandler);
return NS_OK;
}
@ -9718,6 +9718,11 @@ nsDocShell::ScrollToAnchor(nsACString & aCurHash, nsACString & aNewHash,
return NS_OK;
}
nsIScrollableFrame* rootScroll = shell->GetRootScrollFrameAsScrollable();
if (rootScroll) {
rootScroll->ClearDidHistoryRestore();
}
// If we have no new anchor, we do not want to scroll, unless there is a
// current anchor and we are doing a history load. So return if we have no
// new anchor, and there is no current anchor or the load is not a history

View File

@ -751,7 +751,7 @@ protected:
// For that reasons don't use nsCOMPtr.
nsIDocShellTreeOwner * mTreeOwner; // Weak Reference
nsIDOMEventTarget * mChromeEventHandler; //Weak Reference
mozilla::dom::EventTarget* mChromeEventHandler; //Weak Reference
eCharsetReloadState mCharsetReloadState;

View File

@ -515,6 +515,6 @@ AudioChannelService::GetInternalType(AudioChannelType aType,
break;
}
MOZ_NOT_REACHED();
MOZ_NOT_REACHED("unexpected audio channel type");
return AUDIO_CHANNEL_INT_LAST;
}

View File

@ -23,9 +23,7 @@ LIBRARY_NAME = domaudiochannel_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
ifndef _MSC_VER
FAIL_ON_WARNINGS := 1
endif # !_MSC_VER
CPPSRCS += \
AudioChannelService.cpp \

View File

@ -12,9 +12,7 @@ include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = jsdombase_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
ifndef _MSC_VER
FAIL_ON_WARNINGS := 1
endif # !_MSC_VER
EXTRA_COMPONENTS = \
SiteSpecificUserAgent.js \

View File

@ -660,16 +660,10 @@ StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
NS_IMETHODIMP
VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(target);
nsCOMPtr<nsIDocument> doc =
do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
bool hidden = true;
if (doc) {
doc->GetHidden(&hidden);
}
if (hidden) {
if (!doc || doc->Hidden()) {
// It's important that we call CancelVibrate(), not Vibrate() with an
// empty list, because Vibrate() will fail if we're no longer focused, but
// CancelVibrate() will succeed, so long as nobody else has started a new
@ -687,7 +681,7 @@ VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
void
VibrateWindowListener::RemoveListener()
{
nsCOMPtr<nsIDOMEventTarget> target = do_QueryReferent(mDocument);
nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument);
if (!target) {
return;
}

View File

@ -7432,9 +7432,8 @@ nsEventListenerThisTranslator::TranslateThis(nsISupports *aInitialThis,
nsCOMPtr<nsIDOMEvent> event(do_QueryInterface(aInitialThis));
NS_ENSURE_TRUE(event, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMEventTarget> target;
event->GetCurrentTarget(getter_AddRefs(target));
target.forget(_retval);
nsCOMPtr<EventTarget> target = event->InternalDOMEvent()->GetCurrentTarget();
*_retval = target.forget().get();
return NS_OK;
}

View File

@ -104,7 +104,7 @@ struct nsDelayedBlurOrFocusEvent
nsDelayedBlurOrFocusEvent(uint32_t aType,
nsIPresShell* aPresShell,
nsIDocument* aDocument,
nsIDOMEventTarget* aTarget)
EventTarget* aTarget)
: mType(aType),
mPresShell(aPresShell),
mDocument(aDocument),
@ -119,7 +119,7 @@ struct nsDelayedBlurOrFocusEvent
uint32_t mType;
nsCOMPtr<nsIPresShell> mPresShell;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsIDOMEventTarget> mTarget;
nsCOMPtr<EventTarget> mTarget;
};
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFocusManager)
@ -999,7 +999,7 @@ nsFocusManager::FireDelayedEvents(nsIDocument* aDocument)
if (mDelayedBlurFocusEvents[i].mDocument == aDocument &&
!aDocument->EventHandlingSuppressed()) {
uint32_t type = mDelayedBlurFocusEvents[i].mType;
nsCOMPtr<nsIDOMEventTarget> target = mDelayedBlurFocusEvents[i].mTarget;
nsCOMPtr<EventTarget> target = mDelayedBlurFocusEvents[i].mTarget;
nsCOMPtr<nsIPresShell> presShell = mDelayedBlurFocusEvents[i].mPresShell;
mDelayedBlurFocusEvents.RemoveElementAt(i);
SendFocusOrBlurEvent(type, presShell, aDocument, target, 0, false);
@ -1900,7 +1900,7 @@ nsFocusManager::SendFocusOrBlurEvent(uint32_t aType,
NS_ASSERTION(aType == NS_FOCUS_CONTENT || aType == NS_BLUR_CONTENT,
"Wrong event type for SendFocusOrBlurEvent");
nsCOMPtr<nsIDOMEventTarget> eventTarget = do_QueryInterface(aTarget);
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
// for focus events, if this event was from a mouse or key and event
// handling on the document is suppressed, queue the event and fire it

View File

@ -2587,7 +2587,6 @@ void
nsGlobalWindow::ClearStatus()
{
SetStatus(EmptyString());
SetDefaultStatus(EmptyString());
}
void
@ -3893,17 +3892,17 @@ nsGlobalWindow::SetStatus(const nsAString& aStatus)
{
FORWARD_TO_OUTER(SetStatus, (aStatus), NS_ERROR_NOT_INITIALIZED);
mStatus = aStatus;
/*
* If caller is not chrome and dom.disable_window_status_change is true,
* prevent setting window.status by exiting early
* prevent propagating window.status to the UI by exiting early
*/
if (!CanSetProperty("dom.disable_window_status_change")) {
return NS_OK;
}
mStatus = aStatus;
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
if(browserChrome) {
@ -3914,43 +3913,6 @@ nsGlobalWindow::SetStatus(const nsAString& aStatus)
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::GetDefaultStatus(nsAString& aDefaultStatus)
{
FORWARD_TO_OUTER(GetDefaultStatus, (aDefaultStatus),
NS_ERROR_NOT_INITIALIZED);
aDefaultStatus = mDefaultStatus;
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::SetDefaultStatus(const nsAString& aDefaultStatus)
{
FORWARD_TO_OUTER(SetDefaultStatus, (aDefaultStatus),
NS_ERROR_NOT_INITIALIZED);
/*
* If caller is not chrome and dom.disable_window_status_change is true,
* prevent setting window.defaultStatus by exiting early
*/
if (!CanSetProperty("dom.disable_window_status_change")) {
return NS_OK;
}
mDefaultStatus = aDefaultStatus;
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
if (browserChrome) {
browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT_DEFAULT,
PromiseFlatString(aDefaultStatus).get());
}
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::GetName(nsAString& aName)
{
@ -8071,7 +8033,7 @@ nsGlobalWindow::GetListenerManager(bool aCreateIfNotFound)
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager =
new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
new nsEventListenerManager(static_cast<EventTarget*>(this));
}
return mListenerManager;
@ -8685,7 +8647,7 @@ nsGlobalWindow::DispatchSyncPopState()
domEvent->SetTrusted(true);
nsCOMPtr<nsIDOMEventTarget> outerWindow =
nsCOMPtr<EventTarget> outerWindow =
do_QueryInterface(GetOuterWindow());
NS_ENSURE_TRUE(outerWindow, NS_ERROR_UNEXPECTED);
@ -8995,18 +8957,36 @@ nsGlobalWindow::GetIndexedDB(nsISupports** _retval)
}
if (!IsChromeWindow()) {
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID);
NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
// Whitelist about:home, since it doesn't have a base domain it would not
// pass the thirdPartyUtil check, though it should be able to use
// indexedDB.
bool skipThirdPartyCheck = false;
nsIPrincipal *principal = GetPrincipal();
if (principal) {
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
bool isAbout = false;
if (uri && NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)) && isAbout) {
nsAutoCString path;
skipThirdPartyCheck = NS_SUCCEEDED(uri->GetPath(path)) &&
path.EqualsLiteral("home");
}
}
bool isThirdParty;
rv = thirdPartyUtil->IsThirdPartyWindow(this, nullptr, &isThirdParty);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!skipThirdPartyCheck) {
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID);
NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (isThirdParty) {
NS_WARNING("IndexedDB is not permitted in a third-party window.");
*_retval = nullptr;
return NS_OK;
bool isThirdParty;
rv = thirdPartyUtil->IsThirdPartyWindow(this, nullptr, &isThirdParty);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (isThirdParty) {
NS_WARNING("IndexedDB is not permitted in a third-party window.");
*_retval = nullptr;
return NS_OK;
}
}
}

View File

@ -71,7 +71,7 @@ nsScreen::Reset()
hal::UnlockScreenOrientation();
if (mEventListener) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
if (target) {
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mEventListener, /* usecapture */ true);
@ -368,7 +368,7 @@ nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
// and when we will have to unlock the screen.
// This needs to be done before LockScreenOrientation call to make sure
// the locking can be unlocked.
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
if (!target) {
return false;
}
@ -390,7 +390,7 @@ nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
// This is only for compilers that don't understand that the previous switch
// will always return.
MOZ_NOT_REACHED();
MOZ_NOT_REACHED("unexpected lock orientation permission value");
return false;
}
@ -426,8 +426,7 @@ nsScreen::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
#endif
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetCurrentTarget(getter_AddRefs(target));
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
// We have to make sure that the event we got is the event sent when
// fullscreen is disabled because we could get one when fullscreen

View File

@ -78,7 +78,7 @@ nsWindowRoot::DispatchEvent(nsIDOMEvent* aEvt, bool *aRetVal)
{
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv = nsEventDispatcher::DispatchDOMEvent(
static_cast<nsIDOMEventTarget*>(this), nullptr, aEvt, nullptr, &status);
static_cast<EventTarget*>(this), nullptr, aEvt, nullptr, &status);
*aRetVal = (status != nsEventStatus_eConsumeNoDefault);
return rv;
}
@ -89,7 +89,7 @@ nsWindowRoot::DispatchDOMEvent(nsEvent* aEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return nsEventDispatcher::DispatchDOMEvent(static_cast<nsIDOMEventTarget*>(this),
return nsEventDispatcher::DispatchDOMEvent(static_cast<EventTarget*>(this),
aEvent, aDOMEvent,
aPresContext, aEventStatus);
}
@ -149,7 +149,7 @@ nsWindowRoot::GetListenerManager(bool aCreateIfNotFound)
{
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager =
new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
new nsEventListenerManager(static_cast<EventTarget*>(this));
}
return mListenerManager;

View File

@ -28,6 +28,7 @@ MOCHITEST_FILES = \
test_writable-replaceable.html \
test_domcursor.html \
test_named_frames.html \
test_Image_constructor.html \
$(NULL)
MOCHITEST_CHROME_FILES = \

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=862702
-->
<head>
<meta charset="utf-8">
<!-- Make sure our script runs before anything else -->
<script>
var img = new Image;
</script>
<title>Test for Bug 862702</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 862702 **/
is(Object.getPrototypeOf(img), HTMLImageElement.prototype,
"Wrong prototype object");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=862702">Mozilla Bug 862702</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -630,6 +630,10 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx, JSObject* scope, T* value,
obj = value->WrapObject(cx, scope);
}
if (!obj) {
return false;
}
// We can end up here in all sorts of compartments, per above. Make
// sure to JS_WrapValue!
*vp = JS::ObjectValue(*obj);
@ -660,11 +664,18 @@ WrapNewBindingNonWrapperCachedOwnedObject(JSContext* cx, JSObject* scope,
bool tookOwnership = false;
obj = value->WrapObject(cx, scope, &tookOwnership);
if (obj) {
MOZ_ASSERT(tookOwnership);
}
if (tookOwnership) {
value.forget();
}
}
if (!obj) {
return false;
}
// We can end up here in all sorts of compartments, per above. Make
// sure to JS_WrapValue!
*vp = JS::ObjectValue(*obj);
@ -1734,6 +1745,15 @@ InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue vp,
void
ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj);
inline JSObject*
GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
{
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
JSObject* interfaceProto = protoAndIfaceArray[aId];
return &js::GetReservedSlot(interfaceProto,
DOM_INTERFACE_PROTO_SLOTS_BASE).toObject();
}
} // namespace dom
} // namespace mozilla

View File

@ -122,6 +122,10 @@ DOMInterfaces = {
'nativeOwnership': 'refcounted'
},
'AudioProcessingEvent' : {
'resultNotAddRefed': [ 'inputBuffer', 'outputBuffer' ],
},
'BeforeUnloadEvent': {
'nativeType': 'nsDOMBeforeUnloadEvent',
},
@ -557,6 +561,10 @@ DOMInterfaces = {
'workers': True,
}],
'KeyEvent': {
'nativeType': 'nsDOMKeyboardEvent',
},
'Location': {
# NOTE: Before you turn on codegen for Location, make sure all the
# Unforgeable stuff is dealt with.

View File

@ -209,6 +209,45 @@ def PrototypeIDAndDepth(descriptor):
depth = "0"
return (prototypeID, depth)
def UseHolderForUnforgeable(descriptor):
return (descriptor.concrete and
descriptor.proxy and
any(m for m in descriptor.interface.members if m.isAttr() and m.isUnforgeable()))
def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None):
"""
Generate the code to execute the code in "code" on an unforgeable holder if
needed. code should be a string containing the code to execute. If it
contains a ${holder} string parameter it will be replaced with the
unforgeable holder object.
If isXrayCheck is not None it should be a string that contains a statement
returning whether proxy is an Xray. If isXrayCheck is None the generated
code won't try to unwrap Xrays.
"""
code = string.Template(code).substitute({ "holder": "unforgeableHolder" })
if not isXrayCheck is None:
pre = """// Scope for 'global', 'ac' and 'unforgeableHolder'
{
JSObject* global;
Maybe<JSAutoCompartment> ac;
if (""" + isXrayCheck + """) {
global = js::GetGlobalForObjectCrossCompartment(js::UncheckedUnwrap(proxy));
ac.construct(cx, global);
} else {
global = js::GetGlobalForObjectCrossCompartment(proxy);
}"""
else:
pre = """// Scope for 'global' and 'unforgeableHolder'
{
JSObject* global = js::GetGlobalForObjectCrossCompartment(proxy);"""
return (pre + """
JSObject* unforgeableHolder = GetUnforgeableHolder(global, prototypes::id::%s);
""" + CGIndenter(CGGeneric(code)).define() + """
}
""") % descriptor.name
class CGPrototypeJSClass(CGThing):
def __init__(self, descriptor, properties):
CGThing.__init__(self)
@ -219,10 +258,13 @@ class CGPrototypeJSClass(CGThing):
return ""
def define(self):
(prototypeID, depth) = PrototypeIDAndDepth(self.descriptor)
slotCount = "DOM_INTERFACE_PROTO_SLOTS_BASE"
if UseHolderForUnforgeable(self.descriptor):
slotCount += " + 1 /* slot for the JSObject holding the unforgeable properties */"
return """static DOMIfaceAndProtoJSClass PrototypeClass = {
{
"%sPrototype",
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(%s),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
@ -244,7 +286,7 @@ class CGPrototypeJSClass(CGThing):
%s,
%s
};
""" % (self.descriptor.interface.identifier.name,
""" % (self.descriptor.interface.identifier.name, slotCount,
NativePropertyHooks(self.descriptor),
self.descriptor.interface.identifier.name,
prototypeID, depth)
@ -272,11 +314,15 @@ class CGInterfaceObjectJSClass(CGThing):
else:
hasinstance = "nullptr"
(prototypeID, depth) = PrototypeIDAndDepth(self.descriptor)
slotCount = "DOM_INTERFACE_SLOTS_BASE"
if len(self.descriptor.interface.namedConstructors) > 0:
slotCount += (" + %i /* slots for the named constructors */" %
len(self.descriptor.interface.namedConstructors))
return """
static DOMIfaceAndProtoJSClass InterfaceObjectClass = {
{
"Function",
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE + %i),
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(%s),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
@ -298,7 +344,7 @@ static DOMIfaceAndProtoJSClass InterfaceObjectClass = {
%s,
%s
};
""" % (len(self.descriptor.interface.namedConstructors), ctorname,
""" % (slotCount, ctorname,
hasinstance, ctorname, NativePropertyHooks(self.descriptor),
self.descriptor.interface.identifier.name,
prototypeID, depth)
@ -419,6 +465,12 @@ class CGIfWrapper(CGWrapper):
CGWrapper.__init__(self, CGIndenter(child), pre=pre.define(),
post="\n}")
class CGIfElseWrapper(CGList):
def __init__(self, condition, ifTrue, ifFalse):
kids = [ CGIfWrapper(ifTrue, condition),
CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}") ]
CGList.__init__(self, kids)
class CGTemplatedType(CGWrapper):
def __init__(self, templateName, child, isConst=False, isReference=False):
const = "const " if isConst else ""
@ -1430,13 +1482,6 @@ class AttrDefiner(PropertyDefiner):
# non-static attributes go on the interface prototype object
assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
if unforgeable and len(attributes) != 0 and descriptor.proxy:
raise TypeError("Unforgeable properties are not supported on "
"proxy bindings without [NamedPropertiesObject]. "
"And not even supported on the ones with "
"[NamedPropertiesObject] yet, but we should fix "
"that, since they're safe there.")
def generateArray(self, array, name, doIdArrays):
if len(array) == 0:
return ""
@ -1640,6 +1685,20 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
else:
prefCache = None
if UseHolderForUnforgeable(self.descriptor):
createUnforgeableHolder = CGGeneric("""JSObject* unforgeableHolder = JS_NewObjectWithGivenProto(aCx, nullptr, nullptr, nullptr);
if (!unforgeableHolder) {
return;
}""")
defineUnforgeables = InitUnforgeablePropertiesOnObject(self.descriptor,
"unforgeableHolder",
self.properties)
createUnforgeableHolder = CGList([createUnforgeableHolder,
defineUnforgeables],
"\n")
else:
createUnforgeableHolder = None
getParentProto = ("JSObject* parentProto = %s;\n" +
"if (!parentProto) {\n" +
" return;\n" +
@ -1707,8 +1766,19 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
properties,
chromeProperties,
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL"))
if UseHolderForUnforgeable(self.descriptor):
assert needInterfacePrototypeObject
setUnforgeableHolder = CGGeneric(
"JSObject* proto = protoAndIfaceArray[prototypes::id::%s];\n"
"if (proto) {\n"
" js::SetReservedSlot(proto, DOM_INTERFACE_PROTO_SLOTS_BASE,\n"
" JS::ObjectValue(*unforgeableHolder));\n"
"}" % self.descriptor.name)
else:
setUnforgeableHolder = None
functionBody = CGList(
[CGGeneric(getParentProto), initIds, prefCache, CGGeneric(call)],
[CGGeneric(getParentProto), initIds, prefCache,
createUnforgeableHolder, CGGeneric(call), setUnforgeableHolder],
"\n\n")
return CGIndenter(functionBody).define()
@ -1870,25 +1940,31 @@ def CreateBindingJSObject(descriptor, parent):
"""
return create % parent
def GetAccessCheck(descriptor, globalName):
def GetAccessCheck(descriptor, object):
"""
globalName is the name of the global JSObject*
object is the name of a JSObject*
returns a string
"""
if descriptor.workers:
accessCheck = "mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker()"
else:
accessCheck = "xpc::AccessCheck::isChrome(%s)" % globalName
accessCheck = "xpc::AccessCheck::isChrome(%s)" % object
return accessCheck
def InitUnforgeableProperties(descriptor, properties):
def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturnValue=""):
"""
properties is a PropertyArrays instance
"""
defineUnforgeables = ("if (!DefineUnforgeableAttributes(aCx, obj, %s)) {\n"
" return nullptr;\n"
failureReturn = "return"
if len(failureReturnValue) > 0:
failureReturn += " " + failureReturnValue
failureReturn += ";"
defineUnforgeables = ("if (!DefineUnforgeableAttributes(aCx, " + obj + ", %s)) {\n"
" " + failureReturn + "\n"
"}")
unforgeableAttrs = properties.unforgeableAttrs
unforgeables = []
if unforgeableAttrs.hasNonChromeOnly():
@ -1898,16 +1974,30 @@ def InitUnforgeableProperties(descriptor, properties):
unforgeables.append(
CGIfWrapper(CGGeneric(defineUnforgeables %
unforgeableAttrs.variableName(True)),
GetAccessCheck(descriptor, "global")))
GetAccessCheck(descriptor, obj)))
return CGList(unforgeables, "\n")
return CGIndenter(CGWrapper(
CGList(unforgeables, "\n"),
pre=("\n"
def InitUnforgeableProperties(descriptor, properties):
"""
properties is a PropertyArrays instance
"""
unforgeableAttrs = properties.unforgeableAttrs
if not unforgeableAttrs.hasNonChromeOnly() and not unforgeableAttrs.hasChromeOnly():
return ""
if descriptor.proxy:
unforgeableProperties = CGGeneric(
"// Unforgeable properties on proxy-based bindings are stored in an object held\n"
"// by the interface prototype object.\n")
else:
unforgeableProperties = CGWrapper(
InitUnforgeablePropertiesOnObject(descriptor, "obj", properties, "nullptr"),
pre=(
"// Important: do unforgeable property setup after we have handed\n"
"// over ownership of the C++ object to obj as needed, so that if\n"
"// we fail and it ends up GCed it won't have problems in the\n"
"// finalizer trying to drop its ownership of the C++ object.\n"),
post="\n")).define() if len(unforgeables) > 0 else ""
"// finalizer trying to drop its ownership of the C++ object.\n"))
return CGIndenter(CGWrapper(unforgeableProperties, pre="\n", post="\n")).define()
def AssertInheritanceChain(descriptor):
asserts = ""
@ -2929,10 +3019,16 @@ for (uint32_t i = 0; i < length; ++i) {
if type.isEnum():
assert not isEnforceRange and not isClamp
enumName = type.unroll().inner.identifier.name
declType = CGGeneric(enumName)
if type.nullable():
raise TypeError("We don't support nullable enumerated arguments "
"yet")
enum = type.inner.identifier.name
declType = CGTemplatedType("Nullable", declType)
declType = declType.define()
enumLoc = "const_cast<%s&>(${declName}).SetValue()" % declType
else:
enumLoc = "${declName}"
declType = declType.define()
if invalidEnumValueFatal:
handleInvalidEnumValueCode = " MOZ_ASSERT(index >= 0);\n"
else:
@ -2954,20 +3050,36 @@ for (uint32_t i = 0; i < length; ++i) {
"%(exceptionCode)s\n"
" }\n"
"%(handleInvalidEnumValueCode)s"
" ${declName} = static_cast<%(enumtype)s>(index);\n"
"}" % { "enumtype" : enum,
"values" : enum + "Values::strings",
" %(enumLoc)s = static_cast<%(enumtype)s>(index);\n"
"}" % { "enumtype" : enumName,
"values" : enumName + "Values::strings",
"invalidEnumValueFatal" : toStringBool(invalidEnumValueFatal),
"handleInvalidEnumValueCode" : handleInvalidEnumValueCode,
"exceptionCode" : CGIndenter(exceptionCodeIndented).define() })
"exceptionCode" : CGIndenter(exceptionCodeIndented).define(),
"enumLoc" : enumLoc,
})
setNull = "const_cast<%s&>(${declName}).SetNull();" % declType
if type.nullable():
template = CGIfElseWrapper("${val}.isNullOrUndefined()",
CGGeneric(setNull),
CGGeneric(template)).define()
if defaultValue is not None:
assert(defaultValue.type.tag() == IDLType.Tags.domstring)
template = handleDefault(template,
("${declName} = %sValues::%s" %
(enum,
getEnumValueName(defaultValue.value))))
return (template, CGGeneric(enum), None, isOptional)
if isinstance(defaultValue, IDLNullValue):
assert type.nullable()
template = handleDefault(template, setNull)
else:
assert(defaultValue.type.tag() == IDLType.Tags.domstring)
template = handleDefault(template,
("%s = %sValues::%s" %
(enumLoc, enumName,
getEnumValueName(defaultValue.value))))
if type.nullable() and not isOptional:
# isOptional will handle the const bits itself
declType = "const " + declType
return (template, CGGeneric(declType), None, isOptional)
if type.isCallback():
assert not isEnforceRange and not isClamp
@ -3586,18 +3698,28 @@ if (!returnArray) {
if type.isEnum():
if type.nullable():
raise TypeError("We don't support nullable enumerated return types "
"yet")
return ("""MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
JSString* %(resultStr)s = JS_NewStringCopyN(cx, %(strings)s[uint32_t(%(result)s)].value, %(strings)s[uint32_t(%(result)s)].length);
if (!%(resultStr)s) {
resultLoc = "%s.Value()" % result
else:
resultLoc = result
conversion = ("""{
// Scope for resultStr
MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
JSString* resultStr = JS_NewStringCopyN(cx, %(strings)s[uint32_t(%(result)s)].value, %(strings)s[uint32_t(%(result)s)].length);
if (!resultStr) {
%(exceptionCode)s
}
""" % { "result" : result,
"resultStr" : result + "_str",
"strings" : type.inner.identifier.name + "Values::strings",
"exceptionCode" : exceptionCodeIndented.define() } +
setValue("JS::StringValue(%s_str)" % result), False)
}
""" % { "result" : resultLoc,
"strings" : type.unroll().inner.identifier.name + "Values::strings",
"exceptionCode" : CGIndenter(exceptionCodeIndented).define() } +
CGIndenter(CGGeneric(setValue("JS::StringValue(resultStr)"))).define() +
"\n}")
if type.nullable():
conversion = CGIfElseWrapper(
"%s.IsNull()" % result,
CGGeneric(setValue("JS::NullValue()", False)),
CGGeneric(conversion)).define()
return conversion, False
if type.isCallback() or type.isCallbackInterface():
# See comments in WrapNewBindingObject explaining why we need
@ -3778,9 +3900,10 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
return CGGeneric("nsString"), True
return CGGeneric("DOMString"), True
if returnType.isEnum():
result = CGGeneric(returnType.unroll().inner.identifier.name)
if returnType.nullable():
raise TypeError("We don't support nullable enum return values")
return CGGeneric(returnType.inner.identifier.name), False
result = CGTemplatedType("Nullable", result)
return result, False
if returnType.isGeckoInterface():
result = CGGeneric(descriptorProvider.getDescriptor(
returnType.unroll().inner.identifier.name).nativeType)
@ -6159,7 +6282,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
indexedGetter = self.descriptor.operations['IndexedGetter']
indexedSetter = self.descriptor.operations['IndexedSetter']
setOrIndexedGet = ""
setOrIndexedGet = "bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);\n"
if self.descriptor.supportsIndexedProperties():
setOrIndexedGet += "int32_t index = GetArrayIndexFromId(cx, id);\n"
readonly = toStringBool(indexedSetter is None)
@ -6170,6 +6293,22 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
"}\n") % (self.descriptor.nativeType)
if UseHolderForUnforgeable(self.descriptor):
getUnforgeable = """if (!JS_GetPropertyDescriptorById(cx, ${holder}, id, flags, desc)) {
return false;
}
MOZ_ASSERT_IF(desc->obj, desc->obj == ${holder});"""
getUnforgeable = CallOnUnforgeableHolder(self.descriptor,
getUnforgeable, "isXray")
getUnforgeable += """if (desc->obj) {
desc->obj = proxy;
return !isXray || JS_WrapPropertyDescriptor(cx, desc);
}
"""
else:
getUnforgeable = ""
if indexedSetter or self.descriptor.operations['NamedSetter']:
setOrIndexedGet += "if (flags & JSRESOLVE_ASSIGNING) {\n"
if indexedSetter:
@ -6183,6 +6322,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
setOrIndexedGet += (" FillPropertyDescriptor(desc, proxy, JSVAL_VOID, false);\n" +
" return true;\n" +
" }\n")
setOrIndexedGet += CGIndenter(CGGeneric(getUnforgeable)).define()
if self.descriptor.operations['NamedSetter']:
if not 'NamedCreator' in self.descriptor.operations:
# FIXME need to check that this is a 'supported property name'
@ -6197,13 +6337,19 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
setOrIndexedGet += "}"
if indexedGetter:
setOrIndexedGet += (" else {\n" +
CGIndenter(CGGeneric(get)).define() +
CGIndenter(CGGeneric(get + "\n" + getUnforgeable)).define() +
"}")
else:
setOrIndexedGet += (" else {\n" +
CGIndenter(CGGeneric(getUnforgeable)).define() +
"}")
setOrIndexedGet += "\n\n"
elif indexedGetter:
setOrIndexedGet += ("if (!(flags & JSRESOLVE_ASSIGNING)) {\n" +
CGIndenter(CGGeneric(get)).define() +
"}\n\n")
else:
if indexedGetter:
setOrIndexedGet += ("if (!(flags & JSRESOLVE_ASSIGNING)) {\n" +
CGIndenter(CGGeneric(get)).define() +
"}\n\n")
setOrIndexedGet += getUnforgeable
if self.descriptor.supportsNamedProperties():
readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None)
@ -6224,7 +6370,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
namedGet = ""
return setOrIndexedGet + """JSObject* expando;
if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
if (!isXray && (expando = GetExpandoObject(proxy))) {
if (!JS_GetPropertyDescriptorById(cx, expando, id, flags, desc)) {
return false;
}
@ -6265,6 +6411,19 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
" return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" +
"}\n") % self.descriptor.name
if UseHolderForUnforgeable(self.descriptor):
defineOnUnforgeable = ("JSBool hasUnforgeable;\n"
"if (!JS_HasPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
" return false;\n"
"}\n"
"if (hasUnforgeable) {\n"
" JSBool defined;\n"
" return js_DefineOwnProperty(cx, ${holder}, id, *desc, &defined);\n"
"}\n")
set += CallOnUnforgeableHolder(self.descriptor,
defineOnUnforgeable,
"xpc::WrapperFactory::IsXrayWrapper(proxy)")
namedSetter = self.descriptor.operations['NamedSetter']
if namedSetter:
if not self.descriptor.operations['NamedCreator'] is namedSetter:
@ -6329,7 +6488,10 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
body = None
return body
delete = ""
delete = """MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
"""
indexedBody = getDeleterBody("Indexed")
if indexedBody is not None:
@ -6340,6 +6502,19 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
" return true;\n" +
"}\n") % self.descriptor.nativeType
if UseHolderForUnforgeable(self.descriptor):
unforgeable = ("JSBool hasUnforgeable;\n"
"if (!JS_HasPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
" return false;\n"
"}\n"
"if (hasUnforgeable) {\n"
" // We should throw if Throw is true!\n"
" *bp = false;\n"
" return true;\n"
"}")
delete += CallOnUnforgeableHolder(self.descriptor, unforgeable)
delete += "\n"
namedBody = getDeleterBody("Named")
if namedBody is not None:
# We always return above for an index id in the case when we support
@ -6366,31 +6541,43 @@ class CGDOMJSProxyHandler_getOwnPropertyNames(ClassMethod):
def getBody(self):
# Per spec, we do indices, then named props, then everything else
if self.descriptor.supportsIndexedProperties():
addIndices = """uint32_t length = UnwrapProxy(proxy)->Length();
addIndices = """
uint32_t length = UnwrapProxy(proxy)->Length();
MOZ_ASSERT(int32_t(length) >= 0);
for (int32_t i = 0; i < int32_t(length); ++i) {
if (!props.append(INT_TO_JSID(i))) {
return false;
}
}
"""
else:
addIndices = ""
if self.descriptor.supportsNamedProperties():
addNames = """nsTArray<nsString> names;
addNames = """
nsTArray<nsString> names;
UnwrapProxy(proxy)->GetSupportedNames(names);
if (!AppendNamedPropertyIds(cx, proxy, names, props)) {
return false;
}
"""
else:
addNames = ""
return addIndices + addNames + """JSObject* expando;
if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
if UseHolderForUnforgeable(self.descriptor):
addUnforgeable = (
"if (!js::GetPropertyNames(cx, ${holder}, JSITER_OWNONLY | JSITER_HIDDEN, &props)) {\n"
" return false;\n"
"}")
addUnforgeable = CallOnUnforgeableHolder(self.descriptor,
addUnforgeable,
"isXray")
else:
addUnforgeable = ""
return """bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
""" + addIndices + addUnforgeable + addNames + """
JSObject* expando;
if (!isXray && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
!js::GetPropertyNames(cx, expando, JSITER_OWNONLY | JSITER_HIDDEN, &props)) {
return false;
}
@ -6416,6 +6603,17 @@ class CGDOMJSProxyHandler_hasOwn(ClassMethod):
else:
indexed = ""
if UseHolderForUnforgeable(self.descriptor):
unforgeable = ("JSBool b = true;\n"
"JSBool ok = JS_AlreadyHasOwnPropertyById(cx, ${holder}, id, &b);\n"
"*bp = !!b;\n"
"if (!ok || *bp) {\n"
" return ok;\n"
"}")
unforgeable = CallOnUnforgeableHolder(self.descriptor, unforgeable)
else:
unforgeable = ""
if self.descriptor.supportsNamedProperties():
# If we support indexed properties we always return above for index
# property names, so no need to check for those here.
@ -6428,7 +6626,11 @@ class CGDOMJSProxyHandler_hasOwn(ClassMethod):
else:
named = ""
return indexed + """JSObject* expando = GetExpandoObject(proxy);
return """MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
""" + indexed + unforgeable + """
JSObject* expando = GetExpandoObject(proxy);
if (expando) {
JSBool b = true;
JSBool ok = JS_HasPropertyById(cx, expando, id, &b);
@ -6451,7 +6653,20 @@ class CGDOMJSProxyHandler_get(ClassMethod):
ClassMethod.__init__(self, "get", "bool", args)
self.descriptor = descriptor
def getBody(self):
getFromExpando = """JSObject* expando = DOMProxyHandler::GetExpandoObject(proxy);
if UseHolderForUnforgeable(self.descriptor):
hasUnforgeable = (
"JSBool hasUnforgeable;\n"
"if (!JS_AlreadyHasOwnPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
" return false;\n"
"}\n"
"if (hasUnforgeable) {\n"
" return JS_ForwardGetPropertyTo(cx, ${holder}, id, proxy, vp.address());\n"
"}")
getUnforgeableOrExpando = CallOnUnforgeableHolder(self.descriptor,
hasUnforgeable)
else:
getUnforgeableOrExpando = ""
getUnforgeableOrExpando += """JSObject* expando = DOMProxyHandler::GetExpandoObject(proxy);
if (expando) {
JSBool hasProp;
if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
@ -6475,9 +6690,9 @@ if (expando) {
} else {
%s
}
""" % (stripTrailingWhitespace(getFromExpando.replace('\n', '\n ')))
""" % (stripTrailingWhitespace(getUnforgeableOrExpando.replace('\n', '\n ')))
else:
getIndexedOrExpando = getFromExpando + "\n"
getIndexedOrExpando = getUnforgeableOrExpando + "\n"
if self.descriptor.supportsNamedProperties():
getNamed = CGProxyNamedGetter(self.descriptor, templateValues)
@ -6604,7 +6819,9 @@ class CGDOMJSProxyHandler(CGClass):
# XXXbz This should really just test supportsIndexedProperties() and
# supportsNamedProperties(), but that would make us throw in all cases
# because we don't know whether we're in strict mode.
if descriptor.operations['IndexedSetter'] or descriptor.operations['NamedSetter']:
if (descriptor.operations['IndexedSetter'] or
descriptor.operations['NamedSetter'] or
UseHolderForUnforgeable(descriptor)):
methods.append(CGDOMJSProxyHandler_defineProperty(descriptor))
methods.extend([CGDOMJSProxyHandler_getOwnPropertyNames(descriptor),
CGDOMJSProxyHandler_hasOwn(descriptor),
@ -7516,10 +7733,14 @@ class CGNativeMember(ClassMethod):
# Outparam
return "void", "", "retval = ${declName};"
if type.isEnum():
enumName = type.unroll().inner.identifier.name
if type.nullable():
raise TypeError("We don't support nullable enum return values")
typeName = type.inner.identifier.name
return typeName, "%s(0)" % typeName, "return ${declName};"
enumName = CGTemplatedType("Nullable",
CGGeneric(enumName)).define()
defaultValue = "%s()" % enumName
else:
defaultValue = "%s(0)" % enumName
return enumName, defaultValue, "return ${declName};"
if type.isGeckoInterface():
iface = type.unroll().inner;
nativeType = self.descriptor.getDescriptor(
@ -7709,7 +7930,7 @@ class CGNativeMember(ClassMethod):
return declType, True, False
if type.isEnum():
return type.inner.identifier.name, False, True
return type.unroll().inner.identifier.name, False, True
if type.isCallback() or type.isCallbackInterface():
forceOwningType = optional or isMember

View File

@ -42,9 +42,14 @@ class nsCycleCollectionParticipant;
#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
// Interface objects store a number of reserved slots equal to
// DOM_INTERFACE_BASE_SLOTS + number of named constructors.
// DOM_INTERFACE_SLOTS_BASE + number of named constructors.
#define DOM_INTERFACE_SLOTS_BASE (DOM_XRAY_EXPANDO_SLOT + 1)
// Interface prototype objects store a number of reserved slots equal to
// DOM_INTERFACE_PROTO_SLOTS_BASE or DOM_INTERFACE_PROTO_SLOTS_BASE + 1 if a
// slot for the unforgeable holder is needed.
#define DOM_INTERFACE_PROTO_SLOTS_BASE (DOM_XRAY_EXPANDO_SLOT + 1)
MOZ_STATIC_ASSERT(DOM_PROTO_INSTANCE_CLASS_SLOT != DOM_XRAY_EXPANDO_SLOT,
"Interface prototype object use both of these, so they must "
"not be the same slot.");

View File

@ -143,8 +143,8 @@ DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::
return false;
}
return JS_DefinePropertyById(cx, expando, id, desc->value, desc->getter, desc->setter,
desc->attrs);
JSBool dummy;
return js_DefineOwnProperty(cx, expando, id, *desc, &dummy);
}
bool

View File

@ -2227,8 +2227,11 @@ class IDLValue(IDLObject):
if type == self.type:
return self # Nothing to do
# If the type allows null, rerun this matching on the inner type
if type.nullable():
# If the type allows null, rerun this matching on the inner type, except
# nullable enums. We handle those specially, because we want our
# default string values to stay strings even when assigned to a nullable
# enum.
if type.nullable() and not type.isEnum():
innerValue = self.coerceToType(type.inner, location)
return IDLValue(self.location, type, innerValue.value)
@ -2253,10 +2256,11 @@ class IDLValue(IDLObject):
(self.value, type), [location])
elif self.type.isString() and type.isEnum():
# Just keep our string, but make sure it's a valid value for this enum
if self.value not in type.inner.values():
enum = type.unroll().inner
if self.value not in enum.values():
raise WebIDLError("'%s' is not a valid default value for enum %s"
% (self.value, type.inner.identifier.name),
[location, type.inner.location])
% (self.value, enum.identifier.name),
[location, enum.location])
return self
elif self.type.isFloat() and type.isFloat():
if (not type.isUnrestricted() and

View File

@ -378,9 +378,14 @@ public:
// Enumerated types
void PassEnum(TestEnum);
void PassNullableEnum(const Nullable<TestEnum>&);
void PassOptionalEnum(const Optional<TestEnum>&);
void PassEnumWithDefault(TestEnum);
void PassOptionalNullableEnum(const Optional<Nullable<TestEnum> >&);
void PassOptionalNullableEnumWithDefaultValue(const Nullable<TestEnum>&);
void PassOptionalNullableEnumWithDefaultValue2(const Nullable<TestEnum>&);
TestEnum ReceiveEnum();
Nullable<TestEnum> ReceiveNullableEnum();
TestEnum EnumAttribute();
TestEnum ReadonlyEnumAttribute();
void SetEnumAttribute(TestEnum);

View File

@ -357,13 +357,14 @@ interface TestInterface {
// Enumerated types
void passEnum(TestEnum arg);
// No support for nullable enums yet
// void passNullableEnum(TestEnum? arg);
void passNullableEnum(TestEnum? arg);
void passOptionalEnum(optional TestEnum arg);
void passEnumWithDefault(optional TestEnum arg = "a");
// void passOptionalNullableEnum(optional TestEnum? arg);
// void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null);
void passOptionalNullableEnum(optional TestEnum? arg);
void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null);
void passOptionalNullableEnumWithDefaultValue2(optional TestEnum? arg = "a");
TestEnum receiveEnum();
TestEnum? receiveNullableEnum();
attribute TestEnum enumAttribute;
readonly attribute TestEnum readonlyEnumAttribute;

View File

@ -265,13 +265,14 @@ interface TestExampleInterface {
// Enumerated types
void passEnum(TestEnum arg);
// No support for nullable enums yet
// void passNullableEnum(TestEnum? arg);
void passNullableEnum(TestEnum? arg);
void passOptionalEnum(optional TestEnum arg);
void passEnumWithDefault(optional TestEnum arg = "a");
// void passOptionalNullableEnum(optional TestEnum? arg);
// void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null);
void passOptionalNullableEnum(optional TestEnum? arg);
void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null);
void passOptionalNullableEnumWithDefaultValue2(optional TestEnum? arg = "a");
TestEnum receiveEnum();
TestEnum? receiveNullableEnum();
attribute TestEnum enumAttribute;
readonly attribute TestEnum readonlyEnumAttribute;

View File

@ -287,14 +287,14 @@ interface TestJSImplInterface {
// Enumerated types
void passEnum(MyTestEnum arg);
// No support for nullable enums yet
// void passNullableEnum(MyTestEnum? arg);
// Optional enum arg doesn't work with callback interfaces. See bug 843355.
//void passOptionalEnum(optional MyTestEnum arg);
void passNullableEnum(MyTestEnum? arg);
void passOptionalEnum(optional MyTestEnum arg);
void passEnumWithDefault(optional MyTestEnum arg = "a");
// void passOptionalNullableEnum(optional MyTestEnum? arg);
// void passOptionalNullableEnumWithDefaultValue(optional MyTestEnum? arg = null);
void passOptionalNullableEnum(optional MyTestEnum? arg);
void passOptionalNullableEnumWithDefaultValue(optional MyTestEnum? arg = null);
void passOptionalNullableEnumWithDefaultValue2(optional MyTestEnum? arg = "a");
MyTestEnum receiveEnum();
MyTestEnum? receiveNullableEnum();
attribute MyTestEnum enumAttribute;
readonly attribute MyTestEnum readonlyEnumAttribute;

View File

@ -41,23 +41,16 @@ public:
void Notify(const BluetoothSignal& aParam);
nsIDOMEventTarget*
ToIDOMEventTarget() const
{
return static_cast<nsDOMEventTargetHelper*>(
const_cast<BluetoothAdapter*>(this));
}
nsISupports*
ToISupports() const
ToISupports()
{
return ToIDOMEventTarget();
return static_cast<EventTarget*>(this);
}
void Unroot();
virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);
private:
BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue);
~BluetoothAdapter();

View File

@ -42,17 +42,10 @@ public:
void Notify(const BluetoothSignal& aParam);
nsIDOMEventTarget*
ToIDOMEventTarget() const
{
return static_cast<nsDOMEventTargetHelper*>(
const_cast<BluetoothDevice*>(this));
}
nsISupports*
ToISupports() const
ToISupports()
{
return ToIDOMEventTarget();
return static_cast<EventTarget*>(this);
}
void SetPropertyByValue(const BluetoothNamedValue& aValue);
@ -63,7 +56,7 @@ private:
const BluetoothValue& aValue);
~BluetoothDevice();
void Root();
JSObject* mJsUuids;
JSObject* mJsServices;

View File

@ -181,7 +181,7 @@ IccManager::NotifyStkCommand(const nsAString& aMessage)
nsRefPtr<StkCommandEvent> event = StkCommandEvent::Create(this, aMessage);
NS_ASSERTION(event, "This should never fail!");
return event->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("stkcommand"));
return event->Dispatch(this, NS_LITERAL_STRING("stkcommand"));
}
NS_IMETHODIMP

View File

@ -40,13 +40,6 @@ public:
private:
nsCOMPtr<nsIIccProvider> mProvider;
nsRefPtr<Listener> mListener;
nsIDOMEventTarget*
ToIDOMEventTarget() const
{
return static_cast<nsDOMEventTargetHelper*>(
const_cast<IccManager*>(this));
}
};
} // namespace icc

View File

@ -24,10 +24,10 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(StkCommandEvent, nsDOMEvent)
static already_AddRefed<StkCommandEvent>
Create(mozilla::dom::EventTarget* aOwner, const nsAString& aMessage);
Create(EventTarget* aOwner, const nsAString& aMessage);
nsresult
Dispatch(nsIDOMEventTarget* aTarget, const nsAString& aEventType)
Dispatch(EventTarget* aTarget, const nsAString& aEventType)
{
NS_ASSERTION(aTarget, "Null pointer!");
NS_ASSERTION(!aEventType.IsEmpty(), "Empty event type!");

View File

@ -102,7 +102,7 @@ HelperBase::~HelperBase()
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
if (mainThread) {
NS_ProxyRelease(mainThread, static_cast<nsIDOMEventTarget*>(request));
NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request));
}
}
}

View File

@ -15,13 +15,14 @@
#include "IDBTransaction.h"
USING_INDEXEDDB_NAMESPACE
using namespace mozilla::dom;
namespace {
class EventFiringRunnable : public nsRunnable
{
public:
EventFiringRunnable(nsIDOMEventTarget* aTarget,
EventFiringRunnable(EventTarget* aTarget,
nsIDOMEvent* aEvent)
: mTarget(aTarget), mEvent(aEvent)
{ }
@ -32,7 +33,7 @@ public:
}
private:
nsCOMPtr<nsIDOMEventTarget> mTarget;
nsCOMPtr<EventTarget> mTarget;
nsCOMPtr<nsIDOMEvent> mEvent;
};

View File

@ -191,9 +191,8 @@ IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
return NS_OK;
}
nsCOMPtr<nsIDOMEventTarget> eventTarget;
rv = aVisitor.mDOMEvent->GetTarget(getter_AddRefs(eventTarget));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<EventTarget> eventTarget =
aVisitor.mDOMEvent->InternalDOMEvent()->GetTarget();
nsCOMPtr<nsIIDBRequest> strongRequest = do_QueryInterface(eventTarget);
IDBRequest* request = static_cast<IDBRequest*>(strongRequest.get());

View File

@ -392,8 +392,10 @@ Key::EncodeNumber(double aFloat, uint8_t aType)
Float64Union pun;
pun.d = aFloat;
// Note: The subtraction from 0 below is necessary to fix
// MSVC build warning C4146 (negating an unsigned value).
uint64_t number = pun.u & PR_UINT64(0x8000000000000000) ?
-pun.u :
(0 - pun.u) :
(pun.u | PR_UINT64(0x8000000000000000));
number = NS_SWAP64(number);
@ -416,9 +418,11 @@ Key::DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd)
aPos += sizeof(number);
Float64Union pun;
// Note: The subtraction from 0 below is necessary to fix
// MSVC build warning C4146 (negating an unsigned value).
pun.u = number & PR_UINT64(0x8000000000000000) ?
(number & ~PR_UINT64(0x8000000000000000)) :
-number;
(0 - number);
return pun.d;
}

View File

@ -12,9 +12,7 @@ include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = dom_indexeddb_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
ifndef _MSC_VER
FAIL_ON_WARNINGS := 1
endif # !_MSC_VER
CPPSRCS = \
AsyncConnectionHelper.cpp \

View File

@ -25,6 +25,7 @@
#include <algorithm>
using namespace mozilla;
using namespace mozilla::dom;
USING_INDEXEDDB_NAMESPACE
USING_QUOTA_NAMESPACE
@ -2247,7 +2248,7 @@ OpenDatabaseHelper::GetSuccessResult(JSContext* aCx,
NS_ENSURE_SUCCESS(rv, rv);
}
return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMEventTarget*, mDatabase),
return WrapNative(aCx, NS_ISUPPORTS_CAST(EventTarget*, mDatabase),
aVal);
}
@ -2382,7 +2383,7 @@ SetVersionHelper::GetSuccessResult(JSContext* aCx,
mOpenRequest->SetTransaction(mTransaction);
return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMEventTarget*, mDatabase),
return WrapNative(aCx, NS_ISUPPORTS_CAST(EventTarget*, mDatabase),
aVal);
}

View File

@ -1296,7 +1296,7 @@ IPCOpenDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsresult
IPCOpenDatabaseHelper::GetSuccessResult(JSContext* aCx, jsval* aVal)
{
return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMEventTarget*, mDatabase),
return WrapNative(aCx, NS_ISUPPORTS_CAST(EventTarget*, mDatabase),
aVal);
}
@ -1335,7 +1335,7 @@ IPCSetVersionHelper::GetSuccessResult(JSContext* aCx, jsval* aVal)
{
mOpenRequest->SetTransaction(mTransaction);
return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMEventTarget*, mDatabase),
return WrapNative(aCx, NS_ISUPPORTS_CAST(EventTarget*, mDatabase),
aVal);
}

View File

@ -257,22 +257,20 @@ IndexedDBDatabaseParent::SetOpenRequest(IDBOpenDBRequest* aRequest)
MOZ_ASSERT(aRequest);
MOZ_ASSERT(!mOpenRequest);
nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(aRequest);
nsresult rv = target->AddEventListener(NS_LITERAL_STRING(SUCCESS_EVT_STR),
mEventListener, false);
nsresult rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(SUCCESS_EVT_STR),
mEventListener, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = target->AddEventListener(NS_LITERAL_STRING(ERROR_EVT_STR),
mEventListener, false);
rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(ERROR_EVT_STR),
mEventListener, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = target->AddEventListener(NS_LITERAL_STRING(BLOCKED_EVT_STR),
mEventListener, false);
rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(BLOCKED_EVT_STR),
mEventListener, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = target->AddEventListener(NS_LITERAL_STRING(UPGRADENEEDED_EVT_STR),
mEventListener, false);
rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(UPGRADENEEDED_EVT_STR),
mEventListener, false);
NS_ENSURE_SUCCESS(rv, rv);
mOpenRequest = aRequest;
@ -293,12 +291,10 @@ IndexedDBDatabaseParent::HandleEvent(nsIDOMEvent* aEvent)
nsresult rv = aEvent->GetType(type);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMEventTarget> target;
rv = aEvent->GetTarget(getter_AddRefs(target));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetTarget();
if (mDatabase &&
SameCOMIdentity(target, NS_ISUPPORTS_CAST(nsIDOMEventTarget*,
SameCOMIdentity(target, NS_ISUPPORTS_CAST(EventTarget*,
mDatabase))) {
rv = HandleDatabaseEvent(aEvent, type);
NS_ENSURE_SUCCESS(rv, rv);
@ -307,7 +303,7 @@ IndexedDBDatabaseParent::HandleEvent(nsIDOMEvent* aEvent)
}
if (mOpenRequest &&
SameCOMIdentity(target, NS_ISUPPORTS_CAST(nsIDOMEventTarget*,
SameCOMIdentity(target, NS_ISUPPORTS_CAST(EventTarget*,
mOpenRequest))) {
rv = HandleRequestEvent(aEvent, type);
NS_ENSURE_SUCCESS(rv, rv);
@ -440,8 +436,8 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
nsRefPtr<IDBOpenDBRequest> request;
mOpenRequest.swap(request);
nsIDOMEventTarget* target =
static_cast<nsIDOMEventTarget*>(databaseConcrete);
EventTarget* target =
static_cast<EventTarget*>(databaseConcrete);
#ifdef DEBUG
{
@ -674,7 +670,7 @@ IndexedDBTransactionParent::SetTransaction(IDBTransaction* aTransaction)
MOZ_ASSERT(aTransaction);
MOZ_ASSERT(!mTransaction);
nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(aTransaction);
EventTarget* target = static_cast<EventTarget*>(aTransaction);
NS_NAMED_LITERAL_STRING(complete, COMPLETE_EVT_STR);
nsresult rv = target->AddEventListener(complete, mEventListener, false);
@ -715,14 +711,9 @@ IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent)
else if (type.EqualsLiteral(ABORT_EVT_STR)) {
#ifdef DEBUG
{
nsCOMPtr<nsIDOMEventTarget> target;
if (NS_FAILED(aEvent->GetTarget(getter_AddRefs(target)))) {
NS_WARNING("Failed to get target!");
}
else {
MOZ_ASSERT(SameCOMIdentity(target, NS_ISUPPORTS_CAST(nsIDOMEventTarget*,
mTransaction)));
}
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetTarget();
MOZ_ASSERT(SameCOMIdentity(target, NS_ISUPPORTS_CAST(EventTarget*,
mTransaction)));
}
#endif
params = AbortResult(mTransaction->GetAbortCode());
@ -2187,7 +2178,7 @@ IndexedDBDeleteDatabaseRequestParent::SetOpenRequest(
MOZ_ASSERT(aOpenRequest);
MOZ_ASSERT(!mOpenRequest);
nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(aOpenRequest);
EventTarget* target = static_cast<EventTarget*>(aOpenRequest);
nsresult rv = target->AddEventListener(NS_LITERAL_STRING(SUCCESS_EVT_STR),
mEventListener, false);

View File

@ -25,7 +25,7 @@ interface nsIVariant;
* @see <http://www.whatwg.org/html/#window>
*/
[scriptable, uuid(39cb59d4-fba9-48a9-b70b-570a7ec2ebfa)]
[scriptable, uuid(67af2eda-4a0d-4a08-8a97-81b8fd46f1f4)]
interface nsIDOMWindow : nsISupports
{
// the current browsing context
@ -367,8 +367,6 @@ interface nsIDOMWindow : nsISupports
/* [replaceable] controllers */
readonly attribute nsIControllers controllers;
attribute DOMString defaultStatus;
readonly attribute float mozInnerScreenX;
readonly attribute float mozInnerScreenY;
readonly attribute float devicePixelRatio;

View File

@ -348,7 +348,7 @@ ProcessPriorityManager::OnContentDocumentGlobalCreated(
return;
}
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(innerWindow);
nsCOMPtr<EventTarget> target = do_QueryInterface(innerWindow);
NS_ENSURE_TRUE_VOID(target);
nsWeakPtr weakWin = do_GetWeakReference(innerWindow);

View File

@ -1418,7 +1418,7 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
// content manipulate the frame state.
nsRefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(mTabChildGlobal),
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
aMessageName, false, &cloneData, nullptr, nullptr);
}
@ -1910,11 +1910,10 @@ TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
{
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
NS_ENSURE_TRUE(window, true);
nsCOMPtr<nsIDOMEventTarget> chromeHandler =
nsCOMPtr<EventTarget> chromeHandler =
do_QueryInterface(window->GetChromeEventHandler());
NS_ENSURE_TRUE(chromeHandler, true);
nsRefPtr<ContentListener> listener = new ContentListener(this);
NS_ENSURE_TRUE(listener, true);
chromeHandler->AddEventListener(aType, listener, capture);
return true;
}
@ -1957,7 +1956,7 @@ TabChild::RecvAsyncMessage(const nsString& aMessage,
StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData);
nsRefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(mTabChildGlobal),
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
aMessage, false, &cloneData, nullptr, nullptr);
}
return true;
@ -2048,16 +2047,14 @@ TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
if (!mCx && !mTabChildGlobal) {
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
NS_ENSURE_TRUE(window, false);
nsCOMPtr<nsIDOMEventTarget> chromeHandler =
nsCOMPtr<EventTarget> chromeHandler =
do_QueryInterface(window->GetChromeEventHandler());
NS_ENSURE_TRUE(chromeHandler, false);
nsRefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
NS_ENSURE_TRUE(scope, false);
mTabChildGlobal = scope;
nsISupports* scopeSupports = NS_ISUPPORTS_CAST(nsIDOMEventTarget*, scope);
nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
NS_ENSURE_TRUE(InitTabChildGlobalInternal(scopeSupports, globalId), false);

View File

@ -12,9 +12,7 @@ include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = dom_network_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
ifndef _MSC_VER
FAIL_ON_WARNINGS := 1
endif # !_MSC_VER
EXTRA_COMPONENTS = \
TCPSocket.js \

View File

@ -51,13 +51,6 @@ private:
nsCOMPtr<nsIMobileConnectionProvider> mProvider;
nsRefPtr<Listener> mListener;
nsRefPtr<icc::IccManager> mIccManager;
nsIDOMEventTarget*
ToIDOMEventTarget() const
{
return static_cast<nsDOMEventTargetHelper*>(
const_cast<MobileConnection*>(this));
}
};
} // namespace network

View File

@ -109,7 +109,7 @@ TCPSocketParent::RecvData(const SendableData& aData)
break;
default:
MOZ_NOT_REACHED();
MOZ_NOT_REACHED("unexpected SendableData type");
return false;
}
return true;

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