Changeset 224378 in webkit
- Timestamp:
- Nov 2, 2017 8:48:11 PM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r224374 r224378 1 2017-11-01 Ryosuke Niwa <rniwa@webkit.org> 2 3 Assert that updateStyle and updateLayout are only called when it's safe to dispatch events 4 https://bugs.webkit.org/show_bug.cgi?id=179157 5 <rdar://problem/35144778> 6 7 Reviewed by Zalan Bujtas. 8 9 Added assertions to Document::updateStyleIfNeeded and Document::updateLayout that these functions are 10 only called when NoEventDispatchAssertion::isEventAllowedInMainThread() is true with two exceptions: 11 1. Inside SVGImage::draw which triggers a layout on a separate document. 12 2. While doing a nested layout for a frame flattening. 13 14 No new tests since there should be no behavioral changes. 15 16 * dom/ContainerNode.cpp: 17 (NoEventDispatchAssertion::DisableAssertionsInScope::s_existingCount): Deleted. This is now an instance 18 variable of DisableAssertionsInScope. 19 (ContainerNode::removeNodeWithScriptAssertion): Moved childrenChanged out of the scope since it could 20 invoke respondToChangedSelection via HTMLTextAreaElement::childrenChanged. 21 * dom/Document.cpp: 22 (WebCore::Document::updateStyleIfNeeded): Added the assertion. Allow updateWidgetPositions() to call 23 this function but exit early when checking needsStyleRecalc(). 24 (WebCore::Document::updateLayout): Added the assertion. 25 * dom/NoEventDispatchAssertion.h: 26 (WebCore::NoEventDispatchAssertion::DisableAssertionsInScope::DisableAssertionsInScope): Made this class 27 store the original value of s_count as an instance variable to support re-entrancy. 28 (WebCore::NoEventDispatchAssertion::DisableAssertionsInScope::~DisableAssertionsInScope): Ditto. 29 * page/LayoutContext.cpp: 30 (WebCore::LayoutContext::runOrScheduleAsynchronousTasks): Temporarily disable the assertion. This is safe 31 since SVGImage has its own document. 32 * svg/SVGSVGElement.cpp: 33 (WebCore::checkIntersectionWithoutUpdatingLayout): Extracted out of SVGSVGElement::checkIntersection. 34 (WebCore::checkEnclosureWithoutUpdatingLayout): Extracted out of SVGSVGElement::checkEnclosure. 35 (WebCore::SVGSVGElement::getIntersectionList): Use checkIntersectionWithoutUpdatingLayout to avoid 36 calling updateLayoutIgnorePendingStylesheets while iterating over elements. 37 (WebCore::SVGSVGElement::getEnclosureList): Ditto. 38 (WebCore::SVGSVGElement::checkIntersection): 39 (WebCore::SVGSVGElement::checkEnclosure): 40 * svg/graphics/SVGImage.cpp: 41 (WebCore::SVGImage::draw): Temporarily disable the assertion. This is safe as SVGImage has its own page. 42 1 43 2017-11-02 Alex Christensen <achristensen@webkit.org> 2 44 -
trunk/Source/WebCore/dom/ContainerNode.cpp
r224356 r224378 73 73 #if !ASSERT_DISABLED 74 74 unsigned NoEventDispatchAssertion::s_count = 0; 75 unsigned NoEventDispatchAssertion::DisableAssertionsInScope::s_existingCount = 0;76 75 NoEventDispatchAssertion::EventAllowedScope* NoEventDispatchAssertion::EventAllowedScope::s_currentScope = nullptr; 77 76 #endif … … 144 143 return false; 145 144 146 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;147 NoEventDispatchAssertion::InMainThread assertNoEventDispatch;148 149 document().nodeWillBeRemoved(childToRemove);150 151 ASSERT_WITH_SECURITY_IMPLICATION(childToRemove.parentNode() == this);152 ASSERT(!childToRemove.isDocumentFragment());153 154 RefPtr<Node> previousSibling = childToRemove.previousSibling();155 RefPtr<Node> nextSibling = childToRemove.nextSibling();156 removeBetween(previousSibling.get(), nextSibling.get(), childToRemove);157 notifyChildNodeRemoved(*this, childToRemove);158 159 145 ChildChange change; 160 change.type = is<Element>(childToRemove) ? ElementRemoved : (is<Text>(childToRemove) ? TextRemoved : NonContentsChildRemoved); 161 change.previousSiblingElement = (!previousSibling || is<Element>(*previousSibling)) ? downcast<Element>(previousSibling.get()) : ElementTraversal::previousSibling(*previousSibling); 162 change.nextSiblingElement = (!nextSibling || is<Element>(*nextSibling)) ? downcast<Element>(nextSibling.get()) : ElementTraversal::nextSibling(*nextSibling); 163 change.source = source; 146 { 147 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; 148 NoEventDispatchAssertion::InMainThread assertNoEventDispatch; 149 150 document().nodeWillBeRemoved(childToRemove); 151 152 ASSERT_WITH_SECURITY_IMPLICATION(childToRemove.parentNode() == this); 153 ASSERT(!childToRemove.isDocumentFragment()); 154 155 RefPtr<Node> previousSibling = childToRemove.previousSibling(); 156 RefPtr<Node> nextSibling = childToRemove.nextSibling(); 157 removeBetween(previousSibling.get(), nextSibling.get(), childToRemove); 158 notifyChildNodeRemoved(*this, childToRemove); 159 160 change.type = is<Element>(childToRemove) ? ElementRemoved : (is<Text>(childToRemove) ? TextRemoved : NonContentsChildRemoved); 161 change.previousSiblingElement = (!previousSibling || is<Element>(*previousSibling)) ? downcast<Element>(previousSibling.get()) : ElementTraversal::previousSibling(*previousSibling); 162 change.nextSiblingElement = (!nextSibling || is<Element>(*nextSibling)) ? downcast<Element>(nextSibling.get()) : ElementTraversal::nextSibling(*nextSibling); 163 change.source = source; 164 } 165 166 // FIXME: Move childrenChanged into NoEventDispatchAssertion block. 164 167 childrenChanged(change); 165 168 -
trunk/Source/WebCore/dom/Document.cpp
r224356 r224378 1924 1924 bool Document::updateStyleIfNeeded() 1925 1925 { 1926 RefPtr<FrameView> frameView = view(); 1926 1927 { 1927 1928 NoEventDispatchAssertion::InMainThread noEventDispatchAssertion; 1928 1929 ASSERT(isMainThread()); 1929 ASSERT(! view() || !view()->isPainting());1930 1931 if (! view() || view()->layoutContext().isInRenderTreeLayout())1930 ASSERT(!frameView || !frameView->isPainting()); 1931 1932 if (!frameView || frameView->layoutContext().isInRenderTreeLayout()) 1932 1933 return false; 1933 1934 … … 1938 1939 } 1939 1940 1941 // The early exit for needsStyleRecalc() is needed when updateWidgetPositions() is called in runOrScheduleAsynchronousTasks(). 1942 ASSERT(NoEventDispatchAssertion::InMainThread::isEventAllowed() || (frameView && frameView->isInChildFrameWithFrameFlattening())); 1943 1940 1944 resolveStyle(); 1941 1945 return true; … … 1944 1948 void Document::updateLayout() 1945 1949 { 1950 ASSERT(isMainThread()); 1946 1951 ASSERT(LayoutDisallowedScope::isLayoutAllowed()); 1947 ASSERT(isMainThread());1948 1952 1949 1953 RefPtr<FrameView> frameView = view(); … … 1953 1957 return; 1954 1958 } 1959 ASSERT(NoEventDispatchAssertion::InMainThread::isEventAllowed() || (frameView && frameView->isInChildFrameWithFrameFlattening())); 1960 1955 1961 1956 1962 RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView()); -
trunk/Source/WebCore/dom/NoEventDispatchAssertion.h
r224356 r224378 139 139 140 140 #if !ASSERT_DISABLED 141 // FIXME: Remove this class once the sync layout inside SVGImage::draw is removed. 141 142 class DisableAssertionsInScope { 142 143 public: 143 144 DisableAssertionsInScope() 144 145 { 145 if (!isMainThread()) 146 return; 147 s_existingCount = s_count; 148 s_count = 0; 146 ASSERT(isMainThread()); 147 std::swap(s_count, m_originalCount); 149 148 } 150 149 151 150 ~DisableAssertionsInScope() 152 151 { 153 s_count = s_existingCount; 154 s_existingCount = 0; 152 s_count = m_originalCount; 155 153 } 156 154 private: 157 WEBCORE_EXPORT static unsigned s_existingCount;155 unsigned m_originalCount { 0 }; 158 156 }; 159 157 #else -
trunk/Source/WebCore/svg/SVGSVGElement.cpp
r223947 r224378 324 324 } 325 325 326 Ref<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(SVGRect& rect, SVGElement* referenceElement, bool (*checkFunction)( RefPtr<SVGElement>&&, SVGRect&))326 Ref<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(SVGRect& rect, SVGElement* referenceElement, bool (*checkFunction)(SVGElement&, SVGRect&)) 327 327 { 328 328 Vector<Ref<Element>> elements; 329 329 for (auto& element : descendantsOfType<SVGElement>(referenceElement ? *referenceElement : *this)) { 330 if (checkFunction( &element, rect))330 if (checkFunction(element, rect)) 331 331 elements.append(element); 332 332 } … … 334 334 } 335 335 336 static bool checkIntersectionWithoutUpdatingLayout(SVGElement& element, SVGRect& rect) 337 { 338 return RenderSVGModelObject::checkIntersection(element.renderer(), rect.propertyReference()); 339 } 340 341 static bool checkEnclosureWithoutUpdatingLayout(SVGElement& element, SVGRect& rect) 342 { 343 return RenderSVGModelObject::checkEnclosure(element.renderer(), rect.propertyReference()); 344 } 345 336 346 Ref<NodeList> SVGSVGElement::getIntersectionList(SVGRect& rect, SVGElement* referenceElement) 337 347 { 338 348 document().updateLayoutIgnorePendingStylesheets(); 339 return collectIntersectionOrEnclosureList(rect, referenceElement, checkIntersection );349 return collectIntersectionOrEnclosureList(rect, referenceElement, checkIntersectionWithoutUpdatingLayout); 340 350 } 341 351 … … 343 353 { 344 354 document().updateLayoutIgnorePendingStylesheets(); 345 return collectIntersectionOrEnclosureList(rect, referenceElement, checkEnclosure );355 return collectIntersectionOrEnclosureList(rect, referenceElement, checkEnclosureWithoutUpdatingLayout); 346 356 } 347 357 … … 351 361 return false; 352 362 element->document().updateLayoutIgnorePendingStylesheets(); 353 return RenderSVGModelObject::checkIntersection(element->renderer(), rect.propertyReference());363 return checkIntersectionWithoutUpdatingLayout(*element, rect); 354 364 } 355 365 … … 359 369 return false; 360 370 element->document().updateLayoutIgnorePendingStylesheets(); 361 return RenderSVGModelObject::checkEnclosure(element->renderer(), rect.propertyReference());371 return checkEnclosureWithoutUpdatingLayout(*element, rect); 362 372 } 363 373 -
trunk/Source/WebCore/svg/SVGSVGElement.h
r223947 r224378 154 154 Frame* frameForCurrentScale() const; 155 155 void inheritViewAttributes(const SVGViewElement&); 156 Ref<NodeList> collectIntersectionOrEnclosureList(SVGRect&, SVGElement*, bool (*checkFunction)( RefPtr<SVGElement>&&, SVGRect&));156 Ref<NodeList> collectIntersectionOrEnclosureList(SVGRect&, SVGElement*, bool (*checkFunction)(SVGElement&, SVGRect&)); 157 157 158 158 bool m_useCurrentView { false }; -
trunk/Source/WebCore/svg/graphics/SVGImage.cpp
r224150 r224378 44 44 #include "LibWebRTCProvider.h" 45 45 #include "MainFrame.h" 46 #include "NoEventDispatchAssertion.h" 46 47 #include "Page.h" 47 48 #include "PageConfiguration.h" … … 311 312 view->resize(containerSize()); 312 313 313 if (view->needsLayout()) 314 view->layoutContext().layout(); 314 { 315 NoEventDispatchAssertion::DisableAssertionsInScope disabledScope; 316 if (view->needsLayout()) 317 view->layoutContext().layout(); 318 } 315 319 316 320 view->paint(context, intersection(context.clipBounds(), enclosingIntRect(srcRect)));
Note: See TracChangeset
for help on using the changeset viewer.