| Index: Source/core/css/CSSParser-in.cpp
 | 
| diff --git a/Source/core/css/CSSParser-in.cpp b/Source/core/css/CSSParser-in.cpp
 | 
| index e16ad3539876c8e73c9c05cc6298700b07ee0769..a562e7445b63495f9fefd38c1ac25a4db6c01a92 100644
 | 
| --- a/Source/core/css/CSSParser-in.cpp
 | 
| +++ b/Source/core/css/CSSParser-in.cpp
 | 
| @@ -2451,11 +2451,15 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
 | 
|  
 | 
|      case CSSPropertyGridColumn:
 | 
|      case CSSPropertyGridRow:
 | 
| -    case CSSPropertyGridArea:
 | 
|          if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
 | 
|              return false;
 | 
|          return parseGridItemPositionShorthand(propId, important);
 | 
|  
 | 
| +    case CSSPropertyGridArea:
 | 
| +        if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
 | 
| +            return false;
 | 
| +        return parseGridAreaShorthand(important);
 | 
| +
 | 
|      case CSSPropertyGridTemplate:
 | 
|          if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
 | 
|              return false;
 | 
| @@ -4575,6 +4579,11 @@ PassRefPtr<CSSValue> CSSParser::parseGridPosition()
 | 
|          return cssValuePool().createIdentifierValue(CSSValueAuto);
 | 
|      }
 | 
|  
 | 
| +    if (value->id != CSSValueSpan && value->unit == CSSPrimitiveValue::CSS_IDENT) {
 | 
| +        m_valueList->next();
 | 
| +        return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING);
 | 
| +    }
 | 
| +
 | 
|      RefPtr<CSSPrimitiveValue> numericValue;
 | 
|      RefPtr<CSSPrimitiveValue> gridLineName;
 | 
|      bool hasSeenSpanKeyword = false;
 | 
| @@ -4615,35 +4624,96 @@ PassRefPtr<CSSValue> CSSParser::parseGridPosition()
 | 
|      return values.release();
 | 
|  }
 | 
|  
 | 
| -bool CSSParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool important)
 | 
| +static PassRefPtr<CSSValue> gridMissingGridPositionValue(CSSValue* value)
 | 
|  {
 | 
| -    ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
 | 
| +    if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->isString())
 | 
| +        return value;
 | 
| +
 | 
| +    return cssValuePool().createIdentifierValue(CSSValueAuto);
 | 
| +}
 | 
|  
 | 
| +bool CSSParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool important)
 | 
| +{
 | 
|      ShorthandScope scope(this, shorthandId);
 | 
|      const StylePropertyShorthand& shorthand = shorthandForProperty(shorthandId);
 | 
| -    if (!parseValue(shorthand.properties()[0], important))
 | 
| -        return false;
 | 
| +    ASSERT(shorthand.length() == 2);
 | 
|  
 | 
| -    size_t index = 1;
 | 
| -    for (; index < shorthand.length(); ++index) {
 | 
| -        if (!m_valueList->current())
 | 
| -            break;
 | 
| +    RefPtr<CSSValue> startValue = parseGridPosition();
 | 
| +    if (!startValue)
 | 
| +        return false;
 | 
|  
 | 
| +    RefPtr<CSSValue> endValue;
 | 
| +    if (m_valueList->current()) {
 | 
|          if (!isForwardSlashOperator(m_valueList->current()))
 | 
|              return false;
 | 
|  
 | 
|          if (!m_valueList->next())
 | 
|              return false;
 | 
|  
 | 
| -        if (!parseValue(shorthand.properties()[index], important))
 | 
| +        endValue = parseGridPosition();
 | 
| +        if (!endValue || m_valueList->current())
 | 
|              return false;
 | 
| +    } else {
 | 
| +        endValue = gridMissingGridPositionValue(startValue.get());
 | 
|      }
 | 
|  
 | 
| -    // Only one value out of the 2 positions was specified, the opposite value should be set to 'auto'.
 | 
| -    // FIXME: If the first property was <ident>, the opposite value should be the same <ident>.
 | 
| -    for (; index < shorthand.length(); ++index)
 | 
| -        addProperty(shorthand.properties()[index], cssValuePool().createIdentifierValue(CSSValueAuto), important);
 | 
| +    addProperty(shorthand.properties()[0], startValue, important);
 | 
| +    addProperty(shorthand.properties()[1], endValue, important);
 | 
| +    return true;
 | 
| +}
 | 
| +
 | 
| +bool CSSParser::parseGridAreaShorthand(bool important)
 | 
| +{
 | 
| +    ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
 | 
| +
 | 
| +    ShorthandScope scope(this, CSSPropertyGridArea);
 | 
| +    const StylePropertyShorthand& shorthand = gridAreaShorthand();
 | 
| +    ASSERT(shorthand.length() == 4);
 | 
| +
 | 
| +    RefPtr<CSSValue> rowStartValue = parseGridPosition();
 | 
| +    if (!rowStartValue)
 | 
| +        return false;
 | 
| +
 | 
| +    RefPtr<CSSValue> columnStartValue;
 | 
| +    if (!parseSingleGridAreaLonghand(columnStartValue))
 | 
| +        return false;
 | 
| +
 | 
| +    RefPtr<CSSValue> rowEndValue;
 | 
| +    if (!parseSingleGridAreaLonghand(rowEndValue))
 | 
| +        return false;
 | 
| +
 | 
| +    RefPtr<CSSValue> columnEndValue;
 | 
| +    if (!parseSingleGridAreaLonghand(columnEndValue))
 | 
| +        return false;
 | 
| +
 | 
| +    if (!columnStartValue)
 | 
| +        columnStartValue = gridMissingGridPositionValue(rowStartValue.get());
 | 
| +
 | 
| +    if (!rowEndValue)
 | 
| +        rowEndValue = gridMissingGridPositionValue(rowStartValue.get());
 | 
| +
 | 
| +    if (!columnEndValue)
 | 
| +        columnEndValue = gridMissingGridPositionValue(columnStartValue.get());
 | 
| +
 | 
| +    addProperty(CSSPropertyGridRowStart, rowStartValue, important);
 | 
| +    addProperty(CSSPropertyGridColumnStart, columnStartValue, important);
 | 
| +    addProperty(CSSPropertyGridRowEnd, rowEndValue, important);
 | 
| +    addProperty(CSSPropertyGridColumnEnd, columnEndValue, important);
 | 
| +    return true;
 | 
| +}
 | 
| +
 | 
| +bool CSSParser::parseSingleGridAreaLonghand(RefPtr<CSSValue>& property)
 | 
| +{
 | 
| +    if (!m_valueList->current())
 | 
| +        return true;
 | 
| +
 | 
| +    if (!isForwardSlashOperator(m_valueList->current()))
 | 
| +        return false;
 | 
| +
 | 
| +    if (!m_valueList->next())
 | 
| +        return false;
 | 
|  
 | 
| +    property = parseGridPosition();
 | 
|      return true;
 | 
|  }
 | 
|  
 | 
| 
 |