mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
d9879cd4ec
commit
a80b1ea22a
@ -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());
|
||||
|
||||
|
@ -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) ||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -1810,7 +1810,7 @@ Element::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
|
||||
bool* aDefer)
|
||||
{
|
||||
*aDefer = true;
|
||||
return GetOrCreateListenerManager();
|
||||
return GetListenerManager(true);
|
||||
}
|
||||
|
||||
Element::nsAttrInfo
|
||||
|
@ -1225,7 +1225,7 @@ FragmentOrElement::MarkNodeChildren(nsINode* aNode)
|
||||
JS::ExposeObjectToActiveJS(o);
|
||||
}
|
||||
|
||||
nsEventListenerManager* elm = aNode->GetExistingListenerManager();
|
||||
nsEventListenerManager* elm = aNode->GetListenerManager(false);
|
||||
if (elm) {
|
||||
elm->MarkForCC();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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); \
|
||||
} \
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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_
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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"),
|
||||
|
@ -372,7 +372,7 @@ nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget)
|
||||
if (!target)
|
||||
return nullptr;
|
||||
|
||||
return target->GetOrCreateListenerManager();
|
||||
return target->GetListenerManager(true);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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; \
|
||||
} \
|
||||
|
@ -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); \
|
||||
} \
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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')
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 *
|
||||
|
@ -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; \
|
||||
} \
|
||||
|
@ -1202,7 +1202,7 @@ TabChild::~TabChild()
|
||||
mGlobal = nullptr;
|
||||
|
||||
if (mTabChildGlobal) {
|
||||
nsEventListenerManager* elm = mTabChildGlobal->GetExistingListenerManager();
|
||||
nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(false);
|
||||
if (elm) {
|
||||
elm->Disconnect();
|
||||
}
|
||||
|
@ -579,7 +579,6 @@ var interfaceNamesInGlobalScope =
|
||||
"WheelEvent",
|
||||
"Window",
|
||||
"WindowUtils",
|
||||
"Worker",
|
||||
"XMLDocument",
|
||||
"XMLHttpRequest",
|
||||
"XMLHttpRequestUpload",
|
||||
|
@ -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 {
|
||||
};
|
@ -410,7 +410,6 @@ WEBIDL_FILES = [
|
||||
'WheelEvent.webidl',
|
||||
'WifiOptions.webidl',
|
||||
'Window.webidl',
|
||||
'Worker.webidl',
|
||||
'WorkerLocation.webidl',
|
||||
'WorkerMessagePort.webidl',
|
||||
'WorkerNavigator.webidl',
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
672
dom/workers/Worker.cpp
Normal 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
35
dom/workers/Worker.h
Normal 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__ */
|
@ -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>;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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"),
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user