Backed out 5 changesets (bug 865407) for Windows crashes.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 10 Jan 2014 11:50:49 -0500
changeset 173176 803536e9aac225d129d6ab431d74a3ab73e40f78
parent 173175 faafb9526e32b28f3b4647845442a3d3971183ec
child 173177 656e14ae93635886e0ac22cd889d73a175ca3d12
push id5166
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:47:54 +0000
treeherdermozilla-aurora@977eb2548b2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs865407
milestone29.0a1
backs outd3e7f639267094b2ea372e7094a3a6c806a653a2
7ba94f08b7a51d2f0e617815c0cf54448ffb9e0a
3de6e32a43469425ef4acbdabb76dfdb7be0622d
5c0572c6727b106a6bfddfc8235088fee52c3e90
5db43cac79f5dc23f5efa994c1b2aa7552510546
Backed out 5 changesets (bug 865407) for Windows crashes. Backed out changeset d3e7f6392670 (bug 865407) Backed out changeset 7ba94f08b7a5 (bug 865407) Backed out changeset 3de6e32a4346 (bug 865407) Backed out changeset 5c0572c6727b (bug 865407) Backed out changeset 5db43cac79f5 (bug 865407)
content/html/content/src/HTMLMediaElement.cpp
content/html/content/src/TextTrackManager.cpp
content/html/content/src/TextTrackManager.h
content/media/TextTrack.cpp
content/media/TextTrack.h
content/media/TextTrackCue.cpp
content/media/TextTrackCue.h
content/media/TextTrackCueList.cpp
content/media/TextTrackCueList.h
content/media/TextTrackList.cpp
content/media/TextTrackList.h
content/media/webvtt/WebVTTParserWrapper.js
content/media/webvtt/nsIWebVTTParserWrapper.idl
content/media/webvtt/vtt.jsm
dom/webidl/VTTCue.webidl
layout/style/html.css
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3672,22 +3672,22 @@ void HTMLMediaElement::FireTimeUpdate(bo
   }
   if (mFragmentEnd >= 0.0 && time >= mFragmentEnd) {
     Pause();
     mFragmentEnd = -1.0;
     mFragmentStart = -1.0;
     mDecoder->SetFragmentEndTime(mFragmentEnd);
   }
 
-  // Update the cues displaying on the video.
+  // Update visible text tracks.
   // Here mTextTrackManager can be null if the cycle collector has unlinked
   // us before our parent. In that case UnbindFromTree will call us
   // when our parent is unlinked.
   if (mTextTrackManager) {
-    mTextTrackManager->UpdateCueDisplay();
+    mTextTrackManager->Update(time);
   }
 }
 
 void HTMLMediaElement::GetCurrentSpec(nsCString& aString)
 {
   if (mLoadingSrc) {
     mLoadingSrc->GetSpec(aString);
   } else {
--- a/content/html/content/src/TextTrackManager.cpp
+++ b/content/html/content/src/TextTrackManager.cpp
@@ -3,50 +3,33 @@
 
 /* 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/. */
 
 #include "mozilla/dom/TextTrackManager.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLTrackElement.h"
-#include "mozilla/dom/TextTrack.h"
-#include "mozilla/dom/TextTrackCue.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "nsComponentManagerUtils.h"
-#include "nsVideoFrame.h"
-#include "nsIFrame.h"
-#include "nsTArrayHelpers.h"
-#include "nsIWebVTTParserWrapper.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_3(TextTrackManager, mTextTracks,
                            mPendingTextTracks, mNewCues)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TextTrackManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TextTrackManager, Release)
 
-StaticRefPtr<nsIWebVTTParserWrapper> TextTrackManager::sParserWrapper;
-
 TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
   : mMediaElement(aMediaElement)
 {
   MOZ_COUNT_CTOR(TextTrackManager);
   mNewCues = new TextTrackCueList(mMediaElement->OwnerDoc()->GetParentObject());
   mTextTracks = new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
   mPendingTextTracks =
     new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
-
-  if (!sParserWrapper) {
-    nsCOMPtr<nsIWebVTTParserWrapper> parserWrapper =
-      do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID);
-    sParserWrapper = parserWrapper;
-    ClearOnShutdown(&sParserWrapper);
-  }
 }
 
 TextTrackManager::~TextTrackManager()
 {
   MOZ_COUNT_DTOR(TextTrackManager);
 }
 
 TextTrackList*
@@ -98,52 +81,19 @@ TextTrackManager::RemoveTextTrack(TextTr
 
 void
 TextTrackManager::DidSeek()
 {
   mTextTracks->DidSeek();
 }
 
 void
-TextTrackManager::UpdateCueDisplay()
+TextTrackManager::Update(double aTime)
 {
-  nsIFrame* frame = mMediaElement->GetPrimaryFrame();
-  if (!frame) {
-    return;
-  }
-
-  nsVideoFrame* videoFrame = do_QueryFrame(frame);
-  if (!videoFrame) {
-    return;
-  }
-
-  nsCOMPtr<nsIContent> overlay = videoFrame->GetCaptionOverlay();
-  if (!overlay) {
-    return;
-  }
-
-  nsTArray<nsRefPtr<TextTrackCue> > activeCues;
-  mTextTracks->GetAllActiveCues(activeCues);
-
-  if (activeCues.Length() > 0) {
-    nsCOMPtr<nsIWritableVariant> jsCues =
-      do_CreateInstance("@mozilla.org/variant;1");
-
-    jsCues->SetAsArray(nsIDataType::VTYPE_INTERFACE,
-                       &NS_GET_IID(nsIDOMEventTarget),
-                       activeCues.Length(),
-                       static_cast<void*>(activeCues.Elements()));
-
-    nsPIDOMWindow* window = mMediaElement->OwnerDoc()->GetWindow();
-    if (window) {
-      sParserWrapper->ProcessCues(window, jsCues, overlay);
-    }
-  } else if (overlay->nsINode::Length() > 0) {
-    nsContentUtils::SetNodeTextContent(overlay, EmptyString(), true);
-  }
+  mTextTracks->Update(aTime);
 }
 
 void
 TextTrackManager::AddCue(TextTrackCue& aCue)
 {
   mNewCues->AddCue(aCue);
 }
 
--- a/content/html/content/src/TextTrackManager.h
+++ b/content/html/content/src/TextTrackManager.h
@@ -6,26 +6,21 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_TextTrackManager_h
 #define mozilla_dom_TextTrackManager_h
 
 #include "mozilla/dom/TextTrack.h"
 #include "mozilla/dom/TextTrackList.h"
 #include "mozilla/dom/TextTrackCueList.h"
-#include "mozilla/StaticPtr.h"
-
-class nsIWebVTTParserWrapper;
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMediaElement;
-class TextTrack;
-class TextTrackCue;
 
 class TextTrackManager
 {
 public:
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TextTrackManager)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TextTrackManager);
 
   TextTrackManager(HTMLMediaElement *aMediaElement);
@@ -37,60 +32,32 @@ public:
                                            const nsAString& aLanguage);
   void AddTextTrack(TextTrack* aTextTrack);
   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
   void DidSeek();
 
   void AddCue(TextTrackCue& aCue);
   void AddCues(TextTrack* aTextTrack);
 
-  /**
-   * Overview of WebVTT cuetext and anonymous content setup.
-   *
-   * WebVTT nodes are the parsed version of WebVTT cuetext. WebVTT cuetext is
-   * the portion of a WebVTT cue that specifies what the caption will actually
-   * show up as on screen.
-   *
-   * WebVTT cuetext can contain markup that loosely relates to HTML markup. It
-   * can contain tags like <b>, <u>, <i>, <c>, <v>, <ruby>, <rt>, <lang>,
-   * including timestamp tags.
-   *
-   * When the caption is ready to be displayed the WebVTT nodes are converted
-   * over to anonymous DOM content. <i>, <u>, <b>, <ruby>, and <rt> all become
-   * HTMLElements of their corresponding HTML markup tags. <c> and <v> are
-   * converted to <span> tags. Timestamp tags are converted to XML processing
-   * instructions. Additionally, all cuetext tags support specifying of classes.
-   * This takes the form of <foo.class.subclass>. These classes are then parsed
-   * and set as the anonymous content's class attribute.
-   *
-   * Rules on constructing DOM objects from WebVTT nodes can be found here
-   * http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules.
-   * Current rules are taken from revision on April 15, 2013.
-   */
-
-  /**
-   * Converts the TextTrackCue's cuetext into a tree of DOM objects and attaches
-   * it to a div on it's owning TrackElement's MediaElement's caption overlay.
-   */
-  void UpdateCueDisplay();
+  // Update the display of cues on the video as per the current play back time
+  // of aTime.
+  void Update(double aTime);
 
   void PopulatePendingList();
 
 private:
   // The HTMLMediaElement that this TextTrackManager manages the TextTracks of.
   // This is a weak reference as the life time of TextTrackManager is dependent
   // on the HTMLMediaElement, so it should not be trying to hold the
   // HTMLMediaElement alive.
   HTMLMediaElement* mMediaElement;
   // List of the TextTrackManager's owning HTMLMediaElement's TextTracks.
   nsRefPtr<TextTrackList> mTextTracks;
   // List of text track objects awaiting loading.
   nsRefPtr<TextTrackList> mPendingTextTracks;
   // List of newly introduced Text Track cues.
   nsRefPtr<TextTrackCueList> mNewCues;
-
-  static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TextTrackManager_h
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -67,16 +67,24 @@ TextTrack::SetDefaultSettings()
   mCueList = new TextTrackCueList(mParent);
   mActiveCueList = new TextTrackCueList(mParent);
   mRegionList = new TextTrackRegionList(mParent);
   mCuePos = 0;
   mDirty = false;
   mReadyState = HTMLTrackElement::NONE;
 }
 
+void
+TextTrack::Update(double aTime)
+{
+  if (mCueList) {
+    mCueList->Update(aTime);
+  }
+}
+
 JSObject*
 TextTrack::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TextTrackBinding::Wrap(aCx, aScope, this);
 }
 
 void
 TextTrack::SetMode(TextTrackMode aValue)
@@ -129,21 +137,21 @@ TextTrack::RemoveRegion(const TextTrackR
   if (!mRegionList->GetRegionById(aRegion.Id())) {
     aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return;
   }
 
   mRegionList->RemoveTextTrackRegion(aRegion);
 }
 
