Merge autoland to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Sun, 11 Jun 2017 22:06:02 -0400
changeset 411521 e80316ec40e40f3cfd5a438bf17abc1980ea4c06
parent 411516 981da978f1f686ad024fa958c9d27d2f8acc5ad0 (current diff)
parent 411520 acacb9c914f1deb3cc6f879abc8587d6a023b9f6 (diff)
child 411527 042829191d730dd6e901d09fb62bbf4274fe5895
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to m-c. a=merge
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1758,16 +1758,26 @@ MediaCache::NoteSeek(MediaCacheStream* a
   }
 }
 
 void
 MediaCacheStream::NotifyDataLength(int64_t aLength)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
+  if (mStreamLength < 0 && aLength >= 0) {
+    uint32_t length = uint32_t(std::min(aLength, int64_t(UINT32_MAX)));
+    LOG("MediaCacheStream::NotifyDataLength(this=%p) "
+        "MEDIACACHESTREAM_NOTIFIED_LENGTH=%" PRIu32,
+        this,
+        length);
+    Telemetry::Accumulate(
+      Telemetry::HistogramID::MEDIACACHESTREAM_NOTIFIED_LENGTH, length);
+  }
+
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   mStreamLength = aLength;
 }
 
 void
 MediaCacheStream::NotifyDataStarted(int64_t aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
--- a/layout/generic/Selection.h
+++ b/layout/generic/Selection.h
@@ -432,17 +432,17 @@ private:
   // proves to be a performance concern, then an interval tree may be a
   // possible solution, allowing the calculation of the overlap interval in
   // O(log n) time, though this would require rebalancing and other overhead.
   nsTArray<RangeData> mRanges;
 
   RefPtr<nsRange> mAnchorFocusRange;
   RefPtr<nsFrameSelection> mFrameSelection;
   RefPtr<nsAutoScrollTimer> mAutoScrollTimer;
-  nsCOMArray<nsISelectionListener> mSelectionListeners;
+  FallibleTArray<nsCOMPtr<nsISelectionListener>> mSelectionListeners;
   nsRevocableEventPtr<ScrollSelectionIntoViewEvent> mScrollEvent;
   CachedOffsetForFrame* mCachedOffsetForFrame;
   nsDirection mDirection;
   SelectionType mSelectionType;
   UniquePtr<SelectionCustomColors> mCustomColors;
 
   /**
    * True if the current selection operation was initiated by user action.
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -18,17 +18,16 @@
 #include "nsString.h"
 #include "nsFrameSelection.h"
 #include "nsISelectionListener.h"
 #include "nsContentCID.h"
 #include "nsDeviceContext.h"
 #include "nsIContent.h"
 #include "nsIDOMNode.h"
 #include "nsRange.h"
-#include "nsCOMArray.h"
 #include "nsITableCellLayout.h"
 #include "nsTArray.h"
 #include "nsTableWrapperFrame.h"
 #include "nsTableCellFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsIContentIterator.h"
 #include "nsIDocumentEncoder.h"
@@ -6360,17 +6359,17 @@ Selection::AddSelectionListener(nsISelec
   }
   return NS_OK;
 }
 
 void
 Selection::AddSelectionListener(nsISelectionListener* aNewListener,
                                 ErrorResult& aRv)
 {
-  bool result = mSelectionListeners.AppendObject(aNewListener); // AddRefs
+  bool result = mSelectionListeners.AppendElement(aNewListener, fallible); // AddRefs
   if (!result) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 NS_IMETHODIMP
 Selection::RemoveSelectionListener(nsISelectionListener* aListenerToRemove)
 {
@@ -6383,17 +6382,17 @@ Selection::RemoveSelectionListener(nsISe
   }
   return NS_OK;
 }
 
 void
 Selection::RemoveSelectionListener(nsISelectionListener* aListenerToRemove,
                                    ErrorResult& aRv)
 {
-  bool result = mSelectionListeners.RemoveObject(aListenerToRemove); // Releases
+  bool result = mSelectionListeners.RemoveElement(aListenerToRemove); // Releases
   if (!result) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 Element*
 Selection::GetCommonEditingHostForAllRanges()
 {
@@ -6485,31 +6484,28 @@ Selection::NotifySelectionListeners()
     }
   }
 
   RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
   if (frameSelection->GetBatching()) {
     frameSelection->SetDirty();
     return NS_OK;
   }
-  nsCOMArray<nsISelectionListener> selectionListeners(mSelectionListeners);
-  int32_t cnt = selectionListeners.Count();
-  if (cnt != mSelectionListeners.Count()) {
-    return NS_ERROR_OUT_OF_MEMORY;  // nsCOMArray is fallible
-  }
+  AutoTArray<nsCOMPtr<nsISelectionListener>, 8>
+    selectionListeners(mSelectionListeners);
 
   nsCOMPtr<nsIDOMDocument> domdoc;
   nsIPresShell* ps = GetPresShell();
   if (ps) {
     domdoc = do_QueryInterface(ps->GetDocument());
   }
 
   short reason = frameSelection->PopReason();
-  for (int32_t i = 0; i < cnt; i++) {
-    selectionListeners[i]->NotifySelectionChanged(domdoc, this, reason);
+  for (auto& listener : selectionListeners) {
+    listener->NotifySelectionChanged(domdoc, this, reason);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Selection::StartBatchChanges()
 {
   if (mFrameSelection) {
--- a/servo/components/style/counter_style/mod.rs
+++ b/servo/components/style/counter_style/mod.rs
@@ -290,33 +290,31 @@ pub enum System {
         first_symbol_value: Option<i32>
     },
     /// 'extends <counter-style-name>'
     Extends(CustomIdent),
 }
 
 impl Parse for System {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "cyclic" => Ok(System::Cyclic),
             "numeric" => Ok(System::Numeric),
             "alphabetic" => Ok(System::Alphabetic),
             "symbolic" => Ok(System::Symbolic),
             "additive" => Ok(System::Additive),
             "fixed" => {
                 let first_symbol_value = input.try(|i| i.expect_integer()).ok();
                 Ok(System::Fixed { first_symbol_value: first_symbol_value })
             }
             "extends" => {
                 let other = parse_counter_style_name(input)?;
                 Ok(System::Extends(other))
             }
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 }
 
 impl ToCss for System {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             System::Cyclic => dest.write_str("cyclic"),
             System::Numeric => dest.write_str("numeric"),
@@ -612,29 +610,29 @@ pub enum SpeakAs {
     // SpellOut,
     /// <counter-style-name>
     Other(CustomIdent),
 }
 
 impl Parse for SpeakAs {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         let mut is_spell_out = false;
-        let result: Result<_, ParseError> = input.try(|input| {
-            let ident = input.expect_ident()?;
-            (match_ignore_ascii_case! { &ident,
+        let result = input.try(|input| {
+            let ident = input.expect_ident().map_err(|_| ())?;
+            match_ignore_ascii_case! { &*ident,
                 "auto" => Ok(SpeakAs::Auto),
                 "bullets" => Ok(SpeakAs::Bullets),
                 "numbers" => Ok(SpeakAs::Numbers),
                 "words" => Ok(SpeakAs::Words),
                 "spell-out" => {
                     is_spell_out = true;
                     Err(())
                 }
-                _ => Err(())
-            }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+                _ => Err(()),
+            }
         });
         if is_spell_out {
             // spell-out is not supported, but don’t parse it as a <counter-style-name>.
             // See bug 1024178.
             return Err(StyleParseError::UnspecifiedError.into())
         }
         result.or_else(|_| {
             Ok(SpeakAs::Other(parse_counter_style_name(input)?))
--- a/servo/components/style/gecko_string_cache/mod.rs
+++ b/servo/components/style/gecko_string_cache/mod.rs
@@ -143,21 +143,18 @@ impl WeakAtom {
     #[inline]
     pub fn to_string(&self) -> String {
         String::from_utf16(self.as_slice()).unwrap()
     }
 
     /// Returns whether this atom is static.
     #[inline]
     pub fn is_static(&self) -> bool {
-        // FIXME(emilio): re-introduce bitfield accessors:
-        //
-        // https://github.com/servo/rust-bindgen/issues/519
         unsafe {
-            ((*self.as_ptr())._bitfield_1 & (0x80000000 as u32)) != 0
+            (*self.as_ptr()).mIsStatic() != 0
         }
     }
 
     /// Returns the length of the atom string.
     #[inline]
     pub fn len(&self) -> u32 {
         // FIXME(emilio): re-introduce bitfield accessors:
         //
--- a/servo/components/style/macros.rs
+++ b/servo/components/style/macros.rs
@@ -1,14 +1,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Various macro helpers.
 
+/// A macro to parse an identifier, or return an `UnexpectedIndent` error
+/// otherwise.
+///
+/// FIXME(emilio): The fact that `UnexpectedIdent` is a `SelectorParseError`
+/// doesn't make a lot of sense to me.
+macro_rules! try_match_ident_ignore_ascii_case {
+    ($ident:expr, $( $match_body:tt )*) => {
+        let __ident = $ident;
+        (match_ignore_ascii_case! { &*__ident,
+            $( $match_body )*
+            _ => Err(()),
+        })
+        .map_err(|()| {
+            ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident).into()
+        })
+    }
+}
+
 macro_rules! define_numbered_css_keyword_enum {
     ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => {
         define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
     };
     ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
         #[allow(non_camel_case_types, missing_docs)]
         #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
@@ -16,21 +34,19 @@ macro_rules! define_numbered_css_keyword
             $( $variant = $value ),+
         }
 
         impl $crate::parser::Parse for $name {
             #[allow(missing_docs)]
             fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
                              input: &mut ::cssparser::Parser<'i, 't>)
                              -> Result<$name, ::style_traits::ParseError<'i>> {
-                let ident = try!(input.expect_ident());
-                (match_ignore_ascii_case! { &ident,
+                try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                     $( $css => Ok($name::$variant), )+
-                    _ => Err(())
-                }).map_err(|()| ::selectors::parser::SelectorParseError::UnexpectedIdent(ident).into())
+                }
             }
         }
 
         impl ::style_traits::values::ToCss for $name {
             fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
                 where W: ::std::fmt::Write,
             {
                 match *self {
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -110,25 +110,23 @@
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T::${to_rust_ident(values[0])}
     }
 
     /// Parse a display value.
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        let ident = try!(input.expect_ident());
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             % for value in values:
                 "${value}" => {
                     Ok(computed_value::T::${to_rust_ident(value)})
                 },
             % endfor
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
 
     % if product == "servo":
         fn cascade_property_custom(_declaration: &PropertyDeclaration,
                                    _inherited_style: &ComputedValues,
                                    context: &mut computed::Context,
@@ -290,27 +288,25 @@
                 SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest),
             }
         }
     }
     /// baseline | sub | super | top | text-top | middle | bottom | text-bottom
     /// | <percentage> | <length>
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes))
-        .map(SpecifiedValue::LengthOrPercentage)
-        .or_else(|_| {
-            let ident = try!(input.expect_ident());
-            (match_ignore_ascii_case! { &ident,
-                % for keyword in vertical_align_keywords:
-                    "${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
-                % endfor
-                _ => Err(())
-            }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
-        })
+        if let Ok(lop) = input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes)) {
+            return Ok(SpecifiedValue::LengthOrPercentage(lop));
+        }
+
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
+            % for keyword in vertical_align_keywords:
+                "${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
+            % endfor
+        }
     }
 
     /// The computed value for `vertical-align`.
     pub mod computed_value {
         use std::fmt;
         use style_traits::ToCss;
         use values::computed;
 
@@ -1992,18 +1988,17 @@
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         TOUCH_ACTION_AUTO
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "auto" => Ok(TOUCH_ACTION_AUTO),
             "none" => Ok(TOUCH_ACTION_NONE),
             "manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
             "pan-x" => {
                 if input.try(|i| i.expect_ident_matching("pan-y")).is_ok() {
                     Ok(TOUCH_ACTION_PAN_X | TOUCH_ACTION_PAN_Y)
                 } else {
                     Ok(TOUCH_ACTION_PAN_X)
@@ -2011,15 +2006,14 @@
             },
             "pan-y" => {
                 if input.try(|i| i.expect_ident_matching("pan-x")).is_ok() {
                     Ok(TOUCH_ACTION_PAN_X | TOUCH_ACTION_PAN_Y)
                 } else {
                     Ok(TOUCH_ACTION_PAN_Y)
                 }
             },
-            _ => Err(()),
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 
     #[cfg(feature = "gecko")]
     impl_bitflags_conversions!(SpecifiedValue);
 </%helpers:longhand>
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -1,17 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 <% from data import Method, to_camel_case, to_rust_ident, to_camel_case_lower, SYSTEM_FONT_LONGHANDS %>
 
-<% data.new_style_struct("Font",
-                         inherited=True) %>
+<% data.new_style_struct("Font", inherited=True) %>
 
 <%def name="nongecko_unreachable()">
     %if product == "gecko":
         ${caller.body()}
     %else:
         unreachable!()
     %endif
 </%def>
@@ -442,25 +441,25 @@ macro_rules! impl_gecko_keyword_from_tra
                 SpecifiedValue::System(_) => Ok(())
             }
         }
     }
 
     /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        let result: Result<_, ParseError> = input.try(|input| {
-            let ident = try!(input.expect_ident());
-            (match_ignore_ascii_case! { &ident,
+        let result = input.try(|input| {
+            let ident = input.expect_ident().map_err(|_| ())?;
+            match_ignore_ascii_case! { &ident,
                 "normal" => Ok(SpecifiedValue::Normal),
                 "bold" => Ok(SpecifiedValue::Bold),
                 "bolder" => Ok(SpecifiedValue::Bolder),
                 "lighter" => Ok(SpecifiedValue::Lighter),
                 _ => Err(())
-            }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+            }
         });
         result.or_else(|_| {
             SpecifiedValue::from_int(input.expect_integer()?)
                 .map_err(|()| StyleParseError::UnspecifiedError.into())
         })
     }
 
     impl SpecifiedValue {
@@ -684,27 +683,25 @@ macro_rules! impl_gecko_keyword_from_tra
         // HTML font-size 7 corresponds to this value
         XXXLarge = 7,
     }
 
     pub use self::KeywordSize::*;
 
     impl KeywordSize {
         pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-            let ident = input.expect_ident()?;
-            (match_ignore_ascii_case! {&*ident,
+            try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                 "xx-small" => Ok(XXSmall),
                 "x-small" => Ok(XSmall),
                 "small" => Ok(Small),
                 "medium" => Ok(Medium),
                 "large" => Ok(Large),
                 "x-large" => Ok(XLarge),
                 "xx-large" => Ok(XXLarge),
-                _ => Err(())
-            }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+            }
         }
     }
 
     impl Default for KeywordSize {
         fn default() -> Self {
             Medium
         }
     }
@@ -926,22 +923,20 @@ macro_rules! impl_gecko_keyword_from_tra
         if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) {
             return Ok(SpecifiedValue::Length(lop))
         }
 
         if let Ok(kw) = input.try(KeywordSize::parse) {
             return Ok(SpecifiedValue::Keyword(kw, 1.))
         }
 
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! {&*ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "smaller" => Ok(SpecifiedValue::Smaller),
             "larger" => Ok(SpecifiedValue::Larger),
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 
     impl SpecifiedValue {
         pub fn system_font(f: SystemFont) -> Self {
             SpecifiedValue::System(f)
         }
         pub fn get_system(&self) -> Option<SystemFont> {
             if let SpecifiedValue::System(s) = *self {
@@ -1207,35 +1202,33 @@ macro_rules! impl_gecko_keyword_from_tra
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         SpecifiedValue { weight: true, style: true }
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         let mut result = SpecifiedValue { weight: false, style: false };
-        let ident = try!(input.expect_ident());
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "none" => Ok(result),
             "weight" => {
                 result.weight = true;
                 if input.try(|input| input.expect_ident_matching("style")).is_ok() {
                     result.style = true;
                 }
                 Ok(result)
             },
             "style" => {
                 result.style = true;
                 if input.try(|input| input.expect_ident_matching("weight")).is_ok() {
                     result.weight = true;
                 }
                 Ok(result)
             },
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 
     #[cfg(feature = "gecko")]
     impl From<u8> for SpecifiedValue {
         fn from(bits: u8) -> SpecifiedValue {
             use gecko_bindings::structs;
 
             SpecifiedValue {
@@ -2338,17 +2331,16 @@ https://drafts.csswg.org/css-fonts-4/#lo
         //! the specified system font. When the cascade function (in helpers)
         //! detects that a value has a system font, it will resolve it, and
         //! cache it on the ComputedValues. After this, it can be just fetched
         //! whenever a font longhand on the same element needs the system font.
 
         use app_units::Au;
         use cssparser::Parser;
         use properties::longhands;
-        use selectors::parser::SelectorParseError;
         use std::hash::{Hash, Hasher};
         use style_traits::ParseError;
         use values::computed::{ToComputedValue, Context};
         <%
             system_fonts = """caption icon menu message-box small-caption status-bar
                               -moz-window -moz-document -moz-workspace -moz-desktop
                               -moz-info -moz-dialog -moz-button -moz-pull-down-menu
                               -moz-list -moz-field""".split()
@@ -2460,23 +2452,21 @@ https://drafts.csswg.org/css-fonts-4/#lo
             % for name in SYSTEM_FONT_LONGHANDS:
                 pub ${name}: longhands::${name}::computed_value::T,
             % endfor
             pub system_font: SystemFont,
         }
 
         impl SystemFont {
             pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-                let ident = input.expect_ident()?;
-                (match_ignore_ascii_case! { &*ident,
+                try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                     % for font in system_fonts:
                         "${font}" => Ok(SystemFont::${to_camel_case(font)}),
                     % endfor
-                    _ => Err(())
-                }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+                }
             }
         }
     }
 % else:
     pub mod system_font {
         use cssparser::Parser;
 
         // We don't parse system fonts, but in the interest of not littering
--- a/servo/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs
@@ -190,25 +190,22 @@
         } else {
             let mut value = 0;
             // bitfield representing what we've seen so far
             // bit 1 is fill, bit 2 is stroke, bit 3 is markers
             let mut seen = 0;
             let mut pos = 0;
 
             loop {
-
                 let result: Result<_, ParseError> = input.try(|i| {
-                    let ident = i.expect_ident()?;
-                    (match_ignore_ascii_case! { &ident,
+                    try_match_ident_ignore_ascii_case! { i.expect_ident()?,
                         "fill" => Ok(FILL),
                         "stroke" => Ok(STROKE),
                         "markers" => Ok(MARKERS),
-                        _ => Err(())
-                    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
+                    }
                 });
 
                 match result {
                     Ok(val) => {
                         if (seen & (1 << val)) != 0 {
                             // don't parse the same ident twice
                             return Err(StyleParseError::UnspecifiedError.into())
                         } else {
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -101,34 +101,37 @@
         computed_value::T {
             first: Side::Clip,
             second: Side::Clip,
             sides_are_logical: true,
         }
     }
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
-        let first = try!(Side::parse(context, input));
+        let first = Side::parse(context, input)?;
         let second = input.try(|input| Side::parse(context, input)).ok();
         Ok(SpecifiedValue {
             first: first,
             second: second,
         })
     }
     impl Parse for Side {
         fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<Side, ParseError<'i>> {
-            if let Ok(ident) = input.try(|input| input.expect_ident()) {
-                (match_ignore_ascii_case! { &ident,
-                    "clip" => Ok(Side::Clip),
-                    "ellipsis" => Ok(Side::Ellipsis),
-                    _ => Err(())
-                }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
-            } else {
-                Ok(Side::String(try!(input.expect_string()).into_owned().into_boxed_str()))
+            match input.next()? {
+                Token::Ident(ident) => {
+                    try_match_ident_ignore_ascii_case! { ident,
+                        "clip" => Ok(Side::Clip),
+                        "ellipsis" => Ok(Side::Ellipsis),
+                    }
+                }
+                Token::QuotedString(v) => {
+                    Ok(Side::String(v.into_owned().into_boxed_str()))
+                }
+                other => Err(BasicParseError::UnexpectedToken(other).into()),
             }
         }
     }
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             try!(self.first.to_css(dest));
             if let Some(ref second) = self.second {
--- a/servo/components/style/properties/shorthand/box.mako.rs
+++ b/servo/components/style/properties/shorthand/box.mako.rs
@@ -10,19 +10,17 @@
     % if product == "gecko":
         use properties::longhands::overflow_x::SpecifiedValue;
     % endif
 
     pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                -> Result<Longhands, ParseError<'i>> {
         % if product == "gecko":
             let moz_kw_found = input.try(|i| {
-                let ident = i.expect_ident()?;
-                (match_ignore_ascii_case! {
-                    &ident,
+                try_match_ident_ignore_ascii_case! { i.expect_ident()?,
                     "-moz-scrollbars-horizontal" => {
                         Ok(expanded! {
                             overflow_x: SpecifiedValue::scroll,
                             overflow_y: SpecifiedValue::hidden,
                         })
                     }
                     "-moz-scrollbars-vertical" => {
                         Ok(expanded! {
@@ -31,24 +29,23 @@
                         })
                     }
                     "-moz-scrollbars-none" => {
                         Ok(expanded! {
                             overflow_x: SpecifiedValue::hidden,
                             overflow_y: SpecifiedValue::hidden,
                         })
                     }
-                    _ => Err(())
-                }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+                }
             });
             if moz_kw_found.is_ok() {
                 return moz_kw_found
             }
         % endif
-        let overflow = try!(parse_overflow(context, input));
+        let overflow = parse_overflow(context, input)?;
         Ok(expanded! {
             overflow_x: overflow,
             overflow_y: overflow,
         })
     }
 
     impl<'a> ToCss for LonghandsToSerialize<'a>  {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
--- a/servo/components/style/values/generics/grid.rs
+++ b/servo/components/style/values/generics/grid.rs
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Generic types for the handling of
 //! [grids](https://drafts.csswg.org/css-grid/).
 
 use cssparser::{Parser, serialize_identifier};
 use parser::{Parse, ParserContext};
-use selectors::parser::SelectorParseError;
 use std::{fmt, mem, usize};
 use style_traits::{ToCss, ParseError, StyleParseError};
 use values::{CSSFloat, CustomIdent};
 use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue};
 use values::specified::Integer;
 
 #[derive(PartialEq, Clone, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -345,22 +344,20 @@ impl Parse for RepeatCount {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
             if i.value() > 0 {
                 Ok(RepeatCount::Number(i))
             } else {
                 Err(StyleParseError::UnspecifiedError.into())
             }
         } else {
-            let ident = input.expect_ident()?;
-            (match_ignore_ascii_case! { &ident,
+            try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                 "auto-fill" => Ok(RepeatCount::AutoFill),
                 "auto-fit" => Ok(RepeatCount::AutoFit),
-                _ => Err(()),
-            }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+            }
         }
     }
 }
 
 impl ComputedValueAsSpecified for RepeatCount {}
 no_viewport_percentage!(RepeatCount);
 
 /// The structure containing `<line-names>` and `<track-size>` values.
--- a/servo/components/style/values/generics/mod.rs
+++ b/servo/components/style/values/generics/mod.rs
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Generic types that share their serialization implementations
 //! for both specified and computed values.
 
 use counter_style::{Symbols, parse_counter_style_name};
 use cssparser::Parser;
 use parser::{Parse, ParserContext};
-use selectors::parser::SelectorParseError;
 use std::fmt;
 use style_traits::{OneOrMoreCommaSeparated, ToCss, ParseError, StyleParseError};
 use super::CustomIdent;
 use values::specified::url::SpecifiedUrl;
 
 pub mod background;
 pub mod basic_shape;
 pub mod border;
@@ -323,23 +322,21 @@ impl<ColorType> SVGPaint<ColorType> {
             fallback: self.fallback.as_ref().map(|color| f(color))
         }
     }
 }
 
 impl<ColorType> SVGPaintKind<ColorType> {
     /// Parse a keyword value only
     fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "none" => Ok(SVGPaintKind::None),
             "context-fill" => Ok(SVGPaintKind::ContextFill),
             "context-stroke" => Ok(SVGPaintKind::ContextStroke),
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 }
 
 impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
             let fallback = input.try(|i| ColorType::parse(context, i));
             Ok(SVGPaint {
--- a/servo/components/style/values/specified/align.rs
+++ b/servo/components/style/values/specified/align.rs
@@ -338,73 +338,68 @@ impl From<AlignJustifyContent> for u16 {
 
 // auto | normal | stretch | <baseline-position>
 fn parse_auto_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>)
                                               -> Result<AlignFlags, ParseError<'i>> {
     if let Ok(baseline) = input.try(parse_baseline) {
         return Ok(baseline);
     }
 
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "auto" => Ok(ALIGN_AUTO),
         "normal" => Ok(ALIGN_NORMAL),
         "stretch" => Ok(ALIGN_STRETCH),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    }
 }
 
 // normal | stretch | <baseline-position>
 fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
     if let Ok(baseline) = input.try(parse_baseline) {
         return Ok(baseline);
     }
 
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "normal" => Ok(ALIGN_NORMAL),
         "stretch" => Ok(ALIGN_STRETCH),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    }
 }
 
 // normal | <baseline-position>
 fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
     if let Ok(baseline) = input.try(parse_baseline) {
         return Ok(baseline);
     }
 
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
-        "normal" => Ok(ALIGN_NORMAL),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    input.expect_ident_matching("normal")?;
+    Ok(ALIGN_NORMAL)
 }
 
 // <baseline-position>
 fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "baseline" => Ok(ALIGN_BASELINE),
-        "first" => return input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE).map_err(|e| e.into()),
-        "last" => return input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE).map_err(|e| e.into()),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        "first" => {
+            input.expect_ident_matching("baseline")?;
+            Ok(ALIGN_BASELINE)
+        }
+        "last" => {
+            input.expect_ident_matching("baseline")?;
+            Ok(ALIGN_LAST_BASELINE)
+        }
+    }
 }
 
 // <content-distribution>
 fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "stretch" => Ok(ALIGN_STRETCH),
         "space-between" => Ok(ALIGN_SPACE_BETWEEN),
         "space-around" => Ok(ALIGN_SPACE_AROUND),
         "space-evenly" => Ok(ALIGN_SPACE_EVENLY),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    }
 }
 
 // [ <overflow-position>? && <content-position> ]
 fn parse_overflow_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
     // <content-position> followed by optional <overflow-position>
     if let Ok(mut content) = input.try(parse_content_position) {
         if let Ok(overflow) = input.try(parse_overflow_position) {
             content |= overflow;
@@ -417,37 +412,33 @@ fn parse_overflow_content_position<'i, '
             return Ok(overflow | content)
         }
     }
     return Err(StyleParseError::UnspecifiedError.into())
 }
 
 // <content-position>
 fn parse_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "start" => Ok(ALIGN_START),
         "end" => Ok(ALIGN_END),
         "flex-start" => Ok(ALIGN_FLEX_START),
         "flex-end" => Ok(ALIGN_FLEX_END),
         "center" => Ok(ALIGN_CENTER),
         "left" => Ok(ALIGN_LEFT),
         "right" => Ok(ALIGN_RIGHT),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    }
 }
 
 // <overflow-position>
 fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "safe" => Ok(ALIGN_SAFE),
         "unsafe" => Ok(ALIGN_UNSAFE),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    }
 }
 
 // [ <overflow-position>? && <self-position> ]
 fn parse_overflow_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
     // <self-position> followed by optional <overflow-position>
     if let Ok(mut self_position) = input.try(parse_self_position) {
         if let Ok(overflow) = input.try(parse_overflow_position) {
             self_position |= overflow;
@@ -460,29 +451,27 @@ fn parse_overflow_self_position<'i, 't>(
             return Ok(overflow | self_position)
         }
     }
     return Err(StyleParseError::UnspecifiedError.into())
 }
 
 // <self-position>
 fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
-    let ident = input.expect_ident()?;
-    (match_ignore_ascii_case! { &ident,
+    try_match_ident_ignore_ascii_case! { input.expect_ident()?,
         "start" => Ok(ALIGN_START),
         "end" => Ok(ALIGN_END),
         "flex-start" => Ok(ALIGN_FLEX_START),
         "flex-end" => Ok(ALIGN_FLEX_END),
         "center" => Ok(ALIGN_CENTER),
         "left" => Ok(ALIGN_LEFT),
         "right" => Ok(ALIGN_RIGHT),
         "self-start" => Ok(ALIGN_SELF_START),
         "self-end" => Ok(ALIGN_SELF_END),
-        _ => Err(())
-    }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+    }
 }
 
 // [ legacy && [ left | right | center ] ]
 fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
     let a = input.expect_ident()?;
     let b = input.expect_ident()?;
     if a.eq_ignore_ascii_case("legacy") {
         (match_ignore_ascii_case! { &b,
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -4,17 +4,16 @@
 
 //! CSS handling for the specified value of
 //! [`basic-shape`][basic-shape]s
 //!
 //! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
 
 use cssparser::Parser;
 use parser::{Parse, ParserContext};
-use selectors::parser::SelectorParseError;
 use std::borrow::Cow;
 use std::fmt;
 use style_traits::{ToCss, ParseError, StyleParseError};
 use values::generics::basic_shape::{Circle as GenericCircle};
 use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse};
 use values::generics::basic_shape::{FillRule, BasicShape as GenericBasicShape};
 use values::generics::basic_shape::{FloatAreaShape as GenericFloatAreaShape, InsetRect as GenericInsetRect};
 use values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
@@ -86,23 +85,21 @@ impl<ReferenceBox: Parse> Parse for Shap
 }
 
 impl Parse for GeometryBox {
     fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
             return Ok(GeometryBox::ShapeBox(shape_box))
         }
 
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "fill-box" => Ok(GeometryBox::FillBox),
             "stroke-box" => Ok(GeometryBox::StrokeBox),
             "view-box" => Ok(GeometryBox::ViewBox),
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 }
 
 impl Parse for BasicShape {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         let function = input.expect_function()?;
         input.parse_nested_block(move |i| {
             (match_ignore_ascii_case! { &function,
@@ -226,22 +223,20 @@ impl ToCss for Ellipse {
 
 impl Parse for ShapeRadius {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                      -> Result<Self, ParseError<'i>> {
         if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
             return Ok(GenericShapeRadius::Length(lop))
         }
 
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "closest-side" => Ok(GenericShapeRadius::ClosestSide),
             "farthest-side" => Ok(GenericShapeRadius::FarthestSide),
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 }
 
 /// https://drafts.csswg.org/css-shapes/#basic-shape-serialization
 ///
 /// Positions get serialized differently with basic shapes. Keywords
 /// are converted to percentages where possible. Only the two or four
 /// value forms are used. In case of two keyword-percentage pairs,
--- a/servo/components/style/values/specified/border.rs
+++ b/servo/components/style/values/specified/border.rs
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Specified types for CSS values related to borders.
 
 use app_units::Au;
 use cssparser::Parser;
 use parser::{Parse, ParserContext};
-use selectors::parser::SelectorParseError;
 use style_traits::ParseError;
 use values::computed::{Context, ToComputedValue};
 use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
 use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
 use values::generics::border::BorderImageSlice as GenericBorderImageSlice;
 use values::generics::border::BorderRadius as GenericBorderRadius;
 use values::generics::rect::Rect;
 use values::specified::{AllowQuirks, Number, NumberOrPercentage};
@@ -53,23 +52,21 @@ impl BorderSideWidth {
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
         allow_quirks: AllowQuirks)
         -> Result<Self, ParseError<'i>>
     {
         if let Ok(length) = input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
             return Ok(BorderSideWidth::Length(length));
         }
-        let ident = input.expect_ident()?;
-        (match_ignore_ascii_case! { &ident,
+        try_match_ident_ignore_ascii_case! { input.expect_ident()?,
             "thin" => Ok(BorderSideWidth::Thin),
             "medium" => Ok(BorderSideWidth::Medium),
             "thick" => Ok(BorderSideWidth::Thick),
-            _ => Err(())
-        }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
+        }
     }
 }
 
 impl Parse for BorderSideWidth {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         Self::parse_quirky(context, input, AllowQuirks::No)
     }
 }
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -8437,16 +8437,26 @@
     "alert_emails": ["gsquelart@mozilla.com"],
     "bug_numbers": [1369538],
     "expires_in_version": "60",
     "kind": "linear",
     "high": 520000,
     "n_buckets": 66,
     "description": "MediaCacheStream stream length size in KB; Either known size from the HTTP header if available, or otherwise the size actually downloaded. Recorded at every MediaCacheStream destruction."
   },
+  "MEDIACACHESTREAM_NOTIFIED_LENGTH": {
+    "record_in_processes": ["main", "content"],
+    "alert_emails": ["gsquelart@mozilla.com"],
+    "bug_numbers": [1371205],
+    "expires_in_version": "60",
+    "kind": "linear",
+    "high": 16777216,
+    "n_buckets": 66,
+    "description": "MediaCacheStream stream notified length size in bytes, from the HTTP header. Recorded when each MediaCacheStream is first notified."
+  },
   "VIDEO_MFT_OUTPUT_NULL_SAMPLES": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["cpearce@mozilla.com"],
     "expires_in_version": "53",
     "kind": "enumerated",
     "n_values": 10,
     "description": "Does the WMF video decoder return success but null output? 0 = playback successful, 1 = excessive null output but able to decode some frames, 2 = excessive null output and gave up, 3 = null output but recovered, 4 = non-excessive null output without being able to decode frames.",
     "bug_numbers": [1176071]