Modified: trunk/Source/WebCore/ChangeLog (208290 => 208291)
--- trunk/Source/WebCore/ChangeLog 2016-11-02 17:48:23 UTC (rev 208290)
+++ trunk/Source/WebCore/ChangeLog 2016-11-02 18:07:32 UTC (rev 208291)
@@ -1,3 +1,24 @@
+2016-11-02 Dave Hyatt <hy...@apple.com>
+
+ [CSS Parser] Support scroll-snap-* properties
+ https://bugs.webkit.org/show_bug.cgi?id=164321
+
+ Reviewed by Simon Fraser.
+
+ * css/CSSPrimitiveValue.h:
+ * css/StyleBuilderConverter.h:
+ (WebCore::StyleBuilderConverter::convertScrollSnapPoints):
+ (WebCore::StyleBuilderConverter::convertSnapCoordinatePair):
+ (WebCore::StyleBuilderConverter::convertScrollSnapCoordinates):
+ * css/parser/CSSPropertyParser.cpp:
+ (WebCore::consumePositionLonghand):
+ (WebCore::consumePositionX):
+ (WebCore::consumePositionY):
+ (WebCore::consumePositionList):
+ (WebCore::consumeScrollSnapDestination):
+ (WebCore::consumeScrollSnapPoints):
+ (WebCore::CSSPropertyParser::parseSingleValue):
+
2016-11-02 David Kilzer <ddkil...@apple.com>
Add logging for "WebKit encountered an internal error" messages
Modified: trunk/Source/WebCore/css/CSSPrimitiveValue.h (208290 => 208291)
--- trunk/Source/WebCore/css/CSSPrimitiveValue.h 2016-11-02 17:48:23 UTC (rev 208290)
+++ trunk/Source/WebCore/css/CSSPrimitiveValue.h 2016-11-02 18:07:32 UTC (rev 208291)
@@ -113,6 +113,7 @@
CSS_DPCM = 32,
CSS_FR = 33,
#if ENABLE(CSS_SCROLL_SNAP)
+ // FIXME-NEWPARSER: Remove once new parser lands.
CSS_LENGTH_REPEAT = 34,
#endif
CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.)
Modified: trunk/Source/WebCore/css/StyleBuilderConverter.h (208290 => 208291)
--- trunk/Source/WebCore/css/StyleBuilderConverter.h 2016-11-02 17:48:23 UTC (rev 208290)
+++ trunk/Source/WebCore/css/StyleBuilderConverter.h 2016-11-02 18:07:32 UTC (rev 208291)
@@ -807,17 +807,28 @@
inline std::unique_ptr<ScrollSnapPoints> StyleBuilderConverter::convertScrollSnapPoints(StyleResolver& styleResolver, const CSSValue& value)
{
+ // FIXME-NEWPARSER: Old parser supports an identifier value called "elements" when it seems like
+ // "none" is what others use. For now, support both in the converter.
auto points = std::make_unique<ScrollSnapPoints>();
-
+
if (is<CSSPrimitiveValue>(value)) {
- ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueElements);
+ ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueElements || downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
points->usesElements = true;
return points;
}
-
+
for (auto& currentValue : downcast<CSSValueList>(value)) {
+ if (is<CSSFunctionValue>(currentValue.get())) {
+ auto& functionValue = downcast<CSSFunctionValue>(currentValue.get());
+ points->repeatOffset = parseSnapCoordinate(styleResolver, *functionValue.arguments()->item(0));
+ points->hasRepeat = true;
+ break;
+ }
+
auto& itemValue = downcast<CSSPrimitiveValue>(currentValue.get());
if (auto* lengthRepeat = itemValue.lengthRepeatValue()) {
+ // FIXME-NEWPARSER: Old parsing code, which uses a special primitive value.
+ // Can remove this once new parser turns on.
if (auto* interval = lengthRepeat->interval()) {
points->repeatOffset = parseSnapCoordinate(styleResolver, *interval);
points->hasRepeat = true;
@@ -832,6 +843,16 @@
inline LengthSize StyleBuilderConverter::convertSnapCoordinatePair(StyleResolver& styleResolver, const CSSValue& value, size_t offset)
{
+ // FIXME-NEWPARSER: Can make this unconditional once old parser is gone. This is just how
+ // we detect that we're dealing with the new parser's pairs.
+ if (value.isPrimitiveValue() && downcast<CSSPrimitiveValue>(value).pairValue()) {
+ Pair* pair = downcast<CSSPrimitiveValue>(value).pairValue();
+ Length lengthX = convertPositionComponent<CSSValueLeft, CSSValueRight>(styleResolver, *pair->first());
+ Length lengthY = convertPositionComponent<CSSValueTop, CSSValueBottom>(styleResolver, *pair->second());
+ return LengthSize(lengthX, lengthY);
+ }
+
+ // FIXME-NEWPARSER: Remove once old parser is gone.
auto& valueList = downcast<CSSValueList>(value);
return LengthSize(parseSnapCoordinate(styleResolver, *valueList.item(offset)), parseSnapCoordinate(styleResolver, *valueList.item(offset + 1)));
}
@@ -838,7 +859,31 @@
inline Vector<LengthSize> StyleBuilderConverter::convertScrollSnapCoordinates(StyleResolver& styleResolver, const CSSValue& value)
{
+ if (is<CSSPrimitiveValue>(value)) {
+ ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
+ return Vector<LengthSize>();
+ }
+
auto& valueList = downcast<CSSValueList>(value);
+ if (!valueList.length())
+ return Vector<LengthSize>();
+
+ // FIXME-NEWPARSER: Can make this unconditional once old parser is gone. This is just how
+ // we detect that we're dealing with the new parser's pairs.
+ if (valueList.item(0)->isPrimitiveValue() && downcast<CSSPrimitiveValue>(*valueList.item(0)).pairValue()) {
+ Vector<LengthSize> coordinates;
+ coordinates.reserveInitialCapacity(valueList.length());
+ for (auto& snapCoordinate : valueList) {
+ Pair* pair = downcast<CSSPrimitiveValue>(*snapCoordinate.ptr()).pairValue();
+ Length lengthX = convertPositionComponent<CSSValueLeft, CSSValueRight>(styleResolver, *pair->first());
+ Length lengthY = convertPositionComponent<CSSValueTop, CSSValueBottom>(styleResolver, *pair->second());
+ coordinates.uncheckedAppend(LengthSize(lengthX, lengthY));
+ }
+ return coordinates;
+ }
+
+ // FIXME-NEWPARSER: Remove all of this once old parser is gone, including all the functions
+ // it calls.
ASSERT(!(valueList.length() % 2));
size_t pointCount = valueList.length() / 2;
Vector<LengthSize> coordinates;
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp (208290 => 208291)
--- trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp 2016-11-02 17:48:23 UTC (rev 208290)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp 2016-11-02 18:07:32 UTC (rev 208291)
@@ -1719,7 +1719,7 @@
}
template <CSSValueID start, CSSValueID end>
-static RefPtr<CSSValue> consumePositionLonghand(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+static RefPtr<CSSPrimitiveValue> consumePositionLonghand(CSSParserTokenRange& range, CSSParserMode cssParserMode)
{
if (range.peek().type() == IdentToken) {
CSSValueID id = range.peek().id();
@@ -1738,12 +1738,12 @@
return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll);
}
-static RefPtr<CSSValue> consumePositionX(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+static RefPtr<CSSPrimitiveValue> consumePositionX(CSSParserTokenRange& range, CSSParserMode cssParserMode)
{
return consumePositionLonghand<CSSValueLeft, CSSValueRight>(range, cssParserMode);
}
-static RefPtr<CSSValue> consumePositionY(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+static RefPtr<CSSPrimitiveValue> consumePositionY(CSSParserTokenRange& range, CSSParserMode cssParserMode)
{
return consumePositionLonghand<CSSValueTop, CSSValueBottom>(range, cssParserMode);
}
@@ -2006,15 +2006,20 @@
#if ENABLE(CSS_SCROLL_SNAP)
-static RefPtr<CSSValueList> consumePositionList(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+static RefPtr<CSSValueList> consumeSnapPointCoordinateList(CSSParserTokenRange& range, CSSParserMode cssParserMode)
{
- RefPtr<CSSValueList> positions = CSSValueList::createCommaSeparated();
+ RefPtr<CSSValueList> positions = CSSValueList::createSpaceSeparated();
do {
- RefPtr<CSSValue> position = consumePosition(range, cssParserMode, UnitlessQuirk::Forbid);
- if (!position)
+
+ RefPtr<CSSPrimitiveValue> first = consumePositionX(range, cssParserMode);
+ if (!first || range.atEnd())
return nullptr;
+ RefPtr<CSSPrimitiveValue> second = consumePositionY(range, cssParserMode);
+ if (!second)
+ return nullptr;
+ RefPtr<CSSValue> position = createPrimitiveValuePair(first.releaseNonNull(), second.releaseNonNull(), Pair::IdenticalValueEncoding::DoNotCoalesce);
positions->append(position.releaseNonNull());
- } while (consumeCommaIncludingWhitespace(range));
+ } while (!range.atEnd());
return positions;
}
@@ -2022,23 +2027,45 @@
{
if (range.peek().id() == CSSValueNone)
return consumeIdent(range);
- return consumePositionList(range, cssParserMode);
+ return consumeSnapPointCoordinateList(range, cssParserMode);
}
+static RefPtr<CSSValue> consumeScrollSnapDestination(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+ RefPtr<CSSPrimitiveValue> first = consumePositionX(range, cssParserMode);
+ if (!first || range.atEnd())
+ return nullptr;
+ RefPtr<CSSPrimitiveValue> second = consumePositionY(range, cssParserMode);
+ if (!second)
+ return nullptr;
+ return createPrimitiveValuePair(first.releaseNonNull(), second.releaseNonNull(), Pair::IdenticalValueEncoding::DoNotCoalesce);
+}
+
static RefPtr<CSSValue> consumeScrollSnapPoints(CSSParserTokenRange& range, CSSParserMode cssParserMode)
{
- if (range.peek().id() == CSSValueNone)
+ if (range.peek().id() == CSSValueNone || range.peek().id() == CSSValueElements)
return consumeIdent(range);
- if (range.peek().functionId() == CSSValueRepeat) {
- CSSParserTokenRange args = consumeFunction(range);
- RefPtr<CSSPrimitiveValue> parsedValue = consumeLengthOrPercent(args, cssParserMode, ValueRangeNonNegative);
- if (args.atEnd() && parsedValue && (parsedValue->isCalculated() || parsedValue->doubleValue() > 0)) {
- RefPtr<CSSFunctionValue> result = CSSFunctionValue::create(CSSValueRepeat);
- result->append(parsedValue.releaseNonNull());
- return result;
+
+ RefPtr<CSSValueList> points = CSSValueList::createSpaceSeparated();
+ do {
+ if (range.peek().functionId() == CSSValueRepeat) {
+ CSSParserTokenRange args = consumeFunction(range);
+ RefPtr<CSSPrimitiveValue> parsedValue = consumeLengthOrPercent(args, cssParserMode, ValueRangeNonNegative);
+ if (args.atEnd() && parsedValue && (parsedValue->isCalculated() || parsedValue->doubleValue() > 0)) {
+ Ref<CSSFunctionValue> result = CSSFunctionValue::create(CSSValueRepeat);
+ result->append(parsedValue.releaseNonNull());
+ points->append(WTFMove(result));
+ }
+ } else {
+ RefPtr<CSSValue> length = consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, UnitlessQuirk::Forbid);
+ if (!length)
+ return nullptr;
+ points->append(length.releaseNonNull());
}
- }
- return nullptr;
+ } while (!range.atEnd());
+
+
+ return points;
}
#endif
@@ -3602,6 +3629,8 @@
#if ENABLE(CSS_SCROLL_SNAP)
case CSSPropertyWebkitScrollSnapCoordinate:
return consumeScrollSnapCoordinate(m_range, m_context.mode);
+ case CSSPropertyWebkitScrollSnapDestination:
+ return consumeScrollSnapDestination(m_range, m_context.mode);
case CSSPropertyWebkitScrollSnapPointsX:
case CSSPropertyWebkitScrollSnapPointsY:
return consumeScrollSnapPoints(m_range, m_context.mode);