Merge from Chromium at DEPS revision 261286

This commit was generated by merge_to_master.py.

Change-Id: I756d37445fd7f470b1689ad81318e715d4244987
diff --git a/Source/core/css/CSSBasicShapes.cpp b/Source/core/css/CSSBasicShapes.cpp
index 876d8b6..72bfcef 100644
--- a/Source/core/css/CSSBasicShapes.cpp
+++ b/Source/core/css/CSSBasicShapes.cpp
@@ -41,7 +41,7 @@
 
 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CSSBasicShape)
 
-static String buildCircleString(const String& radius, const String& centerX, const String& centerY, const String& layoutBox)
+static String buildCircleString(const String& radius, const String& centerX, const String& centerY, const String& box)
 {
     char at[] = "at";
     char separator[] = " ";
@@ -60,9 +60,9 @@
         result.append(centerY);
     }
     result.append(")");
-    if (layoutBox.length()) {
+    if (box.length()) {
         result.appendLiteral(separator);
-        result.append(layoutBox);
+        result.append(box);
     }
     return result.toString();
 }
@@ -117,7 +117,7 @@
     return buildCircleString(m_radius ? m_radius->cssText() : String(),
         serializePositionOffset(*normalizedCX->getPairValue(), *normalizedCY->getPairValue()),
         serializePositionOffset(*normalizedCY->getPairValue(), *normalizedCX->getPairValue()),
-        m_layoutBox ? m_layoutBox->cssText() : String());
+        m_referenceBox ? m_referenceBox->cssText() : String());
 }
 
 bool CSSBasicShapeCircle::equals(const CSSBasicShape& shape) const
@@ -129,7 +129,7 @@
     return compareCSSValuePtr(m_centerX, other.m_centerX)
         && compareCSSValuePtr(m_centerY, other.m_centerY)
         && compareCSSValuePtr(m_radius, other.m_radius)
-        && compareCSSValuePtr(m_layoutBox, other.m_layoutBox);
+        && compareCSSValuePtr(m_referenceBox, other.m_referenceBox);
 }
 
 void CSSBasicShapeCircle::trace(Visitor* visitor)
@@ -184,7 +184,7 @@
         m_radiusY ? m_radiusY->cssText() : String(),
         serializePositionOffset(*normalizedCX->getPairValue(), *normalizedCY->getPairValue()),
         serializePositionOffset(*normalizedCY->getPairValue(), *normalizedCX->getPairValue()),
-        m_layoutBox ? m_layoutBox->cssText() : String());
+        m_referenceBox ? m_referenceBox->cssText() : String());
 }
 
 bool CSSBasicShapeEllipse::equals(const CSSBasicShape& shape) const
@@ -197,7 +197,7 @@
         && compareCSSValuePtr(m_centerY, other.m_centerY)
         && compareCSSValuePtr(m_radiusX, other.m_radiusX)
         && compareCSSValuePtr(m_radiusY, other.m_radiusY)
-        && compareCSSValuePtr(m_layoutBox, other.m_layoutBox);
+        && compareCSSValuePtr(m_referenceBox, other.m_referenceBox);
 }
 
 void CSSBasicShapeEllipse::trace(Visitor* visitor)
@@ -209,7 +209,7 @@
     CSSBasicShape::trace(visitor);
 }
 
-static String buildPolygonString(const WindRule& windRule, const Vector<String>& points, const String& layoutBox)
+static String buildPolygonString(const WindRule& windRule, const Vector<String>& points, const String& box)
 {
     ASSERT(!(points.size() % 2));
 
@@ -227,8 +227,8 @@
         // add length of two strings, plus one for the space separator.
         length += points[i].length() + 1 + points[i + 1].length();
     }
-    if (!layoutBox.isEmpty())
-        length += layoutBox.length() + 1;
+    if (!box.isEmpty())
+        length += box.length() + 1;
     result.reserveCapacity(length);
 
     if (windRule == RULE_EVENODD)
@@ -246,9 +246,9 @@
 
     result.append(')');
 
-    if (!layoutBox.isEmpty()) {
+    if (!box.isEmpty()) {
         result.append(' ');
-        result.append(layoutBox);
+        result.append(box);
     }
 
     return result.toString();
@@ -262,7 +262,7 @@
     for (size_t i = 0; i < m_values.size(); ++i)
         points.append(m_values.at(i)->cssText());
 
-    return buildPolygonString(m_windRule, points, m_layoutBox ? m_layoutBox->cssText() : String());
+    return buildPolygonString(m_windRule, points, m_referenceBox ? m_referenceBox->cssText() : String());
 }
 
 bool CSSBasicShapePolygon::equals(const CSSBasicShape& shape) const
@@ -272,7 +272,7 @@
 
     const CSSBasicShapePolygon& rhs = static_cast<const CSSBasicShapePolygon&>(shape);
 
-    if (!compareCSSValuePtr(m_layoutBox, rhs.m_layoutBox))
+    if (!compareCSSValuePtr(m_referenceBox, rhs.m_referenceBox))
         return false;
 
     return compareCSSValueVector(m_values, rhs.m_values);
diff --git a/Source/core/css/CSSBasicShapes.h b/Source/core/css/CSSBasicShapes.h
index 3645169..4c510e0 100644
--- a/Source/core/css/CSSBasicShapes.h
+++ b/Source/core/css/CSSBasicShapes.h
@@ -52,14 +52,14 @@
     virtual String cssText() const = 0;
     virtual bool equals(const CSSBasicShape&) const = 0;
 
-    CSSPrimitiveValue* layoutBox() const { return m_layoutBox.get(); }
-    void setLayoutBox(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> layoutBox) { m_layoutBox = layoutBox; }
+    CSSPrimitiveValue* referenceBox() const { return m_referenceBox.get(); }
+    void setReferenceBox(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> referenceBox) { m_referenceBox = referenceBox; }
 
-    virtual void trace(Visitor* visitor) { visitor->trace(m_layoutBox); }
+    virtual void trace(Visitor* visitor) { visitor->trace(m_referenceBox); }
 
 protected:
     CSSBasicShape() { }
-    RefPtrWillBeMember<CSSPrimitiveValue> m_layoutBox;
+    RefPtrWillBeMember<CSSPrimitiveValue> m_referenceBox;
 };
 
 class CSSBasicShapeCircle FINAL : public CSSBasicShape {
diff --git a/Source/core/css/CSSComputedStyleDeclaration.cpp b/Source/core/css/CSSComputedStyleDeclaration.cpp
index 7a28a22..71388a9 100644
--- a/Source/core/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -296,12 +296,13 @@
     CSSPropertyWebkitMaskRepeat,
     CSSPropertyWebkitMaskSize,
     CSSPropertyOrder,
+    CSSPropertyPerspective,
     CSSPropertyWebkitPerspective,
+    CSSPropertyPerspectiveOrigin,
     CSSPropertyWebkitPerspectiveOrigin,
     CSSPropertyWebkitPrintColorAdjust,
     CSSPropertyWebkitRtlOrdering,
     CSSPropertyShapeOutside,
-    CSSPropertyShapePadding,
     CSSPropertyShapeImageThreshold,
     CSSPropertyShapeMargin,
     CSSPropertyWebkitTapHighlightColor,
@@ -315,7 +316,9 @@
     CSSPropertyWebkitTextSecurity,
     CSSPropertyWebkitTextStrokeColor,
     CSSPropertyWebkitTextStrokeWidth,
+    CSSPropertyTransform,
     CSSPropertyWebkitTransform,
+    CSSPropertyTransformOrigin,
     CSSPropertyWebkitTransformOrigin,
     CSSPropertyTransformStyle,
     CSSPropertyWebkitTransformStyle,
@@ -1438,7 +1441,7 @@
     if (shapeValue->type() == ShapeValue::Outside)
         return cssValuePool().createIdentifierValue(CSSValueOutsideShape);
     if (shapeValue->type() == ShapeValue::Box)
-        return cssValuePool().createValue(shapeValue->layoutBox());
+        return cssValuePool().createValue(shapeValue->cssBox());
     if (shapeValue->type() == ShapeValue::Image) {
         if (shapeValue->image())
             return shapeValue->image()->cssValue();
@@ -1449,8 +1452,8 @@
 
     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
     list->append(valueForBasicShape(style, shapeValue->shape()));
-    if (shapeValue->layoutBox() != BoxMissing)
-        list->append(cssValuePool().createValue(shapeValue->layoutBox()));
+    if (shapeValue->cssBox() != BoxMissing)
+        list->append(cssValuePool().createValue(shapeValue->cssBox()));
     return list.release();
 }
 
@@ -1490,8 +1493,11 @@
     case CSSPropertyLeft:
     case CSSPropertyRight:
     case CSSPropertyTop:
+    case CSSPropertyPerspectiveOrigin:
     case CSSPropertyWebkitPerspectiveOrigin:
+    case CSSPropertyTransform:
     case CSSPropertyWebkitTransform:
+    case CSSPropertyTransformOrigin:
     case CSSPropertyWebkitTransformOrigin:
     case CSSPropertyWidth:
     case CSSPropertyWebkitFilter:
@@ -1976,7 +1982,8 @@
             return valuesForGridShorthand(gridRowShorthand());
         case CSSPropertyGridArea:
             return valuesForGridShorthand(gridAreaShorthand());
-
+        case CSSPropertyGridTemplate:
+            return valuesForGridShorthand(gridTemplateShorthand());
         case CSSPropertyGridTemplateAreas:
             if (!style->namedGridAreaRowCount()) {
                 ASSERT(!style->namedGridAreaColumnCount());
@@ -2502,10 +2509,12 @@
         case CSSPropertyWebkitMarginTopCollapse:
         case CSSPropertyWebkitMarginBeforeCollapse:
             return cssValuePool().createValue(style->marginBeforeCollapse());
+        case CSSPropertyPerspective:
         case CSSPropertyWebkitPerspective:
             if (!style->hasPerspective())
                 return cssValuePool().createIdentifierValue(CSSValueNone);
             return zoomAdjustedPixelValue(style->perspective(), *style);
+        case CSSPropertyPerspectiveOrigin:
         case CSSPropertyWebkitPerspectiveOrigin: {
             RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
             if (renderer) {
@@ -2551,8 +2560,10 @@
         }
         case CSSPropertySpeak:
             return cssValuePool().createValue(style->speak());
+        case CSSPropertyTransform:
         case CSSPropertyWebkitTransform:
             return computedTransform(renderer, *style);
+        case CSSPropertyTransformOrigin:
         case CSSPropertyWebkitTransformOrigin: {
             RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
             if (renderer) {
@@ -2640,8 +2651,6 @@
             return cssValuePool().createValue(style->wrapFlow());
         case CSSPropertyShapeMargin:
             return cssValuePool().createValue(style->shapeMargin());
-        case CSSPropertyShapePadding:
-            return cssValuePool().createValue(style->shapePadding());
         case CSSPropertyShapeImageThreshold:
             return cssValuePool().createValue(style->shapeImageThreshold(), CSSPrimitiveValue::CSS_NUMBER);
         case CSSPropertyShapeOutside:
@@ -2764,13 +2773,6 @@
             ASSERT_NOT_REACHED();
             break;
 
-        // FIXME: crbug.com/154772 Unimplemented css-transforms properties
-        case CSSPropertyPerspective:
-        case CSSPropertyPerspectiveOrigin:
-        case CSSPropertyTransform:
-        case CSSPropertyTransformOrigin:
-            break;
-
         /* Unimplemented @font-face properties */
         case CSSPropertyFontStretch:
         case CSSPropertySrc:
diff --git a/Source/core/css/CSSGradientValue.h b/Source/core/css/CSSGradientValue.h
index c8ca0d7..4ba5d84 100644
--- a/Source/core/css/CSSGradientValue.h
+++ b/Source/core/css/CSSGradientValue.h
@@ -69,6 +69,22 @@
     void trace(Visitor*);
 };
 
+} // namespace WebCore
+
+
+// We have to declare the VectorTraits specialization before CSSGradientValue
+// declares its inline capacity vector below.
+namespace WTF {
+
+template <> struct VectorTraits<WebCore::CSSGradientColorStop> : VectorTraitsBase<WebCore::CSSGradientColorStop> {
+    static const bool canInitializeWithMemset = true;
+    static const bool canMoveWithMemcpy = true;
+};
+
+}
+
+namespace WebCore {
+
 class CSSGradientValue : public CSSImageGeneratorValue {
 public:
     PassRefPtr<Image> image(RenderObject*, const IntSize&);
diff --git a/Source/core/css/CSSGrammar.y b/Source/core/css/CSSGrammar.y
index 6b32b95..019aead 100644
--- a/Source/core/css/CSSGrammar.y
+++ b/Source/core/css/CSSGrammar.y
@@ -60,7 +60,7 @@
 
 %}
 
-%pure_parser
+%pure-parser
 
 %parse-param { BisonCSSParser* parser }
 %lex-param { BisonCSSParser* parser }
diff --git a/Source/core/css/CSSMatrix.cpp b/Source/core/css/CSSMatrix.cpp
index 6e11a82..303817a 100644
--- a/Source/core/css/CSSMatrix.cpp
+++ b/Source/core/css/CSSMatrix.cpp
@@ -57,6 +57,7 @@
     if (string.isEmpty())
         return;
 
+    // FIXME: crbug.com/154722 - should this continue to use legacy style parsing?
     RefPtrWillBeRawPtr<MutableStylePropertySet> styleDeclaration = MutableStylePropertySet::create();
     if (BisonCSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, HTMLStandardMode, 0)) {
         // Convert to TransformOperations. This can fail if a property
diff --git a/Source/core/css/CSSParserValues.h b/Source/core/css/CSSParserValues.h
index fbde0b7..1297446 100644
--- a/Source/core/css/CSSParserValues.h
+++ b/Source/core/css/CSSParserValues.h
@@ -191,6 +191,12 @@
         --m_current;
         return current();
     }
+    void setCurrentIndex(unsigned index)
+    {
+        ASSERT(index < m_values.size());
+        if (index < m_values.size())
+            m_current = index;
+    }
 
     CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
 
diff --git a/Source/core/css/CSSPrimitiveValueMappings.h b/Source/core/css/CSSPrimitiveValueMappings.h
index 352dad2..0fc39c2 100644
--- a/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/Source/core/css/CSSPrimitiveValueMappings.h
@@ -4706,11 +4706,11 @@
     return TouchActionDelayNone;
 }
 
-template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LayoutBox layoutBox)
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CSSBoxType cssBox)
     : CSSValue(PrimitiveClass)
 {
     m_primitiveUnitType = CSS_VALUE_ID;
-    switch (layoutBox) {
+    switch (cssBox) {
     case MarginBox:
         m_value.valueID = CSSValueMarginBox;
         break;
@@ -4729,7 +4729,7 @@
     }
 }
 
-template<> inline CSSPrimitiveValue::operator LayoutBox() const
+template<> inline CSSPrimitiveValue::operator CSSBoxType() const
 {
     switch (getValueID()) {
     case CSSValueMarginBox:
diff --git a/Source/core/css/CSSProperties.in b/Source/core/css/CSSProperties.in
index 7520750..55b9b91 100644
--- a/Source/core/css/CSSProperties.in
+++ b/Source/core/css/CSSProperties.in
@@ -110,7 +110,6 @@
 shape-image-threshold type_name=float
 shape-margin type_name=Length, converter=convertLength
 shape-outside type_name=ShapeValue*, custom_value
-shape-padding type_name=Length, converter=convertLength
 size custom_all
 speak
 table-layout
@@ -214,6 +213,7 @@
 -webkit-mask-repeat-x custom_all
 -webkit-mask-repeat-y custom_all
 -webkit-mask-size custom_all
+perspective-origin custom_all
 -webkit-perspective-origin custom_all
 -webkit-perspective-origin-x type_name=Length, converter=convertLength
 -webkit-perspective-origin-y type_name=Length, converter=convertLength
@@ -228,6 +228,7 @@
 -webkit-text-security
 -webkit-text-stroke-color custom_all
 text-underline-position custom_value
+transform-origin custom_all
 -webkit-transform-origin-x type_name=Length, converter=convertLength
 -webkit-transform-origin-y type_name=Length, converter=convertLength
 -webkit-transform-origin-z type_name=float, converter=convertComputedLength<float>
diff --git a/Source/core/css/CSSProperty.cpp b/Source/core/css/CSSProperty.cpp
index 338634c..e03ad3a 100644
--- a/Source/core/css/CSSProperty.cpp
+++ b/Source/core/css/CSSProperty.cpp
@@ -588,6 +588,7 @@
     case CSSPropertyGridColumn:
     case CSSPropertyGridColumnEnd:
     case CSSPropertyGridColumnStart:
+    case CSSPropertyGridTemplate:
     case CSSPropertyGridTemplateColumns:
     case CSSPropertyGridTemplateRows:
     case CSSPropertyGridRow:
@@ -663,7 +664,6 @@
     case CSSPropertyWebkitWrapFlow:
     case CSSPropertyShapeMargin:
     case CSSPropertyShapeImageThreshold:
-    case CSSPropertyShapePadding:
     case CSSPropertyShapeOutside:
     case CSSPropertyWebkitWrapThrough:
     case CSSPropertyWebkitAppRegion:
diff --git a/Source/core/css/CSSPropertyNames.in b/Source/core/css/CSSPropertyNames.in
index 8763716..c06f709 100644
--- a/Source/core/css/CSSPropertyNames.in
+++ b/Source/core/css/CSSPropertyNames.in
@@ -323,6 +323,7 @@
 grid-column
 grid-column-end
 grid-column-start
+grid-template
 grid-template-columns
 grid-template-rows
 grid-row
@@ -411,11 +412,9 @@
 -webkit-user-select
 -webkit-shape-outside alias_for=shape-outside
 -webkit-shape-margin alias_for=shape-margin
--webkit-shape-padding alias_for=shape-padding
 -webkit-shape-image-threshold alias_for=shape-image-threshold
 shape-outside
 shape-margin
-shape-padding
 shape-image-threshold
 -webkit-wrap-flow
 -webkit-wrap-through
diff --git a/Source/core/css/CSSPropertySourceData.cpp b/Source/core/css/CSSPropertySourceData.cpp
index 6a5ff1b..26bf1b6 100644
--- a/Source/core/css/CSSPropertySourceData.cpp
+++ b/Source/core/css/CSSPropertySourceData.cpp
@@ -30,10 +30,6 @@
 
 #include "config.h"
 
-#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
-#define CSSPROPERTYSOURCEDATA_HIDE_GLOBALS 1
-#endif
-
 #include "core/css/CSSPropertySourceData.h"
 
 #include "wtf/StaticConstructors.h"
@@ -114,17 +110,13 @@
     return StringHash::hash(name) + 3 * StringHash::hash(value) + 7 * important + 13 * parsedOk + 31;
 }
 
-// Global init routines
-DEFINE_GLOBAL(CSSPropertySourceData, emptyCSSPropertySourceData, "", "e", false, false)
-
-// static
-void CSSPropertySourceData::init()
+void CSSRuleSourceData::trace(Visitor* visitor)
 {
-    static bool initialized;
-    if (!initialized) {
-        new ((void *) &emptyCSSPropertySourceData) CSSPropertySourceData("", "e", false, false, false, SourceRange(0, 0));
-        initialized = true;
-    }
+    visitor->trace(ruleHeaderRange);
+    visitor->trace(ruleBodyRange);
+    visitor->trace(selectorRanges);
+    visitor->trace(styleSourceData);
+    visitor->trace(childRules);
 }
 
 } // namespace WebCore
diff --git a/Source/core/css/CSSPropertySourceData.h b/Source/core/css/CSSPropertySourceData.h
index b5d51e2..a4c1ca8 100644
--- a/Source/core/css/CSSPropertySourceData.h
+++ b/Source/core/css/CSSPropertySourceData.h
@@ -31,6 +31,7 @@
 #ifndef CSSPropertySourceData_h
 #define CSSPropertySourceData_h
 
+#include "heap/Handle.h"
 #include "wtf/Forward.h"
 #include "wtf/RefCounted.h"
 #include "wtf/Vector.h"
@@ -41,17 +42,21 @@
 class StyleRuleBase;
 
 struct SourceRange {
+    ALLOW_ONLY_INLINE_ALLOCATION();
+public:
     SourceRange();
     SourceRange(unsigned start, unsigned end);
     unsigned length() const;
 
+    void trace(Visitor*) { }
+
     unsigned start;
     unsigned end;
 };
 
 struct CSSPropertySourceData {
-    static void init();
-
+    ALLOW_ONLY_INLINE_ALLOCATION();
+public:
     CSSPropertySourceData(const String& name, const String& value, bool important, bool disabled, bool parsedOk, const SourceRange& range);
     CSSPropertySourceData(const CSSPropertySourceData& other);
     CSSPropertySourceData();
@@ -59,6 +64,8 @@
     String toString() const;
     unsigned hash() const;
 
+    void trace(Visitor* visitor) { visitor->trace(range); }
+
     String name;
     String value;
     bool important;
@@ -67,24 +74,22 @@
     SourceRange range;
 };
 
-#ifndef CSSPROPERTYSOURCEDATA_HIDE_GLOBALS
-extern const CSSPropertySourceData emptyCSSPropertySourceData;
-#endif
-
-struct CSSStyleSourceData : public RefCounted<CSSStyleSourceData> {
-    static PassRefPtr<CSSStyleSourceData> create()
+struct CSSStyleSourceData : public RefCountedWillBeGarbageCollected<CSSStyleSourceData> {
+    static PassRefPtrWillBeRawPtr<CSSStyleSourceData> create()
     {
-        return adoptRef(new CSSStyleSourceData());
+        return adoptRefWillBeNoop(new CSSStyleSourceData());
     }
 
-    Vector<CSSPropertySourceData> propertyData;
+    void trace(Visitor* visitor) { visitor->trace(propertyData); }
+
+    WillBeHeapVector<CSSPropertySourceData> propertyData;
 };
 
 struct CSSRuleSourceData;
-typedef Vector<RefPtr<CSSRuleSourceData> > RuleSourceDataList;
-typedef Vector<SourceRange> SelectorRangeList;
+typedef WillBeHeapVector<RefPtrWillBeMember<CSSRuleSourceData> > RuleSourceDataList;
+typedef WillBeHeapVector<SourceRange> SelectorRangeList;
 
-struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> {
+struct CSSRuleSourceData : public RefCountedWillBeGarbageCollected<CSSRuleSourceData> {
     enum Type {
         UNKNOWN_RULE,
         STYLE_RULE,
@@ -99,14 +104,14 @@
         FILTER_RULE
     };
 
-    static PassRefPtr<CSSRuleSourceData> create(Type type)
+    static PassRefPtrWillBeRawPtr<CSSRuleSourceData> create(Type type)
     {
-        return adoptRef(new CSSRuleSourceData(type));
+        return adoptRefWillBeNoop(new CSSRuleSourceData(type));
     }
 
-    static PassRefPtr<CSSRuleSourceData> createUnknown()
+    static PassRefPtrWillBeRawPtr<CSSRuleSourceData> createUnknown()
     {
-        return adoptRef(new CSSRuleSourceData(UNKNOWN_RULE));
+        return adoptRefWillBeNoop(new CSSRuleSourceData(UNKNOWN_RULE));
     }
 
     CSSRuleSourceData(Type type)
@@ -116,6 +121,8 @@
             styleSourceData = CSSStyleSourceData::create();
     }
 
+    void trace(Visitor*);
+
     Type type;
 
     // Range of the selector list in the enclosing source.
@@ -128,7 +135,7 @@
     SelectorRangeList selectorRanges;
 
     // Only for CSSStyleRules, CSSFontFaceRules, and CSSPageRules.
-    RefPtr<CSSStyleSourceData> styleSourceData;
+    RefPtrWillBeMember<CSSStyleSourceData> styleSourceData;
 
     // Only for CSSMediaRules.
     RuleSourceDataList childRules;
@@ -136,4 +143,18 @@
 
 } // namespace WebCore
 
+namespace WTF {
+
+template <> struct VectorTraits<WebCore::SourceRange> : VectorTraitsBase<WebCore::SourceRange> {
+    static const bool canInitializeWithMemset = true;
+    static const bool canMoveWithMemcpy = true;
+};
+
+template <> struct VectorTraits<WebCore::CSSPropertySourceData> : VectorTraitsBase<WebCore::CSSPropertySourceData> {
+    static const bool canInitializeWithMemset = true;
+    static const bool canMoveWithMemcpy = true;
+};
+
+}
+
 #endif // CSSPropertySourceData_h
diff --git a/Source/core/css/CSSSelector.cpp b/Source/core/css/CSSSelector.cpp
index cddc68b..94238d4 100644
--- a/Source/core/css/CSSSelector.cpp
+++ b/Source/core/css/CSSSelector.cpp
@@ -397,6 +397,8 @@
     if (tagHistory()) {
         printf("\n%*s--> (relation == %d)\n", indent, "", relation());
         tagHistory()->show(indent + 2);
+    } else {
+        printf("\n%*s--> (relation == %d)\n", indent, "", relation());
     }
 }
 
diff --git a/Source/core/css/CSSSelector.h b/Source/core/css/CSSSelector.h
index 00e1551..d9c9933 100644
--- a/Source/core/css/CSSSelector.h
+++ b/Source/core/css/CSSSelector.h
@@ -288,7 +288,7 @@
         bool isShadowPseudoElement() const;
         bool isHostPseudoClass() const;
 
-        // FIXME: selectors with no tagHistory() get a relation() of Descendant. It should instead be
+        // FIXME: selectors with no tagHistory() get a relation() of Descendant (and sometimes even SubSelector). It should instead be
         // None.
         Relation relation() const { return static_cast<Relation>(m_relation); }
 
diff --git a/Source/core/css/CSSShorthands.in b/Source/core/css/CSSShorthands.in
index f66d649..22d246e 100644
--- a/Source/core/css/CSSShorthands.in
+++ b/Source/core/css/CSSShorthands.in
@@ -21,6 +21,7 @@
 flex longhands=flex-grow;flex-shrink;flex-basis
 flex-flow longhands=flex-direction;flex-wrap
 font longhands=font-family;font-size;font-style;font-variant;font-weight;line-height
+grid-template longhands=grid-template-columns;grid-template-rows;grid-template-areas
 grid-area longhands=grid-row-start;grid-column-start;grid-row-end;grid-column-end
 grid-column longhands=grid-column-start;grid-column-end
 grid-row longhands=grid-row-start;grid-row-end
diff --git a/Source/core/css/CSSTokenizer-in.cpp b/Source/core/css/CSSTokenizer-in.cpp
index 69197eb..dec709f 100644
--- a/Source/core/css/CSSTokenizer-in.cpp
+++ b/Source/core/css/CSSTokenizer-in.cpp
@@ -304,14 +304,17 @@
     return m_currentCharacter16;
 }
 
