diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 824004bc95..20372ed9ff 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1184,6 +1184,10 @@ FragmentOrElement::DestroyContent() // The child can remove itself from the parent in BindToTree. mAttrsAndChildren.ChildAt(i)->DestroyContent(); } + ShadowRoot* shadowRoot = GetShadowRoot(); + if (shadowRoot) { + shadowRoot->DestroyContent(); + } } void diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp index de7b9f7ce5..405e6c3e31 100644 --- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -711,6 +711,15 @@ ShadowRoot::ContentRemoved(nsIDocument* aDocument, } } +void +ShadowRoot::DestroyContent() +{ + if (mOlderShadow) { + mOlderShadow->DestroyContent(); + } + DocumentFragment::DestroyContent(); +} + NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList, mShadowRoot) diff --git a/dom/base/ShadowRoot.h b/dom/base/ShadowRoot.h index 8382cab113..01ec66aa4d 100644 --- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -133,6 +133,8 @@ public: { mIsComposedDocParticipant = aIsComposedDocParticipant; } + + virtual void DestroyContent() MOZ_OVERRIDE; protected: virtual ~ShadowRoot(); diff --git a/dom/base/WindowNamedPropertiesHandler.cpp b/dom/base/WindowNamedPropertiesHandler.cpp index d0ec08ba20..4d397fbcc1 100644 --- a/dom/base/WindowNamedPropertiesHandler.cpp +++ b/dom/base/WindowNamedPropertiesHandler.cpp @@ -19,6 +19,13 @@ namespace dom { static bool ShouldExposeChildWindow(nsString& aNameBeingResolved, nsIDOMWindow *aChild) { + nsCOMPtr piWin = do_QueryInterface(aChild); + NS_ENSURE_TRUE(piWin, false); + Element* e = piWin->GetFrameElementInternal(); + if (e && e->IsInShadowTree()) { + return false; + } + // If we're same-origin with the child, go ahead and expose it. nsCOMPtr sop = do_QueryInterface(aChild); NS_ENSURE_TRUE(sop, false); @@ -63,9 +70,6 @@ ShouldExposeChildWindow(nsString& aNameBeingResolved, nsIDOMWindow *aChild) // allow the child to arbitrarily pollute the parent namespace, and requires // cross-origin communication only in a limited set of cases that can be // computed independently by the parent. - nsCOMPtr piWin = do_QueryInterface(aChild); - NS_ENSURE_TRUE(piWin, false); - Element* e = piWin->GetFrameElementInternal(); return e && e->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, aNameBeingResolved, eCaseMatters); } diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index e57e16cc54..1a349111e0 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -194,7 +194,7 @@ nsFrameLoader::Create(Element* aOwner, bool aNetworkCreated) NS_ENSURE_TRUE(aOwner, nullptr); nsIDocument* doc = aOwner->OwnerDoc(); NS_ENSURE_TRUE(!doc->IsResourceDoc() && - ((!doc->IsLoadedAsData() && aOwner->GetUncomposedDoc()) || + ((!doc->IsLoadedAsData() && aOwner->GetComposedDoc()) || doc->IsStaticDocument()), nullptr); @@ -349,7 +349,7 @@ private: nsresult nsFrameLoader::ReallyStartLoadingInternal() { - NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc()); + NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInComposedDoc()); PROFILER_LABEL("nsFrameLoader", "ReallyStartLoading", js::ProfileEntry::Category::OTHER); @@ -876,12 +876,12 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size, // want here. For now, hack. if (!mRemoteBrowserShown) { if (!mOwnerContent || - !mOwnerContent->GetUncomposedDoc()) { + !mOwnerContent->GetComposedDoc()) { return false; } nsRefPtr layerManager = - nsContentUtils::LayerManagerForDocument(mOwnerContent->GetUncomposedDoc()); + nsContentUtils::LayerManagerForDocument(mOwnerContent->GetComposedDoc()); if (!layerManager) { // This is just not going to work. return false; @@ -972,8 +972,8 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther, return NS_ERROR_DOM_SECURITY_ERR; } - nsIDocument* ourDoc = ourContent->GetCurrentDoc(); - nsIDocument* otherDoc = otherContent->GetCurrentDoc(); + nsIDocument* ourDoc = ourContent->GetComposedDoc(); + nsIDocument* otherDoc = otherContent->GetComposedDoc(); if (!ourDoc || !otherDoc) { // Again, how odd, given that we had docshells return NS_ERROR_NOT_IMPLEMENTED; @@ -1191,8 +1191,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther, otherChildDocument->GetParentDocument(); // Make sure to swap docshells between the two frames. - nsIDocument* ourDoc = ourContent->GetUncomposedDoc(); - nsIDocument* otherDoc = otherContent->GetUncomposedDoc(); + nsIDocument* ourDoc = ourContent->GetComposedDoc(); + nsIDocument* otherDoc = otherContent->GetComposedDoc(); if (!ourDoc || !otherDoc) { // Again, how odd, given that we had docshells return NS_ERROR_NOT_IMPLEMENTED; @@ -1612,7 +1612,7 @@ nsFrameLoader::MaybeCreateDocShell() // XXXbz this is such a total hack.... We really need to have a // better setup for doing this. nsIDocument* doc = mOwnerContent->OwnerDoc(); - if (!(doc->IsStaticDocument() || mOwnerContent->IsInDoc())) { + if (!(doc->IsStaticDocument() || mOwnerContent->IsInComposedDoc())) { return NS_ERROR_UNEXPECTED; } @@ -2674,17 +2674,40 @@ nsFrameLoader::RequestNotifyAfterRemotePaint() // If remote browsing (e10s), handle this with the TabParent. if (mRemoteBrowser) { unused << mRemoteBrowser->SendRequestNotifyAfterRemotePaint(); - return NS_OK; } - // If not remote browsing, directly use the document's window. - nsCOMPtr window = do_GetInterface(mDocShell); - if (!window) { - NS_WARNING("Unable to get window for synchronous MozAfterRemotePaint event."); - return NS_OK; + return NS_OK; +} + +NS_IMETHODIMP +nsFrameLoader::RequestNotifyLayerTreeReady() +{ + if (mRemoteBrowser) { + return mRemoteBrowser->RequestNotifyLayerTreeReady() ? NS_OK : NS_ERROR_NOT_AVAILABLE; } - window->SetRequestNotifyAfterRemotePaint(); + nsRefPtr event = + new AsyncEventDispatcher(mOwnerContent, + NS_LITERAL_STRING("MozLayerTreeReady"), + true, false); + event->PostDOMEvent(); + + return NS_OK; +} + +NS_IMETHODIMP +nsFrameLoader::RequestNotifyLayerTreeCleared() +{ + if (mRemoteBrowser) { + return mRemoteBrowser->RequestNotifyLayerTreeCleared() ? NS_OK : NS_ERROR_NOT_AVAILABLE; + } + + nsRefPtr event = + new AsyncEventDispatcher(mOwnerContent, + NS_LITERAL_STRING("MozLayerTreeCleared"), + true, false); + event->PostDOMEvent(); + return NS_OK; } diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index fd9213a24f..5c22d17ae0 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -514,7 +514,7 @@ nsFrameMessageManager::GetDelayedScripts(JSContext* aCx, JS::MutableHandleRefreshAgentsVolume(this); } -void -nsPIDOMWindow::SendAfterRemotePaintIfRequested() -{ - if (!mSendAfterRemotePaint) { - return; - } - - mSendAfterRemotePaint = false; - - nsContentUtils::DispatchChromeEvent(GetExtantDoc(), - GetParentTarget(), - NS_LITERAL_STRING("MozAfterRemotePaint"), - false, false); -} - // nsISpeechSynthesisGetter #ifdef MOZ_WEBSPEECH diff --git a/dom/base/nsIFrameLoader.idl b/dom/base/nsIFrameLoader.idl index b60a8ff20f..0d57130902 100644 --- a/dom/base/nsIFrameLoader.idl +++ b/dom/base/nsIFrameLoader.idl @@ -16,7 +16,7 @@ interface nsIDOMElement; interface nsITabParent; interface nsILoadContext; -[scriptable, builtinclass, uuid(28b6b043-46ec-412f-9be9-db22938b0d6d)] +[scriptable, builtinclass, uuid(d24f9330-ae4e-11e4-ab27-0800200c9a66)] interface nsIFrameLoader : nsISupports { /** @@ -121,6 +121,14 @@ interface nsIFrameLoader : nsISupports */ void requestNotifyAfterRemotePaint(); + /** + * Request an event when the layer tree from the remote tab becomes + * available or unavailable. When this happens, a mozLayerTreeReady + * or mozLayerTreeCleared event is fired. + */ + void requestNotifyLayerTreeReady(); + void requestNotifyLayerTreeCleared(); + /** * The default event mode automatically forwards the events * handled in EventStateManager::HandleCrossProcessEvent to diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index f851d0f0ea..916f765313 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -131,7 +131,7 @@ IsJavaMIME(const nsACString & aMIMEType) static bool InActiveDocument(nsIContent *aContent) { - if (!aContent->IsInDoc()) { + if (!aContent->IsInComposedDoc()) { return false; } nsIDocument *doc = aContent->OwnerDoc(); @@ -3333,11 +3333,10 @@ nsObjectLoadingContent::GetContentDocument() nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); - if (!thisContent->IsInDoc()) { + if (!thisContent->IsInComposedDoc()) { return nullptr; } - // XXXbz should this use GetComposedDoc()? sXBL/XBL2 issue! nsIDocument *sub_doc = thisContent->OwnerDoc()->GetSubDocumentFor(thisContent); if (!sub_doc) { return nullptr; diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 0e0befac3c..399f3021bf 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -769,17 +769,6 @@ public: return mMarkedCCGeneration; } - // Sets the condition that we send an NS_AFTER_REMOTE_PAINT message just before the next - // composite. Used in non-e10s implementations. - void SetRequestNotifyAfterRemotePaint() - { - mSendAfterRemotePaint = true; - } - - // Sends an NS_AFTER_REMOTE_PAINT message if requested by - // SetRequestNotifyAfterRemotePaint(). - void SendAfterRemotePaintIfRequested(); - virtual already_AddRefed GetOpener() = 0; // aLoadInfo will be passed on through to the windowwatcher. // aForceNoOpener will act just like a "noopener" feature in aOptions except @@ -885,10 +874,6 @@ protected: bool mHasNotifiedGlobalCreated; uint32_t mMarkedCCGeneration; - - // If true, send an NS_AFTER_REMOTE_PAINT message before compositing in a - // non-e10s implementation. - bool mSendAfterRemotePaint; }; diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index 7972090e31..1eb67803de 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -765,6 +765,7 @@ support-files = file_bug503473-frame.sjs skip-if = buildapp == 'b2g' || e10s support-files = file_bug1011748_redirect.sjs file_bug1011748_OK.sjs [test_bug1025933.html] +[test_bug1037687.html] [test_element.matches.html] [test_user_select.html] skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' diff --git a/dom/base/test/test_bug1037687.html b/dom/base/test/test_bug1037687.html new file mode 100644 index 0000000000..097a3d1e6e --- /dev/null +++ b/dom/base/test/test_bug1037687.html @@ -0,0 +1,63 @@ + + + + + + Test for Bug 1037687 + + + + + +Mozilla Bug 1037687 +

