Backed out 2 changesets (bug 915757, bug 919885) for frequent Android Armv6 mochitest-8 crashes.

Backed out changeset 04610078280c (bug 915757)
Backed out changeset db9190b3ce60 (bug 919885)
This commit is contained in:
Ryan VanderMeulen 2013-10-14 14:38:54 -04:00
parent d9879cd4ec
commit a80b1ea22a
63 changed files with 1179 additions and 805 deletions

View File

@ -329,7 +329,7 @@ DocManager::AddListeners(nsIDocument* aDocument,
{
nsPIDOMWindow* window = aDocument->GetWindow();
EventTarget* target = window->GetChromeEventHandler();
nsEventListenerManager* elm = target->GetOrCreateListenerManager();
nsEventListenerManager* elm = target->GetListenerManager(true);
elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
dom::TrustedEventsAtCapture());
@ -359,7 +359,7 @@ DocManager::RemoveListeners(nsIDocument* aDocument)
if (!target)
return;
nsEventListenerManager* elm = target->GetOrCreateListenerManager();
nsEventListenerManager* elm = target->GetListenerManager(true);
elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
dom::TrustedEventsAtCapture());

View File

@ -46,7 +46,7 @@ nsCoreUtils::HasClickListener(nsIContent *aContent)
{
NS_ENSURE_TRUE(aContent, false);
nsEventListenerManager* listenerManager =
aContent->GetExistingListenerManager();
aContent->GetListenerManager(false);
return listenerManager &&
(listenerManager->HasListenersFor(nsGkAtoms::onclick) ||

View File

@ -1060,19 +1060,15 @@ public:
nsCycleCollectionTraversalCallback &cb);
/**
* Get the eventlistener manager for aNode, creating it if it does not
* already exist.
* Get the eventlistener manager for aNode. If a new eventlistener manager
* was created, aCreated is set to true.
*
* @param aNode The node for which to get the eventlistener manager.
* @param aCreateIfNotFound If false, returns a listener manager only if
* one already exists.
*/
static nsEventListenerManager* GetListenerManagerForNode(nsINode* aNode);
/**
* Get the eventlistener manager for aNode, returning null if it does not
* already exist.
*
* @param aNode The node for which to get the eventlistener manager.
*/
static nsEventListenerManager* GetExistingListenerManagerForNode(const nsINode* aNode);
static nsEventListenerManager* GetListenerManager(nsINode* aNode,
bool aCreateIfNotFound);
static void UnmarkGrayJSListenersInCCGenerationDocuments(uint32_t aGeneration);

View File

@ -800,12 +800,6 @@ public:
* See nsIDOMEventTarget
*/
NS_DECL_NSIDOMEVENTTARGET
virtual nsEventListenerManager*
GetExistingListenerManager() const MOZ_OVERRIDE;
virtual nsEventListenerManager*
GetOrCreateListenerManager() MOZ_OVERRIDE;
using mozilla::dom::EventTarget::RemoveEventListener;
using nsIDOMEventTarget::AddEventListener;
virtual void AddEventListener(const nsAString& aType,

View File

@ -1810,7 +1810,7 @@ Element::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
bool* aDefer)
{
*aDefer = true;
return GetOrCreateListenerManager();
return GetListenerManager(true);
}
Element::nsAttrInfo

View File

@ -1225,7 +1225,7 @@ FragmentOrElement::MarkNodeChildren(nsINode* aNode)
JS::ExposeObjectToActiveJS(o);
}
nsEventListenerManager* elm = aNode->GetExistingListenerManager();
nsEventListenerManager* elm = aNode->GetListenerManager(false);
if (elm) {
elm->MarkForCC();
}

View File