-UChar*& CSSTokenizer::currentCharacter16()
+UChar* CSSTokenizer::allocateStringBuffer16(size_t len)
 {
-    if (!m_currentCharacter16) {
-        m_dataStart16 = adoptArrayPtr(new UChar[m_length]);
-        m_currentCharacter16 = m_dataStart16.get();
-    }
+    // Allocates and returns a CSSTokenizer owned buffer for storing
+    // UTF-16 data. Used to get a suitable life span for UTF-16
+    // strings, identifiers and URIs created by the tokenizer.
+    OwnPtr<UChar[]> buffer = adoptArrayPtr(new UChar[len]);
 
-    return m_currentCharacter16;
+    UChar* bufferPtr = buffer.get();
+
+    m_cssStrings16.append(buffer.release());
+    return bufferPtr;
 }
 
 template <>
@@ -412,7 +415,7 @@
         return unicode;
     }
 
-    return *currentCharacter<CharacterType>()++;
+    return *src++;
 }
 
 template <>
@@ -438,6 +441,24 @@
     ++result;
 }
 
+template <typename SrcCharacterType>
+size_t CSSTokenizer::peekMaxIdentifierLen(SrcCharacterType* src)
+{
+    // The decoded form of an identifier (after resolving escape
+    // sequences) will not contain more characters (ASCII or UTF-16
+    // codepoints) than the input. This code can therefore ignore
+    // escape sequences completely.
+    SrcCharacterType* start = src;
+    do {
+        if (LIKELY(*src != '\\'))
+            src++;
+        else
+            parseEscape<SrcCharacterType>(src);
+    } while (isCSSLetter(src[0]) || (src[0] == '\\' && isCSSEscape(src[1])));
+
+    return src - start;
+}
+
 template <typename SrcCharacterType, typename DestCharacterType>
 inline bool CSSTokenizer::parseIdentifierInternal(SrcCharacterType*& src, DestCharacterType*& result, bool& hasEscape)
 {
@@ -471,7 +492,7 @@
     if (UNLIKELY(!parseIdentifierInternal(currentCharacter<CharacterType>(), result, hasEscape))) {
         // Found an escape we couldn't handle with 8 bits, copy what has been recognized and continue
         ASSERT(is8BitSource());
-        UChar*& result16 = currentCharacter16();
+        UChar* result16 = allocateStringBuffer16((result - start) + peekMaxIdentifierLen(currentCharacter<CharacterType>()));
         UChar* start16 = result16;
         int i = 0;
         for (; i < result - start; i++)
@@ -489,6 +510,18 @@
     resultString.init(start, result - start);
 }
 
+template <typename SrcCharacterType>
+size_t CSSTokenizer::peekMaxStringLen(SrcCharacterType* src, UChar quote)
+{
+    // The decoded form of a CSS string (after resolving escape
+    // sequences) will not contain more characters (ASCII or UTF-16
+    // codepoints) than the input. This code can therefore ignore
+    // escape sequences completely and just return the length of the
+    // input string (possibly including terminating quote if any).
+    SrcCharacterType* end = checkAndSkipString(src, quote);
+    return end ? end - src : 0;
+}
+
 template <typename SrcCharacterType, typename DestCharacterType>
 inline bool CSSTokenizer::parseStringInternal(SrcCharacterType*& src, DestCharacterType*& result, UChar quote)
 {
@@ -532,7 +565,7 @@
     if (UNLIKELY(!parseStringInternal(currentCharacter<CharacterType>(), result, quote))) {
         // Found an escape we couldn't handle with 8 bits, copy what has been recognized and continue
         ASSERT(is8BitSource());
-        UChar*& result16 = currentCharacter16();
+        UChar* result16 = allocateStringBuffer16((result - start) + peekMaxStringLen(currentCharacter<CharacterType>(), quote));
         UChar* start16 = result16;
         int i = 0;
         for (; i < result - start; i++)
@@ -580,6 +613,29 @@
     return true;
 }
 
+template <typename SrcCharacterType>
+inline size_t CSSTokenizer::peekMaxURILen(SrcCharacterType* src, UChar quote)
+{
+    // The decoded form of a URI (after resolving escape sequences)
+    // will not contain more characters (ASCII or UTF-16 codepoints)
+    // than the input. This code can therefore ignore escape sequences
+    // completely.
+    SrcCharacterType* start = src;
+    if (quote) {
+        ASSERT(quote == '"' || quote == '\'');
+        return peekMaxStringLen(src, quote);
+    }
+
+    while (isURILetter(*src)) {
+        if (LIKELY(*src != '\\'))
+            src++;
+        else
+            parseEscape<SrcCharacterType>(src);
+    }
+
+    return src - start;
+}
+
 template <typename SrcCharacterType, typename DestCharacterType>
 inline bool CSSTokenizer::parseURIInternal(SrcCharacterType*& src, DestCharacterType*& dest, UChar quote)
 {
@@ -593,7 +649,7 @@
             *dest++ = *src++;
         } else {
             unsigned unicode = parseEscape<SrcCharacterType>(src);
-            if (unicode > 0xff && sizeof(SrcCharacterType) == 1)
+            if (unicode > 0xff && sizeof(DestCharacterType) == 1)
                 return false;
             UnicodeToChars(dest, unicode);
         }
@@ -619,11 +675,12 @@
         // Reset the current character to the start of the URI and re-parse with
         // a 16-bit destination.
         ASSERT(is8BitSource());
-        UChar* uriStart16 = currentCharacter16();
         currentCharacter<CharacterType>() = uriStart;
-        bool result = parseURIInternal(currentCharacter<CharacterType>(), currentCharacter16(), quote);
+        UChar* result16 = allocateStringBuffer16(peekMaxURILen(currentCharacter<CharacterType>(), quote));
+        UChar* uriStart16 = result16;
+        bool result = parseURIInternal(currentCharacter<CharacterType>(), result16, quote);
         ASSERT_UNUSED(result, result);
-        string.init(uriStart16, currentCharacter16() - uriStart16);
+        string.init(uriStart16, result16 - uriStart16);
     }
 
     currentCharacter<CharacterType>() = uriEnd + 1;
diff --git a/Source/core/css/CSSTokenizer.h b/Source/core/css/CSSTokenizer.h
index 5d8fae1..508bf71 100644
--- a/Source/core/css/CSSTokenizer.h
+++ b/Source/core/css/CSSTokenizer.h
@@ -74,7 +74,7 @@
     inline unsigned tokenStartOffset();
 
 private:
-    UChar*& currentCharacter16();
+    UChar* allocateStringBuffer16(size_t len);
 
     template <typename CharacterType>
     inline CharacterType*& currentCharacter();
@@ -92,29 +92,33 @@
     inline CSSParserLocation tokenLocation();
 
     template <typename CharacterType>
-    unsigned parseEscape(CharacterType*&);
+    static unsigned parseEscape(CharacterType*&);
     template <typename DestCharacterType>
-    inline void UnicodeToChars(DestCharacterType*&, unsigned);
-    template <typename SrcCharacterType, typename DestCharacterType>
-    inline bool parseIdentifierInternal(SrcCharacterType*&, DestCharacterType*&, bool&);
+    static inline void UnicodeToChars(DestCharacterType*&, unsigned);
 
+    template <typename SrcCharacterType, typename DestCharacterType>
+    static inline bool parseIdentifierInternal(SrcCharacterType*&, DestCharacterType*&, bool&);
+    template <typename SrcCharacterType>
+    static size_t peekMaxIdentifierLen(SrcCharacterType*);
     template <typename CharacterType>
     inline void parseIdentifier(CharacterType*&, CSSParserString&, bool&);
 
+    template <typename SrcCharacterType>
+    static size_t peekMaxStringLen(SrcCharacterType*, UChar quote);
     template <typename SrcCharacterType, typename DestCharacterType>
-    inline bool parseStringInternal(SrcCharacterType*&, DestCharacterType*&, UChar);
-
+    static inline bool parseStringInternal(SrcCharacterType*&, DestCharacterType*&, UChar);
     template <typename CharacterType>
     inline void parseString(CharacterType*&, CSSParserString& resultString, UChar);
 
     template <typename CharacterType>
     inline bool findURI(CharacterType*& start, CharacterType*& end, UChar& quote);
-
+    template <typename SrcCharacterType>
+    static size_t peekMaxURILen(SrcCharacterType*, UChar quote);
     template <typename SrcCharacterType, typename DestCharacterType>
-    inline bool parseURIInternal(SrcCharacterType*&, DestCharacterType*&, UChar quote);
-
+    static inline bool parseURIInternal(SrcCharacterType*&, DestCharacterType*&, UChar quote);
     template <typename CharacterType>
     inline void parseURI(CSSParserString&);
+
     template <typename CharacterType>
     inline bool parseUnicodeRange();
     template <typename CharacterType>
@@ -155,6 +159,13 @@
     OwnPtr<UChar[]> m_dataStart16;
     LChar* m_currentCharacter8;
     UChar* m_currentCharacter16;
+
+    // During parsing of an ASCII stylesheet we might locate escape
+    // sequences that expand into UTF-16 code points. Strings,
+    // identifiers and URIs containing such escape sequences are
+    // stored in m_cssStrings16 so that we don't have to store the
+    // whole stylesheet as UTF-16.
+    Vector<OwnPtr<UChar[]> > m_cssStrings16;
     union {
         LChar* ptr8;
         UChar* ptr16;
diff --git a/Source/core/css/MediaList.cpp b/Source/core/css/MediaList.cpp
index 8f27f81..8fc86c2 100644
--- a/Source/core/css/MediaList.cpp
+++ b/Source/core/css/MediaList.cpp
@@ -71,8 +71,16 @@
     if (mediaString.isEmpty())
         return MediaQuerySet::create();
 
-    return MediaQueryParser::parse(mediaString);
+    BisonCSSParser parser(strictCSSParserContext());
+    return parser.parseMediaQueryList(mediaString);
+}
 
+PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQuerySet::createOffMainThread(const String& mediaString)
+{
+    if (mediaString.isEmpty())
+        return MediaQuerySet::create();
+
+    return MediaQueryParser::parse(mediaString);
 }
 
 bool MediaQuerySet::set(const String& mediaString)
diff --git a/Source/core/css/MediaList.h b/Source/core/css/MediaList.h
index 108448e..15e69d6 100644
--- a/Source/core/css/MediaList.h
+++ b/Source/core/css/MediaList.h
@@ -46,6 +46,7 @@
         return adoptRefWillBeNoop(new MediaQuerySet());
     }
     static PassRefPtrWillBeRawPtr<MediaQuerySet> create(const String& mediaString);
