Merge mozilla-central and inbound
authorEd Morley <emorley@mozilla.com>
Fri, 10 Jan 2014 15:25:50 +0000
changeset 162959 3f4308d223cf7c350c240f96f67c0680ae829799
parent 162817 30f3710477c2f3cf6d939146a6950801341d6d09 (current diff)
parent 162958 d3e7f639267094b2ea372e7094a3a6c806a653a2 (diff)
child 162960 cbe9f7791348460899a877bfe8068ef6d5799b4c
push id25975
push userryanvm@gmail.com
push dateFri, 10 Jan 2014 19:46:47 +0000
treeherderautoland@e89afc241513 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.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 mozilla-central and inbound
intl/uconv/util/ubase.h
--- a/browser/base/content/test/general/browser_save_link-perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_link-perwindowpb.js
@@ -11,20 +11,23 @@ let NetUtil = tempScope.NetUtil;
 // Trigger a save of a link in public mode, then trigger an identical save
 // in private mode and ensure that the second request is differentiated from
 // the first by checking that cookies set by the first response are not sent
 // during the second request.
 function triggerSave(aWindow, aCallback) {
   var fileName;
   let testBrowser = aWindow.gBrowser.selectedBrowser;
   // This page sets a cookie if and only if a cookie does not exist yet
-  testBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/general/bug792517-2.html");
+  let testURI = "http://mochi.test:8888/browser/browser/base/content/test/general/bug792517-2.html";
+  testBrowser.loadURI(testURI);
   testBrowser.addEventListener("pageshow", function pageShown(event) {
-    if (event.target.location == "about:blank")
+    if (event.target.location != testURI) {
+      testBrowser.loadURI(testURI);
       return;
+    }
     testBrowser.removeEventListener("pageshow", pageShown, false);
 
     executeSoon(function () {
       aWindow.document.addEventListener("popupshown", function(e) contextMenuOpened(aWindow, e), false);
 
       var link = testBrowser.contentDocument.getElementById("fff");
       EventUtils.synthesizeMouseAtCenter(link,
                                          { type: "contextmenu", button: 2 },
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -843,17 +843,17 @@ class Automation(object):
   def checkForCrashes(self, minidumpDir, symbolsPath):
     return mozcrash.check_for_crashes(minidumpDir, symbolsPath, test_name=self.lastTestSeen)
 
   def runApp(self, testURL, env, app, profileDir, extraArgs,
              runSSLTunnel = False, utilityPath = None,
              xrePath = None, certPath = None,
              debuggerInfo = None, symbolsPath = None,
              timeout = -1, maxTime = None, onLaunch = None,
-             webapprtChrome = False):
+             webapprtChrome = False, hide_subtests=None):
     """
     Run the app, log the duration it took to execute, return the status code.
     Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
     """
 
     if utilityPath == None:
       utilityPath = self.DIST_BIN
     if xrePath == None:
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -119,19 +119,16 @@ SIMPLE_PROGRAMS += $(CPP_UNIT_TEST_BINS)
 INCLUDES += -I$(DIST)/include/testing
 LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS)
 
 ifndef MOZ_PROFILE_GENERATE
 libs:: $(CPP_UNIT_TEST_BINS) $(call mkdir_deps,$(DIST)/cppunittests)
 	$(NSINSTALL) $(CPP_UNIT_TEST_BINS) $(DIST)/cppunittests
 endif
 
-check::
-	@$(PYTHON) $(topsrcdir)/testing/runcppunittests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(subst .cpp,$(BIN_SUFFIX),$(CPP_UNIT_TESTS))
-
 cppunittests-remote: DM_TRANS?=adb
 cppunittests-remote:
 	@if [ '${TEST_DEVICE}' != '' -o '$(DM_TRANS)' = 'adb' ]; then \
 		$(PYTHON) -u $(topsrcdir)/testing/remotecppunittests.py \
 			--xre-path=$(DEPTH)/dist/bin \
 			--localLib=$(DEPTH)/dist/$(MOZ_APP_NAME) \
 			--dm_trans=$(DM_TRANS) \
 			--deviceIP=${TEST_DEVICE} \
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8813,16 +8813,20 @@ nsDocument::SetScrollToRef(nsIURI *aDocu
     mScrollToRef = Substring(start, end);
   }
 }
 
 void
 nsDocument::ScrollToRef()
 {
   if (mScrolledToRefAlready) {
+    nsCOMPtr<nsIPresShell> shell = GetShell();
+    if (shell) {
+      shell->ScrollToAnchor();
+    }
     return;
   }
 
   if (mScrollToRef.IsEmpty()) {
     return;
   }
 
   char* tmpstr = ToNewCString(mScrollToRef);
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1894,17 +1894,21 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
   mErrorLoad = mErrorLoad || NS_FAILED(status);
 
   if (mUpload && !mUploadComplete && !mErrorLoad &&
       (mState & XML_HTTP_REQUEST_ASYNC)) {
     if (mProgressTimerIsActive) {
       mProgressTimerIsActive = false;
       mProgressNotifier->Cancel();
     }
-    MaybeDispatchProgressEvents(true);
+    if (mUploadTransferred < mUploadTotal) {
+      mUploadTransferred = mUploadTotal;
+      mProgressSinceLastProgressEvent = true;
+      MaybeDispatchProgressEvents(true);
+    }
     mUploadComplete = true;
     DispatchProgressEvent(mUpload, NS_LITERAL_STRING(LOAD_STR),
                           true, mUploadTotal, mUploadTotal);
   }
 
   mContext = ctxt;
   mState |= XML_HTTP_REQUEST_PARSEBODY;
   ChangeState(XML_HTTP_REQUEST_HEADERS_RECEIVED);
@@ -3405,19 +3409,16 @@ nsXMLHttpRequest::MaybeDispatchProgressE
 
   if (!aFinalProgress) {
     StartProgressEventTimer();
   }
 
   // We're uploading if our state is XML_HTTP_REQUEST_OPENED or
   // XML_HTTP_REQUEST_SENT
   if ((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState) {
-    if (aFinalProgress) {
-      mUploadTotal = mUploadTransferred;
-    }
     if (mUpload && !mUploadComplete) {
       DispatchProgressEvent(mUpload, NS_LITERAL_STRING(PROGRESS_STR),
                             mUploadLengthComputable, mUploadTransferred,
                             mUploadTotal);
     }
   } else {
     if (aFinalProgress) {
       mLoadTotal = mLoadTransferred;
--- a/content/base/test/test_bug435425.html
+++ b/content/base/test/test_bug435425.html
@@ -18,25 +18,33 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 435425 **/
 
 var xhr = null;
 var upload = null;
 var currentEvents = null;
 var expectedResponseText = null;
+var uploadTotal = 0;
 
 function logEvent(evt) {
   var i = 0;
   while ((currentEvents.length != i) &&
          currentEvents[i].optional &&
          ((currentEvents[i].type != evt.type) ||
           !(evt.target instanceof currentEvents[i].target))) {
     ++i;
   }
+  if (evt.target instanceof XMLHttpRequestUpload) {
+    if (evt.type == "loadstart") {
+      uploadTotal = evt.total
+    } else {
+      is(evt.total, uploadTotal, "event(" + evt.type +  ").total should not change during upload.");
+    }
+  }
   ok(i != currentEvents.length, "Extra or wrong event?");
   is(evt.type, currentEvents[i].type, "Wrong event!")
   ok(evt.target instanceof currentEvents[i].target,
      "Wrong event target [" + evt.target + "," + evt.type + "]!");
   // If we handled non-optional event, remove all optional events before the 
   // handled event and then the non-optional event from the list.
   if (!currentEvents[i].optional) {
     for (;i != -1; --i) {
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -1785,33 +1785,16 @@ bool CanvasRenderingContext2D::DrawCusto
   }
 
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
     // check that the element i focused
     nsCOMPtr<nsIDOMElement> focusedElement;
     fm->GetFocusedElement(getter_AddRefs(focusedElement));
     if (SameCOMIdentity(aElement.AsDOMNode(), focusedElement)) {
-      // get the bounds of the current path
-      mgfx::Rect bounds;
-      bounds = mPath->GetBounds(mTarget->GetTransform());
-
-      // and set them as the accessible area
-      nsRect rect(canvas->ClientLeft() + bounds.x, canvas->ClientTop() + bounds.y,
-               bounds.width, bounds.height);
-      rect.x *= AppUnitsPerCSSPixel();
-      rect.y *= AppUnitsPerCSSPixel();
-      rect.width *= AppUnitsPerCSSPixel();
-      rect.height *= AppUnitsPerCSSPixel();
-
-      nsIFrame* frame = aElement.GetPrimaryFrame();
-      if(frame) {
-        frame->SetRect(rect);
-      }
-
       return true;
     }
   }
 
   return false;
 }
 
 void
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -151,16 +151,21 @@ WebGLContext::WebGLContext()
     mStencilClearValue = 0;
     mStencilRefFront = 0;
     mStencilRefBack = 0;
     mStencilValueMaskFront = 0xffffffff;
     mStencilValueMaskBack  = 0xffffffff;
     mStencilWriteMaskFront = 0xffffffff;
     mStencilWriteMaskBack  = 0xffffffff;
 
+    mViewportX = 0;
+    mViewportY = 0;
+    mViewportWidth = 0;
+    mViewportHeight = 0;
+
     mScissorTestEnabled = 0;
     mDitherEnabled = 1;
     mRasterizerDiscardEnabled = 0; // OpenGL ES 3.0 spec p244
 
     // initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
     // so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
     mGLMaxVertexAttribs = 0;
     mGLMaxTextureUnits = 0;
@@ -188,16 +193,17 @@ WebGLContext::WebGLContext()
     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     mContextStatus = ContextNotLost;
     mContextLostErrorSet = false;
     mLoseContextOnHeapMinimize = false;
     mCanLoseContextInForeground = true;
 
     mAlreadyGeneratedWarnings = 0;
     mAlreadyWarnedAboutFakeVertexAttrib0 = false;
+    mAlreadyWarnedAboutViewportLargerThanDest = false;
     mMaxWarnings = Preferences::GetInt("webgl.max-warnings-per-context", 32);
     if (mMaxWarnings < -1)
     {
         GenerateWarning("webgl.max-warnings-per-context size is too large (seems like a negative value wrapped)");
         mMaxWarnings = 0;
     }
 
     mLastUseIndex = 0;
@@ -568,16 +574,18 @@ WebGLContext::SetDimensions(int32_t widt
 #ifdef DEBUG
     if (gl->DebugMode()) {
         printf_stderr("--- WebGL context created: %p\n", gl.get());
     }
 #endif
 
     mWidth = width;
     mHeight = height;
+    mViewportWidth = width;
+    mViewportHeight = height;
     mResetLayer = true;
     mOptionsFrozen = true;
 
     mHasRobustness = gl->HasRobustness();
 
     // increment the generation number
     ++mGeneration;
 
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -1131,16 +1131,22 @@ protected:
     GLuint mStencilValueMaskFront, mStencilValueMaskBack,
               mStencilWriteMaskFront, mStencilWriteMaskBack;
     realGLboolean mColorWriteMask[4];
     realGLboolean mDepthWriteMask;
     GLfloat mColorClearValue[4];
     GLint mStencilClearValue;
     GLfloat mDepthClearValue;
 
+    GLint mViewportX;
+    GLint mViewportY;
+    GLsizei mViewportWidth;
+    GLsizei mViewportHeight;
+    bool mAlreadyWarnedAboutViewportLargerThanDest;
+
     nsCOMPtr<nsITimer> mContextRestorer;
     bool mAllowRestore;
     bool mContextLossTimerRunning;
     bool mDrawSinceContextLossTimerSet;
     ContextStatus mContextStatus;
     bool mContextLostErrorSet;
 
     // Used for some hardware (particularly Tegra 2 and 4) that likes to
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -48,17 +48,17 @@
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
 static GLenum InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2);
 
-inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
+const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
     return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
                              : static_cast<const WebGLRectangleObject*>(this);
 }
 
 WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, GLenum target, GLenum format)
     : mGL(gl)
     , mGLName(0)
 {
@@ -3062,16 +3062,21 @@ WebGLContext::Viewport(GLint x, GLint y,
     if (IsContextLost())
         return;
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("viewport: negative size");
 
     MakeContextCurrent();
     gl->fViewport(x, y, width, height);
+
+    mViewportX = x;
+    mViewportY = y;
+    mViewportWidth = width;
+    mViewportHeight = height;
 }
 
 void
 WebGLContext::CompileShader(WebGLShader *shader)
 {
     if (IsContextLost())
         return;
 
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -485,19 +485,21 @@ uint32_t WebGLContext::GetBitsPerTexel(G
         int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
         switch (format) {
             case LOCAL_GL_ALPHA:
             case LOCAL_GL_LUMINANCE:
                 return 1 * multiplier;
             case LOCAL_GL_LUMINANCE_ALPHA:
                 return 2 * multiplier;
             case LOCAL_GL_RGB:
+            case LOCAL_GL_RGB32F:
             case LOCAL_GL_SRGB_EXT:
                 return 3 * multiplier;
             case LOCAL_GL_RGBA:
+            case LOCAL_GL_RGBA32F:
             case LOCAL_GL_SRGB_ALPHA_EXT:
                 return 4 * multiplier;
             case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
             case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
                 return 2;
             case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
             case LOCAL_GL_ATC_RGB:
@@ -514,17 +516,17 @@ uint32_t WebGLContext::GetBitsPerTexel(G
         }
     } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
     {
         return 16;
     }
 
-    MOZ_ASSERT(false);
+    MOZ_ASSERT(false, "Unhandled format+type combo.");
     return 0;
 }
 
 bool WebGLContext::ValidateTexFormatAndType(GLenum format, GLenum type, int jsArrayType,
                                               uint32_t *texelSize, const char *info)
 {
     if (IsExtensionEnabled(WEBGL_depth_texture)) {
         if (format == LOCAL_GL_DEPTH_COMPONENT) {
--- a/content/canvas/src/WebGLContextVertices.cpp
+++ b/content/canvas/src/WebGLContextVertices.cpp
@@ -728,16 +728,30 @@ void WebGLContext::Draw_cleanup()
             mDrawCallsSinceLastFlush++;
 
             if (mDrawCallsSinceLastFlush >= MAX_DRAW_CALLS_SINCE_FLUSH) {
                 gl->fFlush();
                 mDrawCallsSinceLastFlush = 0;
             }
         }
     }
+
+    // Let's check the viewport
+    const WebGLRectangleObject* rect = FramebufferRectangleObject();
+    if (rect) {
+        if (mViewportWidth > rect->Width() ||
+            mViewportHeight > rect->Height())
+        {
+            if (!mAlreadyWarnedAboutViewportLargerThanDest) {
+                GenerateWarning("Drawing to a destination rect smaller than the viewport rect. "
+                                "(This warning will only be given once)");
+                mAlreadyWarnedAboutViewportLargerThanDest = true;
+            }
+        }
+    }
 }
 
 /*
  * Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
  * that will be legal to be read from bound VBOs.
  */
 
 bool
--- 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 visible text tracks.
+  // Update the cues displaying on the video.
   // 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->Update(time);
+    mTextTrackManager->UpdateCueDisplay();
   }
 }
 
 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,33 +3,50 @@
 
 /* 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*
@@ -81,19 +98,52 @@ TextTrackManager::RemoveTextTrack(TextTr
 
 void
 TextTrackManager::DidSeek()
 {
   mTextTracks->DidSeek();
 }
 
 void
-TextTrackManager::Update(double aTime)
+TextTrackManager::UpdateCueDisplay()
 {
-  mTextTracks->Update(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);
+  }
 }
 
 void
 TextTrackManager::AddCue(TextTrackCue& aCue)
 {
   mNewCues->AddCue(aCue);
 }
 
--- a/content/html/content/src/TextTrackManager.h
+++ b/content/html/content/src/TextTrackManager.h
@@ -6,21 +6,26 @@
  * 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);
@@ -32,32 +37,60 @@ public:
                                            const nsAString& aLanguage);
   void AddTextTrack(TextTrack* aTextTrack);
   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
   void DidSeek();
 
   void AddCue(TextTrackCue& aCue);
   void AddCues(TextTrack* aTextTrack);
 
-  // Update the display of cues on the video as per the current play back time
-  // of aTime.
-  void Update(double aTime);
+  /**
+   * 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();
 
   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,24 +67,16 @@ 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)
@@ -137,21 +129,21 @@ TextTrack::RemoveRegion(const TextTrackR
   if (!mRegionList->GetRegionById(aRegion.Id())) {
     aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return;
   }
 
   mRegionList->RemoveTextTrackRegion(aRegion);
 }
 
-TextTrackCueList*
-TextTrack::GetActiveCues()
+void
+TextTrack::UpdateActiveCueList()
 {
   if (mMode == TextTrackMode::Disabled || !mMediaElement) {
-    return nullptr;
+    return;
   }
 
   // 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;
@@ -171,19 +163,31 @@ TextTrack::GetActiveCues()
   // 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,17 +1,15 @@
 /* -*- 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 {
@@ -31,16 +29,17 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 StaticRefPtr<nsIWebVTTParserWrapper> TextTrackCue::sParserWrapper;
 
 // Set cue setting defaults based on step 19 & seq.
 // in http://dev.w3.org/html5/webvtt/#parsing
 void
 TextTrackCue::SetDefaultCueSettings()
 {
   mPosition = 50;
+  mPositionAlign = AlignSetting::Middle;
   mSize = 100;
   mPauseOnExit = false;
   mSnapToLines = true;
   mLine = WEBVTT_AUTO;
   mAlign = AlignSetting::Middle;
   mLineAlign = AlignSetting::Start;
   mVertical = DirectionSetting::_empty;
 }
@@ -95,67 +94,16 @@ 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,16 +9,17 @@
 
 #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
@@ -215,16 +216,36 @@ public:
       return;
     }
 
     mReset = true;
     mPosition = aPosition;
     CueChanged();
   }
 
+  AlignSetting PositionAlign() const
+  {
+    return mPositionAlign;
+  }
+
+  void SetPositionAlign(AlignSetting aPositionAlign, ErrorResult& aRv)
+  {
+    if (mPositionAlign == aPositionAlign)
+      return;
+
+    if (aPositionAlign == AlignSetting::Left ||
+        aPositionAlign == AlignSetting::Right) {
+      return aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    }
+
+    mReset = true;
+    mPositionAlign = aPositionAlign;
+    CueChanged();
+  }
+
   int32_t Size() const
   {
     return mSize;
   }
 
   void SetSize(int32_t aSize, ErrorResult& aRv)
   {
     if (mSize == aSize) {
@@ -271,96 +292,81 @@ 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;
   nsRefPtr<HTMLTrackElement> mTrackElement;
   nsString mId;
   int32_t mPosition;
+  AlignSetting mPositionAlign;
   int32_t mSize;
   bool mPauseOnExit;
   bool mSnapToLines;
   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
-  nsCOMPtr<nsIContent> mDisplayState;
+  nsRefPtr<nsGenericHTMLElement> 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,27 +33,16 @@ 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)
@@ -111,10 +100,17 @@ 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,31 +36,29 @@ 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,16 +2,17 @@
 /* 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)
@@ -22,21 +23,24 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 TextTrackList::TextTrackList(nsISupports* aGlobal) : mGlobal(aGlobal)
 {
   SetIsDOMBinding();
 }
 
 void
-TextTrackList::Update(double aTime)
+TextTrackList::GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues)
 {
-  uint32_t length = Length(), i;
-  for (i = 0; i < length; i++) {
-    mTextTracks[i]->Update(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);
+    }
   }
 }
 
 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();
   }
 
-  // Time is in seconds.
-  void Update(double aTime);
+  // Get all the current active cues.
+  void GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
 
   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/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -234,16 +234,17 @@ support-files =
 [test_source.html]
 [test_source_write.html]
 [test_source_null.html]
 [test_standalone.html]
 [test_volume.html]
 [test_video_to_canvas.html]
 [test_audiowrite.html]
 [test_mediarecorder_creation.html]
+[test_mediarecorder_creation_fail.html]
 [test_mediarecorder_avoid_recursion.html]
 [test_mediarecorder_record_timeslice.html]
 [test_mediarecorder_record_audiocontext.html]
 [test_mediarecorder_record_4ch_audiocontext.html]
 [test_mediarecorder_record_stopms.html]
 [test_mediarecorder_record_nosrc.html]
 [test_mozHasAudio.html]
 [test_source_media.html]
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_mediarecorder_creation_fail.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test MediaRecorder Record with media.ogg.enabled = false</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function startTest() {
+  var element = document.createElement('audio');
+
+  element.src = 'detodos.opus';
+  element.stream = element.mozCaptureStream();
+  // the expect sequence should be
+  // 1. onerror
+  // 2. ondataavailable
+  // 3. onstop
+  var callbackStep = 0;
+  var mediaRecorder = new MediaRecorder(element.stream);
+
+  mediaRecorder.onerror = function (e) {
+    is(callbackStep, 0, 'should fired onstop callback');
+    is(e.name, 'GenericError', 'error name should be GenericError');
+    is(mediaRecorder.mimeType, '', 'mimetype should be empty');
+    is(mediaRecorder.state, 'recording', 'state is recording');
+    info('onerror callback fired');
+    SpecialPowers.setBoolPref('media.ogg.enabled', true);
+    callbackStep = 1;
+  };
+
+  mediaRecorder.onwarning = function () {
+    ok(false, 'Unexpected onwarning callback fired');
+  };
+
+  mediaRecorder.onstop = function () {
+    info('onstop callback fired');
+    is(mediaRecorder.state, 'inactive', 'state should be inactive');
+    is(callbackStep, 2, 'should fired onstop callback');
+    SimpleTest.finish();
+  };
+
+  // This handler fires every 250ms to generate a blob.
+  mediaRecorder.ondataavailable = function (evt) {
+    info('ondataavailable callback fired');
+    is(callbackStep, 1, 'should fired ondataavailable callback');
+    is(evt.data.size, 0, 'data size should be zero');
+    ok(evt instanceof BlobEvent,
+       'Events fired from ondataavailable should be BlobEvent');
+    is(evt.data.type, '', 'encoder start fail, blob miemType should be empty');
+    callbackStep = 2;
+  };
+
+  // Start recording once canplaythrough fires
+  element.oncanplaythrough = function() {
+    SpecialPowers.setBoolPref("media.ogg.enabled", false);
+    mediaRecorder.start(250);
+    is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
+    is(mediaRecorder.stream, element.stream,
+       'Media recorder stream = element stream at the start of recording');
+  };
+
+  element.play();
+}
+
+startTest();
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/test/test_texttrackcue.html
+++ b/content/media/test/test_texttrackcue.html
@@ -99,16 +99,42 @@ SpecialPowers.pushPrefEnv({"set": [["med
 
       cue.lineAlign = "middle";
       is(cue.lineAlign, "middle", "Cue's line align should be middle.");
       cue.lineAlign = "START";
       is(cue.lineAlign, "middle", "Cue's line align should be middle.");
       cue.lineAlign = "end";
       is(cue.lineAlign, "end", "Cue's line align should be end.");
 
+      // Check that cue position align works properly
+      is(cue.positionAlign, "middle", "Cue's default position alignment should be middle.");
+
+      var exceptionHappened = false;
+      try {
+        cue.positionAlign = "left";
+      } catch(e) {
+        exceptionHappened = true;
+        is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
+      }
+      ok(exceptionHappened, "Exception should have happened.");
+
+      exceptionHappened = false;
+      try {
+        cue.positionAlign = "right";
+      } catch(e) {
+        exceptionHappened = true;
+        is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
+      }
+      ok(exceptionHappened, "Exception should have happened.");
+
+      cue.positionAlign = "start";
+      is(cue.positionAlign, "start", "Cue's position align should be start.");
+      cue.positionAlign = "end";
+      is(cue.positionAlign, "end", "Cue's position align should be end.");
+
       // Check that we can create and add new VTTCues
       var vttCue = new VTTCue(3.999, 4, "foo");
       trackElement.track.addCue(vttCue);
       is(cueList.length, 7, "Cue list length should now be 7.");
 
       // Check that new VTTCue was added correctly
       cue = cueList[6];
       is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
--- a/content/media/webaudio/OscillatorNode.cpp
+++ b/content/media/webaudio/OscillatorNode.cpp
@@ -18,17 +18,18 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_3(Osc
                                      mPeriodicWave, mFrequency, mDetune)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OscillatorNode)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(OscillatorNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(OscillatorNode, AudioNode)
 
-static const float sLeak = 0.995f;
+static const float sLeakTriangle = 0.995f;
+static const float sLeak = 0.999f;
 
 class DCBlocker
 {
 public:
   // These are sane defauts when the initial mPhase is zero
   DCBlocker(float aLastInput = 0.0f,
             float aLastOutput = 0.0f,
             float aPole = 0.995)
@@ -315,34 +316,34 @@ public:
   }
 
   void ComputeSquare(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd)
   {
     for (uint32_t i = aStart; i < aEnd; ++i) {
       UpdateParametersIfNeeded(ticks, i);
       // Integration to get us a square. It turns out we can have a
       // pure integrator here.
-      mSquare += BipolarBLIT();
+      mSquare = mSquare * sLeak + BipolarBLIT();
       aOutput[i] = mSquare;
       // maybe we want to apply a gain, the wg has not decided yet
       aOutput[i] *= 1.5;
       IncrementPhase();
     }
   }
 
   void ComputeSawtooth(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd)
   {
     float dcoffset;
     for (uint32_t i = aStart; i < aEnd; ++i) {
       UpdateParametersIfNeeded(ticks, i);
       // DC offset so the Saw does not ramp up to infinity when integrating.
       dcoffset = mFinalFrequency / mSource->SampleRate();
       // Integrate and offset so we get mAmplitudeAtZero sawtooth. We have a
       // very low frequency component somewhere here, but I'm not sure where.
-      mSaw += UnipolarBLIT() - dcoffset;
+      mSaw = mSaw * sLeak + (UnipolarBLIT() - dcoffset);
       // reverse the saw so we are spec compliant
       aOutput[i] = -mSaw * 1.5;
 
       IncrementPhase();
     }
   }
 
   void ComputeTriangle(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd)
@@ -351,17 +352,17 @@ public:
       UpdateParametersIfNeeded(ticks, i);
       // Integrate to get a square
       mSquare += BipolarBLIT();
       // Leaky integrate to get a triangle. We get too much dc offset if we don't
       // leaky integrate here.
       // C6 = k0 / period
       // (period is samplingrate / frequency, k0 = (PI/2)/(2*PI)) = 0.25
       float C6 = 0.25 / (mSource->SampleRate() / mFinalFrequency);
-      mTriangle = mTriangle * sLeak + mSquare + C6;
+      mTriangle = mTriangle * sLeakTriangle + mSquare + C6;
       // DC Block, and scale back to [-1.0; 1.0]
       aOutput[i] = mDCBlocker.Process(mTriangle) / (mSignalPeriod/2) * 1.5;
 
       IncrementPhase();
     }
   }
 
   void ComputeCustom(float* aOutput,
--- a/content/media/webvtt/WebVTTParserWrapper.js
+++ b/content/media/webvtt/WebVTTParserWrapper.js
@@ -45,16 +45,21 @@ 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,16 +2,17 @@
  * 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
 {
   /**
@@ -56,13 +57,31 @@ 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,31 +3,38 @@
  * 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 355f375b6cf04763dcb1843d5683a7c489846425
+ * Code taken from commit 33a837b1ceef138a61a3b2f6fac90d5c70bd90d9
  */
+(function(global) {
 
-(function(global) {
+  function ParsingError(message) {
+    this.name = "ParsingError";
+    this.message = message || "";
+  }
+  ParsingError.prototype = Object.create(Error.prototype);
+  ParsingError.prototype.constructor = ParsingError;
 
   // 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]);
@@ -41,46 +48,49 @@ 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.
-    get: function(k, dflt) {
+    // 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];
+      }
       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);
@@ -94,83 +104,114 @@ 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") {
+        continue;
+      }
       var kv = groups[i].split(keyValueDelim);
-      if (kv.length !== 2)
+      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 "error";
+      if (ts === null) {
+        throw new ParsingError("Malformed time stamp.");
+      }
       // 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.region(k, v);
+          settings.set(k, v);
           break;
         case "vertical":
           settings.alt(k, v, ["rl", "lr"]);
           break;
         case "line":
-          settings.integer(k, v);
-          settings.percent(k, v) ? settings.set("snapToLines", false) : null;
-          settings.alt(k, v, ["auto"]);
+          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"]);
+          }
           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 "error";
+    if (input.substr(0, 3) !== "-->") {     // (3) next characters must match "-->"
+      throw new ParsingError("Malformed time stamp (time stamps must be separated by '-->').");
+    }
     input = input.substr(3);
     skipWhitespace();
     cue.endTime = consumeTimeStamp();     // (5) collect cue end time
 
     // 4.1 WebVTT cue settings list.
     skipWhitespace();
     consumeCueSettings(input, cue);
   }
@@ -203,18 +244,19 @@ 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(/^([^<]*)(<[^>]+>?)?/);
@@ -223,36 +265,39 @@ 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 = [];
 
@@ -267,261 +312,667 @@ 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.ProcessingInstruction();
-          node.target = "timestamp";
-          node.data = ts;
+          node = window.document.createProcessingInstruction("timestamp", 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 CueBoundingBox(cue) {
-    // TODO: Apply unicode bidi algorithm and assign the result to 'direction'
-    this.direction = "ltr";
+  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);
 
-    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));
+    // 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, "%")
+      });
+    }
 
-    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));
+    // 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.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);
-    }());
+  // 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);
 
-    // 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;
+    // 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;
       }
     }
 
-    this.height = cue.vertical === "" ? "auto" : boxLen;
-    this.width = cue.vertical === "" ? boxLen : "auto";
+    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.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.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.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;
+    };
   }
-
-  const WEBVTT = "WEBVTT";
+  RegionBoundingBox.prototype = Object.create(BoundingBox.prototype);
+  RegionBoundingBox.prototype.constructor = RegionBoundingBox;
 
   function WebVTTParser(window, decoder) {
     this.window = window;
     this.state = "INITIAL";
     this.buffer = "";
-    this.decoder = decoder || TextDecoder("utf8");
+    this.decoder = decoder || new 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 "[StringDecoder] Error - expected string data";
-
+        if (!data) {
+          return "";
+        }
+        if (typeof data !== "string") {
+          throw new Error("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);
   };
 
-  WebVTTParser.processCues = function(window, cues) {
-    if (!window || !cues)
+  // 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) {
       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;
 
-    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;
-    });
+    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);
+    }
   };
 
   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});
       }
 