-void
-TextTrack::UpdateActiveCueList()
+TextTrackCueList*
+TextTrack::GetActiveCues()
 {
   if (mMode == TextTrackMode::Disabled || !mMediaElement) {
-    return;
+    return nullptr;
   }
 
   // If we are dirty, i.e. an event happened that may cause the sorted mCueList
   // to have changed like a seek or an insert for a cue, than we need to rebuild
   // the active cue list from scratch.
   if (mDirty) {
     mCuePos = 0;
     mDirty = false;
@@ -163,31 +171,19 @@ TextTrack::UpdateActiveCueList()
   // We can stop iterating safely once we encounter a cue that does not have
   // a valid start time as the cue list is sorted.
   for (; mCuePos < mCueList->Length() &&
          (*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) {
     if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) {
       mActiveCueList->AddCue(*(*mCueList)[mCuePos]);
     }
   }
-}
-
-TextTrackCueList*
-TextTrack::GetActiveCues() {
-  UpdateActiveCueList();
   return mActiveCueList;
 }
 
-void
-TextTrack::GetActiveCueArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues)
-{
-  UpdateActiveCueList();
-  mActiveCueList->GetArray(aCues);
-}
-
 uint16_t
 TextTrack::ReadyState() const
 {
   return mReadyState;
 }
 
 void
 TextTrack::SetReadyState(uint16_t aState)
--- a/content/media/TextTrack.h
+++ b/content/media/TextTrack.h
@@ -78,42 +78,42 @@ public:
   {
     if (mMode == TextTrackMode::Disabled) {
       return nullptr;
     }
     return mCueList;
   }
 
   TextTrackCueList* GetActiveCues();
-  void GetActiveCueArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
 
   TextTrackRegionList* GetRegions() const
   {
     if (mMode != TextTrackMode::Disabled) {
       return mRegionList;
     }
     return nullptr;
   }
 
   uint16_t ReadyState() const;
   void SetReadyState(uint16_t aState);
 
   void AddRegion(TextTrackRegion& aRegion);
   void RemoveRegion(const TextTrackRegion& aRegion, ErrorResult& aRv);
 
+  // Time is in seconds.
+  void Update(double aTime);
+
   void AddCue(TextTrackCue& aCue);
   void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
   void CueChanged(TextTrackCue& aCue);
   void SetDirty() { mDirty = true; }
 
   IMPL_EVENT_HANDLER(cuechange)
 
 private:
-  void UpdateActiveCueList();
-
   nsCOMPtr<nsISupports> mParent;
   nsRefPtr<HTMLMediaElement> mMediaElement;
 
   TextTrackKind mKind;
   nsString mLabel;
   nsString mLanguage;
   nsString mType;
   nsString mId;
--- a/content/media/TextTrackCue.cpp
+++ b/content/media/TextTrackCue.cpp
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "mozilla/dom/HTMLTrackElement.h"
 #include "mozilla/dom/TextTrackCue.h"
+#include "nsIFrame.h"
+#include "nsVideoFrame.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 
 // Alternate value for the 'auto' keyword.
 #define WEBVTT_AUTO -1
 
 namespace mozilla {
 namespace dom {
@@ -94,16 +96,67 @@ TextTrackCue::StashDocument(nsISupports*
   }
   mDocument = window->GetDoc();
   if (!mDocument) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   return NS_OK;
 }
 
+void
+TextTrackCue::CreateCueOverlay()
+{
+  mDocument->CreateElem(NS_LITERAL_STRING("div"), nullptr,
+                        kNameSpaceID_XHTML,
+                        getter_AddRefs(mDisplayState));
+  nsGenericHTMLElement* cueDiv =
+    static_cast<nsGenericHTMLElement*>(mDisplayState.get());
+  cueDiv->SetClassName(NS_LITERAL_STRING("caption-text"));
+}
+
+void
+TextTrackCue::RenderCue()
+{
+  nsRefPtr<DocumentFragment> frag = GetCueAsHTML();
+  if (!frag || !mTrackElement) {
+    return;
+  }
+
+  if (!mDisplayState) {
+    CreateCueOverlay();
+  }
+
+  HTMLMediaElement* parent = mTrackElement->mMediaParent;
+  if (!parent) {
+    return;
+  }
+
+  nsIFrame* frame = parent->GetPrimaryFrame();
+  if (!frame) {
+    return;
+  }
+
+  nsVideoFrame* videoFrame = do_QueryFrame(frame);
+  if (!videoFrame) {
+    return;
+  }
+
+  nsIContent* overlay =  videoFrame->GetCaptionOverlay();
+  if (!overlay) {
+    return;
+  }
+
+  ErrorResult rv;
+  nsContentUtils::SetNodeTextContent(overlay, EmptyString(), true);
+  nsContentUtils::SetNodeTextContent(mDisplayState, EmptyString(), true);
+
+  mDisplayState->AppendChild(*frag, rv);
+  overlay->AppendChild(*mDisplayState, rv);
+}
+
 already_AddRefed<DocumentFragment>
 TextTrackCue::GetCueAsHTML()
 {
   MOZ_ASSERT(mDocument);
 
   if (!sParserWrapper) {
     nsresult rv;
     nsCOMPtr<nsIWebVTTParserWrapper> parserWrapper =
--- a/content/media/TextTrackCue.h
+++ b/content/media/TextTrackCue.h
@@ -9,17 +9,16 @@
 
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/VTTCueBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIWebVTTParserWrapper.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIDocument.h"
-#include "mozilla/dom/HTMLDivElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTrackElement;
 class TextTrack;
 
 class TextTrackCue MOZ_FINAL : public nsDOMEventTargetHelper
@@ -292,57 +291,73 @@ public:
     mReset = true;
     mText = aText;
     CueChanged();
   }
 
   IMPL_EVENT_HANDLER(enter)
   IMPL_EVENT_HANDLER(exit)
 
-  HTMLDivElement* GetDisplayState()
-  {
-    return static_cast<HTMLDivElement*>(mDisplayState.get());
-  }
-
-  void SetDisplayState(HTMLDivElement* aDisplayState)
-  {
-    mDisplayState = aDisplayState;
-  }
-
-  bool HasBeenReset()
-  {
-    return mReset;
-  }
-
   // Helper functions for implementation.
   bool
   operator==(const TextTrackCue& rhs) const
   {
     return mId.Equals(rhs.mId);
   }
 
   const nsAString& Id() const
   {
     return mId;
   }
 
   /**
+   * Overview of WebVTT cuetext and anonymous content setup.
+   *
+   * WebVTT nodes are the parsed version of WebVTT cuetext. WebVTT cuetext is
+   * the portion of a WebVTT cue that specifies what the caption will actually
+   * show up as on screen.
+   *
+   * WebVTT cuetext can contain markup that loosely relates to HTML markup. It
+   * can contain tags like <b>, <u>, <i>, <c>, <v>, <ruby>, <rt>, <lang>,
+   * including timestamp tags.
+   *
+   * When the caption is ready to be displayed the WebVTT nodes are converted
+   * over to anonymous DOM content. <i>, <u>, <b>, <ruby>, and <rt> all become
+   * HTMLElements of their corresponding HTML markup tags. <c> and <v> are
+   * converted to <span> tags. Timestamp tags are converted to XML processing
+   * instructions. Additionally, all cuetext tags support specifying of classes.
+   * This takes the form of <foo.class.subclass>. These classes are then parsed
+   * and set as the anonymous content's class attribute.
+   *
+   * Rules on constructing DOM objects from WebVTT nodes can be found here
+   * http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules.
+   * Current rules are taken from revision on April 15, 2013.
+   */
+
+  /**
+   * Converts the TextTrackCue's cuetext into a tree of DOM objects and attaches
+   * it to a div on it's owning TrackElement's MediaElement's caption overlay.
+   */
+  void RenderCue();
+
+  /**
    * Produces a tree of anonymous content based on the tree of the processed
    * cue text.
    *
    * Returns a DocumentFragment that is the head of the tree of anonymous
    * content.
    */
   already_AddRefed<DocumentFragment> GetCueAsHTML();
 
   void SetTrackElement(HTMLTrackElement* aTrackElement);
 
 private:
   void CueChanged();
   void SetDefaultCueSettings();
+  void CreateCueOverlay();
   nsresult StashDocument(nsISupports* aGlobal);
 
   nsRefPtr<nsIDocument> mDocument;
   nsString mText;
   double mStartTime;
   double mEndTime;
 
   nsRefPtr<TextTrack> mTrack;
@@ -356,17 +371,17 @@ private:
   nsString mRegionId;
   DirectionSetting mVertical;
   int mLine;
   AlignSetting mAlign;
   AlignSetting mLineAlign;
 
   // Holds the computed DOM elements that represent the parsed cue text.
   // http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-display-state
-  nsRefPtr<nsGenericHTMLElement> mDisplayState;
+  nsCOMPtr<nsIContent> mDisplayState;
   // Tells whether or not we need to recompute mDisplayState. This is set
   // anytime a property that relates to the display of the TextTrackCue is
   // changed.
   bool mReset;
 
   static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper;
 };
 
--- a/content/media/TextTrackCueList.cpp
+++ b/content/media/TextTrackCueList.cpp
@@ -33,16 +33,27 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 TextTrackCueList::TextTrackCueList(nsISupports* aParent) : mParent(aParent)
 {
   SetIsDOMBinding();
 }
 
+void
+TextTrackCueList::Update(double aTime)
+{
+  const uint32_t length = mList.Length();
+  for (uint32_t i = 0; i < length; i++) {
+    if (aTime > mList[i]->StartTime() && aTime < mList[i]->EndTime()) {
+      mList[i]->RenderCue();
+    }
+  }
+}
+
 JSObject*
 TextTrackCueList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TextTrackCueListBinding::Wrap(aCx, aScope, this);
 }
 
 TextTrackCue*
 TextTrackCueList::IndexedGetter(uint32_t aIndex, bool& aFound)
@@ -100,17 +111,10 @@ TextTrackCueList::RemoveCueAt(uint32_t a
 }
 
 void
 TextTrackCueList::RemoveAll()
 {
   mList.Clear();
 }
 
-void
-TextTrackCueList::GetArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues)
-{
-  aCues = nsTArray<nsRefPtr<TextTrackCue> >(mList);
-}
-
-
 } // namespace dom
 } // namespace mozilla
--- a/content/media/TextTrackCueList.h
+++ b/content/media/TextTrackCueList.h
@@ -36,29 +36,31 @@ public:
     return mParent;
   }
 
   uint32_t Length() const
   {
     return mList.Length();
   }
 
+  // Time is in seconds.
+  void Update(double aTime);
+
   TextTrackCue* IndexedGetter(uint32_t aIndex, bool& aFound);
   TextTrackCue* operator[](uint32_t aIndex);
   TextTrackCue* GetCueById(const nsAString& aId);
 
   // Adds a cue to mList by performing an insertion sort on mList.
   // We expect most files to already be sorted, so an insertion sort starting
   // from the end of the current array should be more efficient than a general
   // sort step after all cues are loaded.
   void AddCue(TextTrackCue& aCue);
   void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
   void RemoveCueAt(uint32_t aIndex);
   void RemoveAll();
-  void GetArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
 
 private:
   nsCOMPtr<nsISupports> mParent;
 
   // A sorted list of TextTrackCues sorted by earliest start time. If the start
   // times are equal then it will be sorted by end time, earliest first.
   nsTArray< nsRefPtr<TextTrackCue> > mList;
 };