+    static PassRefPtrWillBeRawPtr<MediaQuerySet> createOffMainThread(const String& mediaString);
 
     bool set(const String&);
     bool add(const String&);
diff --git a/Source/core/css/MediaQueryList.cpp b/Source/core/css/MediaQueryList.cpp
index 4ada713..d76b5bb 100644
--- a/Source/core/css/MediaQueryList.cpp
+++ b/Source/core/css/MediaQueryList.cpp
@@ -64,11 +64,11 @@
     m_matcher->removeListener(listener.get(), this);
 }
 
-void MediaQueryList::evaluate(MediaQueryEvaluator* evaluator, bool& notificationNeeded)
+bool MediaQueryList::evaluate(MediaQueryEvaluator* evaluator)
 {
     if (m_evaluationRound != m_matcher->evaluationRound() && evaluator)
         setMatches(evaluator->eval(m_media.get()));
-    notificationNeeded = m_changeRound == m_matcher->evaluationRound();
+    return m_changeRound == m_matcher->evaluationRound();
 }
 
 void MediaQueryList::setMatches(bool newValue)
diff --git a/Source/core/css/MediaQueryList.h b/Source/core/css/MediaQueryList.h
index f4af596..e832f29 100644
--- a/Source/core/css/MediaQueryList.h
+++ b/Source/core/css/MediaQueryList.h
@@ -47,7 +47,7 @@
     void addListener(PassRefPtrWillBeRawPtr<MediaQueryListListener>);
     void removeListener(PassRefPtrWillBeRawPtr<MediaQueryListListener>);
 
-    void evaluate(MediaQueryEvaluator*, bool& notificationNeeded);
+    bool evaluate(MediaQueryEvaluator*);
 
     void trace(Visitor*);
 
diff --git a/Source/core/css/MediaQueryMatcher.cpp b/Source/core/css/MediaQueryMatcher.cpp
index 4efffd2..bc1f47c 100644
--- a/Source/core/css/MediaQueryMatcher.cpp
+++ b/Source/core/css/MediaQueryMatcher.cpp
@@ -39,9 +39,7 @@
 
 void MediaQueryMatcher::Listener::evaluate(ScriptState* state, MediaQueryEvaluator* evaluator)
 {
-    bool notify;
-    m_query->evaluate(evaluator, notify);
-    if (notify)
+    if (m_query->evaluate(evaluator))
         m_listener->queryChanged(state, m_query.get());
 }
 
diff --git a/Source/core/css/MediaQuerySetTest.cpp b/Source/core/css/MediaQuerySetTest.cpp
index ef8178c..920e265 100644
--- a/Source/core/css/MediaQuerySetTest.cpp
+++ b/Source/core/css/MediaQuerySetTest.cpp
@@ -16,106 +16,147 @@
 typedef struct {
     const char* input;
     const char* output;
+    bool shouldWorkOnOldParser;
 } TestCase;
 
+static void testMediaQuery(TestCase test, MediaQuerySet& querySet, bool oldParser)
+{
+    StringBuilder output;
+    size_t j = 0;
+    while (j < querySet.queryVector().size()) {
+        String queryText = querySet.queryVector()[j]->cssText();
+        output.append(queryText);
+        ++j;
+        if (j >= querySet.queryVector().size())
+            break;
+        output.append(", ");
+    }
+    if (!oldParser || test.shouldWorkOnOldParser) {
+        if (test.output)
+            ASSERT_STREQ(test.output, output.toString().ascii().data());
+        else
+            ASSERT_STREQ(test.input, output.toString().ascii().data());
+    }
+}
+
 TEST(MediaQueryParserTest, Basic)
 {
     // The first string represents the input string.
     // The second string represents the output string, if present.
     // Otherwise, the output string is identical to the first string.
     TestCase testCases[] = {
-        {"screen", 0},
-        {"screen and (color)", 0},
-        {"all and (min-width:500px)", "(min-width: 500px)"},
-        {"all and (min-width:/*bla*/500px)", "(min-width: 500px)"},
-        {"(min-width:500px)", "(min-width: 500px)"},
-        {"screen and (color), projection and (color)", 0},
-        {"not screen and (color)", 0},
-        {"only screen and (color)", 0},
-        {"screen and (color), projection and (color)", 0},
-        {"aural and (device-aspect-ratio: 16/9)", 0},
-        {"speech and (min-device-width: 800px)", 0},
-        {"example", 0},
-        {"screen and (max-weight: 3kg) and (color), (monochrome)", "not all, (monochrome)"},
-        {"(min-width: -100px)", "not all"},
-        {"(example, all,), speech", "not all, speech"},
-        {"&test, screen", "not all, screen"},
-        {"print and (min-width: 25cm)", 0},
-        {"screen and (min-width: 400px) and (max-width: 700px)", "screen and (max-width: 700px) and (min-width: 400px)"},
-        {"screen and (device-width: 800px)", 0},
-        {"screen and (device-height: 60em)", 0},
-        {"screen and (device-aspect-ratio: 16/9)", 0},
-        {"(device-aspect-ratio: 16.0/9.0)", "not all"},
-        {"(device-aspect-ratio: 16/ 9)", "(device-aspect-ratio: 16/9)"},
-        {"(device-aspect-ratio: 16/\r9)", "(device-aspect-ratio: 16/9)"},
-        {"all and (color)", "(color)"},
-        {"all and (min-color: 1)", "(min-color: 1)"},
-        {"all and (min-color: 1.0)", "not all"},
-        {"all and (min-color: 2)", "(min-color: 2)"},
-        {"all and (color-index)", "(color-index)"},
-        {"all and (min-color-index: 1)", "(min-color-index: 1)"},
-        {"all and (monochrome)", "(monochrome)"},
-        {"all and (min-monochrome: 1)", "(min-monochrome: 1)"},
-        {"all and (min-monochrome: 2)", "(min-monochrome: 2)"},
-        {"print and (monochrome)", 0},
-        {"handheld and (grid) and (max-width: 15em)", 0},
-        {"handheld and (grid) and (max-device-height: 7em)", 0},
-        {"screen and (max-width: 50%)", "not all"},
-        {"screen and (max-WIDTH: 500px)", "screen and (max-width: 500px)"},
-        {"screen and (max-width: 24.4em)", 0},
-        {"screen and (max-width: 24.4EM)", "screen and (max-width: 24.4em)"},
-        {"screen and (max-width: blabla)", "not all"},
-        {"screen and (max-width: 1)", "not all"},
-        {"screen and (max-width: 0)", 0},
-        {"screen and (max-width: 1deg)", "not all"},
-        {"handheld and (min-width: 20em), \nscreen and (min-width: 20em)", "handheld and (min-width: 20em), screen and (min-width: 20em)"},
-        {"print and (min-resolution: 300dpi)", 0},
-        {"print and (min-resolution: 118dpcm)", 0},
-        {"(resolution: 0.83333333333333333333dppx)", "(resolution: 0.8333333333333334dppx)"},
-        {"(resolution: 2.4dppx)", 0},
-        {"all and(color)", "not all"},
-        {"all and (", "not all"},
-        {"test;,all", "not all, all"},
-        {"(color:20example)", "not all"},
-        {"not braille", 0},
-        {",screen", "not all, screen"},
-        {",all", "not all, all"},
-        {",,all,,", "not all, not all, all, not all, not all"},
-        {",,all,, ", "not all, not all, all, not all, not all"},
-        {",screen,,&invalid,,", "not all, screen, not all, not all, not all, not all"},
-        {",screen,,(invalid,),,", "not all, screen, not all, not all, not all, not all"},
-        {",(all,),,", "not all, not all, not all, not all"},
-        {",", "not all, not all"},
-        {"  ", ""},
-        {"(color", "(color)"},
-        {"(min-color: 2", "(min-color: 2)"},
-        {"(orientation: portrait)", 0},
-        {"tv and (scan: progressive)", 0},
-        {"(pointer: coarse)", 0},
-        {"(min-orientation:portrait)", "not all"},
-        {"all and (orientation:portrait)", "(orientation: portrait)"},
-        {"all and (orientation:landscape)", "(orientation: landscape)"},
+        {"screen", 0, true},
+        {"screen and (color)", 0, true},
+        {"all and (min-width:500px)", "(min-width: 500px)", true},
+        {"all and (min-width:/*bla*/500px)", "(min-width: 500px)", true},
+        {"(min-width:500px)", "(min-width: 500px)", true},
+        {"screen and (color), projection and (color)", 0, true},
+        {"not screen and (color)", 0, true},
+        {"only screen and (color)", 0, true},
+        {"screen and (color), projection and (color)", 0, true},
+        {"aural and (device-aspect-ratio: 16/9)", 0, true},
+        {"speech and (min-device-width: 800px)", 0, true},
+        {"example", 0, true},
+        {"screen and (max-weight: 3kg) and (color), (monochrome)", "not all, (monochrome)", true},
+        {"(min-width: -100px)", "not all", true},
+        {"(example, all,), speech", "not all, speech", true},
+        {"&test, screen", "not all, screen", true},
+        {"print and (min-width: 25cm)", 0, true},
+        {"screen and (min-width: 400px) and (max-width: 700px)", "screen and (max-width: 700px) and (min-width: 400px)", true},
+        {"screen and (device-width: 800px)", 0, true},
+        {"screen and (device-height: 60em)", 0, true},
+        {"screen and (device-aspect-ratio: 16/9)", 0, true},
+        {"(device-aspect-ratio: 16.0/9.0)", "not all", true},
+        {"(device-aspect-ratio: 16/ 9)", "(device-aspect-ratio: 16/9)", true},
+        {"(device-aspect-ratio: 16/\r9)", "(device-aspect-ratio: 16/9)", true},
+        {"all and (color)", "(color)", true},
+        {"all and (min-color: 1)", "(min-color: 1)", true},
+        {"all and (min-color: 1.0)", "not all", true},
+        {"all and (min-color: 2)", "(min-color: 2)", true},
+        {"all and (color-index)", "(color-index)", true},
+        {"all and (min-color-index: 1)", "(min-color-index: 1)", true},
+        {"all and (monochrome)", "(monochrome)", true},
+        {"all and (min-monochrome: 1)", "(min-monochrome: 1)", true},
+        {"all and (min-monochrome: 2)", "(min-monochrome: 2)", true},
+        {"print and (monochrome)", 0, true},
+        {"handheld and (grid) and (max-width: 15em)", 0, true},
+        {"handheld and (grid) and (max-device-height: 7em)", 0, true},
+        {"screen and (max-width: 50%)", "not all", true},
+        {"screen and (max-WIDTH: 500px)", "screen and (max-width: 500px)", true},
+        {"screen and (max-width: 24.4em)", 0, true},
+        {"screen and (max-width: 24.4EM)", "screen and (max-width: 24.4em)", true},
+        {"screen and (max-width: blabla)", "not all", true},
+        {"screen and (max-width: 1)", "not all", true},
+        {"screen and (max-width: 0)", 0, true},
+        {"screen and (max-width: 1deg)", "not all", true},
+        {"handheld and (min-width: 20em), \nscreen and (min-width: 20em)", "handheld and (min-width: 20em), screen and (min-width: 20em)", true},
+        {"print and (min-resolution: 300dpi)", 0, true},
+        {"print and (min-resolution: 118dpcm)", 0, true},
+        {"(resolution: 0.83333333333333333333dppx)", "(resolution: 0.8333333333333334dppx)", true},
+        {"(resolution: 2.4dppx)", 0, true},
+        {"all and(color)", "not all", true},
+        {"all and (", "not all", true},
+        {"test;,all", "not all, all", true},
+        {"(color:20example)", "not all", false},
+        {"not braille", 0, true},
+        {",screen", "not all, screen", true},
+        {",all", "not all, all", true},
+        {",,all,,", "not all, not all, all, not all, not all", true},
+        {",,all,, ", "not all, not all, all, not all, not all", true},
+        {",screen,,&invalid,,", "not all, screen, not all, not all, not all, not all", true},
+        {",screen,,(invalid,),,", "not all, screen, not all, not all, not all, not all", true},
+        {",(all,),,", "not all, not all, not all, not all", true},
+        {",", "not all, not all", true},
+        {"  ", "", true},
+        {"(color", "(color)", true},
+        {"(min-color: 2", "(min-color: 2)", true},
+        {"(orientation: portrait)", 0, true},
+        {"tv and (scan: progressive)", 0, true},
+        {"(pointer: coarse)", 0, true},
+        {"(min-orientation:portrait)", "not all", true},
+        {"all and (orientation:portrait)", "(orientation: portrait)", true},
+        {"all and (orientation:landscape)", "(orientation: landscape)", true},
         {"NOT braille, tv AND (max-width: 200px) and (min-WIDTH: 100px) and (orientation: landscape), (color)",
-            "not braille, tv and (max-width: 200px) and (min-width: 100px) and (orientation: landscape), (color)"},
+            "not braille, tv and (max-width: 200px) and (min-width: 100px) and (orientation: landscape), (color)", true},
+        {"(m\\61x-width: 300px)", "(max-width: 300px)", true},
+        {"(max-width: 400\\70\\78)", "(max-width: 400px)", false},
+        {"(max-width: 500\\0070\\0078)", "(max-width: 500px)", false},
+        {"(max-width: 600\\000070\\000078)", "(max-width: 600px)", false},
+        {"(max-width: 700px), (max-width: 700px)", "(max-width: 700px), (max-width: 700px)", true},
+        {"(max-width: 800px()), (max-width: 800px)", "not all, (max-width: 800px)", true},
+        {"(max-width: 900px(()), (max-width: 900px)", "not all", true},
+        {"(max-width: 600px(())))), (max-width: 600px)", "not all, (max-width: 600px)", true},
+        {"(max-width: 500px(((((((((())))), (max-width: 500px)", "not all", true},
+        {"(max-width: 800px[]), (max-width: 800px)", "not all, (max-width: 800px)", true},
+        {"(max-width: 900px[[]), (max-width: 900px)", "not all", true},
+        {"(max-width: 600px[[]]]]), (max-width: 600px)", "not all, (max-width: 600px)", true},
+        {"(max-width: 500px[[[[[[[[[[]]]]), (max-width: 500px)", "not all", true},
+        {"(max-width: 800px{}), (max-width: 800px)", "not all, (max-width: 800px)", true},
+        {"(max-width: 900px{{}), (max-width: 900px)", "not all", true},
+        {"(max-width: 600px{{}}}}), (max-width: 600px)", "not all, (max-width: 600px)", true},
+        {"(max-width: 500px{{{{{{{{{{}}}}), (max-width: 500px)", "not all", true},
+        {"[(), (max-width: 400px)", "not all", true},
+        {"[{}, (max-width: 500px)", "not all", true},
+        {"[{]}], (max-width: 900px)", "not all, (max-width: 900px)", true},
+        {"[{[]{}{{{}}}}], (max-width: 900px)", "not all, (max-width: 900px)", true},
+        {"[{[}], (max-width: 900px)", "not all", true},
+        {"[({)}], (max-width: 900px)", "not all", true},
+        {"[]((), (max-width: 900px)", "not all", true},
+        {"((), (max-width: 900px)", "not all", true},
+        {"(foo(), (max-width: 900px)", "not all", true},
+        {"[](()), (max-width: 900px)", "not all, (max-width: 900px)", true},
+        {"all an[isdfs bla())()]icalc(i)(()), (max-width: 400px)", "not all, (max-width: 400px)", true},
+        {"all an[isdfs bla())(]icalc(i)(()), (max-width: 500px)", "not all", true},
+        {"all an[isdfs bla())(]icalc(i)(())), (max-width: 600px)", "not all", true},
+        {"all an[isdfs bla())(]icalc(i)(()))], (max-width: 800px)", "not all, (max-width: 800px)", true},
         {0, 0} // Do not remove the terminator line.
     };
 
     for (unsigned i = 0; testCases[i].input; ++i) {
-        RefPtrWillBeRawPtr<MediaQuerySet> querySet = MediaQuerySet::create(testCases[i].input);
-        StringBuilder output;
-        size_t j = 0;
-        while (j < querySet->queryVector().size()) {
-            String queryText = querySet->queryVector()[j]->cssText();
-            output.append(queryText);
-            ++j;
-            if (j >= querySet->queryVector().size())
-                break;
-            output.append(", ");
-        }
-        if (testCases[i].output)
-            ASSERT_STREQ(testCases[i].output, output.toString().ascii().data());
-        else
-            ASSERT_STREQ(testCases[i].input, output.toString().ascii().data());
+        RefPtrWillBeRawPtr<MediaQuerySet> oldParserQuerySet = MediaQuerySet::create(testCases[i].input);
+        RefPtrWillBeRawPtr<MediaQuerySet> threadSafeQuerySet = MediaQuerySet::createOffMainThread(testCases[i].input);
+        testMediaQuery(testCases[i], *oldParserQuerySet, true);
+        testMediaQuery(testCases[i], *threadSafeQuerySet, false);
     }
 }
 