-      // Advance tells whether or not to remove the collected line from the buffer
-      // after it is read.
-      function collectNextLine(advance) {
+      function collectNextLine() {
         var buffer = self.buffer;
         var pos = 0;
-        advance = typeof advance === "undefined" ? true : advance;
-        while (pos < buffer.length && buffer[pos] != '\r' && buffer[pos] != '\n')
+        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;
-        if (advance)
-          self.buffer = buffer.substr(pos);
+        }
+        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.region(k, v);
+            settings.set(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/);
@@ -532,17 +983,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", "none");
+          region.scroll = settings.get("scroll", "");
           self.onregion(region);
         }
       }
 
       // 3.2 WebVTT metadata header syntax
       function parseHeader(input) {
         parseOptions(input, function (k, v) {
           switch (k) {
@@ -553,43 +1004,34 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]
           }
         }, /:/);
       }
 
       // 5.1 WebVTT file parsing.
       try {
         var line;
         if (self.state === "INITIAL") {
-          // Wait until we have enough data to parse the header.
-          if (self.buffer.length <= WEBVTT.length)
+          // We can't start parsing until we have the first line.
+          if (!/\r\n|\n/.test(self.buffer)) {
             return this;
+          }
 
-          // 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";
+          line = collectNextLine();
+
+          var m = line.match(/^WEBVTT([ \t].*)?$/);
+          if (!m || !m[0]) {
+            throw new ParsingError("Malformed WebVTT signature.");
           }
-          // 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]/.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);
+          if (!/\r\n|\n/.test(self.buffer)) {
             return this;
           }
 
           line = collectNextLine();
 
           switch (self.state) {
           case "HEADER":
             // 13-18 - Allow a header (metadata) under the WEBVTT line.
@@ -597,79 +1039,90 @@ 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;
-          default: // BADCUE
+          case "BADCUE": // 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;
-        // 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";
+        // Enter BADWEBVTT state if header was not parsed correctly otherwise
+        // another exception occurred so enter BADCUE state.
+        self.state = self.state === "INITIAL" ? "BADWEBVTT" : "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/system/gonk/OpenFileFinder.cpp
+++ b/dom/system/gonk/OpenFileFinder.cpp
@@ -5,16 +5,29 @@
 #include "OpenFileFinder.h"
 
 #include "mozilla/FileUtils.h"
 #include "nsPrintfCString.h"
 
 #include <sys/stat.h>
 #include <errno.h>
 
+#define USE_DEBUG 0
+
+#undef LOG
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO,  "OpenFileFinder", ## args)
+#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN,  "OpenFileFinder", ## args)
+#define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "OpenFileFinder", ## args)
+
+#if USE_DEBUG
+#define DBG(args...)  __android_log_print(ANDROID_LOG_DEBUG, "OpenFileFinder" , ## args)
+#else
+#define DBG(args...)
+#endif
+
 namespace mozilla {
 namespace system {
 
 OpenFileFinder::OpenFileFinder(const nsACString& aPath,
                                bool aCheckIsB2gOrDescendant /* = true */)
   : mPath(aPath),
     mProcDir(nullptr),
     mFdDir(nullptr),
--- a/dom/system/gonk/OpenFileFinder.h
+++ b/dom/system/gonk/OpenFileFinder.h
@@ -4,29 +4,16 @@
 
 #ifndef mozilla_system_openfilefinder_h__
 #define mozilla_system_openfilefinder_h__
 
 #include "nsString.h"
 
 #include <dirent.h>
 
-#define USE_DEBUG 0
-
-#undef LOG
-#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO,  "OpenFileFinder", ## args)
-#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN,  "OpenFileFinder", ## args)
-#define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "OpenFileFinder", ## args)
-
-#if USE_DEBUG
-#define DBG(args...)  __android_log_print(ANDROID_LOG_DEBUG, "OpenFileFinder" , ## args)
-#else
-#define DBG(args...)
-#endif
-
 namespace mozilla {
 namespace system {
 
 class OpenFileFinder
 {
 public:
   enum State
   {
--- a/dom/webidl/VTTCue.webidl
+++ b/dom/webidl/VTTCue.webidl
@@ -37,17 +37,27 @@ interface VTTCue : EventTarget {
   attribute boolean snapToLines;
   // XXXhumph: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20651
   // attribute (long or AutoKeyword) line;
   [SetterThrows]
   attribute AlignSetting lineAlign;
   [SetterThrows]
   attribute long position;
   [SetterThrows]
+  attribute AlignSetting positionAlign;
+  [SetterThrows]
   attribute long size;
   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/gfx/gl/GLReadTexImageHelper.cpp
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -8,16 +8,18 @@
 #include "GLContext.h"
 #include "OGLShaderProgram.h"
 #include "gfxTypes.h"
 #include "gfxContext.h"
 #include "ScopedGLHelpers.h"
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 
+using namespace mozilla::gfx;
+
 namespace mozilla {
 namespace gl {
 
 GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl)
     : mGL(gl)
 {
     mPrograms[0] = 0;
     mPrograms[1] = 0;
@@ -199,24 +201,24 @@ GetActualReadFormats(GLContext* gl, GLen
         return false;
     } else {
         readFormat = destFormat;
         readType = destType;
         return true;
     }
 }
 
-static void SwapRAndBComponents(gfxImageSurface* surf)
+static void SwapRAndBComponents(DataSourceSurface* surf)
 {
-  uint8_t *row = surf->Data();
+  uint8_t *row = surf->GetData();
 
-  size_t rowBytes = surf->Width()*4;
+  size_t rowBytes = surf->GetSize().width*4;
   size_t rowHole = surf->Stride() - rowBytes;
 
-  size_t rows = surf->Height();
+  size_t rows = surf->GetSize().height;
 
   while (rows) {
 
     const uint8_t *rowEnd = row + rowBytes;
 
     while (row != rowEnd) {
       row[0] ^= row[2];
       row[2] ^= row[0];
@@ -277,29 +279,29 @@ ReadPixelsIntoImageSurface(GLContext* gl
 
     nsAutoPtr<gfxImageSurface> tempSurf;
     gfxImageSurface* readSurf = nullptr;
     int readPixelSize = 0;
     if (needsTempSurf) {
         if (gl->DebugMode()) {
             NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
         }
-        gfx::SurfaceFormat readFormatGFX;
+        SurfaceFormat readFormatGFX;
 
         switch (readFormat) {
             case LOCAL_GL_RGBA:
             case LOCAL_GL_BGRA: {
-                readFormatGFX = hasAlpha ? gfx::FORMAT_B8G8R8A8
-                                         : gfx::FORMAT_B8G8R8X8;
+                readFormatGFX = hasAlpha ? FORMAT_B8G8R8A8
+                                         : FORMAT_B8G8R8X8;
                 break;
             }
             case LOCAL_GL_RGB: {
                 MOZ_ASSERT(readPixelSize == 2);
                 MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
-                readFormatGFX = gfx::FORMAT_R5G6B5;
+                readFormatGFX = FORMAT_R5G6B5;
                 break;
             }
             default: {
                 MOZ_CRASH("Bad read format.");
             }
         }
 
         switch (readType) {
@@ -353,17 +355,22 @@ ReadPixelsIntoImageSurface(GLContext* gl
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
 
     if (readSurf != dest) {
         MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
         MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
         // So we just copied in RGBA in big endian, or le: 0xAABBGGRR.
         // We want 0xAARRGGBB, so swap R and B:
         dest->Flush();
-        SwapRAndBComponents(readSurf);
+        RefPtr<DataSourceSurface> readDSurf =
+            Factory::CreateWrappingDataSourceSurface(readSurf->Data(),
+                                                     readSurf->Stride(),
+                                                     ToIntSize(readSurf->GetSize()),
+                                                     ImageFormatToSurfaceFormat(readSurf->Format()));
+        SwapRAndBComponents(readDSurf);
         dest->MarkDirty();
 
         gfxContext ctx(dest);
         ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
         ctx.SetSource(readSurf);
         ctx.Paint();
     }
 
@@ -392,76 +399,80 @@ ReadPixelsIntoImageSurface(GLContext* gl
                 }
             }
             dest->MarkDirty();
         }
     }
 #endif
 }
 
-static already_AddRefed<gfxImageSurface> YInvertImageSurface(gfxImageSurface* aSurf)
+static TemporaryRef<DataSourceSurface> YInvertImageSurface(DataSourceSurface* aSurf)
 {
-  gfxIntSize size = aSurf->GetSize();
-  nsRefPtr<gfxImageSurface> temp = new gfxImageSurface(size, aSurf->Format());
-  nsRefPtr<gfxContext> ctx = new gfxContext(temp);
+  RefPtr<DataSourceSurface> temp =
+    Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
+                                               aSurf->GetFormat(),
+                                               aSurf->Stride());
+  RefPtr<DrawTarget> dt =
+    Factory::CreateDrawTargetForData(BACKEND_CAIRO,
+                                     temp->GetData(),
+                                     temp->GetSize(),
+                                     temp->Stride(),
+                                     temp->GetFormat());
+  nsRefPtr<gfxContext> ctx = new gfxContext(dt);
   ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
   ctx->Scale(1.0, -1.0);
-  ctx->Translate(-gfxPoint(0.0, size.height));
-  ctx->SetSource(aSurf);
+  ctx->Translate(-gfxPoint(0.0, aSurf->GetSize().height));
+
+  nsRefPtr<gfxImageSurface> thebesSurf =
+    new gfxImageSurface(aSurf->GetData(),
+                        ThebesIntSize(aSurf->GetSize()),
+                        aSurf->Stride(),
+                        SurfaceFormatToImageFormat(aSurf->GetFormat()));
+  ctx->SetSource(thebesSurf);
   ctx->Paint();
   return temp.forget();
 }
 
-already_AddRefed<gfxImageSurface>
-GetTexImage(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat)
+TemporaryRef<DataSourceSurface>
+ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFormat)
 {
     gl->MakeCurrent();
     gl->GuaranteeResolve();
     gl->fActiveTexture(LOCAL_GL_TEXTURE0);
     gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
 
-    gfxIntSize size;
+    IntSize size;
     gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
     gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
 
-    nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxImageFormatARGB32);
-    if (!surf || surf->CairoStatus()) {
+    RefPtr<DataSourceSurface> surf =
+      Factory::CreateDataSourceSurfaceWithStride(size, FORMAT_B8G8R8A8,
+                                                 GetAlignedStride<4>(size.width * BytesPerPixel(FORMAT_B8G8R8A8)));
+
+    if (!surf) {
         return nullptr;
     }
 
     uint32_t currentPackAlignment = 0;
     gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
     if (currentPackAlignment != 4) {
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
     }
-    gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->Data());
+    gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->GetData());
     if (currentPackAlignment != 4) {
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
     }
 
-    if (aFormat == gfx::FORMAT_R8G8B8A8 || aFormat == gfx::FORMAT_R8G8B8X8) {
+    if (aFormat == FORMAT_R8G8B8A8 || aFormat == FORMAT_R8G8B8X8) {
       SwapRAndBComponents(surf);
     }
 
     if (aYInvert) {
       surf = YInvertImageSurface(surf);
     }
-    return surf.forget();
-}
-
-TemporaryRef<gfx::DataSourceSurface>
-ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat)
-{
-    nsRefPtr<gfxImageSurface> image = GetTexImage(gl, aTexture, aYInvert, aFormat);
-    RefPtr<gfx::DataSourceSurface> surf =
-        gfx::Factory::CreateDataSourceSurface(gfx::ToIntSize(image->GetSize()), aFormat);
-
-    if (!image->CopyTo(surf)) {
-        return nullptr;
-    }
 
     return surf.forget();
 }
 
 void
 ReadScreenIntoImageSurface(GLContext* gl, gfxImageSurface* dest)
 {
     ScopedBindFramebuffer autoFB(gl, 0);
--- a/gfx/gl/GLReadTexImageHelper.h
+++ b/gfx/gl/GLReadTexImageHelper.h
@@ -22,19 +22,16 @@ namespace gfx {
 class DataSourceSurface;
 }
 
 namespace gl {
 
 void ReadPixelsIntoImageSurface(GLContext* aGL, gfxImageSurface* aSurface);
 void ReadScreenIntoImageSurface(GLContext* aGL, gfxImageSurface* aSurface);
 
-already_AddRefed<gfxImageSurface>
-GetTexImage(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
-
 TemporaryRef<gfx::DataSourceSurface>
 ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
 
 class GLReadTexImageHelper MOZ_FINAL
 {
     // The GLContext is the sole owner of the GLBlitHelper.
     GLContext* mGL;
 
--- a/gfx/gl/SharedSurfaceGralloc.cpp
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -6,22 +6,24 @@
 #include "mozilla/Preferences.h"
 
 #include "SharedSurfaceGralloc.h"
 
 #include "GLContext.h"
 #include "SharedSurfaceGL.h"
 #include "SurfaceFactory.h"
 #include "GLLibraryEGL.h"
+#include "mozilla/layers/GrallocTextureClient.h"
 #include "mozilla/layers/ShadowLayers.h"
 
 #include "ui/GraphicBuffer.h"
 #include "../layers/ipc/ShadowLayers.h"
 #include "ScopedGLHelpers.h"
 
+#include "gfxPlatform.h"
 #include "gfx2DGlue.h"
 
 #define DEBUG_GRALLOC
 #ifdef DEBUG_GRALLOC
 #define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0)
 #else
 #define DEBUG_PRINT(...) do { } while (0)
 #endif
@@ -67,44 +69,45 @@ SharedSurface_Gralloc::Create(GLContext*
     GLLibraryEGL* egl = &sEGLLibrary;
     MOZ_ASSERT(egl);
 
     DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
 
     if (!HasExtensions(egl, prodGL))
         return nullptr;
 
-    SurfaceDescriptor baseDesc;
-    SurfaceDescriptorGralloc desc;
+    gfxContentType type = hasAlpha ? GFX_CONTENT_COLOR_ALPHA
+                                   : GFX_CONTENT_COLOR;
+
+    gfxImageFormat format
+      = gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
 
-    gfxContentType type = hasAlpha ? GFX_CONTENT_COLOR_ALPHA
-                                                : GFX_CONTENT_COLOR;
-    if (!allocator->AllocSurfaceDescriptorWithCaps(size, type, USING_GL_RENDERING_ONLY, &baseDesc))
-        return false;
+    GrallocTextureClientOGL* grallocTC =
+      new GrallocTextureClientOGL(
+          allocator,
+          gfx::ImageFormatToSurfaceFormat(format),
+          TEXTURE_FLAGS_DEFAULT);
 
-    if (baseDesc.type() != SurfaceDescriptor::TSurfaceDescriptorGralloc) {
-        allocator->DestroySharedSurface(&baseDesc);
-        return false;
+    if (!grallocTC->AllocateForGLRendering(size)) {
+      return nullptr;
     }
 
-    desc = baseDesc.get_SurfaceDescriptorGralloc();
-
-    sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(desc);
+    sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
 
     EGLDisplay display = egl->Display();
     EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
     EGLint attrs[] = {
         LOCAL_EGL_NONE, LOCAL_EGL_NONE
     };
     EGLImage image = egl->fCreateImage(display,
                                        EGL_NO_CONTEXT,
                                        LOCAL_EGL_NATIVE_BUFFER_ANDROID,
                                        clientBuffer, attrs);
     if (!image) {
-        allocator->DestroySharedSurface(&baseDesc);
+        grallocTC->DropTextureData()->DeallocateSharedData(allocator);
         return nullptr;
     }
 
     prodGL->MakeCurrent();
     GLuint prodTex = 0;
     prodGL->fGenTextures(1, &prodTex);
     ScopedBindTexture autoTex(prodGL, prodTex);
 
@@ -112,17 +115,17 @@ SharedSurface_Gralloc::Create(GLContext*
     prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
     prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
     prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
 
     prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
 
     egl->fDestroyImage(display, image);
 
-    SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, desc, prodTex);
+    SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, grallocTC, prodTex);
 
     DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get());
 
     return surf;
 }
 
 
 bool
@@ -134,22 +137,16 @@ SharedSurface_Gralloc::HasExtensions(GLL
 
 SharedSurface_Gralloc::~SharedSurface_Gralloc()
 {
 
     DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
 
     mGL->MakeCurrent();
     mGL->fDeleteTextures(1, (GLuint*)&mProdTex);
-
-    SurfaceDescriptor desc(mDesc);
-
-    if (mAllocator) {
-        mAllocator->DestroySharedSurface(&desc);
-    }
 }
 
 void
 SharedSurface_Gralloc::Fence()
 {
     // We should be able to rely on genlock write locks/read locks.
     // But they're broken on some configs, and even a glFinish doesn't
     // work.  glReadPixels seems to, though.
--- a/gfx/gl/SharedSurfaceGralloc.h
+++ b/gfx/gl/SharedSurfaceGralloc.h
@@ -2,23 +2,23 @@
 /* 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/. */
 
 #ifndef SHARED_SURFACE_GRALLOC_H_
 #define SHARED_SURFACE_GRALLOC_H_
 
 #include "SharedSurfaceGL.h"
+#include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/LayersSurfaces.h"
-#include "mozilla/layers/ISurfaceAllocator.h"
+#include "mozilla/layers/TextureClient.h"
 
 namespace mozilla {
 namespace layers {
 class ISurfaceAllocator;
-class SurfaceDescriptorGralloc;
 }
 
 namespace gl {
 class GLContext;
 class GLLibraryEGL;
 
 class SharedSurface_Gralloc
     : public SharedSurface_GL
@@ -34,43 +34,34 @@ public:
         MOZ_ASSERT(surf->Type() == SharedSurfaceType::Gralloc);
 
         return (SharedSurface_Gralloc*)surf;
     }
 
 protected:
     GLLibraryEGL* const mEGL;
     RefPtr<layers::ISurfaceAllocator> mAllocator;
-    // We keep the SurfaceDescriptor around, because we'll end up
-    // using it often and it's handy to do so.  The actual
-    // GraphicBuffer is kept alive by the sp<GraphicBuffer> in
-    // GrallocBufferActor; the actor will stay alive until we
-    // explicitly destroy this descriptor (and thus deallocate the
-    // actor) it in the destructor of this class.  This is okay to do
-    // on the client, but is very bad to do on the server (because on
-    // the client, the actor has no chance of going away unless the
-    // whole app died).
-    layers::SurfaceDescriptorGralloc mDesc;
+    RefPtr<layers::TextureClient> mTextureClient;
     const GLuint mProdTex;
 
     SharedSurface_Gralloc(GLContext* prodGL,
                           const gfx::IntSize& size,
                           bool hasAlpha,
                           GLLibraryEGL* egl,
                           layers::ISurfaceAllocator* allocator,
-                          layers::SurfaceDescriptorGralloc& desc,
+                          layers::TextureClient* textureClient,
                           GLuint prodTex)
         : SharedSurface_GL(SharedSurfaceType::Gralloc,
                            AttachmentType::GLTexture,
                            prodGL,
                            size,
                            hasAlpha)
         , mEGL(egl)
         , mAllocator(allocator)
-        , mDesc(desc)
+        , mTextureClient(textureClient)
         , mProdTex(prodTex)
     {}
 
     static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
 
 public:
     virtual ~SharedSurface_Gralloc();
 
@@ -79,18 +70,18 @@ public:
 
     virtual void LockProdImpl();
     virtual void UnlockProdImpl();
 
     virtual GLuint Texture() const {
         return mProdTex;
     }
 
-    layers::SurfaceDescriptorGralloc& GetDescriptor() {
-        return mDesc;
+    layers::TextureClient* GetTextureClient() {
+        return mTextureClient;
     }
 };
 
 class SurfaceFactory_Gralloc
     : public SurfaceFactory_GL
 {
 protected:
     RefPtr<layers::ISurfaceAllocator> mAllocator;
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -1110,44 +1110,50 @@ void WriteSnapshotLinkToDumpFile(T* aObj
   }
   nsCString string(aObj->Name());
   string.Append("-");
   string.AppendInt((uint64_t)aObj);
   fprintf_stderr(aFile, "href=\"javascript:ViewImage('%s')\"", string.BeginReading());
 }
 
 template <typename T>
-void WriteSnapshotToDumpFile_internal(T* aObj, gfxASurface* aSurf)
+void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf)
 {
+  nsRefPtr<gfxImageSurface> deprecatedSurf =
+    new gfxImageSurface(aSurf->GetData(),
+                        ThebesIntSize(aSurf->GetSize()),
+                        aSurf->Stride(),
+                        SurfaceFormatToImageFormat(aSurf->GetFormat()));
   nsCString string(aObj->Name());
   string.Append("-");
   string.AppendInt((uint64_t)aObj);
   if (gfxUtils::sDumpPaintFile) {
     fprintf_stderr(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
   }
-  aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
+  deprecatedSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
   if (gfxUtils::sDumpPaintFile) {
     fprintf_stderr(gfxUtils::sDumpPaintFile, "\";");
   }
 }
 
-void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf)
+void WriteSnapshotToDumpFile(Layer* aLayer, DataSourceSurface* aSurf)
 {
   WriteSnapshotToDumpFile_internal(aLayer, aSurf);
 }
 
-void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf)
+void WriteSnapshotToDumpFile(LayerManager* aManager, DataSourceSurface* aSurf)
 {
   WriteSnapshotToDumpFile_internal(aManager, aSurf);
 }
 
 void WriteSnapshotToDumpFile(Compositor* aCompositor, DrawTarget* aTarget)
 {
-  nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aTarget);
-  WriteSnapshotToDumpFile_internal(aCompositor, surf);
+  RefPtr<SourceSurface> surf = aTarget->Snapshot();
+  RefPtr<DataSourceSurface> dSurf = surf->GetDataSurface();
+  WriteSnapshotToDumpFile_internal(aCompositor, dSurf);
 }
 #endif
 
 void
 Layer::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml)
 {
   if (aDumpHtml) {
     fprintf_stderr(aFile, "<li><a id=\"%p\" ", this);
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -2041,17 +2041,17 @@ protected:
   // 0 is a special value that means "no ID".
   uint64_t mId;
 };
 
 void SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget);
 void SetAntialiasingFlags(Layer* aLayer, gfx::DrawTarget* aTarget);
 
 #ifdef MOZ_DUMP_PAINTING
-void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf);
-void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf);
+void WriteSnapshotToDumpFile(Layer* aLayer, gfx::DataSourceSurface* aSurf);
+void WriteSnapshotToDumpFile(LayerManager* aManager, gfx::DataSourceSurface* aSurf);
 void WriteSnapshotToDumpFile(Compositor* aCompositor, gfx::DrawTarget* aTarget);
 #endif
 
 }
 }
 
 #endif /* GFX_LAYERS_H */
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -10,46 +10,42 @@
 #include "Layers.h"                     // for Layer, etc
 #include "SurfaceStream.h"              // for SurfaceStream
 #include "SurfaceTypes.h"               // for SurfaceStreamHandle
 #include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/layers/CompositableForwarder.h"
+#include "mozilla/layers/GrallocTextureClient.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
+#include "mozilla/layers/TextureClientOGL.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for printf_stderr, NS_ASSERTION
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
 #ifdef MOZ_WIDGET_GONK
 #include "SharedSurfaceGralloc.h"
 #endif
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
-namespace gfx {
-class SharedSurface;
-}
-}
-
-namespace mozilla {
 namespace layers {
 
 /* static */ TemporaryRef<CanvasClient>
 CanvasClient::CreateCanvasClient(CanvasClientType aType,
                                  CompositableForwarder* aForwarder,
                                  TextureFlags aFlags)
 {
   if (aType == CanvasClientGLContext &&
       aForwarder->GetCompositorBackendType() == LAYERS_OPENGL) {
     aFlags |= TEXTURE_DEALLOCATE_CLIENT;
-    return new DeprecatedCanvasClientSurfaceStream(aForwarder, aFlags);
+    return new CanvasClientSurfaceStream(aForwarder, aFlags);
   }
   if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
     aFlags |= TEXTURE_DEALLOCATE_CLIENT;
     return new DeprecatedCanvasClient2D(aForwarder, aFlags);
   }
   return new CanvasClient2D(aForwarder, aFlags);
 }
 
@@ -101,16 +97,83 @@ CanvasClient2D::Update(gfx::IntSize aSiz
 
 TemporaryRef<BufferTextureClient>
 CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
 {
   return CompositableClient::CreateBufferTextureClient(aFormat,
                                                        mTextureInfo.mTextureFlags | aFlags);
 }
 
+CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder,
+                                                     TextureFlags aFlags)
+  : CanvasClient(aLayerForwarder, aFlags)
+{
+}
+
+void
+CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
+{
+  GLScreenBuffer* screen = aLayer->mGLContext->Screen();
+  SurfaceStream* stream = screen->Stream();
+
+  bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+  bool bufferCreated = false;
+  if (isCrossProcess) {
+#ifdef MOZ_WIDGET_GONK
+    SharedSurface* surf = stream->SwapConsumer();
+    if (!surf) {
+      printf_stderr("surf is null post-SwapConsumer!\n");
+      return;
+    }
+
+    if (surf->Type() != SharedSurfaceType::Gralloc) {
+      printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
+      MOZ_ASSERT(false);
+      return;
+    }
+
+    SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
+
+    GrallocTextureClientOGL* grallocTextureClient =
+      static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient());
+
+    // If IPDLActor is null means this TextureClient didn't AddTextureClient yet
+    if (!grallocTextureClient->GetIPDLActor()) {
+      grallocTextureClient->SetTextureFlags(mTextureInfo.mTextureFlags);
+      AddTextureClient(grallocTextureClient);
+    }
+
+    if (grallocTextureClient->GetIPDLActor()) {
+      GetForwarder()->UseTexture(this, grallocTextureClient);
+    }
+#else
+    printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
+    MOZ_ASSERT(false);
+#endif
+  } else {
+    if (!mBuffer) {
+      StreamTextureClientOGL* textureClient =
+        new StreamTextureClientOGL(mTextureInfo.mTextureFlags);
+      textureClient->InitWith(stream);
+      mBuffer = textureClient;
+      bufferCreated = true;
+    }
+
+    if (bufferCreated && !AddTextureClient(mBuffer)) {
+      mBuffer = nullptr;
+    }
+
+    if (mBuffer) {
+      GetForwarder()->UseTexture(this, mBuffer);
+    }
+  }
+
+  aLayer->Painted();
+}
+
 void
 DeprecatedCanvasClient2D::Updated()
 {
   mForwarder->UpdateTexture(this, 1, mDeprecatedTextureClient->LockSurfaceDescriptor());
 }
 
 
 DeprecatedCanvasClient2D::DeprecatedCanvasClient2D(CompositableForwarder* aFwd,
@@ -201,17 +264,18 @@ DeprecatedCanvasClientSurfaceStream::Upd
 
 #ifdef MOZ_WIDGET_GONK
     if (surf->Type() != SharedSurfaceType::Gralloc) {
       printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
       return;
     }
 
     SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
-    mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
+    //XXX todo
+    //mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
 #else
     printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
     MOZ_ASSERT(false);
 #endif
   } else {
     SurfaceStreamHandle handle = stream->GetShareHandle();
     mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
 
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -14,16 +14,22 @@
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 
 namespace mozilla {
+namespace gfx {
+class SharedSurface;
+}
+}
+
+namespace mozilla {
 namespace layers {
 
 class ClientCanvasLayer;
 class CompositableForwarder;
 
 /**
  * Compositable client for 2d and webgl canvas.
  */
@@ -90,16 +96,39 @@ public:
   {
     mBuffer = nullptr;
   }
 
 private:
   RefPtr<TextureClient> mBuffer;
 };
 
+// Used for GL canvases where we don't need to do any readback, i.e., with a
+// GL backend.
+class CanvasClientSurfaceStream : public CanvasClient
+{
+public:
+  CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder, TextureFlags aFlags);
+
+  TextureInfo GetTextureInfo() const
+  {
+    return TextureInfo(COMPOSITABLE_IMAGE);
+  }
+
+  virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
+
+  virtual void OnDetach() MOZ_OVERRIDE
+  {
+    mBuffer = nullptr;
+  }
+
+private:
+  RefPtr<TextureClient> mBuffer;
+};
+
 class DeprecatedCanvasClient2D : public CanvasClient
 {
 public:
   DeprecatedCanvasClient2D(CompositableForwarder* aLayerForwarder,
                            TextureFlags aFlags);
 
   TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -46,55 +46,56 @@ public:
   }
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     CanvasLayer::SetVisibleRegion(aRegion);
   }
-  
+
   virtual void Initialize(const Data& aData);
 
   virtual void RenderLayer();
-  
+
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = CanvasLayerAttributes(mFilter, mBounds);
   }
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
-  
+
   virtual void Disconnect()
   {
     mCanvasClient = nullptr;
     ClientLayer::Disconnect();
   }
 
   virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
   {
     return mCanvasClient;
   }
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
-  
+
   CanvasClientType GetCanvasClientType()
   {
     if (mGLContext) {
       return CanvasClient::CanvasClientGLContext;
     }
     return CanvasClient::CanvasClientSurface;
   }
 
   RefPtr<CanvasClient> mCanvasClient;
 
   friend class DeprecatedCanvasClient2D;
   friend class CanvasClient2D;
   friend class DeprecatedCanvasClientSurfaceStream;
+  friend class CanvasClientSurfaceStream;
 };
 }
 }
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -517,18 +517,18 @@ BufferTextureClient::AllocateForSurface(
   mSize = aSize;
   return true;
 }
 
 TemporaryRef<gfx::DrawTarget>
 BufferTextureClient::GetAsDrawTarget()
 {
   MOZ_ASSERT(IsValid());
-  // XXX - uncomment when ContentClient's locking is fixed
-  // MOZ_ASSERT(mLocked);
+  // XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed
+  NS_WARN_IF_FALSE(mLocked, "GetAsDrawTarget should be called on locked textures only");
 
   if (mDrawTarget) {
     return mDrawTarget;
   }
 
   ImageDataSerializer serializer(GetBuffer());
   if (!serializer.IsValid()) {
     return nullptr;
@@ -555,26 +555,28 @@ BufferTextureClient::GetAsDrawTarget()
     mDrawTarget->CopySurface(surface, rect, IntPoint(0,0));
   }
   return mDrawTarget;
 }
 
 bool
 BufferTextureClient::Lock(OpenMode aMode)
 {
-  MOZ_ASSERT(!mLocked);
+  // XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed
+  NS_WARN_IF_FALSE(!mLocked, "The TextureClient is already Locked!");
   mOpenMode = aMode;
   mLocked = true;
   return true;
 }
 
 void
 BufferTextureClient::Unlock()
 {
-  MOZ_ASSERT(mLocked);
+  // XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed
+  NS_WARN_IF_FALSE(mLocked, "The TextureClient is already Unlocked!");
   mLocked = false;
   if (!mDrawTarget) {
     mUsingFallbackDrawTarget = false;
     return;
   }
 
   mDrawTarget->Flush();
   if (mUsingFallbackDrawTarget && (mOpenMode & OPEN_WRITE)) {
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -65,23 +65,17 @@ CanvasLayerComposite::RenderLayer(const 
   if (!mImageHost || !mImageHost->IsAttached()) {
     return;
   }
 
   mCompositor->MakeCurrent();
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
-    RefPtr<gfx::DataSourceSurface> dSurf = mImageHost->GetAsSurface();
-    gfxPlatform *platform = gfxPlatform::GetPlatform();
-    RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
-                                                                   dSurf->GetSize(),
-                                                                   dSurf->Stride(),
-                                                                   dSurf->GetFormat());
-    nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
+    RefPtr<gfx::DataSourceSurface> surf = mImageHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
 #endif
 
   GraphicsFilter filter = mFilter;
 #ifdef ANDROID
   // Bug 691354
   // Using the LINEAR filter we get unexplained artifacts.
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -328,17 +328,17 @@ ContainerRender(ContainerT* aContainer,
     // invariant: our GL context should be current here, I don't think we can
     // assert it though
   }
 
   if (needsSurface) {
     // Unbind the current surface and rebind the previous one.
 #ifdef MOZ_DUMP_PAINTING
     if (gfxUtils::sDumpPainting) {
-      nsRefPtr<gfxImageSurface> surf = surface->Dump(aManager->GetCompositor());
+      RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor());
       WriteSnapshotToDumpFile(aContainer, surf);
     }
 #endif
 
     compositor->SetRenderTarget(previousTarget);
     EffectChain effectChain;
     LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(aContainer->GetMaskLayer(),
                                                             effectChain,
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -79,23 +79,17 @@ void
 ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect)
 {
   if (!mImageHost || !mImageHost->IsAttached()) {
     return;
   }
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
-    RefPtr<gfx::DataSourceSurface> dSurf = mImageHost->GetAsSurface();
-    gfxPlatform *platform = gfxPlatform::GetPlatform();
-    RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
-                                                                   dSurf->GetSize(),
-                                                                   dSurf->Stride(),
-                                                                   dSurf->GetFormat());
-    nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
+    RefPtr<gfx::DataSourceSurface> surf = mImageHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
 #endif
 
   mCompositor->MakeCurrent();
 
   EffectChain effectChain;
   LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -838,17 +838,17 @@ class CompositingRenderTarget : public T
 {
 public:
   CompositingRenderTarget(const gfx::IntPoint& aOrigin)
     : mOrigin(aOrigin)
   {}
   virtual ~CompositingRenderTarget() {}
 
 #ifdef MOZ_DUMP_PAINTING
-  virtual already_AddRefed<gfxImageSurface> Dump(Compositor* aCompositor) { return nullptr; }
+  virtual TemporaryRef<gfx::DataSourceSurface> Dump(Compositor* aCompositor) { return nullptr; }
 #endif
 
   const gfx::IntPoint& GetOrigin() { return mOrigin; }
 
 private:
   gfx::IntPoint mOrigin;
 };
 
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -106,24 +106,18 @@ ThebesLayerComposite::RenderLayer(const 
              "buffer is corrupted");
 
   gfx::Matrix4x4 transform;
   ToMatrix4x4(GetEffectiveTransform(), transform);
   gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
-    RefPtr<gfx::DataSourceSurface> dSurf = mBuffer->GetAsSurface();
-    if (dSurf) {
-      gfxPlatform *platform = gfxPlatform::GetPlatform();
-      RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
-                                                                     dSurf->GetSize(),
-                                                                     dSurf->Stride(),
-                                                                     dSurf->GetFormat());
-      nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
+    RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface();
+    if (surf) {
       WriteSnapshotToDumpFile(this, surf);
     }
   }
 #endif
 
   EffectChain effectChain;
   LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
 
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -128,17 +128,17 @@ namespace mozilla {
 namespace layers {
 
 /**
  * Constant describing the tolerance in distance we use, multiplied by the
  * device DPI, before we start panning the screen. This is to prevent us from
  * accidentally processing taps as touch moves, and from very short/accidental
  * touches moving the screen.
  */
-static float gTouchStartTolerance = 1.0f/16.0f;
+static float gTouchStartTolerance = 1.0f/2.0f;
 
 /**
  * Angle from axis within which we stay axis-locked
  */
 static const double AXIS_LOCK_ANGLE = M_PI / 6.0; // 30 degrees
 
 /**
  * The distance in inches the user must pan before axis lock can be broken
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
@@ -1,18 +1,21 @@
 /* -*- Mode: C++; tab-width: 20; 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 "CompositingRenderTargetOGL.h"
 #include "GLContext.h"
 #include "GLReadTexImageHelper.h"
+#include "mozilla/gfx/2D.h"
 
 using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace mozilla::gl;
 using namespace mozilla::layers;
 
 CompositingRenderTargetOGL::~CompositingRenderTargetOGL()
 {
   mGL->fDeleteTextures(1, &mTextureHandle);
   mGL->fDeleteFramebuffers(1, &mFBO);
 }
 
@@ -52,22 +55,22 @@ CompositingRenderTargetOGL::BindRenderTa
       }
     }
 
     mCompositor->PrepareViewport(mInitParams.mSize, mTransform);
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
-already_AddRefed<gfxImageSurface>
+TemporaryRef<DataSourceSurface>
 CompositingRenderTargetOGL::Dump(Compositor* aCompositor)
 {
   MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
   CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(aCompositor);
-  return GetTexImage(mGL, mTextureHandle, true, compositorOGL->GetFBOFormat());
+  return ReadBackSurface(mGL, mTextureHandle, true, compositorOGL->GetFBOFormat());
 }
 #endif
 
 void
 CompositingRenderTargetOGL::InitializeImpl()
 {
   MOZ_ASSERT(mInitParams.mStatus == InitParams::READY);
 
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -24,16 +24,19 @@
 #include "nsString.h"                   // for nsAutoCString
 
 class gfxImageSurface;
 
 namespace mozilla {
 namespace gl {
   class BindableTexture;
 }
+namespace gfx {
+  class DataSourceSurface;
+}
 
 namespace layers {
 
 class TextureSource;
 
 class CompositingRenderTargetOGL : public CompositingRenderTarget
 {
   typedef mozilla::gl::GLContext GLContext;
@@ -147,17 +150,17 @@ public:
     return gfx::FORMAT_UNKNOWN;
   }
 
   const gfxMatrix& GetTransform() {
     return mTransform;
   }
 
 #ifdef MOZ_DUMP_PAINTING
-  virtual already_AddRefed<gfxImageSurface> Dump(Compositor* aCompositor);
+  virtual TemporaryRef<gfx::DataSourceSurface> Dump(Compositor* aCompositor);
 #endif
 
 private:
   /**
    * Actually do the initialisation. Note that we leave our FBO bound, and so
    * calling this method is only suitable when about to use this render target.
    */
   void InitializeImpl();
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -88,49 +88,63 @@ GrallocTextureClientOGL::DropTextureData
     return result;
   }
 }
 
 GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor,
                                                  gfx::IntSize aSize,
                                                  TextureFlags aFlags)
 : BufferTextureClient(nullptr, gfx::FORMAT_UNKNOWN, aFlags)
+, mAllocator(nullptr)
 , mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN)
 , mMappedBuffer(nullptr)
 {
   InitWith(aActor, aSize);
   MOZ_COUNT_CTOR(GrallocTextureClientOGL);
 }
 
 GrallocTextureClientOGL::GrallocTextureClientOGL(CompositableClient* aCompositable,
                                                  gfx::SurfaceFormat aFormat,
                                                  TextureFlags aFlags)
 : BufferTextureClient(aCompositable, aFormat, aFlags)
+, mAllocator(nullptr)
+, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN)
+, mMappedBuffer(nullptr)
+{
+  MOZ_COUNT_CTOR(GrallocTextureClientOGL);
+}
+
+GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
+                                                 gfx::SurfaceFormat aFormat,
+                                                 TextureFlags aFlags)
+: BufferTextureClient(nullptr, aFormat, aFlags)
+, mAllocator(aAllocator)
 , mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN)
 , mMappedBuffer(nullptr)
 {
   MOZ_COUNT_CTOR(GrallocTextureClientOGL);
 }
 
 GrallocTextureClientOGL::~GrallocTextureClientOGL()
 {
   MOZ_COUNT_DTOR(GrallocTextureClientOGL);
     if (ShouldDeallocateInDestructor()) {
     // If the buffer has never been shared we must deallocate it or it would
     // leak.
     if (mBufferLocked) {
       mBufferLocked->Unlock();
     } else {
-      MOZ_ASSERT(mCompositable);
       // We just need to wrap the actor in a SurfaceDescriptor because that's what
       // ISurfaceAllocator uses as input, we don't care about the other parameters.
       SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
                                                       IntSize(0, 0),
                                                       false, false);
-      mCompositable->GetForwarder()->DestroySharedSurface(&sd);
+
+      ISurfaceAllocator* allocator = GetAllocator();
+      allocator->DestroySharedSurface(&sd);
     }
   }
 }
 
 void
 GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize)
 {
   MOZ_ASSERT(aActor);
@@ -190,18 +204,16 @@ GrallocTextureClientOGL::GetBuffer() con
   return mMappedBuffer;
 }
 
 bool
 GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
                                             TextureAllocationFlags)
 {
   MOZ_ASSERT(IsValid());
-  MOZ_ASSERT(mCompositable);
-  ISurfaceAllocator* allocator = mCompositable->GetForwarder();
 
   uint32_t format;
   uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN;
   bool swapRB = GetFlags() & TEXTURE_RB_SWAPPED;
 
   switch (mFormat) {
   case gfx::FORMAT_R8G8B8A8:
     format = swapRB ? android::PIXEL_FORMAT_BGRA_8888 : android::PIXEL_FORMAT_RGBA_8888;
@@ -233,23 +245,55 @@ GrallocTextureClientOGL::AllocateForYCbC
 {
   MOZ_ASSERT(IsValid());
   return AllocateGralloc(aYSize,
                          HAL_PIXEL_FORMAT_YV12,
                          android::GraphicBuffer::USAGE_SW_READ_OFTEN);
 }
 
 bool
+GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize)
+{
+  MOZ_ASSERT(IsValid());
+
+  uint32_t format;
+  uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
+                   android::GraphicBuffer::USAGE_HW_TEXTURE;
+
+  switch (mFormat) {
+  case gfx::FORMAT_R8G8B8A8:
+  case gfx::FORMAT_B8G8R8A8:
+    format = android::PIXEL_FORMAT_RGBA_8888;
+    break;
+  case gfx::FORMAT_R8G8B8X8:
+  case gfx::FORMAT_B8G8R8X8:
+    // there is no android BGRX format?
+    format = android::PIXEL_FORMAT_RGBX_8888;
+    break;
+  case gfx::FORMAT_R5G6B5:
+    format = android::PIXEL_FORMAT_RGB_565;
+    break;
+  case gfx::FORMAT_A8:
+    format = android::PIXEL_FORMAT_A_8;
+    break;
+  default:
+    NS_WARNING("Unsupported surface format");
+    return false;
+  }
+
+  return AllocateGralloc(aSize, format, usage);
+}
+
+bool
 GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
                                          uint32_t aAndroidFormat,
                                          uint32_t aUsage)
 {
   MOZ_ASSERT(IsValid());
-  MOZ_ASSERT(mCompositable);
-  ISurfaceAllocator* allocator = mCompositable->GetForwarder();
+  ISurfaceAllocator* allocator = GetAllocator();
 
   MaybeMagicGrallocBufferHandle handle;
   PGrallocBufferChild* actor =
     allocator->AllocGrallocBuffer(aSize,
                                   aAndroidFormat,
                                   aUsage,
                                   &handle);
   if (!actor) {
@@ -290,12 +334,21 @@ GrallocTextureClientOGL::Allocate(uint32
 size_t
 GrallocTextureClientOGL::GetBufferSize() const
 {
   // see Bug 908196
   MOZ_CRASH("This method should never be called.");
   return 0;
 }
 
+ISurfaceAllocator*
+GrallocTextureClientOGL::GetAllocator()
+{
+  MOZ_ASSERT(mCompositable || mAllocator);
+  return mCompositable ?
+         mCompositable->GetForwarder() :
+         mAllocator;
+}
+
 } // namesapace layers
 } // namesapace mozilla
 
 #endif // MOZ_WIDGET_GONK
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -34,16 +34,19 @@ class GrallocTextureClientOGL : public B
 {
 public:
   GrallocTextureClientOGL(GrallocBufferActor* aActor,
                           gfx::IntSize aSize,
                           TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
   GrallocTextureClientOGL(CompositableClient* aCompositable,
                           gfx::SurfaceFormat aFormat,
                           TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+  GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
+                          gfx::SurfaceFormat aFormat,
+                          TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
 
   ~GrallocTextureClientOGL();
 
   virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
@@ -51,16 +54,18 @@ public:
   virtual bool IsAllocated() const MOZ_OVERRIDE;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
 
   void InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize);
 
+  void SetTextureFlags(TextureFlags aFlags) { AddFlags(aFlags); }
+
   gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
   android::GraphicBuffer* GetGraphicBuffer()
   {
     return mGraphicBuffer.get();
   }
 
   android::PixelFormat GetPixelFormat()
@@ -82,35 +87,40 @@ public:
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
                                 gfx::IntSize aCbCrSize,
                                 StereoMode aStereoMode) MOZ_OVERRIDE;
 
+  bool AllocateForGLRendering(gfx::IntSize aSize);
+
   bool AllocateGralloc(gfx::IntSize aYSize, uint32_t aAndroidFormat, uint32_t aUsage);
 
   virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
 
   virtual size_t GetBufferSize() const MOZ_OVERRIDE;
 
   void SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked);
 
 protected:
+  ISurfaceAllocator* GetAllocator();
 
   /**
    * Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
    */
   GrallocBufferActor* mGrallocActor;
 
   RefPtr<GraphicBufferLocked> mBufferLocked;
 
   android::sp<android::GraphicBuffer> mGraphicBuffer;
 
+  RefPtr<ISurfaceAllocator> mAllocator;
+
   /**
    * Flags that are used when locking the gralloc buffer
    */
   uint32_t mGrallocFlags;
   /**
    * Points to a mapped gralloc buffer between calls to lock and unlock.
    * Should be null outside of the lock-unlock pair.
    */
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -1,17 +1,18 @@
 /* -*- Mode: C++; tab-width: 20; 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/layers/TextureClientOGL.h"
 #include "GLContext.h"                  // for GLContext, etc
+#include "SurfaceStream.h"
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/layers/ISurfaceAllocator.h"
+#include "mozilla/layers/TextureClientOGL.h"
 #include "nsSize.h"                     // for nsIntSize
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 class CompositableForwarder;
@@ -60,16 +61,52 @@ SharedTextureClientOGL::InitWith(gl::Sha
 }
 
 bool
 SharedTextureClientOGL::IsAllocated() const
 {
   return mHandle != 0;
 }
 
+StreamTextureClientOGL::StreamTextureClientOGL(TextureFlags aFlags)
+  : TextureClient(aFlags)
+  , mStream(0)
+{
+}
+
+StreamTextureClientOGL::~StreamTextureClientOGL()
+{
+  // the data is owned externally.
+}
+
+bool
+StreamTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+{
+  if (!IsAllocated()) {
+    return false;
+  }
+
+  gfx::SurfaceStreamHandle handle = mStream->GetShareHandle();
+  aOutDescriptor = SurfaceStreamDescriptor(handle, false);
+  return true;
+}
+
+void
+StreamTextureClientOGL::InitWith(gfx::SurfaceStream* aStream)
+{
+  MOZ_ASSERT(!IsAllocated());
+  mStream = aStream;
+}
+
+bool
+StreamTextureClientOGL::IsAllocated() const
+{
+  return mStream != 0;
+}
+
 DeprecatedTextureClientSharedOGL::DeprecatedTextureClientSharedOGL(CompositableForwarder* aForwarder,
                                                const TextureInfo& aTextureInfo)
   : DeprecatedTextureClient(aForwarder, aTextureInfo)
   , mGL(nullptr)
 {
 }
 
 void
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -10,16 +10,22 @@
 #include "gfxTypes.h"
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureClient.h"  // for DeprecatedTextureClient, etc
 
 namespace mozilla {
+namespace gfx {
+class SurfaceStream;
+}
+}
+
+namespace mozilla {
 namespace layers {
 
 class CompositableForwarder;
 
 /**
  * A TextureClient implementation to share TextureMemory that is already
  * on the GPU, for the OpenGL backend.
  */
@@ -52,16 +58,40 @@ public:
 
 protected:
   gl::SharedTextureHandle mHandle;
   gfx::IntSize mSize;
   gl::SharedTextureShareType mShareType;
   bool mInverted;
 };
 