@ -144,7 +144,7 @@ MarkMessageManagers()
continue;
}
static_cast<nsInProcessTabChildGlobal*>(et)->MarkForCC();
nsEventListenerManager* elm = et->GetExistingListenerManager();
nsEventListenerManager* elm = et->GetListenerManager(false);
if (elm) {
elm->MarkForCC();
}
@ -188,13 +188,13 @@ MarkContentViewer(nsIContentViewer* aViewer, bool aCleanupJS,
doc->GetMarkedCCGeneration() != nsCCUncollectableMarker::sGeneration) {
doc->MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
if (aCleanupJS) {
nsEventListenerManager* elm = doc->GetExistingListenerManager();
nsEventListenerManager* elm = doc->GetListenerManager(false);
if (elm) {
elm->MarkForCC();
}
nsCOMPtr<EventTarget> win = do_QueryInterface(doc->GetInnerWindow());
if (win) {
elm = win->GetExistingListenerManager();
elm = win->GetListenerManager(false);
if (elm) {
elm->MarkForCC();
}

View File

@ -3630,7 +3630,7 @@ nsContentUtils::HasMutationListeners(nsINode* aNode,
if (aNode->IsInDoc()) {
nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
if (piTarget) {
nsEventListenerManager* manager = piTarget->GetExistingListenerManager();
nsEventListenerManager* manager = piTarget->GetListenerManager(false);
if (manager && manager->HasMutationListeners()) {
return true;
}
@ -3641,7 +3641,7 @@ nsContentUtils::HasMutationListeners(nsINode* aNode,
// might not be in our chain. If we don't have a window, we might have a
// mutation listener. Check quickly to see.
while (aNode) {
nsEventListenerManager* manager = aNode->GetExistingListenerManager();
nsEventListenerManager* manager = aNode->GetListenerManager(false);
if (manager && manager->HasMutationListeners()) {
return true;
}
@ -3763,8 +3763,13 @@ nsContentUtils::TraverseListenerManager(nsINode *aNode,
}
nsEventListenerManager*
nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
nsContentUtils::GetListenerManager(nsINode *aNode,
bool aCreateIfNotFound)
{
if (!aCreateIfNotFound && !aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
return nullptr;
}
if (!sEventListenerManagersHash.ops) {
// We're already shut down, don't bother creating an event listener
// manager.
@ -3772,6 +3777,17 @@ nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
return nullptr;
}
if (!aCreateIfNotFound) {
EventListenerManagerMapEntry *entry =
static_cast<EventListenerManagerMapEntry *>
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
return entry->mListenerManager;
}
return nullptr;
}
EventListenerManagerMapEntry *entry =
static_cast<EventListenerManagerMapEntry *>
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
@ -3790,31 +3806,6 @@ nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
return entry->mListenerManager;
}
nsEventListenerManager*
nsContentUtils::GetExistingListenerManagerForNode(const nsINode *aNode)
{
if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
return nullptr;
}
if (!sEventListenerManagersHash.ops) {
// We're already shut down, don't bother creating an event listener
// manager.
return nullptr;
}
EventListenerManagerMapEntry *entry =
static_cast<EventListenerManagerMapEntry *>
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
return entry->mListenerManager;
}
return nullptr;
}
/* static */
void
nsContentUtils::RemoveListenerManager(nsINode *aNode)

View File

@ -1659,7 +1659,7 @@ nsDocument::DeleteCycleCollectable()
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDocument)
if (Element::CanSkip(tmp, aRemovingAllowed)) {
nsEventListenerManager* elm = tmp->GetExistingListenerManager();
nsEventListenerManager* elm = tmp->GetListenerManager(false);
if (elm) {
elm->MarkForCC();
}
@ -6966,9 +6966,9 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
}
nsEventListenerManager*
nsDocument::GetOrCreateListenerManager()
nsDocument::GetListenerManager(bool aCreateIfNotFound)
{
if (!mListenerManager) {
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager =
new nsEventListenerManager(static_cast<EventTarget*>(this));
SetFlags(NODE_HAS_LISTENERMANAGER);
@ -6977,12 +6977,6 @@ nsDocument::GetOrCreateListenerManager()
return mListenerManager;
}
nsEventListenerManager*
nsDocument::GetExistingListenerManager() const
{
return mListenerManager;
}
nsresult
nsDocument::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
@ -7676,7 +7670,8 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
// Check our event listener manager for unload/beforeunload listeners.
nsCOMPtr<EventTarget> piTarget = do_QueryInterface(mScriptGlobalObject);
if (piTarget) {
nsEventListenerManager* manager = piTarget->GetExistingListenerManager();
nsEventListenerManager* manager =
piTarget->GetListenerManager(false);
if (manager && manager->HasUnloadListeners()) {
return false;
}

View File

@ -773,8 +773,8 @@ public:
// nsIDOMEventTarget
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
virtual nsEventListenerManager* GetOrCreateListenerManager() MOZ_OVERRIDE;
virtual nsEventListenerManager* GetExistingListenerManager() const MOZ_OVERRIDE;
virtual nsEventListenerManager*
GetListenerManager(bool aCreateIfNotFound) MOZ_OVERRIDE;
// nsIScriptObjectPrincipal
virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE;

View File

@ -1038,7 +1038,7 @@ nsINode::AddEventListener(const nsAString& aType,
aWantsUntrusted = true;
}
nsEventListenerManager* listener_manager = GetOrCreateListenerManager();
nsEventListenerManager* listener_manager = GetListenerManager(true);
NS_ENSURE_STATE(listener_manager);
listener_manager->AddEventListener(aType, aListener, aUseCapture,
aWantsUntrusted);
@ -1059,7 +1059,7 @@ nsINode::AddEventListener(const nsAString& aType,
wantsUntrusted = aWantsUntrusted.Value();
}
nsEventListenerManager* listener_manager = GetOrCreateListenerManager();
nsEventListenerManager* listener_manager = GetListenerManager(true);
if (!listener_manager) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
@ -1095,7 +1095,7 @@ nsINode::RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture)
{
nsEventListenerManager* elm = GetExistingListenerManager();
nsEventListenerManager* elm = GetListenerManager(false);
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
}
@ -1157,15 +1157,9 @@ nsINode::DispatchDOMEvent(WidgetEvent* aEvent,
}
nsEventListenerManager*
nsINode::GetOrCreateListenerManager()
nsINode::GetListenerManager(bool aCreateIfNotFound)
{
return nsContentUtils::GetListenerManagerForNode(this);
}
nsEventListenerManager*
nsINode::GetExistingListenerManager() const
{
return nsContentUtils::GetExistingListenerManagerForNode(this);
return nsContentUtils::GetListenerManager(this, aCreateIfNotFound);
}
nsIScriptContext*
@ -2170,7 +2164,8 @@ size_t
nsINode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t n = 0;
nsEventListenerManager* elm = GetExistingListenerManager();
nsEventListenerManager* elm =
const_cast<nsINode*>(this)->GetListenerManager(false);
if (elm) {
n += elm->SizeOfIncludingThis(aMallocSizeOf);
}
@ -2188,13 +2183,13 @@ nsINode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
#define EVENT(name_, id_, type_, struct_) \
EventHandlerNonNull* nsINode::GetOn##name_() { \
nsEventListenerManager *elm = GetExistingListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(false); \
return elm ? elm->GetEventHandler(nsGkAtoms::on##name_, EmptyString()) \
: nullptr; \
} \
void nsINode::SetOn##name_(EventHandlerNonNull* handler) \
{ \
nsEventListenerManager *elm = GetOrCreateListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(true); \
if (elm) { \
elm->SetEventHandler(nsGkAtoms::on##name_, EmptyString(), handler); \
} \

View File

@ -231,7 +231,7 @@ nsNodeUtils::LastRelease(nsINode* aNode)
#ifdef DEBUG
if (nsContentUtils::IsInitialized()) {
nsEventListenerManager* manager =
nsContentUtils::GetExistingListenerManagerForNode(aNode);
nsContentUtils::GetListenerManager(aNode, false);
if (!manager) {
NS_ERROR("Huh, our bit says we have a listener manager list, "
"but there's nothing in the hash!?!!");
@ -480,7 +480,7 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
nsPIDOMWindow* window = newDoc->GetInnerWindow();
if (window) {
nsEventListenerManager* elm = aNode->GetExistingListenerManager();
nsEventListenerManager* elm = aNode->GetListenerManager(false);
if (elm) {
window->SetMutationListeners(elm->MutationListenerBits());
if (elm->MayHavePaintEventListener()) {

View File

@ -2172,8 +2172,7 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
NS_ASSERTION(!(mState & XML_HTTP_REQUEST_SYNCLOOPING),
"We weren't supposed to support HTML parsing with XHR!");
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(mResponseXML);
nsEventListenerManager* manager =
eventTarget->GetOrCreateListenerManager();
nsEventListenerManager* manager = eventTarget->GetListenerManager(true);
manager->AddEventListenerByType(new nsXHRParseEndListener(this),
NS_LITERAL_STRING("DOMContentLoaded"),
dom::TrustedEventsAtSystemGroupBubble());

View File

@ -26,8 +26,8 @@ template <class T> struct Nullable;
// IID for the dom::EventTarget interface
#define NS_EVENTTARGET_IID \
{ 0xce3817d0, 0x177b, 0x402f, \
{ 0xae, 0x75, 0xf8, 0x4e, 0xbe, 0x5a, 0x07, 0xc3 } }
{ 0x0a5aed21, 0x0bab, 0x48b3, \
{ 0xbe, 0x4b, 0xd4, 0xf9, 0xd4, 0xea, 0xc7, 0xdb } }
class EventTarget : public nsIDOMEventTarget,
public nsWrapperCache
@ -70,17 +70,6 @@ public:
// current inner or if there is no window around at all.
virtual nsIDOMWindow* GetOwnerGlobal() = 0;
/**
* Get the event listener manager, creating it if it does not already exist.
*/
virtual nsEventListenerManager* GetOrCreateListenerManager() = 0;
/**
* Get the event listener manager, returning null if it does not already
* exist.
*/
virtual nsEventListenerManager* GetExistingListenerManager() const = 0;
protected:
EventHandlerNonNull* GetEventHandler(nsIAtom* aType,
const nsAString& aTypeString);

View File

@ -16,7 +16,7 @@ EventTarget::RemoveEventListener(const nsAString& aType,
bool aUseCapture,
ErrorResult& aRv)
{
nsEventListenerManager* elm = GetExistingListenerManager();
nsEventListenerManager* elm = GetListenerManager(false);
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
}
@ -25,7 +25,7 @@ EventTarget::RemoveEventListener(const nsAString& aType,
EventHandlerNonNull*
EventTarget::GetEventHandler(nsIAtom* aType, const nsAString& aTypeString)
{
nsEventListenerManager* elm = GetExistingListenerManager();
nsEventListenerManager* elm = GetListenerManager(false);
return elm ? elm->GetEventHandler(aType, aTypeString) : nullptr;
}
@ -52,7 +52,7 @@ void
EventTarget::SetEventHandler(nsIAtom* aType, const nsAString& aTypeString,
EventHandlerNonNull* aHandler)
{
GetOrCreateListenerManager()->SetEventHandler(aType, aTypeString, aHandler);
GetListenerManager(true)->SetEventHandler(aType, aTypeString, aHandler);
}
} // namespace dom

View File

@ -154,7 +154,7 @@ nsDOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture)
{
nsEventListenerManager* elm = GetExistingListenerManager();
nsEventListenerManager* elm = GetListenerManager(false);
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
}
@ -181,7 +181,7 @@ nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
NS_ENSURE_SUCCESS(rv, rv);
}
nsEventListenerManager* elm = GetOrCreateListenerManager();
nsEventListenerManager* elm = GetListenerManager(true);
NS_ENSURE_STATE(elm);
elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
return NS_OK;
@ -205,7 +205,7 @@ nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
wantsUntrusted = aWantsUntrusted.Value();
}
nsEventListenerManager* elm = GetOrCreateListenerManager();
nsEventListenerManager* elm = GetListenerManager(true);
if (!elm) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
@ -319,21 +319,15 @@ nsDOMEventTargetHelper::DispatchDOMEvent(WidgetEvent* aEvent,
}
nsEventListenerManager*
nsDOMEventTargetHelper::GetOrCreateListenerManager()
nsDOMEventTargetHelper::GetListenerManager(bool aCreateIfNotFound)
{
if (!mListenerManager) {
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager = new nsEventListenerManager(this);
}
return mListenerManager;
}
nsEventListenerManager*
nsDOMEventTargetHelper::GetExistingListenerManager() const
{
return mListenerManager;
}
nsIScriptContext*
nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
{

View File

@ -44,12 +44,6 @@ public:
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsDOMEventTargetHelper)
NS_DECL_NSIDOMEVENTTARGET
virtual nsEventListenerManager*
GetExistingListenerManager() const MOZ_OVERRIDE;
virtual nsEventListenerManager*
GetOrCreateListenerManager() MOZ_OVERRIDE;
using mozilla::dom::EventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
@ -225,11 +219,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMEventTargetHelper,
virtual nsresult DispatchDOMEvent(mozilla::WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent, nsPresContext* aPresContext, nsEventStatus* aEventStatus) { \
return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); \
} \
virtual nsEventListenerManager * GetOrCreateListenerManager() { \
return _to GetOrCreateListenerManager(); \
} \
virtual nsEventListenerManager * GetExistingListenerManager() const { \
return _to GetExistingListenerManager(); \
virtual nsEventListenerManager * GetListenerManager(bool aMayCreate) { \
return _to GetListenerManager(aMayCreate); \
} \
virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv) { \
return _to GetContextForEventHandlers(aRv); \
@ -241,14 +232,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMEventTargetHelper,
#define NS_REALLY_FORWARD_NSIDOMEVENTTARGET(_class) \
using _class::AddEventListener; \
using _class::RemoveEventListener; \
NS_FORWARD_NSIDOMEVENTTARGET(_class::) \
virtual nsEventListenerManager* \
GetOrCreateListenerManager() { \
return _class::GetOrCreateListenerManager(); \
} \
virtual nsEventListenerManager* \
GetExistingListenerManager() const { \
return _class::GetExistingListenerManager(); \
}
NS_FORWARD_NSIDOMEVENTTARGET(_class::)
#endif // nsDOMEventTargetHelper_h_

View File

@ -185,7 +185,8 @@ public:
if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) {
return NS_OK;
}
mManager = mTarget->GetExistingListenerManager();
mManager =
static_cast<nsEventListenerManager*>(mTarget->GetListenerManager(false));
}
if (mManager) {
NS_ASSERTION(aVisitor.mEvent->currentTarget == nullptr,

View File

@ -560,8 +560,7 @@ NS_AddSystemEventListener(mozilla::dom::EventTarget* aTarget,
bool aUseCapture,
bool aWantsUntrusted)
{
nsEventListenerManager* listenerManager =
aTarget->GetOrCreateListenerManager();
nsEventListenerManager* listenerManager = aTarget->GetListenerManager(true);
NS_ENSURE_STATE(listenerManager);
mozilla::dom::EventListenerFlags flags;
flags.mInSystemGroup = true;

View File

@ -162,11 +162,8 @@ nsEventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
*aCount = 0;
*aOutArray = nullptr;
nsCOMArray<nsIEventListenerInfo> listenerInfos;
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
nsEventListenerManager* elm = eventTarget->GetExistingListenerManager();
nsEventListenerManager* elm =
aEventTarget->GetListenerManager(false);
if (elm) {
elm->GetListenerInfo(&listenerInfos);
}
@ -224,10 +221,7 @@ nsEventListenerService::HasListenersFor(nsIDOMEventTarget* aEventTarget,
const nsAString& aType,
bool* aRetVal)
{
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
nsEventListenerManager* elm = eventTarget->GetExistingListenerManager();
nsEventListenerManager* elm = aEventTarget->GetListenerManager(false);
*aRetVal = elm && elm->HasListenersFor(aType);
return NS_OK;
}
@ -241,10 +235,7 @@ nsEventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget,
NS_PRECONDITION(aTarget, "Missing target");
NS_PRECONDITION(aListener, "Missing listener");
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
nsEventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
nsEventListenerManager* manager = aTarget->GetListenerManager(true);
NS_ENSURE_STATE(manager);
EventListenerFlags flags =
@ -263,10 +254,7 @@ nsEventListenerService::RemoveSystemEventListener(nsIDOMEventTarget *aTarget,
NS_PRECONDITION(aTarget, "Missing target");
NS_PRECONDITION(aListener, "Missing listener");
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
nsEventListenerManager* manager = eventTarget->GetExistingListenerManager();
nsEventListenerManager* manager = aTarget->GetListenerManager(false);
if (manager) {
EventListenerFlags flags =
aUseCapture ? TrustedEventsAtSystemGroupCapture() :
@ -285,11 +273,7 @@ nsEventListenerService::AddListenerForAllEvents(nsIDOMEventTarget* aTarget,
bool aSystemEventGroup)
{
NS_ENSURE_STATE(aTarget && aListener);
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
nsEventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
nsEventListenerManager* manager = aTarget->GetListenerManager(true);
NS_ENSURE_STATE(manager);
manager->AddListenerForAllEvents(aListener, aUseCapture, aWantsUntrusted,
aSystemEventGroup);
@ -303,11 +287,7 @@ nsEventListenerService::RemoveListenerForAllEvents(nsIDOMEventTarget* aTarget,
bool aSystemEventGroup)
{
NS_ENSURE_STATE(aTarget && aListener);
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
nsEventListenerManager* manager = eventTarget->GetExistingListenerManager();
nsEventListenerManager* manager = aTarget->GetListenerManager(false);
if (manager) {
manager->RemoveListenerForAllEvents(aListener, aUseCapture, aSystemEventGroup);
}

View File

@ -842,7 +842,7 @@ nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
if ((win = document->GetInnerWindow())) {
nsCOMPtr<EventTarget> piTarget(do_QueryInterface(win));
return piTarget->GetOrCreateListenerManager();
return piTarget->GetListenerManager(true);
}
return nullptr;
@ -1009,7 +1009,8 @@ nsGenericHTMLElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
UnsetFlags(NODE_HAS_ACCESSKEY);
}
else if (IsEventAttributeName(aAttribute)) {
if (nsEventListenerManager* manager = GetExistingListenerManager()) {
nsEventListenerManager* manager = GetListenerManager(false);
if (manager) {
manager->RemoveEventHandler(aAttribute, EmptyString());
}
}

View File

@ -1562,7 +1562,8 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
mTextListener->SetFrame(nullptr);
nsCOMPtr<EventTarget> target = do_QueryInterface(mTextCtrlElement);
nsEventListenerManager* manager = target->GetExistingListenerManager();
nsEventListenerManager* manager =
target->GetListenerManager(false);
if (manager) {
manager->RemoveEventListenerByType(mTextListener,
NS_LITERAL_STRING("keydown"),
@ -1969,7 +1970,7 @@ nsTextEditorState::InitializeKeyboardEventListeners()
{
//register key listeners
nsCOMPtr<EventTarget> target = do_QueryInterface(mTextCtrlElement);
nsEventListenerManager* manager = target->GetOrCreateListenerManager();
nsEventListenerManager* manager = target->GetListenerManager(true);
if (manager) {
manager->AddEventListenerByType(mTextListener,
NS_LITERAL_STRING("keydown"),

View File

@ -372,7 +372,7 @@ nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget)
if (!target)
return nullptr;
return target->GetOrCreateListenerManager();
return target->GetListenerManager(true);
}
void

View File

@ -664,7 +664,7 @@ nsSVGElement::UnsetAttrInternal(int32_t aNamespaceID, nsIAtom* aName,
mContentStyleRule = nullptr;
if (IsEventAttributeName(aName)) {
nsEventListenerManager* manager = GetExistingListenerManager();
nsEventListenerManager* manager = GetListenerManager(false);
if (manager) {
nsIAtom* eventName = GetEventNameForAttr(aName);
manager->RemoveEventHandler(eventName, EmptyString());

View File

@ -498,7 +498,8 @@ nsXBLBinding::InstallEventHandlers()
nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
if (handlerChain) {
nsEventListenerManager* manager = mBoundElement->GetOrCreateListenerManager();
nsEventListenerManager* manager =
mBoundElement->GetListenerManager(true);
if (!manager)
return;
@ -647,7 +648,7 @@ nsXBLBinding::UnhookEventHandlers()
if (handlerChain) {
nsEventListenerManager* manager =
mBoundElement->GetExistingListenerManager();
mBoundElement->GetListenerManager(false);
if (!manager) {
return;
}

View File

@ -561,7 +561,7 @@ nsXBLService::AttachGlobalKeyHandler(EventTarget* aTarget)
piTarget = doc; // We're a XUL keyset. Attach to our document.
}
nsEventListenerManager* manager = piTarget->GetOrCreateListenerManager();
nsEventListenerManager* manager = piTarget->GetListenerManager(true);
if (!piTarget || !manager)
return NS_ERROR_FAILURE;
@ -611,7 +611,7 @@ nsXBLService::DetachGlobalKeyHandler(EventTarget* aTarget)
if (doc)
piTarget = do_QueryInterface(doc);
nsEventListenerManager* manager = piTarget->GetOrCreateListenerManager();
nsEventListenerManager* manager = piTarget->GetListenerManager(true);
if (!piTarget || !manager)
return NS_ERROR_FAILURE;

View File

@ -496,7 +496,7 @@ nsXULElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer)
nsCOMPtr<EventTarget> piTarget = do_QueryInterface(window);
*aDefer = false;
return piTarget->GetOrCreateListenerManager();
return piTarget->GetListenerManager(true);
}
return nsStyledElement::GetEventListenerManagerForAttr(aAttrName, aDefer);
@ -1671,7 +1671,7 @@ nsXULElement::AddPopupListener(nsIAtom* aName)
new nsXULPopupListener(this, isContext);
// Add the popup as a listener on this element.
nsEventListenerManager* manager = GetOrCreateListenerManager();
nsEventListenerManager* manager = GetListenerManager(true);
SetFlags(listenerFlag);
if (isContext) {

View File

@ -141,6 +141,9 @@
// Drag and drop
#include "nsIDOMDataTransfer.h"
// Workers
#include "mozilla/dom/workers/Workers.h"
#include "nsIDOMFile.h"
#include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
@ -191,6 +194,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using mozilla::dom::workers::ResolveWorkerClasses;
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
@ -3601,6 +3605,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
// Handle resolving if id refers to a name resolved by DOM worker code.
JS::RootedObject tmp(cx, NULL);
if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) {
return NS_ERROR_FAILURE;
}
if (tmp) {
*objp = tmp;
return NS_OK;
}
// Check for names managed by the script namespace manager. Call
// GlobalResolve() after we call FindChildWithName() so that named child
// frames will override external properties which have been registered with

View File

@ -1570,7 +1570,8 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
if (tmp->mCachedXBLPrototypeHandlers) {
tmp->mCachedXBLPrototypeHandlers->Enumerate(MarkXBLHandlers, nullptr);
}
if (nsEventListenerManager* elm = tmp->GetExistingListenerManager()) {
nsEventListenerManager* elm = tmp->GetListenerManager(false);
if (elm) {
elm->MarkForCC();
}
tmp->UnmarkGrayTimers();
@ -8064,7 +8065,8 @@ nsGlobalWindow::RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture)
{
if (nsRefPtr<nsEventListenerManager> elm = GetExistingListenerManager()) {
nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
}
return NS_OK;
@ -8119,7 +8121,7 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
aWantsUntrusted = true;
}
nsEventListenerManager* manager = GetOrCreateListenerManager();
nsEventListenerManager* manager = GetListenerManager(true);
NS_ENSURE_STATE(manager);
manager->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
return NS_OK;
@ -8145,7 +8147,7 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
wantsUntrusted = aWantsUntrusted.Value();
}
nsEventListenerManager* manager = GetOrCreateListenerManager();
nsEventListenerManager* manager = GetListenerManager(true);
if (!manager) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
@ -8180,11 +8182,11 @@ nsGlobalWindow::AddSystemEventListener(const nsAString& aType,
}
nsEventListenerManager*
nsGlobalWindow::GetOrCreateListenerManager()
nsGlobalWindow::GetListenerManager(bool aCreateIfNotFound)
{
FORWARD_TO_INNER_CREATE(GetOrCreateListenerManager, (), nullptr);
FORWARD_TO_INNER_CREATE(GetListenerManager, (aCreateIfNotFound), nullptr);
if (!mListenerManager) {
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager =
new nsEventListenerManager(static_cast<EventTarget*>(this));
}
@ -8192,14 +8194,6 @@ nsGlobalWindow::GetOrCreateListenerManager()
return mListenerManager;
}
nsEventListenerManager*
nsGlobalWindow::GetExistingListenerManager() const
{
FORWARD_TO_INNER(GetExistingListenerManager, (), nullptr);
return mListenerManager;
}
nsIScriptContext*
nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
{
@ -11547,7 +11541,8 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
aWindowSizes->mDOMOther += aWindowSizes->mMallocSizeOf(this);
if (IsInnerWindow()) {
nsEventListenerManager* elm = GetExistingListenerManager();
nsEventListenerManager* elm =
const_cast<nsGlobalWindow*>(this)->GetListenerManager(false);
if (elm) {
aWindowSizes->mDOMOther +=
elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
@ -12088,7 +12083,7 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
#define ERROR_EVENT(name_, id_, type_, struct_) \
NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx, \
JS::Value *vp) { \
nsEventListenerManager *elm = GetExistingListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(false); \
if (elm) { \
OnErrorEventHandlerNonNull* h = elm->GetOnErrorEventHandler(); \
if (h) { \
@ -12101,7 +12096,7 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
} \
NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx, \
const JS::Value &v) { \
nsEventListenerManager *elm = GetOrCreateListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(true); \
if (!elm) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
@ -12118,7 +12113,7 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
#define BEFOREUNLOAD_EVENT(name_, id_, type_, struct_) \
NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx, \
JS::Value *vp) { \
nsEventListenerManager *elm = GetExistingListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(false); \
if (elm) { \
BeforeUnloadEventHandlerNonNull* h = \
elm->GetOnBeforeUnloadEventHandler(); \
@ -12132,7 +12127,7 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
} \
NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx, \
const JS::Value &v) { \
nsEventListenerManager *elm = GetOrCreateListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(true); \
if (!elm) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \

View File

@ -371,13 +371,6 @@ public:
// nsIDOMEventTarget
NS_DECL_NSIDOMEVENTTARGET
virtual nsEventListenerManager*
GetExistingListenerManager() const MOZ_OVERRIDE;
virtual nsEventListenerManager*
GetOrCreateListenerManager() MOZ_OVERRIDE;
using mozilla::dom::EventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
@ -559,7 +552,7 @@ public:
return static_cast<nsGlobalWindow *>(GetOuterWindow());
}
nsGlobalWindow *GetCurrentInnerWindowInternal() const
nsGlobalWindow *GetCurrentInnerWindowInternal()
{
return static_cast<nsGlobalWindow *>(mInnerWindow);
}
@ -715,13 +708,13 @@ public:
#define EVENT(name_, id_, type_, struct_) \
mozilla::dom::EventHandlerNonNull* GetOn##name_() \
{ \
nsEventListenerManager *elm = GetExistingListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(false); \
return elm ? elm->GetEventHandler(nsGkAtoms::on##name_, EmptyString()) \
: nullptr; \
} \
void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler) \
{ \
nsEventListenerManager *elm = GetOrCreateListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(true); \
if (elm) { \
elm->SetEventHandler(nsGkAtoms::on##name_, EmptyString(), handler); \
} \
@ -729,12 +722,12 @@ public:
#define ERROR_EVENT(name_, id_, type_, struct_) \
mozilla::dom::OnErrorEventHandlerNonNull* GetOn##name_() \
{ \
nsEventListenerManager *elm = GetExistingListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(false); \
return elm ? elm->GetOnErrorEventHandler() : nullptr; \
} \
void SetOn##name_(mozilla::dom::OnErrorEventHandlerNonNull* handler) \
{ \
nsEventListenerManager *elm = GetOrCreateListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(true); \
if (elm) { \
elm->SetEventHandler(handler); \
} \
@ -742,12 +735,12 @@ public:
#define BEFOREUNLOAD_EVENT(name_, id_, type_, struct_) \
mozilla::dom::BeforeUnloadEventHandlerNonNull* GetOn##name_() \
{ \
nsEventListenerManager *elm = GetExistingListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(false); \
return elm ? elm->GetOnBeforeUnloadEventHandler() : nullptr; \
} \
void SetOn##name_(mozilla::dom::BeforeUnloadEventHandlerNonNull* handler) \
{ \
nsEventListenerManager *elm = GetOrCreateListenerManager(); \
nsEventListenerManager *elm = GetListenerManager(true); \
if (elm) { \
elm->SetEventHandler(handler); \
} \

View File

@ -64,7 +64,8 @@ NS_IMPL_DOMTARGET_DEFAULTS(nsWindowRoot)
NS_IMETHODIMP
nsWindowRoot::RemoveEventListener(const nsAString& aType, nsIDOMEventListener* aListener, bool aUseCapture)
{
if (nsRefPtr<nsEventListenerManager> elm = GetExistingListenerManager()) {
nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
if (elm) {
elm->RemoveEventListener(aType, aListener, aUseCapture);
}
return NS_OK;
@ -104,7 +105,7 @@ nsWindowRoot::AddEventListener(const nsAString& aType,
"aWantsUntrusted to false or make the aWantsUntrusted "
"explicit by making optional_argc non-zero.");
nsEventListenerManager* elm = GetOrCreateListenerManager();
nsEventListenerManager* elm = GetListenerManager(true);
NS_ENSURE_STATE(elm);
elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
return NS_OK;
@ -118,7 +119,7 @@ nsWindowRoot::AddEventListener(const nsAString& aType,
ErrorResult& aRv)
{
bool wantsUntrusted = !aWantsUntrusted.IsNull() && aWantsUntrusted.Value();
nsEventListenerManager* elm = GetOrCreateListenerManager();
nsEventListenerManager* elm = GetListenerManager(true);
if (!elm) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
@ -144,9 +145,9 @@ nsWindowRoot::AddSystemEventListener(const nsAString& aType,
}
nsEventListenerManager*
nsWindowRoot::GetOrCreateListenerManager()
nsWindowRoot::GetListenerManager(bool aCreateIfNotFound)
{
if (!mListenerManager) {
if (!mListenerManager && aCreateIfNotFound) {
mListenerManager =
new nsEventListenerManager(static_cast<EventTarget*>(this));
}
@ -154,12 +155,6 @@ nsWindowRoot::GetOrCreateListenerManager()
return mListenerManager;
}
nsEventListenerManager*
nsWindowRoot::GetExistingListenerManager() const
{
return mListenerManager;
}
nsIScriptContext*
nsWindowRoot::GetContextForEventHandlers(nsresult* aRv)
{

View File

@ -28,12 +28,6 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMEVENTTARGET
virtual nsEventListenerManager*
GetExistingListenerManager() const MOZ_OVERRIDE;
virtual nsEventListenerManager*
GetOrCreateListenerManager() MOZ_OVERRIDE;
using mozilla::dom::EventTarget::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,

View File

@ -31,9 +31,6 @@
# true for workers, false otherwise).
# * customFinalize - The native class will use a custom finalize hook
# (defaults to true for workers, false otherwise).
# * customWrapperManagement - The native class will be responsible for
# preserving its own wrapper (no AddProperty
# hook will be generated, defaults to false).
# * notflattened - The native type does not have nsIClassInfo, so when
# wrapping it the right IID needs to be passed in.
# * register - True if this binding should be registered. Defaults to true.
@ -206,13 +203,6 @@ DOMInterfaces = {
'concrete': False
},
'ChromeWorker': {
'headerFile': 'mozilla/dom/WorkerPrivate.h',
'nativeType': 'mozilla::dom::workers::ChromeWorkerPrivate',
'customFinalize': True,
'customWrapperManagement': True,
},
'DOMRectList': {
'headerFile': 'mozilla/dom/DOMRect.h',
'resultNotAddRefed': [ 'item' ]
@ -1435,16 +1425,6 @@ DOMInterfaces = {
'workers': True
}],
'Worker': {
'headerFile': 'mozilla/dom/WorkerPrivate.h',
'nativeType': 'mozilla::dom::workers::WorkerPrivate',
'implicitJSContext': [
'terminate',
],
'customFinalize': True,
'customWrapperManagement': True,
},
'WorkerLocation': {
'headerFile': 'mozilla/dom/workers/bindings/Location.h',
'workers': True,
@ -1886,4 +1866,4 @@ addExternalIface('CameraReleaseCallback', nativeType='nsICameraReleaseCallback',
addExternalIface('CameraStartRecordingCallback', nativeType='nsICameraStartRecordingCallback', headerFile='nsIDOMCameraManager.h')
addExternalIface('CameraPreviewStateChange', nativeType='nsICameraPreviewStateChange', headerFile='nsIDOMCameraManager.h')
addExternalIface('CameraPreviewStreamCallback', nativeType='nsICameraPreviewStreamCallback', headerFile='nsIDOMCameraManager.h')
addExternalIface('CameraRecorderStateChange', nativeType='nsICameraRecorderStateChange', headerFile='nsIDOMCameraManager.h')
addExternalIface('CameraRecorderStateChange', nativeType='nsICameraRecorderStateChange', headerFile='nsIDOMCameraManager.h')

View File

@ -53,10 +53,6 @@ def toStringBool(arg):
def toBindingNamespace(arg):
return re.sub("((_workers)?$)", "Binding\\1", arg);
def wantsAddProperty(desc):
return desc.concrete and not desc.nativeOwnership == 'worker' and \
desc.wrapperCache and not desc.customWrapperManagement
class CGThing():
"""
Abstract base class for things that spit out code.
@ -213,7 +209,7 @@ static const DOMJSClass Class = {
};
""" % (self.descriptor.interface.identifier.name,
classFlags,
ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'JS_PropertyStub',
ADDPROPERTY_HOOK_NAME if self.descriptor.concrete and not self.descriptor.nativeOwnership == 'worker' and self.descriptor.wrapperCache else 'JS_PropertyStub',
enumerateHook, newResolveHook, FINALIZE_HOOK_NAME, callHook, traceHook,
CGIndenter(CGGeneric(DOMClass(self.descriptor))).define())
@ -701,16 +697,9 @@ class CGHeaders(CGWrapper):
if desc.interface.isExternal():
continue
def addHeaderForFunc(func):
if func is None:
return
# Include the right class header, which we can only do
# if this is a class member function.
if not desc.headerIsDefault:
# An explicit header file was provided, assume that we know
# what we're doing.
return
if "::" in func:
if func is not None and "::" in func:
# Strip out the function name and convert "::" to "/"
bindingHeaders.add("/".join(func.split("::")[:-1]) + ".h")
for m in desc.interface.members:
@ -8000,7 +7989,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGConstructNavigatorObject(descriptor))
if descriptor.concrete and not descriptor.proxy:
if wantsAddProperty(descriptor):
if not descriptor.nativeOwnership == 'worker' and descriptor.wrapperCache:
cgThings.append(CGAddPropertyHook(descriptor))
# Always have a finalize hook, regardless of whether the class

View File

@ -238,7 +238,6 @@ class Descriptor(DescriptorProvider):
headerDefault = self.nativeType
headerDefault = headerDefault.replace("::", "/") + ".h"
self.headerFile = desc.get('headerFile', headerDefault)
self.headerIsDefault = self.headerFile == headerDefault
if self.jsImplParent == self.nativeType:
self.jsImplParentHeader = self.headerFile
else:
@ -357,17 +356,12 @@ class Descriptor(DescriptorProvider):
(self.interface.identifier.name, self.nativeOwnership))
self.customTrace = desc.get('customTrace', self.nativeOwnership == 'worker')
self.customFinalize = desc.get('customFinalize', self.nativeOwnership == 'worker')
self.customWrapperManagement = desc.get('customWrapperManagement', False)
if desc.get('wantsQI', None) != None:
self._wantsQI = desc.get('wantsQI', None)
self.wrapperCache = (not self.interface.isCallback() and
(self.nativeOwnership == 'worker' or
(self.nativeOwnership != 'owned' and
desc.get('wrapperCache', True))))
if self.customWrapperManagement and not self.wrapperCache:
raise TypeError("Descriptor for %s has customWrapperManagement "
"but is not wrapperCached." %
(self.interface.identifier.name))
def make_name(name):
return name + "_workers" if self.workers else name

View File

@ -13,7 +13,6 @@
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/ErrorResult.h"
#include "nsCOMPtr.h"
#include "nsGenericHTMLElement.h"
#include "nsWrapperCache.h"
// Forward declare this before we include TestCodeGenBinding.h, because that header relies on including

View File

@ -157,11 +157,6 @@ public:
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMEVENTTARGET
virtual nsEventListenerManager*
GetExistingListenerManager() const MOZ_OVERRIDE;
virtual nsEventListenerManager*
GetOrCreateListenerManager() MOZ_OVERRIDE;
virtual void
AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,

View File

@ -3479,15 +3479,9 @@ nsDOMDeviceStorage::DispatchDOMEvent(WidgetEvent* aEvent,
}
nsEventListenerManager *
nsDOMDeviceStorage::GetOrCreateListenerManager()
nsDOMDeviceStorage::GetListenerManager(bool aMayCreate)
{
return nsDOMEventTargetHelper::GetOrCreateListenerManager();
}
nsEventListenerManager *
nsDOMDeviceStorage::GetExistingListenerManager() const
{
return nsDOMEventTargetHelper::GetExistingListenerManager();
return nsDOMEventTargetHelper::GetListenerManager(aMayCreate);
}
nsIScriptContext *

View File

@ -45,7 +45,7 @@ interface nsIScriptContext;
interface nsIDOMEventListener;
interface nsIDOMEvent;
[scriptable, builtinclass, uuid(b128448c-7b53-4769-92cb-cd6eafee676c)]
[scriptable, builtinclass, uuid(31e92e56-4d23-4a4a-9cfe-a6d12cf434bc)]
interface nsIDOMEventTarget : nsISupports
{
/**
@ -267,6 +267,15 @@ interface nsIDOMEventTarget : nsISupports
in nsPresContextPtr aPresContext,
in nsEventStatusPtr aEventStatus);
/**
* Get the event listener manager, the guy you talk to to register for events
* on this node.
* @param aMayCreate If PR_FALSE, returns a listener manager only if
* one already exists.
*/
[notxpcom, nostdcall]
nsEventListenerManagerPtr GetListenerManager(in boolean aMayCreate);
/**
* Get the script context in which the event handlers should be run.
* May return null.
@ -296,7 +305,7 @@ aClass::RemoveSystemEventListener(const nsAString& aType, \
nsIDOMEventListener *aListener, \
bool aUseCapture) \
{ \
nsEventListenerManager* listenerManager = GetExistingListenerManager(); \
nsEventListenerManager* listenerManager = GetListenerManager(false); \
if (!listenerManager) { \
return NS_OK; \
} \

View File

@ -1202,7 +1202,7 @@ TabChild::~TabChild()
mGlobal = nullptr;
if (mTabChildGlobal) {
nsEventListenerManager* elm = mTabChildGlobal->GetExistingListenerManager();
nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(false);
if (elm) {
elm->Disconnect();
}

View File

@ -579,7 +579,6 @@ var interfaceNamesInGlobalScope =
"WheelEvent",
"Window",
"WindowUtils",
"Worker",
"XMLDocument",
"XMLHttpRequest",
"XMLHttpRequestUpload",

View File

@ -1,31 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html
*
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera
* Software ASA.
* You are granted a license to use, reproduce and create derivative works of
* this document.
*/
[Constructor(DOMString scriptURL),
Func="mozilla::dom::workers::WorkerPrivate::WorkerAvailable"]
interface Worker : EventTarget {
void terminate();
[Throws]
void postMessage(any message, optional sequence<any> transfer);
attribute EventHandler onmessage;
};
Worker implements AbstractWorker;
[Constructor(DOMString scriptURL),
Func="mozilla::dom::workers::ChromeWorkerPrivate::WorkerAvailable"]
interface ChromeWorker : Worker {
};

View File

@ -410,7 +410,6 @@ WEBIDL_FILES = [
'WheelEvent.webidl',
'WifiOptions.webidl',
'Window.webidl',
'Worker.webidl',
'WorkerLocation.webidl',
'WorkerMessagePort.webidl',
'WorkerNavigator.webidl',

View File

@ -28,10 +28,7 @@
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/dom/AtomList.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ErrorEventBinding.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/WorkerBinding.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Preferences.h"
#include "mozilla/Util.h"
@ -51,6 +48,7 @@
#include "Events.h"
#include "SharedWorker.h"
#include "Worker.h"
#include "WorkerPrivate.h"
#ifdef MOZ_NUWA_PROCESS
@ -96,6 +94,7 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define MAX_IDLE_THREADS 20
#define PREF_WORKERS_PREFIX "dom.workers."
#define PREF_WORKERS_ENABLED PREF_WORKERS_PREFIX "enabled"
#define PREF_WORKERS_MAX_PER_DOMAIN PREF_WORKERS_PREFIX "maxPerDomain"
#define PREF_MAX_SCRIPT_RUN_TIME_CONTENT "dom.max_script_run_time"
@ -162,9 +161,9 @@ jsid gStringIDs[ID_COUNT] = { JSID_VOID };
const char* gStringChars[] = {
"Worker",
"ChromeWorker",
"Event",
"MessageEvent",
"ErrorEvent"
"WorkerEvent",
"WorkerMessageEvent",
"WorkerErrorEvent"
// XXX Don't care about ProgressEvent since it should never leak to the main
// thread.
@ -967,13 +966,12 @@ public:
BEGIN_WORKERS_NAMESPACE
// Entry point for main thread non-window globals.
// Entry point for the DOM.
bool
ResolveWorkerClasses(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId,
unsigned aFlags, JS::MutableHandle<JSObject*> aObjp)
{
AssertIsOnMainThread();
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
// Make sure our strings are interned.
if (JSID_IS_VOID(gStringIDs[0])) {
@ -989,28 +987,51 @@ ResolveWorkerClasses(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid
}
}
bool isChrome = false;
bool shouldResolve = false;
for (uint32_t i = 0; i < ID_COUNT; i++) {
if (gStringIDs[i] == aId) {
shouldResolve = true;
isChrome = nsContentUtils::IsCallerChrome();
// Don't resolve if this is ChromeWorker and we're not chrome. Otherwise
// always resolve.
shouldResolve = gStringIDs[ID_ChromeWorker] == aId ? isChrome : true;
break;
}
}
if (!shouldResolve) {
aObjp.set(nullptr);
if (shouldResolve) {
// Don't do anything if workers are disabled.
if (!isChrome && !Preferences::GetBool(PREF_WORKERS_ENABLED)) {
aObjp.set(nullptr);
return true;
}
JSObject* eventTarget = EventTargetBinding_workers::GetProtoObject(aCx, aObj);
if (!eventTarget) {
return false;
}
JSObject* worker = worker::InitClass(aCx, aObj, eventTarget, true);
if (!worker) {
return false;
}
if (isChrome && !chromeworker::InitClass(aCx, aObj, worker, true)) {
return false;
}
if (!events::InitClasses(aCx, aObj, true)) {
return false;
}
aObjp.set(aObj);
return true;
}
if (!WorkerBinding::GetConstructorObject(aCx, aObj) ||
!ChromeWorkerBinding::GetConstructorObject(aCx, aObj) ||
!ErrorEventBinding::GetConstructorObject(aCx, aObj) ||
!MessageEventBinding::GetConstructorObject(aCx, aObj)) {
return false;
}
aObjp.set(aObj);
// Not resolved.
aObjp.set(nullptr);
return true;
}
@ -1973,20 +1994,17 @@ RuntimeService::ResumeWorkersForWindow(nsPIDOMWindow* aWindow)
}
nsresult
RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
RuntimeService::CreateSharedWorker(JSContext* aCx, nsPIDOMWindow* aWindow,
const nsAString& aScriptURL,
const nsAString& aName,
SharedWorker** aSharedWorker)
{
AssertIsOnMainThread();
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
JSContext* cx = aGlobal.GetContext();
MOZ_ASSERT(aCx);
MOZ_ASSERT(aWindow);
WorkerPrivate::LoadInfo loadInfo;
nsresult rv = WorkerPrivate::GetLoadInfo(cx, window, nullptr, aScriptURL,
nsresult rv = WorkerPrivate::GetLoadInfo(aCx, aWindow, nullptr, aScriptURL,
false, &loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
@ -1996,7 +2014,7 @@ RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
rv = loadInfo.mResolvedScriptURI->GetSpec(scriptSpec);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<WorkerPrivate> workerPrivate;
WorkerPrivate* workerPrivate = nullptr;
{
MutexAutoLock lock(mMutex);
@ -2013,21 +2031,26 @@ RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
bool created = false;
if (!workerPrivate) {
ErrorResult rv;
workerPrivate =
WorkerPrivate::Constructor(aGlobal, aScriptURL, false, true, aName,
&loadInfo, rv);
NS_ENSURE_TRUE(workerPrivate, rv.ErrorCode());
nsRefPtr<WorkerPrivate> newWorkerPrivate =
WorkerPrivate::Create(aCx, JS::NullPtr(), nullptr, aScriptURL, false,
true, aName, &loadInfo);
NS_ENSURE_TRUE(newWorkerPrivate, NS_ERROR_FAILURE);
if (!RegisterWorker(aCx, newWorkerPrivate)) {
NS_WARNING("Failed to register worker!");
return NS_ERROR_FAILURE;
}
created = true;
newWorkerPrivate.forget(&workerPrivate);
}
MOZ_ASSERT(workerPrivate->IsSharedWorker());
nsRefPtr<SharedWorker> sharedWorker =
new SharedWorker(window, workerPrivate);
new SharedWorker(aWindow, workerPrivate);
if (!workerPrivate->RegisterSharedWorker(cx, sharedWorker)) {
if (!workerPrivate->RegisterSharedWorker(aCx, sharedWorker)) {
NS_WARNING("Worker is unreachable, this shouldn't happen!");
sharedWorker->Close();
return NS_ERROR_FAILURE;
@ -2037,9 +2060,9 @@ RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
// worker already existed.
if (!created) {
nsTArray<WorkerPrivate*>* windowArray;
if (!mWindowMap.Get(window, &windowArray)) {
if (!mWindowMap.Get(aWindow, &windowArray)) {
windowArray = new nsTArray<WorkerPrivate*>(1);
mWindowMap.Put(window, windowArray);
mWindowMap.Put(aWindow, windowArray);
}
if (!windowArray->Contains(workerPrivate)) {

View File

@ -145,9 +145,8 @@ public:
ResumeWorkersForWindow(nsPIDOMWindow* aWindow);
nsresult
CreateSharedWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsAString& aName,
CreateSharedWorker(JSContext* aCx, nsPIDOMWindow* aWindow,
const nsAString& aScriptURL, const nsAString& aName,
SharedWorker** aSharedWorker);
void

View File

@ -16,6 +16,7 @@
#include "MessagePort.h"
#include "RuntimeService.h"
#include "Worker.h"
#include "WorkerPrivate.h"
using mozilla::dom::Optional;
@ -66,6 +67,9 @@ SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
{
AssertIsOnMainThread();
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
RuntimeService* rts = RuntimeService::GetOrCreateService();
if (!rts) {
aRv = NS_ERROR_NOT_AVAILABLE;
@ -78,7 +82,7 @@ SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
}
nsRefPtr<SharedWorker> sharedWorker;
nsresult rv = rts->CreateSharedWorker(aGlobal, aScriptURL, name,
nsresult rv = rts->CreateSharedWorker(aCx, window, aScriptURL, name,
getter_AddRefs(sharedWorker));
if (NS_FAILED(rv)) {
aRv = rv;

View File

@ -28,7 +28,7 @@ class SharedWorker MOZ_FINAL : public nsDOMEventTargetHelper
typedef mozilla::ErrorResult ErrorResult;
typedef mozilla::dom::GlobalObject GlobalObject;
nsRefPtr<WorkerPrivate> mWorkerPrivate;
WorkerPrivate* mWorkerPrivate;
nsRefPtr<MessagePort> mMessagePort;
nsTArray<nsCOMPtr<nsIDOMEvent>> mSuspendedEvents;
uint64_t mSerial;
@ -83,8 +83,7 @@ public:
private:
// This class can only be created from the RuntimeService.
SharedWorker(nsPIDOMWindow* aWindow,
WorkerPrivate* aWorkerPrivate);
SharedWorker(nsPIDOMWindow* aWindow, WorkerPrivate* aWorkerPrivate);
// This class is reference-counted and will be destroyed from Release().
~SharedWorker();

672
dom/workers/Worker.cpp Normal file
View File

@ -0,0 +1,672 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* 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 "Worker.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/EventHandlerBinding.h"
#include "nsJSUtils.h"
#include "jsapi.h"
#include "EventTarget.h"
#include "RuntimeService.h"
#include "WorkerPrivate.h"
#include "WorkerInlines.h"
#define FUNCTION_FLAGS \
JSPROP_ENUMERATE
USING_WORKERS_NAMESPACE
using namespace mozilla::dom;
using mozilla::ErrorResult;
namespace {
class Worker
{
static const DOMJSClass sClass;
static const DOMIfaceAndProtoJSClass sProtoClass;
static const JSPropertySpec sProperties[];
static const JSFunctionSpec sFunctions[];
protected:
enum {
// The constructor function holds a WorkerPrivate* in its first reserved
// slot.
CONSTRUCTOR_SLOT_PARENT = 0
};
public:
static const JSClass*
Class()
{
return sClass.ToJSClass();
}
static const JSClass*
ProtoClass()
{
return sProtoClass.ToJSClass();
}
static const DOMClass*
DOMClassStruct()
{
return &sClass.mClass;
}
static JSObject*
InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
bool aMainRuntime)
{
JS::Rooted<JSObject*> proto(aCx,
js::InitClassWithReserved(aCx, aObj, aParentProto, ProtoClass(),
Construct, 0, sProperties, sFunctions,
NULL, NULL));
if (!proto) {
return NULL;
}
js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
JS::PrivateValue(const_cast<DOMClass *>(DOMClassStruct())));
if (!aMainRuntime) {
WorkerPrivate* parent = GetWorkerPrivateFromContext(aCx);
parent->AssertIsOnWorkerThread();
JSObject* constructor = JS_GetConstructor(aCx, proto);
if (!constructor)
return NULL;
js::SetFunctionNativeReserved(constructor, CONSTRUCTOR_SLOT_PARENT,
PRIVATE_TO_JSVAL(parent));
}
return proto;
}
static WorkerPrivate*
GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName);
static JSObject*
Create(JSContext* aCx, WorkerPrivate* aParentObj, const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName);
protected:
static bool
ConstructInternal(JSContext* aCx, JS::CallArgs aArgs, bool aIsChromeWorker)
{
if (!aArgs.length()) {
JS_ReportError(aCx, "Constructor requires at least one argument!");
return false;
}
JS::RootedString scriptURLStr(aCx, JS_ValueToString(aCx, aArgs[0]));
if (!scriptURLStr) {
return false;
}
nsDependentJSString scriptURL;
if (!scriptURL.init(aCx, scriptURLStr)) {
return false;
}
JS::Rooted<JS::Value> priv(aCx,
js::GetFunctionNativeReserved(&aArgs.callee(), CONSTRUCTOR_SLOT_PARENT));
WorkerPrivate* parent;
if (priv.isUndefined()) {
parent = NULL;
} else {
parent = static_cast<WorkerPrivate*>(priv.get().toPrivate());
parent->AssertIsOnWorkerThread();
}
JS::Rooted<JSObject*> obj(aCx,
Create(aCx, parent, scriptURL, aIsChromeWorker, false, EmptyString()));
if (!obj) {
return false;
}
aArgs.rval().setObject(*obj);
return true;
}
private:
// No instance of this class should ever be created so these are explicitly
// left without an implementation to prevent linking in case someone tries to
// make one.
Worker();
~Worker();
static bool
IsWorker(JS::Handle<JS::Value> v)
{
return v.isObject() && ClassIsWorker(JS_GetClass(&v.toObject()));
}
static bool
GetEventListener(JSContext* aCx, const JS::CallArgs aArgs,
const nsAString &aNameStr)
{
WorkerPrivate* worker =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(),
NS_ConvertUTF16toUTF8(aNameStr).get());
MOZ_ASSERT(worker);
ErrorResult rv;
nsRefPtr<EventHandlerNonNull> handler =
worker->GetEventListener(Substring(aNameStr, 2), rv);
if (rv.Failed()) {
JS_ReportError(aCx, "Failed to get listener!");
return false;
}
if (!handler) {
aArgs.rval().setNull();
} else {
aArgs.rval().setObject(*handler->Callable());
}
return true;
}
static bool
GetOnerrorImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return GetEventListener(aCx, aArgs, NS_LITERAL_STRING("onerror"));
}
static bool
GetOnerror(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, GetOnerrorImpl>(aCx, args);
}
static bool
GetOnmessageImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return GetEventListener(aCx, aArgs, NS_LITERAL_STRING("onmessage"));
}
static bool
GetOnmessage(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, GetOnmessageImpl>(aCx, args);
}
static bool
SetEventListener(JSContext* aCx, JS::CallArgs aArgs,
const nsAString& aNameStr)
{
WorkerPrivate* worker =
GetInstancePrivate(aCx, &aArgs.thisv().toObject(),
NS_ConvertUTF16toUTF8(aNameStr).get());
MOZ_ASSERT(worker);
JS::Rooted<JSObject*> listener(aCx);
if (!JS_ValueToObject(aCx, aArgs.get(0), &listener)) {
return false;
}
nsRefPtr<EventHandlerNonNull> handler;
if (listener && JS_ObjectIsCallable(aCx, listener)) {
handler = new EventHandlerNonNull(listener);
} else {
handler = nullptr;
}
ErrorResult rv;
worker->SetEventListener(Substring(aNameStr, 2), handler, rv);
if (rv.Failed()) {
JS_ReportError(aCx, "Failed to set listener!");
return false;
}
aArgs.rval().setUndefined();
return true;
}
static bool
SetOnerrorImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return SetEventListener(aCx, aArgs, NS_LITERAL_STRING("onerror"));
}
static bool
SetOnerror(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, SetOnerrorImpl>(aCx, args);
}
static bool
SetOnmessageImpl(JSContext* aCx, JS::CallArgs aArgs)
{
return SetEventListener(aCx, aArgs, NS_LITERAL_STRING("onmessage"));
}
static bool
SetOnmessage(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return JS::CallNonGenericMethod<IsWorker, SetOnmessageImpl>(aCx, args);
}
static bool
Construct(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return ConstructInternal(aCx, args, false);
}
static void
Finalize(JSFreeOp* aFop, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_finalize(aFop);
}
}
static void
Trace(JSTracer* aTrc, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_trace(aTrc);
}
}
static bool
Terminate(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
if (!obj) {
return false;
}
const char* name = sFunctions[0].name;
WorkerPrivate* worker = GetInstancePrivate(aCx, obj, name);
if (!worker) {
return !JS_IsExceptionPending(aCx);
}
if (!worker->Terminate(aCx)) {
return false;
}
JS_RVAL(aCx, aVp).setUndefined();
return true;
}
static bool
PostMessage(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
if (!obj) {
return false;
}
const char* name = sFunctions[1].name;
WorkerPrivate* worker = GetInstancePrivate(aCx, obj, name);
if (!worker) {
return !JS_IsExceptionPending(aCx);
}
JS::Rooted<JS::Value> message(aCx);
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/v",
message.address(), transferable.address())) {
return false;
}
if (!worker->PostMessage(aCx, message, transferable)) {
return false;
}
JS_RVAL(aCx, aVp).setUndefined();
return true;
}
};
const DOMJSClass Worker::sClass = {
{
"Worker",
JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(3) |
JSCLASS_IMPLEMENTS_BARRIERS,
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
NULL, NULL, NULL, NULL, Trace
},
{
INTERFACE_CHAIN_1(prototypes::id::EventTarget_workers),
false,
&sWorkerNativePropertyHooks
}
};
const DOMIfaceAndProtoJSClass Worker::sProtoClass = {
{
// XXXbz we use "Worker" here to match sClass so that we can
// js::InitClassWithReserved this JSClass and then call
// JS_NewObject with our sClass and have it find the right
// prototype.
"Worker",
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
nullptr, /* finalize */
nullptr, /* checkAccess */
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
nullptr, /* trace */
JSCLASS_NO_INTERNAL_MEMBERS
},
eInterfacePrototype,
&sWorkerNativePropertyHooks,
"[object Worker]",
prototypes::id::_ID_Count,
0
};
const JSPropertySpec Worker::sProperties[] = {
JS_PSGS("onerror", GetOnerror, SetOnerror, JSPROP_ENUMERATE),
JS_PSGS("onmessage", GetOnmessage, SetOnmessage, JSPROP_ENUMERATE),
JS_PS_END
};
const JSFunctionSpec Worker::sFunctions[] = {
JS_FN("terminate", Terminate, 0, FUNCTION_FLAGS),
JS_FN("postMessage", PostMessage, 1, FUNCTION_FLAGS),
JS_FS_END
};
class ChromeWorker : public Worker
{
static const DOMJSClass sClass;
static const DOMIfaceAndProtoJSClass sProtoClass;
public:
static const JSClass*
Class()
{
return sClass.ToJSClass();
}
static const JSClass*
ProtoClass()
{
return sProtoClass.ToJSClass();
}
static const DOMClass*
DOMClassStruct()
{
return &sClass.mClass;
}
static JSObject*
InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
bool aMainRuntime)
{
JS::Rooted<JSObject*> proto(aCx,
js::InitClassWithReserved(aCx, aObj, aParentProto, ProtoClass(),
Construct, 0, NULL, NULL, NULL, NULL));
if (!proto) {
return NULL;
}
js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
JS::PrivateValue(const_cast<DOMClass *>(DOMClassStruct())));
if (!aMainRuntime) {
WorkerPrivate* parent = GetWorkerPrivateFromContext(aCx);
parent->AssertIsOnWorkerThread();
JSObject* constructor = JS_GetConstructor(aCx, proto);
if (!constructor)
return NULL;
js::SetFunctionNativeReserved(constructor, CONSTRUCTOR_SLOT_PARENT,
PRIVATE_TO_JSVAL(parent));
}
return proto;
}
private:
// No instance of this class should ever be created so these are explicitly
// left without an implementation to prevent linking in case someone tries to
// make one.
ChromeWorker();
~ChromeWorker();
static WorkerPrivate*
GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
{
if (aObj) {
const JSClass* classPtr = JS_GetClass(aObj);
if (classPtr == Class()) {
return UnwrapDOMObject<WorkerPrivate>(aObj);
}
}
return Worker::GetInstancePrivate(aCx, aObj, aFunctionName);
}
static bool
Construct(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
return ConstructInternal(aCx, args, true);
}
static void
Finalize(JSFreeOp* aFop, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_finalize(aFop);
}
}
static void
Trace(JSTracer* aTrc, JSObject* aObj)
{
JS_ASSERT(JS_GetClass(aObj) == Class());
WorkerPrivate* worker = UnwrapDOMObject<WorkerPrivate>(aObj);
if (worker) {
worker->_trace(aTrc);
}
}
};
const DOMJSClass ChromeWorker::sClass = {
{ "ChromeWorker",
JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(3) |
JSCLASS_IMPLEMENTS_BARRIERS,
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
NULL, NULL, NULL, NULL, Trace,
},
{
INTERFACE_CHAIN_1(prototypes::id::EventTarget_workers),
false,
&sWorkerNativePropertyHooks
}
};
const DOMIfaceAndProtoJSClass ChromeWorker::sProtoClass = {
{
// XXXbz we use "ChromeWorker" here to match sClass so that we can
// js::InitClassWithReserved this JSClass and then call
// JS_NewObject with our sClass and have it find the right
// prototype.
"ChromeWorker",
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
nullptr, /* finalize */
nullptr, /* checkAccess */
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
nullptr, /* trace */
JSCLASS_NO_INTERNAL_MEMBERS
},
eInterfacePrototype,
&sWorkerNativePropertyHooks,
"[object ChromeWorker]",
prototypes::id::_ID_Count,
0
};
WorkerPrivate*
Worker::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
const char* aFunctionName)
{
const JSClass* classPtr = JS_GetClass(aObj);
if (ClassIsWorker(classPtr)) {
return UnwrapDOMObject<WorkerPrivate>(aObj);
}
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
Class()->name, aFunctionName, classPtr->name);
return NULL;
}
JSObject*
Worker::Create(JSContext* aCx, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
bool aIsSharedWorker, const nsAString& aSharedWorkerName)
{
MOZ_ASSERT_IF(aIsSharedWorker, !aSharedWorkerName.IsVoid());
MOZ_ASSERT_IF(!aIsSharedWorker, aSharedWorkerName.IsEmpty());
RuntimeService* runtimeService;
if (aParent) {
runtimeService = RuntimeService::GetService();
NS_ASSERTION(runtimeService, "Null runtime service!");
}
else {
runtimeService = RuntimeService::GetOrCreateService();
if (!runtimeService) {
JS_ReportError(aCx, "Failed to create runtime service!");
return nullptr;
}
}
const JSClass* classPtr = aIsChromeWorker ? ChromeWorker::Class() : Class();
JS::Rooted<JSObject*> obj(aCx,
JS_NewObject(aCx, const_cast<JSClass*>(classPtr), nullptr, nullptr));
if (!obj) {
return nullptr;
}
// Ensure that the DOM_OBJECT_SLOT always has a PrivateValue set, as this will
// be accessed in the Trace() method if WorkerPrivate::Create() triggers a GC.
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
nsRefPtr<WorkerPrivate> worker =
WorkerPrivate::Create(aCx, obj, aParent, aScriptURL, aIsChromeWorker,
aIsSharedWorker, aSharedWorkerName);
if (!worker) {
// It'd be better if we could avoid allocating the JSObject until after we
// make sure we have a WorkerPrivate, but failing that we should at least
// make sure that the DOM_OBJECT_SLOT always has a PrivateValue.
return nullptr;
}
// Worker now owned by the JS object.
NS_ADDREF(worker.get());
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::PrivateValue(worker));
if (!runtimeService->RegisterWorker(aCx, worker)) {
return nullptr;
}
// Worker now also owned by its thread.
NS_ADDREF(worker.get());
return obj;
}
} // anonymous namespace
BEGIN_WORKERS_NAMESPACE
namespace worker {
JSObject*
InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto,
bool aMainRuntime)
{
return Worker::InitClass(aCx, aGlobal, aProto, aMainRuntime);
}
} // namespace worker
WorkerCrossThreadDispatcher*
GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker)
{
if (JSVAL_IS_PRIMITIVE(aWorker)) {
return NULL;
}
WorkerPrivate* w =
Worker::GetInstancePrivate(aCx, JSVAL_TO_OBJECT(aWorker),
"GetWorkerCrossThreadDispatcher");
if (!w) {
return NULL;
}
return w->GetCrossThreadDispatcher();
}
namespace chromeworker {
bool
InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto,
bool aMainRuntime)
{
return !!ChromeWorker::InitClass(aCx, aGlobal, aProto, aMainRuntime);
}
} // namespace chromeworker
bool
ClassIsWorker(const JSClass* aClass)
{
return Worker::Class() == aClass || ChromeWorker::Class() == aClass;
}
bool
GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr, JSMSG_GETTER_ONLY);
return false;
}
END_WORKERS_NAMESPACE

35
dom/workers/Worker.h Normal file
View File

@ -0,0 +1,35 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* 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 mozilla_dom_workers_worker_h__
#define mozilla_dom_workers_worker_h__
#include "Workers.h"
BEGIN_WORKERS_NAMESPACE
namespace worker {
JSObject*
InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto,
bool aMainRuntime);
} // namespace worker
namespace chromeworker {
bool
InitClass(JSContext* aCx, JSObject* aGlobal, JSObject* aProto,
bool aMainRuntime);
} // namespace chromeworker
bool
ClassIsWorker(const JSClass* aClass);
END_WORKERS_NAMESPACE
#endif /* mozilla_dom_workers_worker_h__ */

View File

@ -13,7 +13,6 @@
#include "nsIDOMDOMException.h"
#include "nsIDOMEvent.h"
#include "nsIDOMFile.h"
#include "nsIDOMMessageEvent.h"
#include "nsIDocument.h"
#include "nsIDocShell.h"
#include "nsIMemoryReporter.h"
@ -36,17 +35,13 @@
#include "mozilla/Likely.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ErrorEvent.h"
#include "mozilla/dom/ErrorEventBinding.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/ImageDataBinding.h"
#include "mozilla/dom/WorkerBinding.h"
#include "mozilla/Preferences.h"
#include "mozilla/Util.h"
#include "nsAlgorithm.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsError.h"
#include "nsEventDispatcher.h"
#include "nsDOMMessageEvent.h"
#include "nsDOMJSUtils.h"
#include "nsHostObjectProtocolHandler.h"
@ -71,6 +66,7 @@
#include "RuntimeService.h"
#include "ScriptLoader.h"
#include "SharedWorker.h"
#include "Worker.h"
#include "WorkerFeature.h"
#include "WorkerMessagePort.h"
#include "WorkerScope.h"
@ -81,8 +77,6 @@
// GC will run five seconds after the last event is processed.
#define IDLE_GC_TIMER_DELAY_MS 5000
#define PREF_WORKERS_ENABLED "dom.workers.enabled"
using mozilla::InternalScriptErrorEvent;
using mozilla::MutexAutoLock;
using mozilla::TimeDuration;
@ -894,6 +888,8 @@ public:
{
MOZ_ASSERT_IF(mToMessagePort, aWorkerPrivate->IsSharedWorker());
bool mainRuntime;
JS::Rooted<JSObject*> target(aCx);
if (mTarget == ParentThread) {
// Don't fire this event if the JS object has been disconnected from the
// private object.
@ -909,65 +905,39 @@ public:
mClonedObjects);
}
mainRuntime = !aWorkerPrivate->GetParent();
target = aWorkerPrivate->GetJSObject();
NS_ASSERTION(target, "Must have a target!");
if (aWorkerPrivate->IsSuspended()) {
aWorkerPrivate->QueueRunnable(this);
return true;
}
aWorkerPrivate->AssertInnerWindowIsCorrect();
// Release reference to objects that were AddRef'd for
// cloning into worker when array goes out of scope.
nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
clonedObjects.SwapElements(mClonedObjects);
JS::Rooted<JS::Value> messageData(aCx);
if (!mBuffer.read(aCx, messageData.address(),
workers::WorkerStructuredCloneCallbacks(!aWorkerPrivate->GetParent()))) {
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return false;
}
else {
NS_ASSERTION(aWorkerPrivate == GetWorkerPrivateFromContext(aCx),
"Badness!");
if (mToMessagePort) {
WorkerMessagePort* port =
aWorkerPrivate->GetMessagePort(mMessagePortSerial);
if (!port) {
// Must have been closed already.
return true;
}
return port->MaybeDispatchEvent(aCx, mBuffer, mClonedObjects);
}
nsRefPtr<nsDOMMessageEvent> event =
new nsDOMMessageEvent(aWorkerPrivate, nullptr, nullptr);
nsresult rv =
event->InitMessageEvent(NS_LITERAL_STRING("message"),
false /* non-bubbling */,
true /* cancelable */,
messageData,
EmptyString(),
EmptyString(),
nullptr);
if (NS_FAILED(rv)) {
xpc::Throw(aCx, rv);
return false;
}
event->SetTrusted(true);
nsCOMPtr<nsIDOMEvent> domEvent = do_QueryObject(event);
nsEventStatus dummy = nsEventStatus_eIgnore;
aWorkerPrivate->DispatchDOMEvent(nullptr, domEvent, nullptr, &dummy);
return true;
mainRuntime = false;
target = JS::CurrentGlobalOrNull(aCx);
}
MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
if (mToMessagePort) {
nsRefPtr<WorkerMessagePort> port =
aWorkerPrivate->GetMessagePort(mMessagePortSerial);
if (!port) {
// Must have been closed already.
return true;
}
return port->MaybeDispatchEvent(aCx, mBuffer, mClonedObjects);
}
JS::Rooted<JSObject*> target(aCx, JS::CurrentGlobalOrNull(aCx));
NS_ASSERTION(target, "This should never be null!");
JS::Rooted<JSObject*> event(aCx,
CreateMessageEvent(aCx, mBuffer, mClonedObjects, false));
CreateMessageEvent(aCx, mBuffer, mClonedObjects, mainRuntime));
if (!event) {
return false;
}
@ -1008,17 +978,6 @@ public:
{
return aWorkerPrivate->NotifyInternal(aCx, mStatus);
}
void
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aDispatchResult)
{
if (!aDispatchResult) {
// We couldn't dispatch to the worker, which means it's already dead.
// Undo the busy count modification.
aWorkerPrivate->ModifyBusyCount(aCx, false);
}
}
};
class CloseRunnable MOZ_FINAL : public WorkerControlRunnable
@ -1106,7 +1065,7 @@ public:
return true;
}
JS::Rooted<JSObject*> target(aCx, aWorkerPrivate->GetWrapper());
JS::Rooted<JSObject*> target(aCx, aWorkerPrivate->GetJSObject());
uint64_t innerWindowId;
bool fireAtScope = true;
@ -1135,10 +1094,9 @@ public:
innerWindowId = aWorkerPrivate->GetInnerWindowId();
}
return ReportErrorRunnable::ReportError(aCx, parent, fireAtScope,
aWorkerPrivate, mMessage,
mFilename, mLine, mLineNumber,
mColumnNumber, mFlags,
return ReportErrorRunnable::ReportError(aCx, parent, fireAtScope, target,
mMessage, mFilename, mLine,
mLineNumber, mColumnNumber, mFlags,
mErrorNumber, innerWindowId);
}
@ -1147,17 +1105,14 @@ public:
WorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
}
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
// aTarget is the worker object that we are going to fire an error at
// (if any).
static bool
ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aFireAtScope, WorkerPrivate* aTarget,
const nsString& aMessage, const nsString& aFilename,
const nsString& aLine, uint32_t aLineNumber,
uint32_t aColumnNumber, uint32_t aFlags,
bool aFireAtScope, JSObject* aTarget, const nsString& aMessage,
const nsString& aFilename, const nsString& aLine,
uint32_t aLineNumber, uint32_t aColumnNumber, uint32_t aFlags,
uint32_t aErrorNumber, uint64_t aInnerWindowId)
{
JS::Rooted<JSObject*> target(aCx, aTarget);
if (aWorkerPrivate) {
aWorkerPrivate->AssertIsOnWorkerThread();
}
@ -1181,28 +1136,27 @@ public:
// they show up in the error console.
if (!JSREPORT_IS_WARNING(aFlags)) {
// First fire an ErrorEvent at the worker.
if (aTarget) {
ErrorEventInit init;
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
init.mCancelable = true;
if (target) {
JS::Rooted<JSObject*> event(aCx,
CreateErrorEvent(aCx, message, filename, aLineNumber, !aWorkerPrivate));
if (!event) {
return false;
}
nsRefPtr<ErrorEvent> event =
ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
bool preventDefaultCalled;
if (!DispatchEventToTarget(aCx, target, event, &preventDefaultCalled)) {
return false;
}
nsEventStatus status = nsEventStatus_eIgnore;
aTarget->DispatchDOMEvent(nullptr, event, nullptr, &status);
if (status == nsEventStatus_eConsumeNoDefault) {
if (preventDefaultCalled) {
return true;
}
}
// Now fire an event at the global object, but don't do that if the error
// code is too much recursion and this is the same script threw the error.
if (aFireAtScope && (aTarget || aErrorNumber != JSMSG_OVER_RECURSED)) {
JS::Rooted<JSObject*> target(aCx, JS::CurrentGlobalOrNull(aCx));
if (aFireAtScope && (target || aErrorNumber != JSMSG_OVER_RECURSED)) {
target = JS::CurrentGlobalOrNull(aCx);
NS_ASSERTION(target, "This should never be null!");
bool preventDefaultCalled;
@ -1800,7 +1754,7 @@ WorkerRunnable::Run()
if (mTarget == WorkerThread) {
targetCompartmentObject = JS::CurrentGlobalOrNull(cx);
} else {
targetCompartmentObject = mWorkerPrivate->GetWrapper();
targetCompartmentObject = mWorkerPrivate->GetJSObject();
}
NS_ASSERTION(cx, "Must have a context!");
@ -2058,33 +2012,30 @@ NS_IMPL_ISUPPORTS1(WorkerPrivate::MemoryReporter, nsIMemoryReporter)
template <class Derived>
WorkerPrivateParent<Derived>::WorkerPrivateParent(
JSContext* aCx,
WorkerPrivate* aParent,
const nsAString& aScriptURL,
bool aIsChromeWorker,
JSContext* aCx,
JS::HandleObject aObject,
WorkerPrivate* aParent,
const nsAString& aScriptURL,
bool aIsChromeWorker,
bool aIsSharedWorker,
const nsAString& aSharedWorkerName,
LoadInfo& aLoadInfo)
: mMutex("WorkerPrivateParent Mutex"),
: EventTarget(aParent ? aCx : nullptr), mMutex("WorkerPrivateParent Mutex"),
mCondVar(mMutex, "WorkerPrivateParent CondVar"),
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
mParent(aParent), mScriptURL(aScriptURL),
mJSObject(aObject), mParent(aParent), mScriptURL(aScriptURL),
mSharedWorkerName(aSharedWorkerName), mBusyCount(0), mMessagePortSerial(0),
mParentStatus(Pending), mRooted(false), mParentSuspended(false),
mParentStatus(Pending), mJSObjectRooted(false), mParentSuspended(false),
mIsChromeWorker(aIsChromeWorker), mMainThreadObjectsForgotten(false),
mIsSharedWorker(aIsSharedWorker)
{
SetIsDOMBinding();
MOZ_ASSERT_IF(aIsSharedWorker, !aSharedWorkerName.IsVoid() &&
NS_IsMainThread());
MOZ_ASSERT_IF(!aIsSharedWorker, aSharedWorkerName.IsEmpty());
MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivateParent);
MOZ_ASSERT_IF(aIsSharedWorker, !aObject && !aSharedWorkerName.IsVoid());
MOZ_ASSERT_IF(!aIsSharedWorker, aObject && aSharedWorkerName.IsEmpty());
if (aLoadInfo.mWindow) {
AssertIsOnMainThread();
MOZ_ASSERT(aLoadInfo.mWindow->IsInnerWindow(),
"Should have inner window here!");
BindToOwner(aLoadInfo.mWindow);
NS_ASSERTION(aLoadInfo.mWindow->IsInnerWindow(),
"Should have inner window here!");
}
mLoadInfo.StealFrom(aLoadInfo);
@ -2104,63 +2055,17 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
RuntimeService::GetDefaultJSSettings(mJSSettings);
}
if (!aIsSharedWorker) {
SetIsDOMBinding();
SetWrapper(aObject);
}
}
template <class Derived>
WorkerPrivateParent<Derived>::~WorkerPrivateParent()
{
MOZ_ASSERT(!mRooted);
}
template <class Derived>
NS_IMPL_ADDREF_INHERITED(WorkerPrivateParent<Derived>, nsDOMEventTargetHelper)
template <class Derived>
NS_IMPL_RELEASE_INHERITED(WorkerPrivateParent<Derived>, nsDOMEventTargetHelper)
template <class Derived>
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WorkerPrivateParent<Derived>)
// No new interfaces, just cycle collection.
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
template <class Derived>
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
nsDOMEventTargetHelper)
// Nothing else to traverse
// The various strong references in LoadInfo are managed manually and cannot
// be cycle collected.
tmp->AssertIsOnParentThread();
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
template <class Derived>
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
nsDOMEventTargetHelper)
tmp->AssertIsOnParentThread();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
template <class Derived>
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
nsDOMEventTargetHelper)
tmp->AssertIsOnParentThread();
NS_IMPL_CYCLE_COLLECTION_TRACE_END
template <class Derived>
JSObject*
WorkerPrivateParent<Derived>::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aScope)
{
MOZ_ASSERT(!mIsSharedWorker,
"We should never wrap a WorkerPrivate for a SharedWorker");
AssertIsOnParentThread();
JSObject* obj = WorkerBinding::Wrap(aCx, aScope, ParentAsWorkerPrivate());
if (mRooted) {
PreserveWrapper(this);
}
return obj;
MOZ_COUNT_DTOR(mozilla::dom::workers::WorkerPrivateParent);
}
template <class Derived>
@ -2456,23 +2361,54 @@ WorkerPrivateParent<Derived>::SynchronizeAndResume(
return true;
}
template <class Derived>
void
WorkerPrivateParent<Derived>::_trace(JSTracer* aTrc)
{
// This should only happen on the parent thread but we can't assert that
// because it can also happen on the cycle collector thread when this is a
// top-level worker.
EventTarget::_trace(aTrc);
}
template <class Derived>
void
WorkerPrivateParent<Derived>::_finalize(JSFreeOp* aFop)
{
AssertIsOnParentThread();
MOZ_ASSERT(!mRooted);
MOZ_ASSERT(mJSObject);
MOZ_ASSERT(!mJSObjectRooted);
ClearWrapper();
// Ensure that we're held alive across the TerminatePrivate call, and then
// release the reference our wrapper held to us.
nsRefPtr<WorkerPrivateParent<Derived> > kungFuDeathGrip = dont_AddRef(this);
// Clear the JS object.
mJSObject = nullptr;
if (!TerminatePrivate(nullptr)) {
NS_WARNING("Failed to terminate!");
}
// Before calling through to the base class we need to grab another reference
// if we're on the main thread. Otherwise the base class' _Finalize method
// will call Release, and some of our members cannot be released during
// finalization. Of course, if those members are already gone then we can skip
// this mess...
WorkerPrivateParent<Derived>* extraSelfRef = NULL;
if (!mParent && !mMainThreadObjectsForgotten) {
AssertIsOnMainThread();
NS_ADDREF(extraSelfRef = this);
}
EventTarget::_finalize(aFop);
if (extraSelfRef) {
nsCOMPtr<nsIRunnable> runnable =
NS_NewNonOwningRunnableMethod(extraSelfRef,
&WorkerPrivateParent<Derived>::Release);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
NS_WARNING("Failed to proxy release, this will leak!");
}
}
}
template <class Derived>
@ -2501,14 +2437,18 @@ WorkerPrivateParent<Derived>::ModifyBusyCount(JSContext* aCx, bool aIncrease)
NS_ASSERTION(aIncrease || mBusyCount, "Mismatched busy count mods!");
if (aIncrease) {
if (mBusyCount++ == 0) {
Root(true);
if (mBusyCount++ == 0 && mJSObject) {
if (!RootJSObject(aCx, true)) {
return false;
}
}
return true;
}
if (--mBusyCount == 0) {
Root(false);
if (--mBusyCount == 0 && mJSObject) {
if (!RootJSObject(aCx, false)) {
return false;
}
bool shouldCancel;
{
@ -2525,29 +2465,27 @@ WorkerPrivateParent<Derived>::ModifyBusyCount(JSContext* aCx, bool aIncrease)
}
template <class Derived>
void
WorkerPrivateParent<Derived>::Root(bool aRoot)
bool
WorkerPrivateParent<Derived>::RootJSObject(JSContext* aCx, bool aRoot)
{
AssertIsOnParentThread();
if (aRoot == mRooted) {
return;
if (aRoot != mJSObjectRooted) {
if (aRoot) {
NS_ASSERTION(mJSObject, "Nothing to root?");
if (!JS_AddNamedObjectRoot(aCx, &mJSObject, "Worker root")) {
NS_WARNING("JS_AddNamedObjectRoot failed!");
return false;
}
}
else {
JS_RemoveObjectRoot(aCx, &mJSObject);
}
mJSObjectRooted = aRoot;
}
if (aRoot) {
NS_ADDREF_THIS();
if (GetWrapperPreserveColor()) {
PreserveWrapper(this);
}
}
else {
if (GetWrapperPreserveColor()) {
ReleaseWrapper(this);
}
NS_RELEASE_THIS();
}
mRooted = aRoot;
return true;
}
template <class Derived>
@ -2577,21 +2515,20 @@ WorkerPrivateParent<Derived>::ForgetMainThreadObjects(
}
template <class Derived>
void
bool
WorkerPrivateParent<Derived>::PostMessageInternal(
JSContext* aCx,
JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value> >& aTransferable,
JS::Handle<JS::Value> aMessage,
JS::Handle<JS::Value> aTransferable,
bool aToMessagePort,
uint64_t aMessagePortSerial,
ErrorResult& aRv)
uint64_t aMessagePortSerial)
{
AssertIsOnParentThread();
{
MutexAutoLock lock(mMutex);
if (mParentStatus > Running) {
return;
return true;
}
}
@ -2615,34 +2552,18 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
}
}
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
if (aTransferable.WasPassed()) {
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
JSObject* array =
JS_NewArrayObject(aCx, realTransferable.Length(),
const_cast<JS::Value*>(realTransferable.Elements()));
if (!array) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
transferable.setObject(*array);
}
nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
JSAutoStructuredCloneBuffer buffer;
if (!buffer.write(aCx, aMessage, transferable, callbacks, &clonedObjects)) {
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return;
if (!buffer.write(aCx, aMessage, aTransferable, callbacks, &clonedObjects)) {
return false;
}
nsRefPtr<MessageEventRunnable> runnable =
new MessageEventRunnable(ParentAsWorkerPrivate(),
WorkerRunnable::WorkerThread, buffer,
clonedObjects, aToMessagePort, aMessagePortSerial);
if (!runnable->Dispatch(aCx)) {
aRv.Throw(NS_ERROR_FAILURE);
}
return runnable->Dispatch(aCx);
}
template <class Derived>
@ -2656,8 +2577,23 @@ WorkerPrivateParent<Derived>::PostMessageToMessagePort(
{
AssertIsOnMainThread();
PostMessageInternal(aCx, aMessage, aTransferable, true, aMessagePortSerial,
aRv);
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
if (aTransferable.WasPassed()) {
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
JSObject* array =
JS_NewArrayObject(aCx, realTransferable.Length(),
const_cast<jsval*>(realTransferable.Elements()));
if (!array) {
aRv = NS_ERROR_OUT_OF_MEMORY;
return;
}
transferable.setObject(*array);
}
if (!PostMessageInternal(aCx, aMessage, transferable, true,
aMessagePortSerial)) {
aRv = NS_ERROR_FAILURE;
}
}
template <class Derived>
@ -3255,13 +3191,13 @@ WorkerPrivateParent<Derived>::ParentJSContext() const
nsContentUtils::GetSafeJSContext();
}
WorkerPrivate::WorkerPrivate(JSContext* aCx,
WorkerPrivate::WorkerPrivate(JSContext* aCx, JS::HandleObject aObject,
WorkerPrivate* aParent,
const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName,
LoadInfo& aLoadInfo)
: WorkerPrivateParent<WorkerPrivate>(aCx, aParent, aScriptURL,
: WorkerPrivateParent<WorkerPrivate>(aCx, aObject, aParent, aScriptURL,
aIsChromeWorker, aIsSharedWorker,
aSharedWorkerName, aLoadInfo),
mJSContext(nullptr), mErrorHandlerRecursionCount(0), mNextTimeoutId(1),
@ -3270,137 +3206,55 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
mCloseHandlerFinished(false), mMemoryReporterRunning(false),
mBlockedForMemoryReporter(false)
{
MOZ_ASSERT_IF(aIsSharedWorker, !aSharedWorkerName.IsVoid());
MOZ_ASSERT_IF(!aIsSharedWorker, aSharedWorkerName.IsEmpty());
MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivate);
MOZ_ASSERT_IF(aIsSharedWorker, !aObject && !aSharedWorkerName.IsVoid());
MOZ_ASSERT_IF(!aIsSharedWorker, aObject && aSharedWorkerName.IsEmpty());
}
WorkerPrivate::~WorkerPrivate()
{
MOZ_COUNT_DTOR(mozilla::dom::workers::WorkerPrivate);
}
// static
already_AddRefed<WorkerPrivate>
WorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
ErrorResult& aRv)
WorkerPrivate::Create(JSContext* aCx, JS::HandleObject aObject,
WorkerPrivate* aParent, const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName, LoadInfo* aLoadInfo)
{
return WorkerPrivate::Constructor(aGlobal, aScriptURL, false, false,
EmptyString(), nullptr, aRv);
}
// static
bool
WorkerPrivate::WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */)
{
// If we're already on a worker workers are clearly enabled.
if (!NS_IsMainThread()) {
return true;
}
// If our caller is chrome, workers are always available.
if (nsContentUtils::IsCallerChrome()) {
return true;
}
// Else check the pref.
return Preferences::GetBool(PREF_WORKERS_ENABLED);
}
// static
already_AddRefed<ChromeWorkerPrivate>
ChromeWorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
ErrorResult& aRv)
{
return WorkerPrivate::Constructor(aGlobal, aScriptURL, true, false,
EmptyString(), nullptr, aRv).downcast<ChromeWorkerPrivate>();
}
// static
bool
ChromeWorkerPrivate::WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */)
{
// Chrome is always allowed to use workers, and content is never allowed to
// use ChromeWorker, so all we have to check is the caller.
return nsContentUtils::ThreadsafeIsCallerChrome();
}
// static
already_AddRefed<WorkerPrivate>
WorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv)
{
WorkerPrivate* parent = NS_IsMainThread() ?
nullptr :
GetCurrentThreadWorkerPrivate();
if (parent) {
parent->AssertIsOnWorkerThread();
if (aParent) {
aParent->AssertIsOnWorkerThread();
} else {
AssertIsOnMainThread();
}
JSContext* cx = aGlobal.GetContext();
MOZ_ASSERT_IF(aIsSharedWorker, !aSharedWorkerName.IsVoid());
MOZ_ASSERT_IF(!aIsSharedWorker, aSharedWorkerName.IsEmpty());
MOZ_ASSERT_IF(aIsSharedWorker, !aObject && !aSharedWorkerName.IsVoid());
MOZ_ASSERT_IF(!aIsSharedWorker, aObject && aSharedWorkerName.IsEmpty());
mozilla::Maybe<LoadInfo> stackLoadInfo;
if (!aLoadInfo) {
stackLoadInfo.construct();
nsresult rv = GetLoadInfo(cx, nullptr, parent, aScriptURL,
nsresult rv = GetLoadInfo(aCx, nullptr, aParent, aScriptURL,
aIsChromeWorker, stackLoadInfo.addr());
if (NS_FAILED(rv)) {
scriptloader::ReportLoadError(cx, aScriptURL, rv, !parent);
aRv.Throw(rv);
scriptloader::ReportLoadError(aCx, aScriptURL, rv, !aParent);
return nullptr;
}
aLoadInfo = stackLoadInfo.addr();
}
// NB: This has to be done before creating the WorkerPrivate, because it will
// attempt to use static variables that are initialized in the RuntimeService
// constructor.
RuntimeService* runtimeService;
if (!parent) {
runtimeService = RuntimeService::GetOrCreateService();
if (!runtimeService) {
JS_ReportError(cx, "Failed to create runtime service!");
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
}
else {
runtimeService = RuntimeService::GetService();
}
MOZ_ASSERT(runtimeService);
nsRefPtr<WorkerPrivate> worker =
new WorkerPrivate(cx, parent, aScriptURL, aIsChromeWorker,
new WorkerPrivate(aCx, aObject, aParent, aScriptURL, aIsChromeWorker,
aIsSharedWorker, aSharedWorkerName, *aLoadInfo);
nsRefPtr<CompileScriptRunnable> compiler = new CompileScriptRunnable(worker);
if (!compiler->Dispatch(cx)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
if (!compiler->Dispatch(aCx)) {
return nullptr;
}
if (!runtimeService->RegisterWorker(cx, worker)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// The worker will be owned by its JSObject (via the reference we return from
// this function), but it also needs to be owned by its thread, so AddRef it
// again.
NS_ADDREF(worker.get());
return worker.forget();
}
@ -5155,6 +5009,15 @@ WorkerPrivateParent<Derived>::StealHostObjectURIs(nsTArray<nsCString>& aArray)
aArray.SwapElements(mHostObjectURIs);
}
template <class Derived>
JSObject*
WorkerPrivateParent<Derived>::WrapObject(JSContext* aCx,
JS::HandleObject aScope)
{
MOZ_CRASH("This should never be called!");
return nullptr;
}
WorkerCrossThreadDispatcher*
WorkerPrivate::GetCrossThreadDispatcher()
{
@ -5310,24 +5173,6 @@ WorkerPrivate::AssertIsOnWorkerThread() const
BEGIN_WORKERS_NAMESPACE
WorkerCrossThreadDispatcher*
GetWorkerCrossThreadDispatcher(JSContext* aCx, JS::Value aWorker)
{
if (!aWorker.isObject()) {
return nullptr;
}
WorkerPrivate* w = nullptr;
UNWRAP_OBJECT(Worker, aCx, &aWorker.toObject(), w);
MOZ_ASSERT(w);
return w->GetCrossThreadDispatcher();
}
// Can't use NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerPrivateParent) because of the
// templates.
template <>
WorkerPrivateParent<WorkerPrivate>::cycleCollection WorkerPrivateParent<WorkerPrivate>::_cycleCollectorGlobal = WorkerPrivateParent<WorkerPrivate>::cycleCollection();
// Force instantiation.
template class WorkerPrivateParent<WorkerPrivate>;

View File

@ -20,7 +20,6 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDataHashtable.h"
#include "nsDOMEventTargetHelper.h"
#include "nsEventQueue.h"
#include "nsHashKeys.h"
#include "nsString.h"
@ -29,6 +28,7 @@
#include "nsTPriorityQueue.h"
#include "StructuredCloneTags.h"
#include "EventTarget.h"
#include "Queue.h"
#include "WorkerFeature.h"
@ -234,7 +234,7 @@ public:
};
template <class Derived>
class WorkerPrivateParent : public nsDOMEventTargetHelper
class WorkerPrivateParent : public EventTarget
{
class SynchronizeAndResumeRunnable;
@ -300,12 +300,11 @@ protected:
mozilla::CondVar mMemoryReportCondVar;
private:
JSObject* mJSObject;
WorkerPrivate* mParent;
nsString mScriptURL;
nsString mSharedWorkerName;
LocationInfo mLocationInfo;
// The lifetime of these objects within LoadInfo is managed explicitly;
// they do not need to be cycle collected.
LoadInfo mLoadInfo;
// Only used for top level workers.
@ -325,17 +324,17 @@ private:
uint64_t mBusyCount;
uint64_t mMessagePortSerial;
Status mParentStatus;
bool mRooted;
bool mJSObjectRooted;
bool mParentSuspended;
bool mIsChromeWorker;
bool mMainThreadObjectsForgotten;
bool mIsSharedWorker;
protected:
WorkerPrivateParent(JSContext* aCx, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
bool aIsSharedWorker, const nsAString& aSharedWorkerName,
LoadInfo& aLoadInfo);
WorkerPrivateParent(JSContext* aCx, JS::HandleObject aObject,
WorkerPrivate* aParent, const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName, LoadInfo& aLoadInfo);
~WorkerPrivateParent();
@ -357,21 +356,12 @@ private:
return NotifyPrivate(aCx, Terminating);
}
void
bool
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value> >& aTransferable,
bool aToMessagePort, uint64_t aMessagePortSerial,
ErrorResult& aRv);
JS::Handle<JS::Value> aTransferable,
bool aToMessagePort, uint64_t aMessagePortSerial);
public:
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerPrivateParent,
nsDOMEventTargetHelper)
// May be called on any thread...
bool
Start();
@ -405,20 +395,23 @@ public:
SynchronizeAndResume(JSContext* aCx, nsPIDOMWindow* aWindow,
nsIScriptContext* aScriptContext);
void
_finalize(JSFreeOp* aFop);
virtual void
_trace(JSTracer* aTrc) MOZ_OVERRIDE;
virtual void
_finalize(JSFreeOp* aFop) MOZ_OVERRIDE;
void
Finish(JSContext* aCx)
{
Root(false);
RootJSObject(aCx, false);
}
bool
Terminate(JSContext* aCx)
{
AssertIsOnParentThread();
Root(false);
RootJSObject(aCx, false);
return TerminatePrivate(aCx);
}
@ -428,25 +421,24 @@ public:
bool
ModifyBusyCount(JSContext* aCx, bool aIncrease);
void
Root(bool aRoot);
bool
RootJSObject(JSContext* aCx, bool aRoot);
void
ForgetMainThreadObjects(nsTArray<nsCOMPtr<nsISupports> >& aDoomed);
void
bool
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value> >& aTransferable,
ErrorResult& aRv)
JS::Handle<JS::Value> aTransferable)
{
PostMessageInternal(aCx, aMessage, aTransferable, false, 0, aRv);
return PostMessageInternal(aCx, aMessage, aTransferable, false, 0);
}
void
PostMessageToMessagePort(JSContext* aCx,
uint64_t aMessagePortSerial,
JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value> >& aTransferable,
const Optional<Sequence<JS::Value > >& aTransferable,
ErrorResult& aRv);
bool
@ -545,6 +537,12 @@ public:
return mLoadInfo.mScriptContext;
}
JSObject*
GetJSObject() const
{
return mJSObject;
}
const nsString&
ScriptURL() const
{
@ -708,8 +706,8 @@ public:
void
StealHostObjectURIs(nsTArray<nsCString>& aArray);
IMPL_EVENT_HANDLER(message)
IMPL_EVENT_HANDLER(error)
virtual JSObject*
WrapObject(JSContext* aCx, JS::HandleObject aScope) MOZ_OVERRIDE;
#ifdef DEBUG
void
@ -793,22 +791,14 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
nsCOMPtr<nsIThread> mThread;
#endif
protected:
public:
~WorkerPrivate();
public:
static already_AddRefed<WorkerPrivate>
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
ErrorResult& aRv);
static already_AddRefed<WorkerPrivate>
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv);
static bool
WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */);
Create(JSContext* aCx, JS::HandleObject aObject, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
bool aIsSharedWorker, const nsAString& aSharedWorkerName,
LoadInfo* aLoadInfo = nullptr);
static nsresult
GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, WorkerPrivate* aParent,
@ -1028,10 +1018,10 @@ public:
GetMessagePort(uint64_t aMessagePortSerial);
private:
WorkerPrivate(JSContext* aCx, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
bool aIsSharedWorker, const nsAString& aSharedWorkerName,
LoadInfo& aLoadInfo);
WorkerPrivate(JSContext* aCx, JS::HandleObject aObject,
WorkerPrivate* aParent, const nsAString& aScriptURL,
bool aIsChromeWorker, bool aIsSharedWorker,
const nsAString& aSharedWorkerName, LoadInfo& aLoadInfo);
bool
Dispatch(WorkerRunnable* aEvent, EventQueue* aQueue);
@ -1110,31 +1100,9 @@ private:
uint64_t aMessagePortSerial);
};
// This class is only used to trick the DOM bindings. We never create
// instances of it, and static_casting to it is fine since it doesn't add
// anything to WorkerPrivate.
class ChromeWorkerPrivate : public WorkerPrivate
{
public:
static already_AddRefed<ChromeWorkerPrivate>
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
ErrorResult& rv);
static bool
WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */);
private:
ChromeWorkerPrivate() MOZ_DELETE;
ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
};
WorkerPrivate*
GetWorkerPrivateFromContext(JSContext* aCx);
WorkerPrivate*
GetCurrentThreadWorkerPrivate();
bool
IsCurrentThreadRunningChromeWorker();

View File

@ -23,7 +23,6 @@
#include "mozilla/dom/XMLHttpRequestBinding.h"
#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
#include "mozilla/dom/URLBinding.h"
#include "mozilla/dom/WorkerBinding.h"
#include "mozilla/dom/WorkerLocationBinding.h"
#include "mozilla/dom/WorkerNavigatorBinding.h"
#include "mozilla/OSFileConstants.h"
@ -45,6 +44,7 @@
#include "Navigator.h"
#include "Principal.h"
#include "ScriptLoader.h"
#include "Worker.h"
#include "WorkerPrivate.h"
#include "XMLHttpRequest.h"
@ -1451,10 +1451,16 @@ CreateGlobalScope(JSContext* aCx)
return nullptr;
}
JS::Rooted<JSObject*> workerProto(aCx,
worker::InitClass(aCx, global, eventTargetProto, false));
if (!workerProto) {
return nullptr;
}
if (worker->IsChromeWorker()) {
if (!DefineChromeWorkerFunctions(aCx, global) ||
!DefineOSFileConstants(aCx, global) ||
!ChromeWorkerBinding::GetConstructorObject(aCx, global)) {
if (!chromeworker::InitClass(aCx, global, workerProto, false) ||
!DefineChromeWorkerFunctions(aCx, global) ||
!DefineOSFileConstants(aCx, global)) {
return nullptr;
}
}
@ -1475,7 +1481,6 @@ CreateGlobalScope(JSContext* aCx)
!XMLHttpRequestBinding_workers::GetConstructorObject(aCx, global) ||
!XMLHttpRequestUploadBinding_workers::GetConstructorObject(aCx, global) ||
!URLBinding_workers::GetConstructorObject(aCx, global) ||
!WorkerBinding::GetConstructorObject(aCx, global) ||
!WorkerLocationBinding_workers::GetConstructorObject(aCx, global) ||
!WorkerNavigatorBinding_workers::GetConstructorObject(aCx, global)) {
return nullptr;
@ -1490,11 +1495,4 @@ CreateGlobalScope(JSContext* aCx)
return global;
}
bool
GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr, JSMSG_GETTER_ONLY);
return false;
}
END_WORKERS_NAMESPACE

View File

@ -9,10 +9,6 @@ TEST_DIRS += ['test']
MODULE = 'dom'
# Public stuff.
EXPORTS.mozilla.dom += [
'WorkerPrivate.h',
]
EXPORTS.mozilla.dom.workers += [
'Workers.h',
]
@ -51,6 +47,7 @@ CPP_SOURCES += [
'ScriptLoader.cpp',
'SharedWorker.cpp',
'URL.cpp',
'Worker.cpp',
'WorkerMessagePort.cpp',
'WorkerPrivate.cpp',
'WorkerScope.cpp',

View File

@ -73,7 +73,6 @@ class Selection;
namespace dom {
class Element;
class EventTarget;
} // namespace dom
} // namespace mozilla
@ -664,7 +663,7 @@ public:
nsIDOMNode *aEndNode,
int32_t aEndOffset);
virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget() = 0;
// Fast non-refcounting editor root element accessor
mozilla::dom::Element *GetRoot();
@ -820,7 +819,7 @@ protected:
nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
nsCOMPtr<nsIPrivateTextRangeList> mIMETextRangeList; // IME special selection ranges
nsCOMPtr<nsIDOMCharacterData> mIMETextNode; // current IME text node
nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
nsCOMPtr<nsIDOMEventTarget> mEventTarget; // The form field as an event receiver
nsCOMPtr<nsIDOMEventListener> mEventListener;
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes

View File

@ -6,7 +6,6 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Preferences.h" // for Preferences
#include "mozilla/dom/Element.h" // for Element
#include "mozilla/dom/EventTarget.h" // for EventTarget
#include "nsAString.h"
#include "nsCaret.h" // for nsCaret
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
@ -56,7 +55,6 @@
class nsPresContext;
using namespace mozilla;
using mozilla::dom::EventTarget;
nsEditorEventListener::nsEditorEventListener() :
mEditor(nullptr), mCommitText(false),
@ -105,11 +103,11 @@ nsEditorEventListener::InstallToEditor()
{
NS_PRECONDITION(mEditor, "The caller must set mEditor");
nsCOMPtr<EventTarget> piTarget = mEditor->GetDOMEventTarget();
nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
// register the event listeners with the listener manager
nsEventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
nsEventListenerManager* elmP = piTarget->GetListenerManager(true);
NS_ENSURE_STATE(elmP);
#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
@ -183,12 +181,13 @@ nsEditorEventListener::Disconnect()
void
nsEditorEventListener::UninstallFromEditor()
{
nsCOMPtr<EventTarget> piTarget = mEditor->GetDOMEventTarget();
nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
if (!piTarget) {
return;
}
nsEventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
nsEventListenerManager* elmP =
piTarget->GetListenerManager(true);
if (!elmP) {
return;
}

View File

@ -70,7 +70,6 @@
#include "nsIParserService.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/HTMLBodyElement.h"
#include "nsTextFragment.h"
@ -5218,14 +5217,14 @@ nsHTMLEditor::GetActiveEditingHost()
return content->GetEditingHost();
}
already_AddRefed<mozilla::dom::EventTarget>
already_AddRefed<nsIDOMEventTarget>
nsHTMLEditor::GetDOMEventTarget()
{
// Don't use getDocument here, because we have no way of knowing
// whether Init() was ever called. So we need to get the document
// ourselves, if it exists.
NS_PRECONDITION(mDocWeak, "This editor has not been initialized yet");
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryReferent(mDocWeak);
nsCOMPtr<nsIDOMEventTarget> target = do_QueryReferent(mDocWeak.get());
return target.forget();
}

View File

@ -106,7 +106,7 @@ public:
virtual already_AddRefed<nsIContent> GetFocusedContent();
virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
virtual bool IsActiveInDOMWindow();
virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget();
virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget();
virtual mozilla::dom::Element* GetEditorRoot() MOZ_OVERRIDE;
virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode);
virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);