diff --git a/Source/core/css/RuleFeature.cpp b/Source/core/css/RuleFeature.cpp
index f8ce8dd..7b793eb 100644
--- a/Source/core/css/RuleFeature.cpp
+++ b/Source/core/css/RuleFeature.cpp
@@ -54,7 +54,7 @@
         case CSSSelector::PseudoShadow:
             return true;
         default:
-            return false;
+            return selector.isCustomPseudoElement();
         }
     }
     if (selector.m_match != CSSSelector::PseudoClass)
@@ -103,23 +103,23 @@
 }
 
 // This method is somewhat conservative in what it accepts.
-RuleFeatureSet::InvalidationSetMode RuleFeatureSet::supportsClassDescendantInvalidation(const CSSSelector& selector)
+RuleFeatureSet::InvalidationSetMode RuleFeatureSet::invalidationSetModeForSelector(const CSSSelector& selector)
 {
     bool foundDescendantRelation = false;
     bool foundIdent = false;
     for (const CSSSelector* component = &selector; component; component = component->tagHistory()) {
 
         // FIXME: next up: Tag and Id.
-        if (component->m_match == CSSSelector::Class || component->isAttributeSelector()) {
+        if (component->m_match == CSSSelector::Class || component->isAttributeSelector() || component->isCustomPseudoElement()) {
             if (!foundDescendantRelation)
                 foundIdent = true;
         } else if (component->pseudoType() == CSSSelector::PseudoHost || component->pseudoType() == CSSSelector::PseudoAny) {
             if (const CSSSelectorList* selectorList = component->selectorList()) {
                 for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) {
-                    InvalidationSetMode hostMode = supportsClassDescendantInvalidation(*selector);
+                    InvalidationSetMode hostMode = invalidationSetModeForSelector(*selector);
                     if (hostMode == UseSubtreeStyleChange)
                         return foundDescendantRelation ? UseLocalStyleChange : UseSubtreeStyleChange;
-                    if (hostMode == AddFeatures)
+                    if (!foundDescendantRelation && hostMode == AddFeatures)
                         foundIdent = true;
                 }
             }
@@ -152,6 +152,8 @@
         features.classes.append(selector.value());
     else if (selector.isAttributeSelector())
         features.attributes.append(selector.attribute().localName());
+    else if (selector.isCustomPseudoElement())
+        features.customPseudoElement = true;
 }
 
 RuleFeatureSet::RuleFeatureSet()
@@ -170,7 +172,7 @@
 
 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector)
 {
-    InvalidationSetMode mode = supportsClassDescendantInvalidation(selector);
+    InvalidationSetMode mode = invalidationSetModeForSelector(selector);
     if (mode != AddFeatures)
         return mode;
 
@@ -216,6 +218,8 @@
                 invalidationSet->addClass(*it);
             for (Vector<AtomicString>::const_iterator it = features.attributes.begin(); it != features.attributes.end(); ++it)
                 invalidationSet->addAttribute(*it);
+            if (features.customPseudoElement)
+                invalidationSet->setCustomPseudoInvalid();
         } else if (current->pseudoType() == CSSSelector::PseudoHost || current->pseudoType() == CSSSelector::PseudoAny) {
             if (const CSSSelectorList* selectorList = current->selectorList()) {
                 for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector))
@@ -348,10 +352,10 @@
     m_metadata.clear();
     m_classInvalidationSets.clear();
     m_attributeInvalidationSets.clear();
-    m_pendingInvalidationMap.clear();
+    m_styleInvalidator.clearPendingInvalidations();
 }
 
-void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element* element)
+void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element& element)
 {
     unsigned changedSize = changedClasses.size();
     for (unsigned i = 0; i < changedSize; ++i) {
@@ -359,7 +363,7 @@
     }
 }
 
-void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element* element)
+void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element& element)
 {
     if (!oldClasses.size())
         scheduleStyleInvalidationForClassChange(newClasses, element);
@@ -392,41 +396,21 @@
     }
 }
 
-void RuleFeatureSet::scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element* element)
+void RuleFeatureSet::scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element& element)
 {
-    if (RefPtr<DescendantInvalidationSet> invalidationSet = m_attributeInvalidationSets.get(attributeName.localName())) {
-        ensurePendingInvalidationList(element).append(invalidationSet);
-        element->setNeedsStyleInvalidation();
-    }
+    if (RefPtr<DescendantInvalidationSet> invalidationSet = m_attributeInvalidationSets.get(attributeName.localName()))
+        m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
 }
 
-void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, Element* element)
+void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, Element& element)
 {
-    if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationSets.get(className)) {
-        ensurePendingInvalidationList(element).append(invalidationSet);
-        element->setNeedsStyleInvalidation();
-    }
+    if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationSets.get(className))
+        m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
 }
 
-RuleFeatureSet::InvalidationList& RuleFeatureSet::ensurePendingInvalidationList(Element* element)
+StyleInvalidator& RuleFeatureSet::styleInvalidator()
 {
-    PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(element, nullptr);
-    if (addResult.isNewEntry)
-        addResult.storedValue->value = adoptPtr(new InvalidationList);
-    return *addResult.storedValue->value;
-}
-
-void RuleFeatureSet::clearStyleInvalidation(Node* node)
-{
-    node->clearChildNeedsStyleInvalidation();
-    node->clearNeedsStyleInvalidation();
-    if (node->isElementNode())
-        m_pendingInvalidationMap.remove(toElement(node));
-}
-
-RuleFeatureSet::PendingInvalidationMap& RuleFeatureSet::pendingInvalidationMap()
-{
-    return m_pendingInvalidationMap;
+    return m_styleInvalidator;
 }
 
 } // namespace WebCore
diff --git a/Source/core/css/RuleFeature.h b/Source/core/css/RuleFeature.h
index 2e6a9b7..6103e22 100644
--- a/Source/core/css/RuleFeature.h
+++ b/Source/core/css/RuleFeature.h
@@ -23,6 +23,7 @@
 #define RuleFeature_h
 
 #include "core/css/invalidation/DescendantInvalidationSet.h"
+#include "core/css/invalidation/StyleInvalidator.h"
 #include "wtf/Forward.h"
 #include "wtf/HashSet.h"
 #include "wtf/text/AtomicStringHash.h"
@@ -84,13 +85,10 @@
         return m_metadata.idsInRules.contains(idValue);
     }
 
-    void scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element*);
-    void scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element*);
+    void scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element&);
+    void scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element&);
 
-    void scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element*);
-
-    // Clears all style invalidation state for the passed node.
-    void clearStyleInvalidation(Node*);
+    void scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element&);
 
     int hasIdsInSelectors() const
     {
@@ -102,14 +100,11 @@
     // FIXME: record these internally to this class instead calls from StyleResolver to here.
     void addContentAttr(const AtomicString& attributeName);
 
+    StyleInvalidator& styleInvalidator();
+
     Vector<RuleFeature> siblingRules;
     Vector<RuleFeature> uncommonAttributeRules;
 
-    typedef Vector<RefPtr<DescendantInvalidationSet> > InvalidationList;
-    typedef HashMap<Element*, OwnPtr<InvalidationList> > PendingInvalidationMap;
-
-    PendingInvalidationMap& pendingInvalidationMap();
-
 private:
     typedef HashMap<AtomicString, RefPtr<DescendantInvalidationSet> > InvalidationSetMap;
 
@@ -134,7 +129,7 @@
         UseSubtreeStyleChange
     };
 
-    static InvalidationSetMode supportsClassDescendantInvalidation(const CSSSelector&);
+    static InvalidationSetMode invalidationSetModeForSelector(const CSSSelector&);
 
     void collectFeaturesFromSelector(const CSSSelector&, FeatureMetadata&, InvalidationSetMode);
     void collectFeaturesFromSelectorList(const CSSSelectorList*, FeatureMetadata&, InvalidationSetMode);
@@ -146,27 +141,25 @@
     InvalidationSetMode updateInvalidationSets(const CSSSelector&);
 
     struct InvalidationSetFeatures {
+        InvalidationSetFeatures() : customPseudoElement(false) { }
         Vector<AtomicString> classes;
         Vector<AtomicString> attributes;
         AtomicString id;
         AtomicString tagName;
+        bool customPseudoElement;
     };
 
     static void extractInvalidationSetFeature(const CSSSelector&, InvalidationSetFeatures&);
     const CSSSelector* extractInvalidationSetFeatures(const CSSSelector&, InvalidationSetFeatures&);
     void addFeaturesToInvalidationSets(const CSSSelector&, const InvalidationSetFeatures&);
 
-    void addClassToInvalidationSet(const AtomicString& className, Element*);
-
-    InvalidationList& ensurePendingInvalidationList(Element*);
+    void addClassToInvalidationSet(const AtomicString& className, Element&);
 
     FeatureMetadata m_metadata;
     InvalidationSetMap m_classInvalidationSets;
     InvalidationSetMap m_attributeInvalidationSets;
-
-    PendingInvalidationMap m_pendingInvalidationMap;
-
     bool m_targetedStyleRecalcEnabled;
+    StyleInvalidator m_styleInvalidator;
 };
 
 
diff --git a/Source/core/css/RuleSet.cpp b/Source/core/css/RuleSet.cpp
index fefc1e4..a745456 100644
--- a/Source/core/css/RuleSet.cpp
+++ b/Source/core/css/RuleSet.cpp
@@ -177,10 +177,12 @@
 #endif
 
     const CSSSelector* it = &component;
-    for (; it->relation() == CSSSelector::SubSelector; it = it->tagHistory()) {
+    for (; it && it->relation() == CSSSelector::SubSelector; it = it->tagHistory()) {
         extractValuesforSelector(it, id, className, customPseudoElementName, tagName);
     }
-    extractValuesforSelector(it, id, className, customPseudoElementName, tagName);
+    // FIXME: this null check should not be necessary. See crbug.com/358475
+    if (it)
+        extractValuesforSelector(it, id, className, customPseudoElementName, tagName);
 
     // Prefer rule sets in order of most likely to apply infrequently.
     if (!id.isEmpty()) {
diff --git a/Source/core/css/RuntimeCSSEnabled.cpp b/Source/core/css/RuntimeCSSEnabled.cpp
index 07864df..fe1c429 100644
--- a/Source/core/css/RuntimeCSSEnabled.cpp
+++ b/Source/core/css/RuntimeCSSEnabled.cpp
@@ -52,7 +52,6 @@
     setCSSPropertiesEnabled(exclusionProperties, WTF_ARRAY_LENGTH(exclusionProperties), RuntimeEnabledFeatures::cssExclusionsEnabled());
     CSSPropertyID shapeProperties[] = {
         CSSPropertyShapeMargin,
-        CSSPropertyShapePadding,
         CSSPropertyShapeImageThreshold,
         CSSPropertyShapeOutside,
     };
@@ -83,6 +82,7 @@
         CSSPropertyGridArea,
         CSSPropertyGridAutoFlow,
         CSSPropertyGridTemplateAreas,
+        CSSPropertyGridTemplate,
         CSSPropertyJustifySelf
     };
     setCSSPropertiesEnabled(cssGridLayoutProperties, WTF_ARRAY_LENGTH(cssGridLayoutProperties), RuntimeEnabledFeatures::cssGridLayoutEnabled());
diff --git a/Source/core/css/StylePropertySerializer.cpp b/Source/core/css/StylePropertySerializer.cpp
index 489527f..3b6e94a 100644
--- a/Source/core/css/StylePropertySerializer.cpp
+++ b/Source/core/css/StylePropertySerializer.cpp
@@ -313,6 +313,7 @@
         return getShorthandValue(webkitTextEmphasisShorthand());
     case CSSPropertyWebkitTextStroke:
         return getShorthandValue(webkitTextStrokeShorthand());
+    case CSSPropertyTransformOrigin:
     case CSSPropertyWebkitTransformOrigin:
         return getShorthandValue(webkitTransformOriginShorthand());
     case CSSPropertyWebkitTransition:
diff --git a/Source/core/css/invalidation/DescendantInvalidationSet.cpp b/Source/core/css/invalidation/DescendantInvalidationSet.cpp
index f7c802d..18bd5b6 100644
--- a/Source/core/css/invalidation/DescendantInvalidationSet.cpp
+++ b/Source/core/css/invalidation/DescendantInvalidationSet.cpp
@@ -38,6 +38,7 @@
 
 DescendantInvalidationSet::DescendantInvalidationSet()
     : m_allDescendantsMightBeInvalid(false)
+    , m_customPseudoInvalid(false)
 {
 }
 
@@ -52,6 +53,9 @@
         return;
     }
 
+    if (other.customPseudoInvalid())
+        setCustomPseudoInvalid();
+
     if (other.m_classes) {
         HashSet<AtomicString>::const_iterator end = other.m_classes->end();
         for (HashSet<AtomicString>::const_iterator it = other.m_classes->begin(); it != end; ++it)
diff --git a/Source/core/css/invalidation/DescendantInvalidationSet.h b/Source/core/css/invalidation/DescendantInvalidationSet.h
index 93c18e6..92646fc 100644
--- a/Source/core/css/invalidation/DescendantInvalidationSet.h
+++ b/Source/core/css/invalidation/DescendantInvalidationSet.h
@@ -66,6 +66,10 @@
 
     void setWholeSubtreeInvalid();
     bool wholeSubtreeInvalid() const { return m_allDescendantsMightBeInvalid; }
+
+    void setCustomPseudoInvalid() { m_customPseudoInvalid = true; }
+    bool customPseudoInvalid() const { return m_customPseudoInvalid; }
+
 private:
     DescendantInvalidationSet();
 
@@ -77,6 +81,9 @@
     // If true, all descendants might be invalidated, so a full subtree recalc is required.
     bool m_allDescendantsMightBeInvalid;
 
+    // If true, all descendants which are custom pseudo elements must be invalidated.
+    bool m_customPseudoInvalid;
+
     // FIXME: optimize this if it becomes a memory issue.
     OwnPtr<HashSet<AtomicString> > m_classes;
     OwnPtr<HashSet<AtomicString> > m_ids;
diff --git a/Source/core/css/invalidation/StyleInvalidator.cpp b/Source/core/css/invalidation/StyleInvalidator.cpp
index fe40049..947c135 100644
--- a/Source/core/css/invalidation/StyleInvalidator.cpp
+++ b/Source/core/css/invalidation/StyleInvalidator.cpp
@@ -16,24 +16,50 @@
 
 namespace WebCore {
 
-void StyleInvalidator::invalidate()
+void StyleInvalidator::invalidate(Document& document)
 {
-    if (Element* documentElement = m_document.documentElement())
+    if (Element* documentElement = document.documentElement())
         invalidate(*documentElement);
-    m_document.clearChildNeedsStyleInvalidation();
-    m_document.clearNeedsStyleInvalidation();
+    document.clearChildNeedsStyleInvalidation();
+    document.clearNeedsStyleInvalidation();
+    clearPendingInvalidations();
+}
+
+void StyleInvalidator::scheduleInvalidation(PassRefPtr<DescendantInvalidationSet> invalidationSet, Element& element)
+{
+    ensurePendingInvalidationList(element).append(invalidationSet);
+    element.setNeedsStyleInvalidation();
+}
+
+StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationList(Element& element)
+{
+    PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(&element, nullptr);
+    if (addResult.isNewEntry)
+        addResult.storedValue->value = adoptPtr(new InvalidationList);
+    return *addResult.storedValue->value;
+}
+
+void StyleInvalidator::clearInvalidation(Node& node)
+{
+    if (node.isElementNode() && node.needsStyleInvalidation())
+        m_pendingInvalidationMap.remove(toElement(&node));
+    node.clearChildNeedsStyleInvalidation();
+    node.clearNeedsStyleInvalidation();
+}
+
+void StyleInvalidator::clearPendingInvalidations()
+{
     m_pendingInvalidationMap.clear();
 }
 
-StyleInvalidator::StyleInvalidator(Document& document)
-    : m_document(document)
-    , m_pendingInvalidationMap(document.styleResolver()->ruleFeatureSet().pendingInvalidationMap())
+StyleInvalidator::StyleInvalidator()
 { }
 
 void StyleInvalidator::RecursionData::pushInvalidationSet(const DescendantInvalidationSet& invalidationSet)
 {
     invalidationSet.getClasses(m_invalidationClasses);
     invalidationSet.getAttributes(m_invalidationAttributes);
+    m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid();
     m_foundInvalidationSet = true;
 }
 
@@ -52,6 +78,8 @@
                 return true;
         }
     }
+    if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom)
+        return true;
 
     return false;
 }
