summaryrefslogtreecommitdiffstats
path: root/dom/base
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base')
-rw-r--r--dom/base/Element.cpp36
-rw-r--r--dom/base/Element.h2
-rw-r--r--dom/base/nsImageLoadingContent.cpp36
-rw-r--r--dom/base/nsImageLoadingContent.h10
4 files changed, 64 insertions, 20 deletions
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 52d06b0f8..79b36a314 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1230,6 +1230,42 @@ Element::GetAttribute(const nsAString& aName, DOMString& aReturn)
}
}
+bool
+Element::ToggleAttribute(const nsAString& aName,
+ const Optional<bool>& aForce,
+ ErrorResult& aError)
+{
+ aError = nsContentUtils::CheckQName(aName, false);
+ if (aError.Failed()) {
+ return false;
+ }
+
+ nsAutoString nameToUse;
+ const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
+ if (!name) {
+ if (aForce.WasPassed() && !aForce.Value()) {
+ return false;
+ }
+ nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(nameToUse);
+ if (!nameAtom) {
+ aError.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return false;
+ }
+ aError = SetAttr(kNameSpaceID_None, nameAtom, EmptyString(), true);
+ return true;
+ }
+ if (aForce.WasPassed() && aForce.Value()) {
+ return true;
+ }
+ // Hold a strong reference here so that the atom or nodeinfo doesn't go
+ // away during UnsetAttr. If it did UnsetAttr would be left with a
+ // dangling pointer as argument without knowing it.
+ nsAttrName tmp(*name);
+
+ aError = UnsetAttr(name->NamespaceID(), name->LocalName(), true);
+ return false;
+}
+
void
Element::SetAttribute(const nsAString& aName,
const nsAString& aValue,
diff --git a/dom/base/Element.h b/dom/base/Element.h
index 049984d1b..c269ab14a 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -686,6 +686,8 @@ public:
void GetAttributeNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
nsAString& aReturn);
+ bool ToggleAttribute(const nsAString& aName, const Optional<bool>& aForce,
+ ErrorResult& aError);
void SetAttribute(const nsAString& aName, const nsAString& aValue,
ErrorResult& aError);
void SetAttributeNS(const nsAString& aNamespaceURI,
diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp
index d25dd6319..0c6c37b44 100644
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -94,8 +94,7 @@ nsImageLoadingContent::nsImageLoadingContent()
mNewRequestsWillNeedAnimationReset(false),
mStateChangerDepth(0),
mCurrentRequestRegistered(false),
- mPendingRequestRegistered(false),
- mFrameCreateCalled(false)
+ mPendingRequestRegistered(false)
{
if (!nsContentUtils::GetImgLoaderForChannel(nullptr, nullptr)) {
mLoadingEnabled = false;
@@ -489,10 +488,8 @@ nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
{
NS_ASSERTION(aFrame, "aFrame is null");
- mFrameCreateCalled = true;
-
- TrackImage(mCurrentRequest);
- TrackImage(mPendingRequest);
+ TrackImage(mCurrentRequest, aFrame);
+ TrackImage(mPendingRequest, aFrame);
// We need to make sure that our image request is registered, if it should
// be registered.
@@ -513,8 +510,6 @@ nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame)
{
NS_ASSERTION(aFrame, "aFrame is null");
- mFrameCreateCalled = false;
-
// We need to make sure that our image request is deregistered.
nsPresContext* presContext = GetFramePresContext();
if (mCurrentRequest) {
@@ -1486,7 +1481,8 @@ nsImageLoadingContent::OnVisibilityChange(Visibility aNewVisibility,
}
void
-nsImageLoadingContent::TrackImage(imgIRequest* aImage)
+nsImageLoadingContent::TrackImage(imgIRequest* aImage,
+ nsIFrame* aFrame /*= nullptr */)
{
if (!aImage)
return;
@@ -1499,13 +1495,21 @@ nsImageLoadingContent::TrackImage(imgIRequest* aImage)
return;
}
- // We only want to track this request if we're visible. Ordinarily we check
- // the visible count, but that requires a frame; in cases where
- // GetOurPrimaryFrame() cannot obtain a frame (e.g. <feImage>), we assume
- // we're visible if FrameCreated() was called.
- nsIFrame* frame = GetOurPrimaryFrame();
- if ((frame && frame->GetVisibility() == Visibility::APPROXIMATELY_NONVISIBLE) ||
- (!frame && !mFrameCreateCalled)) {
+ if (!aFrame) {
+ aFrame = GetOurPrimaryFrame();
+ }
+
+ /* This line is deceptively simple. It hides a lot of subtlety. Before we
+ * create an nsImageFrame we call nsImageFrame::ShouldCreateImageFrameFor
+ * to determine if we should create an nsImageFrame or create a frame based
+ * on the display of the element (ie inline, block, etc). Inline, block, etc
+ * frames don't register for visibility tracking so they will return UNTRACKED
+ * from GetVisibility(). So this line is choosing to mark such images as
+ * visible. Once the image loads we will get an nsImageFrame and the proper
+ * visibility. This is a pitfall of tracking the visibility on the frames
+ * instead of the content node.
+ */
+ if (!aFrame || aFrame->GetVisibility() == Visibility::APPROXIMATELY_NONVISIBLE) {
return;
}
diff --git a/dom/base/nsImageLoadingContent.h b/dom/base/nsImageLoadingContent.h
index 85db2bd2c..5f7daff72 100644
--- a/dom/base/nsImageLoadingContent.h
+++ b/dom/base/nsImageLoadingContent.h
@@ -364,6 +364,11 @@ protected:
*
* No-op if aImage is null.
*
+ * @param aFrame If called from FrameCreated the frame passed to FrameCreated.
+ * This is our frame, but at the time of the FrameCreated call
+ * our primary frame pointer hasn't been set yet, so this is
+ * only way to get our frame.
+ *
* @param aNonvisibleAction A requested action if the frame has become
* nonvisible. If Nothing(), no action is
* requested. If DISCARD_IMAGES is specified, the
@@ -371,7 +376,7 @@ protected:
* associated with to discard their surfaces if
* possible.
*/
- void TrackImage(imgIRequest* aImage);
+ void TrackImage(imgIRequest* aImage, nsIFrame* aFrame = nullptr);
void UntrackImage(imgIRequest* aImage,
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
@@ -454,9 +459,6 @@ private:
// registered with the refresh driver.
bool mCurrentRequestRegistered;
bool mPendingRequestRegistered;
-
- // True when FrameCreate has been called but FrameDestroy has not.
- bool mFrameCreateCalled;
};
#endif // nsImageLoadingContent_h__