import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1224810 - "TraceLogger: Add the script information for the event created by BytecodeCompiler". r=hv1989 (12b6891fa7)
- Bug 1227677 - Simplify emitting of comprehension variables. r=shu (4e9ea2fee7)
- bug 1223529 - remove ipc/chromium/Makefile.in. r=gps (8d71334ca0)
- Bug 1225682 - Don't use nsAuto{,C}String as class member variables in widget/. r=roc (4355625107)
- Bug 1225188. Implement window.onstorage. r=smaug (50168cdffb)
- Bug 1286158 - Add Android 64bit support for libevent. r=billm (b33cb1fccf)
- Bug 1162524: Fix error handling |UnixSocketWatcher::Connect|, r=kmachulis (04e67535b4)
- Bug 1178514 - Mark one-argument constructors in IPDL tests as 'explicit'. r=bent (cc6fde1e1c)
- some warnings stuff (68ecef6622)
- Bug 1170231: Part 1 - Remove condition that may cause deadlock in IPC when mediating interrupt races; r=dvander (79dd6902a2)
- Bug 1170231: Part 2 - Regression test for IPC race mediation deadlock; r=dvander (eabe33218f)
- Bug 1167396 - Make ProtocolCloneContext::mContentParent a smart pointer. r=bent (519ad9f47e)
- Bug 1213567: Prevent neutering from occurring during CreateWindow(Ex) calls; r=jimm (6550685051)
- Bug 1177013 - Bug fixes for CPOW cancelation (r=dvander) (b50da43c07)
- Bug 1217640 - MessageChannel::Call() should delete aMsg when the channel is not connected. r=jld (899b0e6349)
- Bug 1159037: Ensure correct parent and child message are passed to MessageListener::MediateInterruptRace; r=dvander (96c1f42029)
- Bug 1177013 - Telemetry for CPOW cancelation (r=dvander) (ec704af72c)
- Bug 1050122 - Part 2: Disable preallocate when proc loader is not initialized. r=khuey (2d35b8e25e)
This commit is contained in:
2023-06-02 11:49:08 +08:00
parent c4d71010c8
commit 193db9294d
44 changed files with 760 additions and 164 deletions
+1
View File
@@ -911,6 +911,7 @@ GK_ATOM(onstatechange, "onstatechange")
GK_ATOM(onstatuschanged, "onstatuschanged")
GK_ATOM(onstkcommand, "onstkcommand")
GK_ATOM(onstksessionend, "onstksessionend")
GK_ATOM(onstorage, "onstorage")
GK_ATOM(onstorageareachanged, "onstorageareachanged")
GK_ATOM(onsubmit, "onsubmit")
GK_ATOM(onsuccess, "onsuccess")
+4 -2
View File
@@ -531,8 +531,10 @@ WINDOW_EVENT(popstate,
eBasicEventClass)
// Not supported yet
// WINDOW_EVENT(redo)
// Not supported yet
// WINDOW_EVENT(storage)
WINDOW_EVENT(storage,
eStorage,
EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
// Not supported yet
// WINDOW_EVENT(undo)
WINDOW_EVENT(unload,
@@ -25,7 +25,6 @@
"Window attribute: onclose": true,
"Window attribute: oncuechange": true,
"Window attribute: onmousewheel": true,
"Window attribute: onstorage": true,
"Window unforgeable attribute: window": true,
"Window unforgeable attribute: document": true,
"Window unforgeable attribute: top": true
+12 -1
View File
@@ -18,6 +18,10 @@
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_B2G_LOADER
#include "ProcessUtils.h"
#endif
// This number is fairly arbitrary ... the intention is to put off
// launching another app process until the last one has finished
// loading its content, to reduce CPU/memory/IO contention.
@@ -133,7 +137,14 @@ PreallocatedProcessManagerImpl::Init()
os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
/* weakRef = */ false);
}
RereadPrefs();
#ifdef MOZ_B2G_LOADER
if (!mozilla::ipc::ProcLoaderIsInitialized()) {
Disable();
} else
#endif
{
RereadPrefs();
}
}
NS_IMETHODIMP
+1 -1
View File
@@ -136,7 +136,7 @@ interface WindowEventHandlers {
attribute EventHandler onpagehide;
attribute EventHandler onpageshow;
attribute EventHandler onpopstate;
//(Not implemented)attribute EventHandler onstorage;
attribute EventHandler onstorage;
attribute EventHandler onunload;
};
+1 -1
View File
@@ -73,7 +73,7 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] in ('Linux', 'Android'):
# from the function using it which breaks the build. Work around that by
# forcing there to be only one partition.
if '-flto' in CONFIG['OS_CXXFLAGS'] and not CONFIG['CLANG_CXX']:
LDFLAGS += ['--param lto-partitions=1']
LDFLAGS += ['--param lto-partitions=1']
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
# For sandbox includes and the include dependencies those have
+2 -1
View File
@@ -29,4 +29,5 @@ if CONFIG['MOZ_SANDBOX']:
LDFLAGS += ['-pie']
FAIL_ON_WARNINGS = True
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
-40
View File
@@ -1,40 +0,0 @@
# 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/.
OS_CXXFLAGS := $(filter-out -fshort-wchar,$(OS_CXXFLAGS))
ACDEFINES =
ifndef MOZ_NATIVE_LIBEVENT # {
vpath %.c \
$(srcdir)/src/third_party/libevent \
$(NULL)
endif # }
vpath %.cc \
$(srcdir)/src/base \
$(srcdir)/src/chrome/common \
$(NULL)
vpath %.mm \
$(srcdir)/src/base \
$(srcdir)/src/chrome/common \
$(NULL)
OS_CXXFLAGS += $(TK_CFLAGS)
include $(topsrcdir)/config/rules.mk
ifdef MOZ_NATIVE_LIBEVENT # {
export-preqs = \
$(call mkdir_deps,$(CURDIR)/third_party/libevent) \
$(NULL)
export:: $(DIST)/third_party/libevent/event.h
$(DIST)/third_party/libevent/event.h:: $(export-preqs)
echo '#include <event.h>' > $(CURDIR)/third_party/libevent/event.h
endif # }
@@ -15,7 +15,7 @@
#include "base/scoped_nsautorelease_pool.h"
#include "base/time.h"
#include "nsDependentSubstring.h"
#include "third_party/libevent/event.h"
#include "event.h"
#include "mozilla/UniquePtr.h"
// This macro checks that the _EVENT_SIZEOF_* constants defined in
+5 -3
View File
@@ -14,9 +14,10 @@ environment indicated by the first path component. You have to run
then be found in "include/event2/".
You then need to modify the _EVENT_SIZEOF_* constants in the generated linux,
mac and bsd headers to be appropriate for both 32-bit and 64-bit platforms. Use
__LP64__ to distinguish the two cases. If you get something wrong the
CHECK_EVENT_SIZEOF static assertions in message_pump_libevent.cc will fail.
android, mac and bsd headers to be appropriate for both 32-bit and 64-bit
platforms. Use __LP64__ to distinguish the two cases. If you get something
wrong the CHECK_EVENT_SIZEOF static assertions in message_pump_libevent.cc will
fail.
2. This is ugly, prepare yourself. OS X has a weird problem with how the
"TAILQ_END(head)" is used, causing a linking error. Just replace all use of the
@@ -39,5 +40,6 @@ ipc/chromium/src/third_party/libevent/patches/:
- "avoid-empty-sighandler.patch". This fixes some OS X crashes.
- "android64_support.patch". This fixes Android 64-bit support.
7. Apply "libevent-backport-upstream-fixes.patch", which incorporates some upstream fixes from 2.1.*
@@ -398,26 +398,47 @@
your system. */
/* #undef _EVENT_PTHREAD_CREATE_JOINABLE */
/* ------------------------------------------------------------------------ */
/* MOZILLA NOTE: the following constants are hand-modified to be suitable */
/* for both 32-bit and 64-bit platforms. See README.mozilla for details. */
/* ------------------------------------------------------------------------ */
/* The size of `int', as computed by sizeof. */
#define _EVENT_SIZEOF_INT 4
/* The size of `long', as computed by sizeof. */
#ifdef __LP64__
#define _EVENT_SIZEOF_LONG 8
#else
#define _EVENT_SIZEOF_LONG 4
#endif
/* The size of `long long', as computed by sizeof. */
#define _EVENT_SIZEOF_LONG_LONG 8
/* The size of `pthread_t', as computed by sizeof. */
#ifdef __LP64__
#define _EVENT_SIZEOF_PTHREAD_T 8
#else
#define _EVENT_SIZEOF_PTHREAD_T 4
#endif
/* The size of `short', as computed by sizeof. */
#define _EVENT_SIZEOF_SHORT 2
/* The size of `size_t', as computed by sizeof. */
#ifdef __LP64__
#define _EVENT_SIZEOF_SIZE_T 8
#else
#define _EVENT_SIZEOF_SIZE_T 4
#endif
/* The size of `void *', as computed by sizeof. */
#ifdef __LP64__
#define _EVENT_SIZEOF_VOID_P 8
#else
#define _EVENT_SIZEOF_VOID_P 4
#endif
/* Define to 1 if you have the ANSI C header files. */
#define _EVENT_STDC_HEADERS 1
@@ -0,0 +1,52 @@
diff --git a/ipc/chromium/src/third_party/libevent/android/event2/event-config.h b/ipc/chromium/src/third_party/libevent/android/event2/event-config.h
--- a/ipc/chromium/src/third_party/libevent/android/event2/event-config.h
+++ b/ipc/chromium/src/third_party/libevent/android/event2/event-config.h
@@ -397,32 +397,48 @@
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef _EVENT_PTHREAD_CREATE_JOINABLE */
/* The size of `int', as computed by sizeof. */
#define _EVENT_SIZEOF_INT 4
/* The size of `long', as computed by sizeof. */
+#ifdef __LP64__
+#define _EVENT_SIZEOF_LONG 8
+#else
#define _EVENT_SIZEOF_LONG 4
+#endif
/* The size of `long long', as computed by sizeof. */
#define _EVENT_SIZEOF_LONG_LONG 8
/* The size of `pthread_t', as computed by sizeof. */
+#ifdef __LP64__
+#define _EVENT_SIZEOF_PTHREAD_T 8
+#else
#define _EVENT_SIZEOF_PTHREAD_T 4
+#endif
/* The size of `short', as computed by sizeof. */
#define _EVENT_SIZEOF_SHORT 2
/* The size of `size_t', as computed by sizeof. */
+#ifdef __LP64__
+#define _EVENT_SIZEOF_SIZE_T 8
+#else
#define _EVENT_SIZEOF_SIZE_T 4
+#endif
/* The size of `void *', as computed by sizeof. */
+#ifdef __LP64__
+#define _EVENT_SIZEOF_VOID_P 8
+#else
#define _EVENT_SIZEOF_VOID_P 4
+#endif
/* Define to 1 if you have the ANSI C header files. */
#define _EVENT_STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define _EVENT_TIME_WITH_SYS_TIME 1
/* Version number of package */
+1
View File
@@ -54,6 +54,7 @@ if os_linux:
'libevent/epoll_sub.c',
]
# We allow warnings for third-party code that can be updated from upstream.
ALLOW_COMPILER_WARNINGS = True
FINAL_LIBRARY = 'xul'
+34 -28
View File
@@ -14,6 +14,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/Move.h"
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/Telemetry.h"
#include "nsDebug.h"
#include "nsISupportsImpl.h"
#include "nsContentUtils.h"
@@ -864,7 +865,8 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
return false;
}
if (DispatchingSyncMessagePriority() == IPC::Message::PRIORITY_NORMAL &&
if (mCurrentTransaction &&
DispatchingSyncMessagePriority() == IPC::Message::PRIORITY_NORMAL &&
msg->priority() > IPC::Message::PRIORITY_NORMAL)
{
// Don't allow sending CPOWs while we're dispatching a sync message.
@@ -874,22 +876,23 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
if (mCurrentTransaction &&
(msg->priority() < DispatchingSyncMessagePriority() ||
mAwaitingSyncReplyPriority > msg->priority() ||
DispatchingSyncMessagePriority() == IPC::Message::PRIORITY_URGENT ||
DispatchingAsyncMessagePriority() == IPC::Message::PRIORITY_URGENT))
mAwaitingSyncReplyPriority > msg->priority()))
{
CancelCurrentTransactionInternal();
mLink->SendMessage(new CancelMessage());
}
IPC_ASSERT(msg->is_sync(), "can only Send() sync messages here");
IPC_ASSERT(msg->priority() >= DispatchingSyncMessagePriority(),
"can't send sync message of a lesser priority than what's being dispatched");
IPC_ASSERT(AwaitingSyncReplyPriority() <= msg->priority(),
"nested sync message sends must be of increasing priority");
IPC_ASSERT(DispatchingSyncMessagePriority() != IPC::Message::PRIORITY_URGENT,
"not allowed to send messages while dispatching urgent messages");
if (mCurrentTransaction) {
IPC_ASSERT(msg->priority() >= DispatchingSyncMessagePriority(),
"can't send sync message of a lesser priority than what's being dispatched");
IPC_ASSERT(AwaitingSyncReplyPriority() <= msg->priority(),
"nested sync message sends must be of increasing priority");
IPC_ASSERT(DispatchingSyncMessagePriority() != IPC::Message::PRIORITY_URGENT,
"not allowed to send messages while dispatching urgent messages");
}
IPC_ASSERT(DispatchingAsyncMessagePriority() != IPC::Message::PRIORITY_URGENT,
"not allowed to send messages while dispatching urgent messages");
@@ -985,6 +988,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
bool
MessageChannel::Call(Message* aMsg, Message* aReply)
{
nsAutoPtr<Message> msg(aMsg);
AssertWorkerThread();
mMonitor->AssertNotCurrentThreadOwns();
@@ -994,7 +998,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
// This must come before MonitorAutoLock, as its destructor acquires the
// monitor lock.
CxxStackFrame cxxframe(*this, OUT_MESSAGE, aMsg);
CxxStackFrame cxxframe(*this, OUT_MESSAGE, msg);
// mMonitor can be NULL in some conditions
if (!mMonitor) {
@@ -1004,7 +1008,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
MonitorAutoLock lock(*mMonitor);
if (!Connected()) {
ReportConnectionError("MessageChannel::Call", aMsg);
ReportConnectionError("MessageChannel::Call", msg);
return false;
}
@@ -1013,9 +1017,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
"cannot issue Interrupt call while blocked on sync request");
IPC_ASSERT(!DispatchingSyncMessage(),
"violation of sync handler invariant");
IPC_ASSERT(aMsg->is_interrupt(), "can only Call() Interrupt messages here");
nsAutoPtr<Message> msg(aMsg);
IPC_ASSERT(msg->is_interrupt(), "can only Call() Interrupt messages here");
msg->set_seqno(NextSeqno());
msg->set_interrupt_remote_stack_depth_guess(mRemoteStackDepthGuess);
@@ -1334,11 +1336,6 @@ MessageChannel::DispatchSyncMessage(const Message& aMsg, Message*& aReply)
MOZ_ASSERT_IF(prio > IPC::Message::PRIORITY_NORMAL, NS_IsMainThread());
MaybeScriptBlocker scriptBlocker(this, prio > IPC::Message::PRIORITY_NORMAL);
IPC_ASSERT(prio >= DispatchingSyncMessagePriority(),
"priority inversion while dispatching sync message");
IPC_ASSERT(prio >= mAwaitingSyncReplyPriority,
"dispatching a message of lower priority while waiting for a response");
MessageChannel* dummy;
MessageChannel*& blockingVar = ShouldBlockScripts() ? gParentProcessBlocker : dummy;
@@ -1412,8 +1409,9 @@ MessageChannel::DispatchInterruptMessage(const Message& aMsg, size_t stackDepth)
// processing of the other side's in-call.
bool defer;
const char* winner;
switch (mListener->MediateInterruptRace((mSide == ChildSide) ? aMsg : mInterruptStack.top(),
(mSide != ChildSide) ? mInterruptStack.top() : aMsg))
const Message& parentMsg = (mSide == ChildSide) ? aMsg : mInterruptStack.top();
const Message& childMsg = (mSide == ChildSide) ? mInterruptStack.top() : aMsg;
switch (mListener->MediateInterruptRace(parentMsg, childMsg))
{
case RIPChildWins:
winner = "child";
@@ -1490,9 +1488,6 @@ MessageChannel::MaybeUndeferIncall()
IPC_ASSERT(mDeferred.top().interrupt_remote_stack_depth_guess() <= stackDepth,
"fatal logic error");
if (mDeferred.top().interrupt_remote_stack_depth_guess() < RemoteViewOfStackDepth(stackDepth))
return;
// maybe time to process this message
Message call = mDeferred.top();
mDeferred.pop();
@@ -2042,22 +2037,33 @@ MessageChannel::CancelCurrentTransactionInternal()
// tampered with (by us). If so, they don't reset the variable to the old
// value.
MOZ_ASSERT(!mCurrentTransaction);
MOZ_ASSERT(mCurrentTransaction);
mCurrentTransaction = 0;
mAwaitingSyncReply = false;
mAwaitingSyncReplyPriority = 0;
// We could also zero out mDispatchingSyncMessage here. However, that would
// cause a race because mDispatchingSyncMessage is a worker-thread-only
// field and we can be called on the I/O thread. Luckily, we can check to
// see if mCurrentTransaction is 0 before examining DispatchSyncMessage.
}
void
MessageChannel::CancelCurrentTransaction()
{
MonitorAutoLock lock(*mMonitor);
CancelCurrentTransactionInternal();
mLink->SendMessage(new CancelMessage());
if (mCurrentTransaction) {
CancelCurrentTransactionInternal();
mLink->SendMessage(new CancelMessage());
}
}
void
CancelCPOWs()
{
if (gParentProcessBlocker) {
mozilla::Telemetry::Accumulate(mozilla::Telemetry::IPC_TRANSACTION_CANCEL, true);
gParentProcessBlocker->CancelCurrentTransaction();
}
}
+1 -1
View File
@@ -570,7 +570,7 @@ class MessageChannel : HasResultCodes
public:
explicit AutoEnterTransaction(MessageChannel *aChan, int32_t aMsgSeqno)
: mChan(aChan),
mNewTransaction(0),
mNewTransaction(INT32_MAX),
mOldTransaction(mChan->mCurrentTransaction)
{
mChan->mMonitor->AssertCurrentThreadOwns();
+15
View File
@@ -57,6 +57,21 @@ private:
bool mReneuter;
};
class MOZ_RAII SuppressedNeuteringRegion
{
public:
SuppressedNeuteringRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
~SuppressedNeuteringRegion();
static inline bool IsNeuteringSuppressed() { return sSuppressNeutering; }
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
bool mReenable;
static bool sSuppressNeutering;
};
} // namespace ipc
} // namespace mozilla
+1 -1
View File
@@ -21,7 +21,7 @@ void SetThisProcessName(const char *aName);
#ifdef MOZ_B2G_LOADER
// see ProcessUtils_linux.cpp for explaination.
void ProcLoaderClientGeckoInit();
bool ProcLoaderIsInitialized();
bool ProcLoaderLoad(const char *aArgv[],
const char *aEnvp[],
const base::file_handle_mapping_vector &aFdsRemap,
+5
View File
@@ -227,6 +227,11 @@ ProcLoaderClientGeckoInit()
sProcLoaderLoop = MessageLoop::current();
}
bool ProcLoaderIsInitialized()
{
return sProcLoaderPid != 0;
}
/**
* Shutdown and destroy the client of B2G loader service.
*/
+12
View File
@@ -26,6 +26,18 @@ using base::ProcessId;
namespace mozilla {
namespace ipc {
ProtocolCloneContext::ProtocolCloneContext()
: mNeckoParent(nullptr)
{}
ProtocolCloneContext::~ProtocolCloneContext()
{}
void ProtocolCloneContext::SetContentParent(ContentParent* aContentParent)
{
mContentParent = aContentParent;
}
static StaticMutex gProtocolMutex;
IToplevelProtocol::IToplevelProtocol(ProtocolId aProtoId)
+5 -9
View File
@@ -131,19 +131,15 @@ class ProtocolCloneContext
typedef mozilla::dom::ContentParent ContentParent;
typedef mozilla::net::NeckoParent NeckoParent;
ContentParent* mContentParent;
RefPtr<ContentParent> mContentParent;
NeckoParent* mNeckoParent;
public:
ProtocolCloneContext()
: mContentParent(nullptr)
, mNeckoParent(nullptr)
{}
ProtocolCloneContext();
void SetContentParent(ContentParent* aContentParent)
{
mContentParent = aContentParent;
}
~ProtocolCloneContext();
void SetContentParent(ContentParent* aContentParent);
ContentParent* GetContentParent() { return mContentParent; }
+115 -1
View File
@@ -15,6 +15,7 @@
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsIXULAppInfo.h"
#include "nsWindowsDllInterceptor.h"
#include "WinUtils.h"
#include "mozilla/ArrayUtils.h"
@@ -436,6 +437,93 @@ ProcessOrDeferMessage(HWND hwnd,
return res;
}
/*
* It is bad to subclass a window when neutering is active because you'll end
* up subclassing the *neutered* window procedure instead of the real window
* procedure. Since CreateWindow* fires WM_CREATE (and could thus trigger
* neutering), we intercept these calls and suppress neutering for the duration
* of the call. This ensures that any subsequent subclassing replaces the
* correct window procedure.
*/
WindowsDllInterceptor sUser32Interceptor;
typedef HWND (WINAPI *CreateWindowExWPtr)(DWORD,LPCWSTR,LPCWSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
typedef HWND (WINAPI *CreateWindowExAPtr)(DWORD,LPCSTR,LPCSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
typedef HWND (WINAPI *CreateWindowWPtr)(LPCWSTR,LPCWSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
typedef HWND (WINAPI *CreateWindowAPtr)(LPCSTR,LPCSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
CreateWindowExWPtr sCreateWindowExWStub = nullptr;
CreateWindowExAPtr sCreateWindowExAStub = nullptr;
CreateWindowWPtr sCreateWindowWStub = nullptr;
CreateWindowAPtr sCreateWindowAStub = nullptr;
HWND WINAPI
CreateWindowExWHook(DWORD aExStyle, LPCWSTR aClassName, LPCWSTR aWindowName,
DWORD aStyle, int aX, int aY, int aWidth, int aHeight,
HWND aParent, HMENU aMenu, HINSTANCE aInstance,
LPVOID aParam)
{
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
return sCreateWindowExWStub(aExStyle, aClassName, aWindowName, aStyle, aX, aY,
aWidth, aHeight, aParent, aMenu, aInstance, aParam);
}
HWND WINAPI
CreateWindowExAHook(DWORD aExStyle, LPCSTR aClassName, LPCSTR aWindowName,
DWORD aStyle, int aX, int aY, int aWidth, int aHeight,
HWND aParent, HMENU aMenu, HINSTANCE aInstance,
LPVOID aParam)
{
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
return sCreateWindowExAStub(aExStyle, aClassName, aWindowName, aStyle, aX, aY,
aWidth, aHeight, aParent, aMenu, aInstance, aParam);
}
HWND WINAPI
CreateWindowWHook(LPCWSTR aClassName, LPCWSTR aWindowName, DWORD aStyle, int aX,
int aY, int aWidth, int aHeight, HWND aParent, HMENU aMenu,
HINSTANCE aInstance, LPVOID aParam)
{
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
return sCreateWindowWStub(aClassName, aWindowName, aStyle, aX, aY, aWidth,
aHeight, aParent, aMenu, aInstance, aParam);
}
HWND WINAPI
CreateWindowAHook(LPCSTR aClassName, LPCSTR aWindowName, DWORD aStyle, int aX,
int aY, int aWidth, int aHeight, HWND aParent, HMENU aMenu,
HINSTANCE aInstance, LPVOID aParam)
{
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
return sCreateWindowAStub(aClassName, aWindowName, aStyle, aX, aY, aWidth,
aHeight, aParent, aMenu, aInstance, aParam);
}
void
InitCreateWindowHook()
{
sUser32Interceptor.Init("user32.dll");
if (!sCreateWindowExWStub) {
sUser32Interceptor.AddHook("CreateWindowExW",
reinterpret_cast<intptr_t>(CreateWindowExWHook),
(void**) &sCreateWindowExWStub);
}
if (!sCreateWindowExAStub) {
sUser32Interceptor.AddHook("CreateWindowExA",
reinterpret_cast<intptr_t>(CreateWindowExAHook),
(void**) &sCreateWindowExAStub);
}
if (!sCreateWindowWStub) {
sUser32Interceptor.AddHook("CreateWindowW",
reinterpret_cast<intptr_t>(CreateWindowWHook),
(void**) &sCreateWindowWStub);
}
if (!sCreateWindowAStub) {
sUser32Interceptor.AddHook("CreateWindowA",
reinterpret_cast<intptr_t>(CreateWindowAHook),
(void**) &sCreateWindowAStub);
}
}
} // namespace
// We need the pointer value of this in PluginInstanceChild.
@@ -610,7 +698,9 @@ CallWindowProcedureHook(int nCode,
HWND hWnd = reinterpret_cast<CWPSTRUCT*>(lParam)->hwnd;
if (!gNeuteredWindows->Contains(hWnd) && NeuterWindowProcedure(hWnd)) {
if (!gNeuteredWindows->Contains(hWnd) &&
!SuppressedNeuteringRegion::IsNeuteringSuppressed() &&
NeuterWindowProcedure(hWnd)) {
if (!gNeuteredWindows->AppendElement(hWnd)) {
NS_ERROR("Out of memory!");
RestoreWindowProcedure(hWnd);
@@ -710,6 +800,8 @@ InitUIThread()
gCOMWindow = FindCOMWindow();
}
MOZ_ASSERT(gWinEventHook);
InitCreateWindowHook();
}
} // namespace windows
@@ -943,6 +1035,26 @@ DeneuteredWindowRegion::~DeneuteredWindowRegion()
}
}
SuppressedNeuteringRegion::SuppressedNeuteringRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
: mReenable(::gUIThreadId == ::GetCurrentThreadId() && ::gWindowHook)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (mReenable) {
MOZ_ASSERT(!sSuppressNeutering);
sSuppressNeutering = true;
}
}
SuppressedNeuteringRegion::~SuppressedNeuteringRegion()
{
if (mReenable) {
MOZ_ASSERT(sSuppressNeutering);
sSuppressNeutering = false;
}
}
bool SuppressedNeuteringRegion::sSuppressNeutering = false;
bool
MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
{
@@ -997,6 +1109,8 @@ MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
NS_ASSERTION(timerId, "SetTimer failed!");
}
NeuteredWindowRegion neuteredRgn(true);
{
while (1) {
MSG msg = { 0 };
+1 -1
View File
@@ -16,7 +16,7 @@ class IPDLUnitTestProcessChild : public mozilla::ipc::ProcessChild
typedef mozilla::ipc::ProcessChild ProcessChild;
public:
IPDLUnitTestProcessChild(ProcessId aParentPid) :
explicit IPDLUnitTestProcessChild(ProcessId aParentPid) :
ProcessChild(aParentPid)
{ }
+20
View File
@@ -0,0 +1,20 @@
namespace mozilla {
namespace _ipdltest {
intr protocol PTestRaceDeadlock {
both:
async StartRace();
parent:
intr Lose();
child:
intr Win();
intr Rpc();
async __delete__();
/* Tests that race resolution does not cause deadlocks */
};
} // namespace _ipdltest
} // namespace mozilla
+2 -2
View File
@@ -42,7 +42,7 @@ class TestBridgeMainSubParent :
public PTestBridgeMainSubParent
{
public:
TestBridgeMainSubParent(Transport* aTransport)
explicit TestBridgeMainSubParent(Transport* aTransport)
: mTransport(aTransport)
{}
virtual ~TestBridgeMainSubParent() {}
@@ -126,7 +126,7 @@ class TestBridgeMainSubChild :
public PTestBridgeMainSubChild
{
public:
TestBridgeMainSubChild(Transport* aTransport)
explicit TestBridgeMainSubChild(Transport* aTransport)
: mGotHi(false)
, mTransport(aTransport)
{}
+1 -1
View File
@@ -20,7 +20,7 @@ class TestDataStructuresSub :
public PTestDataStructuresSubChild
{
public:
TestDataStructuresSub(uint32_t i) : mI(i)
explicit TestDataStructuresSub(uint32_t i) : mI(i)
{ }
virtual ~TestDataStructuresSub()
{ }
+2 -2
View File
@@ -40,7 +40,7 @@ namespace _ipdltest2 {
class TestOpensOpenedParent : public PTestOpensOpenedParent
{
public:
TestOpensOpenedParent(Transport* aTransport)
explicit TestOpensOpenedParent(Transport* aTransport)
: mTransport(aTransport)
{}
virtual ~TestOpensOpenedParent() {}
@@ -83,7 +83,7 @@ namespace _ipdltest2 {
class TestOpensOpenedChild : public PTestOpensOpenedChild
{
public:
TestOpensOpenedChild(Transport* aTransport)
explicit TestOpensOpenedChild(Transport* aTransport)
: mGotHi(false)
, mTransport(aTransport)
{}
+130
View File
@@ -0,0 +1,130 @@
#include "TestRaceDeadlock.h"
#include "IPDLUnitTests.h" // fail etc.
// #define TEST_TIMEOUT 5000
using namespace mozilla::ipc;
typedef mozilla::ipc::MessageChannel::Message Message;
namespace mozilla {
namespace _ipdltest {
static RacyInterruptPolicy
MediateRace(const Message& parent, const Message& child)
{
return (PTestRaceDeadlock::Msg_Win__ID == parent.type()) ?
RIPParentWins : RIPChildWins;
}
//-----------------------------------------------------------------------------
// parent
TestRaceDeadlockParent::TestRaceDeadlockParent()
{
MOZ_COUNT_CTOR(TestRaceDeadlockParent);
}
TestRaceDeadlockParent::~TestRaceDeadlockParent()
{
MOZ_COUNT_DTOR(TestRaceDeadlockParent);
}
void
TestRaceDeadlockParent::Main()
{
Test1();
Close();
}
bool
TestRaceDeadlockParent::ShouldContinueFromReplyTimeout()
{
fail("This test should not hang");
GetIPCChannel()->CloseWithTimeout();
return false;
}
void
TestRaceDeadlockParent::Test1()
{
#if defined(TEST_TIMEOUT)
SetReplyTimeoutMs(TEST_TIMEOUT);
#endif
if (!SendStartRace()) {
fail("sending StartRace");
}
if (!CallRpc()) {
fail("calling Rpc");
}
}
bool
TestRaceDeadlockParent::AnswerLose()
{
return true;
}
RacyInterruptPolicy
TestRaceDeadlockParent::MediateInterruptRace(const Message& parent,
const Message& child)
{
return MediateRace(parent, child);
}
//-----------------------------------------------------------------------------
// child
TestRaceDeadlockChild::TestRaceDeadlockChild()
{
MOZ_COUNT_CTOR(TestRaceDeadlockChild);
}
TestRaceDeadlockChild::~TestRaceDeadlockChild()
{
MOZ_COUNT_DTOR(TestRaceDeadlockChild);
}
bool
TestRaceDeadlockParent::RecvStartRace()
{
if (!CallWin()) {
fail("calling Win");
}
return true;
}
bool
TestRaceDeadlockChild::RecvStartRace()
{
if (!SendStartRace()) {
fail("calling SendStartRace");
}
if (!CallLose()) {
fail("calling Lose");
}
return true;
}
bool
TestRaceDeadlockChild::AnswerWin()
{
return true;
}
bool
TestRaceDeadlockChild::AnswerRpc()
{
return true;
}
RacyInterruptPolicy
TestRaceDeadlockChild::MediateInterruptRace(const Message& parent,
const Message& child)
{
return MediateRace(parent, child);
}
} // namespace _ipdltest
} // namespace mozilla
+75
View File
@@ -0,0 +1,75 @@
#ifndef mozilla__ipdltest_TestRaceDeadlock_h
#define mozilla__ipdltest_TestRaceDeadlock_h 1
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/PTestRaceDeadlockParent.h"
#include "mozilla/_ipdltest/PTestRaceDeadlockChild.h"
namespace mozilla {
namespace _ipdltest {
class TestRaceDeadlockParent :
public PTestRaceDeadlockParent
{
public:
TestRaceDeadlockParent();
virtual ~TestRaceDeadlockParent();
static bool RunTestInProcesses() { return true; }
static bool RunTestInThreads() { return true; }
void Main();
protected:
virtual bool ShouldContinueFromReplyTimeout() override;
void Test1();
virtual bool RecvStartRace() override;
virtual bool AnswerLose() override;
virtual mozilla::ipc::RacyInterruptPolicy
MediateInterruptRace(const Message& parent, const Message& child) override;
virtual void ActorDestroy(ActorDestroyReason why) override
{
if (NormalShutdown != why)
fail("unexpected destruction!");
passed("ok");
QuitParent();
}
};
class TestRaceDeadlockChild :
public PTestRaceDeadlockChild
{
public:
TestRaceDeadlockChild();
virtual ~TestRaceDeadlockChild();
protected:
virtual bool RecvStartRace() override;
virtual bool AnswerWin() override;
virtual bool AnswerRpc() override;
virtual mozilla::ipc::RacyInterruptPolicy
MediateInterruptRace(const Message& parent, const Message& child) override;
virtual void ActorDestroy(ActorDestroyReason why) override
{
if (NormalShutdown != why)
fail("unexpected destruction!");
QuitChild();
}
};
} // namespace _ipdltest
} // namespace mozilla
#endif // ifndef mozilla__ipdltest_TestRaceDeadlock_h
+4 -4
View File
@@ -22,7 +22,7 @@ class TestShutdownSubsubParent :
public PTestShutdownSubsubParent
{
public:
TestShutdownSubsubParent(bool expectParentDeleted) :
explicit TestShutdownSubsubParent(bool expectParentDeleted) :
mExpectParentDeleted(expectParentDeleted)
{
}
@@ -44,7 +44,7 @@ class TestShutdownSubParent :
public PTestShutdownSubParent
{
public:
TestShutdownSubParent(bool expectCrash) :
explicit TestShutdownSubParent(bool expectCrash) :
mExpectCrash(expectCrash),
mDeletedCount(0)
{
@@ -131,7 +131,7 @@ class TestShutdownSubsubChild :
public PTestShutdownSubsubChild
{
public:
TestShutdownSubsubChild(bool expectParentDeleted) :
explicit TestShutdownSubsubChild(bool expectParentDeleted) :
mExpectParentDeleted(expectParentDeleted)
{
}
@@ -152,7 +152,7 @@ class TestShutdownSubChild :
public PTestShutdownSubChild
{
public:
TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash)
explicit TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash)
{
}
+2
View File
@@ -33,6 +33,7 @@ SOURCES += [
'TestMultiMgrs.cpp',
'TestNestedLoops.cpp',
'TestOpens.cpp',
'TestRaceDeadlock.cpp',
'TestRaceDeferral.cpp',
'TestRacyInterruptReplies.cpp',
'TestRacyReentry.cpp',
@@ -102,6 +103,7 @@ IPDL_SOURCES += [
'PTestNestedLoops.ipdl',
'PTestOpens.ipdl',
'PTestOpensOpened.ipdl',
'PTestRaceDeadlock.ipdl',
'PTestRaceDeferral.ipdl',
'PTestRacyInterruptReplies.ipdl',
'PTestRacyReentry.ipdl',
+3 -3
View File
@@ -29,14 +29,14 @@ UnixSocketWatcher::Connect(const struct sockaddr* aAddr, socklen_t aAddrLen)
MOZ_ASSERT(IsOpen());
MOZ_ASSERT(aAddr || !aAddrLen);
if (connect(GetFd(), aAddr, aAddrLen) < 0) {
if (TEMP_FAILURE_RETRY(connect(GetFd(), aAddr, aAddrLen) < 0)) {
if (errno == EINPROGRESS) {
mConnectionStatus = SOCKET_IS_CONNECTING;
// Set up a write watch to receive the connect signal
AddWatchers(WRITE_WATCHER, false);
} else {
OnError("connect", errno);
return NS_OK;
}
OnError("connect", errno);
return NS_ERROR_FAILURE;
}
+7 -5
View File
@@ -31,7 +31,8 @@ using mozilla::Maybe;
class MOZ_STACK_CLASS AutoCompilationTraceLogger
{
public:
AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id);
AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id,
const ReadOnlyCompileOptions& options);
private:
TraceLoggerThread* logger;
@@ -117,10 +118,11 @@ class MOZ_STACK_CLASS BytecodeCompiler
Maybe<BytecodeEmitter> emitter;
};
AutoCompilationTraceLogger::AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id)
AutoCompilationTraceLogger::AutoCompilationTraceLogger(ExclusiveContext* cx,
const TraceLoggerTextId id, const ReadOnlyCompileOptions& options)
: logger(cx->isJSContext() ? TraceLoggerForMainThread(cx->asJSContext()->runtime())
: TraceLoggerForCurrentThread()),
event(logger, TraceLogger_AnnotateScripts),
event(logger, TraceLogger_AnnotateScripts, options),
scriptLogger(logger, event),
typeLogger(logger, id)
{}
@@ -131,7 +133,7 @@ BytecodeCompiler::BytecodeCompiler(ExclusiveContext* cx,
SourceBufferHolder& sourceBuffer,
Handle<ScopeObject*> enclosingStaticScope,
TraceLoggerTextId logId)
: traceLogger(cx, logId),
: traceLogger(cx, logId, options),
keepAtoms(cx->perThreadData),
cx(cx),
alloc(alloc),
@@ -785,7 +787,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
.setNoScriptRval(false)
.setSelfHostingMode(false);
AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy);
AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy, options);
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
/* foldConstants = */ true, nullptr, lazy);
+22 -28
View File
@@ -5938,38 +5938,32 @@ BytecodeEmitter::emitFor(ParseNode* pn)
bool
BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope)
{
// ES6 specifies that loop variables get a fresh binding in each iteration.
// This is currently implemented for C-style for(;;) loops, but not
// for-in/of loops, though a similar approach should work. See bug 449811.
//
// In `for (let x in/of EXPR)`, ES6 specifies that EXPR is evaluated in a
// scope containing an uninitialized `x`. If EXPR accesses `x`, we should
// get a ReferenceError due to the TDZ violation. This is not yet
// implemented. See bug 1069480.
// ES6 specifies that lexical for-loop variables get a fresh binding each
// iteration, and that evaluation of the expression looped over occurs with
// these variables uninitialized. But these rules only apply to *standard*
// for-in/of loops, and we haven't extended these requirements to
// comprehension syntax.
*letBlockScope = pn->isKind(PNK_LEXICALSCOPE);
MOZ_ASSERT_IF(*letBlockScope, pn->isLexical());
if (*letBlockScope) {
// This is initially-ES7-tracked syntax, now with considerably
// murkier outlook. The |enterBlockScope()| precipitated by the
// outparam-set here initializes the let-binding in
// |emitComprehensionFor{In,Of}| with |undefined|, so there's nothing
// to do here.
MOZ_ASSERT(pn->isLexical());
} else {
// This is legacy comprehension syntax. We'll have PNK_LET here, using
// a lexical scope provided by/for the entire comprehension. Name
// analysis assumes declarations initialize lets, but as we're handling
// this declaration manually, we must also initialize manually to avoid
// triggering dead zone checks.
MOZ_ASSERT(pn->isKind(PNK_LET));
MOZ_ASSERT(pn->pn_count == 1);
// If the left part is 'var x', emit code to define x if necessary using a
// prologue opcode, but do not emit a pop. If it is 'let x', enterBlockScope
// will initialize let bindings in emitForOf and emitForIn with
// undefineds.
//
// Due to the horror of legacy comprehensions, there is a third case where
// we have PNK_LET without a lexical scope, because those expressions are
// parsed with single lexical scope for the entire comprehension. In this
// case we must initialize the lets to not trigger dead zone checks via
// InitializeVars.
if (!*letBlockScope) {
emittingForInit = true;
if (pn->isKind(PNK_VAR)) {
if (!emitVariables(pn, DefineVars))
return false;
} else {
MOZ_ASSERT(pn->isKind(PNK_LET));
if (!emitVariables(pn, InitializeVars))
return false;
}
if (!emitVariables(pn, InitializeVars))
return false;
emittingForInit = false;
}
@@ -12,6 +12,3 @@
[Window attribute: onmousewheel]
expected: FAIL
[Window attribute: onstorage]
expected: FAIL
@@ -655,12 +655,6 @@
[HTMLLinkElement interface: document.createElement("link") must inherit property "crossOrigin" with the proper type (1)]
expected: FAIL
[HTMLBodyElement interface: attribute onstorage]
expected: FAIL
[HTMLBodyElement interface: document.createElement("body") must inherit property "onstorage" with the proper type (17)]
expected: FAIL
[HTMLPreElement must be primary interface of document.createElement("listing")]
expected: FAIL
@@ -2104,9 +2098,6 @@
[Window interface: attribute ontoggle]
expected: FAIL
[Window interface: attribute onstorage]
expected: FAIL
[Window interface: operation setTimeout(Function,long,any)]
expected: FAIL
@@ -2158,9 +2149,6 @@
[Window interface: window must inherit property "ontoggle" with the proper type (98)]
expected: FAIL
[Window interface: window must inherit property "onstorage" with the proper type (112)]
expected: FAIL
[Window interface: calling createImageBitmap(ImageBitmapSource,long,long,long,long) on window with too few arguments must throw TypeError]
expected: FAIL
@@ -2620,12 +2608,6 @@
[HTMLMarqueeElement interface: document.createElement("marquee") must inherit property "stop" with the proper type (15)]
expected: FAIL
[HTMLFrameSetElement interface: attribute onstorage]
expected: FAIL
[HTMLFrameSetElement interface: document.createElement("frameset") must inherit property "onstorage" with the proper type (13)]
expected: FAIL
[Document interface: iframe.contentDocument must inherit property "styleSheetSets" with the proper type (31)]
expected: FAIL
@@ -1,5 +1,4 @@
[event_body_attribute.html]
type: testharness
[localStorage mutations fire StorageEvents that are caught by the event listener specified as an attribute on the body.]
expected: FAIL
disabled:
if e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1205675
@@ -0,0 +1,60 @@
iframe = document.createElement("IFRAME");
iframe.src = "about:blank";
document.body.appendChild(iframe);
iframe.contentWindow.document.body.textContent = "Nothing to see here.";
storageEventList = new Array();
iframe.contentWindow.onstorage = function(e) {
window.parent.storageEventList.push(e);
};
function runAfterNStorageEvents(callback, expectedNumEvents)
{
countStorageEvents(callback, expectedNumEvents, 0)
}
function countStorageEvents(callback, expectedNumEvents, times)
{
function onTimeout()
{
var currentCount = storageEventList.length;
if (currentCount == expectedNumEvents) {
callback();
} else if (currentCount > expectedNumEvents) {
msg = "got at least " + currentCount + ", expected only " + expectedNumEvents + " events";
callback(msg);
} else if (times > 50) {
msg = "Timeout: only got " + currentCount + ", expected " + expectedNumEvents + " events";
callback(msg);
} else {
countStorageEvents(callback, expectedNumEvents, times+1);
}
}
setTimeout(onTimeout, 20);
}
function clearStorage(storageName, callback)
{
if (window[storageName].length === 0) {
storageEventList = [];
setTimeout(callback, 0);
} else {
window[storageName].clear();
runAfterNStorageEvents(function() {
storageEventList = [];
callback();
}, 1);
}
}
function testStorages(testCallback)
{
testCallback("sessionStorage");
var hit = false;
add_result_callback(function() {
if (!hit) {
hit = true;
testCallback("localStorage");
}
});
}
@@ -0,0 +1,116 @@
testStorages(function(storageString) {
async_test(function(t) {
assert_true(storageString in window, storageString + " exist");
var storage = window[storageString];
t.add_cleanup(function() { storage.clear() });
clearStorage(storageString, t.step_func(step0));
assert_equals(storage.length, 0, "storage.length");
function step0(msg)
{
iframe.onload = t.step_func(step1);
// Null out the existing handler eventTestHarness.js set up;
// otherwise this test won't be testing much of anything useful.
iframe.contentWindow.onstorage = null;
iframe.src = "resources/event_body_handler.html";
}
function step1(msg)
{
storageEventList = new Array();
storage.setItem('FOO', 'BAR');
runAfterNStorageEvents(t.step_func(step2), 1);
}
function step2(msg)
{
if (msg != undefined) {
assert_unreached(msg);
}
assert_equals(storageEventList.length, 1);
assert_equals(storageEventList[0].key, "FOO");
assert_equals(storageEventList[0].oldValue, null);
assert_equals(storageEventList[0].newValue, "BAR");
storage.setItem('FU', 'BAR');
storage.setItem('a', '1');
storage.setItem('b', '2');
storage.setItem('b', '3');
runAfterNStorageEvents(t.step_func(step3), 5);
}
function step3(msg)
{
if (msg != undefined) {
assert_unreached(msg);
}
assert_equals(storageEventList.length, 5);
assert_equals(storageEventList[1].key, "FU");
assert_equals(storageEventList[1].oldValue, null);
assert_equals(storageEventList[1].newValue, "BAR");
assert_equals(storageEventList[2].key, "a");
assert_equals(storageEventList[2].oldValue, null);
assert_equals(storageEventList[2].newValue, "1");
assert_equals(storageEventList[3].key, "b");
assert_equals(storageEventList[3].oldValue, null);
assert_equals(storageEventList[3].newValue, "2");
assert_equals(storageEventList[4].key, "b");
assert_equals(storageEventList[4].oldValue, "2");
assert_equals(storageEventList[4].newValue, "3");
storage.removeItem('FOO');
runAfterNStorageEvents(t.step_func(step4), 6);
}
function step4(msg)
{
if(msg != undefined) {
assert_unreached(msg);
}
assert_equals(storageEventList.length, 6);
assert_equals(storageEventList[5].key, "FOO");
assert_equals(storageEventList[5].oldValue, "BAR");
assert_equals(storageEventList[5].newValue, null);
storage.removeItem('FU');
runAfterNStorageEvents(t.step_func(step5), 7);
}
function step5(msg)
{
if(msg != undefined) {
assert_unreached(msg);
}
assert_equals(storageEventList.length, 7);
assert_equals(storageEventList[6].key, "FU");
assert_equals(storageEventList[6].oldValue, "BAR");
assert_equals(storageEventList[6].newValue, null);
storage.clear();
runAfterNStorageEvents(t.step_func(step6), 8);
}
function step6(msg)
{
if(msg != undefined) {
assert_unreached(msg);
}
assert_equals(storageEventList.length, 8);
assert_equals(storageEventList[7].key, null);
assert_equals(storageEventList[7].oldValue, null);
assert_equals(storageEventList[7].newValue, null);
t.done();
}
}, storageString + " mutations fire StorageEvents that are caught by the event listener specified as an attribute on the body.");
});
@@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
<script>
function handleStorageEvent(e) {
window.parent.storageEventList.push(e);
}
</script>
</head>
<body onstorage="handleStorageEvent(event);">
</body>
</html>
@@ -5172,6 +5172,12 @@
"keyed" : true,
"description" : "Exceptions thrown by add-ons"
},
"IPC_TRANSACTION_CANCEL": {
"alert_emails": ["billm@mozilla.com"],
"expires_in_version": "never",
"kind": "boolean",
"description": "True when an IPC transaction is canceled"
},
"IPC_SAME_PROCESS_MESSAGE_COPY_OOM_KB": {
"expires_in_version": "50",
"kind": "exponential",
+1
View File
@@ -98,6 +98,7 @@ NS_EVENT_MESSAGE(eHashChange)
NS_EVENT_MESSAGE(eImageAbort)
NS_EVENT_MESSAGE(eLoadError)
NS_EVENT_MESSAGE(ePopState)
NS_EVENT_MESSAGE(eStorage)
NS_EVENT_MESSAGE(eBeforeUnload)
NS_EVENT_MESSAGE(eReadyStateChange)
+1 -1
View File
@@ -1136,7 +1136,7 @@ nsresult GfxInfoBase::GetInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aResu
const nsCString&
GfxInfoBase::GetApplicationVersion()
{
static nsAutoCString version;
static nsCString version;
static bool versionInitialized = false;
if (!versionInitialized) {
// If we fail to get the version, we will not try again.
+1 -1
View File
@@ -269,7 +269,7 @@ private:
void Clear();
private:
nsAutoString mString;
nsString mString;
RefPtr<TextRangeArray> mClauses;
TextRange mCaret;
+1 -1
View File
@@ -63,7 +63,7 @@ private:
void InhibitFailed();
void InhibitSucceeded(uint32_t aInhibitRequest);
nsAutoCString mTopic;
nsCString mTopic;
DBusConnection* mConnection;
DesktopEnvironment mDesktopEnvironment;