@@ -60,10 +88,10 @@
 {
     bool thisElementNeedsStyleRecalc = false;
     if (element.needsStyleInvalidation()) {
-        if (RuleFeatureSet::InvalidationList* invalidationList = m_pendingInvalidationMap.get(&element)) {
+        if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&element)) {
             // FIXME: it's really only necessary to clone the render style for this element, not full style recalc.
             thisElementNeedsStyleRecalc = true;
-            for (RuleFeatureSet::InvalidationList::const_iterator it = invalidationList->begin(); it != invalidationList->end(); ++it) {
+            for (InvalidationList::const_iterator it = invalidationList->begin(); it != invalidationList->end(); ++it) {
                 m_recursionData.pushInvalidationSet(**it);
                 if ((*it)->wholeSubtreeInvalid()) {
                     element.setNeedsStyleRecalc(SubtreeStyleChange);
diff --git a/Source/core/css/invalidation/StyleInvalidator.h b/Source/core/css/invalidation/StyleInvalidator.h
index 77e6071..d92921c 100644
--- a/Source/core/css/invalidation/StyleInvalidator.h
+++ b/Source/core/css/invalidation/StyleInvalidator.h
@@ -5,16 +5,24 @@
 #ifndef StyleInvalidator_h
 #define StyleInvalidator_h
 
-#include "core/css/RuleFeature.h"
 #include "heap/Heap.h"
 
 namespace WebCore {
 
+class DescendantInvalidationSet;
+class Document;
+class Element;
+
 class StyleInvalidator {
-    STACK_ALLOCATED();
 public:
-    explicit StyleInvalidator(Document&);
-    void invalidate();
+    StyleInvalidator();
+    void invalidate(Document&);
+    void scheduleInvalidation(PassRefPtr<DescendantInvalidationSet>, Element&);
+
+    // Clears all style invalidation state for the passed node.
+    void clearInvalidation(Node&);
+
+    void clearPendingInvalidations();
 
 private:
     bool invalidate(Element&);
@@ -23,7 +31,10 @@
     bool checkInvalidationSetsAgainstElement(Element&);
 
     struct RecursionData {
-        RecursionData() : m_foundInvalidationSet(false) { }
+        RecursionData()
+            : m_foundInvalidationSet(false)
+            , m_invalidateCustomPseudo(false)
+        { }
         void pushInvalidationSet(const DescendantInvalidationSet&);
         bool matchesCurrentInvalidationSets(Element&);
         bool foundInvalidationSet() { return m_foundInvalidationSet; }
@@ -31,6 +42,7 @@
         Vector<AtomicString> m_invalidationClasses;
         Vector<AtomicString> m_invalidationAttributes;
         bool m_foundInvalidationSet;
+        bool m_invalidateCustomPseudo;
     };
 
     class RecursionCheckpoint {
@@ -39,6 +51,7 @@
             : m_prevClassLength(data->m_invalidationClasses.size()),
             m_prevAttributeLength(data->m_invalidationAttributes.size()),
             m_prevFoundInvalidationSet(data->m_foundInvalidationSet),
+            m_prevInvalidateCustomPseudo(data->m_invalidateCustomPseudo),
             m_data(data)
         { }
         ~RecursionCheckpoint()
@@ -46,17 +59,23 @@
             m_data->m_invalidationClasses.remove(m_prevClassLength, m_data->m_invalidationClasses.size() - m_prevClassLength);
             m_data->m_invalidationAttributes.remove(m_prevAttributeLength, m_data->m_invalidationAttributes.size() - m_prevAttributeLength);
             m_data->m_foundInvalidationSet = m_prevFoundInvalidationSet;
+            m_data->m_invalidateCustomPseudo = m_prevInvalidateCustomPseudo;
         }
 
     private:
         int m_prevClassLength;
         int m_prevAttributeLength;
         bool m_prevFoundInvalidationSet;
+        bool m_prevInvalidateCustomPseudo;
         RecursionData* m_data;
     };
 
-    Document& m_document;
-    RuleFeatureSet::PendingInvalidationMap& m_pendingInvalidationMap;
+    typedef Vector<RefPtr<DescendantInvalidationSet> > InvalidationList;
+    typedef HashMap<Element*, OwnPtr<InvalidationList> > PendingInvalidationMap;
+
+    InvalidationList& ensurePendingInvalidationList(Element&);
+
+    PendingInvalidationMap m_pendingInvalidationMap;
     RecursionData m_recursionData;
 };
 
diff --git a/Source/core/css/parser/BisonCSSParser-in.cpp b/Source/core/css/parser/BisonCSSParser-in.cpp
index 1bd084d..59dc912 100644
--- a/Source/core/css/parser/BisonCSSParser-in.cpp
+++ b/Source/core/css/parser/BisonCSSParser-in.cpp
@@ -109,7 +109,7 @@
     : m_context(context)
     , m_important(false)
     , m_id(CSSPropertyInvalid)
-    , m_styleSheet(0)
+    , m_styleSheet(nullptr)
     , m_supportsCondition(false)
     , m_selectorListForParseSelector(0)
     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
@@ -129,7 +129,6 @@
 #if YYDEBUG > 0
     cssyydebug = 1;
 #endif
-    CSSPropertySourceData::init();
 }
 
 BisonCSSParser::~BisonCSSParser()
@@ -287,7 +286,6 @@
         acceptsNegativeNumbers = false;
         return true;
     case CSSPropertyShapeMargin:
-    case CSSPropertyShapePadding:
         acceptsNegativeNumbers = false;
         return RuntimeEnabledFeatures::cssShapesEnabled();
     case CSSPropertyBottom:
@@ -331,7 +329,7 @@
 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
 {
     ASSERT(!string.isEmpty());
-    bool acceptsNegativeNumbers;
+    bool acceptsNegativeNumbers = false;
 
     // In @viewport, width and height are shorthands, not simple length values.
     if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
@@ -971,7 +969,7 @@
 
 static bool parseTranslateTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
 {
-    if (propertyID != CSSPropertyWebkitTransform)
+    if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
         return false;
     if (string.isEmpty())
         return false;
@@ -989,7 +987,7 @@
         if (!transformList)
             return false;
     }
-    properties->addParsedProperty(CSSProperty(CSSPropertyWebkitTransform, transformList.release(), important));
+    properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
     return true;
 }
 
@@ -1212,6 +1210,19 @@
     return ok;
 }
 
+PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
+{
+    ASSERT(!m_mediaList);
+
+    // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
+    // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
+    setupParser("@-internal-medialist ", string, "");
+    cssyyparse(this);
+
+    ASSERT(m_mediaList);
+    return m_mediaList.release();
+}
+
 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
 {
     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
@@ -1405,14 +1416,14 @@
     CSSPropertyParser::Units m_unit;
 };
 
-PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform()
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
 {
     if (!m_valueList)
         return nullptr;
 
     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
-        RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(value);
+        RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
         if (!parsedTransformValue)
             return nullptr;
 
@@ -1422,7 +1433,7 @@
     return list.release();
 }
 
-PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSParserValue *value)
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
 {
     if (value->unit != CSSParserValue::Function || !value->function)
         return nullptr;
@@ -1466,7 +1477,8 @@
                 return nullptr;
         } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
             // 1st param of perspective() must be a non-negative number (deprecated) or length.
-            if (!validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
+            if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
+                || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
                 return nullptr;
         } else if (!validUnit(a, unit, HTMLStandardMode)) {
             return nullptr;
@@ -1682,7 +1694,7 @@
 {
     m_allowImportRules = m_allowNamespaceDeclarations = false;
 
-    RefPtr<CSSRuleSourceData> data = popSupportsRuleData();
+    RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
     RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
     String conditionText;
     unsigned conditionOffset = data->ruleHeaderRange.start + 9;
@@ -1709,9 +1721,9 @@
 void BisonCSSParser::markSupportsRuleHeaderStart()
 {
     if (!m_supportsRuleDataStack)
-        m_supportsRuleDataStack = adoptPtr(new RuleSourceDataList());
+        m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
 
-    RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
+    RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
     data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
     m_supportsRuleDataStack->append(data);
 }
@@ -1726,10 +1738,10 @@
         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
 }
 
-PassRefPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
+PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
 {
     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
-    RefPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
+    RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
     m_supportsRuleDataStack->removeLast();
     return data.release();
 }
diff --git a/Source/core/css/parser/BisonCSSParser.h b/Source/core/css/parser/BisonCSSParser.h
index 90c9c7e..d801e31 100644
--- a/Source/core/css/parser/BisonCSSParser.h
+++ b/Source/core/css/parser/BisonCSSParser.h
@@ -78,10 +78,10 @@
 };
 
 class BisonCSSParser {
+    STACK_ALLOCATED();
     friend inline int cssyylex(void*, BisonCSSParser*);
-
 public:
-    BisonCSSParser(const CSSParserContext&);
+    explicit BisonCSSParser(const CSSParserContext&);
     ~BisonCSSParser();
 
     void rollbackLastProperties(int num);
@@ -98,6 +98,7 @@
     static PassRefPtrWillBeRawPtr<CSSValue> parseAnimationTimingFunctionValue(const String&);
     bool parseDeclaration(MutableStylePropertySet*, const String&, CSSParserObserver*, StyleSheetContents* contextStyleSheet);
     static PassRefPtr<ImmutableStylePropertySet> parseInlineStyleDeclaration(const String&, Element*);
+    PassRefPtrWillBeRawPtr<MediaQuerySet> parseMediaQueryList(const String&);
     PassOwnPtr<Vector<double> > parseKeyframeKeyList(const String&);
 
     static bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, const Document&);
@@ -137,7 +138,7 @@
     StyleRuleBase* createSupportsRule(bool conditionIsSupported, RuleList*);
     void markSupportsRuleHeaderStart();
     void markSupportsRuleHeaderEnd();
-    PassRefPtr<CSSRuleSourceData> popSupportsRuleData();
+    PassRefPtrWillBeRawPtr<CSSRuleSourceData> popSupportsRuleData();
     StyleRuleBase* createHostRule(RuleList* rules);
 
     void startDeclarationsForMarginBox();
@@ -177,14 +178,14 @@
 
     bool m_important;
     CSSPropertyID m_id;
-    StyleSheetContents* m_styleSheet;
-    RefPtrWillBePersistent<StyleRuleBase> m_rule;
-    RefPtrWillBePersistent<StyleKeyframe> m_keyframe;
-    RefPtrWillBePersistent<MediaQuerySet> m_mediaList;
+    RawPtrWillBeMember<StyleSheetContents> m_styleSheet;
+    RefPtrWillBeMember<StyleRuleBase> m_rule;
+    RefPtrWillBeMember<StyleKeyframe> m_keyframe;
+    RefPtrWillBeMember<MediaQuerySet> m_mediaList;
     OwnPtr<CSSParserValueList> m_valueList;
     bool m_supportsCondition;
 
-    WillBePersistentHeapVector<CSSProperty, 256> m_parsedProperties;
+    WillBeHeapVector<CSSProperty, 256> m_parsedProperties;
     CSSSelectorList* m_selectorListForParseSelector;
 
     unsigned m_numParsedPropertiesBeforeMarginBox;
@@ -227,6 +228,7 @@
 
 private:
     class StyleDeclarationScope {
+        STACK_ALLOCATED();
         WTF_MAKE_NONCOPYABLE(StyleDeclarationScope);
     public:
         StyleDeclarationScope(BisonCSSParser* parser, const StylePropertySet* declaration)
@@ -288,24 +290,24 @@
 
     CSSParserLocation m_locationLabel;
 
-    WillBePersistentHeapVector<RefPtrWillBeMember<StyleRuleBase> > m_parsedRules;
-    WillBePersistentHeapVector<RefPtrWillBeMember<StyleKeyframe> > m_parsedKeyframes;
-    WillBePersistentHeapVector<RefPtrWillBeMember<MediaQuerySet> > m_parsedMediaQuerySets;
-    WillBePersistentHeapVector<OwnPtrWillBeMember<RuleList> > m_parsedRuleLists;
+    WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> > m_parsedRules;
+    WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > m_parsedKeyframes;
+    WillBeHeapVector<RefPtrWillBeMember<MediaQuerySet> > m_parsedMediaQuerySets;
+    WillBeHeapVector<OwnPtrWillBeMember<RuleList> > m_parsedRuleLists;
     Vector<CSSParserSelector*> m_floatingSelectors;
     Vector<Vector<OwnPtr<CSSParserSelector> >*> m_floatingSelectorVectors;
     Vector<CSSParserValueList*> m_floatingValueLists;
     Vector<CSSParserFunction*> m_floatingFunctions;
 
-    OwnPtrWillBePersistent<MediaQuery> m_floatingMediaQuery;
-    OwnPtrWillBePersistent<MediaQueryExp> m_floatingMediaQueryExp;
-    OwnPtrWillBePersistent<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > m_floatingMediaQueryExpList;
+    OwnPtrWillBeMember<MediaQuery> m_floatingMediaQuery;
+    OwnPtrWillBeMember<MediaQueryExp> m_floatingMediaQueryExp;
+    OwnPtrWillBeMember<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > m_floatingMediaQueryExpList;
 
-    OwnPtrWillBePersistent<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > m_floatingKeyframeVector;
+    OwnPtrWillBeMember<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > m_floatingKeyframeVector;
 
     Vector<OwnPtr<CSSParserSelector> > m_reusableSelectorVector;
 
-    OwnPtr<RuleSourceDataList> m_supportsRuleDataStack;
+    OwnPtrWillBeMember<RuleSourceDataList> m_supportsRuleDataStack;
 
     bool isLoggingErrors();
     void logError(const String& message, const CSSParserLocation&);
diff --git a/Source/core/css/parser/CSSParserObserver.h b/Source/core/css/parser/CSSParserObserver.h
index c795f50..c6711a4 100644
--- a/Source/core/css/parser/CSSParserObserver.h
+++ b/Source/core/css/parser/CSSParserObserver.h
@@ -49,6 +49,7 @@
 
 // This only implemented by StyleSheetHandler in InspectorStyleSheet.cpp.
 class CSSParserObserver {
+    STACK_ALLOCATED();
 public:
     virtual void startRuleHeader(CSSRuleSourceData::Type, unsigned offset) = 0;
     virtual void endRuleHeader(unsigned offset) = 0;
diff --git a/Source/core/css/parser/CSSPropertyParser.cpp b/Source/core/css/parser/CSSPropertyParser.cpp
index 5b96d31..8a1a642 100644
--- a/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1108,11 +1108,12 @@
         else
             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg);
         break;
+    case CSSPropertyTransform:
     case CSSPropertyWebkitTransform:
         if (id == CSSValueNone)
             validPrimitive = true;
         else {
-            RefPtrWillBeRawPtr<CSSValue> transformValue = parseTransform();
+            RefPtrWillBeRawPtr<CSSValue> transformValue = parseTransform(propId);
             if (transformValue) {
                 addProperty(propId, transformValue.release(), important);
                 return true;
@@ -1120,6 +1121,18 @@
             return false;
         }
         break;
+    case CSSPropertyTransformOrigin: {
+        RefPtrWillBeRawPtr<CSSValueList> list = parseTransformOrigin();
+        if (!list)
+            return false;
+        // These values are added to match gecko serialization.
+        if (list->length() == 1)
+            list->append(cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE));
+        if (list->length() == 2)
+            list->append(cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX));
+        addProperty(propId, list.release(), important);
+        return true;
+    }
     case CSSPropertyWebkitTransformOrigin:
     case CSSPropertyWebkitTransformOriginX:
     case CSSPropertyWebkitTransformOriginY:
@@ -1128,7 +1141,7 @@
         RefPtrWillBeRawPtr<CSSValue> val2 = nullptr;
         RefPtrWillBeRawPtr<CSSValue> val3 = nullptr;
         CSSPropertyID propId1, propId2, propId3;
-        if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
+        if (parseWebkitTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
             addProperty(propId1, val1.release(), important);
             if (val2)
                 addProperty(propId2, val2.release(), important);
@@ -1138,28 +1151,40 @@
         }
         return false;
     }
-    case CSSPropertyWebkitPerspective:
-        if (id == CSSValueNone)
+    case CSSPropertyPerspective:
+        if (id == CSSValueNone) {
             validPrimitive = true;
-        else {
-            // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
-            if (validUnit(value, FNumber | FLength | FNonNeg)) {
-                RefPtrWillBeRawPtr<CSSValue> val = createPrimitiveNumericValue(value);
-                if (val) {
-                    addProperty(propId, val.release(), important);
-                    return true;
-                }
-                return false;
-            }
+        } else if (validUnit(value, FLength | FNonNeg)) {
+            addProperty(propId, createPrimitiveNumericValue(value), important);
+            return true;
         }
         break;
+    case CSSPropertyWebkitPerspective:
+        if (id == CSSValueNone) {
+            validPrimitive = true;
+        } else if (validUnit(value, FNumber | FLength | FNonNeg)) {
+            // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
+            addProperty(propId, createPrimitiveNumericValue(value), important);
+            return true;
+        }
+        break;
+    case CSSPropertyPerspectiveOrigin: {
+        RefPtrWillBeRawPtr<CSSValueList> list = parseTransformOrigin();
+        if (!list || list->length() == 3)
+            return false;
+        // This values are added to match gecko serialization.
+        if (list->length() == 1)
+            list->append(cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE));
+        addProperty(propId, list.release(), important);
+        return true;
+    }
     case CSSPropertyWebkitPerspectiveOrigin:
     case CSSPropertyWebkitPerspectiveOriginX:
     case CSSPropertyWebkitPerspectiveOriginY: {
         RefPtrWillBeRawPtr<CSSValue> val1 = nullptr;
         RefPtrWillBeRawPtr<CSSValue> val2 = nullptr;
         CSSPropertyID propId1, propId2;
-        if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
+        if (parseWebkitPerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
             addProperty(propId1, val1.release(), important);
             if (val2)
                 addProperty(propId2, val2.release(), important);
@@ -1218,7 +1243,8 @@
     case CSSPropertyGridTemplateRows:
         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
             return false;
-        return parseGridTrackList(propId, important);
+        parsedValue = parseGridTrackList(important);
+        break;
 
     case CSSPropertyGridColumnEnd:
     case CSSPropertyGridColumnStart:
@@ -1246,6 +1272,11 @@
         parsedValue = parseGridTemplateAreas();
         break;
 
+    case CSSPropertyGridTemplate:
+        if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
+            return false;
+        return parseGridTemplateShorthand(important);
+
     case CSSPropertyWebkitMarginCollapse: {
         if (num == 1) {
             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
@@ -1483,7 +1514,6 @@
         parsedValue = parseShapeProperty(propId);
         break;
     case CSSPropertyShapeMargin:
-    case CSSPropertyShapePadding:
         validPrimitive = (RuntimeEnabledFeatures::cssShapesEnabled() && !id && validUnit(value, FLength | FNonNeg));
         break;
     case CSSPropertyShapeImageThreshold:
@@ -1609,12 +1639,6 @@
     case CSSPropertyUserZoom:
         validPrimitive = false;
         break;
-    // FIXME: crbug.com/154772 Unimplemented css-transforms properties
-    case CSSPropertyPerspective:
-    case CSSPropertyPerspectiveOrigin:
-    case CSSPropertyTransform:
-    case CSSPropertyTransformOrigin:
-        return false;
     default:
         return parseSVGValue(propId, important);
     }
@@ -3103,7 +3127,7 @@
     return nullptr;
 }
 
-bool CSSPropertyParser::parseTransformOriginShorthand(RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2, RefPtrWillBeRawPtr<CSSValue>& value3)
+bool CSSPropertyParser::parseWebkitTransformOriginShorthand(RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2, RefPtrWillBeRawPtr<CSSValue>& value3)
 {
     parse2ValuesFillPosition(m_valueList.get(), value1, value2);
 
@@ -3458,6 +3482,122 @@
     return true;
 }
 
+bool CSSPropertyParser::parseGridTemplateRowsAndAreas(PassRefPtrWillBeRawPtr<CSSValue> templateColumns, bool important)
+{
+    NamedGridAreaMap gridAreaMap;
+    size_t rowCount = 0;
+    size_t columnCount = 0;
+    bool trailingIdentWasAdded = false;
+    RefPtrWillBeRawPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated();
+
+    // At least template-areas strings must be defined.
+    if (!m_valueList->current())
+        return false;
+
+    while (m_valueList->current()) {
+        // Handle leading <custom-ident>*.
+        if (m_valueList->current()->unit == CSSParserValue::ValueList) {
+            if (trailingIdentWasAdded) {
+                // A row's trailing ident must be concatenated with the next row's leading one.
+                parseGridLineNames(*m_valueList, *templateRows, static_cast<CSSGridLineNamesValue*>(templateRows->item(templateRows->length() - 1)));
+            } else {
+                parseGridLineNames(*m_valueList, *templateRows);
+            }
+        }
+
+        // Handle a template-area's row.
+        if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount))
+            return false;
+        ++rowCount;
+
+        // Handle template-rows's track-size.
+        if (m_valueList->current() && m_valueList->current()->unit != CSSParserValue::ValueList && m_valueList->current()->unit != CSSPrimitiveValue::CSS_STRING) {
+            RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
+            if (!value)
+                return false;
+            templateRows->append(value);
+        } else {
+            templateRows->append(cssValuePool().createIdentifierValue(CSSValueAuto));
+        }
+
+        // This will handle the trailing/leading <custom-ident>* in the grammar.
+        trailingIdentWasAdded = false;
+        if (m_valueList->current() && m_valueList->current()->unit == CSSParserValue::ValueList) {
+            parseGridLineNames(*m_valueList, *templateRows);
+            trailingIdentWasAdded = true;
+        }
+    }
+
+    // [<track-list> /]?
+    if (templateColumns)
+        addProperty(CSSPropertyGridTemplateColumns, templateColumns, important);
+    else
+        addProperty(CSSPropertyGridTemplateColumns,  cssValuePool().createIdentifierValue(CSSValueNone), important);
+
+    // [<line-names>? <string> [<track-size> <line-names>]? ]+
+    RefPtrWillBeRawPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount);
+    addProperty(CSSPropertyGridTemplateAreas, templateAreas.release(), important);
+    addProperty(CSSPropertyGridTemplateRows, templateRows.release(), important);
+
+
+    return true;
+}
+
+
+bool CSSPropertyParser::parseGridTemplateShorthand(bool important)
+{
+    ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
+
+    ShorthandScope scope(this, CSSPropertyGridTemplate);
+    ASSERT(gridTemplateShorthand().length() == 3);
+
+    // At least "none" must be defined.
+    if (!m_valueList->current())
+        return false;
+
+    bool firstValueIsNone = m_valueList->current()->id == CSSValueNone;
+
+    // 1- 'none' case.
+    if (firstValueIsNone && !m_valueList->next()) {
+        addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important);
+        addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifierValue(CSSValueNone), important);
+        addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important);
+        return true;
+    }
+
+    unsigned index = 0;
+    RefPtrWillBeRawPtr<CSSValue> columnsValue = nullptr;
+    if (firstValueIsNone) {
+        columnsValue = cssValuePool().createIdentifierValue(CSSValueNone);
+    } else {
+        columnsValue = parseGridTrackList(important);
+    }
+
+    // 2- <grid-template-columns> / <grid-template-columns> syntax.
+    if (columnsValue) {
+        if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current()) && m_valueList->next()))
+            return false;
+        index = m_valueList->currentIndex();
+        if (RefPtrWillBeRawPtr<CSSValue> rowsValue = parseGridTrackList(important)) {
+            if (m_valueList->current())
+                return false;
+            addProperty(CSSPropertyGridTemplateColumns, columnsValue, important);
+            addProperty(CSSPropertyGridTemplateRows, rowsValue, important);
+            addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important);
+            return true;
+        }
+    }
+
+
+    // 3- [<track-list> /]? [<line-names>? <string> [<track-size> <line-names>]? ]+ syntax.
+    // The template-columns <track-list> can't be 'none'.
+    if (firstValueIsNone)
+        return false;
+    // It requires to rewind parsing due to previous syntax failures.
+    m_valueList->setCurrentIndex(index);
+    return parseGridTemplateRowsAndAreas(columnsValue, important);
+}
+
 bool CSSPropertyParser::parseGridAreaShorthand(bool important)
 {
     ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
@@ -3513,72 +3653,76 @@
     return true;
 }
 
