Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(650)

Unified Diff: Source/core/html/HTMLImageElement.cpp

Issue 200923002: Post a microtask to load <img> elements. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: all tests fixed Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/html/HTMLImageElement.cpp
diff --git a/Source/core/html/HTMLImageElement.cpp b/Source/core/html/HTMLImageElement.cpp
index ff90239a68388aead040d64d21e63c905971801b..a759371bb146c40320a204e9c745075e42cbf070 100644
--- a/Source/core/html/HTMLImageElement.cpp
+++ b/Source/core/html/HTMLImageElement.cpp
@@ -26,8 +26,10 @@
#include "CSSPropertyNames.h"
#include "HTMLNames.h"
#include "RuntimeEnabledFeatures.h"
+#include "bindings/v8/DOMWrapperWorld.h"
#include "bindings/v8/ScriptEventListener.h"
#include "core/dom/Attribute.h"
+#include "core/dom/Microtask.h"
#include "core/fetch/ImageResource.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLCanvasElement.h"
@@ -36,9 +38,20 @@
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/html/parser/HTMLSrcsetParser.h"
#include "core/rendering/RenderImage.h"
+#include "wtf/Vector.h"
+#include <v8.h>
using namespace std;
+namespace {
+typedef Vector<WebCore::HTMLImageElement*> PendingUpdateQueueType;
+static PendingUpdateQueueType& PendingUpdateQueue()
+{
+ DEFINE_STATIC_LOCAL(Vector<WebCore::HTMLImageElement*>, pendingUpdateFromElementCalls, ());
+ return pendingUpdateFromElementCalls;
+}
+}
+
namespace WebCore {
using namespace HTMLNames;
@@ -49,6 +62,7 @@ HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form)
, m_compositeOperator(CompositeSourceOver)
, m_imageDevicePixelRatio(1.0f)
, m_formWasSetByParser(false)
+ , m_pendingUpdate(PendingUpdateNone)
{
ScriptWrappable::init(this);
if (form && form->inDocument()) {
@@ -73,6 +87,7 @@ HTMLImageElement::~HTMLImageElement()
{
if (m_form)
m_form->disassociate(*this);
+ cancelPendingUpdate();
abarth-chromium 2014/04/01 23:57:14 This algorithm is O(N^2) when tearing down the doc
}
PassRefPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document& document, int width, int height)
@@ -163,7 +178,7 @@ void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
if (renderer() && renderer()->isImage())
toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRatio);
}
- m_imageLoader.updateFromElementIgnoringPreviousError();
+ enqueueUpdate(PendingUpdateIgnoreError);
} else if (name == usemapAttr) {
setIsLink(!value.isNull());
} else if (name == compositeAttr) {
@@ -235,7 +250,7 @@ Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
// If we have been inserted from a renderer-less document,
// our loader may have not fetched the image, so do it now.
if (insertionPoint->inDocument() && !m_imageLoader.image())
- m_imageLoader.updateFromElement();
+ enqueueUpdate(PendingUpdateNormal);
return HTMLElement::insertedInto(insertionPoint);
}
@@ -383,13 +398,17 @@ int HTMLImageElement::y() const
bool HTMLImageElement::complete() const
{
- return m_imageLoader.imageComplete();
+ return m_imageLoader.imageComplete() && !hasPendingUpdate();
}
void HTMLImageElement::didMoveToNewDocument(Document& oldDocument)
{
m_imageLoader.elementDidMoveToNewDocument();
HTMLElement::didMoveToNewDocument(oldDocument);
+ if (hasPendingUpdate()) {
+ document().incrementLoadEventDelayCount();
+ oldDocument.decrementLoadEventDelayCount();
+ }
}
bool HTMLImageElement::isServerMap() const
@@ -472,4 +491,80 @@ FloatSize HTMLImageElement::defaultDestinationSize() const
return size;
}
+void HTMLImageElement::enqueueUpdate(PendingUpdateType type)
+{
+ ASSERT(type != PendingUpdateNone);
+
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ bool isIsolatedWorld = false;
+ if (isolate && isolate->InContext()) {
+ if (DOMWrapperWorld::current(isolate).isIsolatedWorld())
+ isIsolatedWorld = true;
+ }
abarth-chromium 2014/04/01 23:57:14 The HTMLImageElement shouldn't have any knowledge
+
+ if (m_imageLoader.shouldLoadImmediately() || isIsolatedWorld) {
abarth-chromium 2014/04/01 23:57:14 It's wrong to make image loading work differently
+ if (hasPendingUpdate())
+ cancelPendingUpdate();
+ if (type == PendingUpdateNormal)
+ m_imageLoader.updateFromElement();
+ else
+ m_imageLoader.updateFromElementIgnoringPreviousError();
+ return;
+ }
+
+ if (hasPendingUpdate()) {
+ ASSERT(PendingUpdateQueue().contains(this));
+ if (m_pendingUpdate == PendingUpdateNormal && type == PendingUpdateIgnoreError)
+ m_pendingUpdate = PendingUpdateIgnoreError;
+ } else {
+ document().incrementLoadEventDelayCount();
+ PendingUpdateQueue().append(this);
+ m_pendingUpdate = type;
+ }
+ if (PendingUpdateQueue().size() == 1)
+ Microtask::enqueueMicrotask(&processUpdateFromElementQueue);
+}
+
+void HTMLImageElement::cancelPendingUpdate()
+{
+ if (hasPendingUpdate()) {
+ size_t pos = PendingUpdateQueue().find(this);
+ ASSERT(pos != kNotFound);
+ PendingUpdateQueue().remove(pos);
+ m_pendingUpdate = PendingUpdateNone;
+ document().decrementLoadEventDelayCount();
+ }
+}
+
+/* static */ void HTMLImageElement::processUpdateFromElementQueue()
abarth-chromium 2014/04/01 23:57:14 We don't use /* static */ comments in Blink
+{
+ PendingUpdateQueueType pending;
+ pending.swap(PendingUpdateQueue());
+
+ // We keep this vector separately, because we can only call
+ // decrementLoadEventDelayCount after we've updated all image elements
+ // because the load event may destroy image elements.
+ Vector<RefPtr<Document> > documents;
+
+ {
+ PendingUpdateQueueType::const_iterator i, end;
+ for (i = pending.begin(), end = pending.end(); i != end; ++i) {
+ RefPtr<HTMLImageElement> current = *i;
+ if (current->m_pendingUpdate == PendingUpdateIgnoreError) {
+ current->m_pendingUpdate = PendingUpdateNone;
+ current->m_imageLoader.updateFromElementIgnoringPreviousError();
+ documents.append(&current->document());
+ } else {
+ ASSERT(current->m_pendingUpdate == PendingUpdateNormal);
+ current->m_pendingUpdate = PendingUpdateNone;
+ current->m_imageLoader.updateFromElement();
+ documents.append(&current->document());
+ }
+ }
+ }
+ Vector<RefPtr<Document> >::const_iterator i, end;
+ for (i = documents.begin(), end = documents.end(); i != end; ++i) {
+ (*i)->decrementLoadEventDelayCount();
+ }
+}
}

Powered by Google App Engine
This is Rietveld 408576698