--- a/content/media/TextTrackList.cpp
+++ b/content/media/TextTrackList.cpp
@@ -2,17 +2,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/. */
 
 #include "mozilla/dom/TextTrackList.h"
 #include "mozilla/dom/TextTrackListBinding.h"
 #include "mozilla/dom/TrackEvent.h"
 #include "nsThreadUtils.h"
-#include "mozilla/dom/TextTrackCue.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_2(TextTrackList,
                                      nsDOMEventTargetHelper,
                                      mGlobal,
                                      mTextTracks)
@@ -23,24 +22,21 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 TextTrackList::TextTrackList(nsISupports* aGlobal) : mGlobal(aGlobal)
 {
   SetIsDOMBinding();
 }
 
 void
-TextTrackList::GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues)
+TextTrackList::Update(double aTime)
 {
-  nsTArray< nsRefPtr<TextTrackCue> > cues;
-  for (uint32_t i = 0; i < Length(); i++) {
-    if (mTextTracks[i]->Mode() != TextTrackMode::Disabled) {
-      mTextTracks[i]->GetActiveCueArray(cues);
-      aCues.AppendElements(cues);
-    }
+  uint32_t length = Length(), i;
+  for (i = 0; i < length; i++) {
+    mTextTracks[i]->Update(aTime);
   }
 }
 
 JSObject*
 TextTrackList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TextTrackListBinding::Wrap(aCx, aScope, this);
 }
--- a/content/media/TextTrackList.h
+++ b/content/media/TextTrackList.h
@@ -33,18 +33,18 @@ public:
     return mGlobal;
   }
 
   uint32_t Length() const
   {
     return mTextTracks.Length();
   }
 
-  // Get all the current active cues.
-  void GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
+  // Time is in seconds.
+  void Update(double aTime);
 
   TextTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
 
   already_AddRefed<TextTrack> AddTextTrack(HTMLMediaElement* aMediaElement,
                                            TextTrackKind aKind,
                                            const nsAString& aLabel,
                                            const nsAString& aLanguage);
   TextTrack* GetTrackById(const nsAString& aId);
--- a/content/media/webvtt/WebVTTParserWrapper.js
+++ b/content/media/webvtt/WebVTTParserWrapper.js
@@ -45,21 +45,16 @@ WebVTTParserWrapper.prototype =
     this.parser.onregion = callback.onRegion;
   },
 
   convertCueToDOMTree: function(window, cue)
   {
     return WebVTTParser.convertCueToDOMTree(window, cue.text);
   },
 
-  processCues: function(window, cues, overlay)
-  {
-    WebVTTParser.processCues(window, cues, null, overlay);
-  },
-
   classDescription: "Wrapper for the JS WebVTTParser (vtt.js)",
   classID: Components.ID(WEBVTTPARSERWRAPPER_CID),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebVTTParserWrapper]),
   classInfo: XPCOMUtils.generateCI({
     classID:    WEBVTTPARSERWRAPPER_CID,
     contractID: WEBVTTPARSERWRAPPER_CONTRACTID,
     interfaces: [Ci.nsIWebVTTParserWrapper]
   })
--- a/content/media/webvtt/nsIWebVTTParserWrapper.idl
+++ b/content/media/webvtt/nsIWebVTTParserWrapper.idl
@@ -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/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMHTMLElement;
 interface nsIWebVTTListener;
 interface nsIDOMWindow;
-interface nsIVariant;
 
 /**
  * Interface for a wrapper of a JS WebVTT parser (vtt.js).
  */
 [scriptable, uuid(1604a67f-3b72-4027-bcba-6dddd5be6b10)]
 interface nsIWebVTTParserWrapper : nsISupports
 {
   /**
@@ -57,31 +56,13 @@ interface nsIWebVTTParserWrapper : nsISu
    *
    * @param window A window object with which the document fragment will be
    *               created.
    * @param cue    The cue whose content will be converted to a document
    *               fragment.
    */
   nsIDOMHTMLElement convertCueToDOMTree(in nsIDOMWindow window,
                                         in nsISupports cue);
-
-
-  /**
-   * Compute the display state of the VTTCues in cues along with any VTTRegions
-   * that they might be in. First, it computes the positioning and styling of
-   * the cues and regions passed and converts them into a DOM tree rooted at
-   * a containing HTMLDivElement. It then adjusts those computed divs for
-   * overlap avoidance using the dimensions of 'overlay'. Finally, it adds the
-   * computed divs to the VTTCues display state property for use later.
-   *
-   * @param window  A window object with which it will create the DOM tree
-   *                and containing div element.
-   * @param cues    An array of VTTCues who need there display state to be
-   *                computed.
-   * @param overlay The HTMLElement that the cues will be displayed within.
-   */
-  void processCues(in nsIDOMWindow window, in nsIVariant cues,
-                   in nsISupports overlay);
 };
 
 %{C++
 #define NS_WEBVTTPARSERWRAPPER_CONTRACTID "@mozilla.org/webvttParserWrapper;1"
 %}
--- a/content/media/webvtt/vtt.jsm
+++ b/content/media/webvtt/vtt.jsm
@@ -3,38 +3,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 this.EXPORTED_SYMBOLS = ["WebVTTParser"];
 
 /**
  * Code below is vtt.js the JS WebVTTParser.
  * Current source code can be found at http://github.com/andreasgal/vtt.js
  *
- * Code taken from commit 33a837b1ceef138a61a3b2f6fac90d5c70bd90d9
+ * Code taken from commit 355f375b6cf04763dcb1843d5683a7c489846425
  */
-(function(global) {
 
-  function ParsingError(message) {
-    this.name = "ParsingError";
-    this.message = message || "";
-  }
-  ParsingError.prototype = Object.create(Error.prototype);
-  ParsingError.prototype.constructor = ParsingError;
+(function(global) {
 
   // Try to parse input as a time stamp.
   function parseTimeStamp(input) {
 
     function computeSeconds(h, m, s, f) {
       return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
     }
 
     var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
-    if (!m) {
+    if (!m)
       return null;
-    }
 
     if (m[3]) {
       // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
       return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]);
     } else if (m[1] > 59) {
       // Timestamp takes the form of [hours]:[minutes].[milliseconds]
       // First position is hours as it's over 59.
       return computeSeconds(m[1], m[2], 0,  m[4]);
@@ -48,49 +41,46 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
   // assignment to a specific key.
   function Settings() {
     this.values = Object.create(null);
   }
 
   Settings.prototype = {
     // Only accept the first assignment to any key.
     set: function(k, v) {
-      if (!this.get(k) && v !== "") {
+      if (!this.get(k) && v !== "")
         this.values[k] = v;
-      }
     },
     // Return the value for a key, or a default value.
-    // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
-    // a number of possible default values as properties where 'defaultKey' is
-    // the key of the property that will be chosen; otherwise it's assumed to be
-    // a single value.
-    get: function(k, dflt, defaultKey) {
-      if (defaultKey) {
-        return this.has(k) ? this.values[k] : dflt[defaultKey];
-      }
+    get: function(k, dflt) {
       return this.has(k) ? this.values[k] : dflt;
     },
     // Check whether we have a value for a key.
     has: function(k) {
       return k in this.values;
     },
     // Accept a setting if its one of the given alternatives.
     alt: function(k, v, a) {
       for (var n = 0; n < a.length; ++n) {
         if (v === a[n]) {
           this.set(k, v);
           break;
         }
       }
     },
+    // Accept a region if it doesn't have the special string '-->'
+    region: function(k, v) {
+      if (!v.match(/-->/)) {
+        this.set(k, v);
+      }
+    },
     // Accept a setting if its a valid (signed) integer.
     integer: function(k, v) {
-      if (/^-?\d+$/.test(v)) { // integer
+      if (/^-?\d+$/.test(v)) // integer
         this.set(k, parseInt(v, 10));
-      }
     },
     // Accept a setting if its a valid percentage.
     percent: function(k, v, frac) {
       var m;
       if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
         v = v.replace("%", "");
         if (!m[2] || (m[2] && frac)) {
           v = parseFloat(v);
@@ -104,114 +94,83 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
     }
   };
 
   // Helper function to parse input into groups separated by 'groupDelim', and
   // interprete each group as a key/value pair separated by 'keyValueDelim'.
   function parseOptions(input, callback, keyValueDelim, groupDelim) {
     var groups = groupDelim ? input.split(groupDelim) : [input];
     for (var i in groups) {
-      if (typeof groups[i] !== "string") {
+      var kv = groups[i].split(keyValueDelim);
+      if (kv.length !== 2)
         continue;
-      }
-      var kv = groups[i].split(keyValueDelim);
-      if (kv.length !== 2) {
-        continue;
-      }
       var k = kv[0];
       var v = kv[1];
       callback(k, v);
     }
   }
 
   function parseCue(input, cue) {
     // 4.1 WebVTT timestamp
     function consumeTimeStamp() {
       var ts = parseTimeStamp(input);
-      if (ts === null) {
-        throw new ParsingError("Malformed time stamp.");
-      }
+      if (ts === null)
+        throw "error";
       // Remove time stamp from input.
       input = input.replace(/^[^\s-]+/, "");
       return ts;
     }
 
     // 4.4.2 WebVTT cue settings
     function consumeCueSettings(input, cue) {
       var settings = new Settings();
 
       parseOptions(input, function (k, v) {
         switch (k) {
         case "region":
-          settings.set(k, v);
+          settings.region(k, v);
           break;
         case "vertical":
           settings.alt(k, v, ["rl", "lr"]);
           break;
         case "line":
-          var vals = v.split(","),
-              vals0 = vals[0];
-          settings.integer(k, vals0);
-          settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
-          settings.alt(k, vals0, ["auto"]);
-          if (vals.length === 2) {
-            settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
-          }
+          settings.integer(k, v);
+          settings.percent(k, v) ? settings.set("snapToLines", false) : null;
+          settings.alt(k, v, ["auto"]);
           break;
         case "position":
-          vals = v.split(",");
-          settings.percent(k, vals[0]);
-          if (vals.length === 2) {
-            settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
-          }
-          break;
         case "size":
           settings.percent(k, v);
           break;
         case "align":
           settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
           break;
         }
       }, /:/, /\s/);
 
       // Apply default values for any missing fields.
       cue.regionId = settings.get("region", "");
       cue.vertical = settings.get("vertical", "");
       cue.line = settings.get("line", "auto");
-      cue.lineAlign = settings.get("lineAlign", "start");
       cue.snapToLines = settings.get("snapToLines", true);
+      cue.position = settings.get("position", 50);
       cue.size = settings.get("size", 100);
       cue.align = settings.get("align", "middle");
-      cue.position = settings.get("position", {
-        start: 0,
-        left: 0,
-        middle: 50,
-        end: 100,
-        right: 100
-      }, cue.align);
-      cue.positionAlign = settings.get("positionAlign", {
-        start: "start",
-        left: "start",
-        middle: "middle",
-        end: "end",
-        right: "end"
-      }, cue.align);
     }
 
     function skipWhitespace() {
       input = input.replace(/^\s+/, "");
     }
 
     // 4.1 WebVTT cue timings.
     skipWhitespace();
     cue.startTime = consumeTimeStamp();   // (1) collect cue start time
     skipWhitespace();
-    if (input.substr(0, 3) !== "-->") {     // (3) next characters must match "-->"
-      throw new ParsingError("Malformed time stamp (time stamps must be separated by '-->').");
-    }
+    if (input.substr(0, 3) !== "-->")     // (3) next characters must match "-->"
+      throw "error";
     input = input.substr(3);
     skipWhitespace();
     cue.endTime = consumeTimeStamp();     // (5) collect cue end time
 
     // 4.1 WebVTT cue settings list.
     skipWhitespace();
     consumeCueSettings(input, cue);
   }
@@ -244,19 +203,18 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
   const NEEDS_PARENT = {
     rt: "ruby"
   };
 
   // Parse content into a document fragment.
   function parseContent(window, input) {
     function nextToken() {
       // Check for end-of-string.
-      if (!input) {
+      if (!input)
         return null;
-      }
 
       // Consume 'n' characters from the input.
       function consume(result) {
         input = input.substr(result.length);
         return result;
       }
 
       var m = input.match(/^([^<]*)(<[^>]+>?)?/);
@@ -265,39 +223,36 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
       return consume(m[1] ? m[1] : m[2]);
     }
 
     // Unescape a string 's'.
     function unescape1(e) {
       return ESCAPE[e];
     }
     function unescape(s) {
-      while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
+      while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/)))
         s = s.replace(m[0], unescape1);
-      }
       return s;
     }
 
     function shouldAdd(current, element) {
       return !NEEDS_PARENT[element.localName] ||
              NEEDS_PARENT[element.localName] === current.localName;
     }
 
     // Create an element for this tag.
     function createElement(type, annotation) {
       var tagName = TAG_NAME[type];
-      if (!tagName) {
+      if (!tagName)
         return null;
-      }
       var element = window.document.createElement(tagName);
       element.localName = tagName;
       var name = TAG_ANNOTATION[type];
-      if (name && annotation) {
+      if (name && annotation)
         element[name] = annotation.trim();
-      }
       return element;
     }
 
     var rootDiv = window.document.createElement("div"),
         current = rootDiv,
         t,
         tagStack = [];
 
@@ -312,667 +267,261 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
           }
           // Otherwise just ignore the end tag.
           continue;
         }
         var ts = parseTimeStamp(t.substr(1, t.length - 2));
         var node;
         if (ts) {
           // Timestamps are lead nodes as well.
-          node = window.document.createProcessingInstruction("timestamp", ts);
+          node = window.ProcessingInstruction();
+          node.target = "timestamp";
+          node.data = ts;
           current.appendChild(node);
           continue;
         }
         var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
         // If we can't parse the tag, skip to the next tag.
-        if (!m) {
+        if (!m)
           continue;
-        }
         // Try to construct an element, and ignore the tag if we couldn't.
         node = createElement(m[1], m[3]);
-        if (!node) {
+        if (!node)
           continue;
-        }
         // Determine if the tag should be added based on the context of where it
         // is placed in the cuetext.
-        if (!shouldAdd(current, node)) {
+        if (!shouldAdd(current, node))
           continue;
-        }
         // Set the class list (as a list of classes, separated by space).
-        if (m[2]) {
+        if (m[2])
           node.className = m[2].substr(1).replace('.', ' ');
-        }
         // Append the node to the current node, and enter the scope of the new
         // node.
         tagStack.push(m[1]);
         current.appendChild(node);
         current = node;
         continue;
       }
 
       // Text nodes are leaf nodes.
       current.appendChild(window.document.createTextNode(unescape(t)));
     }
 
     return rootDiv;
   }
 
