summaryrefslogtreecommitdiffstats
path: root/Source/WebCore
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore')
-rw-r--r--Source/WebCore/CMakeLists.txt8
-rw-r--r--Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp13
-rw-r--r--Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h2
-rw-r--r--Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl3
-rw-r--r--Source/WebCore/Modules/webdatabase/DatabaseContext.cpp4
-rw-r--r--Source/WebCore/accessibility/AccessibilityNodeObject.cpp39
-rw-r--r--Source/WebCore/accessibility/AccessibilityNodeObject.h1
-rw-r--r--Source/WebCore/accessibility/AccessibilityProgressIndicator.cpp31
-rw-r--r--Source/WebCore/accessibility/AccessibilityProgressIndicator.h1
-rw-r--r--Source/WebCore/accessibility/AccessibilityRenderObject.cpp9
-rw-r--r--Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp106
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowCustom.cpp25
-rw-r--r--Source/WebCore/bindings/scripts/CodeGeneratorJS.pm66
-rw-r--r--Source/WebCore/css/CSSComputedStyleDeclaration.cpp6
-rw-r--r--Source/WebCore/css/CSSFontFace.cpp2
-rw-r--r--Source/WebCore/css/CSSGrammar.y.in26
-rw-r--r--Source/WebCore/css/CSSParser.cpp10
-rw-r--r--Source/WebCore/css/CSSParserValues.cpp25
-rw-r--r--Source/WebCore/css/CSSParserValues.h6
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.h1
-rw-r--r--Source/WebCore/css/CSSPropertyNames.in3
-rw-r--r--Source/WebCore/css/DocumentRuleSets.cpp3
-rw-r--r--Source/WebCore/css/SelectorChecker.cpp4
-rw-r--r--Source/WebCore/css/StyleBuilderConverter.h58
-rw-r--r--Source/WebCore/cssjit/SelectorCompiler.cpp12
-rw-r--r--Source/WebCore/dom/Document.cpp33
-rw-r--r--Source/WebCore/dom/Document.h4
-rw-r--r--Source/WebCore/dom/Element.cpp2
-rw-r--r--Source/WebCore/dom/Node.cpp59
-rw-r--r--Source/WebCore/dom/Node.h3
-rw-r--r--Source/WebCore/editing/SpellChecker.cpp4
-rw-r--r--Source/WebCore/editing/atk/FrameSelectionAtk.cpp7
-rw-r--r--Source/WebCore/html/HTMLMarqueeElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLMarqueeElement.h3
-rw-r--r--Source/WebCore/html/ImageData.cpp3
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp26
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext2D.h9
-rw-r--r--Source/WebCore/inspector/InspectorIndexedDBAgent.cpp2
-rw-r--r--Source/WebCore/page/DOMWindow.cpp2
-rw-r--r--Source/WebCore/page/EventHandler.cpp29
-rw-r--r--Source/WebCore/page/Frame.cpp4
-rw-r--r--Source/WebCore/page/FrameView.cpp10
-rw-r--r--Source/WebCore/page/History.cpp9
-rw-r--r--Source/WebCore/page/Location.cpp10
-rw-r--r--Source/WebCore/page/SecurityOrigin.cpp5
-rw-r--r--Source/WebCore/page/Settings.in1
-rw-r--r--Source/WebCore/page/animation/AnimationController.cpp2
-rw-r--r--Source/WebCore/platform/LengthPoint.cpp38
-rw-r--r--Source/WebCore/platform/LengthPoint.h76
-rw-r--r--Source/WebCore/platform/SharedBuffer.cpp6
-rw-r--r--Source/WebCore/platform/URL.cpp50
-rw-r--r--Source/WebCore/platform/URL.h13
-rw-r--r--Source/WebCore/platform/graphics/PlatformDisplay.cpp18
-rw-r--r--Source/WebCore/platform/graphics/WOFFFileFormat.cpp35
-rw-r--r--Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp9
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.cpp13
-rw-r--r--Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp3
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp7
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp274
-rw-r--r--Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp14
-rw-r--r--Source/WebCore/platform/graphics/qt/FontPlatformData.h3
-rw-r--r--Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp15
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp2
-rw-r--r--Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp2
-rw-r--r--Source/WebCore/platform/network/qt/ResourceRequest.h2
-rw-r--r--Source/WebCore/platform/network/qt/ResourceRequestQt.cpp16
-rw-r--r--Source/WebCore/platform/qt/RenderThemeQtMobile.cpp8
-rw-r--r--Source/WebCore/rendering/AutoTableLayout.cpp32
-rw-r--r--Source/WebCore/rendering/AutoTableLayout.h8
-rw-r--r--Source/WebCore/rendering/InlineIterator.h2
-rw-r--r--Source/WebCore/rendering/LogicalSelectionOffsetCaches.h11
-rw-r--r--Source/WebCore/rendering/RenderBlock.cpp373
-rw-r--r--Source/WebCore/rendering/RenderBlock.h14
-rw-r--r--Source/WebCore/rendering/RenderBlockFlow.cpp26
-rw-r--r--Source/WebCore/rendering/RenderBlockFlow.h4
-rw-r--r--Source/WebCore/rendering/RenderBlockLineLayout.cpp4
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp46
-rw-r--r--Source/WebCore/rendering/RenderBox.h2
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp112
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.h19
-rw-r--r--Source/WebCore/rendering/RenderHTMLCanvas.cpp13
-rw-r--r--Source/WebCore/rendering/RenderImage.cpp30
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp5
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp33
-rw-r--r--Source/WebCore/rendering/RenderObject.cpp3
-rw-r--r--Source/WebCore/rendering/RenderReplaced.cpp38
-rw-r--r--Source/WebCore/rendering/RenderReplaced.h1
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp7
-rw-r--r--Source/WebCore/rendering/RenderTableCell.cpp16
-rw-r--r--Source/WebCore/rendering/RenderTableCell.h2
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp12
-rw-r--r--Source/WebCore/rendering/TableLayout.h2
-rw-r--r--Source/WebCore/rendering/line/BreakingContext.h6
-rw-r--r--Source/WebCore/rendering/line/LineWidth.cpp13
-rw-r--r--Source/WebCore/rendering/line/LineWidth.h28
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.cpp1
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.h8
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp3
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.h2
-rw-r--r--Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp4
-rw-r--r--Source/WebCore/rendering/style/WillChangeData.cpp26
-rw-r--r--Source/WebCore/rendering/style/WillChangeData.h2
-rw-r--r--Source/WebCore/svg/SVGLengthContext.cpp2
-rw-r--r--Source/WebCore/svg/SVGSVGElement.cpp2
-rw-r--r--Source/WebCore/svg/animation/SMILTime.h2
-rw-r--r--Source/WebCore/svg/animation/SMILTimeContainer.cpp14
-rw-r--r--Source/WebCore/svg/animation/SMILTimeContainer.h2
-rw-r--r--Source/WebCore/svg/animation/SVGSMILElement.cpp2
-rw-r--r--Source/WebCore/workers/WorkerGlobalScope.idl6
109 files changed, 1450 insertions, 785 deletions
diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt
index cb9244302..ff9e12889 100644
--- a/Source/WebCore/CMakeLists.txt
+++ b/Source/WebCore/CMakeLists.txt
@@ -2099,6 +2099,7 @@ set(WebCore_SOURCES
platform/FileSystem.cpp
platform/Language.cpp
platform/Length.cpp
+ platform/LengthPoint.cpp
platform/LengthSize.cpp
platform/LinkHash.cpp
platform/Logging.cpp
@@ -3352,6 +3353,11 @@ if (ENABLE_USER_MESSAGE_HANDLERS)
)
endif ()
+if (USE_WOFF2)
+ list(APPEND WebCore_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}/woff2/src")
+ list(APPEND WebCore_LIBRARIES woff2)
+endif ()
+
set(WebCoreTestSupport_INCLUDE_DIRECTORIES
"${WEBCORE_DIR}/platform/mock"
"${WEBCORE_DIR}/testing"
@@ -3782,7 +3788,7 @@ if (ENABLE_GRAPHICS_CONTEXT_3D AND NOT WIN32)
set_target_properties(ANGLESupport PROPERTIES FOLDER "WebCore")
# Suppress null conversion warnings for sources in Source/ThirdParty/ANGLE
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ if (COMPILER_IS_CLANG)
ADD_TARGET_PROPERTIES(ANGLESupport COMPILE_FLAGS "-Wno-null-conversion")
endif ()
diff --git a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp
index f5bc6a8c3..9272dfc98 100644
--- a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp
+++ b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp
@@ -35,6 +35,10 @@
#include "Page.h"
#include "SecurityOrigin.h"
+#if PLATFORM(QT)
+#include "Settings.h"
+#endif
+
namespace WebCore {
DOMWindowIndexedDatabase::DOMWindowIndexedDatabase(DOMWindow* window)
@@ -93,9 +97,9 @@ void DOMWindowIndexedDatabase::willDetachGlobalObjectFromFrame()
DOMWindowProperty::willDetachGlobalObjectFromFrame();
}
-IDBFactory* DOMWindowIndexedDatabase::indexedDB(DOMWindow* window)
+IDBFactory* DOMWindowIndexedDatabase::indexedDB(DOMWindow& window)
{
- return from(window)->indexedDB();
+ return from(&window)->indexedDB();
}
IDBFactory* DOMWindowIndexedDatabase::indexedDB()
@@ -108,6 +112,11 @@ IDBFactory* DOMWindowIndexedDatabase::indexedDB()
if (!page)
return nullptr;
+#if PLATFORM(QT)
+ if (!page->settings().offlineStorageDatabaseEnabled())
+ return nullptr;
+#endif
+
if (!m_window->isCurrentlyDisplayedInFrame())
return nullptr;
diff --git a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h
index 3ffb71c5c..7f3c193a9 100644
--- a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h
+++ b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h
@@ -44,7 +44,7 @@ public:
static DOMWindowIndexedDatabase* from(DOMWindow*);
- static IDBFactory* indexedDB(DOMWindow*);
+ static IDBFactory* indexedDB(DOMWindow&);
virtual void disconnectFrameForDocumentSuspension() override;
virtual void reconnectFrameFromDocumentSuspension(Frame*) override;
diff --git a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl
index d1b02038f..72b7b2750 100644
--- a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl
+++ b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl
@@ -27,6 +27,7 @@
[
Conditional=INDEXED_DATABASE,
] partial interface DOMWindow {
- // This space is intentionally left blank.
+ [EnabledAtRuntime=IndexedDB] readonly attribute IDBFactory indexedDB;
+ [EnabledAtRuntime=IndexedDB, ImplementedAs=indexedDB] readonly attribute IDBFactory webkitIndexedDB;
};
diff --git a/Source/WebCore/Modules/webdatabase/DatabaseContext.cpp b/Source/WebCore/Modules/webdatabase/DatabaseContext.cpp
index 42be91b15..8f3ff3665 100644
--- a/Source/WebCore/Modules/webdatabase/DatabaseContext.cpp
+++ b/Source/WebCore/Modules/webdatabase/DatabaseContext.cpp
@@ -198,6 +198,10 @@ bool DatabaseContext::allowDatabaseAccess() const
{
if (is<Document>(*m_scriptExecutionContext)) {
Document& document = downcast<Document>(*m_scriptExecutionContext);
+#if PLATFORM(QT)
+ if (document.page() && !document.page()->settings().offlineStorageDatabaseEnabled())
+ return false;
+#endif
if (!document.page() || (document.page()->usesEphemeralSession() && !SchemeRegistry::allowsDatabaseAccessInPrivateBrowsing(document.securityOrigin()->protocol())))
return false;
return true;
diff --git a/Source/WebCore/accessibility/AccessibilityNodeObject.cpp b/Source/WebCore/accessibility/AccessibilityNodeObject.cpp
index 1e3a91518..5be294ff0 100644
--- a/Source/WebCore/accessibility/AccessibilityNodeObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityNodeObject.cpp
@@ -1354,7 +1354,6 @@ void AccessibilityNodeObject::visibleText(Vector<AccessibilityText>& textOrder)
case RadioButtonRole:
case SwitchRole:
case TabRole:
- case ProgressIndicatorRole:
useTextUnderElement = true;
break;
default:
@@ -1395,9 +1394,17 @@ void AccessibilityNodeObject::helpText(Vector<AccessibilityText>& textOrder) con
textOrder.append(AccessibilityText(summary, SummaryText));
// The title attribute should be used as help text unless it is already being used as descriptive text.
+ // However, when the title attribute is the only text alternative provided, it may be exposed as the
+ // descriptive text. This is problematic in the case of meters because the HTML spec suggests authors
+ // can expose units through this attribute. Therefore, if the element is a meter, change its source
+ // type to HelpText.
const AtomicString& title = getAttribute(titleAttr);
- if (!title.isEmpty())
- textOrder.append(AccessibilityText(title, TitleTagText));
+ if (!title.isEmpty()) {
+ if (!isMeter())
+ textOrder.append(AccessibilityText(title, TitleTagText));
+ else
+ textOrder.append(AccessibilityText(title, HelpText));
+ }
}
void AccessibilityNodeObject::accessibilityText(Vector<AccessibilityText>& textOrder)
@@ -1893,6 +1900,32 @@ static String accessibleNameForNode(Node* node, Node* labelledbyNode)
return String();
}
+String AccessibilityNodeObject::accessibilityDescriptionForChildren() const
+{
+ Node* node = this->node();
+ if (!node)
+ return String();
+
+ AXObjectCache* cache = axObjectCache();
+ if (!cache)
+ return String();
+
+ StringBuilder builder;
+ for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
+ if (!is<Element>(child))
+ continue;
+
+ if (AccessibilityObject* axObject = cache->getOrCreate(child)) {
+ String description = axObject->ariaLabeledByAttribute();
+ if (description.isEmpty())
+ description = accessibleNameForNode(child);
+ appendNameToStringBuilder(builder, description);
+ }
+ }
+
+ return builder.toString();
+}
+
String AccessibilityNodeObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
{
StringBuilder builder;
diff --git a/Source/WebCore/accessibility/AccessibilityNodeObject.h b/Source/WebCore/accessibility/AccessibilityNodeObject.h
index 5a9f351ed..7b63eaa67 100644
--- a/Source/WebCore/accessibility/AccessibilityNodeObject.h
+++ b/Source/WebCore/accessibility/AccessibilityNodeObject.h
@@ -123,6 +123,7 @@ public:
virtual unsigned hierarchicalLevel() const override;
virtual String textUnderElement(AccessibilityTextUnderElementMode = AccessibilityTextUnderElementMode()) const override;
+ virtual String accessibilityDescriptionForChildren() const;
virtual String accessibilityDescription() const override;
virtual String helpText() const override;
virtual String title() const override;
diff --git a/Source/WebCore/accessibility/AccessibilityProgressIndicator.cpp b/Source/WebCore/accessibility/AccessibilityProgressIndicator.cpp
index f3a13d918..19485396f 100644
--- a/Source/WebCore/accessibility/AccessibilityProgressIndicator.cpp
+++ b/Source/WebCore/accessibility/AccessibilityProgressIndicator.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "AccessibilityProgressIndicator.h"
+#include "AXObjectCache.h"
#include "FloatConversion.h"
#include "HTMLMeterElement.h"
#include "HTMLNames.h"
@@ -60,6 +61,36 @@ bool AccessibilityProgressIndicator::computeAccessibilityIsIgnored() const
return accessibilityIsIgnoredByDefault();
}
+String AccessibilityProgressIndicator::valueDescription() const
+{
+ // If the author has explicitly provided a value through aria-valuetext, use it.
+ String description = AccessibilityRenderObject::valueDescription();
+ if (!description.isEmpty())
+ return description;
+
+#if ENABLE(METER_ELEMENT)
+ if (!m_renderer->isMeter())
+ return String();
+
+ HTMLMeterElement* meter = meterElement();
+ if (!meter)
+ return String();
+
+ // The HTML spec encourages authors to include a textual representation of the meter's state in
+ // the element's contents. We'll fall back on that if there is not a more accessible alternative.
+ AccessibilityObject* axMeter = axObjectCache()->getOrCreate(meter);
+ if (is<AccessibilityNodeObject>(axMeter)) {
+ description = downcast<AccessibilityNodeObject>(axMeter)->accessibilityDescriptionForChildren();
+ if (!description.isEmpty())
+ return description;
+ }
+
+ return meter->textContent();
+#endif
+
+ return String();
+}
+
float AccessibilityProgressIndicator::valueForRange() const
{
if (!m_renderer)
diff --git a/Source/WebCore/accessibility/AccessibilityProgressIndicator.h b/Source/WebCore/accessibility/AccessibilityProgressIndicator.h
index f58f39460..3833b2c2c 100644
--- a/Source/WebCore/accessibility/AccessibilityProgressIndicator.h
+++ b/Source/WebCore/accessibility/AccessibilityProgressIndicator.h
@@ -46,6 +46,7 @@ private:
virtual bool isProgressIndicator() const override { return true; }
+ virtual String valueDescription() const override;
virtual float valueForRange() const override;
virtual float maxValueForRange() const override;
virtual float minValueForRange() const override;
diff --git a/Source/WebCore/accessibility/AccessibilityRenderObject.cpp b/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
index 67df80e1a..dff12e007 100644
--- a/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -1366,6 +1366,15 @@ bool AccessibilityRenderObject::computeAccessibilityIsIgnored() const
if (isWebArea())
return false;
+#if ENABLE(METER_ELEMENT)
+ // The render tree of meter includes a RenderBlock (meter) and a RenderMeter (div).
+ // We expose the latter and thus should ignore the former. However, if the author
+ // includes a title attribute on the element, hasAttributesRequiredForInclusion()
+ // will return true, potentially resulting in a redundant accessible object.
+ if (is<HTMLMeterElement>(node))
+ return true;
+#endif
+
// Using the presence of an accessible name to decide an element's visibility is not
// as definitive as previous checks, so this should remain as one of the last.
if (hasAttributesRequiredForInclusion())
diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
index a873067df..353b0b1b8 100644
--- a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
+++ b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
@@ -108,54 +108,24 @@ static const gchar* webkitAccessibleGetName(AtkObject* object)
g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0);
returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0);
- AccessibilityObject* coreObject = core(object);
- if (coreObject->isFieldset()) {
- AccessibilityObject* label = coreObject->titleUIElement();
- if (label) {
- AtkObject* atkObject = label->wrapper();
- if (ATK_IS_TEXT(atkObject))
- return atk_text_get_text(ATK_TEXT(atkObject), 0, -1);
- }
- }
-
- if (coreObject->isControl()) {
- AccessibilityObject* label = coreObject->correspondingLabelForControlElement();
- if (label) {
- AtkObject* atkObject = label->wrapper();
- if (ATK_IS_TEXT(atkObject))
- return atk_text_get_text(ATK_TEXT(atkObject), 0, -1);
- }
-
- // Try text under the node.
- String textUnder = coreObject->textUnderElement();
- if (textUnder.length())
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, textUnder);
- }
-
- if (coreObject->isImage() || coreObject->isInputImage() || coreObject->isImageMap() || coreObject->isImageMapLink()) {
- Node* node = coreObject->node();
- if (is<HTMLElement>(node)) {
- // Get the attribute rather than altText String so as not to fall back on title.
- const AtomicString& alt = downcast<HTMLElement>(*node).getAttribute(HTMLNames::altAttr);
- if (!alt.isEmpty())
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, alt);
- }
+ Vector<AccessibilityText> textOrder;
+ core(object)->accessibilityText(textOrder);
+
+ for (const auto& text : textOrder) {
+ // FIXME: This check is here because AccessibilityNodeObject::titleElementText()
+ // appends an empty String for the LabelByElementText source when there is a
+ // titleUIElement(). Removing this check makes some fieldsets lose their name.
+ if (text.text.isEmpty())
+ continue;
+
+ // WebCore Accessibility should provide us with the text alternative computation
+ // in the order defined by that spec. So take the first thing that our platform
+ // does not expose via the AtkObject description.
+ if (text.textSource != HelpText && text.textSource != SummaryText)
+ return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, text.text);
}
- // Fallback for the webArea object: just return the document's title.
- if (coreObject->isWebArea()) {
- Document* document = coreObject->document();
- if (document)
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, document->title());
- }
-
- // Nothing worked so far, try with the AccessibilityObject's
- // title() before going ahead with stringValue().
- String axTitle = accessibilityTitle(coreObject);
- if (!axTitle.isEmpty())
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, axTitle);
-
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, coreObject->stringValue());
+ return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, "");
}
static const gchar* webkitAccessibleGetDescription(AtkObject* object)
@@ -163,27 +133,26 @@ static const gchar* webkitAccessibleGetDescription(AtkObject* object)
g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0);
returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0);
- AccessibilityObject* coreObject = core(object);
- Node* node = nullptr;
- if (coreObject->isAccessibilityRenderObject())
- node = coreObject->node();
- if (!is<HTMLElement>(node) || coreObject->ariaRoleAttribute() != UnknownRole || coreObject->isImage())
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, accessibilityDescription(coreObject));
-
- // atk_table_get_summary returns an AtkObject. We have no summary object, so expose summary here.
- if (coreObject->roleValue() == TableRole) {
- const AtomicString& summary = downcast<HTMLTableElement>(*node).summary();
- if (!summary.isEmpty())
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, summary);
- }
+ Vector<AccessibilityText> textOrder;
+ core(object)->accessibilityText(textOrder);
+
+ bool nameTextAvailable = false;
+ for (const auto& text : textOrder) {
+ // WebCore Accessibility should provide us with the text alternative computation
+ // in the order defined by that spec. So take the first thing that our platform
+ // does not expose via the AtkObject name.
+ if (text.textSource == HelpText || text.textSource == SummaryText)
+ return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, text.text);
- // The title attribute should be reliably available as the object's descripton.
- // We do not want to fall back on other attributes in its absence. See bug 25524.
- String title = downcast<HTMLElement>(*node).title();
- if (!title.isEmpty())
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, title);
+ // If there is no other text alternative, the title tag contents will have been
+ // used for the AtkObject name. We don't want to duplicate it here.
+ if (text.textSource == TitleTagText && nameTextAvailable)
+ return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, text.text);
- return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, accessibilityDescription(coreObject));
+ nameTextAvailable = true;
+ }
+
+ return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, "");
}
static void removeAtkRelationByType(AtkRelationSet* relationSet, AtkRelationType relationType)
@@ -458,6 +427,10 @@ static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object)
if (!isReadOnly.isEmpty())
attributeSet = addToAtkAttributeSet(attributeSet, "readonly", isReadOnly.utf8().data());
+ String valueDescription = coreObject->valueDescription();
+ if (!valueDescription.isEmpty())
+ attributeSet = addToAtkAttributeSet(attributeSet, "valuetext", valueDescription.utf8().data());
+
// According to the W3C Core Accessibility API Mappings 1.1, section 5.4.1 General Rules:
// "User agents must expose the WAI-ARIA role string if the API supports a mechanism to do so."
// In the case of ATK, the mechanism to do so is an object attribute pair (xml-roles:"string").
@@ -544,8 +517,7 @@ static AtkRole atkRole(AccessibilityObject* coreObject)
case BusyIndicatorRole:
return ATK_ROLE_PROGRESS_BAR; // Is this right?
case ProgressIndicatorRole:
- // return ATK_ROLE_SPIN_BUTTON; // Some confusion about this role in AccessibilityRenderObject.cpp
- return ATK_ROLE_PROGRESS_BAR;
+ return coreObject->isMeter() ? ATK_ROLE_LEVEL_BAR : ATK_ROLE_PROGRESS_BAR;
case WindowRole:
return ATK_ROLE_WINDOW;
case PopUpButtonRole:
diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 8d6a4c33b..0154a04b9 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -76,21 +76,6 @@ static EncodedJSValue jsDOMWindowWebKit(ExecState* exec, EncodedJSValue thisValu
}
#endif
-#if ENABLE(INDEXED_DATABASE)
-static EncodedJSValue jsDOMWindowIndexedDB(ExecState* exec, EncodedJSValue thisValue, PropertyName)
-{
- UNUSED_PARAM(exec);
- auto* castedThis = toJSDOMWindow(JSValue::decode(thisValue));
- if (!RuntimeEnabledFeatures::sharedFeatures().indexedDBEnabled())
- return JSValue::encode(jsUndefined());
- if (!castedThis || !BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->wrapped()))
- return JSValue::encode(jsUndefined());
- auto& impl = castedThis->wrapped();
- JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(DOMWindowIndexedDatabase::indexedDB(&impl)));
- return JSValue::encode(result);
-}
-#endif
-
static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObject, Frame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, String& errorMessage)
{
// Allow access to toString() cross-domain, but always Object.prototype.toString.
@@ -263,16 +248,6 @@ bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, Property
if (getStaticPropertySlot<JSDOMWindow, Base>(exec, *JSDOMWindow::info()->staticPropHashTable, thisObject, propertyName, slot))
return true;
-#if ENABLE(INDEXED_DATABASE)
- // FIXME: With generated JS bindings built on static property tables there is no way to
- // completely remove a generated property at runtime. So to completely disable IndexedDB
- // at runtime we have to not generate these accessors and have to handle them specially here.
- // Once https://webkit.org/b/145669 is resolved, they can once again be auto generated.
- if (RuntimeEnabledFeatures::sharedFeatures().indexedDBEnabled() && (propertyName == exec->propertyNames().indexedDB || propertyName == exec->propertyNames().webkitIndexedDB)) {
- slot.setCustom(thisObject, DontDelete | ReadOnly | CustomAccessor, jsDOMWindowIndexedDB);
- return true;
- }
-#endif
#if ENABLE(USER_MESSAGE_HANDLERS)
if (propertyName == exec->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) {
slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit);
diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
index 5e8905460..9dbf5105d 100644
--- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -730,6 +730,23 @@ sub OperationShouldBeOnInstance
return 0;
}
+sub GetJSCAttributesForAttribute
+{
+ my $interface = shift;
+ my $attribute = shift;
+
+ my @specials = ();
+ push(@specials, "DontDelete") if IsUnforgeable($interface, $attribute);
+
+ # As per Web IDL specification, constructor properties on the ECMAScript global object should not be enumerable.
+ my $is_global_constructor = $attribute->signature->type =~ /Constructor$/;
+ push(@specials, "DontEnum") if ($attribute->signature->extendedAttributes->{"NotEnumerable"} || $is_global_constructor);
+ push(@specials, "ReadOnly") if IsReadonly($attribute);
+ push(@specials, "CustomAccessor") unless $is_global_constructor or IsJSBuiltin($interface, $attribute);
+ push(@specials, "Accessor | Builtin") if IsJSBuiltin($interface, $attribute);
+ return (@specials > 0) ? join(" | ", @specials) : "0";
+}
+
sub GetIndexedGetterFunction
{
my $interface = shift;
@@ -1225,6 +1242,7 @@ sub GenerateHeader
# Constructor
if ($interfaceName eq "DOMWindow") {
push(@headerContent, " $className(JSC::VM&, JSC::Structure*, Ref<$implType>&&, JSDOMWindowShell*);\n");
+ push(@headerContent, " void finishCreation(JSC::VM&, JSDOMWindowShell*);\n");
} elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
push(@headerContent, " $className(JSC::VM&, JSC::Structure*, Ref<$implType>&&);\n");
} elsif (!NeedsImplementationClass($interface)) {
@@ -1387,19 +1405,17 @@ sub GeneratePropertiesHashTable
foreach my $attribute (@{$interface->attributes}) {
next if ($attribute->isStatic);
next if AttributeShouldBeOnInstance($interface, $attribute) != $isInstance;
+
+ # DOMWindow adds RuntimeEnabled attributes after creation so do not add them to the static table.
+ if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
+ $propertyCount -= 1;
+ next;
+ }
+
my $name = $attribute->signature->name;
push(@$hashKeys, $name);
- my @specials = ();
- push(@specials, "DontDelete") if IsUnforgeable($interface, $attribute);
-
- # As per Web IDL specification, constructor properties on the ECMAScript global object should not be enumerable.
- my $is_global_constructor = $attribute->signature->type =~ /Constructor$/;
- push(@specials, "DontEnum") if ($attribute->signature->extendedAttributes->{"NotEnumerable"} || $is_global_constructor);
- push(@specials, "ReadOnly") if IsReadonly($attribute);
- push(@specials, "CustomAccessor") unless $is_global_constructor or IsJSBuiltin($interface, $attribute);
- push(@specials, "Accessor | Builtin") if IsJSBuiltin($interface, $attribute);
- my $special = (@specials > 0) ? join(" | ", @specials) : "0";
+ my $special = GetJSCAttributesForAttribute($interface, $attribute);
push(@$hashSpecials, $special);
my $getter = GetAttributeGetterName($interfaceName, $className, $interface, $attribute);
@@ -2157,6 +2173,29 @@ sub GenerateImplementation
push(@implContent, " : $parentClassName(vm, structure, WTFMove(impl), shell)\n");
push(@implContent, "{\n");
push(@implContent, "}\n\n");
+
+ push(@implContent, "void ${className}::finishCreation(VM& vm, JSDOMWindowShell* shell)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " Base::finishCreation(vm, shell);\n\n");
+ # Support for RuntimeEnabled attributes on DOMWindow.
+ foreach my $attribute (@{$interface->attributes}) {
+ next unless $attribute->signature->extendedAttributes->{"EnabledAtRuntime"};
+
+ AddToImplIncludes("RuntimeEnabledFeatures.h");
+ my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
+ push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
+ my $enable_function = GetRuntimeEnableFunctionName($attribute->signature);
+ my $attributeName = $attribute->signature->name;
+ push(@implContent, " if (${enable_function}()) {\n");
+ my $getter = GetAttributeGetterName($interfaceName, $className, $interface, $attribute);
+ my $setter = IsReadonly($attribute) ? "nullptr" : GetAttributeSetterName($interfaceName, $className, $interface, $attribute);
+ push(@implContent, " auto* customGetterSetter = CustomGetterSetter::create(vm, $getter, $setter);\n");
+ my $jscAttributes = GetJSCAttributesForAttribute($interface, $attribute);
+ push(@implContent, " putDirectCustomAccessor(vm, vm.propertyNames->$attributeName, customGetterSetter, attributesForStructure($jscAttributes));\n");
+ push(@implContent, " }\n");
+ push(@implContent, "#endif\n") if $conditionalString;
+ }
+ push(@implContent, "}\n\n");
} elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
AddIncludesForTypeInImpl($interfaceName);
push(@implContent, "${className}::$className(VM& vm, Structure* structure, Ref<$implType>&& impl)\n");
@@ -2340,12 +2379,7 @@ sub GenerateImplementation
# Global constructors can be disabled at runtime.
if ($attribute->signature->type =~ /Constructor$/) {
- if ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
- AddToImplIncludes("RuntimeEnabledFeatures.h");
- my $enable_function = GetRuntimeEnableFunctionName($attribute->signature);
- push(@implContent, " if (!${enable_function}())\n");
- push(@implContent, " return JSValue::encode(jsUndefined());\n");
- } elsif ($attribute->signature->extendedAttributes->{"EnabledBySetting"}) {
+ if ($attribute->signature->extendedAttributes->{"EnabledBySetting"}) {
AddToImplIncludes("Frame.h");
AddToImplIncludes("Settings.h");
my $enable_function = ToMethodName($attribute->signature->extendedAttributes->{"EnabledBySetting"}) . "Enabled";
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
index 79da5802c..afb1c69c2 100644
--- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
@@ -2991,6 +2991,12 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
return zoomAdjustedPixelValueForLength(style->minWidth(), *style);
case CSSPropertyObjectFit:
return cssValuePool.createValue(style->objectFit());
+ case CSSPropertyObjectPosition: {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(zoomAdjustedPixelValueForLength(style->objectPosition().x(), *style));
+ list->append(zoomAdjustedPixelValueForLength(style->objectPosition().y(), *style));
+ return list;
+ }
case CSSPropertyOpacity:
return cssValuePool.createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyOrphans:
diff --git a/Source/WebCore/css/CSSFontFace.cpp b/Source/WebCore/css/CSSFontFace.cpp
index 552e99cfa..008ef8594 100644
--- a/Source/WebCore/css/CSSFontFace.cpp
+++ b/Source/WebCore/css/CSSFontFace.cpp
@@ -276,6 +276,8 @@ void CSSFontFace::setStatus(Status newStatus)
void CSSFontFace::fontLoaded(CSSFontFaceSource&)
{
+ Ref<CSSFontFace> protectedThis(*this);
+
// If the font is already in the cache, CSSFontFaceSource may report it's loaded before it is added here as a source.
// Let's not pump the state machine until we've got all our sources. font() and load() are smart enough to act correctly
// when a source is failed or succeeded before we have asked it to load.
diff --git a/Source/WebCore/css/CSSGrammar.y.in b/Source/WebCore/css/CSSGrammar.y.in
index 8cc70be80..0aad45663 100644
--- a/Source/WebCore/css/CSSGrammar.y.in
+++ b/Source/WebCore/css/CSSGrammar.y.in
@@ -294,12 +294,12 @@ static bool selectorListDoesNotMatchAnyPseudoElement(const Vector<std::unique_pt
%type <keyframeRuleList> keyframes_rule
%destructor { delete $$; } keyframes_rule
-// These parser values never need to be destroyed because they are never functions or value lists.
-%type <value> calc_func_term key unary_term
+// These parser values never need to be destroyed because they are never functions, value lists, or variables.
+%type <value> key unary_term
-// These parser values need to be destroyed because they might be functions.
-%type <value> calc_function function variable_function min_or_max_function term
-%destructor { destroy($$); } calc_function function variable_function min_or_max_function term
+// These parser values need to be destroyed because they might be functions, value lists, or variables.
+%type <value> calc_func_term calc_function function min_or_max_function term variable_function
+%destructor { destroy($$); } calc_func_term calc_function function min_or_max_function term variable_function
%type <id> property
@@ -823,14 +823,18 @@ key_list:
}
| key_list maybe_space ',' maybe_space key {
$$ = $1;
- ASSERT($5.unit != CSSParserValue::Function); // No need to call destroy.
if ($$)
$$->addValue($5);
}
;
key:
- maybe_unary_operator PERCENTAGE { $$.id = CSSValueInvalid; $$.isInt = false; $$.fValue = $1 * $2; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ maybe_unary_operator PERCENTAGE {
+ $$.id = CSSValueInvalid;
+ $$.isInt = false;
+ $$.fValue = $1 * $2;
+ $$.unit = CSSPrimitiveValue::CSS_NUMBER;
+ }
| IDENT {
$$.id = CSSValueInvalid;
$$.isInt = false;
@@ -1838,10 +1842,10 @@ invalid_var_fallback:
'!' | ';';
calc_func_term:
- unary_term
- | variable_function { $$ = $1; }
- | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
- ;
+ unary_term
+ | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
+ | variable_function
+ ;
/*
* The grammar requires spaces around binary ‘+’ and ‘-’ operators.
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp
index 9aec1c8ac..3ac15d00c 100644
--- a/Source/WebCore/css/CSSParser.cpp
+++ b/Source/WebCore/css/CSSParser.cpp
@@ -2886,6 +2886,16 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
case CSSPropertyColumnWidth: // auto | <length>
parsedValue = parseColumnWidth();
break;
+ case CSSPropertyObjectPosition: {
+ RefPtr<CSSPrimitiveValue> val1;
+ RefPtr<CSSPrimitiveValue> val2;
+ parseFillPosition(*m_valueList, val1, val2);
+ if (val1) {
+ addProperty(CSSPropertyObjectPosition, createPrimitiveValuePair(val1.release(), val2.release()), important);
+ return true;
+ }
+ return false;
+ }
// End of CSS3 properties
case CSSPropertyWillChange: // auto | [scroll-position | contents | <custom-ident>]#
diff --git a/Source/WebCore/css/CSSParserValues.cpp b/Source/WebCore/css/CSSParserValues.cpp
index db7540e8a..7fb74c6b8 100644
--- a/Source/WebCore/css/CSSParserValues.cpp
+++ b/Source/WebCore/css/CSSParserValues.cpp
@@ -46,29 +46,26 @@ void destroy(const CSSParserValue& value)
CSSParserValueList::~CSSParserValueList()
{
- for (size_t i = 0, size = m_values.size(); i < size; i++)
- destroy(m_values[i]);
+ for (auto& value : m_values)
+ destroy(value);
}
-void CSSParserValueList::addValue(const CSSParserValue& v)
+void CSSParserValueList::addValue(const CSSParserValue& value)
{
- m_values.append(v);
+ m_values.append(value);
}
-void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
+void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& value)
{
- m_values.insert(i, v);
+ m_values.insert(i, value);
}
-void CSSParserValueList::deleteValueAt(unsigned i)
+void CSSParserValueList::extend(CSSParserValueList& other)
{
- m_values.remove(i);
-}
-
-void CSSParserValueList::extend(CSSParserValueList& valueList)
-{
- for (unsigned int i = 0; i < valueList.size(); ++i)
- m_values.append(*(valueList.valueAt(i)));
+ for (auto& value : other.m_values) {
+ m_values.append(value);
+ value.unit = 0; // We moved the CSSParserValue from the other list; this acts like std::move.
+ }
}
bool CSSParserValueList::containsVariables() const
diff --git a/Source/WebCore/css/CSSParserValues.h b/Source/WebCore/css/CSSParserValues.h
index 77a5b1957..ebc16fe0f 100644
--- a/Source/WebCore/css/CSSParserValues.h
+++ b/Source/WebCore/css/CSSParserValues.h
@@ -18,8 +18,7 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef CSSParserValues_h
-#define CSSParserValues_h
+#pragma once
#include "CSSSelector.h"
#include "CSSValueKeywords.h"
@@ -140,7 +139,6 @@ public:
void addValue(const CSSParserValue&);
void insertValueAt(unsigned, const CSSParserValue&);
- void deleteValueAt(unsigned);
void extend(CSSParserValueList&);
unsigned size() const { return m_values.size(); }
@@ -274,5 +272,3 @@ template<unsigned length> inline bool equalLettersIgnoringASCIICase(const CSSPar
}
}
-
-#endif
diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h
index ab5cd6094..23375815c 100644
--- a/Source/WebCore/css/CSSPrimitiveValue.h
+++ b/Source/WebCore/css/CSSPrimitiveValue.h
@@ -210,6 +210,7 @@ public:
#if ENABLE(CSS_SCROLL_SNAP)
bool isLengthRepeat() const { return m_primitiveUnitType == CSS_LENGTH_REPEAT; }
#endif
+ bool isPair() const { return m_primitiveUnitType == CSS_PAIR; }
bool isPropertyID() const { return m_primitiveUnitType == CSS_PROPERTY_ID; }
bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; }
bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; }
diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in
index 0fd1d491a..2621e483e 100644
--- a/Source/WebCore/css/CSSPropertyNames.in
+++ b/Source/WebCore/css/CSSPropertyNames.in
@@ -145,7 +145,7 @@ background [Longhands=background-image|background-position-x|background-position
background-attachment [FillLayerProperty, NameForMethods=Attachment]
background-blend-mode [FillLayerProperty, NameForMethods=BlendMode]
background-clip [FillLayerProperty, NameForMethods=Clip]
-background-color [VisitedLinkColorSupport, Initial=invalidColor, NoDefaultColor]
+background-color [VisitedLinkColorSupport, NoDefaultColor]
background-image [FillLayerProperty, NameForMethods=Image]
background-origin [FillLayerProperty, NameForMethods=Origin]
background-position [Longhands=background-position-x|background-position-y]
@@ -274,6 +274,7 @@ max-width [Initial=initialMaxSize, Converter=LengthMaxSizing]
min-height [Initial=initialMinSize, Converter=LengthSizing]
min-width [Initial=initialMinSize, Converter=LengthSizing]
object-fit
+object-position [Converter=ObjectPosition]
opacity
// Honor -webkit-opacity as a synonym for opacity. This was the only syntax that worked in Safari 1.1,
// and may be in use on some websites and widgets.
diff --git a/Source/WebCore/css/DocumentRuleSets.cpp b/Source/WebCore/css/DocumentRuleSets.cpp
index 9cc08deb7..93f28b94d 100644
--- a/Source/WebCore/css/DocumentRuleSets.cpp
+++ b/Source/WebCore/css/DocumentRuleSets.cpp
@@ -114,6 +114,9 @@ void DocumentRuleSets::collectFeatures() const
m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
+
+ m_ancestorClassRuleSets.clear();
+ m_ancestorAttributeRuleSetsForHTML.clear();
}
RuleSet* DocumentRuleSets::ancestorClassRules(AtomicStringImpl* className) const
diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp
index 0f0d365c0..9b0fe19d8 100644
--- a/Source/WebCore/css/SelectorChecker.cpp
+++ b/Source/WebCore/css/SelectorChecker.cpp
@@ -912,6 +912,10 @@ bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont
if (m_strictParsing || element.isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
addStyleRelation(checkingContext, element, StyleRelation::AffectedByHover);
+ // See the comment in generateElementIsHovered() in SelectorCompiler.
+ if (checkingContext.resolvingMode == SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements && !context.isMatchElement)
+ return true;
+
if (element.hovered() || InspectorInstrumentation::forcePseudoState(const_cast<Element&>(element), CSSSelector::PseudoClassHover))
return true;
}
diff --git a/Source/WebCore/css/StyleBuilderConverter.h b/Source/WebCore/css/StyleBuilderConverter.h
index 34f6fe317..6ae433bd8 100644
--- a/Source/WebCore/css/StyleBuilderConverter.h
+++ b/Source/WebCore/css/StyleBuilderConverter.h
@@ -57,7 +57,7 @@ namespace WebCore {
// Note that we assume the CSS parser only allows valid CSSValue types.
class StyleBuilderConverter {
public:
- static Length convertLength(StyleResolver&, CSSValue&);
+ static Length convertLength(StyleResolver&, const CSSValue&);
static Length convertLengthOrAuto(StyleResolver&, CSSValue&);
static Length convertLengthSizing(StyleResolver&, CSSValue&);
static Length convertLengthMaxSizing(StyleResolver&, CSSValue&);
@@ -65,6 +65,7 @@ public:
template <typename T> static T convertLineWidth(StyleResolver&, CSSValue&);
static float convertSpacing(StyleResolver&, CSSValue&);
static LengthSize convertRadius(StyleResolver&, CSSValue&);
+ static LengthPoint convertObjectPosition(StyleResolver&, CSSValue&);
static TextDecoration convertTextDecoration(StyleResolver&, CSSValue&);
template <typename T> static T convertNumber(StyleResolver&, CSSValue&);
template <typename T> static T convertNumberOrAuto(StyleResolver&, CSSValue&);
@@ -148,6 +149,10 @@ private:
#if ENABLE(CSS_SCROLL_SNAP)
static Length parseSnapCoordinate(StyleResolver&, const CSSValue&);
#endif
+
+ static Length convertTo100PercentMinusLength(const Length&);
+ static Length convertPositionComponent(StyleResolver&, const CSSPrimitiveValue&);
+
#if ENABLE(CSS_GRID_LAYOUT)
static GridLength createGridTrackBreadth(CSSPrimitiveValue&, StyleResolver&);
static GridTrackSize createGridTrackSize(CSSValue&, StyleResolver&);
@@ -158,7 +163,7 @@ private:
static CSSToLengthConversionData csstoLengthConversionDataWithTextZoomFactor(StyleResolver&);
};
-inline Length StyleBuilderConverter::convertLength(StyleResolver& styleResolver, CSSValue& value)
+inline Length StyleBuilderConverter::convertLength(StyleResolver& styleResolver, const CSSValue& value)
{
auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
CSSToLengthConversionData conversionData = styleResolver.useSVGZoomRulesForLength() ?
@@ -298,6 +303,54 @@ inline LengthSize StyleBuilderConverter::convertRadius(StyleResolver& styleResol
return LengthSize(radiusWidth, radiusHeight);
}
+inline Length StyleBuilderConverter::convertTo100PercentMinusLength(const Length& length)
+{
+ if (length.isPercent())
+ return Length(100 - length.value(), Percent);
+
+ // Turn this into a calc expression: calc(100% - length)
+ auto lhs = std::make_unique<CalcExpressionLength>(Length(100, Percent));
+ auto rhs = std::make_unique<CalcExpressionLength>(length);
+ auto op = std::make_unique<CalcExpressionBinaryOperation>(WTFMove(lhs), WTFMove(rhs), CalcSubtract);
+ return Length(CalculationValue::create(WTFMove(op), CalculationRangeAll));
+}
+
+inline Length StyleBuilderConverter::convertPositionComponent(StyleResolver& styleResolver, const CSSPrimitiveValue& value)
+{
+ Length length;
+
+ auto* lengthValue = &value;
+ bool relativeToTrailingEdge = false;
+
+ if (value.isPair()) {
+ auto& first = *value.getPairValue()->first();
+ if (first.getValueID() == CSSValueRight || first.getValueID() == CSSValueBottom)
+ relativeToTrailingEdge = true;
+
+ lengthValue = value.getPairValue()->second();
+ }
+
+ length = convertLength(styleResolver, *lengthValue);
+
+ if (relativeToTrailingEdge)
+ length = convertTo100PercentMinusLength(length);
+
+ return length;
+}
+
+inline LengthPoint StyleBuilderConverter::convertObjectPosition(StyleResolver& styleResolver, CSSValue& value)
+{
+ auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+ Pair* pair = primitiveValue.getPairValue();
+ if (!pair || !pair->first() || !pair->second())
+ return RenderStyle::initialObjectPosition();
+
+ Length lengthX = convertPositionComponent(styleResolver, *pair->first());
+ Length lengthY = convertPositionComponent(styleResolver, *pair->second());
+
+ return LengthPoint(lengthX, lengthY);
+}
+
inline TextDecoration StyleBuilderConverter::convertTextDecoration(StyleResolver&, CSSValue& value)
{
TextDecoration result = RenderStyle::initialTextDecoration();
@@ -735,7 +788,6 @@ inline std::unique_ptr<ScrollSnapPoints> StyleBuilderConverter::convertScrollSna
return points;
}
- points->hasRepeat = false;
for (auto& currentValue : downcast<CSSValueList>(value)) {
auto& itemValue = downcast<CSSPrimitiveValue>(currentValue.get());
if (auto* lengthRepeat = itemValue.getLengthRepeatValue()) {
diff --git a/Source/WebCore/cssjit/SelectorCompiler.cpp b/Source/WebCore/cssjit/SelectorCompiler.cpp
index 7139f52d7..7597a9c90 100644
--- a/Source/WebCore/cssjit/SelectorCompiler.cpp
+++ b/Source/WebCore/cssjit/SelectorCompiler.cpp
@@ -3164,10 +3164,22 @@ void SelectorCodeGenerator::generateElementIsHovered(Assembler::JumpList& failur
generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByHover);
+ Assembler::JumpList successCases;
+ if (m_selectorContext != SelectorContext::QuerySelector && fragment.relationToRightFragment != FragmentRelation::Rightmost) {
+ // :hover always matches when not in rightmost position when collecting rules for descendant style invalidation optimization.
+ // Resolving style for a matching descendant will set parent childrenAffectedByHover bit even when the element is not currently hovered.
+ // This bit has to be set for the event based :hover invalidation to work.
+ // FIXME: We should just collect style relation bits and apply them as needed when computing style invalidation optimization.
+ LocalRegister checkingContext(m_registerAllocator);
+ successCases.append(branchOnResolvingMode(Assembler::Equal, SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements, checkingContext));
+ }
+
FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
functionCall.setFunctionAddress(elementIsHovered);
functionCall.setOneArgument(elementAddressRegister);
failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
+
+ successCases.link(&m_assembler);
}
void SelectorCodeGenerator::generateElementIsInLanguage(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index 5fe400c82..c7d87bb6c 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -343,19 +343,6 @@ static inline bool isValidNamePart(UChar32 c)
return true;
}
-static bool shouldInheritSecurityOriginFromOwner(const URL& url)
-{
- // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
- //
- // If a Document has the address "about:blank"
- // The origin of the Document is the origin it was assigned when its browsing context was created.
- //
- // Note: We generalize this to all "blank" URLs and invalid URLs because we
- // treat all of these URLs as about:blank.
- //
- return url.isEmpty() || url.isBlankURL();
-}
-
static Widget* widgetForElement(Element* focusedElement)
{
if (!focusedElement)
@@ -546,8 +533,6 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig
, m_cookieCacheExpiryTimer(*this, &Document::invalidateDOMCookieCache)
, m_disabledFieldsetElementsCount(0)
, m_hasInjectedPlugInsScript(false)
- , m_renderTreeBeingDestroyed(false)
- , m_hasPreparedForDestruction(false)
, m_hasStyleWithViewportUnits(false)
{
allDocuments().add(this);
@@ -680,6 +665,7 @@ void Document::removedLastRef()
// until after removeDetachedChildren returns, so we protect ourselves.
incrementReferencingNodeCount();
+ prepareForDestruction();
// We must make sure not to be retaining any of our children through
// these extra pointers or we will create a reference cycle.
m_focusedElement = nullptr;
@@ -2575,12 +2561,11 @@ void Document::cancelParsing()
void Document::implicitOpen()
{
- cancelParsing();
-
removeChildren();
setCompatibilityMode(DocumentCompatibilityMode::NoQuirksMode);
+ cancelParsing();
m_parser = createParser();
setParsing(true);
setReadyState(Loading);
@@ -5080,6 +5065,20 @@ RefPtr<XPathResult> Document::evaluate(const String& expression, Node* contextNo
return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
}
+static bool shouldInheritSecurityOriginFromOwner(const URL& url)
+{
+ // Paraphrased from <https://html.spec.whatwg.org/multipage/browsers.html#origin> (8 July 2016)
+ //
+ // If a Document has the address "about:blank"
+ // The origin of the document is the origin it was assigned when its browsing context was created.
+ // If a Document has the address "about:srcdoc"
+ // The origin of the document is the origin of its parent document.
+ //
+ // Note: We generalize this to invalid URLs because we treat such URLs as about:blank.
+ //
+ return url.isEmpty() || equalIgnoringASCIICase(url.string(), blankURL()) || equalLettersIgnoringASCIICase(url.string(), "about:srcdoc");
+}
+
void Document::initSecurityContext()
{
if (haveInitializedSecurityOrigin()) {
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index 1472b0bdc..cd35b20e6 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -1759,8 +1759,8 @@ private:
unsigned m_disabledFieldsetElementsCount;
bool m_hasInjectedPlugInsScript;
- bool m_renderTreeBeingDestroyed;
- bool m_hasPreparedForDestruction;
+ bool m_renderTreeBeingDestroyed { false };
+ bool m_hasPreparedForDestruction { false };
bool m_hasStyleWithViewportUnits;
bool m_isTimerThrottlingEnabled { false };
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 84ccf5666..cd85ae496 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -2489,7 +2489,7 @@ bool Element::needsStyleInvalidation() const
return false;
if (styleChangeType() >= FullStyleChange)
return false;
- if (!document().styleResolverIfExists())
+ if (document().hasPendingForcedStyleRecalc())
return false;
return true;
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index ba9886615..34495b5c7 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -938,65 +938,6 @@ bool Node::containsIncludingHostElements(const Node* node) const
#endif
}
-static inline Node* ancestor(Node* node, unsigned depth)
-{
- for (unsigned i = 0; i < depth; ++i)
- node = node->parentNode();
- return node;
-}
-
-Node* commonAncestor(Node& thisNode, Node& otherNode)
-{
- unsigned thisDepth = 0;
- for (auto node = &thisNode; node; node = node->parentNode()) {
- if (node == &otherNode)
- return node;
- thisDepth++;
- }
- unsigned otherDepth = 0;
- for (auto node = &otherNode; node; node = node->parentNode()) {
- if (node == &thisNode)
- return &thisNode;
- otherDepth++;
- }
-
- Node* thisAncestor = &thisNode;
- Node* otherAncestor = &otherNode;
- if (thisDepth > otherDepth)
- thisAncestor = ancestor(thisAncestor, thisDepth - otherDepth);
- else if (otherDepth > thisDepth)
- otherAncestor = ancestor(otherAncestor, otherDepth - thisDepth);
-
- for (; thisAncestor; thisAncestor = thisAncestor->parentNode()) {
- if (thisAncestor == otherAncestor)
- return thisAncestor;
- otherAncestor = otherAncestor->parentNode();
- }
- ASSERT(!otherAncestor);
- return nullptr;
-}
-
-Node* commonAncestorCrossingShadowBoundary(Node& node, Node& other)
-{
- if (&node == &other)
- return &node;
-
- Element* shadowHost = node.shadowHost();
- // FIXME: This test might be wrong for user-authored shadow trees.
- if (shadowHost && shadowHost == other.shadowHost())
- return shadowHost;
-
- TreeScope* scope = commonTreeScope(&node, &other);
- if (!scope)
- return nullptr;
-
- Node* parentNode = scope->ancestorInThisScope(&node);
- ASSERT(parentNode);
- Node* parentOther = scope->ancestorInThisScope(&other);
- ASSERT(parentOther);
- return commonAncestor(*parentNode, *parentOther);
-}
-
Node* Node::pseudoAwarePreviousSibling() const
{
Element* parentOrHost = is<PseudoElement>(*this) ? downcast<PseudoElement>(*this).hostElement() : parentElement();
diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h
index ec24e2163..842bd8775 100644
--- a/Source/WebCore/dom/Node.h
+++ b/Source/WebCore/dom/Node.h
@@ -791,9 +791,6 @@ inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
return parentNode();
}
-Node* commonAncestor(Node&, Node&);
-Node* commonAncestorCrossingShadowBoundary(Node&, Node&);
-
} // namespace WebCore
#if ENABLE(TREE_DEBUGGING)
diff --git a/Source/WebCore/editing/SpellChecker.cpp b/Source/WebCore/editing/SpellChecker.cpp
index 577ec957f..d9ee2f149 100644
--- a/Source/WebCore/editing/SpellChecker.cpp
+++ b/Source/WebCore/editing/SpellChecker.cpp
@@ -77,6 +77,8 @@ void SpellCheckRequest::didSucceed(const Vector<TextCheckingResult>& results)
{
if (!m_checker)
return;
+
+ Ref<SpellCheckRequest> protectedThis(*this);
m_checker->didCheckSucceed(m_requestData.sequence(), results);
m_checker = nullptr;
}
@@ -85,6 +87,8 @@ void SpellCheckRequest::didCancel()
{
if (!m_checker)
return;
+
+ Ref<SpellCheckRequest> protectedThis(*this);
m_checker->didCheckCancel(m_requestData.sequence());
m_checker = nullptr;
}
diff --git a/Source/WebCore/editing/atk/FrameSelectionAtk.cpp b/Source/WebCore/editing/atk/FrameSelectionAtk.cpp
index 45f0e3b7f..ef77128ba 100644
--- a/Source/WebCore/editing/atk/FrameSelectionAtk.cpp
+++ b/Source/WebCore/editing/atk/FrameSelectionAtk.cpp
@@ -94,12 +94,15 @@ void FrameSelection::notifyAccessibilityForSelectionChange(const AXTextStateChan
if (!m_selection.start().isNotNull() || !m_selection.end().isNotNull())
return;
- RenderObject* focusedNode = m_selection.end().containerNode()->renderer();
+ Node* focusedNode = m_selection.end().containerNode();
+ if (!focusedNode)
+ return;
+
AXObjectCache* cache = m_frame->document()->existingAXObjectCache();
if (!cache)
return;
- AccessibilityObject* accessibilityObject = cache->getOrCreate(focusedNode);
+ AccessibilityObject* accessibilityObject = cache->getOrCreate(focusedNode->renderer());
if (!accessibilityObject)
return;
diff --git a/Source/WebCore/html/HTMLMarqueeElement.cpp b/Source/WebCore/html/HTMLMarqueeElement.cpp
index 6bd6545af..4791ae9ae 100644
--- a/Source/WebCore/html/HTMLMarqueeElement.cpp
+++ b/Source/WebCore/html/HTMLMarqueeElement.cpp
@@ -55,7 +55,7 @@ int HTMLMarqueeElement::minimumDelay() const
// WinIE uses 60ms as the minimum delay by default.
return 60;
}
- return 0;
+ return 16; // Don't allow timers at < 16ms intervals to avoid CPU hogging: webkit.org/b/160609
}
bool HTMLMarqueeElement::isPresentationAttribute(const QualifiedName& name) const
diff --git a/Source/WebCore/html/HTMLMarqueeElement.h b/Source/WebCore/html/HTMLMarqueeElement.h
index 394a163b5..a20926ecd 100644
--- a/Source/WebCore/html/HTMLMarqueeElement.h
+++ b/Source/WebCore/html/HTMLMarqueeElement.h
@@ -41,12 +41,15 @@ public:
void start();
virtual void stop() override;
+ // Number of pixels to move on each scroll movement. Defaults to 6.
int scrollAmount() const;
void setScrollAmount(int, ExceptionCode&);
+ // Interval between each scroll movement, in milliseconds. Defaults to 60.
int scrollDelay() const;
void setScrollDelay(int, ExceptionCode&);
+ // Loop count. -1 means loop indefinitely.
int loop() const;
void setLoop(int, ExceptionCode&);
diff --git a/Source/WebCore/html/ImageData.cpp b/Source/WebCore/html/ImageData.cpp
index 27b57c372..907eb702c 100644
--- a/Source/WebCore/html/ImageData.cpp
+++ b/Source/WebCore/html/ImageData.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2016 Apple Inc. All rights reserved.
* Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -115,6 +115,7 @@ ImageData::ImageData(const IntSize& size)
: m_size(size)
, m_data(Uint8ClampedArray::createUninitialized(size.width() * size.height() * 4))
{
+ ASSERT_WITH_SECURITY_IMPLICATION(m_data);
}
ImageData::ImageData(const IntSize& size, PassRefPtr<Uint8ClampedArray> byteArray)
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 829e7b356..b87f68ee4 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -350,12 +350,25 @@ inline void CanvasRenderingContext2D::FontProxy::drawBidiText(GraphicsContext& c
context.drawBidiText(m_font, run, point, action);
}
+void CanvasRenderingContext2D::realizeSaves()
+{
+ if (m_unrealizedSaveCount)
+ realizeSavesLoop();
+
+ if (m_unrealizedSaveCount) {
+ static NeverDestroyed<String> consoleMessage(ASCIILiteral("CanvasRenderingContext2D.save() has been called without a matching restore() too many times. Ignoring save()."));
+ canvas()->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, consoleMessage);
+ }
+}
+
void CanvasRenderingContext2D::realizeSavesLoop()
{
ASSERT(m_unrealizedSaveCount);
ASSERT(m_stateStack.size() >= 1);
GraphicsContext* context = drawingContext();
do {
+ if (m_stateStack.size() > MaxSaveCount)
+ break;
m_stateStack.append(state());
if (context)
context->save();
@@ -1458,7 +1471,7 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* imageElement, const F
if (image->isSVGImage()) {
image->setImageObserver(nullptr);
- image->setContainerSize(normalizedSrcRect.size());
+ image->setContainerSize(imageRect.size());
}
if (rectContainsCanvas(normalizedDstRect)) {
@@ -2090,8 +2103,17 @@ RefPtr<ImageData> CanvasRenderingContext2D::getImageData(ImageBuffer::Coordinate
return createEmptyImageData(imageDataRect.size());
RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect, coordinateSystem);
- if (!byteArray)
+ if (!byteArray) {
+ StringBuilder consoleMessage;
+ consoleMessage.appendLiteral("Unable to get image data from canvas. Requested size was ");
+ consoleMessage.appendNumber(imageDataRect.width());
+ consoleMessage.appendLiteral(" x ");
+ consoleMessage.appendNumber(imageDataRect.height());
+
+ canvas()->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, consoleMessage.toString());
+ ec = INVALID_STATE_ERR;
return nullptr;
+ }
return ImageData::create(imageDataRect.size(), byteArray.release());
}
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h
index a334873dc..783e95d31 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h
@@ -318,7 +318,7 @@ private:
CanvasDidDrawApplyAll = 0xffffffff
};
- State& modifiableState() { ASSERT(!m_unrealizedSaveCount); return m_stateStack.last(); }
+ State& modifiableState() { ASSERT(!m_unrealizedSaveCount || m_stateStack.size() >= MaxSaveCount); return m_stateStack.last(); }
const State& state() const { return m_stateStack.last(); }
void applyLineDash() const;
@@ -334,11 +334,7 @@ private:
GraphicsContext* drawingContext() const;
void unwindStateStack();
- void realizeSaves()
- {
- if (m_unrealizedSaveCount)
- realizeSavesLoop();
- }
+ void realizeSaves();
void realizeSavesLoop();
void applyStrokePattern();
@@ -394,6 +390,7 @@ private:
virtual PlatformLayer* platformLayer() const override;
#endif
+ static const unsigned MaxSaveCount = 1024 * 16;
Vector<State, 1> m_stateStack;
unsigned m_unrealizedSaveCount { 0 };
bool m_usesCSSCompatibilityParseMode;
diff --git a/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp b/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp
index d6deef34f..37827fcda 100644
--- a/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp
+++ b/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp
@@ -494,7 +494,7 @@ static IDBFactory* assertIDBFactory(ErrorString& errorString, Document* document
return nullptr;
}
- IDBFactory* idbFactory = DOMWindowIndexedDatabase::indexedDB(domWindow);
+ IDBFactory* idbFactory = DOMWindowIndexedDatabase::indexedDB(*domWindow);
if (!idbFactory)
errorString = ASCIILiteral("No IndexedDB factory for given frame found");
diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp
index d91420c58..9bc231ca2 100644
--- a/Source/WebCore/page/DOMWindow.cpp
+++ b/Source/WebCore/page/DOMWindow.cpp
@@ -477,6 +477,8 @@ Page* DOMWindow::page()
void DOMWindow::frameDestroyed()
{
+ Ref<DOMWindow> protectedThis(*this);
+
willDestroyDocumentInFrame();
FrameDestructionObserver::frameDestroyed();
resetDOMWindowProperties();
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index f13749ba0..e8aa9dfb3 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -1128,14 +1128,14 @@ HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTe
}
}
+ // We should always start hit testing a clean tree.
+ if (m_frame.document())
+ m_frame.document()->updateLayoutIgnorePendingStylesheets();
HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width());
-
RenderView* renderView = m_frame.contentRenderer();
if (!renderView)
return result;
-
- // We should always start hittesting a clean tree.
- renderView->document().updateLayoutIgnorePendingStylesheets();
+
// hitTestResultAtPoint is specifically used to hitTest into all frames, thus it always allows child frame content.
HitTestRequest request(hitType | HitTestRequest::AllowChildFrameContent);
renderView->hitTest(request, result);
@@ -1948,6 +1948,24 @@ void EventHandler::invalidateClick()
m_clickNode = nullptr;
}
+static Node* targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNode)
+{
+ if (!mousePressNode || !mouseReleaseNode)
+ return nullptr;
+
+ if (mousePressNode == mouseReleaseNode)
+ return mouseReleaseNode;
+
+ Element* mouseReleaseShadowHost = mouseReleaseNode->shadowHost();
+ if (mouseReleaseShadowHost && mouseReleaseShadowHost == mousePressNode->shadowHost()) {
+ // We want to dispatch the click to the shadow tree host element to give listeners the illusion that the
+ // shadom tree is a single element. For example, we want to give the illusion that <input type="range">
+ // is a single element even though it is a composition of multiple shadom tree elements.
+ return mouseReleaseShadowHost;
+ }
+ return nullptr;
+}
+
bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& platformMouseEvent)
{
RefPtr<FrameView> protector(m_frame.view());
@@ -2009,8 +2027,7 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& platformMou
bool contextMenuEvent = platformMouseEvent.button() == RightButton;
- Node* targetNode = mouseEvent.targetNode();
- Node* nodeToClick = (m_clickNode && targetNode) ? commonAncestorCrossingShadowBoundary(*m_clickNode, *targetNode) : nullptr;
+ Node* nodeToClick = targetNodeForClickEvent(m_clickNode.get(), mouseEvent.targetNode());
bool swallowClickEvent = m_clickCount > 0 && !contextMenuEvent && nodeToClick && !dispatchMouseEvent(eventNames().clickEvent, nodeToClick, true, m_clickCount, platformMouseEvent, true);
if (m_resizeLayer) {
diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp
index c3b46c920..b1b84a462 100644
--- a/Source/WebCore/page/Frame.cpp
+++ b/Source/WebCore/page/Frame.cpp
@@ -217,8 +217,8 @@ Frame::~Frame()
disconnectOwnerElement();
- for (auto& observer : m_destructionObservers)
- observer->frameDestroyed();
+ while (auto* destructionObserver = m_destructionObservers.takeAny())
+ destructionObserver->frameDestroyed();
if (!isMainFrame())
m_mainFrame.selfOnlyDeref();
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index e1dd28906..4bae77613 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -2649,7 +2649,9 @@ void FrameView::scheduleRelayoutOfSubtree(RenderElement& newRelayoutRoot)
ASSERT(!renderView.documentBeingDestroyed());
ASSERT(frame().view() == this);
- if (renderView.needsLayout()) {
+ // When m_layoutRoot is already set, ignore the renderView's needsLayout bit
+ // since we need to resolve the conflict between the m_layoutRoot and newRelayoutRoot layouts.
+ if (renderView.needsLayout() && !m_layoutRoot) {
m_layoutRoot = &newRelayoutRoot;
convertSubtreeLayoutToFullLayout();
return;
@@ -2657,7 +2659,7 @@ void FrameView::scheduleRelayoutOfSubtree(RenderElement& newRelayoutRoot)
if (!layoutPending() && m_layoutSchedulingEnabled) {
std::chrono::milliseconds delay = renderView.document().minimumLayoutDelay();
- ASSERT(!newRelayoutRoot.container() || !newRelayoutRoot.container()->needsLayout());
+ ASSERT(!newRelayoutRoot.container() || is<RenderView>(newRelayoutRoot.container()) || !newRelayoutRoot.container()->needsLayout());
m_layoutRoot = &newRelayoutRoot;
InspectorInstrumentation::didInvalidateLayout(frame());
m_delayedLayout = delay.count();
@@ -2678,7 +2680,7 @@ void FrameView::scheduleRelayoutOfSubtree(RenderElement& newRelayoutRoot)
if (isObjectAncestorContainerOf(m_layoutRoot, &newRelayoutRoot)) {
// Keep the current root.
newRelayoutRoot.markContainingBlocksForLayout(ScheduleRelayout::No, m_layoutRoot);
- ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
+ ASSERT(!m_layoutRoot->container() || is<RenderView>(m_layoutRoot->container()) || !m_layoutRoot->container()->needsLayout());
return;
}
@@ -2686,7 +2688,7 @@ void FrameView::scheduleRelayoutOfSubtree(RenderElement& newRelayoutRoot)
// Re-root at newRelayoutRoot.
m_layoutRoot->markContainingBlocksForLayout(ScheduleRelayout::No, &newRelayoutRoot);
m_layoutRoot = &newRelayoutRoot;
- ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
+ ASSERT(!m_layoutRoot->container() || is<RenderView>(m_layoutRoot->container()) || !m_layoutRoot->container()->needsLayout());
InspectorInstrumentation::didInvalidateLayout(frame());
return;
}
diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp
index b9571c1d4..d4f184ced 100644
--- a/Source/WebCore/page/History.cpp
+++ b/Source/WebCore/page/History.cpp
@@ -154,6 +154,15 @@ void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const Str
return;
}
+ if (fullURL.hasUsername() || fullURL.hasPassword()) {
+ ec.code = SECURITY_ERR;
+ if (stateObjectType == StateObjectType::Replace)
+ ec.message = makeString("Attempt to use history.replaceState() to change session history URL to ", fullURL.string(), " is insecure; Username/passwords aren't allowed in state object URLs");
+ else
+ ec.message = makeString("Attempt to use history.pushState() to add URL ", fullURL.string(), " to session history is insecure; Username/passwords aren't allowed in state object URLs");
+ return;
+ }
+
Document* mainDocument = m_frame->page()->mainFrame().document();
History* mainHistory = nullptr;
if (mainDocument) {
diff --git a/Source/WebCore/page/Location.cpp b/Source/WebCore/page/Location.cpp
index fea54e4af..7eb40017a 100644
--- a/Source/WebCore/page/Location.cpp
+++ b/Source/WebCore/page/Location.cpp
@@ -60,7 +60,15 @@ String Location::href() const
if (!m_frame)
return String();
- return url().string();
+ auto& url = this->url();
+
+ if (!url.hasUsername() && !url.hasPassword())
+ return url.string();
+
+ URL urlWithoutCredentials(url);
+ urlWithoutCredentials.setUser(WTF::emptyString());
+ urlWithoutCredentials.setPass(WTF::emptyString());
+ return urlWithoutCredentials.string();
}
String Location::protocol() const
diff --git a/Source/WebCore/page/SecurityOrigin.cpp b/Source/WebCore/page/SecurityOrigin.cpp
index 976c33f3f..997a74882 100644
--- a/Source/WebCore/page/SecurityOrigin.cpp
+++ b/Source/WebCore/page/SecurityOrigin.cpp
@@ -375,11 +375,6 @@ bool SecurityOrigin::canAccessStorage(const SecurityOrigin* topOrigin, ShouldAll
if (m_storageBlockingPolicy == BlockAllStorage)
return false;
- // We allow access to local storage from file URLs also when allowFileAccessFromFileURLs setting is enabled,
- // for backwards compatibility only in WebKitGTK+ 2.12 branch, this should not be backported to any other branch, nor trunk.
- if (isLocal() && !m_universalAccess && m_enforceFilePathSeparation && shouldAllowFromThirdParty != AlwaysAllowFromThirdParty)
- return false;
-
// FIXME: This check should be replaced with an ASSERT once we can guarantee that topOrigin is not null.
if (!topOrigin)
return true;
diff --git a/Source/WebCore/page/Settings.in b/Source/WebCore/page/Settings.in
index b54f8d31d..24f7e40ec 100644
--- a/Source/WebCore/page/Settings.in
+++ b/Source/WebCore/page/Settings.in
@@ -79,6 +79,7 @@ needsSiteSpecificQuirks initial=false
domTimersThrottlingEnabled initial=true
webArchiveDebugModeEnabled initial=false, conditional=WEB_ARCHIVE
localFileContentSniffingEnabled initial=false
+offlineStorageDatabaseEnabled initial=false
offlineWebApplicationCacheEnabled initial=false
enforceCSSMIMETypeInNoQuirksMode initial=true
usesEncodingDetector initial=false
diff --git a/Source/WebCore/page/animation/AnimationController.cpp b/Source/WebCore/page/animation/AnimationController.cpp
index 9bcb2fed1..e1d7f4a50 100644
--- a/Source/WebCore/page/animation/AnimationController.cpp
+++ b/Source/WebCore/page/animation/AnimationController.cpp
@@ -48,7 +48,7 @@
namespace WebCore {
-static const double cAnimationTimerDelay = 0.025;
+static const double cAnimationTimerDelay = 1.0 / 60;
static const double cBeginAnimationUpdateTimeNotSet = -1;
class AnimationPrivateUpdateBlock {
diff --git a/Source/WebCore/platform/LengthPoint.cpp b/Source/WebCore/platform/LengthPoint.cpp
new file mode 100644
index 000000000..6e6235cfc
--- /dev/null
+++ b/Source/WebCore/platform/LengthPoint.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LengthPoint.h"
+
+#include "TextStream.h"
+
+namespace WebCore {
+
+TextStream& operator<<(TextStream& ts, const LengthPoint& size)
+{
+ return ts << size.x() << " " << size.y();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/LengthPoint.h b/Source/WebCore/platform/LengthPoint.h
new file mode 100644
index 000000000..21b1a3f47
--- /dev/null
+++ b/Source/WebCore/platform/LengthPoint.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LengthPoint_h
+#define LengthPoint_h
+
+#include "Length.h"
+
+namespace WebCore {
+
+struct LengthPoint {
+public:
+ LengthPoint()
+ {
+ }
+
+ LengthPoint(Length x, Length y)
+ : m_x(WTFMove(x))
+ , m_y(WTFMove(y))
+ {
+ }
+
+ bool operator==(const LengthPoint& o) const
+ {
+ return m_x == o.m_x && m_y == o.m_y;
+ }
+
+ bool operator!=(const LengthPoint& o) const
+ {
+ return !(*this == o);
+ }
+
+ void setX(Length x) { m_x = WTFMove(x); }
+ const Length& x() const { return m_x; }
+
+ void setY(Length y) { m_y = WTFMove(y); }
+ const Length& y() const { return m_y; }
+
+ LengthPoint blend(const LengthPoint& from, double progress) const
+ {
+ return LengthPoint(m_x.blend(from.x(), progress), m_y.blend(from.y(), progress));
+ }
+
+private:
+ // FIXME: it would be nice to pack the two Lengths together better somehow (to avoid padding between them).
+ Length m_x;
+ Length m_y;
+};
+
+TextStream& operator<<(TextStream&, const LengthPoint&);
+
+} // namespace WebCore
+
+#endif // LengthPoint_h
diff --git a/Source/WebCore/platform/SharedBuffer.cpp b/Source/WebCore/platform/SharedBuffer.cpp
index 00fcf6753..c7e05bf23 100644
--- a/Source/WebCore/platform/SharedBuffer.cpp
+++ b/Source/WebCore/platform/SharedBuffer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
* Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
* Copyright (C) 2015 Canon Inc. All rights reserved.
*
@@ -144,6 +144,10 @@ const char* SharedBuffer::data() const
PassRefPtr<ArrayBuffer> SharedBuffer::createArrayBuffer() const
{
RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::createUninitialized(static_cast<unsigned>(size()), sizeof(char));
+ if (!arrayBuffer) {
+ WTFLogAlways("SharedBuffer::createArrayBuffer Unable to create buffer. Requested size was %d x %lu\n", size(), sizeof(char));
+ return nullptr;
+ }
const char* segment = 0;
unsigned position = 0;
diff --git a/Source/WebCore/platform/URL.cpp b/Source/WebCore/platform/URL.cpp
index b2e1fde94..857bc7e6e 100644
--- a/Source/WebCore/platform/URL.cpp
+++ b/Source/WebCore/platform/URL.cpp
@@ -104,15 +104,19 @@ enum URLCharacterClasses {
PathSegmentEndChar = 1 << 5,
// not allowed in path
- BadChar = 1 << 6
+ BadChar = 1 << 6,
+
+ // "\t" | "\n" | "\r"
+ TabNewline = 1 << 7
};
static const unsigned char characterClassTable[256] = {
/* 0 nul */ PathSegmentEndChar, /* 1 soh */ BadChar,
/* 2 stx */ BadChar, /* 3 etx */ BadChar,
/* 4 eot */ BadChar, /* 5 enq */ BadChar, /* 6 ack */ BadChar, /* 7 bel */ BadChar,
- /* 8 bs */ BadChar, /* 9 ht */ BadChar, /* 10 nl */ BadChar, /* 11 vt */ BadChar,
- /* 12 np */ BadChar, /* 13 cr */ BadChar, /* 14 so */ BadChar, /* 15 si */ BadChar,
+ /* 8 bs */ BadChar, /* 9 ht */ BadChar | TabNewline, /* 10 nl */ BadChar | TabNewline,
+ /* 11 vt */ BadChar, /* 12 np */ BadChar, /* 13 cr */ BadChar | TabNewline,
+ /* 14 so */ BadChar, /* 15 si */ BadChar,
/* 16 dle */ BadChar, /* 17 dc1 */ BadChar, /* 18 dc2 */ BadChar, /* 19 dc3 */ BadChar,
/* 20 dc4 */ BadChar, /* 21 nak */ BadChar, /* 22 syn */ BadChar, /* 23 etb */ BadChar,
/* 24 can */ BadChar, /* 25 em */ BadChar, /* 26 sub */ BadChar, /* 27 esc */ BadChar,
@@ -350,6 +354,7 @@ static inline bool isIPv6Char(unsigned char c) { return characterClassTable[c] &
static inline bool isPathSegmentEndChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & PathSegmentEndChar; }
static inline bool isPathSegmentEndChar(UChar c) { return c <= 0xff && (characterClassTable[c] & PathSegmentEndChar); }
static inline bool isBadChar(unsigned char c) { return characterClassTable[c] & BadChar; }
+static inline bool isTabNewline(UChar c) { return c <= 0xff && (characterClassTable[c] & TabNewline); }
static inline bool isSchemeCharacterMatchIgnoringCase(char character, char schemeCharacter)
{
@@ -455,7 +460,7 @@ URL::URL(const URL& base, const String& relative, const TextEncoding& encoding)
init(base, relative, encoding.encodingForFormSubmission());
}
-static bool shouldTrimFromURL(unsigned char c)
+static bool shouldTrimFromURL(UChar c)
{
// Browsers ignore leading/trailing whitespace and control
// characters from URLs. Note that c is an *unsigned* char here
@@ -473,9 +478,14 @@ void URL::init(const URL& base, const String& relative, const TextEncoding& enco
return;
}
+ // Get rid of leading and trailing whitespace and control characters.
+ String rel = relative.stripWhiteSpace(shouldTrimFromURL);
+
+ // Get rid of any tabs and newlines.
+ rel = rel.removeCharacters(isTabNewline);
+
// For compatibility with Win IE, treat backslashes as if they were slashes,
// as long as we're not dealing with javascript: or data: URLs.
- String rel = relative;
if (rel.contains('\\') && !(protocolIsJavaScript(rel) || protocolIs(rel, "data")))
rel = substituteBackslashes(rel);
@@ -500,16 +510,6 @@ void URL::init(const URL& base, const String& relative, const TextEncoding& enco
len = strlen(str);
}
- // Get rid of leading whitespace and control characters.
- while (len && shouldTrimFromURL(*str)) {
- str++;
- --len;
- }
-
- // Get rid of trailing whitespace and control characters.
- while (len && shouldTrimFromURL(str[len - 1]))
- str[--len] = '\0';
-
// According to the RFC, the reference should be interpreted as an
// absolute URI if possible, using the "leftmost, longest"
// algorithm. If the URI reference is absolute it will have a
@@ -1934,12 +1934,26 @@ bool protocolIs(const String& url, const char* protocol)
{
// Do the comparison without making a new string object.
assertProtocolIsGood(protocol);
- for (int i = 0; ; ++i) {
- if (!protocol[i])
+ bool isLeading = true;
+ for (int i = 0, j = 0; url[i]; ++i) {
+ // skip leading whitespace and control characters.
+ if (isLeading && shouldTrimFromURL(url[i]))
+ continue;
+ isLeading = false;
+
+ // skip any tabs and newlines.
+ if (isTabNewline(url[i]))
+ continue;
+
+ if (!protocol[j])
return url[i] == ':';
- if (!isLetterMatchIgnoringCase(url[i], protocol[i]))
+ if (!isLetterMatchIgnoringCase(url[i], protocol[j]))
return false;
+
+ ++j;
}
+
+ return false;
}
bool isValidProtocol(const String& protocol)
diff --git a/Source/WebCore/platform/URL.h b/Source/WebCore/platform/URL.h
index 5fcee4880..f9bfce6dc 100644
--- a/Source/WebCore/platform/URL.h
+++ b/Source/WebCore/platform/URL.h
@@ -120,6 +120,9 @@ public:
WEBCORE_EXPORT String fragmentIdentifier() const;
WEBCORE_EXPORT bool hasFragmentIdentifier() const;
+ bool hasUsername() const;
+ bool hasPassword() const;
+
// Unlike user() and pass(), these functions don't decode escape sequences.
// This is necessary for accurate round-tripping, because encoding doesn't encode '%' characters.
String encodedUser() const;
@@ -354,6 +357,16 @@ inline bool URL::hasPort() const
return m_hostEnd < m_portEnd;
}
+inline bool URL::hasUsername() const
+{
+ return m_userEnd > m_userStart;
+}
+
+inline bool URL::hasPassword() const
+{
+ return m_passwordEnd > (m_userEnd + 1);
+}
+
inline bool URL::protocolIsInHTTPFamily() const
{
return m_protocolIsInHTTPFamily;
diff --git a/Source/WebCore/platform/graphics/PlatformDisplay.cpp b/Source/WebCore/platform/graphics/PlatformDisplay.cpp
index 19a6b99a8..bdae5f45f 100644
--- a/Source/WebCore/platform/graphics/PlatformDisplay.cpp
+++ b/Source/WebCore/platform/graphics/PlatformDisplay.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "PlatformDisplay.h"
+#include <cstdlib>
#include <mutex>
#include <wtf/NeverDestroyed.h>
@@ -112,10 +113,8 @@ PlatformDisplay::PlatformDisplay()
PlatformDisplay::~PlatformDisplay()
{
- // WinCairo crashes when terminating EGL on exit.
- // https://bugs.webkit.org/show_bug.cgi?id=145832
-#if USE(EGL) && !PLATFORM(WIN)
- terminateEGLDisplay();
+#if USE(EGL)
+ ASSERT(m_eglDisplay == EGL_NO_DISPLAY);
#endif
}
@@ -159,10 +158,21 @@ void PlatformDisplay::initializeEGLDisplay()
terminateEGLDisplay();
return;
}
+
+ // EGL registers atexit handlers to cleanup its global display list.
+ // Since the global PlatformDisplay instance is created before,
+ // when the PlatformDisplay destructor is called, EGL has already removed the
+ // display from the list, causing eglTerminate() to crash. So, here we register
+ // our own atexit handler, after EGL has been initialized and after the global
+ // instance has been created to ensure we call eglTerminate() before the other
+ // EGL atexit handlers and the PlatformDisplay destructor.
+ // See https://bugs.webkit.org/show_bug.cgi?id=157973.
+ std::atexit([] { PlatformDisplay::sharedDisplay().terminateEGLDisplay(); });
}
void PlatformDisplay::terminateEGLDisplay()
{
+ ASSERT(m_eglDisplayInitialized);
if (m_eglDisplay == EGL_NO_DISPLAY)
return;
eglTerminate(m_eglDisplay);
diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
index 051871ac6..61a58b904 100644
--- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
+++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
@@ -30,6 +30,11 @@
#include "SharedBuffer.h"
#include <wtf/ByteOrder.h>
+#if USE(WOFF2)
+#include "woff2_common.h"
+#include "woff2_dec.h"
+#endif
+
namespace WebCore {
static bool readUInt32(SharedBuffer* buffer, size_t& offset, uint32_t& value)
@@ -75,7 +80,14 @@ bool isWOFF(SharedBuffer* buffer)
size_t offset = 0;
uint32_t signature;
- return readUInt32(buffer, offset, signature) && signature == woffSignature;
+ if (!readUInt32(buffer, offset, signature))
+ return false;
+
+#if USE(WOFF2)
+ return signature == woffSignature || signature == woff2::kWoff2Signature;
+#else
+ return signature == woffSignature;
+#endif
}
bool convertWOFFToSfnt(SharedBuffer* woff, Vector<char>& sfnt)
@@ -86,7 +98,26 @@ bool convertWOFFToSfnt(SharedBuffer* woff, Vector<char>& sfnt)
// Read the WOFF header.
uint32_t signature;
- if (!readUInt32(woff, offset, signature) || signature != woffSignature) {
+ if (!readUInt32(woff, offset, signature)) {
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+#if USE(WOFF2)
+ if (signature == woff2::kWoff2Signature) {
+ const uint8_t* woffData = reinterpret_cast_ptr<const uint8_t*>(woff->data());
+ const size_t woffSize = woff->size();
+ const size_t sfntSize = woff2::ComputeWOFF2FinalSize(woffData, woffSize);
+
+ if (!sfnt.tryReserveCapacity(sfntSize))
+ return false;
+ sfnt.resize(sfntSize);
+
+ return woff2::ConvertWOFF2ToTTF(reinterpret_cast<uint8_t*>(sfnt.data()), sfnt.size(), woffData, woffSize);
+ }
+#endif
+
+ if (signature != woffSignature) {
ASSERT_NOT_REACHED();
return false;
}
diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index 1904ed91a..e50ec669d 100644
--- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -5,7 +5,7 @@
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Igalia, S.L.
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
- * Copyright (C) 2015 Apple, Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -540,9 +540,12 @@ void FEGaussianBlur::platformApplySoftware()
IntSize paintSize = absolutePaintRect().size();
paintSize.scale(filter().filterScale());
RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized(paintSize.width() * paintSize.height() * 4);
- Uint8ClampedArray* tmpPixelArray = tmpImageData.get();
+ if (!tmpImageData) {
+ WTFLogAlways("FEGaussianBlur::platformApplySoftware Unable to create buffer. Requested size was %d x %d\n", paintSize.width(), paintSize.height());
+ return;
+ }
- platformApply(srcPixelArray, tmpPixelArray, kernelSize.width(), kernelSize.height(), paintSize);
+ platformApply(srcPixelArray, tmpImageData.get(), kernelSize.width(), kernelSize.height(), paintSize);
}
void FEGaussianBlur::dump()
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
index 1dcb0cb06..515d1299b 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
* Copyright (C) 2012 University of Szeged
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -260,6 +260,9 @@ inline void FilterEffect::copyImageBytes(Uint8ClampedArray* source, Uint8Clamped
IntSize scaledPaintSize(m_absolutePaintRect.size());
scaledPaintSize.scale(m_filter.filterScale());
+ if (!source || !destination)
+ return;
+
// Initialize the destination to transparent black, if not entirely covered by the source.
if (scaledRect.x() < 0 || scaledRect.y() < 0 || scaledRect.maxX() > scaledPaintSize.width() || scaledRect.maxY() > scaledPaintSize.height())
memset(destination->data(), 0, destination->length());
@@ -315,6 +318,10 @@ void FilterEffect::copyUnmultipliedImage(Uint8ClampedArray* destination, const I
ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
inputSize.scale(m_filter.filterScale());
m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
+ if (!m_unmultipliedImageResult) {
+ WTFLogAlways("FilterEffect::copyUnmultipliedImage Unable to create buffer. Requested size was %d x %d\n", inputSize.width(), inputSize.height());
+ return;
+ }
unsigned char* sourceComponent = m_premultipliedImageResult->data();
unsigned char* destinationComponent = m_unmultipliedImageResult->data();
unsigned char* end = sourceComponent + (inputSize.width() * inputSize.height() * 4);
@@ -351,6 +358,10 @@ void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const
ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
inputSize.scale(m_filter.filterScale());
m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
+ if (!m_premultipliedImageResult) {
+ WTFLogAlways("FilterEffect::copyPremultipliedImage Unable to create buffer. Requested size was %d x %d\n", inputSize.width(), inputSize.height());
+ return;
+ }
unsigned char* sourceComponent = m_unmultipliedImageResult->data();
unsigned char* destinationComponent = m_premultipliedImageResult->data();
unsigned char* end = sourceComponent + (inputSize.width() * inputSize.height() * 4);
diff --git a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
index a1a189a2b..27517db20 100644
--- a/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
+++ b/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
@@ -91,6 +91,9 @@ bool FontCustomPlatformData::supportsFormat(const String& format)
{
return equalLettersIgnoringASCIICase(format, "truetype")
|| equalLettersIgnoringASCIICase(format, "opentype")
+#if USE(WOFF2)
+ || equalLettersIgnoringASCIICase(format, "woff2")
+#endif
|| equalLettersIgnoringASCIICase(format, "woff");
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
index 428038c08..310a02247 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
@@ -537,11 +537,18 @@ void MediaPlayerPrivateGStreamerBase::repaint()
void MediaPlayerPrivateGStreamerBase::triggerRepaint(GstSample* sample)
{
+ bool triggerResize;
{
WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
+ triggerResize = !m_sample;
m_sample = sample;
}
+ if (triggerResize) {
+ LOG_MEDIA_MESSAGE("First sample reached the sink, triggering video dimensions update");
+ m_player->sizeChanged();
+ }
+
#if USE(COORDINATED_GRAPHICS_THREADED)
#if USE(GSTREAMER_GL)
pushTextureToCompositor();
diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index d2ae28f2c..df7c46836 100644
--- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -39,6 +39,8 @@
#include <gst/app/gstappsrc.h>
#include <gst/gst.h>
#include <gst/pbutils/missing-plugins.h>
+#include <wtf/Condition.h>
+#include <wtf/Lock.h>
#include <wtf/MainThread.h>
#include <wtf/Noncopyable.h>
#include <wtf/glib/GMutexLocker.h>
@@ -83,7 +85,7 @@ class CachedResourceStreamingClient final : public PlatformMediaResourceClient,
class ResourceHandleStreamingClient : public ResourceHandleClient, public StreamingClient {
WTF_MAKE_NONCOPYABLE(ResourceHandleStreamingClient); WTF_MAKE_FAST_ALLOCATED;
public:
- ResourceHandleStreamingClient(WebKitWebSrc*, const ResourceRequest&);
+ ResourceHandleStreamingClient(WebKitWebSrc*, ResourceRequest&&);
virtual ~ResourceHandleStreamingClient();
// StreamingClient virtual methods.
@@ -102,6 +104,12 @@ class ResourceHandleStreamingClient : public ResourceHandleClient, public Stream
virtual void wasBlocked(ResourceHandle*);
virtual void cannotShowURL(ResourceHandle*);
+ ThreadIdentifier m_thread { 0 };
+ Lock m_initializeRunLoopConditionMutex;
+ Condition m_initializeRunLoopCondition;
+ RunLoop* m_runLoop { nullptr };
+ Lock m_terminateRunLoopConditionMutex;
+ Condition m_terminateRunLoopCondition;
RefPtr<ResourceHandle> m_resource;
};
@@ -127,18 +135,19 @@ struct _WebKitWebSrcPrivate {
RefPtr<PlatformMediaResourceLoader> loader;
RefPtr<PlatformMediaResource> resource;
- ResourceHandleStreamingClient* client;
+ std::unique_ptr<ResourceHandleStreamingClient> client;
bool didPassAccessControlCheck;
guint64 offset;
guint64 size;
gboolean seekable;
- gboolean paused;
+ bool paused;
bool isSeeking;
guint64 requestedOffset;
+ bool createdInMainThread;
MainThreadNotifier<MainThreadSourceNotification> notifier;
GRefPtr<GstBuffer> buffer;
};
@@ -172,57 +181,20 @@ static gboolean webKitWebSrcQueryWithParent(GstPad*, GstObject*, GstQuery*);
static void webKitWebSrcNeedData(WebKitWebSrc*);
static void webKitWebSrcEnoughData(WebKitWebSrc*);
-static void webKitWebSrcSeek(WebKitWebSrc*);
+static gboolean webKitWebSrcSeek(WebKitWebSrc*, guint64);
static GstAppSrcCallbacks appsrcCallbacks = {
// need_data
[](GstAppSrc*, guint, gpointer userData) {
- WebKitWebSrc* src = WEBKIT_WEB_SRC(userData);
- WebKitWebSrcPrivate* priv = src->priv;
-
- {
- WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
- if (!priv->paused)
- return;
- }
-
- GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
- priv->notifier.notify(MainThreadSourceNotification::NeedData, [protector] { webKitWebSrcNeedData(protector.get()); });
+ webKitWebSrcNeedData(WEBKIT_WEB_SRC(userData));
},
// enough_data
[](GstAppSrc*, gpointer userData) {
- WebKitWebSrc* src = WEBKIT_WEB_SRC(userData);
- WebKitWebSrcPrivate* priv = src->priv;
-
- {
- WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
- if (priv->paused)
- return;
- }
-
- GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
- priv->notifier.notify(MainThreadSourceNotification::EnoughData, [protector] { webKitWebSrcEnoughData(protector.get()); });
+ webKitWebSrcEnoughData(WEBKIT_WEB_SRC(userData));
},
// seek_data
[](GstAppSrc*, guint64 offset, gpointer userData) -> gboolean {
- WebKitWebSrc* src = WEBKIT_WEB_SRC(userData);
- WebKitWebSrcPrivate* priv = src->priv;
-
- {
- WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
- if (offset == priv->offset && priv->requestedOffset == priv->offset)
- return TRUE;
-
- if (!priv->seekable)
- return FALSE;
-
- priv->isSeeking = true;
- priv->requestedOffset = offset;
- }
-
- GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
- priv->notifier.notify(MainThreadSourceNotification::Seek, [protector] { webKitWebSrcSeek(protector.get()); });
- return TRUE;
+ return webKitWebSrcSeek(WEBKIT_WEB_SRC(userData), offset);
},
{ nullptr }
};
@@ -287,6 +259,8 @@ static void webkit_web_src_init(WebKitWebSrc* src)
src->priv = priv;
new (priv) WebKitWebSrcPrivate();
+ priv->createdInMainThread = isMainThread();
+
priv->appsrc = GST_APP_SRC(gst_element_factory_make("appsrc", 0));
if (!priv->appsrc) {
GST_ERROR_OBJECT(src, "Failed to create appsrc");
@@ -412,28 +386,37 @@ static void webKitWebSrcStop(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
- ASSERT(isMainThread());
+ if (priv->resource || (priv->loader && !priv->keepAlive)) {
+ GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
+ priv->notifier.cancelPendingNotifications(MainThreadSourceNotification::NeedData | MainThreadSourceNotification::EnoughData | MainThreadSourceNotification::Seek);
+ bool keepAlive = priv->keepAlive;
+ priv->notifier.notify(MainThreadSourceNotification::Stop, [protector, keepAlive] {
+ WebKitWebSrcPrivate* priv = protector->priv;
+
+ WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(protector.get()));
+ if (priv->resource) {
+ priv->resource->stop();
+ priv->resource->setClient(nullptr);
+ priv->resource = nullptr;
+ }
+
+ if (!keepAlive)
+ priv->loader = nullptr;
+ });
+ }
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
bool wasSeeking = std::exchange(priv->isSeeking, false);
- priv->notifier.cancelPendingNotifications(MainThreadSourceNotification::NeedData | MainThreadSourceNotification::EnoughData | MainThreadSourceNotification::Seek);
-
- if (priv->client) {
- delete priv->client;
- priv->client = 0;
- }
-
- if (!priv->keepAlive)
- priv->loader = nullptr;
+ priv->client = nullptr;
if (priv->buffer) {
unmapGstBuffer(priv->buffer.get());
priv->buffer.clear();
}
- priv->paused = FALSE;
+ priv->paused = false;
priv->offset = 0;
priv->seekable = FALSE;
@@ -510,8 +493,6 @@ static void webKitWebSrcStart(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
- ASSERT(isMainThread());
-
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
priv->didPassAccessControlCheck = false;
@@ -576,37 +557,41 @@ static void webKitWebSrcStart(WebKitWebSrc* src)
// We always request Icecast/Shoutcast metadata, just in case ...
request.setHTTPHeaderField(HTTPHeaderName::IcyMetadata, "1");
- bool loadFailed = true;
- if (priv->player && !priv->loader)
- priv->loader = priv->player->createResourceLoader();
+ if (!priv->player || !priv->createdInMainThread) {
+ priv->client = std::make_unique<ResourceHandleStreamingClient>(src, WTFMove(request));
+ if (priv->client->loadFailed()) {
+ GST_ERROR_OBJECT(src, "Failed to setup streaming client");
+ priv->client = nullptr;
+ locker.unlock();
+ webKitWebSrcStop(src);
+ } else
+ GST_DEBUG_OBJECT(src, "Started request");
+ return;
+ }
+
+ locker.unlock();
+ GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
+ priv->notifier.notify(MainThreadSourceNotification::Start, [protector, request] {
+ WebKitWebSrcPrivate* priv = protector->priv;
+
+ WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(protector.get()));
+ if (!priv->loader)
+ priv->loader = priv->player->createResourceLoader();
- if (priv->loader) {
PlatformMediaResourceLoader::LoadOptions loadOptions = 0;
if (request.url().protocolIsBlob())
loadOptions |= PlatformMediaResourceLoader::LoadOption::BufferData;
priv->resource = priv->loader->requestResource(request, loadOptions);
- loadFailed = !priv->resource;
-
- if (priv->resource)
- priv->resource->setClient(std::make_unique<CachedResourceStreamingClient>(src));
- } else {
- priv->client = new ResourceHandleStreamingClient(src, request);
- loadFailed = priv->client->loadFailed();
- }
-
- if (loadFailed) {
- GST_ERROR_OBJECT(src, "Failed to setup streaming client");
- if (priv->client) {
- delete priv->client;
- priv->client = nullptr;
+ if (priv->resource) {
+ priv->resource->setClient(std::make_unique<CachedResourceStreamingClient>(protector.get()));
+ GST_DEBUG_OBJECT(protector.get(), "Started request");
+ } else {
+ GST_ERROR_OBJECT(protector.get(), "Failed to setup streaming client");
+ priv->loader = nullptr;
+ locker.unlock();
+ webKitWebSrcStop(protector.get());
}
- priv->loader = nullptr;
- priv->resource = nullptr;
- locker.unlock();
- webKitWebSrcStop(src);
- return;
- }
- GST_DEBUG_OBJECT(src, "Started request");
+ });
}
static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStateChange transition)
@@ -638,16 +623,13 @@ static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStat
case GST_STATE_CHANGE_READY_TO_PAUSED:
{
GST_DEBUG_OBJECT(src, "READY->PAUSED");
- GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
- priv->notifier.notify(MainThreadSourceNotification::Start, [protector] { webKitWebSrcStart(protector.get()); });
+ webKitWebSrcStart(src);
break;
}
case GST_STATE_CHANGE_PAUSED_TO_READY:
{
GST_DEBUG_OBJECT(src, "PAUSED->READY");
- priv->notifier.cancelPendingNotifications();
- GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
- priv->notifier.notify(MainThreadSourceNotification::Stop, [protector] { webKitWebSrcStop(protector.get()); });
+ webKitWebSrcStop(src);
break;
}
default:
@@ -772,59 +754,91 @@ static void webKitWebSrcUriHandlerInit(gpointer gIface, gpointer)
iface->set_uri = webKitWebSrcSetUri;
}
-// appsrc callbacks
-
static void webKitWebSrcNeedData(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
- ASSERT(isMainThread());
-
GST_DEBUG_OBJECT(src, "Need more data");
{
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
- priv->paused = FALSE;
+ if (!priv->paused)
+ return;
+ priv->paused = false;
+ if (priv->client) {
+ priv->client->setDefersLoading(false);
+ return;
+ }
}
- if (priv->client)
- priv->client->setDefersLoading(false);
- if (priv->resource)
- priv->resource->setDefersLoading(false);
+ GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
+ priv->notifier.notify(MainThreadSourceNotification::NeedData, [protector] {
+ WebKitWebSrcPrivate* priv = protector->priv;
+ if (priv->resource)
+ priv->resource->setDefersLoading(false);
+ });
}
static void webKitWebSrcEnoughData(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
- ASSERT(isMainThread());
-
GST_DEBUG_OBJECT(src, "Have enough data");
{
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
- priv->paused = TRUE;
+ if (priv->paused)
+ return;
+ priv->paused = true;
+ if (priv->client) {
+ priv->client->setDefersLoading(true);
+ return;
+ }
}
- if (priv->client)
- priv->client->setDefersLoading(true);
- if (priv->resource)
- priv->resource->setDefersLoading(true);
+ GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
+ priv->notifier.notify(MainThreadSourceNotification::EnoughData, [protector] {
+ WebKitWebSrcPrivate* priv = protector->priv;
+ if (priv->resource)
+ priv->resource->setDefersLoading(true);
+ });
}
-static void webKitWebSrcSeek(WebKitWebSrc* src)
+static gboolean webKitWebSrcSeek(WebKitWebSrc* src, guint64 offset)
{
- ASSERT(isMainThread());
+ WebKitWebSrcPrivate* priv = src->priv;
+
+ {
+ WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
+ if (offset == priv->offset && priv->requestedOffset == priv->offset)
+ return TRUE;
+
+ if (!priv->seekable)
+ return FALSE;
+
+ priv->isSeeking = true;
+ priv->requestedOffset = offset;
+ }
GST_DEBUG_OBJECT(src, "Seeking to offset: %" G_GUINT64_FORMAT, src->priv->requestedOffset);
+ if (priv->client) {
+ webKitWebSrcStop(src);
+ webKitWebSrcStart(src);
+ return TRUE;
+ }
- webKitWebSrcStop(src);
- webKitWebSrcStart(src);
+ GRefPtr<WebKitWebSrc> protector = WTF::ensureGRef(src);
+ priv->notifier.notify(MainThreadSourceNotification::Seek, [protector] {
+ webKitWebSrcStop(protector.get());
+ webKitWebSrcStart(protector.get());
+ });
+ return TRUE;
}
void webKitWebSrcSetMediaPlayer(WebKitWebSrc* src, WebCore::MediaPlayer* player)
{
ASSERT(player);
+ ASSERT(src->priv->createdInMainThread);
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
src->priv->player = player;
}
@@ -1051,17 +1065,47 @@ void CachedResourceStreamingClient::loadFinished(PlatformMediaResource&)
handleNotifyFinished();
}
-ResourceHandleStreamingClient::ResourceHandleStreamingClient(WebKitWebSrc* src, const ResourceRequest& request)
+ResourceHandleStreamingClient::ResourceHandleStreamingClient(WebKitWebSrc* src, ResourceRequest&& request)
: StreamingClient(src)
{
- m_resource = ResourceHandle::create(0 /*context*/, request, this, false, false);
+ LockHolder locker(m_initializeRunLoopConditionMutex);
+ m_thread = createThread("ResourceHandleStreamingClient", [this, request] {
+ {
+ LockHolder locker(m_initializeRunLoopConditionMutex);
+ m_runLoop = &RunLoop::current();
+ m_resource = ResourceHandle::create(nullptr /*context*/, request, this, true, false);
+ m_initializeRunLoopCondition.notifyOne();
+ }
+ if (!m_resource)
+ return;
+
+ m_runLoop->dispatch([this] { m_resource->setDefersLoading(false); });
+ m_runLoop->run();
+ {
+ LockHolder locker(m_terminateRunLoopConditionMutex);
+ m_runLoop = nullptr;
+ m_resource->clearClient();
+ m_resource->cancel();
+ m_resource = nullptr;
+ m_terminateRunLoopCondition.notifyOne();
+ }
+ });
+ m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex);
}
ResourceHandleStreamingClient::~ResourceHandleStreamingClient()
{
- if (m_resource) {
- m_resource->cancel();
- m_resource = nullptr;
+ if (m_thread) {
+ detachThread(m_thread);
+ m_thread = 0;
+ }
+
+ if (m_runLoop == &RunLoop::current())
+ m_runLoop->stop();
+ else {
+ LockHolder locker(m_terminateRunLoopConditionMutex);
+ m_runLoop->stop();
+ m_terminateRunLoopCondition.wait(m_terminateRunLoopConditionMutex);
}
}
@@ -1072,8 +1116,10 @@ bool ResourceHandleStreamingClient::loadFailed() const
void ResourceHandleStreamingClient::setDefersLoading(bool defers)
{
- if (m_resource)
- m_resource->setDefersLoading(defers);
+ m_runLoop->dispatch([this, defers] {
+ if (m_resource)
+ m_resource->setDefersLoading(defers);
+ });
}
char* ResourceHandleStreamingClient::getOrCreateReadBuffer(size_t requestedSize, size_t& actualSize)
diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
index 39cd47ce2..78e159aa0 100644
--- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
@@ -24,9 +24,7 @@
#include "FontPlatformData.h"
#include "SharedBuffer.h"
-#if USE(ZLIB)
#include "WOFFFileFormat.h"
-#endif
#include <QStringList>
namespace WebCore {
@@ -41,7 +39,6 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription&
std::unique_ptr<FontCustomPlatformData> createFontCustomPlatformData(SharedBuffer& buffer)
{
-#if USE(ZLIB)
SharedBuffer* fontBuffer = &buffer;
RefPtr<SharedBuffer> sfntBuffer;
if (isWOFF(&buffer)) {
@@ -52,15 +49,9 @@ std::unique_ptr<FontCustomPlatformData> createFontCustomPlatformData(SharedBuffe
sfntBuffer = SharedBuffer::adoptVector(sfnt);
fontBuffer = sfntBuffer.get();
}
-#endif // USE(ZLIB)
const QByteArray fontData(fontBuffer->data(), fontBuffer->size());
-#if !USE(ZLIB)
- if (fontData.startsWith("wOFF")) {
- qWarning("WOFF support requires QtWebKit to be built with zlib support.");
- return 0;
- }
-#endif // !USE(ZLIB)
+
// Pixel size doesn't matter at this point, it is set in FontCustomPlatformData::fontPlatformData.
QRawFont rawFont(fontData, /*pixelSize = */0, QFont::PreferDefaultHinting);
if (!rawFont.isValid())
@@ -75,8 +66,9 @@ bool FontCustomPlatformData::supportsFormat(const String& format)
{
return equalLettersIgnoringASCIICase(format, "truetype")
|| equalLettersIgnoringASCIICase(format, "opentype")
-#if USE(ZLIB)
|| equalLettersIgnoringASCIICase(format, "woff")
+#if USE(WOFF2)
+ || equalLettersIgnoringASCIICase(format, "woff2")
#endif
;
}
diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformData.h b/Source/WebCore/platform/graphics/qt/FontPlatformData.h
index 14e36f018..c8375ebcd 100644
--- a/Source/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -34,6 +34,8 @@
namespace WebCore {
+class SharedBuffer;
+
class FontPlatformDataPrivate : public RefCounted<FontPlatformDataPrivate> {
WTF_MAKE_NONCOPYABLE(FontPlatformDataPrivate); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -117,6 +119,7 @@ public:
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
void setOrientation(FontOrientation) { } // FIXME: Implement.
+ PassRefPtr<SharedBuffer> openTypeTable(uint32_t table) const;
unsigned hash() const;
diff --git a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index a239d643d..2ed4a98c3 100644
--- a/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -25,6 +25,7 @@
#include "FontPlatformData.h"
#include "FontCascade.h"
+#include "SharedBuffer.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -139,6 +140,20 @@ bool FontPlatformData::operator==(const FontPlatformData& other) const
return equals;
}
+PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
+{
+ const char tag[4] = {
+ char(table & 0xff),
+ char((table & 0xff00) >> 8),
+ char((table & 0xff0000) >> 16),
+ char(table >> 24)
+ };
+ QByteArray tableData = m_data->rawFont.fontTable(tag);
+
+ // TODO: Wrap SharedBuffer around QByteArray when it's possible
+ return SharedBuffer::create(tableData.data(), tableData.size());
+}
+
unsigned FontPlatformData::hash() const
{
if (!m_data)
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 618bf63ae..9e992381c 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -362,7 +362,7 @@ void GraphicsContext3DPrivate::createGraphicsSurfaces(const IntSize& size)
{
#if USE(GRAPHICS_SURFACE)
if (size.isEmpty())
- m_graphicsSurface.clear();
+ m_graphicsSurface = nullptr;
else
m_graphicsSurface = GraphicsSurface::create(size, m_surfaceFlags, m_platformContext);
#endif
diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index 2ff7df102..306f99e0e 100644
--- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -606,7 +606,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
// Add remaining headers.
foreach (const QNetworkReply::RawHeaderPair& pair, m_replyWrapper->reply()->rawHeaderPairs())
- response.setHTTPHeaderField(QString::fromLatin1(pair.first), QString::fromLatin1(pair.second));
+ response.setHTTPHeaderField(String(pair.first.constData(), pair.first.size()), String(pair.second.constData(), pair.second.size()));
}
QUrl redirection = m_replyWrapper->reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
diff --git a/Source/WebCore/platform/network/qt/ResourceRequest.h b/Source/WebCore/platform/network/qt/ResourceRequest.h
index 1e4911f4b..e74d9024c 100644
--- a/Source/WebCore/platform/network/qt/ResourceRequest.h
+++ b/Source/WebCore/platform/network/qt/ResourceRequest.h
@@ -59,7 +59,7 @@ class NetworkingContext;
{
}
- void updateFromDelegatePreservingOldHTTPBody(const ResourceRequest& delegateProvidedRequest) { *this = delegateProvidedRequest; }
+ void updateFromDelegatePreservingOldProperties(const ResourceRequest& delegateProvidedRequest) { *this = delegateProvidedRequest; }
QNetworkRequest toNetworkRequest(NetworkingContext* = 0) const;
diff --git a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp
index 46229027e..83c50062d 100644
--- a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp
+++ b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp
@@ -89,6 +89,13 @@ static void resolveBlobUrl(const QUrl& url, QUrl& resolvedUrl)
}
#endif
+static inline QByteArray stringToByteArray(const String& string)
+{
+ if (string.is8Bit())
+ return QByteArray(reinterpret_cast<const char*>(string.characters8()), string.length());
+ return QString(string).toLatin1();
+}
+
QNetworkRequest ResourceRequest::toNetworkRequest(NetworkingContext *context) const
{
QNetworkRequest request;
@@ -105,14 +112,13 @@ QNetworkRequest ResourceRequest::toNetworkRequest(NetworkingContext *context) co
const HTTPHeaderMap &headers = httpHeaderFields();
for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end();
it != end; ++it) {
- QByteArray name = QString(it->key).toLatin1();
- QByteArray value = QString(it->value).toLatin1();
+ QByteArray name = stringToByteArray(it->key);
// QNetworkRequest::setRawHeader() would remove the header if the value is null
// Make sure to set an empty header instead of null header.
- if (!value.isNull())
- request.setRawHeader(name, value);
+ if (!it->value.isNull())
+ request.setRawHeader(name, stringToByteArray(it->value));
else
- request.setRawHeader(name, "");
+ request.setRawHeader(name, QByteArrayLiteral(""));
}
// Make sure we always have an Accept header; some sites require this to
diff --git a/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp b/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
index 977e42c9a..6ac59a5b8 100644
--- a/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
+++ b/Source/WebCore/platform/qt/RenderThemeQtMobile.cpp
@@ -275,9 +275,13 @@ QSizeF StylePainterMobile::sizeForPainterScale(const QRectF& rect) const
void StylePainterMobile::drawChecker(QPainter* painter, const QRect& rect, const QColor& color) const
{
painter->setRenderHint(QPainter::Antialiasing, true);
- QPen pen(Qt::darkGray);
+ int minSideSize = qMin(rect.width(), rect.height());
+ QPen pen(minSideSize < 12 ? color : Qt::darkGray);
pen.setCosmetic(true);
- painter->setPen(pen);
+ if (minSideSize < 12 || minSideSize >= 16)
+ painter->setPen(pen);
+ else
+ painter->setPen(Qt::NoPen);
painter->scale(rect.width(), rect.height());
QPainterPath path;
path.moveTo(0.18, 0.47);
diff --git a/Source/WebCore/rendering/AutoTableLayout.cpp b/Source/WebCore/rendering/AutoTableLayout.cpp
index 3b93a5118..27330f7b0 100644
--- a/Source/WebCore/rendering/AutoTableLayout.cpp
+++ b/Source/WebCore/rendering/AutoTableLayout.cpp
@@ -181,9 +181,27 @@ void AutoTableLayout::fullRecalc()
recalcColumn(i);
}
+static bool shouldScaleColumnsForParent(const RenderTable& table)
+{
+ RenderBlock* containingBlock = table.containingBlock();
+ while (containingBlock && !is<RenderView>(containingBlock)) {
+ // It doesn't matter if our table is auto or fixed: auto means we don't
+ // scale. Fixed doesn't care if we do or not because it doesn't depend
+ // on the cell contents' preferred widths.
+ if (is<RenderTableCell>(containingBlock))
+ return false;
+ containingBlock = containingBlock->containingBlock();
+ }
+ return true;
+}
+
// FIXME: This needs to be adapted for vertical writing modes.
-static bool shouldScaleColumns(RenderTable* table)
+static bool shouldScaleColumnsForSelf(RenderTable* table)
{
+ // Normally, scale all columns to satisfy this from CSS2.2:
+ // "A percentage value for a column width is relative to the table width.
+ // If the table has 'width: auto', a percentage represents a constraint on the column's width"
+
// A special case. If this table is not fixed width and contained inside
// a cell, then don't bloat the maxwidth by examining percentage growth.
bool scale = true;
@@ -220,7 +238,7 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
maxWidth = 0;
float maxPercent = 0;
float maxNonPercent = 0;
- bool scaleColumns = shouldScaleColumns(m_table);
+ bool scaleColumnsForSelf = shouldScaleColumnsForSelf(m_table);
// We substitute 0 percent by (epsilon / percentScaleFactor) percent in two places below to avoid division by zero.
// FIXME: Handle the 0% cases properly.
@@ -230,7 +248,7 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
for (size_t i = 0; i < m_layoutStruct.size(); ++i) {
minWidth += m_layoutStruct[i].effectiveMinLogicalWidth;
maxWidth += m_layoutStruct[i].effectiveMaxLogicalWidth;
- if (scaleColumns) {
+ if (scaleColumnsForSelf) {
if (m_layoutStruct[i].effectiveLogicalWidth.isPercent()) {
float percent = std::min(m_layoutStruct[i].effectiveLogicalWidth.percent(), remainingPercent);
float logicalWidth = m_layoutStruct[i].effectiveMaxLogicalWidth * 100 / std::max(percent, epsilon);
@@ -241,10 +259,12 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
}
}
- if (scaleColumns) {
+ if (scaleColumnsForSelf) {
maxNonPercent = maxNonPercent * 100 / std::max(remainingPercent, epsilon);
- maxWidth = std::max(maxWidth, LayoutUnit(std::min<float>(maxNonPercent, tableMaxWidth)));
- maxWidth = std::max(maxWidth, LayoutUnit(std::min<float>(maxPercent, tableMaxWidth)));
+ m_scaledWidthFromPercentColumns = LayoutUnit(std::min<float>(maxNonPercent, tableMaxWidth));
+ m_scaledWidthFromPercentColumns = std::max(m_scaledWidthFromPercentColumns, LayoutUnit(std::min<float>(maxPercent, tableMaxWidth)));
+ if (m_scaledWidthFromPercentColumns > maxWidth && shouldScaleColumnsForParent(*m_table))
+ maxWidth = m_scaledWidthFromPercentColumns;
}
maxWidth = std::max(maxWidth, LayoutUnit(spanMaxLogicalWidth));
diff --git a/Source/WebCore/rendering/AutoTableLayout.h b/Source/WebCore/rendering/AutoTableLayout.h
index ce108ad90..f73f62cf8 100644
--- a/Source/WebCore/rendering/AutoTableLayout.h
+++ b/Source/WebCore/rendering/AutoTableLayout.h
@@ -36,9 +36,10 @@ public:
explicit AutoTableLayout(RenderTable*);
virtual ~AutoTableLayout();
- virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) override;
- virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const override;
- virtual void layout() override;
+ void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) override;
+ LayoutUnit scaledWidthFromPercentColumns() const override { return m_scaledWidthFromPercentColumns; }
+ void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const override;
+ void layout() override;
private:
void fullRecalc();
@@ -63,6 +64,7 @@ private:
Vector<RenderTableCell*, 4> m_spanCells;
bool m_hasPercent : 1;
mutable bool m_effectiveLogicalWidthDirty : 1;
+ LayoutUnit m_scaledWidthFromPercentColumns;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/InlineIterator.h b/Source/WebCore/rendering/InlineIterator.h
index 0c8fb3827..4dc5b4f21 100644
--- a/Source/WebCore/rendering/InlineIterator.h
+++ b/Source/WebCore/rendering/InlineIterator.h
@@ -492,7 +492,7 @@ static inline unsigned numberOfIsolateAncestors(const InlineIterator& iter)
// of BidiResolver which knows nothing about RenderObjects.
static inline void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, RenderObject& obj, unsigned pos, RenderElement& root)
{
- BidiRun* isolatedRun = new BidiRun(pos, 0, obj, resolver.context(), resolver.dir());
+ BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolver.dir());
resolver.runs().addRun(isolatedRun);
// FIXME: isolatedRuns() could be a hash of object->run and then we could cheaply
// ASSERT here that we didn't create multiple objects for the same inline.
diff --git a/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h b/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h
index aefe10738..cb48a3642 100644
--- a/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h
+++ b/Source/WebCore/rendering/LogicalSelectionOffsetCaches.h
@@ -38,7 +38,8 @@ public:
void setBlock(RenderBlock* block, const LogicalSelectionOffsetCaches* cache, bool parentCacheHasFloatsOrFlowThreads = false)
{
m_block = block;
- m_hasFloatsOrFlowThreads = parentCacheHasFloatsOrFlowThreads || m_hasFloatsOrFlowThreads || m_block->containsFloats() || m_block->flowThreadContainingBlock();
+ bool blockHasFloatsOrFlowThreads = m_block ? (m_block->containsFloats() || m_block->flowThreadContainingBlock()) : false;
+ m_hasFloatsOrFlowThreads = parentCacheHasFloatsOrFlowThreads || m_hasFloatsOrFlowThreads || blockHasFloatsOrFlowThreads;
m_cache = cache;
m_cachedLogicalLeftSelectionOffset = false;
m_cachedLogicalRightSelectionOffset = false;
@@ -49,9 +50,9 @@ public:
ASSERT(m_cache);
if (m_hasFloatsOrFlowThreads || !m_cachedLogicalLeftSelectionOffset) {
m_cachedLogicalLeftSelectionOffset = true;
- m_logicalLeftSelectionOffset = m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache);
+ m_logicalLeftSelectionOffset = m_block ? m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0);
} else
- ASSERT(m_logicalLeftSelectionOffset == m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache));
+ ASSERT(m_logicalLeftSelectionOffset == (m_block ? m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0)));
return m_logicalLeftSelectionOffset;
}
@@ -60,9 +61,9 @@ public:
ASSERT(m_cache);
if (m_hasFloatsOrFlowThreads || !m_cachedLogicalRightSelectionOffset) {
m_cachedLogicalRightSelectionOffset = true;
- m_logicalRightSelectionOffset = m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache);
+ m_logicalRightSelectionOffset = m_block ? m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0);
} else
- ASSERT(m_logicalRightSelectionOffset == m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache));
+ ASSERT(m_logicalRightSelectionOffset == (m_block ? m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0)));
return m_logicalRightSelectionOffset;
}
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 3ffdef97d..bf1a78a7f 100644
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -92,11 +92,136 @@ struct SameSizeAsRenderBlock : public RenderBox {
COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
-static TrackedDescendantsMap* gPositionedDescendantsMap;
-static TrackedDescendantsMap* gPercentHeightDescendantsMap;
+typedef HashMap<const RenderBlock*, std::unique_ptr<TrackedRendererListHashSet>> TrackedDescendantsMap;
+typedef HashMap<const RenderBox*, std::unique_ptr<HashSet<const RenderBlock*>>> TrackedContainerMap;
-static TrackedContainerMap* gPositionedContainerMap;
-static TrackedContainerMap* gPercentHeightContainerMap;
+static TrackedDescendantsMap* percentHeightDescendantsMap;
+static TrackedContainerMap* percentHeightContainerMap;
+
+static void insertIntoTrackedRendererMaps(const RenderBlock& container, RenderBox& descendant)
+{
+ if (!percentHeightDescendantsMap) {
+ percentHeightDescendantsMap = new TrackedDescendantsMap;
+ percentHeightContainerMap = new TrackedContainerMap;
+ }
+
+ auto& descendantSet = percentHeightDescendantsMap->ensure(&container, [] {
+ return std::make_unique<TrackedRendererListHashSet>();
+ }).iterator->value;
+
+ bool added = descendantSet->add(&descendant).isNewEntry;
+ if (!added) {
+ ASSERT(percentHeightContainerMap->get(&descendant));
+ ASSERT(percentHeightContainerMap->get(&descendant)->contains(&container));
+ return;
+ }
+
+ auto& containerSet = percentHeightContainerMap->ensure(&descendant, [] {
+ return std::make_unique<HashSet<const RenderBlock*>>();
+ }).iterator->value;
+
+ ASSERT(!containerSet->contains(&container));
+ containerSet->add(&container);
+}
+
+static void removeFromTrackedRendererMaps(RenderBox& descendant)
+{
+ if (!percentHeightDescendantsMap)
+ return;
+
+ std::unique_ptr<HashSet<const RenderBlock*>> containerSet = percentHeightContainerMap->take(&descendant);
+ if (!containerSet)
+ return;
+
+ for (auto* container : *containerSet) {
+ // FIXME: Disabling this assert temporarily until we fix the layout
+ // bugs associated with positioned objects not properly cleared from
+ // their ancestor chain before being moved. See webkit bug 93766.
+ // ASSERT(descendant->isDescendantOf(container));
+ auto descendantsMapIterator = percentHeightDescendantsMap->find(container);
+ ASSERT(descendantsMapIterator != percentHeightDescendantsMap->end());
+ if (descendantsMapIterator == percentHeightDescendantsMap->end())
+ continue;
+ auto& descendantSet = descendantsMapIterator->value;
+ ASSERT(descendantSet->contains(&descendant));
+ descendantSet->remove(&descendant);
+ if (descendantSet->isEmpty())
+ percentHeightDescendantsMap->remove(descendantsMapIterator);
+ }
+}
+
+class PositionedDescendantsMap {
+public:
+ enum class MoveDescendantToEnd { No, Yes };
+ void addDescendant(const RenderBlock& containingBlock, RenderBox& positionedDescendant, MoveDescendantToEnd moveDescendantToEnd)
+ {
+ // Protect against double insert where a descendant would end up with multiple containing blocks.
+ auto* previousContainingBlock = m_containerMap.get(&positionedDescendant);
+ if (previousContainingBlock && previousContainingBlock != &containingBlock) {
+ if (auto* descendants = m_descendantsMap.get(previousContainingBlock))
+ descendants->remove(&positionedDescendant);
+ }
+
+ auto& descendants = m_descendantsMap.ensure(&containingBlock, [] {
+ return std::make_unique<TrackedRendererListHashSet>();
+ }).iterator->value;
+
+ bool isNewEntry = moveDescendantToEnd == MoveDescendantToEnd::Yes ? descendants->appendOrMoveToLast(&positionedDescendant).isNewEntry
+ : descendants->add(&positionedDescendant).isNewEntry;
+ if (!isNewEntry) {
+ ASSERT(m_containerMap.contains(&positionedDescendant));
+ return;
+ }
+ m_containerMap.set(&positionedDescendant, &containingBlock);
+ }
+
+ void removeDescendant(const RenderBox& positionedDescendant)
+ {
+ auto* containingBlock = m_containerMap.take(&positionedDescendant);
+ if (!containingBlock)
+ return;
+
+ auto descendantsIterator = m_descendantsMap.find(containingBlock);
+ ASSERT(descendantsIterator != m_descendantsMap.end());
+ if (descendantsIterator == m_descendantsMap.end())
+ return;
+
+ auto& descendants = descendantsIterator->value;
+ ASSERT(descendants->contains(const_cast<RenderBox*>(&positionedDescendant)));
+
+ descendants->remove(const_cast<RenderBox*>(&positionedDescendant));
+ if (descendants->isEmpty())
+ m_descendantsMap.remove(descendantsIterator);
+ }
+
+ void removeContainingBlock(const RenderBlock& containingBlock)
+ {
+ auto descendants = m_descendantsMap.take(&containingBlock);
+ if (!descendants)
+ return;
+
+ for (auto* renderer : *descendants)
+ m_containerMap.remove(renderer);
+ }
+
+ TrackedRendererListHashSet* positionedRenderers(const RenderBlock& containingBlock) const
+ {
+ return m_descendantsMap.get(&containingBlock);
+ }
+
+private:
+ using DescendantsMap = HashMap<const RenderBlock*, std::unique_ptr<TrackedRendererListHashSet>>;
+ using ContainerMap = HashMap<const RenderBox*, const RenderBlock*>;
+
+ DescendantsMap m_descendantsMap;
+ ContainerMap m_containerMap;
+};
+
+static PositionedDescendantsMap& positionedDescendantsMap()
+{
+ static NeverDestroyed<PositionedDescendantsMap> mapForPositionedDescendants;
+ return mapForPositionedDescendants;
+}
typedef HashMap<RenderBlock*, std::unique_ptr<ListHashSet<RenderInline*>>> ContinuationOutlineTableMap;
@@ -192,21 +317,24 @@ RenderBlock::RenderBlock(Document& document, Ref<RenderStyle>&& style, BaseTypeF
{
}
-static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap)
+static void removeBlockFromPercentageDescendantAndContainerMaps(RenderBlock* block)
{
- if (std::unique_ptr<TrackedRendererListHashSet> descendantSet = descendantMap->take(block)) {
- TrackedRendererListHashSet::iterator end = descendantSet->end();
- for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
- TrackedContainerMap::iterator it = containerMap->find(*descendant);
- ASSERT(it != containerMap->end());
- if (it == containerMap->end())
- continue;
- HashSet<RenderBlock*>* containerSet = it->value.get();
- ASSERT(containerSet->contains(block));
- containerSet->remove(block);
- if (containerSet->isEmpty())
- containerMap->remove(it);
- }
+ if (!percentHeightDescendantsMap)
+ return;
+ std::unique_ptr<TrackedRendererListHashSet> descendantSet = percentHeightDescendantsMap->take(block);
+ if (!descendantSet)
+ return;
+
+ for (auto* descendant : *descendantSet) {
+ auto it = percentHeightContainerMap->find(descendant);
+ ASSERT(it != percentHeightContainerMap->end());
+ if (it == percentHeightContainerMap->end())
+ continue;
+ auto* containerSet = it->value.get();
+ ASSERT(containerSet->contains(block));
+ containerSet->remove(block);
+ if (containerSet->isEmpty())
+ percentHeightContainerMap->remove(it);
}
}
@@ -216,10 +344,8 @@ RenderBlock::~RenderBlock()
if (gRareDataMap)
gRareDataMap->remove(this);
- if (gPercentHeightDescendantsMap)
- removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
- if (gPositionedDescendantsMap)
- removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap);
+ removeBlockFromPercentageDescendantAndContainerMaps(this);
+ positionedDescendantsMap().removeContainingBlock(*this);
}
void RenderBlock::willBeDestroyed()
@@ -244,14 +370,20 @@ void RenderBlock::removePositionedObjectsIfNeeded(const RenderStyle& oldStyle, c
if (oldStyle.position() == newStyle.position() && hadTransform == willHaveTransform)
return;
- // We are no longer a containing block.
+ // We are no longer the containing block for fixed descendants.
+ if (hadTransform && !willHaveTransform) {
+ // Our positioned descendants will be inserted into a new containing block's positioned objects list during the next layout.
+ removePositionedObjects(nullptr, NewContainingBlock);
+ return;
+ }
+
+ // We are no longer the containing block for absolute positioned descendants.
if (newStyle.position() == StaticPosition && !willHaveTransform) {
- // Clear our positioned objects list. Our absolutely positioned descendants will be
- // inserted into our containing block's positioned objects list during layout.
+ // Our positioned descendants will be inserted into a new containing block's positioned objects list during the next layout.
removePositionedObjects(nullptr, NewContainingBlock);
return;
}
-
+
// We are a new containing block.
if (oldStyle.position() == StaticPosition && !hadTransform) {
// Remove our absolutely positioned descendants from their current containing block.
@@ -1157,10 +1289,10 @@ void RenderBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, R
void RenderBlock::dirtyForLayoutFromPercentageHeightDescendants()
{
- if (!gPercentHeightDescendantsMap)
+ if (!percentHeightDescendantsMap)
return;
- TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this);
+ TrackedRendererListHashSet* descendants = percentHeightDescendantsMap->get(this);
if (!descendants)
return;
@@ -1264,34 +1396,33 @@ bool RenderBlock::simplifiedLayout()
return true;
}
-void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderObject& child)
+void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderBox& positionedChild)
{
- if (child.style().position() != FixedPosition)
+ if (positionedChild.style().position() != FixedPosition)
return;
- bool hasStaticBlockPosition = child.style().hasStaticBlockPosition(isHorizontalWritingMode());
- bool hasStaticInlinePosition = child.style().hasStaticInlinePosition(isHorizontalWritingMode());
+ bool hasStaticBlockPosition = positionedChild.style().hasStaticBlockPosition(isHorizontalWritingMode());
+ bool hasStaticInlinePosition = positionedChild.style().hasStaticInlinePosition(isHorizontalWritingMode());
if (!hasStaticBlockPosition && !hasStaticInlinePosition)
return;
- auto o = child.parent();
- while (o && !is<RenderView>(*o) && o->style().position() != AbsolutePosition)
- o = o->parent();
- if (o->style().position() != AbsolutePosition)
+ auto* parent = positionedChild.parent();
+ while (parent && !is<RenderView>(*parent) && parent->style().position() != AbsolutePosition)
+ parent = parent->parent();
+ if (!parent || parent->style().position() != AbsolutePosition)
return;
- auto& box = downcast<RenderBox>(child);
if (hasStaticInlinePosition) {
LogicalExtentComputedValues computedValues;
- box.computeLogicalWidthInRegion(computedValues);
+ positionedChild.computeLogicalWidthInRegion(computedValues);
LayoutUnit newLeft = computedValues.m_position;
- if (newLeft != box.logicalLeft())
- box.setChildNeedsLayout(MarkOnlyThis);
+ if (newLeft != positionedChild.logicalLeft())
+ positionedChild.setChildNeedsLayout(MarkOnlyThis);
} else if (hasStaticBlockPosition) {
- LayoutUnit oldTop = box.logicalTop();
- box.updateLogicalHeight();
- if (box.logicalTop() != oldTop)
- box.setChildNeedsLayout(MarkOnlyThis);
+ LayoutUnit oldTop = positionedChild.logicalTop();
+ positionedChild.updateLogicalHeight();
+ if (positionedChild.logicalTop() != oldTop)
+ positionedChild.setChildNeedsLayout(MarkOnlyThis);
}
}
@@ -2049,6 +2180,8 @@ LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock& rootBlock, Layou
ASSERT(currentCache);
auto info = currentCache->containingBlockInfo(*cb);
cb = info.block();
+ if (!cb)
+ break;
currentCache = info.cache();
}
return logicalLeft;
@@ -2071,6 +2204,8 @@ LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock& rootBlock, Layo
ASSERT(currentCache);
auto info = currentCache->containingBlockInfo(*cb);
cb = info.block();
+ if (!cb)
+ break;
currentCache = info.cache();
}
return logicalRight;
@@ -2108,148 +2243,79 @@ RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) con
return beforeBlock;
}
-void RenderBlock::insertIntoTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap, bool forceNewEntry)
-{
- if (!descendantsMap) {
- descendantsMap = new TrackedDescendantsMap;
- containerMap = new TrackedContainerMap;
- }
-
- TrackedRendererListHashSet* descendantSet = descendantsMap->get(this);
- if (!descendantSet) {
- descendantSet = new TrackedRendererListHashSet;
- descendantsMap->set(this, std::unique_ptr<TrackedRendererListHashSet>(descendantSet));
- }
-
- if (forceNewEntry) {
- descendantSet->remove(&descendant);
- containerMap->remove(&descendant);
- }
-
- bool added = descendantSet->add(&descendant).isNewEntry;
- if (!added) {
- ASSERT(containerMap->get(&descendant));
- ASSERT(containerMap->get(&descendant)->contains(this));
- return;
- }
-
- HashSet<RenderBlock*>* containerSet = containerMap->get(&descendant);
- if (!containerSet) {
- containerSet = new HashSet<RenderBlock*>;
- containerMap->set(&descendant, std::unique_ptr<HashSet<RenderBlock*>>(containerSet));
- }
- ASSERT(!containerSet->contains(this));
- containerSet->add(this);
-}
-
-void RenderBlock::removeFromTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
-{
- if (!descendantsMap)
- return;
-
- std::unique_ptr<HashSet<RenderBlock*>> containerSet = containerMap->take(&descendant);
- if (!containerSet)
- return;
-
- for (auto it = containerSet->begin(), end = containerSet->end(); it != end; ++it) {
- RenderBlock* container = *it;
-
- // FIXME: Disabling this assert temporarily until we fix the layout
- // bugs associated with positioned objects not properly cleared from
- // their ancestor chain before being moved. See webkit bug 93766.
- // ASSERT(descendant->isDescendantOf(container));
-
- TrackedDescendantsMap::iterator descendantsMapIterator = descendantsMap->find(container);
- ASSERT(descendantsMapIterator != descendantsMap->end());
- if (descendantsMapIterator == descendantsMap->end())
- continue;
- TrackedRendererListHashSet* descendantSet = descendantsMapIterator->value.get();
- ASSERT(descendantSet->contains(&descendant));
- descendantSet->remove(&descendant);
- if (descendantSet->isEmpty())
- descendantsMap->remove(descendantsMapIterator);
- }
-}
-
TrackedRendererListHashSet* RenderBlock::positionedObjects() const
{
- if (gPositionedDescendantsMap)
- return gPositionedDescendantsMap->get(this);
- return nullptr;
+ return positionedDescendantsMap().positionedRenderers(*this);
}
-void RenderBlock::insertPositionedObject(RenderBox& o)
+void RenderBlock::insertPositionedObject(RenderBox& positioned)
{
ASSERT(!isAnonymousBlock());
- if (o.isRenderFlowThread())
+ if (positioned.isRenderFlowThread())
return;
-
- insertIntoTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap, isRenderView());
+
+ positionedDescendantsMap().addDescendant(*this, positioned, isRenderView() ? PositionedDescendantsMap::MoveDescendantToEnd::Yes
+ : PositionedDescendantsMap::MoveDescendantToEnd::No);
}
-void RenderBlock::removePositionedObject(RenderBox& o)
+void RenderBlock::removePositionedObject(const RenderBox& rendererToRemove)
{
- removeFromTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
+ positionedDescendantsMap().removeDescendant(rendererToRemove);
}
-void RenderBlock::removePositionedObjects(RenderBlock* o, ContainingBlockState containingBlockState)
+void RenderBlock::removePositionedObjects(const RenderBlock* newContainingBlockCandidate, ContainingBlockState containingBlockState)
{
- TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+ auto* positionedDescendants = positionedObjects();
if (!positionedDescendants)
return;
- Vector<RenderBox*, 16> deadObjects;
-
- for (auto it = positionedDescendants->begin(), end = positionedDescendants->end(); it != end; ++it) {
- RenderBox* r = *it;
- if (!o || r->isDescendantOf(o)) {
- if (containingBlockState == NewContainingBlock)
- r->setChildNeedsLayout(MarkOnlyThis);
-
- // It is parent blocks job to add positioned child to positioned objects list of its containing block
- // Parent layout needs to be invalidated to ensure this happens.
- RenderElement* p = r->parent();
- while (p && !p->isRenderBlock())
- p = p->parent();
- if (p)
- p->setChildNeedsLayout();
-
- deadObjects.append(r);
- }
+ Vector<RenderBox*, 16> renderersToRemove;
+ for (auto* renderer : *positionedDescendants) {
+ if (newContainingBlockCandidate && !renderer->isDescendantOf(newContainingBlockCandidate))
+ continue;
+ renderersToRemove.append(renderer);
+ if (containingBlockState == NewContainingBlock)
+ renderer->setChildNeedsLayout(MarkOnlyThis);
+ // It is the parent block's job to add positioned children to positioned objects list of its containing block.
+ // Dirty the parent to ensure this happens.
+ auto* parent = renderer->parent();
+ while (parent && !parent->isRenderBlock())
+ parent = parent->parent();
+ if (parent)
+ parent->setChildNeedsLayout();
}
-
- for (unsigned i = 0; i < deadObjects.size(); i++)
- removePositionedObject(*deadObjects.at(i));
+ for (auto* renderer : renderersToRemove)
+ removePositionedObject(*renderer);
}
void RenderBlock::addPercentHeightDescendant(RenderBox& descendant)
{
- insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+ insertIntoTrackedRendererMaps(*this, descendant);
}
void RenderBlock::removePercentHeightDescendant(RenderBox& descendant)
{
- removeFromTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+ removeFromTrackedRendererMaps(descendant);
}
TrackedRendererListHashSet* RenderBlock::percentHeightDescendants() const
{
- return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
+ return percentHeightDescendantsMap ? percentHeightDescendantsMap->get(this) : nullptr;
}
bool RenderBlock::hasPercentHeightContainerMap()
{
- return gPercentHeightContainerMap;
+ return percentHeightContainerMap;
}
bool RenderBlock::hasPercentHeightDescendant(RenderBox& descendant)
{
- // We don't null check gPercentHeightContainerMap since the caller
+ // We don't null check percentHeightContainerMap since the caller
// already ensures this and we need to call this function on every
// descendant in clearPercentHeightDescendantsFrom().
- ASSERT(gPercentHeightContainerMap);
- return gPercentHeightContainerMap->contains(&descendant);
+ ASSERT(percentHeightContainerMap);
+ return percentHeightContainerMap->contains(&descendant);
}
void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox& descendant)
@@ -2268,7 +2334,7 @@ void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox& descendant)
void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox& parent)
{
- ASSERT(gPercentHeightContainerMap);
+ ASSERT(percentHeightContainerMap);
for (RenderObject* child = parent.firstChild(); child; child = child->nextInPreOrder(&parent)) {
if (!is<RenderBox>(*child))
continue;
@@ -3768,17 +3834,12 @@ RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const Rend
#ifndef NDEBUG
void RenderBlock::checkPositionedObjectsNeedLayout()
{
- if (!gPositionedDescendantsMap)
- return;
-
- TrackedRendererListHashSet* positionedDescendantSet = positionedObjects();
- if (!positionedDescendantSet)
+ auto* positionedDescendants = positionedObjects();
+ if (!positionedDescendants)
return;
- for (auto it = positionedDescendantSet->begin(), end = positionedDescendantSet->end(); it != end; ++it) {
- RenderBox* currBox = *it;
- ASSERT(!currBox->needsLayout());
- }
+ for (auto* renderer : *positionedDescendants)
+ ASSERT(!renderer->needsLayout());
}
#endif
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index bb618e486..49468c586 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -42,8 +42,6 @@ struct BidiRun;
struct PaintInfo;
typedef WTF::ListHashSet<RenderBox*> TrackedRendererListHashSet;
-typedef WTF::HashMap<const RenderBlock*, std::unique_ptr<TrackedRendererListHashSet>> TrackedDescendantsMap;
-typedef WTF::HashMap<const RenderBox*, std::unique_ptr<HashSet<RenderBlock*>>> TrackedContainerMap;
enum CaretType { CursorCaret, DragCaret };
enum ContainingBlockState { NewContainingBlock, SameContainingBlock };
@@ -83,8 +81,8 @@ public:
virtual void invalidateLineLayoutPath() { }
void insertPositionedObject(RenderBox&);
- static void removePositionedObject(RenderBox&);
- void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock);
+ static void removePositionedObject(const RenderBox&);
+ void removePositionedObjects(const RenderBlock*, ContainingBlockState = SameContainingBlock);
TrackedRendererListHashSet* positionedObjects() const;
bool hasPositionedObjects() const
@@ -316,7 +314,7 @@ protected:
void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false);
virtual void layoutPositionedObject(RenderBox&, bool relayoutChildren, bool fixedPositionObjectsOnly);
- void markFixedPositionObjectForLayoutIfNeeded(RenderObject& child);
+ void markFixedPositionObjectForLayoutIfNeeded(RenderBox& child);
LayoutUnit marginIntrinsicLogicalWidthForChild(RenderBox&) const;
@@ -417,12 +415,6 @@ private:
virtual bool isSelfCollapsingBlock() const override;
virtual bool childrenPreventSelfCollapsing() const;
- // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
- virtual bool hasLines() const { return false; }
-
- void insertIntoTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*&, TrackedContainerMap*&, bool forceNewEntry = false);
- static void removeFromTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
-
void createFirstLetterRenderer(RenderElement* firstLetterBlock, RenderText* currentTextChild);
void updateFirstLetterStyle(RenderElement* firstLetterBlock, RenderObject* firstLetterContainer);
diff --git a/Source/WebCore/rendering/RenderBlockFlow.cpp b/Source/WebCore/rendering/RenderBlockFlow.cpp
index 33bce4025..53ff0b6c7 100644
--- a/Source/WebCore/rendering/RenderBlockFlow.cpp
+++ b/Source/WebCore/rendering/RenderBlockFlow.cpp
@@ -1648,7 +1648,15 @@ static inline bool needsAppleMailPaginationQuirk(RootInlineBox& lineBox)
return false;
}
-
+
+static void clearShouldBreakAtLineToAvoidWidowIfNeeded(RenderBlockFlow& blockFlow)
+{
+ if (!blockFlow.shouldBreakAtLineToAvoidWidow())
+ return;
+ blockFlow.clearShouldBreakAtLineToAvoidWidow();
+ blockFlow.setDidBreakAtLineToAvoidWidow();
+}
+
void RenderBlockFlow::adjustLinePositionForPagination(RootInlineBox* lineBox, LayoutUnit& delta, bool& overflowsRegion, RenderFlowThread* flowThread)
{
// FIXME: Ignore anonymous inline blocks. Handle the delta already having been set because of
@@ -1702,8 +1710,11 @@ void RenderBlockFlow::adjustLinePositionForPagination(RootInlineBox* lineBox, La
logicalBottom = intMinForLayoutUnit;
lineBox->computeReplacedAndTextLineTopAndBottom(logicalOffset, logicalBottom);
lineHeight = logicalBottom - logicalOffset;
- if (logicalOffset == intMaxForLayoutUnit || lineHeight > pageLogicalHeight)
- return; // Give up. We're genuinely too big even after excluding blank space and overflow.
+ if (logicalOffset == intMaxForLayoutUnit || lineHeight > pageLogicalHeight) {
+ // Give up. We're genuinely too big even after excluding blank space and overflow.
+ clearShouldBreakAtLineToAvoidWidowIfNeeded(*this);
+ return;
+ }
pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
}
@@ -1712,10 +1723,8 @@ void RenderBlockFlow::adjustLinePositionForPagination(RootInlineBox* lineBox, La
int lineIndex = lineCount(lineBox);
if (remainingLogicalHeight < lineHeight || (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex)) {
- if (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex) {
- clearShouldBreakAtLineToAvoidWidow();
- setDidBreakAtLineToAvoidWidow();
- }
+ if (lineBreakToAvoidWidow() == lineIndex)
+ clearShouldBreakAtLineToAvoidWidowIfNeeded(*this);
// If we have a non-uniform page height, then we have to shift further possibly.
if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
return;
@@ -3528,7 +3537,8 @@ bool RenderBlockFlow::relayoutForPagination(LayoutStateMaintainer& statePusher)
bool RenderBlockFlow::hasLines() const
{
- ASSERT(childrenInline());
+ if (!childrenInline())
+ return false;
if (auto simpleLineLayout = this->simpleLineLayout())
return simpleLineLayout->lineCount();
diff --git a/Source/WebCore/rendering/RenderBlockFlow.h b/Source/WebCore/rendering/RenderBlockFlow.h
index 3b9d81268..84766c45b 100644
--- a/Source/WebCore/rendering/RenderBlockFlow.h
+++ b/Source/WebCore/rendering/RenderBlockFlow.h
@@ -345,8 +345,8 @@ public:
RootInlineBox* firstRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.firstLineBox()); }
RootInlineBox* lastRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.lastLineBox()); }
- virtual bool hasLines() const override final;
- virtual void invalidateLineLayoutPath() override final;
+ bool hasLines() const;
+ void invalidateLineLayoutPath() final;
enum LineLayoutPath { UndeterminedPath = 0, SimpleLinesPath, LineBoxesPath, ForceLineBoxesPath };
LineLayoutPath lineLayoutPath() const { return static_cast<LineLayoutPath>(renderBlockFlowLineLayoutPath()); }
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index 451de09c9..d67c38daa 100644
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -2250,6 +2250,10 @@ void RenderBlockFlow::marginCollapseLinesFromStart(LineLayoutState& layoutState,
if (!stopLine->hasAnonymousInlineBlock())
return;
+ // We already handled top of block with startLine.
+ if (stopLine == firstRootBox())
+ return;
+
// Re-run margin collapsing on the block sequence that stopLine is a part of.
// First go backwards to get the entire sequence.
RootInlineBox* prev = stopLine;
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index c437851c0..e4809d288 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -120,18 +120,12 @@ static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
RenderBox::RenderBox(Element& element, Ref<RenderStyle>&& style, BaseTypeFlags baseTypeFlags)
: RenderBoxModelObject(element, WTFMove(style), baseTypeFlags)
- , m_minPreferredLogicalWidth(-1)
- , m_maxPreferredLogicalWidth(-1)
- , m_inlineBoxWrapper(nullptr)
{
setIsBox();
}
RenderBox::RenderBox(Document& document, Ref<RenderStyle>&& style, BaseTypeFlags baseTypeFlags)
: RenderBoxModelObject(document, WTFMove(style), baseTypeFlags)
- , m_minPreferredLogicalWidth(-1)
- , m_maxPreferredLogicalWidth(-1)
- , m_inlineBoxWrapper(nullptr)
{
setIsBox();
}
@@ -516,17 +510,19 @@ void RenderBox::updateFromStyle()
boxHasOverflowClip = false;
}
}
-
// Check for overflow clip.
// It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
if (boxHasOverflowClip) {
- if (!s_hadOverflowClip)
- // Erase the overflow
- repaint();
+ if (!s_hadOverflowClip && hasRenderOverflow()) {
+ // Erase the overflow.
+ // Overflow changes have to result in immediate repaints of the entire layout overflow area because
+ // repaints issued by removal of descendants get clipped using the updated style when they shouldn't.
+ repaintRectangle(visualOverflowRect());
+ repaintRectangle(layoutOverflowRect());
+ }
setHasOverflowClip();
}
}
-
setHasTransformRelatedProperty(styleToUse.hasTransformRelatedProperty());
setHasReflection(styleToUse.boxReflect());
}
@@ -2121,13 +2117,14 @@ std::unique_ptr<InlineElementBox> RenderBox::createInlineBox()
void RenderBox::dirtyLineBoxes(bool fullLayout)
{
- if (m_inlineBoxWrapper) {
- if (fullLayout) {
- delete m_inlineBoxWrapper;
- m_inlineBoxWrapper = nullptr;
- } else
- m_inlineBoxWrapper->dirtyLineBoxes();
- }
+ if (!m_inlineBoxWrapper)
+ return;
+
+ if (fullLayout) {
+ delete m_inlineBoxWrapper;
+ m_inlineBoxWrapper = nullptr;
+ } else
+ m_inlineBoxWrapper->dirtyLineBoxes();
}
void RenderBox::positionLineBox(InlineElementBox& box)
@@ -2163,12 +2160,13 @@ void RenderBox::positionLineBox(InlineElementBox& box)
void RenderBox::deleteLineBoxWrapper()
{
- if (m_inlineBoxWrapper) {
- if (!documentBeingDestroyed())
- m_inlineBoxWrapper->removeFromParent();
- delete m_inlineBoxWrapper;
- m_inlineBoxWrapper = nullptr;
- }
+ if (!m_inlineBoxWrapper)
+ return;
+
+ if (!documentBeingDestroyed())
+ m_inlineBoxWrapper->removeFromParent();
+ delete m_inlineBoxWrapper;
+ m_inlineBoxWrapper = nullptr;
}
LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index 508ba3d28..8e63a2c82 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -740,7 +740,7 @@ protected:
LayoutUnit m_maxPreferredLogicalWidth;
// For inline replaced elements, the inline box that owns us.
- InlineElementBox* m_inlineBoxWrapper;
+ InlineElementBox* m_inlineBoxWrapper { nullptr };
// Our overflow information.
RefPtr<RenderOverflow> m_overflow;
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 98e9f2d06..5b0a83de7 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -363,7 +363,7 @@ LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
return std::max(clientLogicalBottom(), maxChildLogicalBottom);
}
-bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox& child) const
+bool RenderFlexibleBox::hasOrthogonalFlow(const RenderBox& child) const
{
// FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
return isHorizontalFlow() != child.isHorizontalWritingMode();
@@ -450,14 +450,14 @@ LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHei
return contentLogicalWidth();
}
-Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(RenderBox& child, SizeType sizeType, const Length& size)
+Optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(const RenderBox& child, SizeType sizeType, const Length& size)
{
// FIXME: This is wrong for orthogonal flows. It should use the flexbox's writing-mode, not the child's in order
// to figure out the logical height/width.
if (isColumnFlow()) {
// We don't have to check for "auto" here - computeContentLogicalHeight will just return Nullopt for that case anyway.
if (size.isIntrinsic())
- child.layoutIfNeeded();
+ const_cast<RenderBox&>(child).layoutIfNeeded(); // FIXME: Should not need to do a layout here.
return child.computeContentLogicalHeight(sizeType, size, child.logicalHeight() - child.borderAndPaddingLogicalHeight());
}
// FIXME: Figure out how this should work for regions and pass in the appropriate values.
@@ -648,15 +648,14 @@ LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox&
{
return isHorizontalFlow() ? child.horizontalBorderAndPaddingExtent() : child.verticalBorderAndPaddingExtent();
}
-
-bool RenderFlexibleBox::mainAxisExtentIsDefinite() const
-{
- return isColumnFlow() ? hasDefiniteLogicalHeight() : hasDefiniteLogicalWidth();
-}
-
-bool RenderFlexibleBox::mainAxisLengthIsIndefinite(const Length& flexBasis) const
+
+bool RenderFlexibleBox::mainAxisLengthIsDefinite(const RenderBox& child, const Length& flexBasis) const
{
- return flexBasis.isAuto() || (flexBasis.isPercentOrCalculated() && !mainAxisExtentIsDefinite());
+ if (flexBasis.isAuto())
+ return false;
+ if (flexBasis.isPercentOrCalculated())
+ return isColumnFlow() ? bool(child.computePercentageLogicalHeight(flexBasis)) : hasDefiniteLogicalWidth();
+ return true;
}
LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox& child) const
@@ -855,7 +854,72 @@ void RenderFlexibleBox::prepareOrderIteratorAndMargins()
}
}
-LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox& child, LayoutUnit childSize)
+bool RenderFlexibleBox::crossAxisLengthIsDefinite(const RenderBox& child, const Length& length) const
+{
+ if (length.isAuto())
+ return false;
+ if (length.isPercentOrCalculated())
+ return hasOrthogonalFlow(child) ? hasDefiniteLogicalWidth() : bool(child.computePercentageLogicalHeight(length));
+ return length.isFixed();
+}
+
+
+Optional<LayoutUnit> RenderFlexibleBox::computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const
+{
+ ASSERT(child.hasAspectRatio());
+ ASSERT(child.intrinsicSize().height() > 0);
+
+ Optional<LayoutUnit> crossSize;
+ if (crossSizeLength.isFixed())
+ crossSize = LayoutUnit(crossSizeLength.value());
+ else {
+ ASSERT(crossSizeLength.isPercentOrCalculated());
+ crossSize = hasOrthogonalFlow(child) ?
+ adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(crossSizeLength, contentWidth())) :
+ child.computePercentageLogicalHeight(crossSizeLength);
+ }
+
+ if (!crossSize)
+ return crossSize;
+
+ const LayoutSize& childIntrinsicSize = child.intrinsicSize();
+ double ratio = childIntrinsicSize.width().toFloat() / childIntrinsicSize.height().toFloat();
+ if (isHorizontalFlow())
+ return LayoutUnit(crossSize.value() * ratio);
+ return LayoutUnit(crossSize.value() / ratio);
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox& child, LayoutUnit childSize)
+{
+ Length crossMin = isHorizontalFlow() ? child.style().minHeight() : child.style().minWidth();
+ Length crossMax = isHorizontalFlow() ? child.style().maxHeight() : child.style().maxWidth();
+
+ if (crossAxisLengthIsDefinite(child, crossMax)) {
+ Optional<LayoutUnit> maxValue = computeMainSizeFromAspectRatioUsing(child, crossMax);
+ if (maxValue)
+ childSize = std::min(maxValue.value(), childSize);
+ }
+
+ if (crossAxisLengthIsDefinite(child, crossMin)) {
+ Optional<LayoutUnit> minValue = computeMainSizeFromAspectRatioUsing(child, crossMin);
+ if (minValue)
+ childSize = std::max(minValue.value(), childSize);
+ }
+
+ return childSize;
+}
+
+bool RenderFlexibleBox::useChildAspectRatio(const RenderBox& child) const
+{
+ if (!child.hasAspectRatio())
+ return false;
+ if (!child.intrinsicSize().height())
+ return false;
+ Length crossSize = isHorizontalFlow() ? child.style().height() : child.style().width();
+ return crossAxisLengthIsDefinite(child, crossSize);
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(const RenderBox& child, LayoutUnit childSize)
{
Length max = isHorizontalFlow() ? child.style().maxWidth() : child.style().maxHeight();
Optional<LayoutUnit> maxExtent = Nullopt;
@@ -863,26 +927,36 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox& child, Layo
maxExtent = computeMainAxisExtentForChild(child, MaxSize, max);
childSize = std::min(childSize, maxExtent.valueOr(childSize));
}
-
+
Length min = isHorizontalFlow() ? child.style().minWidth() : child.style().minHeight();
if (min.isSpecifiedOrIntrinsic())
return std::max(childSize, computeMainAxisExtentForChild(child, MinSize, min).valueOr(childSize));
-
- if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE) {
+
+ if (!isFlexibleBoxImpl() && min.isAuto() && mainAxisOverflowForChild(child) == OVISIBLE && !(isColumnFlow() && is<RenderFlexibleBox>(child))) {
// This is the implementation of CSS flexbox section 4.5 which defines the minimum size of "pure" flex
// items. For any other item the value should be 0, this also includes RenderFlexibleBox's derived clases
// (RenderButton, RenderFullScreen...) because that's just an implementation detail.
+ // FIXME: For now we don't handle nested column flexboxes. Need to implement better intrinsic
+ // size handling from the flex box spec first (4.5).
LayoutUnit contentSize = computeMainAxisExtentForChild(child, MinSize, Length(MinContent)).value();
ASSERT(contentSize >= 0);
+ if (child.hasAspectRatio() && child.intrinsicSize().height() > 0)
+ contentSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, contentSize);
contentSize = std::min(contentSize, maxExtent.valueOr(contentSize));
-
+
Length mainSize = isHorizontalFlow() ? child.style().width() : child.style().height();
- if (!mainAxisLengthIsIndefinite(mainSize)) {
+ if (mainAxisLengthIsDefinite(child, mainSize)) {
LayoutUnit resolvedMainSize = computeMainAxisExtentForChild(child, MainOrPreferredSize, mainSize).value();
ASSERT(resolvedMainSize >= 0);
LayoutUnit specifiedSize = std::min(resolvedMainSize, maxExtent.valueOr(resolvedMainSize));
-
return std::max(childSize, std::min(specifiedSize, contentSize));
+ } else if (useChildAspectRatio(child)) {
+ Length crossSizeLength = isHorizontalFlow() ? child.style().height() : child.style().width();
+ Optional<LayoutUnit> transferredSize = computeMainSizeFromAspectRatioUsing(child, crossSizeLength);
+ if (transferredSize) {
+ transferredSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, transferredSize.value());
+ return std::max(childSize, std::min(transferredSize.value(), contentSize));
+ }
}
return std::max(childSize, contentSize);
}
@@ -1085,7 +1159,7 @@ void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox& chil
child.updateLogicalHeight();
}
-EOverflow RenderFlexibleBox::mainAxisOverflowForChild(RenderBox& child) const
+EOverflow RenderFlexibleBox::mainAxisOverflowForChild(const RenderBox& child) const
{
if (isHorizontalFlow())
return child.style().overflowX();
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h
index 9bae316aa..f2e5d1760 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.h
+++ b/Source/WebCore/rendering/RenderFlexibleBox.h
@@ -85,8 +85,8 @@ private:
// Use an inline capacity of 8, since flexbox containers usually have less than 8 children.
typedef Vector<LayoutRect, 8> ChildFrameRects;
- virtual bool isFlexibleBox() const override final { return true; }
- bool hasOrthogonalFlow(RenderBox& child) const;
+ bool isFlexibleBox() const final { return true; }
+ bool hasOrthogonalFlow(const RenderBox& child) const;
bool isColumnFlow() const;
bool isLeftToRightFlow() const;
bool isMultiline() const;
@@ -98,7 +98,7 @@ private:
LayoutUnit mainAxisExtent() const;
LayoutUnit crossAxisContentExtent() const;
LayoutUnit mainAxisContentExtent(LayoutUnit contentLogicalHeight);
- Optional<LayoutUnit> computeMainAxisExtentForChild(RenderBox& child, SizeType, const Length& size);
+ Optional<LayoutUnit> computeMainAxisExtentForChild(const RenderBox& child, SizeType, const Length& size);
WritingMode transformedWritingMode() const;
LayoutUnit flowAwareBorderStart() const;
LayoutUnit flowAwareBorderEnd() const;
@@ -122,7 +122,7 @@ private:
LayoutUnit mainAxisBorderAndPaddingExtentForChild(RenderBox& child) const;
LayoutUnit mainAxisScrollbarExtentForChild(RenderBox& child) const;
LayoutUnit preferredMainAxisContentExtentForChild(RenderBox& child, bool hasInfiniteLineLength);
- EOverflow mainAxisOverflowForChild(RenderBox&) const;
+ EOverflow mainAxisOverflowForChild(const RenderBox&) const;
void layoutFlexItems(bool relayoutChildren, Vector<LineContext>&);
LayoutUnit autoMarginOffsetInMainAxis(const OrderedFlexItemList&, LayoutUnit& availableFreeSpace);
@@ -139,7 +139,8 @@ private:
LayoutUnit computeChildMarginValue(const Length& margin);
void prepareOrderIteratorAndMargins();
- LayoutUnit adjustChildSizeForMinAndMax(RenderBox&, LayoutUnit childSize);
+ LayoutUnit adjustChildSizeForMinAndMax(const RenderBox&, LayoutUnit childSize);
+ LayoutUnit adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox&, LayoutUnit childSize);
bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent, bool& hasInfiniteLineLength);
bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit>& childSizes, bool hasInfiniteLineLength);
@@ -158,9 +159,11 @@ private:
void flipForRightToLeftColumn();
void flipForWrapReverse(const Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
- bool mainAxisExtentIsDefinite() const;
- bool mainAxisLengthIsIndefinite(const Length& flexBasis) const;
-
+ bool mainAxisLengthIsDefinite(const RenderBox&, const Length&) const;
+ bool crossAxisLengthIsDefinite(const RenderBox&, const Length&) const;
+ bool useChildAspectRatio(const RenderBox&) const;
+ Optional<LayoutUnit> computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const;
+
virtual bool isFlexibleBoxImpl() const { return false; };
mutable OrderIterator m_orderIterator;
diff --git a/Source/WebCore/rendering/RenderHTMLCanvas.cpp b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
index f2de75d52..199f903b4 100644
--- a/Source/WebCore/rendering/RenderHTMLCanvas.cpp
+++ b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -101,18 +101,7 @@ void RenderHTMLCanvas::canvasSizeChanged()
if (!parent())
return;
-
- if (!preferredLogicalWidthsDirty())
- setPreferredLogicalWidthsDirty(true);
-
- LayoutSize oldSize = size();
- updateLogicalWidth();
- updateLogicalHeight();
- if (oldSize == size())
- return;
-
- if (!selfNeedsLayout())
- setNeedsLayout();
+ setNeedsLayoutIfNeededAfterIntrinsicSizeChange();
}
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index d8ee8150b..00d907829 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -294,29 +294,8 @@ void RenderImage::repaintOrMarkForLayout(ImageSizeChangeType imageSizeChange, co
bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize || imageSizeChange != ImageSizeChangeNone;
- if (imageSourceHasChangedSize) {
- setPreferredLogicalWidthsDirty(true);
-
- // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required.
- bool imageSizeIsConstrained = style().logicalWidth().isSpecified() && style().logicalHeight().isSpecified();
-
- // FIXME: We only need to recompute the containing block's preferred size
- // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
- // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
- bool containingBlockNeedsToRecomputePreferredSize =
- style().logicalWidth().isPercentOrCalculated()
- || style().logicalMaxWidth().isPercentOrCalculated()
- || style().logicalMinWidth().isPercentOrCalculated();
-
- bool layoutSizeDependsOnIntrinsicSize = style().aspectRatioType() == AspectRatioFromIntrinsic;
-
- if (!imageSizeIsConstrained || containingBlockNeedsToRecomputePreferredSize || layoutSizeDependsOnIntrinsicSize) {
- // FIXME: It's not clear that triggering a layout guarantees a repaint in all cases.
- // But many callers do depend on this code causing a layout.
- setNeedsLayout();
- return;
- }
- }
+ if (imageSourceHasChangedSize && setNeedsLayoutIfNeededAfterIntrinsicSizeChange())
+ return;
if (everHadLayout() && !selfNeedsLayout()) {
// The inner content rectangle is calculated during layout, but may need an update now
@@ -574,6 +553,11 @@ bool RenderImage::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect,
ObjectFit objectFit = style().objectFit();
if (objectFit != ObjectFitFill && objectFit != ObjectFitCover)
return false;
+
+ LengthPoint objectPosition = style().objectPosition();
+ if (objectPosition != RenderStyle::initialObjectPosition())
+ return false;
+
// Check for image with alpha.
return imageResource().cachedImage() && imageResource().cachedImage()->currentFrameKnownToBeOpaque(this);
}
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 3125c62f6..749099044 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -1206,7 +1206,7 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBoxInRegion(const RenderRegi
LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
{
// Only first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
- ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER);
+ ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER || hasSelfPaintingLayer());
if (!firstLineBoxIncludingCulling() && !continuation())
return LayoutRect();
@@ -1807,8 +1807,7 @@ void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
if (!container)
container = this;
- region.clip = region.bounds;
- container->computeAbsoluteRepaintRect(region.clip);
+ region.clip = container->computeAbsoluteRepaintRect(region.bounds);
if (region.clip.height() < 0) {
region.clip.setHeight(0);
region.clip.setWidth(0);
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index d0cba5316..dae97f749 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -1805,15 +1805,15 @@ void RenderLayer::beginTransparencyLayers(GraphicsContext& context, const LayerP
context.clip(pixelSnappedClipRect);
#if ENABLE(CSS_COMPOSITING)
- // RenderSVGRoot takes care of its blend mode.
- if (!renderer().isSVGRoot() && hasBlendMode())
+ bool usesCompositeOperation = hasBlendMode() && !(renderer().isSVGRoot() && parent() && parent()->isRootLayer());
+ if (usesCompositeOperation)
context.setCompositeOperation(context.compositeOperation(), blendMode());
#endif
context.beginTransparencyLayer(renderer().opacity());
#if ENABLE(CSS_COMPOSITING)
- if (!renderer().isSVGRoot() && hasBlendMode())
+ if (usesCompositeOperation)
context.setCompositeOperation(context.compositeOperation(), BlendModeNormal);
#endif
@@ -6423,6 +6423,19 @@ void RenderLayer::repaintIncludingNonCompositingDescendants(RenderLayerModelObje
}
}
+static bool mayCreateGraphicalGroup(const RenderElement& renderer)
+{
+ bool createsGraphicalGroup = renderer.hasClipPath()
+ || renderer.hasFilter()
+ || renderer.hasBackdropFilter()
+#if ENABLE(CSS_COMPOSITING)
+ || renderer.hasBlendMode()
+#endif
+ || renderer.isTransparent()
+ || renderer.hasMask();
+ return createsGraphicalGroup || (renderer.style().willChange() && renderer.style().willChange()->canCreateGraphicalGroup());
+}
+
bool RenderLayer::shouldBeNormalFlowOnly() const
{
return (renderer().hasOverflowClip()
@@ -6434,20 +6447,14 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
|| renderer().isRenderIFrame()
|| (renderer().style().specifiesColumns() && !isRootLayer())
|| renderer().isInFlowRenderFlowThread())
- && !renderer().isPositioned()
&& !renderer().hasTransformRelatedProperty()
- && !renderer().hasClipPath()
- && !renderer().hasFilter()
- && !renderer().hasBackdropFilter()
+ && !renderer().isPositioned()
+ && !needsCompositedScrolling()
+ && !renderer().style().hasFlowFrom()
#if PLATFORM(IOS)
&& !hasAcceleratedTouchScrolling()
#endif
-#if ENABLE(CSS_COMPOSITING)
- && !renderer().hasBlendMode()
-#endif
- && !isTransparent()
- && !needsCompositedScrolling()
- && !renderer().style().hasFlowFrom();
+ && !mayCreateGraphicalGroup(renderer());
}
bool RenderLayer::shouldBeSelfPaintingLayer() const
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index edb4f3398..df2cd277d 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -1924,8 +1924,7 @@ void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
region.type = styleRegion.type;
- region.clip = region.bounds;
- computeAbsoluteRepaintRect(region.clip);
+ region.clip = computeAbsoluteRepaintRect(region.bounds);
if (region.clip.height() < 0) {
region.clip.setHeight(0);
region.clip.setWidth(0);
diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp
index a818ad0fa..6b36b13e3 100644
--- a/Source/WebCore/rendering/RenderReplaced.cpp
+++ b/Source/WebCore/rendering/RenderReplaced.cpp
@@ -287,6 +287,31 @@ bool RenderReplaced::hasReplacedLogicalHeight() const
return false;
}
+bool RenderReplaced::setNeedsLayoutIfNeededAfterIntrinsicSizeChange()
+{
+ setPreferredLogicalWidthsDirty(true);
+
+ // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required.
+ bool imageSizeIsConstrained = style().logicalWidth().isSpecified() && style().logicalHeight().isSpecified();
+
+ // FIXME: We only need to recompute the containing block's preferred size
+ // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
+ // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
+ bool containingBlockNeedsToRecomputePreferredSize =
+ style().logicalWidth().isPercentOrCalculated()
+ || style().logicalMaxWidth().isPercentOrCalculated()
+ || style().logicalMinWidth().isPercentOrCalculated();
+
+ bool layoutSizeDependsOnIntrinsicSize = style().aspectRatioType() == AspectRatioFromIntrinsic;
+
+ if (!imageSizeIsConstrained || containingBlockNeedsToRecomputePreferredSize || layoutSizeDependsOnIntrinsicSize) {
+ setNeedsLayout();
+ return true;
+ }
+
+ return false;
+}
+
void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio) const
{
FloatSize intrinsicSize;
@@ -338,8 +363,6 @@ LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize)
return contentRect;
ObjectFit objectFit = style().objectFit();
- if (objectFit == ObjectFitFill)
- return contentRect;
LayoutRect finalRect = contentRect;
switch (objectFit) {
@@ -354,13 +377,14 @@ LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize)
finalRect.setSize(intrinsicSize);
break;
case ObjectFitFill:
- ASSERT_NOT_REACHED();
+ break;
}
- // FIXME: This is where object-position should be taken into account, but since it's not
- // implemented yet, assume the initial value of "50% 50%".
- LayoutUnit xOffset = (contentRect.width() - finalRect.width()) / 2;
- LayoutUnit yOffset = (contentRect.height() - finalRect.height()) / 2;
+ LengthPoint objectPosition = style().objectPosition();
+
+ LayoutUnit xOffset = minimumValueForLength(objectPosition.x(), contentRect.width() - finalRect.width());
+ LayoutUnit yOffset = minimumValueForLength(objectPosition.y(), contentRect.height() - finalRect.height());
+
finalRect.move(xOffset, yOffset);
return finalRect;
diff --git a/Source/WebCore/rendering/RenderReplaced.h b/Source/WebCore/rendering/RenderReplaced.h
index 9f7dfc571..72dbb81d1 100644
--- a/Source/WebCore/rendering/RenderReplaced.h
+++ b/Source/WebCore/rendering/RenderReplaced.h
@@ -37,6 +37,7 @@ public:
bool hasReplacedLogicalWidth() const;
bool hasReplacedLogicalHeight() const;
+ bool setNeedsLayoutIfNeededAfterIntrinsicSizeChange();
protected:
RenderReplaced(Element&, Ref<RenderStyle>&&);
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 05325314a..b3be2de98 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -300,6 +300,13 @@ void RenderTable::updateLogicalWidth()
// Ensure we aren't bigger than our available width.
setLogicalWidth(std::min(availableContentLogicalWidth, maxPreferredLogicalWidth()));
+ LayoutUnit maxWidth = maxPreferredLogicalWidth();
+ // scaledWidthFromPercentColumns depends on m_layoutStruct in TableLayoutAlgorithmAuto, which
+ // maxPreferredLogicalWidth fills in. So scaledWidthFromPercentColumns has to be called after
+ // maxPreferredLogicalWidth.
+ LayoutUnit scaledWidth = m_tableLayout->scaledWidthFromPercentColumns() + bordersPaddingAndSpacingInRowDirection();
+ maxWidth = std::max(scaledWidth, maxWidth);
+ setLogicalWidth(std::min(availableContentLogicalWidth, maxWidth));
}
// Ensure we aren't smaller than our min preferred width.
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp
index efd90c18c..35e5e0b88 100644
--- a/Source/WebCore/rendering/RenderTableCell.cpp
+++ b/Source/WebCore/rendering/RenderTableCell.cpp
@@ -404,6 +404,13 @@ LayoutUnit RenderTableCell::cellBaselinePosition() const
return firstLineBaseline().valueOr(borderAndPaddingBefore() + contentLogicalHeight());
}
+static inline void markCellDirtyWhenCollapsedBorderChanges(RenderTableCell* cell)
+{
+ if (!cell)
+ return;
+ cell->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
ASSERT(style().display() == TABLE_CELL);
@@ -422,8 +429,15 @@ void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* ol
// If border was changed, notify table.
RenderTable* table = this->table();
- if (table && oldStyle && oldStyle->border() != style().border())
+ if (table && oldStyle && oldStyle->border() != style().border()) {
table->invalidateCollapsedBorders(this);
+ if (table->collapseBorders() && diff == StyleDifferenceLayout) {
+ markCellDirtyWhenCollapsedBorderChanges(table->cellBelow(this));
+ markCellDirtyWhenCollapsedBorderChanges(table->cellAbove(this));
+ markCellDirtyWhenCollapsedBorderChanges(table->cellBefore(this));
+ markCellDirtyWhenCollapsedBorderChanges(table->cellAfter(this));
+ }
+ }
}
// The following rules apply for resolving conflicts and figuring out which border
diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h
index bd69f09e3..17a0171a0 100644
--- a/Source/WebCore/rendering/RenderTableCell.h
+++ b/Source/WebCore/rendering/RenderTableCell.h
@@ -284,6 +284,8 @@ inline LayoutUnit RenderTableCell::logicalHeightForRowSizing() const
{
// FIXME: This function does too much work, and is very hot during table layout!
LayoutUnit adjustedLogicalHeight = logicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
+ if (!style().logicalHeight().isSpecified())
+ return adjustedLogicalHeight;
LayoutUnit styleLogicalHeight = valueForLength(style().logicalHeight(), 0);
// In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
// Call computedCSSPadding* directly to avoid including implicitPadding.
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index 1907657e9..7f9100b6e 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -251,6 +251,15 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
cell->setCol(table()->effColToCol(col));
}
+static LayoutUnit resolveLogicalHeightForRow(const Length& rowLogicalHeight)
+{
+ if (rowLogicalHeight.isFixed())
+ return rowLogicalHeight.value();
+ if (rowLogicalHeight.isCalculated())
+ return rowLogicalHeight.nonNanCalculatedValue(0);
+ return 0;
+}
+
LayoutUnit RenderTableSection::calcRowLogicalHeight()
{
#ifndef NDEBUG
@@ -278,7 +287,7 @@ LayoutUnit RenderTableSection::calcRowLogicalHeight()
LayoutUnit baselineDescent = 0;
// Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
- m_rowPos[r + 1] = std::max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0), LayoutUnit::fromPixel(0));
+ m_rowPos[r + 1] = std::max(m_rowPos[r] + resolveLogicalHeightForRow(m_grid[r].logicalHeight), LayoutUnit::fromPixel(0));
Row& row = m_grid[r].row;
unsigned totalCols = row.size();
@@ -372,6 +381,7 @@ void RenderTableSection::layout()
ASSERT(!needsCellRecalc());
ASSERT(!table()->needsSectionRecalc());
+ m_forceSlowPaintPathWithOverflowingCell = false;
// addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
// can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
m_grid.shrinkToFit();
diff --git a/Source/WebCore/rendering/TableLayout.h b/Source/WebCore/rendering/TableLayout.h
index 23169aa65..6c0b32d24 100644
--- a/Source/WebCore/rendering/TableLayout.h
+++ b/Source/WebCore/rendering/TableLayout.h
@@ -21,6 +21,7 @@
#ifndef TableLayout_h
#define TableLayout_h
+#include "LayoutUnit.h"
#include <wtf/FastMalloc.h>
#include <wtf/Noncopyable.h>
@@ -39,6 +40,7 @@ public:
virtual ~TableLayout() { }
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) = 0;
+ virtual LayoutUnit scaledWidthFromPercentColumns() const { return LayoutUnit(0); }
virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const = 0;
virtual void layout() = 0;
diff --git a/Source/WebCore/rendering/line/BreakingContext.h b/Source/WebCore/rendering/line/BreakingContext.h
index c1f947689..799d2c063 100644
--- a/Source/WebCore/rendering/line/BreakingContext.h
+++ b/Source/WebCore/rendering/line/BreakingContext.h
@@ -559,9 +559,9 @@ inline void BreakingContext::handleReplaced()
m_ignoringSpaces = true;
}
if (downcast<RenderListMarker>(*m_current.renderer()).isInside())
- m_width.addUncommittedReplacedWidth(replacedLogicalWidth);
+ m_width.addUncommittedWidth(replacedLogicalWidth);
} else
- m_width.addUncommittedReplacedWidth(replacedLogicalWidth);
+ m_width.addUncommittedWidth(replacedLogicalWidth);
if (is<RenderRubyRun>(*m_current.renderer())) {
m_width.applyOverhang(downcast<RenderRubyRun>(m_current.renderer()), m_lastObject, m_nextObject);
downcast<RenderRubyRun>(m_current.renderer())->updatePriorContextFromCachedBreakIterator(m_renderTextInfo.lineBreakIterator);
@@ -747,7 +747,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
float charWidth = 0;
bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE;
// Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
- // which is only possible if the word is the first thing on the line, that is, if |w| is zero.
+ // which is only possible if the word is the first thing on the line.
bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.hasCommitted()) || m_currWS == PRE);
bool midWordBreak = false;
bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap;
diff --git a/Source/WebCore/rendering/line/LineWidth.cpp b/Source/WebCore/rendering/line/LineWidth.cpp
index f3b12b3ef..71e05cb23 100644
--- a/Source/WebCore/rendering/line/LineWidth.cpp
+++ b/Source/WebCore/rendering/line/LineWidth.cpp
@@ -37,14 +37,6 @@ namespace WebCore {
LineWidth::LineWidth(RenderBlockFlow& block, bool isFirstLine, IndentTextOrNot shouldIndentText)
: m_block(block)
- , m_uncommittedWidth(0)
- , m_committedWidth(0)
- , m_overhangWidth(0)
- , m_trailingWhitespaceWidth(0)
- , m_trailingCollapsedWhitespaceWidth(0)
- , m_left(0)
- , m_right(0)
- , m_availableWidth(0)
, m_isFirstLine(isFirstLine)
, m_shouldIndentText(shouldIndentText)
{
@@ -136,10 +128,7 @@ void LineWidth::commit()
{
m_committedWidth += m_uncommittedWidth;
m_uncommittedWidth = 0;
- if (m_hasUncommittedReplaced) {
- m_hasCommittedReplaced = true;
- m_hasUncommittedReplaced = false;
- }
+ m_hasCommitted = true;
}
void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)
diff --git a/Source/WebCore/rendering/line/LineWidth.h b/Source/WebCore/rendering/line/LineWidth.h
index 949d2c392..370b3a0f8 100644
--- a/Source/WebCore/rendering/line/LineWidth.h
+++ b/Source/WebCore/rendering/line/LineWidth.h
@@ -59,7 +59,7 @@ public:
float availableWidth() const { return m_availableWidth; }
float logicalLeftOffset() const { return m_left; }
- bool hasCommitted() const { return m_committedWidth > 0 || m_hasCommittedReplaced; }
+ bool hasCommitted() const { return m_hasCommitted; }
void updateAvailableWidth(LayoutUnit minimumHeight = 0);
void shrinkAvailableWidthForNewFloatIfNeeded(const FloatingObject&);
@@ -67,11 +67,6 @@ public:
{
m_uncommittedWidth += delta;
}
- void addUncommittedReplacedWidth(float delta)
- {
- addUncommittedWidth(delta);
- m_hasUncommittedReplaced = true;
- }
void commit();
void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
void fitBelowFloats(bool isFirstLine = false);
@@ -87,17 +82,16 @@ private:
#endif
RenderBlockFlow& m_block;
- float m_uncommittedWidth;
- float m_committedWidth;
- float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
- float m_trailingWhitespaceWidth;
- float m_trailingCollapsedWhitespaceWidth;
- float m_left;
- float m_right;
- float m_availableWidth;
- bool m_isFirstLine;
- bool m_hasUncommittedReplaced { false };
- bool m_hasCommittedReplaced { false };
+ float m_uncommittedWidth { 0 };
+ float m_committedWidth { 0 };
+ float m_overhangWidth { 0 }; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
+ float m_trailingWhitespaceWidth { 0 };
+ float m_trailingCollapsedWhitespaceWidth { 0 };
+ float m_left { 0 };
+ float m_right { 0 };
+ float m_availableWidth { 0 };
+ bool m_isFirstLine { true };
+ bool m_hasCommitted { false };
IndentTextOrNot m_shouldIndentText;
};
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp
index ebd4c9142..39c43ee15 100644
--- a/Source/WebCore/rendering/style/RenderStyle.cpp
+++ b/Source/WebCore/rendering/style/RenderStyle.cpp
@@ -811,6 +811,7 @@ bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, unsigned& chan
|| rareNonInheritedData->userDrag != other.rareNonInheritedData->userDrag
|| rareNonInheritedData->m_borderFit != other.rareNonInheritedData->m_borderFit
|| rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit
+ || rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition
|| rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering)
return true;
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 559df8182..7f84a0754 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -40,6 +40,7 @@
#include "Length.h"
#include "LengthBox.h"
#include "LengthFunctions.h"
+#include "LengthPoint.h"
#include "LengthSize.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
@@ -1035,8 +1036,9 @@ public:
TextOrientation textOrientation() const { return static_cast<TextOrientation>(rareInheritedData->m_textOrientation); }
ObjectFit objectFit() const { return static_cast<ObjectFit>(rareNonInheritedData->m_objectFit); }
-
- // Return true if any transform related property (currently transform, transformStyle3D or perspective)
+ LengthPoint objectPosition() const { return rareNonInheritedData->m_objectPosition; }
+
+ // Return true if any transform related property (currently transform, transformStyle3D or perspective)
// indicates that we are transforming
bool hasTransformRelatedProperty() const { return hasTransform() || preserves3D() || hasPerspective(); }
@@ -1606,6 +1608,7 @@ public:
bool setTextOrientation(TextOrientation);
void setObjectFit(ObjectFit fit) { SET_VAR(rareNonInheritedData, m_objectFit, fit); }
+ void setObjectPosition(const LengthPoint& position) { SET_VAR(rareNonInheritedData, m_objectPosition, position); }
void setRubyPosition(RubyPosition position) { SET_VAR(rareInheritedData, m_rubyPosition, position); }
@@ -1896,6 +1899,7 @@ public:
static TextOrientation initialTextOrientation() { return TextOrientation::
Mixed; }
static ObjectFit initialObjectFit() { return ObjectFitFill; }
+ static LengthPoint initialObjectPosition() { return LengthPoint(Length(50.0f, Percent), Length(50.0f, Percent)); }
static EEmptyCell initialEmptyCells() { return SHOW; }
static EListStylePosition initialListStylePosition() { return OUTSIDE; }
static EListStyleType initialListStyleType() { return Disc; }
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index 24ae59cf2..120bd5f5a 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -63,6 +63,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
#endif
, m_willChange(RenderStyle::initialWillChange())
, m_mask(FillLayer(MaskFillLayer))
+ , m_objectPosition(RenderStyle::initialObjectPosition())
#if ENABLE(CSS_SHAPES)
, m_shapeOutside(RenderStyle::initialShapeOutside())
, m_shapeMargin(RenderStyle::initialShapeMargin())
@@ -149,6 +150,7 @@ inline StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonIn
, m_mask(o.m_mask)
, m_maskBoxImage(o.m_maskBoxImage)
, m_pageSize(o.m_pageSize)
+ , m_objectPosition(o.m_objectPosition)
#if ENABLE(CSS_SHAPES)
, m_shapeOutside(o.m_shapeOutside)
, m_shapeMargin(o.m_shapeMargin)
@@ -253,6 +255,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_mask == o.m_mask
&& m_maskBoxImage == o.m_maskBoxImage
&& m_pageSize == o.m_pageSize
+ && m_objectPosition == o.m_objectPosition
#if ENABLE(CSS_SHAPES)
&& arePointingToEqualData(m_shapeOutside, o.m_shapeOutside)
&& m_shapeMargin == o.m_shapeMargin
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
index 9b1b2ad53..069b92878 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -32,6 +32,7 @@
#include "CursorData.h"
#include "DataRef.h"
#include "FillLayer.h"
+#include "LengthPoint.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
#include "ShapeValue.h"
@@ -154,6 +155,7 @@ public:
NinePieceImage m_maskBoxImage;
LengthSize m_pageSize;
+ LengthPoint m_objectPosition;
#if ENABLE(CSS_SHAPES)
RefPtr<ShapeValue> m_shapeOutside;
diff --git a/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp b/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp
index 8d8858f84..854c3e25f 100644
--- a/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp
+++ b/Source/WebCore/rendering/style/StyleScrollSnapPoints.cpp
@@ -31,8 +31,8 @@
namespace WebCore {
ScrollSnapPoints::ScrollSnapPoints()
- : repeatOffset(100, Percent)
- , hasRepeat(true)
+ : repeatOffset(0, Fixed)
+ , hasRepeat(false)
, usesElements(false)
{
}
diff --git a/Source/WebCore/rendering/style/WillChangeData.cpp b/Source/WebCore/rendering/style/WillChangeData.cpp
index 77d4aa871..cff2e7cd3 100644
--- a/Source/WebCore/rendering/style/WillChangeData.cpp
+++ b/Source/WebCore/rendering/style/WillChangeData.cpp
@@ -99,6 +99,30 @@ static bool propertyCreatesStackingContext(CSSPropertyID property)
}
}
+static bool propertyCreatesGraphicalGroup(CSSPropertyID property)
+{
+ switch (property) {
+ case CSSPropertyClipPath:
+ case CSSPropertyWebkitClipPath:
+ case CSSPropertyMask:
+ case CSSPropertyOpacity:
+#if ENABLE(CSS_COMPOSITING)
+ case CSSPropertyMixBlendMode:
+ case CSSPropertyIsolation:
+#endif
+ case CSSPropertyFilter:
+#if ENABLE(FILTERS_LEVEL_2)
+ case CSSPropertyWebkitBackdropFilter:
+#endif
+ case CSSPropertyWebkitMask:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskBoxImage:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool propertyTriggersCompositing(CSSPropertyID property)
{
switch (property) {
@@ -137,6 +161,8 @@ void WillChangeData::addFeature(Feature feature, CSSPropertyID propertyID)
m_canTriggerCompositingOnInline |= propertyTriggersCompositing(propertyID);
m_canTriggerCompositing |= m_canTriggerCompositingOnInline | propertyTriggersCompositingOnBoxesOnly(propertyID);
+
+ m_canCreateGraphicalGroup |= propertyCreatesGraphicalGroup(propertyID);
}
WillChangeData::FeaturePropertyPair WillChangeData::featureAt(size_t index) const
diff --git a/Source/WebCore/rendering/style/WillChangeData.h b/Source/WebCore/rendering/style/WillChangeData.h
index 49e76089d..6bab28da6 100644
--- a/Source/WebCore/rendering/style/WillChangeData.h
+++ b/Source/WebCore/rendering/style/WillChangeData.h
@@ -57,6 +57,7 @@ public:
bool canCreateStackingContext() const { return m_canCreateStackingContext; }
bool canTriggerCompositing() const { return m_canTriggerCompositing; }
bool canTriggerCompositingOnInline() const { return m_canTriggerCompositingOnInline; }
+ bool canCreateGraphicalGroup() const { return m_canCreateGraphicalGroup; }
enum Feature {
ScrollPosition,
@@ -124,6 +125,7 @@ private:
bool m_canCreateStackingContext { false };
bool m_canTriggerCompositing { false };
bool m_canTriggerCompositingOnInline { false };
+ bool m_canCreateGraphicalGroup { false };
};
diff --git a/Source/WebCore/svg/SVGLengthContext.cpp b/Source/WebCore/svg/SVGLengthContext.cpp
index fe4b66994..1bd857b9d 100644
--- a/Source/WebCore/svg/SVGLengthContext.cpp
+++ b/Source/WebCore/svg/SVGLengthContext.cpp
@@ -91,7 +91,7 @@ float SVGLengthContext::valueForLength(const Length& length, SVGLengthMode mode)
{
if (length.isPercent())
return convertValueFromPercentageToUserUnits(length.value() / 100, mode, IGNORE_EXCEPTION);
- if (length.isAuto())
+ if (length.isAuto() || !length.isSpecified())
return 0;
FloatSize viewportSize;
diff --git a/Source/WebCore/svg/SVGSVGElement.cpp b/Source/WebCore/svg/SVGSVGElement.cpp
index e5fbd7465..7990139b3 100644
--- a/Source/WebCore/svg/SVGSVGElement.cpp
+++ b/Source/WebCore/svg/SVGSVGElement.cpp
@@ -64,7 +64,7 @@ inline SVGSVGElement::SVGSVGElement(const QualifiedName& tagName, Document& docu
, m_y(LengthModeHeight)
, m_width(LengthModeWidth, ASCIILiteral("100%"))
, m_height(LengthModeHeight, ASCIILiteral("100%"))
- , m_timeContainer(RefPtr<SMILTimeContainer>(SMILTimeContainer::create(this)).releaseNonNull())
+ , m_timeContainer(SMILTimeContainer::create(this))
{
ASSERT(hasTagName(SVGNames::svgTag));
registerAnimatedPropertiesForSVGSVGElement();
diff --git a/Source/WebCore/svg/animation/SMILTime.h b/Source/WebCore/svg/animation/SMILTime.h
index 60d1301a0..3047d97af 100644
--- a/Source/WebCore/svg/animation/SMILTime.h
+++ b/Source/WebCore/svg/animation/SMILTime.h
@@ -31,6 +31,8 @@
namespace WebCore {
+const double SMILAnimationFrameDelay = 1.0 / 60;
+
class SMILTime {
public:
SMILTime() : m_time(0) { }
diff --git a/Source/WebCore/svg/animation/SMILTimeContainer.cpp b/Source/WebCore/svg/animation/SMILTimeContainer.cpp
index 57d9c7f7f..cbf3b7ba5 100644
--- a/Source/WebCore/svg/animation/SMILTimeContainer.cpp
+++ b/Source/WebCore/svg/animation/SMILTimeContainer.cpp
@@ -35,8 +35,6 @@
namespace WebCore {
-static const double animationFrameDelay = 0.025;
-
SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
: m_beginTime(0)
, m_pauseTime(0)
@@ -100,7 +98,7 @@ void SMILTimeContainer::notifyIntervalsChanged()
{
// Schedule updateAnimations() to be called asynchronously so multiple intervals
// can change with updateAnimations() only called once at the end.
- startTimer(0);
+ startTimer(elapsed(), 0);
}
SMILTime SMILTimeContainer::elapsed() const
@@ -161,7 +159,7 @@ void SMILTimeContainer::resume()
m_resumeTime = monotonicallyIncreasingTime();
m_pauseTime = 0;
- startTimer(0);
+ startTimer(elapsed(), 0);
}
void SMILTimeContainer::setElapsed(SMILTime time)
@@ -198,7 +196,7 @@ void SMILTimeContainer::setElapsed(SMILTime time)
updateAnimations(time, true);
}
-void SMILTimeContainer::startTimer(SMILTime fireTime, SMILTime minimumDelay)
+void SMILTimeContainer::startTimer(SMILTime elapsed, SMILTime fireTime, SMILTime minimumDelay)
{
if (!m_beginTime || isPaused())
return;
@@ -206,7 +204,7 @@ void SMILTimeContainer::startTimer(SMILTime fireTime, SMILTime minimumDelay)
if (!fireTime.isFinite())
return;
- SMILTime delay = std::max(fireTime - elapsed(), minimumDelay);
+ SMILTime delay = std::max(fireTime - elapsed, minimumDelay);
m_timer.startOneShot(delay.value());
}
@@ -309,7 +307,7 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
#ifndef NDEBUG
m_preventScheduledAnimationsChanges = false;
#endif
- startTimer(earliestFireTime, animationFrameDelay);
+ startTimer(elapsed, earliestFireTime, SMILAnimationFrameDelay);
return;
}
@@ -321,7 +319,7 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
m_preventScheduledAnimationsChanges = false;
#endif
- startTimer(earliestFireTime, animationFrameDelay);
+ startTimer(elapsed, earliestFireTime, SMILAnimationFrameDelay);
}
}
diff --git a/Source/WebCore/svg/animation/SMILTimeContainer.h b/Source/WebCore/svg/animation/SMILTimeContainer.h
index d2856027a..ae4cba4d9 100644
--- a/Source/WebCore/svg/animation/SMILTimeContainer.h
+++ b/Source/WebCore/svg/animation/SMILTimeContainer.h
@@ -67,7 +67,7 @@ private:
SMILTimeContainer(SVGSVGElement* owner);
void timerFired();
- void startTimer(SMILTime fireTime, SMILTime minimumDelay = 0);
+ void startTimer(SMILTime elapsed, SMILTime fireTime, SMILTime minimumDelay = 0);
void updateAnimations(SMILTime elapsed, bool seekToTime = false);
void updateDocumentOrderIndexes();
diff --git a/Source/WebCore/svg/animation/SVGSMILElement.cpp b/Source/WebCore/svg/animation/SVGSMILElement.cpp
index 4410b5bd3..f75f945a5 100644
--- a/Source/WebCore/svg/animation/SVGSMILElement.cpp
+++ b/Source/WebCore/svg/animation/SVGSMILElement.cpp
@@ -1042,7 +1042,7 @@ SMILTime SVGSMILElement::calculateNextProgressTime(SMILTime elapsed) const
return repeatingDurationEnd;
return m_intervalEnd;
}
- return elapsed + 0.025;
+ return elapsed + SMILAnimationFrameDelay;
}
return m_intervalBegin >= elapsed ? m_intervalBegin : SMILTime::unresolved();
}
diff --git a/Source/WebCore/workers/WorkerGlobalScope.idl b/Source/WebCore/workers/WorkerGlobalScope.idl
index e12d26514..2a703764c 100644
--- a/Source/WebCore/workers/WorkerGlobalScope.idl
+++ b/Source/WebCore/workers/WorkerGlobalScope.idl
@@ -33,9 +33,9 @@
] interface WorkerGlobalScope : EventTarget {
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
- [Replaceable] readonly attribute WorkerGlobalScope self;
+ readonly attribute WorkerGlobalScope self;
#endif
- [Replaceable] readonly attribute WorkerLocation location;
+ readonly attribute WorkerLocation location;
void close();
attribute EventHandler onerror;
@@ -45,7 +45,7 @@
// WorkerUtils
[Custom] void importScripts(/*[Variadic] DOMString urls */);
- [Replaceable] readonly attribute WorkerNavigator navigator;
+ readonly attribute WorkerNavigator navigator;
// Additional constructors