-void CSSPropertyParser::parseGridLineNames(CSSParserValueList* parserValueList, CSSValueList& valueList)
+void CSSPropertyParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames)
 {
-    ASSERT(parserValueList->current() && parserValueList->current()->unit == CSSParserValue::ValueList);
+    ASSERT(inputList.current() && inputList.current()->unit == CSSParserValue::ValueList);
 
-    CSSParserValueList* identList = parserValueList->current()->valueList;
+    CSSParserValueList* identList = inputList.current()->valueList;
     if (!identList->size()) {
-        parserValueList->next();
+        inputList.next();
         return;
     }
 
-    RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create();
+    // Need to ensure the identList is at the heading index, since the parserList might have been rewound.
+    identList->setCurrentIndex(0);
+
+    RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = previousNamedAreaTrailingLineNames;
+    if (!lineNames)
+        lineNames = CSSGridLineNamesValue::create();
     while (CSSParserValue* identValue = identList->current()) {
         ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT);
         RefPtrWillBeRawPtr<CSSPrimitiveValue> lineName = createPrimitiveStringValue(identValue);
         lineNames->append(lineName.release());
         identList->next();
     }
-    valueList.append(lineNames.release());
+    if (!previousNamedAreaTrailingLineNames)
+        valueList.append(lineNames.release());
 
-    parserValueList->next();
+    inputList.next();
 }
 
-bool CSSPropertyParser::parseGridTrackList(CSSPropertyID propId, bool important)
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackList(bool important)
 {
     ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
 
     CSSParserValue* value = m_valueList->current();
     if (value->id == CSSValueNone) {
-        if (m_valueList->next())
-            return false;
-
-        addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
-        return true;
+        m_valueList->next();
+        return cssValuePool().createIdentifierValue(CSSValueNone);
     }
 
     RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
     // Handle leading  <ident>*.
     value = m_valueList->current();
     if (value && value->unit == CSSParserValue::ValueList)
-        parseGridLineNames(m_valueList.get(), *values);
+        parseGridLineNames(*m_valueList, *values);
 
     bool seenTrackSizeOrRepeatFunction = false;
     while (CSSParserValue* currentValue = m_valueList->current()) {
+        if (isForwardSlashOperator(currentValue))
+            break;
         if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "repeat(")) {
             if (!parseGridTrackRepeatFunction(*values))
-                return false;
+                return nullptr;
             seenTrackSizeOrRepeatFunction = true;
         } else {
             RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
             if (!value)
-                return false;
+                return nullptr;
             values->append(value);
             seenTrackSizeOrRepeatFunction = true;
         }
         // This will handle the trailing <ident>* in the grammar.
         value = m_valueList->current();
         if (value && value->unit == CSSParserValue::ValueList)
-            parseGridLineNames(m_valueList.get(), *values);
+            parseGridLineNames(*m_valueList, *values);
     }
 
     // We should have found a <track-size> or else it is not a valid <track-list>
     if (!seenTrackSizeOrRepeatFunction)
-        return false;
+        return nullptr;
 
-    addProperty(propId, values.release(), important);
-    return true;
+    return values;
 }
 
 bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list)
@@ -3596,7 +3740,7 @@
     // Handle leading <ident>*.
     CSSParserValue* currentValue = arguments->current();
     if (currentValue && currentValue->unit == CSSParserValue::ValueList)
-        parseGridLineNames(arguments, *repeatedValues);
+        parseGridLineNames(*arguments, *repeatedValues);
 
     while (arguments->current()) {
         RefPtrWillBeRawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments);
@@ -3608,7 +3752,7 @@
         // This takes care of any trailing <ident>* in the grammar.
         currentValue = arguments->current();
         if (currentValue && currentValue->unit == CSSParserValue::ValueList)
-            parseGridLineNames(arguments, *repeatedValues);
+            parseGridLineNames(*arguments, *repeatedValues);
     }
 
     for (size_t i = 0; i < repetitions; ++i) {
@@ -3676,71 +3820,79 @@
     return createPrimitiveNumericValue(currentValue);
 }
 
+bool CSSPropertyParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, const size_t rowCount, size_t& columnCount)
+{
+    CSSParserValue* currentValue = m_valueList->current();
+    if (!currentValue || currentValue->unit != CSSPrimitiveValue::CSS_STRING)
+        return false;
+
+    String gridRowNames = currentValue->string;
+    if (!gridRowNames.length())
+        return false;
+
+    Vector<String> columnNames;
+    gridRowNames.split(' ', columnNames);
+
+    if (!columnCount) {
+        columnCount = columnNames.size();
+        ASSERT(columnCount);
+    } else if (columnCount != columnNames.size()) {
+        // The declaration is invalid is all the rows don't have the number of columns.
+        return false;
+    }
+
+    for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) {
+        const String& gridAreaName = columnNames[currentCol];
+
+        // Unamed areas are always valid (we consider them to be 1x1).
+        if (gridAreaName == ".")
+            continue;
+
+        // We handle several grid areas with the same name at once to simplify the validation code.
+        size_t lookAheadCol;
+        for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) {
+            if (columnNames[lookAheadCol + 1] != gridAreaName)
+                break;
+        }
+
+        NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
+        if (gridAreaIt == gridAreaMap.end()) {
+            gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol)));
+        } else {
+            GridCoordinate& gridCoordinate = gridAreaIt->value;
+
+            // The following checks test that the grid area is a single filled-in rectangle.
+            // 1. The new row is adjacent to the previously parsed row.
+            if (rowCount != gridCoordinate.rows.finalPositionIndex + 1)
+                return false;
+
+            // 2. The new area starts at the same position as the previously parsed area.
+            if (currentCol != gridCoordinate.columns.initialPositionIndex)
+                return false;
+
+            // 3. The new area ends at the same position as the previously parsed area.
+            if (lookAheadCol != gridCoordinate.columns.finalPositionIndex)
+                return false;
+
+            ++gridCoordinate.rows.finalPositionIndex;
+        }
+        currentCol = lookAheadCol;
+    }
+
+    m_valueList->next();
+    return true;
+}
+
 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTemplateAreas()
 {
     NamedGridAreaMap gridAreaMap;
     size_t rowCount = 0;
     size_t columnCount = 0;
 
-    while (CSSParserValue* currentValue = m_valueList->current()) {
-        if (currentValue->unit != CSSPrimitiveValue::CSS_STRING)
+    while (m_valueList->current()) {
+        if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount))
             return nullptr;
-
-        String gridRowNames = currentValue->string;
-        if (!gridRowNames.length())
-            return nullptr;
-
-        Vector<String> columnNames;
-        gridRowNames.split(' ', columnNames);
-
-        if (!columnCount) {
-            columnCount = columnNames.size();
-            ASSERT(columnCount);
-        } else if (columnCount != columnNames.size()) {
-            // The declaration is invalid is all the rows don't have the number of columns.
-            return nullptr;
-        }
-
-        for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) {
-            const String& gridAreaName = columnNames[currentCol];
-
-            // Unamed areas are always valid (we consider them to be 1x1).
-            if (gridAreaName == ".")
-                continue;
-
-            // We handle several grid areas with the same name at once to simplify the validation code.
-            size_t lookAheadCol;
-            for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) {
-                if (columnNames[lookAheadCol + 1] != gridAreaName)
-                    break;
-            }
-
-            NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
-            if (gridAreaIt == gridAreaMap.end()) {
-                gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol)));
-            } else {
-                GridCoordinate& gridCoordinate = gridAreaIt->value;
-
-                // The following checks test that the grid area is a single filled-in rectangle.
-                // 1. The new row is adjacent to the previously parsed row.
-                if (rowCount != gridCoordinate.rows.finalPositionIndex + 1)
-                    return nullptr;
-
-                // 2. The new area starts at the same position as the previously parsed area.
-                if (currentCol != gridCoordinate.columns.initialPositionIndex)
-                    return nullptr;
-
-                // 3. The new area ends at the same position as the previously parsed area.
-                if (lookAheadCol != gridCoordinate.columns.finalPositionIndex)
-                    return nullptr;
-
-                ++gridCoordinate.rows.finalPositionIndex;
-            }
-            currentCol = lookAheadCol;
-        }
-
         ++rowCount;
-        m_valueList->next();
     }
 
     if (!rowCount || !columnCount)
@@ -7232,8 +7384,71 @@
 
     return list.release();
 }
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransformOrigin()
+{
+    CSSParserValue* value = m_valueList->current();
+    CSSValueID id = value->id;
+    RefPtrWillBeRawPtr<CSSValue> xValue = nullptr;
+    RefPtrWillBeRawPtr<CSSValue> yValue = nullptr;
+    RefPtrWillBeRawPtr<CSSValue> zValue = nullptr;
+    if (id == CSSValueLeft || id == CSSValueRight) {
+        xValue = cssValuePool().createIdentifierValue(id);
+    } else if (id == CSSValueTop || id == CSSValueBottom) {
+        yValue = cssValuePool().createIdentifierValue(id);
+    } else if (id == CSSValueCenter) {
+        // Unresolved as to whether this is X or Y.
+    } else if (validUnit(value, FPercent | FLength)) {
+        xValue = createPrimitiveNumericValue(value);
+    } else {
+        return nullptr;
+    }
 
-bool CSSPropertyParser::parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtrWillBeRawPtr<CSSValue>& value, RefPtrWillBeRawPtr<CSSValue>& value2, RefPtrWillBeRawPtr<CSSValue>& value3)
+    if ((value = m_valueList->next())) {
+        id = value->id;
+        if (!xValue && (id == CSSValueLeft || id == CSSValueRight)) {
+            xValue = cssValuePool().createIdentifierValue(id);
+        } else if (!yValue && (id == CSSValueTop || id == CSSValueBottom)) {
+            yValue = cssValuePool().createIdentifierValue(id);
+        } else if (id == CSSValueCenter) {
+            // Resolved below.
+        } else if (!yValue && validUnit(value, FPercent | FLength)) {
+            yValue = createPrimitiveNumericValue(value);
+        } else {
+            return nullptr;
+        }
+
+        // If X or Y have not been resolved, they must be center.
+        if (!xValue)
+            xValue = cssValuePool().createIdentifierValue(CSSValueCenter);
+        if (!yValue)
+            yValue = cssValuePool().createIdentifierValue(CSSValueCenter);
+
+        if ((value = m_valueList->next())) {
+            if (!validUnit(value, FLength))
+                return nullptr;
+            zValue = createPrimitiveNumericValue(value);
+
+            if ((value = m_valueList->next()))
+                return nullptr;
+        }
+    } else if (!xValue) {
+        if (yValue) {
+            xValue = cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
+        } else {
+            xValue = cssValuePool().createIdentifierValue(CSSValueCenter);
+        }
+    }
+
+    RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+    list->append(xValue.release());
+    if (yValue)
+        list->append(yValue.release());
+    if (zValue)
+        list->append(zValue.release());
+    return list.release();
+}
+
+bool CSSPropertyParser::parseWebkitTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtrWillBeRawPtr<CSSValue>& value, RefPtrWillBeRawPtr<CSSValue>& value2, RefPtrWillBeRawPtr<CSSValue>& value3)
 {
     propId1 = propId;
     propId2 = propId;
@@ -7246,9 +7461,9 @@
 
     switch (propId) {
         case CSSPropertyWebkitTransformOrigin:
-            if (!parseTransformOriginShorthand(value, value2, value3))
+            if (!parseWebkitTransformOriginShorthand(value, value2, value3))
                 return false;
-            // parseTransformOriginShorthand advances the m_valueList pointer
+            // parseWebkitTransformOriginShorthand advances the m_valueList pointer
             break;
         case CSSPropertyWebkitTransformOriginX: {
             value = parseFillPositionX(m_valueList.get());
@@ -7277,7 +7492,7 @@
     return value;
 }
 
-bool CSSPropertyParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtrWillBeRawPtr<CSSValue>& value, RefPtrWillBeRawPtr<CSSValue>& value2)
+bool CSSPropertyParser::parseWebkitPerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtrWillBeRawPtr<CSSValue>& value, RefPtrWillBeRawPtr<CSSValue>& value2)
 {
     propId1 = propId;
     propId2 = propId;
diff --git a/Source/core/css/parser/CSSPropertyParser.h b/Source/core/css/parser/CSSPropertyParser.h
index c78a167..11877a3 100644
--- a/Source/core/css/parser/CSSPropertyParser.h
+++ b/Source/core/css/parser/CSSPropertyParser.h
@@ -29,6 +29,7 @@
 #include "core/css/CSSCalculationValue.h"
 #include "core/css/CSSFilterValue.h"
 #include "core/css/CSSGradientValue.h"
+#include "core/css/CSSGridTemplateAreasValue.h"
 #include "core/css/CSSParserMode.h"
 #include "core/css/CSSParserValues.h"
 #include "core/css/CSSProperty.h"
@@ -50,6 +51,7 @@
 class CSSValueList;
 class CSSBasicShape;
 class CSSBasicShapeInset;
+class CSSGridLineNamesValue;
 class Document;
 class Element;
 class ImmutableStylePropertySet;
@@ -137,7 +139,7 @@
     PassRefPtrWillBeRawPtr<CSSValue> parseAnimationProperty(AnimationParseContext&);
     PassRefPtrWillBeRawPtr<CSSValue> parseAnimationTimingFunction();
 
-    bool parseTransformOriginShorthand(RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&);
+    bool parseWebkitTransformOriginShorthand(RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&);
     bool parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result);
     bool parseAnimationProperty(CSSPropertyID, RefPtrWillBeRawPtr<CSSValue>&, AnimationParseContext&);
     bool parseTransitionShorthand(CSSPropertyID, bool important);
