Commit 3bf96911 authored by Alberto Garcia's avatar Alberto Garcia
Browse files

Update upstream source from tag 'upstream/2.28.4'

Update to upstream version '2.28.4'
with Debian dir ec47417be943a3377c0c22af7bceb2add761a0d2
parents c70e3e77 f4931007
......@@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">JavaScriptCore GLib Reference Manual</p></th></tr></table></div>
<div><p class="releaseinfo">for JavaScriptCore 2.28.3</p></div>
<div><p class="releaseinfo">for JavaScriptCore 2.28.4</p></div>
</div>
<hr>
</div>
......
......@@ -175,7 +175,7 @@ have included when compiling your code.</p>
<hr>
<div class="refsect2">
<a name="JSC-MICRO-VERSION:CAPS"></a><h3>JSC_MICRO_VERSION</h3>
<pre class="programlisting">#define JSC_MICRO_VERSION (3)
<pre class="programlisting">#define JSC_MICRO_VERSION (4)
</pre>
</div>
</div>
......
......@@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">WebKitGTK Reference Manual</p></th></tr></table></div>
<div><p class="releaseinfo">for WebKitGTK 2.28.3</p></div>
<div><p class="releaseinfo">for WebKitGTK 2.28.4</p></div>
</div>
<hr>
</div>
......
......@@ -213,7 +213,7 @@ against at application run time.</p>
<hr>
<div class="refsect2">
<a name="WEBKIT-MICRO-VERSION:CAPS"></a><h3>WEBKIT_MICRO_VERSION</h3>
<pre class="programlisting">#define WEBKIT_MICRO_VERSION (3)
<pre class="programlisting">#define WEBKIT_MICRO_VERSION (4)
</pre>
<p>Like <a class="link" href="webkit2gtk-4.0-WebKitVersion.html#webkit-get-micro-version" title="webkit_get_micro_version ()"><code class="function">webkit_get_micro_version()</code></a>, but from the headers used at
application compile time, rather than from the library linked
......
......@@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">WebKitDOMGTK+ Reference Manual</p></th></tr></table></div>
<div><p class="releaseinfo">for WebKitDOMGTK+ 2.28.3</p></div>
<div><p class="releaseinfo">for WebKitDOMGTK+ 2.28.4</p></div>
</div>
<hr>
</div>
......
================
WebKitGTK 2.28.4
================
What's new in WebKitGTK 2.28.4?
- Fix several crashes and rendering issues.
================
WebKitGTK 2.28.3
================
......
......@@ -48,6 +48,13 @@ function initializeReadableStream(underlyingSource, strategy)
// Initialized with null value to enable distinction with undefined case.
@putByIdDirectPrivate(this, "readableStreamController", null);
// FIXME: We should introduce https://streams.spec.whatwg.org/#create-readable-stream.
// For now, we emulate this with underlyingSource with private properties.
if (@getByIdDirectPrivate(underlyingSource, "pull") !== @undefined) {
@setupReadableStreamDefaultController(this, underlyingSource, @undefined, 1, @getByIdDirectPrivate(underlyingSource, "start"), @getByIdDirectPrivate(underlyingSource, "pull"), @getByIdDirectPrivate(underlyingSource, "cancel"));
return this;
}
const type = underlyingSource.type;
const typeString = @toString(type);
......@@ -65,7 +72,8 @@ function initializeReadableStream(underlyingSource, strategy)
} else if (type === @undefined) {
if (strategy.highWaterMark === @undefined)
strategy.highWaterMark = 1;
@putByIdDirectPrivate(this, "readableStreamController", new @ReadableStreamDefaultController(this, underlyingSource, strategy.size, strategy.highWaterMark, @isReadableStream));
@setupReadableStreamDefaultController(this, underlyingSource, strategy.size, strategy.highWaterMark, underlyingSource.start, underlyingSource.pull, underlyingSource.cancel);
} else
@throwRangeError("Invalid type for underlying source");
......
......@@ -63,8 +63,26 @@ function privateInitializeReadableStreamDefaultController(stream, underlyingSour
@putByIdDirectPrivate(this, "pulling", false);
@putByIdDirectPrivate(this, "strategy", @validateAndNormalizeQueuingStrategy(size, highWaterMark));
const controller = this;
@promiseInvokeOrNoopNoCatch(underlyingSource, "start", [this]).@then(() => {
return this;
}
// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller, starting from step 6.
// The other part is implemented in privateInitializeReadableStreamDefaultController.
function setupReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark, startMethod, pullMethod, cancelMethod)
{
"use strict";
const controller = new @ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark, @isReadableStream);
const startAlgorithm = () => @promiseInvokeOrNoopMethodNoCatch(underlyingSource, startMethod, [controller]);
const pullAlgorithm = () => @promiseInvokeOrNoopMethod(underlyingSource, pullMethod, [controller]);
const cancelAlgorithm = (reason) => @promiseInvokeOrNoopMethod(underlyingSource, cancelMethod, [reason]);
@putByIdDirectPrivate(controller, "pullAlgorithm", pullAlgorithm);
@putByIdDirectPrivate(controller, "cancelAlgorithm", cancelAlgorithm);
@putByIdDirectPrivate(controller, "pull", @readableStreamDefaultControllerPull);
@putByIdDirectPrivate(controller, "cancel", @readableStreamDefaultControllerCancel);
@putByIdDirectPrivate(stream, "readableStreamController", controller);
startAlgorithm().@then(() => {
@putByIdDirectPrivate(controller, "started", true);
@assert(!@getByIdDirectPrivate(controller, "pulling"));
@assert(!@getByIdDirectPrivate(controller, "pullAgain"));
......@@ -72,12 +90,6 @@ function privateInitializeReadableStreamDefaultController(stream, underlyingSour
}, (error) => {
@readableStreamDefaultControllerError(controller, error);
});
@putByIdDirectPrivate(this, "cancel", @readableStreamDefaultControllerCancel);
@putByIdDirectPrivate(this, "pull", @readableStreamDefaultControllerPull);
return this;
}
function readableStreamDefaultControllerError(controller, error)
......@@ -137,18 +149,20 @@ function readableStreamTee(stream, shouldClone)
reason2: @undefined,
};
teeState.cancelPromiseCapability = @newPromiseCapability(@InternalPromise);
teeState.cancelPromiseCapability = @newPromiseCapability(@Promise);
const pullFunction = @readableStreamTeePullFunction(teeState, reader, shouldClone);
const branch1 = new @ReadableStream({
"pull": pullFunction,
"cancel": @readableStreamTeeBranch1CancelFunction(teeState, stream)
});
const branch2 = new @ReadableStream({
"pull": pullFunction,
"cancel": @readableStreamTeeBranch2CancelFunction(teeState, stream)
});
const branch1Source = { };
@putByIdDirectPrivate(branch1Source, "pull", pullFunction);
@putByIdDirectPrivate(branch1Source, "cancel", @readableStreamTeeBranch1CancelFunction(teeState, stream));
const branch2Source = { };
@putByIdDirectPrivate(branch2Source, "pull", pullFunction);
@putByIdDirectPrivate(branch2Source, "cancel", @readableStreamTeeBranch2CancelFunction(teeState, stream));
const branch1 = new @ReadableStream(branch1Source);
const branch2 = new @ReadableStream(branch2Source);
@getByIdDirectPrivate(reader, "closedPromiseCapability").@promise.@then(@undefined, function(e) {
if (teeState.closedOrErrored)
......@@ -322,7 +336,7 @@ function readableStreamDefaultControllerCallPullIfNeeded(controller)
@assert(!@getByIdDirectPrivate(controller, "pullAgain"));
@putByIdDirectPrivate(controller, "pulling", true);
@promiseInvokeOrNoop(@getByIdDirectPrivate(controller, "underlyingSource"), "pull", [controller]).@then(function() {
@getByIdDirectPrivate(controller, "pullAlgorithm").@call(@undefined).@then(function() {
@putByIdDirectPrivate(controller, "pulling", false);
if (@getByIdDirectPrivate(controller, "pullAgain")) {
@putByIdDirectPrivate(controller, "pullAgain", false);
......@@ -385,7 +399,7 @@ function readableStreamDefaultControllerCancel(controller, reason)
"use strict";
@putByIdDirectPrivate(controller, "queue", @newQueue());
return @promiseInvokeOrNoop(@getByIdDirectPrivate(controller, "underlyingSource"), "cancel", [reason]);
return @getByIdDirectPrivate(controller, "cancelAlgorithm").@call(@undefined, reason);
}
function readableStreamDefaultControllerPull(controller)
......
......@@ -36,16 +36,34 @@ function shieldingPromiseResolve(result)
return promise;
}
function promiseInvokeOrNoopNoCatch(object, key, args)
function promiseInvokeOrNoopMethodNoCatch(object, method, args)
{
"use strict";
const method = object[key];
if (method === @undefined)
return @Promise.@resolve();
return @shieldingPromiseResolve(method.@apply(object, args));
}
function promiseInvokeOrNoopNoCatch(object, key, args)
{
"use strict";
return @promiseInvokeOrNoopMethodNoCatch(object, object[key], args);
}
function promiseInvokeOrNoopMethod(object, method, args)
{
"use strict";
try {
return @promiseInvokeOrNoopMethodNoCatch(object, method, args);
}
catch(error) {
return @Promise.@reject(error);
}
}
function promiseInvokeOrNoop(object, key, args)
{
"use strict";
......@@ -56,7 +74,6 @@ function promiseInvokeOrNoop(object, key, args)
catch(error) {
return @Promise.@reject(error);
}
}
function promiseInvokeOrFallbackOrNoop(object, key1, args1, key2, args2)
......
......@@ -59,6 +59,8 @@ page/scrolling/nicosia/ScrollingTreeStickyNode.cpp
page/scrolling/generic/ScrollingThreadGeneric.cpp
platform/ScrollAnimationKinetic.cpp
platform/UserAgentQuirks.cpp
platform/graphics/GLContext.cpp
......
......@@ -142,7 +142,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
Vector<RefPtr<WebAnimation>> webAnimations;
// First, let's get all qualifying animations in their right group.
for (const auto& animation : m_allAnimations) {
for (const auto& animation : m_animations) {
if (!animation || !animation->isRelevant() || animation->timeline() != this || !is<KeyframeEffect>(animation->effect()))
continue;
......@@ -151,15 +151,15 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
continue;
if (is<CSSTransition>(animation.get()) && downcast<CSSTransition>(animation.get())->owningElement())
cssTransitions.append(animation.get());
cssTransitions.append(animation);
else if (is<CSSAnimation>(animation.get()) && downcast<CSSAnimation>(animation.get())->owningElement())
cssAnimations.append(animation.get());
cssAnimations.append(animation);
else
webAnimations.append(animation.get());
webAnimations.append(animation);
}
// Now sort CSS Transitions by their composite order.
std::sort(cssTransitions.begin(), cssTransitions.end(), [](auto& lhs, auto& rhs) {
std::stable_sort(cssTransitions.begin(), cssTransitions.end(), [](auto& lhs, auto& rhs) {
// https://drafts.csswg.org/css-transitions-2/#animation-composite-order
auto* lhsTransition = downcast<CSSTransition>(lhs.get());
auto* rhsTransition = downcast<CSSTransition>(rhs.get());
......@@ -181,7 +181,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
});
// Now sort CSS Animations by their composite order.
std::sort(cssAnimations.begin(), cssAnimations.end(), [](auto& lhs, auto& rhs) {
std::stable_sort(cssAnimations.begin(), cssAnimations.end(), [](auto& lhs, auto& rhs) {
// https://drafts.csswg.org/css-animations-2/#animation-composite-order
auto* lhsOwningElement = downcast<CSSAnimation>(lhs.get())->owningElement();
auto* rhsOwningElement = downcast<CSSAnimation>(rhs.get())->owningElement();
......@@ -194,7 +194,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
return compareAnimationsByCompositeOrder(*lhs, *rhs, lhsOwningElement->ensureKeyframeEffectStack().cssAnimationList());
});
std::sort(webAnimations.begin(), webAnimations.end(), [](auto& lhs, auto& rhs) {
std::stable_sort(webAnimations.begin(), webAnimations.end(), [](auto& lhs, auto& rhs) {
return lhs->globalPosition() < rhs->globalPosition();
});
......
......@@ -80,7 +80,7 @@ void KeyframeEffectStack::ensureEffectsAreSorted()
if (m_isSorted || m_effects.size() < 2)
return;
std::sort(m_effects.begin(), m_effects.end(), [&](auto& lhs, auto& rhs) {
std::stable_sort(m_effects.begin(), m_effects.end(), [&](auto& lhs, auto& rhs) {
auto* lhsAnimation = lhs->animation();
auto* rhsAnimation = rhs->animation();
......
......@@ -37,6 +37,11 @@ namespace WebCore {
bool compareAnimationsByCompositeOrder(WebAnimation& lhsAnimation, WebAnimation& rhsAnimation, const AnimationList* cssAnimationList)
{
// We should not ever be calling this function with two WebAnimation objects that are the same. If that were the case,
// then comparing objects of this kind would yield inconsistent results when comparing A == B and B == A. As such,
// this function should be called with std::stable_sort().
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&lhsAnimation != &rhsAnimation);
bool lhsHasOwningElement = is<DeclarativeAnimation>(lhsAnimation) && downcast<DeclarativeAnimation>(lhsAnimation).owningElement();
bool rhsHasOwningElement = is<DeclarativeAnimation>(rhsAnimation) && downcast<DeclarativeAnimation>(rhsAnimation).owningElement();
......
......@@ -245,6 +245,7 @@ namespace WebCore {
macro(byobRequest) \
macro(caches) \
macro(cancel) \
macro(cancelAlgorithm) \
macro(cancelIdleCallback) \
macro(cloneArrayBuffer) \
macro(close) \
......@@ -307,6 +308,7 @@ namespace WebCore {
macro(privateGetStats) \
macro(pull) \
macro(pullAgain) \
macro(pullAlgorithm) \
macro(pulling) \
macro(queue) \
macro(queuedAddIceCandidate) \
......@@ -329,6 +331,7 @@ namespace WebCore {
macro(setBodyFromInputRequest) \
macro(setStatus) \
macro(showModalDialog) \
macro(start) \
macro(startConsumingStream) \
macro(started) \
macro(startedPromise) \
......
......@@ -751,6 +751,10 @@ String StyleProperties::pageBreakPropertyValue(const StylePropertyShorthand& sho
// FIXME: Remove this isGlobalKeyword check after we do this consistently for all shorthands in getPropertyValue.
if (value->isGlobalKeyword())
return value->cssText();
if (!is<CSSPrimitiveValue>(*value))
return String();
CSSValueID valueId = downcast<CSSPrimitiveValue>(*value).valueID();
switch (valueId) {
case CSSValuePage:
......
......@@ -4644,6 +4644,19 @@ void Document::nodeWillBeRemoved(Node& node)
m_markers->removeMarkers(node);
}
void Document::parentlessNodeMovedToNewDocument(Node& node)
{
Vector<Range*, 5> rangesAffected;
for (auto* range : m_ranges) {
if (range->parentlessNodeMovedToNewDocumentAffectsRange(node))
rangesAffected.append(range);
}
for (auto* range : rangesAffected)
range->updateRangeForParentlessNodeMovedToNewDocument(node);
}
static Node* fallbackFocusNavigationStartingNodeAfterRemoval(Node& node)
{
return node.previousSibling() ? node.previousSibling() : node.parentNode();
......
......@@ -815,6 +815,7 @@ public:
void nodeChildrenWillBeRemoved(ContainerNode&);
// nodeWillBeRemoved is only safe when removing one node at a time.
void nodeWillBeRemoved(Node&);
void parentlessNodeMovedToNewDocument(Node&);
enum class AcceptChildOperation { Replace, InsertOrAdd };
bool canAcceptChild(const Node& newChild, const Node* refChild, AcceptChildOperation) const;
......
......@@ -2050,6 +2050,9 @@ void Node::moveNodeToNewDocument(Document& oldDocument, Document& newDocument)
oldDocument.moveNodeIteratorsToNewDocument(*this, newDocument);
if (!parentNode())
oldDocument.parentlessNodeMovedToNewDocument(*this);
if (AXObjectCache::accessibilityEnabled()) {
if (auto* cache = oldDocument.existingAXObjectCache())
cache->remove(*this);
......
......@@ -1659,6 +1659,18 @@ void Range::nodeWillBeRemoved(Node& node)
boundaryNodeWillBeRemoved(m_end, node);
}
bool Range::parentlessNodeMovedToNewDocumentAffectsRange(Node& node)
{
return node.containsIncludingShadowDOM(m_start.container());
}
void Range::updateRangeForParentlessNodeMovedToNewDocument(Node& node)
{
m_ownerDocument->detachRange(*this);
m_ownerDocument = node.document();
m_ownerDocument->attachRange(*this);
}
static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node& text, unsigned offset, unsigned length)
{
if (boundary.container() != &text)
......
......@@ -138,6 +138,8 @@ public:
void nodeChildrenChanged(ContainerNode&);
void nodeChildrenWillBeRemoved(ContainerNode&);
void nodeWillBeRemoved(Node&);
bool parentlessNodeMovedToNewDocumentAffectsRange(Node&);
void updateRangeForParentlessNodeMovedToNewDocument(Node&);
void textInserted(Node&, unsigned offset, unsigned length);
void textRemoved(Node&, unsigned offset, unsigned length);
......
......@@ -124,13 +124,6 @@ void HTMLAppletElement::updateWidget(CreatePlugins createPlugins)
setNeedsWidgetUpdate(false);
RenderEmbeddedObject* renderer = renderEmbeddedObject();
LayoutUnit contentWidth = renderer->style().width().isFixed() ? LayoutUnit(renderer->style().width().value()) :
renderer->width() - renderer->horizontalBorderAndPaddingExtent();
LayoutUnit contentHeight = renderer->style().height().isFixed() ? LayoutUnit(renderer->style().height().value()) :
renderer->height() - renderer->verticalBorderAndPaddingExtent();
Vector<String> paramNames;
Vector<String> paramValues;
......@@ -175,7 +168,20 @@ void HTMLAppletElement::updateWidget(CreatePlugins createPlugins)
RefPtr<Frame> frame = document().frame();
ASSERT(frame);
renderer->setWidget(frame->loader().subframeLoader().createJavaAppletWidget(roundedIntSize(LayoutSize(contentWidth, contentHeight)), *this, paramNames, paramValues));
auto contentSize = LayoutSize { };
{
auto* renderer = renderEmbeddedObject();
auto& style = renderer->style();
contentSize = LayoutSize { style.width().isFixed() ? LayoutUnit(style.width().value()) : renderer->width() - renderer->horizontalBorderAndPaddingExtent(),
style.height().isFixed() ? LayoutUnit(style.height().value()) : renderer->height() - renderer->verticalBorderAndPaddingExtent() };
}
auto widget = frame->loader().subframeLoader().createJavaAppletWidget(roundedIntSize(contentSize), *this, paramNames, paramValues);
// createJavaAppletWidget needs to check if the plugin(replacement) is obscured. Since the overlapping test requires up-to-date geometry, it initiates a top level style recalc/layout.
// Let's see if this element still has a renderer after the style recalc.
if (auto* renderer = renderEmbeddedObject())
renderer->setWidget(WTFMove(widget));
#endif // !PLATFORM(IOS_FAMILY)
}
......
/*
* Copyright (C) 2006-2018 Apple Inc. All rights reserved.
* Copyright (C) 2006-2020 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
......@@ -461,9 +461,11 @@ void FrameLoader::submitForm(Ref<FormSubmission>&& submission)
return;
}
if (WTF::protocolIsJavaScript(submission->action())) {
if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(URL(submission->action())))
return;
URL formAction = submission->action();
if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(formAction))
return;
if (WTF::protocolIsJavaScript(formAction)) {
m_isExecutingJavaScriptFormAction = true;
Ref<Frame> protect(m_frame);
m_frame.script().executeIfJavaScriptURL(submission->action(), nullptr, DoNotReplaceDocumentIfJavaScriptURL);
......
......@@ -303,7 +303,7 @@ Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement& ownerElemen
URL upgradedRequestURL = requestURL;
initiatingDocument.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(upgradedRequestURL, ContentSecurityPolicy::InsecureRequestType::Load);
auto* frame = ownerElement.contentFrame();
RefPtr<Frame> frame = makeRefPtr(ownerElement.contentFrame());
if (frame)
frame->navigationScheduler().scheduleLocationChange(initiatingDocument, initiatingDocument.securityOrigin(), upgradedRequestURL, m_frame.loader().outgoingReferrer(), lockHistory, lockBackForwardList);
else
......@@ -316,7 +316,7 @@ Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement& ownerElemen
return ownerElement.contentFrame();
}
Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const URL& url, const String& name, const String& referrer)
RefPtr<Frame> SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const URL& url, const String& name, const String& referrer)
{
Ref<Frame> protect(m_frame);
auto document = makeRef(ownerElement.document());
......@@ -376,7 +376,10 @@ Frame* SubframeLoader::loadSubframe(HTMLFrameOwnerElement& ownerElement, const U
if (frame->loader().state() == FrameStateComplete && !frame->loader().policyDocumentLoader())
frame->loader().checkCompleted();
return frame.get();
if (!frame->tree().parent())
return nullptr;
return frame;
}
bool SubframeLoader::allowPlugins()
......
......@@ -70,7 +70,7 @@ public:
private:
bool requestPlugin(HTMLPlugInImageElement&, const URL&, const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback);
Frame* loadOrRedirectSubframe(HTMLFrameOwnerElement&, const URL&, const AtomString& frameName, LockHistory, LockBackForwardList);
Frame* loadSubframe(HTMLFrameOwnerElement&, const URL&, const String& name, const String& referrer);
RefPtr<Frame> loadSubframe(HTMLFrameOwnerElement&, const URL&, const String& name, const String& referrer);
bool loadPlugin(HTMLPlugInImageElement&, const URL&, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback);
bool shouldUsePlugin(const URL&, const String& mimeType, bool hasFallback, bool& useFallback);
......
......@@ -37,6 +37,7 @@
#include "HTMLNames.h"
#include "HitTestLocation.h"
#include "HitTestResult.h"
#include "ImageBuffer.h"
#include "InlineElementBox.h"
#include "InlineIterator.h"
#include "InlineTextBox.h"
......
......@@ -29,6 +29,7 @@
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMasker.h"
#include "RenderSVGResourceSolidColor.h"
#include "RenderSVGRoot.h"
#include "RenderView.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
......@@ -190,8 +191,14 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject&
{
ASSERT(object.node());
if (needsLayout && !object.renderTreeBeingDestroyed())
object.setNeedsLayout();
if (needsLayout && !object.renderTreeBeingDestroyed()) {
// If we are inside the layout of an RenderSVGRoot, do not cross the SVG boundary to
// invalidate the ancestor renderer because it may have finished its layout already.
if (is<RenderSVGRoot>(object) && downcast<RenderSVGRoot>(object).isInLayout())
object.setNeedsLayout(MarkOnlyThis);
else
object.setNeedsLayout(MarkContainingBlockChain);
}
if (is<RenderElement>(object))
removeFromCacheAndInvalidateDependencies(downcast<RenderElement>(object), needsLayout);
......
......@@ -45,6 +45,7 @@
#include "SVGViewSpec.h"
#include "TransformState.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/SetForScope.h>
#include <wtf/StackStats.h>
namespace WebCore {
......@@ -53,7 +54,6 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(RenderSVGRoot);
RenderSVGRoot::RenderSVGRoot(SVGSVGElement& element, RenderStyle&& style)
: RenderReplaced(element, WTFMove(style))
, m_objectBoundingBoxValid(false)
, m_isLayoutSizeChanged(false)
, m_needsBoundariesOrTransformUpdate(true)
, m_hasBoxDecorations(false)
......@@ -140,6 +140,7 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight(Optional<LayoutUnit> esti
void RenderSVGRoot::layout()
{
SetForScope<bool> change(m_inLayout, true);
StackStats::LayoutCheckPoint layoutCheckPoint;
ASSERT(needsLayout());
......
......@@ -46,6 +46,7 @@ public:
void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const override;
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
bool isInLayout() const { return m_inLayout; }
void setNeedsBoundariesUpdate() override { m_needsBoundariesOrTransformUpdate = true; }
bool needsBoundariesUpdate() override { return m_needsBoundariesOrTransformUpdate; }
void setNeedsTransformUpdate() override { m_needsBoundariesOrTransformUpdate = true; }
......@@ -106,7 +107,8 @@ private:
IntSize m_containerSize;
FloatRect m_objectBoundingBox;
bool m_objectBoundingBoxValid;
bool m_objectBoundingBoxValid { false };