+/**
+ * A TextureClient implementation to share SurfaceStream.
+ */
+class StreamTextureClientOGL : public TextureClient
+{
+public:
+  StreamTextureClientOGL(TextureFlags aFlags);
+
+  ~StreamTextureClientOGL();
+
+  virtual bool IsAllocated() const MOZ_OVERRIDE;
+
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
+
+  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE { return nullptr; }
+
+  void InitWith(gfx::SurfaceStream* aStream);
+
+  virtual gfx::IntSize GetSize() const { return gfx::IntSize(); }
+
+protected:
+  gfx::SurfaceStream* mStream;
+};
+
 class DeprecatedTextureClientSharedOGL : public DeprecatedTextureClient
 {
 public:
   DeprecatedTextureClientSharedOGL(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo);
   ~DeprecatedTextureClientSharedOGL() { ReleaseResources(); }
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_SHARED_GL; }
   virtual bool EnsureAllocated(gfx::IntSize aSize, gfxContentType aType);
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -103,16 +103,21 @@ CreateTextureHostOGL(const SurfaceDescri
       const SharedTextureDescriptor& desc = aDesc.get_SharedTextureDescriptor();
       result = new SharedTextureHostOGL(aFlags,
                                         desc.shareType(),
                                         desc.handle(),
                                         desc.size(),
                                         desc.inverted());
       break;
     }
+    case SurfaceDescriptor::TSurfaceStreamDescriptor: {
+      const SurfaceStreamDescriptor& desc = aDesc.get_SurfaceStreamDescriptor();
+      result = new StreamTextureHostOGL(aFlags, desc);
+      break;
+    }
 #ifdef XP_MACOSX
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
       const SurfaceDescriptorMacIOSurface& desc =
         aDesc.get_SurfaceDescriptorMacIOSurface();
       result = new MacIOSurfaceTextureHostOGL(aFlags, desc);
       break;
     }
 #endif