@@ -150,14 +152,17 @@
     PassRefPtrWillBeRawPtr<CSSValue> parseGridPosition();
     bool parseIntegerOrStringFromGridPosition(RefPtrWillBeRawPtr<CSSPrimitiveValue>& numericValue, RefPtrWillBeRawPtr<CSSPrimitiveValue>& gridLineName);
     bool parseGridItemPositionShorthand(CSSPropertyID, bool important);
+    bool parseGridTemplateRowsAndAreas(PassRefPtrWillBeRawPtr<CSSValue>, bool important);
+    bool parseGridTemplateShorthand(bool important);
     bool parseGridAreaShorthand(bool important);
     bool parseSingleGridAreaLonghand(RefPtrWillBeRawPtr<CSSValue>&);
-    bool parseGridTrackList(CSSPropertyID, bool important);
+    PassRefPtrWillBeRawPtr<CSSValue> parseGridTrackList(bool important);
     bool parseGridTrackRepeatFunction(CSSValueList&);
     PassRefPtrWillBeRawPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList);
     PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue*);
+    bool parseGridTemplateAreasRow(NamedGridAreaMap&, const size_t, size_t&);
     PassRefPtrWillBeRawPtr<CSSValue> parseGridTemplateAreas();
-    void parseGridLineNames(CSSParserValueList* inputList, CSSValueList&);
+    void parseGridLineNames(CSSParserValueList&, CSSValueList&, CSSGridLineNamesValue* = 0);
 
     bool parseClipShape(CSSPropertyID, bool important);
 
@@ -237,10 +242,11 @@
     static bool isBlendMode(CSSValueID);
     static bool isCompositeOperator(CSSValueID);
 
-    PassRefPtrWillBeRawPtr<CSSValueList> parseTransform();
-    PassRefPtrWillBeRawPtr<CSSValue> parseTransformValue(CSSParserValue*);
-    bool parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&);
-    bool parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2,  RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&);
+    PassRefPtrWillBeRawPtr<CSSValueList> parseTransformOrigin();
+    PassRefPtrWillBeRawPtr<CSSValueList> parseTransform(CSSPropertyID);
+    PassRefPtrWillBeRawPtr<CSSValue> parseTransformValue(CSSPropertyID, CSSParserValue*);
+    bool parseWebkitTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&);
+    bool parseWebkitPerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2,  RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&);
 
     bool parseTextEmphasisStyle(bool important);
 
diff --git a/Source/core/css/parser/MediaQueryParser.cpp b/Source/core/css/parser/MediaQueryParser.cpp
index a4afb61..108a299 100644
--- a/Source/core/css/parser/MediaQueryParser.cpp
+++ b/Source/core/css/parser/MediaQueryParser.cpp
@@ -25,7 +25,7 @@
 const MediaQueryParser::State MediaQueryParser::ReadFeatureValue = &MediaQueryParser::readFeatureValue;
 const MediaQueryParser::State MediaQueryParser::ReadFeatureEnd = &MediaQueryParser::readFeatureEnd;
 const MediaQueryParser::State MediaQueryParser::SkipUntilComma = &MediaQueryParser::skipUntilComma;
-const MediaQueryParser::State MediaQueryParser::SkipUntilParenthesis = &MediaQueryParser::skipUntilParenthesis;
+const MediaQueryParser::State MediaQueryParser::SkipUntilBlockEnd = &MediaQueryParser::skipUntilBlockEnd;
 const MediaQueryParser::State MediaQueryParser::Done = &MediaQueryParser::done;
 
 // FIXME: Replace the MediaQueryTokenizer with a generic CSSTokenizer, once there is one,
@@ -111,7 +111,7 @@
         --token;
         m_state = ReadFeatureEnd;
     } else {
-        m_state = SkipUntilParenthesis;
+        m_state = SkipUntilBlockEnd;
     }
 }
 
@@ -136,31 +136,69 @@
         m_mediaQueryData.addParserValue(type, *token);
         m_state = ReadFeatureValue;
     } else {
-        m_state = SkipUntilParenthesis;
+        m_state = SkipUntilBlockEnd;
     }
 }
 
 void MediaQueryParser::skipUntilComma(MediaQueryTokenType type, TokenIterator& token)
 {
-    if (type == CommaToken || type == EOFToken) {
+    if ((type == CommaToken && m_blockStack.isEmpty()) || type == EOFToken) {
         m_state = ReadRestrictor;
         m_mediaQueryData.clear();
         m_querySet->addMediaQuery(MediaQuery::createNotAll());
     }
 }
 
-void MediaQueryParser::skipUntilParenthesis(MediaQueryTokenType type, TokenIterator& token)
+void MediaQueryParser::skipUntilBlockEnd(MediaQueryTokenType type, TokenIterator& token)
 {
-    if (type == RightParenthesisToken)
+    if (m_blockStack.isEmpty())
         m_state = SkipUntilComma;
 }
 
 void MediaQueryParser::done(MediaQueryTokenType type, TokenIterator& token) { }
 
+void MediaQueryParser::popIfBlockMatches(Vector<BlockType>& blockStack, BlockType type)
+{
+    if (!blockStack.isEmpty() && blockStack.last() == type)
+        blockStack.removeLast();
+}
+
+bool MediaQueryParser::observeBlock(BlockParameters& parameters, MediaQueryTokenType type)
+{
+    if (type == parameters.leftToken) {
+        if (parameters.stateChange == ModifyState)
+            m_state = SkipUntilBlockEnd;
+        m_blockStack.append(parameters.blockType);
+    } else if (type == parameters.rightToken) {
+        popIfBlockMatches(m_blockStack, parameters.blockType);
+    } else {
+        return false;
+    }
+    return true;
+}
+
+void MediaQueryParser::observeBlocks(MediaQueryTokenType type)
+{
+    enum { BlockParametersCount = 4 };
+    BlockParameters blockParameterSet[BlockParametersCount] = {
+        { LeftParenthesisToken, RightParenthesisToken, ParenthesisBlock, DoNotModifyState },
+        { FunctionToken, RightParenthesisToken, ParenthesisBlock, ModifyState },
+        { LeftBracketToken, RightBracketToken, BracketsBlock, ModifyState },
+        { LeftBraceToken, RightBraceToken, BracesBlock, ModifyState }
+    };
+
+    for (unsigned i = 0; i < BlockParametersCount; ++i) {
+        if (observeBlock(blockParameterSet[i], type))
+            break;
+    }
+}
+
 void MediaQueryParser::processToken(TokenIterator& token)
 {
     MediaQueryTokenType type = token->type();
 
+    observeBlocks(type);
+
     // Call the function that handles current state
     if (type != WhitespaceToken && type != CommentToken)
         ((this)->*(m_state))(type, token);
diff --git a/Source/core/css/parser/MediaQueryParser.h b/Source/core/css/parser/MediaQueryParser.h
index fcb82c5..27496a7 100644
--- a/Source/core/css/parser/MediaQueryParser.h
+++ b/Source/core/css/parser/MediaQueryParser.h
@@ -58,6 +58,24 @@
 
     typedef Vector<MediaQueryToken>::iterator TokenIterator;
 
+    enum BlockType {
+        ParenthesisBlock,
+        BracketsBlock,
+        BracesBlock
+    };
+
+    enum StateChange {
+        ModifyState,
+        DoNotModifyState
+    };
+
+    struct BlockParameters {
+        MediaQueryTokenType leftToken;
+        MediaQueryTokenType rightToken;
+        BlockType blockType;
+        StateChange stateChange;
+    };
+
     void processToken(TokenIterator&);
 
     void readRestrictor(MediaQueryTokenType, TokenIterator&);
@@ -69,17 +87,21 @@
     void readFeatureValue(MediaQueryTokenType, TokenIterator&);
     void readFeatureEnd(MediaQueryTokenType, TokenIterator&);
     void skipUntilComma(MediaQueryTokenType, TokenIterator&);
-    void skipUntilParenthesis(MediaQueryTokenType, TokenIterator&);
+    void skipUntilBlockEnd(MediaQueryTokenType, TokenIterator&);
     void done(MediaQueryTokenType, TokenIterator&);
 
     typedef void (MediaQueryParser::*State)(MediaQueryTokenType, TokenIterator&);
 
     void setStateAndRestrict(State, MediaQuery::Restrictor);
+    bool observeBlock(BlockParameters&, MediaQueryTokenType);
+    void observeBlocks(MediaQueryTokenType);
+    static void popIfBlockMatches(Vector<MediaQueryParser::BlockType>& blockStack, BlockType);
 
     State m_state;
     Vector<MediaQueryToken> m_tokens;
     MediaQueryData m_mediaQueryData;
     RefPtrWillBeMember<MediaQuerySet> m_querySet;
+    Vector<BlockType> m_blockStack;
 
     const static State ReadRestrictor;
     const static State ReadMediaType;
@@ -90,7 +112,7 @@
     const static State ReadFeatureValue;
     const static State ReadFeatureEnd;
     const static State SkipUntilComma;
-    const static State SkipUntilParenthesis;
+    const static State SkipUntilBlockEnd;
     const static State Done;
 
 };
diff --git a/Source/core/css/parser/MediaQueryToken.h b/Source/core/css/parser/MediaQueryToken.h
index 4629ef3..156ff79 100644
--- a/Source/core/css/parser/MediaQueryToken.h
+++ b/Source/core/css/parser/MediaQueryToken.h
@@ -23,8 +23,12 @@
     CommaToken = 9,
     LeftParenthesisToken = 10,
     RightParenthesisToken = 11,
-    EOFToken = 12,
-    CommentToken = 13,
+    LeftBracketToken = 12,
+    RightBracketToken = 13,
+    LeftBraceToken = 14,
+    RightBraceToken = 15,
+    EOFToken = 16,
+    CommentToken = 17,
 };
 
 enum NumericValueType {
diff --git a/Source/core/css/parser/MediaQueryTokenizer.cpp b/Source/core/css/parser/MediaQueryTokenizer.cpp
index df0ea53..4e09cc2 100644
--- a/Source/core/css/parser/MediaQueryTokenizer.cpp
+++ b/Source/core/css/parser/MediaQueryTokenizer.cpp
@@ -77,6 +77,26 @@
     return MediaQueryToken(RightParenthesisToken);
 }
 