-  // This is a list of all the Unicode characters that have a strong
-  // right-to-left category. What this means is that these characters are
-  // written right-to-left for sure. It was generated by pulling all the strong
-  // right-to-left characters out of the Unicode data table. That table can
-  // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
-  var strongRTLChars = [0x05BE, 0x05C0, 0x05C3, 0x05C6, 0x05D0, 0x05D1,
-      0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA,
-      0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3,
-      0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05F0, 0x05F1,
-      0x05F2, 0x05F3, 0x05F4, 0x0608, 0x060B, 0x060D, 0x061B, 0x061E, 0x061F,
-      0x0620, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
-      0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631,
-      0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A,
-      0x063B, 0x063C, 0x063D, 0x063E, 0x063F, 0x0640, 0x0641, 0x0642, 0x0643,
-      0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x066D, 0x066E,
-      0x066F, 0x0671, 0x0672, 0x0673, 0x0674, 0x0675, 0x0676, 0x0677, 0x0678,
-      0x0679, 0x067A, 0x067B, 0x067C, 0x067D, 0x067E, 0x067F, 0x0680, 0x0681,
-      0x0682, 0x0683, 0x0684, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689, 0x068A,
-      0x068B, 0x068C, 0x068D, 0x068E, 0x068F, 0x0690, 0x0691, 0x0692, 0x0693,
-      0x0694, 0x0695, 0x0696, 0x0697, 0x0698, 0x0699, 0x069A, 0x069B, 0x069C,
-      0x069D, 0x069E, 0x069F, 0x06A0, 0x06A1, 0x06A2, 0x06A3, 0x06A4, 0x06A5,
-      0x06A6, 0x06A7, 0x06A8, 0x06A9, 0x06AA, 0x06AB, 0x06AC, 0x06AD, 0x06AE,
-      0x06AF, 0x06B0, 0x06B1, 0x06B2, 0x06B3, 0x06B4, 0x06B5, 0x06B6, 0x06B7,
-      0x06B8, 0x06B9, 0x06BA, 0x06BB, 0x06BC, 0x06BD, 0x06BE, 0x06BF, 0x06C0,
-      0x06C1, 0x06C2, 0x06C3, 0x06C4, 0x06C5, 0x06C6, 0x06C7, 0x06C8, 0x06C9,
-      0x06CA, 0x06CB, 0x06CC, 0x06CD, 0x06CE, 0x06CF, 0x06D0, 0x06D1, 0x06D2,
-      0x06D3, 0x06D4, 0x06D5, 0x06E5, 0x06E6, 0x06EE, 0x06EF, 0x06FA, 0x06FB,
-      0x06FC, 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704,
-      0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, 0x070B, 0x070C, 0x070D,
-      0x070F, 0x0710, 0x0712, 0x0713, 0x0714, 0x0715, 0x0716, 0x0717, 0x0718,
-      0x0719, 0x071A, 0x071B, 0x071C, 0x071D, 0x071E, 0x071F, 0x0720, 0x0721,
-      0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727, 0x0728, 0x0729, 0x072A,
-      0x072B, 0x072C, 0x072D, 0x072E, 0x072F, 0x074D, 0x074E, 0x074F, 0x0750,
-      0x0751, 0x0752, 0x0753, 0x0754, 0x0755, 0x0756, 0x0757, 0x0758, 0x0759,
-      0x075A, 0x075B, 0x075C, 0x075D, 0x075E, 0x075F, 0x0760, 0x0761, 0x0762,
-      0x0763, 0x0764, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769, 0x076A, 0x076B,
-      0x076C, 0x076D, 0x076E, 0x076F, 0x0770, 0x0771, 0x0772, 0x0773, 0x0774,
-      0x0775, 0x0776, 0x0777, 0x0778, 0x0779, 0x077A, 0x077B, 0x077C, 0x077D,
-      0x077E, 0x077F, 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786,
-      0x0787, 0x0788, 0x0789, 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F,
-      0x0790, 0x0791, 0x0792, 0x0793, 0x0794, 0x0795, 0x0796, 0x0797, 0x0798,
-      0x0799, 0x079A, 0x079B, 0x079C, 0x079D, 0x079E, 0x079F, 0x07A0, 0x07A1,
-      0x07A2, 0x07A3, 0x07A4, 0x07A5, 0x07B1, 0x07C0, 0x07C1, 0x07C2, 0x07C3,
-      0x07C4, 0x07C5, 0x07C6, 0x07C7, 0x07C8, 0x07C9, 0x07CA, 0x07CB, 0x07CC,
-      0x07CD, 0x07CE, 0x07CF, 0x07D0, 0x07D1, 0x07D2, 0x07D3, 0x07D4, 0x07D5,
-      0x07D6, 0x07D7, 0x07D8, 0x07D9, 0x07DA, 0x07DB, 0x07DC, 0x07DD, 0x07DE,
-      0x07DF, 0x07E0, 0x07E1, 0x07E2, 0x07E3, 0x07E4, 0x07E5, 0x07E6, 0x07E7,
-      0x07E8, 0x07E9, 0x07EA, 0x07F4, 0x07F5, 0x07FA, 0x0800, 0x0801, 0x0802,
-      0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B,
-      0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x0811, 0x0812, 0x0813, 0x0814,
-      0x0815, 0x081A, 0x0824, 0x0828, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834,
-      0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083A, 0x083B, 0x083C, 0x083D,
-      0x083E, 0x0840, 0x0841, 0x0842, 0x0843, 0x0844, 0x0845, 0x0846, 0x0847,
-      0x0848, 0x0849, 0x084A, 0x084B, 0x084C, 0x084D, 0x084E, 0x084F, 0x0850,
-      0x0851, 0x0852, 0x0853, 0x0854, 0x0855, 0x0856, 0x0857, 0x0858, 0x085E,
-      0x08A0, 0x08A2, 0x08A3, 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9,
-      0x08AA, 0x08AB, 0x08AC, 0x200F, 0xFB1D, 0xFB1F, 0xFB20, 0xFB21, 0xFB22,
-      0xFB23, 0xFB24, 0xFB25, 0xFB26, 0xFB27, 0xFB28, 0xFB2A, 0xFB2B, 0xFB2C,
-      0xFB2D, 0xFB2E, 0xFB2F, 0xFB30, 0xFB31, 0xFB32, 0xFB33, 0xFB34, 0xFB35,
-      0xFB36, 0xFB38, 0xFB39, 0xFB3A, 0xFB3B, 0xFB3C, 0xFB3E, 0xFB40, 0xFB41,
-      0xFB43, 0xFB44, 0xFB46, 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C,
-      0xFB4D, 0xFB4E, 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55,
-      0xFB56, 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D, 0xFB5E,
-      0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, 0xFB64, 0xFB65, 0xFB66, 0xFB67,
-      0xFB68, 0xFB69, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70,
-      0xFB71, 0xFB72, 0xFB73, 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79,
-      0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81, 0xFB82,
-      0xFB83, 0xFB84, 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B,
-      0xFB8C, 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
-      0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D,
-      0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, 0xFBA4, 0xFBA5, 0xFBA6,
-      0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF,
-      0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8,
-      0xFBB9, 0xFBBA, 0xFBBB, 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1,
-      0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
-      0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, 0xFBE4,
-      0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, 0xFBEC, 0xFBED,
-      0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6,
-      0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF,
-      0xFC00, 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08,
-      0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, 0xFC0F, 0xFC10, 0xFC11,
-      0xFC12, 0xFC13, 0xFC14, 0xFC15, 0xFC16, 0xFC17, 0xFC18, 0xFC19, 0xFC1A,
-      0xFC1B, 0xFC1C, 0xFC1D, 0xFC1E, 0xFC1F, 0xFC20, 0xFC21, 0xFC22, 0xFC23,
-      0xFC24, 0xFC25, 0xFC26, 0xFC27, 0xFC28, 0xFC29, 0xFC2A, 0xFC2B, 0xFC2C,
-      0xFC2D, 0xFC2E, 0xFC2F, 0xFC30, 0xFC31, 0xFC32, 0xFC33, 0xFC34, 0xFC35,
-      0xFC36, 0xFC37, 0xFC38, 0xFC39, 0xFC3A, 0xFC3B, 0xFC3C, 0xFC3D, 0xFC3E,
-      0xFC3F, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, 0xFC47,
-      0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0xFC4C, 0xFC4D, 0xFC4E, 0xFC4F, 0xFC50,
-      0xFC51, 0xFC52, 0xFC53, 0xFC54, 0xFC55, 0xFC56, 0xFC57, 0xFC58, 0xFC59,
-      0xFC5A, 0xFC5B, 0xFC5C, 0xFC5D, 0xFC5E, 0xFC5F, 0xFC60, 0xFC61, 0xFC62,
-      0xFC63, 0xFC64, 0xFC65, 0xFC66, 0xFC67, 0xFC68, 0xFC69, 0xFC6A, 0xFC6B,
-      0xFC6C, 0xFC6D, 0xFC6E, 0xFC6F, 0xFC70, 0xFC71, 0xFC72, 0xFC73, 0xFC74,
-      0xFC75, 0xFC76, 0xFC77, 0xFC78, 0xFC79, 0xFC7A, 0xFC7B, 0xFC7C, 0xFC7D,
-      0xFC7E, 0xFC7F, 0xFC80, 0xFC81, 0xFC82, 0xFC83, 0xFC84, 0xFC85, 0xFC86,
-      0xFC87, 0xFC88, 0xFC89, 0xFC8A, 0xFC8B, 0xFC8C, 0xFC8D, 0xFC8E, 0xFC8F,
-      0xFC90, 0xFC91, 0xFC92, 0xFC93, 0xFC94, 0xFC95, 0xFC96, 0xFC97, 0xFC98,
-      0xFC99, 0xFC9A, 0xFC9B, 0xFC9C, 0xFC9D, 0xFC9E, 0xFC9F, 0xFCA0, 0xFCA1,
-      0xFCA2, 0xFCA3, 0xFCA4, 0xFCA5, 0xFCA6, 0xFCA7, 0xFCA8, 0xFCA9, 0xFCAA,
-      0xFCAB, 0xFCAC, 0xFCAD, 0xFCAE, 0xFCAF, 0xFCB0, 0xFCB1, 0xFCB2, 0xFCB3,
-      0xFCB4, 0xFCB5, 0xFCB6, 0xFCB7, 0xFCB8, 0xFCB9, 0xFCBA, 0xFCBB, 0xFCBC,
-      0xFCBD, 0xFCBE, 0xFCBF, 0xFCC0, 0xFCC1, 0xFCC2, 0xFCC3, 0xFCC4, 0xFCC5,
-      0xFCC6, 0xFCC7, 0xFCC8, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE,
-      0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD4, 0xFCD5, 0xFCD6, 0xFCD7,
-      0xFCD8, 0xFCD9, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFCDE, 0xFCDF, 0xFCE0,
-      0xFCE1, 0xFCE2, 0xFCE3, 0xFCE4, 0xFCE5, 0xFCE6, 0xFCE7, 0xFCE8, 0xFCE9,
-      0xFCEA, 0xFCEB, 0xFCEC, 0xFCED, 0xFCEE, 0xFCEF, 0xFCF0, 0xFCF1, 0xFCF2,
-      0xFCF3, 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB,
-      0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04,
-      0xFD05, 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFD0D,
-      0xFD0E, 0xFD0F, 0xFD10, 0xFD11, 0xFD12, 0xFD13, 0xFD14, 0xFD15, 0xFD16,
-      0xFD17, 0xFD18, 0xFD19, 0xFD1A, 0xFD1B, 0xFD1C, 0xFD1D, 0xFD1E, 0xFD1F,
-      0xFD20, 0xFD21, 0xFD22, 0xFD23, 0xFD24, 0xFD25, 0xFD26, 0xFD27, 0xFD28,
-      0xFD29, 0xFD2A, 0xFD2B, 0xFD2C, 0xFD2D, 0xFD2E, 0xFD2F, 0xFD30, 0xFD31,
-      0xFD32, 0xFD33, 0xFD34, 0xFD35, 0xFD36, 0xFD37, 0xFD38, 0xFD39, 0xFD3A,
-      0xFD3B, 0xFD3C, 0xFD3D, 0xFD50, 0xFD51, 0xFD52, 0xFD53, 0xFD54, 0xFD55,
-      0xFD56, 0xFD57, 0xFD58, 0xFD59, 0xFD5A, 0xFD5B, 0xFD5C, 0xFD5D, 0xFD5E,
-      0xFD5F, 0xFD60, 0xFD61, 0xFD62, 0xFD63, 0xFD64, 0xFD65, 0xFD66, 0xFD67,
-      0xFD68, 0xFD69, 0xFD6A, 0xFD6B, 0xFD6C, 0xFD6D, 0xFD6E, 0xFD6F, 0xFD70,
-      0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD76, 0xFD77, 0xFD78, 0xFD79,
-      0xFD7A, 0xFD7B, 0xFD7C, 0xFD7D, 0xFD7E, 0xFD7F, 0xFD80, 0xFD81, 0xFD82,
-      0xFD83, 0xFD84, 0xFD85, 0xFD86, 0xFD87, 0xFD88, 0xFD89, 0xFD8A, 0xFD8B,
-      0xFD8C, 0xFD8D, 0xFD8E, 0xFD8F, 0xFD92, 0xFD93, 0xFD94, 0xFD95, 0xFD96,
-      0xFD97, 0xFD98, 0xFD99, 0xFD9A, 0xFD9B, 0xFD9C, 0xFD9D, 0xFD9E, 0xFD9F,
-      0xFDA0, 0xFDA1, 0xFDA2, 0xFDA3, 0xFDA4, 0xFDA5, 0xFDA6, 0xFDA7, 0xFDA8,
-      0xFDA9, 0xFDAA, 0xFDAB, 0xFDAC, 0xFDAD, 0xFDAE, 0xFDAF, 0xFDB0, 0xFDB1,
-      0xFDB2, 0xFDB3, 0xFDB4, 0xFDB5, 0xFDB6, 0xFDB7, 0xFDB8, 0xFDB9, 0xFDBA,
-      0xFDBB, 0xFDBC, 0xFDBD, 0xFDBE, 0xFDBF, 0xFDC0, 0xFDC1, 0xFDC2, 0xFDC3,
-      0xFDC4, 0xFDC5, 0xFDC6, 0xFDC7, 0xFDF0, 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4,
-      0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, 0xFE70,
-      0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A,
-      0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, 0xFE80, 0xFE81, 0xFE82, 0xFE83,
-      0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C,
-      0xFE8D, 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95,
-      0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E,
-      0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
-      0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, 0xFEB0,
-      0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9,
-      0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2,
-      0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB,
-      0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4,
-      0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD,
-      0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6,
-      0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
-      0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8,
-      0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0x10800, 0x10801, 0x10802, 0x10803,
-      0x10804, 0x10805, 0x10808, 0x1080A, 0x1080B, 0x1080C, 0x1080D, 0x1080E,
-      0x1080F, 0x10810, 0x10811, 0x10812, 0x10813, 0x10814, 0x10815, 0x10816,
-      0x10817, 0x10818, 0x10819, 0x1081A, 0x1081B, 0x1081C, 0x1081D, 0x1081E,
-      0x1081F, 0x10820, 0x10821, 0x10822, 0x10823, 0x10824, 0x10825, 0x10826,
-      0x10827, 0x10828, 0x10829, 0x1082A, 0x1082B, 0x1082C, 0x1082D, 0x1082E,
-      0x1082F, 0x10830, 0x10831, 0x10832, 0x10833, 0x10834, 0x10835, 0x10837,
-      0x10838, 0x1083C, 0x1083F, 0x10840, 0x10841, 0x10842, 0x10843, 0x10844,
-      0x10845, 0x10846, 0x10847, 0x10848, 0x10849, 0x1084A, 0x1084B, 0x1084C,
-      0x1084D, 0x1084E, 0x1084F, 0x10850, 0x10851, 0x10852, 0x10853, 0x10854,
-      0x10855, 0x10857, 0x10858, 0x10859, 0x1085A, 0x1085B, 0x1085C, 0x1085D,
-      0x1085E, 0x1085F, 0x10900, 0x10901, 0x10902, 0x10903, 0x10904, 0x10905,
-      0x10906, 0x10907, 0x10908, 0x10909, 0x1090A, 0x1090B, 0x1090C, 0x1090D,
-      0x1090E, 0x1090F, 0x10910, 0x10911, 0x10912, 0x10913, 0x10914, 0x10915,
-      0x10916, 0x10917, 0x10918, 0x10919, 0x1091A, 0x1091B, 0x10920, 0x10921,
-      0x10922, 0x10923, 0x10924, 0x10925, 0x10926, 0x10927, 0x10928, 0x10929,
-      0x1092A, 0x1092B, 0x1092C, 0x1092D, 0x1092E, 0x1092F, 0x10930, 0x10931,
-      0x10932, 0x10933, 0x10934, 0x10935, 0x10936, 0x10937, 0x10938, 0x10939,
-      0x1093F, 0x10980, 0x10981, 0x10982, 0x10983, 0x10984, 0x10985, 0x10986,
-      0x10987, 0x10988, 0x10989, 0x1098A, 0x1098B, 0x1098C, 0x1098D, 0x1098E,
-      0x1098F, 0x10990, 0x10991, 0x10992, 0x10993, 0x10994, 0x10995, 0x10996,
-      0x10997, 0x10998, 0x10999, 0x1099A, 0x1099B, 0x1099C, 0x1099D, 0x1099E,
-      0x1099F, 0x109A0, 0x109A1, 0x109A2, 0x109A3, 0x109A4, 0x109A5, 0x109A6,
-      0x109A7, 0x109A8, 0x109A9, 0x109AA, 0x109AB, 0x109AC, 0x109AD, 0x109AE,
-      0x109AF, 0x109B0, 0x109B1, 0x109B2, 0x109B3, 0x109B4, 0x109B5, 0x109B6,
-      0x109B7, 0x109BE, 0x109BF, 0x10A00, 0x10A10, 0x10A11, 0x10A12, 0x10A13,
-      0x10A15, 0x10A16, 0x10A17, 0x10A19, 0x10A1A, 0x10A1B, 0x10A1C, 0x10A1D,
-      0x10A1E, 0x10A1F, 0x10A20, 0x10A21, 0x10A22, 0x10A23, 0x10A24, 0x10A25,
-      0x10A26, 0x10A27, 0x10A28, 0x10A29, 0x10A2A, 0x10A2B, 0x10A2C, 0x10A2D,
-      0x10A2E, 0x10A2F, 0x10A30, 0x10A31, 0x10A32, 0x10A33, 0x10A40, 0x10A41,
-      0x10A42, 0x10A43, 0x10A44, 0x10A45, 0x10A46, 0x10A47, 0x10A50, 0x10A51,
-      0x10A52, 0x10A53, 0x10A54, 0x10A55, 0x10A56, 0x10A57, 0x10A58, 0x10A60,
-      0x10A61, 0x10A62, 0x10A63, 0x10A64, 0x10A65, 0x10A66, 0x10A67, 0x10A68,
-      0x10A69, 0x10A6A, 0x10A6B, 0x10A6C, 0x10A6D, 0x10A6E, 0x10A6F, 0x10A70,
-      0x10A71, 0x10A72, 0x10A73, 0x10A74, 0x10A75, 0x10A76, 0x10A77, 0x10A78,
-      0x10A79, 0x10A7A, 0x10A7B, 0x10A7C, 0x10A7D, 0x10A7E, 0x10A7F, 0x10B00,
-      0x10B01, 0x10B02, 0x10B03, 0x10B04, 0x10B05, 0x10B06, 0x10B07, 0x10B08,
-      0x10B09, 0x10B0A, 0x10B0B, 0x10B0C, 0x10B0D, 0x10B0E, 0x10B0F, 0x10B10,
-      0x10B11, 0x10B12, 0x10B13, 0x10B14, 0x10B15, 0x10B16, 0x10B17, 0x10B18,
-      0x10B19, 0x10B1A, 0x10B1B, 0x10B1C, 0x10B1D, 0x10B1E, 0x10B1F, 0x10B20,
-      0x10B21, 0x10B22, 0x10B23, 0x10B24, 0x10B25, 0x10B26, 0x10B27, 0x10B28,
-      0x10B29, 0x10B2A, 0x10B2B, 0x10B2C, 0x10B2D, 0x10B2E, 0x10B2F, 0x10B30,
-      0x10B31, 0x10B32, 0x10B33, 0x10B34, 0x10B35, 0x10B40, 0x10B41, 0x10B42,
-      0x10B43, 0x10B44, 0x10B45, 0x10B46, 0x10B47, 0x10B48, 0x10B49, 0x10B4A,
-      0x10B4B, 0x10B4C, 0x10B4D, 0x10B4E, 0x10B4F, 0x10B50, 0x10B51, 0x10B52,
-      0x10B53, 0x10B54, 0x10B55, 0x10B58, 0x10B59, 0x10B5A, 0x10B5B, 0x10B5C,
-      0x10B5D, 0x10B5E, 0x10B5F, 0x10B60, 0x10B61, 0x10B62, 0x10B63, 0x10B64,
-      0x10B65, 0x10B66, 0x10B67, 0x10B68, 0x10B69, 0x10B6A, 0x10B6B, 0x10B6C,
-      0x10B6D, 0x10B6E, 0x10B6F, 0x10B70, 0x10B71, 0x10B72, 0x10B78, 0x10B79,
-      0x10B7A, 0x10B7B, 0x10B7C, 0x10B7D, 0x10B7E, 0x10B7F, 0x10C00, 0x10C01,
-      0x10C02, 0x10C03, 0x10C04, 0x10C05, 0x10C06, 0x10C07, 0x10C08, 0x10C09,
-      0x10C0A, 0x10C0B, 0x10C0C, 0x10C0D, 0x10C0E, 0x10C0F, 0x10C10, 0x10C11,
-      0x10C12, 0x10C13, 0x10C14, 0x10C15, 0x10C16, 0x10C17, 0x10C18, 0x10C19,
-      0x10C1A, 0x10C1B, 0x10C1C, 0x10C1D, 0x10C1E, 0x10C1F, 0x10C20, 0x10C21,
-      0x10C22, 0x10C23, 0x10C24, 0x10C25, 0x10C26, 0x10C27, 0x10C28, 0x10C29,
-      0x10C2A, 0x10C2B, 0x10C2C, 0x10C2D, 0x10C2E, 0x10C2F, 0x10C30, 0x10C31,
-      0x10C32, 0x10C33, 0x10C34, 0x10C35, 0x10C36, 0x10C37, 0x10C38, 0x10C39,
-      0x10C3A, 0x10C3B, 0x10C3C, 0x10C3D, 0x10C3E, 0x10C3F, 0x10C40, 0x10C41,
-      0x10C42, 0x10C43, 0x10C44, 0x10C45, 0x10C46, 0x10C47, 0x10C48, 0x1EE00,
-      0x1EE01, 0x1EE02, 0x1EE03, 0x1EE05, 0x1EE06, 0x1EE07, 0x1EE08, 0x1EE09,
-      0x1EE0A, 0x1EE0B, 0x1EE0C, 0x1EE0D, 0x1EE0E, 0x1EE0F, 0x1EE10, 0x1EE11,
-      0x1EE12, 0x1EE13, 0x1EE14, 0x1EE15, 0x1EE16, 0x1EE17, 0x1EE18, 0x1EE19,
-      0x1EE1A, 0x1EE1B, 0x1EE1C, 0x1EE1D, 0x1EE1E, 0x1EE1F, 0x1EE21, 0x1EE22,
-      0x1EE24, 0x1EE27, 0x1EE29, 0x1EE2A, 0x1EE2B, 0x1EE2C, 0x1EE2D, 0x1EE2E,
-      0x1EE2F, 0x1EE30, 0x1EE31, 0x1EE32, 0x1EE34, 0x1EE35, 0x1EE36, 0x1EE37,
-      0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE4D, 0x1EE4E,
-      0x1EE4F, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D,
-      0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE67, 0x1EE68, 0x1EE69, 0x1EE6A,
-      0x1EE6C, 0x1EE6D, 0x1EE6E, 0x1EE6F, 0x1EE70, 0x1EE71, 0x1EE72, 0x1EE74,
-      0x1EE75, 0x1EE76, 0x1EE77, 0x1EE79, 0x1EE7A, 0x1EE7B, 0x1EE7C, 0x1EE7E,
-      0x1EE80, 0x1EE81, 0x1EE82, 0x1EE83, 0x1EE84, 0x1EE85, 0x1EE86, 0x1EE87,
-      0x1EE88, 0x1EE89, 0x1EE8B, 0x1EE8C, 0x1EE8D, 0x1EE8E, 0x1EE8F, 0x1EE90,
-      0x1EE91, 0x1EE92, 0x1EE93, 0x1EE94, 0x1EE95, 0x1EE96, 0x1EE97, 0x1EE98,
-      0x1EE99, 0x1EE9A, 0x1EE9B, 0x1EEA1, 0x1EEA2, 0x1EEA3, 0x1EEA5, 0x1EEA6,
-      0x1EEA7, 0x1EEA8, 0x1EEA9, 0x1EEAB, 0x1EEAC, 0x1EEAD, 0x1EEAE, 0x1EEAF,
-      0x1EEB0, 0x1EEB1, 0x1EEB2, 0x1EEB3, 0x1EEB4, 0x1EEB5, 0x1EEB6, 0x1EEB7,
-      0x1EEB8, 0x1EEB9, 0x1EEBA, 0x1EEBB, 0x10FFFD];
-
-  function determineBidi(cueDiv) {
-    var nodeStack = [],
-        text = "";
-
-    if (!cueDiv || !cueDiv.childNodes) {
-      return "ltr";
-    }
-
-    function pushNodes(nodeStack, node) {
-      for (var i = node.childNodes.length - 1; i >= 0; i--) {
-        nodeStack.push(node.childNodes[i]);
-      }
-    }
-
-    function nextTextNode(nodeStack) {
-      if (!nodeStack || !nodeStack.length) {
-        return null;
-      }
-
-      var node = nodeStack.pop();
-      if (node.textContent) {
-        // TODO: This should match all unicode type B characters (paragraph
-        // separator characters). See issue #115.
-        var m = node.textContent.match(/^.*(\n|\r)/);
-        if (m) {
-          nodeStack.length = 0;
-          return m[0];
-        }
-        return node.textContent;
-      }
-      if (node.tagName === "ruby") {
-        return nextTextNode(nodeStack);
-      }
-      if (node.childNodes) {
-        pushNodes(nodeStack, node);
-        return nextTextNode(nodeStack);
-      }
-    }
-
-    pushNodes(nodeStack, cueDiv);
-    while ((text = nextTextNode(nodeStack))) {
-      for (var i = 0; i < text.length; i++) {
-        if (strongRTLChars.indexOf(text.charCodeAt(i)) !== -1) {
-          return "rtl";
-        }
-      }
-    }
-    return "ltr";
-  }
-
   function computeLinePos(cue) {
     if (typeof cue.line === "number" &&
-        (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) {
+        (cue.snapToLines || (cue.line >= 0 && cue.line <= 100)))
       return cue.line;
-    }
-    if (!cue.track) {
+    if (!cue.track)
       return -1;
-    }
     // TODO: Have to figure out a way to determine what the position of the
     // Track is in the Media element's list of TextTracks and return that + 1,
     // negated.
     return 100;
   }
 