@@ -458,16 +463,194 @@ SharedTextureHostOGL::SetCompositor(Comp
 
 gfx::SurfaceFormat
 SharedTextureHostOGL::GetFormat() const
 {
   MOZ_ASSERT(mTextureSource);
   return mTextureSource->GetFormat();
 }
 
+void
+StreamTextureSourceOGL::BindTexture(GLenum activetex)
+{
+  MOZ_ASSERT(gl());
+  gl()->fActiveTexture(activetex);
+  gl()->fBindTexture(mTextureTarget, mTextureHandle);
+}
+
+bool
+StreamTextureSourceOGL::RetrieveTextureFromStream()
+{
+  gl()->MakeCurrent();
+
+  SharedSurface* sharedSurf = mStream->SwapConsumer();
+  if (!sharedSurf) {
+    // We don't have a valid surf to show yet.
+    return false;
+  }
+
+  gl()->MakeCurrent();
+
+  mSize = IntSize(sharedSurf->Size().width, sharedSurf->Size().height);
+
+  DataSourceSurface* toUpload = nullptr;
+  switch (sharedSurf->Type()) {
+    case SharedSurfaceType::GLTextureShare: {
+      SharedSurface_GLTexture* glTexSurf = SharedSurface_GLTexture::Cast(sharedSurf);
+      glTexSurf->SetConsumerGL(gl());
+      mTextureHandle = glTexSurf->Texture();
+      mTextureTarget = glTexSurf->TextureTarget();
+      MOZ_ASSERT(mTextureHandle);
+      mFormat = sharedSurf->HasAlpha() ? FORMAT_R8G8B8A8
+                                       : FORMAT_R8G8B8X8;
+      break;
+    }
+    case SharedSurfaceType::EGLImageShare: {
+      SharedSurface_EGLImage* eglImageSurf =
+          SharedSurface_EGLImage::Cast(sharedSurf);
+
+      mTextureHandle = eglImageSurf->AcquireConsumerTexture(gl());
+      mTextureTarget = eglImageSurf->TextureTarget();
+      if (!mTextureHandle) {
+        toUpload = eglImageSurf->GetPixels();
+        MOZ_ASSERT(toUpload);
+      } else {
+        mFormat = sharedSurf->HasAlpha() ? FORMAT_R8G8B8A8
+                                         : FORMAT_R8G8B8X8;
+      }
+      break;
+    }
+#ifdef XP_MACOSX
+    case SharedSurfaceType::IOSurface: {
+      SharedSurface_IOSurface* glTexSurf = SharedSurface_IOSurface::Cast(sharedSurf);
+      mTextureHandle = glTexSurf->Texture();
+      mTextureTarget = glTexSurf->TextureTarget();
+      MOZ_ASSERT(mTextureHandle);
+      mFormat = sharedSurf->HasAlpha() ? FORMAT_R8G8B8A8
+                                       : FORMAT_R8G8B8X8;
+      break;
+    }
+#endif
+    case SharedSurfaceType::Basic: {
+      toUpload = SharedSurface_Basic::Cast(sharedSurf)->GetData();
+      MOZ_ASSERT(toUpload);
+      break;
+    }
+    default:
+      MOZ_CRASH("Invalid SharedSurface type.");
+  }
+
+  if (toUpload) {
+    // mBounds seems to end up as (0,0,0,0) a lot, so don't use it?
+    nsIntSize size(ThebesIntSize(toUpload->GetSize()));
+    nsIntRect rect(nsIntPoint(0,0), size);
+    nsIntRegion bounds(rect);
+    mFormat = UploadSurfaceToTexture(gl(),
+                                     toUpload,
+                                     bounds,
+                                     mUploadTexture,
+                                     true);
+    mTextureHandle = mUploadTexture;
+    mTextureTarget = LOCAL_GL_TEXTURE_2D;
+  }
+
+  MOZ_ASSERT(mTextureHandle);
+  gl()->fBindTexture(mTextureTarget, mTextureHandle);
+  gl()->fTexParameteri(mTextureTarget,
+                      LOCAL_GL_TEXTURE_WRAP_S,
+                      LOCAL_GL_CLAMP_TO_EDGE);
+  gl()->fTexParameteri(mTextureTarget,
+                      LOCAL_GL_TEXTURE_WRAP_T,
+                      LOCAL_GL_CLAMP_TO_EDGE);
+
+  return true;
+}
+
+void
+StreamTextureSourceOGL::DeallocateDeviceData()
+{
+  if (mUploadTexture) {
+    MOZ_ASSERT(gl());
+    gl()->MakeCurrent();
+    gl()->fDeleteTextures(1, &mUploadTexture);
+    mUploadTexture = 0;
+    mTextureHandle = 0;
+  }
+}
+
+gl::GLContext*
+StreamTextureSourceOGL::gl() const
+{
+  return mCompositor ? mCompositor->gl() : nullptr;
+}
+
+void
+StreamTextureSourceOGL::SetCompositor(Compositor* aCompositor)
+{
+  mCompositor = static_cast<CompositorOGL*>(aCompositor);
+}
+
+StreamTextureHostOGL::StreamTextureHostOGL(TextureFlags aFlags,
+                                           const SurfaceStreamDescriptor& aDesc)
+  : TextureHost(aFlags)
+{
+  mStream = SurfaceStream::FromHandle(aDesc.handle());
+  MOZ_ASSERT(mStream);
+}
+
+StreamTextureHostOGL::~StreamTextureHostOGL()
+{
+  // If need to deallocate textures, call DeallocateSharedData() before
+  // the destructor
+}
+
+bool
+StreamTextureHostOGL::Lock()
+{
+  if (!mCompositor) {
+    return false;
+  }
+
+  if (!mTextureSource) {
+    mTextureSource = new StreamTextureSourceOGL(mCompositor,
+                                                mStream);
+  }
+
+  return mTextureSource->RetrieveTextureFromStream();
+}
+
+void
+StreamTextureHostOGL::Unlock()
+{
+}
+
+void
+StreamTextureHostOGL::SetCompositor(Compositor* aCompositor)
+{
+  CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
+  mCompositor = glCompositor;
+  if (mTextureSource) {
+    mTextureSource->SetCompositor(glCompositor);
+  }
+}
+
+gfx::SurfaceFormat
+StreamTextureHostOGL::GetFormat() const
+{
+  MOZ_ASSERT(mTextureSource);
+  return mTextureSource->GetFormat();
+}
+
+gfx::IntSize
+StreamTextureHostOGL::GetSize() const
+{
+  MOZ_ASSERT(mTextureSource);
+  return mTextureSource->GetSize();
+}
+
 TextureImageDeprecatedTextureHostOGL::~TextureImageDeprecatedTextureHostOGL()
 {
   MOZ_COUNT_DTOR(TextureImageDeprecatedTextureHostOGL);
   if (mTexture && mTexture->InUpdate()) {
     mTexture->EndUpdate();
   }
 }
 
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -331,16 +331,118 @@ protected:
   CompositorOGL* mCompositor;
   gl::SharedTextureHandle mSharedHandle;
   gl::SharedTextureShareType mShareType;
 
   RefPtr<SharedTextureSourceOGL> mTextureSource;
 };
 
 /**
+ * A texture source meant for use with StreamTextureHostOGL.
+ *
+ * It does not own any texture, we get texture from SurfaceStream.
+ */
+class StreamTextureSourceOGL : public NewTextureSource
+                             , public TextureSourceOGL
+{
+public:
+  StreamTextureSourceOGL(CompositorOGL* aCompositor,
+                         gfx::SurfaceStream* aStream)
+    : mCompositor(aCompositor)
+    , mStream(aStream)
+    , mTextureHandle(0)
+    , mTextureTarget(LOCAL_GL_TEXTURE_2D)
+    , mUploadTexture(0)
+    , mFormat(gfx::FORMAT_UNKNOWN)
+  {
+    MOZ_COUNT_CTOR(StreamTextureSourceOGL);
+  }
+
+  ~StreamTextureSourceOGL()
+  {
+    MOZ_COUNT_DTOR(StreamTextureSourceOGL);
+  }
+
+  virtual TextureSourceOGL* AsSourceOGL() { return this; }
+
+  virtual void BindTexture(GLenum activetex) MOZ_OVERRIDE;
+
+  virtual bool IsValid() const MOZ_OVERRIDE { return !!gl(); }
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
+
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
+
+  virtual GLenum GetTextureTarget() const { return mTextureTarget; }
+
+  virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return LOCAL_GL_CLAMP_TO_EDGE; }
+
+  virtual void DeallocateDeviceData();
+
+  bool RetrieveTextureFromStream();
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+protected:
+  gl::GLContext* gl() const;
+
+  CompositorOGL* mCompositor;
+  gfx::SurfaceStream* mStream;
+  GLuint mTextureHandle;
+  GLenum mTextureTarget;
+  GLuint mUploadTexture;
+  gfx::IntSize mSize;
+  gfx::SurfaceFormat mFormat;
+};
+
+/**
+ * A TextureHost for shared SurfaceStream
+ */
+class StreamTextureHostOGL : public TextureHost
+{
+public:
+  StreamTextureHostOGL(TextureFlags aFlags,
+                       const SurfaceStreamDescriptor& aDesc);
+
+  virtual ~StreamTextureHostOGL();
+
+  // SharedTextureHostOGL doesn't own any GL texture
+  virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+  virtual bool Lock() MOZ_OVERRIDE;
+
+  virtual void Unlock() MOZ_OVERRIDE;
+
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
+
+  virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
+  {
+    return mTextureSource;
+  }
+
+  virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
+  {
+    return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
+  }
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual const char* Name() { return "StreamTextureHostOGL"; }
+#endif
+
+protected:
+  CompositorOGL* mCompositor;
+  gfx::SurfaceStream* mStream;
+  RefPtr<StreamTextureSourceOGL> mTextureSource;
+};
+
+/**
  * DeprecatedTextureHost implementation using a TextureImage as the underlying texture.
  */
 class TextureImageDeprecatedTextureHostOGL : public DeprecatedTextureHost
                                            , public TextureSourceOGL
                                            , public TileIterator
 {
 public:
   TextureImageDeprecatedTextureHostOGL(gl::TextureImage* aTexImage = nullptr)
new file mode 100644
--- /dev/null
+++ b/gfx/tests/gtest/TestSkipChars.cpp
@@ -0,0 +1,135 @@
+/* -*- 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 "gtest/gtest.h"
+
+#include "gfxSkipChars.h"
+#include "mozilla/ArrayUtils.h"
+
+static bool
+TestConstructor()
+{
+  gfxSkipChars skipChars;
+
+  EXPECT_TRUE(skipChars.GetOriginalCharCount() == 0) <<
+    "[1] Make sure the gfxSkipChars was properly initialized with constructor";
+
+  return true;
+}
+
+static bool
+TestLength()
+{
+  gfxSkipChars skipChars;
+
+  skipChars.KeepChars(100);
+
+  EXPECT_TRUE(skipChars.GetOriginalCharCount() == 100) <<
+    "[1] Check length after keeping chars";
+
+  skipChars.SkipChars(50);
+
+  EXPECT_TRUE(skipChars.GetOriginalCharCount() == 150) <<
+    "[2] Check length after skipping chars";
+
+  skipChars.SkipChars(50);
+
+  EXPECT_TRUE(skipChars.GetOriginalCharCount() == 200) <<
+    "[3] Check length after skipping more chars";
+
+  skipChars.KeepChar();
+
+  EXPECT_TRUE(skipChars.GetOriginalCharCount() == 201) <<
+    "[4] Check length after keeping a final char";
+
+  return true;
+}
+
+static bool
+TestIterator()
+{
+  // Test a gfxSkipChars that starts with kept chars
+  gfxSkipChars skipChars1;
+
+  skipChars1.KeepChars(9);
+  skipChars1.SkipChar();
+  skipChars1.KeepChars(9);
+  skipChars1.SkipChar();
+  skipChars1.KeepChars(9);
+
+  EXPECT_TRUE(skipChars1.GetOriginalCharCount() == 29) <<
+    "[1] Check length";
+
+  gfxSkipCharsIterator iter1(skipChars1);
+
+  EXPECT_TRUE(iter1.GetOriginalOffset() == 0) <<
+    "[2] Check initial original offset";
+  EXPECT_TRUE(iter1.GetSkippedOffset() == 0) <<
+    "[3] Check initial skipped offset";
+
+  uint32_t expectSkipped1[] =
+  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+     9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+    18, 19, 20, 21, 22, 23, 24, 25, 26, 27 };
+
+  for (uint32_t i = 0; i < mozilla::ArrayLength(expectSkipped1); i++) {
+    EXPECT_TRUE(iter1.ConvertOriginalToSkipped(i) == expectSkipped1[i]) <<
+      "[4] Check mapping of original to skipped for " << i;
+  }
+
+  uint32_t expectOriginal1[] =
+  {  0,  1,  2,  3,  4,  5,  6,  7,  8,
+    10, 11, 12, 13, 14, 15, 16, 17, 18,
+    20, 21, 22, 23, 24, 25, 26, 27, 28 };
+
+  for (uint32_t i = 0; i < mozilla::ArrayLength(expectOriginal1); i++) {
+    EXPECT_TRUE(iter1.ConvertSkippedToOriginal(i) == expectOriginal1[i]) <<
+      "[5] Check mapping of skipped to original for " << i;
+  }
+
+  // Test a gfxSkipChars that starts with skipped chars
+  gfxSkipChars skipChars2;
+
+  skipChars2.SkipChars(9);
+  skipChars2.KeepChar();
+  skipChars2.SkipChars(9);
+  skipChars2.KeepChar();
+  skipChars2.SkipChars(9);
+
+  EXPECT_TRUE(skipChars2.GetOriginalCharCount() == 29) <<
+    "[6] Check length";
+
+  gfxSkipCharsIterator iter2(skipChars2);
+
+  EXPECT_TRUE(iter2.GetOriginalOffset() == 0) <<
+    "[7] Check initial original offset";
+  EXPECT_TRUE(iter2.GetSkippedOffset() == 0) <<
+    "[8] Check initial skipped offset";
+
+  uint32_t expectSkipped2[] =
+  {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+     2,  2,  2,  2,  2,  2,  2,  2,  2,  2 };
+
+  for (uint32_t i = 0; i < mozilla::ArrayLength(expectSkipped2); i++) {
+    EXPECT_TRUE(iter2.ConvertOriginalToSkipped(i) == expectSkipped2[i]) <<
+      "[9] Check mapping of original to skipped for " << i;
+  }
+
+  uint32_t expectOriginal2[] = { 9, 19, 29 };
+
+  for (uint32_t i = 0; i < mozilla::ArrayLength(expectOriginal2); i++) {
+    EXPECT_TRUE(iter2.ConvertSkippedToOriginal(i) == expectOriginal2[i]) <<
+      "[10] Check mapping of skipped to original for " << i;
+  }
+
+  return true;
+}
+
+TEST(Gfx, gfxSkipChars) {
+  TestConstructor();
+  TestLength();
+  TestIterator();
+}
--- a/gfx/tests/gtest/moz.build
+++ b/gfx/tests/gtest/moz.build
@@ -10,16 +10,17 @@ UNIFIED_SOURCES += [
     'gfxSurfaceRefCountTest.cpp',
     # Disabled on suspicion of causing bug 904227
     #'gfxWordCacheTest.cpp',
     'TestAsyncPanZoomController.cpp',
     'TestBufferRotation.cpp',
     'TestColorNames.cpp',
     'TestLayers.cpp',
     'TestRegion.cpp',
+    'TestSkipChars.cpp',
     # Hangs on linux in ApplyGdkScreenFontOptions
     #'gfxFontSelectionTest.cpp',
     'TestTextures.cpp',
     # Test works but it doesn't assert anything
     #'gfxTextRunPerfTest.cpp',
     'TestTiledLayerBuffer.cpp',
 ]
 
--- a/gfx/thebes/gfxPattern.cpp
+++ b/gfx/thebes/gfxPattern.cpp
@@ -174,18 +174,21 @@ Pattern*
 gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform)
 {
   if (mGfxPattern) {
     mGfxPattern->~Pattern();
     mGfxPattern = nullptr;
   }
 
   if (!mPattern) {
+    Matrix adjustedMatrix = mTransform;
+    if (aPatternTransform)
+      AdjustTransformForPattern(adjustedMatrix, aTarget->GetTransform(), aPatternTransform);
     mGfxPattern = new (mSurfacePattern.addr())
-      SurfacePattern(mSourceSurface, ToExtendMode(mExtend), mTransform, mFilter);
+      SurfacePattern(mSourceSurface, ToExtendMode(mExtend), adjustedMatrix, mFilter);
     return mGfxPattern;
   }
 
   GraphicsExtend extend = (GraphicsExtend)cairo_pattern_get_extend(mPattern);
 
   switch (cairo_pattern_get_type(mPattern)) {
   case CAIRO_PATTERN_TYPE_SOLID:
     {
--- a/gfx/thebes/gfxSkipChars.cpp
+++ b/gfx/thebes/gfxSkipChars.cpp
@@ -1,231 +1,140 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 "gfxSkipChars.h"
 
-#include <stdlib.h>
-#include <algorithm>
-
-#define SHORTCUT_FREQUENCY 256
-
-// Even numbered list entries are "keep" entries
-static bool
-IsKeepEntry(uint32_t aEntry)
+void
+gfxSkipCharsIterator::SetOriginalOffset(int32_t aOffset)
 {
-    return !(aEntry & 1);
-}
+    aOffset += mOriginalStringToSkipCharsOffset;
+    NS_ASSERTION(uint32_t(aOffset) <= mSkipChars->mCharCount,
+                 "Invalid offset");
 
-void
-gfxSkipChars::BuildShortcuts()
-{
-    if (!mList || mCharCount < SHORTCUT_FREQUENCY)
-        return;
-  
-    mShortcuts = new Shortcut[mCharCount/SHORTCUT_FREQUENCY];
-    if (!mShortcuts)
+    mOriginalStringOffset = aOffset;
+
+    uint32_t rangeCount = mSkipChars->mRanges.Length();
+    if (rangeCount == 0) {
+        mSkippedStringOffset = aOffset;
         return;
-  
-    uint32_t i;
-    uint32_t nextShortcutIndex = 0;
-    uint32_t originalCharOffset = 0;
-    uint32_t skippedCharOffset = 0;
-    for (i = 0; i < mListLength; ++i) {
-        uint8_t len = mList[i];
-    
-        // We use >= here to ensure that when mCharCount is a multiple of
-        // SHORTCUT_FREQUENCY, we fill in the final shortcut with a reference
-        // to the last element of mList. This means that in general when a list
-        // element ends on an offset that's a multiple of SHORTCUT_FREQUENCY,
-        // that list element is the shortcut for that offset, which is
-        // slightly suboptimal (the *next* element is the one we really want),
-        // but it's all correct and simpler this way.
-        while (originalCharOffset + len >= (nextShortcutIndex + 1)*SHORTCUT_FREQUENCY) {
-            mShortcuts[nextShortcutIndex] =
-                Shortcut(i, originalCharOffset, skippedCharOffset);
-            ++nextShortcutIndex;
-        }
-    
-        originalCharOffset += len;
-        if (IsKeepEntry(i)) {
-            skippedCharOffset += len;
+    }
+
+    // at start of string?
+    if (aOffset == 0) {
+        mSkippedStringOffset = 0;
+        mCurrentRangeIndex =
+            rangeCount && mSkipChars->mRanges[0].Start() == 0 ? 0 : -1;
+        return;
+    }
+
+    // find the range that includes or precedes aOffset
+    uint32_t lo = 0, hi = rangeCount;
+    const gfxSkipChars::SkippedRange* ranges = mSkipChars->mRanges.Elements();
+    while (lo < hi) {
+        uint32_t mid = (lo + hi) / 2;
+        if (uint32_t(aOffset) < ranges[mid].Start()) {
+            hi = mid;
+        } else {
+            lo = mid + 1;
         }
     }
+
+    if (lo == rangeCount) {
+        mCurrentRangeIndex = rangeCount - 1;
+    } else if (uint32_t(aOffset) < ranges[lo].Start()) {
+        mCurrentRangeIndex = lo - 1;
+        if (mCurrentRangeIndex == -1) {
+            mSkippedStringOffset = aOffset;
+            return;
+        }
+    } else {
+        mCurrentRangeIndex = lo;
+    }
+
+    const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex];
+    if (uint32_t(aOffset) < r.End()) {
+        mSkippedStringOffset = r.SkippedOffset();
+        return;
+    }
+
+    mSkippedStringOffset = aOffset - r.NextDelta();
 }
 
 void
-gfxSkipCharsIterator::SetOffsets(uint32_t aOffset, bool aInOriginalString)
+gfxSkipCharsIterator::SetSkippedOffset(uint32_t aOffset)
 {
-    NS_ASSERTION(aOffset <= mSkipChars->mCharCount,
-                 "Invalid offset");
+    NS_ASSERTION((mSkipChars->mRanges.IsEmpty() &&
+                  aOffset <= mSkipChars->mCharCount) ||
+                 (aOffset <= mSkipChars->LastRange().SkippedOffset() +
+                                 mSkipChars->mCharCount -
+                                 mSkipChars->LastRange().End()),
+                 "Invalid skipped offset");
+    mSkippedStringOffset = aOffset;
 
-    if (mSkipChars->mListLength == 0) {
-        mOriginalStringOffset = mSkippedStringOffset = aOffset;
+    uint32_t rangeCount = mSkipChars->mRanges.Length();
+    if (rangeCount == 0) {
+        mOriginalStringOffset = aOffset;
         return;
     }
-  
-    if (aOffset == 0) {
-        // Start from the beginning of the string.
-        mSkippedStringOffset = 0;
-        mOriginalStringOffset = 0;
-        mListPrefixLength = 0;
-        mListPrefixKeepCharCount = 0;
-        mListPrefixCharCount = 0;
-        if (aInOriginalString) {
-            // Nothing more to do!
-            return;
-        }
-    }
-  
-    if (aInOriginalString && mSkipChars->mShortcuts &&
-        abs(int32_t(aOffset) - int32_t(mListPrefixCharCount)) > SHORTCUT_FREQUENCY) {
-        // Take a shortcut. This makes SetOffsets(..., true) O(1) by bounding
-        // the iterations in the loop below to at most SHORTCUT_FREQUENCY iterations
-        uint32_t shortcutIndex = aOffset/SHORTCUT_FREQUENCY;
-        if (shortcutIndex == 0) {
-            mListPrefixLength = 0;
-            mListPrefixKeepCharCount = 0;
-            mListPrefixCharCount = 0;
+
+    uint32_t lo = 0, hi = rangeCount;
+    const gfxSkipChars::SkippedRange* ranges = mSkipChars->mRanges.Elements();
+    while (lo < hi) {
+        uint32_t mid = (lo + hi) / 2;
+        if (aOffset < ranges[mid].SkippedOffset()) {
+            hi = mid;
         } else {
-            const gfxSkipChars::Shortcut& shortcut = mSkipChars->mShortcuts[shortcutIndex - 1];
-            mListPrefixLength = shortcut.mListPrefixLength;
-            mListPrefixKeepCharCount = shortcut.mListPrefixKeepCharCount;
-            mListPrefixCharCount = shortcut.mListPrefixCharCount;
+            lo = mid + 1;
         }
     }
-  
-    int32_t currentRunLength = mSkipChars->mList[mListPrefixLength];
-    for (;;) {
-        // See if aOffset is in the string segment described by
-        // mSkipChars->mList[mListPrefixLength]
-        uint32_t segmentOffset = aInOriginalString ? mListPrefixCharCount : mListPrefixKeepCharCount;
-        if ((aInOriginalString || IsKeepEntry(mListPrefixLength)) &&
-            aOffset >= segmentOffset && aOffset < segmentOffset + currentRunLength) {
-            int32_t offsetInSegment = aOffset - segmentOffset;
-            mOriginalStringOffset = mListPrefixCharCount + offsetInSegment;
-            mSkippedStringOffset = mListPrefixKeepCharCount;
-            if (IsKeepEntry(mListPrefixLength)) {
-                mSkippedStringOffset += offsetInSegment;
-            }
+
+    if (lo == rangeCount) {
+        mCurrentRangeIndex = rangeCount - 1;
+    } else if (aOffset < ranges[lo].SkippedOffset()) {
+        mCurrentRangeIndex = lo - 1;
+        if (mCurrentRangeIndex == -1) {
+            mOriginalStringOffset = aOffset;
             return;
         }
-        
-        if (aOffset < segmentOffset) {
-            // We need to move backwards
-            if (mListPrefixLength <= 0) {
-                // nowhere to go backwards
-                mOriginalStringOffset = mSkippedStringOffset = 0;
-                return;
-            }
-            // Go backwards one segment and restore invariants
-            --mListPrefixLength;
-            currentRunLength = mSkipChars->mList[mListPrefixLength];
-            mListPrefixCharCount -= currentRunLength;
-            if (IsKeepEntry(mListPrefixLength)) {
-                mListPrefixKeepCharCount -= currentRunLength;
-            }
-        } else {
-            // We need to move forwards
-            if (mListPrefixLength >= mSkipChars->mListLength - 1) {
-                // nowhere to go forwards
-                mOriginalStringOffset = mListPrefixCharCount + currentRunLength;
-                mSkippedStringOffset = mListPrefixKeepCharCount;
-                if (IsKeepEntry(mListPrefixLength)) {
-                    mSkippedStringOffset += currentRunLength;
-                }
-                return;
-            }
-            // Go forwards one segment and restore invariants
-            mListPrefixCharCount += currentRunLength;
-            if (IsKeepEntry(mListPrefixLength)) {
-                mListPrefixKeepCharCount += currentRunLength;
-            }
-            ++mListPrefixLength;
-            currentRunLength = mSkipChars->mList[mListPrefixLength];
-        }
+    } else {
+        mCurrentRangeIndex = lo;
     }
+
+    const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex];
+    mOriginalStringOffset = r.End() + aOffset - r.SkippedOffset();
 }
 
 bool
 gfxSkipCharsIterator::IsOriginalCharSkipped(int32_t* aRunLength) const
 {
-    if (mSkipChars->mListLength == 0) {
+    if (mCurrentRangeIndex == -1) {
+        // we're before the first skipped range (if any)
         if (aRunLength) {
-            *aRunLength = mSkipChars->mCharCount - mOriginalStringOffset;
+            uint32_t end = mSkipChars->mRanges.IsEmpty() ?
+                mSkipChars->mCharCount : mSkipChars->mRanges[0].Start();
+            *aRunLength = end - mOriginalStringOffset;
         }
         return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset);
     }
-  
-    uint32_t listPrefixLength = mListPrefixLength;
-    // figure out which segment we're in
-    uint32_t currentRunLength = mSkipChars->mList[listPrefixLength];
-    // Zero-length list entries are possible. Advance until mListPrefixLength
-    // is pointing to a run with real characters (or we're at the end of the
-    // string).
-    while (currentRunLength == 0 && listPrefixLength < mSkipChars->mListLength - 1) {
-        ++listPrefixLength;
-        // This does not break the iterator's invariant because no skipped
-        // or kept characters are being added
-        currentRunLength = mSkipChars->mList[listPrefixLength];
-    }
-    NS_ASSERTION(uint32_t(mOriginalStringOffset) >= mListPrefixCharCount,
-                 "Invariant violation");
-    uint32_t offsetIntoCurrentRun =
-      uint32_t(mOriginalStringOffset) - mListPrefixCharCount;
-    if (listPrefixLength >= mSkipChars->mListLength - 1 &&
-        offsetIntoCurrentRun >= currentRunLength) {
-        NS_ASSERTION(listPrefixLength == mSkipChars->mListLength - 1 &&
-                     offsetIntoCurrentRun == currentRunLength,
-                     "Overran end of string");
-        // We're at the end of the string
+
+    const gfxSkipChars::SkippedRange& range =
+        mSkipChars->mRanges[mCurrentRangeIndex];
+
+    if (uint32_t(mOriginalStringOffset) < range.End()) {
         if (aRunLength) {
-            *aRunLength = 0;
+            *aRunLength = range.End() - mOriginalStringOffset;
         }
         return true;
     }
-  
-    bool isSkipped = !IsKeepEntry(listPrefixLength);
-    if (aRunLength) {
-        // Long runs of all-skipped or all-kept characters will be encoded as
-        // sequences of 255, 0, 255, 0 etc. Compute the maximum run length by skipping
-        // over zero entries.
-        uint32_t runLength = currentRunLength - offsetIntoCurrentRun;
-        for (uint32_t i = listPrefixLength + 2; i < mSkipChars->mListLength; i += 2) {
-            if (mSkipChars->mList[i - 1] != 0)
-                break;
-            runLength += mSkipChars->mList[i];
-        }
-        *aRunLength = runLength;
-    }
-    return isSkipped;
-}
 
-void
-gfxSkipCharsBuilder::FlushRun()
-{
-    NS_ASSERTION((mBuffer.Length() & 1) == mRunSkipped,
-                 "out of sync?");
-    // Fill in buffer entries starting at mBufferLength, as many as necessary
-    uint32_t charCount = mRunCharCount;
-    for (;;) {
-        uint32_t chars = std::min<uint32_t>(255, charCount);
-        if (!mBuffer.AppendElement(chars)) {
-            mInErrorState = true;
-            return;
-        }
-        charCount -= chars;
-        if (charCount == 0)
-            break;
-        if (!mBuffer.AppendElement(0)) {
-            mInErrorState = true;
-            return;
-        }
+    if (aRunLength) {
+        uint32_t end =
+            uint32_t(mCurrentRangeIndex) + 1 < mSkipChars->mRanges.Length() ?
+                mSkipChars->mRanges[mCurrentRangeIndex + 1].Start() :
+                mSkipChars->mCharCount;
+        *aRunLength = end - mOriginalStringOffset;
     }
-  
-    NS_ASSERTION(mCharCount + mRunCharCount >= mCharCount,
-                 "String length overflow");
-    mCharCount += mRunCharCount;
-    mRunCharCount = 0;
-    mRunSkipped = !mRunSkipped;
+
+    return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset);
 }
--- a/gfx/thebes/gfxSkipChars.h
+++ b/gfx/thebes/gfxSkipChars.h
@@ -1,316 +1,302 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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/. */
 
 #ifndef GFX_SKIP_CHARS_H
 #define GFX_SKIP_CHARS_H
 
-#include "nsAutoPtr.h"
 #include "nsTArray.h"
 
 /*
  * gfxSkipChars is a data structure representing a list of characters that
  * have been skipped. The initial string is called the "original string"
  * and after skipping some characters, the result is called the "skipped string".
  * gfxSkipChars provides efficient ways to translate between offsets in the
  * original string and the skipped string. It is used by textrun code to keep
  * track of offsets before and after text transformations such as whitespace
  * compression and control code deletion.
  */
 
 /**
- * gfxSkipCharsBuilder is a helper class that accumulates a list of (skip, keep)
- * commands and can eventually be used to construct a real gfxSkipChars.
- * gfxSkipCharsBuilder objects are quite large so don't keep these around.
- * On the positive side, the Skip/KeepChar(s) methods are very efficient,
- * especially when you have runs of all-kept or all-skipped characters.
- * 
- * mBuffer is an array of bytes; even numbered bytes represent characters kept,
- * odd numbered bytes represent characters skipped. After those characters
- * are accounted for, we have mRunCharCount characters which are kept or
- * skipped depending on the value of mRunSkipped.
- * 
- * mCharCount is the sum of counts of all skipped and kept characters, i.e.,
- * the length of the original string.
+ * The gfxSkipChars is represented as a sorted array of skipped ranges.
+ *
+ * A freshly-created gfxSkipChars means "all chars kept".
  */
-class gfxSkipCharsBuilder {
+class gfxSkipChars
+{
+private:
+    class SkippedRange
+    {
+    public:
+        SkippedRange(uint32_t aOffset, uint32_t aLength, uint32_t aDelta)
+            : mOffset(aOffset), mLength(aLength), mDelta(aDelta)
+        { }
+
+        uint32_t Start() const
+        {
+            return mOffset;
+        }
+
+        uint32_t End() const
+        {
+            return mOffset + mLength;
+        }
+
+        uint32_t Length() const
+        {
+            return mLength;
+        }
+
+        uint32_t SkippedOffset() const
+        {
+            return mOffset - mDelta;
+        }
+
+        uint32_t Delta() const
+        {
+            return mDelta;
+        }
+
+        uint32_t NextDelta() const
+        {
+            return mDelta + mLength;
+        }
+
+        void Extend(uint32_t aChars)
+        {
+            mLength += aChars;
+        }
+
+    private:
+        uint32_t mOffset; // original-string offset at which we want to skip
+        uint32_t mLength; // number of skipped chars at this offset
+        uint32_t mDelta;  // sum of lengths of preceding skipped-ranges
+    };
+
 public:
-    gfxSkipCharsBuilder() :
-        mCharCount(0), mRunCharCount(0), mRunSkipped(false), mInErrorState(false)
-    {}
-  
-    void SkipChars(uint32_t aChars) {
-        DoChars(aChars, true);
-    }
-    void KeepChars(uint32_t aChars) {
-        DoChars(aChars, false);
-    }
-    void SkipChar() {
-        SkipChars(1);
-    }
-    void KeepChar() {
-        KeepChars(1);
-    }
-    void DoChars(uint32_t aChars, bool aSkipped) {
-        if (aSkipped != mRunSkipped && aChars > 0) {
-            FlushRun();
+    gfxSkipChars()
+        : mCharCount(0)
+    { }
+
+    void SkipChars(uint32_t aChars)
+    {
+        NS_ASSERTION(mCharCount + aChars > mCharCount,
+                     "Character count overflow");
+        uint32_t rangeCount = mRanges.Length();
+        uint32_t delta = 0;
+        if (rangeCount > 0) {
+            SkippedRange& lastRange = mRanges[rangeCount - 1];
+            if (lastRange.End() == mCharCount) {
+                lastRange.Extend(aChars);
+                mCharCount += aChars;
+                return;
+            }
+            delta = lastRange.NextDelta();
         }
-        NS_ASSERTION(mRunCharCount + aChars > mRunCharCount,
-                     "Character count overflow");
-        mRunCharCount += aChars;
+        mRanges.AppendElement(SkippedRange(mCharCount, aChars, delta));
+        mCharCount += aChars;
     }
 
-    bool IsOK() { return !mInErrorState; }
-
-    uint32_t GetCharCount() { return mCharCount + mRunCharCount; }
-    bool GetAllCharsKept() { return mBuffer.Length() == 0; }
-
-    friend class gfxSkipChars;
-
-private:
-    typedef AutoFallibleTArray<uint8_t,256> Buffer;
+    void KeepChars(uint32_t aChars)
+    {
+        NS_ASSERTION(mCharCount + aChars > mCharCount,
+                     "Character count overflow");
+        mCharCount += aChars;
+    }
 
-    /**
-     * Moves mRunCharCount/mRunSkipped to the buffer (updating mCharCount),
-     * sets mRunCharCount to zero and toggles mRunSkipped.
-     */
-    void FlushRun();
-  
-    Buffer       mBuffer;
-    uint32_t     mCharCount;
-    uint32_t     mRunCharCount;
-    bool mRunSkipped; // == mBuffer.Length()&1
-    bool mInErrorState;
-};
+    void SkipChar()
+    {
+        SkipChars(1);
+    }
 
-/**
- * The gfxSkipChars list is represented as a list of bytes of the form
- * [chars to keep, chars to skip, chars to keep, chars to skip, ...]
- * In the special case where all chars are to be kept, the list is length
- * zero.
- * 
- * A freshly-created gfxSkipChars means "all chars kept".
- */
-class gfxSkipChars {
-public:
-    gfxSkipChars() : mListLength(0), mCharCount(0) {}
-  
-    void TakeFrom(gfxSkipChars* aSkipChars) {
-        mList = aSkipChars->mList.forget();
-        mListLength = aSkipChars->mListLength;
+    void KeepChar()
+    {
+        KeepChars(1);
+    }
+
+    void TakeFrom(gfxSkipChars* aSkipChars)
+    {
+        mRanges.SwapElements(aSkipChars->mRanges);
         mCharCount = aSkipChars->mCharCount;
         aSkipChars->mCharCount = 0;
-        aSkipChars->mListLength = 0;
-        BuildShortcuts();
+    }
+
+    int32_t GetOriginalCharCount() const
+    {
+        return mCharCount;
     }
-  
-    void TakeFrom(gfxSkipCharsBuilder* aSkipCharsBuilder) {
-        if (!aSkipCharsBuilder->mBuffer.Length()) {
-            NS_ASSERTION(!aSkipCharsBuilder->mRunSkipped, "out of sync");
-            // all characters kept
-            mCharCount = aSkipCharsBuilder->mRunCharCount;
-            mList = nullptr;
-            mListLength = 0;
-        } else {
-            aSkipCharsBuilder->FlushRun();
-            mCharCount = aSkipCharsBuilder->mCharCount;
-            mList = new uint8_t[aSkipCharsBuilder->mBuffer.Length()];
-            if (!mList) {
-                mListLength = 0;
-            } else {
-                mListLength = aSkipCharsBuilder->mBuffer.Length();
-                memcpy(mList, aSkipCharsBuilder->mBuffer.Elements(), mListLength);
-            }
-        }
-        aSkipCharsBuilder->mBuffer.Clear();
-        aSkipCharsBuilder->mCharCount = 0;
-        aSkipCharsBuilder->mRunCharCount = 0;    
-        aSkipCharsBuilder->mRunSkipped = false;
-        BuildShortcuts();
+
+    const SkippedRange& LastRange() const
+    {
+        // this is only valid if mRanges is non-empty; no assertion here
+        // because nsTArray will already assert if we abuse it
+        return mRanges[mRanges.Length() - 1];
     }
-  
-    void SetAllKeep(uint32_t aLength) {
-        mCharCount = aLength;
-        mList = nullptr;
-        mListLength = 0;
-    }
-  
-    int32_t GetOriginalCharCount() const { return mCharCount; }
 
     friend class gfxSkipCharsIterator;
 
 private:
-    struct Shortcut {
-        uint32_t mListPrefixLength;
-        uint32_t mListPrefixCharCount;
-        uint32_t mListPrefixKeepCharCount;
-    
-        Shortcut() {}
-        Shortcut(uint32_t aListPrefixLength, uint32_t aListPrefixCharCount,
-                 uint32_t aListPrefixKeepCharCount) :
-            mListPrefixLength(aListPrefixLength),
-            mListPrefixCharCount(aListPrefixCharCount),
-            mListPrefixKeepCharCount(aListPrefixKeepCharCount) {}
-    };
-  
-    void BuildShortcuts();
-
-    nsAutoArrayPtr<uint8_t>  mList;
-    nsAutoArrayPtr<Shortcut> mShortcuts;
-    uint32_t                 mListLength;
-    uint32_t                 mCharCount;
+    nsTArray<SkippedRange> mRanges;
+    uint32_t               mCharCount;
 };
 
 /**
  * A gfxSkipCharsIterator represents a position in the original string. It lets you
  * map efficiently to and from positions in the string after skipped characters
  * have been removed. You can also specify an offset that is added to all
  * incoming original string offsets and subtracted from all outgoing original
  * string offsets --- useful when the gfxSkipChars corresponds to something
  * offset from the original DOM coordinates, which it often does for gfxTextRuns.
- * 
+ *
  * The current positions (in both the original and skipped strings) are
  * always constrained to be >= 0 and <= the string length. When the position
  * is equal to the string length, it is at the end of the string. The current
  * positions do not include any aOriginalStringToSkipCharsOffset.
- * 
+ *
  * When the position in the original string corresponds to a skipped character,
  * the skipped-characters offset is the offset of the next unskipped character,
  * or the skipped-characters string length if there is no next unskipped character.
  */
-class gfxSkipCharsIterator {
+class gfxSkipCharsIterator
+{
 public:
     /**
      * @param aOriginalStringToSkipCharsOffset add this to all incoming and
      * outgoing original string offsets
      */
     gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
                          int32_t aOriginalStringToSkipCharsOffset,
                          int32_t aOriginalStringOffset)
         : mSkipChars(&aSkipChars),
-          mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset),
-          mListPrefixLength(0), mListPrefixCharCount(0), mListPrefixKeepCharCount(0) {
+          mOriginalStringOffset(0),
+          mSkippedStringOffset(0),
+          mCurrentRangeIndex(-1),
+          mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
+    {
           SetOriginalOffset(aOriginalStringOffset);
     }
 
     gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
                          int32_t aOriginalStringToSkipCharsOffset = 0)
         : mSkipChars(&aSkipChars),
-          mOriginalStringOffset(0), mSkippedStringOffset(0),
-          mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset),
-          mListPrefixLength(0), mListPrefixCharCount(0), mListPrefixKeepCharCount(0) {
-    }
+          mOriginalStringOffset(0),
+          mSkippedStringOffset(0),
+          mCurrentRangeIndex(-1),
+          mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
+    { }
 
     gfxSkipCharsIterator(const gfxSkipCharsIterator& aIterator)
         : mSkipChars(aIterator.mSkipChars),
           mOriginalStringOffset(aIterator.mOriginalStringOffset),
           mSkippedStringOffset(aIterator.mSkippedStringOffset),
-          mOriginalStringToSkipCharsOffset(aIterator.mOriginalStringToSkipCharsOffset),
-          mListPrefixLength(aIterator.mListPrefixLength),
-          mListPrefixCharCount(aIterator.mListPrefixCharCount),
-          mListPrefixKeepCharCount(aIterator.mListPrefixKeepCharCount)
-    {}
-  
+          mCurrentRangeIndex(aIterator.mCurrentRangeIndex),
+          mOriginalStringToSkipCharsOffset(aIterator.mOriginalStringToSkipCharsOffset)
+    { }
+
     /**
      * The empty constructor creates an object that is useless until it is assigned.
      */
-    gfxSkipCharsIterator() : mSkipChars(nullptr) {}
+    gfxSkipCharsIterator()
+        : mSkipChars(nullptr)
+    { }
 
     /**
      * Return true if this iterator is properly initialized and usable.
-     */  
-    bool IsInitialized() { return mSkipChars != nullptr; }
+     */
+    bool IsInitialized()
+    {
+        return mSkipChars != nullptr;
+    }
 
     /**
      * Set the iterator to aOriginalStringOffset in the original string.
      * This can efficiently move forward or backward from the current position.
      * aOriginalStringOffset is clamped to [0,originalStringLength].
      */
-    void SetOriginalOffset(int32_t aOriginalStringOffset) {
-        SetOffsets(aOriginalStringOffset + mOriginalStringToSkipCharsOffset, true);
-    }
-    
+    void SetOriginalOffset(int32_t aOriginalStringOffset);
+
     /**
      * Set the iterator to aSkippedStringOffset in the skipped string.
      * This can efficiently move forward or backward from the current position.
      * aSkippedStringOffset is clamped to [0,skippedStringLength].
      */
-    void SetSkippedOffset(uint32_t aSkippedStringOffset) {
-        SetOffsets(aSkippedStringOffset, false);
-    }
-    
-    uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset) {
+    void SetSkippedOffset(uint32_t aSkippedStringOffset);
+
+    uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset)
+    {
         SetOriginalOffset(aOriginalStringOffset);
         return GetSkippedOffset();
     }
-    uint32_t ConvertSkippedToOriginal(int32_t aSkippedStringOffset) {
+
+    uint32_t ConvertSkippedToOriginal(int32_t aSkippedStringOffset)
+    {
         SetSkippedOffset(aSkippedStringOffset);
         return GetOriginalOffset();
     }
-  
+
     /**
      * Test if the character at the current position in the original string
      * is skipped or not. If aRunLength is non-null, then *aRunLength is set
      * to a number of characters all of which are either skipped or not, starting
      * at this character. When the current position is at the end of the original
      * string, we return true and *aRunLength is set to zero.
      */
     bool IsOriginalCharSkipped(int32_t* aRunLength = nullptr) const;
-    
-    void AdvanceOriginal(int32_t aDelta) {
-        SetOffsets(mOriginalStringOffset + aDelta, true);
+
+    void AdvanceOriginal(int32_t aDelta)
+    {
+        SetOriginalOffset(GetOriginalOffset() + aDelta);
     }
-    void AdvanceSkipped(int32_t aDelta) {
-        SetOffsets(mSkippedStringOffset + aDelta, false);
+
+    void AdvanceSkipped(int32_t aDelta)
+    {
+        SetSkippedOffset(GetSkippedOffset() + aDelta);
     }
-  
+
     /**
      * @return the offset within the original string
      */
-    int32_t GetOriginalOffset() const {
+    int32_t GetOriginalOffset() const
+    {
         return mOriginalStringOffset - mOriginalStringToSkipCharsOffset;
     }
+
     /**
      * @return the offset within the skipped string corresponding to the
      * current position in the original string. If the current position
      * in the original string is a character that is skipped, then we return
      * the position corresponding to the first non-skipped character in the
      * original string after the current position, or the length of the skipped
      * string if there is no such character.
      */
-    uint32_t GetSkippedOffset() const { return mSkippedStringOffset; }
+    uint32_t GetSkippedOffset() const
+    {
+        return mSkippedStringOffset;
+    }
 
-    int32_t GetOriginalEnd() const {
+    int32_t GetOriginalEnd() const
+    {
         return mSkipChars->GetOriginalCharCount() -
             mOriginalStringToSkipCharsOffset;
     }
 
 private:
-    void SetOffsets(uint32_t aOffset, bool aInOriginalString);
-  
     const gfxSkipChars* mSkipChars;
+
+    // Current position
     int32_t mOriginalStringOffset;
     uint32_t mSkippedStringOffset;
 
+    // Index of the last skippedRange that precedes or contains the current
+    // position in the original string.
+    // If index == -1 then we are before the first skipped char.
+    int32_t mCurrentRangeIndex;
+
     // This offset is added to map from "skipped+unskipped characters in
     // the original DOM string" character space to "skipped+unskipped
     // characters in the textrun's gfxSkipChars" character space
     int32_t mOriginalStringToSkipCharsOffset;
-
-    /*
-     * This is used to speed up cursor-style traversal. The invariant is that
-     * the first mListPrefixLength bytes of mSkipChars.mList sum to
-     * mListPrefixCharCount, and the even-indexed bytes in that prefix sum to
-     * mListPrefixKeepCharCount.
-     * Also, 0 <= mListPrefixLength < mSkipChars.mListLength, or else
-     * mSkipChars.mListLength is zero.
-     * Also, mListPrefixCharCount <= mOriginalStringOffset (and therefore
-     * mListPrefixKeepCharCount < mSkippedStringOffset).
-     */
-    uint32_t mListPrefixLength;
-    uint32_t mListPrefixCharCount;
-    uint32_t mListPrefixKeepCharCount;
 };
 
 #endif /*GFX_SKIP_CHARS_H*/
deleted file mode 100644
--- a/intl/uconv/util/ubase.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*- 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/. */
-#ifndef ubase_h__
-#define ubase_h__
-
-#include "prtypes.h"
-#include <stdint.h>
-
-#define PRIVATE 
-#define MODULE_PRIVATE
-
-#endif
--- a/intl/uconv/util/ugen.c
+++ b/intl/uconv/util/ugen.c
@@ -1,176 +1,176 @@
 /* -*- Mode: C; tab-width: 4; 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 "unicpriv.h"
 /*=================================================================================
 
 =================================================================================*/
-typedef  PRBool (*uSubGeneratorFunc) (uint16_t in, unsigned char* out);
+typedef  int (*uSubGeneratorFunc) (uint16_t in, unsigned char* out);
 /*=================================================================================
 
 =================================================================================*/
 
-typedef PRBool (*uGeneratorFunc) (
-                                  int32_t*    state,
-                                  uint16_t    in,
-                                  unsigned char*  out,
-                                  uint32_t     outbuflen,
-                                  uint32_t*    outlen
-                                  );
+typedef int (*uGeneratorFunc) (
+                               int32_t*    state,
+                               uint16_t    in,
+                               unsigned char*  out,
+                               uint32_t     outbuflen,
+                               uint32_t*    outlen
+                               );
 
-MODULE_PRIVATE PRBool uGenerate(  
-                                uScanClassID scanClass,
-                                int32_t*    state,
-                                uint16_t    in,
-                                unsigned char*  out,
-                                uint32_t     outbuflen,
-                                uint32_t*    outlen
-                                );
+int uGenerate(
+              uScanClassID scanClass,
+              int32_t*    state,
+              uint16_t    in,
+              unsigned char*  out,
+              uint32_t     outbuflen,
+              uint32_t*    outlen
+              );
 
 #define uSubGenerator(sub,in,out) (* m_subgenerator[sub])((in),(out))
 
-PRIVATE PRBool uCheckAndGenAlways1Byte(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       );
-PRIVATE PRBool uCheckAndGenAlways2Byte(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       );
-PRIVATE PRBool uCheckAndGenAlways2ByteShiftGR(
-                                              int32_t*    state,
-                                              uint16_t    in,
-                                              unsigned char*  out,
-                                              uint32_t     outbuflen,
-                                              uint32_t*    outlen
-                                              );
-MODULE_PRIVATE PRBool uGenerateShift(
-                                     uShiftOutTable   *shift,
-                                     int32_t*   state,
-                                     uint16_t   in,
-                                     unsigned char* out,
-                                     uint32_t    outbuflen,
-                                     uint32_t*   outlen
-                                     );
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8F(
-                                           int32_t*   state,
-                                           uint16_t   in,
-                                           unsigned char* out,
-                                           uint32_t    outbuflen,
-                                           uint32_t*   outlen
-                                           );
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA2(
-                                             int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             );
+int uCheckAndGenAlways1Byte(
+                               int32_t*   state,
+                               uint16_t   in,
+                               unsigned char* out,
+                               uint32_t    outbuflen,
+                               uint32_t*   outlen
+                               );
+int uCheckAndGenAlways2Byte(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            );
+int uCheckAndGenAlways2ByteShiftGR(
+                                   int32_t*    state,
+                                   uint16_t    in,
+                                   unsigned char*  out,
+                                   uint32_t     outbuflen,
+                                   uint32_t*    outlen
+                                   );
+int uGenerateShift(
+                   uShiftOutTable   *shift,
+                   int32_t*   state,
+                   uint16_t   in,
+                   unsigned char* out,
+                   uint32_t    outbuflen,
+                   uint32_t*   outlen
+                   );
+int uCheckAndGen2ByteGRPrefix8F(
+                                int32_t*   state,
+                                uint16_t   in,
+                                unsigned char* out,
+                                uint32_t    outbuflen,
+                                uint32_t*   outlen
+                                );
+int uCheckAndGen2ByteGRPrefix8EA2(
+                                  int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  );
 
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA3(
-                                             int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             );
+int uCheckAndGen2ByteGRPrefix8EA3(
+                                  int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  );
 
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA4(
-                                             int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             );
+int uCheckAndGen2ByteGRPrefix8EA4(
+                                  int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  );
 
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA5(
-                                             int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             );
+int uCheckAndGen2ByteGRPrefix8EA5(
+                                  int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  );
 
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA6(
-                                             int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             );
+int uCheckAndGen2ByteGRPrefix8EA6(
+                                  int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  );
 
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA7(
-                                             int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             );
-PRIVATE PRBool uCnGAlways8BytesDecomposedHangul(
-                                              int32_t*    state,
-                                              uint16_t    in,
-                                              unsigned char*  out,
-                                              uint32_t     outbuflen,
-                                              uint32_t*    outlen
-                                              );
+int uCheckAndGen2ByteGRPrefix8EA7(
+                                  int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  );
+int uCnGAlways8BytesDecomposedHangul(
+                                     int32_t*    state,
+                                     uint16_t    in,
+                                     unsigned char*  out,
+                                     uint32_t     outbuflen,
+                                     uint32_t*    outlen
+                                     );
 
-PRIVATE PRBool uCheckAndGenJohabHangul(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       );
+int uCheckAndGenJohabHangul(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            );
 
-PRIVATE PRBool uCheckAndGenJohabSymbol(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       );
+int uCheckAndGenJohabSymbol(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            );
 
 
-PRIVATE PRBool uCheckAndGen4BytesGB18030(
-                                         int32_t*   state,
-                                         uint16_t   in,
-                                         unsigned char* out,
-                                         uint32_t    outbuflen,
-                                         uint32_t*   outlen
-                                         );
+int uCheckAndGen4BytesGB18030(
+                              int32_t*   state,
+                              uint16_t   in,
+                              unsigned char* out,
+                              uint32_t    outbuflen,
+                              uint32_t*   outlen
+                              );
 
-PRIVATE PRBool uGenAlways2Byte(
-                               uint16_t    in,
-                               unsigned char* out
-                               );
-PRIVATE PRBool uGenAlways2ByteShiftGR(
-                                      uint16_t     in,
-                                      unsigned char*  out
-                                      );
-PRIVATE PRBool uGenAlways1Byte(
-                               uint16_t    in,
-                               unsigned char* out
-                               );
-PRIVATE PRBool uGenAlways1BytePrefix8E(
-                                       uint16_t    in,
-                                       unsigned char* out
-                                       );
-                                   /*=================================================================================
-                                   
+int uGenAlways2Byte(
+                    uint16_t    in,
+                    unsigned char* out
+                    );
+int uGenAlways2ByteShiftGR(
+                           uint16_t     in,
+                           unsigned char*  out
+                           );
+int uGenAlways1Byte(
+                    uint16_t    in,
+                    unsigned char* out
+                    );
+int uGenAlways1BytePrefix8E(
+                            uint16_t    in,
+                            unsigned char* out
+                            );
+/*=================================================================================
+
 =================================================================================*/
-PRIVATE const uGeneratorFunc m_generator[uNumOfCharsetType] =
+const uGeneratorFunc m_generator[uNumOfCharsetType] =
 {
     uCheckAndGenAlways1Byte,
     uCheckAndGenAlways2Byte,
     uCheckAndGenAlways2ByteShiftGR,
     uCheckAndGen2ByteGRPrefix8F,
     uCheckAndGen2ByteGRPrefix8EA2,
     uCheckAndGen2ByteGRPrefix8EA3,
     uCheckAndGen2ByteGRPrefix8EA4,
@@ -183,378 +183,377 @@ PRIVATE const uGeneratorFunc m_generator
     uCheckAndGen4BytesGB18030,
     uCheckAndGenAlways2Byte   /* place-holder for GR128 */
 };
 
 /*=================================================================================
 
 =================================================================================*/
 
-PRIVATE const uSubGeneratorFunc m_subgenerator[uNumOfCharType] =
+const uSubGeneratorFunc m_subgenerator[uNumOfCharType] =
 {
     uGenAlways1Byte,
     uGenAlways2Byte,
     uGenAlways2ByteShiftGR,
     uGenAlways1BytePrefix8E
-        
 };
 /*=================================================================================
 
 =================================================================================*/
-MODULE_PRIVATE PRBool uGenerate(  
-                                uScanClassID scanClass,
-                                int32_t*    state,
-                                uint16_t    in,
-                                unsigned char*  out,
-                                uint32_t     outbuflen,
-                                uint32_t*    outlen
-                                )
+int uGenerate(
+              uScanClassID scanClass,
+              int32_t*    state,
+              uint16_t    in,
+              unsigned char*  out,
+              uint32_t     outbuflen,
+              uint32_t*    outlen
+              )
 {
     return (* m_generator[scanClass]) (state,in,out,outbuflen,outlen);
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uGenAlways1Byte(
-                               uint16_t    in,
-                               unsigned char* out
-                               )
+int uGenAlways1Byte(
+                    uint16_t    in,
+                    unsigned char* out
+                    )
 {
     out[0] = (unsigned char)in;
-    return PR_TRUE;
+    return 1;
 }
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uGenAlways2Byte(
-                               uint16_t    in,
-                               unsigned char* out
-                               )
+int uGenAlways2Byte(
+                    uint16_t    in,
+                    unsigned char* out
+                    )
 {
     out[0] = (unsigned char)((in >> 8) & 0xff);
     out[1] = (unsigned char)(in & 0xff);
-    return PR_TRUE;
+    return 1;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uGenAlways2ByteShiftGR(
-                                      uint16_t     in,
-                                      unsigned char*  out
-                                      )
+int uGenAlways2ByteShiftGR(
+                           uint16_t     in,
+                           unsigned char*  out
+                           )
 {
     out[0] = (unsigned char)(((in >> 8) & 0xff) | 0x80);
     out[1] = (unsigned char)((in & 0xff) | 0x80);
-    return PR_TRUE;
+    return 1;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uGenAlways1BytePrefix8E(
-                                       uint16_t    in,
-                                       unsigned char* out
-                                       )
+int uGenAlways1BytePrefix8E(
+                            uint16_t    in,
+                            unsigned char* out
+                            )
 {
     out[0] = 0x8E;
     out[1] = (unsigned char)(in  & 0xff);
-    return PR_TRUE;
+    return 1;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGenAlways1Byte(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       )
+int uCheckAndGenAlways1Byte(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            )
 {
     /* Don't check inlen. The caller should ensure it is larger than 0 */
     /*  Oops, I don't agree. Code changed to check every time. [CATA] */
     if(outbuflen < 1)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 1;
         out[0] = in & 0xff;
-        return PR_TRUE;
+        return 1;
     }
 }
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGenAlways2Byte(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       )
+int uCheckAndGenAlways2Byte(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            )
 {
     if(outbuflen < 2)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 2;
         out[0] = ((in >> 8 ) & 0xff);
         out[1] = in  & 0xff;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGenAlways2ByteShiftGR(
-                                              int32_t*    state,
-                                              uint16_t    in,
-                                              unsigned char*  out,
-                                              uint32_t     outbuflen,
-                                              uint32_t*    outlen
-                                              )
+int uCheckAndGenAlways2ByteShiftGR(
+                                   int32_t*    state,
+                                   uint16_t    in,
+                                   unsigned char*  out,
+                                   uint32_t     outbuflen,
+                                   uint32_t*    outlen
+                                   )
 {
     if(outbuflen < 2)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 2;
         out[0] = ((in >> 8 ) & 0xff) | 0x80;
         out[1] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-MODULE_PRIVATE PRBool uGenerateShift(
-                                   uShiftOutTable   *shift,
-                                   int32_t*   state,
-                                   uint16_t   in,
-                                   unsigned char* out,
-                                   uint32_t    outbuflen,
-                                   uint32_t*   outlen
-                                   )
+int uGenerateShift(
+                   uShiftOutTable   *shift,
+                   int32_t*   state,
+                   uint16_t   in,
+                   unsigned char* out,
+                   uint32_t    outbuflen,
+                   uint32_t*   outlen
+                   )
 {
     int16_t i;
     const uShiftOutCell* cell = &(shift->shiftcell[0]);
     int16_t itemnum = shift->numOfItem;
     unsigned char inH, inL;
     inH = (in >> 8) & 0xff;
     inL = (in & 0xff );
     for(i=0;i<itemnum;i++)
     {
         if( ( inL >=  cell[i].shiftout_MinLB) &&
             ( inL <=  cell[i].shiftout_MaxLB) &&
             ( inH >=  cell[i].shiftout_MinHB) &&
             ( inH <=  cell[i].shiftout_MaxHB) )
         {
             if(outbuflen < cell[i].reserveLen)
               {
-                return PR_FALSE;
+                return 0;
               }
             else
             {
                 *outlen = cell[i].reserveLen;
                 return (uSubGenerator(cell[i].classID,in,out));
             }
         }
     }
-    return PR_FALSE;
+    return 0;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8F( int32_t*   state,
-                                           uint16_t   in,
-                                           unsigned char* out,
-                                           uint32_t    outbuflen,
-                                           uint32_t*   outlen
-                                           )
+int uCheckAndGen2ByteGRPrefix8F(int32_t*   state,
+                                uint16_t   in,
+                                unsigned char* out,
+                                uint32_t    outbuflen,
+                                uint32_t*   outlen
+                                )
 {
     if(outbuflen < 3)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 3;
         out[0] = 0x8F;
         out[1] = ((in >> 8 ) & 0xff) | 0x80;
         out[2] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA2( int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             )
+int uCheckAndGen2ByteGRPrefix8EA2(int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 4;
         out[0] = 0x8E;
         out[1] = 0xA2;
         out[2] = ((in >> 8 ) & 0xff) | 0x80;
         out[3] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA3( int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             )
+int uCheckAndGen2ByteGRPrefix8EA3(int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 4;
         out[0] = 0x8E;
         out[1] = 0xA3;
         out[2] = ((in >> 8 ) & 0xff) | 0x80;
         out[3] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA4( int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             )
+int uCheckAndGen2ByteGRPrefix8EA4(int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 4;
         out[0] = 0x8E;
         out[1] = 0xA4;
         out[2] = ((in >> 8 ) & 0xff) | 0x80;
         out[3] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA5( int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             )
+int uCheckAndGen2ByteGRPrefix8EA5(int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 4;
         out[0] = 0x8E;
         out[1] = 0xA5;
         out[2] = ((in >> 8 ) & 0xff) | 0x80;
         out[3] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA6( int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             )
+int uCheckAndGen2ByteGRPrefix8EA6(int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 4;
         out[0] = 0x8E;
         out[1] = 0xA6;
         out[2] = ((in >> 8 ) & 0xff) | 0x80;
         out[3] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA7( int32_t*   state,
-                                             uint16_t   in,
-                                             unsigned char* out,
-                                             uint32_t    outbuflen,
-                                             uint32_t*   outlen
-                                             )
+int uCheckAndGen2ByteGRPrefix8EA7(int32_t*   state,
+                                  uint16_t   in,
+                                  unsigned char* out,
+                                  uint32_t    outbuflen,
+                                  uint32_t*   outlen
+                                  )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     else
     {
         *outlen = 4;
         out[0] = 0x8E;
         out[1] = 0xA7;
         out[2] = ((in >> 8 ) & 0xff) | 0x80;
         out[3] = (in  & 0xff)  | 0x80;
-        return PR_TRUE;
+        return 1;
     }
 }
 /*=================================================================================
 
 =================================================================================*/
 #define SBase 0xAC00
 #define LCount 19
 #define VCount 21
 #define TCount 28
 #define NCount (VCount * TCount)
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCnGAlways8BytesDecomposedHangul(
-                                              int32_t*    state,
-                                              uint16_t    in,
-                                              unsigned char*  out,
-                                              uint32_t     outbuflen,
-                                              uint32_t*    outlen
-                                              )
+int uCnGAlways8BytesDecomposedHangul(
+                                     int32_t*    state,
+                                     uint16_t    in,
+                                     unsigned char*  out,
+                                     uint32_t     outbuflen,
+                                     uint32_t*    outlen
+                                     )
 {
     static const uint8_t lMap[LCount] = {
         0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xa9, 0xb1, 0xb2, 0xb3, 0xb5,
             0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe
     };
     
     static const uint8_t tMap[TCount] = {
         0xd4, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa9, 0xaa, 
             0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb4, 0xb5, 
             0xb6, 0xb7, 0xb8, 0xba, 0xbb, 0xbc, 0xbd, 0xbe
     };
 
     uint16_t SIndex, LIndex, VIndex, TIndex;
 
     if(outbuflen < 8)
-        return PR_FALSE;
+        return 0;
 
     /* the following line are copy from Unicode 2.0 page 3-13 */
     /* item 1 of Hangul Syllabel Decomposition */
     SIndex =  in - SBase;
     
     /* the following lines are copy from Unicode 2.0 page 3-14 */
     /* item 2 of Hangul Syllabel Decomposition w/ modification */
     LIndex = SIndex / NCount;
@@ -570,29 +569,29 @@ PRIVATE PRBool uCnGAlways8BytesDecompose
      */
     *outlen = 8;
     out[0] = out[2] = out[4] = out[6] = 0xa4;
     out[1] = 0xd4;
     out[3] = lMap[LIndex] ;
     out[5] = (VIndex + 0xbf);
     out[7] = tMap[TIndex];
 
-    return PR_TRUE;
+    return 1;
 }
 
-PRIVATE PRBool uCheckAndGenJohabHangul(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       )
+int uCheckAndGenJohabHangul(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            )
 {
     if(outbuflen < 2)
-        return PR_FALSE;
+        return 0;
     else
     {
     /*
     See Table 4-45 (page 183) of CJKV Information Processing
     for detail explanation of the following table.
         */
         /*
         static const uint8_t lMap[LCount] = {
@@ -628,29 +627,29 @@ PRIVATE PRBool uCheckAndGenJohabHangul(
             ((LIndex+2)<<10) | 
             (vMap[VIndex]<<5)| 
             tMap[TIndex];
         out[0] = (ch >> 8);
         out[1] = ch & 0x00FF;
 #if 0
         printf("Johab Hangul %x %x in=%x L=%d V=%d T=%d\n", out[0], out[1], in, LIndex, VIndex, TIndex); 
 #endif 
-        return PR_TRUE;
+        return 1;
     }
 }
-PRIVATE PRBool uCheckAndGenJohabSymbol(
-                                       int32_t*   state,
-                                       uint16_t   in,
-                                       unsigned char* out,
-                                       uint32_t    outbuflen,
-                                       uint32_t*   outlen
-                                       )
+int uCheckAndGenJohabSymbol(
+                            int32_t*   state,
+                            uint16_t   in,
+                            unsigned char* out,
+                            uint32_t    outbuflen,
+                            uint32_t*   outlen
+                            )
 {
     if(outbuflen < 2)
-        return PR_FALSE;
+        return 0;
     else
     {
     /* The following code are based on the Perl code listed under
     * "ISO-2022-KR or EUC-KR to Johab Conversion" (page 1013)
     * in the book "CJKV Information Processing" by 
     * Ken Lunde <lunde@adobe.com>
     *
     * sub convert2johab($) { # Convert ISO-2022-KR or EUC-KR to Johab
@@ -684,30 +683,30 @@ PRIVATE PRBool uCheckAndGenJohabSymbol(
         }
         *outlen = 2;
         out[0] =  ((hi+hi_off) >> 1) + ((hi<74) ? 200 : 187 ) - fe_off;
         out[1] =  lo + (((hi+lo_off) & 1) ? ((lo > 110) ? 34 : 16) : 
         128);
 #if 0
         printf("Johab Symbol %x %x in=%x\n", out[0], out[1], in); 
 #endif
-        return PR_TRUE;
+        return 1;
     }
 }
-PRIVATE PRBool uCheckAndGen4BytesGB18030(
-                                         int32_t*   state,
-                                         uint16_t   in,
-                                         unsigned char* out,
-                                         uint32_t    outbuflen,
-                                         uint32_t*   outlen
-                                         )
+int uCheckAndGen4BytesGB18030(
+                              int32_t*   state,
+                              uint16_t   in,
+                              unsigned char* out,
+                              uint32_t    outbuflen,
+                              uint32_t*   outlen
+                              )
 {
     if(outbuflen < 4)
-        return PR_FALSE;
+        return 0;
     out[0] = (in / (10*126*10)) + 0x81;
     in %= (10*126*10);
     out[1] = (in / (10*126)) + 0x30;
     in %= (10*126);
     out[2] = (in / (10)) + 0x81;
     out[3] = (in % 10) + 0x30;
     *outlen = 4;
-    return PR_TRUE;
+    return 1;
 }
--- a/intl/uconv/util/umap.c
+++ b/intl/uconv/util/umap.c
@@ -2,140 +2,140 @@
 /* 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 "PRIntlpriv.h" */
 #include "unicpriv.h" 
 
 
 typedef uint16_t (* MapFormatFunc)(uint16_t in,const uTable *uT,const uMapCell *cell);
-typedef PRBool (* HitFormateFunc)(uint16_t in,const uMapCell *cell);
+typedef int (* HitFormateFunc)(uint16_t in,const uMapCell *cell);
 typedef void (* FillInfoFormateFunc)(const uTable *uT, const uMapCell *cell, uint32_t* info);
 
 
-PRIVATE PRBool uHitFormate0(uint16_t in,const uMapCell *cell);
-PRIVATE PRBool uHitFormate2(uint16_t in,const uMapCell *cell);
-PRIVATE uint16_t uMapFormate0(uint16_t in,const uTable *uT,const uMapCell *cell);
-PRIVATE uint16_t uMapFormate1(uint16_t in,const uTable *uT,const uMapCell *cell);
-PRIVATE uint16_t uMapFormate2(uint16_t in,const uTable *uT,const uMapCell *cell);
-PRIVATE void uFillInfoFormate0(const uTable *uT,const uMapCell *cell,uint32_t* aInfo);
-PRIVATE void uFillInfoFormate1(const uTable *uT,const uMapCell *cell,uint32_t* aInfo);
-PRIVATE void uFillInfoFormate2(const uTable *uT,const uMapCell *cell,uint32_t* aInfo);
+int uHitFormate0(uint16_t in,const uMapCell *cell);
+int uHitFormate2(uint16_t in,const uMapCell *cell);
+uint16_t uMapFormate0(uint16_t in,const uTable *uT,const uMapCell *cell);
+uint16_t uMapFormate1(uint16_t in,const uTable *uT,const uMapCell *cell);
+uint16_t uMapFormate2(uint16_t in,const uTable *uT,const uMapCell *cell);
+void uFillInfoFormate0(const uTable *uT,const uMapCell *cell,uint32_t* aInfo);
+void uFillInfoFormate1(const uTable *uT,const uMapCell *cell,uint32_t* aInfo);
+void uFillInfoFormate2(const uTable *uT,const uMapCell *cell,uint32_t* aInfo);
 
 
-PRIVATE const uMapCell *uGetMapCell(const uTable *uT, int16_t item);
-PRIVATE char uGetFormat(const uTable *uT, int16_t item);
+const uMapCell *uGetMapCell(const uTable *uT, int16_t item);
+char uGetFormat(const uTable *uT, int16_t item);
 
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE const MapFormatFunc m_map[uNumFormatTag] =
+const MapFormatFunc m_map[uNumFormatTag] =
 {
     uMapFormate0,
     uMapFormate1,
     uMapFormate2,
 };
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE const FillInfoFormateFunc m_fillinfo[uNumFormatTag] =
+const FillInfoFormateFunc m_fillinfo[uNumFormatTag] =
 {
     uFillInfoFormate0,
     uFillInfoFormate1,
     uFillInfoFormate2,
 };
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE const HitFormateFunc m_hit[uNumFormatTag] =
+const HitFormateFunc m_hit[uNumFormatTag] =
 {
     uHitFormate0,
     uHitFormate0,
     uHitFormate2,
 };
 
 #define uHit(format,in,cell)   (* m_hit[(format)])((in),(cell))
 #define uMap(format,in,uT,cell)  (* m_map[(format)])((in),(uT),(cell))
 #define uGetMapCell(uT, item) ((uMapCell *)(((uint16_t *)uT) + (uT)->offsetToMapCellArray + (item)*(UMAPCELL_SIZE/sizeof(uint16_t))))
 #define uGetFormat(uT, item) (((((uint16_t *)uT) + (uT)->offsetToFormatArray)[(item)>> 2 ] >> (((item)% 4 ) << 2)) & 0x0f)
 
 /*=================================================================================
 
 =================================================================================*/
-MODULE_PRIVATE PRBool uMapCode(const uTable *uT, uint16_t in, uint16_t* out)
+int uMapCode(const uTable *uT, uint16_t in, uint16_t* out)
 {
-  PRBool done = PR_FALSE;
+  int done = 0;
   uint16_t itemOfList = uT->itemOfList;
   uint16_t i;
   *out = NOMAPPING;
   for(i=0;i<itemOfList;i++)
   {
     const uMapCell* uCell;
     int8_t format = uGetFormat(uT,i);
     uCell = uGetMapCell(uT,i);
     if(uHit(format, in, uCell))
     {
       *out = uMap(format, in, uT,uCell);
-      done = PR_TRUE;
+      done = 1;
       break;
     }
   }
   return ( done && (*out != NOMAPPING));
 }
 
 
 /*
 member function
 */
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uHitFormate0(uint16_t in,const uMapCell *cell)
+int uHitFormate0(uint16_t in,const uMapCell *cell)
 {
   return ( (in >= cell->fmt.format0.srcBegin) &&
     (in <= cell->fmt.format0.srcEnd) ) ;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uHitFormate2(uint16_t in,const uMapCell *cell)
+int uHitFormate2(uint16_t in,const uMapCell *cell)
 {
   return (in == cell->fmt.format2.srcBegin);
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE uint16_t uMapFormate0(uint16_t in,const uTable *uT,const uMapCell *cell)
+uint16_t uMapFormate0(uint16_t in,const uTable *uT,const uMapCell *cell)
 {
   return ((in - cell->fmt.format0.srcBegin) + cell->fmt.format0.destBegin);
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE uint16_t uMapFormate1(uint16_t in,const uTable *uT,const uMapCell *cell)
+uint16_t uMapFormate1(uint16_t in,const uTable *uT,const uMapCell *cell)
 {
   return (*(((uint16_t *)uT) + uT->offsetToMappingTable
     + cell->fmt.format1.mappingOffset + in - cell->fmt.format1.srcBegin));
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE uint16_t uMapFormate2(uint16_t in,const uTable *uT,const uMapCell *cell)
+uint16_t uMapFormate2(uint16_t in,const uTable *uT,const uMapCell *cell)
 {
   return (cell->fmt.format2.destBegin);
 }
 
 #define SET_REPRESENTABLE(info, c)  (info)[(c) >> 5] |= (1L << ((c) & 0x1f))
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE void uFillInfoFormate0(const uTable *uT,const uMapCell *cell,uint32_t* info)
+void uFillInfoFormate0(const uTable *uT,const uMapCell *cell,uint32_t* info)
 {
   uint16_t begin, end, i;
   begin = cell->fmt.format0.srcBegin;
   end = cell->fmt.format0.srcEnd;
   if( (begin >> 5) == (end >> 5)) /* High 17 bits are the same */
   {
     for(i = begin; i <= end; i++)
       SET_REPRESENTABLE(info, i);
@@ -147,29 +147,29 @@ PRIVATE void uFillInfoFormate0(const uTa
     info[ e ] |= (0xFFFFFFFFL >> (31 - ((end) & 0x1f)));
     for(b++ ; b < e ; b++)
       info[b] |= 0xFFFFFFFFL;
   }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE void uFillInfoFormate1(const uTable *uT,const uMapCell *cell,uint32_t* info)
+void uFillInfoFormate1(const uTable *uT,const uMapCell *cell,uint32_t* info)
 {
   uint16_t begin, end, i;
   uint16_t *base;
   begin = cell->fmt.format0.srcBegin;
   end = cell->fmt.format0.srcEnd;
   base = (((uint16_t *)uT) + uT->offsetToMappingTable + cell->fmt.format1.mappingOffset);
   for(i = begin; i <= end; i++) 
   {
     if(0xFFFD != base[i - begin])  /* check every item */
       SET_REPRESENTABLE(info, i);
   }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE void uFillInfoFormate2(const uTable *uT,const uMapCell *cell,uint32_t* info)
+void uFillInfoFormate2(const uTable *uT,const uMapCell *cell,uint32_t* info)
 {
   SET_REPRESENTABLE(info, cell->fmt.format2.srcBegin);
 }
 
--- a/intl/uconv/util/unicpriv.h
+++ b/intl/uconv/util/unicpriv.h
@@ -1,52 +1,52 @@
 /* -*- Mode: C; tab-width: 4; 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/. */
 #ifndef __UNIPRIV__
 #define __UNIPRIV__
 
-#include "ubase.h"
+#include <stdint.h>
 #include "umap.h"
 #include "uconvutil.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-PRBool	uMapCode(const uTable *uT, 
-                    uint16_t in, 
-                    uint16_t* out);
+int uMapCode(const uTable *uT,
+             uint16_t in,
+             uint16_t* out);
 
-PRBool 	uGenerate(uScanClassID scanClass,
-                  int32_t* state, 
-                  uint16_t in, 
-                  unsigned char* out, 
-                  uint32_t outbuflen, 
-                  uint32_t* outlen);
+int uGenerate(uScanClassID scanClass,
+              int32_t* state,
+              uint16_t in,
+              unsigned char* out,
+              uint32_t outbuflen,
+              uint32_t* outlen);
 
-PRBool 	uScan(uScanClassID scanClass,
-              int32_t *state, 
-              unsigned char *in,
-              uint16_t *out, 
-              uint32_t inbuflen, 
-              uint32_t* inscanlen);
+int uScan(uScanClassID scanClass,
+          int32_t *state,
+          unsigned char *in,
+          uint16_t *out,
+          uint32_t inbuflen,
+          uint32_t* inscanlen);
 
-PRBool 	uGenerateShift(uShiftOutTable *shift,
-                       int32_t* state, 
-                       uint16_t in, 
-                       unsigned char* out, 
-                       uint32_t outbuflen, 
-                       uint32_t* outlen);
+int uGenerateShift(uShiftOutTable *shift,
+                   int32_t* state,
+                   uint16_t in,
+                   unsigned char* out,
+                   uint32_t outbuflen,
+                   uint32_t* outlen);
 
-PRBool 	uScanShift(uShiftInTable *shift, 
-                   int32_t *state, 
-                   unsigned char *in,
-                   uint16_t *out, 
-                   uint32_t inbuflen, 
-                   uint32_t* inscanlen);
+int uScanShift(uShiftInTable *shift,
+               int32_t *state,
+               unsigned char *in,
+               uint16_t *out,
+               uint32_t inbuflen,
+               uint32_t* inscanlen);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __UNIPRIV__ */
--- a/intl/uconv/util/uscan.c
+++ b/intl/uconv/util/uscan.c
@@ -3,176 +3,176 @@
  * 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 "unicpriv.h"
 #define CHK_GR94(b) ( (uint8_t) 0xa0 < (uint8_t) (b) && (uint8_t) (b) < (uint8_t) 0xff )
 #define CHK_GR94_2Byte(b1,b2) (CHK_GR94(b1) && CHK_GR94(b2))
 /*=================================================================================
 
 =================================================================================*/
-typedef  PRBool (*uSubScannerFunc) (unsigned char* in, uint16_t* out);
+typedef  int (*uSubScannerFunc) (unsigned char* in, uint16_t* out);
 /*=================================================================================
 
 =================================================================================*/
 
-typedef PRBool (*uScannerFunc) (
-                                int32_t*    state,
-                                unsigned char  *in,
-                                uint16_t    *out,
-                                uint32_t     inbuflen,
-                                uint32_t*    inscanlen
-                                );
+typedef int (*uScannerFunc) (
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             );
 
-MODULE_PRIVATE PRBool uScan(  
-                            uScanClassID scanClass,
+int uScan(
+          uScanClassID scanClass,
+          int32_t*    state,
+          unsigned char  *in,
+          uint16_t    *out,
+          uint32_t     inbuflen,
+          uint32_t*    inscanlen
+          );
+
+#define uSubScanner(sub,in,out) (* m_subscanner[sub])((in),(out))
+
+int uCheckAndScanAlways1Byte(
                             int32_t*    state,
                             unsigned char  *in,
                             uint16_t    *out,
                             uint32_t     inbuflen,
                             uint32_t*    inscanlen
                             );
-
-#define uSubScanner(sub,in,out) (* m_subscanner[sub])((in),(out))
+int uCheckAndScanAlways2Byte(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             );
+int uCheckAndScanAlways2ByteShiftGR(
+                                    int32_t*    state,
+                                    unsigned char  *in,
+                                    uint16_t    *out,
+                                    uint32_t     inbuflen,
+                                    uint32_t*    inscanlen
+                                    );
+int uCheckAndScanAlways2ByteGR128(
+                                  int32_t*    state,
+                                  unsigned char  *in,
+                                  uint16_t    *out,
+                                  uint32_t     inbuflen,
+                                  uint32_t*    inscanlen
+                                          );
+int uScanShift(
+               uShiftInTable    *shift,
+               int32_t*    state,
+               unsigned char  *in,
+               uint16_t    *out,
+               uint32_t     inbuflen,
+               uint32_t*    inscanlen
+               );
 
-PRIVATE PRBool uCheckAndScanAlways1Byte(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        );
-PRIVATE PRBool uCheckAndScanAlways2Byte(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        );
-PRIVATE PRBool uCheckAndScanAlways2ByteShiftGR(
-                                               int32_t*    state,
-                                               unsigned char  *in,
-                                               uint16_t    *out,
-                                               uint32_t     inbuflen,
-                                               uint32_t*    inscanlen
-                                               );
-PRIVATE PRBool uCheckAndScanAlways2ByteGR128(
-                                               int32_t*    state,
-                                               unsigned char  *in,
-                                               uint16_t    *out,
-                                               uint32_t     inbuflen,
-                                               uint32_t*    inscanlen
-                                               );
-MODULE_PRIVATE PRBool uScanShift(  
-                                 uShiftInTable    *shift,
+int uCheckAndScan2ByteGRPrefix8F(
                                  int32_t*    state,
                                  unsigned char  *in,
                                  uint16_t    *out,
                                  uint32_t     inbuflen,
                                  uint32_t*    inscanlen
                                  );
+int uCheckAndScan2ByteGRPrefix8EA2(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   );
+int uCheckAndScan2ByteGRPrefix8EA3(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   );
+int uCheckAndScan2ByteGRPrefix8EA4(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   );
+int uCheckAndScan2ByteGRPrefix8EA5(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   );
+int uCheckAndScan2ByteGRPrefix8EA6(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   );
+int uCheckAndScan2ByteGRPrefix8EA7(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   );
+int uCnSAlways8BytesDecomposedHangul(
+                                     int32_t*    state,
+                                     unsigned char  *in,
+                                     uint16_t    *out,
+                                     uint32_t     inbuflen,
+                                     uint32_t*    inscanlen
+                                     );
+int uCheckAndScanJohabHangul(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             );
+int uCheckAndScanJohabSymbol(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             );
 
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8F(
-                                            int32_t*    state,
-                                            unsigned char  *in,
-                                            uint16_t    *out,
-                                            uint32_t     inbuflen,
-                                            uint32_t*    inscanlen
-                                            );
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA2(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA3(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA4(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA5(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA6(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA7(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCnSAlways8BytesDecomposedHangul(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              );
-PRIVATE PRBool uCheckAndScanJohabHangul(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        );
-PRIVATE PRBool uCheckAndScanJohabSymbol(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        );
+int uCheckAndScan4BytesGB18030(
+                               int32_t*    state,
+                               unsigned char  *in,
+                               uint16_t    *out,
+                               uint32_t     inbuflen,
+                               uint32_t*    inscanlen
+                               );
 
-PRIVATE PRBool uCheckAndScan4BytesGB18030(
-                                          int32_t*    state,
-                                          unsigned char  *in,
-                                          uint16_t    *out,
-                                          uint32_t     inbuflen,
-                                          uint32_t*    inscanlen
-                                          );
+int uScanAlways2Byte(
+                     unsigned char*  in,
+                     uint16_t*    out
+                     );
+int uScanAlways2ByteShiftGR(
+                            unsigned char*  in,
+                            uint16_t*    out
+                            );
+int uScanAlways1Byte(
+                     unsigned char*  in,
+                     uint16_t*    out
+                     );
+int uScanAlways1BytePrefix8E(
+                             unsigned char*  in,
+                             uint16_t*    out
+                             );
+/*=================================================================================
 
-PRIVATE PRBool uScanAlways2Byte(
-                                unsigned char*  in,
-                                uint16_t*    out
-                                );
-PRIVATE PRBool uScanAlways2ByteShiftGR(
-                                       unsigned char*  in,
-                                       uint16_t*    out
-                                       );
-PRIVATE PRBool uScanAlways1Byte(
-                                unsigned char*  in,
-                                uint16_t*    out
-                                );
-PRIVATE PRBool uScanAlways1BytePrefix8E(
-                                        unsigned char*  in,
-                                        uint16_t*    out
-                                        );
-                                    /*=================================================================================
-                                    
 =================================================================================*/
-PRIVATE const uScannerFunc m_scanner[uNumOfCharsetType] =
+const uScannerFunc m_scanner[uNumOfCharsetType] =
 {
     uCheckAndScanAlways1Byte,
     uCheckAndScanAlways2Byte,
     uCheckAndScanAlways2ByteShiftGR,
     uCheckAndScan2ByteGRPrefix8F,
     uCheckAndScan2ByteGRPrefix8EA2,
     uCheckAndScan2ByteGRPrefix8EA3,
     uCheckAndScan2ByteGRPrefix8EA4,
@@ -185,460 +185,460 @@ PRIVATE const uScannerFunc m_scanner[uNu
     uCheckAndScan4BytesGB18030,
     uCheckAndScanAlways2ByteGR128
 };
 
 /*=================================================================================
 
 =================================================================================*/
 
-PRIVATE const uSubScannerFunc m_subscanner[uNumOfCharType] =
+const uSubScannerFunc m_subscanner[uNumOfCharType] =
 {
     uScanAlways1Byte,
     uScanAlways2Byte,
     uScanAlways2ByteShiftGR,
     uScanAlways1BytePrefix8E
 };
 /*=================================================================================
 
 =================================================================================*/
-MODULE_PRIVATE PRBool uScan(  
-                            uScanClassID scanClass,
-                            int32_t*    state,
-                            unsigned char  *in,
-                            uint16_t    *out,
-                            uint32_t     inbuflen,
-                            uint32_t*    inscanlen
-                            )
+int uScan(
+          uScanClassID scanClass,
+          int32_t*    state,
+          unsigned char  *in,
+          uint16_t    *out,
+          uint32_t     inbuflen,
+          uint32_t*    inscanlen
+          )
 {
   return (* m_scanner[scanClass]) (state,in,out,inbuflen,inscanlen);
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uScanAlways1Byte(
-                                unsigned char*  in,
-                                uint16_t*    out
-                                )
+int uScanAlways1Byte(
+                     unsigned char*  in,
+                     uint16_t*    out
+                     )
 {
   *out = (uint16_t) in[0];
-  return PR_TRUE;
+  return 1;
 }
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uScanAlways2Byte(
-                                unsigned char*  in,
-                                uint16_t*    out
-                                )
+int uScanAlways2Byte(
+                     unsigned char*  in,
+                     uint16_t*    out
+                     )
 {
   *out = (uint16_t) (( in[0] << 8) | (in[1]));
-  return PR_TRUE;
+  return 1;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uScanAlways2ByteShiftGR(
-                                       unsigned char*  in,
-                                       uint16_t*    out
-                                       )
+int uScanAlways2ByteShiftGR(
+                            unsigned char*  in,
+                            uint16_t*    out
+                            )
 {
   *out = (uint16_t) ((( in[0] << 8) | (in[1])) &  0x7F7F);
-  return PR_TRUE;
+  return 1;
 }
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uScanAlways1BytePrefix8E(
-                                        unsigned char*  in,
-                                        uint16_t*    out
-                                        )
+int uScanAlways1BytePrefix8E(
+                             unsigned char*  in,
+                             uint16_t*    out
+                             )
 {
   *out = (uint16_t) in[1];
-  return PR_TRUE;
+  return 1;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScanAlways1Byte(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        )
+int uCheckAndScanAlways1Byte(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             )
 {
   /* Don't check inlen. The caller should ensure it is larger than 0 */
   *inscanlen = 1;
   *out = (uint16_t) in[0];
   
-  return PR_TRUE;
+  return 1;
 }
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScanAlways2Byte(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        )
+int uCheckAndScanAlways2Byte(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             )
 {
   if(inbuflen < 2)
-    return PR_FALSE;
+    return 0;
   else
   {
     *inscanlen = 2;
     *out = ((in[0] << 8) | ( in[1])) ;
-    return PR_TRUE;
+    return 1;
   }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScanAlways2ByteShiftGR(
-                                               int32_t*    state,
-                                               unsigned char  *in,
-                                               uint16_t    *out,
-                                               uint32_t     inbuflen,
-                                               uint32_t*    inscanlen
-                                               )
+int uCheckAndScanAlways2ByteShiftGR(
+                                    int32_t*    state,
+                                    unsigned char  *in,
+                                    uint16_t    *out,
+                                    uint32_t     inbuflen,
+                                    uint32_t*    inscanlen
+                                    )
 {
   /*
    * Both bytes should be in the range of [0xa1,0xfe] for 94x94 character sets
    * invoked on GR. No encoding implemented in Mozilla uses 96x96 char. sets.
    * Only 2nd byte range needs to be checked because 
    * 1st byte is checked before calling this in nsUnicodeDecoerHelper.cpp 
    */
   if(inbuflen < 2)    /* will lead to NS_OK_UDEC_MOREINPUT */
-    return PR_FALSE;
+    return 0;
   else if (! CHK_GR94(in[1]))  
   {
     *inscanlen = 2; 
     *out = 0xFF;  /* for 2-byte table, uMap() is guaranteed to fail for 0xFF. */
-    return PR_TRUE;
+    return 1;
   }
   else
   {
     *inscanlen = 2;
     *out = (((in[0] << 8) | ( in[1]))  & 0x7F7F);
-    return PR_TRUE;
+    return 1;
   }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScanAlways2ByteGR128(
-                                               int32_t*    state,
-                                               unsigned char  *in,
-                                               uint16_t    *out,
-                                               uint32_t     inbuflen,
-                                               uint32_t*    inscanlen
-                                               )
+int uCheckAndScanAlways2ByteGR128(
+                                  int32_t*    state,
+                                  unsigned char  *in,
+                                  uint16_t    *out,
+                                  uint32_t     inbuflen,
+                                  uint32_t*    inscanlen
+                                  )
 {
   /*
    * The first byte should be in  [0xa1,0xfe] 
    * and the second byte in [0x41,0xfe]
    * Used by CP949 -> Unicode converter.
    * Only 2nd byte range needs to be checked because 
    * 1st byte is checked before calling this in nsUnicodeDecoderHelper.cpp 
    */
   if(inbuflen < 2)    /* will lead to NS_OK_UDEC_MOREINPUT */
-    return PR_FALSE;
+    return 0;
   else if (in[1] < 0x41)     /* 2nd byte range check */
   {
     *inscanlen = 2; 
     *out = 0xFF;  /* for 2-byte table, uMap() is guaranteed to fail for 0xFF. */
-    return PR_TRUE;
+    return 1;
   }
   else
   {
     *inscanlen = 2;
     *out = (in[0] << 8) |  in[1];
-    return PR_TRUE;
+    return 1;
   }
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uScanShift(
-                                    uShiftInTable    *shift,
-                                    int32_t*    state,
-                                    unsigned char  *in,
-                                    uint16_t    *out,
-                                    uint32_t     inbuflen,
-                                    uint32_t*    inscanlen
-                                    )
+int uScanShift(
+               uShiftInTable    *shift,
+               int32_t*    state,
+               unsigned char  *in,
+               uint16_t    *out,
+               uint32_t     inbuflen,
+               uint32_t*    inscanlen
+               )
 {
   int16_t i;
   const uShiftInCell* cell = &(shift->shiftcell[0]);
   int16_t itemnum = shift->numOfItem;
   for(i=0;i<itemnum;i++)
   {
     if( ( in[0] >=  cell[i].shiftin_Min) &&
       ( in[0] <=  cell[i].shiftin_Max))
     {
       if(inbuflen < cell[i].reserveLen)
-        return PR_FALSE;
+        return 0;
       else
       {
         *inscanlen = cell[i].reserveLen;
         return (uSubScanner(cell[i].classID,in,out));
       }
     }
   }
-  return PR_FALSE;
+  return 0;
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8F(
-                                            int32_t*    state,
-                                            unsigned char  *in,
-                                            uint16_t    *out,
-                                            uint32_t     inbuflen,
-                                            uint32_t*    inscanlen
-                                            )
+int uCheckAndScan2ByteGRPrefix8F(
+                                 int32_t*    state,
+                                 unsigned char  *in,
+                                 uint16_t    *out,
+                                 uint32_t     inbuflen,
+                                 uint32_t*    inscanlen
+                                 )
 {
   if((inbuflen < 3) ||(in[0] != 0x8F)) 
-    return PR_FALSE;
+    return 0;
   else if (! CHK_GR94(in[1]))  /* 2nd byte range check */
   {
     *inscanlen = 2; 
     *out = 0xFF;  /* for 2-byte table, uMap() is guaranteed to fail for 0xFF. */
-    return PR_TRUE;
+    return 1;
   }
   else if (! CHK_GR94(in[2]))  /* 3rd byte range check */
   {
     *inscanlen = 3; 
     *out = 0xFF;  /* for 2-byte table, uMap() is guaranteed to fail for 0xFF. */
-    return PR_TRUE;
+    return 1;
   }
   else
   {
     *inscanlen = 3;
     *out = (((in[1] << 8) | ( in[2]))  & 0x7F7F);
-    return PR_TRUE;
+    return 1;
   }
 }
 /*=================================================================================
 
 =================================================================================*/
 
 /* Macro definition to use for uCheckAndScan2ByteGRPrefix8EAX()
  * where X is 2,3,4,5,6,7 
  */
 #define CNS_8EAX_4BYTE(PREFIX)                    \
   if((inbuflen < 4) || (in[0] != 0x8E))           \
-    return PR_FALSE;                              \
+    return 0;                                     \
   else if((in[1] != (PREFIX)))                    \
   {                                               \
     *inscanlen = 2;                               \
     *out = 0xFF;                                  \
-    return PR_TRUE;                               \
+    return 1;                                     \
   }                                               \
   else if(! CHK_GR94(in[2]))                      \
   {                                               \
     *inscanlen = 3;                               \
     *out = 0xFF;                                  \
-    return PR_TRUE;                               \
+    return 1;                                     \
   }                                               \
   else if(! CHK_GR94(in[3]))                      \
   {                                               \
     *inscanlen = 4;                               \
     *out = 0xFF;                                  \
-    return PR_TRUE;                               \
+    return 1;                                     \
   }                                               \
   else                                            \
   {                                               \
     *inscanlen = 4;                               \
     *out = (((in[2] << 8) | ( in[3]))  & 0x7F7F); \
-    return PR_TRUE;                               \
+    return 1;                                     \
   }    
 
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA2(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCheckAndScan2ByteGRPrefix8EA2(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   )
 {
   CNS_8EAX_4BYTE(0xA2)
 }
 
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA3(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCheckAndScan2ByteGRPrefix8EA3(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   )
 {
   CNS_8EAX_4BYTE(0xA3)
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA4(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCheckAndScan2ByteGRPrefix8EA4(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   )
 {
   CNS_8EAX_4BYTE(0xA4)
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA5(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCheckAndScan2ByteGRPrefix8EA5(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   )
 {
   CNS_8EAX_4BYTE(0xA5)
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA6(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCheckAndScan2ByteGRPrefix8EA6(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   )
 {
   CNS_8EAX_4BYTE(0xA6)
 }
 /*=================================================================================
 
 =================================================================================*/
-PRIVATE PRBool uCheckAndScan2ByteGRPrefix8EA7(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCheckAndScan2ByteGRPrefix8EA7(
+                                   int32_t*    state,
+                                   unsigned char  *in,
+                                   uint16_t    *out,
+                                   uint32_t     inbuflen,
+                                   uint32_t*    inscanlen
+                                   )
 {
   CNS_8EAX_4BYTE(0xA7)
 }
 /*=================================================================================
 
 =================================================================================*/
 #define SBase 0xAC00
 #define SCount 11172
 #define LCount 19
 #define VCount 21
 #define TCount 28
 #define NCount (VCount * TCount)
 
-PRIVATE PRBool uCnSAlways8BytesDecomposedHangul(
-                                              int32_t*    state,
-                                              unsigned char  *in,
-                                              uint16_t    *out,
-                                              uint32_t     inbuflen,
-                                              uint32_t*    inscanlen
-                                              )
+int uCnSAlways8BytesDecomposedHangul(
+                                     int32_t*    state,
+                                     unsigned char  *in,
+                                     uint16_t    *out,
+                                     uint32_t     inbuflen,
+                                     uint32_t*    inscanlen
+                                     )
 {
   
   uint16_t LIndex, VIndex, TIndex;
   /* no 8 bytes, not in a4 range, or the first 2 byte are not a4d4 */
   if((inbuflen < 8) || (0xa4 != in[0]) || (0xd4 != in[1]) ||
     (0xa4 != in[2] ) || (0xa4 != in[4]) || (0xa4 != in[6]))
-    return PR_FALSE;
+    return 0;
   
   /* Compute LIndex  */
   if((in[3] < 0xa1) || (in[3] > 0xbe)) { /* illegal leading consonant */
-    return PR_FALSE;
+    return 0;
   } 
   else {
     static const uint8_t lMap[] = {
       /*        A1   A2   A3   A4   A5   A6   A7  */
       0,   1,0xff,   2,0xff,0xff,   3,
         /*   A8   A9   AA   AB   AC   AD   AE   AF  */
         4,   5,0xff,0xff,0xff,0xff,0xff,0xff,
         /*   B0   B1   B2   B3   B4   B5   B6   B7  */
         0xff,   6,   7,   8,0xff,   9,  10,  11,
         /*   B8   B9   BA   BB   BC   BD   BE       */
         12,  13,  14,  15,  16,  17,  18     
     };
     
     LIndex = lMap[in[3] - 0xa1];
     if(0xff == (0xff & LIndex))
-      return PR_FALSE;
+      return 0;
   }
   
   /* Compute VIndex  */
   if((in[5] < 0xbf) || (in[5] > 0xd3)) { /* illegal medial vowel */
-    return PR_FALSE;
+    return 0;
   } 
   else {
     VIndex = in[5] - 0xbf;
   }
   
   /* Compute TIndex  */
   if(0xd4 == in[7])  
   {
     TIndex = 0;
   } 
   else if((in[7] < 0xa1) || (in[7] > 0xbe)) {/* illegal trailing consonant */
-    return PR_FALSE;
+    return 0;
   } 
   else {
     static const uint8_t tMap[] = {
       /*        A1   A2   A3   A4   A5   A6   A7  */
       1,   2,   3,   4,   5,   6,   7,
         /*   A8   A9   AA   AB   AC   AD   AE   AF  */
         0xff,   8,   9,  10,  11,  12,  13,  14,
         /*   B0   B1   B2   B3   B4   B5   B6   B7  */
         15,  16,  17,0xff,  18,  19,  20,  21,
         /*   B8   B9   BA   BB   BC   BD   BE       */
         22,0xff,  23,  24,  25,  26,  27     
     };
     TIndex = tMap[in[7] - 0xa1];
     if(0xff == (0xff & TIndex))
-      return PR_FALSE;
+      return 0;
   }
   
   *inscanlen = 8;
   /* the following line is from Unicode 2.0 page 3-13 item 5 */
   *out = ( LIndex * VCount + VIndex) * TCount + TIndex + SBase;
   
-  return PR_TRUE;
+  return 1;
 }
 /*=================================================================================
 
 =================================================================================*/
 
-PRIVATE PRBool uCheckAndScanJohabHangul(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        )
+int uCheckAndScanJohabHangul(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             )
 {
 /* since we don't have code to convert Johab to Unicode right now     *
   * make this part of code #if 0 to save space until we fully test it */
   if(inbuflen < 2)
-    return PR_FALSE;
+    return 0;
   else {
   /*
   * See Table 4-45 Johab Encoding's Five-Bit Binary Patterns in page 183
   * of "CJKV Information Processing" for details
     */
     static const uint8_t lMap[32]={ /* totaly 19  */
       0xff,0xff,0,   1,   2,   3,   4,   5,    /* 0-7    */
         6,   7,   8,   9,   10,  11,  12,  13,   /* 8-15   */
@@ -655,40 +655,40 @@ PRIVATE PRBool uCheckAndScanJohabHangul(
       0xff,0,   1,   2,   3,   4,   5,   6,    /* 0-7   */
         7,   8,   9,   10,  11,  12,  13,  14,   /* 8-15  */
         15,  16,  0xff,17,  18,  19,  20,  21,   /* 16-23 */
         22,  23,  24,  25,  26,  27,  0xff,0xff  /* 24-31 */
     };
     uint16_t ch = (in[0] << 8) | in[1];
     uint16_t LIndex, VIndex, TIndex;
     if(0 == (0x8000 & ch))
-      return PR_FALSE;
+      return 0;
     LIndex=lMap[(ch>>10)& 0x1F];
     VIndex=vMap[(ch>>5) & 0x1F];
     TIndex=tMap[(ch>>0) & 0x1F];
     if((0xff==(LIndex)) || 
       (0xff==(VIndex)) || 
       (0xff==(TIndex)))
-      return PR_FALSE;
+      return 0;
     /* the following line is from Unicode 2.0 page 3-13 item 5 */
     *out = ( LIndex * VCount + VIndex) * TCount + TIndex + SBase;
     *inscanlen = 2;
-    return PR_TRUE;
+    return 1;
   }
 }
-PRIVATE PRBool uCheckAndScanJohabSymbol(
-                                        int32_t*    state,
-                                        unsigned char  *in,
-                                        uint16_t    *out,
-                                        uint32_t     inbuflen,
-                                        uint32_t*    inscanlen
-                                        )
+int uCheckAndScanJohabSymbol(
+                             int32_t*    state,
+                             unsigned char  *in,
+                             uint16_t    *out,
+                             uint32_t     inbuflen,
+                             uint32_t*    inscanlen
+                             )
 {
   if(inbuflen < 2)
-    return PR_FALSE;
+    return 0;
   else {
   /*
   * The following code are based on the Perl code lised under
   * "Johab to ISO-2022-KR or EUC-KR Conversion" in page 1014 of
   * "CJKV Information Processing" by Ken Lunde <lunde@adobe.com>
   *
   * sub johab2ks ($) { # Convert Johab to ISO-2022-KR
   *   my @johab = unpack("C*", $_[0]);
@@ -721,39 +721,39 @@ PRIVATE PRBool uCheckAndScanJohabSymbol(
         d8_off = 42;
     }
     
     *out = (((((hi - ((hi < 223) ? 200 : 187)) << 1) -
       (lo < 161 ? 1 : 0) + offset) + d8_off) << 8 ) |
       (lo - ((lo < 161) ? ((lo > 126) ? 34 : 16) : 
     128));
     *inscanlen = 2;
-    return PR_TRUE;
+    return 1;
   }
 }
-PRIVATE PRBool uCheckAndScan4BytesGB18030(
-                                          int32_t*    state,
-                                          unsigned char  *in,
-                                          uint16_t    *out,
-                                          uint32_t     inbuflen,
-                                          uint32_t*    inscanlen
-                                          )
+int uCheckAndScan4BytesGB18030(
+                               int32_t*    state,
+                               unsigned char  *in,
+                               uint16_t    *out,
+                               uint32_t     inbuflen,
+                               uint32_t*    inscanlen
+                               )
 {
   uint32_t  data;
   if(inbuflen < 4) 
-    return PR_FALSE;
+    return 0;
   
   if((in[0] < 0x81 ) || (0xfe < in[0])) 
-    return PR_FALSE;
+    return 0;
   if((in[1] < 0x30 ) || (0x39 < in[1])) 
-    return PR_FALSE;
+    return 0;
   if((in[2] < 0x81 ) || (0xfe < in[2])) 
-    return PR_FALSE;
+    return 0;
   if((in[3] < 0x30 ) || (0x39 < in[3])) 
-    return PR_FALSE;
+    return 0;
   
   data = (((((in[0] - 0x81) * 10 + (in[1] - 0x30)) * 126) + 
     (in[2] - 0x81)) * 10 ) + (in[3] - 0x30);
   
   *inscanlen = 4;
   *out = (data < 0x00010000) ? data : 0xFFFD;
-  return PR_TRUE;
+  return 1;
 }
--- a/intl/unicharutil/util/nsSpecialCasingData.h
+++ b/intl/unicharutil/util/nsSpecialCasingData.h
@@ -1,13 +1,12 @@
 /* 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 "prtypes.h"
 #include <stdint.h>
 
 namespace mozilla {
 namespace unicode {
 
 // Multi-character mappings (from SpecialCasing.txt) map a single Unicode
 // value to a sequence of 2 or 3 Unicode characters. There are currently none
 // defined outside the BMP, so we can use char16_t here. Unused trailing
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -1280,16 +1280,19 @@ MessageChannel::ReportMessageRouteError(
 {
     PrintErrorMessage(mSide, channelName, "Need a route");
     mListener->OnProcessingError(MsgRouteError);
 }
 
 void
 MessageChannel::ReportConnectionError(const char* aChannelName) const
 {
+    AssertWorkerThread();
+    mMonitor->AssertCurrentThreadOwns();
+
     const char* errorMsg = nullptr;
     switch (mChannelState) {
       case ChannelClosed:
         errorMsg = "Closed channel: cannot send/recv";
         break;
       case ChannelOpening:
         errorMsg = "Opening channel: not yet ready for send/recv";
         break;
@@ -1303,16 +1306,18 @@ MessageChannel::ReportConnectionError(co
         errorMsg = "Channel error: cannot send/recv";
         break;
 
       default:
         NS_RUNTIMEABORT("unreached");
     }
 
     PrintErrorMessage(mSide, aChannelName, errorMsg);
+
+    MonitorAutoUnlock unlock(*mMonitor);
     mListener->OnProcessingError(MsgDropped);
 }
 
 bool
 MessageChannel::MaybeHandleError(Result code, const char* channelName)
 {
     if (MsgProcessed == code)
         return true;
--- a/js/jsd/jsd_scpt.cpp
+++ b/js/jsd/jsd_scpt.cpp
@@ -355,17 +355,17 @@ JSScript *
 jsd_GetJSScript (JSDContext *jsdc, JSDScript *script)
 {
     return script->script;
 }
 
 JSFunction *
 jsd_GetJSFunction (JSDContext *jsdc, JSDScript *script)
 {
-    AutoSafeJSContext cx; // NB: Actually unused.
+    AutoSafeJSContext cx;
     return JS_GetScriptFunction(cx, script->script);
 }
 
 JSDScript*
 jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp)
 {
     JSDScript *jsdscript = *iterp;
     
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -603,16 +603,32 @@ function ArrayKeys() {
  */
 function ComputeNumChunks(length) {
   var chunks = length >>> CHUNK_SHIFT;
   if (chunks << CHUNK_SHIFT === length)
     return chunks;
   return chunks + 1;
 }
 
+#define SLICES_PER_WORKER 8
+
+/**
+ * Compute the number of slices given an array length and the number of
+ * chunks. Used in tandem with the workstealing scheduler.
+ */
+function ComputeNumSlices(workers, length, chunks) {
+  if (length !== 0) {
+    var slices = workers * SLICES_PER_WORKER;
+    if (chunks < slices)
+      return workers;
+    return slices;
+  }
+  return workers;
+}
+
 /**
  * Computes the bounds for slice |sliceIndex| of |numItems| items,
  * assuming |numSlices| total slices. If numItems is not evenly
  * divisible by numSlices, then the final thread may have a bit of
  * extra work.
  */
 function ComputeSliceBounds(numItems, sliceIndex, numSlices) {
   var sliceWidth = (numItems / numSlices) | 0;
@@ -671,32 +687,33 @@ function ArrayMapPar(func, mode) {
     // - Breaking out of named blocks does not currently work (bug 684384);
     // - Unreachable Code Elim. can't properly handle if (a && b) (bug 669796)
     if (ShouldForceSequential())
       break parallel;
     if (!TRY_PARALLEL(mode))
       break parallel;
 
     var chunks = ComputeNumChunks(length);
-    var numSlices = ForkJoinSlices();
+    var numWorkers = ForkJoinNumWorkers();
+    var numSlices = ComputeNumSlices(numWorkers, length, chunks);
     var info = ComputeAllSliceBounds(chunks, numSlices);
-    ForkJoin(mapSlice, ForkJoinMode(mode));
+    ForkJoin(mapSlice, ForkJoinMode(mode), numSlices);
     return buffer;
   }
 
   // Sequential fallback:
   ASSERT_SEQUENTIAL_IS_OK(mode);
   for (var i = 0; i < length; i++) {
     // Note: Unlike JS arrays, parallel arrays cannot have holes.
     var v = func(self[i], i, self);
     UnsafePutElements(buffer, i, v);
   }
   return buffer;
 
-  function mapSlice(sliceId, numSlices, warmup) {
+  function mapSlice(sliceId, warmup) {
     var chunkPos = info[SLICE_POS(sliceId)];
     var chunkEnd = info[SLICE_END(sliceId)];
 
     if (warmup && chunkEnd > chunkPos + 1)
       chunkEnd = chunkPos + 1;
 
     while (chunkPos < chunkEnd) {
       var indexStart = chunkPos << CHUNK_SHIFT;
@@ -730,37 +747,38 @@ function ArrayReducePar(func, mode) {
 
   parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc
     if (ShouldForceSequential())
       break parallel;
     if (!TRY_PARALLEL(mode))
       break parallel;
 
     var chunks = ComputeNumChunks(length);
-    var numSlices = ForkJoinSlices();
-    if (chunks < numSlices)
+    var numWorkers = ForkJoinNumWorkers();
+    if (chunks < numWorkers)
       break parallel;
 
+    var numSlices = ComputeNumSlices(numWorkers, length, chunks);
     var info = ComputeAllSliceBounds(chunks, numSlices);
     var subreductions = NewDenseArray(numSlices);
-    ForkJoin(reduceSlice, ForkJoinMode(mode));
+    ForkJoin(reduceSlice, ForkJoinMode(mode), numSlices);
     var accumulator = subreductions[0];
     for (var i = 1; i < numSlices; i++)
       accumulator = func(accumulator, subreductions[i]);
     return accumulator;
   }
 
   // Sequential fallback:
   ASSERT_SEQUENTIAL_IS_OK(mode);
   var accumulator = self[0];
   for (var i = 1; i < length; i++)
     accumulator = func(accumulator, self[i]);
   return accumulator;
 
-  function reduceSlice(sliceId, numSlices, warmup) {
+  function reduceSlice(sliceId, warmup) {
     var chunkStart = info[SLICE_START(sliceId)];
     var chunkPos = info[SLICE_POS(sliceId)];
     var chunkEnd = info[SLICE_END(sliceId)];
 
     // (*) This function is carefully designed so that the warmup
     // (which executes with chunkStart === chunkPos) will execute all
     // potential loads and stores. In particular, the warmup run
     // processes two chunks rather than one. Moreover, it stores
@@ -819,23 +837,25 @@ function ArrayScanPar(func, mode) {
 
   parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc
     if (ShouldForceSequential())
       break parallel;
     if (!TRY_PARALLEL(mode))
       break parallel;
 
     var chunks = ComputeNumChunks(length);
-    var numSlices = ForkJoinSlices();
-    if (chunks < numSlices)
+    var numWorkers = ForkJoinNumWorkers();
+    if (chunks < numWorkers)
       break parallel;
+
+    var numSlices = ComputeNumSlices(numWorkers, length, chunks);
     var info = ComputeAllSliceBounds(chunks, numSlices);
 
     // Scan slices individually (see comment on phase1()).
-    ForkJoin(phase1, ForkJoinMode(mode));
+    ForkJoin(phase1, ForkJoinMode(mode), numSlices);
 
     // Compute intermediates array (see comment on phase2()).
     var intermediates = [];
     var accumulator = buffer[finalElement(0)];
     ARRAY_PUSH(intermediates, accumulator);
     for (var i = 1; i < numSlices - 1; i++) {
       accumulator = func(accumulator, buffer[finalElement(i)]);
       ARRAY_PUSH(intermediates, accumulator);
@@ -845,17 +865,17 @@ function ArrayScanPar(func, mode) {
     // convert from chunks to indices (see comment on phase2()).
     for (var i = 0; i < numSlices; i++) {
       info[SLICE_POS(i)] = info[SLICE_START(i)] << CHUNK_SHIFT;
       info[SLICE_END(i)] = info[SLICE_END(i)] << CHUNK_SHIFT;
     }
     info[SLICE_END(numSlices - 1)] = std_Math_min(info[SLICE_END(numSlices - 1)], length);
 
     // Complete each slice using intermediates array (see comment on phase2()).
-    ForkJoin(phase2, ForkJoinMode(mode));
+    ForkJoin(phase2, ForkJoinMode(mode), numSlices);
     return buffer;
   }
 
   // Sequential fallback:
   ASSERT_SEQUENTIAL_IS_OK(mode);
   scan(self[0], 0, length);
   return buffer;
 
@@ -879,17 +899,17 @@ function ArrayScanPar(func, mode) {
    * result array like:
    *
    *     [A, A+B, A+B+C, D, D+E, D+E+F, G, G+H, G+H+I]
    *      ^~~~~~~~~~~~^  ^~~~~~~~~~~~^  ^~~~~~~~~~~~~^
    *      Slice 0        Slice 1        Slice 2
    *
    * Read on in phase2 to see what we do next!
    */
-  function phase1(sliceId, numSlices, warmup) {
+  function phase1(sliceId, warmup) {
     var chunkStart = info[SLICE_START(sliceId)];
     var chunkPos = info[SLICE_POS(sliceId)];
     var chunkEnd = info[SLICE_END(sliceId)];
 
     if (warmup && chunkEnd > chunkPos + 2)
       chunkEnd = chunkPos + 2;
 
     if (chunkPos === chunkStart) {
@@ -962,17 +982,17 @@ function ArrayScanPar(func, mode) {
    * SUBTLE: Because we are mutating |buffer| in place, we have to
    * be very careful about bailouts!  We cannot checkpoint a chunk
    * at a time as we do elsewhere because that assumes it is safe to
    * replay the portion of a chunk which was already processed.
    * Therefore, in this phase, we track the current position at an
    * index granularity, although this requires two memory writes per
    * index.
    */
-  function phase2(sliceId, numSlices, warmup) {
+  function phase2(sliceId, warmup) {
     if (sliceId === 0)
       return true; // No work to do for the 0th slice.
 
     var indexPos = info[SLICE_POS(sliceId)];
     var indexEnd = info[SLICE_END(sliceId)];
 
     if (warmup)
       indexEnd = std_Math_min(indexEnd, indexPos + CHUNK_SIZE);
@@ -1097,33 +1117,33 @@ function ArrayScatterPar(targets, defaul
       ThrowError(JSMSG_PAR_ARRAY_SCATTER_CONFLICT);
 
     return conflictFunc(elem1, elem2);
   }
 
 
   function parDivideOutputRange() {
     var chunks = ComputeNumChunks(targetsLength);
-    var numSlices = ForkJoinSlices();
+    var numSlices = ComputeNumSlices(ForkJoinNumWorkers(), length, chunks);
     var checkpoints = NewDenseArray(numSlices);
     for (var i = 0; i < numSlices; i++)
       UnsafePutElements(checkpoints, i, 0);
 
     var buffer = NewDenseArray(length);
     var conflicts = NewDenseArray(length);
 
     for (var i = 0; i < length; i++) {
       UnsafePutElements(buffer, i, defaultValue);
       UnsafePutElements(conflicts, i, false);
     }
 
-    ForkJoin(fill, ForkJoinMode(mode));
+    ForkJoin(fill, ForkJoinMode(mode), numSlices);
     return buffer;
 
-    function fill(sliceId, numSlices, warmup) {
+    function fill(sliceId, warmup) {
       var indexPos = checkpoints[sliceId];
       var indexEnd = targetsLength;
       if (warmup)
         indexEnd = std_Math_min(indexEnd, indexPos + CHUNK_SIZE);
 
       // Range in the output for which we are responsible:
       var [outputStart, outputEnd] = ComputeSliceBounds(length, sliceId, numSlices);
 
@@ -1144,17 +1164,17 @@ function ArrayScatterPar(targets, defaul
   }
 
   function parDivideScatterVector() {
     // Subtle: because we will be mutating the localBuffers and
     // conflict arrays in place, we can never replay an entry in the
     // target array for fear of inducing a conflict where none existed
     // before. Therefore, we must proceed not by chunks but rather by
     // individual indices.
-    var numSlices = ForkJoinSlices();
+    var numSlices = ComputeNumSlices(ForkJoinNumWorkers(), length, ComputeNumChunks(length));
     var info = ComputeAllSliceBounds(targetsLength, numSlices);
 
     // FIXME(bug 844890): Use typed arrays here.
     var localBuffers = NewDenseArray(numSlices);
     for (var i = 0; i < numSlices; i++)
       UnsafePutElements(localBuffers, i, NewDenseArray(length));
     var localConflicts = NewDenseArray(numSlices);
     for (var i = 0; i < numSlices; i++) {
@@ -1167,21 +1187,21 @@ function ArrayScatterPar(targets, defaul
     // Initialize the 0th buffer, which will become the output. For
     // the other buffers, we track which parts have been written to
     // using the conflict buffer so they do not need to be
     // initialized.
     var outputBuffer = localBuffers[0];
     for (var i = 0; i < length; i++)
       UnsafePutElements(outputBuffer, i, defaultValue);
 
-    ForkJoin(fill, ForkJoinMode(mode));
+    ForkJoin(fill, ForkJoinMode(mode), numSlices);
     mergeBuffers();
     return outputBuffer;
 
-    function fill(sliceId, numSlices, warmup) {
+    function fill(sliceId, warmup) {
       var indexPos = info[SLICE_POS(sliceId)];
       var indexEnd = info[SLICE_END(sliceId)];
       if (warmup)
         indexEnd = std_Math_min(indexEnd, indexPos + CHUNK_SIZE);
 
       var localbuffer = localBuffers[sliceId];
       var conflicts = localConflicts[sliceId];
       while (indexPos < indexEnd) {
@@ -1270,43 +1290,44 @@ function ArrayFilterPar(func, mode) {
 
   parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc
     if (ShouldForceSequential())
       break parallel;
     if (!TRY_PARALLEL(mode))
       break parallel;
 
     var chunks = ComputeNumChunks(length);
-    var numSlices = ForkJoinSlices();
-    if (chunks < numSlices * 2)
+    var numWorkers = ForkJoinNumWorkers();
+    if (chunks < numWorkers * 2)
       break parallel;
 
+    var numSlices = ComputeNumSlices(numWorkers, length, chunks);
     var info = ComputeAllSliceBounds(chunks, numSlices);
 
     // Step 1. Compute which items from each slice of the result
     // buffer should be preserved. When we're done, we have an array
     // |survivors| containing a bitset for each chunk, indicating
     // which members of the chunk survived. We also keep an array
     // |counts| containing the total number of items that are being
     // preserved from within one slice.
     //
     // FIXME(bug 844890): Use typed arrays here.
     var counts = NewDenseArray(numSlices);
     for (var i = 0; i < numSlices; i++)
       UnsafePutElements(counts, i, 0);
     var survivors = NewDenseArray(chunks);
-    ForkJoin(findSurvivorsInSlice, ForkJoinMode(mode));
+    ForkJoin(findSurvivorsInSlice, ForkJoinMode(mode), numSlices);
 
     // Step 2. Compress the slices into one contiguous set.
     var count = 0;
     for (var i = 0; i < numSlices; i++)
       count += counts[i];
     var buffer = NewDenseArray(count);
     if (count > 0)
-      ForkJoin(copySurvivorsInSlice, ForkJoinMode(mode));
+      ForkJoin(copySurvivorsInSlice, ForkJoinMode(mode), numSlices);
 
     return buffer;
   }
 
   // Sequential fallback:
   ASSERT_SEQUENTIAL_IS_OK(mode);
   var buffer = [];
   for (var i = 0; i < length; i++) {
@@ -1317,17 +1338,17 @@ function ArrayFilterPar(func, mode) {
   return buffer;
 
   /**
    * As described above, our goal is to determine which items we
    * will preserve from a given slice. We do this one chunk at a
    * time. When we finish a chunk, we record our current count and
    * the next chunk sliceId, lest we should bail.
    */
-  function findSurvivorsInSlice(sliceId, numSlices, warmup) {
+  function findSurvivorsInSlice(sliceId, warmup) {
     var chunkPos = info[SLICE_POS(sliceId)];
     var chunkEnd = info[SLICE_END(sliceId)];
 
     if (warmup && chunkEnd > chunkPos)
       chunkEnd = chunkPos + 1;
 
     var count = counts[sliceId];
     while (chunkPos < chunkEnd) {
@@ -1344,17 +1365,17 @@ function ArrayFilterPar(func, mode) {
       UnsafePutElements(survivors, chunkPos, chunkBits,
                         counts, sliceId, count,
                         info, SLICE_POS(sliceId), ++chunkPos);
     }
 
     return chunkEnd === info[SLICE_END(sliceId)];
   }
 
-  function copySurvivorsInSlice(sliceId, numSlices, warmup) {
+  function copySurvivorsInSlice(sliceId, warmup) {
     // Copies the survivors from this slice into the correct position.
     // Note that this is an idempotent operation that does not invoke
     // user code. Therefore, we don't expect bailouts and make an
     // effort to proceed chunk by chunk or avoid duplicating work.
 
     // Total up the items preserved by previous slices.
     var count = 0;
     if (sliceId > 0) { // FIXME(#819219)---work around a bug in Ion's range checks
@@ -1427,28 +1448,29 @@ function ArrayStaticBuildPar(length, fun
 
   parallel: for (;;) {
     if (ShouldForceSequential())
       break parallel;
     if (!TRY_PARALLEL(mode))
       break parallel;
 
     var chunks = ComputeNumChunks(length);
-    var numSlices = ForkJoinSlices();
+    var numWorkers = ForkJoinNumWorkers();
+    var numSlices = ComputeNumSlices(numWorkers, length, chunks);
     var info = ComputeAllSliceBounds(chunks, numSlices);
-    ForkJoin(constructSlice, ForkJoinMode(mode));
+    ForkJoin(constructSlice, ForkJoinMode(mode), numSlices);
     return buffer;
   }
 
   // Sequential fallback:
   ASSERT_SEQUENTIAL_IS_OK(mode);
   fill(0, length);
   return buffer;
 
-  function constructSlice(sliceId, numSlices, warmup) {
+  function constructSlice(sliceId, warmup) {
     var chunkPos = info[SLICE_POS(sliceId)];
     var chunkEnd = info[SLICE_END(sliceId)];
 
     if (warmup && chunkEnd > chunkPos)
       chunkEnd = chunkPos + 1;
 
     while (chunkPos < chunkEnd) {
       var indexStart = chunkPos << CHUNK_SHIFT;
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -119,19 +119,16 @@ SIMPLE_PROGRAMS += $(CPP_UNIT_TEST_BINS)
 INCLUDES += -I$(DIST)/include/testing
 LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS)
 
 ifndef MOZ_PROFILE_GENERATE
 libs:: $(CPP_UNIT_TEST_BINS) $(call mkdir_deps,$(DIST)/cppunittests)
 	$(NSINSTALL) $(CPP_UNIT_TEST_BINS) $(DIST)/cppunittests
 endif
 
-check::
-	@$(PYTHON) $(topsrcdir)/testing/runcppunittests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(subst .cpp,$(BIN_SUFFIX),$(CPP_UNIT_TESTS))
-
 cppunittests-remote: DM_TRANS?=adb
 cppunittests-remote:
 	@if [ '${TEST_DEVICE}' != '' -o '$(DM_TRANS)' = 'adb' ]; then \
 		$(PYTHON) -u $(topsrcdir)/testing/remotecppunittests.py \
 			--xre-path=$(DEPTH)/dist/bin \
 			--localLib=$(DEPTH)/dist/$(MOZ_APP_NAME) \
 			--dm_trans=$(DM_TRANS) \
 			--deviceIP=${TEST_DEVICE} \
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -67,17 +67,19 @@ CheckArgumentsWithinEval(JSContext *cx, 
         // It's an error to use |arguments| in a function that has a rest
         // parameter.
         parser.report(ParseError, false, nullptr, JSMSG_ARGUMENTS_AND_REST);
         return false;
     }
 
     // Force construction of arguments objects for functions that use
     // |arguments| within an eval.
-    RootedScript script(cx, fun->nonLazyScript());
+    RootedScript script(cx, fun->getOrCreateScript(cx));
+    if (!script)
+        return false;
     if (script->argumentsHasVarBinding()) {
         if (!JSScript::argumentsOptimizationFailed(cx, script))
             return false;
     }
 
     // It's an error to use |arguments| in a legacy generator expression.
     if (script->isGeneratorExp() && script->isLegacyGenerator()) {
         parser.report(ParseError, false, nullptr, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
@@ -118,17 +120,19 @@ MaybeCheckEvalFreeVariables(ExclusiveCon
     // If the eval'ed script contains any debugger statement, force construction
     // of arguments objects for the caller script and any other scripts it is
     // transitively nested inside. The debugger can access any variable on the
     // scope chain.
     if (pc.sc->hasDebuggerStatement()) {
         RootedObject scope(cx, scopeChain);
         while (scope->is<ScopeObject>() || scope->is<DebugScopeObject>()) {
             if (scope->is<CallObject>() && !scope->as<CallObject>().isForEval()) {
-                RootedScript script(cx, scope->as<CallObject>().callee().nonLazyScript());
+                RootedScript script(cx, scope->as<CallObject>().callee().getOrCreateScript(cx));
+                if (!script)
+                    return false;
                 if (script->argumentsHasVarBinding()) {
                     if (!JSScript::argumentsOptimizationFailed(cx, script))
                         return false;
                 }
             }
             scope = scope->enclosingScope();
         }
     }
@@ -230,20 +234,18 @@ frontend::CompileScript(ExclusiveContext
     Parser<FullParseHandler> parser(cx, alloc, options, chars, length, /* foldConstants = */ true,
                                     canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
     parser.sct = sct;
     parser.ss = ss;
 
     Directives directives(options.strictOption);
     GlobalSharedContext globalsc(cx, scopeChain, directives, options.extraWarningsOption);
 
-    bool savedCallerFun =
-        options.compileAndGo &&
-        evalCaller &&
-        (evalCaller->function() || evalCaller->savedCallerFun());
+    bool savedCallerFun = options.compileAndGo &&
+                          evalCaller && evalCaller->functionOrCallerFunction();
     Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun,
                                                   options, staticLevel, sourceObject, 0, length));
     if (!script)
         return nullptr;
 
     // Global/eval script bindings are always empty (all names are added to the
     // scope dynamically via JSOP_DEFFUN/VAR).
     InternalHandle<Bindings*> bindings(script, &script->bindings);
@@ -399,17 +401,17 @@ frontend::CompileScript(ExclusiveContext
         return nullptr;
 
     return script;
 }
 
 bool
 frontend::CompileLazyFunction(JSContext *cx, Handle<LazyScript*> lazy, const jschar *chars, size_t length)
 {
-    JS_ASSERT(cx->compartment() == lazy->function()->compartment());
+    JS_ASSERT(cx->compartment() == lazy->functionNonDelazifying()->compartment());
 
     CompileOptions options(cx, lazy->version());
     options.setPrincipals(cx->compartment()->principals)
            .setOriginPrincipals(lazy->originPrincipals())
            .setFileAndLine(lazy->source()->filename(), lazy->lineno())
            .setColumn(lazy->column())
            .setCompileAndGo(true)
            .setNoScriptRval(false)
@@ -422,17 +424,17 @@ frontend::CompileLazyFunction(JSContext 
                                 options);
 #endif
 
     Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
                                     /* foldConstants = */ true, nullptr, lazy);
 
     uint32_t staticLevel = lazy->staticLevel(cx);
 
-    Rooted<JSFunction*> fun(cx, lazy->function());
+    Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
     JS_ASSERT(!lazy->isLegacyGenerator());
     ParseNode *pn = parser.standaloneLazyFunction(fun, staticLevel, lazy->strict(),
                                                   lazy->generatorKind());
     if (!pn)
         return false;
 
     if (!NameFunctions(cx, pn))
         return false;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1280,17 +1280,17 @@ TryConvertFreeName(BytecodeEmitter *bce,
                     // Use generic ops if a catch block is encountered.
                     return false;
                 }
                 if (ssi.hasDynamicScopeObject())
                     hops++;
                 continue;
             }
             RootedScript script(bce->sc->context, ssi.funScript());
-            if (script->function()->atom() == pn->pn_atom)
+            if (script->functionNonDelazifying()->atom() == pn->pn_atom)
                 return false;
             if (ssi.hasDynamicScopeObject()) {
                 uint16_t slot;
                 if (LookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot)) {
                     JSOp op;
                     switch (pn->getOp()) {
                       case JSOP_NAME:     op = JSOP_GETALIASEDVAR; break;
                       case JSOP_SETNAME:  op = JSOP_SETALIASEDVAR; break;
@@ -1862,17 +1862,17 @@ BytecodeEmitter::needsImplicitThis()
 void
 BytecodeEmitter::tellDebuggerAboutCompiledScript(ExclusiveContext *cx)
 {
     // Note: when parsing off thread the resulting scripts need to be handed to
     // the debugger after rejoining to the main thread.
     if (!cx->isJSContext())
         return;
 
-    RootedFunction function(cx, script->function());
+    RootedFunction function(cx, script->functionNonDelazifying());
     CallNewScriptHook(cx->asJSContext(), script, function);
     // Lazy scripts are never top level (despite always being invoked with a
     // nullptr parent), and so the hook should never be fired.
     if (emitterMode != LazyFunction && !parent) {
         GlobalObject *compileAndGoGlobal = nullptr;
         if (script->compileAndGo())
             compileAndGoGlobal = &script->global();
         Debugger::onNewScript(cx->asJSContext(), script, compileAndGoGlobal);
@@ -2790,17 +2790,17 @@ frontend::EmitFunctionScript(ExclusiveCo
      * initializers created within it may be given more precise types.
      */
     if (runOnce) {
         bce->script->setTreatAsRunOnce();
         JS_ASSERT(!bce->script->hasRunOnce());
     }
 
     /* Initialize fun->script() so that the debugger has a valid fun->script(). */
-    RootedFunction fun(cx, bce->script->function());
+    RootedFunction fun(cx, bce->script->functionNonDelazifying());
     JS_ASSERT(fun->isInterpreted());
 
     if (fun->isInterpretedLazy()) {
         AutoLockForCompilation lock(cx);
         fun->setUnlazifiedScript(bce->script);
     } else {
         fun->setScript(bce->script);
     }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/regexp-match-limit.js
@@ -0,0 +1,9 @@
+// See bug 953013
+
+load(libdir + "asserts.js");
+
+function test() {
+    var input = Array(999999+1).join('a');
+    var result = /^([\w])+$/.test(input);
+}
+assertThrowsInstanceOf(test, InternalError);
--- a/js/src/jit-test/tests/basic/string-endswith.js
+++ b/js/src/jit-test/tests/basic/string-endswith.js
@@ -1,39 +1,262 @@
-assertEq("abc".endsWith("abc"), true);
-assertEq("abcd".endsWith("bcd"), true);
-assertEq("abc".endsWith("c"), true);
-assertEq("abc".endsWith("abcd"), false);
-assertEq("abc".endsWith("bbc"), false);
-assertEq("abc".endsWith("b"), false);
-assertEq("abc".endsWith("abc", 3), true);
-assertEq("abc".endsWith("bc", 3), true);
-assertEq("abc".endsWith("a", 3), false);
-assertEq("abc".endsWith("bc", 3), true);
-assertEq("abc".endsWith("a", 1), true);
-assertEq("abc".endsWith("abc", 1), false);
-assertEq("abc".endsWith("b", 2), true);
-assertEq("abc".endsWith("d", 2), false);
-assertEq("abc".endsWith("dcd", 2), false);
-assertEq("abc".endsWith("a", 42), false);
-assertEq("abc".endsWith("bc", Infinity), true);
-assertEq("abc".endsWith("a", Infinity), false);
-assertEq("abc".endsWith("bc", undefined), true);
-assertEq("abc".endsWith("bc", -43), false);
-assertEq("abc".endsWith("bc", -Infinity), false);
-assertEq("abc".endsWith("bc", NaN), false);
-var myobj = {toString : (function () "abc"), endsWith : String.prototype.endsWith};
-assertEq(myobj.endsWith("abc"), true);
-assertEq(myobj.endsWith("ab"), false);
-var gotStr = false, gotPos = false;
-myobj = {toString : (function () {
-    assertEq(gotPos, false);
-    gotStr = true;
-    return "xyz";
-}),
-endsWith : String.prototype.endsWith};
-var idx = {valueOf : (function () {
-    assertEq(gotStr, true);
-    gotPos = true;
-    return 42;
-})};
-myobj.endsWith("elephant", idx);
-assertEq(gotPos, true);
+/*
+* Copyright (c) 2013 Mathias Bynens. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+function assertThrows(fun, errorType) {
+  try {
+    fun();
+    assertEq(true, false, "Expected error, but none was thrown");
+  } catch (e) {
+    assertEq(e instanceof errorType, true, "Wrong error type thrown");
+  }
+}
+assertEq(String.prototype.endsWith.length, 1);
+assertEq(String.prototype.propertyIsEnumerable('endsWith'), false);
+
+assertEq('undefined'.endsWith(), true);
+assertEq('undefined'.endsWith(undefined), true);
+assertEq('undefined'.endsWith(null), false);
+assertEq('null'.endsWith(), false);
+assertEq('null'.endsWith(undefined), false);
+assertEq('null'.endsWith(null), true);
+
+assertEq('abc'.endsWith(), false);
+assertEq('abc'.endsWith(''), true);
+assertEq('abc'.endsWith('\0'), false);
+assertEq('abc'.endsWith('c'), true);
+assertEq('abc'.endsWith('b'), false);
+assertEq('abc'.endsWith('a'), false);
+assertEq('abc'.endsWith('ab'), false);
+assertEq('abc'.endsWith('bc'), true);
+assertEq('abc'.endsWith('abc'), true);
+assertEq('abc'.endsWith('bcd'), false);
+assertEq('abc'.endsWith('abcd'), false);
+assertEq('abc'.endsWith('bcde'), false);
+
+assertEq('abc'.endsWith('', NaN), true);
+assertEq('abc'.endsWith('\0', NaN), false);
+assertEq('abc'.endsWith('c', NaN), false);
+assertEq('abc'.endsWith('b', NaN), false);
+assertEq('abc'.endsWith('a', NaN), false);
+assertEq('abc'.endsWith('ab', NaN), false);
+assertEq('abc'.endsWith('bc', NaN), false);
+assertEq('abc'.endsWith('abc', NaN), false);
+assertEq('abc'.endsWith('bcd', NaN), false);
+assertEq('abc'.endsWith('abcd', NaN), false);
+assertEq('abc'.endsWith('bcde', NaN), false);
+
+assertEq('abc'.endsWith('', false), true);
+assertEq('abc'.endsWith('\0', false), false);
+assertEq('abc'.endsWith('c', false), false);
+assertEq('abc'.endsWith('b', false), false);
+assertEq('abc'.endsWith('a', false), false);
+assertEq('abc'.endsWith('ab', false), false);
+assertEq('abc'.endsWith('bc', false), false);
+assertEq('abc'.endsWith('abc', false), false);
+assertEq('abc'.endsWith('bcd', false), false);
+assertEq('abc'.endsWith('abcd', false), false);
+assertEq('abc'.endsWith('bcde', false), false);
+
+assertEq('abc'.endsWith('', undefined), true);
+assertEq('abc'.endsWith('\0', undefined), false);
+assertEq('abc'.endsWith('c', undefined), true);
+assertEq('abc'.endsWith('b', undefined), false);
+assertEq('abc'.endsWith('a', undefined), false);
+assertEq('abc'.endsWith('ab', undefined), false);
+assertEq('abc'.endsWith('bc', undefined), true);
+assertEq('abc'.endsWith('abc', undefined), true);
+assertEq('abc'.endsWith('bcd', undefined), false);
+assertEq('abc'.endsWith('abcd', undefined), false);
+assertEq('abc'.endsWith('bcde', undefined), false);
+
+assertEq('abc'.endsWith('', null), true);
+assertEq('abc'.endsWith('\0', null), false);
+assertEq('abc'.endsWith('c', null), false);
+assertEq('abc'.endsWith('b', null), false);
+assertEq('abc'.endsWith('a', null), false);
+assertEq('abc'.endsWith('ab', null), false);
+assertEq('abc'.endsWith('bc', null), false);
+assertEq('abc'.endsWith('abc', null), false);
+assertEq('abc'.endsWith('bcd', null), false);
+assertEq('abc'.endsWith('abcd', null), false);
+assertEq('abc'.endsWith('bcde', null), false);
+
+assertEq('abc'.endsWith('', -Infinity), true);
+assertEq('abc'.endsWith('\0', -Infinity), false);
+assertEq('abc'.endsWith('c', -Infinity), false);
+assertEq('abc'.endsWith('b', -Infinity), false);
+assertEq('abc'.endsWith('a', -Infinity), false);
+assertEq('abc'.endsWith('ab', -Infinity), false);
+assertEq('abc'.endsWith('bc', -Infinity), false);
+assertEq('abc'.endsWith('abc', -Infinity), false);
+assertEq('abc'.endsWith('bcd', -Infinity), false);
+assertEq('abc'.endsWith('abcd', -Infinity), false);
+assertEq('abc'.endsWith('bcde', -Infinity), false);
+
+assertEq('abc'.endsWith('', -1), true);
+assertEq('abc'.endsWith('\0', -1), false);
+assertEq('abc'.endsWith('c', -1), false);
+assertEq('abc'.endsWith('b', -1), false);
+assertEq('abc'.endsWith('a', -1), false);
+assertEq('abc'.endsWith('ab', -1), false);
+assertEq('abc'.endsWith('bc', -1), false);
+assertEq('abc'.endsWith('abc', -1), false);
+assertEq('abc'.endsWith('bcd', -1), false);
+assertEq('abc'.endsWith('abcd', -1), false);
+assertEq('abc'.endsWith('bcde', -1), false);
+
+assertEq('abc'.endsWith('', -0), true);
+assertEq('abc'.endsWith('\0', -0), false);
+assertEq('abc'.endsWith('c', -0), false);
+assertEq('abc'.endsWith('b', -0), false);
+assertEq('abc'.endsWith('a', -0), false);
+assertEq('abc'.endsWith('ab', -0), false);
+assertEq('abc'.endsWith('bc', -0), false);
+assertEq('abc'.endsWith('abc', -0), false);
+assertEq('abc'.endsWith('bcd', -0), false);
+assertEq('abc'.endsWith('abcd', -0), false);
+assertEq('abc'.endsWith('bcde', -0), false);
+
+assertEq('abc'.endsWith('', +0), true);
+assertEq('abc'.endsWith('\0', +0), false);
+assertEq('abc'.endsWith('c', +0), false);
+assertEq('abc'.endsWith('b', +0), false);
+assertEq('abc'.endsWith('a', +0), false);
+assertEq('abc'.endsWith('ab', +0), false);
+assertEq('abc'.endsWith('bc', +0), false);
+assertEq('abc'.endsWith('abc', +0), false);
+assertEq('abc'.endsWith('bcd', +0), false);
+assertEq('abc'.endsWith('abcd', +0), false);
+assertEq('abc'.endsWith('bcde', +0), false);
+
+assertEq('abc'.endsWith('', 1), true);
+assertEq('abc'.endsWith('\0', 1), false);
+assertEq('abc'.endsWith('c', 1), false);
+assertEq('abc'.endsWith('b', 1), false);
+assertEq('abc'.endsWith('ab', 1), false);
+assertEq('abc'.endsWith('bc', 1), false);
+assertEq('abc'.endsWith('abc', 1), false);
+assertEq('abc'.endsWith('bcd', 1), false);
+assertEq('abc'.endsWith('abcd', 1), false);
+assertEq('abc'.endsWith('bcde', 1), false);
+
+assertEq('abc'.endsWith('', 2), true);
+assertEq('abc'.endsWith('\0', 2), false);
+assertEq('abc'.endsWith('c', 2), false);
+assertEq('abc'.endsWith('b', 2), true);
+assertEq('abc'.endsWith('ab', 2), true);
+assertEq('abc'.endsWith('bc', 2), false);
+assertEq('abc'.endsWith('abc', 2), false);
+assertEq('abc'.endsWith('bcd', 2), false);
+assertEq('abc'.endsWith('abcd', 2), false);
+assertEq('abc'.endsWith('bcde', 2), false);
+
+assertEq('abc'.endsWith('', +Infinity), true);
+assertEq('abc'.endsWith('\0', +Infinity), false);
+assertEq('abc'.endsWith('c', +Infinity), true);
+assertEq('abc'.endsWith('b', +Infinity), false);
+assertEq('abc'.endsWith('a', +Infinity), false);
+assertEq('abc'.endsWith('ab', +Infinity), false);
+assertEq('abc'.endsWith('bc', +Infinity), true);
+assertEq('abc'.endsWith('abc', +Infinity), true);
+assertEq('abc'.endsWith('bcd', +Infinity), false);
+assertEq('abc'.endsWith('abcd', +Infinity), false);
+assertEq('abc'.endsWith('bcde', +Infinity), false);
+
+assertEq('abc'.endsWith('', true), true);
+assertEq('abc'.endsWith('\0', true), false);
+assertEq('abc'.endsWith('c', true), false);
+assertEq('abc'.endsWith('b', true), false);
+assertEq('abc'.endsWith('ab', true), false);
+assertEq('abc'.endsWith('bc', true), false);
+assertEq('abc'.endsWith('abc', true), false);
+assertEq('abc'.endsWith('bcd', true), false);
+assertEq('abc'.endsWith('abcd', true), false);
+assertEq('abc'.endsWith('bcde', true), false);
+
+assertEq('abc'.endsWith('', 'x'), true);
+assertEq('abc'.endsWith('\0', 'x'), false);
+assertEq('abc'.endsWith('c', 'x'), false);
+assertEq('abc'.endsWith('b', 'x'), false);
+assertEq('abc'.endsWith('a', 'x'), false);
+assertEq('abc'.endsWith('ab', 'x'), false);
+assertEq('abc'.endsWith('bc', 'x'), false);
+assertEq('abc'.endsWith('abc', 'x'), false);
+assertEq('abc'.endsWith('bcd', 'x'), false);
+assertEq('abc'.endsWith('abcd', 'x'), false);
+assertEq('abc'.endsWith('bcde', 'x'), false);
+
+assertEq('[a-z]+(bar)?'.endsWith('(bar)?'), true);
+assertThrows(function() { '[a-z]+(bar)?'.endsWith(/(bar)?/); }, TypeError);
+assertEq('[a-z]+(bar)?'.endsWith('[a-z]+', 6), true);
+assertThrows(function() { '[a-z]+(bar)?'.endsWith(/(bar)?/); }, TypeError);
+assertThrows(function() { '[a-z]+/(bar)?/'.endsWith(/(bar)?/); }, TypeError);
+var global = newGlobal();
+global.eval('this.re = /(bar)?/');
+assertThrows(function() { '[a-z]+/(bar)?/'.endsWith(global.re); }, TypeError);
+
+// http://mathiasbynens.be/notes/javascript-unicode#poo-test
+var string = 'I\xF1t\xEBrn\xE2ti\xF4n\xE0liz\xE6ti\xF8n\u2603\uD83D\uDCA9';
+assertEq(string.endsWith(''), true);
+assertEq(string.endsWith('\xF1t\xEBr'), false);
+assertEq(string.endsWith('\xF1t\xEBr', 5), true);
+assertEq(string.endsWith('\xE0liz\xE6'), false);
+assertEq(string.endsWith('\xE0liz\xE6', 16), true);
+assertEq(string.endsWith('\xF8n\u2603\uD83D\uDCA9'), true);
+assertEq(string.endsWith('\xF8n\u2603\uD83D\uDCA9', 23), true);
+assertEq(string.endsWith('\u2603'), false);
+assertEq(string.endsWith('\u2603', 21), true);
+assertEq(string.endsWith('\uD83D\uDCA9'), true);
+assertEq(string.endsWith('\uD83D\uDCA9', 23), true);
+
+assertThrows(function() { String.prototype.endsWith.call(undefined); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.call(undefined, 'b'); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.call(undefined, 'b', 4); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.call(null); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.call(null, 'b'); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.call(null, 'b', 4); }, TypeError);
+assertEq(String.prototype.endsWith.call(42, '2'), true);
+assertEq(String.prototype.endsWith.call(42, '4'), false);
+assertEq(String.prototype.endsWith.call(42, 'b', 4), false);
+assertEq(String.prototype.endsWith.call(42, '2', 1), false);
+assertEq(String.prototype.endsWith.call(42, '2', 4), true);
+assertEq(String.prototype.endsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 0), false);
+assertEq(String.prototype.endsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 1), false);
+assertEq(String.prototype.endsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 2), true);
+assertThrows(function() { String.prototype.endsWith.call({ 'toString': function() { throw RangeError(); } }, /./); }, RangeError);
+assertThrows(function() { String.prototype.endsWith.call({ 'toString': function() { return 'abc' } }, /./); }, TypeError);
+
+assertThrows(function() { String.prototype.endsWith.apply(undefined); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.apply(undefined, ['b']); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.apply(undefined, ['b', 4]); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.apply(null); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.apply(null, ['b']); }, TypeError);
+assertThrows(function() { String.prototype.endsWith.apply(null, ['b', 4]); }, TypeError);
+assertEq(String.prototype.endsWith.apply(42, ['2']), true);
+assertEq(String.prototype.endsWith.apply(42, ['4']), false);
+assertEq(String.prototype.endsWith.apply(42, ['b', 4]), false);
+assertEq(String.prototype.endsWith.apply(42, ['2', 1]), false);
+assertEq(String.prototype.endsWith.apply(42, ['2', 4]), true);
+assertEq(String.prototype.endsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 0]), false);
+assertEq(String.prototype.endsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 1]), false);
+assertEq(String.prototype.endsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 2]), true);
+assertThrows(function() { String.prototype.endsWith.apply({ 'toString': function() { throw RangeError(); } }, [/./]); }, RangeError);
+assertThrows(function() { String.prototype.endsWith.apply({ 'toString': function() { return 'abc' } }, [/./]); }, TypeError);
--- a/js/src/jit-test/tests/basic/string-startswith.js
+++ b/js/src/jit-test/tests/basic/string-startswith.js
@@ -1,39 +1,243 @@
-assertEq("abc".startsWith("abc"), true);
-assertEq("abcd".startsWith("abc"), true);
-assertEq("abc".startsWith("a"), true);
-assertEq("abc".startsWith("abcd"), false);
-assertEq("abc".startsWith("bcde"), false);
-assertEq("abc".startsWith("b"), false);
-assertEq("abc".startsWith("abc", 0), true);
-assertEq("abc".startsWith("bc", 0), false);
-assertEq("abc".startsWith("bc", 1), true);
-assertEq("abc".startsWith("c", 1), false);
-assertEq("abc".startsWith("abc", 1), false);
-assertEq("abc".startsWith("c", 2), true);
-assertEq("abc".startsWith("d", 2), false);
-assertEq("abc".startsWith("dcd", 2), false);
-assertEq("abc".startsWith("a", 42), false);
-assertEq("abc".startsWith("a", Infinity), false);
-assertEq("abc".startsWith("a", NaN), true);
-assertEq("abc".startsWith("b", NaN), false);
-assertEq("abc".startsWith("ab", -43), true);
-assertEq("abc".startsWith("ab", -Infinity), true);
-assertEq("abc".startsWith("bc", -42), false);
-assertEq("abc".startsWith("bc", -Infinity), false);
-var myobj = {toString : (function () "abc"), startsWith : String.prototype.startsWith};
-assertEq(myobj.startsWith("abc"), true);
-assertEq(myobj.startsWith("bc"), false);
-var gotStr = false, gotPos = false;
-myobj = {toString : (function () {
-    assertEq(gotPos, false);
-    gotStr = true;
-    return "xyz";
-}),
-startsWith : String.prototype.startsWith};
-var idx = {valueOf : (function () {
-    assertEq(gotStr, true);
-    gotPos = true;
-    return 42;
-})};
-myobj.startsWith("elephant", idx);
-assertEq(gotPos, true);
+/*
+* Copyright (c) 2013 Mathias Bynens. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+function assertThrows(fun, errorType) {
+  try {
+    fun();
+    assertEq(true, false, "Expected error, but none was thrown");
+  } catch (e) {
+    assertEq(e instanceof errorType, true, "Wrong error type thrown");
+  }
+}
+
+Object.prototype[1] = 2; // try to break `arguments[1]`
+
+assertEq(String.prototype.startsWith.length, 1);
+assertEq(String.prototype.propertyIsEnumerable('startsWith'), false);
+
+assertEq('undefined'.startsWith(), true);
+assertEq('undefined'.startsWith(undefined), true);
+assertEq('undefined'.startsWith(null), false);
+assertEq('null'.startsWith(), false);
+assertEq('null'.startsWith(undefined), false);
+assertEq('null'.startsWith(null), true);
+
+assertEq('abc'.startsWith(), false);
+assertEq('abc'.startsWith(''), true);
+assertEq('abc'.startsWith('\0'), false);
+assertEq('abc'.startsWith('a'), true);
+assertEq('abc'.startsWith('b'), false);
+assertEq('abc'.startsWith('ab'), true);
+assertEq('abc'.startsWith('bc'), false);
+assertEq('abc'.startsWith('abc'), true);
+assertEq('abc'.startsWith('bcd'), false);
+assertEq('abc'.startsWith('abcd'), false);
+assertEq('abc'.startsWith('bcde'), false);
+
+assertEq('abc'.startsWith('', NaN), true);
+assertEq('abc'.startsWith('\0', NaN), false);
+assertEq('abc'.startsWith('a', NaN), true);
+assertEq('abc'.startsWith('b', NaN), false);
+assertEq('abc'.startsWith('ab', NaN), true);
+assertEq('abc'.startsWith('bc', NaN), false);
+assertEq('abc'.startsWith('abc', NaN), true);
+assertEq('abc'.startsWith('bcd', NaN), false);
+assertEq('abc'.startsWith('abcd', NaN), false);
+assertEq('abc'.startsWith('bcde', NaN), false);
+
+assertEq('abc'.startsWith('', false), true);
+assertEq('abc'.startsWith('\0', false), false);
+assertEq('abc'.startsWith('a', false), true);
+assertEq('abc'.startsWith('b', false), false);
+assertEq('abc'.startsWith('ab', false), true);
+assertEq('abc'.startsWith('bc', false), false);
+assertEq('abc'.startsWith('abc', false), true);
+assertEq('abc'.startsWith('bcd', false), false);
+assertEq('abc'.startsWith('abcd', false), false);
+assertEq('abc'.startsWith('bcde', false), false);
+
+assertEq('abc'.startsWith('', undefined), true);
+assertEq('abc'.startsWith('\0', undefined), false);
+assertEq('abc'.startsWith('a', undefined), true);
+assertEq('abc'.startsWith('b', undefined), false);
+assertEq('abc'.startsWith('ab', undefined), true);
+assertEq('abc'.startsWith('bc', undefined), false);
+assertEq('abc'.startsWith('abc', undefined), true);
+assertEq('abc'.startsWith('bcd', undefined), false);
+assertEq('abc'.startsWith('abcd', undefined), false);
+assertEq('abc'.startsWith('bcde', undefined), false);
+
+assertEq('abc'.startsWith('', null), true);
+assertEq('abc'.startsWith('\0', null), false);
+assertEq('abc'.startsWith('a', null), true);
+assertEq('abc'.startsWith('b', null), false);
+assertEq('abc'.startsWith('ab', null), true);
+assertEq('abc'.startsWith('bc', null), false);
+assertEq('abc'.startsWith('abc', null), true);
+assertEq('abc'.startsWith('bcd', null), false);
+assertEq('abc'.startsWith('abcd', null), false);
+assertEq('abc'.startsWith('bcde', null), false);
+
+assertEq('abc'.startsWith('', -Infinity), true);
+assertEq('abc'.startsWith('\0', -Infinity), false);
+assertEq('abc'.startsWith('a', -Infinity), true);
+assertEq('abc'.startsWith('b', -Infinity), false);
+assertEq('abc'.startsWith('ab', -Infinity), true);
+assertEq('abc'.startsWith('bc', -Infinity), false);
+assertEq('abc'.startsWith('abc', -Infinity), true);
+assertEq('abc'.startsWith('bcd', -Infinity), false);
+assertEq('abc'.startsWith('abcd', -Infinity), false);
+assertEq('abc'.startsWith('bcde', -Infinity), false);
+
+assertEq('abc'.startsWith('', -1), true);
+assertEq('abc'.startsWith('\0', -1), false);
+assertEq('abc'.startsWith('a', -1), true);
+assertEq('abc'.startsWith('b', -1), false);
+assertEq('abc'.startsWith('ab', -1), true);
+assertEq('abc'.startsWith('bc', -1), false);
+assertEq('abc'.startsWith('abc', -1), true);
+assertEq('abc'.startsWith('bcd', -1), false);
+assertEq('abc'.startsWith('abcd', -1), false);
+assertEq('abc'.startsWith('bcde', -1), false);
+
+assertEq('abc'.startsWith('', -0), true);
+assertEq('abc'.startsWith('\0', -0), false);
+assertEq('abc'.startsWith('a', -0), true);
+assertEq('abc'.startsWith('b', -0), false);
+assertEq('abc'.startsWith('ab', -0), true);
+assertEq('abc'.startsWith('bc', -0), false);
+assertEq('abc'.startsWith('abc', -0), true);
+assertEq('abc'.startsWith('bcd', -0), false);
+assertEq('abc'.startsWith('abcd', -0), false);
+assertEq('abc'.startsWith('bcde', -0), false);
+
+assertEq('abc'.startsWith('', +0), true);
+assertEq('abc'.startsWith('\0', +0), false);
+assertEq('abc'.startsWith('a', +0), true);
+assertEq('abc'.startsWith('b', +0), false);
+assertEq('abc'.startsWith('ab', +0), true);
+assertEq('abc'.startsWith('bc', +0), false);
+assertEq('abc'.startsWith('abc', +0), true);
+assertEq('abc'.startsWith('bcd', +0), false);
+assertEq('abc'.startsWith('abcd', +0), false);
+assertEq('abc'.startsWith('bcde', +0), false);
+
+assertEq('abc'.startsWith('', 1), true);
+assertEq('abc'.startsWith('\0', 1), false);
+assertEq('abc'.startsWith('a', 1), false);
+assertEq('abc'.startsWith('b', 1), true);
+assertEq('abc'.startsWith('ab', 1), false);
+assertEq('abc'.startsWith('bc', 1), true);
+assertEq('abc'.startsWith('abc', 1), false);
+assertEq('abc'.startsWith('bcd', 1), false);
+assertEq('abc'.startsWith('abcd', 1), false);
+assertEq('abc'.startsWith('bcde', 1), false);
+
+assertEq('abc'.startsWith('', +Infinity), true);
+assertEq('abc'.startsWith('\0', +Infinity), false);
+assertEq('abc'.startsWith('a', +Infinity), false);
+assertEq('abc'.startsWith('b', +Infinity), false);
+assertEq('abc'.startsWith('ab', +Infinity), false);
+assertEq('abc'.startsWith('bc', +Infinity), false);
+assertEq('abc'.startsWith('abc', +Infinity), false);
+assertEq('abc'.startsWith('bcd', +Infinity), false);
+assertEq('abc'.startsWith('abcd', +Infinity), false);
+assertEq('abc'.startsWith('bcde', +Infinity), false);
+
+assertEq('abc'.startsWith('', true), true);
+assertEq('abc'.startsWith('\0', true), false);
+assertEq('abc'.startsWith('a', true), false);
+assertEq('abc'.startsWith('b', true), true);
+assertEq('abc'.startsWith('ab', true), false);
+assertEq('abc'.startsWith('bc', true), true);
+assertEq('abc'.startsWith('abc', true), false);
+assertEq('abc'.startsWith('bcd', true), false);
+assertEq('abc'.startsWith('abcd', true), false);
+assertEq('abc'.startsWith('bcde', true), false);
+
+assertEq('abc'.startsWith('', 'x'), true);
+assertEq('abc'.startsWith('\0', 'x'), false);
+assertEq('abc'.startsWith('a', 'x'), true);
+assertEq('abc'.startsWith('b', 'x'), false);
+assertEq('abc'.startsWith('ab', 'x'), true);
+assertEq('abc'.startsWith('bc', 'x'), false);
+assertEq('abc'.startsWith('abc', 'x'), true);
+assertEq('abc'.startsWith('bcd', 'x'), false);
+assertEq('abc'.startsWith('abcd', 'x'), false);
+assertEq('abc'.startsWith('bcde', 'x'), false);
+
+assertEq('[a-z]+(bar)?'.startsWith('[a-z]+'), true);
+assertThrows(function() { '[a-z]+(bar)?'.startsWith(/[a-z]+/); }, TypeError);
+assertEq('[a-z]+(bar)?'.startsWith('(bar)?', 6), true);
+assertThrows(function() { '[a-z]+(bar)?'.startsWith(/(bar)?/); }, TypeError);
+assertThrows(function() { '[a-z]+/(bar)?/'.startsWith(/(bar)?/); }, TypeError);
+var global = newGlobal();
+global.eval('this.re = /(bar)?/');
+assertThrows(function() { '[a-z]+/(bar)?/'.startsWith(global.re); }, TypeError);
+
+// http://mathiasbynens.be/notes/javascript-unicode#poo-test
+var string = 'I\xF1t\xEBrn\xE2ti\xF4n\xE0liz\xE6ti\xF8n\u2603\uD83D\uDCA9';
+assertEq(string.startsWith(''), true);
+assertEq(string.startsWith('\xF1t\xEBr'), false);
+assertEq(string.startsWith('\xF1t\xEBr', 1), true);
+assertEq(string.startsWith('\xE0liz\xE6'), false);
+assertEq(string.startsWith('\xE0liz\xE6', 11), true);
+assertEq(string.startsWith('\xF8n\u2603\uD83D\uDCA9'), false);
+assertEq(string.startsWith('\xF8n\u2603\uD83D\uDCA9', 18), true);
+assertEq(string.startsWith('\u2603'), false);
+assertEq(string.startsWith('\u2603', 20), true);
+assertEq(string.startsWith('\uD83D\uDCA9'), false);
+assertEq(string.startsWith('\uD83D\uDCA9', 21), true);
+
+assertThrows(function() { String.prototype.startsWith.call(undefined); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.call(undefined, 'b'); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.call(undefined, 'b', 4); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.call(null); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.call(null, 'b'); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.call(null, 'b', 4); }, TypeError);
+assertEq(String.prototype.startsWith.call(42, '2'), false);
+assertEq(String.prototype.startsWith.call(42, '4'), true);
+assertEq(String.prototype.startsWith.call(42, 'b', 4), false);
+assertEq(String.prototype.startsWith.call(42, '2', 1), true);
+assertEq(String.prototype.startsWith.call(42, '2', 4), false);
+assertEq(String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 0), false);
+assertEq(String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 1), true);
+assertEq(String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 2), false);
+assertThrows(function() { String.prototype.startsWith.call({ 'toString': function() { throw RangeError(); } }, /./); }, RangeError);
+assertThrows(function() { String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, /./); }, TypeError);
+
+assertThrows(function() { String.prototype.startsWith.apply(undefined); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.apply(undefined, ['b']); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.apply(undefined, ['b', 4]); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.apply(null); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.apply(null, ['b']); }, TypeError);
+assertThrows(function() { String.prototype.startsWith.apply(null, ['b', 4]); }, TypeError);
+assertEq(String.prototype.startsWith.apply(42, ['2']), false);
+assertEq(String.prototype.startsWith.apply(42, ['4']), true);
+assertEq(String.prototype.startsWith.apply(42, ['b', 4]), false);
+assertEq(String.prototype.startsWith.apply(42, ['2', 1]), true);
+assertEq(String.prototype.startsWith.apply(42, ['2', 4]), false);
+assertEq(String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 0]), false);
+assertEq(String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 1]), true);
+assertEq(String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 2]), false);
+assertThrows(function() { String.prototype.startsWith.apply({ 'toString': function() { throw RangeError(); } }, [/./]); }, RangeError);
+assertThrows(function() { String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, [/./]); }, TypeError);
--- a/js/src/jit-test/tests/parallel/Array-reducePar-bail.js
+++ b/js/src/jit-test/tests/parallel/Array-reducePar-bail.js
@@ -10,17 +10,18 @@ function testReduce() {
   var aCounter = 0;
   function sum(a, b) {
     var r = a + b;
     if (r == 234) // occurs once per slice
       aCounter++;
     return r;
   }
 
-  var array = build(4096, function() { return 1; });
+  // We use a big array, to make sure that the test runs with 64 slices.
+  var array = build(8 * 4096, function() { return 1; });
   var seqResult = array.reduce(sum);
   var seqCounter = aCounter;
 
   aCounter = 0;
   var parResult = array.reducePar(sum);
   var parCounter = aCounter;
 
   assertEq(true, parCounter >= seqCounter);
--- a/js/src/jit-test/tests/parallel/bailout-executed.js
+++ b/js/src/jit-test/tests/parallel/bailout-executed.js
@@ -1,14 +1,14 @@
 load(libdir + "parallelarray-helpers.js");
 
 function makeObject(e, i, c) {
   var v = {element: e, index: i, collection: c};
 
-  if (e == 512) // note: happens once
+  if (e == 0) // note: happens once
     delete v.index;
 
   return v;
 }
 
 function test() {
   var array = range(0, 768);
   var array1 = array.map(makeObject);
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -108,18 +108,18 @@ BaselineCompiler::compile()
         return Method_Error;
 
     Linker linker(masm);
     JitCode *code = linker.newCode<CanGC>(cx, JSC::BASELINE_CODE);
     if (!code)
         return Method_Error;
 
     JSObject *templateScope = nullptr;
-    if (script->function()) {
-        RootedFunction fun(cx, script->function());
+    if (script->functionNonDelazifying()) {
+        RootedFunction fun(cx, script->functionNonDelazifying());
         if (fun->isHeavyweight()) {
             templateScope = CallObject::createTemplateObject(cx, script, gc::TenuredHeap);
             if (!templateScope)
                 return Method_Error;
 
             if (fun->isNamedLambda()) {
                 RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, gc::TenuredHeap));
                 if (!declEnvObject)
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -177,17 +177,17 @@ class BaselineFrame
     }
 
     unsigned numActualArgs() const {
         return *(size_t *)(reinterpret_cast<const uint8_t *>(this) +
                              BaselineFrame::Size() +
                              offsetOfNumActualArgs());
     }
     unsigned numFormalArgs() const {
-        return script()->function()->nargs();
+        return script()->functionNonDelazifying()->nargs();
     }
     Value &thisValue() const {
         return *(Value *)(reinterpret_cast<const uint8_t *>(this) +
                          BaselineFrame::Size() +
                          offsetOfThis());
     }
     Value *argv() const {
         return (Value *)(reinterpret_cast<const uint8_t *>(this) +
--- a/js/src/jit/BaselineFrameInfo.h
+++ b/js/src/jit/BaselineFrameInfo.h
@@ -177,17 +177,17 @@ class FrameInfo
     { }
 
     bool init(TempAllocator &alloc);
 
     uint32_t nlocals() const {
         return script->nfixed();
     }
     uint32_t nargs() const {
-        return script->function()->nargs();
+        return script->functionNonDelazifying()->nargs();
     }
 
   private:
     inline StackValue *rawPush() {
         StackValue *val = &stack[spIndex++];
         val->reset();
         return val;
     }
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -215,16 +215,18 @@ jit::EnterBaselineAtBranch(JSContext *cx
 MethodStatus
 jit::BaselineCompile(JSContext *cx, HandleScript script)
 {
     JS_ASSERT(!script->hasBaselineScript());
     JS_ASSERT(script->canBaselineCompile());
 
     LifoAlloc alloc(BASELINE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
 
+    script->ensureNonLazyCanonicalFunction(cx);
+
     TempAllocator *temp = alloc.new_<TempAllocator>(&alloc);
     if (!temp)
         return Method_Error;
 
     IonContext ictx(cx, temp);
 
     BaselineCompiler compiler(cx, *temp, script);
     if (!compiler.init())
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3396,17 +3396,18 @@ bool
 CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir)
 {
     Register obj = ToRegister(lir->output());
     JSObject *templateObj = lir->mir()->templateObj();
     CompileInfo &info = lir->mir()->block()->info();
 
     // If we have a template object, we can inline call object creation.
     OutOfLineCode *ool = oolCallVM(NewDeclEnvObjectInfo, lir,
-                                   (ArgList(), ImmGCPtr(info.fun()), Imm32(gc::DefaultHeap)),
+                                   (ArgList(), ImmGCPtr(info.funMaybeLazy()),
+                                    Imm32(gc::DefaultHeap)),
                                    StoreRegisterTo(obj));
     if (!ool)
         return false;
 
     masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap);
     masm.initGCThing(obj, templateObj);
     masm.bind(ool->rejoin());
     return true;
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -46,20 +46,22 @@ class CompileInfo
   public:
     CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
                 ExecutionMode executionMode, bool scriptNeedsArgsObj)
       : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
         executionMode_(executionMode), scriptNeedsArgsObj_(scriptNeedsArgsObj)
     {
         JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
 
-        // The function here can flow in from anywhere so look up the canonical function to ensure that
-        // we do not try to embed a nursery pointer in jit-code.
+        // The function here can flow in from anywhere so look up the canonical
+        // function to ensure that we do not try to embed a nursery pointer in
+        // jit-code. Precisely because it can flow in from anywhere, it's not
+        // guaranteed to be non-lazy. Hence, don't access its script!
         if (fun_) {
-            fun_ = fun_->nonLazyScript()->function();
+            fun_ = fun_->nonLazyScript()->functionNonDelazifying();
             JS_ASSERT(fun_->isTenured());
         }
 
         nimplicit_ = StartArgSlot(script)                   /* scope chain and argument obj */
                    + (fun ? 1 : 0);                         /* this */
         nargs_ = fun ? fun->nargs() : 0;
         nlocals_ = script->nfixed();
         nstack_ = script->nslots() - script->nfixed();
@@ -75,17 +77,17 @@ class CompileInfo
         nlocals_ = nlocals;
         nstack_ = 1;  /* For FunctionCompiler::pushPhiInput/popPhiOutput */
         nslots_ = nlocals_ + nstack_;
     }
 
     JSScript *script() const {
         return script_;
     }
-    JSFunction *fun() const {
+    JSFunction *funMaybeLazy() const {
         return fun_;
     }
     bool constructing() const {
         return constructing_;
     }
     jsbytecode *osrPc() {
         return osrPc_;
     }
@@ -169,17 +171,17 @@ class CompileInfo
         JS_ASSERT(script());
         return 1;
     }
     uint32_t argsObjSlot() const {
         JS_ASSERT(hasArguments());
         return 2;
     }
     uint32_t thisSlot() const {
-        JS_ASSERT(fun());
+        JS_ASSERT(funMaybeLazy());
         JS_ASSERT(nimplicit_ > 0);
         return nimplicit_ - 1;
     }
     uint32_t firstArgSlot() const {
         return nimplicit_;
     }
     uint32_t argSlotUnchecked(uint32_t i) const {
         // During initialization, some routines need to get at arg
@@ -208,26 +210,26 @@ class CompileInfo
     }
 
     uint32_t startArgSlot() const {
         JS_ASSERT(script());
         return StartArgSlot(script());
     }
     uint32_t endArgSlot() const {
         JS_ASSERT(script());
-        return CountArgSlots(script(), fun());
+        return CountArgSlots(script(), funMaybeLazy());
     }
 
     uint32_t totalSlots() const {
-        JS_ASSERT(script() && fun());
+        JS_ASSERT(script() && funMaybeLazy());
         return nimplicit() + nargs() + nlocals();
     }
 
     bool isSlotAliased(uint32_t index) const {
-        if (fun() && index == thisSlot())
+        if (funMaybeLazy() && index == thisSlot())
             return false;
 
         uint32_t arg = index - firstArgSlot();
         if (arg < nargs()) {
             if (script()->formalIsAliased(arg))
                 return true;
             return false;
         }
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1617,17 +1617,19 @@ TrackAllProperties(JSContext *cx, JSObje
 
 static void
 TrackPropertiesForSingletonScopes(JSContext *cx, JSScript *script, BaselineFrame *baselineFrame)
 {
     // Ensure that all properties of singleton call objects which the script
     // could access are tracked. These are generally accessed through
     // ALIASEDVAR operations in baseline and will not be tracked even if they
     // have been accessed in baseline code.
-    JSObject *environment = script->function() ? script->function()->environment() : nullptr;
+    JSObject *environment = script->functionNonDelazifying()
+                            ? script->functionNonDelazifying()->environment()
+                            : nullptr;
 
     while (environment && !environment->is<GlobalObject>()) {
         if (environment->is<CallObject>() && environment->hasSingletonType())
             TrackAllProperties(cx, environment);
         environment = environment->enclosingScope();
     }
 
     if (baselineFrame) {
@@ -1646,16 +1648,20 @@ IonCompile(JSContext *cx, JSScript *scri
 #if JS_TRACE_LOGGING
     AutoTraceLog logger(TraceLogging::defaultLogger(),
                         TraceLogging::ION_COMPILE_START,
                         TraceLogging::ION_COMPILE_STOP,
                         script);
 #endif
     JS_ASSERT(optimizationLevel > Optimization_DontCompile);
 
+    // Make sure the script's canonical function isn't lazy. We can't de-lazify
+    // it in a worker thread.
+    script->ensureNonLazyCanonicalFunction(cx);
+
     TrackPropertiesForSingletonScopes(cx, script, baselineFrame);
 
     LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     if (!alloc)
         return AbortReason_Alloc;
 
     ScopedJSDeletePtr<LifoAlloc> autoDelete(alloc);
 
@@ -1672,18 +1678,19 @@ IonCompile(JSContext *cx, JSScript *scri
 
     if (!cx->compartment()->jitCompartment()->ensureIonStubsExist(cx))
         return AbortReason_Alloc;
 
     MIRGraph *graph = alloc->new_<MIRGraph>(temp);
     if (!graph)
         return AbortReason_Alloc;
 
-    CompileInfo *info = alloc->new_<CompileInfo>(script, script->function(), osrPc, constructing,
-                                                 executionMode, script->needsArgsObj());
+    CompileInfo *info = alloc->new_<CompileInfo>(script, script->functionNonDelazifying(), osrPc,
+                                                 constructing, executionMode,
+                                                 script->needsArgsObj());
     if (!info)
         return AbortReason_Alloc;
 
     BaselineInspector *inspector = alloc->new_<BaselineInspector>(script);
     if (!inspector)
         return AbortReason_Alloc;
 
     BaselineFrameInspector *baselineFrameInspector = nullptr;
@@ -2213,17 +2220,17 @@ jit::CanEnterUsingFastInvoke(JSContext *
     JS_ASSERT(jit::IsIonEnabled(cx));
 
     // Skip if the code is expected to result in a bailout.
     if (!script->hasIonScript() || script->ionScript()->bailoutExpected())
         return Method_Skipped;
 
     // Don't handle arguments underflow, to make this work we would have to pad
     // missing arguments with |undefined|.
-    if (numActualArgs < script->function()->nargs())
+    if (numActualArgs < script->functionNonDelazifying()->nargs())
         return Method_Skipped;
 
     if (!cx->compartment()->ensureJitCompartmentExists(cx))
         return Method_Error;
 
     // This can GC, so afterward, script->ion is not guaranteed to be valid.
     if (!cx->runtime()->jitRuntime()->enterIon())
         return Method_Error;
@@ -2274,17 +2281,17 @@ EnterIon(JSContext *cx, EnterJitData &da
 
 bool
 jit::SetEnterJitData(JSContext *cx, EnterJitData &data, RunState &state, AutoValueVector &vals)
 {
     data.osrFrame = nullptr;
 
     if (state.isInvoke()) {
         CallArgs &args = state.asInvoke()->args();
-        unsigned numFormals = state.script()->function()->nargs();
+        unsigned numFormals = state.script()->functionNonDelazifying()->nargs();
         data.constructing = state.asInvoke()->constructing();
         data.numActualArgs = args.length();
         data.maxArgc = Max(args.length(), numFormals) + 1;
         data.scopeChain = nullptr;
         data.calleeToken = CalleeToToken(&args.callee().as<JSFunction>());
 
         if (data.numActualArgs >= numFormals) {
             data.maxArgv = args.base() + 1;
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -211,17 +211,17 @@ IsPhiObservable(MPhi *phi, Observability
                 !iter->consumer()->toDefinition()->isPhi())
                 return true;
         }
         break;
     }
 
     uint32_t slot = phi->slot();
     CompileInfo &info = phi->block()->info();
-    JSFunction *fun = info.fun();
+    JSFunction *fun = info.funMaybeLazy();
 
     // If the Phi is of the |this| value, it must always be observable.
     if (fun && slot == info.thisSlot())
         return true;
 
     // If the function may need an arguments object, then make sure to preserve
     // the scope chain, because it may be needed to construct the arguments
     // object during bailout.
@@ -2138,21 +2138,20 @@ jit::AnalyzeNewScriptProperties(JSContex
                                 Vector<types::TypeNewScript::Initializer> *initializerList)
 {
     JS_ASSERT(cx->compartment()->activeAnalysis);
 
     // When invoking 'new' on the specified script, try to find some properties
     // which will definitely be added to the created object before it has a
     // chance to escape and be accessed elsewhere.
 
-    if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
+    RootedScript script(cx, fun->getOrCreateScript(cx));
+    if (!script)
         return false;
 
-    RootedScript script(cx, fun->nonLazyScript());
-
     if (!script->compileAndGo() || !script->canBaselineCompile())
         return true;
 
     Vector<PropertyName *> accessedProperties(cx);
 
     LifoAlloc alloc(types::TypeZone::TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
 
     TempAllocator temp(&alloc);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -70,17 +70,17 @@ jit::NewBaselineFrameInspector(TempAlloc
 
     inspector->thisType = types::GetValueType(frame->thisValue());
 
     if (frame->scopeChain()->hasSingletonType())
         inspector->singletonScopeChain = frame->scopeChain();
 
     JSScript *script = frame->script();
 
-    if (script->function()) {
+    if (script->functionNonDelazifying()) {
         if (!inspector->argTypes.reserve(frame->numFormalArgs()))
             return nullptr;
         for (size_t i = 0; i < frame->numFormalArgs(); i++) {
             if (script->formalIsAliased(i))
                 inspector->argTypes.infallibleAppend(types::Type::UndefinedType());
             else if (!script->argsObjAliasesFormals())
                 inspector->argTypes.infallibleAppend(types::GetValueType(frame->unaliasedFormal(i)));
             else if (frame->hasArgsObj())
@@ -344,20 +344,20 @@ IonBuilder::canInlineTarget(JSFunction *
         return InliningDecision_DontInline;
 
     if (!target->isInterpreted())
         return DontInline(nullptr, "Non-interpreted target");
 
     // Allow constructing lazy scripts when performing the definite properties
     // analysis, as baseline has not been used to warm the caller up yet.
     if (target->isInterpreted() && info().executionMode() == DefinitePropertiesAnalysis) {
-        if (!target->getOrCreateScript(analysisContext))
+        RootedScript script(analysisContext, target->getOrCreateScript(analysisContext));
+        if (!script)
             return InliningDecision_Error;
 
-        RootedScript script(analysisContext, target->nonLazyScript());
         if (!script->hasBaselineScript() && script->canBaselineCompile()) {
             MethodStatus status = BaselineCompile(analysisContext, script);
             if (status == Method_Error)
                 return InliningDecision_Error;
             if (status != Method_Compiled)
                 return InliningDecision_DontInline;
         }
     }
@@ -682,17 +682,17 @@ IonBuilder::build()
     // It's safe to start emitting actual IR, so now build the scope chain.
     if (!initScopeChain())
         return false;
 
     if (info().needsArgsObj() && !initArgumentsObject())
         return false;
 
     // Prevent |this| from being DCE'd: necessary for constructors.
-    if (info().fun())
+    if (info().funMaybeLazy())
         current->getSlot(info().thisSlot())->setGuard();
 
     // The type analysis phase attempts to insert unbox operations near
     // definitions of values. It also attempts to replace uses in resume points
     // with the narrower, unboxed variants. However, we must prevent this
     // replacement from happening on values in the entry snapshot. Otherwise we
     // could get this:
     //
@@ -914,29 +914,29 @@ IonBuilder::rewriteParameter(uint32_t sl
 // Apply Type Inference information to parameters early on, unboxing them if
 // they have a definitive type. The actual guards will be emitted by the code
 // generator, explicitly, as part of the function prologue.
 void
 IonBuilder::rewriteParameters()
 {
     JS_ASSERT(info().scopeChainSlot() == 0);
 
-    if (!info().fun())
+    if (!info().funMaybeLazy())
         return;
 
     for (uint32_t i = info().startArgSlot(); i < info().endArgSlot(); i++) {
         MDefinition *param = current->getSlot(i);
         rewriteParameter(i, param, param->toParameter()->index());
     }
 }
 
 bool
 IonBuilder::initParameters()
 {
-    if (!info().fun())
+    if (!info().funMaybeLazy())
         return true;
 
     // If we are doing OSR on a frame which initially executed in the
     // interpreter and didn't accumulate type information, try to use that OSR
     // frame to determine possible initial types for 'this' and parameters.
 
     // For unknownProperties() tests under addType.
     lock();
@@ -985,17 +985,17 @@ IonBuilder::initScopeChain(MDefinition *
     // will try to access the scope. For other scripts, the scope instructions
     // will be held live by resume points and code will still be generated for
     // them, so just use a constant undefined value.
     if (!script()->compileAndGo())
         return abort("non-CNG global scripts are not supported");
 
     lock();
 
-    if (JSFunction *fun = info().fun()) {
+    if (JSFunction *fun = info().funMaybeLazy()) {
         if (!callee) {
             MCallee *calleeIns = MCallee::New(alloc());
             current->add(calleeIns);
             callee = calleeIns;
         }
         scope = MFunctionEnvironment::New(alloc(), callee);
         current->add(scope);
 
@@ -3825,17 +3825,17 @@ class AutoAccumulateReturns
     ~AutoAccumulateReturns() {
         graph_.setReturnAccumulator(prev_);
     }
 };
 
 bool
 IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
 {
-    JS_ASSERT(target->isInterpreted());
+    JS_ASSERT(target->hasScript());
     JS_ASSERT(IsIonInlinablePC(pc));
 
     callInfo.setImplicitlyUsedUnchecked();
 
     // Ensure sufficient space in the slots: needed for inlining from FUNAPPLY.
     uint32_t depth = current->stackDepth() + callInfo.numFormals();
     if (depth > current->nslots()) {
         if (!current->increaseSlots(depth - current->nslots()))
@@ -5293,17 +5293,17 @@ IonBuilder::jsop_eval(uint32_t argc)
     JSFunction *singleton = getSingleCallTarget(calleeTypes);
     if (!singleton)
         return abort("No singleton callee for eval()");
 
     if (script()->global().valueIsEval(ObjectValue(*singleton))) {
         if (argc != 1)
             return abort("Direct eval with more than one argument");
 
-        if (!info().fun())
+        if (!info().funMaybeLazy())
             return abort("Direct eval in global code");
 
         // The 'this' value for the outer and eval scripts must be the
         // same. This is not guaranteed if a primitive string/number/etc.
         // is passed through to the eval invoke as the primitive may be
         // boxed into different objects if accessed via 'this'.
         JSValueType type = thisTypes->getKnownTypeTag();
         if (type != JSVAL_TYPE_OBJECT && type != JSVAL_TYPE_NULL && type != JSVAL_TYPE_UNDEFINED)
@@ -5715,17 +5715,17 @@ IonBuilder::newOsrPreheader(MBasicBlock 
         if (needsArgsObj)
             argsObj = MOsrArgumentsObject::New(alloc(), entry);
         else
             argsObj = MConstant::New(alloc(), UndefinedValue());
         osrBlock->add(argsObj);
         osrBlock->initSlot(info().argsObjSlot(), argsObj);
     }
 
-    if (info().fun()) {
+    if (info().funMaybeLazy()) {
         // Initialize |this| parameter.
         MParameter *thisv = MParameter::New(alloc(), MParameter::THIS_SLOT, nullptr);
         osrBlock->add(thisv);
         osrBlock->initSlot(info().thisSlot(), thisv);
 
         // Initialize arguments.
         for (uint32_t i = 0; i < info().nargs(); i++) {
             uint32_t slot = needsArgsObj ? info().argSlotUnchecked(i) : info().argSlot(i);
@@ -5820,17 +5820,17 @@ IonBuilder::newOsrPreheader(MBasicBlock 
 
     // Finish the osrBlock.
     osrBlock->end(MGoto::New(alloc(), preheader));
     preheader->addPredecessor(alloc(), osrBlock);
     graph().setOsrBlock(osrBlock);
 
     // Wrap |this| with a guaranteed use, to prevent instruction elimination.
     // Prevent |this| from being DCE'd: necessary for constructors.
-    if (info().fun())
+    if (info().funMaybeLazy())
         preheader->getSlot(info().thisSlot())->setGuard();
 
     return preheader;
 }
 
 MBasicBlock *
 IonBuilder::newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool osr)
 {
@@ -5860,17 +5860,17 @@ IonBuilder::newPendingLoopHeader(MBasicB
                 continue;
 
             MPhi *phi = block->getSlot(i)->toPhi();
 
             // Get the type from the baseline frame.
             types::Type existingType = types::Type::UndefinedType();
             uint32_t arg = i - info().firstArgSlot();
             uint32_t var = i - info().firstLocalSlot();
-            if (info().fun() && i == info().thisSlot())
+            if (info().funMaybeLazy() && i == info().thisSlot())
                 existingType = baselineFrame_->thisType;
             else if (arg < info().nargs())
                 existingType = baselineFrame_->argTypes[arg];
             else
                 existingType = baselineFrame_->varTypes[var];
 
             // Extract typeset from value.
             types::TemporaryTypeSet *typeSet =
@@ -9235,20 +9235,20 @@ IonBuilder::jsop_deffun(uint32_t index)
     current->add(deffun);
 
     return resumeAfter(deffun);
 }
 
 bool
 IonBuilder::jsop_this()
 {
-    if (!info().fun())
+    if (!info().funMaybeLazy())
         return abort("JSOP_THIS outside of a JSFunction.");
 
-    if (script()->strict() || info().fun()->isSelfHostedBuiltin()) {
+    if (script()->strict() || info().funMaybeLazy()->isSelfHostedBuiltin()) {
         // No need to wrap primitive |this| in strict mode or self-hosted code.
         current->pushSlot(info().thisSlot());
         return true;
     }
 
     if (thisTypes->getKnownTypeTag() == JSVAL_TYPE_OBJECT ||
         (thisTypes->empty() && baselineFrame_ && baselineFrame_->thisType.isSomeObject()))
     {
@@ -9394,33 +9394,34 @@ IonBuilder::walkScopeChain(unsigned hops
 
 bool
 IonBuilder::hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall)
 {
     JSScript *outerScript = ScopeCoordinateFunctionScript(script(), pc);
     if (!outerScript || !outerScript->treatAsRunOnce())
         return false;
 
-    types::TypeObjectKey *funType = types::TypeObjectKey::get(outerScript->function());
+    types::TypeObjectKey *funType =
+            types::TypeObjectKey::get(outerScript->functionNonDelazifying());
     if (funType->hasFlags(constraints(), types::OBJECT_FLAG_RUNONCE_INVALIDATED))
         return false;
 
     // The script this aliased var operation is accessing will run only once,
     // so there will be only one call object and the aliased var access can be
     // compiled in the same manner as a global access. We still need to find
     // the call object though.
 
     // Look for the call object on the current script's function's scope chain.
     // If the current script is inner to the outer script and the function has
     // singleton type then it should show up here.
 
     MDefinition *scope = current->getSlot(info().scopeChainSlot());
     scope->setImplicitlyUsedUnchecked();
 
-    JSObject *environment = script()->function()->environment();
+    JSObject *environment = script()->functionNonDelazifying()->environment();
     while (environment && !environment->is<GlobalObject>()) {
         if (environment->is<CallObject>() &&
             !environment->as<CallObject>().isForEval() &&
             environment->as<CallObject>().callee().nonLazyScript() == outerScript)
         {
             JS_ASSERT(environment->hasSingletonType());
             *pcall = environment;
             return true;
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -614,17 +614,17 @@ HandleException(ResumeFromException *rfe
                 bool popSPSFrame = cx->runtime()->spsProfiler.enabled();
                 if (invalidated)
                     popSPSFrame = ionScript->hasSPSInstrumentation();
 
                 // When profiling, each frame popped needs a notification that
                 // the function has exited, so invoke the probe that a function
                 // is exiting.
                 JSScript *script = frames.script();
-                probes::ExitScript(cx, script, script->function(), popSPSFrame);
+                probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
                 if (!frames.more())
                     break;
                 ++frames;
             }
 
             if (invalidated)
                 ionScript->decref(cx->runtime()->defaultFreeOp());
 
@@ -633,17 +633,17 @@ HandleException(ResumeFromException *rfe
             bool calledDebugEpilogue = false;
 
             HandleExceptionBaseline(cx, iter, rfe, &calledDebugEpilogue);
             if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME)
                 return;
 
             // Unwind profiler pseudo-stack
             JSScript *script = iter.script();
-            probes::ExitScript(cx, script, script->function(),
+            probes::ExitScript(cx, script, script->functionNonDelazifying(),
                                iter.baselineFrame()->hasPushedSPSFrame());
             // After this point, any pushed SPS frame would have been popped if it needed
             // to be.  Unset the flag here so that if we call DebugEpilogue below,
             // it doesn't try to pop the SPS frame again.
             iter.baselineFrame()->unsetPushedSPSFrame();
  
             if (cx->compartment()->debugMode() && !calledDebugEpilogue) {
                 // If DebugEpilogue returns |true|, we have to perform a forced
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -511,23 +511,23 @@ JSObject *
 NewStringObject(JSContext *cx, HandleString str)
 {
     return StringObject::create(cx, str);
 }
 
 bool
 SPSEnter(JSContext *cx, HandleScript script)
 {
-    return cx->runtime()->spsProfiler.enter(cx, script, script->function());
+    return cx->runtime()->spsProfiler.enter(cx, script, script->functionNonDelazifying());
 }
 
 bool
 SPSExit(JSContext *cx, HandleScript script)
 {
-    cx->runtime()->spsProfiler.exit(cx, script, script->function());
+    cx->runtime()->spsProfiler.exit(cx, script, script->functionNonDelazifying());
     return true;
 }
 
 bool
 OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, bool *out)
 {
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, key, &id))
--- a/js/src/jit/shared/BaselineCompiler-shared.h
+++ b/js/src/jit/shared/BaselineCompiler-shared.h
@@ -91,17 +91,19 @@ class BaselineCompilerShared
         JS_ASSERT(!icEntries_.empty());
         ICLoadLabel loadLabel;
         loadLabel.label = label;
         loadLabel.icEntry = icEntries_.length() - 1;
         return icLoadLabels_.append(loadLabel);
     }
 
     JSFunction *function() const {
-        return script->function();
+        // Not delazifying here is ok as the function is guaranteed to have
+        // been delazified before compilation started.
+        return script->functionNonDelazifying();
     }
 
     PCMappingSlotInfo getStackTopSlotInfo() {
         JS_ASSERT(frame.numUnsyncedSlots() <= 2);
         switch (frame.numUnsyncedSlots()) {
           case 0:
             return PCMappingSlotInfo::MakeSlotInfo();
           case 1:
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -256,17 +256,17 @@ CodeGeneratorShared::encode(LSnapshot *s
 
     uint32_t startIndex = 0;
     for (MResumePoint **it = mirOperandIter.begin(), **end = mirOperandIter.end();
          it != end;
          ++it)
     {
         MResumePoint *mir = *it;
         MBasicBlock *block = mir->block();
-        JSFunction *fun = block->info().fun();
+        JSFunction *fun = block->info().funMaybeLazy();
         JSScript *script = block->info().script();
         jsbytecode *pc = mir->pc();
         uint32_t exprStack = mir->stackDepth() - block->info().ninvoke();
         snapshots_.startFrame(fun, script, pc, exprStack);
 
         // Ensure that all snapshot which are encoded can safely be used for
         // bailouts.
         DebugOnly<jsbytecode *> bailPC = pc;
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -350,17 +350,17 @@ MSG_DEF(JSMSG_NO_REST_NAME,           29
 MSG_DEF(JSMSG_ARGUMENTS_AND_REST,     297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter")
 MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used")
 MSG_DEF(JSMSG_REST_WITH_DEFAULT,      299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
 MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
 MSG_DEF(JSMSG_YIELD_IN_DEFAULT,       301, 0, JSEXN_SYNTAXERR, "yield in default expression")
 MSG_DEF(JSMSG_INTRINSIC_NOT_DEFINED,  302, 1, JSEXN_REFERENCEERR, "no intrinsic function {0}")
 MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 303, 2, JSEXN_ERR,      "{0} is being assigned a {1}, but already has one")
 MSG_DEF(JSMSG_PAR_ARRAY_BAD_ARG,      304, 0, JSEXN_RANGEERR, "invalid parallel method argument")
-MSG_DEF(JSMSG_UNUSED305,              305, 0, JSEXN_NONE, "")
+MSG_DEF(JSMSG_REGEXP_RUNTIME_ERROR,   305, 0, JSEXN_INTERNALERR, "an error occurred while executing regular expression")
 MSG_DEF(JSMSG_UNUSED306,              306, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_UNUSED307,              307, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_CONFLICT, 308, 0, JSEXN_ERR, "no conflict resolution function provided")
 MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BOUNDS, 309, 0, JSEXN_ERR, "index in scatter vector out of bounds")
 MSG_DEF(JSMSG_CANT_REPORT_NC_AS_NE,   310, 0, JSEXN_TYPEERR, "proxy can't report a non-configurable own property as non-existent")
 MSG_DEF(JSMSG_CANT_REPORT_E_AS_NE,    311, 0, JSEXN_TYPEERR, "proxy can't report an existing own property as non-existent on a non-extensible object")
 MSG_DEF(JSMSG_CANT_REPORT_NEW,        312, 0, JSEXN_TYPEERR, "proxy can't report a new property on a non-extensible object")
 MSG_DEF(JSMSG_CANT_REPORT_INVALID,    313, 0, JSEXN_TYPEERR, "proxy can't report an incompatible property descriptor")
@@ -429,8 +429,9 @@ MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM,   
 MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED,  375, 0, JSEXN_SYNTAXERR, "modules are not implemented yet")
 MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL, 376, 0, JSEXN_SYNTAXERR, "export declarations may only appear at top level")
 MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, 377, 0, JSEXN_SYNTAXERR, "missing '}' after export specifier list")
 MSG_DEF(JSMSG_NO_EXPORT_NAME,           378, 0, JSEXN_SYNTAXERR, "missing export name")
 MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT, 379, 0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword")
 MSG_DEF(JSMSG_INVALID_PROTOTYPE,        380, 0, JSEXN_TYPEERR, "prototype field is not an object")
 MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 381, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type")
 MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL,      382, 0, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed")
+MSG_DEF(JSMSG_INVALID_ARG_TYPE,         383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -220,17 +220,18 @@ FollowBranch(JSContext *cx, JSScript *sc
 /* Common representation of slots throughout analyses and the compiler. */
 static inline uint32_t ThisSlot() {
     return 0;
 }
 static inline uint32_t ArgSlot(uint32_t arg) {
     return 1 + arg;
 }
 static inline uint32_t LocalSlot(JSScript *script, uint32_t local) {
-    return 1 + (script->function() ? script->function()->nargs() : 0) + local;
+    return 1 + local +
+           (script->functionNonDelazifying() ? script->functionNonDelazifying()->nargs() : 0);
 }
 static inline uint32_t TotalSlots(JSScript *script) {
     return LocalSlot(script, 0) + script->nfixed();
 }
 
 static inline uint32_t StackSlot(JSScript *script, uint32_t index) {
     return TotalSlots(script) + index;
 }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3979,26 +3979,26 @@ JS_CloneFunctionObject(JSContext *cx, JS
         parent = cx->global();
 
     if (!funobj->is<JSFunction>()) {
         AutoCompartment ac(cx, funobj);
         ReportIsNotFunction(cx, ObjectValue(*funobj));
         return nullptr;
     }
 
-    /*
-     * If a function was compiled to be lexically nested inside some other
-     * script, we cannot clone it without breaking the compiler's assumptions.
-     */
     RootedFunction fun(cx, &funobj->as<JSFunction>());
     if (fun->isInterpretedLazy()) {
         AutoCompartment ac(cx, funobj);
         if (!fun->getOrCreateScript(cx))
             return nullptr;
     }
+    /*
+     * If a function was compiled to be lexically nested inside some other
+     * script, we cannot clone it without breaking the compiler's assumptions.
+     */
     if (fun->isInterpreted() && (fun->nonLazyScript()->enclosingStaticScope() ||
         (fun->nonLazyScript()->compileAndGo() && !parent->is<GlobalObject>())))
     {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
         return nullptr;
     }
 
     if (fun->isBoundFunction()) {
@@ -4686,17 +4686,18 @@ JS_CompileFunction(JSContext *cx, JS::Ha
 JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JSScript *scriptArg, const char *name, unsigned indent)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     RootedScript script(cx, scriptArg);
-    RootedFunction fun(cx, script->function());
+    script->ensureNonLazyCanonicalFunction(cx);
+    RootedFunction fun(cx, script->functionNonDelazifying());
     if (fun)
         return JS_DecompileFunction(cx, fun, indent);
     bool haveSource = script->scriptSource()->hasSourceData();
     if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
         return nullptr;
     return haveSource ? script->sourceData(cx) : js_NewStringCopyZ<CanGC>(cx, "[no source]");
 }
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -38,16 +38,17 @@ using namespace js::gc;
 using mozilla::DebugOnly;
 
 JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
   : options_(options),
     zone_(zone),
     runtime_(zone->runtimeFromMainThread()),
     principals(nullptr),
     isSystem(false),
+    isSelfHosting(false),
     marked(true),
 #ifdef DEBUG
     firedOnNewGlobalObject(false),
 #endif
     global_(nullptr),
     enterCompartmentDepth(0),
     data(nullptr),
     objectMetadataCallback(nullptr),
@@ -719,17 +720,17 @@ CreateLazyScriptsForCompartment(JSContex
     AutoObjectVector lazyFunctions(cx);
 
     // Find all live lazy scripts in the compartment, and via them all root
     // lazy functions in the compartment: those which have not been compiled
     // and which have a source object, indicating that their parent has been
     // compiled.
     for (gc::CellIter i(cx->zone(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) {
         LazyScript *lazy = i.get<LazyScript>();
-        JSFunction *fun = lazy->function();
+        JSFunction *fun = lazy->functionNonDelazifying();
         if (fun->compartment() == cx->compartment() &&
             lazy->sourceObject() && !lazy->maybeScript())
         {
             MOZ_ASSERT(fun->isInterpretedLazy());
             MOZ_ASSERT(lazy == fun->lazyScriptOrNull());
             if (!lazyFunctions.append(fun))
                 return false;
         }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -122,16 +122,17 @@ struct JSCompartment
 
   private:
     JS::Zone                     *zone_;
     JSRuntime                    *runtime_;
 
   public:
     JSPrincipals                 *principals;
     bool                         isSystem;
+    bool                         isSelfHosting;
     bool                         marked;
 
 #ifdef DEBUG
     bool                         firedOnNewGlobalObject;
 #endif
 
     void mark() { marked = true; }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -450,17 +450,19 @@ js::CloneFunctionAndScript(JSContext *cx
     }
     RootedFunction clone(cx, NewFunctionWithProto(cx, NullPtr(), nullptr, 0,
                                                   JSFunction::INTERPRETED, NullPtr(), NullPtr(),
                                                   cloneProto, JSFunction::FinalizeKind,
                                                   TenuredObject));
     if (!clone)
         return nullptr;
 
-    RootedScript srcScript(cx, srcFun->nonLazyScript());
+    RootedScript srcScript(cx, srcFun->getOrCreateScript(cx));
+    if (!srcScript)
+        return nullptr;
     RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript));
     if (!clonedScript)
         return nullptr;
 
     clone->setArgCount(srcFun->nargs());
     clone->setFlags(srcFun->flags());
     clone->initAtom(srcFun->displayAtom());
     clone->initScript(clonedScript);
@@ -517,21 +519,40 @@ JSFunction::trace(JSTracer *trc)
     }
 
     if (atom_)
         MarkString(trc, &atom_, "atom");
 
     if (isInterpreted()) {
         // Functions can be be marked as interpreted despite having no script
         // yet at some points when parsing, and can be lazy with no lazy script
-        // for self hosted code.
-        if (hasScript() && u.i.s.script_)
-            MarkScriptUnbarriered(trc, &u.i.s.script_, "script");
-        else if (isInterpretedLazy() && u.i.s.lazy_)
+        // for self-hosted code.
+        if (hasScript() && u.i.s.script_) {
+            // Functions can be relazified under the following conditions:
+            // - their compartment isn't currently executing scripts or being
+            //   debugged
+            // - they are not in the self-hosting compartment
+            // - they aren't generators
+            // - they don't have JIT code attached
+            // - they don't have child functions
+            // - they have information for un-lazifying them again later
+            // This information can either be a LazyScript, or the name of a
+            // self-hosted function which can be cloned over again. The latter
+            // is stored in the first extended slot.
+            if (IS_GC_MARKING_TRACER(trc) && !compartment()->hasBeenEntered() &&
+                !compartment()->debugMode() && !compartment()->isSelfHosting &&
+                u.i.s.script_->isRelazifiable() && (!isSelfHostedBuiltin() || isExtended()))
+            {
+                relazify(trc);
+            } else {
+                MarkScriptUnbarriered(trc, &u.i.s.script_, "script");
+            }
+        } else if (isInterpretedLazy() && u.i.s.lazy_) {
             MarkLazyScriptUnbarriered(trc, &u.i.s.lazy_, "lazyScript");
+        }
         if (u.i.env_)
             MarkObjectUnbarriered(trc, &u.i.env_, "fun_callscope");
     }
 }
 
 static void
 fun_trace(JSTracer *trc, JSObject *obj)
 {
@@ -1121,21 +1142,28 @@ JSFunction::createScriptForLazilyInterpr
         // THING_ROOT_LAZY_SCRIPT).
         AutoSuppressGC suppressGC(cx);
 
         RootedScript script(cx, lazy->maybeScript());
 
         if (script) {
             AutoLockForCompilation lock(cx);
             fun->setUnlazifiedScript(script);
+            // Remember the lazy script on the compiled script, so it can be
+            // stored on the function again in case of re-lazification.
+            // Only functions without inner functions are re-lazified.
+            if (!lazy->numInnerFunctions())
+                script->setLazyScript(lazy);
             return true;
         }
 
-        if (fun != lazy->function()) {
-            script = lazy->function()->getOrCreateScript(cx);
+        if (fun != lazy->functionNonDelazifying()) {
+            if (!lazy->functionDelazifying(cx))
+                return false;
+            script = lazy->functionNonDelazifying()->nonLazyScript();
             if (!script)
                 return false;
 
             AutoLockForCompilation lock(cx);
             fun->setUnlazifiedScript(script);
             return true;
         }
 
@@ -1155,27 +1183,28 @@ JSFunction::createScriptForLazilyInterpr
         if (script) {
             RootedObject enclosingScope(cx, lazy->enclosingScope());
             RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, fun, script));
             if (!clonedScript)
                 return false;
 
             clonedScript->setSourceObject(lazy->sourceObject());
 
-            fun->initAtom(script->function()->displayAtom());
+            fun->initAtom(script->functionNonDelazifying()->displayAtom());
             clonedScript->setFunction(fun);
 
             {
                 AutoLockForCompilation lock(cx);
                 fun->setUnlazifiedScript(clonedScript);
             }
 
             CallNewScriptHook(cx, clonedScript, fun);
 
-            lazy->initScript(clonedScript);
+            if (!lazy->maybeScript())
+                lazy->initScript(clonedScript);
             return true;
         }
 
         JS_ASSERT(lazy->source()->hasSourceData());
 
         // Parse and compile the script from source.
         SourceDataCache::AutoSuppressPurge asp(cx);
         const jschar *chars = lazy->source()->chars(cx, asp);
@@ -1185,41 +1214,87 @@ JSFunction::createScriptForLazilyInterpr
         const jschar *lazyStart = chars + lazy->begin();
         size_t lazyLength = lazy->end() - lazy->begin();
 
         if (!frontend::CompileLazyFunction(cx, lazy, lazyStart, lazyLength))
             return false;
 
         script = fun->nonLazyScript();
 
+        // Remember the compiled script on the lazy script itself, in case
+        // there are clones of the function still pointing to the lazy script.
+        if (!lazy->maybeScript())
+            lazy->initScript(script);
+
         // Try to insert the newly compiled script into the lazy script cache.
         if (!lazy->numInnerFunctions()) {
             // A script's starting column isn't set by the bytecode emitter, so
             // specify this from the lazy script so that if an identical lazy
             // script is encountered later a match can be determined.
             script->setColumn(lazy->column());
 
             LazyScriptCache::Lookup lookup(cx, lazy);
             cx->runtime()->lazyScriptCache.insert(lookup, script);
+
+            // Remember the lazy script on the compiled script, so it can be
+            // stored on the function again in case of re-lazification.
+            // Only functions without inner functions are re-lazified.
+            script->setLazyScript(lazy);
         }
-
-        // Remember the compiled script on the lazy script itself, in case
-        // there are clones of the function still pointing to the lazy script.
-        lazy->initScript(script);
         return true;
     }
 
-    /* Lazily cloned self hosted script. */
+    /* Lazily cloned self-hosted script. */
+    JS_ASSERT(fun->isSelfHostedBuiltin());
     RootedAtom funAtom(cx, &fun->getExtendedSlot(0).toString()->asAtom());
     if (!funAtom)
         return false;
     Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
     return cx->runtime()->cloneSelfHostedFunctionScript(cx, funName, fun);
 }
 
+void
+JSFunction::relazify(JSTracer *trc)
+{
+    JSScript *script = nonLazyScript();
+    JS_ASSERT(script->isRelazifiable());
+    JS_ASSERT(!compartment()->hasBeenEntered());
+    JS_ASSERT(!compartment()->debugMode());
+
+    // If the script's canonical function isn't lazy, we have to mark the
+    // script. Otherwise, the following scenario would leave it unmarked
+    // and cause it to be swept while a function is still expecting it to be
+    // valid:
+    // 1. an incremental GC slice causes the canonical function to relazify
+    // 2. a clone is used and delazifies the canonical function
+    // 3. another GC slice causes the clone to relazify
+    // The result is that no function marks the script, but the canonical
+    // function expects it to be valid.
+    if (script->functionNonDelazifying()->hasScript())
+        MarkScriptUnbarriered(trc, &u.i.s.script_, "script");
+
+    flags_ &= ~INTERPRETED;
+    flags_ |= INTERPRETED_LAZY;
+    LazyScript *lazy = script->maybeLazyScript();
+    u.i.s.lazy_ = lazy;
+    if (lazy) {
+        JS_ASSERT(!isSelfHostedBuiltin());
+        // If this is the script stored in the lazy script to be cloned
+        // for un-lazifying other functions, reset it so the script can
+        // be freed.
+        if (lazy->maybeScript() == script)
+            lazy->resetScript();
+        MarkLazyScriptUnbarriered(trc, &u.i.s.lazy_, "lazyScript");
+    } else {
+        JS_ASSERT(isSelfHostedBuiltin());
+        JS_ASSERT(isExtended());
+        JS_ASSERT(getExtendedSlot(0).toString()->isAtom());
+    }
+}
+
 /* ES5 15.3.4.5.1 and 15.3.4.5.2. */
 bool
 js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedFunction fun(cx, &args.callee().as<JSFunction>());
     JS_ASSERT(fun->isBoundFunction());
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -274,16 +274,17 @@ class JSFunction : public JSObject
     }
 
     static inline size_t offsetOfNargs() { return offsetof(JSFunction, nargs_); }
     static inline size_t offsetOfFlags() { return offsetof(JSFunction, flags_); }
     static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); }
     static inline size_t offsetOfAtom() { return offsetof(JSFunction, atom_); }
 
     static bool createScriptForLazilyInterpretedFunction(JSContext *cx, js::HandleFunction fun);
+    void relazify(JSTracer *trc);
 
     // Function Scripts
     //
     // Interpreted functions may either have an explicit JSScript (hasScript())
     // or be lazy with sufficient information to construct the JSScript if
     // necessary (isInterpretedLazy()).
     //
     // A lazy function will have a LazyScript if the function came from parsed
@@ -303,45 +304,43 @@ class JSFunction : public JSObject
 
     JSScript *getOrCreateScript(JSContext *cx) {
         JS_ASSERT(isInterpreted());
         JS_ASSERT(cx);
         if (isInterpretedLazy()) {
             JS::RootedFunction self(cx, this);
             if (!createScriptForLazilyInterpretedFunction(cx, self))
                 return nullptr;
-            JS_ASSERT(self->hasScript());
-            return self->u.i.s.script_;
+            return self->nonLazyScript();
         }
-        JS_ASSERT(hasScript());
-        return u.i.s.script_;
+        return nonLazyScript();
     }
 
     JSScript *existingScript() {
         JS_ASSERT(isInterpreted());
         if (isInterpretedLazy()) {
             js::LazyScript *lazy = lazyScript();
             JSScript *script = lazy->maybeScript();
             JS_ASSERT(script);
 
             if (shadowZone()->needsBarrier())
                 js::LazyScript::writeBarrierPre(lazy);
 
             flags_ &= ~INTERPRETED_LAZY;
             flags_ |= INTERPRETED;
             initScript(script);
         }
-        JS_ASSERT(hasScript());
-        return u.i.s.script_;
+        return nonLazyScript();
     }
 
     JSScript *nonLazyScript() const {
         js::AutoThreadSafeAccess ts(this);
+        JS_ASSERT(js::CurrentThreadCanReadCompilationData());
         JS_ASSERT(hasScript());
-        JS_ASSERT(js::CurrentThreadCanReadCompilationData());
+        JS_ASSERT(u.i.s.script_);
         return u.i.s.script_;
     }