+MediaQueryToken MediaQueryTokenizer::leftBracket(UChar cc)
+{
+    return MediaQueryToken(LeftBracketToken);
+}
+
+MediaQueryToken MediaQueryTokenizer::rightBracket(UChar cc)
+{
+    return MediaQueryToken(RightBracketToken);
+}
+
+MediaQueryToken MediaQueryTokenizer::leftBrace(UChar cc)
+{
+    return MediaQueryToken(LeftBraceToken);
+}
+
+MediaQueryToken MediaQueryTokenizer::rightBrace(UChar cc)
+{
+    return MediaQueryToken(RightBraceToken);
+}
+
 MediaQueryToken MediaQueryTokenizer::plusOrFullStop(UChar cc)
 {
     if (nextCharsAreNumber()) {
@@ -333,20 +353,19 @@
 {
     // FIXME: Is this as efficient as it can be?
     // The possibility of escape chars mandates a copy AFAICT.
-    Vector<UChar> result;
+    StringBuilder result;
     while (true) {
-        if (isNameChar(m_input.currentInputChar())) {
-            result.append(consume());
+        UChar cc = consume();
+        if (isNameChar(cc)) {
+            result.append(cc);
             continue;
         }
-        if (nextTwoCharsAreValidEscape()) {
-            // "consume()" fixes a spec bug.
-            // The first code point should be consumed before consuming the escaped code point.
-            consume();
+        if (twoCharsAreValidEscape(cc, m_input.currentInputChar())) {
             result.append(consumeEscape());
             continue;
         }
-        return String(result);
+        reconsume(cc);
+        return result.toString();
     }
 }
 
@@ -357,14 +376,15 @@
     ASSERT(cc != '\n');
     if (isASCIIHexDigit(cc)) {
         unsigned consumedHexDigits = 1;
-        String hexChars;
-        do {
-            hexChars.append(cc);
+        StringBuilder hexChars;
+        hexChars.append(cc);
+        while (consumedHexDigits < 6 && isASCIIHexDigit(m_input.currentInputChar())) {
             cc = consume();
+            hexChars.append(cc);
             consumedHexDigits++;
-        } while (consumedHexDigits < 6 && isASCIIHexDigit(cc));
+        };
         bool ok = false;
-        UChar codePoint = hexChars.toUIntStrict(&ok, 16);
+        UChar codePoint = hexChars.toString().toUIntStrict(&ok, 16);
         if (!ok)
             return WTF::Unicode::replacementCharacter;
         return codePoint;
@@ -376,11 +396,11 @@
     return cc;
 }
 
-bool MediaQueryTokenizer::nextTwoCharsAreValidEscape()
+bool MediaQueryTokenizer::nextTwoCharsAreValidEscape(unsigned offset)
 {
-    if (m_input.leftChars() < 2)
+    if (m_input.leftChars() < offset + 1)
         return false;
-    return twoCharsAreValidEscape(m_input.peek(1), m_input.peek(2));
+    return twoCharsAreValidEscape(m_input.peek(offset), m_input.peek(offset + 1));
 }
 
 // http://www.w3.org/TR/css3-syntax/#starts-with-a-number
@@ -401,13 +421,13 @@
 bool MediaQueryTokenizer::nextCharsAreIdentifier()
 {
     UChar firstChar = m_input.currentInputChar();
-    if (isNameStart(firstChar) || nextTwoCharsAreValidEscape())
+    if (isNameStart(firstChar) || nextTwoCharsAreValidEscape(0))
         return true;
 
     if (firstChar == '-') {
         if (isNameStart(m_input.peek(1)))
             return true;
-        return nextTwoCharsAreValidEscape();
+        return nextTwoCharsAreValidEscape(1);
     }
 
     return false;
diff --git a/Source/core/css/parser/MediaQueryTokenizer.h b/Source/core/css/parser/MediaQueryTokenizer.h
index b31c0cb..0625d28 100644
--- a/Source/core/css/parser/MediaQueryTokenizer.h
+++ b/Source/core/css/parser/MediaQueryTokenizer.h
@@ -40,7 +40,7 @@
     String consumeName();
     UChar consumeEscape();
 
-    bool nextTwoCharsAreValidEscape();
+    bool nextTwoCharsAreValidEscape(unsigned offset);
     bool nextCharsAreNumber();
     bool nextCharsAreIdentifier();
 
@@ -51,6 +51,10 @@
     MediaQueryToken whiteSpace(UChar);
     MediaQueryToken leftParenthesis(UChar);
     MediaQueryToken rightParenthesis(UChar);
+    MediaQueryToken leftBracket(UChar);
+    MediaQueryToken rightBracket(UChar);
+    MediaQueryToken leftBrace(UChar);
+    MediaQueryToken rightBrace(UChar);
     MediaQueryToken plusOrFullStop(UChar);
     MediaQueryToken comma(UChar);
     MediaQueryToken hyphenMinus(UChar);
diff --git a/Source/core/css/parser/MediaQueryTokenizerTest.cpp b/Source/core/css/parser/MediaQueryTokenizerTest.cpp
index ea08889..48a972b 100644
--- a/Source/core/css/parser/MediaQueryTokenizerTest.cpp
+++ b/Source/core/css/parser/MediaQueryTokenizerTest.cpp
@@ -19,6 +19,7 @@
 {
     TestCase testCases[] = {
         { "(max-width: 50px)", "(max-width: 50px)" },
+        { "(max-width: 50\\70\\78)", "(max-width: 50px)" },
         { "(max-width: /* comment */50px)", "(max-width: 50px)" },
         { "(max-width: /** *commen*t */60px)", "(max-width: 60px)" },
         { "(max-width: /** *commen*t **/70px)", "(max-width: 70px)" },
@@ -66,6 +67,14 @@
             testToken(c, LeftParenthesisToken);
         else if (c == ')')
             testToken(c, RightParenthesisToken);
+        else if (c == '[')
+            testToken(c, LeftBracketToken);
+        else if (c == ']')
+            testToken(c, RightBracketToken);
+        else if (c == '{')
+            testToken(c, LeftBraceToken);
+        else if (c == '}')
+            testToken(c, RightBraceToken);
         else if (c == '.' || c == '+' || c == '-' || c == '/' || c == '\\')
             testToken(c, DelimiterToken);
         else if (c == ',')
diff --git a/Source/core/css/resolver/AnimatedStyleBuilder.cpp b/Source/core/css/resolver/AnimatedStyleBuilder.cpp
index 22dca93..70f3200 100644
--- a/Source/core/css/resolver/AnimatedStyleBuilder.cpp
+++ b/Source/core/css/resolver/AnimatedStyleBuilder.cpp
@@ -40,6 +40,7 @@
 #include "core/animation/AnimatableLengthBox.h"
 #include "core/animation/AnimatableLengthBoxAndBool.h"
 #include "core/animation/AnimatableLengthPoint.h"
+#include "core/animation/AnimatableLengthPoint3D.h"
 #include "core/animation/AnimatableLengthSize.h"
 #include "core/animation/AnimatableRepeatable.h"
 #include "core/animation/AnimatableSVGLength.h"
@@ -553,13 +554,22 @@
     case CSSPropertyWebkitMaskSize:
         setOnFillLayers<CSSPropertyWebkitMaskSize>(style->accessMaskLayers(), value, state);
         return;
-    case CSSPropertyWebkitPerspective:
+    case CSSPropertyPerspective:
         style->setPerspective(clampTo<float>(toAnimatableDouble(value)->toDouble()));
         return;
+    case CSSPropertyPerspectiveOrigin: {
+        ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
+        const AnimatableLengthPoint* animatableLengthPoint = toAnimatableLengthPoint(value);
+        style->setPerspectiveOriginX(animatableValueToLength(animatableLengthPoint->x(), state));
+        style->setPerspectiveOriginY(animatableValueToLength(animatableLengthPoint->y(), state));
+        return;
+    }
     case CSSPropertyWebkitPerspectiveOriginX:
+        ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
         style->setPerspectiveOriginX(animatableValueToLength(value, state));
         return;
     case CSSPropertyWebkitPerspectiveOriginY:
+        ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
         style->setPerspectiveOriginY(animatableValueToLength(value, state));
         return;
     case CSSPropertyShapeOutside:
@@ -575,19 +585,30 @@
         style->setTextStrokeColor(toAnimatableColor(value)->color());
         style->setVisitedLinkTextStrokeColor(toAnimatableColor(value)->visitedLinkColor());
         return;
-    case CSSPropertyWebkitTransform: {
+    case CSSPropertyTransform: {
         const TransformOperations& operations = toAnimatableTransform(value)->transformOperations();
         // FIXME: This normalization (handling of 'none') should be performed at input in AnimatableValueFactory.
         style->setTransform(operations.size() ? operations : TransformOperations(true));
         return;
     }
+    case CSSPropertyTransformOrigin: {
+        ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
+        const AnimatableLengthPoint3D* animatableLengthPoint3D = toAnimatableLengthPoint3D(value);
+        style->setTransformOriginX(animatableValueToLength(animatableLengthPoint3D->x(), state));
+        style->setTransformOriginY(animatableValueToLength(animatableLengthPoint3D->y(), state));
+        style->setTransformOriginZ(clampTo<float>(toAnimatableDouble(animatableLengthPoint3D->z())->toDouble()));
+        return;
+    }
     case CSSPropertyWebkitTransformOriginX:
+        ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
         style->setTransformOriginX(animatableValueToLength(value, state));
         return;
     case CSSPropertyWebkitTransformOriginY:
+        ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
         style->setTransformOriginY(animatableValueToLength(value, state));
         return;
     case CSSPropertyWebkitTransformOriginZ:
+        ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
         style->setTransformOriginZ(toAnimatableDouble(value)->toDouble());
         return;
     case CSSPropertyWidows:
diff --git a/Source/core/css/resolver/ElementResolveContext.h b/Source/core/css/resolver/ElementResolveContext.h
index 04056fe..0b3996e 100644
--- a/Source/core/css/resolver/ElementResolveContext.h
+++ b/Source/core/css/resolver/ElementResolveContext.h
@@ -34,6 +34,7 @@
 
 // ElementResolveContext is immutable and serves as an input to the style resolve process.
 class ElementResolveContext {
+    STACK_ALLOCATED();
 public:
     ElementResolveContext()
         : m_element(0)
diff --git a/Source/core/css/resolver/SharedStyleFinder.cpp b/Source/core/css/resolver/SharedStyleFinder.cpp
index 021f0b6..16ebf2f 100644
--- a/Source/core/css/resolver/SharedStyleFinder.cpp
+++ b/Source/core/css/resolver/SharedStyleFinder.cpp
@@ -212,16 +212,8 @@
         return false;
     if (candidate.isLink() != element().isLink())
         return false;
-    if (candidate.hovered() != element().hovered())
-        return false;
-    if (candidate.active() != element().active())
-        return false;
-    if (candidate.focused() != element().focused())
-        return false;
     if (candidate.shadowPseudoId() != element().shadowPseudoId())
         return false;
-    if (candidate == document().cssTarget())
-        return false;
     if (!sharingCandidateHasIdenticalStyleAffectingAttributes(candidate))
         return false;
     if (candidate.additionalPresentationAttributeStyle() != element().additionalPresentationAttributeStyle())
diff --git a/Source/core/css/resolver/SharedStyleFinder.h b/Source/core/css/resolver/SharedStyleFinder.h
index 0c263cd..e41c3aa 100644
--- a/Source/core/css/resolver/SharedStyleFinder.h
+++ b/Source/core/css/resolver/SharedStyleFinder.h
@@ -36,6 +36,7 @@
 class StyleResolver;
 
 class SharedStyleFinder {
+    STACK_ALLOCATED();
 public:
     // RuleSets are passed non-const as the act of matching against them can cause them
     // to be compacted. :(
@@ -72,8 +73,8 @@
 
     bool m_elementAffectedByClassRules;
     const RuleFeatureSet& m_features;
-    RuleSet* m_siblingRuleSet;
-    RuleSet* m_uncommonAttributeRuleSet;
+    RawPtrWillBeMember<RuleSet> m_siblingRuleSet;
+    RawPtrWillBeMember<RuleSet> m_uncommonAttributeRuleSet;
     StyleResolver& m_styleResolver;
     const ElementResolveContext& m_context;
 };
diff --git a/Source/core/css/resolver/StyleAdjuster.cpp b/Source/core/css/resolver/StyleAdjuster.cpp
index 624d735..af6781c 100644
--- a/Source/core/css/resolver/StyleAdjuster.cpp
+++ b/Source/core/css/resolver/StyleAdjuster.cpp
@@ -34,6 +34,7 @@
 #include "core/dom/ContainerNode.h"
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
+#include "core/dom/NodeRenderStyle.h"
 #include "core/html/HTMLIFrameElement.h"
 #include "core/html/HTMLInputElement.h"
 #include "core/html/HTMLTableCellElement.h"
@@ -166,9 +167,11 @@
     for (size_t i = 0; i < style->willChangeProperties().size(); ++i) {
         switch (style->willChangeProperties()[i]) {
         case CSSPropertyOpacity:
+        case CSSPropertyTransform:
         case CSSPropertyWebkitTransform:
         case CSSPropertyTransformStyle:
         case CSSPropertyWebkitTransformStyle:
+        case CSSPropertyPerspective:
         case CSSPropertyWebkitPerspective:
         case CSSPropertyWebkitMask:
         case CSSPropertyWebkitMaskBoxImage:
@@ -236,7 +239,7 @@
 
     // will-change:transform should result in the same rendering behavior as having a transform,
     // including the creation of a containing block for fixed position descendants.
-    if (!style->hasTransform() && style->willChangeProperties().contains(CSSPropertyWebkitTransform)) {
+    if (!style->hasTransform() && (style->willChangeProperties().contains(CSSPropertyWebkitTransform) || style->willChangeProperties().contains(CSSPropertyTransform))) {
         bool makeIdentity = true;
         style->setTransform(TransformOperations(makeIdentity));
     }
@@ -281,6 +284,13 @@
         if ((isSVGForeignObjectElement(*e) || isSVGTextElement(*e)) && style->isDisplayInlineType())
             style->setDisplay(BLOCK);
     }
+
+    if (e && e->renderStyle() && e->renderStyle()->textAutosizingMultiplier() != 1) {
+        // Preserve the text autosizing multiplier on style recalc.
+        // (The autosizer will update it during layout if it needs to be changed.)
+        style->setTextAutosizingMultiplier(e->renderStyle()->textAutosizingMultiplier());
+        style->setUnique();
+    }
 }
 
 void StyleAdjuster::adjustStyleForTagName(RenderStyle* style, RenderStyle* parentStyle, Element& element)
diff --git a/Source/core/css/resolver/StyleBuilderCustom.cpp b/Source/core/css/resolver/StyleBuilderCustom.cpp
index 6e0ba84..25509fd 100644
--- a/Source/core/css/resolver/StyleBuilderCustom.cpp
+++ b/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -582,6 +582,121 @@
         state.style()->setTextIndentLine(TextIndentFirstLine);
 }
 
+void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state)
+{
+    applyInitialCSSPropertyWebkitTransformOriginX(state);
+    applyInitialCSSPropertyWebkitTransformOriginY(state);
+    applyInitialCSSPropertyWebkitTransformOriginZ(state);
+}
+
+void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state)
+{
+    applyInheritCSSPropertyWebkitTransformOriginX(state);
+    applyInheritCSSPropertyWebkitTransformOriginY(state);
+    applyInheritCSSPropertyWebkitTransformOriginZ(state);
+}
+
+void StyleBuilderFunctions::applyValueCSSPropertyTransformOrigin(StyleResolverState& state, CSSValue* value)
+{
+    CSSValueList* list = toCSSValueList(value);
+    ASSERT(list->length() == 3);
+    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
+    if (primitiveValue->isValueID()) {
+        switch (primitiveValue->getValueID()) {
+        case CSSValueLeft:
+            state.style()->setTransformOriginX(Length(0, Percent));
+            break;
+        case CSSValueRight:
+            state.style()->setTransformOriginX(Length(100, Percent));
+            break;
+        case CSSValueCenter:
+            state.style()->setTransformOriginX(Length(50, Percent));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    } else {
+        state.style()->setTransformOriginX(StyleBuilderConverter::convertLength(state, primitiveValue));
+    }
+
+    primitiveValue = toCSSPrimitiveValue(list->item(1));
+    if (primitiveValue->isValueID()) {
+        switch (primitiveValue->getValueID()) {
+        case CSSValueTop:
+            state.style()->setTransformOriginY(Length(0, Percent));
+            break;
+        case CSSValueBottom:
+            state.style()->setTransformOriginY(Length(100, Percent));
+            break;
+        case CSSValueCenter:
+            state.style()->setTransformOriginY(Length(50, Percent));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    } else {
+        state.style()->setTransformOriginY(StyleBuilderConverter::convertLength(state, primitiveValue));
+    }
+
+    primitiveValue = toCSSPrimitiveValue(list->item(2));
+    state.style()->setTransformOriginZ(StyleBuilderConverter::convertComputedLength<float>(state, primitiveValue));
+}
+
+void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state)
+{
+    applyInitialCSSPropertyWebkitPerspectiveOriginX(state);
+    applyInitialCSSPropertyWebkitPerspectiveOriginY(state);
+}
+
+void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state)
+{
+    applyInheritCSSPropertyWebkitPerspectiveOriginX(state);
+    applyInheritCSSPropertyWebkitPerspectiveOriginY(state);
+}
+
+void StyleBuilderFunctions::applyValueCSSPropertyPerspectiveOrigin(StyleResolverState& state, CSSValue* value)
+{
+    CSSValueList* list = toCSSValueList(value);
+    ASSERT(list->length() == 2);
+    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
+    if (primitiveValue->isValueID()) {
+        switch (primitiveValue->getValueID()) {
+        case CSSValueLeft:
+            state.style()->setPerspectiveOriginX(Length(0, Percent));
+            break;
+        case CSSValueRight:
+            state.style()->setPerspectiveOriginX(Length(100, Percent));
+            break;
+        case CSSValueCenter:
+            state.style()->setPerspectiveOriginX(Length(50, Percent));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    } else {
+        state.style()->setPerspectiveOriginX(StyleBuilderConverter::convertLength(state, primitiveValue));
+    }
+
+    primitiveValue = toCSSPrimitiveValue(list->item(1));
+    if (primitiveValue->isValueID()) {
+        switch (primitiveValue->getValueID()) {
+        case CSSValueTop:
+            state.style()->setPerspectiveOriginY(Length(0, Percent));
+            break;
+        case CSSValueBottom:
+            state.style()->setPerspectiveOriginY(Length(100, Percent));
+            break;
+        case CSSValueCenter:
+            state.style()->setPerspectiveOriginY(Length(50, Percent));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    } else {
+        state.style()->setPerspectiveOriginY(StyleBuilderConverter::convertLength(state, primitiveValue));
+    }
+}
+
 void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value)
 {
     if (!value->isPrimitiveValue())
@@ -1339,6 +1454,7 @@
     case CSSPropertyWebkitColumnRule:
     case CSSPropertyFlex:
     case CSSPropertyFlexFlow:
+    case CSSPropertyGridTemplate:
     case CSSPropertyGridColumn:
     case CSSPropertyGridRow:
     case CSSPropertyGridArea:
@@ -1422,6 +1538,7 @@
         state.style()->setTextStrokeWidth(width);
         return;
     }
+    case CSSPropertyTransform:
     case CSSPropertyWebkitTransform: {
         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
         TransformOperations operations;
@@ -1429,6 +1546,7 @@
         state.style()->setTransform(operations);
         return;
     }
+    case CSSPropertyPerspective:
     case CSSPropertyWebkitPerspective: {
         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
 
@@ -1443,8 +1561,8 @@
         float perspectiveValue;
         if (primitiveValue->isLength()) {
             perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData());
-        } else if (primitiveValue->isNumber()) {
-            // For backward compatibility, treat valueless numbers as px.
+        } else if (id == CSSPropertyWebkitPerspective && primitiveValue->isNumber()) {
+            // Prefixed version treats unitless numbers as px.
             perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData());
         } else {
             return;
@@ -1740,12 +1858,6 @@
         return;
     }
 
-    // FIXME: crbug.com/154772 Unimplemented css-transforms properties
-    case CSSPropertyPerspective:
-    case CSSPropertyPerspectiveOrigin:
-    case CSSPropertyTransform:
-    case CSSPropertyTransformOrigin:
-        return;
     // These properties are aliased and we already applied the property on the prefixed version.
     case CSSPropertyAnimationDelay:
     case CSSPropertyAnimationDirection:
@@ -1950,6 +2062,7 @@
     case CSSPropertyWebkitMaskRepeatX:
     case CSSPropertyWebkitMaskRepeatY:
     case CSSPropertyWebkitMaskSize:
+    case CSSPropertyPerspectiveOrigin:
     case CSSPropertyWebkitPerspectiveOrigin:
     case CSSPropertyWebkitPerspectiveOriginX:
     case CSSPropertyWebkitPerspectiveOriginY:
@@ -1967,6 +2080,7 @@
     case CSSPropertyWebkitTransformOriginX:
     case CSSPropertyWebkitTransformOriginY:
     case CSSPropertyWebkitTransformOriginZ:
+    case CSSPropertyTransformOrigin:
     case CSSPropertyTransformStyle:
     case CSSPropertyWebkitTransformStyle:
     case CSSPropertyWebkitTransitionDelay:
@@ -1979,7 +2093,6 @@
     case CSSPropertyWebkitClipPath:
     case CSSPropertyWebkitWrapFlow:
     case CSSPropertyShapeMargin:
-    case CSSPropertyShapePadding:
     case CSSPropertyShapeImageThreshold:
     case CSSPropertyWebkitWrapThrough:
     case CSSPropertyShapeOutside:
diff --git a/Source/core/css/resolver/StyleResolver.cpp b/Source/core/css/resolver/StyleResolver.cpp
index 0d1fee7..4094b23 100644
--- a/Source/core/css/resolver/StyleResolver.cpp
+++ b/Source/core/css/resolver/StyleResolver.cpp
@@ -1084,7 +1084,7 @@
     // the style to impose the stacking rules. Note that this is also
     // done in StyleResolver::adjustRenderStyle().
     RenderStyle* style = state.style();
-    if (style->hasAutoZIndex() && (style->opacity() < 1.0f || style->hasTransform()))
+    if (style->hasAutoZIndex() && (style->opacity() < 1.0f || style->hasTransformRelatedProperty()))
         style->setZIndex(0);
 
     // Start loading resources used by animations.
diff --git a/Source/core/css/resolver/ViewportStyleResolver.cpp b/Source/core/css/resolver/ViewportStyleResolver.cpp
index 2a5d3f1..84b1c11 100644
--- a/Source/core/css/resolver/ViewportStyleResolver.cpp
+++ b/Source/core/css/resolver/ViewportStyleResolver.cpp
@@ -45,8 +45,8 @@
 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ViewportStyleResolver);
 
 ViewportStyleResolver::ViewportStyleResolver(Document* document)
-    : m_document(document),
-    m_hasAuthorStyle(false)
+    : m_document(document)
+    , m_hasAuthorStyle(false)
 {
     ASSERT(m_document);
 }
@@ -87,10 +87,8 @@
     if (!m_document)
         return;
 
-    if (!m_propertySet || (!m_hasAuthorStyle && m_document->hasLegacyViewportTag())) {
-        ASSERT(!m_hasAuthorStyle);
-        m_propertySet = nullptr;
-        m_document->setViewportDescription(ViewportDescription());
+    if (!m_propertySet) {
+        m_document->setViewportDescription(ViewportDescription(ViewportDescription::UserAgentStyleSheet));
         return;
     }