mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to m-i.
This commit is contained in:
commit
7c1ae1ff7c
@ -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());
|
||||
|
@ -3648,10 +3648,6 @@ var XULBrowserWindow = {
|
||||
// unsupported
|
||||
},
|
||||
|
||||
setJSDefaultStatus: function () {
|
||||
// unsupported
|
||||
},
|
||||
|
||||
setDefaultStatus: function (status) {
|
||||
this.defaultStatus = status;
|
||||
this.updateStatusField();
|
||||
|
@ -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;
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
18
content/base/crashtests/863950.html
Normal file
18
content/base/crashtests/863950.html
Normal 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>
|
@ -133,3 +133,4 @@ load 841205.html
|
||||
load 844404.html
|
||||
load 847127.html
|
||||
load 849601.html
|
||||
load 863950.html
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
return y;
|
||||
}
|
||||
|
||||
uint32_t Which()
|
||||
virtual uint32_t Which()
|
||||
{
|
||||
uint32_t w;
|
||||
GetWhich(&w);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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 */ }
|
||||
|
||||
|
52
content/media/webaudio/AudioProcessingEvent.cpp
Normal file
52
content/media/webaudio/AudioProcessingEvent.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
83
content/media/webaudio/AudioProcessingEvent.h
Normal file
83
content/media/webaudio/AudioProcessingEvent.h
Normal 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
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
377
content/media/webaudio/ScriptProcessorNode.cpp
Normal file
377
content/media/webaudio/ScriptProcessorNode.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
70
content/media/webaudio/ScriptProcessorNode.h
Normal file
70
content/media/webaudio/ScriptProcessorNode.h
Normal 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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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',
|
||||
]
|
||||
|
||||
|
@ -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 \
|
||||
|
52
content/media/webaudio/test/test_audioBufferSourceNode.html
Normal file
52
content/media/webaudio/test/test_audioBufferSourceNode.html
Normal 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>
|
139
content/media/webaudio/test/test_scriptProcessorNode.html
Normal file
139
content/media/webaudio/test/test_scriptProcessorNode.html
Normal 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>
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -515,6 +515,6 @@ AudioChannelService::GetInternalType(AudioChannelType aType,
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_NOT_REACHED();
|
||||
MOZ_NOT_REACHED("unexpected audio channel type");
|
||||
return AUDIO_CHANNEL_INT_LAST;
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 = \
|
||||
|
32
dom/base/test/test_Image_constructor.html
Normal file
32
dom/base/test/test_Image_constructor.html
Normal 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>
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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!");
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user