+ +
+
+
+ + diff --git a/dom/bindings/DOMJSProxyHandler.cpp b/dom/bindings/DOMJSProxyHandler.cpp index f50520ffc7..3fbe3d1ed1 100644 --- a/dom/bindings/DOMJSProxyHandler.cpp +++ b/dom/bindings/DOMJSProxyHandler.cpp @@ -33,17 +33,22 @@ const char DOMProxyHandler::family = 0; js::DOMProxyShadowsResult DOMProxyShadows(JSContext* cx, JS::Handle proxy, JS::Handle id) { + JS::Rooted expando(cx, DOMProxyHandler::GetExpandoObject(proxy)); JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO); - if (v.isObject()) { + bool isOverrideBuiltins = !v.isObject() && !v.isUndefined(); + if (expando) { bool hasOwn; - Rooted object(cx, &v.toObject()); - if (!JS_AlreadyHasOwnPropertyById(cx, object, id, &hasOwn)) + if (!JS_AlreadyHasOwnPropertyById(cx, expando, id, &hasOwn)) return js::ShadowCheckFailed; - return hasOwn ? js::Shadows : js::DoesntShadow; + if (hasOwn) { + return isOverrideBuiltins ? + js::ShadowsViaIndirectExpando : js::ShadowsViaDirectExpando; + } } - if (v.isUndefined()) { + if (!isOverrideBuiltins) { + // Our expando, if any, didn't shadow, so we're not shadowing at all. return js::DoesntShadow; } diff --git a/dom/html/HTMLObjectElement.cpp b/dom/html/HTMLObjectElement.cpp index cf7c6f1f51..99c2bb5b40 100644 --- a/dom/html/HTMLObjectElement.cpp +++ b/dom/html/HTMLObjectElement.cpp @@ -72,7 +72,7 @@ HTMLObjectElement::DoneAddingChildren(bool aHaveNotified) // If we're already in a document, we need to trigger the load // Otherwise, BindToTree takes care of that. - if (IsInDoc()) { + if (IsInComposedDoc()) { StartObjectLoad(aHaveNotified); } } @@ -312,7 +312,7 @@ HTMLObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName, // We also don't want to start loading the object when we're not yet in // a document, just in case that the caller wants to set additional // attributes before inserting the node into the document. - if (aNotify && IsInDoc() && mIsDoneAddingChildren && + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) { return LoadObject(aNotify, true); } @@ -329,7 +329,7 @@ HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, NS_ENSURE_SUCCESS(rv, rv); // See comment in SetAttr - if (aNotify && IsInDoc() && mIsDoneAddingChildren && + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) { return LoadObject(aNotify, true); } @@ -541,7 +541,7 @@ HTMLObjectElement::StartObjectLoad(bool aNotify) { // BindToTree can call us asynchronously, and we may be removed from the tree // in the interim - if (!IsInDoc() || !OwnerDoc()->IsActive()) { + if (!IsInComposedDoc() || !OwnerDoc()->IsActive()) { return; } diff --git a/dom/html/HTMLSharedObjectElement.cpp b/dom/html/HTMLSharedObjectElement.cpp index 15244b5e5e..bf8119d76a 100644 --- a/dom/html/HTMLSharedObjectElement.cpp +++ b/dom/html/HTMLSharedObjectElement.cpp @@ -83,7 +83,7 @@ HTMLSharedObjectElement::DoneAddingChildren(bool aHaveNotified) // If we're already in a document, we need to trigger the load // Otherwise, BindToTree takes care of that. - if (IsInDoc()) { + if (IsInComposedDoc()) { StartObjectLoad(aHaveNotified); } } @@ -191,7 +191,7 @@ HTMLSharedObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName, // We also don't want to start loading the object when we're not yet in // a document, just in case that the caller wants to set additional // attributes before inserting the node into the document. - if (aNotify && IsInDoc() && mIsDoneAddingChildren && + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == URIAttrName()) { return LoadObject(aNotify, true); } @@ -324,7 +324,7 @@ HTMLSharedObjectElement::StartObjectLoad(bool aNotify) { // BindToTree can call us asynchronously, and we may be removed from the tree // in the interim - if (!IsInDoc() || !OwnerDoc()->IsActive()) { + if (!IsInComposedDoc() || !OwnerDoc()->IsActive()) { return; } diff --git a/dom/html/nsGenericHTMLFrameElement.cpp b/dom/html/nsGenericHTMLFrameElement.cpp index 467c69af86..8d7537108c 100644 --- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -131,7 +131,7 @@ nsGenericHTMLFrameElement::GetContentWindow() void nsGenericHTMLFrameElement::EnsureFrameLoader() { - if (!IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) { + if (!IsInComposedDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) { // If frame loader is there, we just keep it around, cached return; } @@ -221,7 +221,7 @@ nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); - if (aDocument) { + if (IsInComposedDoc()) { NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!"); diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp index 6c9e523a80..f3f6459710 100644 --- a/dom/indexedDB/ActorsChild.cpp +++ b/dom/indexedDB/ActorsChild.cpp @@ -458,7 +458,8 @@ private: return rv; } - if (NS_WARN_IF(!JS_SetElement(aCx, array, index, value))) { + if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value, + JSPROP_ENUMERATE))) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } @@ -511,7 +512,8 @@ private: return rv; } - if (NS_WARN_IF(!JS_SetElement(aCx, array, index, value))) { + if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value, + JSPROP_ENUMERATE))) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } @@ -1100,7 +1102,7 @@ BackgroundFactoryRequestChild::Recv__delete__( IDBOpenDBRequest* request = GetOpenDBRequest(); MOZ_ASSERT(request); - + request->NoteComplete(); if (NS_WARN_IF(!result)) { diff --git a/dom/indexedDB/Key.cpp b/dom/indexedDB/Key.cpp index 046fcf5f5f..f2c23a8365 100644 --- a/dom/indexedDB/Key.cpp +++ b/dom/indexedDB/Key.cpp @@ -218,7 +218,7 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd, aTypeOffset = 0; - if (!JS_SetElement(aCx, array, index++, val)) { + if (!JS_DefineElement(aCx, array, index++, val, JSPROP_ENUMERATE)) { NS_WARNING("Failed to set array element!"); IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; diff --git a/dom/indexedDB/KeyPath.cpp b/dom/indexedDB/KeyPath.cpp index e003937791..beb19f2f1b 100644 --- a/dom/indexedDB/KeyPath.cpp +++ b/dom/indexedDB/KeyPath.cpp @@ -359,7 +359,7 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue, return rv; } - if (!JS_SetElement(aCx, arrayObj, i, value)) { + if (!JS_DefineElement(aCx, arrayObj, i, value, JSPROP_ENUMERATE)) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } @@ -471,7 +471,7 @@ KeyPath::ToJSVal(JSContext* aCx, JS::MutableHandle aValue) const return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } - if (!JS_SetElement(aCx, array, i, val)) { + if (!JS_DefineElement(aCx, array, i, val, JSPROP_ENUMERATE)) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index c88e4b7617..a5aa259fe5 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2645,6 +2645,86 @@ TabParent::GetTabId(uint64_t* aId) return NS_OK; } +class LayerTreeUpdateRunnable MOZ_FINAL + : public nsRunnable +{ + uint64_t mLayersId; + bool mActive; + +public: + explicit LayerTreeUpdateRunnable(uint64_t aLayersId, bool aActive) + : mLayersId(aLayersId), mActive(aActive) {} + +private: + NS_IMETHOD Run() { + MOZ_ASSERT(NS_IsMainThread()); + TabParent* tabParent = TabParent::GetTabParentFromLayersId(mLayersId); + if (tabParent) { + tabParent->LayerTreeUpdate(mActive); + } + return NS_OK; + } +}; + +// This observer runs on the compositor thread, so we dispatch a runnable to the +// main thread to actually dispatch the event. +class LayerTreeUpdateObserver : public CompositorUpdateObserver +{ + virtual void ObserveUpdate(uint64_t aLayersId, bool aActive) { + nsRefPtr runnable = new LayerTreeUpdateRunnable(aLayersId, aActive); + NS_DispatchToMainThread(runnable); + } +}; + +bool +TabParent::RequestNotifyLayerTreeReady() +{ + RenderFrameParent* frame = GetRenderFrame(); + if (!frame) { + return false; + } + + CompositorParent::RequestNotifyLayerTreeReady(frame->GetLayersId(), + new LayerTreeUpdateObserver()); + return true; +} + +bool +TabParent::RequestNotifyLayerTreeCleared() +{ + RenderFrameParent* frame = GetRenderFrame(); + if (!frame) { + return false; + } + + CompositorParent::RequestNotifyLayerTreeCleared(frame->GetLayersId(), + new LayerTreeUpdateObserver()); + return true; +} + +bool +TabParent::LayerTreeUpdate(bool aActive) +{ + nsCOMPtr target = do_QueryInterface(mFrameElement); + if (!target) { + NS_WARNING("Could not locate target for layer tree message."); + return true; + } + + nsCOMPtr event; + NS_NewDOMEvent(getter_AddRefs(event), mFrameElement, nullptr, nullptr); + if (aActive) { + event->InitEvent(NS_LITERAL_STRING("MozLayerTreeReady"), true, false); + } else { + event->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false); + } + event->SetTrusted(true); + event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; + bool dummy; + mFrameElement->DispatchEvent(event, &dummy); + return true; +} + bool TabParent::RecvRemotePaintIsReady() { diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 0b96dba448..c2c592fafc 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -376,6 +376,11 @@ public: bool SendLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope); + // See nsIFrameLoader requestNotifyLayerTreeReady. + bool RequestNotifyLayerTreeReady(); + bool RequestNotifyLayerTreeCleared(); + bool LayerTreeUpdate(bool aActive); + protected: bool ReceiveMessage(const nsString& aMessage, bool aSync, diff --git a/dom/mobilemessage/MmsMessage.cpp b/dom/mobilemessage/MmsMessage.cpp index 5cd8dcdcd1..57d4672bcd 100644 --- a/dom/mobilemessage/MmsMessage.cpp +++ b/dom/mobilemessage/MmsMessage.cpp @@ -587,7 +587,7 @@ MmsMessage::GetAttachments(JSContext* aCx, JS::MutableHandle aAttachm return NS_ERROR_FAILURE; } - if (!JS_SetElement(aCx, attachments, i, attachmentObj)) { + if (!JS_DefineElement(aCx, attachments, i, attachmentObj, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } } diff --git a/dom/mobilemessage/MobileMessageCallback.cpp b/dom/mobilemessage/MobileMessageCallback.cpp index 981e80641a..c6c62acd5d 100644 --- a/dom/mobilemessage/MobileMessageCallback.cpp +++ b/dom/mobilemessage/MobileMessageCallback.cpp @@ -197,7 +197,7 @@ MobileMessageCallback::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize) JS::Rooted deleteArrayObj(cx, JS_NewArrayObject(cx, aSize)); for (uint32_t i = 0; i < aSize; i++) { - JS_SetElement(cx, deleteArrayObj, i, aDeleted[i]); + JS_DefineElement(cx, deleteArrayObj, i, aDeleted[i], JSPROP_ENUMERATE); } JS::Rooted deleteArrayVal(cx, JS::ObjectValue(*deleteArrayObj)); diff --git a/dom/mobilemessage/ipc/SmsParent.cpp b/dom/mobilemessage/ipc/SmsParent.cpp index 67336230c4..f7cdbe2c5f 100644 --- a/dom/mobilemessage/ipc/SmsParent.cpp +++ b/dom/mobilemessage/ipc/SmsParent.cpp @@ -120,7 +120,7 @@ GetParamsFromSendMmsMessageRequest(JSContext* aCx, JS::Rooted obj(aCx, MmsAttachmentDataToJSObject(aCx, aRequest.attachments().ElementAt(i))); NS_ENSURE_TRUE(obj, false); - if (!JS_SetElement(aCx, attachmentArray, i, obj)) { + if (!JS_DefineElement(aCx, attachmentArray, i, obj, JSPROP_ENUMERATE)) { return false; } } diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 15ce8ce694..dc2395ff7a 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -1426,6 +1426,22 @@ CompositorParent::PostInsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) } } +/* static */ void +CompositorParent::RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver) +{ + EnsureLayerTreeMapReady(); + MonitorAutoLock lock(*sIndirectLayerTreesLock); + sIndirectLayerTrees[aLayersId].mLayerTreeReadyObserver = aObserver; +} + +/* static */ void +CompositorParent::RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver) +{ + EnsureLayerTreeMapReady(); + MonitorAutoLock lock(*sIndirectLayerTreesLock); + sIndirectLayerTrees[aLayersId].mLayerTreeClearedObserver = aObserver; +} + /** * This class handles layer updates pushed directly from child * processes to the compositor thread. It's associated with a @@ -1455,26 +1471,26 @@ public: virtual IToplevelProtocol* CloneToplevel(const InfallibleTArray& aFds, base::ProcessHandle aPeerProcess, - mozilla::ipc::ProtocolCloneContext* aCtx) override; + mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE; - virtual void ActorDestroy(ActorDestroyReason aWhy) override; + virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; // FIXME/bug 774388: work out what shutdown protocol we need. - virtual bool RecvRequestOverfill() override { return true; } - virtual bool RecvWillStop() override { return true; } - virtual bool RecvStop() override { return true; } - virtual bool RecvPause() override { return true; } - virtual bool RecvResume() override { return true; } - virtual bool RecvNotifyChildCreated(const uint64_t& child) override; - virtual bool RecvAdoptChild(const uint64_t& child) override { return false; } + virtual bool RecvRequestOverfill() MOZ_OVERRIDE { return true; } + virtual bool RecvWillStop() MOZ_OVERRIDE { return true; } + virtual bool RecvStop() MOZ_OVERRIDE { return true; } + virtual bool RecvPause() MOZ_OVERRIDE { return true; } + virtual bool RecvResume() MOZ_OVERRIDE { return true; } + virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE; + virtual bool RecvAdoptChild(const uint64_t& child) MOZ_OVERRIDE { return false; } virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, - const nsIntRect& aRect) override + const nsIntRect& aRect) MOZ_OVERRIDE { return true; } - virtual bool RecvFlushRendering() override { return true; } - virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return true; } - virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; } - virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray* intervals) override { return true; } - virtual bool RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) override + virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; } + virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) MOZ_OVERRIDE { return true; } + virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE { return true; } + virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray* intervals) MOZ_OVERRIDE { return true; } + virtual bool RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) MOZ_OVERRIDE { *aWidth = gfxPlatform::GetPlatform()->GetTileWidth(); *aHeight = gfxPlatform::GetPlatform()->GetTileHeight(); @@ -1485,15 +1501,15 @@ public: /** * Tells this CompositorParent to send a message when the compositor has received the transaction. */ - virtual bool RecvRequestNotifyAfterRemotePaint() override; + virtual bool RecvRequestNotifyAfterRemotePaint() MOZ_OVERRIDE; virtual PLayerTransactionParent* AllocPLayerTransactionParent(const nsTArray& aBackendHints, const uint64_t& aId, TextureFactoryIdentifier* aTextureFactoryIdentifier, - bool *aSuccess) override; + bool *aSuccess) MOZ_OVERRIDE; - virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) override; + virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE; virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, const uint64_t& aTransactionId, @@ -1502,15 +1518,16 @@ public: bool aIsFirstPaint, bool aScheduleComposite, uint32_t aPaintSequenceNumber, - bool aIsRepeatTransaction) override; - virtual void ForceComposite(LayerTransactionParent* aLayerTree) override; + bool aIsRepeatTransaction) MOZ_OVERRIDE; + virtual void ForceComposite(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE; + virtual void NotifyClearCachedResources(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE; virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree, - const TimeStamp& aTime) override; - virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) override; + const TimeStamp& aTime) MOZ_OVERRIDE; + virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE; virtual void GetAPZTestData(const LayerTransactionParent* aLayerTree, - APZTestData* aOutData) override; + APZTestData* aOutData) MOZ_OVERRIDE; - virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override; + virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) MOZ_OVERRIDE; void DidComposite(uint64_t aId); @@ -1737,6 +1754,12 @@ CrossProcessCompositorParent::ShadowLayersUpdated( mNotifyAfterRemotePaint = false; } + if (state->mLayerTreeReadyObserver) { + nsRefPtr observer = state->mLayerTreeReadyObserver; + state->mLayerTreeReadyObserver = nullptr; + observer->ObserveUpdate(id, true); + } + aLayerTree->SetPendingTransactionId(aTransactionId); } @@ -1823,6 +1846,23 @@ CrossProcessCompositorParent::ForceComposite(LayerTransactionParent* aLayerTree) } } +void +CrossProcessCompositorParent::NotifyClearCachedResources(LayerTransactionParent* aLayerTree) +{ + uint64_t id = aLayerTree->GetId(); + MOZ_ASSERT(id != 0); + + nsRefPtr observer; + { // scope lock + MonitorAutoLock lock(*sIndirectLayerTreesLock); + observer = sIndirectLayerTrees[id].mLayerTreeClearedObserver; + sIndirectLayerTrees[id].mLayerTreeClearedObserver = nullptr; + } + if (observer) { + observer->ObserveUpdate(id, false); + } +} + bool CrossProcessCompositorParent::SetTestSampleTime( LayerTransactionParent* aLayerTree, const TimeStamp& aTime) diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 3a3b06071d..44a0d7a23b 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -130,7 +130,18 @@ private: CancelableTask* mSetNeedsCompositeTask; }; -class CompositorParent final : public PCompositorParent, +class CompositorUpdateObserver +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorUpdateObserver); + + virtual void ObserveUpdate(uint64_t aLayersId, bool aActive) = 0; + +protected: + virtual ~CompositorUpdateObserver() {} +}; + +class CompositorParent MOZ_FINAL : public PCompositorParent, public ShadowLayersManager { NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent) @@ -305,6 +316,8 @@ public: LayerTransactionParent* mLayerTree; nsTArray mPluginData; bool mUpdatedPluginDataAvailable; + nsRefPtr mLayerTreeReadyObserver; + nsRefPtr mLayerTreeClearedObserver; }; /** @@ -319,6 +332,9 @@ public: */ static void PostInsertVsyncProfilerMarker(mozilla::TimeStamp aVsyncTimestamp); + static void RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver); + static void RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver); + float ComputeRenderIntegrity(); /** diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index 9a6362f2bb..e2408b9199 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -843,6 +843,8 @@ LayerTransactionParent::RecvClearCachedResources() // context, it's just a subtree root. We need to scope the clear // of resources to exactly that subtree, so we specify it here. mLayerManager->ClearCachedResources(mRoot); + + mShadowLayersManager->NotifyClearCachedResources(this); } return true; } diff --git a/gfx/layers/ipc/ShadowLayersManager.h b/gfx/layers/ipc/ShadowLayersManager.h index 474aa2ca0f..16414e8226 100644 --- a/gfx/layers/ipc/ShadowLayersManager.h +++ b/gfx/layers/ipc/ShadowLayersManager.h @@ -29,6 +29,8 @@ public: virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) { return nullptr; } + virtual void NotifyClearCachedResources(LayerTransactionParent* aLayerTree) { } + virtual void ForceComposite(LayerTransactionParent* aLayerTree) { } virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree, const TimeStamp& aTime) { return true; } diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 7cde5360c3..c7cc8ed262 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3294,7 +3294,7 @@ EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandlePropertyName n if (*shadowsResult == ShadowCheckFailed) return false; - if (*shadowsResult == Shadows) { + if (DOMProxyIsShadowing(*shadowsResult)) { holder.set(obj); return true; } @@ -6604,7 +6604,7 @@ TryAttachNativeGetPropStub(JSContext* cx, HandleScript script, jsbytecode* pc, } // If it's a shadowed listbase proxy property, attach stub to call Proxy::get instead. - if (isDOMProxy && domProxyShadowsResult == Shadows) { + if (isDOMProxy && DOMProxyIsShadowing(domProxyShadowsResult)) { MOZ_ASSERT(obj == holder); #if JS_HAS_NO_SUCH_METHOD if (isCallProp) diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp index de18dc0315..f15ddf1f66 100644 --- a/js/src/jit/IonCaches.cpp +++ b/js/src/jit/IonCaches.cpp @@ -1711,9 +1711,10 @@ GetPropertyIC::tryAttachProxy(JSContext* cx, HandleScript outerScript, IonScript DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx, obj, id); if (shadows == ShadowCheckFailed) return false; - if (shadows == Shadows) + if (DOMProxyIsShadowing(shadows)) return tryAttachDOMProxyShadowed(cx, outerScript, ion, obj, returnAddr, emitted); + MOZ_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique); return tryAttachDOMProxyUnshadowed(cx, outerScript, ion, obj, name, shadows == DoesntShadowUnique, returnAddr, emitted); } @@ -3078,7 +3079,7 @@ SetPropertyIC::update(JSContext* cx, HandleScript outerScript, size_t cacheIndex DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx, obj, id); if (shadows == ShadowCheckFailed) return false; - if (shadows == Shadows) { + if (DOMProxyIsShadowing(shadows)) { if (!cache.attachDOMProxyShadowed(cx, outerScript, ion, obj, returnAddr)) return false; addedSetterStub = true; diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index cef1674fdd..3e681ddbb3 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1138,14 +1138,23 @@ NukeCrossCompartmentWrappers(JSContext* cx, * The DOMProxyShadowsCheck function will be called to check if the property for * id should be gotten from the prototype, or if there is an own property that * shadows it. - * If DoesntShadow is returned then the slot at listBaseExpandoSlot should - * either be undefined or point to an expando object that would contain the own - * property. - * If DoesntShadowUnique is returned then the slot at listBaseExpandoSlot should - * contain a private pointer to a ExpandoAndGeneration, which contains a - * JS::Value that should either be undefined or point to an expando object, and - * a uint32 value. If that value changes then the IC for getting a property will - * be invalidated. + * * If ShadowsViaDirectExpando is returned, then the slot at + * listBaseExpandoSlot contains an expando object which has the property in + * question. + * * If ShadowsViaIndirectExpando is returned, then the slot at + * listBaseExpandoSlot contains a private pointer to an ExpandoAndGeneration + * and the expando object in the ExpandoAndGeneration has the property in + * question. + * * If DoesntShadow is returned then the slot at listBaseExpandoSlot should + * either be undefined or point to an expando object that would contain the + * own property. + * * If DoesntShadowUnique is returned then the slot at listBaseExpandoSlot + * should contain a private pointer to a ExpandoAndGeneration, which contains + * a JS::Value that should either be undefined or point to an expando object, + * and a uint32 value. If that value changes then the IC for getting a + * property will be invalidated. + * * If Shadows is returned, that means the property is an own property of the + * proxy but doesn't live on the expando object. */ struct ExpandoAndGeneration { @@ -1178,7 +1187,9 @@ typedef enum DOMProxyShadowsResult { ShadowCheckFailed, Shadows, DoesntShadow, - DoesntShadowUnique + DoesntShadowUnique, + ShadowsViaDirectExpando, + ShadowsViaIndirectExpando } DOMProxyShadowsResult; typedef DOMProxyShadowsResult (* DOMProxyShadowsCheck)(JSContext* cx, JS::HandleObject object, JS::HandleId id); @@ -1189,6 +1200,11 @@ SetDOMProxyInformation(const void* domProxyHandlerFamily, uint32_t domProxyExpan const void* GetDOMProxyHandlerFamily(); uint32_t GetDOMProxyExpandoSlot(); DOMProxyShadowsCheck GetDOMProxyShadowsCheck(); +inline bool DOMProxyIsShadowing(DOMProxyShadowsResult result) { + return result == Shadows || + result == ShadowsViaDirectExpando || + result == ShadowsViaIndirectExpando; +} /* Implemented in jsdate.cpp. */ diff --git a/js/xpconnect/public/nsTArrayHelpers.h b/js/xpconnect/public/nsTArrayHelpers.h index 6bed2cee38..aa0ce8198b 100644 --- a/js/xpconnect/public/nsTArrayHelpers.h +++ b/js/xpconnect/public/nsTArrayHelpers.h @@ -34,8 +34,8 @@ nsTArrayToJSArray(JSContext* aCx, const nsTArray& aSourceArray, rv = nsContentUtils::WrapNative(aCx, obj, &wrappedVal); NS_ENSURE_SUCCESS(rv, rv); - if (!JS_SetElement(aCx, arrayObj, index, wrappedVal)) { - NS_WARNING("JS_SetElement failed!"); + if (!JS_DefineElement(aCx, arrayObj, index, wrappedVal, JSPROP_ENUMERATE)) { + NS_WARNING("JS_DefineElement failed!"); return NS_ERROR_FAILURE; } } @@ -74,8 +74,8 @@ nsTArrayToJSArray(JSContext* aCx, return NS_ERROR_OUT_OF_MEMORY; } - if (!JS_SetElement(aCx, arrayObj, index, s)) { - NS_WARNING("JS_SetElement failed!"); + if (!JS_DefineElement(aCx, arrayObj, index, s, JSPROP_ENUMERATE)) { + NS_WARNING("JS_DefineElement failed!"); return NS_ERROR_FAILURE; } } diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp index 94e6a492cb..136d264470 100644 --- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -1280,7 +1280,7 @@ XPCConvert::NativeArray2JS(MutableHandleValue d, const void** s, PR_BEGIN_MACRO \ for (i = 0; i < count; i++) { \ if (!NativeData2JS(¤t, ((_t*)*s)+i, type, iid, pErr) || \ - !JS_SetElement(cx, array, i, current)) \ + !JS_DefineElement(cx, array, i, current, JSPROP_ENUMERATE)) \ goto failure; \ } \ PR_END_MACRO diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index cf76f9a68d..c7a47cb873 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -8986,13 +8986,6 @@ PresShell::WillPaintWindow() void PresShell::DidPaintWindow() { - if (mDocument) { - nsCOMPtr window = mDocument->GetWindow(); - if (window) { - window->SendAfterRemotePaintIfRequested(); - } - } - nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext(); if (rootPresContext != mPresContext) { // This could be a popup's presshell. No point in notifying XPConnect diff --git a/storage/src/mozStorageStatementRow.cpp b/storage/src/mozStorageStatementRow.cpp index 72425f9a70..24cb503763 100644 --- a/storage/src/mozStorageStatementRow.cpp +++ b/storage/src/mozStorageStatementRow.cpp @@ -95,7 +95,7 @@ StatementRow::GetProperty(nsIXPConnectWrappedNative *aWrapper, // Copy the blob over to the JS array. for (uint32_t i = 0; i < length; i++) { - if (!::JS_SetElement(aCtx, scope, i, blob[i])) { + if (!::JS_DefineElement(aCtx, scope, i, blob[i], JSPROP_ENUMERATE)) { *_retval = false; return NS_OK; } diff --git a/toolkit/components/places/PlaceInfo.cpp b/toolkit/components/places/PlaceInfo.cpp index 29ac5bf5db..dac99fcf8c 100644 --- a/toolkit/components/places/PlaceInfo.cpp +++ b/toolkit/components/places/PlaceInfo.cpp @@ -119,7 +119,7 @@ PlaceInfo::GetVisits(JSContext* aContext, JS::Rooted jsobj(aContext, wrapper->GetJSObject()); NS_ENSURE_STATE(jsobj); - bool rc = JS_SetElement(aContext, visits, idx, jsobj); + bool rc = JS_DefineElement(aContext, visits, idx, jsobj, JSPROP_ENUMERATE); NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED); } diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index d628c660f5..4ffc419c60 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -1739,8 +1739,8 @@ TelemetryImpl::ReflectSQL(const SlowSQLEntryType *entry, if (!arrayObj) { return false; } - return (JS_SetElement(cx, arrayObj, 0, stat->hitCount) - && JS_SetElement(cx, arrayObj, 1, stat->totalTime) + return (JS_DefineElement(cx, arrayObj, 0, stat->hitCount, JSPROP_ENUMERATE) + && JS_DefineElement(cx, arrayObj, 1, stat->totalTime, JSPROP_ENUMERATE) && JS_DefineProperty(cx, obj, sql.BeginReading(), arrayObj, JSPROP_ENUMERATE)); } @@ -2328,13 +2328,16 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle ret) const size_t length = stacks.GetStackCount(); for (size_t i = 0; i < length; ++i) { - if (!JS_SetElement(cx, durationArray, i, mHangReports.GetDuration(i))) { + if (!JS_DefineElement(cx, durationArray, i, mHangReports.GetDuration(i), + JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } - if (!JS_SetElement(cx, systemUptimeArray, i, mHangReports.GetSystemUptime(i))) { + if (!JS_DefineElement(cx, systemUptimeArray, i, mHangReports.GetSystemUptime(i), + JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } - if (!JS_SetElement(cx, firefoxUptimeArray, i, mHangReports.GetFirefoxUptime(i))) { + if (!JS_DefineElement(cx, firefoxUptimeArray, i, mHangReports.GetFirefoxUptime(i), + JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } const nsTArray& annotationInfo = @@ -2347,7 +2350,7 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle ret) } JS::RootedValue indexValue(cx); indexValue.setNumber(annotationInfo[iterIndex].mHangIndex); - if (!JS_SetElement(cx, keyValueArray, 0, indexValue)) { + if (!JS_DefineElement(cx, keyValueArray, 0, indexValue, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } JS::Rooted jsAnnotation(cx, JS_NewPlainObject(cx)); @@ -2369,11 +2372,11 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle ret) return NS_ERROR_FAILURE; } } - if (!JS_SetElement(cx, keyValueArray, 1, jsAnnotation)) { + if (!JS_DefineElement(cx, keyValueArray, 1, jsAnnotation, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } - if (!JS_SetElement(cx, annotationsArray, iterIndex, - keyValueArray)) { + if (!JS_DefineElement(cx, annotationsArray, iterIndex, + keyValueArray, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } } @@ -2409,7 +2412,8 @@ CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) { if (!moduleInfoArray) { return nullptr; } - if (!JS_SetElement(cx, moduleArray, moduleIndex, moduleInfoArray)) { + if (!JS_DefineElement(cx, moduleArray, moduleIndex, moduleInfoArray, + JSPROP_ENUMERATE)) { return nullptr; } @@ -2420,7 +2424,7 @@ CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) { if (!str) { return nullptr; } - if (!JS_SetElement(cx, moduleInfoArray, index++, str)) { + if (!JS_DefineElement(cx, moduleInfoArray, index++, str, JSPROP_ENUMERATE)) { return nullptr; } @@ -2429,7 +2433,7 @@ CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) { if (!id) { return nullptr; } - if (!JS_SetElement(cx, moduleInfoArray, index++, id)) { + if (!JS_DefineElement(cx, moduleInfoArray, index++, id, JSPROP_ENUMERATE)) { return nullptr; } } @@ -2451,7 +2455,7 @@ CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) { return nullptr; } - if (!JS_SetElement(cx, reportArray, i, pcArray)) { + if (!JS_DefineElement(cx, reportArray, i, pcArray, JSPROP_ENUMERATE)) { return nullptr; } @@ -2465,13 +2469,14 @@ CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) { } int modIndex = (std::numeric_limits::max() == frame.mModIndex) ? -1 : frame.mModIndex; - if (!JS_SetElement(cx, framePair, 0, modIndex)) { + if (!JS_DefineElement(cx, framePair, 0, modIndex, JSPROP_ENUMERATE)) { return nullptr; } - if (!JS_SetElement(cx, framePair, 1, static_cast(frame.mOffset))) { + if (!JS_DefineElement(cx, framePair, 1, static_cast(frame.mOffset), + JSPROP_ENUMERATE)) { return nullptr; } - if (!JS_SetElement(cx, pcArray, pcIndex, framePair)) { + if (!JS_DefineElement(cx, pcArray, pcIndex, framePair, JSPROP_ENUMERATE)) { return nullptr; } }