View File

@ -1584,10 +1584,10 @@ nsPlaintextEditor::SelectEntireDocument(nsISelection *aSelection)
return NS_OK;
}
already_AddRefed<mozilla::dom::EventTarget>
already_AddRefed<nsIDOMEventTarget>
nsPlaintextEditor::GetDOMEventTarget()
{
nsCOMPtr<mozilla::dom::EventTarget> copy = mEventTarget;
nsCOMPtr<nsIDOMEventTarget> copy = mEventTarget;
return copy.forget();
}

View File

@ -120,7 +120,7 @@ public:
virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget();
virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget();
virtual nsresult BeginIMEComposition();
virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,

View File

@ -865,7 +865,7 @@ nsDocShellTreeOwner::AddChromeListeners()
nsCOMPtr<EventTarget> target;
GetDOMEventTarget(mWebBrowser, getter_AddRefs(target));
nsEventListenerManager* elmP = target->GetOrCreateListenerManager();
nsEventListenerManager* elmP = target->GetListenerManager(true);
if (elmP) {
elmP->AddEventListenerByType(this, NS_LITERAL_STRING("dragover"),
dom::TrustedEventsAtSystemGroupBubble());
@ -895,7 +895,7 @@ nsDocShellTreeOwner::RemoveChromeListeners()
if (!piTarget)
return NS_OK;
nsEventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
nsEventListenerManager* elmP = piTarget->GetListenerManager(true);
if (elmP)
{
elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("dragover"),

View File

@ -118,13 +118,13 @@ GetPrefsFor(nsEventStructType aEventStructType)
static bool
HasMouseListener(nsIContent* aContent)
{
if (nsEventListenerManager* elm = aContent->GetExistingListenerManager()) {
return elm->HasListenersFor(nsGkAtoms::onclick) ||
elm->HasListenersFor(nsGkAtoms::onmousedown) ||
elm->HasListenersFor(nsGkAtoms::onmouseup);
nsEventListenerManager* elm = aContent->GetListenerManager(false);
if (!elm) {
return false;
}
return false;
return elm->HasListenersFor(nsGkAtoms::onclick) ||
elm->HasListenersFor(nsGkAtoms::onmousedown) ||
elm->HasListenersFor(nsGkAtoms::onmouseup);
}
static bool

View File

@ -2208,7 +2208,7 @@ MayHavePaintEventListener(nsPIDOMWindow* aInnerWindow)
return false;
nsEventListenerManager* manager = nullptr;
if ((manager = parentTarget->GetExistingListenerManager()) &&
if ((manager = parentTarget->GetListenerManager(false)) &&
manager->MayHavePaintEventListener()) {
return true;
}
@ -2236,7 +2236,7 @@ MayHavePaintEventListener(nsPIDOMWindow* aInnerWindow)
EventTarget* tabChildGlobal;
return root &&
(tabChildGlobal = root->GetParentTarget()) &&
(manager = tabChildGlobal->GetExistingListenerManager()) &&
(manager = tabChildGlobal->GetListenerManager(false)) &&
manager->MayHavePaintEventListener();
}

View File

@ -171,8 +171,8 @@ let Scheduler = {
if (error instanceof PromiseWorker.WorkerError) {
throw OS.File.Error.fromMsg(error.data);
}
// Extract something meaningful from ErrorEvent
if (error instanceof ErrorEvent) {
// Extract something meaningful from WorkerErrorEvent
if (typeof error == "object" && error && error.constructor.name == "WorkerErrorEvent") {
let message = error.message;
if (message == "uncaught exception: [object StopIteration]") {
throw StopIteration;