-  function BoundingBox() {
-  }
-
-  BoundingBox.prototype.applyStyles = function(styles) {
-    var div = this.div;
-    Object.keys(styles).forEach(function(style) {
-      div.style[style] = styles[style];
-    });
-  };
-
-  BoundingBox.prototype.formatStyle = function(val, unit) {
-    return val === 0 ? 0 : val + unit;
-  };
-
-  function BasicBoundingBox(window, cue) {
-    BoundingBox.call(this);
-
-    // Parse our cue's text into a DOM tree rooted at 'div'.
-    this.div = parseContent(window, cue.text);
+  function CueBoundingBox(cue) {
+    // TODO: Apply unicode bidi algorithm and assign the result to 'direction'
+    this.direction = "ltr";
 
-    // Calculate the distance from the reference edge of the viewport to the text
-    // position of the cue box. The reference edge will be resolved later when
-    // the box orientation styles are applied.
-    var textPos = 0;
-    switch (cue.positionAlign) {
-    case "start":
-      textPos = cue.position;
-      break;
-    case "middle":
-      textPos = cue.position - (cue.size / 2);
-      break;
-    case "end":
-      textPos = cue.position - cue.size;
-      break;
-    }
-
-    // Horizontal box orientation; textPos is the distance from the left edge of the
-    // area to the left edge of the box and cue.size is the distance extending to
-    // the right from there.
-    if (cue.vertical === "") {
-      this.applyStyles({
-        left:  this.formatStyle(textPos, "%"),
-        width: this.formatStyle(cue.size, "%"),
-      });
-    // Vertical box orientation; textPos is the distance from the top edge of the
-    // area to the top edge of the box and cue.size is the height extending
-    // downwards from there.
-    } else {
-      this.applyStyles({
-        top: this.formatStyle(textPos, "%"),
-        height: this.formatStyle(cue.size, "%")
-      });
-    }
+    var boxLen = (function(direction){
+      var maxLen = 0;
+      if ((cue.vertical === "" &&
+          (cue.align === "left" ||
+           (cue.align === "start" && direction === "ltr") ||
+           (cue.align === "end" && direction === "rtl"))) ||
+         ((cue.vertical === "rl" || cue.vertical === "lr") &&
+          (cue.align === "start" || cue.align === "left")))
+        maxLen = 100 - cue.position;
+      else if ((cue.vertical === "" &&
+                (cue.align === "right" ||
+                 (cue.align === "end" && direction === "ltr") ||
+                 (cue.align === "start" && direction === "rtl"))) ||
+               ((cue.vertical === "rl" || cue.vertical === "lr") &&
+                 (cue.align === "end" || cue.align === "right")))
+        maxLen = cue.position;
+      else if (cue.align === "middle") {
+        if (cue.position <= 50)
+          maxLen = cue.position * 2;
+        else
+          maxLen = (100 - cue.position) * 2;
+      }
+      return cue.size < maxLen ? cue.size : maxLen;
+    }(this.direction));
 
-    // All WebVTT cue-setting alignments are equivalent to the CSS mirrors of
-    // them except "middle" which is "center" in CSS.
-    this.applyStyles({
-      "textAlign": cue.align === "middle" ? "center" : cue.align
-    });
-  }
-  BasicBoundingBox.prototype = Object.create(BoundingBox.prototype);
-  BasicBoundingBox.prototype.constructor = BasicBoundingBox;
-
-  const CUE_FONT_SIZE = 2.5;
-  const SCROLL_DURATION = 0.433;
-  const LINE_HEIGHT = 0.0533;
-  const REGION_FONT_SIZE = 1.3;
+    this.left = (function(direction) {
+      if (cue.vertical === "") {
+        if (direction === "ltr") {
+          if (cue.align === "start" || cue.align === "left")
+            return cue.position;
+          else if (cue.align === "end" || cue.align === "right")
+            return cue.position - boxLen;
+          else if (cue.align === "middle")
+            return cue.position - (boxLen / 2);
+        } else if (direction === "rtl") {
+          if (cue.align === "end" || cue.align === "left")
+            return 100 - cue.position;
+          else if (cue.align === "start" || cue.align === "right")
+            return 100 - cue.position - boxLen;
+          else if (cue.align === "middle")
+            return 100 - cue.position - (boxLen / 2);
+        }
+      }
+      return cue.snapToLines ? 0 : computeLinePos(cue);
+    }(this.direction));
 
-  // Constructs the computed display state of the cue (a div). Places the div
-  // into the overlay which should be a block level element (usually a div).
-  function CueBoundingBox(window, cue, overlay) {
-    BasicBoundingBox.call(this, window, cue);
-    this.applyStyles({
-      direction: determineBidi(this.div),
-      writingMode: cue.vertical === "" ? "horizontal-tb"
-                                       : cue.vertical === "lr" ? "vertical-lr"
-                                                               : "vertical-rl",
-      position: "absolute",
-      unicodeBidi: "plaintext",
-      fontSize: CUE_FONT_SIZE + "vh",
-      fontFamily: "sans-serif",
-      color: "rgba(255, 255, 255, 1)",
-      backgroundColor: "rgba(0, 0, 0, 0.8)",
-      whiteSpace: "pre-line"
-    });
-
-    // Append the div to the overlay so we can get the computed styles of the
-    // element in order to position for overlap avoidance.
-    overlay.appendChild(this.div);
+    this.top = (function() {
+      if (cue.vertical === "rl" || cue.vertical === "lr") {
+        if (cue.align === "start" || cue.align === "left")
+          return cue.position;
+        else if (cue.align === "end" || cue.align === "right")
+          return cue.position - boxLen;
+        else if (cue.align === "middle")
+          return cue.position - (boxLen / 2);
+      }
+      return cue.snapToLines ? 0 : computeLinePos(cue);
+    }());
 
-    // Calculate the distance from the reference edge of the viewport to the line
-    // position of the cue box. The reference edge will be resolved later when
-    // the box orientation styles are applied. Default if snapToLines is not set
-    // is 85.
-    var linePos = 85;
-    if (!cue.snapToLines) {
-      var computedLinePos = computeLinePos(cue),
-          boxComputedStyle = window.getComputedStyle(this.div),
-          size = cue.vertical === "" ? boxComputedStyle.getPropertyValue("height") :
-                                       boxComputedStyle.getPropertyValue("width"),
-          // Get the percentage value of the computed height as getPropertyValue
-          // returns pixels.
-          overlayHeight = window.getComputedStyle(overlay).getPropertyValue("height"),
-          calculatedPercentage = (size.replace("px", "") / overlayHeight.replace("px", "")) * 100;
-
-      switch (cue.lineAlign) {
-      case "start":
-        linePos = computedLinePos;
-        break;
-      case "middle":
-        linePos = computedLinePos - (calculatedPercentage / 2);
-        break;
-      case "end":
-        linePos = computedLinePos - calculatedPercentage;
-        break;
+    // Apply a margin to the edges of the bounding box. The margin is user agent
+    // defined and is expressed as a percentage of the containing box's width.
+    var edgeMargin = 10;
+    if (cue.snapToLines) {
+      if (cue.vertical === "") {
+        if (this.left < edgeMargin && this.left + boxLen > edgeMargin) {
+          this.left += edgeMargin;
+          boxLen -= edgeMargin;
+        }
+        var rightMargin = 100 - edgeMargin;
+        if (this.left < rightMargin && this.left + boxLen > rightMargin)
+          boxLen -= edgeMargin;
+      } else if (cue.vertical === "lr" || cue.vertical === "rl") {
+        if (this.top < edgeMargin && this.top + boxLen > edgeMargin) {
+          this.top += edgeMargin;
+          boxLen -= edgeMargin;
+        }
+        var bottomMargin = 100 - edgeMargin;
+        if (this.top < bottomMargin && this.top + boxLen > bottomMargin)
+          boxLen -= edgeMargin;
       }
     }
 
-    switch (cue.vertical) {
-    case "":
-      this.applyStyles({
-        top: this.formatStyle(linePos, "%")
-      });
-      break;
-    case "rl":
-      this.applyStyles({
-        left: this.formatStyle(linePos, "%")
-      });
-      break;
-    case "lr":
-      this.applyStyles({
-        right: this.formatStyle(linePos, "%")
-      });
-      break;
-    }
-
-    cue.displayState = this.div;
-  }
-  CueBoundingBox.prototype = Object.create(BasicBoundingBox.prototype);
-  CueBoundingBox.prototype.constuctor = CueBoundingBox;
-
-  function RegionBoundingBox(window, region) {
-    BoundingBox.call(this);
-    this.div = window.document.createElement("div");
-
-    var left = region.viewportAnchorX -
-               region.regionAnchorX * region.width / 100,
-        top = region.viewportAnchorY -
-              region.regionAnchorY * region.lines * LINE_HEIGHT / 100;
+    this.height = cue.vertical === "" ? "auto" : boxLen;
+    this.width = cue.vertical === "" ? boxLen : "auto";
 
-    this.applyStyles({
-      position: "absolute",
-      writingMode: "horizontal-tb",
-      backgroundColor: "rgba(0, 0, 0, 0.8)",
-      wordWrap: "break-word",
-      overflowWrap: "break-word",
-      font: REGION_FONT_SIZE + "vh/" + LINE_HEIGHT + "vh sans-serif",
-      lineHeight: LINE_HEIGHT + "vh",
-      color: "rgba(255, 255, 255, 1)",
-      overflow: "hidden",
-      width: this.formatStyle(region.width, "%"),
-      minHeight: "0",
-      // TODO: This value is undefined in the spec, but I am assuming that they
-      // refer to lines * line height to get the max height See issue #107.
-      maxHeight: this.formatStyle(region.lines * LINE_HEIGHT, "px"),
-      left: this.formatStyle(left, "%"),
-      top: this.formatStyle(top, "%"),
-      display: "inline-flex",
-      flexFlow: "column",
-      justifyContent: "flex-end"
-    });
+    this.writingMode = cue.vertical === "" ?
+                       "horizontal-tb" :
+                       cue.vertical === "lr" ? "vertical-lr" : "vertical-rl";
+    this.position = "absolute";
+    this.unicodeBidi = "plaintext";
+    this.textAlign = cue.align === "middle" ? "center" : cue.align;
+    this.font = "5vh sans-serif";
+    this.color = "rgba(255,255,255,1)";
+    this.whiteSpace = "pre-line";
+  }
 
-    this.maybeAddCue = function(cue) {
-      if (region.id !== cue.regionId) {
-        return false;
-      }
-
-      var basicBox = new BasicBoundingBox(window, cue);
-      basicBox.applyStyles({
-        position: "relative",
-        unicodeBidi: "plaintext",
-        width: "auto"
-      });
-
-      if (this.div.childNodes.length === 1 && region.scroll === "up") {
-        this.applyStyles({
-          transitionProperty: "top",
-          transitionDuration: SCROLL_DURATION + "s"
-        });
-      }
-
-      this.div.appendChild(basicBox.div);
-      return true;
-    };
-  }
-  RegionBoundingBox.prototype = Object.create(BoundingBox.prototype);
-  RegionBoundingBox.prototype.constructor = RegionBoundingBox;
+  const WEBVTT = "WEBVTT";
 
   function WebVTTParser(window, decoder) {
     this.window = window;
     this.state = "INITIAL";
     this.buffer = "";
-    this.decoder = decoder || new TextDecoder("utf8");
+    this.decoder = decoder || TextDecoder("utf8");
   }
 
   // Helper to allow strings to be decoded instead of the default binary utf8 data.
   WebVTTParser.StringDecoder = function() {
     return {
       decode: function(data) {
-        if (!data) {
-          return "";
-        }
-        if (typeof data !== "string") {
-          throw new Error("Error - expected string data.");
-        }
+        if (!data) return "";
+        if (typeof data !== "string") throw "[StringDecoder] Error - expected string data";
+
         return decodeURIComponent(escape(data));
       }
     };
   };
 
   WebVTTParser.convertCueToDOMTree = function(window, cuetext) {
-    if (!window || !cuetext) {
+    if (!window || !cuetext)
       return null;
-    }
     return parseContent(window, cuetext);
   };
 
-  // Runs the processing model over the cues and regions passed to it.
-  // @param overlay A block level element (usually a div) that the computed cues
-  //                and regions will be placed into.
-  WebVTTParser.processCues = function(window, cues, regions, overlay) {
-    if (!window || !cues || !overlay) {
+  WebVTTParser.processCues = function(window, cues) {
+    if (!window || !cues)
       return null;
-    }
-
-    // Remove all previous children.
-    while (overlay.firstChild) {
-      overlay.removeChild(overlay.firstChild);
-    }
-
-    var regionBoxes = regions ? regions.map(function(region) {
-      return new RegionBoundingBox(window, region);
-    }) : null;
 
-    function mapCueToRegion(cue) {
-      for (var i = 0; i < regionBoxes.length; i++) {
-        if (regionBoxes[i].maybeAddCue(cue)) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    for (var i = 0; i < cues.length; i++) {
-      // Check to see if this cue is contained within a VTTRegion.
-      if (regionBoxes && mapCueToRegion(cues[i])) {
-        continue;
-      }
-      // Check to see if we can just reuse the last computed styles of the cue.
-      if (cues[i].hasBeenReset !== true && cues[i].displayState) {
-        overlay.appendChild(cues[i].displayState);
-        continue;
-      }
-      // Compute the position of the cue box on the cue overlay.
-      var cueBox = new CueBoundingBox(window, cues[i], overlay);
-    }
+    return cues.map(function(cue) {
+      var div = parseContent(window, cue.text);
+      div.style = new CueBoundingBox(cue);
+      // TODO: Adjust divs based on other cues already processed.
+      // TODO: Account for regions.
+      return div;
+    });
   };
 
   WebVTTParser.prototype = {
     parse: function (data) {
       var self = this;
 
       // If there is no data then we won't decode it, but will just try to parse
       // whatever is in buffer already. This may occur in circumstances, for
       // example when flush() is called.
       if (data) {
         // Try to decode the data that we received.
         self.buffer += self.decoder.decode(data, {stream: true});
       }
 
-      function collectNextLine() {
+      // Advance tells whether or not to remove the collected line from the buffer
+      // after it is read.
+      function collectNextLine(advance) {
         var buffer = self.buffer;
         var pos = 0;
-        while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
+        advance = typeof advance === "undefined" ? true : advance;
+        while (pos < buffer.length && buffer[pos] != '\r' && buffer[pos] != '\n')
           ++pos;
-        }
         var line = buffer.substr(0, pos);
         // Advance the buffer early in case we fail below.
-        if (buffer[pos] === '\r') {
+        if (buffer[pos] === '\r')
           ++pos;
-        }
-        if (buffer[pos] === '\n') {
+        if (buffer[pos] === '\n')
           ++pos;
-        }
-        self.buffer = buffer.substr(pos);
+        if (advance)
+          self.buffer = buffer.substr(pos);
         return line;
       }
 
       // 3.4 WebVTT region and WebVTT region settings syntax
       function parseRegion(input) {
         var settings = new Settings();
 
         parseOptions(input, function (k, v) {
           switch (k) {
           case "id":
-            settings.set(k, v);
+            settings.region(k, v);
             break;
           case "width":
             settings.percent(k, v, true);
             break;
           case "lines":
             settings.integer(k, v);
             break;
           case "regionanchor":
           case "viewportanchor":
             var xy = v.split(',');
-            if (xy.length !== 2) {
+            if (xy.length !== 2)
               break;
-            }
             // We have to make sure both x and y parse, so use a temporary
             // settings object here.
             var anchor = new Settings();
             anchor.percent("x", xy[0], true);
             anchor.percent("y", xy[1], true);
-            if (!anchor.has("x") || !anchor.has("y")) {
+            if (!anchor.has("x") || !anchor.has("y"))
               break;
-            }
             settings.set(k + "X", anchor.get("x"));
             settings.set(k + "Y", anchor.get("y"));
             break;
           case "scroll":
             settings.alt(k, v, ["up"]);
             break;
           }
         }, /=/, /\s/);
@@ -983,17 +532,17 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
           var region = new self.window.VTTRegion();
           region.id = settings.get("id");
           region.width = settings.get("width", 100);
           region.lines = settings.get("lines", 3);
           region.regionAnchorX = settings.get("regionanchorX", 0);
           region.regionAnchorY = settings.get("regionanchorY", 100);
           region.viewportAnchorX = settings.get("viewportanchorX", 0);
           region.viewportAnchorY = settings.get("viewportanchorY", 100);
-          region.scroll = settings.get("scroll", "");
+          region.scroll = settings.get("scroll", "none");
           self.onregion(region);
         }
       }
 
       // 3.2 WebVTT metadata header syntax
       function parseHeader(input) {
         parseOptions(input, function (k, v) {
           switch (k) {
@@ -1004,34 +553,43 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
           }
         }, /:/);
       }
 
       // 5.1 WebVTT file parsing.
       try {
         var line;
         if (self.state === "INITIAL") {
-          // We can't start parsing until we have the first line.
-          if (!/\r\n|\n/.test(self.buffer)) {
+          // Wait until we have enough data to parse the header.
+          if (self.buffer.length <= WEBVTT.length)
             return this;
-          }
 
-          line = collectNextLine();
-
-          var m = line.match(/^WEBVTT([ \t].*)?$/);
-          if (!m || !m[0]) {
-            throw new ParsingError("Malformed WebVTT signature.");
+          // Collect the next line, but do not remove the collected line from the
+          // buffer as we may not have the full WEBVTT signature yet when
+          // incrementally parsing.
+          line = collectNextLine(false);
+          // (4-12) - Check for the "WEBVTT" identifier followed by an optional space or tab,
+          // and ignore the rest of the line.
+          if (line.substr(0, WEBVTT.length) !== WEBVTT ||
+              line.length > WEBVTT.length && !/[ \t]/.test(line[WEBVTT.length])) {
+            throw "error";
           }
-
+          // Now that we've read the WEBVTT signature we can remove it from
+          // the buffer.
+          collectNextLine(true);
           self.state = "HEADER";
         }
 
         while (self.buffer) {
           // We can't parse a line until we have the full line.
-          if (!/\r\n|\n/.test(self.buffer)) {
+          if (!/[\r\n]/.test(self.buffer)) {
+            // If we are in the midst of parsing a cue, report it early. We will report it
+            // again when updates come in.
+            if (self.state === "CUETEXT" && self.cue && self.onpartialcue)
+              self.onpartialcue(self.cue);
             return this;
           }
 
           line = collectNextLine();
 
           switch (self.state) {
           case "HEADER":
             // 13-18 - Allow a header (metadata) under the WEBVTT line.
@@ -1039,90 +597,79 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
               parseHeader(line);
             } else if (!line) {
               // An empty line terminates the header and starts the body (cues).
               self.state = "ID";
             }
             continue;
           case "NOTE":
             // Ignore NOTE blocks.
-            if (!line) {
+            if (!line)
               self.state = "ID";
-            }
             continue;
           case "ID":
             // Check for the start of NOTE blocks.
             if (/^NOTE($|[ \t])/.test(line)) {
               self.state = "NOTE";
               break;
             }
             // 19-29 - Allow any number of line terminators, then initialize new cue values.
-            if (!line) {
+            if (!line)
               continue;
-            }
             self.cue = new self.window.VTTCue(0, 0, "");
             self.state = "CUE";
             // 30-39 - Check if self line contains an optional identifier or timing data.
-            if (line.indexOf("-->") === -1) {
+            if (line.indexOf("-->") == -1) {
               self.cue.id = line;
               continue;
             }
             // Process line as start of a cue.
             /*falls through*/
           case "CUE":
             // 40 - Collect cue timings and settings.
             try {
               parseCue(line, self.cue);
             } catch (e) {
-              // If it's not a parsing error then throw it to the consumer.
-              if (!(e instanceof ParsingError)) {
-                throw e;
-              }
               // In case of an error ignore rest of the cue.
               self.cue = null;
               self.state = "BADCUE";
               continue;
             }
             self.state = "CUETEXT";
             continue;
           case "CUETEXT":
             // 41-53 - Collect the cue text, create a cue, and add it to the output.
             if (!line) {
               // We are done parsing self cue.
               self.oncue && self.oncue(self.cue);
               self.cue = null;
               self.state = "ID";
               continue;
             }
-            if (self.cue.text) {
+            if (self.cue.text)
               self.cue.text += "\n";
-            }
             self.cue.text += line;
             continue;
-          case "BADCUE": // BADCUE
+          default: // BADCUE
             // 54-62 - Collect and discard the remaining cue.
             if (!line) {
               self.state = "ID";
             }
             continue;
           }
         }
       } catch (e) {
-        // If it's not a parsing error then throw it to the consumer.
-        if (!(e instanceof ParsingError)) {
-          throw e;
-        }
         // If we are currently parsing a cue, report what we have, and then the error.
-        if (self.state === "CUETEXT" && self.cue && self.oncue) {
+        if (self.state === "CUETEXT" && self.cue && self.oncue)
           self.oncue(self.cue);
-        }
         self.cue = null;
-        // Enter BADWEBVTT state if header was not parsed correctly otherwise
-        // another exception occurred so enter BADCUE state.
-        self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE";
+        // Report the error and enter the BADCUE state, except if we haven't even made
+        // it through the header yet.
+        if (self.state !== "INITIAL")
+          self.state = "BADCUE";
       }
       return this;
     },
     flush: function () {
       var self = this;
       // Finish decoding the stream.
       self.buffer += self.decoder.decode();
       // Synthesize the end of the current cue or region.
--- a/dom/webidl/VTTCue.webidl
+++ b/dom/webidl/VTTCue.webidl
@@ -48,16 +48,8 @@ interface VTTCue : EventTarget {
   attribute AlignSetting align;
   attribute DOMString text;
   DocumentFragment getCueAsHTML();
 
   attribute EventHandler onenter;
 
   attribute EventHandler onexit;
 };
-
-// Mozilla extensions.
-partial interface VTTCue {
-  [ChromeOnly]
-  attribute HTMLDivElement? displayState;
-  [ChromeOnly]
-  readonly attribute boolean hasBeenReset;
-};
--- a/layout/style/html.css
+++ b/layout/style/html.css
@@ -723,19 +723,35 @@ audio:not([controls]) {
 *|*::-moz-html-canvas-content {
   display: block !important;
   /* we want to be an absolute and fixed container */
   -moz-transform: translate(0) !important;
 }
 
 video > .caption-box {
   position: relative;
-  overflow: hidden;
-  padding: 1.5%;
-  box-sizing: border-box;
+  pointer-events: none;
+}
+
+video > div .caption-text {
+  position: absolute;
+  bottom: 24px;
+  padding: 5px;
+  left: 0;
+  right: 0;
+  text-align: center;
+  pointer-events: auto;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 20px;
+  color: white;
+  text-shadow:
+    -2px -2px 1px #000,
+    2px -2px 1px #000,
+    -2px 2px 1px #000,
+    2px 2px 1px #000;
 }
 
 /* emulation of non-standard HTML <marquee> tag */
 marquee {
   width: -moz-available;
   display: inline-block;
   vertical-align: text-bottom;
   text-align: start;